// File: fjamour[P]icentral/src/experiments.cc
// Function: insertion_test_fuad_hash(graph_t&, int)
void insertion_test_fuad_hash(graph_t& graph, int num_edges_to_insert)
{
    printf("==========================================================\n");
    printf("Graph: \t\t\t%s\n", graph.graph_name.c_str());
    printf("Graph # nodes: \t\t%d\n", graph.size());
    printf("Graph # edges: \t\t%d\n", graph.edge_set.size());
    graph_hash_t g;
    g.fill_graph(graph);
    
    double brandes_time;
    timer tm;
    
    int num_iter = g.size();
    printf("Brandes runtime: \t");
    tm.start();
    tr1_map_t(double) bc_vec = brandes_bc_hash(g);
    tm.stop();
    brandes_time = tm.interval();
    printf("%f\n", brandes_time);
    printf("Brandes avg iter time: \t%f\n", brandes_time/num_iter);
    
    vector<edge_t> rand_edge_vec;
    printf("Generating edges...\n");
    for(int i = 0; i < num_edges_to_insert; ++i) {
        edge_t rand_edge;
        node_id_t src, dst;
        do {
            src = rand()%graph.size();
            dst = rand()%graph.size();
            rand_edge.first    = src;
            rand_edge.second   = dst;
        } while(graph.has_edge(rand_edge) ||
                find(rand_edge_vec.begin(), rand_edge_vec.end(), rand_edge) != rand_edge_vec.end());
        rand_edge_vec.push_back(rand_edge);
    }

    double tot_fuad_time = 0;
    double tot_speedup = 0;
    
    vector<bcc_stat_t> bcc_stat_vec;
    for(int i = 0; i < rand_edge_vec.size(); ++i) {
        bcc_stat_t bcc_stat;
        edge_t rand_edge = rand_edge_vec[i];
        printf("Inserting edge (%d, %d) and updating bc...\n", rand_edge.first, rand_edge.second);
        tm.start();
        graph.insert_edge_update_bc_experimental(rand_edge.first, rand_edge.second, bcc_stat);
        tm.stop();
        
        double avg_iter_time_naive;
        graph.approx_bcc_iter_tm(rand_edge.first, rand_edge.second, avg_iter_time_naive);
        tot_fuad_time += tm.interval();
        
        tot_speedup += (brandes_time/tm.interval());
        
        printf("\tBCC num nodes: \t\t%d\n", bcc_stat.bcc_num_nodes);
        printf("\tBCC num edges: \t\t%d\n", bcc_stat.bcc_num_edges);
        printf("\n");
        printf("\tTime to update BC: \t%f\n", tm.interval());
        printf("\tSpeedup: \t\t%f\n", brandes_time/tm.interval());
        printf("\n");
        printf("\tBCC num d0 BFS: \t%d\n", bcc_stat.num_d0_iter);
        printf("\tBCC d0 time: \t\t%f\n", bcc_stat.tot_d0_tm/bcc_stat.num_d0_iter);
        printf("\tBCC num d1 BFS: \t%d\n", bcc_stat.num_d1_iter);
        printf("\tBCC d1 time: \t\t%f\n", bcc_stat.tot_d1_tm/bcc_stat.num_d1_iter);
        printf("\tBCC num d2 BFS: \t%d\n", bcc_stat.num_d2_iter);
        printf("\tBCC d2 time: \t\t%f\n", bcc_stat.tot_d2_tm/bcc_stat.num_d2_iter);
        printf("\tavg iter time naive: \t%f\n", avg_iter_time_naive);
        //printf("\tBCC bcc find time: \t%f\n", bcc_stat.bcc_find_time);
        //printf("\tBCC sssp time: \t\t%f\n", bcc_stat.sssp_tm);
        
        
        
        bcc_stat_vec.push_back(bcc_stat);
    }
    
    //double avg_speedup = (num_edges_to_insert*brandes_time)/tot_fuad_time;
    double avg_speedup = tot_speedup/num_edges_to_insert;
    
    printf("[[Average speedup: %f]]\n", avg_speedup); 
}

// Assembly:
subq $0x4b8, %rsp            # imm = 0x4B8
movq %rdi, 0x4b0(%rsp)
movl %esi, 0x4ac(%rsp)
leaq 0x31703(%rip), %rdi     # 0x7b2e0
xorl %eax, %eax
movb %al, 0x8f(%rsp)
callq 0x9040
movq 0x4b0(%rsp), %rdi
addq $0x108, %rdi            # imm = 0x108
callq 0x9250
movq %rax, %rsi
movb 0x8f(%rsp), %al
leaq 0x3170c(%rip), %rdi     # 0x7b31c
callq 0x9040
movq 0x4b0(%rsp), %rdi
callq 0x56b40
movq %rax, %rsi
movb 0x8f(%rsp), %al
leaq 0x316f7(%rip), %rdi     # 0x7b32a
callq 0x9040
movq 0x4b0(%rsp), %rdi
addq $0x30, %rdi
callq 0x4dbe0
movq %rax, %rsi
movb 0x8f(%rsp), %al
leaq 0x316e5(%rip), %rdi     # 0x7b33f
callq 0x9040
leaq 0x200(%rsp), %rdi
movq %rdi, 0x90(%rsp)
callq 0x41780
movq 0x90(%rsp), %rdi
movq 0x4b0(%rsp), %rsi
callq 0x53670
jmp 0x49c8b
leaq 0x200(%rsp), %rdi
callq 0x52790
movq %rax, 0x80(%rsp)
jmp 0x49ca2
movq 0x80(%rsp), %rax
movl %eax, 0x1c4(%rsp)
leaq 0x3169c(%rip), %rdi     # 0x7b354
xorl %eax, %eax
callq 0x9040
jmp 0x49cc1
leaq 0x1c8(%rsp), %rdi
callq 0x2d430
jmp 0x49cd0
leaq 0x190(%rsp), %rdi
leaq 0x200(%rsp), %rsi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
callq 0x2c530
jmp 0x49cec
leaq 0x1c8(%rsp), %rdi
callq 0x2d450
jmp 0x49cfb
leaq 0x1c8(%rsp), %rdi
callq 0x2d470
movsd %xmm0, 0x78(%rsp)
jmp 0x49d10
movsd 0x78(%rsp), %xmm0
movsd %xmm0, 0x1e8(%rsp)
movsd 0x1e8(%rsp), %xmm0
leaq 0x31821(%rip), %rdi     # 0x7b550
movb $0x1, %al
callq 0x9040
jmp 0x49d38
movsd 0x1e8(%rsp), %xmm0
cvtsi2sdl 0x1c4(%rsp), %xmm1
divsd %xmm1, %xmm0
leaq 0x316e5(%rip), %rdi     # 0x7b43a
movb $0x1, %al
callq 0x9040
jmp 0x49d5e
leaq 0x178(%rsp), %rdi
callq 0x4db80
leaq 0x316e4(%rip), %rdi     # 0x7b456
xorl %eax, %eax
callq 0x9040
jmp 0x49d7b
movl $0x0, 0x174(%rsp)
movl 0x174(%rsp), %eax
cmpl 0x4ac(%rsp), %eax
jge 0x49f78
leaq 0x16c(%rsp), %rdi
callq 0x41760
jmp 0x49da9
jmp 0x49dab
callq 0x91a0
cltq
movq %rax, 0x68(%rsp)
movq 0x4b0(%rsp), %rdi
callq 0x56b40
movq %rax, 0x70(%rsp)
jmp 0x49dcb
movq 0x70(%rsp), %rcx
movq 0x68(%rsp), %rax
xorl %edx, %edx
divq %rcx
movl %edx, %eax
movl %eax, 0x168(%rsp)
callq 0x91a0
cltq
movq %rax, 0x58(%rsp)
movq 0x4b0(%rsp), %rdi
callq 0x56b40
movq %rax, 0x60(%rsp)
jmp 0x49e03
movq 0x60(%rsp), %rcx
movq 0x58(%rsp), %rax
xorl %edx, %edx
divq %rcx
movl %edx, %eax
movl %eax, 0x164(%rsp)
movl 0x168(%rsp), %eax
movl %eax, 0x16c(%rsp)
movl 0x164(%rsp), %eax
movl %eax, 0x170(%rsp)
movq 0x4b0(%rsp), %rdi
leaq 0x16c(%rsp), %rsi
callq 0x57340
movb %al, 0x57(%rsp)
jmp 0x49e52
movb 0x57(%rsp), %cl
movb $0x1, %al
testb $0x1, %cl
movb %al, 0x56(%rsp)
jne 0x49ef2
jmp 0x49e67
leaq 0x178(%rsp), %rdi
movq %rdi, 0x40(%rsp)
callq 0x47550
movq 0x40(%rsp), %rdi
movq %rax, 0x150(%rsp)
callq 0x473d0
movq %rax, 0x148(%rsp)
movq 0x150(%rsp), %rdi
movq 0x148(%rsp), %rsi
leaq 0x16c(%rsp), %rdx
callq 0x4db20
movq %rax, 0x48(%rsp)
jmp 0x49eb7
movq 0x48(%rsp), %rax
movq %rax, 0x158(%rsp)
leaq 0x178(%rsp), %rdi
callq 0x473d0
movq %rax, 0x140(%rsp)
leaq 0x158(%rsp), %rdi
leaq 0x140(%rsp), %rsi
callq 0x4dae0
movb %al, 0x56(%rsp)
movb 0x56(%rsp), %al
testb $0x1, %al
jne 0x49dab
leaq 0x178(%rsp), %rdi
leaq 0x16c(%rsp), %rsi
callq 0x42130
jmp 0x49f15
jmp 0x49f17
movl 0x174(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x174(%rsp)
jmp 0x49d86
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f8(%rsp)
movl %eax, 0x1f4(%rsp)
jmp 0x4a370
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f8(%rsp)
movl %eax, 0x1f4(%rsp)
jmp 0x4a363
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f8(%rsp)
movl %eax, 0x1f4(%rsp)
jmp 0x4a356
xorps %xmm0, %xmm0
movsd %xmm0, 0x138(%rsp)
xorps %xmm0, %xmm0
movsd %xmm0, 0x130(%rsp)
leaq 0x118(%rsp), %rdi
callq 0x4e090
movl $0x0, 0x114(%rsp)
movslq 0x114(%rsp), %rax
movq %rax, 0x38(%rsp)
leaq 0x178(%rsp), %rdi
callq 0x47680
movq %rax, %rcx
movq 0x38(%rsp), %rax
cmpq %rcx, %rax
jae 0x4a2e2
movslq 0x114(%rsp), %rsi
leaq 0x178(%rsp), %rdi
callq 0x4dbc0
movq (%rax), %rax
movq %rax, 0xa8(%rsp)
movl 0xa8(%rsp), %esi
movl 0xac(%rsp), %edx
leaq 0x3163a(%rip), %rdi     # 0x7b642
xorl %eax, %eax
callq 0x9040
jmp 0x4a011
leaq 0x1c8(%rsp), %rdi
callq 0x2d430
jmp 0x4a020
movq 0x4b0(%rsp), %rdi
movl 0xa8(%rsp), %esi
movl 0xac(%rsp), %edx
leaq 0xb0(%rsp), %rcx
movl $0xffffffff, %r9d       # imm = 0xFFFFFFFF
movl %r9d, %r8d
callq 0x575f0
jmp 0x4a04e
leaq 0x1c8(%rsp), %rdi
callq 0x2d450
jmp 0x4a05d
movq 0x4b0(%rsp), %rdi
movl 0xa8(%rsp), %esi
movl 0xac(%rsp), %edx
leaq 0xa0(%rsp), %rcx
movl $0xffffffff, %r8d       # imm = 0xFFFFFFFF
callq 0x57880
jmp 0x4a088
leaq 0x1c8(%rsp), %rdi
callq 0x2d470
movsd %xmm0, 0x30(%rsp)
jmp 0x4a09d
movsd 0x30(%rsp), %xmm1
movsd 0x138(%rsp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x138(%rsp)
movsd 0x1e8(%rsp), %xmm0
movsd %xmm0, 0x20(%rsp)
leaq 0x1c8(%rsp), %rdi
callq 0x2d470
movsd %xmm0, 0x28(%rsp)
jmp 0x4a0dd
movsd 0x28(%rsp), %xmm0
movsd 0x20(%rsp), %xmm1
divsd %xmm0, %xmm1
movsd 0x130(%rsp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x130(%rsp)
movl 0xb0(%rsp), %esi
leaq 0x3155d(%rip), %rdi     # 0x7b66e
xorl %eax, %eax
callq 0x9040
jmp 0x4a11a
movl 0xb4(%rsp), %esi
leaq 0x3155c(%rip), %rdi     # 0x7b684
xorl %eax, %eax
callq 0x9040
jmp 0x4a131
leaq 0x31cea(%rip), %rdi     # 0x7be22
xorl %eax, %eax
callq 0x9040
jmp 0x4a141
leaq 0x1c8(%rsp), %rdi
callq 0x2d470
movsd %xmm0, 0x18(%rsp)
jmp 0x4a156
movsd 0x18(%rsp), %xmm0
leaq 0x3126d(%rip), %rdi     # 0x7b3d0
movb $0x1, %al
callq 0x9040
jmp 0x4a16c
movsd 0x1e8(%rsp), %xmm0
movsd %xmm0, 0x8(%rsp)
leaq 0x1c8(%rsp), %rdi
callq 0x2d470
movsd %xmm0, 0x10(%rsp)
jmp 0x4a190
movsd 0x10(%rsp), %xmm1
movsd 0x8(%rsp), %xmm0
divsd %xmm1, %xmm0
leaq 0x31242(%rip), %rdi     # 0x7b3e9
movb $0x1, %al
callq 0x9040
jmp 0x4a1b0
leaq 0x31c6b(%rip), %rdi     # 0x7be22
xorl %eax, %eax
callq 0x9040
jmp 0x4a1c0
movl 0xc0(%rsp), %esi
leaq 0x314cc(%rip), %rdi     # 0x7b69a
xorl %eax, %eax
callq 0x9040
jmp 0x4a1d7
movsd 0xd0(%rsp), %xmm0
cvtsi2sdl 0xc0(%rsp), %xmm1
divsd %xmm1, %xmm0
leaq 0x314bc(%rip), %rdi     # 0x7b6b0
movb $0x1, %al
callq 0x9040
jmp 0x4a1fd
movl 0xc4(%rsp), %esi
leaq 0x314b9(%rip), %rdi     # 0x7b6c4
xorl %eax, %eax
callq 0x9040
jmp 0x4a214
movsd 0xd8(%rsp), %xmm0
cvtsi2sdl 0xc4(%rsp), %xmm1
divsd %xmm1, %xmm0
leaq 0x314a9(%rip), %rdi     # 0x7b6da
movb $0x1, %al
callq 0x9040
jmp 0x4a23a
movl 0xc8(%rsp), %esi
leaq 0x314a6(%rip), %rdi     # 0x7b6ee
xorl %eax, %eax
callq 0x9040
jmp 0x4a251
movsd 0xe0(%rsp), %xmm0
cvtsi2sdl 0xc8(%rsp), %xmm1
divsd %xmm1, %xmm0
leaq 0x31496(%rip), %rdi     # 0x7b704
movb $0x1, %al
callq 0x9040
jmp 0x4a277
movsd 0xa0(%rsp), %xmm0
leaq 0x31491(%rip), %rdi     # 0x7b718
movb $0x1, %al
callq 0x9040
jmp 0x4a290
leaq 0x118(%rsp), %rdi
leaq 0xb0(%rsp), %rsi
callq 0x4e0a0
jmp 0x4a2a7
jmp 0x4a2a9
movl 0x114(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x114(%rsp)
jmp 0x49fa8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x1f8(%rsp)
movl %eax, 0x1f4(%rsp)
leaq 0x118(%rsp), %rdi
callq 0x4e110
jmp 0x4a356
movsd 0x130(%rsp), %xmm0
cvtsi2sdl 0x4ac(%rsp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x98(%rsp)
movsd 0x98(%rsp), %xmm0
leaq 0x31110(%rip), %rdi     # 0x7b421
movb $0x1, %al
callq 0x9040
jmp 0x4a31a
leaq 0x118(%rsp), %rdi
callq 0x4e110
leaq 0x178(%rsp), %rdi
callq 0x4dc40
leaq 0x190(%rsp), %rdi
callq 0x2d420
leaq 0x200(%rsp), %rdi
callq 0x41f20
addq $0x4b8, %rsp            # imm = 0x4B8
retq
leaq 0x178(%rsp), %rdi
callq 0x4dc40
leaq 0x190(%rsp), %rdi
callq 0x2d420
leaq 0x200(%rsp), %rdi
callq 0x41f20
movq 0x1f8(%rsp), %rdi
callq 0x9cf0
nopw (%rax,%rax)