// 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>::tree_trim<100>(int)
int tree_trim(int const tree_id){
	TreeBase const& base = tree_bases()[tree_id];
	int const root_id = base.root;

	//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;

	//Start at the root, then dive inside the tree
	int node_id = root_id;
	int depth = 0;
	double smallest_count = -1;
	int smallest_id = 0;
	//a for loop instead of a while to avoid infinite loops. Since we don't expect to do more turn than node_count
	int i = 0;
	double leaf_count = 0;
	double sum_count_leaves = 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;
				node_id = node.parent;
			}
		}
		else{ //Leaf
			stack[depth] = -1; //Reset to -1
			depth -= 1;
			i += 1;
			leaf_count += 1;
			if(trim_type == TRIM_COUNT){//Trim based on count
				double count = 0;
				for(int i = 0; i < label_count; ++i)
					count += static_cast<double>(node.counters[i]);
				sum_count_leaves += count;
				if(smallest_count < 0 || count < smallest_count || (count == smallest_count && func::rand_uniform() < 0.5)){
					smallest_count = count;
					smallest_id = node_id;
				}
			}
			else if(trim_type == TRIM_FADING){//Trim based on a fading count
				sum_count_leaves += node.fading_score;
				if(smallest_count < 0 || node.fading_score < smallest_count || (node.fading_score == smallest_count && func::rand_uniform() < 0.5)){
					smallest_count = node.fading_score;
					smallest_id = node_id;
				}
			}
			else if(trim_type == TRIM_RANDOM){//Trim based on Reservoir Sampling
				double const r = func::rand_uniform();

				if(r < (1.0/leaf_count))
					smallest_id = node_id;
			}
			node_id = node.parent;
		}
		if(depth >= max_stack_size)
			return -1;
	}
	if(depth != -1)
		return -2;
	if(sum_count_leaves > 0 && (smallest_count/sum_count_leaves) > maximum_trim_size)
		return -3;
	return smallest_id;
}

// Assembly:
pushq %rbp
pushq %rbx
subq $0x198, %rsp            # imm = 0x198
movq %rdi, %rbx
movslq 0x17dc(%rdi), %rax
imulq $-0x38, %rax, %rax
addq %rdi, %rax
movslq %esi, %rcx
imulq $0x38, %rcx, %rcx
movl 0x17bc(%rcx,%rax), %ebp
movq %rsp, %rdi
movl $0x190, %edx            # imm = 0x190
movl $0xff, %esi
callq 0x1040
movl 0x17d4(%rbx), %eax
leaq 0x44(%rbx), %rcx
movl 0x40(%rbx), %edx
xorpd %xmm1, %xmm1
movsd 0x3dcf(%rip), %xmm4     # 0x6030
xorl %esi, %esi
movsd 0x3dad(%rip), %xmm2     # 0x6018
xorl %r8d, %r8d
xorl %edi, %edi
xorpd %xmm3, %xmm3
xorpd %xmm0, %xmm0
cmpl %eax, %edi
jge 0x2370
testl %ebp, %ebp
js 0x2370
movl %ebp, %r10d
shlq $0x7, %r10
leaq (%rcx,%r10), %r9
cmpl $-0x1, (%rcx,%r10)
movslq %esi, %r10
je 0x22c8
movl (%rsp,%r10,4), %r11d
cmpl $0x1, %r11d
je 0x2313
testl %r11d, %r11d
je 0x2301
cmpl $-0x1, %r11d
jne 0x234f
movl $0x0, (%rsp,%r10,4)
incl %esi
movl $0x54, %r10d
jmp 0x233d
movl $0xffffffff, (%rsp,%r10,4) # imm = 0xFFFFFFFF
decl %esi
incl %edi
addsd %xmm2, %xmm3
movl $0x58, %r10d
cmpl $0x1, %edx
je 0x235a
cmpl $0x2, %edx
je 0x2327
cmpl $0x3, %edx
jne 0x233d
cvtdq2pd 0x68(%r9), %xmm6
movapd %xmm6, %xmm5
unpckhpd %xmm6, %xmm5            # xmm5 = xmm5[1],xmm6[1]
addsd %xmm6, %xmm5
jmp 0x232d
movl $0x1, (%rsp,%r10,4)
incl %esi
movl $0x50, %r10d
jmp 0x233d
movl $0xffffffff, (%rsp,%r10,4) # imm = 0xFFFFFFFF
decl %esi
incl %edi
movl $0x58, %r10d
jmp 0x233d
movsd 0x78(%r9), %xmm5
addsd %xmm5, %xmm0
ucomisd %xmm4, %xmm1
ja 0x2344
ucomisd %xmm5, %xmm4
jae 0x2344
movapd %xmm4, %xmm5
movl %r8d, %ebp
movl %ebp, %r8d
movl (%r9,%r10), %ebp
movapd %xmm5, %xmm4
cmpl $0x64, %esi
jl 0x2278
jmp 0x239c
movapd %xmm2, %xmm5
divsd %xmm3, %xmm5
ucomisd %xmm1, %xmm5
cmovbel %r8d, %ebp
movapd %xmm4, %xmm5
jmp 0x2344
movl $0xfffffffe, %eax       # imm = 0xFFFFFFFE
cmpl $-0x1, %esi
jne 0x23a1
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x2397
divsd %xmm0, %xmm4
movl $0xfffffffd, %eax       # imm = 0xFFFFFFFD
ucomisd 0x1838(%rbx), %xmm4
ja 0x23a1
movl %r8d, %eax
jmp 0x23a1
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
addq $0x198, %rsp            # imm = 0x198
popq %rbx
popq %rbp
retq
nop