// File: chhylp123[P]hifiasm/htab.cpp
// Function: ha_pt_gen(hifiasm_opt_t const*, void const*, int, int, All_reads*, int*, int*)
ha_pt_t *ha_pt_gen(const hifiasm_opt_t *asm_opt, const void *flt_tab, int read_from_store, int is_hp_mode, All_reads *rs, int *hom_cov, int *het_cov)
{
	int64_t cnt[YAK_N_COUNTS], tot_cnt;
	int peak_hom, peak_het, i, extra_flag1, extra_flag2;
	ha_ct_t *ct;
	ha_pt_t *pt;
	if (read_from_store) {///if reads have already been read
		extra_flag1 = extra_flag2 = HAF_RS_READ;
	} else if (rs->total_reads == 0) {///if reads & length have not been scanned
		extra_flag1 = HAF_RS_WRITE_LEN;
		extra_flag2 = HAF_RS_WRITE_SEQ;
	} else {///if length has been loaded but reads have not
		extra_flag1 = HAF_RS_WRITE_SEQ;
		extra_flag2 = HAF_RS_READ;
	}
	if(is_hp_mode) extra_flag1 |= HAF_SKIP_READ, extra_flag2 |= HAF_SKIP_READ;

	ct = ha_count(asm_opt, HAF_COUNT_EXACT|extra_flag1,  !(asm_opt->flag&HA_F_NO_HPC), asm_opt->k_mer_length, asm_opt->mz_win, NULL, flt_tab, rs, NULL, 1, NULL, 0);
	fprintf(stderr, "[M::%s::%.3f*%.2f] ==> counted %ld distinct minimizer k-mers\n", __func__,
			yak_realtime(), yak_cpu_usage(), (long)ct->tot);
	ha_ct_hist(ct, cnt, asm_opt->thread_num);
	fprintf(stderr, "[M::%s] count[%d] = %ld (for sanity check)\n", __func__, YAK_MAX_COUNT, (long)cnt[YAK_MAX_COUNT]);
	peak_hom = ha_analyze_count(YAK_N_COUNTS, asm_opt->min_hist_kmer_cnt, asm_opt->hg_size>0?(ct->bs/asm_opt->hg_size):(-1), cnt, &peak_het);
	if (hom_cov) *hom_cov = peak_hom;
	if (het_cov) *het_cov = peak_het;
	if (peak_hom > 0) fprintf(stderr, "[M::%s] peak_hom: %d; peak_het: %d\n", __func__, peak_hom, peak_het);
	///here ha_ct_shrink is mostly used to remove k-mer appearing only 1 time
	if (flt_tab == 0) {
		int cutoff = (int)(peak_hom * asm_opt->high_factor);
		if (cutoff > YAK_MAX_COUNT - 1) cutoff = YAK_MAX_COUNT - 1;
		if((extra_flag1 & HAF_SKIP_READ) && (extra_flag2 & HAF_SKIP_READ)) cutoff = YAK_MAX_COUNT - 1;
		ha_ct_shrink(ct, 2, cutoff, asm_opt->thread_num);
		for (i = 2, tot_cnt = 0; i <= cutoff; ++i) tot_cnt += cnt[i] * i;
	} else {
		///Note: here is just to remove minimizer appearing YAK_MAX_COUNT times
		///minimizer with YAK_MAX_COUNT occ may apper > YAK_MAX_COUNT times, so it may lead to overflow at ha_pt_gen
		ha_ct_shrink(ct, 2, YAK_MAX_COUNT - 1, asm_opt->thread_num);
		for (i = 2, tot_cnt = 0; i <= YAK_MAX_COUNT - 1; ++i) tot_cnt += cnt[i] * i;
	}
	if(!(asm_opt->flag & HA_F_FAST))
	{
		fprintf(stderr, "[M::%s::] counting in normal mode\n", __func__);
		pt = ha_pt_gen(ct, asm_opt->thread_num, 0);
		ha_count(asm_opt, HAF_COUNT_EXACT|extra_flag2,  !(asm_opt->flag&HA_F_NO_HPC), asm_opt->k_mer_length, asm_opt->mz_win, pt, flt_tab, rs, NULL, 1, NULL, 0);
		assert((uint64_t)tot_cnt == pt->tot_pos);
	}
	else
	{
		fprintf(stderr, "[M::%s::] counting in fast mode\n", __func__);
		pt = ha_pt_gen_dp(asm_opt, ct, HAF_COUNT_EXACT|extra_flag2, asm_opt->thread_num, flt_tab, rs, peak_hom, peak_het);
	}
	//ha_pt_sort(pt, asm_opt->thread_num);
	fprintf(stderr, "[M::%s::%.3f*%.2f] ==> indexed %ld positions, counted %ld distinct minimizer k-mers\n", __func__,
			yak_realtime(), yak_cpu_usage(), (long)pt->tot_pos, (long)pt->tot);
	return pt;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x80c0, %rsp           # imm = 0x80C0
movq 0x10(%rbp), %rax
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl %edx, -0x14(%rbp)
movl %ecx, -0x18(%rbp)
movq %r8, -0x20(%rbp)
movq %r9, -0x28(%rbp)
cmpl $0x0, -0x14(%rbp)
je 0x18a1c1
movl $0x10, -0x804c(%rbp)
movl $0x10, -0x8048(%rbp)
jmp 0x18a1f8
movq -0x20(%rbp), %rax
cmpq $0x0, 0x50(%rax)
jne 0x18a1e2
movl $0x4, -0x8048(%rbp)
movl $0x8, -0x804c(%rbp)
jmp 0x18a1f6
movl $0x8, -0x8048(%rbp)
movl $0x10, -0x804c(%rbp)
jmp 0x18a1f8
cmpl $0x0, -0x18(%rbp)
je 0x18a21c
movl -0x8048(%rbp), %eax
orl $0x40, %eax
movl %eax, -0x8048(%rbp)
movl -0x804c(%rbp), %eax
orl $0x40, %eax
movl %eax, -0x804c(%rbp)
movq -0x8(%rbp), %rdi
movl -0x8048(%rbp), %esi
orl $0x1, %esi
movq -0x8(%rbp), %rax
movl (%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
setne %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %edx
movq -0x8(%rbp), %rax
movl 0x80(%rax), %ecx
movq -0x8(%rbp), %rax
movl 0x94(%rax), %r8d
movq -0x10(%rbp), %r10
movq -0x20(%rbp), %rax
xorl %r9d, %r9d
xorl %r11d, %r11d
movq %r10, (%rsp)
movq %rax, 0x8(%rsp)
movq $0x0, 0x10(%rsp)
movl $0x1, 0x18(%rsp)
movq $0x0, 0x20(%rsp)
movl $0x0, 0x28(%rsp)
callq 0x1886f0
movq %rax, -0x8058(%rbp)
movq 0x239d40(%rip), %rax    # 0x3c3fe0
movq (%rax), %rax
movq %rax, -0x8078(%rbp)
callq 0x1b7ca0
movsd %xmm0, -0x8070(%rbp)
callq 0x1b7d20
movq -0x8078(%rbp), %rdi
movaps %xmm0, %xmm1
movsd -0x8070(%rbp), %xmm0
movq -0x8058(%rbp), %rax
movq 0x10(%rax), %rcx
leaq 0x20090b(%rip), %rsi    # 0x38abeb
leaq 0x200a04(%rip), %rdx    # 0x38aceb
movb $0x2, %al
callq 0x22a0
movq -0x8058(%rbp), %rdi
leaq -0x8030(%rbp), %rsi
movq -0x8(%rbp), %rax
movl 0x7c(%rax), %edx
callq 0x189a70
movq 0x239cd1(%rip), %rax    # 0x3c3fe0
movq (%rax), %rdi
movq -0x38(%rbp), %r8
leaq 0x2009d8(%rip), %rsi    # 0x38acf5
leaq 0x2009c7(%rip), %rdx    # 0x38aceb
movl $0xfff, %ecx            # imm = 0xFFF
movb $0x0, %al
callq 0x22a0
movq -0x8(%rbp), %rax
movl 0xec(%rax), %eax
movl %eax, -0x8068(%rbp)
movq -0x8(%rbp), %rax
cmpq $0x0, 0x200(%rax)
jle 0x18a36f
movq -0x8058(%rbp), %rax
movq 0x18(%rax), %rax
movq -0x8(%rbp), %rcx
xorl %edx, %edx
divq 0x200(%rcx)
movq %rax, -0x8080(%rbp)
jmp 0x18a37f
movq $-0x1, %rax
movq %rax, -0x8080(%rbp)
jmp 0x18a37f
movl -0x8068(%rbp), %esi
movq -0x8080(%rbp), %rax
movl %eax, %edx
leaq -0x8030(%rbp), %rcx
movl $0x1000, %edi           # imm = 0x1000
leaq -0x8040(%rbp), %r8
callq 0x1925c0
movl %eax, -0x803c(%rbp)
cmpq $0x0, -0x28(%rbp)
je 0x18a3bf
movl -0x803c(%rbp), %ecx
movq -0x28(%rbp), %rax
movl %ecx, (%rax)
cmpq $0x0, 0x10(%rbp)
je 0x18a3d2
movl -0x8040(%rbp), %ecx
movq 0x10(%rbp), %rax
movl %ecx, (%rax)
cmpl $0x0, -0x803c(%rbp)
jle 0x18a407
movq 0x239bfe(%rip), %rax    # 0x3c3fe0
movq (%rax), %rdi
movl -0x803c(%rbp), %ecx
movl -0x8040(%rbp), %r8d
leaq 0x2007c4(%rip), %rsi    # 0x38abbd
leaq 0x2008eb(%rip), %rdx    # 0x38aceb
movb $0x0, %al
callq 0x22a0
cmpq $0x0, -0x10(%rbp)
jne 0x18a4e8
cvtsi2sdl -0x803c(%rbp), %xmm0
movq -0x8(%rbp), %rax
mulsd 0xb8(%rax), %xmm0
cvttsd2si %xmm0, %eax
movl %eax, -0x8064(%rbp)
cmpl $0xffe, -0x8064(%rbp)   # imm = 0xFFE
jle 0x18a446
movl $0xffe, -0x8064(%rbp)   # imm = 0xFFE
movl -0x8048(%rbp), %eax
andl $0x40, %eax
cmpl $0x0, %eax
je 0x18a46c
movl -0x804c(%rbp), %eax
andl $0x40, %eax
cmpl $0x0, %eax
je 0x18a46c
movl $0xffe, -0x8064(%rbp)   # imm = 0xFFE
movq -0x8058(%rbp), %rdi
movl -0x8064(%rbp), %edx
movq -0x8(%rbp), %rax
movl 0x7c(%rax), %ecx
movl $0x2, %esi
callq 0x1891f0
movl $0x2, -0x8044(%rbp)
movq $0x0, -0x8038(%rbp)
movl -0x8044(%rbp), %eax
cmpl -0x8064(%rbp), %eax
jg 0x18a4e6
movslq -0x8044(%rbp), %rax
movq -0x8030(%rbp,%rax,8), %rax
movslq -0x8044(%rbp), %rcx
imulq %rcx, %rax
addq -0x8038(%rbp), %rax
movq %rax, -0x8038(%rbp)
movl -0x8044(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8044(%rbp)
jmp 0x18a49f
jmp 0x18a561
movq -0x8058(%rbp), %rdi
movq -0x8(%rbp), %rax
movl 0x7c(%rax), %ecx
movl $0x2, %esi
movl $0xffe, %edx            # imm = 0xFFE
callq 0x1891f0
movl $0x2, -0x8044(%rbp)
movq $0x0, -0x8038(%rbp)
cmpl $0xffe, -0x8044(%rbp)   # imm = 0xFFE
jg 0x18a55f
movslq -0x8044(%rbp), %rax
movq -0x8030(%rbp,%rax,8), %rax
movslq -0x8044(%rbp), %rcx
imulq %rcx, %rax
addq -0x8038(%rbp), %rax
movq %rax, -0x8038(%rbp)
movl -0x8044(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8044(%rbp)
jmp 0x18a51a
jmp 0x18a561
movq -0x8(%rbp), %rax
movl (%rax), %eax
andl $0x1000, %eax           # imm = 0x1000
cmpl $0x0, %eax
jne 0x18a664
movq 0x239a64(%rip), %rax    # 0x3c3fe0
movq (%rax), %rdi
leaq 0x20079b(%rip), %rsi    # 0x38ad21
leaq 0x20075e(%rip), %rdx    # 0x38aceb
movb $0x0, %al
callq 0x22a0
movq -0x8058(%rbp), %rdi
movq -0x8(%rbp), %rax
movl 0x7c(%rax), %esi
xorl %edx, %edx
callq 0x186b00
movq %rax, -0x8060(%rbp)
movq -0x8(%rbp), %rdi
movl -0x804c(%rbp), %esi
orl $0x1, %esi
movq -0x8(%rbp), %rax
movl (%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
setne %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %edx
movq -0x8(%rbp), %rax
movl 0x80(%rax), %ecx
movq -0x8(%rbp), %rax
movl 0x94(%rax), %r8d
movq -0x8060(%rbp), %r9
movq -0x10(%rbp), %r10
movq -0x20(%rbp), %rax
xorl %r11d, %r11d
xorl %r11d, %r11d
movq %r10, (%rsp)
movq %rax, 0x8(%rsp)
movq $0x0, 0x10(%rsp)
movl $0x1, 0x18(%rsp)
movq $0x0, 0x20(%rsp)
movl $0x0, 0x28(%rsp)
callq 0x1886f0
movq -0x8038(%rbp), %rax
movq -0x8060(%rbp), %rcx
cmpq 0x10(%rcx), %rax
jne 0x18a643
jmp 0x18a662
leaq 0x2006fa(%rip), %rdi    # 0x38ad44
leaq 0x2002ae(%rip), %rsi    # 0x38a8ff
movl $0x4fc, %edx            # imm = 0x4FC
leaq 0x200708(%rip), %rcx    # 0x38ad65
callq 0x2130
jmp 0x18a6c7
movq 0x239975(%rip), %rax    # 0x3c3fe0
movq (%rax), %rdi
leaq 0x20074d(%rip), %rsi    # 0x38adc2
leaq 0x20066f(%rip), %rdx    # 0x38aceb
movb $0x0, %al
callq 0x22a0
movq -0x8(%rbp), %rdi
movq -0x8058(%rbp), %rsi
movl -0x804c(%rbp), %edx
orl $0x1, %edx
movq -0x8(%rbp), %rax
movl 0x7c(%rax), %ecx
movq -0x10(%rbp), %r8
movq -0x20(%rbp), %r9
movl -0x803c(%rbp), %r10d
movl -0x8040(%rbp), %eax
movl %r10d, (%rsp)
movl %eax, 0x8(%rsp)
callq 0x189f00
movq %rax, -0x8060(%rbp)
movq 0x239912(%rip), %rax    # 0x3c3fe0
movq (%rax), %rax
movq %rax, -0x8090(%rbp)
callq 0x1b7ca0
movsd %xmm0, -0x8088(%rbp)
callq 0x1b7d20
movq -0x8090(%rbp), %rdi
movaps %xmm0, %xmm1
movsd -0x8088(%rbp), %xmm0
movq -0x8060(%rbp), %rax
movq 0x10(%rax), %rcx
movq -0x8060(%rbp), %rax
movq 0x8(%rax), %r8
leaq 0x2006ca(%rip), %rsi    # 0x38ade3
leaq 0x2005cb(%rip), %rdx    # 0x38aceb
movb $0x2, %al
callq 0x22a0
movq -0x8060(%rbp), %rax
addq $0x80c0, %rsp           # imm = 0x80C0
popq %rbp
retq
nopw (%rax,%rax)