// File: 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
movq %rsp, %rbp
subq $0x220, %rsp            # imm = 0x220
movb %cl, %al
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movl %edx, -0x18(%rbp)
movsd %xmm0, -0x20(%rbp)
andb $0x1, %al
movb %al, -0x21(%rbp)
movl %r8d, -0x28(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x218(%rbp)
movl $0x0, -0x1c4(%rbp)
cmpl $0x64, -0x1c4(%rbp)
jge 0x94b6
movslq -0x1c4(%rbp), %rax
movl $0xffffffff, -0x1c0(%rbp,%rax,4) # imm = 0xFFFFFFFF
movl -0x1c4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c4(%rbp)
jmp 0x948a
movl -0x14(%rbp), %eax
movl %eax, -0x1c8(%rbp)
movl $0x0, -0x1cc(%rbp)
movl $0x0, -0x1d0(%rbp)
movq -0x218(%rbp), %rdx
movl -0x1d0(%rbp), %ecx
xorl %eax, %eax
cmpl 0x17d4(%rdx), %ecx
movb %al, -0x219(%rbp)
jge 0x9500
cmpl $0x0, -0x1c8(%rbp)
setge %al
movb %al, -0x219(%rbp)
movb -0x219(%rbp), %al
testb $0x1, %al
jne 0x950f
jmp 0x9bb3
movq -0x218(%rbp), %rdi
callq 0x1b00
movslq -0x1c8(%rbp), %rcx
shlq $0x7, %rcx
addq %rcx, %rax
movq %rax, -0x1d8(%rbp)
movq -0x1d8(%rbp), %rdi
callq 0x29e0
testb $0x1, %al
jne 0x9a85
movslq -0x1cc(%rbp), %rax
cmpl $-0x1, -0x1c0(%rbp,%rax,4)
jne 0x96d3
testb $0x1, -0x21(%rbp)
je 0x95bd
movq -0x1d8(%rbp), %rax
movslq -0x18(%rbp), %rcx
movsd 0x30(%rax,%rcx,8), %xmm0
ucomisd -0x20(%rbp), %xmm0
jbe 0x958d
movsd -0x20(%rbp), %xmm0
movq -0x1d8(%rbp), %rax
movslq -0x18(%rbp), %rcx
movsd %xmm0, 0x30(%rax,%rcx,8)
movq -0x1d8(%rbp), %rax
movslq -0x18(%rbp), %rcx
movsd 0x10(%rax,%rcx,8), %xmm0
ucomisd -0x20(%rbp), %xmm0
jbe 0x95bb
movsd -0x20(%rbp), %xmm0
movq -0x1d8(%rbp), %rax
movslq -0x18(%rbp), %rcx
movsd %xmm0, 0x10(%rax,%rcx,8)
jmp 0x9623
movq -0x1d8(%rbp), %rax
movslq -0x18(%rbp), %rcx
movsd 0x30(%rax,%rcx,8), %xmm1
movsd -0x20(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x95ef
movsd -0x20(%rbp), %xmm0
movq -0x1d8(%rbp), %rax
movslq -0x18(%rbp), %rcx
movsd %xmm0, 0x30(%rax,%rcx,8)
movq -0x1d8(%rbp), %rax
movslq -0x18(%rbp), %rcx
movsd 0x10(%rax,%rcx,8), %xmm1
movsd -0x20(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x9621
movsd -0x20(%rbp), %xmm0
movq -0x1d8(%rbp), %rax
movslq -0x18(%rbp), %rcx
movsd %xmm0, 0x10(%rax,%rcx,8)
jmp 0x9623
movq -0x1d8(%rbp), %rax
movslq -0x18(%rbp), %rcx
movsd 0x30(%rax,%rcx,8), %xmm0
movq -0x1d8(%rbp), %rax
movslq -0x18(%rbp), %rcx
subsd 0x10(%rax,%rcx,8), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x969d
jp 0x969d
movq -0x218(%rbp), %rdi
movl -0x1cc(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x1cc(%rbp)
movq -0x1d8(%rbp), %rax
movl 0x58(%rax), %eax
movl %eax, -0x1c8(%rbp)
movq -0x1d8(%rbp), %rax
movl 0x54(%rax), %esi
callq 0x35b0
movq -0x218(%rbp), %rdi
movq -0x1d8(%rbp), %rax
movl 0x50(%rax), %esi
callq 0x35b0
jmp 0x96ce
movslq -0x1cc(%rbp), %rax
movl $0x0, -0x1c0(%rbp,%rax,4)
movl -0x1cc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1cc(%rbp)
movq -0x1d8(%rbp), %rax
movl 0x54(%rax), %eax
movl %eax, -0x1c8(%rbp)
jmp 0x9a80
movslq -0x1cc(%rbp), %rax
cmpl $0x0, -0x1c0(%rbp,%rax,4)
jne 0x971a
movslq -0x1cc(%rbp), %rax
movl $0x1, -0x1c0(%rbp,%rax,4)
movl -0x1cc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1cc(%rbp)
movq -0x1d8(%rbp), %rax
movl 0x50(%rax), %eax
movl %eax, -0x1c8(%rbp)
jmp 0x9a7e
movslq -0x1cc(%rbp), %rax
cmpl $0x1, -0x1c0(%rbp,%rax,4)
jne 0x9a7c
movq -0x218(%rbp), %rdi
movslq -0x1cc(%rbp), %rax
movl $0xffffffff, -0x1c0(%rbp,%rax,4) # imm = 0xFFFFFFFF
movl -0x1cc(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x1cc(%rbp)
movl -0x1d0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1d0(%rbp)
callq 0x1b00
movq -0x218(%rbp), %rdi
movq -0x1d8(%rbp), %rcx
movslq 0x50(%rcx), %rcx
shlq $0x7, %rcx
addq %rcx, %rax
movq %rax, -0x1e0(%rbp)
callq 0x1b00
movq -0x1d8(%rbp), %rcx
movslq 0x54(%rcx), %rcx
shlq $0x7, %rcx
addq %rcx, %rax
movq %rax, -0x1e8(%rbp)
movq -0x1e0(%rbp), %rax
movslq -0x18(%rbp), %rcx
movsd 0x30(%rax,%rcx,8), %xmm0
movq -0x1e0(%rbp), %rax
movslq -0x18(%rbp), %rcx
subsd 0x10(%rax,%rcx,8), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
sete %al
setnp %cl
andb %cl, %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x1ec(%rbp)
movq -0x1e8(%rbp), %rax
movslq -0x18(%rbp), %rcx
movsd 0x30(%rax,%rcx,8), %xmm0
movq -0x1e8(%rbp), %rax
movslq -0x18(%rbp), %rcx
subsd 0x10(%rax,%rcx,8), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
sete %al
setnp %cl
andb %cl, %al
andb $0x1, %al
movzbl %al, %eax
movl %eax, -0x1f0(%rbp)
movq -0x1d8(%rbp), %rax
cmpl $0x0, 0x58(%rax)
setl %al
andb $0x1, %al
movb %al, -0x1f1(%rbp)
movl -0x1c8(%rbp), %eax
cmpl -0x14(%rbp), %eax
sete %al
andb $0x1, %al
movb %al, -0x1f2(%rbp)
movl $0xffffffff, -0x1f8(%rbp) # imm = 0xFFFFFFFF
movl $0xffffffff, -0x1fc(%rbp) # imm = 0xFFFFFFFF
cmpl $0x0, -0x1ec(%rbp)
je 0x988a
movq -0x1d8(%rbp), %rax
movl 0x54(%rax), %eax
movl %eax, -0x1f8(%rbp)
movq -0x1d8(%rbp), %rax
movl 0x50(%rax), %eax
movl %eax, -0x1fc(%rbp)
jmp 0x98b5
cmpl $0x0, -0x1f0(%rbp)
je 0x98b3
movq -0x1d8(%rbp), %rax
movl 0x50(%rax), %eax
movl %eax, -0x1f8(%rbp)
movq -0x1d8(%rbp), %rax
movl 0x54(%rax), %eax
movl %eax, -0x1fc(%rbp)
jmp 0x98b5
cmpl $-0x1, -0x1f8(%rbp)
je 0x9a5a
movq -0x218(%rbp), %rdi
callq 0x1b00
movslq -0x1f8(%rbp), %rcx
shlq $0x7, %rcx
addq %rcx, %rax
movq %rax, -0x208(%rbp)
testb $0x1, -0x1f1(%rbp)
je 0x9989
movq -0x218(%rbp), %rdi
movl -0x1f8(%rbp), %eax
movl %eax, -0x220(%rbp)
callq 0x1a50
movl -0x220(%rbp), %ecx
movq -0x218(%rbp), %rdi
movslq -0x28(%rbp), %rdx
imulq $0x38, %rdx, %rdx
addq %rdx, %rax
movl %ecx, 0x8(%rax)
callq 0x1b00
movq %rax, %rdi
movslq -0x1fc(%rbp), %rax
shlq $0x7, %rax
addq %rax, %rdi
callq 0x1b20
movq -0x1d8(%rbp), %rdi
callq 0x1b20
movq -0x218(%rbp), %rdi
callq 0x1b00
movq %rax, %rcx
movq -0x218(%rbp), %rax
movslq -0x1f8(%rbp), %rdx
shlq $0x7, %rdx
addq %rdx, %rcx
movl $0xffffffff, 0x58(%rcx) # imm = 0xFFFFFFFF
movl 0x17d8(%rax), %ecx
addl $0x2, %ecx
movl %ecx, 0x17d8(%rax)
jmp 0x9bb3
movq -0x218(%rbp), %rdi
callq 0x1b00
movq -0x1d8(%rbp), %rcx
movslq 0x58(%rcx), %rcx
shlq $0x7, %rcx
addq %rcx, %rax
movq %rax, -0x210(%rbp)
movq -0x210(%rbp), %rax
movl 0x50(%rax), %eax
cmpl -0x1c8(%rbp), %eax
jne 0x99d2
movl -0x1f8(%rbp), %ecx
movq -0x210(%rbp), %rax
movl %ecx, 0x50(%rax)
jmp 0x99e2
movl -0x1f8(%rbp), %ecx
movq -0x210(%rbp), %rax
movl %ecx, 0x54(%rax)
movq -0x1d8(%rbp), %rax
movl 0x58(%rax), %ecx
movq -0x208(%rbp), %rax
movl %ecx, 0x58(%rax)
movq -0x218(%rbp), %rdi
movq -0x1d8(%rbp), %rax
movl 0x58(%rax), %eax
movl %eax, -0x1c8(%rbp)
callq 0x1b00
movq %rax, %rdi
movslq -0x1fc(%rbp), %rax
shlq $0x7, %rax
addq %rax, %rdi
callq 0x1b20
movq -0x1d8(%rbp), %rdi
callq 0x1b20
movq -0x218(%rbp), %rax
movl 0x17d8(%rax), %ecx
addl $0x2, %ecx
movl %ecx, 0x17d8(%rax)
testb $0x1, -0x1f2(%rbp)
je 0x9a58
jmp 0x9bb3
jmp 0x9a7a
movl -0x1c8(%rbp), %eax
cmpl -0x14(%rbp), %eax
jne 0x9a6a
jmp 0x9bb3
movq -0x1d8(%rbp), %rax
movl 0x58(%rax), %eax
movl %eax, -0x1c8(%rbp)
jmp 0x9a7c
jmp 0x9a7e
jmp 0x9a80
jmp 0x9b9c
movslq -0x1cc(%rbp), %rax
movl $0xffffffff, -0x1c0(%rbp,%rax,4) # imm = 0xFFFFFFFF
movl -0x1cc(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x1cc(%rbp)
movl -0x1d0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1d0(%rbp)
testb $0x1, -0x21(%rbp)
je 0x9b19
movq -0x1d8(%rbp), %rax
movslq -0x18(%rbp), %rcx
movsd 0x30(%rax,%rcx,8), %xmm0
ucomisd -0x20(%rbp), %xmm0
jbe 0x9ae9
movsd -0x20(%rbp), %xmm0
movq -0x1d8(%rbp), %rax
movslq -0x18(%rbp), %rcx
movsd %xmm0, 0x30(%rax,%rcx,8)
movq -0x1d8(%rbp), %rax
movslq -0x18(%rbp), %rcx
movsd 0x10(%rax,%rcx,8), %xmm0
ucomisd -0x20(%rbp), %xmm0
jbe 0x9b17
movsd -0x20(%rbp), %xmm0
movq -0x1d8(%rbp), %rax
movslq -0x18(%rbp), %rcx
movsd %xmm0, 0x10(%rax,%rcx,8)
jmp 0x9b7f
movq -0x1d8(%rbp), %rax
movslq -0x18(%rbp), %rcx
movsd 0x30(%rax,%rcx,8), %xmm1
movsd -0x20(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x9b4b
movsd -0x20(%rbp), %xmm0
movq -0x1d8(%rbp), %rax
movslq -0x18(%rbp), %rcx
movsd %xmm0, 0x30(%rax,%rcx,8)
movq -0x1d8(%rbp), %rax
movslq -0x18(%rbp), %rcx
movsd 0x10(%rax,%rcx,8), %xmm1
movsd -0x20(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x9b7d
movsd -0x20(%rbp), %xmm0
movq -0x1d8(%rbp), %rax
movslq -0x18(%rbp), %rcx
movsd %xmm0, 0x10(%rax,%rcx,8)
jmp 0x9b7f
movl -0x1c8(%rbp), %eax
cmpl -0x14(%rbp), %eax
jne 0x9b8c
jmp 0x9bb3
movq -0x1d8(%rbp), %rax
movl 0x58(%rax), %eax
movl %eax, -0x1c8(%rbp)
cmpl $0x64, -0x1cc(%rbp)
jl 0x9bae
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x9bcc
jmp 0x94d3
cmpl $-0x1, -0x1cc(%rbp)
je 0x9bc5
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x9bcc
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x220, %rsp            # imm = 0x220
popq %rbp
retq
nopl (%rax,%rax)