// File: /workspace/github_cpp_makefile_star2_O3/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, %r14d
movq %rdi, %rbx
movq 0x368(%rdi), %rdi
testq %rdi, %rdi
je 0x48b8
callq 0x3340
movq $0x0, 0x368(%rbx)
movl %r14d, 0x35c(%rbx)
movq %rbx, %rdi
callq 0x74d8
imull %ebp, %eax
cmpl %r14d, %eax
jbe 0x48e2
movq %rbx, %rdi
callq 0x74d8
movl %eax, %ecx
movl %r14d, %eax
xorl %edx, %edx
divl %ecx
movl %eax, %ebp
movl %ebp, 0x360(%rbx)
movq %r14, 0x8(%rsp)
leal 0x1(%r14), %r12d
movq %rbx, %rdi
callq 0x74d8
movl %r12d, %ecx
subl %eax, %ecx
leal 0x1(%rcx), %eax
imull %ecx, %eax
movl %eax, %ebp
shrl $0x1f, %ebp
addl %eax, %ebp
sarl %ebp
movl 0x360(%rbx), %r15d
cmpl $0x3, %r15d
jl 0x4958
movl $0x1, %r14d
movq %rbx, %rdi
callq 0x74d8
leal 0x2(%r14), %ecx
imull %eax, %ecx
movl %r12d, %eax
subl %ecx, %eax
leal 0x1(%rax), %ecx
imull %eax, %ecx
movl %ecx, %eax
shrl $0x1f, %eax
addl %ecx, %eax
sarl %eax
addl %eax, %ebp
incl %r14d
movl 0x360(%rbx), %r15d
leal -0x1(%r15), %eax
cmpl %eax, %r14d
jl 0x4920
movq %rbx, %rdi
callq 0x74d8
imull %r15d, %eax
movl %r12d, (%rsp)
subl %eax, %r12d
addl %ebp, %r12d
movl %r12d, 0x14(%rsp)
movslq %r12d, %r12
movl $0x28, %ecx
movq %r12, %rax
mulq %rcx
movq $-0x1, %r15
cmovnoq %rax, %r15
movq %r15, %rdi
callq 0x3030
testl %r12d, %r12d
je 0x4a04
leaq (%r12,%r12,4), %r14
leaq (%rax,%r14,8), %rcx
pcmpeqd %xmm0, %xmm0
movq %rax, %rdx
movq $-0x1, (%rdx)
movb $0x0, 0x8(%rdx)
movdqu %xmm0, 0xc(%rdx)
movdqu %xmm0, 0x18(%rdx)
addq $0x28, %rdx
cmpq %rcx, %rdx
jne 0x49a8
movq %rax, 0x368(%rbx)
movq %r15, %rdi
callq 0x3030
leaq (%rax,%r14,8), %rcx
pcmpeqd %xmm0, %xmm0
movq %rax, %rdx
movl (%rsp), %r12d
movq $-0x1, (%rdx)
movb $0x0, 0x8(%rdx)
movdqu %xmm0, 0xc(%rdx)
movdqu %xmm0, 0x18(%rdx)
addq $0x28, %rdx
cmpq %rcx, %rdx
jne 0x49e4
jmp 0x4a17
movq %rax, 0x368(%rbx)
movq %r15, %rdi
callq 0x3030
movl (%rsp), %r12d
movq %rax, 0x388(%rbx)
leaq 0x370(%rbx), %rdi
movslq 0x360(%rbx), %rsi
callq 0x608c
movq %rbx, %rdi
callq 0x74d8
movl %r12d, %ebp
subl %eax, %ebp
movq 0x370(%rbx), %rdi
movslq %ebp, %r15
movq %r15, %rsi
callq 0x60c8
testl %r15d, %r15d
jle 0x4a90
movl %ebp, %eax
shlq $0x3, %rax
xorl %ecx, %ecx
xorl %r13d, %r13d
movl %r13d, %edx
leaq (%rdx,%rdx,4), %rdx
shlq $0x3, %rdx
addq 0x368(%rbx), %rdx
movq 0x370(%rbx), %rsi
movq (%rsi), %rsi
movq %rdx, (%rsi,%rcx)
addl %ebp, %r13d
addq $0x8, %rcx
decl %ebp
cmpq %rcx, %rax
jne 0x4a60
jmp 0x4a93
xorl %r13d, %r13d
movslq 0x360(%rbx), %rax
cmpq $0x3, %rax
jl 0x4b6b
movq 0x8(%rsp), %rax
addl $0x2, %eax
movq %rax, 0x8(%rsp)
movl $0xfffffffd, %esi       # imm = 0xFFFFFFFD
movl $0x1, %ebp
movl %esi, 0x4(%rsp)
movq %rbx, %rdi
callq 0x74d8
movl %eax, %r15d
leal 0x2(%rbp), %eax
imull %r15d, %eax
movl %r12d, %ecx
subl %eax, %ecx
leaq (,%rbp,2), %r14
addq %rbp, %r14
leaq (,%r14,8), %rdi
addq 0x370(%rbx), %rdi
movslq %ecx, %r12
movq %r12, %rsi
callq 0x60c8
testl %r12d, %r12d
jle 0x4b49
movl 0x4(%rsp), %esi
imull %esi, %r15d
addl 0x8(%rsp), %r15d
xorl %eax, %eax
movl %r13d, %ecx
leaq (%rcx,%rcx,4), %rcx
shlq $0x3, %rcx
addq 0x368(%rbx), %rcx
movq 0x370(%rbx), %rdx
movq (%rdx,%r14,8), %rdx
movq %rcx, (%rdx,%rax)
addl %r15d, %r13d
decl %r13d
movl %r15d, %ecx
decl %ecx
addq $0x8, %rax
movl %ecx, %r15d
cmpl $0x1, %ecx
jg 0x4b0f
jmp 0x4b4d
movl 0x4(%rsp), %esi
incq %rbp
movslq 0x360(%rbx), %rax
decq %rax
decl %esi
cmpq %rax, %rbp
movl (%rsp), %r12d
jl 0x4abb
jmp 0x4b6e
decq %rax
leaq (%rax,%rax,2), %rdi
shlq $0x3, %rdi
addq 0x370(%rbx), %rdi
movl $0x1, %esi
callq 0x60c8
movl %r13d, %eax
leaq (%rax,%rax,4), %rax
shlq $0x3, %rax
addq 0x368(%rbx), %rax
movslq 0x360(%rbx), %r14
movq 0x370(%rbx), %rcx
leaq (%r14,%r14,2), %rdx
movq -0x18(%rcx,%rdx,8), %rcx
movq %rax, (%rcx)
movq %rbx, %rdi
callq 0x74d8
imull %r14d, %eax
addl %r13d, %r12d
subl %eax, %r12d
cmpl 0x14(%rsp), %r12d
jne 0x4bdb
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x64e2(%rip), %rdi      # 0xb0c4
leaq 0x6530(%rip), %rsi      # 0xb119
leaq 0x653a(%rip), %rcx      # 0xb12a
movl $0x71, %edx
callq 0x3190