// File: /workspace/github_cpp_makefile_star2_O1/big-data-lab-team[P]OrpailleCC/./src/mondrian_coarse.hpp
// Function: int CoarseMondrianForest<double, funct, KappaMetrics<2, false>, 4, 2, 6000>::adjust_boxes<100>(int, int, double, bool, int)
int adjust_boxes(int const start_id, int const split_dimension, double const split_value, bool const subtree_on_left, int const tree_id){
	//Initialize an array to keep track of where we have to go at each tree level.
	//The max depth expected is MAX_DEPTH.
	int stack[max_stack_size];
	for(int i = 0; i < max_stack_size; ++i)
		stack[i] = -1;

	int node_id = start_id;
	int depth = 0;
	//a for loop instead of a while to avoid infinite loops. Since we don't expect to do more turn than node_count
	//*i* count the number of node deleted.
	int i = 0;
	while(i < node_count && node_id >= 0){
		Node& node = nodes()[node_id];
		if(!node.is_leaf()){  //Internal node
			if (stack[depth] == -1){ //Go right
				if(subtree_on_left){
					if(node.bound_upper[split_dimension] > split_value)
						node.bound_upper[split_dimension] = split_value;
					if(node.bound_lower[split_dimension] > split_value)
						node.bound_lower[split_dimension] = split_value;
				}
				else{
					if(node.bound_upper[split_dimension] < split_value)
						node.bound_upper[split_dimension] = split_value;
					if(node.bound_lower[split_dimension] < split_value)
						node.bound_lower[split_dimension] = split_value;
				}
				if(node.bound_upper[split_dimension] - node.bound_lower[split_dimension] == 0){ //This box is zero, let's go up
					depth -= 1;
					node_id = node.parent;
					node_reset(node.child_right);
					node_reset(node.child_left);
					//NOTE the start_id node shouldn't be at zero.
				}
				else{ //Go right
					stack[depth] = 0;
					depth += 1;
					node_id = node.child_right;
				}
			}
			else if (stack[depth] == 0){ //Go left
				stack[depth] = 1;
				depth += 1;
				node_id = node.child_left;
			}
			else if (stack[depth] == 1){ //Go up
				stack[depth] = -1; //Reset to -1
				depth -= 1;
				i += 1;

				Node const& child_left = nodes()[node.child_left];
				Node const& child_right = nodes()[node.child_right];
				int const left_zeroed = (child_left.bound_upper[split_dimension] - child_left.bound_lower[split_dimension] == 0);
				int const right_zeroed = (child_right.bound_upper[split_dimension] - child_right.bound_lower[split_dimension] == 0);
				bool const is_root = (node.parent < 0);
				bool const is_starting = (node_id == start_id);
				//NOTE either left or right is zeroed. If both are, then we stop going down at that node before
				int replacer_id = -1, other_id = -1;
				if(left_zeroed){ //replace current node with right
					replacer_id = node.child_right;
					other_id = node.child_left;
				}
				else if(right_zeroed){ //replace current node with left
					replacer_id = node.child_left;
					other_id = node.child_right;
				}

				if(replacer_id != -1){
					Node& replacer = nodes()[replacer_id];
					if(is_root){ //The root is replaced by one of the children
						tree_bases()[tree_id].root = replacer_id;
						nodes()[other_id].reset();
						node.reset();
						nodes()[replacer_id].parent = -1;
						node_available += 2;
						break;
					}
					else{ //Replace the current node in the parent 's children
						Node& parent = nodes()[node.parent];
						if(parent.child_left == node_id)
							parent.child_left = replacer_id;
						else
							parent.child_right = replacer_id;
						replacer.parent = node.parent;
					}
					//Set the id to keep exploring the tree before the reset
					node_id = node.parent;
					//reset other_id and node
					nodes()[other_id].reset();
					node.reset();
					node_available += 2;
					if(is_starting)
						break;
				}
				else{
					if(node_id == start_id)
						break;
					node_id = node.parent;
				}
			}
		}
		else{ //Leaf
			stack[depth] = -1; //Reset to -1
			depth -= 1;
			i += 1;
			if(subtree_on_left){
				if(node.bound_upper[split_dimension] > split_value)
					node.bound_upper[split_dimension] = split_value;
				if(node.bound_lower[split_dimension] > split_value)
					node.bound_lower[split_dimension] = split_value;
			}
			else{
				if(node.bound_upper[split_dimension] < split_value)
					node.bound_upper[split_dimension] = split_value;
				if(node.bound_lower[split_dimension] < split_value)
					node.bound_lower[split_dimension] = split_value;
			}
			if(node_id == start_id)
				break;
			node_id = node.parent;
		}
		if(depth >= max_stack_size)
			return -1;
	}
	if(depth != -1)
		return -1;
	return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x1b8, %rsp            # imm = 0x1B8
movl %r8d, %r15d
movl %ecx, %ebx
movsd %xmm0, 0x8(%rsp)
movl %edx, %r12d
movl %esi, %ebp
movq %rdi, %r14
leaq 0x20(%rsp), %rdi
movl $0x190, %edx            # imm = 0x190
movl $0xff, %esi
callq 0x1040
movq %r14, %rdi
movl %ebp, %r10d
movsd 0x8(%rsp), %xmm1
movl %ebx, %r9d
leaq 0x44(%r14), %r13
movslq %r12d, %rbx
movslq %r15d, %rax
imulq $0x38, %rax, %rax
addq %r14, %rax
addq $0x17bc, %rax           # imm = 0x17BC
movq %rax, 0x10(%rsp)
xorpd %xmm2, %xmm2
xorl %r12d, %r12d
xorl %r15d, %r15d
movl %r9d, 0x4(%rsp)
movl %ebp, (%rsp)
movq %rbx, 0x18(%rsp)
cmpl 0x17d4(%rdi), %r12d
jge 0x52d1
testl %ebp, %ebp
js 0x52d1
movl %ebp, %eax
shlq $0x7, %rax
leaq (%rax,%r13), %r14
cmpl $-0x1, (%r13,%rax)
movslq %r15d, %rax
je 0x4f55
movl 0x20(%rsp,%rax,4), %ecx
cmpl $0x1, %ecx
je 0x4fdb
testl %ecx, %ecx
je 0x4fc7
cmpl $-0x1, %ecx
jne 0x52bb
testb %r9b, %r9b
je 0x501a
movsd 0x30(%r14,%rbx,8), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x4f3f
movsd %xmm1, 0x30(%r14,%rbx,8)
movsd 0x10(%r14,%rbx,8), %xmm0
ucomisd %xmm1, %xmm0
ja 0x5033
jmp 0x503f
movl $0xffffffff, 0x20(%rsp,%rax,4) # imm = 0xFFFFFFFF
testb %r9b, %r9b
je 0x4f85
movsd 0x30(%r14,%rbx,8), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x4f76
movsd %xmm1, 0x30(%r14,%rbx,8)
movsd 0x10(%r14,%rbx,8), %xmm0
ucomisd %xmm1, %xmm0
ja 0x4f9e
jmp 0x4faa
ucomisd 0x30(%r14,%rbx,8), %xmm1
jbe 0x4f95
movsd %xmm1, 0x30(%r14,%rbx,8)
ucomisd 0x10(%r14,%rbx,8), %xmm1
jbe 0x4faa
leaq (%r14,%rbx,8), %rax
addq $0x10, %rax
movsd %xmm1, (%rax)
decl %r15d
incl %r12d
movl $0x6, %eax
cmpl %r10d, %ebp
je 0x52c4
movl 0x58(%r14), %ebp
jmp 0x52bb
movl $0x1, 0x20(%rsp,%rax,4)
incl %r15d
movl 0x50(%r14), %ebp
jmp 0x52bb
movl $0xffffffff, 0x20(%rsp,%rax,4) # imm = 0xFFFFFFFF
movslq 0x50(%r14), %rcx
movq %rcx, %rdx
shlq $0x7, %rdx
addq %r13, %rdx
movl 0x54(%r14), %eax
movsd 0x30(%rdx,%rbx,8), %xmm0
subsd 0x10(%rdx,%rbx,8), %xmm0
ucomisd %xmm2, %xmm0
jne 0x5094
jp 0x5094
movl %eax, %edx
movl %ecx, %eax
jmp 0x50d4
ucomisd 0x30(%r14,%rbx,8), %xmm1
jbe 0x502a
movsd %xmm1, 0x30(%r14,%rbx,8)
ucomisd 0x10(%r14,%rbx,8), %xmm1
jbe 0x503f
leaq (%r14,%rbx,8), %rcx
addq $0x10, %rcx
movsd %xmm1, (%rcx)
movsd 0x30(%r14,%rbx,8), %xmm0
subsd 0x10(%r14,%rbx,8), %xmm0
ucomisd %xmm2, %xmm0
jne 0x50b6
jp 0x50b6
decl %r15d
movl 0x54(%r14), %esi
movl 0x58(%r14), %ebp
movq %rdi, %rbx
callq 0x241c
movl 0x50(%r14), %esi
movq %rbx, %rdi
callq 0x241c
xorpd %xmm2, %xmm2
movq %rbx, %rdi
movq 0x18(%rsp), %rbx
movl (%rsp), %r10d
movsd 0x8(%rsp), %xmm1
movl 0x4(%rsp), %r9d
jmp 0x52bb
movslq %eax, %rdx
shlq $0x7, %rdx
addq %r13, %rdx
movsd 0x30(%rdx,%rbx,8), %xmm0
subsd 0x10(%rdx,%rbx,8), %xmm0
ucomisd %xmm2, %xmm0
jne 0x50ca
jp 0x50ca
movl %ecx, %edx
jmp 0x50d4
movl $0x0, 0x20(%rsp,%rax,4)
incl %r15d
movl 0x54(%r14), %ebp
jmp 0x52bb
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
movl 0x58(%r14), %esi
cmpl $-0x1, %edx
je 0x51d2
movslq %edx, %rcx
cltq
testl %esi, %esi
js 0x51ec
movq %rsi, %r11
shlq $0x7, %r11
xorl %r8d, %r8d
cmpl %ebp, 0x50(%r13,%r11)
leaq (%r13,%r11), %r11
setne %r8b
movl %edx, 0x50(%r11,%r8,4)
shlq $0x7, %rcx
movl %esi, 0x58(%r13,%rcx)
movl 0x58(%r14), %ecx
shlq $0x7, %rax
xorl %edx, %edx
movq %rdx, 0x68(%r13,%rax)
xorpd %xmm0, %xmm0
movupd %xmm0, 0x10(%r13,%rax)
movupd %xmm0, 0x20(%r13,%rax)
movupd %xmm0, 0x30(%r13,%rax)
movupd %xmm0, 0x40(%r13,%rax)
movq $-0x1, %rsi
movq %rsi, 0x50(%r13,%rax)
movl $0xffffffff, %r8d       # imm = 0xFFFFFFFF
movl %r8d, (%r13,%rax)
movq %rdx, 0x8(%r13,%rax)
movabsq $-0x4010000000000000, %r11 # imm = 0xBFF0000000000000
movq %r11, 0x60(%r13,%rax)
movl %r8d, 0x58(%r13,%rax)
movl %edx, 0x70(%r13,%rax)
movq %rdx, 0x78(%r13,%rax)
movq %rdx, 0x68(%r14)
movupd %xmm0, 0x10(%r14)
movupd %xmm0, 0x20(%r14)
movupd %xmm0, 0x30(%r14)
movupd %xmm0, 0x40(%r14)
movq %rsi, 0x50(%r14)
movl %r8d, (%r14)
movq %rdx, 0x8(%r14)
movq %r11, 0x60(%r14)
movl %r8d, 0x58(%r14)
movl %edx, 0x70(%r14)
movq %rdx, 0x78(%r14)
addl $0x2, 0x17d8(%rdi)
cmpl %r10d, %ebp
movl $0x0, %eax
movl $0x6, %edx
cmovel %edx, %eax
movl %ecx, %ebp
jmp 0x52b1
cmpl %r10d, %ebp
cmovel %ebp, %esi
movl $0x0, %eax
movl $0x6, %ecx
cmovel %ecx, %eax
movl %esi, %ebp
jmp 0x52b1
movslq 0x17dc(%rdi), %rsi
imulq $-0x38, %rsi, %rsi
movq 0x10(%rsp), %r8
movl %edx, (%r8,%rsi)
shlq $0x7, %rax
xorl %edx, %edx
movq %rdx, 0x68(%r13,%rax)
xorpd %xmm0, %xmm0
movupd %xmm0, 0x10(%r13,%rax)
movupd %xmm0, 0x20(%r13,%rax)
movupd %xmm0, 0x30(%r13,%rax)
movupd %xmm0, 0x40(%r13,%rax)
movq $-0x1, %rsi
movq %rsi, 0x50(%r13,%rax)
movl $0xffffffff, %r8d       # imm = 0xFFFFFFFF
movl %r8d, (%r13,%rax)
movq %rdx, 0x8(%r13,%rax)
movabsq $-0x4010000000000000, %r11 # imm = 0xBFF0000000000000
movq %r11, 0x60(%r13,%rax)
movl %r8d, 0x58(%r13,%rax)
movl %edx, 0x70(%r13,%rax)
movq %rdx, 0x78(%r13,%rax)
movq %rdx, 0x68(%r14)
movupd %xmm0, 0x10(%r14)
movupd %xmm0, 0x20(%r14)
movupd %xmm0, 0x30(%r14)
movupd %xmm0, 0x40(%r14)
movq %rsi, 0x50(%r14)
movl %r8d, (%r14)
movq %rdx, 0x8(%r14)
movq %r11, 0x60(%r14)
movl %r8d, 0x58(%r14)
movl %edx, 0x70(%r14)
movq %rdx, 0x78(%r14)
shlq $0x7, %rcx
movl %r8d, 0x58(%r13,%rcx)
addl $0x2, 0x17d8(%rdi)
movl $0x6, %eax
decl %r15d
incl %r12d
testl %eax, %eax
jne 0x52c4
xorl %eax, %eax
cmpl $0x64, %r15d
setge %al
testl %eax, %eax
je 0x4eda
cmpl $0x6, %eax
jne 0x52de
xorl %eax, %eax
cmpl $-0x1, %r15d
setne %al
negl %eax
jmp 0x52e3
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
addq $0x1b8, %rsp            # imm = 0x1B8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop