// File: ArashPartow[P]exprtk-extras/exprtk_nthroot_bisection.cpp
// Function: void nthroot_via_bisection<double>()
void nthroot_via_bisection()
{
   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;

   const std::string nthroot_via_bisection_program =
      " for (var x := -30; x <= 30; x += 1)   "
      " {                                     "
      "    println('[', x, ']',               "
      "            ' sqrt = ', nthroot(x,2),  "
      "            ' cbrt = ', nthroot(x,3)); "
      " }                                     ";

   exprtk::rtl::io::println<T> println;

   symbol_table_t symbol_table;
   symbol_table.add_function("println",println);

   compositor_t compositor(symbol_table);

   // define function: nthroot(x,n)
   compositor.add(
      function_t("nthroot")
      .var("x")
      .var("n")
      .expression
      (
        " if (abs(frac(n)) > 0)            "
        "    return [null];                "
        " else if (x < 0 and (n % 2 == 0)) "
        "    return [null];                "
        "                                  "
        " var lo := min(0,x);              "
        " var hi := max(0,x);              "
        "                                  "
        " while (true)                     "
        " {                                "
        "    var mid := avg(lo,hi);        "
        "    var y   := pow(mid,n);        "
        "                                  "
        "    if (equal(y, x))              "
        "       break [mid];               "
        "    else if (y < x)               "
        "       lo := mid;                 "
        "    else                          "
        "       hi := mid;                 "
        " };                               "
       ));

   expression_t expression;
   expression.register_symbol_table(symbol_table);

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

   expression.value();
}

// Assembly:
subq $0x16f8, %rsp           # imm = 0x16F8
leaq 0x16d7(%rsp), %rdi
movq %rdi, 0x48(%rsp)
callq 0x114660
movq 0x48(%rsp), %rdx
leaq 0x347d0b(%rip), %rsi    # 0x463560
leaq 0x16d8(%rsp), %rdi
callq 0x11b770
jmp 0x11b864
leaq 0x16d7(%rsp), %rdi
callq 0x114790
leaq 0x1637(%rsp), %rdi
movq %rdi, 0x40(%rsp)
callq 0x114660
movq 0x40(%rsp), %rdx
leaq 0x347dbc(%rip), %rsi    # 0x46364b
leaq 0x1638(%rsp), %rdi
callq 0x11b770
jmp 0x11b89e
leaq 0x1658(%rsp), %rdi
leaq 0x1638(%rsp), %rsi
callq 0x11c160
jmp 0x11b8b5
leaq 0x1638(%rsp), %rdi
callq 0x1147a8
leaq 0x1637(%rsp), %rdi
callq 0x114790
leaq 0x1628(%rsp), %rdi
movl $0x1, %esi
callq 0x11c270
jmp 0x11b8e3
leaq 0x1607(%rsp), %rdi
movq %rdi, 0x38(%rsp)
callq 0x114660
movq 0x38(%rsp), %rdx
leaq 0x347d51(%rip), %rsi    # 0x463652
leaq 0x1608(%rsp), %rdi
callq 0x11b770
jmp 0x11b910
leaq 0x1628(%rsp), %rdi
leaq 0x1608(%rsp), %rsi
leaq 0x1658(%rsp), %rdx
callq 0x11c2b0
jmp 0x11b92f
leaq 0x1608(%rsp), %rdi
callq 0x1147a8
leaq 0x1607(%rsp), %rdi
callq 0x114790
leaq 0xc18(%rsp), %rdi
leaq 0x1628(%rsp), %rsi
callq 0x11c4b0
jmp 0x11b960
leaq 0xb67(%rsp), %rdi
movq %rdi, 0x30(%rsp)
callq 0x114660
movq 0x30(%rsp), %rdx
leaq 0x347cdc(%rip), %rsi    # 0x46365a
leaq 0xb68(%rsp), %rdi
callq 0x11b770
jmp 0x11b98d
leaq 0xb88(%rsp), %rdi
leaq 0xb68(%rsp), %rsi
callq 0x11c6a0
jmp 0x11b9a4
leaq 0xb3f(%rsp), %rdi
movq %rdi, 0x28(%rsp)
callq 0x114660
movq 0x28(%rsp), %rdx
leaq 0x347afb(%rip), %rsi    # 0x4634bd
leaq 0xb40(%rsp), %rdi
callq 0x11b770
jmp 0x11b9d1
leaq 0xb88(%rsp), %rdi
leaq 0xb40(%rsp), %rsi
callq 0x11c720
movq %rax, 0x20(%rsp)
jmp 0x11b9ed
leaq 0xb17(%rsp), %rdi
movq %rdi, 0x18(%rsp)
callq 0x114660
movq 0x18(%rsp), %rdx
leaq 0x347a25(%rip), %rsi    # 0x463430
leaq 0xb18(%rsp), %rdi
callq 0x11b770
jmp 0x11ba1a
movq 0x20(%rsp), %rdi
leaq 0xb18(%rsp), %rsi
callq 0x11c720
movq %rax, 0x10(%rsp)
jmp 0x11ba33
leaq 0xaef(%rsp), %rdi
movq %rdi, 0x8(%rsp)
callq 0x114660
movq 0x8(%rsp), %rdx
leaq 0x347c11(%rip), %rsi    # 0x463662
leaq 0xaf0(%rsp), %rdi
callq 0x11b770
jmp 0x11ba60
movq 0x10(%rsp), %rdi
leaq 0xaf0(%rsp), %rsi
callq 0x11c750
movq %rax, (%rsp)
jmp 0x11ba78
movq (%rsp), %rsi
leaq 0xc18(%rsp), %rdi
xorl %edx, %edx
callq 0x11c650
jmp 0x11ba8d
leaq 0xaf0(%rsp), %rdi
callq 0x1147a8
leaq 0xaef(%rsp), %rdi
callq 0x114790
leaq 0xb18(%rsp), %rdi
callq 0x1147a8
leaq 0xb17(%rsp), %rdi
callq 0x114790
leaq 0xb40(%rsp), %rdi
callq 0x1147a8
leaq 0xb3f(%rsp), %rdi
callq 0x114790
leaq 0xb88(%rsp), %rdi
callq 0x11c780
leaq 0xb68(%rsp), %rdi
callq 0x1147a8
leaq 0xb67(%rsp), %rdi
callq 0x114790
leaq 0xac8(%rsp), %rdi
callq 0x11c7c0
jmp 0x11bb11
leaq 0xac8(%rsp), %rdi
leaq 0x1628(%rsp), %rsi
callq 0x11c870
jmp 0x11bb28
leaq 0x50(%rsp), %rdi
movl $0x7f, %esi
callq 0x11c920
jmp 0x11bb39
leaq 0x1a0(%rsp), %rdi
leaq 0x50(%rsp), %rsi
callq 0x11ca50
jmp 0x11bb4d
leaq 0x50(%rsp), %rdi
callq 0x11d280
leaq 0x1a0(%rsp), %rdi
leaq 0x16d8(%rsp), %rsi
leaq 0xac8(%rsp), %rdx
callq 0x11d2f0
jmp 0x11bb76
leaq 0xac8(%rsp), %rdi
callq 0x11db80
jmp 0x11bb85
leaq 0x1a0(%rsp), %rdi
callq 0x11dba0
leaq 0xac8(%rsp), %rdi
callq 0x11dda0
leaq 0xc18(%rsp), %rdi
callq 0x11dde0
leaq 0x1628(%rsp), %rdi
callq 0x11de70
leaq 0x1658(%rsp), %rdi
callq 0x11def0
leaq 0x16d8(%rsp), %rdi
callq 0x1147a8
addq $0x16f8, %rsp           # imm = 0x16F8
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x16c8(%rsp)
movl %eax, 0x16c4(%rsp)
leaq 0x16d7(%rsp), %rdi
callq 0x114790
jmp 0x11bea4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x16c8(%rsp)
movl %eax, 0x16c4(%rsp)
jmp 0x11bc38
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x16c8(%rsp)
movl %eax, 0x16c4(%rsp)
leaq 0x1638(%rsp), %rdi
callq 0x1147a8
leaq 0x1637(%rsp), %rdi
callq 0x114790
jmp 0x11be97
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x16c8(%rsp)
movl %eax, 0x16c4(%rsp)
jmp 0x11be8a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x16c8(%rsp)
movl %eax, 0x16c4(%rsp)
jmp 0x11bc9a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x16c8(%rsp)
movl %eax, 0x16c4(%rsp)
leaq 0x1608(%rsp), %rdi
callq 0x1147a8
leaq 0x1607(%rsp), %rdi
callq 0x114790
jmp 0x11be7d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x16c8(%rsp)
movl %eax, 0x16c4(%rsp)
jmp 0x11be7d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x16c8(%rsp)
movl %eax, 0x16c4(%rsp)
jmp 0x11bde7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x16c8(%rsp)
movl %eax, 0x16c4(%rsp)
jmp 0x11bdda
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x16c8(%rsp)
movl %eax, 0x16c4(%rsp)
jmp 0x11bdc0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x16c8(%rsp)
movl %eax, 0x16c4(%rsp)
jmp 0x11bdb3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x16c8(%rsp)
movl %eax, 0x16c4(%rsp)
jmp 0x11bda6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x16c8(%rsp)
movl %eax, 0x16c4(%rsp)
jmp 0x11bd99
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x16c8(%rsp)
movl %eax, 0x16c4(%rsp)
jmp 0x11bd8c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x16c8(%rsp)
movl %eax, 0x16c4(%rsp)
leaq 0xaf0(%rsp), %rdi
callq 0x1147a8
leaq 0xaef(%rsp), %rdi
callq 0x114790
leaq 0xb18(%rsp), %rdi
callq 0x1147a8
leaq 0xb17(%rsp), %rdi
callq 0x114790
leaq 0xb40(%rsp), %rdi
callq 0x1147a8
leaq 0xb3f(%rsp), %rdi
callq 0x114790
leaq 0xb88(%rsp), %rdi
callq 0x11c780
leaq 0xb68(%rsp), %rdi
callq 0x1147a8
leaq 0xb67(%rsp), %rdi
callq 0x114790
jmp 0x11be70
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x16c8(%rsp)
movl %eax, 0x16c4(%rsp)
jmp 0x11be70
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x16c8(%rsp)
movl %eax, 0x16c4(%rsp)
jmp 0x11be63
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x16c8(%rsp)
movl %eax, 0x16c4(%rsp)
leaq 0x50(%rsp), %rdi
callq 0x11d280
jmp 0x11be63
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x16c8(%rsp)
movl %eax, 0x16c4(%rsp)
leaq 0x1a0(%rsp), %rdi
callq 0x11dba0
leaq 0xac8(%rsp), %rdi
callq 0x11dda0
leaq 0xc18(%rsp), %rdi
callq 0x11dde0
leaq 0x1628(%rsp), %rdi
callq 0x11de70
leaq 0x1658(%rsp), %rdi
callq 0x11def0
leaq 0x16d8(%rsp), %rdi
callq 0x1147a8
movq 0x16c8(%rsp), %rdi
callq 0x114450
nopw %cs:(%rax,%rax)
nopl (%rax,%rax)