// File: /workspace/github_cpp_makefile_star2_O1/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, 0x84(%rsp)
movq %r9, 0xa0(%rsp)
movq %rdx, 0x88(%rsp)
movq %rsi, 0xa8(%rsp)
movq 0x120(%rsp), %rax
movq %rax, 0x98(%rsp)
movq 0x118(%rsp), %rsi
movq 0x110(%rsp), %rax
movq %rax, 0x28(%rsp)
movq 0x108(%rsp), %r9
movq 0x100(%rsp), %rbp
movq 0xf8(%rsp), %rax
movq %rax, 0x60(%rsp)
movl 0xf0(%rsp), %eax
movq $0x0, 0x50(%rsp)
movq %rcx, 0x8(%rsp)
testl %ecx, %ecx
jle 0x1a8ac1
movq %r8, %r14
movq %rsi, 0x18(%rsp)
movl 0x8(%rsp), %ecx
movq %rcx, 0x40(%rsp)
shlq $0x4, %rcx
leaq (%rcx,%rcx,2), %rcx
xorl %edx, %edx
movl $0x80000000, %esi       # imm = 0x80000000
movq 0x60(%rsp), %rbx
cmpl $0x0, 0xc(%r14,%rdx)
js 0x1a7ea5
movl $0xffffffff, 0x1c(%r14,%rdx) # imm = 0xFFFFFFFF
movl 0x14(%r14,%rdx), %r8d
andl %esi, %r8d
jmp 0x1a7eb9
movl $0x0, 0x1c(%r14,%rdx)
movl 0x14(%r14,%rdx), %r8d
andl %esi, %r8d
incl %r8d
movl %r8d, 0x14(%r14,%rdx)
movl $0xffffffff, 0x18(%r14,%rdx) # imm = 0xFFFFFFFF
addq $0x30, %rdx
cmpq %rdx, %rcx
jne 0x1a7e8a
movq %r9, 0x38(%rsp)
cmpl $0xf, %eax
movl $0xf, %ecx
cmovll %eax, %ecx
movl %ecx, 0x24(%rsp)
movl $0x4000, %esi           # imm = 0x4000
callq 0x1e355c
movq %rax, 0x30(%rsp)
movq $0x0, (%rbx)
movq 0x40(%rsp), %rax
cmpq %rax, 0x8(%rbx)
jae 0x1a7f5b
movq 0x40(%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(%rbx)
movq 0x10(%rbx), %rdi
leaq 0x8(,%rcx,8), %rsi
callq 0x2370
movq %rax, 0x10(%rbx)
movq 0x10(%rbx), %rax
movq 0x8(%rsp), %rcx
cmpl $0x2, %ecx
movl $0x1, %ebx
cmovgel %ecx, %ebx
xorl %ecx, %ecx
movq %r14, 0x78(%rsp)
movl (%r14), %esi
shlq $0x20, %rsi
addq %rcx, %rsi
movq %rsi, (%rbp,%rcx,8)
movq $0x0, (%rax,%rcx,8)
incq %rcx
addq $0x30, %r14
cmpq %rcx, %rbx
jne 0x1a7f76
movq 0x40(%rsp), %rax
leaq (,%rax,8), %rsi
addq %rbp, %rsi
movq %rbp, %rdi
callq 0x194fef
movl $0x1, %r15d
movl $0x1, %esi
movl $0x30, %edx
movq 0x30(%rsp), %r14
movq %r14, %rdi
callq 0x1e3590
movq %rax, %rdi
movq %r14, 0x28(%rax)
movq 0x8(%rsp), %rax
leal (%rax,%rax), %esi
movq %rdi, 0x48(%rsp)
callq 0x19b275
negq %rbx
xorl %eax, %eax
leaq 0x4(%rsp), %r14
movq 0x48(%rsp), %r12
movslq %eax, %r13
cmpq %r15, 0x40(%rsp)
je 0x1a8010
movq (%rbp,%r13,8), %rcx
xorq (%rbp,%r15,8), %rcx
shrq $0x20, %rcx
je 0x1a8046
movl 0x4(%rbp,%r13,8), %esi
movq %r12, %rdi
movq %r14, %rdx
callq 0x19b548
movq %r15, %rcx
subq %r13, %rcx
shlq $0x20, %r13
orq %rcx, %r13
movq 0x20(%r12), %rcx
movl %eax, %eax
movq %r13, (%rcx,%rax,8)
cmpl $0x0, 0x4(%rsp)
je 0x1a8ad3
movl %r15d, %eax
leaq (%rbx,%r15), %rcx
incq %rcx
incq %r15
cmpq $0x1, %rcx
jne 0x1a7ff6
movl $0x1, %esi
movl $0x30, %edx
movq 0x30(%rsp), %rbx
movq %rbx, %rdi
callq 0x1e3590
movq %rax, %r15
movq %rbx, 0x28(%rax)
movq %rax, %rdi
movl $0x10, %esi
callq 0x19b6a3
movq 0x38(%rsp), %r13
movq $0x0, 0x8(%r13)
cmpq $0xf, 0x10(%r13)
ja 0x1a80af
movq $0x10, 0x10(%r13)
movq (%r13), %rdi
movl $0x80, %esi
callq 0x2370
movq %rax, (%r13)
movl $0x30, %esi
movq 0x30(%rsp), %rdi
callq 0x1e36fd
movq %rax, %r14
movq 0x88(%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)
leaq 0x50(%rsp), %rdi
movq %r14, %rsi
xorl %edx, %edx
callq 0x198259
leaq 0x4(%rsp), %rdx
movq %r15, %rdi
movl %ebx, %esi
callq 0x19ba1b
movq %r15, 0x90(%rsp)
movq 0x20(%r15), %rcx
movl %eax, %eax
movq %rax, %rdx
shlq $0x7, %rdx
leaq (%rdx,%rax,8), %rax
movapd 0x86e82(%rip), %xmm0    # 0x22efd0
movupd %xmm0, (%rcx,%rax)
movq %r14, 0x10(%rcx,%rax)
cmpq $0x0, 0x18(%rsp)
sete %bl
movl $0x1, (%rsp)
movl $0x0, 0x5c(%rsp)
movq 0x78(%rsp), %r12
movq %rbp, 0x10(%rsp)
movq 0x48(%rsp), %r15
movq 0x50(%rsp), %rax
testq %rax, %rax
je 0x1a8794
cmpl $0x0, 0x2c(%rax)
je 0x1a8794
leaq 0x50(%rsp), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x19852a
movq %rax, %r14
movl 0x4(%rax), %eax
shlq $0x20, %rax
movq 0x8(%r13), %rcx
orq %rcx, %rax
movq %rax, (%r14)
movq 0x10(%r13), %rax
cmpq %rax, %rcx
jne 0x1a81e7
leaq (%rax,%rax), %rsi
testq %rax, %rax
movl $0x2, %eax
cmoveq %rax, %rsi
movq %rsi, 0x10(%r13)
movq (%r13), %rdi
shlq $0x3, %rsi
callq 0x2370
movq %rax, (%r13)
movq (%r13), %rax
movq 0x8(%r13), %rcx
leaq 0x1(%rcx), %rdx
movq %rdx, 0x8(%r13)
movq %r14, (%rax,%rcx,8)
movl (%r15), %eax
testl %eax, %eax
movq %r14, 0x18(%rsp)
je 0x1a827a
movl 0x8(%r14), %esi
leal -0x1(%rax), %edi
movl %edi, %r8d
andl %esi, %r8d
movq 0x10(%r15), %r9
movl $0x1, %r10d
movl %r8d, %edx
movl %edx, %ecx
shrl $0x4, %ecx
movl (%r9,%rcx,4), %r11d
leal (%rdx,%rdx), %ecx
andl $0x1e, %ecx
movl %r11d, %ebp
shrl %cl, %ebp
testb $0x2, %bpl
jne 0x1a8269
testb $0x1, %bpl
jne 0x1a8258
movq 0x18(%r15), %r14
movl %edx, %r15d
cmpl %esi, (%r14,%r15,4)
movq 0x18(%rsp), %r14
movq 0x48(%rsp), %r15
je 0x1a8269
addl %r10d, %edx
andl %edi, %edx
incl %r10d
cmpl %r8d, %edx
jne 0x1a8221
movl %eax, %edx
jmp 0x1a8273
shrl %cl, %r11d
testb $0x3, %r11b
cmovnel %eax, %edx
movq 0x10(%rsp), %rbp
jmp 0x1a827c
xorl %edx, %edx
cmpl %eax, %edx
sete %al
notb %bl
orb %al, %bl
testb $0x1, %bl
jne 0x1a8470
movq 0x20(%r15), %rax
movl %edx, %ecx
movq (%rax,%rcx,8), %rax
testl %eax, %eax
movq 0x60(%rsp), %rbx
jle 0x1a8455
movl 0x4(%r14), %ecx
xorps %xmm0, %xmm0
cvtsi2sd %ecx, %xmm0
movq %rax, %rdx
sarq $0x20, %rdx
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
movslq (%rbp,%rdx,8), %rsi
leaq (%rsi,%rsi,2), %rsi
shlq $0x4, %rsi
movl 0xc(%r12,%rsi), %r8d
testl %r8d, %r8d
js 0x1a8312
addq %r12, %rsi
xorl %edi, %edi
movl 0x14(%rsi), %r9d
movl $0x7fffffff, %r10d      # imm = 0x7FFFFFFF
andl %r10d, %r9d
je 0x1a830d
movl 0x4(%rsi), %r10d
testl %r10d, %r10d
js 0x1a835b
cmpl $0x40000000, %r8d       # imm = 0x40000000
jb 0x1a831a
cmpl %ecx, %r10d
jne 0x1a831a
movl 0x10(%r14), %r11d
cmpl 0x8(%rsi), %r11d
jne 0x1a831a
movl $0x1, %edi
xorl %r10d, %r10d
jmp 0x1a835e
movb $0x1, %r8b
jmp 0x1a841c
movl 0x1c(%rsi), %r11d
subl %r10d, %r11d
movl %r11d, %ebx
negl %ebx
cmovsl %r11d, %ebx
subl %ecx, %r10d
movl %r10d, %r11d
negl %r11d
cmovsl %r10d, %r11d
movl 0x20(%rsi), %r10d
movl %r10d, %ebp
shrl $0x1f, %ebp
addl %r10d, %ebp
sarl %ebp
subl %ebp, %ebx
movq 0x10(%rsp), %rbp
cmpl %ebx, %r11d
movq 0x60(%rsp), %rbx
setge %r10b
jmp 0x1a835e
movb $0x1, %r10b
testb %r10b, %r10b
jne 0x1a83f3
movl 0x8(%r13), %r10d
decl %r10d
movl %r10d, 0x18(%rsi)
movl %ecx, 0x1c(%rsi)
movl 0x10(%r14), %r10d
movl %r10d, 0x24(%rsi)
movl $0x0, 0x20(%rsi)
movl 0x14(%r14), %r10d
shll $0x1f, %r10d
orl %r9d, %r10d
movl %r10d, 0x14(%rsi)
movl 0x4(%rsi), %r9d
testl %r9d, %r9d
js 0x1a83f3
cmpl $0x40000000, %r8d       # imm = 0x40000000
jb 0x1a83ba
cmpl %ecx, %r9d
jne 0x1a83ba
movl 0x10(%r14), %r10d
movl $0x1, %r8d
cmpl 0x8(%rsi), %r10d
je 0x1a83f6
leal 0x2710(%r9), %r8d
cmpl %ecx, %r8d
jge 0x1a83f3
movl %r9d, %r8d
shrl $0x4, %r8d
cmpl %ecx, %r8d
jge 0x1a83f3
xorps %xmm1, %xmm1
cvtsi2sd %r9d, %xmm1
mulsd 0x81786(%rip), %xmm1    # 0x229b68
ucomisd %xmm1, %xmm0
movl %edi, %r8d
jbe 0x1a83f6
movl $0x1, %r8d
jmp 0x1a83f6
movl %edi, %r8d
movl 0x14(%rsi), %edi
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
cmpq $0x0, 0x98(%rsp)
jne 0x1a8449
movq 0x10(%rbx), %rsi
cmpq $0x0, (%rsi,%rdx,8)
setne %dil
xorb $0x1, %r8b
orb %dil, %r8b
jne 0x1a8449
movq $0x1, (%rsi,%rdx,8)
incl 0x5c(%rsp)
incq %rdx
decq %rax
jne 0x1a82bc
xorl %ecx, %ecx
movl 0x5c(%rsp), %eax
cmpl 0x8(%rsp), %eax
sete %al
jne 0x1a8470
movb %al, %cl
shll $0x4, %ecx
movl %ecx, %eax
jmp 0x1a8781
movq 0xa8(%rsp), %rdx
movq 0x28(%rdx), %rax
movl 0x8(%r14), %ecx
movq (%rax,%rcx,8), %rcx
xorl %eax, %eax
testl %ecx, %ecx
jle 0x1a8781
movq %rcx, %rax
shrq $0x20, %rax
leaq (%rax,%rax,2), %rsi
shlq $0x3, %rsi
addq 0x8(%rdx), %rsi
andl $0x7fffffff, %ecx       # imm = 0x7FFFFFFF
xorl %ebx, %ebx
movq %rcx, 0x70(%rsp)
movq %rsi, 0x68(%rsp)
leaq (%rbx,%rbx,2), %rax
movl 0x4(%r14), %r12d
addq (%rsi,%rax,8), %r12
movl $0x18, %r13d
cmpl 0xa0(%rsp), %r12d
jg 0x1a874f
leaq (%rsi,%rax,8), %r14
movl 0x8(%r14), %esi
movq 0x90(%rsp), %r13
movq %r13, %rdi
leaq 0x4(%rsp), %rdx
callq 0x19ba1b
movl %eax, %eax
movq %rax, %rcx
shlq $0x7, %rcx
leaq (%rcx,%rax,8), %rbp
addq 0x20(%r13), %rbp
cmpl $0x0, 0x4(%rsp)
je 0x1a8518
movq $0x0, (%rbp)
movq $-0x1, 0x8(%rbp)
movl 0x24(%rsp), %eax
cmpl %eax, (%rbp)
jge 0x1a860a
movl 0x8(%r14), %r15d
movl $0x30, %esi
movq 0x30(%rsp), %rdi
callq 0x1e36fd
movq %rax, %r13
movl %r15d, 0x8(%rax)
shlq $0x20, %r12
movslq (%rsp), %rax
orq %r12, %rax
movq %rax, (%r13)
movl $0xffffffff, 0xc(%r13)  # imm = 0xFFFFFFFF
movl $0x1, 0x14(%r13)
movq 0x38(%rsp), %rax
movl 0x8(%rax), %eax
decl %eax
movl %eax, 0xc(%r13)
movl 0x8(%r14), %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 0x18(%rsp), %r14
addl 0x10(%r14), %ecx
movl %ecx, 0x10(%r13)
movl 0x14(%r14), %eax
movl %eax, 0x14(%r13)
leaq 0x50(%rsp), %rdi
movq %r13, %rsi
xorl %edx, %edx
callq 0x198259
movslq (%rbp), %rax
leal 0x1(%rax), %ecx
movl %ecx, (%rbp)
movq %r13, 0x10(%rbp,%rax,8)
testq %rax, %rax
je 0x1a86c6
movq (%r13), %rdx
movq 0x48(%rsp), %r15
leaq -0x1(%rax), %rsi
movq %rsi, %rcx
shrq %rcx
movq 0x10(%rbp,%rcx,8), %rdi
cmpq (%rdi), %rdx
jb 0x1a86d0
movq %rdi, 0x10(%rbp,%rax,8)
movq %rcx, %rax
cmpq $0x1, %rsi
ja 0x1a85df
jmp 0x1a86d3
movq 0x10(%rbp), %rsi
xorl %r13d, %r13d
cmpl %r12d, 0x4(%rsi)
jle 0x1a873b
leaq 0x50(%rsp), %r13
movq %r13, %rdi
xorl %edx, %edx
callq 0x19852a
testq %rax, %rax
je 0x1a86e5
leaq 0x10(%rbp), %rcx
movq %rcx, 0xb0(%rsp)
shlq $0x20, %r12
movl (%rsp), %esi
movl %esi, %ecx
orq %r12, %rcx
movq %rcx, (%rax)
movq 0x38(%rsp), %rcx
movl 0x8(%rcx), %ecx
decl %ecx
movl %ecx, 0xc(%rax)
movl 0x8(%r14), %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 0x18(%rsp), %r14
addl 0x10(%r14), %edx
incl %esi
movl %esi, (%rsp)
movl %edx, 0x10(%rax)
movl 0x14(%r14), %ecx
movl %ecx, 0x14(%rax)
movq %r13, %rdi
xorl %r13d, %r13d
movq %rax, %rsi
xorl %edx, %edx
callq 0x198259
movslq (%rbp), %rsi
xorl %edi, %edi
movq 0xb0(%rsp), %rdx
callq 0x198a96
jmp 0x1a86de
movq %rax, %rcx
movq 0x48(%rsp), %r15
jmp 0x1a86d3
movq %rax, %rcx
incl (%rsp)
movq %r13, 0x10(%rbp,%rcx,8)
xorl %r13d, %r13d
movq 0x10(%rsp), %rbp
jmp 0x1a8745
movq 0xe18f4(%rip), %rax     # 0x289fe0
movq (%rax), %rdi
movl (%rbp), %edx
movq 0x10(%rbp), %rax
movq (%rax), %r8
movq %r8, %rcx
shrq $0x20, %rcx
subq $0x8, %rsp
leaq 0x8b3f0(%rip), %rsi     # 0x233afb
movl %r12d, %r9d
xorl %eax, %eax
pushq 0x10(%rsp)
pushq 0xb0(%rsp)
pushq 0xa0(%rsp)
callq 0x22b0
addq $0x20, %rsp
movq 0x30(%rsp), %rdi
callq 0x1e35f4
movl $0x1, %r13d
movq 0x10(%rsp), %rbp
movq 0x18(%rsp), %r14
movq 0x70(%rsp), %rcx
movq 0x68(%rsp), %rsi
cmpl $0x18, %r13d
je 0x1a875a
testl %r13d, %r13d
jne 0x1a8774
incq %rbx
cmpq %rcx, %rbx
jne 0x1a84b3
movq 0x78(%rsp), %r12
movq 0x38(%rsp), %r13
xorl %eax, %eax
jmp 0x1a8781
movl %r13d, %eax
movq 0x78(%rsp), %r12
movq 0x38(%rsp), %r13
movb $0x1, %bl
testl %eax, %eax
je 0x1a817f
cmpl $0x10, %eax
jne 0x1a8ac1
movq 0x90(%rsp), %rbx
testq %rbx, %rbx
je 0x1a87d4
movq 0x18(%rbx), %rsi
movq 0x28(%rbx), %r14
movq %r14, %rdi
callq 0x1e3632
movq 0x10(%rbx), %rsi
movq %r14, %rdi
callq 0x1e3632
movq 0x20(%rbx), %rsi
movq %r14, %rdi
callq 0x1e3632
movq %r14, %rdi
movq %rbx, %rsi
callq 0x1e3632
movq 0x8(%rsp), %rcx
cmpl $0x2, %ecx
movl $0x1, %eax
cmovgel %ecx, %eax
shlq $0x4, %rax
leaq (%rax,%rax,2), %rcx
xorl %edx, %edx
movl $0x7fffffff, %esi       # imm = 0x7FFFFFFF
xorl %eax, %eax
movl 0x14(%r12,%rdx), %edi
andl %esi, %edi
cmpl $0x1, %edi
sbbl $-0x1, %eax
addq $0x30, %rdx
cmpq %rdx, %rcx
jne 0x1a87f5
cmpq $0x0, 0x28(%rsp)
movq 0x60(%rsp), %rbx
je 0x1a8aa6
testl %eax, %eax
je 0x1a8aa6
movq $0x0, (%rbx)
movq 0x8(%r13), %rax
cmpq %rax, 0x8(%rbx)
jae 0x1a8886
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(%rbx)
movq 0x10(%rbx), %rdi
leaq 0x8(,%rcx,8), %rsi
callq 0x2370
movq %rax, 0x10(%rbx)
movq 0x10(%rbx), %r14
movq 0x8(%r13), %rdx
shlq $0x3, %rdx
movq %r14, %rdi
xorl %esi, %esi
callq 0x20e0
cmpq $0x0, 0x98(%rsp)
je 0x1a88d6
movq 0x28(%rsp), %rdi
movq %rbx, %rsi
movq %r13, %rdx
movq 0x40(%rsp), %rcx
movq %r12, %r8
movl 0x24(%rsp), %r9d
movss 0x84(%rsp), %xmm0
callq 0x1c6697
cmpl $0x1, %eax
jne 0x1a8aa6
movq 0x8(%rsp), %rcx
cmpl $0x2, %ecx
movl $0x1, %eax
cmovgel %ecx, %eax
shlq $0x4, %rax
leaq (%rax,%rax,2), %rax
xorl %ecx, %ecx
testl $0x7fffffff, 0x14(%r12,%rcx) # imm = 0x7FFFFFFF
je 0x1a891f
cmpl $0x0, 0x4(%r12,%rcx)
js 0x1a891f
movslq 0x18(%r12,%rcx), %rdx
testq %rdx, %rdx
js 0x1a891f
movq (%r13), %rsi
movq (%rsi,%rdx,8), %rdx
movl (%rdx), %edx
movq $0x1, (%r14,%rdx,8)
addq $0x30, %rcx
cmpq %rcx, %rax
jne 0x1a88f0
movq 0x8(%r13), %rax
testl %eax, %eax
jle 0x1a8963
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
incq %rax
cmpq $0x0, -0x10(%r14,%rax,8)
je 0x1a895a
movq (%r13), %rcx
movq -0x10(%rcx,%rax,8), %rcx
movslq 0xc(%rcx), %rcx
testq %rcx, %rcx
js 0x1a895a
movq $0x1, (%r14,%rcx,8)
decq %rax
cmpq $0x1, %rax
jg 0x1a8938
xorl %ebx, %ebx
cmpq $0x0, 0x8(%r13)
je 0x1a8996
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
xorl %ecx, %ecx
movl %ebx, %edx
xorl %ebx, %ebx
cmpq $0x0, (%r14,%rcx,8)
setne %bl
movl %edx, %esi
cmoveq %rax, %rsi
addl %edx, %ebx
movq %rsi, (%r14,%rcx,8)
incq %rcx
cmpq %rcx, 0x8(%r13)
ja 0x1a8973
movl %ebx, %ebx
movq 0x28(%rsp), %rcx
movq 0x8(%rcx), %rax
addq %rbx, %rax
cmpq %rax, 0x10(%rcx)
jae 0x1a8a00
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 0x28(%rsp), %r15
movq %rax, 0x10(%r15)
movq (%r15), %rdi
leaq 0x4(,%rcx,4), %rax
leaq (%rax,%rax,2), %rsi
callq 0x2370
movq %rax, (%r15)
movq 0x8(%r13), %rax
testq %rax, %rax
je 0x1a8a67
xorl %ecx, %ecx
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movq (%r14,%rcx,8), %rsi
cmpq %rdx, %rsi
je 0x1a8a5f
movq 0x28(%rsp), %r8
movq 0x8(%r8), %rdi
leaq (%rsi,%rsi,2), %rsi
shlq $0x2, %rsi
addq (%r8), %rsi
leaq (%rdi,%rdi,2), %rdi
movq (%r13), %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 0x1a8a57
movl (%r14,%r8,8), %r8d
leaq (%rsi,%rdi,4), %rsi
movl %r8d, 0x8(%rsi)
incq %rcx
cmpq %rcx, %rax
jne 0x1a8a10
movq 0x28(%rsp), %rax
addq %rbx, 0x8(%rax)
movq 0x8(%rsp), %rcx
cmpl $0x2, %ecx
movl $0x1, %eax
cmovgel %ecx, %eax
shlq $0x4, %rax
leaq (%rax,%rax,2), %rax
xorl %ecx, %ecx
movslq 0x18(%r12,%rcx), %rdx
testq %rdx, %rdx
js 0x1a8a9d
movl (%r14,%rdx,8), %edx
movl %edx, 0x18(%r12,%rcx)
addq $0x30, %rcx
cmpq %rcx, %rax
jne 0x1a8a8a
movq 0x30(%rsp), %rdi
addq $0xb8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x1e35f4
addq $0xb8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x8afa8(%rip), %rdi     # 0x233a82
leaq 0x8aeaa(%rip), %rsi     # 0x23398b
leaq 0x8d676(%rip), %rcx     # 0x23615e
movl $0x3702, %edx           # imm = 0x3702
callq 0x2110