// File: 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:
subq $0xc18, %rsp            # imm = 0xC18
leaq 0xbf7(%rsp), %rdi
movq %rdi, 0x20(%rsp)
callq 0x111640
movq 0x20(%rsp), %rdx
leaq 0x32fd1c(%rip), %rsi    # 0x448541
leaq 0xbf8(%rsp), %rdi
callq 0x118740
jmp 0x118834
leaq 0xbf7(%rsp), %rdi
callq 0x111760
movq $0x0, 0xbd8(%rsp)
movq $0x0, 0xbd0(%rsp)
movq $0x0, 0xbc8(%rsp)
movabsq $-0x4010000000000000, %rax # imm = 0xBFF0000000000000
movq %rax, 0xbc0(%rsp)
movaps 0x334b72(%rip), %xmm0   # 0x44d3f0
movaps %xmm0, 0xbb0(%rsp)
movaps 0x334b53(%rip), %xmm0   # 0x44d3e0
movaps %xmm0, 0xba0(%rsp)
movaps 0x334b34(%rip), %xmm0   # 0x44d3d0
movaps %xmm0, 0xb90(%rsp)
movaps 0x334b15(%rip), %xmm0   # 0x44d3c0
movaps %xmm0, 0xb80(%rsp)
movaps 0x334af6(%rip), %xmm0   # 0x44d3b0
movaps %xmm0, 0xb70(%rsp)
leaq 0xb68(%rsp), %rdi
movl $0x1, %esi
callq 0x1190c0
jmp 0x1188d6
leaq 0xb47(%rsp), %rdi
movq %rdi, 0x18(%rsp)
callq 0x111640
movq 0x18(%rsp), %rdx
leaq 0x32ff32(%rip), %rsi    # 0x448826
leaq 0xb48(%rsp), %rdi
callq 0x118740
jmp 0x118903
leaq 0xb68(%rsp), %rdi
leaq 0xb48(%rsp), %rsi
leaq 0xbd8(%rsp), %rdx
xorl %ecx, %ecx
callq 0x119100
jmp 0x118924
leaq 0xb48(%rsp), %rdi
callq 0x111778
leaq 0xb47(%rsp), %rdi
callq 0x111760
leaq 0xb1f(%rsp), %rdi
movq %rdi, 0x10(%rsp)
callq 0x111640
movq 0x10(%rsp), %rdx
leaq 0x32fed2(%rip), %rsi    # 0x44882e
leaq 0xb20(%rsp), %rdi
callq 0x118740
jmp 0x11896b
leaq 0xb68(%rsp), %rdi
leaq 0xb20(%rsp), %rsi
leaq 0xbd0(%rsp), %rdx
xorl %ecx, %ecx
callq 0x119100
jmp 0x11898c
leaq 0xb20(%rsp), %rdi
callq 0x111778
leaq 0xb1f(%rsp), %rdi
callq 0x111760
leaq 0xaf7(%rsp), %rdi
movq %rdi, 0x8(%rsp)
callq 0x111640
movq 0x8(%rsp), %rdx
leaq 0x32fe74(%rip), %rsi    # 0x448838
leaq 0xaf8(%rsp), %rdi
callq 0x118740
jmp 0x1189d3
leaq 0xb68(%rsp), %rdi
leaq 0xaf8(%rsp), %rsi
leaq 0xbc8(%rsp), %rdx
xorl %ecx, %ecx
callq 0x119100
jmp 0x1189f4
leaq 0xaf8(%rsp), %rdi
callq 0x111778
leaq 0xaf7(%rsp), %rdi
callq 0x111760
leaq 0xacf(%rsp), %rdi
movq %rdi, (%rsp)
callq 0x111640
movq (%rsp), %rdx
leaq 0x32fe16(%rip), %rsi    # 0x448840
leaq 0xad0(%rsp), %rdi
callq 0x118740
jmp 0x118a39
leaq 0xb68(%rsp), %rdi
leaq 0xad0(%rsp), %rsi
leaq 0xb70(%rsp), %rdx
callq 0x1191b0
jmp 0x118a58
leaq 0xad0(%rsp), %rdi
callq 0x111778
leaq 0xacf(%rsp), %rdi
callq 0x111760
leaq 0xaa8(%rsp), %rdi
callq 0x119250
jmp 0x118a81
leaq 0xaa8(%rsp), %rdi
leaq 0xb68(%rsp), %rsi
callq 0x119300
jmp 0x118a98
leaq 0x30(%rsp), %rdi
movl $0x7f, %esi
callq 0x1193b0
jmp 0x118aa9
leaq 0x180(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0x1194e0
jmp 0x118abd
leaq 0x30(%rsp), %rdi
callq 0x119d10
leaq 0x180(%rsp), %rdi
leaq 0xbf8(%rsp), %rsi
leaq 0xaa8(%rsp), %rdx
callq 0x119d80
jmp 0x118ae6
leaq 0xaa8(%rsp), %rdi
callq 0x11a610
jmp 0x118af5
movsd 0xbd0(%rsp), %xmm1
movsd 0xbc8(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jb 0x118d98
movsd 0xbd8(%rsp), %xmm0
leaq 0x32fd23(%rip), %rdi    # 0x448844
movb $0x1, %al
callq 0x111080
jmp 0x118b2a
cvttsd2si 0xbd0(%rsp), %esi
leaq 0x32fd1c(%rip), %rdi    # 0x448856
xorl %eax, %eax
callq 0x111080
jmp 0x118b43
cvttsd2si 0xbc8(%rsp), %esi
leaq 0x32fd15(%rip), %rdi    # 0x448868
xorl %eax, %eax
callq 0x111080
jmp 0x118b5c
cvttsd2si 0xbd0(%rsp), %eax
movl %eax, 0x2c(%rsp)
movl 0x2c(%rsp), %eax
cvttsd2si 0xbc8(%rsp), %ecx
cmpl %ecx, %eax
jg 0x118d86
movslq 0x2c(%rsp), %rax
movsd 0xb70(%rsp,%rax,8), %xmm0
leaq 0x32fce7(%rip), %rdi    # 0x44887a
movb $0x1, %al
callq 0x111080
jmp 0x118b9c
jmp 0x118b9e
movl 0x2c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2c(%rsp)
jmp 0x118b69
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xbe8(%rsp)
movl %eax, 0xbe4(%rsp)
leaq 0xbf7(%rsp), %rdi
callq 0x111760
jmp 0x118e0d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xbe8(%rsp)
movl %eax, 0xbe4(%rsp)
jmp 0x118e00
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xbe8(%rsp)
movl %eax, 0xbe4(%rsp)
jmp 0x118c21
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xbe8(%rsp)
movl %eax, 0xbe4(%rsp)
leaq 0xb48(%rsp), %rdi
callq 0x111778
leaq 0xb47(%rsp), %rdi
callq 0x111760
jmp 0x118df3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xbe8(%rsp)
movl %eax, 0xbe4(%rsp)
jmp 0x118c6a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xbe8(%rsp)
movl %eax, 0xbe4(%rsp)
leaq 0xb20(%rsp), %rdi
callq 0x111778
leaq 0xb1f(%rsp), %rdi
callq 0x111760
jmp 0x118df3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xbe8(%rsp)
movl %eax, 0xbe4(%rsp)
jmp 0x118cb3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xbe8(%rsp)
movl %eax, 0xbe4(%rsp)
leaq 0xaf8(%rsp), %rdi
callq 0x111778
leaq 0xaf7(%rsp), %rdi
callq 0x111760
jmp 0x118df3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xbe8(%rsp)
movl %eax, 0xbe4(%rsp)
jmp 0x118cfc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xbe8(%rsp)
movl %eax, 0xbe4(%rsp)
leaq 0xad0(%rsp), %rdi
callq 0x111778
leaq 0xacf(%rsp), %rdi
callq 0x111760
jmp 0x118df3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xbe8(%rsp)
movl %eax, 0xbe4(%rsp)
jmp 0x118df3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xbe8(%rsp)
movl %eax, 0xbe4(%rsp)
jmp 0x118de6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xbe8(%rsp)
movl %eax, 0xbe4(%rsp)
leaq 0x30(%rsp), %rdi
callq 0x119d10
jmp 0x118de6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xbe8(%rsp)
movl %eax, 0xbe4(%rsp)
leaq 0x180(%rsp), %rdi
callq 0x11a630
jmp 0x118de6
leaq 0x32fac7(%rip), %rdi    # 0x448854
xorl %eax, %eax
callq 0x111080
jmp 0x118d96
jmp 0x118daa
leaq 0x32fae2(%rip), %rdi    # 0x448881
xorl %eax, %eax
callq 0x111080
jmp 0x118da8
jmp 0x118daa
leaq 0x180(%rsp), %rdi
callq 0x11a630
leaq 0xaa8(%rsp), %rdi
callq 0x11a830
leaq 0xb68(%rsp), %rdi
callq 0x11a870
leaq 0xbf8(%rsp), %rdi
callq 0x111778
addq $0xc18, %rsp            # imm = 0xC18
retq
leaq 0xaa8(%rsp), %rdi
callq 0x11a830
leaq 0xb68(%rsp), %rdi
callq 0x11a870
leaq 0xbf8(%rsp), %rdi
callq 0x111778
movq 0xbe8(%rsp), %rdi
callq 0x111440
nopw (%rax,%rax)