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

   compositor_t compositor;

   compositor.add(
      function_t("is_prime")
      .var("x")
      .expression
      (
         " switch                                                    "
         " {                                                         "
         "    case x <= 1       : return [false];                    "
         "    case frac(x) != 0 : return [false];                    "
         "    case x == 2       : return [true ];                    "
         "    default           :                                    "
         "    {                                                      "
         "       var prime_lut[81] :=                                "
         "       {                                                   "
         "            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,     "
         "          107, 109, 113, 127, 131, 137, 139, 149, 151,     "
         "          157, 163, 167, 173, 179, 181, 191, 193, 197,     "
         "          199, 211, 223, 227, 229, 233, 239, 241, 251,     "
         "          257, 263, 269, 271, 277, 281, 283, 293, 307,     "
         "          311, 313, 317, 331, 337, 347, 349, 353, 359,     "
         "          367, 373, 379, 383, 389, 397, 401, 409, 419      "
         "       };                                                  "
         "                                                           "
         "       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];                                            "
      ));

   const std::string primes_via_naive_method_program =
      " for (var i := 1; i < 10000; i += 1) "
      " {                                   "
      "    if (is_prime(i))                 "
      "    {                                "
      "       println(i, ' is prime');      "
      "    }                                "
      " };                                  ";

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

   symbol_table_t& symbol_table = compositor.symbol_table();
   symbol_table.add_function("println",println);

   expression_t expression;
   expression.register_symbol_table(symbol_table);

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

   expression.value();
}

// Assembly:
subq $0x16d8, %rsp           # imm = 0x16D8
leaq 0xcf0(%rsp), %rdi
callq 0x11c070
leaq 0xc3f(%rsp), %rdi
movq %rdi, 0x50(%rsp)
callq 0x114660
movq 0x50(%rsp), %rdx
leaq 0x347d03(%rip), %rsi    # 0x463565
leaq 0xc40(%rsp), %rdi
callq 0x11b770
jmp 0x11b871
leaq 0xc60(%rsp), %rdi
leaq 0xc40(%rsp), %rsi
callq 0x11c250
jmp 0x11b888
leaq 0xc07(%rsp), %rdi
movq %rdi, 0x48(%rsp)
callq 0x114660
movq 0x48(%rsp), %rdx
leaq 0x347c17(%rip), %rsi    # 0x4634bd
leaq 0xc08(%rsp), %rdi
callq 0x11b770
jmp 0x11b8b5
leaq 0xc60(%rsp), %rdi
leaq 0xc08(%rsp), %rsi
callq 0x11c2d0
movq %rax, 0x40(%rsp)
jmp 0x11b8d1
leaq 0xbdf(%rsp), %rdi
movq %rdi, 0x38(%rsp)
callq 0x114660
movq 0x38(%rsp), %rdx
leaq 0x347c7f(%rip), %rsi    # 0x46356e
leaq 0xbe0(%rsp), %rdi
callq 0x11b770
jmp 0x11b8fe
movq 0x40(%rsp), %rdi
leaq 0xbe0(%rsp), %rsi
callq 0x11c300
movq %rax, 0x30(%rsp)
jmp 0x11b917
movq 0x30(%rsp), %rsi
leaq 0xcf0(%rsp), %rdi
xorl %edx, %edx
callq 0x11c200
jmp 0x11b92d
leaq 0xbe0(%rsp), %rdi
callq 0x1147a8
leaq 0xbdf(%rsp), %rdi
callq 0x114790
leaq 0xc08(%rsp), %rdi
callq 0x1147a8
leaq 0xc07(%rsp), %rdi
callq 0x114790
leaq 0xc60(%rsp), %rdi
callq 0x11c330
leaq 0xc40(%rsp), %rdi
callq 0x1147a8
leaq 0xc3f(%rsp), %rdi
callq 0x114790
leaq 0xbb7(%rsp), %rdi
movq %rdi, 0x28(%rsp)
callq 0x114660
movq 0x28(%rsp), %rdx
leaq 0x3485b2(%rip), %rsi    # 0x463f58
leaq 0xbb8(%rsp), %rdi
callq 0x11b770
jmp 0x11b9b5
leaq 0xbb7(%rsp), %rdi
callq 0x114790
leaq 0xb27(%rsp), %rdi
movq %rdi, 0x20(%rsp)
callq 0x114660
movq 0x20(%rsp), %rdx
leaq 0x34867c(%rip), %rsi    # 0x46405c
leaq 0xb28(%rsp), %rdi
callq 0x11b770
jmp 0x11b9ef
leaq 0xb48(%rsp), %rdi
leaq 0xb28(%rsp), %rsi
callq 0x11c370
jmp 0x11ba06
leaq 0xb28(%rsp), %rdi
callq 0x1147a8
leaq 0xb27(%rsp), %rdi
callq 0x114790
leaq 0xcf0(%rsp), %rdi
callq 0x11c480
movq %rax, 0x18(%rsp)
jmp 0x11ba34
movq 0x18(%rsp), %rax
movq %rax, 0xb18(%rsp)
movq 0xb18(%rsp), %rax
movq %rax, 0x8(%rsp)
leaq 0xaf7(%rsp), %rdi
movq %rdi, 0x10(%rsp)
callq 0x114660
movq 0x10(%rsp), %rdx
leaq 0x3485f7(%rip), %rsi    # 0x464063
leaq 0xaf8(%rsp), %rdi
callq 0x11b770
jmp 0x11ba7b
movq 0x8(%rsp), %rdi
leaq 0xaf8(%rsp), %rsi
leaq 0xb48(%rsp), %rdx
callq 0x11c490
jmp 0x11ba97
leaq 0xaf8(%rsp), %rdi
callq 0x1147a8
leaq 0xaf7(%rsp), %rdi
callq 0x114790
leaq 0xad0(%rsp), %rdi
callq 0x11c690
jmp 0x11bac0
movq 0xb18(%rsp), %rsi
leaq 0xad0(%rsp), %rdi
callq 0x11c740
jmp 0x11bad7
leaq 0x58(%rsp), %rdi
movl $0x7f, %esi
callq 0x11c7f0
jmp 0x11bae8
leaq 0x1a8(%rsp), %rdi
leaq 0x58(%rsp), %rsi
callq 0x11c920
jmp 0x11bafc
leaq 0x58(%rsp), %rdi
callq 0x11d150
leaq 0x1a8(%rsp), %rdi
leaq 0xbb8(%rsp), %rsi
leaq 0xad0(%rsp), %rdx
callq 0x11d1c0
jmp 0x11bb25
leaq 0xad0(%rsp), %rdi
callq 0x11da50
jmp 0x11bb34
leaq 0x1a8(%rsp), %rdi
callq 0x11da70
leaq 0xad0(%rsp), %rdi
callq 0x11dc70
leaq 0xb48(%rsp), %rdi
callq 0x11dcb0
leaq 0xbb8(%rsp), %rdi
callq 0x1147a8
leaq 0xcf0(%rsp), %rdi
callq 0x11dce0
addq $0x16d8, %rsp           # imm = 0x16D8
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc30(%rsp)
movl %eax, 0xc2c(%rsp)
jmp 0x11bc53
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc30(%rsp)
movl %eax, 0xc2c(%rsp)
jmp 0x11bc46
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc30(%rsp)
movl %eax, 0xc2c(%rsp)
jmp 0x11bc2c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc30(%rsp)
movl %eax, 0xc2c(%rsp)
jmp 0x11bc1f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc30(%rsp)
movl %eax, 0xc2c(%rsp)
jmp 0x11bc12
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc30(%rsp)
movl %eax, 0xc2c(%rsp)
leaq 0xbe0(%rsp), %rdi
callq 0x1147a8
leaq 0xbdf(%rsp), %rdi
callq 0x114790
leaq 0xc08(%rsp), %rdi
callq 0x1147a8
leaq 0xc07(%rsp), %rdi
callq 0x114790
leaq 0xc60(%rsp), %rdi
callq 0x11c330
leaq 0xc40(%rsp), %rdi
callq 0x1147a8
leaq 0xc3f(%rsp), %rdi
callq 0x114790
jmp 0x11bdb1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc30(%rsp)
movl %eax, 0xc2c(%rsp)
leaq 0xbb7(%rsp), %rdi
callq 0x114790
jmp 0x11bdb1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc30(%rsp)
movl %eax, 0xc2c(%rsp)
jmp 0x11bcc2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc30(%rsp)
movl %eax, 0xc2c(%rsp)
leaq 0xb28(%rsp), %rdi
callq 0x1147a8
leaq 0xb27(%rsp), %rdi
callq 0x114790
jmp 0x11bda4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc30(%rsp)
movl %eax, 0xc2c(%rsp)
jmp 0x11bd97
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc30(%rsp)
movl %eax, 0xc2c(%rsp)
jmp 0x11bd24
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc30(%rsp)
movl %eax, 0xc2c(%rsp)
leaq 0xaf8(%rsp), %rdi
callq 0x1147a8
leaq 0xaf7(%rsp), %rdi
callq 0x114790
jmp 0x11bd97
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc30(%rsp)
movl %eax, 0xc2c(%rsp)
jmp 0x11bd8a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc30(%rsp)
movl %eax, 0xc2c(%rsp)
leaq 0x58(%rsp), %rdi
callq 0x11d150
jmp 0x11bd8a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xc30(%rsp)
movl %eax, 0xc2c(%rsp)
leaq 0x1a8(%rsp), %rdi
callq 0x11da70
leaq 0xad0(%rsp), %rdi
callq 0x11dc70
leaq 0xb48(%rsp), %rdi
callq 0x11dcb0
leaq 0xbb8(%rsp), %rdi
callq 0x1147a8
leaq 0xcf0(%rsp), %rdi
callq 0x11dce0
movq 0xc30(%rsp), %rdi
callq 0x114450
nopl (%rax,%rax)