// File: /workspace/github_cpp_makefile_star2_O1/big-data-lab-team[P]OrpailleCC/./src/mondrian_coarse.hpp
// Function: CoarseMondrianForest<double, funct, KappaMetrics<2, false>, 4, 2, 6000>::CoarseMondrianForest(double, double, double, int, int, int, int, int, bool, int, int, double, bool, bool, double, double, int, int, int, double)
CoarseMondrianForest(double const lifetime, double const base_measure, double const discount_factor, int const tree_count,
		int const tm = COBBLE_MANAGEMENT,
		int const st = NODE_SIZE,
		int const sl = -1,
		int const dd = 0,
		bool const pn = false,
		int const fed = 0,
		int const fes = 0,
		double const tf = 1.0,
		bool const fdt = true,
		bool const ro = true,
		double const fep = 1.0,
		double const fc = 1.0,
		int const sh = 0,
		int const et = 0,
		int const tt = 0,
		double const mts = 1.0): tree_management(tm), size_type(st), size_limit(sl), dont_delete(dd), print_nodes(pn), fe_distribution(fed), fe_split_trigger(fes), tau_factor(tf), generate_full_point(fdt), reset_once(ro), fe_parameter(fep), fading_count(fc), split_helper(sh), extend_type(et), trim_type(tt), maximum_trim_size(mts) {
#ifdef DEBUG
	assert(tree_count >= 1 && "Must have one tree at least");
#endif
	this->lifetime = lifetime;
	this->base_measure = base_measure;
	this->discount_factor = discount_factor;
	this->tree_count = tree_count;

	int const statistics_memory = tree_count * sizeof(TreeBase);
	int const remaining_memory = max_size - statistics_memory;
	this->node_count = (remaining_memory - (remaining_memory%sizeof(Node))) / sizeof(Node);
	this->node_available = node_count;
	this->maximum_tree_count = (node_count - node_count%7)/7;
	//Init all roots as empty
	TreeBase* bases = tree_bases();
	for(int i = 0; i < tree_count; ++i)
		if(tree_management == ROBUR_MANAGEMENT){
			int limit_to_use;
			if(size_limit > 0)
				limit_to_use = size_limit;
			else
				limit_to_use = Utils::div_int<int>(node_count, tree_count);

			//The limit must be an odd number, so we adjust if needed.
			//Because node are added two by two so if the number isn't odd, we may get 1 node above the limit.
			//The number of node in a tree is always odd because there is the root which is always added alone.
			if((limit_to_use%2) == 0)
				limit_to_use -= 1;
			tree_bases()[i].reset(limit_to_use);
			size_limit = limit_to_use;
		}
		else if(tree_management == COBBLE_MANAGEMENT || tree_management == OPTIMISTIC_COBBLE_MANAGEMENT)
			tree_bases()[i].reset(size_limit);
		else
			tree_bases()[i].reset(node_count);
	for(int i = 0; i < node_count; ++i)
		nodes()[i].reset();
#ifdef DEBUG
	cout << "Tree Count = " << this->tree_count << endl;
	cout << "Node Count = " << this->node_count << endl;
	cout << "Sizeof Node = " << sizeof(Node) << endl;
	cout << "Sizeof TreeBase = " << sizeof(TreeBase) << endl;

	cout << "Node Memory = " << remaining_memory << endl;
	cout << "Tree Base Memory = " << statistics_memory << endl;
	assert(node_count >= tree_count && "Not enough memory to have one node per tree");
#endif
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
movl 0x68(%rsp), %eax
movl 0x60(%rsp), %r10d
movl 0x58(%rsp), %r11d
movb 0x50(%rsp), %bl
movb 0x48(%rsp), %bpl
movl 0x40(%rsp), %r14d
movl 0x38(%rsp), %r15d
movb 0x30(%rsp), %r12b
movl %edx, (%rdi)
movl %ecx, 0x4(%rdi)
movl %r8d, 0x8(%rdi)
movl %r9d, 0xc(%rdi)
movb %r12b, 0x10(%rdi)
movl %r15d, 0x14(%rdi)
movl %r14d, 0x18(%rdi)
movsd %xmm3, 0x20(%rdi)
movb %bpl, 0x28(%rdi)
movb %bl, 0x29(%rdi)
movsd %xmm4, 0x30(%rdi)
movl %r11d, 0x38(%rdi)
movl %r10d, 0x3c(%rdi)
movl %eax, 0x40(%rdi)
xorps %xmm3, %xmm3
movups %xmm3, 0x17b4(%rdi)
xorl %eax, %eax
movq %rax, 0x17c4(%rdi)
movl $0xffffffff, 0x17cc(%rdi) # imm = 0xFFFFFFFF
movq %rax, 0x1820(%rdi)
movups %xmm3, 0x17d0(%rdi)
movsd %xmm5, 0x1828(%rdi)
movabsq $0x3fefd70a3d70a3d7, %rax # imm = 0x3FEFD70A3D70A3D7
movq %rax, 0x1830(%rdi)
movsd %xmm6, 0x1838(%rdi)
movl $0x0, 0x1840(%rdi)
movsd %xmm0, 0x17e8(%rdi)
movsd %xmm1, 0x17f0(%rdi)
movsd %xmm2, 0x17f8(%rdi)
movl %esi, 0x17dc(%rdi)
imull $-0x38, %esi, %eax
addl $0x1770, %eax           # imm = 0x1770
sarl $0x7, %eax
movl %eax, 0x17d4(%rdi)
movl %eax, 0x17d8(%rdi)
cltq
imulq $-0x6db6db6d, %rax, %rcx # imm = 0x92492493
shrq $0x20, %rcx
addl %ecx, %eax
movl %eax, %ecx
shrl $0x1f, %ecx
sarl $0x2, %eax
addl %ecx, %eax
movl %eax, 0x17e0(%rdi)
testl %esi, %esi
jle 0x149f
movl %esi, %eax
imulq $0x38, %rax, %rcx
xorl %r8d, %r8d
cmpl $0x2, (%rdi)
jae 0x13ec
movslq 0x17dc(%rdi), %rax
imulq $-0x38, %rax, %rax
addq %rdi, %rax
movl 0x8(%rdi), %edx
jmp 0x1460
jne 0x144c
movl 0x8(%rdi), %eax
testl %eax, %eax
jg 0x13fe
movl 0x17d4(%rdi), %eax
cltd
idivl %esi
movl %eax, %edx
andl $0x1, %edx
addl %edx, %eax
decl %eax
movslq 0x17dc(%rdi), %rdx
imulq $-0x38, %rdx, %rdx
addq %rdi, %rdx
movl $0xffffffff, 0x17bc(%r8,%rdx) # imm = 0xFFFFFFFF
movl %eax, 0x17b4(%r8,%rdx)
movups %xmm3, 0x17c4(%r8,%rdx)
movups %xmm3, 0x17d4(%r8,%rdx)
movl $0x0, 0x17e4(%r8,%rdx)
movl %eax, 0x8(%rdi)
jmp 0x1492
movslq 0x17dc(%rdi), %rax
imulq $-0x38, %rax, %rax
addq %rdi, %rax
movl 0x17d4(%rdi), %edx
movl $0xffffffff, 0x17bc(%r8,%rax) # imm = 0xFFFFFFFF
movl %edx, 0x17b4(%r8,%rax)
movups %xmm3, 0x17c4(%r8,%rax)
movups %xmm3, 0x17d4(%r8,%rax)
movl $0x0, 0x17e4(%r8,%rax)
addq $0x38, %r8
cmpq %r8, %rcx
jne 0x13d4
movslq 0x17d4(%rdi), %rax
testq %rax, %rax
jle 0x151d
addq $0xbc, %rdi
shlq $0x7, %rax
xorl %ecx, %ecx
xorps %xmm0, %xmm0
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movabsq $-0x4010000000000000, %rsi # imm = 0xBFF0000000000000
xorl %r8d, %r8d
movq %rcx, -0x10(%rdi,%r8)
movups %xmm0, -0x68(%rdi,%r8)
movups %xmm0, -0x58(%rdi,%r8)
movups %xmm0, -0x48(%rdi,%r8)
movups %xmm0, -0x38(%rdi,%r8)
movq $-0x1, -0x28(%rdi,%r8)
movl %edx, -0x78(%rdi,%r8)
movq %rcx, -0x70(%rdi,%r8)
movq %rsi, -0x18(%rdi,%r8)
movl %edx, -0x20(%rdi,%r8)
movl $0x0, -0x8(%rdi,%r8)
movq %rcx, (%rdi,%r8)
subq $-0x80, %r8
cmpq %r8, %rax
jne 0x14cd
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq