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

   const std::string max_subarray_sum_program =
      " var zero       := 0;                "
      " var curr_sum   := 0;                "
      " var curr_start := 0;                "
      "                                     "
      " for (var i := 0; i < vec[]; i += 1) "
      " {                                   "
      "    curr_sum += vec[i];              "
      "                                     "
      "    if (curr_sum < zero)             "
      "    {                                "
      "       curr_sum   := 0;              "
      "       curr_start := i + 1;          "
      "    }                                "
      "    else if (curr_sum > max_sum)     "
      "    {                                "
      "       max_sum   := curr_sum;        "
      "       max_start := curr_start;      "
      "       max_end   := i;               "
      "    }                                "
      " }                                   ";

   T max_sum   = T(0);
   T max_start = T(0);
   T max_end   = T(0);

   T vec[] = { T(-1), T(-2), T(3), T(5), T(6), T(-2), T(-1), T(4), T(-4), T(2), T(-1) };

   symbol_table_t symbol_table;

   symbol_table.add_variable("max_sum"  , max_sum  );
   symbol_table.add_variable("max_start", max_start);
   symbol_table.add_variable("max_end"  , max_end  );
   symbol_table.add_vector  ("vec"      , vec      );

   expression_t expression;
   expression.register_symbol_table(symbol_table);

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

   expression.value();

   if (max_start <= max_end)
   {
      printf("Max sum: %10.3f \n", max_sum);
      printf("Start index: %4d\n", static_cast<int>(max_start));
      printf("End index:   %4d\n", static_cast<int>(max_end  ));

      for (int i = static_cast<int>(max_start); i <= static_cast<int>(max_end); ++i)
      {
         printf("%5.3f ",vec[i]);
      }

      printf("\n");
   }
   else
      printf("No maximum sum found.\n");
}

// Assembly:
pushq %r14
pushq %rbx
subq $0xb38, %rsp            # imm = 0xB38
leaq 0x12addd(%rip), %rsi    # 0x23b101
leaq 0x40(%rsp), %rdi
leaq 0x210(%rsp), %rdx
callq 0x1102d8
andq $0x0, 0x18(%rsp)
andq $0x0, 0x10(%rsp)
andq $0x0, 0x8(%rsp)
leaq 0x12fc11(%rip), %rsi    # 0x23ff60
pushq $0xb
popq %rcx
leaq 0x60(%rsp), %rdi
rep  movsq (%rsi), %es:(%rdi)
movq %rsp, %rdi
pushq $0x1
popq %rsi
callq 0x1106b2
leaq 0x12b07a(%rip), %rsi    # 0x23b3e6
leaq 0x210(%rsp), %rdi
leaq 0xc0(%rsp), %rdx
callq 0x1102d8
movq %rsp, %rdi
leaq 0x210(%rsp), %rsi
leaq 0x18(%rsp), %rdx
xorl %ecx, %ecx
callq 0x1106d6
leaq 0x210(%rsp), %rdi
callq 0x10e5d8
leaq 0x12b042(%rip), %rsi    # 0x23b3ee
leaq 0x210(%rsp), %rdi
leaq 0xc0(%rsp), %rdx
callq 0x1102d8
movq %rsp, %rdi
leaq 0x210(%rsp), %rsi
leaq 0x10(%rsp), %rdx
xorl %ecx, %ecx
callq 0x1106d6
leaq 0x210(%rsp), %rdi
callq 0x10e5d8
leaq 0x12b00c(%rip), %rsi    # 0x23b3f8
leaq 0x210(%rsp), %rdi
leaq 0xc0(%rsp), %rdx
callq 0x1102d8
movq %rsp, %rdi
leaq 0x210(%rsp), %rsi
leaq 0x8(%rsp), %rdx
xorl %ecx, %ecx
callq 0x1106d6
leaq 0x210(%rsp), %rdi
callq 0x10e5d8
leaq 0x12afd4(%rip), %rsi    # 0x23b400
leaq 0x210(%rsp), %rdi
leaq 0xc0(%rsp), %rdx
callq 0x1102d8
movq %rsp, %rdi
leaq 0x210(%rsp), %rsi
leaq 0x60(%rsp), %rdx
callq 0x110742
leaq 0x210(%rsp), %rdi
callq 0x10e5d8
leaq 0x20(%rsp), %rdi
callq 0x1107a4
leaq 0x20(%rsp), %rdi
movq %rsp, %rsi
callq 0x110804
leaq 0xc0(%rsp), %rdi
pushq $0x7f
popq %rsi
callq 0x110860
leaq 0x210(%rsp), %rdi
leaq 0xc0(%rsp), %rsi
callq 0x110970
leaq 0xc0(%rsp), %rdi
callq 0x110f88
leaq 0x210(%rsp), %rdi
leaq 0x40(%rsp), %rsi
leaq 0x20(%rsp), %rdx
callq 0x110fd0
movq 0x20(%rsp), %rax
movq 0x8(%rax), %rdi
movq (%rdi), %rax
callq *0x18(%rax)
movsd 0x8(%rsp), %xmm0
ucomisd 0x10(%rsp), %xmm0
jae 0x1104ee
leaq 0x12fa58(%rip), %rdi    # 0x23ff3f
callq 0x10e4f0
jmp 0x110565
movsd 0x18(%rsp), %xmm0
leaq 0x12af09(%rip), %rdi    # 0x23b404
movb $0x1, %al
callq 0x10e060
cvttsd2si 0x10(%rsp), %esi
leaq 0x12af07(%rip), %rdi    # 0x23b416
xorl %eax, %eax
callq 0x10e060
cvttsd2si 0x8(%rsp), %esi
leaq 0x12af05(%rip), %rdi    # 0x23b428
xorl %eax, %eax
callq 0x10e060
cvttsd2si 0x10(%rsp), %eax
movslq %eax, %r14
leaq 0x12af00(%rip), %rbx    # 0x23b43a
cvttsd2si 0x8(%rsp), %eax
cltq
cmpq %rax, %r14
jg 0x11055d
movsd 0x60(%rsp,%r14,8), %xmm0
movq %rbx, %rdi
movb $0x1, %al
callq 0x10e060
incq %r14
jmp 0x11053a
pushq $0xa
popq %rdi
callq 0x10e560
leaq 0x210(%rsp), %rdi
callq 0x111452
leaq 0x20(%rsp), %rdi
callq 0x11158c
movq %rsp, %rdi
callq 0x1115a2
leaq 0x40(%rsp), %rdi
callq 0x10e5d8
addq $0xb38, %rsp            # imm = 0xB38
popq %rbx
popq %r14
retq
movq %rax, %rbx
leaq 0xc0(%rsp), %rdi
callq 0x110f88
jmp 0x1105ec
jmp 0x1105ad
movq %rax, %rbx
jmp 0x1105ec
jmp 0x1105d2
jmp 0x1105c0
jmp 0x1105d2
jmp 0x1105c0
jmp 0x1105d2
jmp 0x1105c0
jmp 0x1105d2
movq %rax, %rbx
leaq 0x210(%rsp), %rdi
callq 0x10e5d8
jmp 0x1105f6
movq %rax, %rbx
jmp 0x1105f6
movq %rax, %rbx
jmp 0x1105fe
movq %rax, %rbx
leaq 0x210(%rsp), %rdi
callq 0x111452
leaq 0x20(%rsp), %rdi
callq 0x11158c
movq %rsp, %rdi
callq 0x1115a2
leaq 0x40(%rsp), %rdi
callq 0x10e5d8
movq %rbx, %rdi
callq 0x10e310