// File: /workspace/github_cpp_makefile_star2_O3/chhylp123[P]hifiasm/inter.cpp
// Function: hc_shortest_k(void*, asg_t const*, unsigned int, int, mg_path_dst_t*, int, int, st_mt_t*, unsigned long*, vec_sp_node_t*, vec_mg_pathv_t*, unsigned long, unsigned long, float)
void hc_shortest_k(void *km0, const asg_t *g, uint32_t src, int32_t n_dst, mg_path_dst_t *dst, int32_t max_dist, int32_t max_k, 
st_mt_t *dst_done, uint64_t *dst_group, vec_sp_node_t *out, vec_mg_pathv_t *res, uint64_t first_src_ban, 
uint64_t detect_mul_way, float len_dif)
{
    sp_node_t *p, *root = 0;
    sp_topk_t *q;
    khash_t(sp) *h;///
    khash_t(sp2) *h2;///alignment->vertice index
    void *km;
    khint_t k;
    int absent;
    int32_t i, j, n_done, n_found;
    uint32_t id;

    // if (res) res->n = 0;///for us, n_pathv = NULL
    if (n_dst <= 0) return;///n_dst: how many candidate vertices
    for (i = 0; i < n_dst; ++i) { // initialize
        mg_path_dst_t *t = &dst[i];
        ///if src and dest are at the same ref id, there are already one path
        if (t->inner)///if two chains are at the same ref id
            t->dist = 0, t->n_path = 1, t->path_end = -1;
        else
            t->dist = -1, t->n_path = 0, t->path_end = -1;
    }
    if (max_k > MG_MAX_SHORT_K) max_k = MG_MAX_SHORT_K;
    km = km_init2(km0, 0x4000);

    // multiple dst[] may have the same dst[].v. We need to group them first.
    // in other words, one ref id may have multiple dst alignment chains
	dst_done->n = 0; kv_resize(uint64_t, *dst_done, (uint64_t)n_dst);
    for (i = 0; i < n_dst; ++i) {
		dst_group[i] = ((((uint64_t)dst[i].v)<<32)|((uint64_t)i));
		dst_done->a[i] = 0;
	}
        
    radix_sort_gfa64(dst_group, dst_group + n_dst);

    h2 = kh_init2(sp2, km); // (h2+dst_group) keeps all destinations from the same ref id
    kh_resize(sp2, h2, n_dst * 2);
    ///please note that one contig in ref may have multiple alignment chains
    ///so h2 is a index that helps us to query it
    ///key(h2) = ref id; value(h2) = start_idx | occ
    for (i = 1, j = 0; i <= n_dst; ++i) {
        if (i == n_dst || dst_group[i]>>32 != dst_group[j]>>32) {
            k = kh_put(sp2, h2, dst_group[j]>>32, &absent);
            kh_val(h2, k) = (((uint64_t)j)<<32)|((uint64_t)(i-j));
            assert(absent);
            j = i;
        }
    }

    h = kh_init2(sp, km); // h keeps visited vertices; path to each visited vertice
    kh_resize(sp, h, 16);

	out->n = 0; kv_resize(sp_node_t*, *out, 16); ///16 is just the initial size    
    id = 0;
    p = gen_sp_node(km, src, 0, id++);///just malloc a node for src; the distance is 0
    p->hash = __ac_Wang_hash(src);///hash is path hash, instead of node hash
    kavl_insert(sp, &root, p, 0);///should be avl tree; p is a node at avl-tree

    ///each cell in the hash table <h> corresponds to one node in the graph
	///each cell in the AVL tree <root> is a path, corresponds to <MG_MAX_SHORT_K> node in the graph
    k = kh_put(sp, h, src, &absent);
    q = &kh_val(h, k);
    ///for normal graph traversal, one node just has one parental node; here each node has at most 16 parental nodes
    q->k = 1, q->p[0] = p, q->mlen = 0, q->qs = q->qe = -1;

    n_done = 0; first_src_ban = first_src_ban?0:1;
    ///the key of avl tree: #define sp_node_cmp(a, b) (((a)->di > (b)->di) - ((a)->di < (b)->di))
    ///the higher bits of (*)->di is distance to src node
    ///so the key of avl tree is distance
    ///in avl tree <root>, one node might be saved multipe times
    while (kavl_size(head, root) > 0) {///thr first root is src
        int32_t i, nv;
        asg_arc_t *av;
        sp_node_t *r;
        ///note that one node in the graph (sp_node_t->v) might be visited multiple times if there are circles
        ///so there might be multipe cells in the avl-tree with the same (sp_node_t->v)
        ///delete the first cell
        r = kavl_erase_first(sp, &root); // take out the closest vertex in the heap (as a binary tree)
        //fprintf(stderr, "XX\t%d\t%d\t%d\t%c%s[%d]\t%d\n", n_out, kavl_size(head, root), n_finished, "><"[(r->v&1)^1], g->seg[r->v>>1].name, r->v, (int32_t)(r->di>>32));
        
		///higher 32 bits might be the distance to root node
        // lower 32 bits now for position in the out[] array
		///r->pre keep the pre-node in the path; follow the pre it is able to recover the whole path
        r->di = ((r->di>>32)<<32)|((uint64_t)out->n); ///n_out is just the id in out
        ///so one node id in graph might be saved multiple times in avl tree and out[]
		kv_push(sp_node_t*, *out, r);

        ///r->v is the dst vertex id
        ///sometimes k==kh_end(h2). Some nodes are found by graph travesal but not in linear chain alignment
        k = kh_get(sp2, h2, r->v);
        // we have reached one dst vertex
        // note that one dst vertex may have multipe alignment chains
        // we can visit some nodes in graph which are not reachable during chaining
        // h2 is used to determine if one node is reachable or not
		// if(src == 2844) {
		// 	fprintf(stderr, "******src->%u, dst->%u, max_dist->%d\n", src, r->v, max_dist);
		// }
        if (k != kh_end(h2) && first_src_ban) { 
            ///node r->v might be visited multiple times
            int32_t j, dist = r->di>>32, off = kh_val(h2, k) >> 32, cnt = (int32_t)kh_val(h2, k);
			// if(src == 2844) {
			// 	fprintf(stderr, "----src->%u, dst->%u, max_dist->%d, cnt->%d\n", src, r->v, max_dist, cnt);
			// }
            //src can reach ref id r->v; there might be not only one alignment chain in r->v
            //so we need to scan all of them
            for (j = 0; j < cnt; ++j) {
                mg_path_dst_t *t = &dst[(int32_t)dst_group[off + j]];///t is a linear alignment at r->v
                int32_t done = 0;
				// if((src>>1) == 51) {
				// 	fprintf(stderr, "###src->%u, dst->%u, max_dist->%d, dist:%d\n", src, r->v, max_dist, dist);
				// }
                ///the src and dest are at the same ref id, say we directly find the shortest path
                if (t->inner) {
                    done = 1;
                } else {
                    int32_t mlen = 0, copy = 0;
                    ///in the first round, we just check reachability without sequence
                    ///so h_seeds = NULL; we can assume mlen = 0
                    /** //path
                    mlen = h_seeds? path_mlen(out, n_out - 1, h, t->qlen) : 0;
                    **/
				   // means this alignment has never been visited before; keep it anyway
				   // note here is the alignment, instead of node
					
				    // if(src == 2844) {
					// 	fprintf(stderr, ">>src->%u, dst->%u, target_dist->%d, dist->%d, max_dist->%d\n", 
					// 	src, r->v, t->target_dist, dist, max_dist);
					// }
                    if (t->n_path == 0) { 
                        copy = 1;
                     // we have a target distance; choose the closest; 
                     // there is already several paths reaching the linear alignment <t>
                    } else if (t->target_dist >= 0) { 
                        // we found the target path; hash is the path hash including multiple nodes, instead of node hash 
                        if (dist == t->target_dist && t->check_hash && r->hash == t->target_hash) { 
                            copy = 1, done = 1;
                        } else {
                            int32_t d0 = t->dist, d1 = dist;
                            d0 = d0 > t->target_dist? d0 - t->target_dist : t->target_dist - d0;
                            d1 = d1 > t->target_dist? d1 - t->target_dist : t->target_dist - d1;
                            ///if the new distance (d1) is smaller than the old distance (d0), update the results
                            ///the length of new path should be closer to t->target_dist
                            if (d1 - mlen/2 < d0 - t->mlen/2) copy = 1;
                        }
                    }
                    if (copy) {
                        t->path_end = out->n-1, t->dist = dist, t->hash = r->hash, t->mlen = mlen, t->is_0 = r->is_0;
                        if (t->target_dist >= 0) {
                            ///src is from li from li to lj, so the dis is generally increased; dijkstra algorithm
                            ///target_dist should be the distance on query
                            if (dist == t->target_dist && t->check_hash && r->hash == t->target_hash) {
								done = 1;
							} else if ((dist > t->target_dist + MG_SHORT_K_EXT) && (dist > (t->target_dist>>4)) && 
								(dist > (t->target_dist*1.25))) {
								done = 1;
							}
                        }
                    }
                    ++t->n_path;///we found a path to the alignment t
                    if (t->n_path >= max_k) done = 1;
                }
                if (detect_mul_way == 0 && dst_done->a[off + j] == 0 && done)
                    dst_done->a[off + j] = 1, ++n_done;
            }
            ///if all alignments have been settle down
            ///pre-end; accelerate the loop
            if (n_done == n_dst) break;
        }
		first_src_ban = 1;
        ///below is used to push new nodes to avl tree for iteration
        nv = asg_arc_n(g, r->v);
        av = asg_arc_a(g, r->v);
        for (i = 0; i < nv; ++i) { // visit all neighbors
            asg_arc_t *ai = &av[i];
            ///v_lv is the (dest_length - overlap_length); it is a normal path length in string graph
            ///ai->v_lv is the path length from r->v to ai->w
            ///(r->di>>32)
            int32_t d = (r->di>>32) + (uint32_t)ai->ul;
            if (d > max_dist) continue; // don't probe vertices too far away
            // h keeps visited vertices; path to each visited vertice
            ///ai->w is the dest ref id; we insert a new ref id, instead of an alignment chain
            k = kh_put(sp, h, ai->v, &absent);///one node might be visited multiple times
            q = &kh_val(h, k);
            if (absent) { // a new vertex visited
                ///q->k: number of walks from src to ai->w
                q->k = 0, q->qs = q->qe = -1; q->mlen = 0;
                ///h_seeds = NULL; so q->mlen = 0
                /** //path
                q->mlen = h_seeds && d + gfa_arc_lw(g, *ai) <= max_dist? node_mlen(km, g, ai->w, &mini, h_seeds, n_seeds, seeds, &q->qs, &q->qe) : 0;
                **/
                //if (ql && qs) fprintf(stderr, "ql=%d,src=%d\tv=%c%s[%d],n_seeds=%d,mlen=%d\n", ql, src, "><"[ai->w&1], g->seg[ai->w>>1].name, ai->w, n_seeds, q->mlen);
            }
            ///if there are less than <max_k> walks from src to ai->w, directly add
            ///if there are more, keep the smallest <max_k> walks
            if (q->k < max_k) { // enough room: add to the heap
                p = gen_sp_node(km, ai->v, d, id++);
                p->pre = out->n - 1;///the parent node of this one 
                p->hash = r->hash + __ac_Wang_hash(ai->v);
                p->is_0 = r->is_0;
                /** //path
                if (ai->rank > 0) p->is_0 = 0;
                **/
                kavl_insert(sp, &root, p, 0);
                q->p[q->k++] = p;
                ks_heapup_sp(q->k, q->p);///adjust heap by distance
            } else if ((int32_t)(q->p[0]->di>>32) > d) { // shorter than the longest path so far: replace the longest
                p = kavl_erase(sp, &root, q->p[0], 0);
                if (p) {
                    p->di = (uint64_t)d<<32 | (id++);
                    p->pre = out->n - 1;
                    p->hash = r->hash + __ac_Wang_hash(ai->v);
                    p->is_0 = r->is_0;
                    /** //path
                    if (ai->rank > 0) p->is_0 = 0;
                    **/
                    kavl_insert(sp, &root, p, 0);
                    ks_heapdown_sp(0, q->k, q->p);
                } else {
                    fprintf(stderr, "Warning: logical bug in gfa_shortest_k(): q->k=%d,q->p[0]->{d,i}={%d,%d},d=%d,src=%u,max_dist=%d,n_dst=%d\n", q->k, (int32_t)(q->p[0]->di>>32), (int32_t)q->p[0]->di, d, src, max_dist, n_dst);
                    km_destroy(km);
                    return;
                }
            } // else: the path is longer than all the existing paths ended at ai->w
        }
    }
    kh_destroy(sp, h);
    // NB: AVL nodes are not deallocated. When km==0, they are memory leaks.

    for (i = 0, n_found = 0; i < n_dst; ++i)
        if (dst[i].n_path > 0) ++n_found;///n_path might be larger than 16
    ///we can assume n_pathv = NULL for now 
    if (n_found > 0 && res) { // then generate the backtrack array
        int32_t n, n_mpath = 1; dst_done->n = 0; kv_resize(uint64_t, *dst_done, out->n); 
		uint64_t *trans = dst_done->a; memset(dst_done->a, 0, out->n*sizeof(*(dst_done->a)));

		if(detect_mul_way) {
			n_mpath = phase_mul_ways(res, dst_done, out, n_dst, dst, max_k, len_dif);
		}
		
		if(n_mpath == 1) {
			// KCALLOC(km, trans, n_out); // used to squeeze unused elements in out[]
			///n_out: how many times that nodes in graph have been visited 
			///note one node might be visited multiples times
			///n_dst: number of alignment chains
			for (i = 0; i < n_dst; ++i) { // mark dst vertices with a target distance
				mg_path_dst_t *t = &dst[i];
				if (t->n_path > 0 && t->target_dist >= 0 && t->path_end >= 0)
					trans[(uint32_t)out->a[t->path_end]->di] = 1;///(int32_t)out[]->di: traverse track corresponds to the alignment chain dst[]
			}
			// for (i = 0; (uint32_t)i < out->n; ++i) { // mark dst vertices without a target distance
			//     k = kh_get(sp2, h2, out->a[i]->v);
			//     if (k != kh_end(h2)) { // TODO: check if this is correct!
			//         int32_t off = kh_val(h2, k)>>32, cnt = (int32_t)kh_val(h2, k);
			//         for (j = off; j < off + cnt; ++j)
			//             if (dst[j].target_dist < 0)
			//                 trans[i] = 1;
			//     }
			// }
			for (i = (int32_t)(out->n) - 1; i >= 0; --i) // mark all predecessors
				if (trans[i] && out->a[i]->pre >= 0)
					trans[out->a[i]->pre] = 1;
			for (i = n = 0; (uint32_t)i < out->n; ++i) // generate coordinate translations
				if (trans[i]) trans[i] = n++;
				else trans[i] = (uint32_t)-1;
			
			kv_resize(mg_pathv_t, *res, res->n + n); //res->n += n;
			for (i = 0; (uint32_t)i < out->n; ++i) { // generate the backtrack array
				mg_pathv_t *p;
				if (trans[i] == (uint32_t)-1) continue;
				p = &res->a[trans[i]+res->n];
				p->v = out->a[i]->v, p->d = out->a[i]->di >> 32;
				p->pre = out->a[i]->pre < 0? out->a[i]->pre:trans[out->a[i]->pre];
			}
			res->n += n;
			for (i = 0; i < n_dst; ++i) // translate "path_end"
				if (dst[i].path_end >= 0)
					dst[i].path_end = trans[dst[i].path_end];
		}
    }

    km_destroy(km);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xb8, %rsp
movss %xmm0, 0x8c(%rsp)
movq %r9, 0x50(%rsp)
movl %ecx, %r12d
movq %rdx, 0x90(%rsp)
movq 0x120(%rsp), %rax
movq %rax, 0xa0(%rsp)
movq 0x118(%rsp), %rcx
movq 0x110(%rsp), %rax
movq %rax, 0xa8(%rsp)
movq 0x108(%rsp), %r14
movq 0x100(%rsp), %rax
movq %rax, 0x40(%rsp)
movq 0xf8(%rsp), %rax
movq %rax, 0x68(%rsp)
movl 0xf0(%rsp), %eax
movq $0x0, 0x48(%rsp)
testl %r12d, %r12d
jle 0x1b1b38
movq %r8, %rbx
movq %rsi, %rbp
movq %rcx, 0x8(%rsp)
movl %r12d, %ecx
movq %rcx, 0x28(%rsp)
shlq $0x4, %rcx
leaq (%rcx,%rcx,2), %rcx
xorl %edx, %edx
movl $0x80000000, %esi       # imm = 0x80000000
cmpl $0x0, 0xc(%rbx,%rdx)
js 0x1b10d3
movl $0xffffffff, 0x1c(%rbx,%rdx) # imm = 0xFFFFFFFF
movl 0x14(%rbx,%rdx), %r8d
andl %esi, %r8d
jmp 0x1b10e6
movl $0x0, 0x1c(%rbx,%rdx)
movl 0x14(%rbx,%rdx), %r8d
andl %esi, %r8d
incl %r8d
movl %r8d, 0x14(%rbx,%rdx)
movl $0xffffffff, 0x18(%rbx,%rdx) # imm = 0xFFFFFFFF
addq $0x30, %rdx
cmpq %rdx, %rcx
jne 0x1b10ba
cmpl $0xf, %eax
movl $0xf, %ecx
cmovll %eax, %ecx
movl %ecx, 0x24(%rsp)
movl $0x4000, %esi           # imm = 0x4000
callq 0x1edf80
movq %rax, 0x38(%rsp)
movq 0x68(%rsp), %r15
movq $0x0, (%r15)
movq 0x28(%rsp), %rax
cmpq %rax, 0x8(%r15)
jae 0x1b1187
movq 0x28(%rsp), %rax
decq %rax
movq %rax, %rcx
shrq %rcx
orq %rax, %rcx
movq %rcx, %rax
shrq $0x2, %rax
orq %rcx, %rax
movq %rax, %rcx
shrq $0x4, %rcx
orq %rax, %rcx
movq %rcx, %rax
shrq $0x8, %rax
orq %rcx, %rax
movq %rax, %rcx
shrq $0x10, %rcx
orq %rax, %rcx
leaq 0x1(%rcx), %rax
movq %rax, 0x8(%r15)
movq 0x10(%r15), %rdi
leaq 0x8(,%rcx,8), %rsi
callq 0x2370
movq %rax, 0x10(%r15)
movq %rbp, 0xb0(%rsp)
movq %r14, 0x18(%rsp)
movq 0x10(%r15), %rax
xorl %ecx, %ecx
movq %rbx, 0x30(%rsp)
movq 0x28(%rsp), %r8
movq 0x40(%rsp), %rdi
movl (%rbx), %esi
shlq $0x20, %rsi
addq %rcx, %rsi
movq %rsi, (%rdi,%rcx,8)
movq $0x0, (%rax,%rcx,8)
incq %rcx
addq $0x30, %rbx
cmpq %rcx, %r8
jne 0x1b11a9
leaq (%rdi,%r8,8), %rsi
callq 0x19dd99
movl $0x1, %ebx
movl $0x1, %esi
movl $0x30, %edx
movq 0x38(%rsp), %r14
movq %r14, %rdi
callq 0x1edfb4
movq %rax, %r13
movq %r14, 0x28(%rax)
leal (%r12,%r12), %esi
movq %rax, %rdi
callq 0x1a3ee9
movq %r12, 0x98(%rsp)
leal 0x1(%r12), %r15d
xorl %ebp, %ebp
leaq 0x14(%rsp), %r14
movq %r13, 0x60(%rsp)
cmpq %rbx, 0x28(%rsp)
jne 0x1b1230
movslq %ebp, %r12
movq 0x40(%rsp), %rax
movq (%rax,%r12,8), %rsi
jmp 0x1b1249
movslq %ebp, %r12
movq 0x40(%rsp), %rax
movq (%rax,%r12,8), %rsi
movq (%rax,%rbx,8), %rax
xorq %rsi, %rax
shrq $0x20, %rax
je 0x1b1282
shrq $0x20, %rsi
movq %r13, %rdi
movq %r14, %rdx
callq 0x1a417a
shlq $0x20, %r12
movl %ebx, %ecx
subl %ebp, %ecx
movslq %ecx, %rcx
orq %r12, %rcx
movq 0x20(%r13), %rdx
movl %eax, %eax
movq %rcx, (%rdx,%rax,8)
cmpl $0x0, 0x14(%rsp)
je 0x1b1c9c
movl %ebx, %ebp
movq 0x60(%rsp), %r13
incq %rbx
cmpq %rbx, %r15
jne 0x1b121b
movl $0x1, %esi
movl $0x30, %edx
movq 0x38(%rsp), %rbx
movq %rbx, %rdi
callq 0x1edfb4
movq %rbx, 0x28(%rax)
movq %rax, 0x58(%rsp)
movq %rax, %rdi
movl $0x10, %esi
callq 0x1a42e8
movq 0x18(%rsp), %rbp
movq $0x0, 0x8(%rbp)
cmpq $0xf, 0x10(%rbp)
ja 0x1b12e5
movq $0x10, 0x10(%rbp)
movq (%rbp), %rdi
movl $0x80, %esi
callq 0x2370
movq %rax, (%rbp)
movl $0x30, %esi
movq 0x38(%rsp), %rdi
callq 0x1ee115
movq %rax, %r14
movq 0x90(%rsp), %rbx
movl %ebx, 0x8(%rax)
movq $0x0, (%rax)
movl $0xffffffff, 0xc(%rax)  # imm = 0xFFFFFFFF
movl $0x1, 0x14(%rax)
movl %ebx, %eax
shll $0xf, %eax
notl %eax
addl %ebx, %eax
movl %eax, %ecx
shrl $0xa, %ecx
xorl %eax, %ecx
leal (%rcx,%rcx,8), %eax
movl %eax, %ecx
shrl $0x6, %ecx
xorl %eax, %ecx
movl %ecx, %eax
shll $0xb, %eax
notl %eax
addl %ecx, %eax
movl %eax, %ecx
shrl $0x10, %ecx
xorl %eax, %ecx
movl %ecx, 0x10(%r14)
movq $0x0, 0x70(%rsp)
leaq 0x48(%rsp), %r12
movq %r12, %rdi
movq %r14, %rsi
xorl %edx, %edx
callq 0x1a0fd6
leaq 0x14(%rsp), %rdx
movq 0x58(%rsp), %r15
movq %r15, %rdi
movl %ebx, %esi
callq 0x1a4645
movq 0x20(%r15), %rcx
movl %eax, %eax
movq %rax, %rdx
shlq $0x7, %rdx
leaq (%rdx,%rax,8), %rax
movq %r14, 0x10(%rcx,%rax)
movapd 0x89e8e(%rip), %xmm0    # 0x23b220
movupd %xmm0, (%rcx,%rax)
movq (%r12), %rax
movq %r15, %r12
testq %rax, %rax
movq 0x30(%rsp), %r15
je 0x1b195d
cmpq $0x0, 0x8(%rsp)
sete %bl
movl $0x1, 0x10(%rsp)
cmpl $0x0, 0x2c(%rax)
je 0x1b195d
leaq 0x48(%rsp), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x1a1259
movl 0x4(%rax), %edx
shlq $0x20, %rdx
movq 0x8(%rbp), %rcx
orq %rcx, %rdx
movq %rax, 0x8(%rsp)
movq %rdx, (%rax)
movq (%rbp), %rax
cmpq 0x10(%rbp), %rcx
jne 0x1b141d
leaq (%rcx,%rcx), %rsi
testq %rcx, %rcx
movl $0x2, %ecx
cmoveq %rcx, %rsi
movq %rsi, 0x10(%rbp)
shlq $0x3, %rsi
movq %rax, %rdi
callq 0x2370
movq %rax, (%rbp)
movq 0x8(%rbp), %rcx
leaq 0x1(%rcx), %rdx
movq %rdx, 0x8(%rbp)
movq 0x8(%rsp), %rdx
movq %rdx, (%rax,%rcx,8)
movl 0x8(%rdx), %eax
movq 0x60(%rsp), %rcx
movl (%rcx), %edx
testl %edx, %edx
je 0x1b14ac
leal -0x1(%rdx), %edi
movl %edi, %r8d
andl %eax, %r8d
movq 0x10(%rcx), %r9
movl $0x1, %r10d
movl %r8d, %esi
movl %esi, %ecx
shrl $0x4, %ecx
movl (%r9,%rcx,4), %r11d
leal (%rsi,%rsi), %ecx
andl $0x1e, %ecx
movl %r11d, %ebp
shrl %cl, %ebp
testb $0x2, %bpl
jne 0x1b1496
testb $0x1, %bpl
jne 0x1b1484
movq 0x60(%rsp), %r14
movq 0x18(%r14), %r14
movl %esi, %r15d
cmpl %eax, (%r14,%r15,4)
je 0x1b1496
addl %r10d, %esi
andl %edi, %esi
incl %r10d
cmpl %r8d, %esi
jne 0x1b1452
jmp 0x1b16d0
shrl %cl, %r11d
testb $0x3, %r11b
cmovnel %edx, %esi
movq 0x30(%rsp), %r15
movq 0x18(%rsp), %rbp
jmp 0x1b14ae
xorl %esi, %esi
cmpl %edx, %esi
sete %cl
notb %bl
orb %cl, %bl
testb $0x1, %bl
jne 0x1b16d0
movq 0x60(%rsp), %rax
movq 0x20(%rax), %rax
movl %esi, %ecx
movq (%rax,%rcx,8), %rax
testl %eax, %eax
movq 0x68(%rsp), %r12
movq 0xa0(%rsp), %r13
jle 0x1b16b1
movq 0x8(%rsp), %rcx
movl 0x4(%rcx), %ecx
xorps %xmm0, %xmm0
cvtsi2sd %ecx, %xmm0
movq %rax, %rdx
sarq $0x20, %rdx
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
movq 0x40(%rsp), %r10
movslq (%r10,%rdx,8), %rsi
leaq (%rsi,%rsi,2), %rsi
shlq $0x4, %rsi
movl 0xc(%r15,%rsi), %r9d
testl %r9d, %r9d
js 0x1b15bb
addq %r15, %rsi
movl 0x4(%rsi), %ebx
movl 0x14(%rsi), %edi
movl %edi, %r10d
andl $0x7fffffff, %r10d      # imm = 0x7FFFFFFF
je 0x1b15c3
testl %ebx, %ebx
js 0x1b164a
cmpl $0x40000000, %r9d       # imm = 0x40000000
jb 0x1b156d
cmpl %ecx, %ebx
jne 0x1b156d
movq 0x8(%rsp), %r8
movl 0x10(%r8), %ebp
movl $0x1, %r8d
movl %ecx, %r11d
cmpl 0x8(%rsi), %ebp
movq 0x18(%rsp), %rbp
movq 0x30(%rsp), %r15
je 0x1b15c9
movl 0x1c(%rsi), %r8d
movl 0x20(%rsi), %r11d
subl %ebx, %r8d
movl %r8d, %ebp
negl %ebp
cmovsl %r8d, %ebp
movl %ebx, %r8d
subl %ecx, %r8d
movl %r8d, %r14d
negl %r14d
cmovsl %r8d, %r14d
movl %r11d, %r8d
shrl $0x1f, %r8d
addl %r11d, %r8d
sarl %r8d
subl %r8d, %ebp
xorl %r8d, %r8d
movl %ebx, %r11d
cmpl %ebp, %r14d
movq 0x18(%rsp), %rbp
movq 0x30(%rsp), %r15
jl 0x1b15c9
jmp 0x1b164d
movb $0x1, %r8b
jmp 0x1b1675
xorl %r8d, %r8d
movl %ebx, %r11d
movl 0x8(%rbp), %edi
decl %edi
movl %edi, 0x18(%rsi)
movl %ecx, 0x1c(%rsi)
movq 0x8(%rsp), %rbx
movl 0x10(%rbx), %edi
movl %edi, 0x24(%rsi)
movl $0x0, 0x20(%rsi)
movl 0x14(%rbx), %edi
shll $0x1f, %edi
orl %r10d, %edi
movl %edi, 0x14(%rsi)
testl %r11d, %r11d
js 0x1b164d
cmpl $0x40000000, %r9d       # imm = 0x40000000
jb 0x1b1614
cmpl %ecx, %r11d
jne 0x1b1614
movq 0x8(%rsp), %r9
movl 0x10(%r9), %r9d
cmpl 0x8(%rsi), %r9d
je 0x1b1642
leal 0x2710(%r11), %r9d
cmpl %ecx, %r9d
jge 0x1b164d
movl %r11d, %r9d
shrl $0x4, %r9d
cmpl %ecx, %r9d
jge 0x1b164d
xorps %xmm1, %xmm1
cvtsi2sd %r11d, %xmm1
mulsd 0x84724(%rip), %xmm1    # 0x235d60
ucomisd %xmm1, %xmm0
jbe 0x1b164d
movl $0x1, %r8d
jmp 0x1b164d
xorl %r8d, %r8d
leal 0x1(%rdi), %r9d
andl $0x7fffffff, %r9d       # imm = 0x7FFFFFFF
andl $0x80000000, %edi       # imm = 0x80000000
orl %r9d, %edi
movl %edi, 0x14(%rsi)
cmpl 0x24(%rsp), %r9d
setge %sil
orb %sil, %r8b
movq 0x40(%rsp), %r10
testq %r13, %r13
jne 0x1b16a5
movq 0x10(%r12), %rsi
cmpq $0x0, (%rsi,%rdx,8)
setne %dil
xorb $0x1, %r8b
orb %dil, %r8b
jne 0x1b16a5
movq $0x1, (%rsi,%rdx,8)
movq 0x70(%rsp), %rsi
incl %esi
movq %rsi, 0x70(%rsp)
incq %rdx
decq %rax
jne 0x1b1504
movq 0x70(%rsp), %rax
cmpl 0x98(%rsp), %eax
movq 0x58(%rsp), %r12
je 0x1b195d
movq 0x8(%rsp), %rax
movl 0x8(%rax), %eax
movq 0x50(%rsp), %rbx
movq 0xb0(%rsp), %rdx
movq 0x28(%rdx), %rcx
movl %eax, %eax
movq (%rcx,%rax,8), %rsi
testl %esi, %esi
jle 0x1b1943
movq %rsi, %rax
shrq $0x20, %rax
leaq (%rax,%rax,2), %rdi
shlq $0x3, %rdi
addq 0x8(%rdx), %rdi
andl $0x7fffffff, %esi       # imm = 0x7FFFFFFF
xorl %ebp, %ebp
movq %rsi, 0x80(%rsp)
movq %rdi, 0x78(%rsp)
leaq (,%rbp,2), %rax
addq %rbp, %rax
movq 0x8(%rsp), %rcx
movl 0x4(%rcx), %r14d
addq (%rdi,%rax,8), %r14
cmpl %ebx, %r14d
jg 0x1b1937
leaq (%rdi,%rax,8), %r15
movl 0x8(%r15), %esi
movq %r12, %rdi
leaq 0x14(%rsp), %rdx
callq 0x1a4645
movl %eax, %eax
movq %rax, %rcx
shlq $0x7, %rcx
leaq (%rcx,%rax,8), %r13
addq 0x20(%r12), %r13
cmpl $0x0, 0x14(%rsp)
je 0x1b1778
movapd 0x8e362(%rip), %xmm0    # 0x23fad0
movupd %xmm0, (%r13)
xorl %eax, %eax
jmp 0x1b177c
movl (%r13), %eax
cmpl 0x24(%rsp), %eax
jge 0x1b186b
movl 0x8(%r15), %ebx
movl $0x30, %esi
movq 0x38(%rsp), %rdi
callq 0x1ee115
movq %rax, %r12
movl %ebx, 0x8(%rax)
movq 0x50(%rsp), %rbx
shlq $0x20, %r14
movslq 0x10(%rsp), %rax
orq %r14, %rax
movq %rax, (%r12)
movl $0x1, 0x14(%r12)
movq 0x18(%rsp), %rax
movl 0x8(%rax), %eax
decl %eax
movl %eax, 0xc(%r12)
movl 0x8(%r15), %eax
movl %eax, %ecx
shll $0xf, %ecx
notl %ecx
addl %eax, %ecx
movl %ecx, %eax
shrl $0xa, %eax
xorl %ecx, %eax
leal (%rax,%rax,8), %eax
movl %eax, %ecx
shrl $0x6, %ecx
xorl %eax, %ecx
movl %ecx, %eax
shll $0xb, %eax
notl %eax
addl %ecx, %eax
movl %eax, %ecx
shrl $0x10, %ecx
xorl %eax, %ecx
movq 0x8(%rsp), %rax
addl 0x10(%rax), %ecx
movl %ecx, 0x10(%r12)
movl 0x14(%rax), %eax
movl %eax, 0x14(%r12)
leaq 0x48(%rsp), %rdi
movq %r12, %rsi
xorl %edx, %edx
callq 0x1a0fd6
movslq (%r13), %rax
leal 0x1(%rax), %ecx
movl %ecx, (%r13)
movq %r12, 0x10(%r13,%rax,8)
movl $0x0, %ecx
testq %rax, %rax
je 0x1b191c
movq (%r12), %rdx
leaq -0x1(%rax), %rsi
movq %rsi, %rcx
shrq %rcx
movq 0x10(%r13,%rcx,8), %rdi
cmpq (%rdi), %rdx
jb 0x1b1919
movq %rdi, 0x10(%r13,%rax,8)
movq %rcx, %rax
cmpq $0x1, %rsi
ja 0x1b1840
jmp 0x1b191c
movq 0x10(%r13), %rsi
cmpl %r14d, 0x4(%rsi)
jle 0x1b192a
leaq 0x48(%rsp), %r12
movq %r12, %rdi
xorl %edx, %edx
callq 0x1a1259
testq %rax, %rax
je 0x1b1c56
movq %r12, %rdi
leaq 0x10(%r13), %r12
shlq $0x20, %r14
movl 0x10(%rsp), %esi
movl %esi, %ecx
orq %r14, %rcx
movq %rcx, (%rax)
movq 0x18(%rsp), %rcx
movl 0x8(%rcx), %ecx
decl %ecx
movl %ecx, 0xc(%rax)
movl 0x8(%r15), %ecx
movl %ecx, %edx
shll $0xf, %edx
notl %edx
addl %ecx, %edx
movl %edx, %ecx
shrl $0xa, %ecx
xorl %edx, %ecx
leal (%rcx,%rcx,8), %ecx
movl %ecx, %edx
shrl $0x6, %edx
xorl %ecx, %edx
movl %edx, %ecx
shll $0xb, %ecx
notl %ecx
addl %edx, %ecx
movl %ecx, %edx
shrl $0x10, %edx
xorl %ecx, %edx
movq 0x8(%rsp), %rcx
addl 0x10(%rcx), %edx
incl %esi
movl %esi, 0x10(%rsp)
movl %edx, 0x10(%rax)
movl 0x14(%rcx), %ecx
movl %ecx, 0x14(%rax)
movq %rax, %rsi
xorl %edx, %edx
callq 0x1a0fd6
movslq (%r13), %rsi
xorl %edi, %edi
movq %r12, %rdx
movq 0x58(%rsp), %r12
callq 0x1a1774
jmp 0x1b192a
movq %rax, %rcx
incl 0x10(%rsp)
movq %r12, 0x10(%r13,%rcx,8)
movq 0x58(%rsp), %r12
movq 0x80(%rsp), %rsi
movq 0x78(%rsp), %rdi
incq %rbp
cmpq %rsi, %rbp
jne 0x1b1717
movq 0x48(%rsp), %rax
movb $0x1, %bl
testq %rax, %rax
movq 0x30(%rsp), %r15
movq 0x18(%rsp), %rbp
jne 0x1b13bd
testq %r12, %r12
je 0x1b1999
movq 0x18(%r12), %rsi
movq 0x28(%r12), %r14
movq %r14, %rdi
callq 0x1ee04f
movq 0x10(%r12), %rsi
movq %r14, %rdi
callq 0x1ee04f
movq 0x20(%r12), %rsi
movq %r14, %rdi
callq 0x1ee04f
movq %r14, %rdi
movq %r12, %rsi
callq 0x1ee04f
leaq 0x14(%r15), %rcx
xorl %eax, %eax
movl $0x7fffffff, %edx       # imm = 0x7FFFFFFF
movq 0x28(%rsp), %rbx
movq %rbx, %rsi
movq 0xa8(%rsp), %r12
movq 0x68(%rsp), %r13
movl (%rcx), %edi
andl %edx, %edi
cmpl $0x1, %edi
sbbl $-0x1, %eax
addq $0x30, %rcx
decq %rsi
jne 0x1b19b9
testq %r12, %r12
je 0x1b1c3b
testl %eax, %eax
je 0x1b1c3b
movq $0x0, (%r13)
movq 0x8(%rbp), %rdx
movq 0x10(%r13), %r14
cmpq %rdx, 0x8(%r13)
jae 0x1b1a4a
decq %rdx
movq %rdx, %rax
shrq %rax
orq %rdx, %rax
movq %rax, %rcx
shrq $0x2, %rcx
orq %rax, %rcx
movq %rcx, %rax
shrq $0x4, %rax
orq %rcx, %rax
movq %rax, %rcx
shrq $0x8, %rcx
orq %rax, %rcx
movq %rcx, %rax
shrq $0x10, %rax
orq %rcx, %rax
leaq 0x1(%rax), %rcx
movq %rcx, 0x8(%r13)
leaq 0x8(,%rax,8), %rsi
movq %r14, %rdi
callq 0x2370
movq %rax, %r14
movq %rax, 0x10(%r13)
movq 0x8(%rbp), %rdx
shlq $0x3, %rdx
movq %r14, %rdi
xorl %esi, %esi
callq 0x20e0
cmpq $0x0, 0xa0(%rsp)
je 0x1b1a8d
movq %r12, %rdi
movq %r13, %rsi
movq %rbp, %rdx
movl %ebx, %ecx
movq %r15, %r8
movl 0x24(%rsp), %r9d
movss 0x8c(%rsp), %xmm0
callq 0x1d06ed
cmpl $0x1, %eax
jne 0x1b1c3b
leaq 0x18(%r15), %rax
testl $0x7fffffff, -0x4(%rax) # imm = 0x7FFFFFFF
je 0x1b1aba
cmpl $0x0, -0x14(%rax)
js 0x1b1aba
movslq (%rax), %rdx
testq %rdx, %rdx
js 0x1b1aba
movq (%rbp), %rsi
movq (%rsi,%rdx,8), %rdx
movl (%rdx), %edx
movq $0x1, (%r14,%rdx,8)
addq $0x30, %rax
decq %rbx
jne 0x1b1a91
movq 0x8(%rbp), %rax
testl %eax, %eax
jle 0x1b1b02
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
incq %rax
cmpq $0x0, -0x10(%r14,%rax,8)
je 0x1b1af5
movq (%rbp), %rcx
movq -0x10(%rcx,%rax,8), %rcx
movslq 0xc(%rcx), %rcx
testq %rcx, %rcx
js 0x1b1af5
movq $0x1, (%r14,%rcx,8)
decq %rax
cmpq $0x1, %rax
ja 0x1b1ad3
movq 0x8(%rbp), %rax
xorl %ebx, %ebx
testq %rax, %rax
je 0x1b1b4a
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
xorl %edx, %edx
movl %ebx, %eax
xorl %ebx, %ebx
cmpq $0x0, (%r14,%rdx,8)
setne %bl
movl %eax, %esi
cmoveq %rcx, %rsi
addl %eax, %ebx
movq %rsi, (%r14,%rdx,8)
incq %rdx
movq 0x8(%rbp), %rax
cmpq %rdx, %rax
ja 0x1b1b10
movl %ebx, %ebx
jmp 0x1b1b4c
addq $0xb8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
xorl %eax, %eax
movq 0x8(%r12), %rcx
addq %rbx, %rcx
cmpq %rcx, 0x10(%r12)
jae 0x1b1bb5
decq %rcx
movq %rcx, %rax
shrq %rax
orq %rcx, %rax
movq %rax, %rcx
shrq $0x2, %rcx
orq %rax, %rcx
movq %rcx, %rax
shrq $0x4, %rax
orq %rcx, %rax
movq %rax, %rcx
shrq $0x8, %rcx
orq %rax, %rcx
movq %rcx, %rax
shrq $0x10, %rax
orq %rcx, %rax
leaq 0x1(%rax), %rcx
movq %rcx, 0x10(%r12)
movq (%r12), %rdi
leaq 0x4(,%rax,4), %rax
leaq (%rax,%rax,2), %rsi
callq 0x2370
movq %rax, (%r12)
movq 0x8(%rbp), %rax
testq %rax, %rax
je 0x1b1c15
xorl %ecx, %ecx
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movq (%r14,%rcx,8), %rsi
cmpq %rdx, %rsi
je 0x1b1c0d
movq 0x8(%r12), %rdi
leaq (%rsi,%rsi,2), %rsi
shlq $0x2, %rsi
addq (%r12), %rsi
leaq (%rdi,%rdi,2), %rdi
movq (%rbp), %r8
movq (%r8,%rcx,8), %r8
movl 0x8(%r8), %r9d
movl %r9d, (%rsi,%rdi,4)
movl 0x4(%r8), %r9d
movl %r9d, 0x4(%rsi,%rdi,4)
movslq 0xc(%r8), %r8
testq %r8, %r8
js 0x1b1c05
movl (%r14,%r8,8), %r8d
leaq (%rsi,%rdi,4), %rsi
movl %r8d, 0x8(%rsi)
incq %rcx
cmpq %rcx, %rax
jne 0x1b1bc1
addq %rbx, 0x8(%r12)
addq $0x18, %r15
movq 0x28(%rsp), %rcx
movslq (%r15), %rax
testq %rax, %rax
js 0x1b1c32
movl (%r14,%rax,8), %eax
movl %eax, (%r15)
addq $0x30, %r15
decq %rcx
jne 0x1b1c23
movq 0x38(%rsp), %rdi
addq $0xb8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x1ee011
movq 0xe3383(%rip), %rax     # 0x294fe0
movq (%rax), %rdi
movl (%r13), %edx
movq 0x10(%r13), %rax
movq (%rax), %r8
movq %r8, %rcx
shrq $0x20, %rcx
subq $0x8, %rsp
leaq 0x8e14e(%rip), %rsi     # 0x23fdcb
movl %r14d, %r9d
xorl %eax, %eax
pushq 0xa0(%rsp)
pushq %rbx
pushq 0xa8(%rsp)
callq 0x22b0
addq $0x20, %rsp
jmp 0x1b1c3b
leaq 0x8e0af(%rip), %rdi     # 0x23fd52
leaq 0x8dfb1(%rip), %rsi     # 0x23fc5b
leaq 0x9077d(%rip), %rcx     # 0x24242e
movl $0x3702, %edx           # imm = 0x3702
callq 0x2110