// File: 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
movq %rsp, %rbp
subq $0x90, %rsp
movl %ecx, -0x90(%rbp)
movl %edx, -0x8c(%rbp)
movl %esi, %r10d
movl -0x90(%rbp), %esi
movq %rdi, %r11
movl -0x8c(%rbp), %edi
movl 0x48(%rbp), %eax
movl 0x40(%rbp), %eax
movl 0x38(%rbp), %eax
movb 0x30(%rbp), %al
movb 0x28(%rbp), %cl
movl 0x20(%rbp), %edx
movl 0x18(%rbp), %edx
movb 0x10(%rbp), %dl
movq %r11, -0x8(%rbp)
movsd %xmm0, -0x10(%rbp)
movsd %xmm1, -0x18(%rbp)
movsd %xmm2, -0x20(%rbp)
movl %r10d, -0x24(%rbp)
movl %edi, -0x28(%rbp)
movl %esi, -0x2c(%rbp)
movl %r8d, -0x30(%rbp)
movl %r9d, -0x34(%rbp)
andb $0x1, %dl
movb %dl, -0x35(%rbp)
movsd %xmm3, -0x40(%rbp)
andb $0x1, %cl
movb %cl, -0x41(%rbp)
andb $0x1, %al
movb %al, -0x42(%rbp)
movsd %xmm4, -0x50(%rbp)
movsd %xmm5, -0x58(%rbp)
movsd %xmm6, -0x60(%rbp)
movq -0x8(%rbp), %rdi
movq %rdi, -0x88(%rbp)
movl -0x28(%rbp), %eax
movl %eax, (%rdi)
movl -0x2c(%rbp), %eax
movl %eax, 0x4(%rdi)
movl -0x30(%rbp), %eax
movl %eax, 0x8(%rdi)
movl -0x34(%rbp), %eax
movl %eax, 0xc(%rdi)
movb -0x35(%rbp), %al
andb $0x1, %al
movb %al, 0x10(%rdi)
movl 0x18(%rbp), %eax
movl %eax, 0x14(%rdi)
movl 0x20(%rbp), %eax
movl %eax, 0x18(%rdi)
movsd -0x40(%rbp), %xmm0
movsd %xmm0, 0x20(%rdi)
movb -0x41(%rbp), %al
andb $0x1, %al
movb %al, 0x28(%rdi)
movb -0x42(%rbp), %al
andb $0x1, %al
movb %al, 0x29(%rdi)
movsd -0x50(%rbp), %xmm0
movsd %xmm0, 0x30(%rdi)
movl 0x38(%rbp), %eax
movl %eax, 0x38(%rdi)
movl 0x40(%rbp), %eax
movl %eax, 0x3c(%rdi)
movl 0x48(%rbp), %eax
movl %eax, 0x40(%rdi)
movl $0x0, 0x17b4(%rdi)
xorps %xmm0, %xmm0
movsd %xmm0, 0x17b8(%rdi)
xorps %xmm0, %xmm0
movsd %xmm0, 0x17c0(%rdi)
movl $0x0, 0x17c8(%rdi)
movl $0xffffffff, 0x17cc(%rdi) # imm = 0xFFFFFFFF
movl $0x0, 0x17d0(%rdi)
movl $0x0, 0x17d4(%rdi)
movl $0x0, 0x17d8(%rdi)
movl $0x0, 0x17dc(%rdi)
movl $0x0, 0x17e0(%rdi)
xorps %xmm0, %xmm0
movsd %xmm0, 0x1820(%rdi)
movsd -0x58(%rbp), %xmm0
movsd %xmm0, 0x1828(%rdi)
movsd 0x9bb3(%rip), %xmm0     # 0xb020
movsd %xmm0, 0x1830(%rdi)
movsd -0x60(%rbp), %xmm0
movsd %xmm0, 0x1838(%rdi)
movl $0x0, 0x1840(%rdi)
movsd -0x10(%rbp), %xmm0
movsd %xmm0, 0x17e8(%rdi)
movsd -0x18(%rbp), %xmm0
movsd %xmm0, 0x17f0(%rdi)
movsd -0x20(%rbp), %xmm0
movsd %xmm0, 0x17f8(%rdi)
movl -0x24(%rbp), %eax
movl %eax, 0x17dc(%rdi)
movslq -0x24(%rbp), %rax
imulq $0x38, %rax, %rax
movl %eax, -0x64(%rbp)
movl $0x1770, %eax           # imm = 0x1770
subl -0x64(%rbp), %eax
movl %eax, -0x68(%rbp)
movslq -0x68(%rbp), %rax
movslq -0x68(%rbp), %rcx
andq $0x7f, %rcx
subq %rcx, %rax
shrq $0x7, %rax
movl %eax, 0x17d4(%rdi)
movl 0x17d4(%rdi), %eax
movl %eax, 0x17d8(%rdi)
movl 0x17d4(%rdi), %eax
movl %eax, -0x80(%rbp)
movl 0x17d4(%rdi), %eax
movl $0x7, %ecx
cltd
idivl %ecx
movl -0x80(%rbp), %eax
subl %edx, %eax
movl $0x7, %ecx
cltd
idivl %ecx
movl %eax, 0x17e0(%rdi)
callq 0x1a50
movq %rax, -0x70(%rbp)
movl $0x0, -0x74(%rbp)
movl -0x74(%rbp), %eax
cmpl -0x24(%rbp), %eax
jge 0x1650
movq -0x88(%rbp), %rax
cmpl $0x2, (%rax)
jne 0x15cf
movq -0x88(%rbp), %rax
cmpl $0x0, 0x8(%rax)
jle 0x1569
movq -0x88(%rbp), %rax
movl 0x8(%rax), %eax
movl %eax, -0x78(%rbp)
jmp 0x1585
movq -0x88(%rbp), %rax
movl 0x17d4(%rax), %edi
movl -0x24(%rbp), %esi
callq 0x1a80
cvttsd2si %xmm0, %eax
movl %eax, -0x78(%rbp)
movl -0x78(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
cmpl $0x0, %edx
jne 0x159e
movl -0x78(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x78(%rbp)
movq -0x88(%rbp), %rdi
callq 0x1a50
movq %rax, %rdi
movslq -0x74(%rbp), %rax
imulq $0x38, %rax, %rax
addq %rax, %rdi
movl -0x78(%rbp), %esi
callq 0x1ab0
movq -0x88(%rbp), %rax
movl -0x78(%rbp), %ecx
movl %ecx, 0x8(%rax)
jmp 0x1640
movq -0x88(%rbp), %rax
cmpl $0x0, (%rax)
je 0x15e7
movq -0x88(%rbp), %rax
cmpl $0x1, (%rax)
jne 0x1612
movq -0x88(%rbp), %rdi
callq 0x1a50
movq %rax, %rdi
movq -0x88(%rbp), %rax
movslq -0x74(%rbp), %rcx
imulq $0x38, %rcx, %rcx
addq %rcx, %rdi
movl 0x8(%rax), %esi
callq 0x1ab0
jmp 0x163e
movq -0x88(%rbp), %rdi
callq 0x1a50
movq %rax, %rdi
movq -0x88(%rbp), %rax
movslq -0x74(%rbp), %rcx
imulq $0x38, %rcx, %rcx
addq %rcx, %rdi
movl 0x17d4(%rax), %esi
callq 0x1ab0
jmp 0x1640
jmp 0x1642
movl -0x74(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x74(%rbp)
jmp 0x1531
movl $0x0, -0x7c(%rbp)
movq -0x88(%rbp), %rcx
movl -0x7c(%rbp), %eax
cmpl 0x17d4(%rcx), %eax
jge 0x1693
movq -0x88(%rbp), %rdi
callq 0x1b00
movq %rax, %rdi
movslq -0x7c(%rbp), %rax
shlq $0x7, %rax
addq %rax, %rdi
callq 0x1b20
movl -0x7c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x7c(%rbp)
jmp 0x1657
addq $0x90, %rsp
popq %rbp
retq
nopl (%rax)