// File: /workspace/github_cpp_makefile_star2_O1/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
shll $0x14, %esi
andl $0x3ff00000, %esi       # imm = 0x3FF00000
movq 0x20(%rdi), %rax
movl %eax, %r11d
notl %r11d
andl $0x1, %r11d
movl %eax, %r10d
andl $0x2, %r10d
cmpq $0x1, %r10
adcl $0x0, %r11d
xorl %ebx, %ebx
testb $0x4, %al
sete %bl
movl %eax, %r10d
andl $0x8, %r10d
cmpq $0x1, %r10
adcl %r11d, %ebx
cmpl $0x2, %ebx
jne 0x2f3fd
movabsq $0x7f000000000000, %r10 # imm = 0x7F000000000000
orq %r10, %rax
movq %rax, 0x20(%rdi)
movq 0x38(%rsp), %rax
leal 0x10000(%rsi), %r10d
cmpl $0x2, %ebx
jb 0x2f54c
movq %rcx, -0x8(%rsp)
movq %r8, -0x18(%rsp)
movb $0x0, (%rax)
movq 0x20(%rdi), %r11
xorl %ebx, %ebx
movl $0x0, %eax
movl $0x0, %ecx
movl $0x0, %r14d
movl $0x0, %r15d
testb %r9b, %r9b
je 0x2f462
btl $0x8, %r11d
setae %al
btl $0x9, %r11d
setae %cl
btl $0xa, %r11d
setae %r14b
btl $0xb, %r11d
setae %r15b
movl %ecx, -0x10(%rsp)
movl %eax, -0xc(%rsp)
movl 0x10(%rdi), %r13d
movl 0x14(%rdi), %r12d
subl (%rdi), %r13d
testb $0x1, %r11b
movl $0x0, %eax
cmovel %r13d, %eax
subl 0x4(%rdi), %r12d
testb $0x2, %r11b
movl $0x0, %ecx
cmovel %r12d, %ecx
addl %eax, %ecx
movl 0x18(%rdi), %eax
subl 0x8(%rdi), %eax
testb $0x4, %r11b
movl $0x0, %ebp
cmovel %eax, %ebp
movl 0x1c(%rdi), %r8d
subl 0xc(%rdi), %r8d
testb $0x8, %r11b
cmovel %r8d, %ebx
addl %ebp, %ebx
addl %ecx, %ebx
testb %r9b, %r9b
je 0x2f4ed
xorl %ecx, %ecx
cmpb $0x0, -0xc(%rsp)
cmovel %ecx, %r13d
cmpb $0x0, -0x10(%rsp)
cmovel %ecx, %r12d
testb %r14b, %r14b
cmovel %ecx, %eax
testb %r15b, %r15b
cmovel %ecx, %r8d
addl %r13d, %r12d
addl %eax, %r8d
addl %r12d, %r8d
addl %r8d, %ebx
movl (%rdx), %ecx
movl 0x4(%rdx), %r8d
movl 0x8(%rdx), %eax
imull %ecx, %eax
addl %r8d, %eax
movl %eax, %r9d
shrl $0x10, %r9d
imull %ecx, %eax
addl %r8d, %eax
movl %eax, 0x8(%rdx)
xorl %r9d, %eax
movl $0x0, 0xc(%rdx)
xorl %edx, %edx
divl %ebx
testb $0x1, %r11b
movq -0x8(%rsp), %r8
jne 0x2f55c
movl (%rdi), %eax
movl 0x10(%rdi), %ecx
subl %eax, %ecx
subl %ecx, %edx
jae 0x2f55c
movl %eax, (%r8)
movl 0x10(%rdi), %eax
movq -0x18(%rsp), %rcx
movl %eax, (%rcx)
orb $0x1, 0x20(%rdi)
orl $0x10041, %esi          # imm = 0x10041
jmp 0x2f60f
movb $0x1, (%rax)
movq 0x20(%rdi), %rdx
testb $0x1, %dl
jne 0x2f5b5
xorl %eax, %eax
jmp 0x2f5cf
testb $0x2, %r11b
jne 0x2f58a
movl 0x4(%rdi), %eax
movl 0x14(%rdi), %ecx
subl %eax, %ecx
subl %ecx, %edx
jae 0x2f58a
movl %eax, (%r8)
movl 0x14(%rdi), %eax
movq -0x18(%rsp), %rcx
movl %eax, (%rcx)
orb $0x2, 0x20(%rdi)
orl $0x10043, %esi          # imm = 0x10043
jmp 0x2f60f
testb $0x4, %r11b
jne 0x2f5ef
movl 0x8(%rdi), %eax
movl 0x18(%rdi), %ecx
subl %eax, %ecx
cmpl %ecx, %edx
jae 0x2f5ef
movl %eax, (%r8)
movl 0x18(%rdi), %eax
movq -0x18(%rsp), %rcx
movl %eax, (%rcx)
orb $0x4, 0x20(%rdi)
orl $0x10047, %esi          # imm = 0x10047
jmp 0x2f60f
movl $0x1, %eax
testb $0x2, %dl
je 0x2f5cf
andl $0x4, %edx
cmpq $0x1, %rdx
movl $0x3, %eax
sbbq $0x0, %rax
leaq 0x23e9f(%rip), %rdx     # 0x53475
movzbl (%rax,%rdx), %edx
orl %edx, %r10d
movl (%rdi,%rax,4), %edx
movl %edx, (%rcx)
movl 0x10(%rdi,%rax,4), %eax
movl %eax, (%r8)
movb $0x1, 0x28(%rdi)
jmp 0x2f612
testb $0x8, %r11b
jne 0x2f612
movl 0xc(%rdi), %eax
movl %eax, (%r8)
movl 0x1c(%rdi), %eax
movq -0x18(%rsp), %rcx
movl %eax, (%rcx)
orb $0x8, 0x20(%rdi)
orl $0x10054, %esi          # imm = 0x10054
movl %esi, %r10d
movl %r10d, %eax
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq