#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */

/* Variables and functions */
double log(double);
double max(double, double);
double rq_pricing_cumul_norm_dist(double);
double sqrt(double);
double rq_pricing_garmankhol(int call, double S, double X, double df_dom,
                             double df_for, double sigma, double tau_e,
                             double tau_d) {
  double d1, d2, m = (call ? 1.0 : -1.0);
  double sigma_tau_sqrt;
  double f = S * df_for / df_dom;
  if (sigma <= 0.0 || X == 0.0 || f / X <= 0.0 || tau_e <= 0.0)
    return df_dom * max(m * (f - X), 0.0);
  sigma_tau_sqrt = sigma * sqrt(tau_e);
  d1 = (log(f / X) + (0.5 * sigma * sigma * tau_e)) / sigma_tau_sqrt;
  d2 = (d1 - sigma_tau_sqrt) * m;
  d1 *= m;
  return df_dom * m *
         (f * rq_pricing_cumul_norm_dist(d1) -
          X * rq_pricing_cumul_norm_dist(d2));
}


x86 assembly (clang, -O0):
<rq_pricing_garmankhol>:
push   %rbp
mov    %rsp,%rbp
sub    $0xb0,%rsp
mov    %edi,-0xc(%rbp)
movsd  %xmm0,-0x18(%rbp)
movsd  %xmm1,-0x20(%rbp)
movsd  %xmm2,-0x28(%rbp)
movsd  %xmm3,-0x30(%rbp)
movsd  %xmm4,-0x38(%rbp)
movsd  %xmm5,-0x40(%rbp)
movsd  %xmm6,-0x48(%rbp)
mov    -0xc(%rbp),%eax
movsd  0xe84(%rip),%xmm0
movsd  0xe84(%rip),%xmm1
movsd  %xmm1,-0x80(%rbp)
cmp    $0x0,%eax
movsd  %xmm0,-0x78(%rbp)
jne    11a1 <rq_pricing_garmankhol+0x61>
movsd  -0x80(%rbp),%xmm0
movsd  %xmm0,-0x78(%rbp)
movsd  -0x78(%rbp),%xmm0
movsd  %xmm0,-0x60(%rbp)
movsd  -0x18(%rbp),%xmm0
mulsd  -0x30(%rbp),%xmm0
divsd  -0x28(%rbp),%xmm0
movsd  %xmm0,-0x70(%rbp)
xorps  %xmm0,%xmm0
ucomisd -0x38(%rbp),%xmm0
jae    120f <rq_pricing_garmankhol+0xcf>
movsd  -0x20(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jne    11ea <rq_pricing_garmankhol+0xaa>
jp     11ea <rq_pricing_garmankhol+0xaa>
jmp    120f <rq_pricing_garmankhol+0xcf>
movsd  -0x70(%rbp),%xmm1
divsd  -0x20(%rbp),%xmm1
xorps  %xmm0,%xmm0
ucomisd %xmm1,%xmm0
jae    120f <rq_pricing_garmankhol+0xcf>
xorps  %xmm0,%xmm0
ucomisd -0x40(%rbp),%xmm0
jb     1250 <rq_pricing_garmankhol+0x110>
movsd  -0x28(%rbp),%xmm0
movsd  %xmm0,-0x88(%rbp)
ff
movsd  -0x60(%rbp),%xmm0
movsd  -0x70(%rbp),%xmm1
subsd  -0x20(%rbp),%xmm1
mulsd  %xmm1,%xmm0
xorps  %xmm1,%xmm1
call   1040 <max@plt>
movaps %xmm0,%xmm1
movsd  -0x88(%rbp),%xmm0
ff
mulsd  %xmm1,%xmm0
movsd  %xmm0,-0x8(%rbp)
jmp    1370 <rq_pricing_garmankhol+0x230>
movsd  -0x38(%rbp),%xmm0
movsd  %xmm0,-0xb0(%rbp)
ff
movsd  -0x40(%rbp),%xmm0
call   1060 <sqrt@plt>
movaps %xmm0,%xmm1
movsd  -0xb0(%rbp),%xmm0
ff
mulsd  %xmm1,%xmm0
movsd  %xmm0,-0x68(%rbp)
movsd  -0x70(%rbp),%xmm0
divsd  -0x20(%rbp),%xmm0
call   1050 <log@plt>
movaps %xmm0,%xmm1
movsd  0xd7b(%rip),%xmm0
mulsd  -0x38(%rbp),%xmm0
mulsd  -0x38(%rbp),%xmm0
movsd  -0x40(%rbp),%xmm2
mulsd  %xmm2,%xmm0
addsd  %xmm1,%xmm0
divsd  -0x68(%rbp),%xmm0
movsd  %xmm0,-0x50(%rbp)
movsd  -0x50(%rbp),%xmm0
subsd  -0x68(%rbp),%xmm0
mulsd  -0x60(%rbp),%xmm0
movsd  %xmm0,-0x58(%rbp)
movsd  -0x60(%rbp),%xmm0
mulsd  -0x50(%rbp),%xmm0
movsd  %xmm0,-0x50(%rbp)
movsd  -0x28(%rbp),%xmm0
mulsd  -0x60(%rbp),%xmm0
movsd  %xmm0,-0x90(%rbp)
ff
movsd  -0x70(%rbp),%xmm0
movsd  %xmm0,-0xa0(%rbp)
ff
movsd  -0x50(%rbp),%xmm0
call   1030 <rq_pricing_cumul_norm_dist@plt>
movsd  %xmm0,-0x98(%rbp)
ff
movsd  -0x20(%rbp),%xmm0
movsd  %xmm0,-0xa8(%rbp)
ff
movsd  -0x58(%rbp),%xmm0
call   1030 <rq_pricing_cumul_norm_dist@plt>
movsd  -0xa8(%rbp),%xmm2
ff
movsd  -0xa0(%rbp),%xmm1
ff
movsd  -0x98(%rbp),%xmm3
ff
movaps %xmm0,%xmm4
movsd  -0x90(%rbp),%xmm0
ff
mulsd  %xmm4,%xmm2
movq   %xmm2,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm2
mulsd  %xmm3,%xmm1
addsd  %xmm2,%xmm1
mulsd  %xmm1,%xmm0
movsd  %xmm0,-0x8(%rbp)
movsd  -0x8(%rbp),%xmm0
add    $0xb0,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<rq_pricing_garmankhol>:
sub    $0x38,%rsp
xor    %eax,%eax
test   %edi,%edi
sete   %al
lea    0xeae(%rip),%rcx
movsd  (%rcx,%rax,8),%xmm6
mulsd  %xmm3,%xmm0
movsd  %xmm2,0x8(%rsp)
divsd  %xmm2,%xmm0
xorpd  %xmm2,%xmm2
ucomisd %xmm2,%xmm1
jne    1171 <rq_pricing_garmankhol+0x31>
jnp    11bf <rq_pricing_garmankhol+0x7f>
ucomisd %xmm4,%xmm2
jae    11bf <rq_pricing_garmankhol+0x7f>
xorpd  %xmm2,%xmm2
ucomisd %xmm5,%xmm2
jae    11bf <rq_pricing_garmankhol+0x7f>
movapd %xmm0,%xmm3
divsd  %xmm1,%xmm3
ucomisd %xmm3,%xmm2
jae    11bf <rq_pricing_garmankhol+0x7f>
movsd  %xmm6,0x20(%rsp)
movsd  %xmm1,0x28(%rsp)
movsd  %xmm0,0x30(%rsp)
xorpd  %xmm0,%xmm0
ucomisd %xmm0,%xmm5
movsd  %xmm4,(%rsp)
movsd  %xmm5,0x18(%rsp)
jb     11dd <rq_pricing_garmankhol+0x9d>
xorps  %xmm0,%xmm0
sqrtsd %xmm5,%xmm0
jmp    11f7 <rq_pricing_garmankhol+0xb7>
subsd  %xmm1,%xmm0
mulsd  %xmm0,%xmm6
xorpd  %xmm1,%xmm1
movapd %xmm6,%xmm0
call   1040 <max@plt>
movapd %xmm0,%xmm1
jmp    128d <rq_pricing_garmankhol+0x14d>
movapd %xmm5,%xmm0
movsd  %xmm3,0x10(%rsp)
call   1060 <sqrt@plt>
movsd  0x10(%rsp),%xmm3
movsd  (%rsp),%xmm4
mulsd  %xmm4,%xmm0
movsd  %xmm0,0x10(%rsp)
movapd %xmm3,%xmm0
call   1050 <log@plt>
movapd %xmm0,%xmm2
movsd  0xdfa(%rip),%xmm0
movsd  (%rsp),%xmm1
mulsd  %xmm1,%xmm0
mulsd  %xmm1,%xmm0
mulsd  0x18(%rsp),%xmm0
addsd  %xmm0,%xmm2
movsd  0x10(%rsp),%xmm3
divsd  %xmm3,%xmm2
movsd  0x20(%rsp),%xmm1
movapd %xmm1,%xmm0
mulsd  %xmm2,%xmm0
subsd  %xmm3,%xmm2
mulsd  %xmm1,%xmm2
movsd  %xmm2,0x18(%rsp)
movsd  0x8(%rsp),%xmm2
mulsd  %xmm1,%xmm2
movsd  %xmm2,0x8(%rsp)
call   1030 <rq_pricing_cumul_norm_dist@plt>
movsd  %xmm0,(%rsp)
movsd  0x18(%rsp),%xmm0
call   1030 <rq_pricing_cumul_norm_dist@plt>
mulsd  0x28(%rsp),%xmm0
movsd  0x30(%rsp),%xmm1
mulsd  (%rsp),%xmm1
subsd  %xmm0,%xmm1
mulsd  0x8(%rsp),%xmm1
movapd %xmm1,%xmm0
add    $0x38,%rsp
ret

LLVM IR (-O0):
define double @rq_pricing_garmankhol(i32 %0, double %1, double %2, double %3, double %4, double %5, double %6, double %7) {
%9 = alloca double
%10 = alloca i32
%11 = alloca double
%12 = alloca double
%13 = alloca double
%14 = alloca double
%15 = alloca double
%16 = alloca double
%17 = alloca double
%18 = alloca double
%19 = alloca double
%20 = alloca double
%21 = alloca double
%22 = alloca double
store i32 %0, i32* %10
store double %1, double* %11
store double %2, double* %12
store double %3, double* %13
store double %4, double* %14
store double %5, double* %15
store double %6, double* %16
store double %7, double* %17
%23 = load i32, i32* %10
%24 = icmp ne i32 %23, 0
%25 = zext i1 %24 to i64
%26 = select i1 %24, double 1.000000e+00, double -1.000000e+00
store double %26, double* %20
%27 = load double, double* %11
%28 = load double, double* %14
%29 = fmul double %27, %28
%30 = load double, double* %13
%31 = fdiv double %29, %30
store double %31, double* %22
%32 = load double, double* %15
%33 = fcmp ole double %32, 0.000000e+00
br i1 %33, label %45, label %34
34: ; preds = %8
%35 = load double, double* %12
%36 = fcmp oeq double %35, 0.000000e+00
br i1 %36, label %45, label %37
37: ; preds = %34
%38 = load double, double* %22
%39 = load double, double* %12
%40 = fdiv double %38, %39
%41 = fcmp ole double %40, 0.000000e+00
br i1 %41, label %45, label %42
42: ; preds = %37
%43 = load double, double* %16
%44 = fcmp ole double %43, 0.000000e+00
br i1 %44, label %45, label %54
45: ; preds = %42, %37, %34, %8
%46 = load double, double* %13
%47 = load double, double* %20
%48 = load double, double* %22
%49 = load double, double* %12
%50 = fsub double %48, %49
%51 = fmul double %47, %50
%52 = call double @max(double %51, double 0.000000e+00)
%53 = fmul double %46, %52
store double %53, double* %9
br label %92
54: ; preds = %42
%55 = load double, double* %15
%56 = load double, double* %16
%57 = call double @sqrt(double %56)
%58 = fmul double %55, %57
store double %58, double* %21
%59 = load double, double* %22
%60 = load double, double* %12
%61 = fdiv double %59, %60
%62 = call double @log(double %61)
%63 = load double, double* %15
%64 = fmul double 5.000000e-01, %63
%65 = load double, double* %15
%66 = fmul double %64, %65
%67 = load double, double* %16
%68 = call double @llvm.fmuladd.f64(double %66, double %67, double %62)
%69 = load double, double* %21
%70 = fdiv double %68, %69
store double %70, double* %18
%71 = load double, double* %18
%72 = load double, double* %21
%73 = fsub double %71, %72
%74 = load double, double* %20
%75 = fmul double %73, %74
store double %75, double* %19
%76 = load double, double* %20
%77 = load double, double* %18
%78 = fmul double %77, %76
store double %78, double* %18
%79 = load double, double* %13
%80 = load double, double* %20
%81 = fmul double %79, %80
%82 = load double, double* %22
%83 = load double, double* %18
%84 = call double @rq_pricing_cumul_norm_dist(double %83)
%85 = load double, double* %12
%86 = load double, double* %19
%87 = call double @rq_pricing_cumul_norm_dist(double %86)
%88 = fmul double %85, %87
%89 = fneg double %88
%90 = call double @llvm.fmuladd.f64(double %82, double %84, double %89)
%91 = fmul double %81, %90
store double %91, double* %9
br label %92
92: ; preds = %54, %45
%93 = load double, double* %9
ret double %93
}

LLVM IR (-O2):
define double @rq_pricing_garmankhol(i32 %0, double %1, double %2, double %3, double %4, double %5, double %6, double %7) {
%9 = icmp eq i32 %0, 0
%10 = select i1 %9, double -1.000000e+00, double 1.000000e+00
%11 = fmul double %1, %4
%12 = fdiv double %11, %3
%13 = fcmp ole double %5, 0.000000e+00
%14 = fcmp oeq double %2, 0.000000e+00
%15 = or i1 %14, %13
br i1 %15, label %21, label %16
16: ; preds = %8
%17 = fdiv double %12, %2
%18 = fcmp ole double %17, 0.000000e+00
%19 = fcmp ole double %6, 0.000000e+00
%20 = or i1 %19, %18
br i1 %20, label %21, label %26
21: ; preds = %16, %8
%22 = fsub double %12, %2
%23 = fmul double %10, %22
%24 = tail call double @max(double %23, double 0.000000e+00)
%25 = fmul double %24, %3
br label %44
26: ; preds = %16
%27 = tail call double @sqrt(double %6)
%28 = fmul double %27, %5
%29 = tail call double @log(double %17)
%30 = fmul double %5, 5.000000e-01
%31 = fmul double %30, %5
%32 = tail call double @llvm.fmuladd.f64(double %31, double %6, double %29)
%33 = fdiv double %32, %28
%34 = fsub double %33, %28
%35 = fmul double %10, %34
%36 = fmul double %10, %33
%37 = fmul double %10, %3
%38 = tail call double @rq_pricing_cumul_norm_dist(double %36)
%39 = tail call double @rq_pricing_cumul_norm_dist(double %35)
%40 = fneg double %39
%41 = fmul double %40, %2
%42 = tail call double @llvm.fmuladd.f64(double %12, double %38, double %41)
%43 = fmul double %37, %42
br label %44
44: ; preds = %26, %21
%45 = phi double [ %25, %21 ], [ %43, %26 ]
ret double %45
}