// File: /workspace/github_cpp_makefile_star2_O2/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:
pushq %rbx
subq $0x2900, %rsp           # imm = 0x2900
leaq 0x131db7(%rip), %rsi    # 0x245129
leaq 0x1540(%rsp), %rdi
leaq 0x230(%rsp), %rdx
callq 0x113328
leaq 0x78(%rsp), %rdi
leaq 0x1540(%rsp), %rsi
callq 0x1137d8
leaq 0x1540(%rsp), %rdi
callq 0x111628
leaq 0x1540(%rsp), %rdi
callq 0x11386a
leaq 0x8(%rsp), %rdi
pushq $0x1
popq %rsi
callq 0x113946
leaq 0x131d69(%rip), %rsi    # 0x245130
leaq 0x230(%rsp), %rdi
leaq 0xc18(%rsp), %rdx
callq 0x113328
leaq 0x8(%rsp), %rdi
leaq 0x230(%rsp), %rsi
leaq 0x78(%rsp), %rdx
callq 0x11396a
leaq 0x230(%rsp), %rdi
callq 0x111628
leaq 0x131d31(%rip), %rsi    # 0x245138
leaq 0x230(%rsp), %rdi
leaq 0xc18(%rsp), %rdx
callq 0x113328
leaq 0x8(%rsp), %rdi
leaq 0x230(%rsp), %rsi
leaq 0x1540(%rsp), %rdx
callq 0x113a32
leaq 0x230(%rsp), %rdi
callq 0x111628
leaq 0x8(%rsp), %rdi
callq 0x113a92
leaq 0x230(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x113ab8
leaq 0x131cd9(%rip), %rsi    # 0x24513f
leaq 0xe0(%rsp), %rdi
leaq 0x17(%rsp), %rdx
callq 0x113328
leaq 0xc18(%rsp), %rdi
leaq 0xe0(%rsp), %rsi
callq 0x113bd6
leaq 0x131cbf(%rip), %rsi    # 0x245153
leaq 0x38(%rsp), %rdi
leaq 0x16(%rsp), %rdx
callq 0x113328
leaq 0x131cae(%rip), %rsi    # 0x245158
leaq 0x18(%rsp), %rdi
leaq 0x15(%rsp), %rdx
callq 0x113328
leaq 0xc18(%rsp), %rdi
leaq 0x38(%rsp), %rsi
leaq 0x18(%rsp), %rdx
callq 0x113c22
movq %rax, %rbx
leaq 0x131c85(%rip), %rsi    # 0x24515f
leaq 0x58(%rsp), %rdi
leaq 0x14(%rsp), %rdx
callq 0x113328
leaq 0x20(%rbx), %rdi
leaq 0x58(%rsp), %rsi
callq 0x1115a0
leaq 0x230(%rsp), %rdi
movq %rbx, %rsi
xorl %edx, %edx
callq 0x113bc6
leaq 0x58(%rsp), %rdi
callq 0x111628
leaq 0x18(%rsp), %rdi
callq 0x111628
leaq 0x38(%rsp), %rdi
callq 0x111628
leaq 0xc18(%rsp), %rdi
callq 0x113c4e
leaq 0xe0(%rsp), %rdi
callq 0x111628
leaq 0x131d74(%rip), %rsi    # 0x2452bc
leaq 0x38(%rsp), %rdi
leaq 0xc18(%rsp), %rdx
callq 0x113328
leaq 0x18(%rsp), %rdi
callq 0x113c6e
leaq 0x18(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x113cce
leaq 0xe0(%rsp), %rdi
pushq $0x7f
popq %rsi
callq 0x113d2a
leaq 0xc18(%rsp), %rdi
leaq 0xe0(%rsp), %rsi
callq 0x113e3a
leaq 0xe0(%rsp), %rdi
callq 0x114452
leaq 0xc18(%rsp), %rdi
leaq 0x38(%rsp), %rsi
leaq 0x18(%rsp), %rdx
callq 0x11449a
movq 0x18(%rsp), %rax
movq 0x8(%rax), %rdi
movq (%rdi), %rax
callq *0x18(%rax)
leaq 0xc18(%rsp), %rdi
callq 0x11491c
leaq 0x18(%rsp), %rdi
callq 0x114a56
leaq 0x38(%rsp), %rdi
callq 0x111628
leaq 0x230(%rsp), %rdi
callq 0x114a6c
leaq 0x8(%rsp), %rdi
callq 0x114ac0
leaq 0x78(%rsp), %rdi
callq 0x114b04
addq $0x2900, %rsp           # imm = 0x2900
popq %rbx
retq
movq %rax, %rbx
leaq 0xe0(%rsp), %rdi
callq 0x114452
jmp 0x1136c2
jmp 0x11362d
movq %rax, %rbx
jmp 0x1136c2
movq %rax, %rbx
jmp 0x1136cc
jmp 0x113661
jmp 0x113641
movq %rax, %rbx
jmp 0x1136e0
movq %rax, %rbx
jmp 0x1136ea
movq %rax, %rbx
jmp 0x1136f4
movq %rax, %rbx
jmp 0x113701
movq %rax, %rbx
jmp 0x11370e
jmp 0x113686
jmp 0x113686
jmp 0x113671
jmp 0x113686
movq %rax, %rbx
leaq 0x230(%rsp), %rdi
callq 0x111628
jmp 0x11371b
movq %rax, %rbx
jmp 0x11371b
jmp 0x113690
movq %rax, %rbx
jmp 0x113725
movq %rax, %rbx
leaq 0x1540(%rsp), %rdi
callq 0x111628
jmp 0x11372f
movq %rax, %rbx
jmp 0x11372f
movq %rax, %rbx
leaq 0xc18(%rsp), %rdi
callq 0x11491c
leaq 0x18(%rsp), %rdi
callq 0x114a56
leaq 0x38(%rsp), %rdi
jmp 0x113709
movq %rax, %rbx
leaq 0x58(%rsp), %rdi
callq 0x111628
leaq 0x18(%rsp), %rdi
callq 0x111628
leaq 0x38(%rsp), %rdi
callq 0x111628
leaq 0xc18(%rsp), %rdi
callq 0x113c4e
leaq 0xe0(%rsp), %rdi
callq 0x111628
leaq 0x230(%rsp), %rdi
callq 0x114a6c
leaq 0x8(%rsp), %rdi
callq 0x114ac0
leaq 0x78(%rsp), %rdi
callq 0x114b04
movq %rbx, %rdi
callq 0x111340