// File: /workspace/github_c_makefile_star2_O0/c-zhou[P]yahs/yahs.c
// Function: run_scaffolding
int run_scaffolding(char *fai, char *agp, char *link_file, cov_norm_t *cov_norm, uint32_t ml, uint8_t mq, re_cuts_t *re_cuts, int8_t *telo_ends, char *out, int resolution, double *noise, uint32_t d_min_cell, double d_mass_frac, long rss_limit, int no_mem_check)
{
    //TODO: adjust wt thres by resolution
    sdict_t *sdict = make_sdict_from_index(fai, ml);
    asm_dict_t *dict = agp? make_asm_dict_from_agp(sdict, agp, 1) : make_asm_dict_from_sdict(sdict);
    
    int i, re = 0;
    uint64_t len = 0;
    for (i = 0; i < dict->n; ++i)
        len += dict->s[i].len;
#ifdef DEBUG_GRAPH_PRUNE
    fprintf(stderr, "[DEBUG_GRAPH_PRUNE::%s] #sequences loaded %d = %lubp\n", __func__, dict->n, len);
#endif

    long rss_intra, rss_inter;

    rss_intra = no_mem_check? 0 : estimate_intra_link_mat_init_rss(dict, resolution, 1);
    if ((rss_limit >= 0 && rss_intra > rss_limit) || rss_intra < 0) {
        // no enough memory
        fprintf(stderr, "[I::%s] No enough memory. Try lower resolutions... End of scaffolding round.\n", __func__);
        fprintf(stderr, "[I::%s] RAM    limit: %.3fGB\n", __func__, (double) rss_limit / GB);
        fprintf(stderr, "[I::%s] RAM required: %.3fGB\n", __func__, (double) rss_intra / GB);
        re = ENOMEM_ERR;
        goto scaff_failed_0;
    }
    rss_limit -= rss_intra;
    fprintf(stderr, "[I::%s] starting norm estimation...\n", __func__);
    intra_link_mat_t *intra_link_mat = intra_link_mat_from_file(link_file, cov_norm, dict, re_cuts, resolution, 1, mq);

#ifdef DEBUG_RAM_USAGE
    fprintf(stderr, "[DEBUG_RAM_USAGE::%s] RAM  peak: %.3fGB\n", __func__, (double) peakrss() / GB);
    fprintf(stderr, "[DEBUG_RAM_USAGE::%s] RAM intra: %.3fGB\n", __func__, (double) rss_intra / GB);
    fprintf(stderr, "[DEBUG_RAM_USAGE::%s] RAM  free: %.3fGB\n", __func__, (double) rss_limit / GB);
#endif

    norm_t *norm = calc_norms(intra_link_mat, d_min_cell, d_mass_frac);
    if (norm == 0) {
        fprintf(stderr, "[W::%s] No enough bands for norm calculation... End of scaffolding round.\n", __func__);
        re = ENOBND_ERR;
        goto scaff_failed_1;
    }

    rss_inter = no_mem_check? 0 : estimate_inter_link_mat_init_rss(dict, resolution, norm->r);
    if ((rss_limit >= 0 && rss_inter > rss_limit) || rss_inter < 0) {
        // no enough memory
        fprintf(stderr, "[I::%s] No enough memory. Try lower resolutions... End of scaffolding round.\n", __func__);
        fprintf(stderr, "[I::%s] RAM    limit: %.3fGB\n", __func__, (double) rss_limit / GB);
        fprintf(stderr, "[I::%s] RAM required: %.3fGB\n", __func__, (double) rss_inter / GB);
        re = ENOMEM_ERR;
        goto scaff_failed_1;
    }
    rss_limit -= rss_inter;
    fprintf(stderr, "[I::%s] starting link estimation...\n", __func__);
    inter_link_mat_t *inter_link_mat = inter_link_mat_from_file(link_file, cov_norm, dict, re_cuts, resolution, norm->r, mq);

#ifdef DEBUG_RAM_USAGE
    fprintf(stderr, "[DEBUG_RAM_USAGE::%s] RAM  peak: %.3fGB\n", __func__, (double) peakrss() / GB);
    fprintf(stderr, "[DEBUG_RAM_USAGE::%s] RAM inter: %.3fGB\n", __func__, (double) rss_inter / GB);
    fprintf(stderr, "[DEBUG_RAM_USAGE::%s] RAM  free: %.3fGB\n", __func__, (double) rss_limit / GB);
#endif

    *noise = inter_link_mat->noise / resolution / resolution;

    double la;
    re = inter_link_norms(inter_link_mat, norm, 1, max_noise_ratio, &la);
    if (re) {
        goto scaff_failed_2;
    }

    int8_t *directs = 0;
    // directs = calc_link_directs_from_file(link_file, dict);
    calc_link_directs(inter_link_mat, .1, dict, directs);
    if(directs) free(directs);

#ifdef DEBUG_LINK
    fprintf(stderr, "[DEBUG_LINK::%s] print_inter_link_norms\n", __func__);
    print_inter_link_norms(stderr, inter_link_mat, dict);
#endif

    int8_t *telos;
    telos = find_aseq_telos(dict, telo_ends);
    fprintf(stderr, "[I::%s] starting scaffolding graph contruction...\n", __func__);
    graph_t *g = build_graph_from_links(inter_link_mat, dict, .1, la, telos);
    
    free(telos);

#ifdef DEBUG_GRAPH_PRUNE
    fprintf(stderr, "[DEBUG_GRAPH_PRUNE::%s] scaffolding graph (before pruning) in GV format\n", __func__);
    graph_print_gv(g, stderr);
    fprintf(stderr, "[DEBUG_GRAPH_PRUNE::%s] scaffolding graph (before pruning) in GFA format\n", __func__);
    graph_print(g, stderr, 1);
#endif

    uint64_t n_arc;
    n_arc = g->n_arc;
#ifdef DEBUG_GRAPH_PRUNE
    fprintf(stderr, "[DEBUG_GRAPH_PRUNE::%s] number edges before trimming: %ld\n", __func__, n_arc);
    int round = 0;
#endif
    while (1) {
        trim_graph_simple_filter(g, .1, .7, .1, 0);
#ifdef DEBUG_GRAPH_PRUNE
        fprintf(stderr, "[DEBUG_GRAPH_PRUNE::%s] number edges after simple trimming round %d: %ld\n", __func__, round, g->n_arc);
        graph_print_gv(g, stderr);
#endif
        trim_graph_tips(g);
        trim_graph_blunts(g);
        trim_graph_repeats(g);
        trim_graph_transitive_edges(g);
        trim_graph_pop_bubbles(g);
        trim_graph_pop_undirected(g);
        trim_graph_weak_edges(g);
        trim_graph_self_loops(g);
#ifdef DEBUG_GRAPH_PRUNE
        fprintf(stderr, "[DEBUG_GRAPH_PRUNE::%s] number edges after trimming round %d: %ld\n", __func__, ++round, g->n_arc);
        graph_print_gv(g, stderr);
#endif
        if (g->n_arc == n_arc)
            break;
        else
            n_arc = g->n_arc;
    }
    trim_graph_ambiguous_edges(g);

#ifdef DEBUG_GRAPH_PRUNE
    fprintf(stderr, "[DEBUG_GRAPH_PRUNE::%s] scaffolding graph (after pruning) in GV format\n", __func__);
    graph_print_gv(g, stderr);
    fprintf(stderr, "[DEBUG_GRAPH_PRUNE::%s] scaffolding graph (after pruning) in GFA format\n", __func__);
    graph_print(g, stderr, 1);
#endif

    asm_dict_t *d = make_asm_dict_from_graph(g, g->sdict);
    // write scaffolds to AGP file
    FILE *agp_out = NULL;
    if (out) {
        char *agp_out_name = (char *) malloc(strlen(out) + 5);
        sprintf(agp_out_name, "%s.agp", out);
        agp_out = fopen(agp_out_name, "w");
        free(agp_out_name);
    } else {
        agp_out = fopen("scaffolds_FINAL.agp", "w");
    }
    if (agp_out == NULL) {
        fprintf(stderr, "[E::%s] fail to open file to write\n", __func__);
        re = 1;
    } else {
        write_asm_dict_to_agp(d, agp_out);
        fclose(agp_out);
    }

    asm_destroy(d);
    graph_destroy(g);

scaff_failed_2:
    inter_link_mat_destroy(inter_link_mat);

scaff_failed_1:
    norm_destroy(norm);
    intra_link_mat_destroy(intra_link_mat);

scaff_failed_0:
    asm_destroy(dict);
    sd_destroy(sdict);

    return re;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xe0, %rsp
movb %r9b, %al
movl 0x48(%rbp), %r9d
movq 0x40(%rbp), %r9
movl 0x38(%rbp), %r9d
movq 0x30(%rbp), %r9
movl 0x28(%rbp), %r9d
movq 0x20(%rbp), %r9
movq 0x18(%rbp), %r9
movq 0x10(%rbp), %r9
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movl %r8d, -0x24(%rbp)
movb %al, -0x25(%rbp)
movsd %xmm0, -0x30(%rbp)
movq -0x8(%rbp), %rdi
movl -0x24(%rbp), %esi
callq 0x17660
movq %rax, -0x38(%rbp)
cmpq $0x0, -0x10(%rbp)
je 0x2bf5c
movq -0x38(%rbp), %rdi
movq -0x10(%rbp), %rsi
movl $0x1, %edx
callq 0x18560
movq %rax, -0xc0(%rbp)
jmp 0x2bf6c
movq -0x38(%rbp), %rdi
callq 0x17d00
movq %rax, -0xc0(%rbp)
movq -0xc0(%rbp), %rax
movq %rax, -0x40(%rbp)
movl $0x0, -0x48(%rbp)
movq $0x0, -0x50(%rbp)
movl $0x0, -0x44(%rbp)
movl -0x44(%rbp), %eax
movq -0x40(%rbp), %rcx
cmpl (%rcx), %eax
jae 0x2bfc2
movq -0x40(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x44(%rbp), %rcx
imulq $0x58, %rcx, %rcx
addq %rcx, %rax
movq 0x8(%rax), %rax
addq -0x50(%rbp), %rax
movq %rax, -0x50(%rbp)
movl -0x44(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x44(%rbp)
jmp 0x2bf8d
cmpl $0x0, 0x48(%rbp)
je 0x2bfd3
xorl %eax, %eax
movq %rax, -0xc8(%rbp)
jmp 0x2bfeb
movq -0x40(%rbp), %rdi
movl 0x28(%rbp), %esi
movl $0x1, %edx
callq 0xe220
movq %rax, -0xc8(%rbp)
movq -0xc8(%rbp), %rax
movq %rax, -0x58(%rbp)
cmpq $0x0, 0x40(%rbp)
jl 0x2c007
movq -0x58(%rbp), %rax
cmpq 0x40(%rbp), %rax
jg 0x2c012
cmpq $0x0, -0x58(%rbp)
jge 0x2c09f
movq 0xcfdf(%rip), %rax      # 0x38ff8
movq (%rax), %rdi
leaq 0x6e65(%rip), %rsi      # 0x32e88
leaq 0x6eac(%rip), %rdx      # 0x32ed6
movb $0x0, %al
callq 0x22c0
movq 0xcfc0(%rip), %rax      # 0x38ff8
movq (%rax), %rdi
cvtsi2sdq 0x40(%rbp), %xmm0
movsd 0x6d77(%rip), %xmm1     # 0x32dc0
divsd %xmm1, %xmm0
leaq 0x6e92(%rip), %rsi      # 0x32ee6
leaq 0x6e7b(%rip), %rdx      # 0x32ed6
movb $0x1, %al
callq 0x22c0
movq 0xcf8f(%rip), %rax      # 0x38ff8
movq (%rax), %rdi
cvtsi2sdq -0x58(%rbp), %xmm0
movsd 0x6d46(%rip), %xmm1     # 0x32dc0
divsd %xmm1, %xmm0
leaq 0x6e7f(%rip), %rsi      # 0x32f04
leaq 0x6e4a(%rip), %rdx      # 0x32ed6
movb $0x1, %al
callq 0x22c0
movl $0xf, -0x48(%rbp)
jmp 0x2c561
movq -0x58(%rbp), %rcx
movq 0x40(%rbp), %rax
subq %rcx, %rax
movq %rax, 0x40(%rbp)
movq 0xcf43(%rip), %rax      # 0x38ff8
movq (%rax), %rdi
leaq 0x6e63(%rip), %rsi      # 0x32f22
leaq 0x6e10(%rip), %rdx      # 0x32ed6
movb $0x0, %al
callq 0x22c0
movq -0x18(%rbp), %rdi
movq -0x20(%rbp), %rsi
movq -0x40(%rbp), %rdx
movq 0x10(%rbp), %rcx
movl 0x28(%rbp), %r8d
movl $0x1, %r9d
movzbl -0x25(%rbp), %eax
movl %eax, (%rsp)
callq 0xe350
movq %rax, -0x68(%rbp)
movq -0x68(%rbp), %rdi
movl 0x38(%rbp), %esi
movsd -0x30(%rbp), %xmm0
callq 0x10120
movq %rax, -0x70(%rbp)
cmpq $0x0, -0x70(%rbp)
jne 0x2c13e
movq 0xcede(%rip), %rax      # 0x38ff8
movq (%rax), %rdi
leaq 0x6e23(%rip), %rsi      # 0x32f47
leaq 0x6dab(%rip), %rdx      # 0x32ed6
movb $0x0, %al
callq 0x22c0
movl $0xe, -0x48(%rbp)
jmp 0x2c54f
cmpl $0x0, 0x48(%rbp)
je 0x2c14f
xorl %eax, %eax
movq %rax, -0xd0(%rbp)
jmp 0x2c169
movq -0x40(%rbp), %rdi
movl 0x28(%rbp), %esi
movq -0x70(%rbp), %rax
movl 0x20(%rax), %edx
callq 0xde40
movq %rax, -0xd0(%rbp)
movq -0xd0(%rbp), %rax
movq %rax, -0x60(%rbp)
cmpq $0x0, 0x40(%rbp)
jl 0x2c185
movq -0x60(%rbp), %rax
cmpq 0x40(%rbp), %rax
jg 0x2c190
cmpq $0x0, -0x60(%rbp)
jge 0x2c21d
movq 0xce61(%rip), %rax      # 0x38ff8
movq (%rax), %rdi
leaq 0x6ce7(%rip), %rsi      # 0x32e88
leaq 0x6d2e(%rip), %rdx      # 0x32ed6
movb $0x0, %al
callq 0x22c0
movq 0xce42(%rip), %rax      # 0x38ff8
movq (%rax), %rdi
cvtsi2sdq 0x40(%rbp), %xmm0
movsd 0x6bf9(%rip), %xmm1     # 0x32dc0
divsd %xmm1, %xmm0
leaq 0x6d14(%rip), %rsi      # 0x32ee6
leaq 0x6cfd(%rip), %rdx      # 0x32ed6
movb $0x1, %al
callq 0x22c0
movq 0xce11(%rip), %rax      # 0x38ff8
movq (%rax), %rdi
cvtsi2sdq -0x60(%rbp), %xmm0
movsd 0x6bc8(%rip), %xmm1     # 0x32dc0
divsd %xmm1, %xmm0
leaq 0x6d01(%rip), %rsi      # 0x32f04
leaq 0x6ccc(%rip), %rdx      # 0x32ed6
movb $0x1, %al
callq 0x22c0
movl $0xf, -0x48(%rbp)
jmp 0x2c54f
movq -0x60(%rbp), %rcx
movq 0x40(%rbp), %rax
subq %rcx, %rax
movq %rax, 0x40(%rbp)
movq 0xcdc5(%rip), %rax      # 0x38ff8
movq (%rax), %rdi
leaq 0x6d55(%rip), %rsi      # 0x32f92
leaq 0x6c92(%rip), %rdx      # 0x32ed6
movb $0x0, %al
callq 0x22c0
movq -0x18(%rbp), %rdi
movq -0x20(%rbp), %rsi
movq -0x40(%rbp), %rdx
movq 0x10(%rbp), %rcx
movl 0x28(%rbp), %r8d
movq -0x70(%rbp), %rax
movl 0x20(%rax), %r9d
movzbl -0x25(%rbp), %eax
movl %eax, (%rsp)
callq 0xeba0
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
movsd 0x8(%rax), %xmm0
cvtsi2sdl 0x28(%rbp), %xmm1
divsd %xmm1, %xmm0
cvtsi2sdl 0x28(%rbp), %xmm1
divsd %xmm1, %xmm0
movq 0x30(%rbp), %rax
movsd %xmm0, (%rax)
movq -0x78(%rbp), %rdi
movq -0x70(%rbp), %rsi
movsd 0xd956(%rip), %xmm0     # 0x39c00
movl $0x1, %edx
leaq -0x80(%rbp), %rcx
callq 0x10da0
movl %eax, -0x48(%rbp)
cmpl $0x0, -0x48(%rbp)
je 0x2c2c6
jmp 0x2c546
movq $0x0, -0x88(%rbp)
movq -0x78(%rbp), %rdi
movq -0x40(%rbp), %rsi
movq -0x88(%rbp), %rdx
movsd 0x5320(%rip), %xmm0     # 0x31608
callq 0x118e0
cmpq $0x0, -0x88(%rbp)
je 0x2c303
movq -0x88(%rbp), %rdi
callq 0x2050
movq -0x40(%rbp), %rdi
movq 0x18(%rbp), %rsi
callq 0x2bcd0
movq %rax, -0x90(%rbp)
movq 0xccda(%rip), %rax      # 0x38ff8
movq (%rax), %rdi
leaq 0x6c8f(%rip), %rsi      # 0x32fb7
leaq 0x6ba7(%rip), %rdx      # 0x32ed6
movb $0x0, %al
callq 0x22c0
movq -0x78(%rbp), %rdi
movq -0x40(%rbp), %rsi
movsd -0x80(%rbp), %xmm1
movq -0x90(%rbp), %rdx
movsd 0x52b6(%rip), %xmm0     # 0x31608
callq 0x2bab0
movq %rax, -0x98(%rbp)
movq -0x90(%rbp), %rdi
callq 0x2050
movq -0x98(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0xa0(%rbp)
movq -0x98(%rbp), %rdi
movsd 0x527d(%rip), %xmm2     # 0x31608
movsd 0x643d(%rip), %xmm1     # 0x327d0
xorl %esi, %esi
movaps %xmm2, %xmm0
callq 0x94f0
movq -0x98(%rbp), %rdi
callq 0x9870
movq -0x98(%rbp), %rdi
callq 0x9a60
movq -0x98(%rbp), %rdi
callq 0x9bc0
movq -0x98(%rbp), %rdi
callq 0x9e40
movq -0x98(%rbp), %rdi
callq 0x9f90
movq -0x98(%rbp), %rdi
callq 0xa130
movq -0x98(%rbp), %rdi
callq 0xa310
movq -0x98(%rbp), %rdi
callq 0x9d80
movq -0x98(%rbp), %rax
movq 0x18(%rax), %rax
cmpq -0xa0(%rbp), %rax
jne 0x2c413
jmp 0x2c42a
movq -0x98(%rbp), %rax
movq 0x18(%rax), %rax
movq %rax, -0xa0(%rbp)
jmp 0x2c37c
movq -0x98(%rbp), %rdi
callq 0xa480
movq -0x98(%rbp), %rdi
movq -0x98(%rbp), %rax
movq 0x8(%rax), %rsi
callq 0xa530
movq %rax, -0xa8(%rbp)
movq $0x0, -0xb0(%rbp)
cmpq $0x0, 0x20(%rbp)
je 0x2c4c3
movq 0x20(%rbp), %rdi
callq 0x2160
movq %rax, %rdi
addq $0x5, %rdi
callq 0x2340
movq %rax, -0xb8(%rbp)
movq -0xb8(%rbp), %rdi
movq 0x20(%rbp), %rdx
leaq 0x6b56(%rip), %rsi      # 0x32fea
movb $0x0, %al
callq 0x24b0
movq -0xb8(%rbp), %rdi
leaq 0x4b67(%rip), %rsi      # 0x31010
callq 0x23f0
movq %rax, -0xb0(%rbp)
movq -0xb8(%rbp), %rdi
callq 0x2050
jmp 0x2c4dd
leaq 0x6b27(%rip), %rdi      # 0x32ff1
leaq 0x4b3f(%rip), %rsi      # 0x31010
callq 0x23f0
movq %rax, -0xb0(%rbp)
cmpq $0x0, -0xb0(%rbp)
jne 0x2c50f
movq 0xcb0a(%rip), %rax      # 0x38ff8
movq (%rax), %rdi
leaq 0x6b0d(%rip), %rsi      # 0x33005
leaq 0x69d7(%rip), %rdx      # 0x32ed6
movb $0x0, %al
callq 0x22c0
movl $0x1, -0x48(%rbp)
jmp 0x2c52e
movq -0xa8(%rbp), %rdi
movq -0xb0(%rbp), %rsi
callq 0x1ae30
movq -0xb0(%rbp), %rdi
callq 0x2150
movq -0xa8(%rbp), %rdi
callq 0x16780
movq -0x98(%rbp), %rdi
callq 0x80b0
movq -0x78(%rbp), %rdi
callq 0xd970
movq -0x70(%rbp), %rdi
callq 0x10070
movq -0x68(%rbp), %rdi
callq 0xd8e0
movq -0x40(%rbp), %rdi
callq 0x16780
movq -0x38(%rbp), %rdi
callq 0x16650
movl -0x48(%rbp), %eax
addq $0xe0, %rsp
popq %rbp
retq
nop