// File: /workspace/github_c_makefile_star2_O1/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 $0x28, %rsp
movl %esi, %ebp
movq %rdi, %rbx
movsd 0x3bc8(%rdi), %xmm0
movsd %xmm0, 0x3bc0(%rdi)
leaq 0x408(%rdi), %r14
movl $0x0, 0x400(%rdi)
movl $0x3fc, %edx            # imm = 0x3FC
xorl %esi, %esi
callq 0x2140
movl $0x1f60, %edx           # imm = 0x1F60
movq %r14, %rdi
xorl %esi, %esi
callq 0x2140
movl 0x3c00(%rbx), %r14d
addl %r14d, %r14d
movq %r14, 0x3bf0(%rbx)
movq 0x2368(%rbx), %r15
movq 0x2370(%rbx), %r12
cmpq %r12, %r15
je 0x3a7d
movl 0x3c00(%rbx), %edx
movq %r15, %rdi
movl %r14d, %esi
callq 0x7098
addq $0xf8, %r15
jmp 0x3a5e
movq %rbx, %rdi
callq 0x31d4
movsd %xmm0, 0x8(%rsp)
callq 0x2050
movabsq $-0x112e0be826d694b3, %rcx # imm = 0xEED1F417D9296B4D
imulq %rcx
movq %rdx, %r15
movq 0x2368(%rbx), %rdi
callq 0x6e40
movq %rax, %r12
movl $0xf8, %edi
addq 0x2368(%rbx), %rdi
callq 0x6e40
cmpq %rax, %r12
jne 0x3e2f
movq %r15, %rcx
shrq $0x3f, %rcx
sarq $0x1a, %r15
movsd 0x8(%rsp), %xmm0
mulsd 0x7536(%rip), %xmm0     # 0xb018
movsd %xmm0, 0x8(%rsp)
movabsq $0x346dc5d63886594b, %rax # imm = 0x346DC5D63886594B
mulq 0x3bd8(%rbx)
addq %rcx, %r15
movq %r15, 0x18(%rsp)
shrq $0xb, %rdx
movq 0xc77c(%rip), %rcx      # 0x10288
leaq 0x776a(%rip), %rdi      # 0xb27d
xorl %r15d, %r15d
movq %rdx, %rsi
movl $0x2710, %edx           # imm = 0x2710
xorl %eax, %eax
callq 0x2040
movq 0xc73c(%rip), %r12      # 0x10268
movq 0x2368(%rbx), %rdi
callq 0x6e40
movq %rax, %r13
movq %rbx, %rdi
callq 0x314a
leaq 0x7771(%rip), %rdi      # 0xb2bb
movq %r12, %rsi
movq %r13, %rdx
movsd 0x8(%rsp), %xmm1
movb $0x2, %al
callq 0x2040
movsd 0x74bb(%rip), %xmm0     # 0xb020
movsd %xmm0, 0x10(%rsp)
xorl %r12d, %r12d
movq 0x3be8(%rbx), %rax
addq %r14, %rax
cmpq 0x3bf8(%rbx), %rax
ja 0x3d91
movsd 0x3be0(%rbx), %xmm0
movsd 0x752b(%rip), %xmm2     # 0xb0c0
unpcklps %xmm2, %xmm0            # xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1]
movapd 0x7530(%rip), %xmm3     # 0xb0d0
subpd %xmm3, %xmm0
movapd %xmm0, %xmm1
unpckhpd %xmm0, %xmm1            # xmm1 = xmm1[1],xmm0[1]
addsd %xmm0, %xmm1
movsd 0x3bd8(%rbx), %xmm0
unpcklps %xmm2, %xmm0            # xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1]
subpd %xmm3, %xmm0
movapd %xmm0, %xmm2
unpckhpd %xmm0, %xmm2            # xmm2 = xmm2[1],xmm0[1]
addsd %xmm0, %xmm2
divsd %xmm2, %xmm1
movsd 0x3bc8(%rbx), %xmm0
movsd %xmm0, 0x20(%rsp)
movsd 0x3bd0(%rbx), %xmm0
xorpd 0x74f3(%rip), %xmm0     # 0xb0e0
mulsd %xmm1, %xmm0
callq 0x2460
mulsd 0x20(%rsp), %xmm0
movsd %xmm0, 0x3bc0(%rbx)
movq %rbx, %rdi
callq 0x366e
movq 0x3be0(%rbx), %r13
incq %r13
movq %r13, 0x3be0(%rbx)
movq 0x2348(%rbx), %rax
movsd 0x73fc(%rip), %xmm0     # 0xb028
testq %rax, %rax
je 0x3c5e
movsd 0x2358(%rbx), %xmm0
movq %rax, %xmm1
punpckldq 0x747a(%rip), %xmm1 # xmm1 = xmm1[0],mem[0],xmm1[1],mem[1]
subpd 0x7482(%rip), %xmm1     # 0xb0d0
movapd %xmm1, %xmm2
unpckhpd %xmm1, %xmm2            # xmm2 = xmm2[1],xmm1[1]
addsd %xmm1, %xmm2
divsd %xmm2, %xmm0
movq %rbx, %rdi
movsd 0x8(%rsp), %xmm1
callq 0x3e92
testb %bpl, %bpl
je 0x3cce
movq 0x3be0(%rbx), %rax
movabsq $0x1cac083126e978d5, %rcx # imm = 0x1CAC083126E978D5
imulq %rcx, %rax
rorq $0x3, %rax
movabsq $0x4189374bc6a7ef, %rcx # imm = 0x4189374BC6A7EF
cmpq %rcx, %rax
ja 0x3cce
callq 0x2050
movabsq $0x112e0be826d694b3, %rcx # imm = 0x112E0BE826D694B3
imulq %rcx
movq %rdx, %r12
movq %rdx, %rax
shrq $0x3f, %rax
shrq $0x1a, %r12
addl %eax, %r12d
addl 0x18(%rsp), %r12d
movq %rbx, %rdi
movl %r12d, %esi
xorl %edx, %edx
callq 0x4370
movq 0x3be0(%rbx), %rax
cmpq 0x3bd8(%rbx), %rax
jae 0x3d1d
cmpq %rax, %r13
jbe 0x3d84
movsd 0x10(%rsp), %xmm0
addsd 0x733b(%rip), %xmm0     # 0xb030
movsd %xmm0, 0x10(%rsp)
movq %rbx, %rdi
callq 0x31d4
movsd 0x10(%rsp), %xmm1
addsd 0x7307(%rip), %xmm1     # 0xb018
mulsd %xmm0, %xmm1
movsd %xmm1, 0x8(%rsp)
jmp 0x3d84
movq 0x3c00(%rbx), %rax
addq %rax, 0x3be8(%rbx)
addq %rax, 0x3bf0(%rbx)
movq $0x0, 0x3be0(%rbx)
movq 0x2368(%rbx), %r13
movq 0x2370(%rbx), %r15
cmpq %r15, %r13
je 0x3d61
movq %r13, %rdi
callq 0x70ee
addq $0xf8, %r13
jmp 0x3d4b
movq %rbx, %rdi
callq 0x31d4
mulsd 0x72a7(%rip), %xmm0     # 0xb018
movsd %xmm0, 0x8(%rsp)
xorpd %xmm0, %xmm0
movsd %xmm0, 0x10(%rsp)
movl %r12d, %r15d
leal 0x32(%r15), %eax
cmpl %eax, %r12d
jle 0x3b6e
movq %rbx, %rdi
movl %r12d, %esi
movl $0x1, %edx
callq 0x4370
movq 0x2368(%rbx), %rdi
callq 0x6e40
movq 0xc4b4(%rip), %rdx      # 0x10268
leaq 0x7550(%rip), %rdi      # 0xb30b
movl %eax, %esi
xorl %eax, %eax
callq 0x2040
movq 0xc1fd(%rip), %r14      # 0xffc8
leaq 0x756e(%rip), %rsi      # 0xb340
movl $0x5, %edx
movq %r14, %rdi
callq 0x22b0
movq %rbx, %rdi
callq 0x2f58
movq %r14, %rdi
callq 0x23d0
movq %rax, %r14
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x2250
movsbl %al, %esi
movq %r14, %rdi
callq 0x2030
movq %rax, %rdi
callq 0x21a0
movq %rbx, %rdi
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x471a
leaq 0x73eb(%rip), %rdi      # 0xb221
leaq 0x7326(%rip), %rsi      # 0xb163
leaq 0x7416(%rip), %rcx      # 0xb25a
movl $0x160, %edx            # imm = 0x160
callq 0x2180