// File: /workspace/github_cpp_makefile_star2_O3/Eshaancoding[P]AutoDiff/src/Variable/eval.cpp
// Function: Variable::eval(bool)
double Variable::eval (bool is_top_node) {
    static int INPUT_ITERATION = 0;
    static vector<int> value_index;
    static vector<int> id_array;
    if (is_top_node) { 
        INPUT_ITERATION = 0;
        id_array.clear();
        value_index.clear();
    }
    if (this->operation == op::clip) {
        // get values
        this->arg->eval(false);
        this->child[0]->eval(false);
        this->child[1]->eval(false);
        // check if max is less than min, or vise versa. (Gives out warning)
        if (this->child[0]->value >= this->child[1]->value) {
            string red = "\033[4;34m";
            string normal = "\033[0m"; 
            cout<<red<<"Warning:"<<normal<<" min is more than / equal to max"<<endl; 
        }
        // do actual clip operations
        if (this->arg->value >= this->child[0]->value &&
            this->arg->value <= this->child[1]->value) {
            // in range
            this->value = this->arg->value;
            return this->value;
        } else if (this->arg->value <= this->child[0]->value) {
            this->value = this->child[0]->value; 
            return this->value;
        } else {
            this->value = this->child[1]->value;
            return this->value;
        }
    }
    else if (this->child[0] != NULL) {
        // this is called binary tree traversal
        // execute left child
        double input_one = this->child[0]->eval(false);
        // execute right child (may not work becuase of 1 input function)
        double input_two = 0;
        if (this->child[1] != NULL) input_two = this->child[1]->eval(false);
        this->value = this->exec_op(input_one, this->operation, input_two);
        // could throw weird numbers (for ex: 3.344105426e74)
        return this->value;
    }
    else {
        // input
        if (this->operation == op::argument || this->operation == op::input) return this->value;
        else {throw invalid_argument("No children return error");}
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
subq $0x50, %rsp
movl %esi, %r14d
movq %rdi, %rbx
movb 0xaf07(%rip), %al       # 0xf1a0
testb %al, %al
je 0x448f
movb 0xaf19(%rip), %al       # 0xf1c0
testb %al, %al
je 0x4499
testb %r14b, %r14b
je 0x42e2
movq 0xaeed(%rip), %rax      # 0xf1a8
cmpq %rax, 0xaeee(%rip)      # 0xf1b0
je 0x42cb
movq %rax, 0xaee5(%rip)      # 0xf1b0
movq 0xaeb6(%rip), %rax      # 0xf188
cmpq %rax, 0xaeb7(%rip)      # 0xf190
je 0x42e2
movq %rax, 0xaeae(%rip)      # 0xf190
movl 0x8(%rbx), %eax
cmpl $0xa, %eax
jne 0x442d
movq 0x28(%rbx), %rdi
xorl %esi, %esi
callq 0x427e
movq 0x10(%rbx), %rdi
xorl %esi, %esi
callq 0x427e
movq 0x18(%rbx), %rdi
xorl %esi, %esi
callq 0x427e
movq 0x10(%rbx), %rax
movq 0x18(%rbx), %rcx
movsd (%rax), %xmm1
ucomisd (%rcx), %xmm1
jb 0x4401
leaq -0x58(%rbp), %r15
movq %r15, -0x10(%r15)
leaq 0x5e66(%rip), %rsi      # 0xa19a
leaq 0x5e66(%rip), %rdx      # 0xa1a1
leaq -0x68(%rbp), %rdi
callq 0x45f8
leaq -0x38(%rbp), %r12
movq %r12, -0x10(%r12)
leaq 0x5e4e(%rip), %rsi      # 0xa1a2
leaq 0x5e4b(%rip), %rdx      # 0xa1a6
leaq -0x48(%rbp), %rdi
callq 0x45f8
movq -0x68(%rbp), %rsi
movq -0x60(%rbp), %rdx
movq 0xac55(%rip), %rdi      # 0xefc8
callq 0x21b0
movq %rax, %r14
leaq 0x5e25(%rip), %rsi      # 0xa1a7
movl $0x8, %edx
movq %rax, %rdi
callq 0x21b0
movq -0x48(%rbp), %rsi
movq -0x40(%rbp), %rdx
movq %r14, %rdi
callq 0x21b0
movq %rax, %r14
leaq 0x5e07(%rip), %rsi      # 0xa1b0
movl $0x20, %edx
movq %rax, %rdi
callq 0x21b0
movq (%r14), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x2180
movsbl %al, %esi
movq %r14, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x2110
movq -0x48(%rbp), %rdi
cmpq %r12, %rdi
je 0x43eb
callq 0x2170
movq -0x68(%rbp), %rdi
cmpq %r15, %rdi
je 0x43f9
callq 0x2170
movq 0x10(%rbx), %rax
movsd (%rax), %xmm1
movq 0x28(%rbx), %rax
movsd (%rax), %xmm0
ucomisd %xmm1, %xmm0
jb 0x441d
movq 0x18(%rbx), %rax
movsd (%rax), %xmm2
ucomisd %xmm0, %xmm2
jae 0x447e
ucomisd %xmm0, %xmm1
jae 0x4468
movq 0x18(%rbx), %rax
movsd (%rax), %xmm0
jmp 0x447e
movq 0x10(%rbx), %rdi
testq %rdi, %rdi
je 0x445d
xorl %esi, %esi
callq 0x427e
movq 0x18(%rbx), %rdi
testq %rdi, %rdi
je 0x4472
xorl %esi, %esi
movsd %xmm0, -0x28(%rbp)
callq 0x427e
movapd %xmm0, %xmm1
movsd -0x28(%rbp), %xmm0
jmp 0x4476
cmpl $0x1, %eax
ja 0x44a3
movsd (%rbx), %xmm0
jmp 0x4482
movsd %xmm1, (%rbx)
movapd %xmm1, %xmm0
jmp 0x4482
xorpd %xmm1, %xmm1
movl 0x8(%rbx), %esi
callq 0x4188
movsd %xmm0, (%rbx)
addq $0x50, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq
callq 0x22c0
jmp 0x42a1
callq 0x230f
jmp 0x42af
movl $0x10, %edi
callq 0x20c0
movq %rax, %r14
leaq 0x5d1a(%rip), %rsi      # 0xa1d1
movq %rax, %rdi
callq 0x2290
movq 0xab1a(%rip), %rsi      # 0xefe0
movq 0xab03(%rip), %rdx      # 0xefd0
movq %r14, %rdi
callq 0x2210
movq %rax, %rbx
movq %r14, %rdi
callq 0x2130
jmp 0x450b
movq %rax, %rbx
jmp 0x44fd
movq %rax, %rbx
jmp 0x450b
movq %rax, %rbx
movq -0x48(%rbp), %rdi
cmpq %r12, %rdi
je 0x44fd
callq 0x2170
movq -0x68(%rbp), %rdi
cmpq %r15, %rdi
je 0x450b
callq 0x2170
movq %rbx, %rdi
callq 0x2250
nop