// File: /workspace/github_cpp_makefile_star2_O2/ArashPartow[P]exprtk-extras/exprtk_jump_diffusion_process.cpp
// Function: void european_option_merton_jump_diffusion_process<double>()
void european_option_merton_jump_diffusion_process()
{
   typedef exprtk::symbol_table<T>         symbol_table_t;
   typedef exprtk::expression<T>           expression_t;
   typedef exprtk::parser<T>               parser_t;
   typedef exprtk::function_compositor<T>  compositor_t;
   typedef typename compositor_t::function function_t;

   const std::string european_option_merton_jump_diffusion_process_program =
      " var lambda_t   := lambda * t;                                                  "
      " var v_sqr      := v^2;                                                         "
      " var sigmaJ_sqr := sigmaJ^2;                                                    "
      "                                                                                "
      " var option_price := 0;                                                         "
      " var factorial    := 1;                                                         "
      "                                                                                "
      " for (var i := 0; i < n; i += 1)                                                "
      " {                                                                              "
      "    var prob    := exp(-lambda_t) * lambda_t^i / factorial;                     "
      "    var r_i     := r - lambda * muJ + (i / t) * log(1 + muJ);                   "
      "    var sigma_i := sqrt(v_sqr + (i * sigmaJ_sqr) / t);                          "
      "                                                                                "
      "    option_price +=                                                             "
      "       switch                                                                   "
      "       {                                                                        "
      "          case callput_flag == 'call' : prob * bsm_call(s, k, r_i, t, sigma_i); "
      "          case callput_flag == 'put'  : prob * bsm_put (s, k, r_i, t, sigma_i); "
      "       };                                                                       "
      "                                                                                "
      "    factorial *= (i > 1) ? i : 1;                                               "
      " };                                                                             "
      "                                                                                "
      " option_price;                                                                  ";

   T s      = T(100.00); // Spot / Stock / Underlying / Base price
   T k      = T(110.00); // Strike price
   T v      = T(  0.30); // Volatility
   T t      = T(  2.22); // Years to maturity
   T r      = T(  0.05); // Risk free rate
   T lambda = T(0.0001); // Jump intensity (average jumps per year)
   T muJ    = T( -0.05); // Mean jump size (negative for downward jumps)
   T sigmaJ = T(  0.30); // Standard deviation of the jump size
   T n      = T( 50.00); // Number of terms in the Poisson sum

   std::string callput_flag;

   symbol_table_t symbol_table(symbol_table_t::e_immutable);
   symbol_table.add_variable ("s"     , s     );
   symbol_table.add_variable ("k"     , k     );
   symbol_table.add_variable ("v"     , v     );
   symbol_table.add_variable ("t"     , t     );
   symbol_table.add_variable ("r"     , r     );
   symbol_table.add_variable ("lambda", lambda);
   symbol_table.add_variable ("muJ"   , muJ   );
   symbol_table.add_variable ("sigmaJ", sigmaJ);
   symbol_table.add_variable ("n"     , n     );
   symbol_table.add_stringvar("callput_flag",callput_flag);
   symbol_table.add_pi();

   compositor_t compositor(symbol_table);

   compositor.add(
      function_t("bsm_call")
      .vars("s", "k", "r", "t", "v")
      .expression
      (
         " var d1 := (log(s / k) + (r + v^2 / 2) * t) / (v * sqrt(t)); "
         " var d2 := d1 - v * sqrt(t);                                 "
         " s * ncdf(d1) - k * exp(-r * t) * ncdf(d2);                  "
      ));

   compositor.add(
      function_t("bsm_put")
      .vars("s", "k", "r", "t", "v")
      .expression
      (
         " var d1 := (log(s / k) + (r + v^2 / 2) * t) / (v * sqrt(t)); "
         " var d2 := d1 - v * sqrt(t);                                 "
         " k * exp(-r * t) * ncdf(-d2) - s * ncdf(-d1);                "
      ));

   expression_t expression;
   expression.register_symbol_table(symbol_table);

   parser_t parser;
   parser.compile(european_option_merton_jump_diffusion_process_program, expression);

   callput_flag = "call";

   const T jdp_call_option_price = expression.value();

   callput_flag = "put";

   const T jdp_put_option_price = expression.value();

   printf("JDPPrice(%4s, %5.3f, %5.3f, %5.3f, %5.3f, %5.3f) = %10.6f\n",
          "call",
          s, k, t, r, v,
          jdp_call_option_price);

   printf("JDPPrice(%4s, %5.3f, %5.3f, %5.3f, %5.3f, %5.3f) = %10.6f\n",
          "put",
          s, k, t, r, v,
          jdp_put_option_price);

   const T put_call_parity_diff =
      (jdp_call_option_price - jdp_put_option_price) -
      (s - k * std::exp(-r * t));

   printf("Put-Call parity difference: %20.17f\n", put_call_parity_diff);
}

// Assembly:
pushq %rbx
subq $0x15d0, %rsp           # imm = 0x15D0
leaq 0x131e0b(%rip), %rsi    # 0x24411d
leaq 0x150(%rsp), %rdi
leaq 0x2c0(%rsp), %rdx
callq 0x1122c8
movabsq $0x4059000000000000, %rax # imm = 0x4059000000000000
movq %rax, 0x38(%rsp)
movabsq $0x405b800000000000, %rax # imm = 0x405B800000000000
movq %rax, 0x30(%rsp)
movabsq $0x3fd3333333333333, %rax # imm = 0x3FD3333333333333
movq %rax, 0x40(%rsp)
movabsq $0x4001c28f5c28f5c3, %rcx # imm = 0x4001C28F5C28F5C3
movq %rcx, 0x28(%rsp)
movabsq $0x3fa999999999999a, %rcx # imm = 0x3FA999999999999A
movq %rcx, 0x20(%rsp)
movabsq $0x3f1a36e2eb1c432d, %rcx # imm = 0x3F1A36E2EB1C432D
movq %rcx, 0x128(%rsp)
movabsq $-0x4056666666666666, %rcx # imm = 0xBFA999999999999A
movq %rcx, 0x120(%rsp)
movq %rax, 0x118(%rsp)
movabsq $0x4049000000000000, %rax # imm = 0x4049000000000000
movq %rax, 0x110(%rsp)
leaq 0x140(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movb $0x0, (%rax)
movq %rsp, %rdi
pushq $0x2
popq %rsi
callq 0x112d64
leaq 0x131bf7(%rip), %rsi    # 0x243fcd
leaq 0x2c0(%rsp), %rdi
leaq 0xca8(%rsp), %rdx
callq 0x1122c8
movq %rsp, %rdi
leaq 0x2c0(%rsp), %rsi
leaq 0x38(%rsp), %rdx
xorl %ecx, %ecx
callq 0x112d88
leaq 0x2c0(%rsp), %rdi
callq 0x1105c8
leaq 0x131b4a(%rip), %rsi    # 0x243f60
leaq 0x2c0(%rsp), %rdi
leaq 0xca8(%rsp), %rdx
callq 0x1122c8
movq %rsp, %rdi
leaq 0x2c0(%rsp), %rsi
leaq 0x30(%rsp), %rdx
xorl %ecx, %ecx
callq 0x112d88
leaq 0x2c0(%rsp), %rdi
callq 0x1105c8
leaq 0x132448(%rip), %rsi    # 0x24489e
leaq 0x2c0(%rsp), %rdi
leaq 0xca8(%rsp), %rdx
callq 0x1122c8
movq %rsp, %rdi
leaq 0x2c0(%rsp), %rsi
leaq 0x40(%rsp), %rdx
xorl %ecx, %ecx
callq 0x112d88
leaq 0x2c0(%rsp), %rdi
callq 0x1105c8
leaq 0x132d96(%rip), %rsi    # 0x24522c
leaq 0x2c0(%rsp), %rdi
leaq 0xca8(%rsp), %rdx
callq 0x1122c8
movq %rsp, %rdi
leaq 0x2c0(%rsp), %rsi
leaq 0x28(%rsp), %rdx
xorl %ecx, %ecx
callq 0x112d88
leaq 0x2c0(%rsp), %rdi
callq 0x1105c8
leaq 0x131ae2(%rip), %rsi    # 0x243fb8
leaq 0x2c0(%rsp), %rdi
leaq 0xca8(%rsp), %rdx
callq 0x1122c8
movq %rsp, %rdi
leaq 0x2c0(%rsp), %rsi
leaq 0x20(%rsp), %rdx
xorl %ecx, %ecx
callq 0x112d88
leaq 0x2c0(%rsp), %rdi
callq 0x1105c8
leaq 0x13238a(%rip), %rsi    # 0x2448a0
leaq 0x2c0(%rsp), %rdi
leaq 0xca8(%rsp), %rdx
callq 0x1122c8
movq %rsp, %rdi
leaq 0x2c0(%rsp), %rsi
leaq 0x128(%rsp), %rdx
xorl %ecx, %ecx
callq 0x112d88
leaq 0x2c0(%rsp), %rdi
callq 0x1105c8
leaq 0x13234e(%rip), %rsi    # 0x2448a7
leaq 0x2c0(%rsp), %rdi
leaq 0xca8(%rsp), %rdx
callq 0x1122c8
movq %rsp, %rdi
leaq 0x2c0(%rsp), %rsi
leaq 0x120(%rsp), %rdx
xorl %ecx, %ecx
callq 0x112d88
leaq 0x2c0(%rsp), %rdi
callq 0x1105c8
leaq 0x13230f(%rip), %rsi    # 0x2448ab
leaq 0x2c0(%rsp), %rdi
leaq 0xca8(%rsp), %rdx
callq 0x1122c8
movq %rsp, %rdi
leaq 0x2c0(%rsp), %rsi
leaq 0x118(%rsp), %rdx
xorl %ecx, %ecx
callq 0x112d88
leaq 0x2c0(%rsp), %rdi
callq 0x1105c8
leaq 0x131a09(%rip), %rsi    # 0x243fe8
leaq 0x2c0(%rsp), %rdi
leaq 0xca8(%rsp), %rdx
callq 0x1122c8
movq %rsp, %rdi
leaq 0x2c0(%rsp), %rsi
leaq 0x110(%rsp), %rdx
xorl %ecx, %ecx
callq 0x112d88
leaq 0x2c0(%rsp), %rdi
callq 0x1105c8
leaq 0x132290(%rip), %rsi    # 0x2448b2
leaq 0x2c0(%rsp), %rdi
leaq 0xca8(%rsp), %rdx
callq 0x1122c8
movq %rsp, %rdi
leaq 0x2c0(%rsp), %rsi
leaq 0x130(%rsp), %rdx
xorl %ecx, %ecx
callq 0x112df4
leaq 0x2c0(%rsp), %rdi
callq 0x1105c8
movq %rsp, %rdi
callq 0x112e66
leaq 0x2c0(%rsp), %rdi
movq %rsp, %rsi
callq 0x112f00
leaq 0x132242(%rip), %rsi    # 0x2448bf
leaq 0x170(%rsp), %rdi
leaq 0xf(%rsp), %rdx
callq 0x1122c8
leaq 0xca8(%rsp), %rdi
leaq 0x170(%rsp), %rsi
callq 0x11301e
leaq 0x131922(%rip), %rsi    # 0x243fcd
leaq 0x48(%rsp), %rdi
leaq 0xe(%rsp), %rdx
callq 0x1122c8
leaq 0x13189f(%rip), %rsi    # 0x243f60
leaq 0xf0(%rsp), %rdi
leaq 0xd(%rsp), %rdx
callq 0x1122c8
leaq 0x1318de(%rip), %rsi    # 0x243fb8
leaq 0xd0(%rsp), %rdi
leaq 0xc(%rsp), %rdx
callq 0x1122c8
leaq 0x132b39(%rip), %rsi    # 0x24522c
leaq 0xb0(%rsp), %rdi
leaq 0xb(%rsp), %rdx
callq 0x1122c8
leaq 0x132192(%rip), %rsi    # 0x24489e
leaq 0x90(%rsp), %rdi
leaq 0xa(%rsp), %rdx
callq 0x1122c8
leaq 0xca8(%rsp), %rdi
leaq 0x48(%rsp), %rsi
leaq 0xf0(%rsp), %rdx
leaq 0xd0(%rsp), %rcx
leaq 0xb0(%rsp), %r8
leaq 0x90(%rsp), %r9
callq 0x11306a
movq %rax, %rbx
leaq 0x13216e(%rip), %rsi    # 0x2448c8
leaq 0x70(%rsp), %rdi
leaq 0x9(%rsp), %rdx
callq 0x1122c8
leaq 0x20(%rbx), %rdi
leaq 0x70(%rsp), %rsi
callq 0x110550
leaq 0x2c0(%rsp), %rdi
movq %rbx, %rsi
xorl %edx, %edx
callq 0x11300e
leaq 0x70(%rsp), %rdi
callq 0x1105c8
leaq 0x90(%rsp), %rdi
callq 0x1105c8
leaq 0xb0(%rsp), %rdi
callq 0x1105c8
leaq 0xd0(%rsp), %rdi
callq 0x1105c8
leaq 0xf0(%rsp), %rdi
callq 0x1105c8
leaq 0x48(%rsp), %rdi
callq 0x1105c8
leaq 0xca8(%rsp), %rdi
callq 0x1130ce
leaq 0x170(%rsp), %rdi
callq 0x1105c8
leaq 0x13218e(%rip), %rsi    # 0x244980
leaq 0x170(%rsp), %rdi
leaq 0xf(%rsp), %rdx
callq 0x1122c8
leaq 0xca8(%rsp), %rdi
leaq 0x170(%rsp), %rsi
callq 0x11301e
leaq 0x1317ad(%rip), %rsi    # 0x243fcd
leaq 0x48(%rsp), %rdi
leaq 0xe(%rsp), %rdx
callq 0x1122c8
leaq 0x13172a(%rip), %rsi    # 0x243f60
leaq 0xf0(%rsp), %rdi
leaq 0xd(%rsp), %rdx
callq 0x1122c8
leaq 0x131769(%rip), %rsi    # 0x243fb8
leaq 0xd0(%rsp), %rdi
leaq 0xc(%rsp), %rdx
callq 0x1122c8
leaq 0x1329c4(%rip), %rsi    # 0x24522c
leaq 0xb0(%rsp), %rdi
leaq 0xb(%rsp), %rdx
callq 0x1122c8
leaq 0x13201d(%rip), %rsi    # 0x24489e
leaq 0x90(%rsp), %rdi
leaq 0xa(%rsp), %rdx
callq 0x1122c8
leaq 0xca8(%rsp), %rdi
leaq 0x48(%rsp), %rsi
leaq 0xf0(%rsp), %rdx
leaq 0xd0(%rsp), %rcx
leaq 0xb0(%rsp), %r8
leaq 0x90(%rsp), %r9
callq 0x11306a
movq %rax, %rbx
leaq 0x1320b9(%rip), %rsi    # 0x244988
leaq 0x70(%rsp), %rdi
leaq 0x9(%rsp), %rdx
callq 0x1122c8
leaq 0x20(%rbx), %rdi
leaq 0x70(%rsp), %rsi
callq 0x110550
leaq 0x2c0(%rsp), %rdi
movq %rbx, %rsi
xorl %edx, %edx
callq 0x11300e
leaq 0x70(%rsp), %rdi
callq 0x1105c8
leaq 0x90(%rsp), %rdi
callq 0x1105c8
leaq 0xb0(%rsp), %rdi
callq 0x1105c8
leaq 0xd0(%rsp), %rdi
callq 0x1105c8
leaq 0xf0(%rsp), %rdi
callq 0x1105c8
leaq 0x48(%rsp), %rdi
callq 0x1105c8
leaq 0xca8(%rsp), %rdi
callq 0x1130ce
leaq 0x170(%rsp), %rdi
callq 0x1105c8
leaq 0x48(%rsp), %rdi
callq 0x1130ee
leaq 0x48(%rsp), %rdi
movq %rsp, %rsi
callq 0x11314e
leaq 0x170(%rsp), %rdi
pushq $0x7f
popq %rsi
callq 0x1131aa
leaq 0xca8(%rsp), %rdi
leaq 0x170(%rsp), %rsi
callq 0x1132ba
leaq 0x170(%rsp), %rdi
callq 0x1138d2
leaq 0xca8(%rsp), %rdi
leaq 0x150(%rsp), %rsi
leaq 0x48(%rsp), %rdx
callq 0x11391a
leaq 0x135a99(%rip), %rsi    # 0x248463
leaq 0x130(%rsp), %rdi
callq 0x110580
movq 0x48(%rsp), %rax
movq 0x8(%rax), %rdi
movq (%rdi), %rax
callq *0x18(%rax)
movsd %xmm0, 0x18(%rsp)
leaq 0x131f91(%rip), %rsi    # 0x244984
leaq 0x130(%rsp), %rdi
callq 0x110580
movq 0x48(%rsp), %rax
movq 0x8(%rax), %rdi
movq (%rdi), %rax
callq *0x18(%rax)
movsd %xmm0, 0x10(%rsp)
movsd 0x38(%rsp), %xmm0
movsd 0x30(%rsp), %xmm1
movsd 0x28(%rsp), %xmm2
movsd 0x20(%rsp), %xmm3
movsd 0x40(%rsp), %xmm4
leaq 0x132006(%rip), %rbx    # 0x244a40
leaq 0x135a22(%rip), %rsi    # 0x248463
movq %rbx, %rdi
movsd 0x18(%rsp), %xmm5
movb $0x6, %al
callq 0x110060
movsd 0x38(%rsp), %xmm0
movsd 0x30(%rsp), %xmm1
movsd 0x28(%rsp), %xmm2
movsd 0x20(%rsp), %xmm3
movsd 0x40(%rsp), %xmm4
leaq 0x131f0e(%rip), %rsi    # 0x244984
movq %rbx, %rdi
movsd 0x10(%rsp), %xmm5
movb $0x6, %al
callq 0x110060
movsd 0x18(%rsp), %xmm0
subsd 0x10(%rsp), %xmm0
movsd %xmm0, 0x18(%rsp)
movsd 0x38(%rsp), %xmm0
movsd %xmm0, 0x10(%rsp)
movsd 0x30(%rsp), %xmm0
movsd %xmm0, 0x68(%rsp)
movsd 0x20(%rsp), %xmm0
xorpd 0x12c552(%rip), %xmm0   # 0x23f010
mulsd 0x28(%rsp), %xmm0
callq 0x1100d0
mulsd 0x68(%rsp), %xmm0
movsd 0x10(%rsp), %xmm1
subsd %xmm0, %xmm1
movsd 0x18(%rsp), %xmm0
subsd %xmm1, %xmm0
leaq 0x131f91(%rip), %rdi    # 0x244a7b
movb $0x1, %al
callq 0x110060
leaq 0xca8(%rsp), %rdi
callq 0x113d9c
leaq 0x48(%rsp), %rdi
callq 0x113ed6
leaq 0x2c0(%rsp), %rdi
callq 0x113eec
movq %rsp, %rdi
callq 0x113f40
leaq 0x130(%rsp), %rdi
callq 0x1105c8
leaq 0x150(%rsp), %rdi
callq 0x1105c8
addq $0x15d0, %rsp           # imm = 0x15D0
popq %rbx
retq
jmp 0x112c09
movq %rax, %rbx
leaq 0x170(%rsp), %rdi
callq 0x1138d2
jmp 0x112c19
jmp 0x112b5c
movq %rax, %rbx
jmp 0x112c19
jmp 0x112bb2
jmp 0x112b7a
jmp 0x112b7a
jmp 0x112b82
jmp 0x112b8a
jmp 0x112b92
jmp 0x112b9a
jmp 0x112ba2
jmp 0x112baa
jmp 0x112bb2
jmp 0x112b7a
movq %rax, %rbx
jmp 0x112c34
movq %rax, %rbx
jmp 0x112c41
movq %rax, %rbx
jmp 0x112c4e
movq %rax, %rbx
jmp 0x112c5b
movq %rax, %rbx
jmp 0x112c68
movq %rax, %rbx
jmp 0x112c72
movq %rax, %rbx
jmp 0x112c7f
movq %rax, %rbx
jmp 0x112c8c
jmp 0x112bf7
jmp 0x112bf7
jmp 0x112be2
jmp 0x112bf7
jmp 0x112be2
jmp 0x112bf7
jmp 0x112be2
jmp 0x112bf7
jmp 0x112be2
jmp 0x112bf7
jmp 0x112be2
jmp 0x112bf7
jmp 0x112be2
jmp 0x112bf7
jmp 0x112be2
jmp 0x112bf7
jmp 0x112be2
jmp 0x112bf7
jmp 0x112be2
jmp 0x112bf7
movq %rax, %rbx
leaq 0x2c0(%rsp), %rdi
callq 0x1105c8
jmp 0x112c99
movq %rax, %rbx
jmp 0x112c99
movq %rax, %rbx
jmp 0x112ca1
jmp 0x112c09
movq %rax, %rbx
leaq 0xca8(%rsp), %rdi
callq 0x113d9c
leaq 0x48(%rsp), %rdi
callq 0x113ed6
jmp 0x112c8c
jmp 0x112c27
movq %rax, %rbx
leaq 0x70(%rsp), %rdi
callq 0x1105c8
leaq 0x90(%rsp), %rdi
callq 0x1105c8
leaq 0xb0(%rsp), %rdi
callq 0x1105c8
leaq 0xd0(%rsp), %rdi
callq 0x1105c8
leaq 0xf0(%rsp), %rdi
callq 0x1105c8
leaq 0x48(%rsp), %rdi
callq 0x1105c8
leaq 0xca8(%rsp), %rdi
callq 0x1130ce
leaq 0x170(%rsp), %rdi
callq 0x1105c8
leaq 0x2c0(%rsp), %rdi
callq 0x113eec
movq %rsp, %rdi
callq 0x113f40
leaq 0x130(%rsp), %rdi
callq 0x1105c8
leaq 0x150(%rsp), %rdi
callq 0x1105c8
movq %rbx, %rdi
callq 0x110310