// File: /workspace/github_cpp_makefile_star2_O3/chhylp123[P]hifiasm/Overlaps.cpp
// Function: calculate_peak(unsigned long*, long long, kvec_t_u32_warp*, long long, long long, long long*, long long*)
void calculate_peak(uint64_t* counts, long long len, kvec_t_u32_warp* a, 
long long TotalMean, long long HapMean, long long* peak0, long long* peak1)
{
    if(len == 0) return;
    long long i, j, total_coverage = 0, current_coverage, step, pre, after, is_found = 0;
    for (i = 0; i < len; i++)
    {
        total_coverage = total_coverage + ((counts[i]>>32) * ((uint32_t)counts[i]));
    }
    current_coverage = total_coverage;
    for (i = len - 1; i >= 0; i--)
    {
        current_coverage = current_coverage - ((counts[i]>>32) * ((uint32_t)counts[i]));
        if(current_coverage <= total_coverage*0.9) break;
    }
    i++;
    step = i*0.1;
    if(step < 2) step = 2;
    ///fprintf(stderr, "step: %lld\n", step);
    

    a->a.n = 0;
    ///for (i = 0; i < len; i++)
    for (i = 1; i < len; i++)
    {
        pre = i - step/2;
        after = i + step/2;
        if(pre < 0) pre = 0;
        if(after >= len) after = len - 1;
        is_found = 0;
        for (j = pre; j < after; j++)
        {
            if(j == i) continue;
            if(((uint32_t)counts[i]) <= ((uint32_t)counts[j]))
            {
                is_found = 1;
                break;
            } 
        }
        
        if(is_found == 0)
        {
            kv_push(uint32_t, a->a, i);
        }
    }

    

    uint32_t peak_0_i, peak_1_i;
    peak_0_i = peak_1_i = 0;

    for (i = 0; i < (long long)a->a.n; i++)
    {
        if(((uint32_t)counts[a->a.a[peak_0_i]]) < ((uint32_t)counts[a->a.a[i]]))
        {
            peak_0_i = i;
        }
    }

    peak_1_i = (uint32_t)-1;
    for (i = 0; i < (long long)a->a.n; i++)
    {
        if(peak_0_i == i) continue;
        if(peak_1_i == (uint32_t)-1)
        {
            peak_1_i = i;
            continue;
        }
        if(((uint32_t)counts[a->a.a[peak_1_i]]) < ((uint32_t)counts[a->a.a[i]]))
        {
            peak_1_i = i;
        }
    }

    if(peak_0_i == peak_1_i) peak_1_i = (uint32_t)-1;

    
    // for (i = 0; i < (long long)a->a.n; i++)
    // {
    //     fprintf(stderr, "i:%lld, freq: %u, num: %u\n", i, 
    //     (uint32_t)(counts[a->a.a[i]]>>32), (uint32_t)counts[a->a.a[i]]);
    // }
    // fprintf(stderr, "peak_0_i: %u, peak_1_i: %u\n", peak_0_i, peak_1_i); 

    (*peak0) = (*peak1) = -1;
    /**
     * There are three cases:
     * 1. very low het rate: don't need purge_dup
     * 2. very high het rate: TotalMean should be equal to peak_0
     * 3. not such high het rate: two peaks, HapMean should be useful
     * **/
    
    if(peak_1_i == (uint32_t)-1)
    {
        (*peak0) = (uint32_t)(counts[a->a.a[peak_0_i]]>>32);
        return;
    }

    (*peak0) = (uint32_t)(counts[a->a.a[peak_0_i]]>>32);
    (*peak1) = (uint32_t)(counts[a->a.a[peak_1_i]]>>32);


    if(TotalMean >= (long long)((uint32_t)(counts[a->a.a[peak_0_i]]>>32)) && 
       TotalMean >= (long long)((uint32_t)(counts[a->a.a[peak_1_i]]>>32)))
    {
        (*peak1) = -1;
        return;
    }

    long long max_cov = MAX((*peak0), TotalMean);
    long long min_cov = MIN((*peak0), TotalMean);
    if(min_cov >= max_cov*0.8)
    {
        max_cov = MAX((*peak1), TotalMean);
        min_cov = MIN((*peak1), TotalMean);
        if(min_cov < max_cov*0.6)
        {
            (*peak1) = -1;
            return;
        }
    }


    long long hap_cov = ((uint32_t)(counts[a->a.a[MIN(peak_0_i, peak_1_i)]]>>32));
    max_cov = MAX(hap_cov, HapMean);
    min_cov = MIN(hap_cov, HapMean);
    ///fprintf(stderr, "hap_cov: %lld, max_cov: %lld, min_cov: %lld\n", hap_cov, max_cov, min_cov); 
    if(min_cov < max_cov*0.70)
    {
        (*peak1) = -1;
        return;
    }

    min_cov = MIN((*peak0), (*peak1));
    max_cov = MAX((*peak0), (*peak1));
    (*peak0) = min_cov;
    (*peak1) = max_cov;
}

// Assembly:
testq %rsi, %rsi
je 0xed7c4
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
leaq -0x18(%rsp), %rsp
movq %rdx, %r13
movq %rdi, %r14
movq 0x50(%rsp), %rbx
jle 0xed794
movq %rsi, %rbp
xorl %edi, %edi
xorl %eax, %eax
movq (%r14,%rdi,8), %rdx
movl %edx, %esi
shrq $0x20, %rdx
imulq %rdx, %rsi
addq %rsi, %rax
incq %rdi
cmpq %rdi, %rbp
jne 0xed58c
testq %rbp, %rbp
jle 0xed794
cvtsi2sd %rax, %xmm0
leaq -0x1(%rbp), %r15
mulsd 0x144039(%rip), %xmm0   # 0x2315f8
movq %r15, %rdi
movq (%r14,%rdi,8), %rdx
movl %edx, %esi
shrq $0x20, %rdx
imulq %rdx, %rsi
subq %rsi, %rax
xorps %xmm1, %xmm1
cvtsi2sd %rax, %xmm1
ucomisd %xmm1, %xmm0
jae 0xed5f4
leaq -0x1(%rdi), %rdx
testq %rdi, %rdi
movq %rdx, %rdi
jg 0xed5c2
movq $-0x1, %rdi
movq $0x0, (%r13)
cmpq $0x1, %rbp
je 0xed79c
movq %rcx, (%rsp)
movq %r8, 0x8(%rsp)
movq %r9, 0x10(%rsp)
incq %rdi
xorps %xmm0, %xmm0
cvtsi2sd %rdi, %xmm0
mulsd 0x1435e9(%rip), %xmm0   # 0x230c10
cvttsd2si %xmm0, %r12
cmpq $0x3, %r12
movl $0x2, %eax
cmovlq %rax, %r12
shrq %r12
movl $0x1, %ebx
xorl %edi, %edi
xorl %ecx, %ecx
movq %rbx, %rax
subq %r12, %rax
leaq (%rbx,%r12), %rdx
testq %rax, %rax
cmovleq %rdi, %rax
cmpq %rbp, %rdx
cmovgeq %r15, %rdx
cmpq %rdx, %rax
jge 0xed676
cmpq %rax, %rbx
je 0xed671
movl (%r14,%rbx,8), %esi
cmpl (%r14,%rax,8), %esi
jbe 0xed6b8
incq %rax
jmp 0xed65d
movq 0x10(%r13), %rax
cmpq 0x8(%r13), %rcx
jne 0xed6aa
leaq (%rcx,%rcx), %rsi
testq %rcx, %rcx
movl $0x2, %ecx
cmoveq %rcx, %rsi
movq %rsi, 0x8(%r13)
shlq $0x2, %rsi
movq %rax, %rdi
callq 0x2370
xorl %edi, %edi
movq %rax, 0x10(%r13)
movq (%r13), %rcx
leaq 0x1(%rcx), %rdx
movq %rdx, (%r13)
movl %ebx, (%rax,%rcx,4)
movq %rdx, %rcx
incq %rbx
cmpq %rbp, %rbx
jne 0xed645
testq %rcx, %rcx
movq 0x10(%rsp), %r9
movq 0x50(%rsp), %rbx
jle 0xed79c
movq 0x10(%r13), %rdx
xorl %esi, %esi
xorl %edi, %edi
movq 0x8(%rsp), %r15
movq (%rsp), %r12
movl %edi, %eax
movl (%rdx,%rax,4), %eax
movl (%r14,%rax,8), %r8d
movl (%rdx,%rsi,4), %r10d
movl %esi, %eax
cmpl (%r14,%r10,8), %r8d
jb 0xed6fb
movl %edi, %eax
incq %rsi
movl %eax, %edi
cmpq %rsi, %rcx
jne 0xed6e4
testq %rcx, %rcx
jle 0xed79e
movl %eax, %esi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
xorl %edi, %edi
cmpq %rdi, %rsi
je 0xed747
cmpl $-0x1, %edx
je 0xed745
movq 0x10(%r13), %r8
movl %edx, %r10d
movl (%r8,%r10,4), %r10d
movl (%r14,%r10,8), %r11d
movl (%r8,%rdi,4), %r10d
movl %edi, %r8d
cmpl (%r14,%r10,8), %r11d
jb 0xed740
movl %edx, %r8d
movl %r8d, %edx
jmp 0xed747
movl %edi, %edx
incq %rdi
cmpq %rdi, %rcx
jne 0xed717
movq $-0x1, (%rbx)
cmpl %edx, %esi
je 0xed7a5
cmpl $-0x1, %edx
je 0xed7a5
movq 0x10(%r13), %rdi
movl (%rdi,%rsi,4), %ecx
movq (%r14,%rcx,8), %rsi
shrq $0x20, %rsi
movq %rsi, (%r9)
movl %edx, %ecx
movl (%rdi,%rcx,4), %ecx
movq (%r14,%rcx,8), %rcx
shrq $0x20, %rcx
movq %rcx, (%rbx)
cmpq %r12, %rsi
jg 0xed7c5
cmpq %r12, %rcx
ja 0xed7c5
movq $-0x1, (%rbx)
jmp 0xed7b6
movq $0x0, (%r13)
xorl %eax, %eax
movq $-0x1, (%rbx)
movq 0x10(%r13), %rcx
movl %eax, %eax
movl (%rcx,%rax,4), %eax
movl 0x4(%r14,%rax,8), %eax
movq %rax, (%r9)
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq (%r9), %rsi
cmpq %r12, %rsi
movq %r12, %r8
cmovgq %rsi, %r8
movq %r12, %r10
cmovlq %rsi, %r10
cvtsi2sd %r10, %xmm0
cvtsi2sd %r8, %xmm1
mulsd 0x143dc5(%rip), %xmm1   # 0x2315b0
ucomisd %xmm1, %xmm0
jb 0xed824
cmpq %r12, %rcx
movq %r12, %r8
cmovgq %rcx, %r8
cmovlq %rcx, %r12
xorps %xmm0, %xmm0
cvtsi2sd %r12, %xmm0
xorps %xmm1, %xmm1
cvtsi2sd %r8, %xmm1
mulsd 0x143d71(%rip), %xmm1   # 0x231588
movq $-0x1, %r8
ucomisd %xmm0, %xmm1
ja 0xed87b
cmpl %edx, %eax
cmovbl %eax, %edx
movl (%rdi,%rdx,4), %eax
movq (%r14,%rax,8), %rax
shrq $0x20, %rax
cmpq %r15, %rax
movq %r15, %rdx
cmovgq %rax, %rdx
cmovgeq %r15, %rax
xorps %xmm0, %xmm0
cvtsi2sd %rax, %xmm0
xorps %xmm1, %xmm1
cvtsi2sd %rdx, %xmm1
mulsd 0x143d46(%rip), %xmm1   # 0x2315a0
movq $-0x1, %r8
ucomisd %xmm0, %xmm1
ja 0xed87b
cmpq %rcx, %rsi
movq %rcx, %rax
cmovlq %rsi, %rax
cmovgq %rsi, %rcx
movq %rax, (%r9)
movq %rcx, %r8
movq %r8, (%rbx)
jmp 0xed7b6