// File: 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
movq %rsp, %rbp
subq $0x220, %rsp            # imm = 0x220
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movq -0x10(%rbp), %rdi
movq %rdi, -0x218(%rbp)
callq 0x1a50
movslq -0x14(%rbp), %rcx
imulq $0x38, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x20(%rbp)
movq -0x20(%rbp), %rax
movl 0x8(%rax), %eax
movl %eax, -0x24(%rbp)
movl $0x0, -0x1c4(%rbp)
cmpl $0x64, -0x1c4(%rbp)
jge 0x2fe1
movslq -0x1c4(%rbp), %rax
movl $0xffffffff, -0x1c0(%rbp,%rax,4) # imm = 0xFFFFFFFF
movl -0x1c4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c4(%rbp)
jmp 0x2fb5
movl -0x24(%rbp), %eax
movl %eax, -0x1c8(%rbp)
movl $0x0, -0x1cc(%rbp)
movsd 0x802c(%rip), %xmm0     # 0xb028
movsd %xmm0, -0x1d8(%rbp)
movl $0x0, -0x1dc(%rbp)
movl $0x0, -0x1e0(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x1e8(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x1f0(%rbp)
movq -0x218(%rbp), %rdx
movl -0x1e0(%rbp), %ecx
xorl %eax, %eax
cmpl 0x17d4(%rdx), %ecx
movb %al, -0x219(%rbp)
jge 0x305b
cmpl $0x0, -0x1c8(%rbp)
setge %al
movb %al, -0x219(%rbp)
movb -0x219(%rbp), %al
testb $0x1, %al
jne 0x306a
jmp 0x33cb
movq -0x218(%rbp), %rdi
callq 0x1b00
movslq -0x1c8(%rbp), %rcx
shlq $0x7, %rcx
addq %rcx, %rax
movq %rax, -0x1f8(%rbp)
movq -0x1f8(%rbp), %rdi
callq 0x29e0
testb $0x1, %al
jne 0x3184
movslq -0x1cc(%rbp), %rax
cmpl $-0x1, -0x1c0(%rbp,%rax,4)
jne 0x30e6
movslq -0x1cc(%rbp), %rax
movl $0x0, -0x1c0(%rbp,%rax,4)
movl -0x1cc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1cc(%rbp)
movq -0x1f8(%rbp), %rax
movl 0x54(%rax), %eax
movl %eax, -0x1c8(%rbp)
jmp 0x317f
movslq -0x1cc(%rbp), %rax
cmpl $0x0, -0x1c0(%rbp,%rax,4)
jne 0x312a
movslq -0x1cc(%rbp), %rax
movl $0x1, -0x1c0(%rbp,%rax,4)
movl -0x1cc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1cc(%rbp)
movq -0x1f8(%rbp), %rax
movl 0x50(%rax), %eax
movl %eax, -0x1c8(%rbp)
jmp 0x317d
movslq -0x1cc(%rbp), %rax
cmpl $0x1, -0x1c0(%rbp,%rax,4)
jne 0x317b
movslq -0x1cc(%rbp), %rax
movl $0xffffffff, -0x1c0(%rbp,%rax,4) # imm = 0xFFFFFFFF
movl -0x1cc(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x1cc(%rbp)
movl -0x1e0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1e0(%rbp)
movq -0x1f8(%rbp), %rax
movl 0x58(%rax), %eax
movl %eax, -0x1c8(%rbp)
jmp 0x317d
jmp 0x317f
jmp 0x33b4
movq -0x218(%rbp), %rax
movslq -0x1cc(%rbp), %rcx
movl $0xffffffff, -0x1c0(%rbp,%rcx,4) # imm = 0xFFFFFFFF
movl -0x1cc(%rbp), %ecx
subl $0x1, %ecx
movl %ecx, -0x1cc(%rbp)
movl -0x1e0(%rbp), %ecx
addl $0x1, %ecx
movl %ecx, -0x1e0(%rbp)
movsd 0x7e55(%rip), %xmm0     # 0xb018
addsd -0x1e8(%rbp), %xmm0
movsd %xmm0, -0x1e8(%rbp)
cmpl $0x3, 0x40(%rax)
jne 0x32b6
xorps %xmm0, %xmm0
movsd %xmm0, -0x200(%rbp)
movl $0x0, -0x204(%rbp)
cmpl $0x2, -0x204(%rbp)
jge 0x3230
movq -0x1f8(%rbp), %rax
movslq -0x204(%rbp), %rcx
cvtsi2sdl 0x68(%rax,%rcx,4), %xmm0
addsd -0x200(%rbp), %xmm0
movsd %xmm0, -0x200(%rbp)
movl -0x204(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x204(%rbp)
jmp 0x31f2
movsd -0x200(%rbp), %xmm0
addsd -0x1f0(%rbp), %xmm0
movsd %xmm0, -0x1f0(%rbp)
xorps %xmm0, %xmm0
ucomisd -0x1d8(%rbp), %xmm0
ja 0x3295
movsd -0x200(%rbp), %xmm1
movsd -0x1d8(%rbp), %xmm0
ucomisd %xmm1, %xmm0
ja 0x3295
movsd -0x200(%rbp), %xmm0
ucomisd -0x1d8(%rbp), %xmm0
jne 0x32b1
jp 0x32b1
callq 0x35a0
movaps %xmm0, %xmm1
movsd 0x7da1(%rip), %xmm0     # 0xb030
ucomisd %xmm1, %xmm0
jbe 0x32b1
movsd -0x200(%rbp), %xmm0
movsd %xmm0, -0x1d8(%rbp)
movl -0x1c8(%rbp), %eax
movl %eax, -0x1dc(%rbp)
jmp 0x33a4
movq -0x218(%rbp), %rax
cmpl $0x2, 0x40(%rax)
jne 0x335a
movq -0x1f8(%rbp), %rax
movsd 0x78(%rax), %xmm0
addsd -0x1f0(%rbp), %xmm0
movsd %xmm0, -0x1f0(%rbp)
xorps %xmm0, %xmm0
ucomisd -0x1d8(%rbp), %xmm0
ja 0x3338
movq -0x1f8(%rbp), %rax
movsd 0x78(%rax), %xmm1
movsd -0x1d8(%rbp), %xmm0
ucomisd %xmm1, %xmm0
ja 0x3338
movq -0x1f8(%rbp), %rax
movsd 0x78(%rax), %xmm0
ucomisd -0x1d8(%rbp), %xmm0
jne 0x3358
jp 0x3358
callq 0x35a0
movaps %xmm0, %xmm1
movsd 0x7cfe(%rip), %xmm0     # 0xb030
ucomisd %xmm1, %xmm0
jbe 0x3358
movq -0x1f8(%rbp), %rax
movsd 0x78(%rax), %xmm0
movsd %xmm0, -0x1d8(%rbp)
movl -0x1c8(%rbp), %eax
movl %eax, -0x1dc(%rbp)
jmp 0x33a2
movq -0x218(%rbp), %rax
cmpl $0x1, 0x40(%rax)
jne 0x33a0
callq 0x35a0
movsd %xmm0, -0x210(%rbp)
movsd -0x210(%rbp), %xmm1
movsd 0x7c94(%rip), %xmm0     # 0xb018
divsd -0x1e8(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x339e
movl -0x1c8(%rbp), %eax
movl %eax, -0x1dc(%rbp)
jmp 0x33a0
jmp 0x33a2
jmp 0x33a4
movq -0x1f8(%rbp), %rax
movl 0x58(%rax), %eax
movl %eax, -0x1c8(%rbp)
cmpl $0x64, -0x1cc(%rbp)
jl 0x33c6
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x3421
jmp 0x302e
cmpl $-0x1, -0x1cc(%rbp)
je 0x33dd
movl $0xfffffffe, -0x4(%rbp) # imm = 0xFFFFFFFE
jmp 0x3421
movsd -0x1f0(%rbp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x3418
movq -0x218(%rbp), %rax
movsd -0x1d8(%rbp), %xmm0
divsd -0x1f0(%rbp), %xmm0
ucomisd 0x1838(%rax), %xmm0
jbe 0x3418
movl $0xfffffffd, -0x4(%rbp) # imm = 0xFFFFFFFD
jmp 0x3421
movl -0x1dc(%rbp), %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x220, %rsp            # imm = 0x220
popq %rbp
retq
nopl (%rax)