// File: /workspace/github_cpp_makefile_star2_O2/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:
pushq %r14
pushq %rbx
subq $0xb48, %rsp            # imm = 0xB48
leaq 0x12f9e0(%rip), %rsi    # 0x2400d6
leaq 0x80(%rsp), %rdi
leaq 0x220(%rsp), %rbx
movq %rbx, %rdx
callq 0x11033a
andq $0x0, (%rbx)
leaq 0x50(%rsp), %rdi
leaq 0x220(%rsp), %rdx
leaq 0xd0(%rsp), %rcx
movl $0x2710, %esi           # imm = 0x2710
callq 0x234fde
movq 0x50(%rsp), %rax
movq 0x58(%rsp), %rcx
subq %rax, %rcx
sarq $0x3, %rcx
xorl %edx, %edx
movq 0x125994(%rip), %xmm0   # 0x2360e0
movapd 0x12599c(%rip), %xmm1   # 0x2360f0
movq %rcx, %rsi
cmpq %rcx, %rdx
jae 0x110782
movq %rsi, %xmm2
punpckldq %xmm0, %xmm2    # xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1]
subpd %xmm1, %xmm2
movapd %xmm2, %xmm3
unpckhpd %xmm2, %xmm3            # xmm3 = xmm3[1],xmm2[1]
addsd %xmm2, %xmm3
movsd %xmm3, (%rax,%rdx,8)
incq %rdx
decq %rsi
jmp 0x110757
leaq 0x30(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0x235034
leaq 0x8(%rsp), %rdi
pushq $0x1
popq %rsi
callq 0x235082
leaq 0x12b48a(%rip), %rsi    # 0x23bc2f
leaq 0x220(%rsp), %rdi
leaq 0xd0(%rsp), %rdx
callq 0x11033a
leaq 0x8(%rsp), %rdi
leaq 0x220(%rsp), %rsi
leaq 0x30(%rsp), %rdx
callq 0x2350a6
leaq 0x220(%rsp), %rdi
callq 0x10e5f8
leaq 0x10(%rsp), %rdi
callq 0x110d8c
leaq 0x10(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x235110
leaq 0xd0(%rsp), %rdi
pushq $0x7f
popq %rsi
callq 0x110dec
leaq 0x220(%rsp), %rdi
leaq 0xd0(%rsp), %rsi
callq 0x110efc
leaq 0xd0(%rsp), %rdi
callq 0x111514
leaq 0x220(%rsp), %rdi
leaq 0x80(%rsp), %rsi
leaq 0x10(%rsp), %rdx
callq 0x11155c
leaq 0xd0(%rsp), %rdi
movb $0x0, (%rdi)
pxor %xmm0, %xmm0
movdqu %xmm0, 0x8(%rdi)
movdqu %xmm0, 0x18(%rdi)
callq 0x1119de
movq 0x10(%rsp), %rax
movq 0x8(%rax), %rdi
movq (%rdi), %rax
callq *0x18(%rax)
movq %xmm0, 0x78(%rsp)
leaq 0xd0(%rsp), %rbx
movq %rbx, %rdi
callq 0x1119ec
movq %rbx, %rdi
callq 0x111a00
movdqa %xmm0, 0xc0(%rsp)
leaq 0x220(%rsp), %rdi
callq 0x111a32
leaq 0x10(%rsp), %rdi
callq 0x111b6c
leaq 0x8(%rsp), %rdi
callq 0x1128b6
leaq 0x30(%rsp), %rdi
callq 0x21cc60
leaq 0x30(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0x235034
leaq 0x8(%rsp), %rdi
pushq $0x1
popq %rsi
callq 0x235082
leaq 0x12b34a(%rip), %rsi    # 0x23bc2f
leaq 0x220(%rsp), %rdi
leaq 0xd0(%rsp), %rdx
callq 0x11033a
leaq 0x8(%rsp), %rdi
leaq 0x220(%rsp), %rsi
leaq 0x30(%rsp), %rdx
callq 0x2350a6
leaq 0x220(%rsp), %rdi
callq 0x10e5f8
leaq 0x2b437b(%rip), %rax    # 0x3c4ca0
movq %rax, 0x48(%rsp)
leaq 0x10(%rsp), %rdi
callq 0x110d8c
leaq 0x10(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x235110
leaq 0xd0(%rsp), %rdi
pushq $0x7f
popq %rsi
callq 0x110dec
leaq 0x220(%rsp), %rdi
leaq 0xd0(%rsp), %rsi
callq 0x110efc
leaq 0xd0(%rsp), %rdi
callq 0x111514
leaq 0x48(%rsp), %r14
leaq 0x220(%rsp), %rdi
movq %r14, 0x8e0(%rdi)
leaq 0x80(%rsp), %rsi
leaq 0x10(%rsp), %rdx
callq 0x11155c
leaq 0xd0(%rsp), %rdi
movb $0x0, (%rdi)
pxor %xmm0, %xmm0
movdqu %xmm0, 0x8(%rdi)
movdqu %xmm0, 0x18(%rdi)
callq 0x1119de
movq 0x10(%rsp), %rax
movq 0x8(%rax), %rdi
movq (%rdi), %rax
callq *0x18(%rax)
movq %xmm0, 0x70(%rsp)
leaq 0xd0(%rsp), %rbx
movq %rbx, %rdi
callq 0x1119ec
movq %rbx, %rdi
callq 0x111a00
movdqa %xmm0, 0xb0(%rsp)
leaq 0x220(%rsp), %rdi
callq 0x111a32
leaq 0x10(%rsp), %rdi
callq 0x111b6c
leaq 0x8(%rsp), %rdi
callq 0x1128b6
leaq 0x30(%rsp), %rdi
callq 0x21cc60
leaq 0x30(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0x235034
leaq 0x8(%rsp), %rdi
pushq $0x1
popq %rsi
callq 0x235082
leaq 0x12b1f2(%rip), %rsi    # 0x23bc2f
leaq 0x220(%rsp), %rdi
leaq 0xd0(%rsp), %rdx
callq 0x11033a
leaq 0x8(%rsp), %rdi
leaq 0x220(%rsp), %rsi
leaq 0x30(%rsp), %rdx
callq 0x2350a6
leaq 0x220(%rsp), %rdi
callq 0x10e5f8
leaq 0x10(%rsp), %rdi
callq 0x110d8c
leaq 0x10(%rsp), %rdi
leaq 0x8(%rsp), %rsi
callq 0x235110
leaq 0x2b425a(%rip), %rax    # 0x3c4cf0
movq %rax, 0x48(%rsp)
leaq 0xd0(%rsp), %rdi
pushq $0x7f
popq %rsi
callq 0x110dec
leaq 0x220(%rsp), %rdi
leaq 0xd0(%rsp), %rsi
callq 0x110efc
leaq 0xd0(%rsp), %rdi
callq 0x111514
leaq 0x220(%rsp), %rdi
movq %r14, 0x8f0(%rdi)
leaq 0x80(%rsp), %rsi
leaq 0x10(%rsp), %rdx
callq 0x11155c
leaq 0xd0(%rsp), %rdi
movb $0x0, (%rdi)
pxor %xmm0, %xmm0
movdqu %xmm0, 0x8(%rdi)
movdqu %xmm0, 0x18(%rdi)
callq 0x1119de
movq 0x10(%rsp), %rax
movq 0x8(%rax), %rdi
movq (%rdi), %rax
callq *0x18(%rax)
movq %xmm0, 0x68(%rsp)
leaq 0xd0(%rsp), %rbx
movq %rbx, %rdi
callq 0x1119ec
movq %rbx, %rdi
callq 0x111a00
movdqa %xmm0, 0xa0(%rsp)
leaq 0x220(%rsp), %rdi
callq 0x111a32
leaq 0x10(%rsp), %rdi
callq 0x111b6c
leaq 0x8(%rsp), %rdi
callq 0x1128b6
leaq 0x30(%rsp), %rdi
callq 0x21cc60
movsd 0x78(%rsp), %xmm0
ucomisd 0x12548d(%rip), %xmm0   # 0x236008
jne 0x110be5
jp 0x110be5
ucomisd 0x70(%rsp), %xmm0
jne 0x110be5
jp 0x110be5
ucomisd 0x68(%rsp), %xmm0
jne 0x110be5
jp 0x110be5
movapd 0xa0(%rsp), %xmm2
movapd %xmm2, %xmm4
movapd 0xb0(%rsp), %xmm1
unpcklpd %xmm1, %xmm4            # xmm4 = xmm4[0],xmm1[0]
movapd 0xc0(%rsp), %xmm0
movapd %xmm0, %xmm3
unpcklpd %xmm0, %xmm3            # xmm3 = xmm3[0],xmm0[0]
subpd %xmm3, %xmm4
divpd %xmm3, %xmm4
mulpd 0x125502(%rip), %xmm4   # 0x2360d0
xorpd %xmm3, %xmm3
cmpltpd %xmm4, %xmm3
movmskpd %xmm3, %eax
testb $0x2, %al
jne 0x110bf3
xorpd %xmm3, %xmm3
jmp 0x110bfb
leaq 0x12fb13(%rip), %rdi    # 0x2406ff
callq 0x10e520
jmp 0x110c11
movapd %xmm4, %xmm3
unpckhpd %xmm4, %xmm3            # xmm3 = xmm3[1],xmm4[1]
testb $0x1, %al
jne 0x110c03
xorpd %xmm4, %xmm4
leaq 0x12fa5f(%rip), %rdi    # 0x240669
movb $0x5, %al
callq 0x10e060
leaq 0x50(%rsp), %rdi
callq 0x21cc60
leaq 0x80(%rsp), %rdi
callq 0x10e5f8
addq $0xb48, %rsp            # imm = 0xB48
popq %rbx
popq %r14
retq
jmp 0x110c9e
jmp 0x110c59
jmp 0x110c6d
jmp 0x110c6d
jmp 0x110c86
jmp 0x110c74
jmp 0x110c86
jmp 0x110c8b
jmp 0x110c90
jmp 0x110c9e
jmp 0x110c59
jmp 0x110c6d
jmp 0x110c6d
jmp 0x110c86
jmp 0x110c74
jmp 0x110c86
jmp 0x110c8b
jmp 0x110c90
jmp 0x110c9e
movq %rax, %rbx
leaq 0xd0(%rsp), %rdi
callq 0x111514
jmp 0x110cae
jmp 0x110c6d
movq %rax, %rbx
jmp 0x110cae
jmp 0x110c86
movq %rax, %rbx
leaq 0x220(%rsp), %rdi
callq 0x10e5f8
jmp 0x110cb8
movq %rax, %rbx
jmp 0x110cb8
movq %rax, %rbx
jmp 0x110cc2
movq %rax, %rbx
jmp 0x110ccc
movq %rax, %rbx
jmp 0x110cd6
jmp 0x110c9e
jmp 0x110c9e
movq %rax, %rbx
leaq 0x220(%rsp), %rdi
callq 0x111a32
leaq 0x10(%rsp), %rdi
callq 0x111b6c
leaq 0x8(%rsp), %rdi
callq 0x1128b6
leaq 0x30(%rsp), %rdi
callq 0x21cc60
leaq 0x50(%rsp), %rdi
callq 0x21cc60
leaq 0x80(%rsp), %rdi
callq 0x10e5f8
movq %rbx, %rdi
callq 0x10e340