// File: /workspace/github_cpp_makefile_star2_O2/big-data-lab-team[P]OrpailleCC/./src/mondrian_coarse.hpp
// Function: CoarseMondrianForest<double, funct, KappaMetrics<2, false>, 4, 2, 6000>::extend_node(int, int, double const*, int, int, double, double*, double, double)
void extend_node(int const node_id, int const tree_id, feature_type const* features, int const label, int const parent_id, double const parent_tau, double* probabilities, double const E, double const sum){
		Node& node = nodes()[node_id];
		int new_parent_id, new_sibling_id;
		bool current_node_on_left = true;
		Utils::turn_array_into_probability(probabilities, feature_count, sum);
		//sample features with probability proportional to e_lower[i] + e_upper[i]
		int const dimension = Utils::pick_from_distribution<func>(probabilities, feature_count);

		//Select the bound to choose the split from
		double lower_value, upper_value;
		if(features[dimension] > node.bound_upper[dimension]){
			lower_value = node.bound_upper[dimension];
			upper_value = features[dimension];
		}
		else if(features[dimension] < node.bound_lower[dimension]){
			lower_value = features[dimension];
			upper_value = node.bound_lower[dimension];
		}

		//sample the split between [lower_value, upper_value]
		double const split_value = func::rand_uniform()*(upper_value - lower_value) + lower_value;
		//insert new node above the current one
		new_parent_id = available_node();
		nodes()[new_parent_id].split_dimension = dimension;
		nodes()[new_parent_id].split_value = split_value;
		nodes()[new_parent_id].tau = parent_tau + E;
		//insert new leaf, sibbling of the current one
		new_sibling_id = available_node();
		node_available -= 2;

		//Update the box of the new parent
		for(int i = 0; i < feature_count; ++i){
			nodes()[new_parent_id].bound_lower[i] = features[i] < node.bound_lower[i] ? features[i] : node.bound_lower[i];
			nodes()[new_parent_id].bound_upper[i] = features[i] > node.bound_upper[i] ? features[i] : node.bound_upper[i];
		}
		//NOTE Creates counters for the label of the new parent
		//for(int i = 0; i < label_count; ++i)
		//nodes[new_parent_id].counters[i] = node.counters[i];
		//nodes[new_parent_id].counters[label] += 1;

		//Creates counters for the label of the new sibling
		for(int i = 0; i < label_count; ++i)
			nodes()[new_sibling_id].counters[i] = 0;
		//No need to increase the counter for the current label because we will call sample_block soon on new_sibling

		sample_block(new_sibling_id, features, label);
		if(features[dimension] == upper_value){ //right
			current_node_on_left = false;
		}
		else{
			current_node_on_left = true;
		}

		//Make the connections between the new nodes
		nodes()[new_parent_id].parent = node.parent;
		if(!node.has_parent() && node_id == tree_bases()[tree_id].root)//We introduce a parent to the root
			tree_bases()[tree_id].root = new_parent_id;
		else{
			Node& parent = nodes()[node.parent];
			if(parent.child_left == node_id)
				parent.child_left = new_parent_id;
			else
				parent.child_right = new_parent_id;
		}


		node.parent = new_parent_id;

		nodes()[new_sibling_id].parent = new_parent_id;
		if(!current_node_on_left){ //right
			nodes()[new_parent_id].child_right = new_sibling_id;
			nodes()[new_parent_id].child_left = node_id;
		}
		else{ //left
			nodes()[new_parent_id].child_left = new_sibling_id;
			nodes()[new_parent_id].child_right = node_id;
		}
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movsd %xmm1, 0x38(%rsp)
movsd %xmm0, 0x30(%rsp)
movl %r8d, 0x10(%rsp)
movq %rcx, %r15
movl %edx, 0x8(%rsp)
movq %rdi, %r14
movq 0x80(%rsp), %r13
leaq 0x44(%rdi), %rax
movq %rax, 0x20(%rsp)
movl %esi, 0x14(%rsp)
movslq %esi, %rax
shlq $0x7, %rax
leaq (%rdi,%rax), %rbx
addq $0x44, %rbx
pushq $0x4
popq %rbp
movq %r13, %rdi
movl %ebp, %esi
movaps %xmm2, %xmm0
callq 0x3994
movq %r13, %rdi
movl %ebp, %esi
callq 0x39ee
movl %eax, %ebp
cltq
movsd (%r15,%rax,8), %xmm0
movsd 0x30(%rbx,%rax,8), %xmm1
ucomisd %xmm1, %xmm0
movq %rax, 0x40(%rsp)
jbe 0x3aaa
movapd %xmm0, %xmm2
movapd %xmm1, %xmm0
jmp 0x3ab0
movsd 0x10(%rbx,%rax,8), %xmm2
movsd %xmm2, 0x18(%rsp)
movapd %xmm2, %xmm1
subsd %xmm0, %xmm1
xorpd %xmm2, %xmm2
mulsd %xmm1, %xmm2
addsd %xmm0, %xmm2
movsd %xmm2, 0x28(%rsp)
movq %r14, %rdi
callq 0x2378
movl %eax, 0xc(%rsp)
movslq %eax, %r13
shlq $0x7, %r13
movq 0x20(%rsp), %rax
movl %ebp, (%rax,%r13)
movsd 0x28(%rsp), %xmm0
movsd %xmm0, 0x8(%rax,%r13)
movsd 0x30(%rsp), %xmm0
addsd 0x38(%rsp), %xmm0
movsd %xmm0, 0x60(%rax,%r13)
movq %r14, %rdi
callq 0x2378
addl $-0x2, 0x17d8(%r14)
movl %eax, %ebp
leaq (%r14,%r13), %rax
addq $0x74, %rax
xorl %ecx, %ecx
cmpq $0x4, %rcx
je 0x3b56
movsd (%r15,%rcx,8), %xmm0
minsd 0x10(%rbx,%rcx,8), %xmm0
movsd %xmm0, -0x20(%rax,%rcx,8)
movsd (%r15,%rcx,8), %xmm0
maxsd 0x30(%rbx,%rcx,8), %xmm0
movsd %xmm0, (%rax,%rcx,8)
incq %rcx
jmp 0x3b28
movslq %ebp, %r12
shlq $0x7, %r12
leaq (%r12,%r14), %rax
addq $0xac, %rax
xorl %ecx, %ecx
cmpq $0x2, %rcx
je 0x3b78
andl $0x0, (%rax,%rcx,4)
incq %rcx
jmp 0x3b69
movq %r14, %rdi
movl %ebp, %esi
movq %r15, %rdx
movl 0x10(%rsp), %ecx
callq 0x23cc
movq 0x40(%rsp), %rax
movsd (%r15,%rax,8), %xmm0
movslq 0x58(%rbx), %rax
movq 0x20(%rsp), %rdi
movl %eax, 0x58(%rdi,%r13)
cmpq $-0x1, %rax
movl 0x14(%rsp), %esi
jne 0x3bd8
movslq 0x17dc(%r14), %rcx
imulq $-0x38, %rcx, %rcx
addq %r14, %rcx
movslq 0x8(%rsp), %rdx
imulq $0x38, %rdx, %rdx
cmpl %esi, 0x17bc(%rdx,%rcx)
jne 0x3bd8
leaq (%rdx,%rcx), %rax
addq $0x17bc, %rax           # imm = 0x17BC
jmp 0x3bef
shlq $0x7, %rax
leaq (%rdi,%rax), %rcx
addq $0x50, %rcx
cmpl %esi, (%rcx)
leaq 0x54(%rdi,%rax), %rax
cmoveq %rcx, %rax
movsd 0x18(%rsp), %xmm1
movl 0xc(%rsp), %ecx
movl %ecx, (%rax)
ucomisd %xmm1, %xmm0
movl %ecx, 0x58(%rbx)
movl %ecx, 0x58(%rdi,%r12)
movl %esi, %eax
cmovnel %ebp, %eax
cmovpl %ebp, %eax
cmovnel %esi, %ebp
cmovpl %esi, %ebp
movl %eax, 0x50(%rdi,%r13)
movl %ebp, 0x54(%rdi,%r13)
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq