// File: /workspace/github_cpp_makefile_star2_O3/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
movq 0x38(%rsp), %rax
shll $0x14, %esi
andl $0x3ff00000, %esi       # imm = 0x3FF00000
leal 0x10000(%rsi), %ebp
movq 0x20(%rdi), %r14
movl %r14d, %r10d
notl %r10d
andl $0x1, %r10d
movl %r14d, %r11d
andl $0x2, %r11d
cmpq $0x1, %r11
adcl $0x0, %r10d
xorl %r11d, %r11d
testb $0x4, %r14b
sete %r11b
movl %r14d, %ebx
andl $0x8, %ebx
cmpq $0x1, %rbx
adcl %r10d, %r11d
cmpl $0x2, %r11d
jne 0x2f122
movabsq $0x7f000000000000, %r10 # imm = 0x7F000000000000
orq %r10, %r14
movq %r14, 0x20(%rdi)
jmp 0x2f128
jb 0x2f2d7
movl %ebp, -0x18(%rsp)
movq %rcx, -0x10(%rsp)
movq %r8, -0x8(%rsp)
movb $0x0, (%rax)
movq 0x20(%rdi), %r11
xorl %ebx, %ebx
movl $0x0, %eax
movl $0x0, %ebp
movl $0x0, %r14d
movl $0x0, %r15d
testb %r9b, %r9b
je 0x2f17d
btl $0x8, %r11d
setae %al
btl $0x9, %r11d
setae %bpl
btl $0xa, %r11d
setae %r14b
btl $0xb, %r11d
setae %r15b
movl %eax, -0x14(%rsp)
movl 0x10(%rdi), %r13d
movl 0x14(%rdi), %r12d
subl (%rdi), %r13d
testb $0x1, %r11b
movl $0x0, %r8d
cmovel %r13d, %r8d
subl 0x4(%rdi), %r12d
testb $0x2, %r11b
movl $0x0, %ecx
cmovel %r12d, %ecx
addl %r8d, %ecx
movl 0x18(%rdi), %r10d
subl 0x8(%rdi), %r10d
testb $0x4, %r11b
movl $0x0, %eax
cmovel %r10d, %eax
movl 0x1c(%rdi), %r8d
subl 0xc(%rdi), %r8d
testb $0x8, %r11b
cmovel %r8d, %ebx
addl %eax, %ebx
addl %ecx, %ebx
testb %r9b, %r9b
je 0x2f208
xorl %eax, %eax
cmpb $0x0, -0x14(%rsp)
cmovel %eax, %r13d
testb %bpl, %bpl
cmovel %eax, %r12d
testb %r14b, %r14b
cmovel %eax, %r10d
testb %r15b, %r15b
cmovel %eax, %r8d
addl %r13d, %r12d
addl %r10d, %r8d
addl %r12d, %r8d
addl %r8d, %ebx
movq -0x8(%rsp), %r10
movq -0x10(%rsp), %r14
movl -0x18(%rsp), %ebp
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
jne 0x2f269
movl (%rdi), %eax
movl 0x10(%rdi), %ecx
subl %eax, %ecx
subl %ecx, %edx
jae 0x2f269
movl %eax, (%r14)
movl 0x10(%rdi), %eax
movl %eax, (%r10)
orb $0x1, 0x20(%rdi)
orl $0x10041, %esi          # imm = 0x10041
jmp 0x2f2d3
testb $0x2, %r11b
jne 0x2f290
movl 0x4(%rdi), %eax
movl 0x14(%rdi), %ecx
subl %eax, %ecx
subl %ecx, %edx
jae 0x2f290
movl %eax, (%r14)
movl 0x14(%rdi), %eax
movl %eax, (%r10)
orb $0x2, 0x20(%rdi)
orl $0x10043, %esi          # imm = 0x10043
jmp 0x2f2d3
testb $0x4, %r11b
jne 0x2f2b7
movl 0x8(%rdi), %eax
movl 0x18(%rdi), %ecx
subl %eax, %ecx
cmpl %ecx, %edx
jae 0x2f2b7
movl %eax, (%r14)
movl 0x18(%rdi), %eax
movl %eax, (%r10)
orb $0x4, 0x20(%rdi)
orl $0x10047, %esi          # imm = 0x10047
jmp 0x2f2d3
testb $0x8, %r11b
jne 0x2f31e
movl 0xc(%rdi), %eax
movl %eax, (%r14)
movl 0x1c(%rdi), %eax
movl %eax, (%r10)
orb $0x8, 0x20(%rdi)
orl $0x10054, %esi          # imm = 0x10054
movl %esi, %ebp
jmp 0x2f31e
movb $0x1, (%rax)
movq 0x20(%rdi), %rdx
testb $0x1, %dl
jne 0x2f2e7
xorl %eax, %eax
jmp 0x2f301
movl $0x1, %eax
testb $0x2, %dl
je 0x2f301
andl $0x4, %edx
cmpq $0x1, %rdx
movl $0x3, %eax
sbbq $0x0, %rax
leaq 0x2324d(%rip), %rdx     # 0x52555
movzbl (%rax,%rdx), %edx
orl %edx, %ebp
movl (%rdi,%rax,4), %edx
movl %edx, (%rcx)
movl 0x10(%rdi,%rax,4), %eax
movl %eax, (%r8)
movb $0x1, 0x28(%rdi)
movl %ebp, %eax
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop