// File: ArashPartow[P]exprtk-extras/exprtk_rtc_overhead.cpp
// Function: void vector_rtc_overhead_analysis_01<double>()
void vector_rtc_overhead_analysis_01()
{
   typedef exprtk::expression<T> expression_t;
   typedef exprtk::parser<T>     parser_t;

   const std::string sieve_of_eratosthenes_program =
      " var sieve[10^8] := [false];                   "
      " var m := trunc(sqrt(sieve[]));                "
      "                                               "
      " sieve[0] := true;                             "
      " sieve[1] := true;                             "
      "                                               "
      " for (var i := 0; i <= m; i += 1)              "
      " {                                             "
      "    assert(i < sieve[]);                       "
      "    if (false == sieve[i])                     "
      "    {                                          "
      "       for (var j := i^2; j < sieve[]; j += i) "
      "       {                                       "
      "          assert(j < sieve[]);                 "
      "          sieve[j] := true;                    "
      "       }                                       "
      "    }                                          "
      " };                                            "
      "                                               "
      " var prime_count := sieve[] - sum(sieve);      "
      "                                               "
      " prime_count == 5761455;                       ";

   T nortc_result  = T(0);
   T rtc_result    = T(0);
   T assert_result = T(0);

   T nortc_time_sec  = T(0);
   T rtc_time_sec    = T(0);
   T assert_time_sec = T(0);

   {
      expression_t expression;

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

      exprtk::timer timer;
      timer.start();

      nortc_result = expression.value();

      timer.stop();
      nortc_time_sec = timer.time();
   }

   {
      vector_access_rtc vec_rtc;

      expression_t expression;

      parser_t parser;
      parser.register_vector_access_runtime_check(vec_rtc);
      parser.compile(sieve_of_eratosthenes_program,expression);

      exprtk::timer timer;
      timer.start();

      rtc_result = expression.value();

      timer.stop();
      rtc_time_sec = timer.time();
   }

   {
      assert_handler asrt_handler;
      expression_t expression;

      parser_t parser;
      parser.register_assert_check(asrt_handler);
      parser.compile(sieve_of_eratosthenes_program,expression);

      exprtk::timer timer;
      timer.start();

      assert_result = expression.value();

      timer.stop();
      assert_time_sec = timer.time();
   }

   if (
        (nortc_result == T(1)         ) &&
        (nortc_result == rtc_result   ) &&
        (nortc_result == assert_result)
      )
   {
      printf("Prime Sieve - NORTC time: %5.3fsec\tRTC time: %5.3fsec\tassert time: %5.3fsec\trtc_overhead: %5.3f%%\tassert_overhead: %5.3f%%\n",
             nortc_time_sec,
             rtc_time_sec,
             assert_time_sec,
             std::max(0.0, 100.0 * ((rtc_time_sec    - nortc_time_sec) / nortc_time_sec)),
             std::max(0.0, 100.0 * ((assert_time_sec - nortc_time_sec) / nortc_time_sec)));
   }
   else
      printf("ERROR - Results of NORTC and RTC runs do not match!\n");
}

// Assembly:
subq $0x2148, %rsp           # imm = 0x2148
leaq 0x2127(%rsp), %rdi
movq %rdi, 0x68(%rsp)
callq 0x111670
movq 0x68(%rsp), %rdx
leaq 0x331c7f(%rip), %rsi    # 0x44a564
leaq 0x2128(%rsp), %rdi
callq 0x118800
jmp 0x1188f4
leaq 0x2127(%rsp), %rdi
callq 0x111790
movq $0x0, 0x2108(%rsp)
movq $0x0, 0x2100(%rsp)
movq $0x0, 0x20f8(%rsp)
movq $0x0, 0x20f0(%rsp)
movq $0x0, 0x20e8(%rsp)
movq $0x0, 0x20e0(%rsp)
leaq 0x20c0(%rsp), %rdi
callq 0x119f50
jmp 0x118958
leaq 0x1648(%rsp), %rdi
movl $0x7f, %esi
callq 0x11a000
jmp 0x11896c
leaq 0x1798(%rsp), %rdi
leaq 0x1648(%rsp), %rsi
callq 0x11a130
jmp 0x118983
leaq 0x1648(%rsp), %rdi
callq 0x11a960
leaq 0x1798(%rsp), %rdi
leaq 0x2128(%rsp), %rsi
leaq 0x20c0(%rsp), %rdx
callq 0x11a9d0
jmp 0x1189af
leaq 0x1620(%rsp), %rdi
callq 0x11b260
jmp 0x1189be
leaq 0x1620(%rsp), %rdi
callq 0x11b290
jmp 0x1189cd
leaq 0x20c0(%rsp), %rdi
callq 0x11b2b0
movsd %xmm0, 0x60(%rsp)
jmp 0x1189e2
movsd 0x60(%rsp), %xmm0
movsd %xmm0, 0x2108(%rsp)
leaq 0x1620(%rsp), %rdi
callq 0x11b2d0
jmp 0x118a00
leaq 0x1620(%rsp), %rdi
callq 0x11b300
movsd %xmm0, 0x58(%rsp)
jmp 0x118a15
movsd 0x58(%rsp), %xmm0
movsd %xmm0, 0x20f0(%rsp)
leaq 0x1798(%rsp), %rdi
callq 0x11b350
leaq 0x20c0(%rsp), %rdi
callq 0x11b550
leaq 0x1618(%rsp), %rdi
callq 0x11b590
leaq 0x15f8(%rsp), %rdi
callq 0x119f50
jmp 0x118a5a
leaq 0xb80(%rsp), %rdi
movl $0x7f, %esi
callq 0x11a000
jmp 0x118a6e
leaq 0xcd0(%rsp), %rdi
leaq 0xb80(%rsp), %rsi
callq 0x11a130
jmp 0x118a85
leaq 0xb80(%rsp), %rdi
callq 0x11a960
leaq 0xcd0(%rsp), %rdi
leaq 0x1618(%rsp), %rsi
callq 0x11b5c0
jmp 0x118aa9
leaq 0xcd0(%rsp), %rdi
leaq 0x2128(%rsp), %rsi
leaq 0x15f8(%rsp), %rdx
callq 0x11a9d0
jmp 0x118ac8
leaq 0xb58(%rsp), %rdi
callq 0x11b260
jmp 0x118ad7
leaq 0xb58(%rsp), %rdi
callq 0x11b290
jmp 0x118ae6
leaq 0x15f8(%rsp), %rdi
callq 0x11b2b0
movsd %xmm0, 0x50(%rsp)
jmp 0x118afb
movsd 0x50(%rsp), %xmm0
movsd %xmm0, 0x2100(%rsp)
leaq 0xb58(%rsp), %rdi
callq 0x11b2d0
jmp 0x118b19
leaq 0xb58(%rsp), %rdi
callq 0x11b300
movsd %xmm0, 0x48(%rsp)
jmp 0x118b2e
movsd 0x48(%rsp), %xmm0
movsd %xmm0, 0x20e8(%rsp)
leaq 0xcd0(%rsp), %rdi
callq 0x11b350
leaq 0x15f8(%rsp), %rdi
callq 0x11b550
leaq 0x1618(%rsp), %rdi
callq 0x11b5e0
leaq 0xb50(%rsp), %rdi
callq 0x11b5f0
leaq 0xb30(%rsp), %rdi
callq 0x119f50
jmp 0x118b80
leaq 0xb8(%rsp), %rdi
movl $0x7f, %esi
callq 0x11a000
jmp 0x118b94
leaq 0x208(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
callq 0x11a130
jmp 0x118bab
leaq 0xb8(%rsp), %rdi
callq 0x11a960
leaq 0x208(%rsp), %rdi
leaq 0xb50(%rsp), %rsi
callq 0x11b620
jmp 0x118bcf
leaq 0x208(%rsp), %rdi
leaq 0x2128(%rsp), %rsi
leaq 0xb30(%rsp), %rdx
callq 0x11a9d0
jmp 0x118bee
leaq 0x90(%rsp), %rdi
callq 0x11b260
jmp 0x118bfd
leaq 0x90(%rsp), %rdi
callq 0x11b290
jmp 0x118c0c
leaq 0xb30(%rsp), %rdi
callq 0x11b2b0
movsd %xmm0, 0x40(%rsp)
jmp 0x118c21
movsd 0x40(%rsp), %xmm0
movsd %xmm0, 0x20f8(%rsp)
leaq 0x90(%rsp), %rdi
callq 0x11b2d0
jmp 0x118c3f
leaq 0x90(%rsp), %rdi
callq 0x11b300
movsd %xmm0, 0x38(%rsp)
jmp 0x118c54
movsd 0x38(%rsp), %xmm0
movsd %xmm0, 0x20e0(%rsp)
leaq 0x208(%rsp), %rdi
callq 0x11b350
leaq 0xb30(%rsp), %rdi
callq 0x11b550
leaq 0xb50(%rsp), %rdi
callq 0x11b640
movsd 0x2108(%rsp), %xmm0
movsd 0x32c36d(%rip), %xmm1   # 0x445008
ucomisd %xmm1, %xmm0
jne 0x118fc1
jp 0x118fc1
movsd 0x2108(%rsp), %xmm0
ucomisd 0x2100(%rsp), %xmm0
jne 0x118fc1
jp 0x118fc1
movsd 0x2108(%rsp), %xmm0
ucomisd 0x20f8(%rsp), %xmm0
jne 0x118fc1
jp 0x118fc1
movsd 0x20f0(%rsp), %xmm0
movsd %xmm0, 0x18(%rsp)
movsd 0x20e8(%rsp), %xmm0
movsd %xmm0, 0x20(%rsp)
movsd 0x20e0(%rsp), %xmm0
movsd %xmm0, 0x28(%rsp)
movq $0x0, 0x88(%rsp)
movsd 0x20e8(%rsp), %xmm0
movsd 0x20f0(%rsp), %xmm1
subsd %xmm1, %xmm0
divsd %xmm1, %xmm0
movsd 0x32c2ce(%rip), %xmm1   # 0x445010
mulsd %xmm1, %xmm0
movsd %xmm0, 0x80(%rsp)
leaq 0x88(%rsp), %rdi
leaq 0x80(%rsp), %rsi
callq 0x11b650
movq %rax, 0x30(%rsp)
jmp 0x118d6b
movq 0x30(%rsp), %rax
movsd (%rax), %xmm0
movsd %xmm0, 0x8(%rsp)
movq $0x0, 0x78(%rsp)
movsd 0x20e0(%rsp), %xmm0
movsd 0x20f0(%rsp), %xmm1
subsd %xmm1, %xmm0
divsd %xmm1, %xmm0
movsd 0x32c26b(%rip), %xmm1   # 0x445010
mulsd %xmm1, %xmm0
movsd %xmm0, 0x70(%rsp)
leaq 0x78(%rsp), %rdi
leaq 0x70(%rsp), %rsi
callq 0x11b650
movq %rax, 0x10(%rsp)
jmp 0x118dc5
movsd 0x8(%rsp), %xmm3
movsd 0x28(%rsp), %xmm2
movsd 0x20(%rsp), %xmm1
movsd 0x18(%rsp), %xmm0
movq 0x10(%rsp), %rax
movsd (%rax), %xmm4
leaq 0x331b82(%rip), %rdi    # 0x44a96f
movb $0x5, %al
callq 0x111080
jmp 0x118df6
jmp 0x118fd3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2118(%rsp)
movl %eax, 0x2114(%rsp)
leaq 0x2127(%rsp), %rdi
callq 0x111790
jmp 0x118ff5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2118(%rsp)
movl %eax, 0x2114(%rsp)
jmp 0x118fe8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2118(%rsp)
movl %eax, 0x2114(%rsp)
jmp 0x118e94
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2118(%rsp)
movl %eax, 0x2114(%rsp)
leaq 0x1648(%rsp), %rdi
callq 0x11a960
jmp 0x118e94
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2118(%rsp)
movl %eax, 0x2114(%rsp)
leaq 0x1798(%rsp), %rdi
callq 0x11b350
leaq 0x20c0(%rsp), %rdi
callq 0x11b550
jmp 0x118fe8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2118(%rsp)
movl %eax, 0x2114(%rsp)
jmp 0x118f23
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2118(%rsp)
movl %eax, 0x2114(%rsp)
jmp 0x118f16
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2118(%rsp)
movl %eax, 0x2114(%rsp)
leaq 0xb80(%rsp), %rdi
callq 0x11a960
jmp 0x118f16
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2118(%rsp)
movl %eax, 0x2114(%rsp)
leaq 0xcd0(%rsp), %rdi
callq 0x11b350
leaq 0x15f8(%rsp), %rdi
callq 0x11b550
leaq 0x1618(%rsp), %rdi
callq 0x11b5e0
jmp 0x118fe8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2118(%rsp)
movl %eax, 0x2114(%rsp)
jmp 0x118fb2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2118(%rsp)
movl %eax, 0x2114(%rsp)
jmp 0x118fa5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2118(%rsp)
movl %eax, 0x2114(%rsp)
leaq 0xb8(%rsp), %rdi
callq 0x11a960
jmp 0x118fa5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2118(%rsp)
movl %eax, 0x2114(%rsp)
leaq 0x208(%rsp), %rdi
callq 0x11b350
leaq 0xb30(%rsp), %rdi
callq 0x11b550
leaq 0xb50(%rsp), %rdi
callq 0x11b640
jmp 0x118fe8
leaq 0x331a23(%rip), %rdi    # 0x44a9eb
xorl %eax, %eax
callq 0x111080
jmp 0x118fd1
jmp 0x118fd3
leaq 0x2128(%rsp), %rdi
callq 0x1117a8
addq $0x2148, %rsp           # imm = 0x2148
retq
leaq 0x2128(%rsp), %rdi
callq 0x1117a8
movq 0x2118(%rsp), %rdi
callq 0x111470
nopw %cs:(%rax,%rax)
nopl (%rax)