// File: BenLangmead[P]bowtie/./range_source.h
// Function: Branch::splitBranch(AllocOnlyPool<RangeState>&, AllocOnlyPool<Edit>&, AllocOnlyPool<Branch>&, unsigned int, RandomSource&, unsigned int, unsigned int, int, bool, EbwtParams const&, unsigned char const*, bool, bool, bool)
Branch* splitBranch(AllocOnlyPool<RangeState>& rpool,
	                    AllocOnlyPool<Edit>& epool,
	                    AllocOnlyPool<Branch>& bpool,
	                    uint32_t pmSz,
	                    RandomSource& rand, uint32_t qlen,
	                    uint32_t qualLim, int seedLen,
	                    bool qualOrder, const EbwtParams& ep,
	                    const uint8_t* ebwt, bool ebwtFw,
	                    bool verbose,
	                    bool quiet)
	{
		assert(!exhausted_);
		assert(ranges_ != NULL);
		assert(curtailed_);
		assert_gt(pmSz, 0);
		Branch *newBranch = bpool.alloc();
		if(newBranch == NULL) {
			return NULL;
		}
		assert(newBranch != NULL);
		uint32_t id = bpool.lastId();
		int tiedPositions[3];
		int numTiedPositions = 0;
		// Lowest marginal cost incurred by any of the positions with
		// non-eliminated outgoing edges
		uint16_t bestCost = 0xffff;
		// Next-lowest
		uint16_t nextCost = 0xffff;
		int numNotEliminated = 0;
		int i = (int)depth0_;
		i = max(0, i - rdepth_);
		// Iterate over revisitable positions in the path
		for(; i <= len_; i++) {
			// If there are still valid options for leaving out of this
			// position
			if(!eliminated(i)) {
				numNotEliminated++;
				uint16_t stratum = (rdepth_ + i < seedLen) ? (1 << 14) : 0;
				uint16_t cost = stratum;
				cost |= (qualOrder ? ranges_[i].eq.flags.quallo : 0);
				if(cost < bestCost) {
					// Demote the old best to the next-best
					nextCost = bestCost;
					// Update the new best
					bestCost = cost;
					numTiedPositions = 1;
					tiedPositions[0] = i;
				} else if(cost == bestCost) {
					// As good as the best so far
					assert_gt(numTiedPositions, 0);
					if(numTiedPositions < 3) {
						tiedPositions[numTiedPositions++] = i;
					} else {
						tiedPositions[0] = tiedPositions[1];
						tiedPositions[1] = tiedPositions[2];
						tiedPositions[2] = i;
					}
				} else if(cost < nextCost) {
					// 'cost' isn't beter than the best, but it is
					// better than the next-best
					nextCost = cost;
				}
			}
		}
		assert_gt(numNotEliminated, 0);
		assert_gt(numTiedPositions, 0);
		//if(nextCost != 0xffff) assert_gt(nextCost, bestCost);
		int r = 0;
		if(numTiedPositions > 1) {
			r = rand.nextU32() % numTiedPositions;
		}
		int pos = tiedPositions[r];
		bool last = false;
		// Pick an edit from among the edits tied for lowest cost
		// (using randomness to break ties).  If the selected edit is
		// the last remaining one at this position, 'last' is set to
		// true.
		TIndexOffU top = 0, bot = 0;
		Edit e = ranges_[pos].pickEdit(pos + rdepth_, rand, top, bot, false, last);
		assert_gt(bot, top);
		// Create and initialize a new Branch
		uint16_t newRdepth = rdepth_ + pos + 1;
		assert_lt((bestCost >> 14), 4);
		uint32_t hamadd = (bestCost & ~0xc000);
		uint16_t depth = pos + rdepth_;
		assert_geq(depth, depth0_);
		uint16_t newDepth0 = depth0_;
		uint16_t newDepth1 = depth1_;
		uint16_t newDepth2 = depth2_;
		uint16_t newDepth3 = depth3_;
		if(depth < depth1_) newDepth0 = depth1_;
		if(depth < depth2_) newDepth1 = depth2_;
		if(depth < depth3_) newDepth2 = depth3_;
		assert_eq((uint32_t)(cost_ & ~0xc000), (uint32_t)(ham_ + hamadd));
		if(!newBranch->init(
				rpool, epool, id, qlen,
				newDepth0, newDepth1, newDepth2, newDepth3,
				newRdepth, 0, cost_, ham_ + hamadd,
				top, bot, ep, ebwt, &edits_))
		{
			return NULL;
		}
		// Add the new edit
		newBranch->edits_.add(e, epool, qlen);
		if(numNotEliminated == 1 && last) {
			// This branch is totally exhausted; there are no more
			// valid outgoing paths from any positions within it.
			// Remove it from the PathManager and mark it as exhausted.
			// The caller should delete it.
			exhausted_ = true;
			if(ranges_ != NULL) {
				assert_gt(rangesSz_, 0);
				if(rpool.free(ranges_, rangesSz_)) {
					ranges_ = NULL;
					rangesSz_ = 0;
				}
			}
		}
		else if(numTiedPositions == 1 && last) {
			// We exhausted the last outgoing edge at the current best
			// cost; update the best cost to be the next-best
			assert_neq(0xffff, nextCost);
			if(bestCost != nextCost) {
				assert_gt(nextCost, bestCost);
				delayedCost_ = (cost_ - bestCost + nextCost);
				delayedIncrease_ = true;
			}
		}
		return newBranch;
	}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x128, %rsp            # imm = 0x128
movq %rcx, -0xd8(%rbp)
movq %rdx, %r10
movq %rsi, %r11
movq %rdi, %rbx
movq -0xd8(%rbp), %rdi
movb 0x50(%rbp), %al
movb 0x48(%rbp), %cl
movb 0x40(%rbp), %dl
movq 0x38(%rbp), %rsi
movq 0x30(%rbp), %rsi
movb 0x28(%rbp), %sil
movl 0x20(%rbp), %r14d
movl 0x18(%rbp), %r14d
movl 0x10(%rbp), %r14d
movq %rbx, -0x38(%rbp)
movq %r11, -0x40(%rbp)
movq %r10, -0x48(%rbp)
movq %rdi, -0x50(%rbp)
movl %r8d, -0x54(%rbp)
movq %r9, -0x60(%rbp)
andb $0x1, %sil
movb %sil, -0x61(%rbp)
andb $0x1, %dl
movb %dl, -0x62(%rbp)
andb $0x1, %cl
movb %cl, -0x63(%rbp)
andb $0x1, %al
movb %al, -0x64(%rbp)
movq -0x38(%rbp), %rax
movq %rax, -0xd0(%rbp)
movq -0x50(%rbp), %rdi
callq 0x40ba0
movq %rax, -0x70(%rbp)
cmpq $0x0, -0x70(%rbp)
jne 0x47559
movq $0x0, -0x30(%rbp)
jmp 0x47adc
movq -0x50(%rbp), %rdi
callq 0x40ea0
movq -0xd0(%rbp), %rcx
movl %eax, -0x74(%rbp)
movl $0x0, -0x84(%rbp)
movw $0xffff, -0x86(%rbp)    # imm = 0xFFFF
movw $0xffff, -0x88(%rbp)    # imm = 0xFFFF
movl $0x0, -0x8c(%rbp)
movzwl 0x4(%rcx), %eax
movl %eax, -0x90(%rbp)
movl $0x0, -0x94(%rbp)
movl -0x90(%rbp), %eax
movzwl 0xc(%rcx), %ecx
subl %ecx, %eax
movl %eax, -0x98(%rbp)
leaq -0x94(%rbp), %rdi
leaq -0x98(%rbp), %rsi
callq 0x31970
movl (%rax), %eax
movl %eax, -0x90(%rbp)
movq -0xd0(%rbp), %rcx
movl -0x90(%rbp), %eax
movzwl 0xe(%rcx), %ecx
cmpl %ecx, %eax
jg 0x4776d
movq -0xd0(%rbp), %rdi
movl -0x90(%rbp), %esi
callq 0x45600
testb $0x1, %al
jne 0x47757
movq -0xd0(%rbp), %rax
movl -0x8c(%rbp), %ecx
addl $0x1, %ecx
movl %ecx, -0x8c(%rbp)
movzwl 0xc(%rax), %edx
addl -0x90(%rbp), %edx
movl 0x20(%rbp), %esi
xorl %eax, %eax
movl $0x4000, %ecx           # imm = 0x4000
cmpl %esi, %edx
cmovll %ecx, %eax
movw %ax, -0x9a(%rbp)
movw -0x9a(%rbp), %ax
movw %ax, -0x9c(%rbp)
testb $0x1, -0x61(%rbp)
je 0x4767d
movq -0xd0(%rbp), %rax
movq 0x18(%rax), %rax
movslq -0x90(%rbp), %rcx
imulq $0x30, %rcx, %rcx
addq %rcx, %rax
movq 0x20(%rax), %rax
shrq $0x29, %rax
andq $0x7f, %rax
movl %eax, -0xdc(%rbp)
jmp 0x47687
xorl %eax, %eax
movl %eax, -0xdc(%rbp)
jmp 0x47687
movl -0xdc(%rbp), %ecx
movzwl -0x9c(%rbp), %eax
orl %ecx, %eax
movw %ax, -0x9c(%rbp)
movzwl -0x9c(%rbp), %eax
movzwl -0x86(%rbp), %ecx
cmpl %ecx, %eax
jge 0x476e0
movw -0x86(%rbp), %ax
movw %ax, -0x88(%rbp)
movw -0x9c(%rbp), %ax
movw %ax, -0x86(%rbp)
movl $0x1, -0x84(%rbp)
movl -0x90(%rbp), %eax
movl %eax, -0x80(%rbp)
jmp 0x47755
movzwl -0x9c(%rbp), %eax
movzwl -0x86(%rbp), %ecx
cmpl %ecx, %eax
jne 0x47731
cmpl $0x3, -0x84(%rbp)
jge 0x4771a
movl -0x90(%rbp), %ecx
movl -0x84(%rbp), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, -0x84(%rbp)
cltq
movl %ecx, -0x80(%rbp,%rax,4)
jmp 0x4772f
movl -0x7c(%rbp), %eax
movl %eax, -0x80(%rbp)
movl -0x78(%rbp), %eax
movl %eax, -0x7c(%rbp)
movl -0x90(%rbp), %eax
movl %eax, -0x78(%rbp)
jmp 0x47753
movzwl -0x9c(%rbp), %eax
movzwl -0x88(%rbp), %ecx
cmpl %ecx, %eax
jge 0x47751
movw -0x9c(%rbp), %ax
movw %ax, -0x88(%rbp)
jmp 0x47753
jmp 0x47755
jmp 0x47757
jmp 0x47759
movl -0x90(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x90(%rbp)
jmp 0x475d3
movl $0x0, -0xa0(%rbp)
cmpl $0x1, -0x84(%rbp)
jle 0x47797
movq -0x60(%rbp), %rdi
callq 0x47b20
xorl %edx, %edx
divl -0x84(%rbp)
movl %edx, -0xa0(%rbp)
movq -0xd0(%rbp), %rax
movslq -0xa0(%rbp), %rcx
movl -0x80(%rbp,%rcx,4), %ecx
movl %ecx, -0xa4(%rbp)
movb $0x0, -0xa5(%rbp)
movl $0x0, -0xac(%rbp)
movl $0x0, -0xb0(%rbp)
movq 0x18(%rax), %rdi
movslq -0xa4(%rbp), %rcx
imulq $0x30, %rcx, %rcx
addq %rcx, %rdi
movl -0xa4(%rbp), %esi
movzwl 0xc(%rax), %eax
addl %eax, %esi
movq -0x60(%rbp), %rdx
leaq -0xac(%rbp), %rcx
leaq -0xb0(%rbp), %r8
xorl %r9d, %r9d
leaq -0xa5(%rbp), %rax
movq %rax, (%rsp)
callq 0x47b70
movq -0xd0(%rbp), %rcx
movl %eax, -0xb4(%rbp)
movzwl 0xc(%rcx), %eax
addl -0xa4(%rbp), %eax
addl $0x1, %eax
movw %ax, -0xb6(%rbp)
movzwl -0x86(%rbp), %eax
andl $0xffff3fff, %eax       # imm = 0xFFFF3FFF
movl %eax, -0xbc(%rbp)
movl -0xa4(%rbp), %eax
movzwl 0xc(%rcx), %edx
addl %edx, %eax
movw %ax, -0xbe(%rbp)
movw 0x4(%rcx), %ax
movw %ax, -0xc0(%rbp)
movw 0x6(%rcx), %ax
movw %ax, -0xc2(%rbp)
movw 0x8(%rcx), %ax
movw %ax, -0xc4(%rbp)
movw 0xa(%rcx), %ax
movw %ax, -0xc6(%rbp)
movzwl -0xbe(%rbp), %eax
movzwl 0x6(%rcx), %ecx
cmpl %ecx, %eax
jge 0x478a0
movq -0xd0(%rbp), %rax
movw 0x6(%rax), %ax
movw %ax, -0xc0(%rbp)
movq -0xd0(%rbp), %rcx
movzwl -0xbe(%rbp), %eax
movzwl 0x8(%rcx), %ecx
cmpl %ecx, %eax
jge 0x478c8
movq -0xd0(%rbp), %rax
movw 0x8(%rax), %ax
movw %ax, -0xc2(%rbp)
movq -0xd0(%rbp), %rcx
movzwl -0xbe(%rbp), %eax
movzwl 0xa(%rcx), %ecx
cmpl %ecx, %eax
jge 0x478f0
movq -0xd0(%rbp), %rax
movw 0xa(%rax), %ax
movw %ax, -0xc4(%rbp)
movq -0xd0(%rbp), %rax
movq -0x70(%rbp), %rdi
movq -0x40(%rbp), %rsi
movq -0x48(%rbp), %rdx
movl -0x74(%rbp), %ecx
movl 0x10(%rbp), %r8d
movw -0xc0(%rbp), %r9w
movw -0xc2(%rbp), %r10w
movw %r10w, -0xee(%rbp)
movw -0xc4(%rbp), %r10w
movw %r10w, -0xec(%rbp)
movw -0xc6(%rbp), %r10w
movw %r10w, -0xea(%rbp)
movw -0xb6(%rbp), %r13w
movw 0x10(%rax), %r12w
movzwl 0x12(%rax), %r10d
addl -0xbc(%rbp), %r10d
movw %r10w, %r15w
movl -0xac(%rbp), %r14d
movl -0xb0(%rbp), %ebx
movq 0x30(%rbp), %r11
movq 0x38(%rbp), %r10
addq $0x50, %rax
movq %rax, -0xe8(%rbp)
xorl %eax, %eax
movw -0xee(%rbp), %ax
movzwl %r9w, %r9d
movzwl %ax, %eax
movl %eax, (%rsp)
movw -0xec(%rbp), %ax
movzwl %ax, %eax
movl %eax, 0x8(%rsp)
movw -0xea(%rbp), %ax
movzwl %ax, %eax
movl %eax, 0x10(%rsp)
movq -0xe8(%rbp), %rax
movzwl %r13w, %r13d
movl %r13d, 0x18(%rsp)
movl $0x0, 0x20(%rsp)
movzwl %r12w, %r12d
movl %r12d, 0x28(%rsp)
movzwl %r15w, %r15d
movl %r15d, 0x30(%rsp)
movl %r14d, 0x38(%rsp)
movl %ebx, 0x40(%rsp)
movq %r11, 0x48(%rsp)
movq %r10, 0x50(%rsp)
movq %rax, 0x58(%rsp)
callq 0x40c40
testb $0x1, %al
jne 0x47a06
movq $0x0, -0x30(%rbp)
jmp 0x47adc
movq -0x70(%rbp), %rdi
addq $0x50, %rdi
movq -0x48(%rbp), %rdx
movl 0x10(%rbp), %eax
movl %eax, %ecx
leaq -0xb4(%rbp), %rsi
callq 0x41bf0
cmpl $0x1, -0x8c(%rbp)
jne 0x47a81
testb $0x1, -0xa5(%rbp)
je 0x47a81
movq -0xd0(%rbp), %rax
movb $0x1, 0x83(%rax)
cmpq $0x0, 0x18(%rax)
je 0x47a7f
movq -0xd0(%rbp), %rax
movq -0x40(%rbp), %rdi
movq 0x18(%rax), %rsi
movzwl 0x20(%rax), %edx
callq 0x45660
testb $0x1, %al
jne 0x47a68
jmp 0x47a7d
movq -0xd0(%rbp), %rax
movq $0x0, 0x18(%rax)
movw $0x0, 0x20(%rax)
jmp 0x47a7f
jmp 0x47ad4
cmpl $0x1, -0x84(%rbp)
jne 0x47ad2
testb $0x1, -0xa5(%rbp)
je 0x47ad2
movzwl -0x86(%rbp), %eax
movzwl -0x88(%rbp), %ecx
cmpl %ecx, %eax
je 0x47ad0
movq -0xd0(%rbp), %rax
movzwl 0x10(%rax), %ecx
movzwl -0x86(%rbp), %edx
subl %edx, %ecx
movzwl -0x88(%rbp), %edx
addl %edx, %ecx
movw %cx, 0x80(%rax)
movb $0x1, 0x85(%rax)
jmp 0x47ad2
jmp 0x47ad4
movq -0x70(%rbp), %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rax
addq $0x128, %rsp            # imm = 0x128
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nopw %cs:(%rax,%rax)
nopl (%rax)