// File: ArashPartow[P]exprtk-extras/exprtk_ornstein_uhlenbeck_process.cpp
// Function: void ornstein_uhlenbeck_process<double>()
void ornstein_uhlenbeck_process()
{
   typedef exprtk::symbol_table<T> symbol_table_t;
   typedef exprtk::expression<T>   expression_t;
   typedef exprtk::parser<T>       parser_t;

   const std::string ornstein_uhlenbeck_process_program =
      " const var mu        := 1;                                                        "
      " const var sigma     := 0.4;                                                      "
      " const var theta     := 2;                                                        "
      " const var tau       := 1 / theta;                                                "
      " const var T         := 10 * tau;                                                 "
      " const var dt        := 0.01 * tau;                                               "
      " const var num_steps := floor(T / dt);                                            "
      " const var stddev    := sqrt(sigma^2 / (2 * theta) * (1 - exp(-2 * theta * dt))); "
      " const var x_0       := 1.0;                                                      "
      "                                                                                  "
      " var x[num_steps] := [0];                                                         "
      "                                                                                  "
      " x[0] := x_0;                                                                     "
      "                                                                                  "
      " for (var i := 0; i < num_steps - 1; i += 1)                                      "
      " {                                                                                "
      "    var mean := x[i] * exp(-theta * dt) + mu * (1 - exp(-theta * dt));            "
      "                                                                                  "
      "    x[i + 1] := normal(mean,stddev);                                              "
      " };                                                                               "
      "                                                                                  "
      "                                                                                  "
      " for (var i := 0; i < x[]; i += 1)                                                "
      " {                                                                                "
      "    println(i * dt, '\t', x[i]);                                                  "
      " }                                                                                ";


   exprtk::rtl::io::println<T> println;
   normal_distribution<T>      normal;

   symbol_table_t symbol_table;
   symbol_table.add_function("println", println);
   symbol_table.add_function("normal" , normal );

   expression_t expression;
   expression.register_symbol_table(symbol_table);

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

   expression.value();
}

// Assembly:
subq $0x1f88, %rsp           # imm = 0x1F88
leaq 0x1f67(%rsp), %rdi
movq %rdi, 0x18(%rsp)
callq 0x1116a0
movq 0x18(%rsp), %rdx
leaq 0x334cc4(%rip), %rsi    # 0x44d559
leaq 0x1f68(%rsp), %rdi
callq 0x1187b0
jmp 0x1188a4
leaq 0x1f67(%rsp), %rdi
callq 0x1117d0
leaq 0x1ec7(%rsp), %rdi
movq %rdi, 0x10(%rsp)
callq 0x1116a0
movq 0x10(%rsp), %rdx
leaq 0x3354de(%rip), %rsi    # 0x44ddad
leaq 0x1ec8(%rsp), %rdi
callq 0x1187b0
jmp 0x1188de
leaq 0x1ee8(%rsp), %rdi
leaq 0x1ec8(%rsp), %rsi
callq 0x118f60
jmp 0x1188f5
leaq 0x1ec8(%rsp), %rdi
callq 0x1117e8
leaq 0x1ec7(%rsp), %rdi
callq 0x1117d0
leaq 0xb10(%rsp), %rdi
callq 0x119070
jmp 0x11891e
leaq 0xb08(%rsp), %rdi
movl $0x1, %esi
callq 0x119200
jmp 0x118932
leaq 0xae7(%rsp), %rdi
movq %rdi, 0x8(%rsp)
callq 0x1116a0
movq 0x8(%rsp), %rdx
leaq 0x335464(%rip), %rsi    # 0x44ddb4
leaq 0xae8(%rsp), %rdi
callq 0x1187b0
jmp 0x11895f
leaq 0xb08(%rsp), %rdi
leaq 0xae8(%rsp), %rsi
leaq 0x1ee8(%rsp), %rdx
callq 0x119240
jmp 0x11897e
leaq 0xae8(%rsp), %rdi
callq 0x1117e8
leaq 0xae7(%rsp), %rdi
callq 0x1117d0
leaq 0xabf(%rsp), %rdi
movq %rdi, (%rsp)
callq 0x1116a0
movq (%rsp), %rdx
leaq 0x335408(%rip), %rsi    # 0x44ddbc
leaq 0xac0(%rsp), %rdi
callq 0x1187b0
jmp 0x1189c3
leaq 0xb08(%rsp), %rdi
leaq 0xac0(%rsp), %rsi
leaq 0xb10(%rsp), %rdx
callq 0x119440
jmp 0x1189e2
leaq 0xac0(%rsp), %rdi
callq 0x1117e8
leaq 0xabf(%rsp), %rdi
callq 0x1117d0
leaq 0xa98(%rsp), %rdi
callq 0x1194e0
jmp 0x118a0b
leaq 0xa98(%rsp), %rdi
leaq 0xb08(%rsp), %rsi
callq 0x119590
jmp 0x118a22
leaq 0x20(%rsp), %rdi
movl $0x7f, %esi
callq 0x119640
jmp 0x118a33
leaq 0x170(%rsp), %rdi
leaq 0x20(%rsp), %rsi
callq 0x119770
jmp 0x118a47
leaq 0x20(%rsp), %rdi
callq 0x119fa0
leaq 0x170(%rsp), %rdi
leaq 0x1f68(%rsp), %rsi
leaq 0xa98(%rsp), %rdx
callq 0x11a010
jmp 0x118a70
leaq 0xa98(%rsp), %rdi
callq 0x11a8a0
jmp 0x118a7f
leaq 0x170(%rsp), %rdi
callq 0x11a8c0
leaq 0xa98(%rsp), %rdi
callq 0x11aac0
leaq 0xb08(%rsp), %rdi
callq 0x11ab00
leaq 0xb10(%rsp), %rdi
callq 0x11ab80
leaq 0x1ee8(%rsp), %rdi
callq 0x11ab90
leaq 0x1f68(%rsp), %rdi
callq 0x1117e8
addq $0x1f88, %rsp           # imm = 0x1F88
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f58(%rsp)
movl %eax, 0x1f54(%rsp)
leaq 0x1f67(%rsp), %rdi
callq 0x1117d0
jmp 0x118cb3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f58(%rsp)
movl %eax, 0x1f54(%rsp)
jmp 0x118b32
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f58(%rsp)
movl %eax, 0x1f54(%rsp)
leaq 0x1ec8(%rsp), %rdi
callq 0x1117e8
leaq 0x1ec7(%rsp), %rdi
callq 0x1117d0
jmp 0x118ca6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f58(%rsp)
movl %eax, 0x1f54(%rsp)
jmp 0x118c99
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f58(%rsp)
movl %eax, 0x1f54(%rsp)
jmp 0x118c8c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f58(%rsp)
movl %eax, 0x1f54(%rsp)
jmp 0x118bad
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f58(%rsp)
movl %eax, 0x1f54(%rsp)
leaq 0xae8(%rsp), %rdi
callq 0x1117e8
leaq 0xae7(%rsp), %rdi
callq 0x1117d0
jmp 0x118c7f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f58(%rsp)
movl %eax, 0x1f54(%rsp)
jmp 0x118bf6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f58(%rsp)
movl %eax, 0x1f54(%rsp)
leaq 0xac0(%rsp), %rdi
callq 0x1117e8
leaq 0xabf(%rsp), %rdi
callq 0x1117d0
jmp 0x118c7f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f58(%rsp)
movl %eax, 0x1f54(%rsp)
jmp 0x118c7f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f58(%rsp)
movl %eax, 0x1f54(%rsp)
jmp 0x118c72
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f58(%rsp)
movl %eax, 0x1f54(%rsp)
leaq 0x20(%rsp), %rdi
callq 0x119fa0
jmp 0x118c72
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f58(%rsp)
movl %eax, 0x1f54(%rsp)
leaq 0x170(%rsp), %rdi
callq 0x11a8c0
leaq 0xa98(%rsp), %rdi
callq 0x11aac0
leaq 0xb08(%rsp), %rdi
callq 0x11ab00
leaq 0xb10(%rsp), %rdi
callq 0x11ab80
leaq 0x1ee8(%rsp), %rdi
callq 0x11ab90
leaq 0x1f68(%rsp), %rdi
callq 0x1117e8
movq 0x1f58(%rsp), %rdi
callq 0x111480