// File: /workspace/github_c_makefile_star2_O2/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movl %esi, %ebp
movq %rdi, %rbx
movsd 0x3bc8(%rdi), %xmm0
movsd %xmm0, 0x3bc0(%rdi)
callq 0x32fe
movl 0x3c00(%rbx), %r14d
addl %r14d, %r14d
movq %r14, 0x3bf0(%rbx)
movq 0x2368(%rbx), %r15
movq 0x2370(%rbx), %r12
cmpq %r12, %r15
je 0x33b6
movl 0x3c00(%rbx), %edx
movq %r15, %rdi
movl %r14d, %esi
callq 0x6820
addq $0xf8, %r15
jmp 0x3397
movq %rbx, %rdi
callq 0x2c40
movsd %xmm0, (%rsp)
callq 0x2040
movq $-0x3b9aca00, %rcx      # imm = 0xC4653600
cqto
idivq %rcx
movq %rax, 0x10(%rsp)
movq 0x2368(%rbx), %rdi
callq 0x6632
movq %rax, %r12
movl $0xf8, %edi
addq 0x2368(%rbx), %rdi
callq 0x6632
cmpq %rax, %r12
jne 0x36a3
movsd (%rsp), %xmm0
mulsd 0x6cb1(%rip), %xmm0     # 0xa0c0
movsd %xmm0, (%rsp)
movq 0x3bd8(%rbx), %rax
xorl %r15d, %r15d
movl $0x2710, %ecx           # imm = 0x2710
xorl %edx, %edx
divq %rcx
movq 0xce29(%rip), %rcx      # 0x10258
leaq 0x6ea7(%rip), %rdi      # 0xa2dd
movq %rax, %rsi
movl $0x2710, %edx           # imm = 0x2710
xorl %eax, %eax
callq 0x2030
movq 0xcdec(%rip), %r12      # 0x10238
movq 0x2368(%rbx), %rdi
callq 0x6632
movq %rax, %r13
movq %rbx, %rdi
callq 0x2bd2
leaq 0x6eb1(%rip), %rdi      # 0xa31b
movq %r12, %rsi
movq %r13, %rdx
movq (%rsp), %xmm1
movb $0x2, %al
callq 0x2030
movsd 0x6c44(%rip), %xmm0     # 0xa0c8
movsd %xmm0, 0x8(%rsp)
xorl %r12d, %r12d
movq 0x3be8(%rbx), %rax
addq %r14, %rax
cmpq 0x3bf8(%rbx), %rax
ja 0x362e
movq 0x3be0(%rbx), %rsi
movq %rbx, %rdi
callq 0x3244
movsd %xmm0, 0x3bc0(%rbx)
movq %rbx, %rdi
callq 0x3008
movq 0x3be0(%rbx), %r13
incq %r13
movq %r13, 0x3be0(%rbx)
movq 0x2348(%rbx), %rax
movq %rax, %xmm1
punpckldq 0x6b38(%rip), %xmm1 # xmm1 = xmm1[0],mem[0],xmm1[1],mem[1]
subpd 0x6b40(%rip), %xmm1     # 0xa030
movsd 0x6bd8(%rip), %xmm0     # 0xa0d0
testq %rax, %rax
je 0x3515
movsd 0x2358(%rbx), %xmm0
movapd %xmm1, %xmm2
unpckhpd %xmm1, %xmm2            # xmm2 = xmm2[1],xmm1[1]
addsd %xmm1, %xmm2
divsd %xmm2, %xmm0
movq %rbx, %rdi
movq (%rsp), %xmm1
callq 0x3706
movq 0x3be0(%rbx), %rcx
movq %rcx, %rax
xorl %edx, %edx
movl $0x3e8, %esi            # imm = 0x3E8
divq %rsi
testb %bpl, %bpl
je 0x356b
testq %rdx, %rdx
jne 0x356b
callq 0x2040
cqto
movl $0x3b9aca00, %ecx       # imm = 0x3B9ACA00
idivq %rcx
movq %rax, %r12
addl 0x10(%rsp), %r12d
movq %rbx, %rdi
movl %r12d, %esi
xorl %edx, %edx
callq 0x3b30
movq 0x3be0(%rbx), %rcx
cmpq 0x3bd8(%rbx), %rcx
jae 0x35b2
cmpq %rcx, %r13
jbe 0x3621
movsd 0x8(%rsp), %xmm0
addsd 0x6b4d(%rip), %xmm0     # 0xa0d8
movsd %xmm0, 0x8(%rsp)
movq %rbx, %rdi
callq 0x2c40
movsd 0x8(%rsp), %xmm1
addsd 0x6b19(%rip), %xmm1     # 0xa0c0
mulsd %xmm0, %xmm1
movsd %xmm1, (%rsp)
jmp 0x3621
movdqu 0x3c00(%rbx), %xmm0
movdqu 0x3be8(%rbx), %xmm1
pshufd $0x44, %xmm0, %xmm0     # xmm0 = xmm0[0,1,0,1]
paddq %xmm1, %xmm0
movdqu %xmm0, 0x3be8(%rbx)
andq $0x0, 0x3be0(%rbx)
movq 0x2368(%rbx), %r13
movq 0x2370(%rbx), %r15
cmpq %r15, %r13
je 0x35ff
movq %r13, %rdi
callq 0x6872
addq $0xf8, %r13
jmp 0x35e9
movq %rbx, %rdi
callq 0x2c40
mulsd 0x6ab1(%rip), %xmm0     # 0xa0c0
movsd %xmm0, (%rsp)
xorpd %xmm0, %xmm0
movsd %xmm0, 0x8(%rsp)
movl %r12d, %r15d
leal 0x32(%r15), %eax
cmpl %eax, %r12d
jle 0x348d
pushq $0x1
popq %rdx
movq %rbx, %rdi
movl %r12d, %esi
callq 0x3b30
movq 0x2368(%rbx), %rdi
callq 0x6632
movq 0xcbe9(%rip), %rdx      # 0x10238
leaq 0x6d15(%rip), %rdi      # 0xa36b
movl %eax, %esi
xorl %eax, %eax
callq 0x2030
movq 0xc962(%rip), %rdi      # 0xffc8
leaq 0x6d33(%rip), %rsi      # 0xa3a0
callq 0x2230
movq %rax, %r14
movq %rbx, %rdi
callq 0x2a1a
movq %r14, %rdi
callq 0x23a0
movq %rax, %rdi
callq 0x20f0
movq %rbx, %rdi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x3eb4
leaq 0x6bd7(%rip), %rdi      # 0xa281
leaq 0x6b12(%rip), %rsi      # 0xa1c3
leaq 0x6c02(%rip), %rcx      # 0xa2ba
movl $0x160, %edx            # imm = 0x160
callq 0x2180