// File: chhylp123[P]hifiasm/inter.cpp
// Function: mg_gchain1_dp(void*, ma_ug_t const*, asg_t const*, int*, mg_lchain_t*, int, int, int, int, int, int, float, float, int, ug_opt_t const*, mg128_t const*, unsigned long**)
int32_t mg_gchain1_dp(void *km, const ma_ug_t *ug, const asg_t *rg, int32_t *n_lc_, mg_lchain_t *lc, int32_t qlen, int32_t max_dist_g, int32_t max_dist_q, int32_t bw, int32_t max_skip,
                      int32_t ref_bonus, float chn_pen_gap, float mask_level, int32_t max_gc_seq_ext, const ug_opt_t *uopt, const mg128_t *an, uint64_t **u_)
{
    int32_t i, j, k, m_dst, n_dst, n_ext, n_u, n_v, n_lc = *n_lc_, rrs, rre;
    int32_t *f, *v, *t, li_qs, li_qe, li_rs, li_re, lj_qs, lj_qe, lj_rs, lj_re;
    int64_t *p;
    uint64_t *u;
    mg_path_dst_t *dst;
    gc_frag_t *a;
    mg_lchain_t *swap;
    // char *qs;
    asg_t *g = ug->g;

    *u_ = 0;
    if (n_lc == 0) return 0;

	// extend_lchain(lc, n_lc, qlen, ug);
    KMALLOC(km, a, n_lc);
    ///n_lc how many linear chains; just filter some linear chains
    for (i = n_ext = 0; i < n_lc; ++i) { // a[] is a view of frag[]; for sorting
        mg_lchain_t *r = &lc[i];
        gc_frag_t *ai = &a[i];
        int32_t is_isolated = 0, min_end_dist_g;
		transfor_coord(r, qlen, ug->u.a[r->v>>1].len, NULL, NULL, &rrs, &rre);
        r->dist_pre = -1;///indicate parent in graph chain
        min_end_dist_g = g->seq[r->v>>1].len - rre;///r->v: ref_id|rev
        if (rrs < min_end_dist_g) min_end_dist_g = rrs;
        if (min_end_dist_g > max_dist_g) is_isolated = 1; // if too far from segment ends
        else if (min_end_dist_g>>3 > r->score) is_isolated = 1; // if the lchain too small relative to distance to the segment ends
        ai->srt = (uint32_t)is_isolated<<31 | r->qe;
        ai->i = i;
        if (!is_isolated) ++n_ext;
    }
    ///if the alignment is too far from segment ends, which means it cannot contribute to graph alignment
    if (n_ext < 2) { // no graph chaining needed; early return
        kfree(km, a);
        KMALLOC(km, u, n_lc);
        for (i = 0; i < n_lc; ++i)
            u[i] = (uint64_t)lc[i].score<<32 | 1;
        *u_ = u;
		// compress_lchain(lc, n_lc, qlen, ug, an);
        return n_lc;
    }
    radix_sort_gc(a, a + n_lc);///sort by: is_isolated(1):qe

    KMALLOC(km, v, n_lc);
    KMALLOC(km, f, n_ext);
    KMALLOC(km, p, n_ext);
    KCALLOC(km, t, n_ext);
    // KMALLOC(km, qs, max_dist_q + 1);//for 

    m_dst = n_dst = 0, dst = 0;
    ///n_ext is number of linear chains that might be included in graph chains
    ///sorted by the positions in query; sorted by qe of each chain
    for (i = 0; i < n_ext; ++i) { // core loop
        gc_frag_t *ai = &a[i];
        mg_lchain_t *li = &lc[ai->i];///linear chain; sorted by qe, i.e. end position in query
		int32_t mm_ovlp = max_ovlp(ug->g, li->v^1);
		transfor_coord(li, qlen, ug->u.a[li->v>>1].len, &li_qs, &li_qe, &li_rs, &li_re);
        ///note segi is query id, instead of ref id; it is not such useful
        /**
         * a[].x: idx_in_minimizer_arr(32)r_pos(32)
         * a[].y: weight(8)query_id(8)flag(8)span(8)q_pos(32)
        **/
        { // collect end points potentially reachable from _i_
            int32_t x = li->qs + bw + mm_ovlp, n_skip = 0;
            if (x > qlen) x = qlen;
            ///collect alignments that can be reachable from the left side
            ///that is, a[x].qe <= x
            x = find_max(i, a, x);
            n_dst = 0;
            for (j = x; j >= 0; --j) { // collect potential destination vertices
                gc_frag_t *aj = &a[j];
                //potential chains that might be overlapped with the left side of li
                mg_lchain_t *lj = &lc[aj->i];
                mg_path_dst_t *q;
                int32_t target_dist, dq/**, so = specific_ovlp(ug, uopt, li->v^1, lj->v^1)**/;
				transfor_coord(lj, qlen, ug->u.a[lj->v>>1].len, &lj_qs, &lj_qe, &lj_rs, &lj_re);
                ///lj->qs >= li->qs && lj->qe <= li->qs, so lj is contained
                if (lj->qs >= li->qs) continue; // lj is contained in li on the query coordinate
				/**
				  * doesn't work for overlap graph
                if (lj_qe > li_qs) { // test overlap on the query
                    int o = lj_qe - li_qs - so;///get_lchain_ovlp(lj, li, ug->g, qlen, ug); 
					///mask_level = 0.5, if overlap is too long
                    ///note here is the overlap in query, so too long overlaps might be wrong
                    if (o > (lj->qe - lj->qs) * mask_level || o > (li->qe - li->qs) * mask_level)
                        continue;
                }
				**/
                dq = li_qs - lj_qe;///dq might be smaller than 0
                if (dq > max_dist_q) break; // if query gap too large, stop
                ///The above filter chains like:
                ///1. lj is contained in li
                ///2. the overlap between li and lj is too large
                ///3. li and lj are too far
                ///above we have checked gap/overlap in query 
                ///then we need to check gap/overlap in reference
                if (li->v != lj->v) { // the two linear chains are on two different refs
                    // minimal graph gap; the real graph gap might be larger
                    int32_t min_dist = li_rs + (g->seq[lj->v>>1].len - lj_re); 
                    if (min_dist > max_dist_g) continue; // graph gap too large
                    //note here min_dist - (lj->qs - li->qe) > bw is important
                    //min_dist is always larger than 0, (lj->qs - li->qe) might be negative 
					/**
				  	  * doesn't work for overlap graph
					min_dist -= so;
					if (min_dist - bw > li->qs - lj->qe) continue; ///note seg* is the query id, instead of ref id
					**/
					target_dist = mg_target_dist(g, lj, li);
                    if (target_dist < 0) continue; // this may happen if the query overlap is far too large
                } else if (lj->rs >= li->rs || lj->re >= li->re) { // not colinear
                    continue;
                } else {///li->v == lj->v and colinear; at the same ref id
                    ///w is indel, w is always positive
                    int32_t dr = li->rs - lj->re, dq = li->qs - lj->qe, w = dr > dq? dr - dq : dq - dr;
                    ///note that l*->v is the ref id, while seg* is the query id
                    if (w > bw) continue; // test bandwidth
                    if (dr > max_dist_g || dr < -max_dist_g) continue;
                    if (lj->re > li->rs) { // test overlap on the graph segment
                        int o = lj->re - li->rs;
                        if (o > (lj->re - lj->rs) * mask_level || o > (li->re - li->rs) * mask_level)
                            continue;
                    }
                    target_dist = mg_target_dist(g, lj, li);
                }
                if (n_dst == m_dst) KEXPAND(km, dst, m_dst); // TODO: watch out the quadratic behavior!
                q = &dst[n_dst++];///q saves information for i->j
                memset(q, 0, sizeof(mg_path_dst_t));
                ///note v is (rid:rev), so two alignment chains might be at the same ref id with different directions
                q->inner = (li->v == lj->v);
                q->v = lj->v^1;///must be v^1 instead of v
                q->meta = j;
                q->qlen = li->qs - lj->qe;///might be negative
				/**
				  * doesn't work for overlap graph
				q->so = 0;
				if(li->v != lj->v && lj->qe > li->qs) {
					lj_qe = lj->qe; li_qs = li->qs + g->seq[lj->v>>1].len - so;
					q->so = lj_qe - li_qs;
					if(q->so < 0) q->so = 0;
				}
				**/
                q->target_dist = target_dist;///cannot understand the target_dist
                q->target_hash = 0;
                q->check_hash = 0;
                if (t[j] == i) {///this pre-cut is weird; attention
                    if (++n_skip > max_skip)
                        break;
                }
                if (p[j] >= 0) t[p[j]] = i;
            }
        }
        ///the above saves all linear chains that might be reached to the left side of chain i
        ///all those chains are saved to dst<n_dst>
        { // confirm reach-ability
            int32_t k;
            // test reach-ability without sequences
            // (g->seg[li->v>>1].len - li->rs) ----> is like the node length in string graph
            mg_shortest_k(km, g, li->v^1, n_dst, dst, max_dist_g + (g->seq[li->v>>1].len - li->rs), MG_MAX_SHORT_K, /**0, 0, 1,**/ 0);
            // remove unreachable destinations
            for (j = k = 0; j < n_dst; ++j) {
                mg_path_dst_t *dj = &dst[j];
                int32_t sc;
                if (dj->n_path == 0) continue; // unreachable
                sc = cal_sc(dj, li, lc, an, a, f, bw, ref_bonus, chn_pen_gap);
                if (sc == INT32_MIN) continue; // out of band
                if (sc + li->score < 0) continue; // negative score and too low
                dst[k] = dst[j];
                dst[k++].srt_key = INT64_MAX/2 - (int64_t)sc; // sort in the descending order
            }
            n_dst = k;
            if (n_dst > 0) {
                radix_sort_dst(dst, dst + n_dst);
                // discard weaker chains if the best score is much larger (assuming base-level heuristic won't lift it to the top chain)
                // dst[0].srt_key has the largest score
                for (j = 1; j < n_dst; ++j) 
                    if ((int64_t)(dst[j].srt_key - dst[0].srt_key) > li->score)//discard chains with too small weight
                        break;
                n_dst = j;
                if (n_dst > max_gc_seq_ext) n_dst = max_gc_seq_ext; // discard weaker chains
            }
        }
		/** //path
        if (n_dst > 0) { // find paths with sequences
            int32_t min_qs = li->qs;
            for (j = 0; j < n_dst; ++j) {
                const mg_lchain_t *lj;
                assert(dst[j].n_path > 0);
                ///a[]->srt = (uint32_t)is_isolated<<31 | r->qe;
                ///a[]->i = i;
                lj = &lc[a[dst[j].meta].i];
                if (lj->qe < min_qs) min_qs = lj->qe;
            }
            ///qs keeps the sequence at the gap between the li and lj in query
            memcpy(qs, &qseq[min_qs], li->qs - min_qs);
            mg_shortest_k(km, g, li->v^1, n_dst, dst, max_dist_g + (g->seg[li->v>>1].len - li->rs), MG_MAX_SHORT_K, li->qs - min_qs, qs, 1, 0);
            if (mg_dbg_flag & MG_DBG_GC1) fprintf(stderr, "[src:%d] q_intv=[%d,%d), src=%c%s[%d], n_dst=%d, max_dist=%d, min_qs=%d, lc_score=%d\n", ai->i, li->qs, li->qe, "><"[(li->v&1)^1], g->seg[li->v>>1].name, li->v^1, n_dst, max_dist_g + (g->seg[li->v>>1].len - li->rs), min_qs, li->score);
        }**/
        { // DP
            int32_t max_f = li->score, max_j = -1, max_d = -1, max_inner = 0;
            uint32_t max_hash = 0;
            for (j = 0; j < n_dst; ++j) {
                mg_path_dst_t *dj = &dst[j];
                int32_t sc;
                sc = cal_sc(dj, li, lc, an, a, f, bw, ref_bonus, chn_pen_gap);
                if (sc == INT32_MIN) continue;
                if (sc > max_f) max_f = sc, max_j = dj->meta, max_d = dj->dist, max_hash = dj->hash, max_inner = dj->inner;
            }
            f[i] = max_f, p[i] = max_j;
            li->dist_pre = max_d;
            li->hash_pre = max_hash;
            li->inner_pre = max_inner;
            v[i] = max_j >= 0 && v[max_j] > max_f? v[max_j] : max_f;
        }
    }
    kfree(km, dst);

	// print_gchain(a, p, lc, n_ext, ug, qlen);

    // kfree(km, qs);
    ///n_ext: number of useful chains
    ///n_lc - n_ext: number of isoated chains
    u = mg_chain_backtrack(km, n_ext, f, p, v, t, 0, 0, n_lc - n_ext, &n_u, &n_v);
    kfree(km, f); kfree(km, p); kfree(km, t);
    ///store the extra isoated chains
    for (i = 0; i < n_lc - n_ext; ++i) {
        u[n_u++] = (uint64_t)lc[a[n_ext + i].i].score << 32 | 1;
        v[n_v++] = n_ext + i;
    }

    ///reorganize lc;
    KMALLOC(km, swap, n_v);
    for (i = 0, k = 0; i < n_u; ++i) {
        int32_t k0 = k, ni = (int32_t)u[i];
        for (j = 0; j < ni; ++j)
            swap[k++] = lc[a[v[k0 + (ni - j - 1)]].i];
    }
    assert(k == n_v);
    memcpy(lc, swap, n_v * sizeof(mg_lchain_t));
    *n_lc_ = n_v;
    *u_ = u;
	// compress_lchain(lc, *n_lc_, qlen, ug, an);

    kfree(km, a);
    kfree(km, swap);
    kfree(km, v);
    return n_u;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1b0, %rsp            # imm = 0x1B0
movq 0x50(%rbp), %rax
movq 0x48(%rbp), %rax
movq 0x40(%rbp), %rax
movl 0x38(%rbp), %eax
movl 0x30(%rbp), %eax
movl 0x28(%rbp), %eax
movl 0x20(%rbp), %eax
movl 0x18(%rbp), %eax
movl 0x10(%rbp), %eax
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
movq %rcx, -0x28(%rbp)
movq %r8, -0x30(%rbp)
movl %r9d, -0x34(%rbp)
movss %xmm0, -0x38(%rbp)
movss %xmm1, -0x3c(%rbp)
movq -0x28(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x60(%rbp)
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0xd0(%rbp)
movq 0x50(%rbp), %rax
movq $0x0, (%rax)
cmpl $0x0, -0x60(%rbp)
jne 0x2888b0
movl $0x0, -0x4(%rbp)
jmp 0x2897a0
movq -0x10(%rbp), %rdi
movslq -0x60(%rbp), %rsi
shlq $0x3, %rsi
callq 0x30e4f0
movq %rax, -0xc0(%rbp)
movl $0x0, -0x54(%rbp)
movl $0x0, -0x40(%rbp)
movl -0x40(%rbp), %eax
cmpl -0x60(%rbp), %eax
jge 0x288a36
movq -0x30(%rbp), %rax
movslq -0x40(%rbp), %rcx
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0xd8(%rbp)
movq -0xc0(%rbp), %rax
movslq -0x40(%rbp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, -0xe0(%rbp)
movl $0x0, -0xe4(%rbp)
movq -0xd8(%rbp), %rdi
movslq -0x34(%rbp), %rsi
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rax
movq -0xd8(%rbp), %rcx
movl 0x8(%rcx), %ecx
shrl %ecx
movl %ecx, %ecx
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movl (%rax), %eax
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
movl %eax, %eax
movl %eax, %edx
xorl %eax, %eax
movl %eax, %r8d
leaq -0x64(%rbp), %r9
leaq -0x68(%rbp), %rax
movq %r8, %rcx
movq %rax, (%rsp)
callq 0x287660
movq -0xd8(%rbp), %rax
movl $0xffffffff, 0x20(%rax) # imm = 0xFFFFFFFF
movq -0xd0(%rbp), %rax
movq 0x20(%rax), %rax
movq -0xd8(%rbp), %rcx
movl 0x8(%rcx), %ecx
shrl %ecx
movl %ecx, %ecx
movl (%rax,%rcx,8), %eax
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
subl -0x68(%rbp), %eax
movl %eax, -0xe8(%rbp)
movl -0x64(%rbp), %eax
cmpl -0xe8(%rbp), %eax
jge 0x2889b3
movl -0x64(%rbp), %eax
movl %eax, -0xe8(%rbp)
movl -0xe8(%rbp), %eax
cmpl 0x10(%rbp), %eax
jle 0x2889ca
movl $0x1, -0xe4(%rbp)
jmp 0x2889eb
movl -0xe8(%rbp), %eax
sarl $0x3, %eax
movq -0xd8(%rbp), %rcx
cmpl 0x1c(%rcx), %eax
jle 0x2889e9
movl $0x1, -0xe4(%rbp)
jmp 0x2889eb
movl -0xe4(%rbp), %ecx
shll $0x1f, %ecx
movq -0xd8(%rbp), %rax
orl 0x18(%rax), %ecx
movq -0xe0(%rbp), %rax
movl %ecx, (%rax)
movl -0x40(%rbp), %ecx
movq -0xe0(%rbp), %rax
movl %ecx, 0x4(%rax)
cmpl $0x0, -0xe4(%rbp)
jne 0x288a26
movl -0x54(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x54(%rbp)
jmp 0x288a28
movl -0x40(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x40(%rbp)
jmp 0x2888d6
cmpl $0x2, -0x54(%rbp)
jge 0x288ac5
movq -0x10(%rbp), %rdi
movq -0xc0(%rbp), %rsi
callq 0x30e2d0
movq -0x10(%rbp), %rdi
movslq -0x60(%rbp), %rsi
shlq $0x3, %rsi
callq 0x30e4f0
movq %rax, -0xb0(%rbp)
movl $0x0, -0x40(%rbp)
movl -0x40(%rbp), %eax
cmpl -0x60(%rbp), %eax
jge 0x288aac
movq -0x30(%rbp), %rax
movslq -0x40(%rbp), %rcx
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movslq 0x1c(%rax), %rdx
shlq $0x20, %rdx
orq $0x1, %rdx
movq -0xb0(%rbp), %rax
movslq -0x40(%rbp), %rcx
movq %rdx, (%rax,%rcx,8)
movl -0x40(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x40(%rbp)
jmp 0x288a6f
movq -0xb0(%rbp), %rcx
movq 0x50(%rbp), %rax
movq %rcx, (%rax)
movl -0x60(%rbp), %eax
movl %eax, -0x4(%rbp)
jmp 0x2897a0
movq -0xc0(%rbp), %rdi
movq -0xc0(%rbp), %rsi
movslq -0x60(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
callq 0x2806f0
movq -0x10(%rbp), %rdi
movslq -0x60(%rbp), %rsi
shlq $0x2, %rsi
callq 0x30e4f0
movq %rax, -0x78(%rbp)
movq -0x10(%rbp), %rdi
movslq -0x54(%rbp), %rsi
shlq $0x2, %rsi
callq 0x30e4f0
movq %rax, -0x70(%rbp)
movq -0x10(%rbp), %rdi
movslq -0x54(%rbp), %rsi
shlq $0x3, %rsi
callq 0x30e4f0
movq %rax, -0xa8(%rbp)
movq -0x10(%rbp), %rdi
movslq -0x54(%rbp), %rsi
movl $0x4, %edx
callq 0x30e1a0
movq %rax, -0x80(%rbp)
movl $0x0, -0x50(%rbp)
movl $0x0, -0x4c(%rbp)
movq $0x0, -0xb8(%rbp)
movl $0x0, -0x40(%rbp)
movl -0x40(%rbp), %eax
cmpl -0x54(%rbp), %eax
jge 0x28952d
movq -0xc0(%rbp), %rax
movslq -0x40(%rbp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, -0xf0(%rbp)
movq -0x30(%rbp), %rax
movq -0xf0(%rbp), %rcx
movslq 0x4(%rcx), %rcx
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0xf8(%rbp)
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rdi
movq -0xf8(%rbp), %rax
movl 0x8(%rax), %esi
xorl $0x1, %esi
callq 0x287d20
movl %eax, -0xfc(%rbp)
movq -0xf8(%rbp), %rdi
movslq -0x34(%rbp), %rsi
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rax
movq -0xf8(%rbp), %rcx
movl 0x8(%rcx), %ecx
shrl %ecx
movl %ecx, %ecx
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movl (%rax), %eax
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
movl %eax, %eax
movl %eax, %edx
leaq -0x84(%rbp), %rcx
leaq -0x88(%rbp), %r8
leaq -0x8c(%rbp), %r9
leaq -0x90(%rbp), %rax
movq %rax, (%rsp)
callq 0x287660
movq -0xf8(%rbp), %rax
movl 0x14(%rax), %eax
addl 0x20(%rbp), %eax
addl -0xfc(%rbp), %eax
movl %eax, -0x100(%rbp)
movl $0x0, -0x104(%rbp)
movl -0x100(%rbp), %eax
cmpl -0x34(%rbp), %eax
jle 0x288c4c
movl -0x34(%rbp), %eax
movl %eax, -0x100(%rbp)
movl -0x40(%rbp), %edi
movq -0xc0(%rbp), %rsi
movl -0x100(%rbp), %edx
callq 0x2897b0
movl %eax, -0x100(%rbp)
movl $0x0, -0x50(%rbp)
movl -0x100(%rbp), %eax
movl %eax, -0x44(%rbp)
cmpl $0x0, -0x44(%rbp)
jl 0x28910b
movq -0xc0(%rbp), %rax
movslq -0x44(%rbp), %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, -0x110(%rbp)
movq -0x30(%rbp), %rax
movq -0x110(%rbp), %rcx
movslq 0x4(%rcx), %rcx
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x118(%rbp)
movq -0x118(%rbp), %rdi
movslq -0x34(%rbp), %rsi
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rax
movq -0x118(%rbp), %rcx
movl 0x8(%rcx), %ecx
shrl %ecx
movl %ecx, %ecx
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movl (%rax), %eax
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
movl %eax, %eax
movl %eax, %edx
leaq -0x94(%rbp), %rcx
leaq -0x98(%rbp), %r8
leaq -0x9c(%rbp), %r9
leaq -0xa0(%rbp), %rax
movq %rax, (%rsp)
callq 0x287660
movq -0x118(%rbp), %rax
movl 0x14(%rax), %eax
movq -0xf8(%rbp), %rcx
cmpl 0x14(%rcx), %eax
jl 0x288d2a
jmp 0x2890fd
movl -0x84(%rbp), %eax
subl -0x98(%rbp), %eax
movl %eax, -0x128(%rbp)
movl -0x128(%rbp), %eax
cmpl 0x18(%rbp), %eax
jle 0x288d4c
jmp 0x28910b
movq -0xf8(%rbp), %rax
movl 0x8(%rax), %eax
movq -0x118(%rbp), %rcx
cmpl 0x8(%rcx), %eax
je 0x288ddb
movl -0x8c(%rbp), %eax
movq -0xd0(%rbp), %rcx
movq 0x20(%rcx), %rcx
movq -0x118(%rbp), %rdx
movl 0x8(%rdx), %edx
shrl %edx
movl %edx, %edx
movl (%rcx,%rdx,8), %ecx
andl $0x7fffffff, %ecx       # imm = 0x7FFFFFFF
subl -0xa0(%rbp), %ecx
addl %ecx, %eax
movl %eax, -0x12c(%rbp)
movl -0x12c(%rbp), %eax
cmpl 0x10(%rbp), %eax
jle 0x288da8
jmp 0x2890fd
movq -0xd0(%rbp), %rdi
movq -0x118(%rbp), %rsi
movq -0xf8(%rbp), %rdx
callq 0x2898a0
movl %eax, -0x124(%rbp)
cmpl $0x0, -0x124(%rbp)
jge 0x288dd6
jmp 0x2890fd
jmp 0x288f5c
movq -0x118(%rbp), %rax
movl 0xc(%rax), %eax
movq -0xf8(%rbp), %rcx
cmpl 0xc(%rcx), %eax
jge 0x288e07
movq -0x118(%rbp), %rax
movl 0x10(%rax), %eax
movq -0xf8(%rbp), %rcx
cmpl 0x10(%rcx), %eax
jl 0x288e0c
jmp 0x2890fd
movq -0xf8(%rbp), %rax
movl 0xc(%rax), %eax
movq -0x118(%rbp), %rcx
subl 0x10(%rcx), %eax
movl %eax, -0x130(%rbp)
movq -0xf8(%rbp), %rax
movl 0x14(%rax), %eax
movq -0x118(%rbp), %rcx
subl 0x18(%rcx), %eax
movl %eax, -0x134(%rbp)
movl -0x130(%rbp), %eax
cmpl -0x134(%rbp), %eax
jle 0x288e62
movl -0x130(%rbp), %eax
subl -0x134(%rbp), %eax
movl %eax, -0x178(%rbp)
jmp 0x288e74
movl -0x134(%rbp), %eax
subl -0x130(%rbp), %eax
movl %eax, -0x178(%rbp)
movl -0x178(%rbp), %eax
movl %eax, -0x138(%rbp)
movl -0x138(%rbp), %eax
cmpl 0x20(%rbp), %eax
jle 0x288e90
jmp 0x2890fd
movl -0x130(%rbp), %eax
cmpl 0x10(%rbp), %eax
jg 0x288eaa
movl -0x130(%rbp), %eax
xorl %ecx, %ecx
subl 0x10(%rbp), %ecx
cmpl %ecx, %eax
jge 0x288eaf
jmp 0x2890fd
movq -0x118(%rbp), %rax
movl 0x10(%rax), %eax
movq -0xf8(%rbp), %rcx
cmpl 0xc(%rcx), %eax
jle 0x288f3a
movq -0x118(%rbp), %rax
movl 0x10(%rax), %eax
movq -0xf8(%rbp), %rcx
subl 0xc(%rcx), %eax
movl %eax, -0x13c(%rbp)
cvtsi2ssl -0x13c(%rbp), %xmm0
movq -0x118(%rbp), %rax
movl 0x10(%rax), %eax
movq -0x118(%rbp), %rcx
subl 0xc(%rcx), %eax
cvtsi2ss %eax, %xmm1
mulss -0x3c(%rbp), %xmm1
ucomiss %xmm1, %xmm0
ja 0x288f33
cvtsi2ssl -0x13c(%rbp), %xmm0
movq -0xf8(%rbp), %rax
movl 0x10(%rax), %eax
movq -0xf8(%rbp), %rcx
subl 0xc(%rcx), %eax
cvtsi2ss %eax, %xmm1
mulss -0x3c(%rbp), %xmm1
ucomiss %xmm1, %xmm0
jbe 0x288f38
jmp 0x2890fd
jmp 0x288f3a
movq -0xd0(%rbp), %rdi
movq -0x118(%rbp), %rsi
movq -0xf8(%rbp), %rdx
callq 0x2898a0
movl %eax, -0x124(%rbp)
jmp 0x288f5c
movl -0x50(%rbp), %eax
cmpl -0x4c(%rbp), %eax
jne 0x288fb5
jmp 0x288f66
cmpl $0x4, -0x4c(%rbp)
jl 0x288f7e
movl -0x4c(%rbp), %eax
movl -0x4c(%rbp), %ecx
sarl %ecx
addl %ecx, %eax
movl %eax, -0x17c(%rbp)
jmp 0x288f8b
movl $0x10, %eax
movl %eax, -0x17c(%rbp)
jmp 0x288f8b
movl -0x17c(%rbp), %eax
movl %eax, -0x4c(%rbp)
movq -0x10(%rbp), %rdi
movq -0xb8(%rbp), %rsi
movslq -0x4c(%rbp), %rax
imulq $0x30, %rax, %rdx
callq 0x30e740
movq %rax, -0xb8(%rbp)
jmp 0x288fb5
movq -0xb8(%rbp), %rax
movl -0x50(%rbp), %ecx
movl %ecx, %edx
addl $0x1, %edx
movl %edx, -0x50(%rbp)
movslq %ecx, %rcx
imulq $0x30, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x120(%rbp)
movq -0x120(%rbp), %rdi
xorl %esi, %esi
movl $0x30, %edx
callq 0x2100
movq -0xf8(%rbp), %rax
movl 0x8(%rax), %eax
movq -0x118(%rbp), %rcx
cmpl 0x8(%rcx), %eax
sete %al
andb $0x1, %al
movzbl %al, %edx
movq -0x120(%rbp), %rax
movl 0xc(%rax), %ecx
andl $0x1, %edx
shll $0x1f, %edx
andl $0x7fffffff, %ecx       # imm = 0x7FFFFFFF
orl %edx, %ecx
movl %ecx, 0xc(%rax)
movq -0x118(%rbp), %rax
movl 0x8(%rax), %ecx
xorl $0x1, %ecx
movq -0x120(%rbp), %rax
movl %ecx, (%rax)
movl -0x44(%rbp), %edx
movq -0x120(%rbp), %rax
movl 0xc(%rax), %ecx
andl $0x3fffffff, %edx       # imm = 0x3FFFFFFF
andl $0xc0000000, %ecx       # imm = 0xC0000000
orl %edx, %ecx
movl %ecx, 0xc(%rax)
movq -0xf8(%rbp), %rax
movl 0x14(%rax), %ecx
movq -0x118(%rbp), %rax
subl 0x18(%rax), %ecx
movq -0x120(%rbp), %rax
movl %ecx, 0x10(%rax)
movl -0x124(%rbp), %ecx
movq -0x120(%rbp), %rax
movl %ecx, 0x4(%rax)
movq -0x120(%rbp), %rax
movl $0x0, 0x8(%rax)
movq -0x120(%rbp), %rax
movl 0xc(%rax), %ecx
andl $0xbfffffff, %ecx       # imm = 0xBFFFFFFF
orl $0x0, %ecx
movl %ecx, 0xc(%rax)
movq -0x80(%rbp), %rax
movslq -0x44(%rbp), %rcx
movl (%rax,%rcx,4), %eax
cmpl -0x40(%rbp), %eax
jne 0x2890d0
movl -0x104(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x104(%rbp)
cmpl 0x28(%rbp), %eax
jle 0x2890ce
jmp 0x28910b
jmp 0x2890d0
movq -0xa8(%rbp), %rax
movslq -0x44(%rbp), %rcx
cmpq $0x0, (%rax,%rcx,8)
jl 0x2890fb
movl -0x40(%rbp), %edx
movq -0x80(%rbp), %rax
movq -0xa8(%rbp), %rcx
movslq -0x44(%rbp), %rsi
movq (%rcx,%rsi,8), %rcx
movl %edx, (%rax,%rcx,4)
jmp 0x2890fd
movl -0x44(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x44(%rbp)
jmp 0x288c77
movq -0x10(%rbp), %rdi
movq -0xd0(%rbp), %rsi
movq -0xf8(%rbp), %rax
movl 0x8(%rax), %edx
xorl $0x1, %edx
movl -0x50(%rbp), %ecx
movq -0xb8(%rbp), %r8
movl 0x10(%rbp), %r9d
movq -0xd0(%rbp), %rax
movq 0x20(%rax), %rax
movq -0xf8(%rbp), %r10
movl 0x8(%r10), %r10d
shrl %r10d
movl %r10d, %r10d
movl (%rax,%r10,8), %eax
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
movq -0xf8(%rbp), %r10
subl 0xc(%r10), %eax
addl %eax, %r9d
xorl %eax, %eax
movl $0xf, (%rsp)
movq $0x0, 0x8(%rsp)
callq 0x284f90
movl $0x0, -0x140(%rbp)
movl $0x0, -0x44(%rbp)
movl -0x44(%rbp), %eax
cmpl -0x50(%rbp), %eax
jge 0x2892ab
movq -0xb8(%rbp), %rax
movslq -0x44(%rbp), %rcx
imulq $0x30, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x148(%rbp)
movq -0x148(%rbp), %rax
movl 0x14(%rax), %eax
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
cmpl $0x0, %eax
jne 0x2891ca
jmp 0x28929d
movq -0x148(%rbp), %rdi
movq -0xf8(%rbp), %rsi
movq -0x30(%rbp), %rdx
movq 0x48(%rbp), %rcx
movq -0xc0(%rbp), %r8
movq -0x70(%rbp), %r9
movl 0x20(%rbp), %r10d
movl 0x30(%rbp), %eax
movss -0x38(%rbp), %xmm0
movl %r10d, (%rsp)
movl %eax, 0x8(%rsp)
callq 0x289910
movl %eax, -0x14c(%rbp)
cmpl $0x80000000, -0x14c(%rbp) # imm = 0x80000000
jne 0x28921b
jmp 0x28929d
movl -0x14c(%rbp), %eax
movq -0xf8(%rbp), %rcx
addl 0x1c(%rcx), %eax
cmpl $0x0, %eax
jge 0x289232
jmp 0x28929d
movq -0xb8(%rbp), %rsi
movslq -0x44(%rbp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rsi
movq -0xb8(%rbp), %rdi
movslq -0x140(%rbp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rdi
movl $0x30, %edx
callq 0x2180
movslq -0x14c(%rbp), %rax
movabsq $0x3fffffffffffffff, %rcx # imm = 0x3FFFFFFFFFFFFFFF
subq %rax, %rcx
movq -0xb8(%rbp), %rax
movl -0x140(%rbp), %edx
movl %edx, %esi
addl $0x1, %esi
movl %esi, -0x140(%rbp)
movslq %edx, %rdx
imulq $0x30, %rdx, %rdx
addq %rdx, %rax
movq %rcx, 0x28(%rax)
movl -0x44(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x44(%rbp)
jmp 0x28918c
movl -0x140(%rbp), %eax
movl %eax, -0x50(%rbp)
cmpl $0x0, -0x50(%rbp)
jle 0x289341
movq -0xb8(%rbp), %rdi
movq -0xb8(%rbp), %rsi
movslq -0x50(%rbp), %rax
imulq $0x30, %rax, %rax
addq %rax, %rsi
callq 0x280bd0
movl $0x1, -0x44(%rbp)
movl -0x44(%rbp), %eax
cmpl -0x50(%rbp), %eax
jge 0x28932b
movq -0xb8(%rbp), %rax
movslq -0x44(%rbp), %rcx
imulq $0x30, %rcx, %rcx
addq %rcx, %rax
movq 0x28(%rax), %rax
movq -0xb8(%rbp), %rcx
subq 0x28(%rcx), %rax
movq -0xf8(%rbp), %rcx
movslq 0x1c(%rcx), %rcx
cmpq %rcx, %rax
jle 0x28931e
jmp 0x28932b
jmp 0x289320
movl -0x44(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x44(%rbp)
jmp 0x2892e3
movl -0x44(%rbp), %eax
movl %eax, -0x50(%rbp)
movl -0x50(%rbp), %eax
cmpl 0x38(%rbp), %eax
jle 0x28933f
movl 0x38(%rbp), %eax
movl %eax, -0x50(%rbp)
jmp 0x289341
movq -0xf8(%rbp), %rax
movl 0x1c(%rax), %eax
movl %eax, -0x150(%rbp)
movl $0xffffffff, -0x154(%rbp) # imm = 0xFFFFFFFF
movl $0xffffffff, -0x158(%rbp) # imm = 0xFFFFFFFF
movl $0x0, -0x15c(%rbp)
movl $0x0, -0x160(%rbp)
movl $0x0, -0x44(%rbp)
movl -0x44(%rbp), %eax
cmpl -0x50(%rbp), %eax
jge 0x289465
movq -0xb8(%rbp), %rax
movslq -0x44(%rbp), %rcx
imulq $0x30, %rcx, %rcx
addq %rcx, %rax
movq %rax, -0x168(%rbp)
movq -0x168(%rbp), %rdi
movq -0xf8(%rbp), %rsi
movq -0x30(%rbp), %rdx
movq 0x48(%rbp), %rcx
movq -0xc0(%rbp), %r8
movq -0x70(%rbp), %r9
movl 0x20(%rbp), %r10d
movl 0x30(%rbp), %eax
movss -0x38(%rbp), %xmm0
movl %r10d, (%rsp)
movl %eax, 0x8(%rsp)
callq 0x289910
movl %eax, -0x16c(%rbp)
cmpl $0x80000000, -0x16c(%rbp) # imm = 0x80000000
jne 0x2893f3
jmp 0x289457
movl -0x16c(%rbp), %eax
cmpl -0x150(%rbp), %eax
jle 0x289455
movl -0x16c(%rbp), %eax
movl %eax, -0x150(%rbp)
movq -0x168(%rbp), %rax
movl 0xc(%rax), %eax
andl $0x3fffffff, %eax       # imm = 0x3FFFFFFF
movl %eax, -0x154(%rbp)
movq -0x168(%rbp), %rax
movl 0x1c(%rax), %eax
movl %eax, -0x158(%rbp)
movq -0x168(%rbp), %rax
movl 0x24(%rax), %eax
movl %eax, -0x160(%rbp)
movq -0x168(%rbp), %rax
movl 0xc(%rax), %eax
shrl $0x1f, %eax
movl %eax, -0x15c(%rbp)
jmp 0x289457
movl -0x44(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x44(%rbp)
jmp 0x289380
movl -0x150(%rbp), %edx
movq -0x70(%rbp), %rax
movslq -0x40(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movslq -0x154(%rbp), %rdx
movq -0xa8(%rbp), %rax
movslq -0x40(%rbp), %rcx
movq %rdx, (%rax,%rcx,8)
movl -0x158(%rbp), %ecx
movq -0xf8(%rbp), %rax
movl %ecx, 0x20(%rax)
movl -0x160(%rbp), %ecx
movq -0xf8(%rbp), %rax
movl %ecx, 0x24(%rax)
movl -0x15c(%rbp), %edx
movq -0xf8(%rbp), %rax
movl 0x4(%rax), %ecx
andl $0x1, %edx
shll $0x1f, %edx
andl $0x7fffffff, %ecx       # imm = 0x7FFFFFFF
orl %edx, %ecx
movl %ecx, 0x4(%rax)
cmpl $0x0, -0x154(%rbp)
jl 0x289502
movq -0x78(%rbp), %rax
movslq -0x154(%rbp), %rcx
movl (%rax,%rcx,4), %eax
cmpl -0x150(%rbp), %eax
jle 0x289502
movq -0x78(%rbp), %rax
movslq -0x154(%rbp), %rcx
movl (%rax,%rcx,4), %eax
movl %eax, -0x180(%rbp)
jmp 0x28950e
movl -0x150(%rbp), %eax
movl %eax, -0x180(%rbp)
movl -0x180(%rbp), %edx
movq -0x78(%rbp), %rax
movslq -0x40(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movl -0x40(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x40(%rbp)
jmp 0x288b5b
movq -0x10(%rbp), %rdi
movq -0xb8(%rbp), %rsi
callq 0x30e2d0
movq -0x10(%rbp), %rdi
movslq -0x54(%rbp), %rsi
movq -0x70(%rbp), %rdx
movq -0xa8(%rbp), %rcx
movq -0x78(%rbp), %r8
movq -0x80(%rbp), %r9
movl -0x60(%rbp), %r11d
subl -0x54(%rbp), %r11d
xorl %eax, %eax
leaq -0x58(%rbp), %r10
leaq -0x5c(%rbp), %rax
movl $0x0, (%rsp)
movl $0x0, 0x8(%rsp)
movl %r11d, 0x10(%rsp)
movq %r10, 0x18(%rsp)
movq %rax, 0x20(%rsp)
callq 0x2839e0
movq %rax, -0xb0(%rbp)
movq -0x10(%rbp), %rdi
movq -0x70(%rbp), %rsi
callq 0x30e2d0
movq -0x10(%rbp), %rdi
movq -0xa8(%rbp), %rsi
callq 0x30e2d0
movq -0x10(%rbp), %rdi
movq -0x80(%rbp), %rsi
callq 0x30e2d0
movl $0x0, -0x40(%rbp)
movl -0x40(%rbp), %eax
movl -0x60(%rbp), %ecx
subl -0x54(%rbp), %ecx
cmpl %ecx, %eax
jge 0x28963d
movq -0x30(%rbp), %rax
movq -0xc0(%rbp), %rcx
movl -0x54(%rbp), %edx
addl -0x40(%rbp), %edx
movslq %edx, %rdx
movslq 0x4(%rcx,%rdx,8), %rcx
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movslq 0x1c(%rax), %rdx
shlq $0x20, %rdx
orq $0x1, %rdx
movq -0xb0(%rbp), %rax
movl -0x58(%rbp), %ecx
movl %ecx, %esi
addl $0x1, %esi
movl %esi, -0x58(%rbp)
movslq %ecx, %rcx
movq %rdx, (%rax,%rcx,8)
movl -0x54(%rbp), %edx
addl -0x40(%rbp), %edx
movq -0x78(%rbp), %rax
movl -0x5c(%rbp), %ecx
movl %ecx, %esi
addl $0x1, %esi
movl %esi, -0x5c(%rbp)
movslq %ecx, %rcx
movl %edx, (%rax,%rcx,4)
movl -0x40(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x40(%rbp)
jmp 0x2895c5
movq -0x10(%rbp), %rdi
movslq -0x5c(%rbp), %rax
imulq $0x28, %rax, %rsi
callq 0x30e4f0
movq %rax, -0xc8(%rbp)
movl $0x0, -0x40(%rbp)
movl $0x0, -0x48(%rbp)
movl -0x40(%rbp), %eax
cmpl -0x58(%rbp), %eax
jge 0x289715
movl -0x48(%rbp), %eax
movl %eax, -0x170(%rbp)
movq -0xb0(%rbp), %rax
movslq -0x40(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movl %eax, -0x174(%rbp)
movl $0x0, -0x44(%rbp)
movl -0x44(%rbp), %eax
cmpl -0x174(%rbp), %eax
jge 0x289705
movq -0x30(%rbp), %rsi
movq -0xc0(%rbp), %rax
movq -0x78(%rbp), %rcx
movl -0x170(%rbp), %edx
movl -0x174(%rbp), %edi
subl -0x44(%rbp), %edi
subl $0x1, %edi
addl %edi, %edx
movslq %edx, %rdx
movslq (%rcx,%rdx,4), %rcx
movslq 0x4(%rax,%rcx,8), %rax
imulq $0x28, %rax, %rax
addq %rax, %rsi
movq -0xc8(%rbp), %rdi
movl -0x48(%rbp), %eax
movl %eax, %ecx
addl $0x1, %ecx
movl %ecx, -0x48(%rbp)
cltq
imulq $0x28, %rax, %rax
addq %rax, %rdi
movl $0x28, %edx
callq 0x2180
movl -0x44(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x44(%rbp)
jmp 0x289694
jmp 0x289707
movl -0x40(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x40(%rbp)
jmp 0x289663
movl -0x48(%rbp), %eax
cmpl -0x5c(%rbp), %eax
jne 0x28971f
jmp 0x28973e
leaq 0x10731f(%rip), %rdi    # 0x390a45
leaq 0x107102(%rip), %rsi    # 0x39082f
movl $0x724, %edx            # imm = 0x724
leaq 0x107315(%rip), %rcx    # 0x390a4e
callq 0x2130
movq -0x30(%rbp), %rdi
movq -0xc8(%rbp), %rsi
movslq -0x5c(%rbp), %rax
imulq $0x28, %rax, %rdx
callq 0x2180
movl -0x5c(%rbp), %ecx
movq -0x28(%rbp), %rax
movl %ecx, (%rax)
movq -0xb0(%rbp), %rcx
movq 0x50(%rbp), %rax
movq %rcx, (%rax)
movq -0x10(%rbp), %rdi
movq -0xc0(%rbp), %rsi
callq 0x30e2d0
movq -0x10(%rbp), %rdi
movq -0xc8(%rbp), %rsi
callq 0x30e2d0
movq -0x10(%rbp), %rdi
movq -0x78(%rbp), %rsi
callq 0x30e2d0
movl -0x58(%rbp), %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x1b0, %rsp            # imm = 0x1B0
popq %rbp
retq
nopl (%rax)