// File: ArashPartow[P]exprtk/exprtk_simple_example_04.cpp
// Function: void fibonacci<double>()
void fibonacci()
{
   typedef exprtk::symbol_table<T>         symbol_table_t;
   typedef exprtk::expression<T>           expression_t;
   typedef exprtk::parser<T>               parser_t;
   typedef exprtk::function_compositor<T>  compositor_t;
   typedef typename compositor_t::function function_t;

   T x = T(0);

   compositor_t compositor;

   compositor.add(
      function_t("fibonacci")
      .var("x")
      .expression
      (
         " switch                      "
         " {                           "
         "    case x == 0 : 0;         "
         "    case x == 1 : 1;         "
         "    default     :            "
         "    {                        "
         "       var prev := 0;        "
         "       var curr := 1;        "
         "       while ((x -= 1) > 0)  "
         "       {                     "
         "          var temp := prev;  "
         "          prev := curr;      "
         "          curr += temp;      "
         "       };                    "
         "    };                       "
         " }                           "
      ));

   symbol_table_t& symbol_table = compositor.symbol_table();
   symbol_table.add_constants();
   symbol_table.add_variable("x",x);

   std::string expression_str = "fibonacci(x)";

   expression_t expression;
   expression.register_symbol_table(symbol_table);

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

   for (std::size_t i = 0; i < 40; ++i)
   {
      x = static_cast<T>(i);

      const T result = expression.value();

      printf("fibonacci(%3d) = %10.0f\n",
             static_cast<int>(i),
             result);
   }
}

// Assembly:
subq $0x1658, %rsp           # imm = 0x1658
movq $0x0, 0x1650(%rsp)
leaq 0xc68(%rsp), %rdi
callq 0x11b050
leaq 0xbb7(%rsp), %rdi
movq %rdi, 0x48(%rsp)
callq 0x113650
movq 0x48(%rsp), %rdx
leaq 0x347d1b(%rip), %rsi    # 0x462569
leaq 0xbb8(%rsp), %rdi
callq 0x11a750
jmp 0x11a85d
leaq 0xbd8(%rsp), %rdi
leaq 0xbb8(%rsp), %rsi
callq 0x11b230
jmp 0x11a874
leaq 0xb7f(%rsp), %rdi
movq %rdi, 0x40(%rsp)
callq 0x113650
movq 0x40(%rsp), %rdx
leaq 0x347c2f(%rip), %rsi    # 0x4624c1
leaq 0xb80(%rsp), %rdi
callq 0x11a750
jmp 0x11a8a1
leaq 0xbd8(%rsp), %rdi
leaq 0xb80(%rsp), %rsi
callq 0x11b2b0
movq %rax, 0x38(%rsp)
jmp 0x11a8bd
leaq 0xb57(%rsp), %rdi
movq %rdi, 0x30(%rsp)
callq 0x113650
movq 0x30(%rsp), %rdx
leaq 0x347c98(%rip), %rsi    # 0x462573
leaq 0xb58(%rsp), %rdi
callq 0x11a750
jmp 0x11a8ea
movq 0x38(%rsp), %rdi
leaq 0xb58(%rsp), %rsi
callq 0x11b2e0
movq %rax, 0x28(%rsp)
jmp 0x11a903
movq 0x28(%rsp), %rsi
leaq 0xc68(%rsp), %rdi
xorl %edx, %edx
callq 0x11b1e0
jmp 0x11a919
leaq 0xb58(%rsp), %rdi
callq 0x113788
leaq 0xb57(%rsp), %rdi
callq 0x113770
leaq 0xb80(%rsp), %rdi
callq 0x113788
leaq 0xb7f(%rsp), %rdi
callq 0x113770
leaq 0xbd8(%rsp), %rdi
callq 0x11b310
leaq 0xbb8(%rsp), %rdi
callq 0x113788
leaq 0xbb7(%rsp), %rdi
callq 0x113770
leaq 0xc68(%rsp), %rdi
callq 0x11b350
movq %rax, 0x20(%rsp)
jmp 0x11a988
movq 0x20(%rsp), %rax
movq %rax, 0xb48(%rsp)
movq 0xb48(%rsp), %rdi
callq 0x11b360
jmp 0x11a9a4
movq 0xb48(%rsp), %rax
movq %rax, 0x10(%rsp)
leaq 0xb27(%rsp), %rdi
movq %rdi, 0x18(%rsp)
callq 0x113650
movq 0x18(%rsp), %rdx
leaq 0x347af2(%rip), %rsi    # 0x4624c1
leaq 0xb28(%rsp), %rdi
callq 0x11a750
jmp 0x11a9de
movq 0x10(%rsp), %rdi
leaq 0xb28(%rsp), %rsi
leaq 0x1650(%rsp), %rdx
xorl %ecx, %ecx
callq 0x11b3c0
jmp 0x11a9fc
leaq 0xb28(%rsp), %rdi
callq 0x113788
leaq 0xb27(%rsp), %rdi
callq 0x113770
leaq 0xaff(%rsp), %rdi
movq %rdi, 0x8(%rsp)
callq 0x113650
movq 0x8(%rsp), %rdx
leaq 0x347d10(%rip), %rsi    # 0x462744
leaq 0xb00(%rsp), %rdi
callq 0x11a750
jmp 0x11aa43
leaq 0xaff(%rsp), %rdi
callq 0x113770
leaq 0xad8(%rsp), %rdi
callq 0x11b470
jmp 0x11aa5f
movq 0xb48(%rsp), %rsi
leaq 0xad8(%rsp), %rdi
callq 0x11b520
jmp 0x11aa76
leaq 0x60(%rsp), %rdi
movl $0x7f, %esi
callq 0x11b5d0
jmp 0x11aa87
leaq 0x1b0(%rsp), %rdi
leaq 0x60(%rsp), %rsi
callq 0x11b700
jmp 0x11aa9b
leaq 0x60(%rsp), %rdi
callq 0x11bf30
leaq 0x1b0(%rsp), %rdi
leaq 0xb00(%rsp), %rsi
leaq 0xad8(%rsp), %rdx
callq 0x11bfa0
jmp 0x11aac4
movq $0x0, 0x58(%rsp)
cmpq $0x28, 0x58(%rsp)
jae 0x11ad3a
movaps 0x342530(%rip), %xmm1   # 0x45d010
movq 0x58(%rsp), %xmm0
punpckldq %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
movapd 0x34252e(%rip), %xmm1   # 0x45d020
subpd %xmm1, %xmm0
movaps %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm1, %xmm0
movsd %xmm0, 0x1650(%rsp)
leaq 0xad8(%rsp), %rdi
callq 0x11c830
movsd %xmm0, (%rsp)
jmp 0x11ab1e
movsd (%rsp), %xmm0
movsd %xmm0, 0x50(%rsp)
movl 0x58(%rsp), %esi
movsd 0x50(%rsp), %xmm0
leaq 0x347c17(%rip), %rdi    # 0x462751
movb $0x1, %al
callq 0x113080
jmp 0x11ab43
jmp 0x11ab45
movq 0x58(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x58(%rsp)
jmp 0x11aacd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xba8(%rsp)
movl %eax, 0xba4(%rsp)
jmp 0x11ac2e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xba8(%rsp)
movl %eax, 0xba4(%rsp)
jmp 0x11ac21
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xba8(%rsp)
movl %eax, 0xba4(%rsp)
jmp 0x11ac07
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xba8(%rsp)
movl %eax, 0xba4(%rsp)
jmp 0x11abfa
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xba8(%rsp)
movl %eax, 0xba4(%rsp)
jmp 0x11abed
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xba8(%rsp)
movl %eax, 0xba4(%rsp)
leaq 0xb58(%rsp), %rdi
callq 0x113788
leaq 0xb57(%rsp), %rdi
callq 0x113770
leaq 0xb80(%rsp), %rdi
callq 0x113788
leaq 0xb7f(%rsp), %rdi
callq 0x113770
leaq 0xbd8(%rsp), %rdi
callq 0x11b310
leaq 0xbb8(%rsp), %rdi
callq 0x113788
leaq 0xbb7(%rsp), %rdi
callq 0x113770
jmp 0x11ad90
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xba8(%rsp)
movl %eax, 0xba4(%rsp)
jmp 0x11ad90
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xba8(%rsp)
movl %eax, 0xba4(%rsp)
jmp 0x11ac90
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xba8(%rsp)
movl %eax, 0xba4(%rsp)
leaq 0xb28(%rsp), %rdi
callq 0x113788
leaq 0xb27(%rsp), %rdi
callq 0x113770
jmp 0x11ad90
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xba8(%rsp)
movl %eax, 0xba4(%rsp)
leaq 0xaff(%rsp), %rdi
callq 0x113770
jmp 0x11ad90
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xba8(%rsp)
movl %eax, 0xba4(%rsp)
jmp 0x11ad83
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xba8(%rsp)
movl %eax, 0xba4(%rsp)
jmp 0x11ad76
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xba8(%rsp)
movl %eax, 0xba4(%rsp)
leaq 0x60(%rsp), %rdi
callq 0x11bf30
jmp 0x11ad76
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xba8(%rsp)
movl %eax, 0xba4(%rsp)
leaq 0x1b0(%rsp), %rdi
callq 0x11c850
jmp 0x11ad76
leaq 0x1b0(%rsp), %rdi
callq 0x11c850
leaq 0xad8(%rsp), %rdi
callq 0x11ca50
leaq 0xb00(%rsp), %rdi
callq 0x113788
leaq 0xc68(%rsp), %rdi
callq 0x11ca90
addq $0x1658, %rsp           # imm = 0x1658
retq
leaq 0xad8(%rsp), %rdi
callq 0x11ca50
leaq 0xb00(%rsp), %rdi
callq 0x113788
leaq 0xc68(%rsp), %rdi
callq 0x11ca90
movq 0xba8(%rsp), %rdi
callq 0x113440
nopw (%rax,%rax)