// File: /workspace/github_cpp_makefile_star2_O2/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, (%rsp)
testq %rsi, %rsi
je 0xae6be
movq %rdx, %r13
movq %rsi, %rbp
movq %rdi, %r15
xorl %eax, %eax
testq %rsi, %rsi
movl $0x0, %r8d
cmovgq %rsi, %r8
xorl %edx, %edx
cmpq %rdx, %r8
je 0xae453
movq (%r15,%rdx,8), %rsi
movl %esi, %edi
shrq $0x20, %rsi
imulq %rsi, %rdi
addq %rdi, %rax
incq %rdx
jmp 0xae438
movq %rcx, 0x8(%rsp)
leaq -0x1(%rbp), %r14
cvtsi2sd %rax, %xmm0
mulsd 0x1350d7(%rip), %xmm0   # 0x1e3540
cmpq $-0x1, %r14
pushq $-0x1
popq %rcx
cmovlq %r14, %rcx
movq %r14, %rdx
movq %r9, 0x10(%rsp)
testq %rdx, %rdx
js 0xae4a5
movq (%r15,%rdx,8), %rsi
movl %esi, %edi
shrq $0x20, %rsi
imulq %rsi, %rdi
subq %rdi, %rax
cvtsi2sd %rax, %xmm1
ucomisd %xmm1, %xmm0
jae 0xae4a2
decq %rdx
jmp 0xae47c
movq %rdx, %rcx
incq %rcx
cvtsi2sd %rcx, %xmm0
mulsd 0x13473b(%rip), %xmm0   # 0x1e2bf0
cvttsd2si %xmm0, %rbx
cmpq $0x3, %rbx
pushq $0x2
popq %rax
cmovlq %rax, %rbx
andq $0x0, (%r13)
shrq %rbx
pushq $0x1
popq %r12
xorl %edi, %edi
xorl %ecx, %ecx
cmpq %rbp, %r12
jge 0xae551
movq %r12, %rax
subq %rbx, %rax
testq %rax, %rax
cmovleq %rdi, %rax
leaq (%r12,%rbx), %rdx
cmpq %rbp, %rdx
cmovgeq %r14, %rdx
cmpq %rdx, %rax
jge 0xae50b
cmpq %rax, %r12
je 0xae506
movl (%r15,%r12,8), %esi
cmpl (%r15,%rax,8), %esi
jbe 0xae54c
incq %rax
jmp 0xae4f2
movq 0x10(%r13), %rax
cmpq 0x8(%r13), %rcx
jne 0xae53d
leaq (%rcx,%rcx), %rsi
testq %rcx, %rcx
pushq $0x2
popq %rcx
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 %r12d, (%rax,%rcx,4)
movq %rdx, %rcx
incq %r12
jmp 0xae4d5
xorl %eax, %eax
testq %rcx, %rcx
cmovleq %rax, %rcx
xorl %edx, %edx
movq 0x10(%rsp), %r11
movq 0x50(%rsp), %rbx
movq 0x8(%rsp), %r14
movl %eax, %esi
cmpq %rdx, %rcx
je 0xae591
movq 0x10(%r13), %rdi
movl (%rdi,%rsi,4), %esi
movl (%r15,%rsi,8), %r8d
movl (%rdi,%rdx,4), %edi
movl %edx, %esi
cmpl (%r15,%rdi,8), %r8d
jb 0xae58a
movl %eax, %esi
incq %rdx
movl %esi, %eax
jmp 0xae56b
pushq $-0x1
popq %rdx
xorl %edi, %edi
movl %edx, %r8d
cmpq %rdi, %rcx
je 0xae5d0
cmpq %rdi, %rsi
je 0xae5cb
cmpl $-0x1, %edx
je 0xae5c9
movq 0x10(%r13), %r9
movl (%r9,%r8,4), %r8d
movl (%r15,%r8,8), %r10d
movl (%r9,%rdi,4), %r9d
movl %edi, %r8d
cmpl (%r15,%r9,8), %r10d
jb 0xae5c4
movl %edx, %r8d
movl %r8d, %edx
jmp 0xae5cb
movl %edi, %edx
incq %rdi
jmp 0xae596
orq $-0x1, (%rbx)
movq 0x10(%r13), %rdi
movl (%rdi,%rsi,4), %ecx
movq (%r15,%rcx,8), %r9
shrq $0x20, %r9
movq %r9, (%r11)
cmpl %edx, %esi
je 0xae6be
cmpl $-0x1, %edx
je 0xae6be
movl (%rdi,%r8,4), %ecx
movq (%r15,%rcx,8), %rcx
shrq $0x20, %rcx
movq %rcx, (%rbx)
cmpq %r14, %r9
jg 0xae618
cmpq %r14, %rcx
ja 0xae618
pushq $-0x1
popq %rax
jmp 0xae6bb
movq (%r11), %rsi
cmpq %r14, %rsi
movq %r14, %r8
cmovgq %rsi, %r8
movq %r14, %r9
cmovlq %rsi, %r9
cvtsi2sd %r9, %xmm0
cvtsi2sd %r8, %xmm1
mulsd 0x134ec2(%rip), %xmm1   # 0x1e3500
ucomisd %xmm1, %xmm0
jb 0xae66a
cmpq %r14, %rcx
movq %r14, %r8
cmovgq %rcx, %r8
cmovlq %rcx, %r14
cvtsi2sd %r14, %xmm0
cvtsi2sd %r8, %xmm1
mulsd 0x134e74(%rip), %xmm1   # 0x1e34d8
ucomisd %xmm0, %xmm1
ja 0xae610
cmpl %edx, %eax
cmovbl %eax, %edx
movl (%rdi,%rdx,4), %eax
movq (%r15,%rax,8), %rax
shrq $0x20, %rax
movq (%rsp), %rdi
cmpq %rdi, %rax
movq %rdi, %rdx
cmovgq %rax, %rdx
cmovgeq %rdi, %rax
cvtsi2sd %rax, %xmm0
cvtsi2sd %rdx, %xmm1
mulsd 0x134e52(%rip), %xmm1   # 0x1e34f0
ucomisd %xmm0, %xmm1
pushq $-0x1
popq %rax
ja 0xae6bb
cmpq %rcx, %rsi
movq %rcx, %rax
cmovlq %rsi, %rax
cmovgq %rsi, %rcx
movq %rax, (%r11)
movq %rcx, %rax
movq %rax, (%rbx)
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq