// File: CMU-SAFARI[P]optimal-seed-solver/optimalSolverLN.cc
// Function: OptimalSolverLN::init(int, int)
void OptimalSolverLN::init(int readLength, int seedNum) {
	//Initialize the matrix
	if  (matrix != NULL) {
		delete [] matrix;
		matrix = NULL;
	}
	if  (base != NULL) {
		delete [] base;
		base = NULL;
	}
	if  (defaultMatrix != NULL) {
		delete [] defaultMatrix;
		defaultMatrix = NULL;
	}
	if  (defaultBase != NULL) {
		delete [] defaultBase;
		defaultBase = NULL;
	}

	this->readLength = readLength;

	if (readLength >= seedNum * minLength)
		this->seedNum = seedNum;
	else
		this->seedNum = readLength / minLength;

	//Position count for the level
	int lvPosCount;

	//Matrix and base overall size
	matrixSize = 0;
	baseSize = 0;

	//For the base case, we need to consider all possible seeds
	lvPosCount = readLength + 1 - minLength;
	baseSize = (lvPosCount + 1) * lvPosCount / 2;

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

#ifdef DEBUG
	cout << "matrixSize: " << matrixSize << endl;
#endif
	//Allocate space for the base
	base = new Cell[baseSize];
	defaultBase = new Cell[baseSize];

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

	//Fill the level0 pointers
	lvPosCount = readLength + 1 - minLength;
	level0.resize(lvPosCount);
	int levelIdx = 0;
	int baseProgress = 0;
	//Initialize the first one
	for (int i = lvPosCount; i > 0; i--) {
		level0[levelIdx] = base + baseProgress;
		baseProgress += i;
		levelIdx++;
	}

	//Just to check the baseSize
	assert (baseProgress == baseSize);

	if (seedNum > 1) {
		//Fill the level pointers. No need to have the last level
		level.resize(seedNum - 1);
		levelIdx = 0;
		int matrixProgress = 0;
		for (int i = 0; i < seedNum - 1; i++) {
			lvPosCount = readLength + 1 - minLength * seedNum;
			level[i] = matrix + matrixProgress;
			matrixProgress += lvPosCount;
		}

		//Just to check the matrixSize
		assert (matrixProgress == matrixSize);
	}
	else {
		level.resize(1);
		level[0] = matrix;
	}


	//Initialize all the seeds
	seeds.resize(seedNum);

	//Initialize statistics
	processedReads = 0;
	divTravel.resize(readLength, 0);
}

// Assembly:
subq $0x148, %rsp            # imm = 0x148
movq %rdi, 0x140(%rsp)
movl %esi, 0x13c(%rsp)
movl %edx, 0x138(%rsp)
movq 0x140(%rsp), %rax
movq %rax, 0x100(%rsp)
cmpq $0x0, 0x370(%rax)
je 0x63d4
movq 0x100(%rsp), %rax
movq 0x370(%rax), %rax
movq %rax, 0xf8(%rsp)
cmpq $0x0, %rax
je 0x63c1
movq 0xf8(%rsp), %rdi
callq 0x3420
movq 0x100(%rsp), %rax
movq $0x0, 0x370(%rax)
movq 0x100(%rsp), %rax
cmpq $0x0, 0x378(%rax)
je 0x6423
movq 0x100(%rsp), %rax
movq 0x378(%rax), %rax
movq %rax, 0xf0(%rsp)
cmpq $0x0, %rax
je 0x6410
movq 0xf0(%rsp), %rdi
callq 0x3420
movq 0x100(%rsp), %rax
movq $0x0, 0x378(%rax)
movq 0x100(%rsp), %rax
cmpq $0x0, 0x3b0(%rax)
je 0x6472
movq 0x100(%rsp), %rax
movq 0x3b0(%rax), %rax
movq %rax, 0xe8(%rsp)
cmpq $0x0, %rax
je 0x645f
movq 0xe8(%rsp), %rdi
callq 0x3420
movq 0x100(%rsp), %rax
movq $0x0, 0x3b0(%rax)
movq 0x100(%rsp), %rax
cmpq $0x0, 0x3b8(%rax)
je 0x64c1
movq 0x100(%rsp), %rax
movq 0x3b8(%rax), %rax
movq %rax, 0xe0(%rsp)
cmpq $0x0, %rax
je 0x64ae
movq 0xe0(%rsp), %rdi
callq 0x3420
movq 0x100(%rsp), %rax
movq $0x0, 0x3b8(%rax)
movq 0x100(%rsp), %rdx
movl 0x13c(%rsp), %eax
movl %eax, 0x360(%rdx)
movl 0x13c(%rsp), %eax
movl 0x138(%rsp), %ecx
imull 0x368(%rdx), %ecx
cmpl %ecx, %eax
jl 0x6506
movq 0x100(%rsp), %rax
movl 0x138(%rsp), %ecx
movl %ecx, 0x364(%rax)
jmp 0x652c
movq 0x100(%rsp), %rcx
movl 0x13c(%rsp), %eax
cltd
idivl 0x368(%rcx)
movl %eax, %ecx
movq 0x100(%rsp), %rax
movl %ecx, 0x364(%rax)
movq 0x100(%rsp), %rcx
movl $0x0, 0x3c0(%rcx)
movl $0x0, 0x3c4(%rcx)
movl 0x13c(%rsp), %eax
addl $0x1, %eax
subl 0x368(%rcx), %eax
movl %eax, 0x134(%rsp)
movl 0x134(%rsp), %eax
addl $0x1, %eax
imull 0x134(%rsp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, %ecx
movq 0x100(%rsp), %rax
movl %ecx, 0x3c4(%rax)
cmpl $0x1, 0x138(%rsp)
jle 0x65ca
movq 0x100(%rsp), %rax
movl 0x13c(%rsp), %ecx
addl $0x1, %ecx
movl 0x368(%rax), %edx
imull 0x138(%rsp), %edx
subl %edx, %ecx
movl 0x138(%rsp), %edx
subl $0x1, %edx
imull %edx, %ecx
movl %ecx, 0x3c0(%rax)
jmp 0x65e8
movq 0x100(%rsp), %rax
movl 0x13c(%rsp), %ecx
addl $0x1, %ecx
subl 0x368(%rax), %ecx
movl %ecx, 0x3c0(%rax)
movq 0x100(%rsp), %rax
movslq 0x3c4(%rax), %rax
movq %rax, 0xd0(%rsp)
movl $0x28, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
movq %rdi, 0xc8(%rsp)
callq 0x3030
movq %rax, %rcx
movq 0xd0(%rsp), %rax
movq %rcx, 0xd8(%rsp)
cmpq $0x0, %rax
je 0x66a3
movq 0xd8(%rsp), %rax
movq 0xd0(%rsp), %rcx
imulq $0x28, %rcx, %rdx
movq %rax, %rcx
addq %rdx, %rcx
movq %rcx, 0xb8(%rsp)
movq %rax, 0xc0(%rsp)
movq 0xc0(%rsp), %rdi
movq %rdi, 0xb0(%rsp)
callq 0xa510
jmp 0x6682
movq 0xb8(%rsp), %rcx
movq 0xb0(%rsp), %rax
addq $0x28, %rax
cmpq %rcx, %rax
movq %rax, 0xc0(%rsp)
jne 0x666b
movq 0x100(%rsp), %rax
movq 0xd8(%rsp), %rcx
movq %rcx, 0x378(%rax)
movslq 0x3c4(%rax), %rax
movq %rax, 0xa0(%rsp)
movl $0x28, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
movq %rdi, 0x98(%rsp)
callq 0x3030
movq %rax, %rcx
movq 0xa0(%rsp), %rax
movq %rcx, 0xa8(%rsp)
cmpq $0x0, %rax
je 0x676d
movq 0xa8(%rsp), %rax
movq 0xa0(%rsp), %rcx
imulq $0x28, %rcx, %rdx
movq %rax, %rcx
addq %rdx, %rcx
movq %rcx, 0x88(%rsp)
movq %rax, 0x90(%rsp)
movq 0x90(%rsp), %rdi
movq %rdi, 0x80(%rsp)
callq 0xa510
jmp 0x674c
movq 0x88(%rsp), %rcx
movq 0x80(%rsp), %rax
addq $0x28, %rax
cmpq %rcx, %rax
movq %rax, 0x90(%rsp)
jne 0x6735
movq 0x100(%rsp), %rax
movq 0xa8(%rsp), %rcx
movq %rcx, 0x3b8(%rax)
movslq 0x3c0(%rax), %rax
movq %rax, 0x70(%rsp)
movl $0x28, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
movq %rdi, 0x68(%rsp)
callq 0x3030
movq %rax, %rcx
movq 0x70(%rsp), %rax
movq %rcx, 0x78(%rsp)
cmpq $0x0, %rax
je 0x6810
movq 0x78(%rsp), %rax
movq 0x70(%rsp), %rcx
imulq $0x28, %rcx, %rdx
movq %rax, %rcx
addq %rdx, %rcx
movq %rcx, 0x58(%rsp)
movq %rax, 0x60(%rsp)
movq 0x60(%rsp), %rdi
movq %rdi, 0x50(%rsp)
callq 0xa510
jmp 0x67f8
movq 0x58(%rsp), %rcx
movq 0x50(%rsp), %rax
addq $0x28, %rax
cmpq %rcx, %rax
movq %rax, 0x60(%rsp)
jne 0x67e7
movq 0x100(%rsp), %rax
movq 0x78(%rsp), %rcx
movq %rcx, 0x370(%rax)
movslq 0x3c0(%rax), %rax
movq %rax, 0x40(%rsp)
movl $0x28, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
movq %rdi, 0x38(%rsp)
callq 0x3030
movq %rax, %rcx
movq 0x40(%rsp), %rax
movq %rcx, 0x48(%rsp)
cmpq $0x0, %rax
je 0x68b0
movq 0x48(%rsp), %rax
movq 0x40(%rsp), %rcx
imulq $0x28, %rcx, %rdx
movq %rax, %rcx
addq %rdx, %rcx
movq %rcx, 0x28(%rsp)
movq %rax, 0x30(%rsp)
movq 0x30(%rsp), %rdi
movq %rdi, 0x20(%rsp)
callq 0xa510
jmp 0x6898
movq 0x28(%rsp), %rcx
movq 0x20(%rsp), %rax
addq $0x28, %rax
cmpq %rcx, %rax
movq %rax, 0x30(%rsp)
jne 0x6887
movq 0x100(%rsp), %rdi
movq 0x48(%rsp), %rax
movq %rax, 0x3b0(%rdi)
movl 0x13c(%rsp), %eax
addl $0x1, %eax
subl 0x368(%rdi), %eax
movl %eax, 0x134(%rsp)
addq $0x398, %rdi            # imm = 0x398
movslq 0x134(%rsp), %rsi
callq 0xa560
movl $0x0, 0x120(%rsp)
movl $0x0, 0x11c(%rsp)
movl 0x134(%rsp), %eax
movl %eax, 0x118(%rsp)
cmpl $0x0, 0x118(%rsp)
jle 0x6a48
movq 0x100(%rsp), %rdi
movq 0x378(%rdi), %rax
movslq 0x11c(%rsp), %rcx
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movq %rax, 0x18(%rsp)
addq $0x398, %rdi            # imm = 0x398
movslq 0x120(%rsp), %rsi
callq 0xa600
movq 0x18(%rsp), %rcx
movq %rcx, (%rax)
movl 0x118(%rsp), %eax
addl 0x11c(%rsp), %eax
movl %eax, 0x11c(%rsp)
movl 0x120(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x120(%rsp)
movl 0x118(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0x118(%rsp)
jmp 0x6913
movq 0xc8(%rsp), %rsi
movq 0xd8(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x128(%rsp)
movl %eax, 0x124(%rsp)
callq 0x3640
jmp 0x6c51
movq 0x98(%rsp), %rsi
movq 0xa8(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x128(%rsp)
movl %eax, 0x124(%rsp)
callq 0x3640
jmp 0x6c51
movq 0x68(%rsp), %rsi
movq 0x78(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x128(%rsp)
movl %eax, 0x124(%rsp)
callq 0x3640
jmp 0x6c51
movq 0x38(%rsp), %rsi
movq 0x48(%rsp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x128(%rsp)
movl %eax, 0x124(%rsp)
callq 0x3640
jmp 0x6c51
movq 0x100(%rsp), %rcx
movl 0x11c(%rsp), %eax
cmpl 0x3c4(%rcx), %eax
jne 0x6a61
jmp 0x6a80
leaq 0x14688(%rip), %rdi     # 0x1b0f0
leaq 0x1469a(%rip), %rsi     # 0x1b109
movl $0x84, %edx
leaq 0x146a1(%rip), %rcx     # 0x1b11c
callq 0x31e0
cmpl $0x1, 0x138(%rsp)
jle 0x6bae
movq 0x100(%rsp), %rdi
addq $0x380, %rdi            # imm = 0x380
movl 0x138(%rsp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0xa560
movl $0x0, 0x120(%rsp)
movl $0x0, 0x114(%rsp)
movl $0x0, 0x110(%rsp)
movl 0x110(%rsp), %eax
movl 0x138(%rsp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jge 0x6b74
movq 0x100(%rsp), %rdi
movl 0x13c(%rsp), %eax
addl $0x1, %eax
movl 0x368(%rdi), %ecx
imull 0x138(%rsp), %ecx
subl %ecx, %eax
movl %eax, 0x134(%rsp)
movq 0x370(%rdi), %rax
movslq 0x114(%rsp), %rcx
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movq %rax, 0x10(%rsp)
addq $0x380, %rdi            # imm = 0x380
movslq 0x110(%rsp), %rsi
callq 0xa600
movq 0x10(%rsp), %rcx
movq %rcx, (%rax)
movl 0x134(%rsp), %eax
addl 0x114(%rsp), %eax
movl %eax, 0x114(%rsp)
movl 0x110(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x110(%rsp)
jmp 0x6ad0
movq 0x100(%rsp), %rcx
movl 0x114(%rsp), %eax
cmpl 0x3c0(%rcx), %eax
jne 0x6b8d
jmp 0x6bac
leaq 0x145ad(%rip), %rdi     # 0x1b141
leaq 0x1456e(%rip), %rsi     # 0x1b109
movl $0x92, %edx
leaq 0x14575(%rip), %rcx     # 0x1b11c
callq 0x31e0
jmp 0x6bf3
movq 0x100(%rsp), %rdi
addq $0x380, %rdi            # imm = 0x380
movl $0x1, %esi
callq 0xa560
movq 0x100(%rsp), %rdi
movq 0x370(%rdi), %rax
movq %rax, 0x8(%rsp)
addq $0x380, %rdi            # imm = 0x380
xorl %eax, %eax
movl %eax, %esi
callq 0xa600
movq 0x8(%rsp), %rcx
movq %rcx, (%rax)
movq 0x100(%rsp), %rdi
addq $0x3c8, %rdi            # imm = 0x3C8
movslq 0x138(%rsp), %rsi
callq 0xa620
movq 0x100(%rsp), %rdi
movl $0x0, 0x400(%rdi)
addq $0x3e8, %rdi            # imm = 0x3E8
movslq 0x13c(%rsp), %rsi
movq $0x0, 0x108(%rsp)
leaq 0x108(%rsp), %rdx
callq 0xa6c0
addq $0x148, %rsp            # imm = 0x148
retq
movq 0x128(%rsp), %rdi
callq 0x35d0
nop