// File: 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
subq $0xd0, %rsp
movb %sil, %al
movq %rdi, -0x10(%rbp)
andb $0x1, %al
movb %al, -0x11(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x90(%rbp)
cmpb $0x0, 0x104c7(%rip)     # 0x151d0
jne 0x4d4e
leaq 0x104be(%rip), %rdi     # 0x151d0
callq 0x22a0
cmpl $0x0, %eax
je 0x4d4e
leaq 0x10495(%rip), %rdi     # 0x151b8
callq 0x52f0
leaq 0x5e1(%rip), %rdi       # 0x5310
leaq 0x10482(%rip), %rsi     # 0x151b8
leaq 0x10453(%rip), %rdx     # 0x15190
callq 0x2180
leaq 0x10487(%rip), %rdi     # 0x151d0
callq 0x2120
cmpb $0x0, 0x1049b(%rip)     # 0x151f0
jne 0x4d9a
leaq 0x10492(%rip), %rdi     # 0x151f0
callq 0x22a0
cmpl $0x0, %eax
je 0x4d9a
leaq 0x10469(%rip), %rdi     # 0x151d8
callq 0x52f0
leaq 0x595(%rip), %rdi       # 0x5310
leaq 0x10456(%rip), %rsi     # 0x151d8
leaq 0x10407(%rip), %rdx     # 0x15190
callq 0x2180
leaq 0x1045b(%rip), %rdi     # 0x151f0
callq 0x2120
testb $0x1, -0x11(%rbp)
je 0x4dc2
movl $0x0, 0x1040a(%rip)     # 0x151b4
leaq 0x10427(%rip), %rdi     # 0x151d8
callq 0x5370
leaq 0x103fb(%rip), %rdi     # 0x151b8
callq 0x5370
movq -0x90(%rbp), %rax
cmpl $0xa, 0x8(%rax)
jne 0x5027
movq -0x90(%rbp), %rax
movq 0x28(%rax), %rdi
xorl %esi, %esi
callq 0x4ce0
movq -0x90(%rbp), %rax
movq 0x10(%rax), %rdi
xorl %esi, %esi
callq 0x4ce0
movq -0x90(%rbp), %rax
movq 0x18(%rax), %rdi
xorl %esi, %esi
callq 0x4ce0
movq -0x90(%rbp), %rax
movq 0x10(%rax), %rcx
movsd (%rcx), %xmm0
movq 0x18(%rax), %rax
ucomisd (%rax), %xmm0
jb 0x4f71
leaq -0x39(%rbp), %rdi
movq %rdi, -0x98(%rbp)
callq 0x2290
movq -0x98(%rbp), %rdx
leaq 0xa332(%rip), %rsi      # 0xf176
leaq -0x38(%rbp), %rdi
callq 0x2200
jmp 0x4e4f
leaq -0x39(%rbp), %rdi
callq 0x21e0
leaq -0x71(%rbp), %rdi
movq %rdi, -0xa0(%rbp)
callq 0x2290
movq -0xa0(%rbp), %rdx
leaq 0xa308(%rip), %rsi      # 0xf17e
leaq -0x70(%rbp), %rdi
callq 0x2200
jmp 0x4e81
leaq -0x71(%rbp), %rdi
callq 0x21e0
movq 0x10137(%rip), %rdi     # 0x14fc8
leaq -0x38(%rbp), %rsi
callq 0x2190
movq %rax, -0xa8(%rbp)
jmp 0x4ea3
movq -0xa8(%rbp), %rdi
leaq 0xa2d2(%rip), %rsi      # 0xf183
callq 0x21b0
movq %rax, -0xb0(%rbp)
jmp 0x4ebf
movq -0xb0(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0x2190
movq %rax, -0xb8(%rbp)
jmp 0x4ed8
movq -0xb8(%rbp), %rdi
leaq 0xa2a6(%rip), %rsi      # 0xf18c
callq 0x21b0
movq %rax, -0xc0(%rbp)
jmp 0x4ef4
movq -0xc0(%rbp), %rdi
movq 0x100b6(%rip), %rsi     # 0x14fb8
callq 0x21d0
jmp 0x4f09
leaq -0x70(%rbp), %rdi
callq 0x2110
leaq -0x38(%rbp), %rdi
callq 0x2110
jmp 0x4f71
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x39(%rbp), %rdi
callq 0x21e0
jmp 0x5147
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x71(%rbp), %rdi
callq 0x21e0
jmp 0x4f63
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x70(%rbp), %rdi
callq 0x2110
leaq -0x38(%rbp), %rdi
callq 0x2110
jmp 0x5147
movq -0x90(%rbp), %rax
movq 0x28(%rax), %rcx
movsd (%rcx), %xmm0
movq 0x10(%rax), %rax
ucomisd (%rax), %xmm0
jb 0x4fc8
movq -0x90(%rbp), %rax
movq 0x28(%rax), %rcx
movsd (%rcx), %xmm1
movq 0x18(%rax), %rax
movsd (%rax), %xmm0
ucomisd %xmm1, %xmm0
jb 0x4fc8
movq -0x90(%rbp), %rax
movq 0x28(%rax), %rcx
movsd (%rcx), %xmm0
movsd %xmm0, (%rax)
movsd (%rax), %xmm0
movsd %xmm0, -0x8(%rbp)
jmp 0x5139
movq -0x90(%rbp), %rax
movq 0x28(%rax), %rcx
movsd (%rcx), %xmm1
movq 0x10(%rax), %rax
movsd (%rax), %xmm0
ucomisd %xmm1, %xmm0
jb 0x5006
movq -0x90(%rbp), %rax
movq 0x10(%rax), %rcx
movsd (%rcx), %xmm0
movsd %xmm0, (%rax)
movsd (%rax), %xmm0
movsd %xmm0, -0x8(%rbp)
jmp 0x5139
movq -0x90(%rbp), %rax
movq 0x18(%rax), %rcx
movsd (%rcx), %xmm0
movsd %xmm0, (%rax)
movsd (%rax), %xmm0
movsd %xmm0, -0x8(%rbp)
jmp 0x5139
movq -0x90(%rbp), %rax
cmpq $0x0, 0x10(%rax)
je 0x50b4
movq -0x90(%rbp), %rax
movq 0x10(%rax), %rdi
xorl %esi, %esi
callq 0x4ce0
movq -0x90(%rbp), %rax
movsd %xmm0, -0x80(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x88(%rbp)
cmpq $0x0, 0x18(%rax)
je 0x507f
movq -0x90(%rbp), %rax
movq 0x18(%rax), %rdi
xorl %esi, %esi
callq 0x4ce0
movsd %xmm0, -0x88(%rbp)
movq -0x90(%rbp), %rdi
movsd -0x80(%rbp), %xmm0
movl 0x8(%rdi), %esi
movsd -0x88(%rbp), %xmm1
callq 0x4ad0
movq -0x90(%rbp), %rax
movsd %xmm0, (%rax)
movsd (%rax), %xmm0
movsd %xmm0, -0x8(%rbp)
jmp 0x5139
movq -0x90(%rbp), %rax
cmpl $0x1, 0x8(%rax)
je 0x50ce
movq -0x90(%rbp), %rax
cmpl $0x0, 0x8(%rax)
jne 0x50e0
movq -0x90(%rbp), %rax
movsd (%rax), %xmm0
movsd %xmm0, -0x8(%rbp)
jmp 0x5139
movl $0x10, %edi
callq 0x20c0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xc8(%rbp)
leaq 0xa0af(%rip), %rsi      # 0xf1ad
callq 0x22c0
jmp 0x5105
movq -0xc8(%rbp), %rdi
movq 0xfecd(%rip), %rsi      # 0x14fe0
movq 0xfeb6(%rip), %rdx      # 0x14fd0
callq 0x2240
movq -0xc8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
callq 0x2150
jmp 0x5147
movsd -0x8(%rbp), %xmm0
addq $0xd0, %rsp
popq %rbp
retq
movq -0x48(%rbp), %rdi
callq 0x2280