// File: /workspace/github_cpp_makefile_star2_O2/CMU-SAFARI[P]optimal-seed-solver/optimalSolver.cc
// Function: OptimalSolver::init(int, int)
void OptimalSolver::init(int readLength, int seedNum) {
	//Initialize the matrix
	if (matrix != NULL) {
		delete [] matrix;
		matrix = NULL;
	}

	this->readLength = readLength;

	if (readLength >= seedNum * tree.getHashLength() )
		this->seedNum = seedNum;
	else
		this->seedNum = readLength / tree.getHashLength();

	//Position count for the level
	int lvPosCount;

	//Matrix overall size
	int matrixSize = 0;

	//For the first 1 seed case, we need to consider all cases
	lvPosCount = readLength + 1 - tree.getHashLength();
	matrixSize += (lvPosCount + 1) * lvPosCount / 2;

	//For the next N-2 seed cases, we need to consider all cases, while leaving
	//the last minLength out (because we don't need to)
	for (int i = 1; i < this->seedNum - 1; i++) {
		//Notice that for the rest levels, we do not need to consider the last
		//hashLength positions
		lvPosCount = readLength + 1 - tree.getHashLength() * (i + 2);
		matrixSize += (lvPosCount + 1) * lvPosCount / 2;
	}

	//For the last seed, it's simpler all cases for dividers
	lvPosCount = readLength + 1 - this->seedNum * tree.getHashLength();
	matrixSize += lvPosCount;

	//Allocate space for the matrix
	matrix = new Cell[matrixSize];
	defaultCells = new Cell[matrixSize];

	//Progress counter
	int matrixProgress = 0;
	//sublevel counter
	int levelIdx = 0;
	//Fill the level pointers
	level.resize(this->seedNum);
	//Find the first row
	lvPosCount = readLength + 1 - tree.getHashLength();
	level[0].resize(lvPosCount);
	for (int i = lvPosCount; i > 0; i--) {
		level[0][levelIdx] = matrix + matrixProgress;
		matrixProgress += i;
		levelIdx++;
	}

	//Find the reminding levels
	for (int idx = 1; idx < this->seedNum - 1; idx++) {
		lvPosCount = readLength + 1 - tree.getHashLength() * (idx + 2);
		level[idx].resize(lvPosCount);
		//reset the sublevel counter
		levelIdx = 0;
		for (int i = lvPosCount; i > 0; i--) {
			level[idx][levelIdx] = matrix + matrixProgress;
			matrixProgress += i;
			levelIdx++;
		}
	}

	//Set the last level
	level[this->seedNum - 1].resize(1);
	level[this->seedNum - 1][0] = matrix + matrixProgress;

	//Just to check the matrixSize
	assert (matrixProgress + readLength + 1 - this->seedNum * tree.getHashLength() == matrixSize);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movl %edx, %ebp
movl %esi, %ebx
movq %rdi, %r14
movq 0x368(%rdi), %rdi
testq %rdi, %rdi
je 0x431e
callq 0x32f0
andq $0x0, 0x368(%r14)
movl %ebx, 0x35c(%r14)
movq %r14, %rdi
callq 0x6b42
imull %ebp, %eax
cmpl %ebx, %eax
jbe 0x4346
movq %r14, %rdi
callq 0x6b42
movl %eax, %ecx
movl %ebx, %eax
xorl %edx, %edx
divl %ecx
movl %eax, %ebp
movl %ebp, 0x360(%r14)
incl %ebx
movq %r14, %rdi
callq 0x6b42
movl %ebx, 0xc(%rsp)
movl %ebx, %ecx
subl %eax, %ecx
leal 0x1(%rcx), %eax
imull %ecx, %eax
pushq $0x2
popq %rcx
cltd
idivl %ecx
movl %eax, %ebp
pushq $0x3
popq %rbx
leal -0x2(%rbx), %r13d
movl 0x360(%r14), %r12d
leal -0x1(%r12), %r15d
movq %r14, %rdi
callq 0x6b42
cmpl %r15d, %r13d
jge 0x43a8
imull %ebx, %eax
movl 0xc(%rsp), %ecx
subl %eax, %ecx
leal 0x1(%rcx), %eax
imull %ecx, %eax
cltd
pushq $0x2
popq %rcx
idivl %ecx
addl %eax, %ebp
incl %ebx
jmp 0x4370
imull %r12d, %eax
movl 0xc(%rsp), %ebx
movl %ebx, %r13d
subl %eax, %r13d
addl %ebp, %r13d
movslq %r13d, %r15
pushq $0x28
popq %rcx
movq %r15, %rax
mulq %rcx
pushq $-0x1
popq %r12
cmovnoq %rax, %r12
movq %r12, %rdi
callq 0x3030
testl %r15d, %r15d
je 0x4406
imulq $0x28, %r15, %rdx
movq %rax, %rcx
addq %rdx, %rcx
pcmpeqd %xmm0, %xmm0
movq %rax, %rdx
orq $-0x1, (%rdx)
movb $0x0, 0x8(%rdx)
movdqu %xmm0, 0xc(%rdx)
movdqu %xmm0, 0x18(%rdx)
addq $0x28, %rdx
cmpq %rcx, %rdx
jne 0x43eb
movq %rax, 0x368(%r14)
movq %r12, %rdi
callq 0x3030
testl %r13d, %r13d
je 0x4446
imulq $0x28, %r15, %rdx
movq %rax, %rcx
addq %rdx, %rcx
pcmpeqd %xmm0, %xmm0
movq %rax, %rdx
orq $-0x1, (%rdx)
movb $0x0, 0x8(%rdx)
movdqu %xmm0, 0xc(%rdx)
movdqu %xmm0, 0x18(%rdx)
addq $0x28, %rdx
cmpq %rcx, %rdx
jne 0x442b
movq %rax, 0x388(%r14)
leaq 0x370(%r14), %rdi
movslq 0x360(%r14), %rsi
callq 0x57fa
movq %r14, %rdi
callq 0x6b42
subl %eax, %ebx
movq 0x370(%r14), %rdi
movslq %ebx, %rsi
callq 0x5830
xorl %eax, %eax
xorl %r15d, %r15d
testl %ebx, %ebx
jle 0x44a9
movl %r15d, %ecx
imulq $0x28, %rcx, %rcx
addq 0x368(%r14), %rcx
movq 0x370(%r14), %rdx
movq (%rdx), %rdx
movq %rcx, (%rdx,%rax)
addl %ebx, %r15d
decl %ebx
addq $0x8, %rax
jmp 0x447e
movl %r13d, 0x10(%rsp)
pushq $-0x3
popq %rsi
pushq $0x1
popq %r13
movl 0xc(%rsp), %r12d
movslq 0x360(%r14), %rax
decq %rax
cmpq %rax, %r13
jge 0x4538
movq %r14, %rdi
movl %esi, 0x14(%rsp)
callq 0x6b42
movl %eax, %ebp
leal 0x2(%r13), %eax
imull %ebp, %eax
movl %r12d, %ecx
subl %eax, %ecx
imulq $0x18, %r13, %rbx
movq 0x370(%r14), %rdi
addq %rbx, %rdi
movslq %ecx, %rsi
callq 0x5830
movl 0x14(%rsp), %esi
imull %esi, %ebp
addl %r12d, %ebp
xorl %eax, %eax
testl %ebp, %ebp
jle 0x4531
movl %r15d, %ecx
imulq $0x28, %rcx, %rcx
addq 0x368(%r14), %rcx
movq 0x370(%r14), %rdx
movq (%rdx,%rbx), %rdx
movq %rcx, (%rdx,%rax)
addl %ebp, %r15d
decl %ebp
addq $0x8, %rax
jmp 0x4505
incq %r13
decl %esi
jmp 0x44ba
imulq $0x18, %rax, %rdi
addq 0x370(%r14), %rdi
pushq $0x1
popq %rsi
callq 0x5830
movl %r15d, %eax
imulq $0x28, %rax, %rax
addq 0x368(%r14), %rax
movslq 0x360(%r14), %rbx
movq 0x370(%r14), %rcx
imulq $0x18, %rbx, %rdx
movq -0x18(%rcx,%rdx), %rcx
movq %rax, (%rcx)
movq %r14, %rdi
callq 0x6b42
imull %ebx, %eax
movl 0xc(%rsp), %ecx
addl %r15d, %ecx
subl %eax, %ecx
cmpl 0x10(%rsp), %ecx
jne 0x459c
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x5b21(%rip), %rdi      # 0xa0c4
leaq 0x5b6f(%rip), %rsi      # 0xa119
leaq 0x5b79(%rip), %rcx      # 0xa12a
pushq $0x71
popq %rdx
callq 0x3170
nop