// File: /workspace/github_cpp_makefile_star2_O2/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 %r14
pushq %rbx
subq $0x50, %rsp
movl %esi, %r14d
movq %rdi, %rbx
movb 0xb495(%rip), %al       # 0xf190
testb %al, %al
je 0x3e99
movb 0xb4a7(%rip), %al       # 0xf1b0
testb %al, %al
je 0x3eec
testb %r14b, %r14b
je 0x3d44
movq 0xb47b(%rip), %rax      # 0xf198
cmpq %rax, 0xb47c(%rip)      # 0xf1a0
je 0x3d2d
movq %rax, 0xb473(%rip)      # 0xf1a0
movq 0xb444(%rip), %rax      # 0xf178
cmpq %rax, 0xb445(%rip)      # 0xf180
je 0x3d44
movq %rax, 0xb43c(%rip)      # 0xf180
movl 0x8(%rbx), %eax
cmpl $0xa, %eax
jne 0x3e37
movq 0x28(%rbx), %rdi
xorl %esi, %esi
callq 0x3ce4
movq 0x10(%rbx), %rdi
xorl %esi, %esi
callq 0x3ce4
movq 0x18(%rbx), %rdi
xorl %esi, %esi
callq 0x3ce4
movq 0x10(%rbx), %rax
movq 0x18(%rbx), %rcx
movsd (%rax), %xmm1
ucomisd (%rcx), %xmm1
jb 0x3e0b
leaq 0x640c(%rip), %rsi      # 0xa19a
leaq -0x60(%rbp), %rdi
leaq -0x40(%rbp), %rdx
callq 0x2090
leaq 0x6400(%rip), %rsi      # 0xa1a2
leaq -0x40(%rbp), %rdi
leaq -0x11(%rbp), %rdx
callq 0x2090
movq 0xb212(%rip), %rdi      # 0xefc8
leaq -0x60(%rbp), %rsi
callq 0x2140
leaq 0x63e1(%rip), %rsi      # 0xa1a7
movq %rax, %rdi
callq 0x2160
leaq -0x40(%rbp), %rsi
movq %rax, %rdi
callq 0x2140
leaq 0x63cf(%rip), %rsi      # 0xa1b0
movq %rax, %rdi
callq 0x2160
movq %rax, %rdi
callq 0x20b0
leaq -0x40(%rbp), %rdi
callq 0x20a0
leaq -0x60(%rbp), %rdi
callq 0x20a0
movq 0x10(%rbx), %rax
movsd (%rax), %xmm1
movq 0x28(%rbx), %rax
movsd (%rax), %xmm0
ucomisd %xmm1, %xmm0
jb 0x3e27
movq 0x18(%rbx), %rax
movsd (%rax), %xmm2
ucomisd %xmm0, %xmm2
jae 0x3e8c
ucomisd %xmm0, %xmm1
jae 0x3e76
movq 0x18(%rbx), %rax
movsd (%rax), %xmm0
jmp 0x3e8c
movq 0x10(%rbx), %rdi
testq %rdi, %rdi
je 0x3e67
xorl %esi, %esi
callq 0x3ce4
movq 0x18(%rbx), %rdi
testq %rdi, %rdi
je 0x3e80
xorl %esi, %esi
movsd %xmm0, -0x20(%rbp)
callq 0x3ce4
movapd %xmm0, %xmm1
movsd -0x20(%rbp), %xmm0
jmp 0x3e84
cmpl $0x1, %eax
ja 0x3f3f
movsd (%rbx), %xmm0
jmp 0x3e90
movsd %xmm1, (%rbx)
movapd %xmm1, %xmm0
jmp 0x3e90
xorpd %xmm1, %xmm1
movl 0x8(%rbx), %esi
callq 0x3bf0
movsd %xmm0, (%rbx)
addq $0x50, %rsp
popq %rbx
popq %r14
popq %rbp
retq
leaq 0xb2f0(%rip), %rdi      # 0xf190
callq 0x2240
testl %eax, %eax
je 0x3d03
xorpd %xmm0, %xmm0
movupd %xmm0, 0xb2bf(%rip)     # 0xf178
andq $0x0, 0xb2c7(%rip)      # 0xf188
leaq 0xb2b0(%rip), %rsi      # 0xf178
leaq 0x16f(%rip), %rdi       # 0x403e
leaq 0xb27a(%rip), %rdx      # 0xf150
callq 0x2130
leaq 0xb2ae(%rip), %rdi      # 0xf190
callq 0x2100
jmp 0x3d03
leaq 0xb2bd(%rip), %rdi      # 0xf1b0
callq 0x2240
testl %eax, %eax
je 0x3d11
xorpd %xmm0, %xmm0
movupd %xmm0, 0xb28c(%rip)     # 0xf198
andq $0x0, 0xb294(%rip)      # 0xf1a8
leaq 0xb27d(%rip), %rsi      # 0xf198
leaq 0x11c(%rip), %rdi       # 0x403e
leaq 0xb227(%rip), %rdx      # 0xf150
callq 0x2130
leaq 0xb27b(%rip), %rdi      # 0xf1b0
callq 0x2100
jmp 0x3d11
pushq $0x10
popq %rdi
callq 0x20c0
movq %rax, %r14
leaq 0x6280(%rip), %rsi      # 0xa1d1
movq %rax, %rdi
callq 0x2260
movq 0xb080(%rip), %rsi      # 0xefe0
movq 0xb069(%rip), %rdx      # 0xefd0
movq %r14, %rdi
callq 0x21f0
movq %rax, %rbx
movq %r14, %rdi
callq 0x2110
jmp 0x3f9b
movq %rax, %rbx
jmp 0x3f92
movq %rax, %rbx
jmp 0x3f9b
movq %rax, %rbx
leaq -0x40(%rbp), %rdi
callq 0x20a0
leaq -0x60(%rbp), %rdi
callq 0x20a0
movq %rbx, %rdi
callq 0x2230
nop