// File: /workspace/github_cpp_makefile_star2_O2/ArashPartow[P]exprtk-extras/exprtk_factorize_fermat.cpp
// Function: void factorize_fermats_method<double>()
void factorize_fermats_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;

   // Form: n = p*q where p,q are prime
   T composites[] =
   {
       199203677,  779234623,  843093203,  883543291, 1197162971, 1282615157, 1368190717,
      1552390397, 1765737859, 1800091571, 1878769589, 1993904873, 2257133471, 2520523529,
      2579094799, 2853450949, 2935025369, 3095780533, 3164132249, 3408963511, 4260042859,
      4608613981, 4654875857, 5085931997, 6064982771, 7278175081, 7289187463, 9206112101
   };

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

   symbol_table_t symbol_table;

   symbol_table.add_vector  ("composites", composites);
   symbol_table.add_function("println"   , println   );

   compositor_t compositor(symbol_table);

   compositor.add(function_t()
      .name("is_square")
      .var("x")
      .expression
      (
         " var s := sqrt(x);  "
         " var t := trunc(s); "
         " (s - t) == 0;      "
      ));

   compositor.add(function_t()
      .name("fermat")
      .var("n")
      .expression
      (
         " if (n == 0)                     "
         " {                               "
         "    return [0];                  "
         " }                               "
         " else if ((n % 2) == 0)          "
         " {                               "
         "    return [n / 2];              "
         " };                              "
         "                                 "
         " var a := ceil(sqrt(n));         "
         "                                 "
         " while (not(is_square(a^2 - n))) "
         " {                               "
         "    a += 1;                      "
         " };                              "
         "                                 "
         " var b := sqrt(a^2 - n);         "
         "                                 "
         " a - b;                          "
      ));

   const std::string factorize_composites_program =
      " for (var i := 0; i < composites[]; i += 1)                               "
      " {                                                                        "
      "    var n       := composites[i];                                         "
      "    var factor0 := fermat(n);                                             "
      "    var factor1 := n / factor0;                                           "
      "                                                                          "
      "    if ((factor0 * factor1 == n) and (factor0 != 1))                      "
      "    {                                                                     "
      "       println('n: ', n, ' factors: { ', factor0 ,' , ', factor1 ,' } '); "
      "    }                                                                     "
      "    else                                                                  "
      "    {                                                                     "
      "       println('failed to factorize ', n);                                "
      "    }                                                                     "
      " }                                                                        "
      "                                                                          ";
   expression_t expression;
   expression.register_symbol_table(symbol_table);

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

   expression.value();
}

// Assembly:
pushq %rbx
subq $0x1600, %rsp           # imm = 0x1600
leaq 0x13610e(%rip), %rsi    # 0x249430
leaq 0xb30(%rsp), %rdi
movl $0xe0, %edx
callq 0x111070
leaq 0x130de2(%rip), %rsi    # 0x24411d
leaq 0xc18(%rsp), %rdi
leaq 0x208(%rsp), %rdx
callq 0x1132d8
leaq 0x50(%rsp), %rdi
leaq 0xc18(%rsp), %rsi
callq 0x113844
leaq 0xc18(%rsp), %rdi
callq 0x1115d8
leaq 0x8(%rsp), %rdi
pushq $0x1
popq %rsi
callq 0x1138d6
leaq 0x130da1(%rip), %rsi    # 0x244124
leaq 0xc18(%rsp), %rdi
leaq 0x208(%rsp), %rdx
callq 0x1132d8
leaq 0x8(%rsp), %rdi
leaq 0xc18(%rsp), %rsi
leaq 0xb30(%rsp), %rdx
callq 0x1138fa
leaq 0xc18(%rsp), %rdi
callq 0x1115d8
leaq 0x130d69(%rip), %rsi    # 0x24412f
leaq 0xc18(%rsp), %rdi
leaq 0x208(%rsp), %rdx
callq 0x1132d8
leaq 0x8(%rsp), %rdi
leaq 0xc18(%rsp), %rsi
leaq 0x50(%rsp), %rdx
callq 0x11395c
leaq 0xc18(%rsp), %rdi
callq 0x1115d8
leaq 0xc18(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x113a24
leaq 0x208(%rsp), %rdi
callq 0x113b42
leaq 0x130d12(%rip), %rsi    # 0x244137
leaq 0xb8(%rsp), %rdi
leaq 0x7(%rsp), %rdx
callq 0x1132d8
leaq 0x208(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
callq 0x111550
leaq 0x130c22(%rip), %rsi    # 0x244075
leaq 0x30(%rsp), %rdi
leaq 0x6(%rsp), %rdx
callq 0x1132d8
leaq 0x248(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0x11e80a
leaq 0x130cc6(%rip), %rsi    # 0x244141
leaq 0x10(%rsp), %rdi
leaq 0x5(%rsp), %rdx
callq 0x1132d8
leaq 0x228(%rsp), %rdi
leaq 0x10(%rsp), %rsi
callq 0x111550
leaq 0xc18(%rsp), %rdi
leaq 0x208(%rsp), %rsi
xorl %edx, %edx
callq 0x113b32
leaq 0x10(%rsp), %rdi
callq 0x1115d8
leaq 0x30(%rsp), %rdi
callq 0x1115d8
leaq 0xb8(%rsp), %rdi
callq 0x1115d8
leaq 0x208(%rsp), %rdi
callq 0x113b9a
leaq 0x208(%rsp), %rdi
callq 0x113b42
leaq 0x130c89(%rip), %rsi    # 0x24417e
leaq 0xb8(%rsp), %rdi
leaq 0x7(%rsp), %rdx
callq 0x1132d8
leaq 0x208(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
callq 0x111550
leaq 0x130ac5(%rip), %rsi    # 0x243fe8
leaq 0x30(%rsp), %rdi
leaq 0x6(%rsp), %rdx
callq 0x1132d8
leaq 0x248(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0x11e80a
leaq 0x130c3a(%rip), %rsi    # 0x244185
leaq 0x10(%rsp), %rdi
leaq 0x5(%rsp), %rdx
callq 0x1132d8
leaq 0x228(%rsp), %rdi
leaq 0x10(%rsp), %rsi
callq 0x111550
leaq 0xc18(%rsp), %rdi
leaq 0x208(%rsp), %rsi
xorl %edx, %edx
callq 0x113b32
leaq 0x10(%rsp), %rdi
callq 0x1115d8
leaq 0x30(%rsp), %rdi
callq 0x1115d8
leaq 0xb8(%rsp), %rdi
callq 0x1115d8
leaq 0x208(%rsp), %rdi
callq 0x113b9a
leaq 0x130e41(%rip), %rsi    # 0x2443f9
leaq 0x30(%rsp), %rdi
leaq 0x208(%rsp), %rdx
callq 0x1132d8
leaq 0x10(%rsp), %rdi
callq 0x113bba
leaq 0x10(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x113c1a
leaq 0xb8(%rsp), %rdi
pushq $0x7f
popq %rsi
callq 0x113c76
leaq 0x208(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
callq 0x113d86
leaq 0xb8(%rsp), %rdi
callq 0x11439e
leaq 0x208(%rsp), %rdi
leaq 0x30(%rsp), %rsi
leaq 0x10(%rsp), %rdx
callq 0x1143e6
movq 0x10(%rsp), %rax
movq 0x8(%rax), %rdi
movq (%rdi), %rax
callq *0x18(%rax)
leaq 0x208(%rsp), %rdi
callq 0x114868
leaq 0x10(%rsp), %rdi
callq 0x1149a2
leaq 0x30(%rsp), %rdi
callq 0x1115d8
leaq 0xc18(%rsp), %rdi
callq 0x1149b8
leaq 0x8(%rsp), %rdi
callq 0x114a0c
leaq 0x50(%rsp), %rdi
callq 0x114a4e
addq $0x1600, %rsp           # imm = 0x1600
popq %rbx
retq
movq %rax, %rbx
leaq 0xb8(%rsp), %rdi
callq 0x11439e
jmp 0x113731
jmp 0x11369d
movq %rax, %rbx
jmp 0x113731
movq %rax, %rbx
jmp 0x11373b
jmp 0x1136d7
jmp 0x1136bd
jmp 0x1136bd
jmp 0x1136c7
jmp 0x1136c7
jmp 0x1136cf
jmp 0x1136d7
jmp 0x1136bd
movq %rax, %rbx
jmp 0x113756
jmp 0x1136c7
movq %rax, %rbx
jmp 0x113760
movq %rax, %rbx
jmp 0x11376d
movq %rax, %rbx
jmp 0x11377a
jmp 0x1136fa
jmp 0x1136e5
jmp 0x1136fa
movq %rax, %rbx
leaq 0xc18(%rsp), %rdi
callq 0x1115d8
jmp 0x113787
movq %rax, %rbx
jmp 0x113787
movq %rax, %rbx
jmp 0x113791
movq %rax, %rbx
leaq 0xc18(%rsp), %rdi
callq 0x1115d8
jmp 0x11379b
movq %rax, %rbx
jmp 0x11379b
movq %rax, %rbx
leaq 0x208(%rsp), %rdi
callq 0x114868
leaq 0x10(%rsp), %rdi
callq 0x1149a2
leaq 0x30(%rsp), %rdi
callq 0x1115d8
jmp 0x11377a
jmp 0x113749
movq %rax, %rbx
leaq 0x10(%rsp), %rdi
callq 0x1115d8
leaq 0x30(%rsp), %rdi
callq 0x1115d8
leaq 0xb8(%rsp), %rdi
callq 0x1115d8
leaq 0x208(%rsp), %rdi
callq 0x113b9a
leaq 0xc18(%rsp), %rdi
callq 0x1149b8
leaq 0x8(%rsp), %rdi
callq 0x114a0c
leaq 0x50(%rsp), %rdi
callq 0x114a4e
movq %rbx, %rdi
callq 0x111310