// File: chhylp123[P]hifiasm/Hash_Table.cpp
// Function: chain_DP(k_mer_hit*, long long, Chain_Data*, overlap_region*, double, int, int, int, void*)
long long chain_DP(k_mer_hit* a, long long a_n, Chain_Data* dp, overlap_region* result, 
              double band_width_threshold, int max_skip, int x_readLen, int y_readLen, void *km)
{
    long long i, j;
    long long self_pos, pos, max_j, max_i, max_score, score;
    long long distance_pos, distance_self_pos, distance_gap,  distance_min;
    ///double band_width_threshold = 0.05;
    double band_width_penalty = 1 / band_width_threshold;
    long long min_score = asm_opt.k_mer_length;
    long long max_indels, max_self_length;
    double gap_rate;
    long long total_indels, total_self_length;
	int32_t ret;
    
    resize_Chain_Data(dp, a_n, km);

	ret = ha_chain_check(a, a_n, dp, min_score, band_width_threshold);
	if (ret > 0) {
		a_n = ret;
		goto skip_dp;
	}

    // fill the score and backtrack arrays
	for (i = 0; i < a_n; ++i) dp->tmp[i] = -1;
	for (i = 0; i < a_n; ++i) 
    {
		int n_chn_skip = 0;
		int n_max_skip = 0;

        pos = a[i].offset;
        self_pos = a[i].self_offset;
        max_j = -1;
        max_score = normal_w(min_score, (int64_t)a[i].cnt);
        max_indels = 0;
        max_self_length = 0;

        ///may have a pre-cut condition for j
        for (j = i - 1; j >= 0; --j) 
        {
            distance_pos = pos - a[j].offset;
            distance_self_pos = self_pos - a[j].self_offset;
            ///a has been sorted by a[].offset
            ///note for a, we do not have any two elements that have both equal offsets and self_offsets
            ///but there maybe two elements that have equal offsets or equal self_offsets
            if(distance_pos == 0 || distance_self_pos <= 0)
            {
                continue;
            }

            distance_gap = distance_pos > distance_self_pos? distance_pos - distance_self_pos : distance_self_pos - distance_pos;
            
            total_indels = dp->indels[j] + distance_gap;
            total_self_length = dp->self_length[j] + distance_self_pos;
            if(total_indels > band_width_threshold * total_self_length)
            {
                continue;
            }

            ///min distance
            distance_min = distance_pos < distance_self_pos? distance_pos:distance_self_pos;
            score = distance_min < min_score? distance_min : min_score;
            ///need to be fixed in r305
			///if (!a[j].good) score = (score >> 1) + (score & 1);
            score = normal_w(score, (int64_t)a[j].cnt);

            gap_rate = (double)((double)(total_indels)/(double)(total_self_length));
            ///if the gap rate > 0.06, score will be negative
            score -= (long long)(gap_rate * score * band_width_penalty);

            score += dp->score[j];

			///find a new max score
			if (score > max_score) {///must use > instead of >=
				max_score = score;
				max_j = j;
				max_indels = total_indels;
				max_self_length = total_self_length;
				n_max_skip = 0;
				if (n_chn_skip > 0) --n_chn_skip;
			} else {
				if (++n_max_skip > max_skip)
					break;
				if (dp->tmp[j] == i) {
					if (++n_chn_skip > max_skip)
						break;
				}
			}
			if (dp->pre[j] >= 0) dp->tmp[dp->pre[j]] = i;
        }

        dp->score[i] = max_score;
        dp->pre[i] = max_j;
        dp->indels[i] = max_indels;
        dp->self_length[i] = max_self_length;
        dp->occ[i] = 1;
        if(max_j != -1) dp->occ[i] = dp->occ[max_j] + 1;
    }

    ///debug_chain(a, a_n, dp);
    // if((*result).x_id == 2162668 && (*result).y_id == 182804) print_chain(a, a_n, dp, 10);
    
skip_dp:

    max_score = -1;
    max_i = -1;
    long long mini_xLen = x_readLen * 2 + 2, tmp_xLen;
    for (i = 0; i < a_n; ++i) 
    {
        if(dp->score[i] > max_score)
        {
            max_score = dp->score[i];
            max_i = i;
            mini_xLen = get_chainLen(a[i].self_offset, a[i].self_offset, x_readLen, 
                                     a[i].offset, a[i].offset, y_readLen);
        }
        else if(dp->score[i] == max_score)
        {
            tmp_xLen = get_chainLen(a[i].self_offset, a[i].self_offset, x_readLen, 
                                    a[i].offset, a[i].offset, y_readLen);

            if(tmp_xLen < mini_xLen)
            {
                max_score = dp->score[i];
                max_i = i;

                mini_xLen = tmp_xLen;
            }
        }
        
    }

    clear_fake_cigar(&(result->f_cigar));
    ///note a has been sorted by offset, that means has been sorted by query offset
    i = max_i;
    result->x_pos_e = a[i].self_offset;
    result->y_pos_e = a[i].offset;
    result->shared_seed = max_score;
    result->overlapLen = mini_xLen;

    distance_self_pos = result->x_pos_e - a[i].self_offset;
    distance_pos = result->y_pos_e - a[i].offset;
    long long pre_distance_gap = distance_pos - distance_self_pos;
    ///record first site
    ///the length of f_cigar should be at least 1
    ///record the offset of reference
    add_fake_cigar(&(result->f_cigar), a[i].self_offset, pre_distance_gap, km);
    long long chainLen = 0;
    if(result->x_pos_strand == 1)
    {
        while (i >= 0)
        {
            distance_self_pos = result->x_pos_e - a[i].self_offset;
            distance_pos = result->y_pos_e - a[i].offset;
            distance_gap = distance_pos - distance_self_pos;
            if(distance_gap != pre_distance_gap)
            {
                pre_distance_gap = distance_gap;
                ///record this site
                add_fake_cigar(&(result->f_cigar), a[i].self_offset, pre_distance_gap, km);
            }

            chainLen++;
            result->x_pos_s = a[i].self_offset;
            result->y_pos_s = a[i].offset;
            i = dp->pre[i];
        }
    }
    else
    {
        while (i >= 0)
        {
            distance_self_pos = result->x_pos_e - a[i].self_offset;
            distance_pos = result->y_pos_e - a[i].offset;
            distance_gap = distance_pos - distance_self_pos;
            if(distance_gap == pre_distance_gap)
            {
                result->f_cigar.length--;
                add_fake_cigar(&(result->f_cigar), a[i].self_offset, pre_distance_gap, km);
            }
            else
            {
                pre_distance_gap = distance_gap;
                add_fake_cigar(&(result->f_cigar), a[i].self_offset, pre_distance_gap, km);
            }

            chainLen++;
            result->x_pos_s = a[i].self_offset;
            result->y_pos_s = a[i].offset;
            i = dp->pre[i];
        }
    }
    return chainLen;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x120, %rsp            # imm = 0x120
movq 0x18(%rbp), %rax
movl 0x10(%rbp), %eax
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movsd %xmm0, -0x28(%rbp)
movl %r8d, -0x2c(%rbp)
movl %r9d, -0x30(%rbp)
movsd 0x360329(%rip), %xmm0   # 0x382000
divsd -0x28(%rbp), %xmm0
movsd %xmm0, -0x98(%rbp)
leaq 0x3a2b0d(%rip), %rax    # 0x3c47f8
movslq 0x80(%rax), %rax
movq %rax, -0xa0(%rbp)
movq -0x18(%rbp), %rdi
movq -0x10(%rbp), %rsi
movq 0x18(%rbp), %rdx
callq 0x226f0
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movl %eax, %esi
movq -0x18(%rbp), %rdx
movq -0xa0(%rbp), %rax
movl %eax, %ecx
movsd -0x28(%rbp), %xmm0
callq 0x21940
movl %eax, -0xcc(%rbp)
cmpl $0x0, -0xcc(%rbp)
jle 0x21d4a
movslq -0xcc(%rbp), %rax
movq %rax, -0x10(%rbp)
jmp 0x221f9
movq $0x0, -0x38(%rbp)
movq -0x38(%rbp), %rax
cmpq -0x10(%rbp), %rax
jge 0x21d7e
movq -0x18(%rbp), %rax
movq 0x28(%rax), %rax
movq -0x38(%rbp), %rcx
movq $-0x1, (%rax,%rcx,8)
movq -0x38(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x38(%rbp)
jmp 0x21d52
movq $0x0, -0x38(%rbp)
movq -0x38(%rbp), %rax
cmpq -0x10(%rbp), %rax
jge 0x221f7
movl $0x0, -0xd0(%rbp)
movl $0x0, -0xd4(%rbp)
movq -0x8(%rbp), %rax
movq -0x38(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x4(%rax), %eax
movq %rax, -0x50(%rbp)
movq -0x8(%rbp), %rax
movq -0x38(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x8(%rax), %eax
movq %rax, -0x48(%rbp)
movq $-0x1, -0x58(%rbp)
movq -0xa0(%rbp), %rax
movq -0x8(%rbp), %rcx
movq -0x38(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rcx
movl 0xc(%rcx), %ecx
cmpq %rcx, %rax
jl 0x21e21
movq -0xa0(%rbp), %rax
movq -0x8(%rbp), %rcx
movq -0x38(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rcx
movl 0xc(%rcx), %ecx
cqto
idivq %rcx
movq %rax, -0x100(%rbp)
jmp 0x21e2f
movl $0x1, %eax
movq %rax, -0x100(%rbp)
jmp 0x21e2f
movq -0x100(%rbp), %rax
movq %rax, -0x68(%rbp)
movq $0x0, -0xa8(%rbp)
movq $0x0, -0xb0(%rbp)
movq -0x38(%rbp), %rax
subq $0x1, %rax
movq %rax, -0x40(%rbp)
cmpq $0x0, -0x40(%rbp)
jl 0x22151
movq -0x50(%rbp), %rax
movq -0x8(%rbp), %rcx
movq -0x40(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rcx
movl 0x4(%rcx), %ecx
subq %rcx, %rax
movq %rax, -0x78(%rbp)
movq -0x48(%rbp), %rax
movq -0x8(%rbp), %rcx
movq -0x40(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rcx
movl 0x8(%rcx), %ecx
subq %rcx, %rax
movq %rax, -0x80(%rbp)
cmpq $0x0, -0x78(%rbp)
je 0x21eaf
cmpq $0x0, -0x80(%rbp)
jg 0x21eb4
jmp 0x22140
movq -0x78(%rbp), %rax
cmpq -0x80(%rbp), %rax
jle 0x21ecf
movq -0x78(%rbp), %rax
subq -0x80(%rbp), %rax
movq %rax, -0x108(%rbp)
jmp 0x21ede
movq -0x80(%rbp), %rax
subq -0x78(%rbp), %rax
movq %rax, -0x108(%rbp)
movq -0x108(%rbp), %rax
movq %rax, -0x88(%rbp)
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rax
movq -0x40(%rbp), %rcx
movslq (%rax,%rcx,4), %rax
addq -0x88(%rbp), %rax
movq %rax, -0xc0(%rbp)
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rax
movq -0x40(%rbp), %rcx
movslq (%rax,%rcx,4), %rax
addq -0x80(%rbp), %rax
movq %rax, -0xc8(%rbp)
cvtsi2sdq -0xc0(%rbp), %xmm0
movsd -0x28(%rbp), %xmm1
cvtsi2sdq -0xc8(%rbp), %xmm2
mulsd %xmm2, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x21f4b
jmp 0x22140
movq -0x78(%rbp), %rax
cmpq -0x80(%rbp), %rax
jge 0x21f62
movq -0x78(%rbp), %rax
movq %rax, -0x110(%rbp)
jmp 0x21f6d
movq -0x80(%rbp), %rax
movq %rax, -0x110(%rbp)
movq -0x110(%rbp), %rax
movq %rax, -0x90(%rbp)
movq -0x90(%rbp), %rax
cmpq -0xa0(%rbp), %rax
jge 0x21f9b
movq -0x90(%rbp), %rax
movq %rax, -0x118(%rbp)
jmp 0x21fa9
movq -0xa0(%rbp), %rax
movq %rax, -0x118(%rbp)
movq -0x118(%rbp), %rax
movq %rax, -0x70(%rbp)
movq -0x70(%rbp), %rax
movq -0x8(%rbp), %rcx
movq -0x40(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rcx
movl 0xc(%rcx), %ecx
cmpq %rcx, %rax
jl 0x21ff3
movq -0x70(%rbp), %rax
movq -0x8(%rbp), %rcx
movq -0x40(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rcx
movl 0xc(%rcx), %ecx
cqto
idivq %rcx
movq %rax, -0x120(%rbp)
jmp 0x22001
movl $0x1, %eax
movq %rax, -0x120(%rbp)
jmp 0x22001
movq -0x120(%rbp), %rax
movq %rax, -0x70(%rbp)
cvtsi2sdq -0xc0(%rbp), %xmm0
cvtsi2sdq -0xc8(%rbp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0xb8(%rbp)
movsd -0xb8(%rbp), %xmm0
cvtsi2sdq -0x70(%rbp), %xmm1
mulsd %xmm1, %xmm0
mulsd -0x98(%rbp), %xmm0
cvttsd2si %xmm0, %rcx
movq -0x70(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x70(%rbp)
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq -0x40(%rbp), %rcx
movslq (%rax,%rcx,4), %rax
addq -0x70(%rbp), %rax
movq %rax, -0x70(%rbp)
movq -0x70(%rbp), %rax
cmpq -0x68(%rbp), %rax
jle 0x220c5
movq -0x70(%rbp), %rax
movq %rax, -0x68(%rbp)
movq -0x40(%rbp), %rax
movq %rax, -0x58(%rbp)
movq -0xc0(%rbp), %rax
movq %rax, -0xa8(%rbp)
movq -0xc8(%rbp), %rax
movq %rax, -0xb0(%rbp)
movl $0x0, -0xd4(%rbp)
cmpl $0x0, -0xd0(%rbp)
jle 0x220c3
movl -0xd0(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0xd0(%rbp)
jmp 0x2210b
movl -0xd4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xd4(%rbp)
cmpl -0x2c(%rbp), %eax
jle 0x220db
jmp 0x22151
movq -0x18(%rbp), %rax
movq 0x28(%rax), %rax
movq -0x40(%rbp), %rcx
movq (%rax,%rcx,8), %rax
cmpq -0x38(%rbp), %rax
jne 0x22109
movl -0xd0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xd0(%rbp)
cmpl -0x2c(%rbp), %eax
jle 0x22107
jmp 0x22151
jmp 0x22109
jmp 0x2210b
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
movq -0x40(%rbp), %rcx
cmpq $0x0, (%rax,%rcx,8)
jl 0x2213e
movq -0x38(%rbp), %rdx
movq -0x18(%rbp), %rax
movq 0x28(%rax), %rax
movq -0x18(%rbp), %rcx
movq 0x8(%rcx), %rcx
movq -0x40(%rbp), %rsi
movq (%rcx,%rsi,8), %rcx
movq %rdx, (%rax,%rcx,8)
jmp 0x22140
movq -0x40(%rbp), %rax
addq $-0x1, %rax
movq %rax, -0x40(%rbp)
jmp 0x21e5c
movq -0x68(%rbp), %rax
movl %eax, %edx
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq -0x38(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movq -0x58(%rbp), %rdx
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
movq -0x38(%rbp), %rcx
movq %rdx, (%rax,%rcx,8)
movq -0xa8(%rbp), %rax
movl %eax, %edx
movq -0x18(%rbp), %rax
movq 0x10(%rax), %rax
movq -0x38(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movq -0xb0(%rbp), %rax
movl %eax, %edx
movq -0x18(%rbp), %rax
movq 0x18(%rax), %rax
movq -0x38(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movq -0x18(%rbp), %rax
movq 0x20(%rax), %rax
movq -0x38(%rbp), %rcx
movl $0x1, (%rax,%rcx,4)
cmpq $-0x1, -0x58(%rbp)
je 0x221e4
movq -0x18(%rbp), %rax
movq 0x20(%rax), %rax
movq -0x58(%rbp), %rcx
movl (%rax,%rcx,4), %edx
addl $0x1, %edx
movq -0x18(%rbp), %rax
movq 0x20(%rax), %rax
movq -0x38(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
jmp 0x221e6
movq -0x38(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x38(%rbp)
jmp 0x21d86
jmp 0x221f9
movq $-0x1, -0x68(%rbp)
movq $-0x1, -0x60(%rbp)
movl -0x30(%rbp), %eax
shll %eax
addl $0x2, %eax
cltq
movq %rax, -0xe0(%rbp)
movq $0x0, -0x38(%rbp)
movq -0x38(%rbp), %rax
cmpq -0x10(%rbp), %rax
jge 0x2239c
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq -0x38(%rbp), %rcx
movslq (%rax,%rcx,4), %rax
cmpq -0x68(%rbp), %rax
jle 0x222ce
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq -0x38(%rbp), %rcx
movslq (%rax,%rcx,4), %rax
movq %rax, -0x68(%rbp)
movq -0x38(%rbp), %rax
movq %rax, -0x60(%rbp)
movq -0x8(%rbp), %rax
movq -0x38(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x8(%rax), %eax
movl %eax, %edi
movq -0x8(%rbp), %rax
movq -0x38(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x8(%rax), %eax
movl %eax, %esi
movslq -0x30(%rbp), %rdx
movq -0x8(%rbp), %rax
movq -0x38(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x4(%rax), %eax
movl %eax, %ecx
movq -0x8(%rbp), %rax
movq -0x38(%rbp), %r8
shlq $0x4, %r8
addq %r8, %rax
movl 0x4(%rax), %eax
movl %eax, %r8d
movslq 0x10(%rbp), %r9
callq 0x21580
movq %rax, -0xe0(%rbp)
jmp 0x22389
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq -0x38(%rbp), %rcx
movslq (%rax,%rcx,4), %rax
cmpq -0x68(%rbp), %rax
jne 0x22387
movq -0x8(%rbp), %rax
movq -0x38(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x8(%rax), %eax
movl %eax, %edi
movq -0x8(%rbp), %rax
movq -0x38(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x8(%rax), %eax
movl %eax, %esi
movslq -0x30(%rbp), %rdx
movq -0x8(%rbp), %rax
movq -0x38(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x4(%rax), %eax
movl %eax, %ecx
movq -0x8(%rbp), %rax
movq -0x38(%rbp), %r8
shlq $0x4, %r8
addq %r8, %rax
movl 0x4(%rax), %eax
movl %eax, %r8d
movslq 0x10(%rbp), %r9
callq 0x21580
movq %rax, -0xe8(%rbp)
movq -0xe8(%rbp), %rax
cmpq -0xe0(%rbp), %rax
jge 0x22385
movq -0x18(%rbp), %rax
movq (%rax), %rax
movq -0x38(%rbp), %rcx
movslq (%rax,%rcx,4), %rax
movq %rax, -0x68(%rbp)
movq -0x38(%rbp), %rax
movq %rax, -0x60(%rbp)
movq -0xe8(%rbp), %rax
movq %rax, -0xe0(%rbp)
jmp 0x22387
jmp 0x22389
jmp 0x2238b
movq -0x38(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x38(%rbp)
jmp 0x22222
movq -0x20(%rbp), %rdi
addq $0x38, %rdi
callq 0x1e1d0
movq -0x60(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x8(%rbp), %rax
movq -0x38(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x8(%rax), %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x8(%rax)
movq -0x8(%rbp), %rax
movq -0x38(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x4(%rax), %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x18(%rax)
movq -0x68(%rbp), %rax
movl %eax, %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x24(%rax)
movq -0xe0(%rbp), %rax
movl %eax, %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x20(%rax)
movq -0x20(%rbp), %rax
movl 0x8(%rax), %eax
movq -0x8(%rbp), %rcx
movq -0x38(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rcx
subl 0x8(%rcx), %eax
movl %eax, %eax
movq %rax, -0x80(%rbp)
movq -0x20(%rbp), %rax
movl 0x18(%rax), %eax
movq -0x8(%rbp), %rcx
movq -0x38(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rcx
subl 0x4(%rcx), %eax
movl %eax, %eax
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
subq -0x80(%rbp), %rax
movq %rax, -0xf0(%rbp)
movq -0x20(%rbp), %rdi
addq $0x38, %rdi
movq -0x8(%rbp), %rax
movq -0x38(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x8(%rax), %esi
movq -0xf0(%rbp), %rax
movl %eax, %edx
movq 0x18(%rbp), %rcx
callq 0x1e500
movq $0x0, -0xf8(%rbp)
movq -0x20(%rbp), %rax
cmpl $0x1, 0xc(%rax)
jne 0x22598
jmp 0x22494
cmpq $0x0, -0x38(%rbp)
jl 0x22593
movq -0x20(%rbp), %rax
movl 0x8(%rax), %eax
movq -0x8(%rbp), %rcx
movq -0x38(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rcx
subl 0x8(%rcx), %eax
movl %eax, %eax
movq %rax, -0x80(%rbp)
movq -0x20(%rbp), %rax
movl 0x18(%rax), %eax
movq -0x8(%rbp), %rcx
movq -0x38(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rcx
subl 0x4(%rcx), %eax
movl %eax, %eax
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
subq -0x80(%rbp), %rax
movq %rax, -0x88(%rbp)
movq -0x88(%rbp), %rax
cmpq -0xf0(%rbp), %rax
je 0x22536
movq -0x88(%rbp), %rax
movq %rax, -0xf0(%rbp)
movq -0x20(%rbp), %rdi
addq $0x38, %rdi
movq -0x8(%rbp), %rax
movq -0x38(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x8(%rax), %esi
movq -0xf0(%rbp), %rax
movl %eax, %edx
movq 0x18(%rbp), %rcx
callq 0x1e500
movq -0xf8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xf8(%rbp)
movq -0x8(%rbp), %rax
movq -0x38(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x8(%rax), %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x4(%rax)
movq -0x8(%rbp), %rax
movq -0x38(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x4(%rax), %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x14(%rax)
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
movq -0x38(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x38(%rbp)
jmp 0x22494
jmp 0x226d6
jmp 0x2259a
cmpq $0x0, -0x38(%rbp)
jl 0x226d4
movq -0x20(%rbp), %rax
movl 0x8(%rax), %eax
movq -0x8(%rbp), %rcx
movq -0x38(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rcx
subl 0x8(%rcx), %eax
movl %eax, %eax
movq %rax, -0x80(%rbp)
movq -0x20(%rbp), %rax
movl 0x18(%rax), %eax
movq -0x8(%rbp), %rcx
movq -0x38(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rcx
subl 0x4(%rcx), %eax
movl %eax, %eax
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
subq -0x80(%rbp), %rax
movq %rax, -0x88(%rbp)
movq -0x88(%rbp), %rax
cmpq -0xf0(%rbp), %rax
jne 0x2263d
movq -0x20(%rbp), %rax
movl 0x40(%rax), %ecx
addl $-0x1, %ecx
movl %ecx, 0x40(%rax)
movq -0x20(%rbp), %rdi
addq $0x38, %rdi
movq -0x8(%rbp), %rax
movq -0x38(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x8(%rax), %esi
movq -0xf0(%rbp), %rax
movl %eax, %edx
movq 0x18(%rbp), %rcx
callq 0x1e500
jmp 0x22677
movq -0x88(%rbp), %rax
movq %rax, -0xf0(%rbp)
movq -0x20(%rbp), %rdi
addq $0x38, %rdi
movq -0x8(%rbp), %rax
movq -0x38(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x8(%rax), %esi
movq -0xf0(%rbp), %rax
movl %eax, %edx
movq 0x18(%rbp), %rcx
callq 0x1e500
movq -0xf8(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xf8(%rbp)
movq -0x8(%rbp), %rax
movq -0x38(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x8(%rax), %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x4(%rax)
movq -0x8(%rbp), %rax
movq -0x38(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x4(%rax), %ecx
movq -0x20(%rbp), %rax
movl %ecx, 0x14(%rax)
movq -0x18(%rbp), %rax
movq 0x8(%rax), %rax
movq -0x38(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x38(%rbp)
jmp 0x2259a
jmp 0x226d6
movq -0xf8(%rbp), %rax
addq $0x120, %rsp            # imm = 0x120
popq %rbp
retq
nopw %cs:(%rax,%rax)