// File: /workspace/github_cpp_makefile_star2_O2/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 $0x1c8, %rsp            # imm = 0x1C8
movl %r8d, 0x1c(%rsp)
movl %esi, %r8d
movq %rdi, %r15
xorl %eax, %eax
cmpq $0x64, %rax
je 0x48da
orl $-0x1, 0x30(%rsp,%rax,4)
incq %rax
jmp 0x48ca
leaq 0x44(%r15), %rbp
movslq %edx, %r9
xorl %r10d, %r10d
pushq $-0x1
popq %rax
movl %eax, 0xc(%rsp)
xorpd %xmm3, %xmm3
xorl %r14d, %r14d
movl %r8d, %ebx
movq %r15, 0x10(%rsp)
movsd %xmm0, 0x28(%rsp)
movl %ecx, 0x8(%rsp)
movl %r8d, 0x4(%rsp)
movq %r9, 0x20(%rsp)
cmpl 0x17d4(%r15), %r10d
jge 0x4bc7
testl %ebx, %ebx
js 0x4bc7
movl %ebx, %eax
shlq $0x7, %rax
leaq (%rax,%rbp), %r13
cmpl $-0x1, (%rbp,%rax)
movslq %r14d, %rax
je 0x498b
movl 0x30(%rsp,%rax,4), %edx
cmpl $0x1, %edx
je 0x4a07
testl %edx, %edx
je 0x49f4
cmpl $-0x1, %edx
jne 0x4a52
movsd 0x30(%r13,%r9,8), %xmm2
testb %cl, %cl
je 0x4a5a
ucomisd %xmm0, %xmm2
jbe 0x4975
movsd %xmm0, 0x30(%r13,%r9,8)
movapd %xmm0, %xmm2
movsd 0x10(%r13,%r9,8), %xmm1
ucomisd %xmm0, %xmm1
ja 0x4a78
jmp 0x4a8b
orl $-0x1, 0x30(%rsp,%rax,4)
movsd 0x30(%r13,%r9,8), %xmm1
testb %cl, %cl
je 0x49b7
ucomisd %xmm0, %xmm1
jbe 0x49a8
movsd %xmm0, 0x30(%r13,%r9,8)
movsd 0x10(%r13,%r9,8), %xmm1
ucomisd %xmm0, %xmm1
ja 0x49cd
jmp 0x49dc
ucomisd %xmm1, %xmm0
jbe 0x49c4
movsd %xmm0, 0x30(%r13,%r9,8)
ucomisd 0x10(%r13,%r9,8), %xmm0
jbe 0x49dc
leaq 0x10(,%r9,8), %rax
addq %r13, %rax
movsd %xmm0, (%rax)
decl %r14d
cmpl %r8d, %ebx
je 0x4bc7
incl %r10d
movl 0x58(%r13), %r12d
jmp 0x4baf
movl $0x1, 0x30(%rsp,%rax,4)
incl %eax
movl 0x50(%r13), %r12d
jmp 0x4bac
orl $-0x1, 0x30(%rsp,%rax,4)
movl %eax, %r14d
decl %r14d
incl %r10d
movslq 0x50(%r13), %rdx
movq %rdx, %rax
shlq $0x7, %rax
addq %rbp, %rax
movl 0x54(%r13), %esi
movl 0x58(%r13), %r12d
movsd 0x30(%rax,%r9,8), %xmm1
subsd 0x10(%rax,%r9,8), %xmm1
ucomisd %xmm3, %xmm1
jne 0x4ae1
jp 0x4ae1
movl %esi, %eax
movl %edx, %esi
jmp 0x4b0b
movl %ebx, %r12d
jmp 0x4baf
ucomisd %xmm2, %xmm0
jbe 0x4a6b
movsd %xmm0, 0x30(%r13,%r9,8)
movapd %xmm0, %xmm2
movsd 0x10(%r13,%r9,8), %xmm1
ucomisd %xmm1, %xmm0
jbe 0x4a8b
leaq 0x10(,%r9,8), %rdx
addq %r13, %rdx
movsd %xmm0, (%rdx)
movapd %xmm0, %xmm1
subsd %xmm1, %xmm2
ucomisd %xmm3, %xmm2
jne 0x4ba1
jp 0x4ba1
decl %r14d
movl 0x54(%r13), %esi
movl 0x58(%r13), %r12d
movq %r15, %rdi
movl %r10d, %ebx
callq 0x2298
movl 0x50(%r13), %esi
movq %r15, %rdi
callq 0x2298
xorpd %xmm3, %xmm3
movl %ebx, %r10d
movq 0x20(%rsp), %r9
movl 0x4(%rsp), %r8d
movsd 0x28(%rsp), %xmm0
movl 0x8(%rsp), %ecx
jmp 0x4baf
movslq %esi, %rax
shlq $0x7, %rax
addq %rbp, %rax
movsd 0x30(%rax,%r9,8), %xmm1
subsd 0x10(%rax,%r9,8), %xmm1
ucomisd %xmm3, %xmm1
movl %edx, %eax
jne 0x4b95
jp 0x4b95
cmpl $-0x1, %eax
je 0x4b95
movslq %eax, %r15
movslq %esi, %rdi
testl %r12d, %r12d
js 0x4bec
movq %r12, %rsi
shlq $0x7, %rsi
xorl %edx, %edx
cmpl %ebx, 0x50(%rbp,%rsi)
leaq (%rbp,%rsi), %rsi
setne %dl
movl %eax, 0x50(%rsi,%rdx,4)
shlq $0x7, %r15
movl %r12d, 0x58(%rbp,%r15)
movl 0x58(%r13), %r12d
shlq $0x7, %rdi
addq %rbp, %rdi
movl %r10d, %r15d
callq 0x16a8
movq %r13, %rdi
callq 0x16a8
xorpd %xmm3, %xmm3
movl %r15d, %r10d
movq 0x20(%rsp), %r9
movl 0x4(%rsp), %r8d
movsd 0x28(%rsp), %xmm0
movl 0x8(%rsp), %ecx
movq 0x10(%rsp), %r15
addl $0x2, 0x17d8(%r15)
pushq $0x6
popq %rax
cmpl %r8d, %ebx
movl %r12d, %ebx
jne 0x4baf
jmp 0x4bba
cmpl %r8d, %ebx
movq 0x10(%rsp), %r15
jne 0x4baf
jmp 0x4bc7
andl $0x0, 0x30(%rsp,%rax,4)
incl %eax
movl 0x54(%r13), %r12d
movl %eax, %r14d
xorl %eax, %eax
movl %r12d, %ebx
cmpl $0x63, %r14d
jg 0x4bd6
testl %eax, %eax
je 0x490e
cmpl $0x6, %eax
jne 0x4bd6
xorl %eax, %eax
cmpl $-0x1, %r14d
setne %al
negl %eax
movl %eax, 0xc(%rsp)
movl 0xc(%rsp), %eax
addq $0x1c8, %rsp            # imm = 0x1C8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x10(%rsp), %rbx
movslq 0x17dc(%rbx), %rcx
imulq $-0x38, %rcx, %rcx
addq %rbx, %rcx
movslq 0x1c(%rsp), %rdx
imulq $0x38, %rdx, %rdx
movl %eax, 0x17bc(%rdx,%rcx)
shlq $0x7, %rdi
addq %rbp, %rdi
callq 0x16a8
movq %r13, %rdi
callq 0x16a8
shlq $0x7, %r15
orl $-0x1, 0x58(%rbp,%r15)
addl $0x2, 0x17d8(%rbx)
jmp 0x4bc7