// File: /workspace/github_cpp_makefile_star2_O3/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, 0x4(%rsp)
movl %ecx, %ebp
movsd %xmm0, 0x10(%rsp)
movl %edx, %r12d
movl %esi, %r14d
movq %rdi, %rbx
leaq 0x20(%rsp), %rdi
movl $0x190, %edx            # imm = 0x190
movl $0xff, %esi
callq 0x1040
movsd 0x10(%rsp), %xmm2
movq %rbx, %rdi
leaq 0x44(%rbx), %r13
movslq %r12d, %r11
xorpd %xmm3, %xmm3
xorps %xmm4, %xmm4
xorl %r10d, %r10d
xorl %r12d, %r12d
movl %r14d, %eax
cmpl 0x17d4(%rdi), %r10d
jge 0x5252
testl %eax, %eax
js 0x5252
movl %eax, %ecx
shlq $0x7, %rcx
leaq (%rcx,%r13), %r15
cmpl $-0x1, (%r13,%rcx)
movslq %r12d, %rcx
je 0x4fa4
movl 0x20(%rsp,%rcx,4), %edx
cmpl $0x1, %edx
je 0x5021
testl %edx, %edx
je 0x500e
cmpl $-0x1, %edx
jne 0x506f
movsd 0x30(%r15,%r11,8), %xmm0
testb %bpl, %bpl
je 0x5076
ucomisd %xmm2, %xmm0
jbe 0x4f8e
movsd %xmm2, 0x30(%r15,%r11,8)
movapd %xmm2, %xmm0
movsd 0x10(%r15,%r11,8), %xmm1
ucomisd %xmm2, %xmm1
ja 0x5094
jmp 0x50a4
movl $0xffffffff, 0x20(%rsp,%rcx,4) # imm = 0xFFFFFFFF
movsd 0x30(%r15,%r11,8), %xmm0
testb %bpl, %bpl
je 0x4fd4
ucomisd %xmm2, %xmm0
jbe 0x4fc5
movsd %xmm2, 0x30(%r15,%r11,8)
movsd 0x10(%r15,%r11,8), %xmm0
ucomisd %xmm2, %xmm0
ja 0x4fea
jmp 0x4ff6
ucomisd %xmm0, %xmm2
jbe 0x4fe1
movsd %xmm2, 0x30(%r15,%r11,8)
ucomisd 0x10(%r15,%r11,8), %xmm2
jbe 0x4ff6
leaq (%r15,%r11,8), %rcx
addq $0x10, %rcx
movsd %xmm2, (%rcx)
decl %r12d
cmpl %r14d, %eax
je 0x5252
incl %r10d
movl 0x58(%r15), %ebx
jmp 0x5236
movl $0x1, 0x20(%rsp,%rcx,4)
incl %ecx
movl 0x50(%r15), %ebx
jmp 0x5233
movl $0xffffffff, 0x20(%rsp,%rcx,4) # imm = 0xFFFFFFFF
movl %ecx, %r12d
decl %r12d
incl %r10d
movslq 0x50(%r15), %rdx
movq %rdx, %rsi
shlq $0x7, %rsi
addq %r13, %rsi
movl 0x54(%r15), %ecx
movl 0x58(%r15), %ebx
movsd 0x30(%rsi,%r11,8), %xmm0
subsd 0x10(%rsi,%r11,8), %xmm0
ucomisd %xmm3, %xmm0
jne 0x510e
jp 0x510e
movl %ecx, %esi
movl %edx, %ecx
jmp 0x5138
movl %eax, %ebx
jmp 0x5236
ucomisd %xmm0, %xmm2
jbe 0x5087
movsd %xmm2, 0x30(%r15,%r11,8)
movapd %xmm2, %xmm0
movsd 0x10(%r15,%r11,8), %xmm1
ucomisd %xmm1, %xmm2
jbe 0x50a4
leaq (%r15,%r11,8), %rax
addq $0x10, %rax
movsd %xmm2, (%rax)
movapd %xmm2, %xmm1
subsd %xmm1, %xmm0
ucomisd %xmm3, %xmm0
jne 0x5225
jp 0x5225
decl %r12d
movl 0x54(%r15), %esi
movl 0x58(%r15), %ebx
movl %ebp, 0xc(%rsp)
movq %rdi, %rbp
movl %r14d, 0x8(%rsp)
movq %r11, 0x18(%rsp)
movl %r10d, %r14d
callq 0x24fc
movl 0x50(%r15), %esi
movq %rbp, %rdi
callq 0x24fc
movl %r14d, %r10d
xorps %xmm4, %xmm4
xorpd %xmm3, %xmm3
movq 0x18(%rsp), %r11
movsd 0x10(%rsp), %xmm2
movl 0x8(%rsp), %r14d
movq %rbp, %rdi
movl 0xc(%rsp), %ebp
jmp 0x5236
movslq %ecx, %rsi
shlq $0x7, %rsi
addq %r13, %rsi
movsd 0x30(%rsi,%r11,8), %xmm0
subsd 0x10(%rsi,%r11,8), %xmm0
ucomisd %xmm3, %xmm0
movl %edx, %esi
jne 0x521e
jp 0x521e
cmpl $-0x1, %esi
je 0x521e
movslq %esi, %rdx
testl %ebx, %ebx
js 0x5276
movq %rbx, %r9
shlq $0x7, %r9
xorl %r8d, %r8d
cmpl %eax, 0x50(%r13,%r9)
leaq (%r13,%r9), %r9
setne %r8b
movl %esi, 0x50(%r9,%r8,4)
shlq $0x7, %rdx
movl %ebx, 0x58(%r13,%rdx)
movl 0x58(%r15), %ebx
movslq %ecx, %rcx
shlq $0x7, %rcx
xorl %edx, %edx
movq %rdx, 0x68(%r13,%rcx)
movups %xmm4, 0x10(%r13,%rcx)
movups %xmm4, 0x20(%r13,%rcx)
movups %xmm4, 0x30(%r13,%rcx)
movups %xmm4, 0x40(%r13,%rcx)
movq $-0x1, %rsi
movq %rsi, 0x50(%r13,%rcx)
movl $0xffffffff, %r8d       # imm = 0xFFFFFFFF
movl %r8d, (%r13,%rcx)
movq %rdx, 0x8(%r13,%rcx)
movabsq $-0x4010000000000000, %r9 # imm = 0xBFF0000000000000
movq %r9, 0x60(%r13,%rcx)
movl %r8d, 0x58(%r13,%rcx)
movl %edx, 0x70(%r13,%rcx)
movq %rdx, 0x78(%r13,%rcx)
movq %rdx, 0x68(%r15)
movups %xmm4, 0x10(%r15)
movups %xmm4, 0x20(%r15)
movups %xmm4, 0x30(%r15)
movups %xmm4, 0x40(%r15)
movq %rsi, 0x50(%r15)
movl %r8d, (%r15)
movq %rdx, 0x8(%r15)
movq %r9, 0x60(%r15)
movl %r8d, 0x58(%r15)
movl %edx, 0x70(%r15)
movq %rdx, 0x78(%r15)
addl $0x2, 0x17d8(%rdi)
movl $0x6, %ecx
cmpl %r14d, %eax
movl %ebx, %eax
jne 0x5236
jmp 0x5240
cmpl %r14d, %eax
jne 0x5236
jmp 0x5252
movl $0x0, 0x20(%rsp,%rcx,4)
incl %ecx
movl 0x54(%r15), %ebx
movl %ecx, %r12d
xorl %ecx, %ecx
movl %ebx, %eax
cmpl $0x63, %r12d
jg 0x525f
testl %ecx, %ecx
je 0x4f25
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
cmpl $0x6, %ecx
jne 0x5264
xorl %eax, %eax
cmpl $-0x1, %r12d
setne %al
negl %eax
jmp 0x5264
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
addq $0x1b8, %rsp            # imm = 0x1B8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movslq 0x17dc(%rdi), %rax
imulq $-0x38, %rax, %rax
addq %rdi, %rax
movslq 0x4(%rsp), %r8
imulq $0x38, %r8, %r8
movl %esi, 0x17bc(%r8,%rax)
movslq %ecx, %rax
shlq $0x7, %rax
xorl %ecx, %ecx
movq %rcx, 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 %rcx, 0x8(%r13,%rax)
movabsq $-0x4010000000000000, %r9 # imm = 0xBFF0000000000000
movq %r9, 0x60(%r13,%rax)
movl %r8d, 0x58(%r13,%rax)
movl %ecx, 0x70(%r13,%rax)
movq %rcx, 0x78(%r13,%rax)
movq %rcx, 0x68(%r15)
movupd %xmm0, 0x10(%r15)
movupd %xmm0, 0x20(%r15)
movupd %xmm0, 0x30(%r15)
movupd %xmm0, 0x40(%r15)
movq %rsi, 0x50(%r15)
movl %r8d, (%r15)
movq %rcx, 0x8(%r15)
movq %r9, 0x60(%r15)
movl %r8d, 0x58(%r15)
movl %ecx, 0x70(%r15)
movq %rcx, 0x78(%r15)
shlq $0x7, %rdx
movl %r8d, 0x58(%r13,%rdx)
addl $0x2, 0x17d8(%rdi)
jmp 0x5252
nop