// File: /workspace/github_cpp_makefile_star2_O2/BenLangmead[P]bowtie/./range_source.h
// Function: RangeState::pickEdit(int, RandomSource&, unsigned int&, unsigned int&, bool, bool&)
Edit pickEdit(int pos, RandomSource& rand,
	              TIndexOffU& top, TIndexOffU& bot, bool indels,
	              bool& last)
	{
		Edit ret;
		ret.type = EDIT_TYPE_MM;
		ret.pos = pos;
		ret.chr = 0;
		ret.qchr = 0;
		ret.reserved = 0;
		assert(!eliminated_);
		assert(!eq.flags.mmA || !eq.flags.mmC || !eq.flags.mmG || !eq.flags.mmT);
		int num = !eq.flags.mmA + !eq.flags.mmC + !eq.flags.mmG + !eq.flags.mmT;
		assert_leq(num, 4);
		assert_gt(num, 0);
		if(num == 2) eq.flags.quallo2 = 127;
		// Only need to pick randomly if there's a quality tie
		if(num > 1) {
			last = false; // not the last at this pos
			// Sum up range sizes and do a random weighted pick
			TIndexOffU tot = 0;
			bool candA = !eq.flags.mmA; bool candC = !eq.flags.mmC;
			bool candG = !eq.flags.mmG; bool candT = !eq.flags.mmT;
			bool candInsA = false, candInsC = false;
			bool candInsG = false, candInsT = false;
			bool candDel = false;
			if(indels) {
				// Insertions and deletions can only be candidates
				// if the user asked for indels
				candInsA = !eq.flags.insA;
				candInsC = !eq.flags.insC;
				candInsG = !eq.flags.insG;
				candInsT = !eq.flags.insT;
				candDel = !eq.flags.del;
			}
			ASSERT_ONLY(int origNum = num);
			if(candA) {
				assert_gt(bots[0], tops[0]);
				tot += (bots[0] - tops[0]);
				assert_gt(num, 0);
				ASSERT_ONLY(num--);
			}
			if(candC) {
				assert_gt(bots[1], tops[1]);
				tot += (bots[1] - tops[1]);
				assert_gt(num, 0);
				ASSERT_ONLY(num--);
			}
			if(candG) {
				assert_gt(bots[2], tops[2]);
				tot += (bots[2] - tops[2]);
				assert_gt(num, 0);
				ASSERT_ONLY(num--);
			}
			if(candT) {
				assert_gt(bots[3], tops[3]);
				tot += (bots[3] - tops[3]);
				assert_gt(num, 0);
				ASSERT_ONLY(num--);
			}
			if(indels) {
				if(candInsA) {
					assert_gt(bots[0], tops[0]);
					tot += (bots[0] - tops[0]);
					assert_gt(num, 0);
					ASSERT_ONLY(num--);
				}
				if(candInsC) {
					assert_gt(bots[1], tops[1]);
					tot += (bots[1] - tops[1]);
					assert_gt(num, 0);
					ASSERT_ONLY(num--);
				}
				if(candInsG) {
					assert_gt(bots[2], tops[2]);
					tot += (bots[2] - tops[2]);
					assert_gt(num, 0);
					ASSERT_ONLY(num--);
				}
				if(candInsT) {
					assert_gt(bots[3], tops[3]);
					tot += (bots[3] - tops[3]);
					assert_gt(num, 0);
					ASSERT_ONLY(num--);
				}
				if(candDel) {
					// Always a candidate?
					// Always a candidate just within the window?
					// We can eliminate some indels based on the content downstream, but not many
				}
			}

			assert_geq(num, 0);
			assert_lt(num, origNum);
			// Throw a dart randomly that hits one of the possible
			// substitutions, with likelihoods weighted by range size
			uint32_t dart = rand.nextU32() % tot;
			if(candA) {
				if(dart < (bots[0] - tops[0])) {
					// Eliminate A mismatch
					top = tops[0];
					bot = bots[0];
					eq.flags.mmA = 1;
					assert_lt(eq.join2.mmElims, 15);
					ret.chr = 'A';
					return ret;
				}
				dart -= (bots[0] - tops[0]);
			}
			if(candC) {
				if(dart < (bots[1] - tops[1])) {
					// Eliminate C mismatch
					top = tops[1];
					bot = bots[1];
					eq.flags.mmC = 1;
					assert_lt(eq.join2.mmElims, 15);
					ret.chr = 'C';
					return ret;
				}
				dart -= (bots[1] - tops[1]);
			}
			if(candG) {
				if(dart < (bots[2] - tops[2])) {
					// Eliminate G mismatch
					top = tops[2];
					bot = bots[2];
					eq.flags.mmG = 1;
					assert_lt(eq.join2.mmElims, 15);
					ret.chr = 'G';
					return ret;
				}
				dart -= (bots[2] - tops[2]);
			}
			if(candT) {
				assert_lt(dart, (bots[3] - tops[3]));
				// Eliminate T mismatch
				top = tops[3];
				bot = bots[3];
				eq.flags.mmT = 1;
				assert_lt(eq.join2.mmElims, 15);
				ret.chr = 'T';
			}
		} else {
			last = true; // last at this pos
			// There's only one; pick it!
			int chr = -1;
			if(!eq.flags.mmA) {
				chr = 0;
			} else if(!eq.flags.mmC) {
				chr = 1;
			} else if(!eq.flags.mmG) {
				chr = 2;
			} else {
				assert(!eq.flags.mmT);
				chr = 3;
			}
			ret.chr = "ACGT"[chr];
			top = tops[chr];
			bot = bots[chr];
			//assert_eq(15, eq.join2.mmElims);
			// Mark entire position as eliminated
			eliminated_ = true;
		}
			return ret;
	}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x28, %rsp
movl %esi, %r12d
movq %rdi, %rbx
movq 0x60(%rsp), %r11
shll $0x14, %r12d
andl $0x3ff00000, %r12d      # imm = 0x3FF00000
leal 0x10000(%r12), %eax
movq 0x20(%rdi), %r10
movl %r10d, %esi
notl %esi
andl $0x1, %esi
movl %r10d, %edi
andl $0x2, %edi
cmpq $0x1, %rdi
adcl $0x0, %esi
xorl %edi, %edi
testb $0x4, %r10b
sete %dil
movl %r10d, %r14d
andl $0x8, %r14d
cmpq $0x1, %r14
adcl %esi, %edi
cmpl $0x2, %edi
jne 0x2658c
movabsq $0x7f000000000000, %rsi # imm = 0x7F000000000000
orq %rsi, %r10
movq %r10, 0x20(%rbx)
jmp 0x26592
jb 0x2673f
movq %rdx, 0x20(%rsp)
movl %eax, 0x1c(%rsp)
movq %rcx, 0x8(%rsp)
movq %r8, 0x10(%rsp)
movb $0x0, (%r11)
movq 0x20(%rbx), %r13
xorl %r14d, %r14d
movl $0x0, %edx
movl $0x0, %ecx
movl $0x0, %esi
movl $0x0, %edi
testb %r9b, %r9b
je 0x265eb
btl $0x8, %r13d
setae %dl
btl $0x9, %r13d
setae %cl
btl $0xa, %r13d
setae %sil
btl $0xb, %r13d
setae %dil
movl 0x10(%rbx), %r10d
movl 0x14(%rbx), %r8d
subl (%rbx), %r10d
testb $0x1, %r13b
movl $0x0, %r11d
cmovel %r10d, %r11d
subl 0x4(%rbx), %r8d
testb $0x2, %r13b
movl $0x0, %ebp
cmovel %r8d, %ebp
addl %r11d, %ebp
movl 0x18(%rbx), %r11d
subl 0x8(%rbx), %r11d
testb $0x4, %r13b
movl $0x0, %eax
cmovel %r11d, %eax
movl 0x1c(%rbx), %r15d
subl 0xc(%rbx), %r15d
testb $0x8, %r13b
cmovel %r15d, %r14d
addl %eax, %r14d
addl %ebp, %r14d
testb %r9b, %r9b
je 0x26670
xorl %eax, %eax
testb %dl, %dl
cmovel %eax, %r10d
testb %cl, %cl
cmovel %eax, %r8d
testb %sil, %sil
cmovel %eax, %r11d
testb %dil, %dil
cmovel %eax, %r15d
addl %r10d, %r8d
addl %r11d, %r15d
addl %r8d, %r15d
addl %r15d, %r14d
movq 0x20(%rsp), %rdi
callq 0x264f6
xorl %edx, %edx
divl %r14d
testb $0x1, %r13b
jne 0x266b1
movl (%rbx), %eax
movl 0x10(%rbx), %ecx
subl %eax, %ecx
subl %ecx, %edx
jae 0x266b1
movq 0x8(%rsp), %rcx
movl %eax, (%rcx)
movl 0x10(%rbx), %eax
movq 0x10(%rsp), %rcx
movl %eax, (%rcx)
orb $0x1, 0x20(%rbx)
orl $0x10041, %r12d         # imm = 0x10041
jmp 0x2673a
testb $0x2, %r13b
jne 0x266e1
movl 0x4(%rbx), %eax
movl 0x14(%rbx), %ecx
subl %eax, %ecx
subl %ecx, %edx
jae 0x266e1
movq 0x8(%rsp), %rcx
movl %eax, (%rcx)
movl 0x14(%rbx), %eax
movq 0x10(%rsp), %rcx
movl %eax, (%rcx)
orb $0x2, 0x20(%rbx)
orl $0x10043, %r12d         # imm = 0x10043
jmp 0x2673a
testb $0x4, %r13b
jne 0x26711
movl 0x8(%rbx), %eax
movl 0x18(%rbx), %ecx
subl %eax, %ecx
cmpl %ecx, %edx
jae 0x26711
movq 0x8(%rsp), %rcx
movl %eax, (%rcx)
movl 0x18(%rbx), %eax
movq 0x10(%rsp), %rcx
movl %eax, (%rcx)
orb $0x4, 0x20(%rbx)
orl $0x10047, %r12d         # imm = 0x10047
jmp 0x2673a
testb $0x8, %r13b
movl 0x1c(%rsp), %eax
jne 0x26785
movl 0xc(%rbx), %eax
movq 0x8(%rsp), %rcx
movl %eax, (%rcx)
movl 0x1c(%rbx), %eax
movq 0x10(%rsp), %rcx
movl %eax, (%rcx)
orb $0x8, 0x20(%rbx)
orl $0x10054, %r12d         # imm = 0x10054
movl %r12d, %eax
jmp 0x26785
movb $0x1, (%r11)
movq 0x20(%rbx), %rdx
testb $0x1, %dl
jne 0x26750
xorl %esi, %esi
jmp 0x26768
testb $0x2, %dl
jne 0x2675a
pushq $0x1
popq %rsi
jmp 0x26768
andl $0x4, %edx
cmpq $0x1, %rdx
pushq $0x3
popq %rsi
sbbq $0x0, %rsi
leaq 0x20d51(%rip), %rdx     # 0x474c0
movzbl (%rsi,%rdx), %edx
orl %edx, %eax
movl (%rbx,%rsi,4), %edx
movl %edx, (%rcx)
movl 0x10(%rbx,%rsi,4), %ecx
movl %ecx, (%r8)
movb $0x1, 0x28(%rbx)
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq