// File: 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
movq %rsp, %rbp
subq $0x60, %rsp
movb %r9b, %al
movq 0x10(%rbp), %r9
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movq %r8, -0x30(%rbp)
andb $0x1, %al
movb %al, -0x31(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x58(%rbp)
leaq -0x4(%rbp), %rdi
callq 0x365a0
movq -0x58(%rbp), %rcx
movl -0x4(%rbp), %eax
andl $0xfff0ffff, %eax       # imm = 0xFFF0FFFF
orl $0x10000, %eax          # imm = 0x10000
movl %eax, -0x4(%rbp)
movl -0x14(%rbp), %edx
movl -0x4(%rbp), %eax
andl $0x3ff, %edx            # imm = 0x3FF
shll $0x14, %edx
andl $0xc00fffff, %eax       # imm = 0xC00FFFFF
orl %edx, %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
andl $0xffffff00, %eax       # imm = 0xFFFFFF00
orl $0x0, %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
andl $0xffff00ff, %eax       # imm = 0xFFFF00FF
orl $0x0, %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
andl $0x3fffffff, %eax       # imm = 0x3FFFFFFF
orl $0x0, %eax
movl %eax, -0x4(%rbp)
movq 0x20(%rcx), %rax
andq $0x1, %rax
cmpq $0x0, %rax
setne %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
movq 0x20(%rcx), %rdx
shrq %rdx
andq $0x1, %rdx
cmpq $0x0, %rdx
setne %dl
xorb $-0x1, %dl
andb $0x1, %dl
movzbl %dl, %edx
addl %edx, %eax
movq 0x20(%rcx), %rdx
shrq $0x2, %rdx
andq $0x1, %rdx
cmpq $0x0, %rdx
setne %dl
xorb $-0x1, %dl
andb $0x1, %dl
movzbl %dl, %edx
addl %edx, %eax
movq 0x20(%rcx), %rcx
shrq $0x3, %rcx
andq $0x1, %rcx
cmpq $0x0, %rcx
setne %cl
xorb $-0x1, %cl
andb $0x1, %cl
movzbl %cl, %ecx
addl %ecx, %eax
movl %eax, -0x38(%rbp)
cmpl $0x2, -0x38(%rbp)
jne 0x47c9a
movq -0x58(%rbp), %rax
movabsq $-0x7f000000000001, %rcx # imm = 0xFF80FFFFFFFFFFFF
andq 0x20(%rax), %rcx
movabsq $0x7f000000000000, %rdx # imm = 0x7F000000000000
orq %rdx, %rcx
movq %rcx, 0x20(%rax)
cmpl $0x1, -0x38(%rbp)
jle 0x47ffc
movq -0x58(%rbp), %rax
movq 0x10(%rbp), %rcx
movb $0x0, (%rcx)
movl $0x0, -0x3c(%rbp)
movq 0x20(%rax), %rcx
andq $0x1, %rcx
cmpq $0x0, %rcx
setne %cl
xorb $-0x1, %cl
andb $0x1, %cl
movb %cl, -0x3d(%rbp)
movq 0x20(%rax), %rcx
shrq %rcx
andq $0x1, %rcx
cmpq $0x0, %rcx
setne %cl
xorb $-0x1, %cl
andb $0x1, %cl
movb %cl, -0x3e(%rbp)
movq 0x20(%rax), %rcx
shrq $0x2, %rcx
andq $0x1, %rcx
cmpq $0x0, %rcx
setne %cl
xorb $-0x1, %cl
andb $0x1, %cl
movb %cl, -0x3f(%rbp)
movq 0x20(%rax), %rax
shrq $0x3, %rax
andq $0x1, %rax
cmpq $0x0, %rax
setne %al
xorb $-0x1, %al
andb $0x1, %al
movb %al, -0x40(%rbp)
movb $0x0, -0x41(%rbp)
movb $0x0, -0x42(%rbp)
movb $0x0, -0x43(%rbp)
movb $0x0, -0x44(%rbp)
movb $0x0, -0x45(%rbp)
testb $0x1, -0x31(%rbp)
je 0x47dcb
movq -0x58(%rbp), %rax
movq 0x20(%rax), %rcx
shrq $0x8, %rcx
andq $0x1, %rcx
cmpq $0x0, %rcx
setne %cl
xorb $-0x1, %cl
andb $0x1, %cl
movb %cl, -0x41(%rbp)
movq 0x20(%rax), %rcx
shrq $0x9, %rcx
andq $0x1, %rcx
cmpq $0x0, %rcx
setne %cl
xorb $-0x1, %cl
andb $0x1, %cl
movb %cl, -0x42(%rbp)
movq 0x20(%rax), %rcx
shrq $0xa, %rcx
andq $0x1, %rcx
cmpq $0x0, %rcx
setne %cl
xorb $-0x1, %cl
andb $0x1, %cl
movb %cl, -0x43(%rbp)
movq 0x20(%rax), %rcx
shrq $0xb, %rcx
andq $0x1, %rcx
cmpq $0x0, %rcx
setne %cl
xorb $-0x1, %cl
andb $0x1, %cl
movb %cl, -0x44(%rbp)
movq 0x20(%rax), %rax
shrq $0xc, %rax
andq $0x1, %rax
cmpq $0x0, %rax
setne %al
xorb $-0x1, %al
andb $0x1, %al
movb %al, -0x45(%rbp)
testb $0x1, -0x3d(%rbp)
je 0x47de0
movq -0x58(%rbp), %rcx
movl 0x10(%rcx), %eax
subl (%rcx), %eax
addl -0x3c(%rbp), %eax
movl %eax, -0x3c(%rbp)
testb $0x1, -0x3e(%rbp)
je 0x47df6
movq -0x58(%rbp), %rcx
movl 0x14(%rcx), %eax
subl 0x4(%rcx), %eax
addl -0x3c(%rbp), %eax
movl %eax, -0x3c(%rbp)
testb $0x1, -0x3f(%rbp)
je 0x47e0c
movq -0x58(%rbp), %rcx
movl 0x18(%rcx), %eax
subl 0x8(%rcx), %eax
addl -0x3c(%rbp), %eax
movl %eax, -0x3c(%rbp)
testb $0x1, -0x40(%rbp)
je 0x47e22
movq -0x58(%rbp), %rcx
movl 0x1c(%rcx), %eax
subl 0xc(%rcx), %eax
addl -0x3c(%rbp), %eax
movl %eax, -0x3c(%rbp)
testb $0x1, -0x31(%rbp)
je 0x47e89
testb $0x1, -0x41(%rbp)
je 0x47e3d
movq -0x58(%rbp), %rcx
movl 0x10(%rcx), %eax
subl (%rcx), %eax
addl -0x3c(%rbp), %eax
movl %eax, -0x3c(%rbp)
testb $0x1, -0x42(%rbp)
je 0x47e53
movq -0x58(%rbp), %rcx
movl 0x14(%rcx), %eax
subl 0x4(%rcx), %eax
addl -0x3c(%rbp), %eax
movl %eax, -0x3c(%rbp)
testb $0x1, -0x43(%rbp)
je 0x47e69
movq -0x58(%rbp), %rcx
movl 0x18(%rcx), %eax
subl 0x8(%rcx), %eax
addl -0x3c(%rbp), %eax
movl %eax, -0x3c(%rbp)
testb $0x1, -0x44(%rbp)
je 0x47e7f
movq -0x58(%rbp), %rcx
movl 0x1c(%rcx), %eax
subl 0xc(%rcx), %eax
addl -0x3c(%rbp), %eax
movl %eax, -0x3c(%rbp)
testb $0x1, -0x45(%rbp)
je 0x47e87
jmp 0x47e87
jmp 0x47e89
movq -0x20(%rbp), %rdi
callq 0x47b20
xorl %edx, %edx
divl -0x3c(%rbp)
movl %edx, -0x4c(%rbp)
testb $0x1, -0x3d(%rbp)
je 0x47ef9
movq -0x58(%rbp), %rdx
movl -0x4c(%rbp), %eax
movl 0x10(%rdx), %ecx
subl (%rdx), %ecx
cmpl %ecx, %eax
jae 0x47ee8
movq -0x58(%rbp), %rax
movl (%rax), %edx
movq -0x28(%rbp), %rcx
movl %edx, (%rcx)
movl 0x10(%rax), %edx
movq -0x30(%rbp), %rcx
movl %edx, (%rcx)
movq 0x20(%rax), %rcx
andq $-0x2, %rcx
orq $0x1, %rcx
movq %rcx, 0x20(%rax)
movl -0x4(%rbp), %eax
andl $0xffffff00, %eax       # imm = 0xFFFFFF00
orl $0x41, %eax
movl %eax, -0x4(%rbp)
jmp 0x480b5
movq -0x58(%rbp), %rax
movl 0x10(%rax), %ecx
subl (%rax), %ecx
movl -0x4c(%rbp), %eax
subl %ecx, %eax
movl %eax, -0x4c(%rbp)
testb $0x1, -0x3e(%rbp)
je 0x47f5b
movq -0x58(%rbp), %rdx
movl -0x4c(%rbp), %eax
movl 0x14(%rdx), %ecx
subl 0x4(%rdx), %ecx
cmpl %ecx, %eax
jae 0x47f49
movq -0x58(%rbp), %rax
movl 0x4(%rax), %edx
movq -0x28(%rbp), %rcx
movl %edx, (%rcx)
movl 0x14(%rax), %edx
movq -0x30(%rbp), %rcx
movl %edx, (%rcx)
movq 0x20(%rax), %rcx
andq $-0x3, %rcx
orq $0x2, %rcx
movq %rcx, 0x20(%rax)
movl -0x4(%rbp), %eax
andl $0xffffff00, %eax       # imm = 0xFFFFFF00
orl $0x43, %eax
movl %eax, -0x4(%rbp)
jmp 0x480b5
movq -0x58(%rbp), %rax
movl 0x14(%rax), %ecx
subl 0x4(%rax), %ecx
movl -0x4c(%rbp), %eax
subl %ecx, %eax
movl %eax, -0x4c(%rbp)
testb $0x1, -0x3f(%rbp)
je 0x47fbd
movq -0x58(%rbp), %rdx
movl -0x4c(%rbp), %eax
movl 0x18(%rdx), %ecx
subl 0x8(%rdx), %ecx
cmpl %ecx, %eax
jae 0x47fab
movq -0x58(%rbp), %rax
movl 0x8(%rax), %edx
movq -0x28(%rbp), %rcx
movl %edx, (%rcx)
movl 0x18(%rax), %edx
movq -0x30(%rbp), %rcx
movl %edx, (%rcx)
movq 0x20(%rax), %rcx
andq $-0x5, %rcx
orq $0x4, %rcx
movq %rcx, 0x20(%rax)
movl -0x4(%rbp), %eax
andl $0xffffff00, %eax       # imm = 0xFFFFFF00
orl $0x47, %eax
movl %eax, -0x4(%rbp)
jmp 0x480b5
movq -0x58(%rbp), %rax
movl 0x18(%rax), %ecx
subl 0x8(%rax), %ecx
movl -0x4c(%rbp), %eax
subl %ecx, %eax
movl %eax, -0x4c(%rbp)
testb $0x1, -0x40(%rbp)
je 0x47ff7
movq -0x58(%rbp), %rax
movl 0xc(%rax), %edx
movq -0x28(%rbp), %rcx
movl %edx, (%rcx)
movl 0x1c(%rax), %edx
movq -0x30(%rbp), %rcx
movl %edx, (%rcx)
movq 0x20(%rax), %rcx
andq $-0x9, %rcx
orq $0x8, %rcx
movq %rcx, 0x20(%rax)
movl -0x4(%rbp), %eax
andl $0xffffff00, %eax       # imm = 0xFFFFFF00
orl $0x54, %eax
movl %eax, -0x4(%rbp)
jmp 0x480b3
movq -0x58(%rbp), %rax
movq 0x10(%rbp), %rcx
movb $0x1, (%rcx)
movl $0xffffffff, -0x50(%rbp) # imm = 0xFFFFFFFF
movq 0x20(%rax), %rax
andq $0x1, %rax
cmpq $0x0, %rax
jne 0x48025
movl $0x0, -0x50(%rbp)
jmp 0x4806d
movq -0x58(%rbp), %rax
movq 0x20(%rax), %rax
shrq %rax
andq $0x1, %rax
cmpq $0x0, %rax
jne 0x48043
movl $0x1, -0x50(%rbp)
jmp 0x4806b
movq -0x58(%rbp), %rax
movq 0x20(%rax), %rax
shrq $0x2, %rax
andq $0x1, %rax
cmpq $0x0, %rax
jne 0x48062
movl $0x2, -0x50(%rbp)
jmp 0x48069
movl $0x3, -0x50(%rbp)
jmp 0x4806b
jmp 0x4806d
movq -0x58(%rbp), %rax
movslq -0x50(%rbp), %rdx
leaq 0x41744(%rip), %rcx     # 0x897c0
movsbl (%rcx,%rdx), %edx
movl -0x4(%rbp), %ecx
andl $0xff, %edx
andl $0xffffff00, %ecx       # imm = 0xFFFFFF00
orl %edx, %ecx
movl %ecx, -0x4(%rbp)
movslq -0x50(%rbp), %rcx
movl (%rax,%rcx,4), %edx
movq -0x28(%rbp), %rcx
movl %edx, (%rcx)
movslq -0x50(%rbp), %rcx
movl 0x10(%rax,%rcx,4), %edx
movq -0x30(%rbp), %rcx
movl %edx, (%rcx)
movb $0x1, 0x28(%rax)
jmp 0x480b5
movl -0x4(%rbp), %eax
addq $0x60, %rsp
popq %rbp
retq
nop