// File: /workspace/github_cpp_makefile_star2_O1/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:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %r8, 0x10(%rsp)
testq %rsi, %rsi
je 0xebf6f
movq %rdx, %r13
movq %rsi, %rbp
movq %rdi, %r15
movq %rcx, (%rsp)
jle 0xebcb7
xorl %ecx, %ecx
xorl %eax, %eax
movq (%r15,%rcx,8), %rdx
movl %edx, %esi
shrq $0x20, %rdx
imulq %rdx, %rsi
addq %rsi, %rax
incq %rcx
cmpq %rcx, %rbp
jne 0xebc9c
jmp 0xebcb9
xorl %eax, %eax
leaq -0x1(%rbp), %r14
movq %rbp, %rcx
testq %rbp, %rbp
jle 0xebd0a
cvtsi2sd %rax, %xmm0
mulsd 0x139826(%rip), %xmm0   # 0x2254f8
movq %r14, %rcx
movq (%r15,%rcx,8), %rdx
movl %edx, %esi
shrq $0x20, %rdx
imulq %rdx, %rsi
subq %rsi, %rax
xorps %xmm1, %xmm1
cvtsi2sd %rax, %xmm1
ucomisd %xmm1, %xmm0
jae 0xebd07
leaq -0x1(%rcx), %rdx
testq %rcx, %rcx
movq %rdx, %rcx
jg 0xebcd5
movq $-0x1, %rcx
incq %rcx
movq %r9, 0x8(%rsp)
movq $0x0, (%r13)
cmpq $0x2, %rbp
jl 0xebdcc
xorps %xmm0, %xmm0
cvtsi2sd %rcx, %xmm0
mulsd 0x138e9f(%rip), %xmm0   # 0x224bd0
cvttsd2si %xmm0, %rbx
cmpq $0x3, %rbx
movl $0x2, %eax
cmovlq %rax, %rbx
shrq %rbx
movl $0x1, %r12d
xorl %esi, %esi
movq %r12, %rax
subq %rbx, %rax
leaq (%r12,%rbx), %rcx
testq %rax, %rax
cmovleq %rsi, %rax
cmpq %rbp, %rcx
cmovgeq %r14, %rcx
cmpq %rcx, %rax
jge 0xebd7f
cmpq %rax, %r12
je 0xebd7a
movl (%r15,%r12,8), %edx
cmpl (%r15,%rax,8), %edx
jbe 0xebdc4
incq %rax
jmp 0xebd66
movq 0x8(%r13), %rax
cmpq %rax, (%r13)
jne 0xebdb0
leaq (%rax,%rax), %rsi
testq %rax, %rax
movl $0x2, %eax
cmoveq %rax, %rsi
movq %rsi, 0x8(%r13)
movq 0x10(%r13), %rdi
shlq $0x2, %rsi
callq 0x2370
xorl %esi, %esi
movq %rax, 0x10(%r13)
movq (%r13), %rax
movq 0x10(%r13), %rcx
leaq 0x1(%rax), %rdx
movq %rdx, (%r13)
movl %r12d, (%rcx,%rax,4)
incq %r12
cmpq %rbp, %r12
jne 0xebd4e
movq (%r13), %rsi
testq %rsi, %rsi
jle 0xebe09
movq 0x10(%r13), %rax
xorl %edx, %edx
xorl %edi, %edi
movq 0x8(%rsp), %rbx
movq (%rsp), %r14
movl %edi, %ecx
movl (%rax,%rcx,4), %ecx
movl (%r15,%rcx,8), %r8d
movl (%rax,%rdx,4), %r9d
movl %edx, %ecx
cmpl (%r15,%r9,8), %r8d
jb 0xebdfd
movl %edi, %ecx
incq %rdx
movl %ecx, %edi
cmpq %rdx, %rsi
jne 0xebde6
jmp 0xebe14
xorl %ecx, %ecx
movq 0x8(%rsp), %rbx
movq (%rsp), %r14
movq 0x50(%rsp), %rax
movl %ecx, %edi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
testq %rsi, %rsi
jle 0xebe61
xorl %r8d, %r8d
cmpq %r8, %rdi
je 0xebe59
cmpl $-0x1, %edx
je 0xebe56
movq 0x10(%r13), %r9
movl %edx, %r10d
movl (%r9,%r10,4), %r10d
movl (%r15,%r10,8), %r10d
movl (%r9,%r8,4), %r11d
movl %r8d, %r9d
cmpl (%r15,%r11,8), %r10d
jb 0xebe51
movl %edx, %r9d
movl %r9d, %edx
jmp 0xebe59
movl %r8d, %edx
incq %r8
cmpq %r8, %rsi
jne 0xebe28
movq $-0x1, %rsi
movq %rsi, (%rax)
movq %rsi, (%rbx)
movq 0x10(%r13), %r8
movl (%r8,%rdi,4), %esi
movq (%r15,%rsi,8), %r9
shrq $0x20, %r9
movq %r9, (%rbx)
cmpl %edx, %ecx
je 0xebf6f
cmpl $-0x1, %edx
je 0xebf6f
movl %edx, %esi
movl (%r8,%rsi,4), %esi
movq (%r15,%rsi,8), %rsi
shrq $0x20, %rsi
movq %rsi, (%rax)
movq $-0x1, %rdi
cmpq %r14, %r9
jg 0xebeb8
cmpq %r14, %rsi
jle 0xebf6c
movq (%rbx), %r9
cmpq %r14, %r9
movq %r14, %r10
cmovgq %r9, %r10
movq %r14, %r11
cmovlq %r9, %r11
xorps %xmm0, %xmm0
cvtsi2sd %r11, %xmm0
xorps %xmm1, %xmm1
cvtsi2sd %r10, %xmm1
mulsd 0x1395cc(%rip), %xmm1   # 0x2254b0
ucomisd %xmm1, %xmm0
jb 0xebf16
cmpq %r14, %rsi
movq %r14, %r10
cmovgq %rsi, %r10
cmovlq %rsi, %r14
xorps %xmm0, %xmm0
cvtsi2sd %r14, %xmm0
xorps %xmm1, %xmm1
cvtsi2sd %r10, %xmm1
mulsd 0x139578(%rip), %xmm1   # 0x225488
ucomisd %xmm0, %xmm1
ja 0xebf6c
cmpl %edx, %ecx
cmovbl %ecx, %edx
movl (%r8,%rdx,4), %ecx
movq (%r15,%rcx,8), %rcx
shrq $0x20, %rcx
movq 0x10(%rsp), %r8
cmpq %r8, %rcx
movq %r8, %rdx
cmovgq %rcx, %rdx
cmovgeq %r8, %rcx
xorps %xmm0, %xmm0
cvtsi2sd %rcx, %xmm0
xorps %xmm1, %xmm1
cvtsi2sd %rdx, %xmm1
mulsd 0x13954e(%rip), %xmm1   # 0x2254a0
ucomisd %xmm0, %xmm1
ja 0xebf6c
cmpq %rsi, %r9
movq %rsi, %rcx
cmovlq %r9, %rcx
cmovgq %r9, %rsi
movq %rcx, (%rbx)
movq %rsi, %rdi
movq %rdi, (%rax)
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq