// File: /workspace/github_cpp_makefile_star2_O2/chhylp123[P]hifiasm/Correct.cpp
// Function: tuning_ext_offset(overlap_region*, k_mer_hit*, long, long, long, long, long, long, long*, long*, long*, long*, long*, long*, long*)
void tuning_ext_offset(overlap_region *z, k_mer_hit *ch_a, int64_t ch_n, int64_t ql, int64_t tl, int64_t wl, 
int64_t fusion_k_len, int64_t fusion_win_occ, int64_t *ch_s0, int64_t *ch_e0, int64_t *qs0, int64_t *qe0, int64_t *ts0, int64_t *te0, int64_t *mode)
{
    ///[qs, qe)
    if((*mode) != 1 && (*mode) != 2) return;
    int64_t qs = *qs0, qe = *qe0, ts = *ts0, te = *te0, ch_s = *ch_s0, ch_e = *ch_e0;
    int64_t ke, ks, p[3], we, ws, k, wid;
    int64_t sl, gq, gt, gl, gg, update, min_g = INT32_MAX, min_id = -1;
    adjust_ext_offset(&qs, &qe, &ts, &te, ql, tl, 0, *mode); p[0] = p[1] = p[2] = -1;
    if((*mode) == 1) {///forward extension
        //qs0 and ts0 are fixed; te0 = -1, qe0 is unreliable
        if(qe > (*qe0)) {
            ///find k-mer hit
            ke = ch_a[ch_s].self_offset;
            for (ch_e = ch_s; (ch_e < ch_n) && (ch_a[ch_e].self_offset < (*qe0)); ch_e++) {
                ke = ch_a[ch_e].self_offset;
            }
            for (ke += fusion_k_len; (ch_e < ch_n) && (ch_a[ch_e].self_offset < ke); ch_e++) {
                if(ch_a[ch_e].self_offset<(*qe0)) continue;
                if((ch_a[ch_e].offset<=(*ts0))||(ch_a[ch_e].self_offset<=(*qs0))) continue;//not co-linear
                if(is_pri_aln(ch_a[ch_e])) {
                    p[2] = ch_e; break;
                } else if(ch_a[ch_e].cnt > 1 && p[1] == -1) {
                    p[1] = ch_e;
                } else if(p[0] == -1) {
                    p[0] = ch_e;
                }
            }
            if(p[2] != -1) p[0] = p[2];
            else if(p[1] != -1) p[0] = p[1];
            if(p[0] != -1) {
                (*mode) = 0;///global
                (*qe0) = ch_a[p[0]].self_offset; (*te0) = ch_a[p[0]].offset; (*ch_e0) = p[0];
                return;
            }

            ///find aligned window
            we = (*qe0); we/=wl; we *= wl; we +=wl; we--; ///next window
            for (k = 0; we < qe && we <= z->x_pos_e && k < fusion_win_occ; we+=wl) {//[ws, we]; [qs, qe)
                wid = get_win_id_by_e(z, we, wl, NULL);
                if(z->w_list.a[wid].y_end == -1) continue;//unmapped
                if(z->w_list.a[wid].x_end < (*qs0)) continue;
                if(z->w_list.a[wid].y_end < (*ts0)) continue;
                sl = z->w_list.a[wid].x_end+1-z->w_list.a[wid].x_start;
                if(z->w_list.a[wid].error > (sl/A_L)) continue;
                gq = z->w_list.a[wid].x_end-(*qs0); 
                gt = z->w_list.a[wid].y_end-(*ts0); 
                gl = MIN(gq, gt); gl/=16; if(gl <= 0) gl = 1;
                gg = (gq>=gt)?(gq-gt):(gt-gq); gg /= gl;
                update = 0;
                if(min_g>gg) {
                    update = 1;
                } else if((min_g==gg)&&(z->w_list.a[min_id].error>z->w_list.a[wid].error)) {
                    update = 1;
                } 
                if(update) {
                    min_g = gg; min_id = wid;
                }
                k++;
            }
        }

        if(min_id != -1) {
            (*qe0) = z->w_list.a[min_id].x_end+1; 
            (*te0) = z->w_list.a[min_id].y_end+1; 
            (*mode) = 0;///global
        } else {
            (*qe0) = qe; (*te0) = te;//extension
        }
    } else if((*mode) == 2) {///backward extension
        //qe0 and te0 are fixed; ts0 = -1, qs0 is unreliable
        if(qs < (*qs0)) {
            ///find k-mer hit
            ks = ch_a[ch_e].self_offset;
            for (ch_s = ch_e; (ch_s >= 0) && (ch_a[ch_s].self_offset > (*qs0)); ch_s--) {
                ks = ch_a[ch_s].self_offset;
            }
            for (ks -= fusion_k_len; (ch_s >= 0) && (ch_a[ch_s].self_offset > ks); ch_s--) {
                if(ch_a[ch_s].self_offset>(*qs0)) continue;
                if((ch_a[ch_s].offset>=(*te0))||(ch_a[ch_s].self_offset>=(*qe0))) continue;//not co-linear
                if(is_pri_aln(ch_a[ch_s])) {
                    p[2] = ch_s; break;
                } else if(ch_a[ch_s].cnt > 1 && p[1] == -1) {
                    p[1] = ch_s;
                } else if(p[0] == -1) {
                    p[0] = ch_s;
                }
            }
            // fprintf(stderr, "-[M::%s::] utg%.6dl(%c), p[0]::%ld, p[1]::%ld, p[2]::%ld\n", 
            //             __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], p[0], p[1], p[2]);
            if(p[2] != -1) p[0] = p[2];
            else if(p[1] != -1) p[0] = p[1];
            if(p[0] != -1) {
                (*mode) = 0;///global
                (*qs0) = ch_a[p[0]].self_offset; (*ts0) = ch_a[p[0]].offset; (*ch_s0) = p[0];
                return;
            }

            ///find aligned window
            ws = (*qs0)-1; ws/=wl; ws*=wl; 
            for (k = 0; ws >= qs && ws >= z->x_pos_s && k < fusion_win_occ; ws-=wl) {//[ws, we]; [qs, qe)
                wid = get_win_id_by_s(z, ws, wl, NULL);
                if(z->w_list.a[wid].y_end == -1) continue;//unmapped
                if(z->w_list.a[wid].x_start >= (*qe0)) continue;
                if(z->w_list.a[wid].y_start >= (*te0)) continue;
                sl = z->w_list.a[wid].x_end+1-z->w_list.a[wid].x_start;
                if(z->w_list.a[wid].error > (sl/A_L)) continue;
                gq = (*qe0) - z->w_list.a[wid].x_start; 
                gt = (*te0) - z->w_list.a[wid].y_start; 
                gl = MIN(gq, gt); gl/=16; if(gl <= 0) gl = 1;
                gg = (gq>=gt)?(gq-gt):(gt-gq); gg /= gl;
                update = 0;
                if(min_g>gg) {
                    update = 1;
                } else if((min_g==gg)&&(z->w_list.a[min_id].error>z->w_list.a[wid].error)) {
                    update = 1;
                } 
                if(update) {
                    min_g = gg; min_id = wid;
                }
                k++;
            }
        }

        if(min_id != -1) {
            (*qs0) = z->w_list.a[min_id].x_start; 
            (*ts0) = z->w_list.a[min_id].y_start; 
            (*mode) = 0;///global
        } else {
            (*qs0) = qs; (*ts0) = ts; ///still extension
        }
    }

    if((*ch_e0) == -1) {
        for ((*ch_e0)=(*ch_s0);((*ch_e0)<ch_n)&&(ch_a[(*ch_e0)].self_offset>=(*qs0))&&(ch_a[(*ch_e0)].self_offset<=(*qe0)); (*ch_e0)++);
    }

    if((*ch_s0) == -1) {
        for ((*ch_s0)=(*ch_e0);((*ch_s0)>=0)&&(ch_a[(*ch_s0)].self_offset>=(*qs0))&&(ch_a[(*ch_s0)].self_offset<=(*qe0)); (*ch_s0)--);
        (*ch_s0)++;
    }
    ///boundry
    for (;((*ch_e0)<ch_n)&&(ch_a[(*ch_e0)].self_offset>=(*qs0))&&(ch_a[(*ch_e0)].self_offset<=(*qe0)); (*ch_e0)++);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %r9, 0x8(%rsp)
movq 0xc0(%rsp), %rax
movq (%rax), %r12
leaq -0x1(%r12), %rax
cmpq $0x1, %rax
ja 0x33178
movq %r8, %r9
movq %rcx, %r8
movq %rdx, %rbx
movq %rdi, (%rsp)
movq %rsi, 0x10(%rsp)
movq 0xb8(%rsp), %r14
movq 0xb0(%rsp), %rdx
movq 0xa8(%rsp), %rcx
movq 0xa0(%rsp), %rax
movq 0x98(%rsp), %r10
movq 0x90(%rsp), %r11
movq (%rax), %r13
leaq 0x40(%rsp), %rdi
movq %r13, (%rdi)
movq (%rcx), %rbp
leaq 0x38(%rsp), %rsi
movq %rbp, (%rsi)
movq (%rdx), %rax
leaq 0x30(%rsp), %rdx
movq %rax, 0x18(%rsp)
movq %rax, (%rdx)
movq (%r14), %rax
leaq 0x28(%rsp), %rcx
movq %rax, 0x20(%rsp)
movq %rax, (%rcx)
movq (%r11), %r14
movq (%r10), %r15
pushq %r12
pushq $0x0
callq 0x3023a
addq $0x10, %rsp
cmpq $0x1, %r12
jne 0x32b81
movq 0x38(%rsp), %r10
cmpq %rbp, %r10
movq 0x8(%rsp), %r12
jle 0x32edb
movq %r14, %rcx
movq %r14, %rax
shlq $0x4, %rax
movq 0x10(%rsp), %r11
leaq (%rax,%r11), %rdx
addq $0x8, %rdx
movl (%rdx), %eax
cmpq %rbx, %r14
cmovleq %rbx, %r14
cmpq %rbx, %rcx
jge 0x32bdc
movl (%rdx), %esi
cmpq %rsi, %rbp
jle 0x32bd9
incq %rcx
addq $0x10, %rdx
movq %rsi, %rax
jmp 0x32b69
movq 0x40(%rsp), %rdi
cmpq %r13, %rdi
movq 0x8(%rsp), %r12
jge 0x3305a
pushq $-0x1
popq %rax
movq %r15, %rcx
shlq $0x4, %rcx
movq 0x10(%rsp), %r9
leaq (%rcx,%r9), %rsi
addq $0x8, %rsi
movl (%rsi), %edx
cmpq $-0x1, %r15
movq %rax, %rcx
cmovlq %r15, %rcx
testq %r15, %r15
js 0x32cbd
movl (%rsi), %r8d
cmpq %r8, %r13
jge 0x32cba
decq %r15
addq $-0x10, %rsi
movq %r8, %rdx
jmp 0x32bb8
movq %rcx, %r14
addq 0x80(%rsp), %rax
movq %r14, %rcx
shlq $0x4, %rcx
leaq (%rcx,%r11), %rsi
addq $0xc, %rsi
pushq $-0x1
popq %rdx
movl $0x7fffffff, %edi       # imm = 0x7FFFFFFF
movq %rdx, %rcx
movq (%rsp), %r15
cmpq %rbx, %r14
jge 0x32c65
movl -0x4(%rsi), %r8d
cmpq %r8, %rax
jle 0x32c65
cmpq %r8, %rbp
jle 0x32c1e
incq %r14
addq $0x10, %rsi
jmp 0x32c02
cmpq %r8, %r13
jge 0x32c15
movl -0x8(%rsi), %r8d
cmpq %r8, 0x18(%rsp)
jge 0x32c15
movl -0xc(%rsi), %r8d
andl %edi, %r8d
cmpl %edi, %r8d
je 0x33133
movl (%rsi), %r9d
cmpl %r8d, %r9d
jae 0x33133
cmpl $0x2, %r9d
jb 0x32c5b
cmpq $-0x1, %rdx
jne 0x32c5b
movq %r14, %rdx
jmp 0x32c15
cmpq $-0x1, %rcx
cmoveq %r14, %rcx
jmp 0x32c15
cmpq $-0x1, %rdx
cmovneq %rdx, %rcx
cmpq $-0x1, %rcx
je 0x32d7b
movq 0xc0(%rsp), %rax
andq $0x0, (%rax)
movq %rcx, %rax
shlq $0x4, %rax
movl 0x8(%r11,%rax), %edx
movq 0xa8(%rsp), %rsi
movq %rdx, (%rsi)
movl 0x4(%r11,%rax), %eax
movq 0xb8(%rsp), %rdx
movq %rax, (%rdx)
movq 0x98(%rsp), %rax
movq %rcx, (%rax)
jmp 0x33178
movq %r15, %rcx
subq 0x80(%rsp), %rdx
movq %rcx, %rsi
shlq $0x4, %rsi
addq %rsi, %r9
addq $0xc, %r9
movl $0x7fffffff, %r10d      # imm = 0x7FFFFFFF
movq %rax, %rsi
movq (%rsp), %r15
testq %rcx, %rcx
js 0x32d4e
movl -0x4(%r9), %r11d
cmpq %r11, %rdx
jge 0x32d4e
cmpq %r11, %r13
jl 0x32d45
movl -0x8(%r9), %r14d
cmpq %r14, 0x20(%rsp)
setle %r8b
cmpq %r11, %rbp
setle %r15b
orb %r8b, %r15b
jne 0x32d41
movl -0xc(%r9), %r8d
andl %r10d, %r8d
cmpl %r10d, %r8d
je 0x33148
movl (%r9), %r15d
cmpl %r8d, %r15d
jae 0x33148
cmpl $0x2, %r15d
jb 0x32d39
cmpq $-0x1, %rax
jne 0x32d39
movq %rcx, %rax
jmp 0x32d41
cmpq $-0x1, %rsi
cmoveq %rcx, %rsi
movq (%rsp), %r15
decq %rcx
addq $-0x10, %r9
jmp 0x32ce0
cmpq $-0x1, %rax
cmovneq %rax, %rsi
cmpq $-0x1, %rsi
je 0x32f03
movq %rsi, %rax
shlq $0x4, %rax
movq 0x10(%rsp), %rcx
movl 0x4(%rcx,%rax), %r14d
movl 0x8(%rcx,%rax), %r11d
jmp 0x3314b
movq %rbp, %rax
cqto
idivq %r12
movq %rdx, %rcx
addq %r12, %rbp
notq %rcx
addq %rbp, %rcx
pushq $-0x1
popq %r11
movl $0x7fffffff, %ebp       # imm = 0x7FFFFFFF
xorl %r14d, %r14d
cmpq %r10, %rcx
jge 0x32e95
movl 0x8(%r15), %eax
cmpq %rax, %rcx
jg 0x32e95
cmpq 0x88(%rsp), %r14
jge 0x32e95
movl 0x4(%r15), %esi
movq %rsi, %rax
xorl %edx, %edx
idivq %r12
subq %rsi, %rdx
leaq (%rdx,%rcx), %rax
cqto
idivq %r12
movq 0x58(%r15), %r9
movq %rax, %rdx
shlq $0x5, %rdx
movslq 0xc(%r9,%rdx), %rdi
cmpq $-0x1, %rdi
je 0x32e25
movq %rax, %rsi
addq %r9, %rdx
movslq 0x4(%rdx), %rax
movq %rax, %r12
subq %r13, %r12
jl 0x32e20
subq 0x18(%rsp), %rdi
jl 0x32e20
subl (%rdx), %eax
incl %eax
movswl 0x14(%rdx), %r15d
cltd
pushq $0x10
popq %r8
idivl %r8d
cmpl %r15d, %eax
jge 0x32e2d
movq (%rsp), %r15
movq 0x8(%rsp), %r12
addq %r12, %rcx
jmp 0x32d9b
movq %r12, %r8
subq %rdi, %r8
cmovlq %r12, %rdi
movq %rdi, %rax
cqto
pushq $0x10
popq %rdi
idivq %rdi
movq %rax, %rdi
cmpq $0x2, %rax
jge 0x32e4e
pushq $0x1
popq %rdi
movq %r8, %rax
negq %rax
cmovsq %r8, %rax
xorl %edx, %edx
divq %rdi
cmpq %rax, %rbp
jle 0x32e73
movq %rax, %rbp
movq %rsi, %r11
movq (%rsp), %r15
movq 0x8(%rsp), %r12
jmp 0x32e90
movq 0x8(%rsp), %r12
jne 0x32e8c
movq %r11, %rax
shlq $0x5, %rax
cmpw %r15w, 0x14(%r9,%rax)
jle 0x32e8c
movq %rsi, %r11
movq (%rsp), %r15
incq %r14
jmp 0x32e25
cmpq $-0x1, %r11
je 0x32edb
movq (%rsp), %rax
movq 0x58(%rax), %rax
shlq $0x5, %r11
movslq 0x4(%rax,%r11), %rcx
incq %rcx
movq 0xa8(%rsp), %r9
movq %rcx, (%r9)
movslq 0xc(%rax,%r11), %rax
incq %rax
movq 0xb8(%rsp), %rcx
movq %rax, (%rcx)
movq 0xc0(%rsp), %rax
andq $0x0, (%rax)
jmp 0x32ef6
movq 0xa8(%rsp), %r9
movq %r10, (%r9)
movq 0x28(%rsp), %rax
movq 0xb8(%rsp), %rcx
movq %rax, (%rcx)
movq 0xa0(%rsp), %r8
jmp 0x3307d
decq %r13
movq %r13, %rax
cqto
idivq %r12
subq %rdx, %r13
pushq $-0x1
popq %r11
movl $0x7fffffff, %r9d       # imm = 0x7FFFFFFF
xorl %r10d, %r10d
cmpq %rdi, %r13
jl 0x3301b
movl 0x4(%r15), %ecx
cmpq %rcx, %r13
jl 0x3301b
cmpq 0x88(%rsp), %r10
jge 0x3301b
movq %rcx, %rax
xorl %edx, %edx
idivq %r12
subq %rcx, %rdx
leaq (%rdx,%r13), %rax
cqto
idivq %r12
movq 0x58(%r15), %r14
movq %rax, %rdx
shlq $0x5, %rdx
cmpl $-0x1, 0xc(%r14,%rdx)
je 0x32fab
addq %r14, %rdx
movslq (%rdx), %r8
movq %rbp, %r12
subq %r8, %r12
jle 0x32fa6
movq %rax, %rcx
movslq 0x8(%rdx), %rax
movq 0x20(%rsp), %rsi
subq %rax, %rsi
jle 0x32fa6
movl 0x4(%rdx), %eax
subl %r8d, %eax
incl %eax
movswl 0x14(%rdx), %r15d
cltd
pushq $0x10
popq %r8
idivl %r8d
cmpl %r15d, %eax
jge 0x32fb3
movq (%rsp), %r15
movq 0x8(%rsp), %r12
subq %r12, %r13
jmp 0x32f1e
movq %r12, %r8
subq %rsi, %r8
cmovlq %r12, %rsi
movq %rsi, %rax
cqto
pushq $0x10
popq %rsi
idivq %rsi
movq %rax, %rsi
cmpq $0x2, %rax
jge 0x32fd4
pushq $0x1
popq %rsi
movq %r8, %rax
negq %rax
cmovsq %r8, %rax
xorl %edx, %edx
divq %rsi
cmpq %rax, %r9
jle 0x32ff9
movq %rax, %r9
movq %rcx, %r11
movq (%rsp), %r15
movq 0x8(%rsp), %r12
jmp 0x33016
movq 0x8(%rsp), %r12
jne 0x33012
movq %r11, %rax
shlq $0x5, %rax
cmpw %r15w, 0x14(%r14,%rax)
jle 0x33012
movq %rcx, %r11
movq (%rsp), %r15
incq %r10
jmp 0x32fab
cmpq $-0x1, %r11
je 0x3305a
movq (%rsp), %rax
movq 0x58(%rax), %rax
shlq $0x5, %r11
movslq (%rax,%r11), %rcx
movq 0xa0(%rsp), %r8
movq %rcx, (%r8)
movslq 0x8(%rax,%r11), %rax
movq 0xb0(%rsp), %rcx
movq %rax, (%rcx)
movq 0xc0(%rsp), %rax
andq $0x0, (%rax)
jmp 0x33075
movq 0xa0(%rsp), %r8
movq %rdi, (%r8)
movq 0x30(%rsp), %rax
movq 0xb0(%rsp), %rcx
movq %rax, (%rcx)
movq 0xa8(%rsp), %r9
movq 0x90(%rsp), %r11
movq 0x98(%rsp), %rdi
movq (%rdi), %rax
cmpq $-0x1, %rax
movq 0x10(%rsp), %r10
je 0x330cc
cmpq $-0x1, (%r11)
jne 0x33108
movq %rax, %rcx
shlq $0x4, %rcx
addq %r10, %rcx
addq $0x8, %rcx
movq %rax, (%r11)
testq %rax, %rax
js 0x330ff
movl (%rcx), %edx
cmpq %rdx, (%r8)
jg 0x330ff
cmpq %rdx, (%r9)
jl 0x330ff
decq %rax
addq $-0x10, %rcx
jmp 0x330af
movq (%r11), %rdx
movq %rdx, %rax
shlq $0x4, %rax
leaq (%rax,%r10), %rcx
addq $0x8, %rcx
movq %rdx, %rax
movq %rdx, (%rdi)
cmpq %rbx, %rdx
jge 0x3309b
movl (%rcx), %esi
cmpq %rsi, (%r8)
jg 0x3309b
leaq 0x1(%rax), %rdx
addq $0x10, %rcx
cmpq %rsi, (%r9)
jge 0x330de
jmp 0x3309b
incq %rax
movq %rax, (%r11)
movq (%rdi), %rax
movq %rax, %rcx
shlq $0x4, %rcx
addq %r10, %rcx
addq $0x8, %rcx
cmpq %rbx, %rax
jge 0x33178
movl (%rcx), %edx
cmpq %rdx, (%r8)
jg 0x33178
cmpq %rdx, (%r9)
jl 0x33178
incq %rax
movq %rax, (%rdi)
addq $0x10, %rcx
jmp 0x33116
cmpq $-0x1, %rdx
cmovneq %rdx, %rcx
cmpq $-0x1, %r14
cmovneq %r14, %rcx
jmp 0x32c6d
movq %rcx, %rsi
movq 0xc0(%rsp), %rax
andq $0x0, (%rax)
movq 0xa0(%rsp), %rax
movq %r11, (%rax)
movq 0xb0(%rsp), %rax
movq %r14, (%rax)
movq 0x90(%rsp), %rax
movq %rsi, (%rax)
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq