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

   const std::string bubble_sort_program =
      " var upper_bound := v[];                      "
      "                                              "
      " repeat                                       "
      "    var new_upper_bound := 0;                 "
      "                                              "
      "    for (var i := 1; i < upper_bound; i += 1) "
      "    {                                         "
      "       assert(i < v[]);                       "
      "       if (v[i - 1] > v[i])                   "
      "       {                                      "
      "          v[i - 1] <=> v[i];                  "
      "          new_upper_bound := i;               "
      "       };                                     "
      "    };                                        "
      "                                              "
      "    upper_bound := new_upper_bound;           "
      "                                              "
      " until (upper_bound <= 1);                    "
      "                                              "
      " var result := true;                          "
      "                                              "
      " for (var i := 1; i < v[]; i += 1)            "
      " {                                            "
      "    assert(i < v[]);                          "
      "    if (v[i - 1] > v[i])                      "
      "    {                                         "
      "       result := false;                       "
      "    };                                        "
      " };                                           "
      "                                              "
      " result;                                      ";

   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);

   const std::size_t num_values = 10000;
   std::vector<T> values(num_values, 0.0);

   for (std::size_t i = 0; i < values.size(); ++i)
   {
      values[i] = static_cast<double>(values.size() - i);
   }

   {
      std::vector<T> v = values;

      symbol_table_t symbol_table;
      symbol_table.add_vector("v", v);

      expression_t expression;
      expression.register_symbol_table(symbol_table);

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

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

      nortc_result = expression.value();

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

   {
      std::vector<T> v = values;

      symbol_table_t symbol_table;
      symbol_table.add_vector("v", v);

      vector_access_rtc vec_rtc;

      expression_t expression;
      expression.register_symbol_table(symbol_table);

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

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

      rtc_result = expression.value();

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

   {
      std::vector<T> v = values;

      symbol_table_t symbol_table;
      symbol_table.add_vector("v", v);

      expression_t expression;
      expression.register_symbol_table(symbol_table);

      assert_handler asrt_handler;

      parser_t parser;
      parser.register_assert_check(asrt_handler);
      parser.compile(bubble_sort_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("Bubble Sort - 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 $0x22a8, %rsp           # imm = 0x22A8
leaq 0x2287(%rsp), %rdi
movq %rdi, 0xb8(%rsp)
callq 0x111670
movq 0xb8(%rsp), %rdx
leaq 0x336562(%rip), %rsi    # 0x44f59d
leaq 0x2288(%rsp), %rdi
callq 0x118800
jmp 0x11904a
leaq 0x2287(%rsp), %rdi
callq 0x111790
movq $0x0, 0x2268(%rsp)
movq $0x0, 0x2260(%rsp)
movq $0x0, 0x2258(%rsp)
movq $0x0, 0x2250(%rsp)
movq $0x0, 0x2248(%rsp)
movq $0x0, 0x2240(%rsp)
movq $0x2710, 0x2238(%rsp) # imm = 0x2710
movq $0x0, 0x2218(%rsp)
leaq 0x2217(%rsp), %rdi
movq %rdi, 0xb0(%rsp)
callq 0x442040
movq 0xb0(%rsp), %rcx
leaq 0x2220(%rsp), %rdi
movl $0x2710, %esi           # imm = 0x2710
leaq 0x2218(%rsp), %rdx
callq 0x442050
jmp 0x1190f0
leaq 0x2217(%rsp), %rdi
callq 0x4420d0
movq $0x0, 0x2208(%rsp)
movq 0x2208(%rsp), %rax
movq %rax, 0xa8(%rsp)
leaq 0x2220(%rsp), %rdi
callq 0x405540
movq %rax, %rcx
movq 0xa8(%rsp), %rax
cmpq %rcx, %rax
jae 0x119209
leaq 0x2220(%rsp), %rdi
callq 0x405540
movq 0x2208(%rsp), %rcx
subq %rcx, %rax
movq %rax, %xmm0
movaps 0x32bf62(%rip), %xmm1   # 0x4450c0
punpckldq %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
movapd 0x32bf66(%rip), %xmm1   # 0x4450d0
subpd %xmm1, %xmm0
movaps %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm1, %xmm0
movsd %xmm0, 0xa0(%rsp)
movq 0x2208(%rsp), %rsi
leaq 0x2220(%rsp), %rdi
callq 0x404fd0
movsd 0xa0(%rsp), %xmm0
movsd %xmm0, (%rax)
movq 0x2208(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x2208(%rsp)
jmp 0x119109
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2278(%rsp)
movl %eax, 0x2274(%rsp)
leaq 0x2287(%rsp), %rdi
callq 0x111790
jmp 0x119c99
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2278(%rsp)
movl %eax, 0x2274(%rsp)
leaq 0x2217(%rsp), %rdi
callq 0x4420d0
jmp 0x119c8c
leaq 0x21f0(%rsp), %rdi
leaq 0x2220(%rsp), %rsi
callq 0x4420e0
jmp 0x119220
leaq 0x21e8(%rsp), %rdi
movl $0x1, %esi
callq 0x4421e0
jmp 0x119234
leaq 0x21c7(%rsp), %rdi
movq %rdi, 0x98(%rsp)
callq 0x111670
movq 0x98(%rsp), %rdx
leaq 0x331e4f(%rip), %rsi    # 0x44b0a7
leaq 0x21c8(%rsp), %rdi
callq 0x118800
jmp 0x119267
leaq 0x21e8(%rsp), %rdi
leaq 0x21c8(%rsp), %rsi
leaq 0x21f0(%rsp), %rdx
callq 0x442220
jmp 0x119286
leaq 0x21c8(%rsp), %rdi
callq 0x1117a8
leaq 0x21c7(%rsp), %rdi
callq 0x111790
leaq 0x21a0(%rsp), %rdi
callq 0x119f50
jmp 0x1192af
leaq 0x21a0(%rsp), %rdi
leaq 0x21e8(%rsp), %rsi
callq 0x4422e0
jmp 0x1192c6
leaq 0x1728(%rsp), %rdi
movl $0x7f, %esi
callq 0x11a000
jmp 0x1192da
leaq 0x1878(%rsp), %rdi
leaq 0x1728(%rsp), %rsi
callq 0x11a130
jmp 0x1192f1
leaq 0x1728(%rsp), %rdi
callq 0x11a960
leaq 0x1878(%rsp), %rdi
leaq 0x2288(%rsp), %rsi
leaq 0x21a0(%rsp), %rdx
callq 0x11a9d0
jmp 0x11931d
leaq 0x1700(%rsp), %rdi
callq 0x11b260
jmp 0x11932c
leaq 0x1700(%rsp), %rdi
callq 0x11b290
leaq 0x21a0(%rsp), %rdi
callq 0x11b2b0
movsd %xmm0, 0x90(%rsp)
jmp 0x119351
movsd 0x90(%rsp), %xmm0
movsd %xmm0, 0x2268(%rsp)
leaq 0x1700(%rsp), %rdi
movq %rdi, 0x80(%rsp)
callq 0x11b2d0
movq 0x80(%rsp), %rdi
callq 0x11b300
movsd %xmm0, 0x88(%rsp)
jmp 0x119390
movsd 0x88(%rsp), %xmm0
movsd %xmm0, 0x2250(%rsp)
leaq 0x1878(%rsp), %rdi
callq 0x11b350
leaq 0x21a0(%rsp), %rdi
callq 0x11b550
leaq 0x21e8(%rsp), %rdi
callq 0x11ffb0
leaq 0x21f0(%rsp), %rdi
callq 0x402fb0
leaq 0x16e8(%rsp), %rdi
leaq 0x2220(%rsp), %rsi
callq 0x4420e0
jmp 0x1193ed
leaq 0x16e0(%rsp), %rdi
movl $0x1, %esi
callq 0x4421e0
jmp 0x119401
leaq 0x16bf(%rsp), %rdi
movq %rdi, 0x78(%rsp)
callq 0x111670
movq 0x78(%rsp), %rdx
leaq 0x331c88(%rip), %rsi    # 0x44b0a7
leaq 0x16c0(%rsp), %rdi
callq 0x118800
jmp 0x11942e
leaq 0x16e0(%rsp), %rdi
leaq 0x16c0(%rsp), %rsi
leaq 0x16e8(%rsp), %rdx
callq 0x442220
jmp 0x11944d
leaq 0x16c0(%rsp), %rdi
callq 0x1117a8
leaq 0x16bf(%rsp), %rdi
callq 0x111790
leaq 0x16b0(%rsp), %rdi
callq 0x11b590
leaq 0x1690(%rsp), %rdi
callq 0x119f50
jmp 0x119483
leaq 0x1690(%rsp), %rdi
leaq 0x16e0(%rsp), %rsi
callq 0x4422e0
jmp 0x11949a
leaq 0xc18(%rsp), %rdi
movl $0x7f, %esi
callq 0x11a000
jmp 0x1194ae
leaq 0xd68(%rsp), %rdi
leaq 0xc18(%rsp), %rsi
callq 0x11a130
jmp 0x1194c5
leaq 0xc18(%rsp), %rdi
callq 0x11a960
leaq 0xd68(%rsp), %rdi
movq %rdi, 0x70(%rsp)
leaq 0x16b0(%rsp), %rsi
callq 0x11b5c0
movq 0x70(%rsp), %rdi
leaq 0x2288(%rsp), %rsi
leaq 0x1690(%rsp), %rdx
callq 0x11a9d0
jmp 0x119508
leaq 0xbf0(%rsp), %rdi
callq 0x11b260
jmp 0x119517
leaq 0xbf0(%rsp), %rdi
callq 0x11b290
leaq 0x1690(%rsp), %rdi
callq 0x11b2b0
movsd %xmm0, 0x68(%rsp)
jmp 0x119539
movsd 0x68(%rsp), %xmm0
movsd %xmm0, 0x2260(%rsp)
leaq 0xbf0(%rsp), %rdi
movq %rdi, 0x58(%rsp)
callq 0x11b2d0
movq 0x58(%rsp), %rdi
callq 0x11b300
movsd %xmm0, 0x60(%rsp)
jmp 0x11956c
movsd 0x60(%rsp), %xmm0
movsd %xmm0, 0x2248(%rsp)
leaq 0xd68(%rsp), %rdi
callq 0x11b350
leaq 0x1690(%rsp), %rdi
callq 0x11b550
leaq 0x16b0(%rsp), %rdi
callq 0x11b5e0
leaq 0x16e0(%rsp), %rdi
callq 0x11ffb0
leaq 0x16e8(%rsp), %rdi
callq 0x402fb0
leaq 0xbd8(%rsp), %rdi
leaq 0x2220(%rsp), %rsi
callq 0x4420e0
jmp 0x1195d3
leaq 0xbd0(%rsp), %rdi
movl $0x1, %esi
callq 0x4421e0
jmp 0x1195e7
leaq 0xbaf(%rsp), %rdi
movq %rdi, 0x50(%rsp)
callq 0x111670
movq 0x50(%rsp), %rdx
leaq 0x331aa2(%rip), %rsi    # 0x44b0a7
leaq 0xbb0(%rsp), %rdi
callq 0x118800
jmp 0x119614
leaq 0xbd0(%rsp), %rdi
leaq 0xbb0(%rsp), %rsi
leaq 0xbd8(%rsp), %rdx
callq 0x442220
jmp 0x119633
leaq 0xbb0(%rsp), %rdi
callq 0x1117a8
leaq 0xbaf(%rsp), %rdi
callq 0x111790
leaq 0xb88(%rsp), %rdi
callq 0x119f50
jmp 0x11965c
leaq 0xb88(%rsp), %rdi
leaq 0xbd0(%rsp), %rsi
callq 0x4422e0
jmp 0x119673
leaq 0xb80(%rsp), %rdi
callq 0x11b5f0
leaq 0x108(%rsp), %rdi
movl $0x7f, %esi
callq 0x11a000
jmp 0x119694
leaq 0x258(%rsp), %rdi
leaq 0x108(%rsp), %rsi
callq 0x11a130
jmp 0x1196ab
leaq 0x108(%rsp), %rdi
callq 0x11a960
leaq 0x258(%rsp), %rdi
movq %rdi, 0x48(%rsp)
leaq 0xb80(%rsp), %rsi
callq 0x11b620
movq 0x48(%rsp), %rdi
leaq 0x2288(%rsp), %rsi
leaq 0xb88(%rsp), %rdx
callq 0x11a9d0
jmp 0x1196ee
leaq 0xe0(%rsp), %rdi
callq 0x11b260
jmp 0x1196fd
leaq 0xe0(%rsp), %rdi
callq 0x11b290
leaq 0xb88(%rsp), %rdi
callq 0x11b2b0
movsd %xmm0, 0x40(%rsp)
jmp 0x11971f
movsd 0x40(%rsp), %xmm0
movsd %xmm0, 0x2258(%rsp)
leaq 0xe0(%rsp), %rdi
movq %rdi, 0x30(%rsp)
callq 0x11b2d0
movq 0x30(%rsp), %rdi
callq 0x11b300
movsd %xmm0, 0x38(%rsp)
jmp 0x119752
movsd 0x38(%rsp), %xmm0
movsd %xmm0, 0x2240(%rsp)
leaq 0x258(%rsp), %rdi
callq 0x11b350
leaq 0xb80(%rsp), %rdi
callq 0x11b640
leaq 0xb88(%rsp), %rdi
callq 0x11b550
leaq 0xbd0(%rsp), %rdi
callq 0x11ffb0
leaq 0xbd8(%rsp), %rdi
callq 0x402fb0
movsd 0x2268(%rsp), %xmm0
movsd 0x32b855(%rip), %xmm1   # 0x445008
ucomisd %xmm1, %xmm0
jne 0x119c4b
jp 0x119c4b
movsd 0x2268(%rsp), %xmm0
ucomisd 0x2260(%rsp), %xmm0
jne 0x119c4b
jp 0x119c4b
movsd 0x2268(%rsp), %xmm0
ucomisd 0x2258(%rsp), %xmm0
jne 0x119c4b
jp 0x119c4b
movsd 0x2250(%rsp), %xmm0
movsd %xmm0, 0x10(%rsp)
movsd 0x2248(%rsp), %xmm0
movsd %xmm0, 0x18(%rsp)
movsd 0x2240(%rsp), %xmm0
movsd %xmm0, 0x20(%rsp)
movq $0x0, 0xd8(%rsp)
movsd 0x2248(%rsp), %xmm0
movsd 0x2250(%rsp), %xmm1
subsd %xmm1, %xmm0
divsd %xmm1, %xmm0
movsd 0x32b7b6(%rip), %xmm1   # 0x445010
movsd %xmm1, 0x8(%rsp)
mulsd %xmm1, %xmm0
movsd %xmm0, 0xd0(%rsp)
leaq 0xd8(%rsp), %rdi
leaq 0xd0(%rsp), %rsi
callq 0x11b650
movsd 0x8(%rsp), %xmm1
movsd (%rax), %xmm0
movsd %xmm0, 0x28(%rsp)
movq $0x0, 0xc8(%rsp)
movsd 0x2240(%rsp), %xmm0
movsd 0x2250(%rsp), %xmm2
subsd %xmm2, %xmm0
divsd %xmm2, %xmm0
mulsd %xmm1, %xmm0
movsd %xmm0, 0xc0(%rsp)
leaq 0xc8(%rsp), %rdi
leaq 0xc0(%rsp), %rsi
callq 0x11b650
movsd 0x10(%rsp), %xmm0
movsd 0x18(%rsp), %xmm1
movsd 0x20(%rsp), %xmm2
movsd 0x28(%rsp), %xmm3
movsd (%rax), %xmm4
leaq 0x336233(%rip), %rdi    # 0x44fb30
movb $0x5, %al
callq 0x111080
jmp 0x119906
jmp 0x119c5d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2278(%rsp)
movl %eax, 0x2274(%rsp)
jmp 0x119c7f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2278(%rsp)
movl %eax, 0x2274(%rsp)
jmp 0x119a0d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2278(%rsp)
movl %eax, 0x2274(%rsp)
jmp 0x119974
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2278(%rsp)
movl %eax, 0x2274(%rsp)
leaq 0x21c8(%rsp), %rdi
callq 0x1117a8
leaq 0x21c7(%rsp), %rdi
callq 0x111790
jmp 0x119a00
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2278(%rsp)
movl %eax, 0x2274(%rsp)
jmp 0x119a00
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2278(%rsp)
movl %eax, 0x2274(%rsp)
jmp 0x1199f3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2278(%rsp)
movl %eax, 0x2274(%rsp)
leaq 0x1728(%rsp), %rdi
callq 0x11a960
jmp 0x1199f3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2278(%rsp)
movl %eax, 0x2274(%rsp)
leaq 0x1878(%rsp), %rdi
callq 0x11b350
leaq 0x21a0(%rsp), %rdi
callq 0x11b550
leaq 0x21e8(%rsp), %rdi
callq 0x11ffb0
leaq 0x21f0(%rsp), %rdi
callq 0x402fb0
jmp 0x119c7f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2278(%rsp)
movl %eax, 0x2274(%rsp)
jmp 0x119b18
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2278(%rsp)
movl %eax, 0x2274(%rsp)
jmp 0x119a6f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2278(%rsp)
movl %eax, 0x2274(%rsp)
leaq 0x16c0(%rsp), %rdi
callq 0x1117a8
leaq 0x16bf(%rsp), %rdi
callq 0x111790
jmp 0x119b0b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2278(%rsp)
movl %eax, 0x2274(%rsp)
jmp 0x119afe
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2278(%rsp)
movl %eax, 0x2274(%rsp)
jmp 0x119af1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2278(%rsp)
movl %eax, 0x2274(%rsp)
leaq 0xc18(%rsp), %rdi
callq 0x11a960
jmp 0x119af1
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2278(%rsp)
movl %eax, 0x2274(%rsp)
leaq 0xd68(%rsp), %rdi
callq 0x11b350
leaq 0x1690(%rsp), %rdi
callq 0x11b550
leaq 0x16b0(%rsp), %rdi
callq 0x11b5e0
leaq 0x16e0(%rsp), %rdi
callq 0x11ffb0
leaq 0x16e8(%rsp), %rdi
callq 0x402fb0
jmp 0x119c7f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2278(%rsp)
movl %eax, 0x2274(%rsp)
jmp 0x119c3c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2278(%rsp)
movl %eax, 0x2274(%rsp)
jmp 0x119b7a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2278(%rsp)
movl %eax, 0x2274(%rsp)
leaq 0xbb0(%rsp), %rdi
callq 0x1117a8
leaq 0xbaf(%rsp), %rdi
callq 0x111790
jmp 0x119c2f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2278(%rsp)
movl %eax, 0x2274(%rsp)
jmp 0x119c2f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2278(%rsp)
movl %eax, 0x2274(%rsp)
jmp 0x119c22
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2278(%rsp)
movl %eax, 0x2274(%rsp)
jmp 0x119c15
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2278(%rsp)
movl %eax, 0x2274(%rsp)
leaq 0x108(%rsp), %rdi
callq 0x11a960
jmp 0x119c15
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2278(%rsp)
movl %eax, 0x2274(%rsp)
leaq 0x258(%rsp), %rdi
callq 0x11b350
leaq 0xb80(%rsp), %rdi
callq 0x11b640
leaq 0xb88(%rsp), %rdi
callq 0x11b550
leaq 0xbd0(%rsp), %rdi
callq 0x11ffb0
leaq 0xbd8(%rsp), %rdi
callq 0x402fb0
jmp 0x119c7f
leaq 0x330d99(%rip), %rdi    # 0x44a9eb
xorl %eax, %eax
callq 0x111080
jmp 0x119c5b
jmp 0x119c5d
leaq 0x2220(%rsp), %rdi
callq 0x402fb0
leaq 0x2288(%rsp), %rdi
callq 0x1117a8
addq $0x22a8, %rsp           # imm = 0x22A8
retq
leaq 0x2220(%rsp), %rdi
callq 0x402fb0
leaq 0x2288(%rsp), %rdi
callq 0x1117a8
movq 0x2278(%rsp), %rdi
callq 0x111470
nopw %cs:(%rax,%rax)