// File: ArashPartow[P]exprtk-extras/exprtk_normal_random_marsaglia_method.cpp
// Function: void normal_random_marsaglia_method<double>()
void normal_random_marsaglia_method()
{
   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;

   exprtk::rtl::io::println<T> println;
   uniform_random_01<T>        unirandom;

   symbol_table_t symbol_table;
   symbol_table.add_function("println", println  );
   symbol_table.add_function("random" , unirandom);
   symbol_table.add_constants();

   compositor_t compositor(symbol_table);

   compositor.add(
      function_t("normal_distribution")
      .vars("mean", "stddev")
      .expression
      (
         " var u := 0;                 "
         " var v := 0;                 "
         " var s := 0;                 "
         "                             "
         " repeat                      "
         "    u := random() * 2 - 1;   "
         "    v := random() * 2 - 1;   "
         "    s := u^2 + v^2;          "
         " until (s > 0 and s < 1);    "
         "                             "
         " s := sqrt(-2 * log(s) / s); "
         " mean + stddev * u * s;      "
      ));

   const std::string normal_random_marsaglia_method_program =
      " const var mean          := pi;                                                      "
      " const var stddev        := 3 * mean / 2;                                            "
      " const var num_samples   := 1e7;                                                     "
      " var values[num_samples] := [normal_distribution(mean, stddev)];                     "
      "                                                                                     "
      " var sample_mean   := avg(values);                                                   "
      " var sample_stddev := sqrt(sum([values - sample_mean]^2) / values[]);                "
      "                                                                                     "
      " println('sample mean:   ', sample_mean  , ' error: ', abs(sample_mean - mean));     "
      " println('sample stddev: ', sample_stddev, ' error: ', abs(sample_stddev - stddev)); "
      "                                                                                     "
      "                                                                                     ";

   expression_t expression;
   expression.register_symbol_table(symbol_table);

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

   expression.value();
}

// Assembly:
subq $0x2ae8, %rsp           # imm = 0x2AE8
leaq 0x2a5f(%rsp), %rdi
movq %rdi, 0x50(%rsp)
callq 0x1146b0
movq 0x50(%rsp), %rdx
leaq 0x349cd0(%rip), %rsi    # 0x465575
leaq 0x2a60(%rsp), %rdi
callq 0x11b7c0
jmp 0x11b8b4
leaq 0x2a80(%rsp), %rdi
leaq 0x2a60(%rsp), %rsi
callq 0x11c280
jmp 0x11b8cb
leaq 0x2a60(%rsp), %rdi
callq 0x1147f8
leaq 0x2a5f(%rsp), %rdi
callq 0x1147e0
leaq 0x1688(%rsp), %rdi
callq 0x11c390
jmp 0x11b8f4
leaq 0x1680(%rsp), %rdi
movl $0x1, %esi
callq 0x11c530
jmp 0x11b908
leaq 0x165f(%rsp), %rdi
movq %rdi, 0x48(%rsp)
callq 0x1146b0
movq 0x48(%rsp), %rdx
leaq 0x349c56(%rip), %rsi    # 0x46557c
leaq 0x1660(%rsp), %rdi
callq 0x11b7c0
jmp 0x11b935
leaq 0x1680(%rsp), %rdi
leaq 0x1660(%rsp), %rsi
leaq 0x2a80(%rsp), %rdx
callq 0x11c570
jmp 0x11b954
leaq 0x1660(%rsp), %rdi
callq 0x1147f8
leaq 0x165f(%rsp), %rdi
callq 0x1147e0
leaq 0x1637(%rsp), %rdi
movq %rdi, 0x40(%rsp)
callq 0x1146b0
movq 0x40(%rsp), %rdx
leaq 0x349bf8(%rip), %rsi    # 0x465584
leaq 0x1638(%rsp), %rdi
callq 0x11b7c0
jmp 0x11b99b
leaq 0x1680(%rsp), %rdi
leaq 0x1638(%rsp), %rsi
leaq 0x1688(%rsp), %rdx
callq 0x11c770
jmp 0x11b9ba
leaq 0x1638(%rsp), %rdi
callq 0x1147f8
leaq 0x1637(%rsp), %rdi
callq 0x1147e0
leaq 0x1680(%rsp), %rdi
callq 0x11c810
jmp 0x11b9e3
leaq 0xc48(%rsp), %rdi
leaq 0x1680(%rsp), %rsi
callq 0x11c870
jmp 0x11b9fa
leaq 0xb97(%rsp), %rdi
movq %rdi, 0x38(%rsp)
callq 0x1146b0
movq 0x38(%rsp), %rdx
leaq 0x349b73(%rip), %rsi    # 0x46558b
leaq 0xb98(%rsp), %rdi
callq 0x11b7c0
jmp 0x11ba27
leaq 0xbb8(%rsp), %rdi
leaq 0xb98(%rsp), %rsi
callq 0x11ca60
jmp 0x11ba3e
leaq 0xb6f(%rsp), %rdi
movq %rdi, 0x30(%rsp)
callq 0x1146b0
movq 0x30(%rsp), %rdx
leaq 0x349b43(%rip), %rsi    # 0x46559f
leaq 0xb70(%rsp), %rdi
callq 0x11b7c0
jmp 0x11ba6b
leaq 0xb47(%rsp), %rdi
movq %rdi, 0x28(%rsp)
callq 0x1146b0
movq 0x28(%rsp), %rdx
leaq 0x349b1b(%rip), %rsi    # 0x4655a4
leaq 0xb48(%rsp), %rdi
callq 0x11b7c0
jmp 0x11ba98
leaq 0xbb8(%rsp), %rdi
leaq 0xb70(%rsp), %rsi
leaq 0xb48(%rsp), %rdx
callq 0x11cae0
movq %rax, 0x20(%rsp)
jmp 0x11babc
leaq 0xb1f(%rsp), %rdi
movq %rdi, 0x18(%rsp)
callq 0x1146b0
movq 0x18(%rsp), %rdx
leaq 0x349ad1(%rip), %rsi    # 0x4655ab
leaq 0xb20(%rsp), %rdi
callq 0x11b7c0
jmp 0x11bae9
movq 0x20(%rsp), %rdi
leaq 0xb20(%rsp), %rsi
callq 0x11cb30
movq %rax, 0x10(%rsp)
jmp 0x11bb02
movq 0x10(%rsp), %rsi
leaq 0xc48(%rsp), %rdi
xorl %edx, %edx
callq 0x11ca10
jmp 0x11bb18
leaq 0xb20(%rsp), %rdi
callq 0x1147f8
leaq 0xb1f(%rsp), %rdi
callq 0x1147e0
leaq 0xb48(%rsp), %rdi
callq 0x1147f8
leaq 0xb47(%rsp), %rdi
callq 0x1147e0
leaq 0xb70(%rsp), %rdi
callq 0x1147f8
leaq 0xb6f(%rsp), %rdi
callq 0x1147e0
leaq 0xbb8(%rsp), %rdi
callq 0x11cb60
leaq 0xb98(%rsp), %rdi
callq 0x1147f8
leaq 0xb97(%rsp), %rdi
callq 0x1147e0
leaq 0xaf7(%rsp), %rdi
movq %rdi, 0x8(%rsp)
callq 0x1146b0
movq 0x8(%rsp), %rdx
leaq 0x349b5d(%rip), %rsi    # 0x465708
leaq 0xaf8(%rsp), %rdi
callq 0x11b7c0
jmp 0x11bbba
leaq 0xaf7(%rsp), %rdi
callq 0x1147e0
leaq 0xad0(%rsp), %rdi
callq 0x11cba0
jmp 0x11bbd6
leaq 0xad0(%rsp), %rdi
leaq 0x1680(%rsp), %rsi
callq 0x11cc50
jmp 0x11bbed
leaq 0x58(%rsp), %rdi
movl $0x7f, %esi
callq 0x11cd00
jmp 0x11bbfe
leaq 0x1a8(%rsp), %rdi
leaq 0x58(%rsp), %rsi
callq 0x11ce30
jmp 0x11bc12
leaq 0x58(%rsp), %rdi
callq 0x11d660
leaq 0x1a8(%rsp), %rdi
leaq 0xaf8(%rsp), %rsi
leaq 0xad0(%rsp), %rdx
callq 0x11d6d0
jmp 0x11bc3b
leaq 0xad0(%rsp), %rdi
callq 0x11df60
jmp 0x11bc4a
leaq 0x1a8(%rsp), %rdi
callq 0x11df80
leaq 0xad0(%rsp), %rdi
callq 0x11e180
leaq 0xaf8(%rsp), %rdi
callq 0x1147f8
leaq 0xc48(%rsp), %rdi
callq 0x11e1c0
leaq 0x1680(%rsp), %rdi
callq 0x11e250
leaq 0x1688(%rsp), %rdi
callq 0x11e2d0
leaq 0x2a80(%rsp), %rdi
callq 0x11e2e0
addq $0x2ae8, %rsp           # imm = 0x2AE8
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a50(%rsp)
movl %eax, 0x2a4c(%rsp)
jmp 0x11bce4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a50(%rsp)
movl %eax, 0x2a4c(%rsp)
leaq 0x2a60(%rsp), %rdi
callq 0x1147f8
leaq 0x2a5f(%rsp), %rdi
callq 0x1147e0
jmp 0x11bfcf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a50(%rsp)
movl %eax, 0x2a4c(%rsp)
jmp 0x11bfc2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a50(%rsp)
movl %eax, 0x2a4c(%rsp)
jmp 0x11bfb5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a50(%rsp)
movl %eax, 0x2a4c(%rsp)
jmp 0x11bd5f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a50(%rsp)
movl %eax, 0x2a4c(%rsp)
leaq 0x1660(%rsp), %rdi
callq 0x1147f8
leaq 0x165f(%rsp), %rdi
callq 0x1147e0
jmp 0x11bfa8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a50(%rsp)
movl %eax, 0x2a4c(%rsp)
jmp 0x11bda8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a50(%rsp)
movl %eax, 0x2a4c(%rsp)
leaq 0x1638(%rsp), %rdi
callq 0x1147f8
leaq 0x1637(%rsp), %rdi
callq 0x1147e0
jmp 0x11bfa8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a50(%rsp)
movl %eax, 0x2a4c(%rsp)
jmp 0x11bfa8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a50(%rsp)
movl %eax, 0x2a4c(%rsp)
jmp 0x11bedc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a50(%rsp)
movl %eax, 0x2a4c(%rsp)
jmp 0x11becf
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a50(%rsp)
movl %eax, 0x2a4c(%rsp)
jmp 0x11beb5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a50(%rsp)
movl %eax, 0x2a4c(%rsp)
jmp 0x11be9b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a50(%rsp)
movl %eax, 0x2a4c(%rsp)
jmp 0x11be8e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a50(%rsp)
movl %eax, 0x2a4c(%rsp)
jmp 0x11be81
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a50(%rsp)
movl %eax, 0x2a4c(%rsp)
leaq 0xb20(%rsp), %rdi
callq 0x1147f8
leaq 0xb1f(%rsp), %rdi
callq 0x1147e0
leaq 0xb48(%rsp), %rdi
callq 0x1147f8
leaq 0xb47(%rsp), %rdi
callq 0x1147e0
leaq 0xb70(%rsp), %rdi
callq 0x1147f8
leaq 0xb6f(%rsp), %rdi
callq 0x1147e0
leaq 0xbb8(%rsp), %rdi
callq 0x11cb60
leaq 0xb98(%rsp), %rdi
callq 0x1147f8
leaq 0xb97(%rsp), %rdi
callq 0x1147e0
jmp 0x11bf9b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a50(%rsp)
movl %eax, 0x2a4c(%rsp)
leaq 0xaf7(%rsp), %rdi
callq 0x1147e0
jmp 0x11bf9b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a50(%rsp)
movl %eax, 0x2a4c(%rsp)
jmp 0x11bf8e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a50(%rsp)
movl %eax, 0x2a4c(%rsp)
jmp 0x11bf81
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a50(%rsp)
movl %eax, 0x2a4c(%rsp)
leaq 0x58(%rsp), %rdi
callq 0x11d660
jmp 0x11bf81
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a50(%rsp)
movl %eax, 0x2a4c(%rsp)
leaq 0x1a8(%rsp), %rdi
callq 0x11df80
leaq 0xad0(%rsp), %rdi
callq 0x11e180
leaq 0xaf8(%rsp), %rdi
callq 0x1147f8
leaq 0xc48(%rsp), %rdi
callq 0x11e1c0
leaq 0x1680(%rsp), %rdi
callq 0x11e250
leaq 0x1688(%rsp), %rdi
callq 0x11e2d0
leaq 0x2a80(%rsp), %rdi
callq 0x11e2e0
movq 0x2a50(%rsp), %rdi
callq 0x114480
nopl (%rax)