// 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>::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 %esi, %ebp
movq %rdi, %rbx
movl 0x68(%rsp), %eax
movl 0x60(%rsp), %esi
movl 0x58(%rsp), %edi
movb 0x50(%rsp), %r10b
movb 0x48(%rsp), %r11b
movl 0x40(%rsp), %r14d
movl 0x38(%rsp), %r15d
movb 0x30(%rsp), %r12b
movl %edx, (%rbx)
movl %ecx, 0x4(%rbx)
movl %r8d, 0x8(%rbx)
movl %r9d, 0xc(%rbx)
movb %r12b, 0x10(%rbx)
movl %r15d, 0x14(%rbx)
movl %r14d, 0x18(%rbx)
movsd %xmm3, 0x20(%rbx)
movb %r11b, 0x28(%rbx)
movb %r10b, 0x29(%rbx)
movsd %xmm4, 0x30(%rbx)
movl %edi, 0x38(%rbx)
movl %esi, 0x3c(%rbx)
movl %eax, 0x40(%rbx)
xorps %xmm3, %xmm3
andq $0x0, 0x17c4(%rbx)
movups %xmm3, 0x17b4(%rbx)
orl $-0x1, 0x17cc(%rbx)
andq $0x0, 0x1820(%rbx)
andq $0x0, 0x17d0(%rbx)
movsd %xmm5, 0x1828(%rbx)
movabsq $0x3fefd70a3d70a3d7, %rax # imm = 0x3FEFD70A3D70A3D7
movq %rax, 0x1830(%rbx)
movsd %xmm6, 0x1838(%rbx)
andl $0x0, 0x1840(%rbx)
leaq 0x17b4(%rbx), %r15
movsd %xmm0, 0x17e8(%rbx)
movsd %xmm1, 0x17f0(%rbx)
movsd %xmm2, 0x17f8(%rbx)
movl %ebp, 0x17dc(%rbx)
imull $-0x38, %ebp, %eax
addl $0x1770, %eax           # imm = 0x1770
sarl $0x7, %eax
movl %eax, 0x17d4(%rbx)
movl %eax, 0x17d8(%rbx)
pushq $0x7
popq %rcx
cltd
idivl %ecx
movl %eax, 0x17e0(%rbx)
xorl %r12d, %r12d
testl %ebp, %ebp
cmovgl %ebp, %r12d
subq $0x1, %r12
jb 0x140b
cmpl $0x2, (%rbx)
jae 0x13b2
movslq 0x17dc(%rbx), %rax
imulq $-0x38, %rax, %rdi
addq %r15, %rdi
movl 0x8(%rbx), %esi
jmp 0x1400
jne 0x13ec
movl 0x8(%rbx), %eax
testl %eax, %eax
jg 0x13c4
movl 0x17d4(%rbx), %eax
cltd
idivl %ebp
movl %eax, %ecx
andl $0x1, %ecx
leal (%rax,%rcx), %r14d
decl %r14d
movslq 0x17dc(%rbx), %rax
imulq $-0x38, %rax, %rdi
addq %r15, %rdi
movl %r14d, %esi
callq 0x168c
movl %r14d, 0x8(%rbx)
jmp 0x1405
movslq 0x17dc(%rbx), %rax
imulq $-0x38, %rax, %rdi
addq %r15, %rdi
movl 0x17d4(%rbx), %esi
callq 0x168c
addq $0x38, %r15
jmp 0x1394
leaq 0x44(%rbx), %r14
xorl %r15d, %r15d
movslq 0x17d4(%rbx), %rax
cmpq %rax, %r15
jge 0x142f
movq %r14, %rdi
callq 0x16a8
incq %r15
subq $-0x80, %r14
jmp 0x1412
popq %rbx
popq %r12
popq %r14
popq %r15
popq %rbp
retq