// File: /workspace/github_cpp_makefile_star2_O2/chhylp123[P]hifiasm/inter.cpp
// Function: mg_lchain_dp(int, int, int, int, int, int, int, float, long, mg128_t*, int*, unsigned long**, void*)
mg128_t *mg_lchain_dp(int max_dist_x, int max_dist_y, int bw, int max_skip, int max_iter, int min_cnt, int min_sc, float chn_pen_gap, 
					  int64_t n, mg128_t *a, int *n_u_, uint64_t **_u, void *km)
{ // TODO: make sure this works when n has more than 32 bits
	int32_t *f, *t, *v, n_u, n_v;
	int64_t *p, i, j, max_ii, st = 0;
	uint64_t *u;

	if (_u) *_u = 0, *n_u_ = 0;
	if (n == 0 || a == 0) return 0;
	KMALLOC(km, p, n);///id of last cell
	KMALLOC(km, f, n);///f[] is the score ending at i, not always the peak
	KMALLOC(km, v, n);///v[] keeps the peak score up to i;
	KCALLOC(km, t, n);///t doesn't matter too much; it is mainly used to accelrate the iteration

	// a[].x: ref_id(31)rev(1)r_pos(32)
 	// a[].y: weight(8)query_id(8)flag(8)span(8)q_pos(32)
	// fill the score and backtrack arrays
	for (i = st = 0, max_ii = -1; i < n; ++i) {
		int64_t max_j = -1, end_j;
        ///max_f -> score of minimizer
		int32_t max_f = normal_sc(a[i].y>>MG_SEED_WT_SHIFT, a[i].y>>32&0xff), n_skip = 0;
		///until we are at the same rid, same direction, and the coordinates are close enough
		while (st < i && (a[i].x>>32 != a[st].x>>32 || a[i].x > a[st].x + max_dist_x)) ++st;
		///max_iter = 10000 in default, which means dp can go back to up to 10000 cells
		if (i - st > max_iter) st = i - max_iter; 
		for (j = i - 1; j >= st; --j) {
			int32_t sc;
			sc = comput_sc(&a[i], &a[j], max_dist_x, max_dist_y, bw, chn_pen_gap);
			if (sc == INT32_MIN) continue;
			sc += f[j];
			if (sc > max_f) {
				max_f = sc, max_j = j;
				if (n_skip > 0) --n_skip;
			} else if (t[j] == (int32_t)i) {///note we scan j backwards; we don't need to update t[] for each i
				if (++n_skip > max_skip)
					break;
			}
			if (p[j] >= 0) t[p[j]] = i;//p[]: prefix idx; means there is a chain longer than 2
		}
		end_j = j;///end_j might be > 0; just the end idx of backwards
		///if not close enough, select a new max
		///max_ii is just used to rescue best-score in case best-score appears before end_j
		if (max_ii < 0 || (int64_t)(a[i].x - a[max_ii].x) > (int64_t)max_dist_x) {///select a new max
			int32_t max = INT32_MIN;
			max_ii = -1;
			for (j = i - 1; j >= st; --j)
				if (max < f[j]) max = f[j], max_ii = j;
		}
		///note: it will happen when `max_ii` < `end_j`; 
		///iteration is terminated at `end_j` mostly because of `max_skip` and `max_iter`
		///max_ii is just used to rescue best-score in case best-score appears before end_j
		if (max_ii >= 0 && max_ii < end_j) {
			int32_t tmp;
			tmp = comput_sc(&a[i], &a[max_ii], max_dist_x, max_dist_y, bw, chn_pen_gap);
			if (tmp != INT32_MIN && max_f < tmp + f[max_ii])
				max_f = tmp + f[max_ii], max_j = max_ii;
		}
		// v[] keeps the peak score up to i (as score might decerase); f[] is the score ending at i, not always the peak
		f[i] = max_f, p[i] = max_j;//p[]: prefix idx
		v[i] = max_j >= 0 && v[max_j] > max_f? v[max_j] : max_f; 
		if (max_ii < 0 || ((int64_t)(a[i].x - a[max_ii].x) <= (int64_t)max_dist_x && f[max_ii] < f[i]))
			max_ii = i;
	}
	///after mg_chain_backtrack, the results are saved in u and v;
	u = mg_chain_backtrack(km, n, f, p, v, t, min_cnt, min_sc, 0, &n_u, &n_v);
	*n_u_ = n_u, *_u = u; // NB: note that u[] may not be sorted by score here
	kfree(km, p); kfree(km, f); kfree(km, t);
	if (n_u == 0) {
		kfree(km, a); kfree(km, v);
		return 0;
	}
	//u[]: sc|occ of chains; chain is mostly sorted by the score; at least the first chain has the largest score
	//v[]: idx of each element
	return compact_a(km, n_u, u, n_v, v, a);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movss %xmm0, 0x18(%rsp)
movl %r8d, %ebx
movl %ecx, 0x50(%rsp)
movl %edx, 0x24(%rsp)
movl %esi, 0x20(%rsp)
movl %edi, 0x10(%rsp)
movq 0xf0(%rsp), %rax
movq 0xe8(%rsp), %rcx
movq 0xd8(%rsp), %r15
testq %rax, %rax
je 0x15b2d5
andq $0x0, (%rax)
andl $0x0, (%rcx)
testq %r15, %r15
sete %al
cmpq $0x0, 0xe0(%rsp)
sete %cl
orb %al, %cl
je 0x15b2f2
xorl %ebx, %ebx
jmp 0x15b8d2
movq %r9, 0x70(%rsp)
movq 0xf8(%rsp), %r14
leaq (,%r15,8), %rsi
movq %r14, %rdi
callq 0x1a39c4
movq %rax, 0x28(%rsp)
leaq (,%r15,4), %r13
movq %r14, %rdi
movq %r13, %rsi
callq 0x1a39c4
movq %rax, %r12
movq %r14, %rdi
movq %r13, %rsi
movq 0xe0(%rsp), %r13
callq 0x1a39c4
movq %rax, %rbp
pushq $0x4
popq %rdx
movq %r14, %rdi
movq %r15, %rsi
callq 0x1a3848
movq %rax, 0x48(%rsp)
movslq 0x10(%rsp), %r8
movslq %ebx, %rax
movq %rax, 0x78(%rsp)
movq %r12, %rbx
xorl %r12d, %r12d
testq %r15, %r15
movl $0x0, %eax
cmovgq %r15, %rax
movq %rax, 0x80(%rsp)
leaq -0x10(%r13), %rax
movq %rax, 0x60(%rsp)
pushq $-0x1
popq %r14
xorl %r9d, %r9d
movq %rbp, 0x38(%rsp)
movq %rbx, 0x40(%rsp)
movq %r8, 0x58(%rsp)
cmpq 0x80(%rsp), %r9
je 0x15b64c
movq %r9, %rax
shlq $0x4, %rax
movq %rax, 0x8(%rsp)
movq 0x8(%r13,%rax), %rcx
movq %rcx, %rax
shrq $0x38, %rax
shrq $0x20, %rcx
movzbl %cl, %r15d
cmpq $0xff, %rax
je 0x15b3f4
cvtsi2sd %eax, %xmm0
cvtsi2sd %r15d, %xmm1
mulsd 0x96640(%rip), %xmm0    # 0x1f1a20
mulsd %xmm0, %xmm1
cvttsd2si %xmm1, %r15d
cmpl $0x2, %r15d
pushq $0x1
popq %rax
cmovll %eax, %r15d
addq %r13, 0x8(%rsp)
cmpq %r9, %r12
movq %r9, %rax
cmovgq %r12, %rax
movq %r12, %rcx
shlq $0x4, %rcx
addq %r13, %rcx
movq %r14, 0x88(%rsp)
cmpq %r9, %r12
jge 0x15b44d
movq 0x8(%rsp), %rdx
movq (%rdx), %rdx
movq (%rcx), %rsi
movq %rsi, %rdi
xorq %rdx, %rdi
shrq $0x20, %rdi
sete %dil
addq %r8, %rsi
cmpq %rsi, %rdx
setbe %dl
testb %dl, %dil
jne 0x15b44a
incq %r12
addq $0x10, %rcx
jmp 0x15b415
movq %r12, %rax
movq %r9, %rcx
subq %rax, %rcx
movq %r9, %r12
movq 0x78(%rsp), %rdx
subq %rdx, %r12
cmpq %rdx, %rcx
cmovleq %rax, %r12
movq %r9, 0x30(%rsp)
leaq -0x1(%r9), %r14
xorl %ebx, %ebx
movq 0x60(%rsp), %r13
movq %r14, %rbp
pushq $-0x1
popq %rax
movq %rax, 0x68(%rsp)
cmpq %r12, %rbp
jl 0x15b515
movq 0x8(%rsp), %rdi
movq %r13, %rsi
movl 0x10(%rsp), %edx
movl 0x20(%rsp), %ecx
movl 0x24(%rsp), %r8d
movss 0x18(%rsp), %xmm0
callq 0x15b8e7
movl %eax, %ecx
negl %ecx
jno 0x15b4b4
movl %r15d, %eax
jmp 0x15b506
movq 0x40(%rsp), %rcx
addl (%rcx,%rbp,4), %eax
cmpl %r15d, %eax
jle 0x15b4d1
xorl %ecx, %ecx
testl %ebx, %ebx
setg %cl
subl %ecx, %ebx
movq %rbp, 0x68(%rsp)
jmp 0x15b4eb
movq 0x48(%rsp), %rax
movq 0x30(%rsp), %rcx
cmpl %ecx, (%rax,%rbp,4)
jne 0x15b4e8
cmpl 0x50(%rsp), %ebx
jge 0x15b515
incl %ebx
movl %r15d, %eax
movq 0x28(%rsp), %rcx
movq (%rcx,%rbp,8), %rcx
testq %rcx, %rcx
js 0x15b506
movq 0x48(%rsp), %rdx
movq 0x30(%rsp), %rsi
movl %esi, (%rdx,%rcx,4)
decq %rbp
addq $-0x10, %r13
movl %eax, %r15d
jmp 0x15b480
movq 0x88(%rsp), %rdx
testq %rdx, %rdx
movq 0xe0(%rsp), %r13
movq 0x40(%rsp), %rbx
movq 0x58(%rsp), %r8
js 0x15b54d
movq 0x8(%rsp), %rax
movq (%rax), %rax
movq %rdx, %rcx
shlq $0x4, %rcx
subq (%r13,%rcx), %rax
cmpq %r8, %rax
jle 0x15b56c
movl $0x80000000, %eax       # imm = 0x80000000
pushq $-0x1
popq %rdx
cmpq %r12, %r14
jl 0x15b56c
movl (%rbx,%r14,4), %ecx
cmpl %ecx, %eax
cmovlq %r14, %rdx
cmovlel %ecx, %eax
decq %r14
jmp 0x15b555
testq %rdx, %rdx
sets %al
cmpq %rbp, %rdx
setge %cl
orb %al, %cl
movq %rdx, %r14
jne 0x15b5dd
movq %r14, %rsi
shlq $0x4, %rsi
addq %r13, %rsi
movq 0x8(%rsp), %rdi
movl 0x10(%rsp), %edx
movl 0x20(%rsp), %ecx
movl 0x24(%rsp), %r8d
movss 0x18(%rsp), %xmm0
callq 0x15b8e7
movq 0x58(%rsp), %r8
movl %eax, %ecx
negl %ecx
jo 0x15b5dd
addl (%rbx,%r14,4), %eax
cmpl %eax, %r15d
jge 0x15b5dd
movq 0x30(%rsp), %r9
leaq (%rbx,%r9,4), %rcx
movl %eax, (%rbx,%r9,4)
movq 0x28(%rsp), %rdx
movq %r14, (%rdx,%r9,8)
movl %eax, %r15d
movq %r14, %rax
movq 0x38(%rsp), %rbp
jmp 0x15b605
movq 0x30(%rsp), %r9
leaq (%rbx,%r9,4), %rcx
movl %r15d, (%rbx,%r9,4)
movq 0x28(%rsp), %rax
movq 0x68(%rsp), %rdx
movq %rdx, (%rax,%r9,8)
movq %rdx, %rax
testq %rdx, %rdx
movq 0x38(%rsp), %rbp
js 0x15b610
movl (%rbp,%rax,4), %eax
cmpl %r15d, %eax
cmovgl %eax, %r15d
movl %r15d, (%rbp,%r9,4)
testq %r14, %r14
js 0x15b63b
movq 0x8(%rsp), %rax
movq (%rax), %rax
movq %r14, %rdx
shlq $0x4, %rdx
subq (%r13,%rdx), %rax
cmpq %r8, %rax
jg 0x15b63e
movl (%rbx,%r14,4), %eax
cmpl (%rcx), %eax
jge 0x15b63e
movq %r9, %r14
incq %r9
addq $0x10, 0x60(%rsp)
jmp 0x15b399
subq $0x8, %rsp
leaq 0x5c(%rsp), %rax
movq %rbx, %rdx
leaq 0x9c(%rsp), %r15
movq 0x100(%rsp), %r12
movq %r12, %rdi
movq 0xe0(%rsp), %rsi
movq 0x30(%rsp), %r14
movq %r14, %rcx
movq %rbp, %r8
movq 0x50(%rsp), %rbx
movq %rbx, %r9
pushq %rax
pushq %r15
pushq $0x0
movl 0xf0(%rsp), %eax
pushq %rax
pushq 0x98(%rsp)
callq 0x15b018
addq $0x30, %rsp
movq %rax, %rcx
movslq (%r15), %r15
movq 0xe8(%rsp), %rax
movl %r15d, (%rax)
movq 0xf0(%rsp), %rax
movq %rcx, 0x8(%rsp)
movq %rcx, (%rax)
movq %r12, %rdi
movq %r14, %rsi
callq 0x1a38cf
movq %r12, %rdi
movq 0x40(%rsp), %rsi
callq 0x1a38cf
movq %r12, %rdi
movq %rbx, %rsi
callq 0x1a38cf
testq %r15, %r15
je 0x15b8ba
movslq 0x54(%rsp), %rsi
shlq $0x4, %rsi
movq %r12, %rdi
callq 0x1a39c4
xorl %ecx, %ecx
testq %r15, %r15
movq %rbp, %rdx
movl $0x0, %ebp
cmovgq %r15, %rbp
movq %rax, %rbx
movq %rdx, %rax
addq $-0x4, %rax
xorl %edx, %edx
movq 0x8(%rsp), %r14
cmpq %rbp, %rdx
je 0x15b77f
movslq (%r14,%rdx,8), %r8
movslq %ecx, %r9
shlq $0x2, %r9
testq %r8, %r8
movl $0x0, %esi
cmovgq %r8, %rsi
movq %rcx, %rdi
shlq $0x4, %rdi
addq %rbx, %rdi
leaq (%r9,%r8,4), %r8
addq %rax, %r8
negq %rsi
xorl %r9d, %r9d
cmpq %r9, %rsi
je 0x15b777
movslq (%r8,%r9,4), %r10
shlq $0x4, %r10
movupd (%r13,%r10), %xmm0
movupd %xmm0, (%rdi)
decq %r9
addq $0x10, %rdi
jmp 0x15b756
incq %rdx
subq %r9, %rcx
jmp 0x15b723
movq %r12, %rdi
movq 0x38(%rsp), %rsi
callq 0x1a38cf
movq %r12, %rdi
movq %r15, 0x18(%rsp)
movq %r15, %r12
shlq $0x4, %r12
movq %r12, %rsi
callq 0x1a39c4
movq %rax, %r15
addq $0x8, %rax
xorl %ecx, %ecx
xorl %edx, %edx
cmpq %rdx, %rbp
je 0x15b7df
movq %rcx, %rsi
shlq $0x4, %rsi
movq (%rbx,%rsi), %rsi
movq %rsi, -0x8(%rax)
movq %rcx, %rsi
shlq $0x20, %rsi
orq %rdx, %rsi
movq %rsi, (%rax)
movslq (%r14,%rdx,8), %rsi
addq %rsi, %rcx
incq %rdx
addq $0x10, %rax
jmp 0x15b7ae
movq %r15, %rsi
addq %r12, %rsi
movq %r15, %rdi
callq 0x158af1
movq 0x18(%rsp), %rax
leaq (,%rax,8), %rsi
movq 0xf8(%rsp), %rdi
callq 0x1a39c4
movq %rax, %r14
shlq $0x3, %rbp
xorl %r13d, %r13d
xorl %r12d, %r12d
movq %rbx, 0x10(%rsp)
cmpq %r13, %rbp
je 0x15b868
movslq 0x8(%r15,%r13,2), %rax
movq 0x8(%rsp), %rcx
movq (%rcx,%rax,8), %rax
movq %rax, (%r14,%r13)
movq %r12, %rdi
shlq $0x4, %rdi
addq 0xe0(%rsp), %rdi
movl 0xc(%r15,%r13,2), %esi
shlq $0x4, %rsi
addq %rbx, %rsi
movslq %eax, %rbx
movq %rbx, %rdx
shlq $0x4, %rdx
callq 0x2160
addq %rbx, %r12
movq 0x10(%rsp), %rbx
addq $0x8, %r13
jmp 0x15b819
movq 0x18(%rsp), %rax
shll $0x3, %eax
movslq %eax, %rdx
movq 0x8(%rsp), %rdi
movq %r14, %rbp
movq %r14, %rsi
callq 0x2160
shlq $0x4, %r12
movq %rbx, %rdi
movq 0xe0(%rsp), %rbx
movq %rbx, %rsi
movq %r12, %rdx
callq 0x2160
movq 0xf8(%rsp), %r12
movq %r12, %rdi
movq %rbx, %rsi
movq 0x10(%rsp), %rbx
callq 0x1a38cf
movq %r15, %r13
jmp 0x15b8bc
xorl %ebx, %ebx
movq %r12, %rdi
movq %r13, %rsi
callq 0x1a38cf
movq %r12, %rdi
movq %rbp, %rsi
callq 0x1a38cf
movq %rbx, %rax
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq