// File: /workspace/github_cpp_makefile_star2_O2/chhylp123[P]hifiasm/inter.cpp
// Function: mg_gchain_gen(void*, void*, asg_t const*, int, unsigned long const*, mg_lchain_t const*, mg128_t const*, unsigned int, int, int)
mg_gchains_t *mg_gchain_gen(void *km_dst, void *km, const asg_t *g, int32_t n_u, const uint64_t *u, const mg_lchain_t *lc, const mg128_t *a,
							uint32_t hash, int32_t min_gc_cnt, int32_t min_gc_score)
{
	mg_gchains_t *gc;
	mg_llchain_t *tmp;
	int32_t i, j, k, st, n_g, n_a, s_tmp, n_tmp, m_tmp;
	KCALLOC(km_dst, gc, 1);
	// count the number of gchains and remaining anchors
	// filter out low-quality g_chains
	for (i = 0, st = 0, n_g = n_a = 0; i < n_u; ++i) {
		///nui: how many linear chaisn in i-th g_chain
		int32_t m = 0, nui = (int32_t)u[i];
		for (j = 0; j < nui; ++j) m += lc[st + j].cnt; // m is the number of anchors in this gchain
		if (m >= min_gc_cnt && (int64_t)(u[i]>>32) >= min_gc_score)
			++n_g, n_a += m;
		st += nui;
	}
	if (n_g == 0) return gc;

	// preallocate
	gc->km = km_dst;
	gc->n_gc = n_g, gc->n_a = n_a;
	KCALLOC(km_dst, gc->gc, n_g);///all graph chains
	KMALLOC(km_dst, gc->a, n_a);///all anchors, aka minimizers

	// core loop
	tmp = 0; s_tmp = n_tmp = m_tmp = 0;
	for (i = k = 0, st = 0, n_a = 0; i < n_u; ++i) {
		int32_t n_a0 = n_a, m = 0, nui = (int32_t)u[i]; ///nui: how many linear chaisn in i-th g_chain
		for (j = 0; j < nui; ++j) m += lc[st + j].cnt; ///how many minizers in i-th g_chain
		if (m >= min_gc_cnt && (int64_t)(u[i]>>32) >= min_gc_score) {
			mg_llchain_t *q;
			uint32_t h = hash;

			gc->gc[k].score = u[i]>>32; ///chain score
			gc->gc[k].off = s_tmp; ///all minimizers of k-th chain: gc->a[gc->gc[k].off, )

			for (j = 0; j < nui; ++j) {///how many linear chains
				const mg_lchain_t *p = &lc[st + j];
				h += __ac_Wang_hash(p->qs) + __ac_Wang_hash(p->re) + __ac_Wang_hash(p->v);
			}
			gc->gc[k].hash = __ac_Wang_hash(h);///hash key for the k-th graph chain

			if (n_tmp == m_tmp) KEXPAND(km, tmp, m_tmp);
			// copy the first lchain to gc->a[] and tmp[] (aka, gc->lc[])
			// for the first lchain, it is easy and we just copy all its anchors
			copy_lchain(&tmp[n_tmp++], &lc[st], &n_a, gc->a, a); 
			///0-th lchain has been stored
			///process the remaining chains
			for (j = 1; j < nui; ++j) { 
				const mg_lchain_t *l0 = &lc[st + j - 1], *l1 = &lc[st + j];
				if (!l1->inner_pre) { // bridging two segments; if l0 and l1 are at different reference
					int32_t s, n_pathv;
					mg_path_dst_t dst;
					mg_pathv_t *p;
					memset(&dst, 0, sizeof(mg_path_dst_t));
					dst.v = l0->v ^ 1;
					assert(l1->dist_pre >= 0);
					dst.target_dist = l1->dist_pre;
					dst.target_hash = l1->hash_pre;///hash value of the whole path
					dst.check_hash = 1;
					p = mg_shortest_k(km, g, l1->v^1, 1, &dst, dst.target_dist, MG_MAX_SHORT_K, &n_pathv);
					if (n_pathv == 0 || dst.target_hash != dst.hash)
						fprintf(stderr, "%c[%d] -> %c[%d], dist=%d, target_dist=%d\n", "><"[(l1->v^1)&1], l1->v^1, "><"[(l0->v^1)&1], l0->v^1, dst.dist, dst.target_dist);
					assert(n_pathv > 0);
					assert(dst.target_hash == dst.hash);
					for (s = n_pathv - 2; s >= 1; --s) { // path found in a backward way, so we need to reverse it
						if (n_tmp == m_tmp) KEXPAND(km, tmp, m_tmp);
						q = &tmp[n_tmp++];
						q->off = q->cnt = q->score = 0;
						q->v = p[s].v^1; // when reversing a path, we also need to flip the orientation
					}
					kfree(km, p);
					if (n_tmp == m_tmp) KEXPAND(km, tmp, m_tmp);
					copy_lchain(&tmp[n_tmp++], l1, &n_a, gc->a, a);
				}
				else { // if both of them are at the same linear chain, just merge them
					#if 1
					int32_t k;
					mg_llchain_t *t = &tmp[n_tmp - 1];//the last lchain, have alread done
					assert(l0->v == l1->v);
					// a[].x: ref_id(31)rev(1)r_pos(32)
 					// a[].y: weight(8)query_id(8)flag(8)span(8)q_pos(32)
					for (k = 0; k < l1->cnt; ++k) {
						const mg128_t *ak = &a[l1->off + k];
						if ((int32_t)ak->x > l0->re && (int32_t)ak->y > l0->qe)//find colinear anchors
							break;
					}
					assert(k < l1->cnt);
					t->cnt += l1->cnt - k, t->score += l1->score;
					memcpy(&gc->a[n_a], &a[l1->off + k], (l1->cnt - k) * sizeof(mg128_t));
					n_a += l1->cnt - k;
					#else // don't use this block; for debugging only
					if (n_tmp == m_tmp) KEXPAND(km, tmp, m_tmp);
					copy_lchain(&tmp[n_tmp++], l1, &n_a, gc->a, a);
					#endif
				}
			}
			gc->gc[k].cnt = n_tmp - s_tmp;
			gc->gc[k].n_anchor = n_a - n_a0;
			++k, s_tmp = n_tmp;
		}
		st += nui;//nui: how many linear chains in this gchain
	}
	assert(n_a <= gc->n_a);

	gc->n_a = n_a;
	gc->n_lc = n_tmp;
	KMALLOC(km_dst, gc->lc, n_tmp);
	memcpy(gc->lc, tmp, n_tmp * sizeof(mg_llchain_t));
	kfree(km, tmp);

	mg_gchain_extra(g, gc);
	mg_gchain_sort_by_score(km, gc);
	return gc;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xe8, %rsp
movq %r9, %rbx
movq %r8, 0x90(%rsp)
movl %ecx, %r14d
movq %rdx, 0xa0(%rsp)
movq %rsi, %r15
movslq 0x138(%rsp), %rax
movq %rax, 0x80(%rsp)
pushq $0x1
popq %rsi
pushq $0x40
popq %rdx
movq %rdi, 0x68(%rsp)
callq 0x1a3848
movq %rax, 0x8(%rsp)
xorl %eax, %eax
testl %r14d, %r14d
cmovlel %eax, %r14d
movq %r14, 0x98(%rsp)
movq %rbx, 0x70(%rsp)
leaq 0x4(%rbx), %rcx
movq %rcx, 0x88(%rsp)
xorl %edx, %edx
xorl %ebx, %ebx
xorl %ecx, %ecx
xorl %esi, %esi
cmpq 0x98(%rsp), %rdx
je 0x15edd7
movq 0x90(%rsp), %rdi
movq (%rdi,%rdx,8), %rdi
movslq %esi, %r8
xorl %r9d, %r9d
testl %edi, %edi
movl $0x0, %r10d
cmovgl %edi, %r10d
imulq $0x28, %r10, %r10
imulq $0x28, %r8, %r11
addq 0x88(%rsp), %r11
xorl %r8d, %r8d
cmpq %r9, %r10
je 0x15ed9d
movl (%r11,%r9), %ebp
addl %ebp, %ebp
sarl %ebp
addl %ebp, %r8d
addq $0x28, %r9
jmp 0x15ed87
cmpl 0x130(%rsp), %r8d
setge %r9b
movq %rdi, %r10
shrq $0x20, %r10
cmpq 0x80(%rsp), %r10
setge %r10b
andb %r9b, %r10b
cmovel %eax, %r8d
addl %r8d, %ebx
movzbl %r10b, %r8d
addl %r8d, %ecx
addl %edi, %esi
incq %rdx
jmp 0x15ed48
testl %ecx, %ecx
movq 0x8(%rsp), %r12
je 0x15f403
movq %r15, 0x30(%rsp)
movq 0x68(%rsp), %r14
movq %r14, (%r12)
movl %ecx, 0x8(%r12)
movl %ebx, 0x10(%r12)
movl %ecx, %esi
pushq $0x48
popq %rdx
movq %r14, %rdi
callq 0x1a3848
movq %rax, 0x18(%r12)
movslq %ebx, %rsi
shlq $0x4, %rsi
movq %r14, %rdi
callq 0x1a39c4
movq %rax, 0x28(%r12)
leaq 0x4(%rsp), %rax
andl $0x0, (%rax)
movq 0x70(%rsp), %rax
addq $0x14, %rax
movq %rax, 0xa8(%rsp)
xorl %eax, %eax
xorl %ecx, %ecx
xorl %r14d, %r14d
xorl %r12d, %r12d
movl $0x0, 0x14(%rsp)
xorl %edx, %edx
movl $0x0, 0x38(%rsp)
xorl %r13d, %r13d
movslq %r12d, %r15
cmpq 0x98(%rsp), %rcx
je 0x15f39c
movl %eax, 0x1c(%rsp)
movq 0x90(%rsp), %rax
movq %rcx, 0x50(%rsp)
movq (%rax,%rcx,8), %rsi
movl %edx, 0x18(%rsp)
movslq %edx, %rcx
xorl %eax, %eax
testl %esi, %esi
movl $0x0, %edx
movq %rsi, 0x58(%rsp)
cmovgl %esi, %edx
imulq $0x28, %rdx, %rbx
imulq $0x28, %rcx, %rdx
movq 0x88(%rsp), %rcx
movq %rdx, 0x48(%rsp)
addq %rdx, %rcx
xorl %edx, %edx
cmpq %rax, %rbx
je 0x15eec6
movl (%rcx,%rax), %esi
addl %esi, %esi
sarl %esi
addl %esi, %edx
addq $0x28, %rax
jmp 0x15eeb2
cmpl 0x130(%rsp), %edx
jl 0x15eee2
movq 0x58(%rsp), %rax
shrq $0x20, %rax
cmpq 0x80(%rsp), %rax
jge 0x15eeeb
movl 0x1c(%rsp), %eax
jmp 0x15f387
movq %r15, 0x40(%rsp)
movl %r12d, 0x28(%rsp)
movq %r13, 0x20(%rsp)
movq 0x8(%rsp), %rcx
movq 0x18(%rcx), %rdx
movslq 0x38(%rsp), %rcx
imulq $0x48, %rcx, %rcx
movl %eax, 0x14(%rdx,%rcx)
movl 0x14(%rsp), %eax
movq %rcx, 0x78(%rsp)
movq %rdx, 0xb0(%rsp)
movl %eax, 0x8(%rdx,%rcx)
movq 0xa8(%rsp), %rax
movq 0x48(%rsp), %rcx
leaq (%rax,%rcx), %r13
xorl %ebp, %ebp
movl 0x128(%rsp), %edi
cmpq %rbp, %rbx
je 0x15ef85
movl %edi, 0x60(%rsp)
movl (%r13,%rbp), %edi
callq 0x15cdd5
movl %eax, %r15d
movl -0x4(%r13,%rbp), %edi
callq 0x15cdd5
movl %r14d, %r12d
movl %eax, %r14d
movl -0xc(%r13,%rbp), %edi
callq 0x15cdd5
addl 0x60(%rsp), %r15d
addl %r14d, %eax
movl %r12d, %r14d
addl %r15d, %eax
addq $0x28, %rbp
movl %eax, %edi
jmp 0x15ef3f
callq 0x15cdd5
movq 0x78(%rsp), %rcx
movq 0xb0(%rsp), %rdx
movl %eax, 0x38(%rdx,%rcx)
movl 0x28(%rsp), %r12d
cmpl %r14d, %r12d
jne 0x15efe4
movl %r14d, %ebx
sarl %ebx
addl %r14d, %ebx
cmpl $0x4, %r14d
pushq $0x10
popq %rax
cmovll %eax, %ebx
movslq %ebx, %rdx
shlq $0x4, %rdx
movq 0x30(%rsp), %rdi
movq 0x20(%rsp), %rsi
callq 0x1a3acc
movl 0x28(%rsp), %r12d
movl %ebx, %r14d
movq 0x8(%rsp), %rdx
movq 0x120(%rsp), %r8
jmp 0x15eff6
movq 0x8(%rsp), %rdx
movq 0x120(%rsp), %r8
movq 0x20(%rsp), %rax
movq 0x40(%rsp), %rdi
incl %r12d
shlq $0x4, %rdi
movq %rax, %r13
addq %rax, %rdi
movq 0x48(%rsp), %rsi
addq 0x70(%rsp), %rsi
movq 0x28(%rdx), %rcx
movq %rsi, 0x48(%rsp)
leaq 0x4(%rsp), %rdx
callq 0x15f4d2
movslq 0x58(%rsp), %rax
movq %rax, 0x40(%rsp)
pushq $0x1
popq %r15
cmpq 0x40(%rsp), %r15
jge 0x15f357
imulq $0x28, %r15, %rax
movq 0x48(%rsp), %rcx
leaq (%rcx,%rax), %r10
movl 0x4(%rcx,%rax), %eax
movslq %r12d, %rbp
testl %eax, %eax
movq %r15, 0x60(%rsp)
js 0x15f1fc
leaq 0xc8(%rsp), %rax
xorps %xmm0, %xmm0
movups %xmm0, 0x10(%rax)
movups %xmm0, (%rax)
movl -0x20(%r10), %eax
xorl $0x1, %eax
movl %eax, 0xb8(%rsp)
movl 0x20(%r10), %r9d
testl %r9d, %r9d
js 0x15f475
movl %r9d, 0xbc(%rsp)
movl 0x24(%r10), %eax
movl %eax, 0xc0(%rsp)
movl $0x40000000, 0xc4(%rsp) # imm = 0x40000000
movq %r10, 0x20(%rsp)
movl 0x8(%r10), %edx
xorl $0x1, %edx
movq 0x30(%rsp), %rdi
movq 0xa0(%rsp), %rsi
pushq $0x1
popq %rcx
leaq 0xb8(%rsp), %r8
leaq 0x3c(%rsp), %rax
pushq %rax
pushq $0xf
callq 0x15bcd0
popq %rcx
popq %rdx
movq %rax, 0x28(%rsp)
movl 0x3c(%rsp), %ebx
testl %ebx, %ebx
je 0x15f2f1
movl 0xc0(%rsp), %eax
cmpl 0xdc(%rsp), %eax
jne 0x15f2f1
testl %ebx, %ebx
jle 0x15f456
movl 0xc0(%rsp), %eax
cmpl 0xdc(%rsp), %eax
jne 0x15f437
movq %r13, %rsi
movl %r12d, %ecx
addl $-0x2, %ebx
imulq $0xc, %rbx, %r13
addq 0x28(%rsp), %r13
movq %rbp, %r15
shlq $0x20, %r15
shlq $0x4, %rbp
orq $0xc, %rbp
testl %ebx, %ebx
jle 0x15f1a9
cmpl %r14d, %ecx
jne 0x15f179
movl %r14d, %r12d
sarl %r12d
addl %r14d, %r12d
cmpl $0x4, %r14d
pushq $0x10
popq %rax
cmovll %eax, %r12d
movslq %r12d, %rdx
shlq $0x4, %rdx
movq 0x30(%rsp), %rdi
movl %ecx, %r14d
callq 0x1a3acc
movl %r14d, %ecx
movq %rax, %rsi
movl %r12d, %r14d
andl $0x0, (%rsi,%rbp)
andq $0x0, -0xc(%rsi,%rbp)
movl (%r13), %eax
xorl $0x1, %eax
movl %eax, -0x4(%rsi,%rbp)
decl %ebx
addq $-0xc, %r13
movabsq $0x100000000, %rax      # imm = 0x100000000
addq %rax, %r15
addq $0x10, %rbp
incl %ecx
jmp 0x15f13f
movq %rsi, %rbp
movq 0x30(%rsp), %r13
movq %r13, %rdi
movq 0x28(%rsp), %rsi
movl %ecx, %r12d
callq 0x1a38cf
cmpl %r14d, %r12d
jne 0x15f2af
movl %r14d, %ebx
sarl %ebx
addl %r14d, %ebx
cmpl $0x4, %r14d
pushq $0x10
popq %rax
cmovll %eax, %ebx
movslq %ebx, %rdx
shlq $0x4, %rdx
movq %r13, %rdi
movq %rbp, %rsi
callq 0x1a3acc
movl %r12d, %ecx
movq %rax, %rbp
movl %ebx, %r14d
jmp 0x15f2b2
movl -0x20(%r10), %ecx
cmpl 0x8(%r10), %ecx
jne 0x15f494
shlq $0x4, %rbp
leaq -0x10(,%r13), %rcx
addq %rbp, %rcx
addl %eax, %eax
sarl %eax
testl %eax, %eax
movl $0x0, %edx
cmovgl %eax, %edx
xorl %ebx, %ebx
movq 0x120(%rsp), %r8
cmpl %ebx, %edx
je 0x15f418
movslq (%r10), %rsi
addq %rbx, %rsi
shlq $0x4, %rsi
movl -0x18(%r10), %edi
cmpl (%r8,%rsi), %edi
jge 0x15f259
addq %r8, %rsi
movl -0x10(%r10), %edi
cmpl 0x8(%rsi), %edi
jl 0x15f25e
incq %rbx
jmp 0x15f231
addl 0x4(%rcx), %eax
subl %ebx, %eax
movl %eax, 0x4(%rcx)
movl 0x1c(%r10), %eax
addl %eax, 0xc(%rcx)
movslq 0x4(%rsp), %r15
movq %r15, %rdi
shlq $0x4, %rdi
movq 0x8(%rsp), %rax
addq 0x28(%rax), %rdi
movl 0x4(%r10), %edx
shlq $0x21, %rdx
sarq $0x21, %rdx
subq %rbx, %rdx
shlq $0x4, %rdx
movq %r10, %rbp
callq 0x2160
movl 0x4(%rbp), %eax
addl %eax, %eax
sarl %eax
addl %r15d, %eax
subl %ebx, %eax
movl %eax, 0x4(%rsp)
jmp 0x15f2e4
movl %r12d, %ecx
movq 0x8(%rsp), %rdx
movq 0x120(%rsp), %r8
movq 0x20(%rsp), %rsi
incl %ecx
movl %ecx, %r12d
sarq $0x1c, %r15
movq %rbp, %r13
addq %rbp, %r15
movq 0x28(%rdx), %rcx
movq %r15, %rdi
leaq 0x4(%rsp), %rdx
callq 0x15f4d2
movq 0x60(%rsp), %r15
incq %r15
jmp 0x15f033
movq 0xf3ce8(%rip), %rax     # 0x252fe0
movq (%rax), %rdi
movq 0x20(%rsp), %rax
movl -0x20(%rax), %r9d
movl 0x8(%rax), %ecx
xorq $0x1, %rcx
movl %ecx, %eax
andl $0x1, %eax
leaq 0x92cc0(%rip), %rsi     # 0x1f1fd7
movsbl (%rax,%rsi), %edx
xorq $0x1, %r9
movl %r9d, %eax
andl $0x1, %eax
movsbl (%rax,%rsi), %r8d
movl 0xbc(%rsp), %r10d
movl 0xd4(%rsp), %r11d
leaq 0x92c6b(%rip), %rsi     # 0x1f1fac
xorl %eax, %eax
pushq %r10
pushq %r11
callq 0x22b0
popq %rcx
popq %rdx
movl 0x3c(%rsp), %ebx
jmp 0x15f102
movl %r12d, %eax
subl 0x14(%rsp), %eax
movq 0x8(%rsp), %rcx
movq 0x18(%rcx), %rcx
movq 0x78(%rsp), %rsi
movl %eax, 0xc(%rcx,%rsi)
movl 0x4(%rsp), %eax
movl %eax, %edx
subl 0x1c(%rsp), %edx
movl %edx, 0x10(%rcx,%rsi)
incl 0x38(%rsp)
movl %r12d, 0x14(%rsp)
movq 0x50(%rsp), %rcx
movl 0x18(%rsp), %edx
addl 0x58(%rsp), %edx
incq %rcx
jmp 0x15ee5a
movq 0x8(%rsp), %rcx
cmpl 0x10(%rcx), %eax
jg 0x15f4b3
movl %eax, 0x10(%rcx)
movl %r12d, 0xc(%rcx)
shlq $0x4, %r15
movq 0x68(%rsp), %rdi
movq %r15, %rsi
movq %rcx, %r12
callq 0x1a39c4
movq %rax, 0x20(%r12)
movq %rax, %rdi
movq %r13, %rsi
movq %r15, %rdx
callq 0x2160
movq 0x30(%rsp), %r14
movq %r14, %rdi
movq %r13, %rsi
callq 0x1a38cf
movq 0xa0(%rsp), %rdi
movq %r12, %rsi
callq 0x15e694
movq %r14, %rdi
movq %r12, %rsi
callq 0x15ebc4
movq %r12, %rax
addq $0xe8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x92bf2(%rip), %rdi     # 0x1f2011
leaq 0x926fd(%rip), %rsi     # 0x1f1b23
leaq 0x92ae7(%rip), %rcx     # 0x1f1f14
movl $0x7fa, %edx            # imm = 0x7FA
callq 0x2110
leaq 0x92ba8(%rip), %rdi     # 0x1f1fe6
leaq 0x926de(%rip), %rsi     # 0x1f1b23
leaq 0x92ac8(%rip), %rcx     # 0x1f1f14
movl $0x7e3, %edx            # imm = 0x7E3
callq 0x2110
leaq 0x92b7d(%rip), %rdi     # 0x1f1fda
leaq 0x926bf(%rip), %rsi     # 0x1f1b23
leaq 0x92aa9(%rip), %rcx     # 0x1f1f14
movl $0x7e2, %edx            # imm = 0x7E2
callq 0x2110
leaq 0x92a86(%rip), %rdi     # 0x1f1f02
leaq 0x926a0(%rip), %rsi     # 0x1f1b23
leaq 0x92a8a(%rip), %rcx     # 0x1f1f14
movl $0x7db, %edx            # imm = 0x7DB
callq 0x2110
leaq 0x92b67(%rip), %rdi     # 0x1f2002
leaq 0x92681(%rip), %rsi     # 0x1f1b23
leaq 0x92a6b(%rip), %rcx     # 0x1f1f14
movl $0x7f2, %edx            # imm = 0x7F2
callq 0x2110
leaq 0x92b63(%rip), %rdi     # 0x1f201d
leaq 0x92662(%rip), %rsi     # 0x1f1b23
leaq 0x92a4c(%rip), %rcx     # 0x1f1f14
movl $0x80a, %edx            # imm = 0x80A
callq 0x2110