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

   const std::string monte_carlo_pi_program =
      " var max_samples := 5 * 10^7;              "
      " var count       := 0;                     "
      "                                           "
      " for (var i := 0; i < max_samples; i += 1) "
      " {                                         "
      "    if ((rnd_01^2 + rnd_01^2) <= 1)        "
      "       count += 1;                         "
      " };                                        "
      "                                           "
      " (4 * count) / max_samples;                ";

   rnd_01<T> rnd01;

   symbol_table_t symbol_table;
   symbol_table.add_function("rnd_01",rnd01);

   expression_t expression;
   expression.register_symbol_table(symbol_table);

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

   const T approximate_pi = expression.value();

   const T real_pi = T(3.141592653589793238462643383279502); // or close enough...

   printf("pi ~ %20.17f\terror: %20.17f\n",
          approximate_pi,
          std::abs(real_pi - approximate_pi));
}

// Assembly:
subq $0xb68, %rsp            # imm = 0xB68
leaq 0xb47(%rsp), %rdi
movq %rdi, 0x28(%rsp)
callq 0x111650
movq 0x28(%rsp), %rdx
leaq 0x330cf4(%rip), %rsi    # 0x449549
leaq 0xb48(%rsp), %rdi
callq 0x118770
jmp 0x118864
leaq 0xb47(%rsp), %rdi
callq 0x111790
leaq 0xb08(%rsp), %rdi
callq 0x118e20
jmp 0x118880
leaq 0xb00(%rsp), %rdi
movl $0x1, %esi
callq 0x118e70
jmp 0x118894
leaq 0xadf(%rsp), %rdi
movq %rdi, 0x20(%rsp)
callq 0x111650
movq 0x20(%rsp), %rdx
leaq 0x330e46(%rip), %rsi    # 0x4496f8
leaq 0xae0(%rsp), %rdi
callq 0x118770
jmp 0x1188c1
leaq 0xb00(%rsp), %rdi
leaq 0xae0(%rsp), %rsi
leaq 0xb08(%rsp), %rdx
callq 0x118eb0
jmp 0x1188e0
leaq 0xae0(%rsp), %rdi
callq 0x1117a8
leaq 0xadf(%rsp), %rdi
callq 0x111790
leaq 0xab8(%rsp), %rdi
callq 0x118f50
jmp 0x118909
leaq 0xab8(%rsp), %rdi
leaq 0xb00(%rsp), %rsi
callq 0x119000
jmp 0x118920
leaq 0x40(%rsp), %rdi
movl $0x7f, %esi
callq 0x1190b0
jmp 0x118931
leaq 0x190(%rsp), %rdi
leaq 0x40(%rsp), %rsi
callq 0x1191e0
jmp 0x118945
leaq 0x40(%rsp), %rdi
callq 0x119a10
leaq 0x190(%rsp), %rdi
leaq 0xb48(%rsp), %rsi
leaq 0xab8(%rsp), %rdx
callq 0x119a80
jmp 0x11896e
leaq 0xab8(%rsp), %rdi
callq 0x11a310
movsd %xmm0, 0x18(%rsp)
jmp 0x118983
movsd 0x18(%rsp), %xmm0
movsd %xmm0, 0x38(%rsp)
movabsq $0x400921fb54442d18, %rax # imm = 0x400921FB54442D18
movq %rax, 0x30(%rsp)
movsd 0x38(%rsp), %xmm1
movsd %xmm1, 0x8(%rsp)
movsd 0x32b656(%rip), %xmm0   # 0x444008
subsd %xmm1, %xmm0
callq 0x11a330
movsd %xmm0, 0x10(%rsp)
jmp 0x1189c3
movsd 0x10(%rsp), %xmm1
movsd 0x8(%rsp), %xmm0
leaq 0x330d29(%rip), %rdi    # 0x4496ff
movb $0x2, %al
callq 0x111080
jmp 0x1189df
leaq 0x190(%rsp), %rdi
callq 0x11a350
leaq 0xab8(%rsp), %rdi
callq 0x11a550
leaq 0xb00(%rsp), %rdi
callq 0x11a590
leaq 0xb08(%rsp), %rdi
callq 0x11a610
leaq 0xb48(%rsp), %rdi
callq 0x1117a8
addq $0xb68, %rsp            # imm = 0xB68
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb38(%rsp)
movl %eax, 0xb34(%rsp)
leaq 0xb47(%rsp), %rdi
callq 0x111790
jmp 0x118b67
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb38(%rsp)
movl %eax, 0xb34(%rsp)
jmp 0x118b5a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb38(%rsp)
movl %eax, 0xb34(%rsp)
jmp 0x118b4d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb38(%rsp)
movl %eax, 0xb34(%rsp)
jmp 0x118ab7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb38(%rsp)
movl %eax, 0xb34(%rsp)
leaq 0xae0(%rsp), %rdi
callq 0x1117a8
leaq 0xadf(%rsp), %rdi
callq 0x111790
jmp 0x118b40
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb38(%rsp)
movl %eax, 0xb34(%rsp)
jmp 0x118b40
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb38(%rsp)
movl %eax, 0xb34(%rsp)
jmp 0x118b33
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb38(%rsp)
movl %eax, 0xb34(%rsp)
leaq 0x40(%rsp), %rdi
callq 0x119a10
jmp 0x118b33
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb38(%rsp)
movl %eax, 0xb34(%rsp)
leaq 0x190(%rsp), %rdi
callq 0x11a350
leaq 0xab8(%rsp), %rdi
callq 0x11a550
leaq 0xb00(%rsp), %rdi
callq 0x11a590
leaq 0xb08(%rsp), %rdi
callq 0x11a610
leaq 0xb48(%rsp), %rdi
callq 0x1117a8
movq 0xb38(%rsp), %rdi
callq 0x111440
nopw %cs:(%rax,%rax)
nop