// File: /workspace/github_cpp_makefile_star2_O2/ryanbarringtoncox[P]AVLTree/AVLTree.cpp
// Function: AVLTree<double>::insert(double)
void AVLTree<T>::insert(T v) {
	Node<T>* temp = new Node<T>(v);
	Node<T>** curr = &root;

	//double rotation flags
	bool rightLeft = false;
	bool leftRight = false;
	
	//tree is empty, insert at root
	if (*curr == 0) {
		*curr = temp;			
	}
	
	else {

		//keep a parent pointer
		Node<T>** dad = &root;
		
		//Critical node is null by default
		cn = 0;
		
		//find spot for new node, keep track of potential cns
		while (*curr != 0) {
			
			if (v == (*curr)->getValue()) return;
			
			if (v < (*curr)->getValue()) {
				if ((*curr)->getBalance() == -1) {
					cn = *curr;
					dad = &*curr;
				}
				if (cn && cn->getBalance() > 0) {
					cout << "Rotate right then left" << endl;
					rightLeft = true;
				}
				curr = &((*curr)->getLeftChild());
			} else if (v > (*curr)->getValue()) {
				if ((*curr)->getBalance() == 1) {
					cn = *curr;	
					dad = &*curr;
				}
				if (cn && cn->getBalance() < 0) {
					cout << "Rotate left then right" << endl;
					leftRight = true;
				}
				curr = &((*curr)->getRightChild());
			}
		}
		
		//insert the node
		*curr = temp;	
		
		
		//no cn, update balances
		if (!cn) {			
			curr = &root;
			while (*curr != 0) {
				if (v < (*curr)->getValue()) {
					(*curr)->decBalance();
					curr = &((*curr)->getLeftChild());
				} else if (v > (*curr)->getValue()) {
					(*curr)->incBalance();					
					curr = &((*curr)->getRightChild());
				}
				else if (v == (*curr)->getValue()) break;
			}			
		}		
		
		//single rotations
		if (cn && !rightLeft && !leftRight) {			
			//cout << "Cn found: " << cn->getValue() << endl;
			curr = &cn;
			
			if ((*curr)->getBalance() == -1) {	
				rightRotation(cn, dad);
			}
			
			if ((*curr)->getBalance()== 1) {	
				leftRotation(cn, dad);
			}
			
			//reset cn balance to zero
			cn->resetBalance();			
			
		}
			
		//double rotations
		if (cn && rightLeft) {
			rightRotation(cn->getRightChild(), &(cn->getRightChild()));
			leftRotation(cn, dad);
			cn->resetBalance();
		}
		if (cn && leftRight) {
			leftRotation(cn->getLeftChild(), &(cn->getLeftChild()));
			rightRotation(cn, dad);
			cn->resetBalance();
		}
	}
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movsd %xmm0, 0x8(%rsp)
movq %rdi, %rbx
pushq $0x28
popq %rdi
callq 0x2150
movq %rax, %r15
movq %rax, %rdi
movsd 0x8(%rsp), %xmm0
callq 0x65dc
movq (%rbx), %rdi
testq %rdi, %rdi
je 0x498c
andq $0x0, 0x8(%rbx)
xorl %r13d, %r13d
movq 0x8745(%rip), %r12      # 0xcfd8
movq %rbx, %r14
movl $0x0, 0x14(%rsp)
movq %rbx, %rbp
testq %rdi, %rdi
je 0x4994
callq 0x65f2
ucomisd 0x8(%rsp), %xmm0
jne 0x48bd
jnp 0x4aac
movq (%r14), %rdi
callq 0x65f2
ucomisd 0x8(%rsp), %xmm0
movq (%r14), %rdi
jbe 0x48e0
callq 0x65f8
cmpl $-0x1, %eax
je 0x490e
movq 0x8(%rbx), %rdi
jmp 0x4918
callq 0x65f2
movsd 0x8(%rsp), %xmm1
ucomisd %xmm0, %xmm1
jbe 0x4984
movq (%r14), %rdi
callq 0x65f8
cmpl $0x1, %eax
jne 0x494a
movq (%r14), %rdi
movq %rdi, 0x8(%rbx)
movq %r14, %rbp
jmp 0x494e
movq (%r14), %rdi
movq %rdi, 0x8(%rbx)
movq %r14, %rbp
testq %rdi, %rdi
je 0x4940
callq 0x65f8
testl %eax, %eax
jle 0x4940
movq %r12, %rdi
leaq 0x3878(%rip), %rsi      # 0x81a8
callq 0x2140
movq %rax, %rdi
callq 0x20b0
movb $0x1, %r13b
movq (%r14), %rdi
callq 0x6610
jmp 0x4981
movq 0x8(%rbx), %rdi
testq %rdi, %rdi
je 0x4979
callq 0x65f8
testl %eax, %eax
jns 0x4979
movq %r12, %rdi
leaq 0x3859(%rip), %rsi      # 0x81bf
callq 0x2140
movq %rax, %rdi
callq 0x20b0
movb $0x1, %al
movl %eax, 0x14(%rsp)
movq (%r14), %rdi
callq 0x661c
movq %rax, %r14
movq (%r14), %rdi
jmp 0x48a1
movq %r15, (%rbx)
jmp 0x4aac
movq %r15, (%r14)
movq 0x8(%rbx), %rdi
testq %rdi, %rdi
jne 0x4a11
movq %rbx, %r14
movq (%r14), %rdi
testq %rdi, %rdi
je 0x4a04
callq 0x65f2
ucomisd 0x8(%rsp), %xmm0
movq (%r14), %rdi
ja 0x49e0
callq 0x65f2
movsd 0x8(%rsp), %xmm1
ucomisd %xmm0, %xmm1
movq (%r14), %rdi
ja 0x49f2
callq 0x65f2
ucomisd 0x8(%rsp), %xmm0
jne 0x49a3
jp 0x49a3
jmp 0x4a04
callq 0x6600
movq (%r14), %rdi
callq 0x6610
movq %rax, %r14
jmp 0x49a3
callq 0x65fc
movq (%r14), %rdi
callq 0x661c
movq %rax, %r14
jmp 0x49a3
movq 0x8(%rbx), %rdi
testq %rdi, %rdi
je 0x4aac
testb $0x1, %r13b
je 0x4a59
callq 0x661c
movq (%rax), %r14
movq 0x8(%rbx), %rdi
callq 0x661c
movq %rbx, %rdi
movq %r14, %rsi
movq %rax, %rdx
callq 0x448c
movq 0x8(%rbx), %rsi
movq %rbx, %rdi
movq %rbp, %rdx
callq 0x43ec
movq 0x8(%rbx), %rdi
callq 0x6604
movq 0x8(%rbx), %rdi
testq %rdi, %rdi
jne 0x4a60
jmp 0x4aac
testb $0x1, 0x14(%rsp)
je 0x4abb
testb $0x1, 0x14(%rsp)
je 0x4aac
callq 0x6610
movq (%rax), %r14
movq 0x8(%rbx), %rdi
callq 0x6610
movq %rbx, %rdi
movq %r14, %rsi
movq %rax, %rdx
callq 0x43ec
movq 0x8(%rbx), %rsi
movq %rbx, %rdi
movq %rbp, %rdx
callq 0x448c
movq 0x8(%rbx), %rdi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x6604
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
callq 0x65f8
cmpl $-0x1, %eax
jne 0x4ad4
movq 0x8(%rbx), %rsi
movq %rbx, %rdi
movq %rbp, %rdx
callq 0x448c
movq 0x8(%rbx), %rdi
callq 0x65f8
cmpl $0x1, %eax
je 0x4a36
jmp 0x4a45
movq %rax, %rbx
pushq $0x28
popq %rsi
movq %r15, %rdi
callq 0x2160
movq %rbx, %rdi
callq 0x2210
nop