// File: chhylp123[P]hifiasm/Hash_Table.cpp
// Function: quick_ck_lchain(k_mer_hit*, long, long, long, double, double, double, long*, long*, int*, int*, long*, long*, long*, long*, long*, long*)
void quick_ck_lchain(k_mer_hit* a, int64_t a_n, int64_t xl, int64_t yl, double chn_pen_gap, double chn_pen_skip, double bw_rate, 
int64_t *p, int64_t *t, int32_t *f, int32_t *ii, int64_t *plus, int64_t *msc, int64_t *msc_i, int64_t *movl, int64_t *si, int64_t *ei)
{
    if(a_n <= 0) return;
    int64_t l, k, is_srt = 1, z; k_mer_hit *ai, *aj;
    int64_t dq, dr, dd, dg, q_span, sc, csc, ddt; 
    int64_t plus0, msc0, msc_i0, movl0; double lin_pen, a_pen;

    *plus = 0; *msc = *msc_i = INT32_MIN; *movl = INT32_MAX; *si = 0; *ei = a_n; 

    for (k = 1, l = 0; k <= a_n; k++) {
        if(k == a_n || a[k].strand != a[l].strand) {
            t[k-1] = 0; ii[k-1] = 0;
            // if(a_n && a[0].readID == 3125488) {
            //     fprintf(stderr, "[M::%s::] ii::[%ld,%ld)(%c), is_srt::%ld, chn_pen_gap::%f, chn_pen_skip::%f, bw_rate::%f\n", __func__, l, k, "+-"[a[l].strand], is_srt, chn_pen_gap, chn_pen_skip, bw_rate);
            // }
            if(is_srt) {
                plus0 = 0; msc0 = msc_i0 = INT32_MIN; movl0 = INT32_MAX; ddt = 0;


                p[l] = -1; f[l] = a[l].cnt&(0xffu);
                if(f[l] >= msc0) {msc0 = f[l]; msc_i0 = l;}///difference
                if(f[l] < plus0) plus0 = f[l];


                for (z = l + 1; z < k; z++) {
                    ///roughly same to comput_sc_ch(&a[z], &a[z-1])
                    ai = &a[z]; aj = &a[z-1];
                    dq = (int64_t)(ai->self_offset) - (int64_t)(aj->self_offset);
                    if(dq <= 0) break;
                    dr = (int64_t)(ai->offset) - (int64_t)(aj->offset);
                    if(dr <= 0) break;
                    dd = dr > dq? dr - dq : dq - dr;//gap
                    // if(a_n && a[0].readID == 3125488) {
                    //     fprintf(stderr, "%ld,", dd);
                    // }
                    if((dd > 16) && (dd > cal_bw(&(a[z]), &(a[z-1]), bw_rate, xl, yl))) break;
                    dg = dr < dq? dr : dq;//len
                    q_span = ai->cnt&(0xffu); 
                    sc = q_span < dg? q_span : dg;
                    sc = normal_w(sc, ((int32_t)(ai->cnt>>8)));
                    if (dd || (dg > q_span && dg > 0)) {
                        lin_pen = (chn_pen_gap*(double)dd);
                        a_pen = ((double)(sc))*((((double)dd)/((double)dg))/bw_rate);
                        ///for long gap
                        // if(lin_pen > a_pen) lin_pen = a_pen;
                        if(dd < 4) lin_pen = ((lin_pen > a_pen)?(a_pen):(lin_pen));
                        else lin_pen = ((lin_pen < a_pen)?(a_pen):(lin_pen));
                        lin_pen += (chn_pen_skip*(double)dg);
                        sc -= (int32_t)lin_pen;
                    }

                    sc += f[z-1]; csc = a[z].cnt&(0xffu); if(sc < csc) break;
                    p[z] = z - 1; f[z] = sc; ddt += dd; 

                    if(f[z] >= msc0) {msc0 = f[z]; msc_i0 = z;}///difference
                    if(f[z] < plus0) plus0 = f[z];
                }

                // if(a_n && a[0].readID == 3125488) {
                //     fprintf(stderr, "\n");
                //     fprintf(stderr, "[M::%s::] msc0::%ld, msc_i0::%ld, (%c)\n", __func__, msc0, msc_i0, "+-"[a[l].strand]);
                // }
                if((z >= k) && (msc_i0 == (k - 1))) {
                    if((k - l >= 2) && (ddt > 16) && (ddt > cal_bw(&(a[k-1]), &(a[l]), bw_rate, xl, yl))) msc_i0 = INT32_MIN;
                    if(msc_i0 == (k - 1)) {
                        if(msc0 >= (*msc)) {
                            movl0 = get_chainLen(a[msc_i0].self_offset, a[msc_i0].self_offset, xl, a[msc_i0].offset, a[msc_i0].offset, yl);
                            if(msc0 > (*msc) || movl0 < (*movl)) {
                                *msc = msc0; *msc_i = msc_i0; *movl = movl0;
                            }
                        }
                        if(plus0 < (*plus)) *plus = plus0;
                        if((*ei) > k) {
                            (*si) = k;
                        } else {
                            (*ei) = l;
                        }
                    }
                }
            }
            l = k; is_srt = 1;
        } else {
            if((a[k].self_offset <= a[k-1].self_offset) || (a[k].offset <= a[k-1].offset)) is_srt = 0;
            t[k-1] = 0; ii[k-1] = 0;
        }
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x130, %rsp            # imm = 0x130
movq 0x48(%rbp), %rax
movq 0x40(%rbp), %rax
movq 0x38(%rbp), %rax
movq 0x30(%rbp), %rax
movq 0x28(%rbp), %rax
movq 0x20(%rbp), %rax
movq 0x18(%rbp), %rax
movq 0x10(%rbp), %rax
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movsd %xmm0, -0x28(%rbp)
movsd %xmm1, -0x30(%rbp)
movsd %xmm2, -0x38(%rbp)
movq %r8, -0x40(%rbp)
movq %r9, -0x48(%rbp)
cmpq $0x0, -0x10(%rbp)
jg 0x26d6e
jmp 0x275db
movq $0x1, -0x60(%rbp)
movq 0x20(%rbp), %rax
movq $0x0, (%rax)
movq 0x30(%rbp), %rax
movq $-0x80000000, (%rax)    # imm = 0x80000000
movq 0x28(%rbp), %rax
movq $-0x80000000, (%rax)    # imm = 0x80000000
movq 0x38(%rbp), %rax
movq $0x7fffffff, (%rax)     # imm = 0x7FFFFFFF
movq 0x40(%rbp), %rax
movq $0x0, (%rax)
movq -0x10(%rbp), %rcx
movq 0x48(%rbp), %rax
movq %rcx, (%rax)
movq $0x1, -0x58(%rbp)
movq $0x0, -0x50(%rbp)
movq -0x58(%rbp), %rax
cmpq -0x10(%rbp), %rax
jg 0x275db
movq -0x58(%rbp), %rax
cmpq -0x10(%rbp), %rax
je 0x26e10
movq -0x8(%rbp), %rax
movq -0x58(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl (%rax), %eax
shrl $0x1f, %eax
movq -0x8(%rbp), %rcx
movq -0x50(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rcx
movl (%rcx), %ecx
shrl $0x1f, %ecx
cmpl %ecx, %eax
je 0x27545
movq -0x48(%rbp), %rax
movq -0x58(%rbp), %rcx
subq $0x1, %rcx
movq $0x0, (%rax,%rcx,8)
movq 0x18(%rbp), %rax
movq -0x58(%rbp), %rcx
subq $0x1, %rcx
movl $0x0, (%rax,%rcx,4)
cmpq $0x0, -0x60(%rbp)
je 0x27530
movq $0x0, -0xc0(%rbp)
movq $-0x80000000, -0xd0(%rbp) # imm = 0x80000000
movq $-0x80000000, -0xc8(%rbp) # imm = 0x80000000
movq $0x7fffffff, -0xd8(%rbp) # imm = 0x7FFFFFFF
movq $0x0, -0xb8(%rbp)
movq -0x40(%rbp), %rax
movq -0x50(%rbp), %rcx
movq $-0x1, (%rax,%rcx,8)
movq -0x8(%rbp), %rax
movq -0x50(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0xc(%rax), %edx
andl $0xff, %edx
movq 0x10(%rbp), %rax
movq -0x50(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movq 0x10(%rbp), %rax
movq -0x50(%rbp), %rcx
movslq (%rax,%rcx,4), %rax
cmpq -0xc8(%rbp), %rax
jl 0x26edf
movq 0x10(%rbp), %rax
movq -0x50(%rbp), %rcx
movslq (%rax,%rcx,4), %rax
movq %rax, -0xc8(%rbp)
movq -0x50(%rbp), %rax
movq %rax, -0xd0(%rbp)
movq 0x10(%rbp), %rax
movq -0x50(%rbp), %rcx
movslq (%rax,%rcx,4), %rax
cmpq -0xc0(%rbp), %rax
jge 0x26f07
movq 0x10(%rbp), %rax
movq -0x50(%rbp), %rcx
movslq (%rax,%rcx,4), %rax
movq %rax, -0xc0(%rbp)
movq -0x50(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x68(%rbp)
movq -0x68(%rbp), %rax
cmpq -0x58(%rbp), %rax
jge 0x27362
movq -0x8(%rbp), %rax
movq -0x68(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq %rax, -0x70(%rbp)
movq -0x8(%rbp), %rax
movq -0x68(%rbp), %rcx
subq $0x1, %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movq %rax, -0x78(%rbp)
movq -0x70(%rbp), %rax
movl 0x8(%rax), %eax
movq -0x78(%rbp), %rcx
movl 0x8(%rcx), %ecx
subq %rcx, %rax
movq %rax, -0x80(%rbp)
cmpq $0x0, -0x80(%rbp)
jg 0x26f6c
jmp 0x27362
movq -0x70(%rbp), %rax
movl 0x4(%rax), %eax
movq -0x78(%rbp), %rcx
movl 0x4(%rcx), %ecx
subq %rcx, %rax
movq %rax, -0x88(%rbp)
cmpq $0x0, -0x88(%rbp)
jg 0x26f93
jmp 0x27362
movq -0x88(%rbp), %rax
cmpq -0x80(%rbp), %rax
jle 0x26fb4
movq -0x88(%rbp), %rax
subq -0x80(%rbp), %rax
movq %rax, -0xf0(%rbp)
jmp 0x26fc6
movq -0x80(%rbp), %rax
subq -0x88(%rbp), %rax
movq %rax, -0xf0(%rbp)
movq -0xf0(%rbp), %rax
movq %rax, -0x90(%rbp)
cmpq $0x10, -0x90(%rbp)
jle 0x27036
movq -0x90(%rbp), %rax
movq %rax, -0xf8(%rbp)
movq -0x8(%rbp), %rdi
movq -0x68(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rdi
movq -0x8(%rbp), %rsi
movq -0x68(%rbp), %rax
subq $0x1, %rax
shlq $0x4, %rax
addq %rax, %rsi
movsd -0x38(%rbp), %xmm0
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rcx
callq 0x2b2f0
movl %eax, %ecx
movq -0xf8(%rbp), %rax
movslq %ecx, %rcx
cmpq %rcx, %rax
jle 0x27036
jmp 0x27362
movq -0x88(%rbp), %rax
cmpq -0x80(%rbp), %rax
jge 0x27053
movq -0x88(%rbp), %rax
movq %rax, -0x100(%rbp)
jmp 0x2705e
movq -0x80(%rbp), %rax
movq %rax, -0x100(%rbp)
movq -0x100(%rbp), %rax
movq %rax, -0x98(%rbp)
movq -0x70(%rbp), %rax
movl 0xc(%rax), %eax
andl $0xff, %eax
movl %eax, %eax
movq %rax, -0xa0(%rbp)
movq -0xa0(%rbp), %rax
cmpq -0x98(%rbp), %rax
jge 0x270a1
movq -0xa0(%rbp), %rax
movq %rax, -0x108(%rbp)
jmp 0x270af
movq -0x98(%rbp), %rax
movq %rax, -0x108(%rbp)
movq -0x108(%rbp), %rax
movq %rax, -0xa8(%rbp)
movq -0xa8(%rbp), %rax
movq -0x70(%rbp), %rcx
movl 0xc(%rcx), %ecx
shrl $0x8, %ecx
movslq %ecx, %rcx
cmpq %rcx, %rax
jl 0x270f8
movq -0xa8(%rbp), %rax
movq -0x70(%rbp), %rcx
movl 0xc(%rcx), %ecx
shrl $0x8, %ecx
movslq %ecx, %rcx
cqto
idivq %rcx
movq %rax, -0x110(%rbp)
jmp 0x27106
movl $0x1, %eax
movq %rax, -0x110(%rbp)
jmp 0x27106
movq -0x110(%rbp), %rax
movq %rax, -0xa8(%rbp)
cmpq $0x0, -0x90(%rbp)
jne 0x27140
movq -0x98(%rbp), %rax
cmpq -0xa0(%rbp), %rax
jle 0x27264
cmpq $0x0, -0x98(%rbp)
jle 0x27264
movsd -0x28(%rbp), %xmm0
cvtsi2sdq -0x90(%rbp), %xmm1
mulsd %xmm1, %xmm0
movsd %xmm0, -0xe0(%rbp)
cvtsi2sdq -0xa8(%rbp), %xmm0
cvtsi2sdq -0x90(%rbp), %xmm1
cvtsi2sdq -0x98(%rbp), %xmm2
divsd %xmm2, %xmm1
divsd -0x38(%rbp), %xmm1
mulsd %xmm1, %xmm0
movsd %xmm0, -0xe8(%rbp)
cmpq $0x4, -0x90(%rbp)
jge 0x271da
movsd -0xe0(%rbp), %xmm0
ucomisd -0xe8(%rbp), %xmm0
jbe 0x271b8
movsd -0xe8(%rbp), %xmm0
movsd %xmm0, -0x118(%rbp)
jmp 0x271c8
movsd -0xe0(%rbp), %xmm0
movsd %xmm0, -0x118(%rbp)
movsd -0x118(%rbp), %xmm0
movsd %xmm0, -0xe0(%rbp)
jmp 0x27222
movsd -0xe0(%rbp), %xmm1
movsd -0xe8(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x27202
movsd -0xe8(%rbp), %xmm0
movsd %xmm0, -0x120(%rbp)
jmp 0x27212
movsd -0xe0(%rbp), %xmm0
movsd %xmm0, -0x120(%rbp)
movsd -0x120(%rbp), %xmm0
movsd %xmm0, -0xe0(%rbp)
movsd -0x30(%rbp), %xmm0
cvtsi2sdq -0x98(%rbp), %xmm2
movsd -0xe0(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0xe0(%rbp)
cvttsd2si -0xe0(%rbp), %eax
movslq %eax, %rcx
movq -0xa8(%rbp), %rax
subq %rcx, %rax
movq %rax, -0xa8(%rbp)
movq 0x10(%rbp), %rax
movq -0x68(%rbp), %rcx
subq $0x1, %rcx
movslq (%rax,%rcx,4), %rax
addq -0xa8(%rbp), %rax
movq %rax, -0xa8(%rbp)
movq -0x8(%rbp), %rax
movq -0x68(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0xc(%rax), %eax
andl $0xff, %eax
movl %eax, %eax
movq %rax, -0xb0(%rbp)
movq -0xa8(%rbp), %rax
cmpq -0xb0(%rbp), %rax
jge 0x272b7
jmp 0x27362
movq -0x68(%rbp), %rdx
subq $0x1, %rdx
movq -0x40(%rbp), %rax
movq -0x68(%rbp), %rcx
movq %rdx, (%rax,%rcx,8)
movq -0xa8(%rbp), %rax
movl %eax, %edx
movq 0x10(%rbp), %rax
movq -0x68(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movq -0x90(%rbp), %rax
addq -0xb8(%rbp), %rax
movq %rax, -0xb8(%rbp)
movq 0x10(%rbp), %rax
movq -0x68(%rbp), %rcx
movslq (%rax,%rcx,4), %rax
cmpq -0xc8(%rbp), %rax
jl 0x27327
movq 0x10(%rbp), %rax
movq -0x68(%rbp), %rcx
movslq (%rax,%rcx,4), %rax
movq %rax, -0xc8(%rbp)
movq -0x68(%rbp), %rax
movq %rax, -0xd0(%rbp)
movq 0x10(%rbp), %rax
movq -0x68(%rbp), %rcx
movslq (%rax,%rcx,4), %rax
cmpq -0xc0(%rbp), %rax
jge 0x2734f
movq 0x10(%rbp), %rax
movq -0x68(%rbp), %rcx
movslq (%rax,%rcx,4), %rax
movq %rax, -0xc0(%rbp)
jmp 0x27351
movq -0x68(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x68(%rbp)
jmp 0x26f13
movq -0x68(%rbp), %rax
cmpq -0x58(%rbp), %rax
jl 0x2752e
movq -0xd0(%rbp), %rax
movq -0x58(%rbp), %rcx
subq $0x1, %rcx
cmpq %rcx, %rax
jne 0x2752e
movq -0x58(%rbp), %rax
subq -0x50(%rbp), %rax
cmpq $0x2, %rax
jl 0x273fe
cmpq $0x10, -0xb8(%rbp)
jle 0x273fe
movq -0xb8(%rbp), %rax
movq %rax, -0x128(%rbp)
movq -0x8(%rbp), %rdi
movq -0x58(%rbp), %rax
subq $0x1, %rax
shlq $0x4, %rax
addq %rax, %rdi
movq -0x8(%rbp), %rsi
movq -0x50(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rsi
movsd -0x38(%rbp), %xmm0
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rcx
callq 0x2b2f0
movl %eax, %ecx
movq -0x128(%rbp), %rax
movslq %ecx, %rcx
cmpq %rcx, %rax
jle 0x273fe
movq $-0x80000000, -0xd0(%rbp) # imm = 0x80000000
movq -0xd0(%rbp), %rax
movq -0x58(%rbp), %rcx
subq $0x1, %rcx
cmpq %rcx, %rax
jne 0x2752c
movq -0xc8(%rbp), %rax
movq 0x28(%rbp), %rcx
cmpq (%rcx), %rax
jl 0x274e7
movq -0x8(%rbp), %rax
movq -0xd0(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x8(%rax), %eax
movl %eax, %edi
movq -0x8(%rbp), %rax
movq -0xd0(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x8(%rax), %eax
movl %eax, %esi
movq -0x18(%rbp), %rdx
movq -0x8(%rbp), %rax
movq -0xd0(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x4(%rax), %eax
movl %eax, %ecx
movq -0x8(%rbp), %rax
movq -0xd0(%rbp), %r8
shlq $0x4, %r8
addq %r8, %rax
movl 0x4(%rax), %eax
movl %eax, %r8d
movq -0x20(%rbp), %r9
callq 0x21580
movq %rax, -0xd8(%rbp)
movq -0xc8(%rbp), %rax
movq 0x28(%rbp), %rcx
cmpq (%rcx), %rax
jg 0x274bb
movq -0xd8(%rbp), %rax
movq 0x38(%rbp), %rcx
cmpq (%rcx), %rax
jge 0x274e5
movq -0xc8(%rbp), %rcx
movq 0x28(%rbp), %rax
movq %rcx, (%rax)
movq -0xd0(%rbp), %rcx
movq 0x30(%rbp), %rax
movq %rcx, (%rax)
movq -0xd8(%rbp), %rcx
movq 0x38(%rbp), %rax
movq %rcx, (%rax)
jmp 0x274e7
movq -0xc0(%rbp), %rax
movq 0x20(%rbp), %rcx
cmpq (%rcx), %rax
jge 0x27505
movq -0xc0(%rbp), %rcx
movq 0x20(%rbp), %rax
movq %rcx, (%rax)
movq 0x48(%rbp), %rax
movq (%rax), %rax
cmpq -0x58(%rbp), %rax
jle 0x2751f
movq -0x58(%rbp), %rcx
movq 0x40(%rbp), %rax
movq %rcx, (%rax)
jmp 0x2752a
movq -0x50(%rbp), %rcx
movq 0x48(%rbp), %rax
movq %rcx, (%rax)
jmp 0x2752c
jmp 0x2752e
jmp 0x27530
movq -0x58(%rbp), %rax
movq %rax, -0x50(%rbp)
movq $0x1, -0x60(%rbp)
jmp 0x275c8
movq -0x8(%rbp), %rax
movq -0x58(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x8(%rax), %eax
movq -0x8(%rbp), %rcx
movq -0x58(%rbp), %rdx
subq $0x1, %rdx
shlq $0x4, %rdx
addq %rdx, %rcx
cmpl 0x8(%rcx), %eax
jbe 0x27599
movq -0x8(%rbp), %rax
movq -0x58(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x4(%rax), %eax
movq -0x8(%rbp), %rcx
movq -0x58(%rbp), %rdx
subq $0x1, %rdx
shlq $0x4, %rdx
addq %rdx, %rcx
cmpl 0x4(%rcx), %eax
ja 0x275a1
movq $0x0, -0x60(%rbp)
movq -0x48(%rbp), %rax
movq -0x58(%rbp), %rcx
subq $0x1, %rcx
movq $0x0, (%rax,%rcx,8)
movq 0x18(%rbp), %rax
movq -0x58(%rbp), %rcx
subq $0x1, %rcx
movl $0x0, (%rax,%rcx,4)
jmp 0x275ca
movq -0x58(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x58(%rbp)
jmp 0x26dc8
addq $0x130, %rsp            # imm = 0x130
popq %rbp
retq
nopw %cs:(%rax,%rax)