// 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>::find_barycenter<100>(int, double*)
int find_barycenter(int const start_id, double* avg_features){
	//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;
	double count[feature_count];
	for(int i = 0; i < feature_count; ++i){
		count[i] = 0;
		avg_features[i] = 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;

			//Count the number of data points
			double data_point_count = 0;
			for(int i = 0; i < label_count; ++i)
				data_point_count += static_cast<double>(node.counters[i]);
			for(int i = 0; i < feature_count; ++i){
				double const middle = (node.bound_upper[i] + node.bound_lower[i]) * 0.5;
				avg_features[i] += middle * data_point_count;
				count[i] += data_point_count;
			}

			if(node_id == start_id)
				break;
			node_id = node.parent;
		}
		if(depth >= max_stack_size)
			return -1;
	}
	if(depth != -1)
		return -1;
	for(int i = 0; i < feature_count; ++i){
		avg_features[i] /= count[i];
	}
	return 0;
}

// Assembly:
pushq %rbp
pushq %r14
pushq %rbx
subq $0x1b0, %rsp            # imm = 0x1B0
movq %rdx, %rbx
movl %esi, %ebp
movq %rdi, %r14
leaq 0x20(%rsp), %rdi
movl $0x190, %edx            # imm = 0x190
movl $0xff, %esi
callq 0x1040
xorps %xmm0, %xmm0
movaps %xmm0, 0x10(%rsp)
movaps %xmm0, (%rsp)
movups %xmm0, 0x10(%rbx)
movups %xmm0, (%rbx)
movl 0x17d4(%r14), %eax
addq $0x44, %r14
xorl %esi, %esi
movsd 0xc59(%rip), %xmm0      # 0x6030
movl %ebp, %edx
xorl %ecx, %ecx
cmpl %eax, %ecx
jge 0x550e
testl %edx, %edx
js 0x550e
movl %edx, %r8d
shlq $0x7, %r8
leaq (%r14,%r8), %rdi
cmpl $-0x1, (%r14,%r8)
movslq %esi, %r8
je 0x5432
movl 0x20(%rsp,%r8,4), %r9d
cmpl $-0x1, %r9d
je 0x54de
cmpl $0x1, %r9d
je 0x54bb
testl %r9d, %r9d
jne 0x54f5
movl $0x50, %r10d
movl $0x1, %edx
jmp 0x54e6
movl $0xffffffff, 0x20(%rsp,%r8,4) # imm = 0xFFFFFFFF
movl %r8d, %esi
decl %esi
xorpd %xmm1, %xmm1
xorl %r8d, %r8d
xorps %xmm2, %xmm2
cvtsi2sdl 0x68(%rdi,%r8,4), %xmm2
addsd %xmm2, %xmm1
incq %r8
cmpq $0x1, %r8
je 0x5447
xorl %r8d, %r8d
movsd 0x30(%rdi,%r8,8), %xmm2
addsd 0x10(%rdi,%r8,8), %xmm2
mulsd %xmm0, %xmm2
mulsd %xmm1, %xmm2
addsd (%rbx,%r8,8), %xmm2
movsd %xmm2, (%rbx,%r8,8)
movsd (%rsp,%r8,8), %xmm2
addsd %xmm1, %xmm2
movsd %xmm2, (%rsp,%r8,8)
incq %r8
cmpq $0x4, %r8
jne 0x5461
movl $0x9, %r9d
movl %edx, %r8d
cmpl %ebp, %edx
je 0x54b0
movl 0x58(%rdi), %r8d
xorl %r9d, %r9d
incl %ecx
cmpl %ebp, %edx
movl %r8d, %edx
jne 0x54f5
jmp 0x54ff
movl $0xffffffff, 0x20(%rsp,%r8,4) # imm = 0xFFFFFFFF
decl %r8d
incl %ecx
movl $0x58, %r10d
movl $0x9, %r9d
movl %r8d, %esi
cmpl %ebp, %edx
jne 0x54ee
jmp 0x54ff
movl $0x54, %r10d
xorl %edx, %edx
movl %edx, 0x20(%rsp,%r8,4)
incl %r8d
movl (%rdi,%r10), %edx
movl %r8d, %esi
xorl %r9d, %r9d
cmpl $0x64, %esi
setge %r9b
testl %r9d, %r9d
je 0x53db
cmpl $0x9, %r9d
jne 0x5536
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
cmpl $-0x1, %esi
jne 0x553b
xorl %eax, %eax
xorl %ecx, %ecx
movsd (%rbx,%rcx,8), %xmm0
divsd (%rsp,%rcx,8), %xmm0
movsd %xmm0, (%rbx,%rcx,8)
incq %rcx
cmpq $0x4, %rcx
jne 0x551c
jmp 0x553b
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
addq $0x1b0, %rsp            # imm = 0x1B0
popq %rbx
popq %r14
popq %rbp
retq
nop