// File: pgrouchy[P]NoiseWorld/mathNet.cpp
// Function: Tree::reduceEqn()
void Tree::reduceEqn() {
    if (!this->isTerminal) {
        switch ((int)this->myVal) {
            case ADD: {
                this->leftTree->reduceEqn();
                this->rightTree->reduceEqn();
                if ((this->leftTree->isConstant) && (this->rightTree->isConstant)) { // reduce the addition of two constants to a single constant
                    this->myVal = this->leftTree->myVal + this->rightTree->myVal;
                    this->isConstant = true;
                    this->isTerminal = true;
                    delete this->leftTree;
                    delete this->rightTree;
                    this->leftTree = NULL;
                    this->rightTree = NULL;
                } else if (this->leftTree->isEqual(this->rightTree)) { // reduce the addition of two equal trees to 2x a single copy of that tree
                    this->myVal = MULTIPLY;
                    this->rightTree->myVal = 2.0;
                    this->rightTree->isConstant = true;
                    this->rightTree->isTerminal = true;
                    delete this->rightTree->leftTree;
                    this->rightTree->leftTree = NULL;
                    delete this->rightTree->rightTree;
                    this->rightTree->rightTree = NULL;
                }
                break;
            }
            case SUBTRACT: {
                this->leftTree->reduceEqn();
                this->rightTree->reduceEqn();
                if ((this->leftTree->isConstant) && (this->rightTree->isConstant)) { // reduce the subtraction of two constants to a single constant
                    this->myVal = this->leftTree->myVal - this->rightTree->myVal;
                    this->isConstant = true;
                    this->isTerminal = true;
                    delete this->leftTree;
                    delete this->rightTree;
                    this->leftTree = NULL;
                    this->rightTree = NULL;
                } else if (this->leftTree->isEqual(this->rightTree)) { // reduce the subtraction of two equal trees to 0
                    this->myVal = 0.0;
                    this->isConstant = true;
                    this->isTerminal = true;
                    delete this->leftTree;
                    delete this->rightTree;
                    this->leftTree = NULL;
                    this->rightTree = NULL;
                }
                break;
            }
            case MULTIPLY: {
                this->leftTree->reduceEqn();
                this->rightTree->reduceEqn();
                if ((this->leftTree->isConstant) && (this->rightTree->isConstant)) { // reduce the multiplication of two constants to a single constant
                    this->myVal = this->leftTree->myVal * this->rightTree->myVal;
                    this->isConstant = true;
                    this->isTerminal = true;
                    delete this->leftTree;
                    delete this->rightTree;
                    this->leftTree = NULL;
                    this->rightTree = NULL;
                } else if ((this->leftTree->isConstant) && ((int)this->leftTree->myVal == 0)) { // reduce the multiplication of a subtree by 0 to 0 (i.e., delete the subtree)
                    this->myVal = 0.0;
                    this->isConstant = true;
                    this->isTerminal = true;
                    delete this->leftTree;
                    delete this->rightTree;
                    this->leftTree = NULL;
                    this->rightTree = NULL;
                } else if ((this->rightTree->isConstant) && ((int)this->rightTree->myVal == 0)) { // reduce the multiplication of a subtree by 0 to 0 (i.e., delete the subtree)
                    this->myVal = 0.0;
                    this->isConstant = true;
                    this->isTerminal = true;
                    delete this->leftTree;
                    delete this->rightTree;
                    this->leftTree = NULL;
                    this->rightTree = NULL;
                }
                break;
            }
            case DIVIDE: {
                this->leftTree->reduceEqn();
                this->rightTree->reduceEqn();
                if ((this->leftTree->isConstant) && (this->rightTree->isConstant)) { // reduce the division of two constants to a single constant
                    if ((int)this->rightTree->myVal != 0) { // skip any division-by-zero operations, such agents will be selected to die after initial evaluation of EMM (see island.cpp)
                        this->myVal = this->leftTree->myVal / this->rightTree->myVal;
                        this->isConstant = true;
                        this->isTerminal = true;
                        delete this->leftTree;
                        delete this->rightTree;
                        this->leftTree = NULL;
                        this->rightTree = NULL;
                    }
                } else if ((this->leftTree->isConstant) && ((int)this->leftTree->myVal == 0)) { // reduce the division of 0 by a subtree to 0
                    this->myVal = 0.0;
                    this->isConstant = true;
                    this->isTerminal = true;
                    delete this->leftTree;
                    delete this->rightTree;
                    this->leftTree = NULL;
                    this->rightTree = NULL;
                }
                break;
            }
        }
    }
}

// Assembly:
subq $0xa8, %rsp
movq %rdi, 0xa0(%rsp)
movq 0xa0(%rsp), %rax
movq %rax, 0x98(%rsp)
cmpl $0x0, 0x18(%rax)
jne 0xb958
movq 0x98(%rsp), %rax
cvttsd2si 0x20(%rax), %eax
movl %eax, %ecx
movq %rcx, 0x90(%rsp)
subl $0x3, %eax
ja 0xb956
movq 0x90(%rsp), %rax
leaq 0xa060(%rip), %rcx      # 0x15208
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0x98(%rsp), %rax
movq (%rax), %rdi
callq 0xb150
movq 0x98(%rsp), %rax
movq 0x8(%rax), %rdi
callq 0xb150
movq 0x98(%rsp), %rax
movq (%rax), %rax
cmpl $0x0, 0x1c(%rax)
je 0xb2ae
movq 0x98(%rsp), %rax
movq 0x8(%rax), %rax
cmpl $0x0, 0x1c(%rax)
je 0xb2ae
movq 0x98(%rsp), %rax
movq (%rax), %rcx
movsd 0x20(%rcx), %xmm0
movq 0x8(%rax), %rcx
addsd 0x20(%rcx), %xmm0
movsd %xmm0, 0x20(%rax)
movl $0x1, 0x1c(%rax)
movl $0x1, 0x18(%rax)
movq (%rax), %rax
movq %rax, 0x88(%rsp)
cmpq $0x0, %rax
je 0xb259
movq 0x88(%rsp), %rdi
callq 0x89f0
movq 0x88(%rsp), %rdi
movl $0x38, %esi
callq 0x32b0
movq 0x98(%rsp), %rax
movq 0x8(%rax), %rax
movq %rax, 0x80(%rsp)
cmpq $0x0, %rax
je 0xb292
movq 0x80(%rsp), %rdi
callq 0x89f0
movq 0x80(%rsp), %rdi
movl $0x38, %esi
callq 0x32b0
movq 0x98(%rsp), %rax
movq $0x0, (%rax)
movq $0x0, 0x8(%rax)
jmp 0xb387
movq 0x98(%rsp), %rax
movq (%rax), %rdi
movq 0x8(%rax), %rsi
callq 0xb960
testb $0x1, %al
jne 0xb2cb
jmp 0xb385
movq 0x98(%rsp), %rax
movsd 0x9f55(%rip), %xmm0     # 0x15230
movsd %xmm0, 0x20(%rax)
movq 0x8(%rax), %rcx
movsd 0x9f44(%rip), %xmm0     # 0x15230
movsd %xmm0, 0x20(%rcx)
movq 0x8(%rax), %rcx
movl $0x1, 0x1c(%rcx)
movq 0x8(%rax), %rcx
movl $0x1, 0x18(%rcx)
movq 0x8(%rax), %rax
movq (%rax), %rax
movq %rax, 0x78(%rsp)
cmpq $0x0, %rax
je 0xb332
movq 0x78(%rsp), %rdi
callq 0x89f0
movq 0x78(%rsp), %rdi
movl $0x38, %esi
callq 0x32b0
movq 0x98(%rsp), %rax
movq 0x8(%rax), %rcx
movq $0x0, (%rcx)
movq 0x8(%rax), %rax
movq 0x8(%rax), %rax
movq %rax, 0x70(%rsp)
cmpq $0x0, %rax
je 0xb371
movq 0x70(%rsp), %rdi
callq 0x89f0
movq 0x70(%rsp), %rdi
movl $0x38, %esi
callq 0x32b0
movq 0x98(%rsp), %rax
movq 0x8(%rax), %rax
movq $0x0, 0x8(%rax)
jmp 0xb387
jmp 0xb956
movq 0x98(%rsp), %rax
movq (%rax), %rdi
callq 0xb150
movq 0x98(%rsp), %rax
movq 0x8(%rax), %rdi
callq 0xb150
movq 0x98(%rsp), %rax
movq (%rax), %rax
cmpl $0x0, 0x1c(%rax)
je 0xb477
movq 0x98(%rsp), %rax
movq 0x8(%rax), %rax
cmpl $0x0, 0x1c(%rax)
je 0xb477
movq 0x98(%rsp), %rax
movq (%rax), %rcx
movsd 0x20(%rcx), %xmm0
movq 0x8(%rax), %rcx
subsd 0x20(%rcx), %xmm0
movsd %xmm0, 0x20(%rax)
movl $0x1, 0x1c(%rax)
movl $0x1, 0x18(%rax)
movq (%rax), %rax
movq %rax, 0x68(%rsp)
cmpq $0x0, %rax
je 0xb42b
movq 0x68(%rsp), %rdi
callq 0x89f0
movq 0x68(%rsp), %rdi
movl $0x38, %esi
callq 0x32b0
movq 0x98(%rsp), %rax
movq 0x8(%rax), %rax
movq %rax, 0x60(%rsp)
cmpq $0x0, %rax
je 0xb45b
movq 0x60(%rsp), %rdi
callq 0x89f0
movq 0x60(%rsp), %rdi
movl $0x38, %esi
callq 0x32b0
movq 0x98(%rsp), %rax
movq $0x0, (%rax)
movq $0x0, 0x8(%rax)
jmp 0xb522
movq 0x98(%rsp), %rax
movq (%rax), %rdi
movq 0x8(%rax), %rsi
callq 0xb960
testb $0x1, %al
jne 0xb494
jmp 0xb520
movq 0x98(%rsp), %rax
xorps %xmm0, %xmm0
movsd %xmm0, 0x20(%rax)
movl $0x1, 0x1c(%rax)
movl $0x1, 0x18(%rax)
movq (%rax), %rax
movq %rax, 0x58(%rsp)
cmpq $0x0, %rax
je 0xb4d9
movq 0x58(%rsp), %rdi
callq 0x89f0
movq 0x58(%rsp), %rdi
movl $0x38, %esi
callq 0x32b0
movq 0x98(%rsp), %rax
movq 0x8(%rax), %rax
movq %rax, 0x50(%rsp)
cmpq $0x0, %rax
je 0xb509
movq 0x50(%rsp), %rdi
callq 0x89f0
movq 0x50(%rsp), %rdi
movl $0x38, %esi
callq 0x32b0
movq 0x98(%rsp), %rax
movq $0x0, (%rax)
movq $0x0, 0x8(%rax)
jmp 0xb522
jmp 0xb956
movq 0x98(%rsp), %rax
movq (%rax), %rdi
callq 0xb150
movq 0x98(%rsp), %rax
movq 0x8(%rax), %rdi
callq 0xb150
movq 0x98(%rsp), %rax
movq (%rax), %rax
cmpl $0x0, 0x1c(%rax)
je 0xb612
movq 0x98(%rsp), %rax
movq 0x8(%rax), %rax
cmpl $0x0, 0x1c(%rax)
je 0xb612
movq 0x98(%rsp), %rax
movq (%rax), %rcx
movsd 0x20(%rcx), %xmm0
movq 0x8(%rax), %rcx
mulsd 0x20(%rcx), %xmm0
movsd %xmm0, 0x20(%rax)
movl $0x1, 0x1c(%rax)
movl $0x1, 0x18(%rax)
movq (%rax), %rax
movq %rax, 0x48(%rsp)
cmpq $0x0, %rax
je 0xb5c6
movq 0x48(%rsp), %rdi
callq 0x89f0
movq 0x48(%rsp), %rdi
movl $0x38, %esi
callq 0x32b0
movq 0x98(%rsp), %rax
movq 0x8(%rax), %rax
movq %rax, 0x40(%rsp)
cmpq $0x0, %rax
je 0xb5f6
movq 0x40(%rsp), %rdi
callq 0x89f0
movq 0x40(%rsp), %rdi
movl $0x38, %esi
callq 0x32b0
movq 0x98(%rsp), %rax
movq $0x0, (%rax)
movq $0x0, 0x8(%rax)
jmp 0xb791
movq 0x98(%rsp), %rax
movq (%rax), %rax
cmpl $0x0, 0x1c(%rax)
je 0xb6d1
movq 0x98(%rsp), %rax
movq (%rax), %rax
cvttsd2si 0x20(%rax), %eax
cmpl $0x0, %eax
jne 0xb6d1
movq 0x98(%rsp), %rax
xorps %xmm0, %xmm0
movsd %xmm0, 0x20(%rax)
movl $0x1, 0x1c(%rax)
movl $0x1, 0x18(%rax)
movq (%rax), %rax
movq %rax, 0x38(%rsp)
cmpq $0x0, %rax
je 0xb685
movq 0x38(%rsp), %rdi
callq 0x89f0
movq 0x38(%rsp), %rdi
movl $0x38, %esi
callq 0x32b0
movq 0x98(%rsp), %rax
movq 0x8(%rax), %rax
movq %rax, 0x30(%rsp)
cmpq $0x0, %rax
je 0xb6b5
movq 0x30(%rsp), %rdi
callq 0x89f0
movq 0x30(%rsp), %rdi
movl $0x38, %esi
callq 0x32b0
movq 0x98(%rsp), %rax
movq $0x0, (%rax)
movq $0x0, 0x8(%rax)
jmp 0xb78f
movq 0x98(%rsp), %rax
movq 0x8(%rax), %rax
cmpl $0x0, 0x1c(%rax)
je 0xb78d
movq 0x98(%rsp), %rax
movq 0x8(%rax), %rax
cvttsd2si 0x20(%rax), %eax
cmpl $0x0, %eax
jne 0xb78d
movq 0x98(%rsp), %rax
xorps %xmm0, %xmm0
movsd %xmm0, 0x20(%rax)
movl $0x1, 0x1c(%rax)
movl $0x1, 0x18(%rax)
movq (%rax), %rax
movq %rax, 0x28(%rsp)
cmpq $0x0, %rax
je 0xb746
movq 0x28(%rsp), %rdi
callq 0x89f0
movq 0x28(%rsp), %rdi
movl $0x38, %esi
callq 0x32b0
movq 0x98(%rsp), %rax
movq 0x8(%rax), %rax
movq %rax, 0x20(%rsp)
cmpq $0x0, %rax
je 0xb776
movq 0x20(%rsp), %rdi
callq 0x89f0
movq 0x20(%rsp), %rdi
movl $0x38, %esi
callq 0x32b0
movq 0x98(%rsp), %rax
movq $0x0, (%rax)
movq $0x0, 0x8(%rax)
jmp 0xb78f
jmp 0xb791
jmp 0xb956
movq 0x98(%rsp), %rax
movq (%rax), %rdi
callq 0xb150
movq 0x98(%rsp), %rax
movq 0x8(%rax), %rdi
callq 0xb150
movq 0x98(%rsp), %rax
movq (%rax), %rax
cmpl $0x0, 0x1c(%rax)
je 0xb89b
movq 0x98(%rsp), %rax
movq 0x8(%rax), %rax
cmpl $0x0, 0x1c(%rax)
je 0xb89b
movq 0x98(%rsp), %rax
movq 0x8(%rax), %rax
cvttsd2si 0x20(%rax), %eax
cmpl $0x0, %eax
je 0xb896
movq 0x98(%rsp), %rax
movq (%rax), %rcx
movsd 0x20(%rcx), %xmm0
movq 0x8(%rax), %rcx
divsd 0x20(%rcx), %xmm0
movsd %xmm0, 0x20(%rax)
movl $0x1, 0x1c(%rax)
movl $0x1, 0x18(%rax)
movq (%rax), %rax
movq %rax, 0x18(%rsp)
cmpq $0x0, %rax
je 0xb84f
movq 0x18(%rsp), %rdi
callq 0x89f0
movq 0x18(%rsp), %rdi
movl $0x38, %esi
callq 0x32b0
movq 0x98(%rsp), %rax
movq 0x8(%rax), %rax
movq %rax, 0x10(%rsp)
cmpq $0x0, %rax
je 0xb87f
movq 0x10(%rsp), %rdi
callq 0x89f0
movq 0x10(%rsp), %rdi
movl $0x38, %esi
callq 0x32b0
movq 0x98(%rsp), %rax
movq $0x0, (%rax)
movq $0x0, 0x8(%rax)
jmp 0xb954
movq 0x98(%rsp), %rax
movq (%rax), %rax
cmpl $0x0, 0x1c(%rax)
je 0xb952
movq 0x98(%rsp), %rax
movq (%rax), %rax
cvttsd2si 0x20(%rax), %eax
cmpl $0x0, %eax
jne 0xb952
movq 0x98(%rsp), %rax
xorps %xmm0, %xmm0
movsd %xmm0, 0x20(%rax)
movl $0x1, 0x1c(%rax)
movl $0x1, 0x18(%rax)
movq (%rax), %rax
movq %rax, 0x8(%rsp)
cmpq $0x0, %rax
je 0xb90e
movq 0x8(%rsp), %rdi
callq 0x89f0
movq 0x8(%rsp), %rdi
movl $0x38, %esi
callq 0x32b0
movq 0x98(%rsp), %rax
movq 0x8(%rax), %rax
movq %rax, (%rsp)
cmpq $0x0, %rax
je 0xb93b
movq (%rsp), %rdi
callq 0x89f0
movq (%rsp), %rdi
movl $0x38, %esi
callq 0x32b0
movq 0x98(%rsp), %rax
movq $0x0, (%rax)
movq $0x0, 0x8(%rax)
jmp 0xb954
jmp 0xb956
jmp 0xb958
addq $0xa8, %rsp
retq