// File: /workspace/github_c_makefile_star2_O0/waynebhayes[P]SAHap/src/Genome.cpp
// Function: SAHap::Genome::optimize(bool)
void Genome::optimize(bool debug) {
	// unsigned int TARGET_MEC = 0;//this->haplotypes[0].size() * this->totalCoverage() * READ_ERROR_RATE;
	// Reset state
	this->t = this->tInitial;
	ResetBuffers();

	unsigned WINDOW_SIZE = increments * 2;
	double ERROR = READ_ERROR_RATE;
	double add = 0.0001; // FIXME: WTF is this?
	range.end = WINDOW_SIZE;
	
	for (auto& haplotype : this->haplotypes) {
		haplotype.initializeWindow(WINDOW_SIZE, increments);
	}

	// Target MEC for the Window
	double PTARGET_MEC = windowTotalCoverage() * ERROR;

	auto start_time = duration_cast<seconds>(system_clock::now().time_since_epoch());
	// assert(this->haplotypes.size() == 2); // FIXME need to change a few things below that assume only 0 and 1 exist.
	assert(this->haplotypes[0].size() == this->haplotypes[1].size());
	printf("Performing %ld meta-iterations of %d each using schedule %s,\n",
	    (long)(this->maxIterations/META_ITER), META_ITER, schedName[SCHEDULE]);
	printf("optimizing objective %s across %lu sites with total coverage %g, target MEC %g\n",
	    objName[OBJECTIVE], this->haplotypes[0].size(), this->meanCoverage(), PTARGET_MEC);

	
	int cpuSeconds = 0;
	int tmp = 0;
	
	while (range.start + WINDOW_SIZE <= numberOfSites) {
		this->t = this->getTemperature(this->curIteration);
		this->iteration();
		this->curIteration++;
		double pBad = this->pBad.getAverage();
		iteration_t prev = curIteration;
		DynamicSchedule(pBad, PTARGET_MEC);
		if (debug && curIteration % REPORT_INTERVAL == 0) {
			auto now_time = duration_cast<seconds>(system_clock::now().time_since_epoch());
			cpuSeconds = (int)(now_time - start_time).count();
			Report(cpuSeconds);
			// if(fracTime() > 0.5 && pBad < 0.01 && mec() <= TARGET_MEC) {
			//     printf("Exiting early because MEC %lu reached target\n", mec());
			//     this->curIteration = this->maxIterations; // basically done
			// }
		}
		if (this->done()){//} || (pmec() <= PTARGET_MEC)){
			range.start += increments;
			range.end += increments;
			curIteration = 0;
			tmp = cpuSeconds;
			
			for (auto& haplotype : haplotypes) {
				haplotype.incrementWindow();
			}

			add = 0;
			PTARGET_MEC = windowTotalCoverage() * ERROR;
		} else if (prev > curIteration) {
			add += 0.0005; // FIXME: WTF is this magic number?
			PTARGET_MEC = windowTotalCoverage() * (ERROR + add);
		}

		if (cpuSeconds  > tmp + 50){ // For Debugging to break out if program can't find optimal solution
			break;
		}
	}
	Report(cpuSeconds, true);
	printf("Finished optimizing %d sites using %s cost function\n", (int)this->haplotypes[0].size(), objName[OBJECTIVE]);
	cout << "MEC: " << mec() << endl;

	// for (auto h : haplotypes) {
	// 	// h.printCoverages();
	// 	h.print_mec();
	// }
	createBlocks();
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xe0, %rsp
movb %sil, %al
movq %rdi, -0x8(%rbp)
andb $0x1, %al
movb %al, -0x9(%rbp)
movq -0x8(%rbp), %rdi
movq %rdi, -0xc0(%rbp)
movsd 0x3bc8(%rdi), %xmm0
movsd %xmm0, 0x3bc0(%rdi)
callq 0x3be0
movq -0xc0(%rbp), %rax
movq 0x3c00(%rax), %rcx
shlq %rcx
movl %ecx, -0x10(%rbp)
movsd 0x1833d(%rip), %xmm0    # 0x1c050
movsd %xmm0, -0x18(%rbp)
movsd 0x18328(%rip), %xmm0    # 0x1c048
movsd %xmm0, -0x20(%rbp)
movl -0x10(%rbp), %ecx
movq %rcx, 0x3bf0(%rax)
addq $0x2368, %rax           # imm = 0x2368
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rdi
callq 0x5cf0
movq %rax, -0x30(%rbp)
movq -0x28(%rbp), %rdi
callq 0x5d20
movq %rax, -0x38(%rbp)
leaq -0x30(%rbp), %rdi
leaq -0x38(%rbp), %rsi
callq 0x5d50
testb $0x1, %al
jne 0x3d66
jmp 0x3d9d
leaq -0x30(%rbp), %rdi
callq 0x5d90
movq %rax, %rcx
movq -0xc0(%rbp), %rax
movq %rcx, -0x40(%rbp)
movq -0x40(%rbp), %rdi
movl -0x10(%rbp), %esi
movq 0x3c00(%rax), %rax
movl %eax, %edx
callq 0x10d00
leaq -0x30(%rbp), %rdi
callq 0x5db0
jmp 0x3d53
movq -0xc0(%rbp), %rdi
callq 0x30f0
mulsd -0x18(%rbp), %xmm0
movsd %xmm0, -0x48(%rbp)
callq 0x2040
movq %rax, -0x60(%rbp)
leaq -0x60(%rbp), %rdi
callq 0x5e00
movq %rax, -0x58(%rbp)
leaq -0x58(%rbp), %rdi
callq 0x5dd0
movq -0xc0(%rbp), %rdi
movq %rax, -0x50(%rbp)
addq $0x2368, %rdi           # imm = 0x2368
xorl %eax, %eax
movl %eax, %esi
callq 0x5b10
movq %rax, %rdi
callq 0x10860
movq -0xc0(%rbp), %rdi
movq %rax, -0xc8(%rbp)
addq $0x2368, %rdi           # imm = 0x2368
movl $0x1, %esi
callq 0x5b10
movq %rax, %rdi
callq 0x10860
movq %rax, %rcx
movq -0xc8(%rbp), %rax
cmpq %rcx, %rax
jne 0x3e2d
jmp 0x3e4c
leaq 0x183e5(%rip), %rdi     # 0x1c219
leaq 0x18320(%rip), %rsi     # 0x1c15b
movl $0x160, %edx            # imm = 0x160
leaq 0x1840b(%rip), %rcx     # 0x1c252
callq 0x2180
movq -0xc0(%rbp), %rax
movq 0x3bd8(%rax), %rax
movl $0x2710, %ecx           # imm = 0x2710
xorl %edx, %edx
divq %rcx
movq %rax, %rsi
movq 0x2741a(%rip), %rcx     # 0x2b288
leaq 0x18400(%rip), %rdi     # 0x1c275
movl $0x2710, %edx           # imm = 0x2710
movb $0x0, %al
callq 0x2030
movq -0xc0(%rbp), %rdi
movq 0x273d9(%rip), %rax     # 0x2b268
movq %rax, -0xd8(%rbp)
addq $0x2368, %rdi           # imm = 0x2368
xorl %eax, %eax
movl %eax, %esi
callq 0x5b10
movq %rax, %rdi
callq 0x10860
movq -0xc0(%rbp), %rdi
movq %rax, -0xd0(%rbp)
callq 0x3060
movq -0xd8(%rbp), %rsi
movq -0xd0(%rbp), %rdx
movsd -0x48(%rbp), %xmm1
leaq 0x183d8(%rip), %rdi     # 0x1c2b3
movb $0x2, %al
callq 0x2030
movl $0x0, -0x64(%rbp)
movl $0x0, -0x68(%rbp)
movq -0xc0(%rbp), %rcx
movq 0x3be8(%rcx), %rax
movl -0x10(%rbp), %edx
addq %rdx, %rax
cmpq 0x3bf8(%rcx), %rax
ja 0x4159
movq -0xc0(%rbp), %rdi
movq 0x3be0(%rdi), %rsi
callq 0x3ac0
movq -0xc0(%rbp), %rdi
movsd %xmm0, 0x3bc0(%rdi)
callq 0x3700
movq -0xc0(%rbp), %rdi
movq 0x3be0(%rdi), %rax
addq $0x1, %rax
movq %rax, 0x3be0(%rdi)
addq $0x408, %rdi            # imm = 0x408
callq 0x4200
movq -0xc0(%rbp), %rdi
movsd %xmm0, -0x70(%rbp)
movq 0x3be0(%rdi), %rax
movq %rax, -0x78(%rbp)
movsd -0x70(%rbp), %xmm0
movsd -0x48(%rbp), %xmm1
callq 0x4270
testb $0x1, -0x9(%rbp)
je 0x400e
movq -0xc0(%rbp), %rax
movq 0x3be0(%rax), %rax
movl $0x3e8, %ecx            # imm = 0x3E8
xorl %edx, %edx
divq %rcx
cmpq $0x0, %rdx
jne 0x400e
callq 0x2040
movq %rax, -0x90(%rbp)
leaq -0x90(%rbp), %rdi
callq 0x5e00
movq %rax, -0x88(%rbp)
leaq -0x88(%rbp), %rdi
callq 0x5dd0
movq %rax, -0x80(%rbp)
leaq -0x80(%rbp), %rdi
leaq -0x50(%rbp), %rsi
callq 0x5e20
movq %rax, -0x98(%rbp)
leaq -0x98(%rbp), %rdi
callq 0x5e90
movq -0xc0(%rbp), %rdi
movl %eax, -0x64(%rbp)
movl -0x64(%rbp), %esi
xorl %edx, %edx
callq 0x4610
movq -0xc0(%rbp), %rdi
callq 0x3380
testb $0x1, %al
jne 0x4023
jmp 0x40fe
movq -0xc0(%rbp), %rax
movq 0x3c00(%rax), %rcx
addq 0x3be8(%rax), %rcx
movq %rcx, 0x3be8(%rax)
movq 0x3c00(%rax), %rcx
addq 0x3bf0(%rax), %rcx
movq %rcx, 0x3bf0(%rax)
movq $0x0, 0x3be0(%rax)
movl -0x64(%rbp), %ecx
movl %ecx, -0x68(%rbp)
addq $0x2368, %rax           # imm = 0x2368
movq %rax, -0xa0(%rbp)
movq -0xa0(%rbp), %rdi
callq 0x5cf0
movq %rax, -0xa8(%rbp)
movq -0xa0(%rbp), %rdi
callq 0x5d20
movq %rax, -0xb0(%rbp)
leaq -0xa8(%rbp), %rdi
leaq -0xb0(%rbp), %rsi
callq 0x5d50
testb $0x1, %al
jne 0x40b1
jmp 0x40de
leaq -0xa8(%rbp), %rdi
callq 0x5d90
movq %rax, -0xb8(%rbp)
movq -0xb8(%rbp), %rdi
callq 0x10d80
leaq -0xa8(%rbp), %rdi
callq 0x5db0
jmp 0x4098
movq -0xc0(%rbp), %rdi
xorps %xmm0, %xmm0
movsd %xmm0, -0x20(%rbp)
callq 0x30f0
mulsd -0x18(%rbp), %xmm0
movsd %xmm0, -0x48(%rbp)
jmp 0x4145
movq -0xc0(%rbp), %rcx
movq -0x78(%rbp), %rax
cmpq 0x3be0(%rcx), %rax
jbe 0x4143
movq -0xc0(%rbp), %rdi
movsd 0x17f37(%rip), %xmm0    # 0x1c058
addsd -0x20(%rbp), %xmm0
movsd %xmm0, -0x20(%rbp)
callq 0x30f0
movsd -0x18(%rbp), %xmm1
addsd -0x20(%rbp), %xmm1
mulsd %xmm1, %xmm0
movsd %xmm0, -0x48(%rbp)
jmp 0x4145
movl -0x64(%rbp), %eax
movl -0x68(%rbp), %ecx
addl $0x32, %ecx
cmpl %ecx, %eax
jle 0x4154
jmp 0x4159
jmp 0x3ef0
movq -0xc0(%rbp), %rdi
movl -0x64(%rbp), %esi
movl $0x1, %edx
callq 0x4610
movq -0xc0(%rbp), %rdi
addq $0x2368, %rdi           # imm = 0x2368
xorl %eax, %eax
movl %eax, %esi
callq 0x5b10
movq %rax, %rdi
callq 0x10860
movl %eax, %esi
movq 0x270d3(%rip), %rdx     # 0x2b268
leaq 0x18167(%rip), %rdi     # 0x1c303
movb $0x0, %al
callq 0x2030
movq 0x26e1e(%rip), %rdi     # 0x2afc8
leaq 0x18187(%rip), %rsi     # 0x1c338
callq 0x2230
movq -0xc0(%rbp), %rdi
movq %rax, -0xe0(%rbp)
callq 0x2df0
movq -0xe0(%rbp), %rdi
callq 0x2460
movq %rax, %rdi
movq 0x26dd1(%rip), %rsi     # 0x2afb0
callq 0x2270
movq -0xc0(%rbp), %rdi
callq 0x4970
addq $0xe0, %rsp
popq %rbp
retq
nopl (%rax)