// File: /workspace/github_cpp_makefile_star2_O2/ArashPartow[P]exprtk/exprtk_simple_example_09.cpp
// Function: void primes<double>()
void primes()
{
   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;

   T x = T(0);

   symbol_table_t symbol_table;

   symbol_table.add_constants();
   symbol_table.add_variable("x",x);

   compositor_t compositor(symbol_table);

   //Mode 1 - if statement based
   compositor.add(
      function_t("is_prime_impl1")
      .vars("x", "y")
      .expression
      (
         " if (y == 1,true,                "
         "    if (0 == (x % y),false,      "
         "       is_prime_impl1(x,y - 1))) "
      ));

   compositor.add(
      function_t("is_prime1")
      .var("x")
      .expression
      (
         " if (frac(x) != 0)                                   "
         "    return [false];                                  "
         " else if (x <= 0)                                    "
         "    return [false];                                  "
         " else                                                "
         "    is_prime_impl1(x,min(x - 1,trunc(sqrt(x)) + 1)); "
      ));

   //Mode 2 - switch statement based
   compositor.add(
      function_t("is_prime_impl2")
      .vars("x", "y")
      .expression
      (
         " switch                                          "
         " {                                               "
         "    case y == 1       : true;                    "
         "    case (x % y) == 0 : false;                   "
         "    default           : is_prime_impl2(x,y - 1); "
         " }                                               "
      ));

   compositor.add(
      function_t("is_prime2")
      .var("x")
      .expression
      (
         " switch                                                                  "
         " {                                                                       "
         "    case x <= 0       : false;                                           "
         "    case frac(x) != 0 : false;                                           "
         "    default           : is_prime_impl2(x,min(x - 1,trunc(sqrt(x)) + 1)); "
         " }                                                                       "
      ));

   //Mode 3 - switch statement and for-loop based
   compositor.add(
      function_t("is_prime3")
      .var("x")
      .expression
      (
         " switch                                              "
         " {                                                   "
         "    case x <= 1       : return [false];              "
         "    case frac(x) != 0 : return [false];              "
         "    case x == 2       : return [true ];              "
         " };                                                  "
         "                                                     "
         " var prime_lut[27] :=                                "
         " {                                                   "
         "      2,   3,   5,   7,  11,  13,  17,  19,  23,     "
         "     29,  31,  37,  41,  43,  47,  53,  59,  61,     "
         "     67,  71,  73,  79,  83,  89,  97, 101, 103      "
         " };                                                  "
         "                                                     "
         " var upper_bound := min(x - 1, trunc(sqrt(x)) + 1);  "
         "                                                     "
         " for (var i := 0; i < prime_lut[]; i += 1)           "
         " {                                                   "
         "    if (prime_lut[i] >= upper_bound)                 "
         "       return [true];                                "
         "    else if ((x % prime_lut[i]) == 0)                "
         "       return [false];                               "
         " };                                                  "
         "                                                     "
         " var lower_bound := prime_lut[prime_lut[] - 1] + 2;  "
         "                                                     "
         " for (var i := lower_bound; i < upper_bound; i += 2) "
         " {                                                   "
         "    if ((x % i) == 0)                                "
         "    {                                                "
         "       return [false];                               "
         "    }                                                "
         " };                                                  "
         "                                                     "
         " return [true];                                      "
      ));

   std::string expression_str1 = "is_prime1(x)";
   std::string expression_str2 = "is_prime2(x)";
   std::string expression_str3 = "is_prime3(x)";

   expression_t expression1;
   expression_t expression2;
   expression_t expression3;
   expression1.register_symbol_table(symbol_table);
   expression2.register_symbol_table(symbol_table);
   expression3.register_symbol_table(symbol_table);

   parser_t parser;

   parser.compile(expression_str1, expression1);
   parser.compile(expression_str2, expression2);
   parser.compile(expression_str3, expression3);

   for (std::size_t i = 0; i < 15000; ++i)
   {
      x = static_cast<T>(i);

      const T result1 = expression1.value();
      const T result2 = expression2.value();
      const T result3 = expression3.value();

      const bool results_concur = (result1 == result2) &&
                                  (result1 == result3) ;

      printf("%03d  Result1: %c  Result2: %c  Result3: %c  "
             "Results Concur: %c\n",
             static_cast<unsigned int>(i),
             (result1 == T(1)) ? 'T' : 'F',
             (result2 == T(1)) ? 'T' : 'F',
             (result3 == T(1)) ? 'T' : 'F',
             (results_concur)  ? 'T' : 'F');
   }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %rbx
subq $0x1548, %rsp           # imm = 0x1548
andq $0x0, 0x70(%rsp)
leaq 0x8(%rsp), %rbx
pushq $0x1
popq %rsi
movq %rbx, %rdi
callq 0x112c22
movq %rbx, %rdi
callq 0x112c46
leaq 0x131d40(%rip), %rsi    # 0x244075
leaq 0xb60(%rsp), %rdi
leaq 0x238(%rsp), %rdx
callq 0x1122c8
leaq 0x8(%rsp), %rdi
leaq 0xb60(%rsp), %rsi
leaq 0x70(%rsp), %rdx
xorl %ecx, %ecx
callq 0x112c6c
leaq 0xb60(%rsp), %rdi
callq 0x1105c8
leaq 0xb60(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x112cd8
leaq 0x131d94(%rip), %rsi    # 0x24411d
leaq 0xe8(%rsp), %rdi
leaq 0x98(%rsp), %rdx
callq 0x1122c8
leaq 0x238(%rsp), %rdi
leaq 0xe8(%rsp), %rsi
callq 0x112df6
leaq 0x131cbb(%rip), %rsi    # 0x244075
leaq 0x30(%rsp), %rdi
leaq 0x78(%rsp), %rdx
callq 0x1122c8
leaq 0x132b7a(%rip), %rsi    # 0x244f4a
leaq 0x10(%rsp), %rdi
leaq 0xc8(%rsp), %rdx
callq 0x1122c8
leaq 0x238(%rsp), %rdi
leaq 0x30(%rsp), %rsi
leaq 0x10(%rsp), %rdx
callq 0x112e42
movq %rax, %rbx
leaq 0x131d29(%rip), %rsi    # 0x24412c
leaq 0x50(%rsp), %rdi
leaq 0x7(%rsp), %rdx
callq 0x1122c8
leaq 0x20(%rbx), %rdi
leaq 0x50(%rsp), %rsi
callq 0x110550
leaq 0xb60(%rsp), %rdi
movq %rbx, %rsi
xorl %edx, %edx
callq 0x112de6
leaq 0x50(%rsp), %rdi
callq 0x1105c8
leaq 0x10(%rsp), %rdi
callq 0x1105c8
leaq 0x30(%rsp), %rdi
callq 0x1105c8
leaq 0x238(%rsp), %rdi
callq 0x112e6e
leaq 0xe8(%rsp), %rdi
callq 0x1105c8
leaq 0x131d1f(%rip), %rsi    # 0x244190
leaq 0xe8(%rsp), %rdi
leaq 0x50(%rsp), %rdx
callq 0x1122c8
leaq 0x238(%rsp), %rdi
leaq 0xe8(%rsp), %rsi
callq 0x112df6
leaq 0x131bd6(%rip), %rsi    # 0x244075
leaq 0x30(%rsp), %rdi
leaq 0x98(%rsp), %rdx
callq 0x1122c8
leaq 0x278(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0x11d8d8
leaq 0x131cd0(%rip), %rsi    # 0x24419a
leaq 0x10(%rsp), %rdi
leaq 0x78(%rsp), %rdx
callq 0x1122c8
leaq 0x258(%rsp), %rdi
leaq 0x10(%rsp), %rsi
callq 0x110550
leaq 0xb60(%rsp), %rdi
leaq 0x238(%rsp), %rsi
xorl %edx, %edx
callq 0x112de6
leaq 0x10(%rsp), %rdi
callq 0x1105c8
leaq 0x30(%rsp), %rdi
callq 0x1105c8
leaq 0x238(%rsp), %rdi
callq 0x112e6e
leaq 0xe8(%rsp), %rdi
callq 0x1105c8
leaq 0x131da2(%rip), %rsi    # 0x2442d9
leaq 0xe8(%rsp), %rdi
leaq 0x98(%rsp), %rdx
callq 0x1122c8
leaq 0x238(%rsp), %rdi
leaq 0xe8(%rsp), %rsi
callq 0x112df6
leaq 0x131b0d(%rip), %rsi    # 0x244075
leaq 0x30(%rsp), %rdi
leaq 0x78(%rsp), %rdx
callq 0x1122c8
leaq 0x1329cc(%rip), %rsi    # 0x244f4a
leaq 0x10(%rsp), %rdi
leaq 0xc8(%rsp), %rdx
callq 0x1122c8
leaq 0x238(%rsp), %rdi
leaq 0x30(%rsp), %rsi
leaq 0x10(%rsp), %rdx
callq 0x112e42
movq %rax, %rbx
leaq 0x131d37(%rip), %rsi    # 0x2442e8
leaq 0x50(%rsp), %rdi
leaq 0x7(%rsp), %rdx
callq 0x1122c8
leaq 0x20(%rbx), %rdi
leaq 0x50(%rsp), %rsi
callq 0x110550
leaq 0xb60(%rsp), %rdi
movq %rbx, %rsi
xorl %edx, %edx
callq 0x112de6
leaq 0x50(%rsp), %rdi
callq 0x1105c8
leaq 0x10(%rsp), %rdi
callq 0x1105c8
leaq 0x30(%rsp), %rdi
callq 0x1105c8
leaq 0x238(%rsp), %rdi
callq 0x112e6e
leaq 0xe8(%rsp), %rdi
callq 0x1105c8
leaq 0x131df0(%rip), %rsi    # 0x24440f
leaq 0xe8(%rsp), %rdi
leaq 0x50(%rsp), %rdx
callq 0x1122c8
leaq 0x238(%rsp), %rdi
leaq 0xe8(%rsp), %rsi
callq 0x112df6
leaq 0x131a28(%rip), %rsi    # 0x244075
leaq 0x30(%rsp), %rdi
leaq 0x98(%rsp), %rdx
callq 0x1122c8
leaq 0x278(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0x11d8d8
leaq 0x131da1(%rip), %rsi    # 0x244419
leaq 0x10(%rsp), %rdi
leaq 0x78(%rsp), %rdx
callq 0x1122c8
leaq 0x258(%rsp), %rdi
leaq 0x10(%rsp), %rsi
callq 0x110550
leaq 0xb60(%rsp), %rdi
leaq 0x238(%rsp), %rsi
xorl %edx, %edx
callq 0x112de6
leaq 0x10(%rsp), %rdi
callq 0x1105c8
leaq 0x30(%rsp), %rdi
callq 0x1105c8
leaq 0x238(%rsp), %rdi
callq 0x112e6e
leaq 0xe8(%rsp), %rdi
callq 0x1105c8
leaq 0x131eeb(%rip), %rsi    # 0x2445d0
leaq 0xe8(%rsp), %rdi
leaq 0x50(%rsp), %rdx
callq 0x1122c8
leaq 0x238(%rsp), %rdi
leaq 0xe8(%rsp), %rsi
callq 0x112df6
leaq 0x131962(%rip), %rsi    # 0x244075
leaq 0x30(%rsp), %rdi
leaq 0x98(%rsp), %rdx
callq 0x1122c8
leaq 0x278(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0x11d8d8
leaq 0x131e9c(%rip), %rsi    # 0x2445da
leaq 0x10(%rsp), %rdi
leaq 0x78(%rsp), %rdx
callq 0x1122c8
leaq 0x258(%rsp), %rdi
leaq 0x10(%rsp), %rsi
callq 0x110550
leaq 0xb60(%rsp), %rdi
leaq 0x238(%rsp), %rsi
xorl %edx, %edx
callq 0x112de6
leaq 0x10(%rsp), %rdi
callq 0x1105c8
leaq 0x30(%rsp), %rdi
callq 0x1105c8
leaq 0x238(%rsp), %rdi
callq 0x112e6e
leaq 0xe8(%rsp), %rdi
callq 0x1105c8
leaq 0x13256f(%rip), %rsi    # 0x244d1a
leaq 0x30(%rsp), %rdi
leaq 0x238(%rsp), %rdx
callq 0x1122c8
leaq 0x132563(%rip), %rsi    # 0x244d27
leaq 0x10(%rsp), %rdi
leaq 0x238(%rsp), %rdx
callq 0x1122c8
leaq 0x132557(%rip), %rsi    # 0x244d34
leaq 0x50(%rsp), %rdi
leaq 0x238(%rsp), %rdx
callq 0x1122c8
leaq 0x98(%rsp), %rdi
callq 0x112e8e
leaq 0x78(%rsp), %rdi
callq 0x112e8e
leaq 0xc8(%rsp), %rdi
callq 0x112e8e
leaq 0x98(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x112eee
leaq 0x78(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x112eee
leaq 0xc8(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x112eee
leaq 0xe8(%rsp), %rdi
pushq $0x7f
popq %rsi
callq 0x112f4a
leaq 0x238(%rsp), %rdi
leaq 0xe8(%rsp), %rsi
callq 0x11305a
leaq 0xe8(%rsp), %rdi
callq 0x113672
leaq 0x238(%rsp), %rdi
leaq 0x30(%rsp), %rsi
leaq 0x98(%rsp), %rdx
callq 0x1136ba
leaq 0x238(%rsp), %rdi
leaq 0x10(%rsp), %rsi
leaq 0x78(%rsp), %rdx
callq 0x1136ba
leaq 0x238(%rsp), %rdi
leaq 0x50(%rsp), %rsi
leaq 0xc8(%rsp), %rdx
callq 0x1136ba
pushq $0x46
popq %rbp
pushq $0x54
popq %r15
leaq 0x132470(%rip), %rbx    # 0x244d41
xorl %r14d, %r14d
cmpq $0x3a98, %r14           # imm = 0x3A98
je 0x1129a4
cvtsi2sd %r14, %xmm0
movsd %xmm0, 0x70(%rsp)
movq 0x98(%rsp), %rax
movq 0x8(%rax), %rdi
movq (%rdi), %rax
callq *0x18(%rax)
movsd %xmm0, 0xc0(%rsp)
movq 0x78(%rsp), %rax
movq 0x8(%rax), %rdi
movq (%rdi), %rax
callq *0x18(%rax)
movsd %xmm0, 0xb8(%rsp)
movq 0xc8(%rsp), %rax
movq 0x8(%rax), %rdi
movq (%rdi), %rax
callq *0x18(%rax)
movsd 0x12c6cf(%rip), %xmm1   # 0x23f008
movsd 0xc0(%rsp), %xmm2
ucomisd %xmm1, %xmm2
movl %r15d, %edx
cmovnel %ebp, %edx
cmovpl %ebp, %edx
movsd 0xb8(%rsp), %xmm3
ucomisd %xmm1, %xmm3
movl %r15d, %ecx
cmovnel %ebp, %ecx
cmovpl %ebp, %ecx
ucomisd %xmm1, %xmm0
movl %r15d, %r8d
cmovnel %ebp, %r8d
cmovpl %ebp, %r8d
ucomisd %xmm0, %xmm2
movl %r15d, %r9d
cmovnel %ebp, %r9d
cmovpl %ebp, %r9d
ucomisd %xmm3, %xmm2
cmovnel %ebp, %r9d
cmovpl %ebp, %r9d
movq %rbx, %rdi
movl %r14d, %esi
xorl %eax, %eax
callq 0x110060
incq %r14
jmp 0x1128d4
leaq 0x238(%rsp), %rdi
callq 0x113b3c
leaq 0xc8(%rsp), %rdi
callq 0x113c76
leaq 0x78(%rsp), %rdi
callq 0x113c76
leaq 0x98(%rsp), %rdi
callq 0x113c76
leaq 0x50(%rsp), %rdi
callq 0x1105c8
leaq 0x10(%rsp), %rdi
callq 0x1105c8
leaq 0x30(%rsp), %rdi
callq 0x1105c8
leaq 0xb60(%rsp), %rdi
callq 0x113c8c
leaq 0x8(%rsp), %rdi
callq 0x113ce0
addq $0x1548, %rsp           # imm = 0x1548
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %rbx
leaq 0xe8(%rsp), %rdi
callq 0x113672
jmp 0x112b20
jmp 0x112b07
movq %rax, %rbx
jmp 0x112b2d
movq %rax, %rbx
jmp 0x112b37
movq %rax, %rbx
jmp 0x112b44
movq %rax, %rbx
jmp 0x112b4e
movq %rax, %rbx
jmp 0x112b58
jmp 0x112a99
jmp 0x112a8a
jmp 0x112a8a
jmp 0x112a8f
jmp 0x112a94
jmp 0x112a99
jmp 0x112a8a
jmp 0x112a8a
jmp 0x112a8f
jmp 0x112a94
jmp 0x112a99
jmp 0x112ac8
jmp 0x112ac8
jmp 0x112a8a
jmp 0x112a8f
jmp 0x112a94
jmp 0x112a99
jmp 0x112a8a
jmp 0x112a8a
jmp 0x112a8f
jmp 0x112a94
jmp 0x112a99
jmp 0x112ac8
jmp 0x112ac8
movq %rax, %rbx
jmp 0x112ae4
movq %rax, %rbx
jmp 0x112aee
movq %rax, %rbx
jmp 0x112afb
movq %rax, %rbx
jmp 0x112b62
jmp 0x112aba
movq %rax, %rbx
leaq 0xb60(%rsp), %rdi
callq 0x1105c8
jmp 0x112b6f
jmp 0x112aba
movq %rax, %rbx
jmp 0x112b6f
jmp 0x112ac8
jmp 0x112ac8
jmp 0x112acd
movq %rax, %rbx
jmp 0x112ada
movq %rax, %rbx
leaq 0x50(%rsp), %rdi
callq 0x1105c8
leaq 0x10(%rsp), %rdi
callq 0x1105c8
leaq 0x30(%rsp), %rdi
callq 0x1105c8
leaq 0x238(%rsp), %rdi
callq 0x112e6e
leaq 0xe8(%rsp), %rdi
jmp 0x112b5d
jmp 0x112b10
movq %rax, %rbx
jmp 0x112b20
jmp 0x112b10
jmp 0x112b10
movq %rax, %rbx
leaq 0x238(%rsp), %rdi
callq 0x113b3c
leaq 0xc8(%rsp), %rdi
callq 0x113c76
leaq 0x78(%rsp), %rdi
callq 0x113c76
leaq 0x98(%rsp), %rdi
callq 0x113c76
leaq 0x50(%rsp), %rdi
callq 0x1105c8
leaq 0x10(%rsp), %rdi
callq 0x1105c8
leaq 0x30(%rsp), %rdi
callq 0x1105c8
leaq 0xb60(%rsp), %rdi
callq 0x113c8c
leaq 0x8(%rsp), %rdi
callq 0x113ce0
movq %rbx, %rdi
callq 0x110310