// 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_counters<100>(int, int, double, bool, int*)
int adjust_counters(int const start_id, int split_dimension, double split_value, bool discharge_left, int* to_remove){
	//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
				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;
				if(node_id == start_id)
					break;
				node_id = node.parent;
			}
		}
		else{ //Leaf
			stack[depth] = -1; //Reset to -1
			depth -= 1;
			i += 1;


			//Compute size of box
			double const max_value = node.bound_upper[split_dimension] - node.bound_lower[split_dimension];
			//Get the percentage on the left (below the split value)
			double percentage = Utils::min(Utils::max((split_value - node.bound_lower[split_dimension]) / max_value, 0.0), 1.0);
			//If this sub-tree is not on the left, invert percentage
			if(!discharge_left)
				percentage = 1 - percentage;
			for(int i = 0; i < label_count; ++i){
				int counter_out = Utils::round(static_cast<double>(node.counters[i]) * percentage);
				int counter_in = Utils::round(static_cast<double>(node.counters[i]) * (1 - percentage));
				int const err = node.counters[i] - counter_in - counter_out;
				if(err != 0)
					cout << "Error counters" << endl;
				to_remove[i] += counter_out;
				node.counters[i] = counter_in;
			}
			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 $0x1e8, %rsp            # imm = 0x1E8
movq %r8, %rbx
movl %ecx, 0xc(%rsp)
movsd %xmm0, 0x30(%rsp)
movl %edx, %r12d
movl %esi, %ebp
movq %rdi, %r15
leaq 0x50(%rsp), %rdi
movl $0x190, %edx            # imm = 0x190
movl $0xff, %esi
callq 0x1040
leaq 0x44(%r15), %rsi
movslq %r12d, %rax
movq %rax, 0x18(%rsp)
xorl %edi, %edi
xorpd %xmm4, %xmm4
movsd 0x1434(%rip), %xmm2     # 0x6018
movsd 0x1454(%rip), %xmm5     # 0x6040
movsd 0x143c(%rip), %xmm6     # 0x6030
movq 0x33dd(%rip), %r12      # 0x7fd8
xorl %r8d, %r8d
movl %ebp, %r9d
movq %r15, 0x28(%rsp)
movq %rsi, 0x20(%rsp)
movl %ebp, 0x8(%rsp)
cmpl 0x17d4(%r15), %edi
jge 0x4e3b
testl %r9d, %r9d
js 0x4e3b
movl %r9d, %eax
shlq $0x7, %rax
leaq (%rsi,%rax), %r14
cmpl $-0x1, (%rsi,%rax)
movslq %r8d, %rax
je 0x4c66
movl 0x50(%rsp,%rax,4), %ecx
cmpl $-0x1, %ecx
je 0x4e11
cmpl $0x1, %ecx
je 0x4df1
testl %ecx, %ecx
jne 0x4e25
movl $0x50, %edx
movl $0x1, %ecx
jmp 0x4e18
movl $0xffffffff, 0x50(%rsp,%rax,4) # imm = 0xFFFFFFFF
movq 0x18(%rsp), %rax
movsd 0x10(%r14,%rax,8), %xmm0
movsd 0x30(%r14,%rax,8), %xmm1
subsd %xmm0, %xmm1
movsd 0x30(%rsp), %xmm7
subsd %xmm0, %xmm7
divsd %xmm1, %xmm7
maxsd %xmm4, %xmm7
minsd %xmm2, %xmm7
cmpb $0x0, 0xc(%rsp)
movq %rdi, 0x38(%rsp)
movl %r9d, 0x10(%rsp)
jne 0x4cb8
movapd %xmm2, %xmm0
subsd %xmm7, %xmm0
movapd %xmm0, %xmm7
decl %r8d
movl %r8d, 0x14(%rsp)
movapd %xmm2, %xmm8
subsd %xmm7, %xmm8
xorl %r13d, %r13d
movsd %xmm7, 0x48(%rsp)
movsd %xmm8, 0x40(%rsp)
movl 0x68(%r14,%r13,4), %eax
xorps %xmm0, %xmm0
cvtsi2sd %eax, %xmm0
movapd %xmm7, %xmm1
mulsd %xmm0, %xmm1
movapd %xmm1, %xmm2
cmpltsd %xmm4, %xmm2
movapd %xmm2, %xmm3
andpd %xmm5, %xmm3
andnpd %xmm6, %xmm2
orpd %xmm3, %xmm2
addsd %xmm1, %xmm2
cvttsd2si %xmm2, %r15d
mulsd %xmm8, %xmm0
movapd %xmm0, %xmm1
cmpltsd %xmm4, %xmm1
movapd %xmm1, %xmm2
andpd %xmm5, %xmm2
andnpd %xmm6, %xmm1
orpd %xmm2, %xmm1
addsd %xmm0, %xmm1
cvttsd2si %xmm1, %ebp
leal (%r15,%rbp), %ecx
cmpl %ecx, %eax
je 0x4d9b
movl $0xe, %edx
movq %r12, %rdi
leaq 0x1375(%rip), %rsi      # 0x60c2
callq 0x1090
movq (%r12), %rax
movq -0x18(%rax), %rdi
addq %r12, %rdi
movl $0xa, %esi
callq 0x1080
movsbl %al, %esi
movq %r12, %rdi
callq 0x1030
movq %rax, %rdi
callq 0x1060
movsd 0x40(%rsp), %xmm8
movsd 0x48(%rsp), %xmm7
movsd 0x12a1(%rip), %xmm6     # 0x6030
movsd 0x12a9(%rip), %xmm5     # 0x6040
xorpd %xmm4, %xmm4
addl %r15d, (%rbx,%r13,4)
movl %ebp, 0x68(%r14,%r13,4)
incq %r13
cmpq $0x1, %r13
je 0x4cda
movl $0x6, %ecx
movl 0x10(%rsp), %edx
movl %edx, %eax
movl 0x8(%rsp), %ebp
cmpl %ebp, %edx
movq 0x20(%rsp), %rsi
je 0x4dcf
movl 0x58(%r14), %eax
xorl %ecx, %ecx
movq 0x38(%rsp), %rdi
incl %edi
cmpl %ebp, %edx
movl %eax, %r9d
movq 0x28(%rsp), %r15
movsd 0x1230(%rip), %xmm2     # 0x6018
movl 0x14(%rsp), %r8d
jne 0x4e25
jmp 0x4e2e
movl $0xffffffff, 0x50(%rsp,%rax,4) # imm = 0xFFFFFFFF
decl %eax
incl %edi
movl $0x58, %edx
movl $0x6, %ecx
movl %eax, %r8d
cmpl %ebp, %r9d
jne 0x4e1e
jmp 0x4e2e
movl $0x54, %edx
xorl %ecx, %ecx
movl %ecx, 0x50(%rsp,%rax,4)
incl %eax
movl (%r14,%rdx), %r9d
movl %eax, %r8d
xorl %ecx, %ecx
cmpl $0x64, %r8d
setge %cl
testl %ecx, %ecx
je 0x4c0f
cmpl $0x6, %ecx
jne 0x4e48
xorl %eax, %eax
cmpl $-0x1, %r8d
setne %al
negl %eax
jmp 0x4e4d
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
addq $0x1e8, %rsp            # imm = 0x1E8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop