// File: fjamour[P]icentral/src/experiments.cc
// Function: incremental_brandes_test(graph_t&, int, std::vector<std::pair<unsigned int, unsigned int>, std::allocator<std::pair<unsigned int, unsigned int>>>)
void incremental_brandes_test(graph_t& graph, int num_edges_to_insert, vector<edge_t> rand_edge_vec)
{
    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());
    double brandes_time;
    timer tm;
    
    printf("Brandes avg time per iteration: \t");
    tm.start();
    vector<double> bc_vec = brandes_bc(graph);
    tm.stop();
    brandes_time = tm.interval();
    printf("%f\n", brandes_time/graph.size());
    printf("Brandes time: \t\t\t\t%f\n", brandes_time);
    
    if(rand_edge_vec.size() == 0) {
        printf("Generating edges...\n");
        gen_rand_edges(num_edges_to_insert, graph, rand_edge_vec);
    }

    vector<edge_stat_t> edge_stat_vec;
 
    vector<vector<int> >    cnt_vec2;
    vector<vector<double> > time_vec2;
    
    for(int i = 0; i < rand_edge_vec.size(); ++i) {
        //printf("Inserting edge [%d]...\n", i);
        edge_t rand_edge = rand_edge_vec[i];
        
        vector<int> cnt_vec;
        vector<double> time_vec;
        cnt_vec.resize(3);
        time_vec.resize(3);
        
        
        incremental_brandes_experimental(graph,
                rand_edge.first, 
                rand_edge.second, 
                bc_vec,
                time_vec,
                cnt_vec);
        cnt_vec2.push_back(cnt_vec);
        time_vec2.push_back(time_vec);
    }

    int tot_cnt_arr[] = {0, 0, 0};
    double tot_time_arr[] = {0, 0, 0};
    double tot_avg_arr[] = {0, 0, 0};
    
    for(int i = 0; i < cnt_vec2.size(); ++i) {
        tot_cnt_arr[0] += cnt_vec2[i][0];
        tot_cnt_arr[1] += cnt_vec2[i][1];
        tot_cnt_arr[2] += cnt_vec2[i][2];
        
        tot_time_arr[0] += time_vec2[i][0];
        tot_time_arr[1] += time_vec2[i][1];
        tot_time_arr[2] += time_vec2[i][2];
        
        tot_avg_arr[0] += (time_vec2[i][0]/cnt_vec2[i][0]);
        tot_avg_arr[1] += (time_vec2[i][1]/cnt_vec2[i][1]);
        tot_avg_arr[2] += (time_vec2[i][2]/cnt_vec2[i][2]);
    }
    double inc_tot_time = tot_time_arr[0] + tot_time_arr[1] + tot_time_arr[2];
    double inc_avg_time = inc_tot_time/rand_edge_vec.size();
    printf("Incremental Brandes time:\t\t%f\n", inc_avg_time);
    printf("\n");
    double avg_d1_tm = tot_time_arr[1]/tot_cnt_arr[1];
    double avg_d2_tm = tot_time_arr[2]/tot_cnt_arr[2];
    double avg_br_tm = brandes_time/graph.size();
    printf("\n");
    printf("Tot d0 BFS:\t\t%d\n", tot_cnt_arr[0]);
    printf("Tot d1 BFS:\t\t%d\n", tot_cnt_arr[1]);
    printf("Tot d2 BFS:\t\t%d\n", tot_cnt_arr[2]);
    printf("\n");
    printf("Avg d1 BFS time:\t\t%f (%f)\n", avg_d1_tm, avg_d1_tm/avg_br_tm);
    printf("Avg d2 BFS time:\t\t%f (%f)\n", avg_d2_tm, avg_d2_tm/avg_br_tm);
    printf("Avg Brandes time:\t\t%f\n", avg_br_tm);
    double avg_inc_iter = 
    (tot_time_arr[1] + tot_time_arr[2])/(tot_cnt_arr[1] + tot_cnt_arr[2]);
    
    double mem_dag_time = (avg_d1_tm-avg_br_tm)*tot_cnt_arr[1] + (avg_d2_tm-avg_br_tm)*tot_cnt_arr[2];
    double mem_dag_speedup = brandes_time/mem_dag_time;
    printf("Ideal mem DAG speedup:\t %f\n", mem_dag_speedup);
    printf("Avg inc BFS time:\t\t%f (%f)\n", avg_inc_iter, avg_inc_iter/avg_br_tm);
    printf("[[Avg speedup:\t\t\t%f]]\n", brandes_time/inc_avg_time);
    
}

// Assembly:
subq $0x1f8, %rsp            # imm = 0x1F8
movq %rdx, 0x60(%rsp)
movq %rdi, 0x1f0(%rsp)
movl %esi, 0x1ec(%rsp)
movq %rdx, 0x1e0(%rsp)
leaq 0x32116(%rip), %rdi     # 0x7b2e0
xorl %eax, %eax
movb %al, 0x6f(%rsp)
callq 0x9040
movq 0x1f0(%rsp), %rdi
addq $0x108, %rdi            # imm = 0x108
callq 0x9250
movq %rax, %rsi
movb 0x6f(%rsp), %al
leaq 0x32125(%rip), %rdi     # 0x7b31c
callq 0x9040
movq 0x1f0(%rsp), %rdi
callq 0x56b40
movq %rax, %rsi
movb 0x6f(%rsp), %al
leaq 0x32113(%rip), %rdi     # 0x7b32a
callq 0x9040
movq 0x1f0(%rsp), %rdi
addq $0x30, %rdi
callq 0x4dbe0
movq %rax, %rsi
movb 0x6f(%rsp), %al
leaq 0x32104(%rip), %rdi     # 0x7b33f
callq 0x9040
movb 0x6f(%rsp), %al
leaq 0x322d1(%rip), %rdi     # 0x7b51c
callq 0x9040
leaq 0x1b8(%rsp), %rdi
movq %rdi, 0x70(%rsp)
callq 0x2d430
movq 0x1f0(%rsp), %rsi
leaq 0x1a0(%rsp), %rdi
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
callq 0x28720
movq 0x70(%rsp), %rdi
callq 0x2d450
jmp 0x49288
leaq 0x1b8(%rsp), %rdi
callq 0x2d470
movsd %xmm0, 0x58(%rsp)
jmp 0x4929d
movsd 0x58(%rsp), %xmm0
movsd %xmm0, 0x1d8(%rsp)
movsd 0x1d8(%rsp), %xmm0
movsd %xmm0, 0x48(%rsp)
movq 0x1f0(%rsp), %rdi
callq 0x56b40
movq %rax, 0x50(%rsp)
jmp 0x492cf
movsd 0x48(%rsp), %xmm0
movq 0x50(%rsp), %rax
movq %rax, %xmm1
movaps 0x31fca(%rip), %xmm2    # 0x7b2b0
punpckldq %xmm2, %xmm1    # xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1]
movapd 0x31fce(%rip), %xmm2    # 0x7b2c0
subpd %xmm2, %xmm1
movaps %xmm1, %xmm2
unpckhpd %xmm1, %xmm1            # xmm1 = xmm1[1,1]
addsd %xmm2, %xmm1
divsd %xmm1, %xmm0
leaq 0x32244(%rip), %rdi     # 0x7b550
movb $0x1, %al
callq 0x9040
jmp 0x49315
movsd 0x1d8(%rsp), %xmm0
leaq 0x32219(%rip), %rdi     # 0x7b53e
movb $0x1, %al
callq 0x9040
jmp 0x4932e
movq 0x60(%rsp), %rdi
callq 0x47680
cmpq $0x0, %rax
jne 0x49384
leaq 0x32111(%rip), %rdi     # 0x7b456
xorl %eax, %eax
callq 0x9040
jmp 0x4934e
movq 0x60(%rsp), %rdx
movl 0x1ec(%rsp), %edi
movq 0x1f0(%rsp), %rsi
callq 0x47910
jmp 0x49369
jmp 0x49384
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x198(%rsp)
movl %eax, 0x194(%rsp)
jmp 0x49ba0
leaq 0x178(%rsp), %rdi
callq 0x4dca0
leaq 0x160(%rsp), %rdi
callq 0x2cf10
leaq 0x148(%rsp), %rdi
callq 0x101b0
movl $0x0, 0x144(%rsp)
movq 0x60(%rsp), %rdi
movslq 0x144(%rsp), %rax
movq %rax, 0x40(%rsp)
callq 0x47680
movq %rax, %rcx
movq 0x40(%rsp), %rax
cmpq %rcx, %rax
jae 0x49505
movq 0x60(%rsp), %rdi
movslq 0x144(%rsp), %rsi
callq 0x4dbc0
movq (%rax), %rax
movq %rax, 0x138(%rsp)
leaq 0x120(%rsp), %rdi
movq %rdi, 0x38(%rsp)
callq 0xfc40
leaq 0x108(%rsp), %rdi
callq 0xfa00
movq 0x38(%rsp), %rdi
movl $0x3, %esi
callq 0x2cfc0
jmp 0x4942b
leaq 0x108(%rsp), %rdi
movl $0x3, %esi
callq 0xf680
jmp 0x4943f
movq 0x1f0(%rsp), %rdi
movl 0x138(%rsp), %esi
movl 0x13c(%rsp), %edx
leaq 0x1a0(%rsp), %rcx
leaq 0x108(%rsp), %r8
leaq 0x120(%rsp), %r9
callq 0x2bfc0
jmp 0x49474
leaq 0x160(%rsp), %rdi
leaq 0x120(%rsp), %rsi
callq 0x4dfb0
jmp 0x4948b
leaq 0x148(%rsp), %rdi
leaq 0x108(%rsp), %rsi
callq 0x4e020
jmp 0x494a2
leaq 0x108(%rsp), %rdi
callq 0xfa50
leaq 0x120(%rsp), %rdi
callq 0xfc70
movl 0x144(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x144(%rsp)
jmp 0x493b6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x198(%rsp)
movl %eax, 0x194(%rsp)
leaq 0x108(%rsp), %rdi
callq 0xfa50
leaq 0x120(%rsp), %rdi
callq 0xfc70
jmp 0x49b79
leaq 0xfc(%rsp), %rdi
xorl %esi, %esi
movl $0xc, %edx
callq 0x9350
leaq 0xe0(%rsp), %rdi
xorl %esi, %esi
movl $0x18, %edx
callq 0x9350
leaq 0xc0(%rsp), %rdi
xorl %esi, %esi
movl $0x18, %edx
callq 0x9350
movl $0x0, 0xbc(%rsp)
movslq 0xbc(%rsp), %rax
movq %rax, 0x30(%rsp)
leaq 0x160(%rsp), %rdi
callq 0x2d120
movq %rax, %rcx
movq 0x30(%rsp), %rax
cmpq %rcx, %rax
jae 0x49811
movslq 0xbc(%rsp), %rsi
leaq 0x160(%rsp), %rdi
callq 0x2d100
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0xfc50
movl (%rax), %eax
addl 0xfc(%rsp), %eax
movl %eax, 0xfc(%rsp)
movslq 0xbc(%rsp), %rsi
leaq 0x160(%rsp), %rdi
callq 0x2d100
movq %rax, %rdi
movl $0x1, %esi
callq 0xfc50
movl (%rax), %eax
addl 0x100(%rsp), %eax
movl %eax, 0x100(%rsp)
movslq 0xbc(%rsp), %rsi
leaq 0x160(%rsp), %rdi
callq 0x2d100
movq %rax, %rdi
movl $0x2, %esi
callq 0xfc50
movl (%rax), %eax
addl 0x104(%rsp), %eax
movl %eax, 0x104(%rsp)
movslq 0xbc(%rsp), %rsi
leaq 0x148(%rsp), %rdi
callq 0x10260
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0xfa30
movsd (%rax), %xmm0
addsd 0xe0(%rsp), %xmm0
movsd %xmm0, 0xe0(%rsp)
movslq 0xbc(%rsp), %rsi
leaq 0x148(%rsp), %rdi
callq 0x10260
movq %rax, %rdi
movl $0x1, %esi
callq 0xfa30
movsd (%rax), %xmm0
addsd 0xe8(%rsp), %xmm0
movsd %xmm0, 0xe8(%rsp)
movslq 0xbc(%rsp), %rsi
leaq 0x148(%rsp), %rdi
callq 0x10260
movq %rax, %rdi
movl $0x2, %esi
callq 0xfa30
movsd (%rax), %xmm0
addsd 0xf0(%rsp), %xmm0
movsd %xmm0, 0xf0(%rsp)
movslq 0xbc(%rsp), %rsi
leaq 0x148(%rsp), %rdi
callq 0x10260
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0xfa30
movsd (%rax), %xmm0
movsd %xmm0, 0x18(%rsp)
movslq 0xbc(%rsp), %rsi
leaq 0x160(%rsp), %rdi
callq 0x2d100
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0xfc50
movsd 0x18(%rsp), %xmm0
cvtsi2sdl (%rax), %xmm1
divsd %xmm1, %xmm0
addsd 0xc0(%rsp), %xmm0
movsd %xmm0, 0xc0(%rsp)
movslq 0xbc(%rsp), %rsi
leaq 0x148(%rsp), %rdi
callq 0x10260
movq %rax, %rdi
movl $0x1, %esi
callq 0xfa30
movsd (%rax), %xmm0
movsd %xmm0, 0x20(%rsp)
movslq 0xbc(%rsp), %rsi
leaq 0x160(%rsp), %rdi
callq 0x2d100
movq %rax, %rdi
movl $0x1, %esi
callq 0xfc50
movsd 0x20(%rsp), %xmm0
cvtsi2sdl (%rax), %xmm1
divsd %xmm1, %xmm0
addsd 0xc8(%rsp), %xmm0
movsd %xmm0, 0xc8(%rsp)
movslq 0xbc(%rsp), %rsi
leaq 0x148(%rsp), %rdi
callq 0x10260
movq %rax, %rdi
movl $0x2, %esi
callq 0xfa30
movsd (%rax), %xmm0
movsd %xmm0, 0x28(%rsp)
movslq 0xbc(%rsp), %rsi
leaq 0x160(%rsp), %rdi
callq 0x2d100
movq %rax, %rdi
movl $0x2, %esi
callq 0xfc50
movsd 0x28(%rsp), %xmm0
cvtsi2sdl (%rax), %xmm1
divsd %xmm1, %xmm0
addsd 0xd0(%rsp), %xmm0
movsd %xmm0, 0xd0(%rsp)
movl 0xbc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xbc(%rsp)
jmp 0x4954c
movq 0x60(%rsp), %rdi
movsd 0xe0(%rsp), %xmm0
movsd 0xe8(%rsp), %xmm1
addsd %xmm1, %xmm0
movsd 0xf0(%rsp), %xmm1
addsd %xmm1, %xmm0
movsd %xmm0, 0xb0(%rsp)
movsd 0xb0(%rsp), %xmm0
movsd %xmm0, 0x10(%rsp)
callq 0x47680
movsd 0x10(%rsp), %xmm0
movq %rax, %xmm1
movaps 0x31a48(%rip), %xmm2    # 0x7b2b0
punpckldq %xmm2, %xmm1    # xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1]
movapd 0x31a4c(%rip), %xmm2    # 0x7b2c0
subpd %xmm2, %xmm1
movaps %xmm1, %xmm2
unpckhpd %xmm1, %xmm1            # xmm1 = xmm1[1,1]
addsd %xmm2, %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0xa8(%rsp)
movsd 0xa8(%rsp), %xmm0
leaq 0x31cb4(%rip), %rdi     # 0x7b554
movb $0x1, %al
callq 0x9040
jmp 0x498a9
leaq 0x32572(%rip), %rdi     # 0x7be22
xorl %eax, %eax
callq 0x9040
jmp 0x498b9
movsd 0xe8(%rsp), %xmm0
cvtsi2sdl 0x100(%rsp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0xa0(%rsp)
movsd 0xf0(%rsp), %xmm0
cvtsi2sdl 0x104(%rsp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x98(%rsp)
movsd 0x1d8(%rsp), %xmm0
movsd %xmm0, (%rsp)
movq 0x1f0(%rsp), %rdi
callq 0x56b40
movq %rax, 0x8(%rsp)
jmp 0x49919
movsd (%rsp), %xmm0
movq 0x8(%rsp), %rax
movq %rax, %xmm1
movaps 0x31981(%rip), %xmm2    # 0x7b2b0
punpckldq %xmm2, %xmm1    # xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1]
movapd 0x31985(%rip), %xmm2    # 0x7b2c0
subpd %xmm2, %xmm1
movaps %xmm1, %xmm2
unpckhpd %xmm1, %xmm1            # xmm1 = xmm1[1,1]
addsd %xmm2, %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x90(%rsp)
leaq 0x324c4(%rip), %rdi     # 0x7be22
xorl %eax, %eax
callq 0x9040
jmp 0x49967
movl 0xfc(%rsp), %esi
leaq 0x31bfe(%rip), %rdi     # 0x7b573
xorl %eax, %eax
callq 0x9040
jmp 0x4997e
movl 0x100(%rsp), %esi
leaq 0x31bf8(%rip), %rdi     # 0x7b584
xorl %eax, %eax
callq 0x9040
jmp 0x49995
movl 0x104(%rsp), %esi
leaq 0x31bf2(%rip), %rdi     # 0x7b595
xorl %eax, %eax
callq 0x9040
jmp 0x499ac
leaq 0x3246f(%rip), %rdi     # 0x7be22
xorl %eax, %eax
callq 0x9040
jmp 0x499bc
movsd 0xa0(%rsp), %xmm0
movsd 0x90(%rsp), %xmm2
movaps %xmm0, %xmm1
divsd %xmm2, %xmm1
leaq 0x31bca(%rip), %rdi     # 0x7b5a6
movb $0x2, %al
callq 0x9040
jmp 0x499e5
movsd 0x98(%rsp), %xmm0
movsd 0x90(%rsp), %xmm2
movaps %xmm0, %xmm1
divsd %xmm2, %xmm1
leaq 0x31bbc(%rip), %rdi     # 0x7b5c1
movb $0x2, %al
callq 0x9040
jmp 0x49a0e
movsd 0x90(%rsp), %xmm0
leaq 0x31bbe(%rip), %rdi     # 0x7b5dc
movb $0x1, %al
callq 0x9040
jmp 0x49a27
movsd 0xe8(%rsp), %xmm0
movsd 0xf0(%rsp), %xmm1
addsd %xmm1, %xmm0
movl 0x100(%rsp), %eax
movl 0x104(%rsp), %ecx
addl %ecx, %eax
cvtsi2sd %eax, %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x88(%rsp)
movsd 0xa0(%rsp), %xmm0
movsd 0x90(%rsp), %xmm3
subsd %xmm3, %xmm0
cvtsi2sdl 0x100(%rsp), %xmm2
movsd 0x98(%rsp), %xmm1
subsd %xmm3, %xmm1
cvtsi2sdl 0x104(%rsp), %xmm3
mulsd %xmm3, %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x80(%rsp)
movsd 0x1d8(%rsp), %xmm0
movsd 0x80(%rsp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x78(%rsp)
movsd 0x78(%rsp), %xmm0
leaq 0x31b22(%rip), %rdi     # 0x7b5f3
movb $0x1, %al
callq 0x9040
jmp 0x49ada
movsd 0x88(%rsp), %xmm0
movsd 0x90(%rsp), %xmm2
movaps %xmm0, %xmm1
divsd %xmm2, %xmm1
leaq 0x31b15(%rip), %rdi     # 0x7b60f
movb $0x2, %al
callq 0x9040
jmp 0x49b03
movsd 0x1d8(%rsp), %xmm0
movsd 0xa8(%rsp), %xmm1
divsd %xmm1, %xmm0
leaq 0x31b0b(%rip), %rdi     # 0x7b62b
movb $0x1, %al
callq 0x9040
jmp 0x49b29
leaq 0x148(%rsp), %rdi
callq 0x10400
leaq 0x160(%rsp), %rdi
callq 0x2d140
leaq 0x178(%rsp), %rdi
callq 0x4dd90
leaq 0x1a0(%rsp), %rdi
callq 0xfa50
addq $0x1f8, %rsp            # imm = 0x1F8
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x198(%rsp)
movl %eax, 0x194(%rsp)
leaq 0x148(%rsp), %rdi
callq 0x10400
leaq 0x160(%rsp), %rdi
callq 0x2d140
leaq 0x178(%rsp), %rdi
callq 0x4dd90
leaq 0x1a0(%rsp), %rdi
callq 0xfa50
movq 0x198(%rsp), %rdi
callq 0x9cf0
nopw (%rax,%rax)