// File: /workspace/github_cpp_makefile_star2_O2/chhylp123[P]hifiasm/inter.cpp
// Function: gen_cns_chain_linear_hard(ul_ov_t*, long, asg_t const*, long, long, double, Chain_Data*, long, long, long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long)
uint64_t gen_cns_chain_linear_hard(ul_ov_t *a, int64_t a_n, const asg_t *rg, int64_t qlen, int64_t bw, double diff_thre, Chain_Data* dp, 
int64_t max_skip, int64_t max_iter, int64_t max_dis, uint64_t mqs, uint64_t mqe, uint64_t ulid, uint64_t ltn, uint64_t rtn)
{
    if(a_n == 0) return 0;
    uint32_t li_v, lj_v; int32_t *f; int64_t *p, *t, st, max_ii, max, qo, cL; ul_ov_t *li, *lj; 
    int64_t mm_ovlp, x, i, j, sc, csc, mm_sc, mm_idx, n_skip, end_j, ch_sc, ch_i; 
    resize_Chain_Data(dp, a_n, NULL); t = dp->tmp; f = dp->score; p = dp->pre;
        
    radix_sort_ul_ov_srt_qe(a, a + a_n);
    for (i = 1, j = 0; i <= a_n; i++) {
        if (i == a_n || a[i].qe != a[j].qe) {
            if(i - j > 1) radix_sort_ul_ov_srt_qs(a+j, a+i);
            j = i;
        }
    }

    memset(t, 0, (a_n*sizeof((*t)))); 
    ch_sc = ch_i = INT32_MIN; 
    for (i = st = 0, max_ii = -1; i < a_n; ++i) {
        li = &(a[i]); 
        mm_ovlp = max_ovlp(rg, ((li->tn<<1)|li->rev)^1);        
        x = (li->qs + mm_ovlp)*diff_thre; 
        if(x < bw) x = bw; 
        x += li->qs + mm_ovlp;
        if (x > qlen+1) x = qlen+1;
        x = find_ul_ov_max(i, a, x+G_CHAIN_INDEL); 

        csc = 1; if(li->el) csc = 0;
        mm_sc = INT32_MIN+1; mm_idx = -1; n_skip = 0; end_j = -1; 

        li_v = (li->tn<<1)|li->rev; li_v ^= 1;
        if ((x-st) > max_iter) st = x-max_iter;
        for (j = x; j >= st; --j) { // collect potential destination vertices
            lj = &(a[j]); 
            if(lj->qe+G_CHAIN_INDEL <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore
            if(f[j] == INT32_MIN) continue;///could not reach the left end
            sc = INT32_MIN;
            if(lj->qs <= li->qs && lj->qe <= li->qe) {///not contained
                lj_v = (lj->tn<<1)|lj->rev; lj_v ^= 1;
                qo = infer_rovlp(li, lj, NULL, NULL, NULL, NULL);
                if(gconnect_test(rg, li_v, lj_v, bw, diff_thre, qo)) {
                    sc = f[j] + csc; 
                }
            }
            if(sc == INT32_MIN) continue;
            if(sc > mm_sc) {
                mm_sc = sc, mm_idx = j;
                if (n_skip > 0) --n_skip;
            } else if (t[j] == i) {
                if (++n_skip > max_skip) break;
            }
            if (p[j] >= 0) t[p[j]] = i;
        }
        
        end_j = j;
        if (max_ii < 0 || (a[i].qe > (a[max_ii].qe+max_dis))) {//too long
            max = INT32_MIN; max_ii = -1;
            for (j = i - 1; (j >= st) && (a[i].qe<=(max_dis+a[j].qe)); --j) {
                if (max < f[j]) {
                    max = f[j], max_ii = j;
                }
            }
        }
                
        if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii]
            lj = &(a[max_ii]); 
            if(((lj->qe+G_CHAIN_INDEL)>li->qs) && (lj->qs<=li->qs) && (lj->qe<=li->qe) && (f[max_ii]!=INT32_MIN)) {
                lj_v = (lj->tn<<1)|lj->rev; lj_v ^= 1; sc = INT32_MIN;
                qo = infer_rovlp(li, lj, NULL, NULL, NULL, NULL);
                if(gconnect_test(rg, li_v, lj_v, bw, diff_thre, qo)) {
                    sc = f[max_ii] + csc; 
                }
                if(sc != INT32_MIN) {
                    if(sc > mm_sc) {
                        mm_sc = sc, mm_idx = max_ii;
                    }
                }
            }
        }

		if(mm_idx == -1) {
			if((ltn) != ((uint64_t)-1)) {
				if(ltn != li->tn) mm_sc = mm_idx = INT32_MIN;
			} else {
				if(((int64_t)li->qs) > ((int64_t)(mqs+bw))) mm_sc = mm_idx = INT32_MIN;
			}
		}
        
        if((mm_sc==(INT32_MIN+1))) {
            mm_sc = csc; 
        }

        
        f[i] = mm_sc; p[i] = mm_idx; 

		// if(ulid == 7723 && ltn == (7723>>1) && rtn == (7829>>1)) {
		// 	fprintf(stderr, "[M::%s::id->%u::%.*s] i::%ld, q::[%u, %u), t::[%u, %u), mm_idx::%ld, mm_sc::%ld\n", 
		// 	__func__, li->tn, (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), i, 
		// 	li->qs, li->qe, li->ts, li->te, mm_idx, mm_sc);
        // }

		if(mm_sc == INT32_MIN) continue;
		if((rtn != ((uint64_t)-1)) && (rtn != li->tn)) continue;
		if((rtn == ((uint64_t)-1)) && (((int64_t)(a[i].qe+bw))<((int64_t)(mqe)))) continue;
        if(mm_sc >= ch_sc) {
			ch_sc = mm_sc; ch_i = i;
		}
		if ((max_ii < 0) || (f[max_ii]<f[i])) {
            max_ii = i;
        }
    }
    // if(ulid == 442462) {
    //  fprintf(stderr, "[M::%s::] ch_i::%ld, mqs::%lu, mqe::%lu\n", 
    //  __func__, ch_i, mqs, mqe);
    // }
    if(ch_i == INT32_MIN) return 0;

    i = ch_i; cL = 0;
    while (i >= 0) {t[cL++] = i; i = p[i];}
    for (i = 0; i < cL; i++) a[i] = a[t[cL-i-1]];
    return cL;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xa8, %rsp
movsd %xmm0, 0x68(%rsp)
movq %r8, 0x10(%rsp)
movq %rcx, 0x80(%rsp)
movq %rdx, 0x60(%rsp)
testq %rsi, %rsi
je 0x1906b7
movq %r9, %r12
movq %rsi, %r14
movq %rdi, %rbp
movq 0xf8(%rsp), %rax
movq %rax, 0x38(%rsp)
xorl %ebx, %ebx
movq %r9, %rdi
xorl %edx, %edx
callq 0x1383e
movq 0x28(%r12), %rax
movq %rax, 0x20(%rsp)
movq (%r12), %rax
movq %rax, 0x30(%rsp)
movq 0x8(%r12), %rax
movq %rax, 0x48(%rsp)
imulq $0x1c, %r14, %rsi
addq %rbp, %rsi
movq %rbp, %rdi
callq 0x156f5c
testq %r14, %r14
movl $0x0, %r15d
cmovgq %r14, %r15
movq %r15, 0x98(%rsp)
negq %r15
leaq 0x1c(%rbp), %r12
pushq $0x1
popq %r13
leaq (%r15,%r13), %rax
cmpq $0x1, %rax
je 0x190201
cmpq %r13, %r14
je 0x1901d4
movl 0x8(%r12), %eax
imulq $0x1c, %rbx, %rcx
cmpl 0x8(%rbp,%rcx), %eax
jne 0x1901d4
movq %rbx, %rax
jmp 0x1901f5
movq %r13, %rcx
subq %rbx, %rcx
movq %r13, %rax
cmpq $0x2, %rcx
jl 0x1901f5
imulq $0x1c, %rbx, %rdi
addq %rbp, %rdi
movq %r12, %rsi
callq 0x1571fa
movq %r13, %rax
incq %r13
addq $0x1c, %r12
movq %rax, %rbx
jmp 0x1901b1
shlq $0x3, %r14
movq 0x20(%rsp), %rdi
xorl %esi, %esi
movq %r14, %rdx
callq 0x20e0
incq 0x80(%rsp)
movq 0x38(%rsp), %rax
addq 0x10(%rsp), %rax
movq %rax, 0x38(%rsp)
leaq -0x14(%rbp), %r13
pushq $-0x1
popq %rax
movq %rax, 0x88(%rsp)
xorl %ebx, %ebx
movq %rax, %r10
xorl %r12d, %r12d
movq $-0x80000000, 0x78(%rsp) # imm = 0x80000000
movq $-0x80000000, 0x40(%rsp) # imm = 0x80000000
movq %rbp, 0x8(%rsp)
cmpq 0x98(%rsp), %r12
je 0x1906a9
movq %rbx, %r15
movq %r13, 0xa0(%rsp)
imulq $0x1c, %r12, %rbx
leaq (%rbx,%rbp), %r14
movl 0xc(%rbp,%rbx), %eax
movl 0x18(%rbp,%rbx), %esi
shrdl $0x1f, %eax, %esi
xorl $0x1, %esi
movq 0x60(%rsp), %rdi
movq %r10, 0x70(%rsp)
callq 0x15d450
movl 0x4(%rbp,%rbx), %ecx
addq %rax, %rcx
cvtsi2sd %rcx, %xmm0
mulsd 0x68(%rsp), %xmm0
cvttsd2si %xmm0, %rdx
movq 0x10(%rsp), %rax
cmpq %rax, %rdx
cmovleq %rax, %rdx
addq %rcx, %rdx
movq 0x80(%rsp), %rax
cmpq %rax, %rdx
cmovgeq %rax, %rdx
subl $-0x80, %edx
movq %r12, 0x50(%rsp)
movl %r12d, %edi
movq %rbp, %rsi
callq 0x160717
movq 0x70(%rsp), %r10
xorl %r9d, %r9d
movslq %eax, %r12
movl 0xc(%rbp,%rbx), %ecx
movl 0x18(%rbp,%rbx), %eax
xorl %r11d, %r11d
btl $0x1e, %eax
setae %r11b
shldl $0x1, %eax, %ecx
xorl $0x1, %ecx
movl %ecx, 0x1c(%rsp)
movq %r12, %rax
subq %r15, %rax
movq %r12, %rbx
movq 0xe8(%rsp), %rcx
subq %rcx, %rbx
cmpq %rcx, %rax
cmovleq %r15, %rbx
imulq $0x1c, %r12, %r13
addq %rbp, %r13
movq $-0x7fffffff, %rbp      # imm = 0x80000001
pushq $-0x1
popq %rax
movq %rax, 0x90(%rsp)
movq $0x0, 0x28(%rsp)
movq 0x30(%rsp), %r15
movq %r11, 0x58(%rsp)
cmpq %rbx, %r12
jl 0x190484
movl 0x8(%r13), %eax
leal 0x80(%rax), %edx
movl 0x4(%r14), %ecx
cmpl %ecx, %edx
jbe 0x190484
cmpl (%r15,%r12,4), %r9d
jo 0x1903ef
cmpl %ecx, 0x4(%r13)
ja 0x1903ef
cmpl 0x8(%r14), %eax
ja 0x1903ef
movl 0xc(%r13), %eax
movl 0x18(%r13), %r15d
shrdl $0x1f, %eax, %r15d
xorl $0x1, %r15d
movq %r14, %rdi
movq %r13, %rsi
xorl %edx, %edx
xorl %ecx, %ecx
xorl %r8d, %r8d
xorl %r9d, %r9d
callq 0x3d261
movq 0x60(%rsp), %rdi
movl 0x1c(%rsp), %esi
movl %r15d, %edx
movq 0x10(%rsp), %rcx
movsd 0x68(%rsp), %xmm0
movq %rax, %r8
callq 0x18e462
testq %rax, %rax
je 0x190401
movq 0x30(%rsp), %r15
movslq (%r15,%r12,4), %rax
movq 0x58(%rsp), %r11
addq %r11, %rax
cmpq $-0x80000000, %rax      # imm = 0x80000000
movl $0x0, %r9d
movq 0x70(%rsp), %r10
jne 0x190418
movq %rbp, %rax
decq %r12
addq $-0x1c, %r13
movq %rax, %rbp
jmp 0x190350
movq %rbp, %rax
movq 0x30(%rsp), %r15
xorl %r9d, %r9d
movq 0x70(%rsp), %r10
movq 0x58(%rsp), %r11
jmp 0x1903f2
cmpq %rbp, %rax
jle 0x19043c
xorl %ecx, %ecx
movq 0x28(%rsp), %rdx
testq %rdx, %rdx
setg %cl
subq %rcx, %rdx
movq %rdx, 0x28(%rsp)
movq %r12, 0x90(%rsp)
jmp 0x190463
movq 0x20(%rsp), %rax
movq 0x50(%rsp), %rcx
cmpq %rcx, (%rax,%r12,8)
jne 0x190460
movq 0x28(%rsp), %rax
cmpq 0xe0(%rsp), %rax
jge 0x190484
incq 0x28(%rsp)
movq %rbp, %rax
movq 0x48(%rsp), %rcx
movq (%rcx,%r12,8), %rcx
testq %rcx, %rcx
js 0x1903f2
movq 0x20(%rsp), %rdx
movq 0x50(%rsp), %rsi
movq %rsi, (%rdx,%rcx,8)
jmp 0x1903f2
testq %r10, %r10
movq 0xf0(%rsp), %r8
movq 0xa0(%rsp), %r13
js 0x1904b2
movl 0x8(%r14), %eax
imulq $0x1c, %r10, %rcx
movq 0x8(%rsp), %rdx
movl 0x8(%rdx,%rcx), %ecx
addq %r8, %rcx
cmpq %rax, %rcx
jge 0x1904f7
movq $-0x80000000, %rax      # imm = 0x80000000
movq %r13, %rcx
movq 0x88(%rsp), %rdx
pushq $-0x1
popq %r10
leaq 0x1(%rdx), %rsi
cmpq %rbx, %rsi
jle 0x1904f7
movl 0x8(%r14), %esi
movl (%rcx), %edi
addq %r8, %rdi
cmpq %rsi, %rdi
jl 0x1904f7
movslq (%r15,%rdx,4), %rsi
cmpq %rsi, %rax
cmovlq %rdx, %r10
cmovleq %rsi, %rax
decq %rdx
addq $-0x1c, %rcx
jmp 0x1904c8
testq %r10, %r10
js 0x1905ac
cmpq %r12, %r10
jge 0x1905ac
imulq $0x1c, %r10, %rsi
movq 0x8(%rsp), %rax
movl 0x8(%rax,%rsi), %eax
leal 0x80(%rax), %edx
movl 0x4(%r14), %ecx
cmpl %ecx, %edx
jbe 0x1905ac
addq 0x8(%rsp), %rsi
cmpl %ecx, 0x4(%rsi)
ja 0x1905ac
cmpl 0x8(%r14), %eax
ja 0x1905ac
cmpl (%r15,%r10,4), %r9d
jo 0x1905ac
movl 0xc(%rsi), %eax
movl 0x18(%rsi), %r15d
shrdl $0x1f, %eax, %r15d
xorl $0x1, %r15d
movq %r14, %rdi
xorl %edx, %edx
xorl %ecx, %ecx
xorl %r8d, %r8d
xorl %r9d, %r9d
movq %r10, %r12
callq 0x3d261
movq 0x60(%rsp), %rdi
movl 0x1c(%rsp), %esi
movl %r15d, %edx
movq 0x30(%rsp), %r15
movq 0x10(%rsp), %rcx
movsd 0x68(%rsp), %xmm0
movq %rax, %r8
callq 0x18e462
movq 0x58(%rsp), %r11
movq %r12, %r10
testq %rax, %rax
je 0x1905ac
movslq (%r15,%r10,4), %rcx
addq %r11, %rcx
cmpq $-0x80000000, %rcx      # imm = 0x80000000
je 0x1905ac
movq %r10, %rax
cmpq %rbp, %rcx
jg 0x190605
movq 0x90(%rsp), %rax
cmpq $-0x1, %rax
jne 0x190602
movq 0x110(%rsp), %rdx
cmpq $-0x1, %rdx
je 0x1905e1
movl 0xc(%r14), %ecx
xorl %eax, %eax
cmpq %rdx, %rcx
movq $-0x80000000, %rcx      # imm = 0x80000000
cmovneq %rcx, %rbp
sete %al
jmp 0x1905fa
movl 0x4(%r14), %ecx
xorl %eax, %eax
cmpq %rcx, 0x38(%rsp)
movq $-0x80000000, %rcx      # imm = 0x80000000
cmovlq %rcx, %rbp
setge %al
negl %eax
orq $-0x80000000, %rax      # imm = 0x80000000
movq %rbp, %rcx
cmpq $-0x7fffffff, %rcx      # imm = 0x80000001
cmovneq %rcx, %r11
movq 0x50(%rsp), %r12
movl %r11d, (%r15,%r12,4)
movq 0x48(%rsp), %rcx
movq %rax, (%rcx,%r12,8)
cmpq $-0x80000000, %r11      # imm = 0x80000000
jne 0x190632
movq 0x8(%rsp), %rbp
jmp 0x190695
movq 0x118(%rsp), %rcx
cmpq $-0x1, %rcx
je 0x190650
movl 0xc(%r14), %eax
cmpq %rcx, %rax
movq 0x8(%rsp), %rbp
je 0x190668
jmp 0x190695
movl 0x8(%r14), %eax
addq 0x10(%rsp), %rax
cmpq 0x100(%rsp), %rax
movq 0x8(%rsp), %rbp
jl 0x190695
movq 0x78(%rsp), %rax
cmpq %rax, %r11
cmovgq %r11, %rax
movq %rax, 0x78(%rsp)
movq 0x40(%rsp), %rax
cmovgeq %r12, %rax
movq %rax, 0x40(%rsp)
testq %r10, %r10
js 0x190692
cmpl %r11d, (%r15,%r10,4)
jge 0x190695
movq %r12, %r10
incq %r12
incq 0x88(%rsp)
addq $0x1c, %r13
jmp 0x190259
movq 0x40(%rsp), %rdx
cmpq $-0x80000000, %rdx      # imm = 0x80000000
jne 0x1906cb
xorl %eax, %eax
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
xorl %eax, %eax
movq 0x20(%rsp), %rdi
movq 0x48(%rsp), %rcx
testq %rdx, %rdx
js 0x1906e9
movq %rdx, (%rdi,%rax,8)
incq %rax
movq (%rcx,%rdx,8), %rdx
jmp 0x1906d7
movq %rbp, %rcx
movq %rax, %rdx
subq $0x1, %rdx
jb 0x1906b9
imulq $0x1c, (%rdi,%rdx,8), %rsi
movupd (%rbp,%rsi), %xmm0
movups 0xc(%rbp,%rsi), %xmm1
movups %xmm1, 0xc(%rcx)
movupd %xmm0, (%rcx)
addq $0x1c, %rcx
jmp 0x1906ef