// File: /workspace/github_cpp_makefile_star2_O2/bolongz[P]Systematic-Alias-Sampling/test.cpp
// Function: main
int main(int argc, char *argv[]){

    
    int samplecount = 0;
    int bincount = 0;

    if(argc != 4){
        std::cout << "Usage: ./test bincount samplecount runtimes" << std::endl;
        exit(1);
    } 
    bincount = atoi(argv[1]); //bincount
    samplecount = atoi(argv[2]); //sampple count
    int times  = atoi(argv[3]) / samplecount; 
    
    
    struct timeval tvs, tvm; 
    std::vector<double> pmf;
    std::vector<double> values;
    
    double h = (8.0) / (bincount - 1); //[take value in [-4, 4]
    
    for(int i = 0; i < bincount; i++){
        double t = -4 + i * h;
        values.push_back(t);
        pmf.push_back(_normal_distribution(0.0, 1.0, t));
    }
    
    //  initial sas class 
    SystematicAliasSampling _sample(pmf, values);
    
    
    _sample.aliastable(); //generate table
    //std::vector<double> av = _sample.aliasvalue;;
    //std::sort(av.begin(), av.end());

    //for(int i = 0 ; i < av.size(); i++){
        //std::cout << av[i] << std::endl;
   //     std::cout << _normal_distribution(0.0, 1.0, av[i]) << std::endl;
    //} 
    std::vector<double> cdf(bincount);
    _sample.cummulative_distribution(cdf);
    
    double span0 =0.0;
    for(int j = 0; j < times ; j++){
        gettimeofday(&tvs, NULL);
        // binary search 
        std::vector<double> b_samples(samplecount);
        for(int i = 0; i < samplecount; i++){
            double x  = __random(gen);
            b_samples[i] = values[std::upper_bound(cdf.begin(), cdf.end(), x) - cdf.begin()];
            //std::cout << std::upper_bound(cdf.begin(), cdf.end(), x) - cdf.begin() << std::endl;
        
        }
        gettimeofday(&tvm, NULL);
        span0 += tvm.tv_sec-tvs.tv_sec + (tvm.tv_usec-tvs.tv_usec)/1000000.0;
    }
    //std::cout << "Binary Serach cost: " << span0 /times <<std::endl;
    
    // alias sampling method 
    std::uniform_real_distribution<double> ___random(0.0, bincount);
    
    double span =0.0;
    for(int j = 0; j < times; j++){
        gettimeofday(&tvs, NULL);
        std::vector<double> alias_samples(samplecount);
        for(int i = 0; i < samplecount; i++){
            double x  = ___random(gen);
            alias_samples[i]  = _sample.aliassample(int(x), x - int(x));
        }
        gettimeofday(&tvm, NULL);
        span += tvm.tv_sec-tvs.tv_sec + (tvm.tv_usec-tvs.tv_usec)/1000000.0;
    }
    //std::cout << "Alias method cost: " << span/times <<std::endl;
   

    // sas sampling 
    double span1 = 0.0;
    for(int j = 0; j < times; j++){
        gettimeofday(&tvs, NULL);
        std::vector<double> samples(samplecount); // store the results
        _sample.systematicaliassampling(samplecount, samples);
        gettimeofday(&tvm, NULL);
    
        span1 += tvm.tv_sec-tvs.tv_sec + (tvm.tv_usec-tvs.tv_usec)/1000000.0;
    }
    //std::cout << "SAS cost: " << span1 /times <<std::endl;
    
    //sas golden sampling 
    /*gettimeofday(&tvs, NULL);
    std::vector<double> samples2(samplecount);
    _sample.goldratioaliassampling(samplecount, samples2);
    
    gettimeofday(&tvm, NULL);
    double span4 = tvm.tv_sec-tvs.tv_sec + (tvm.tv_usec-tvs.tv_usec)/1000000.0;
    std::cout << "SAS-golden cost: " << span4 <<std::endl;
    */
    // normal_distribution in c++11 
    double span2 = 0.0;
    for(int j = 0; j < times; j++){
        gettimeofday(&tvs, NULL);
        std::vector<double> samples3(samplecount);
        __normal_distribution(samplecount, samples3);
        gettimeofday(&tvm, NULL);
        span2 += tvm.tv_sec-tvs.tv_sec + (tvm.tv_usec-tvs.tv_usec)/1000000.0;
    }
    //std::cout << "normal_distribution cost: " << span2/times <<std::endl;
    
    //discrete_distribution sampling in c++11 
    

    std::discrete_distribution<> _discrete_distribution(pmf.begin(), pmf.end());
    double span3 = 0.0;
    for(int j = 0; j < times; j++){
        gettimeofday(&tvs, NULL);
        std::vector<double> samples4(samplecount);;
        for(int i = 0 ; i < samplecount; i++){
            samples4[i] = _discrete_distribution(gen);
        }
        gettimeofday(&tvm, NULL);
        span3 += tvm.tv_sec-tvs.tv_sec + (tvm.tv_usec-tvs.tv_usec)/1000000.0;
    }
    //std::cout << "discrete_distribution cost: " << span3/times <<std::endl;
   
    std::cout << span0 /times <<" " << span/times << " " << span1/times << " " << span2/times <<" " << span3/times << std::endl;

   // std::vector<double> edf(bincount);
   
    //_sample.empirical_distribution(b_samples, edf);
    
   // for(int i = 0; i < bincount ; i++){
    //    std::cout << edf[i]<< std::endl;
        
   // }
   /* for(int j = 0 ; j < 1000; j ++){
        for(int i = 20; i < 2 * bincount; i++){
           // std::cout << "+++++++++++++"; 
           // double cvm = cramer_von_mises_alias(bincount, i);
            double cvm = cramer_von_mises_sas(bincount, i);
            //double cvm = cramer_von_mises_iid(bincount, i);
            std::cout << cvm <<" ";
        }
        std::cout << std::endl;
    }
    */
    return 0; 

}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x1b8, %rsp            # imm = 0x1B8
cmpl $0x4, %edi
jne 0x3005
movq %rsi, %rbx
movq 0x8(%rsi), %rdi
callq 0x2180
movl %eax, %r15d
movq 0x10(%rbx), %rdi
callq 0x2180
movl %eax, %ebp
movq 0x18(%rbx), %rdi
callq 0x2180
cltd
movl %ebp, 0x18(%rsp)
idivl %ebp
movl %eax, 0x5c(%rsp)
xorps %xmm0, %xmm0
leaq 0xd0(%rsp), %rbx
movaps %xmm0, (%rbx)
andq $0x0, 0x10(%rbx)
leaq 0xf0(%rsp), %r14
andq $0x0, 0x10(%r14)
movaps %xmm0, (%r14)
leal -0x1(%r15), %eax
cvtsi2sd %eax, %xmm0
movsd 0x3697(%rip), %xmm1     # 0x6050
divsd %xmm0, %xmm1
movsd %xmm1, 0x8(%rsp)
xorl %ebp, %ebp
testl %r15d, %r15d
movl $0x0, %r13d
movq %r15, 0x48(%rsp)
cmovgl %r15d, %r13d
leaq 0x110(%rsp), %r15
leaq 0x70(%rsp), %r12
cmpl %ebp, %r13d
je 0x2a3e
cvtsi2sd %ebp, %xmm0
mulsd 0x8(%rsp), %xmm0
addsd 0x365d(%rip), %xmm0     # 0x6058
movsd %xmm0, 0x110(%rsp)
movq %r14, %rdi
movq %r15, %rsi
callq 0x3128
movsd 0x110(%rsp), %xmm2
xorpd %xmm0, %xmm0
movsd 0x35ec(%rip), %xmm1     # 0x6010
callq 0x239c
movsd %xmm0, 0x70(%rsp)
movq %rbx, %rdi
movq %r12, %rsi
callq 0x4c52
incl %ebp
jmp 0x29e4
leaq 0x110(%rsp), %rdi
leaq 0xd0(%rsp), %rsi
leaq 0xf0(%rsp), %rdx
callq 0x314a
leaq 0x110(%rsp), %rdi
callq 0x3204
movslq 0x48(%rsp), %rsi
leaq 0xb8(%rsp), %rdi
leaq 0x70(%rsp), %rdx
callq 0x3568
leaq 0x110(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
callq 0x35ba
movl 0x18(%rsp), %eax
movslq %eax, %rcx
movq %rcx, 0x8(%rsp)
xorl %ebp, %ebp
testl %eax, %eax
movl %eax, %r14d
cmovlel %ebp, %r14d
movl 0x5c(%rsp), %eax
testl %eax, %eax
movl $0x0, %ecx
cmovgl %eax, %ecx
movl %ecx, 0x14(%rsp)
xorpd %xmm0, %xmm0
movsd %xmm0, 0x68(%rsp)
leaq 0xa0(%rsp), %rbx
leaq 0x8d7a(%rip), %r12      # 0xb850
leaq 0x79e3(%rip), %r15      # 0xa4c0
cmpl 0x14(%rsp), %ebp
je 0x2bb5
leaq 0x38(%rsp), %rdi
xorl %esi, %esi
callq 0x21a0
leaq 0x70(%rsp), %rdi
movq 0x8(%rsp), %rsi
movq %rbx, %rdx
callq 0x3568
xorl %r13d, %r13d
cmpq %r13, %r14
je 0x2b5e
movq %r12, %rdi
movq %r15, %rsi
callq 0x35f0
movsd %xmm0, 0xa0(%rsp)
movq 0xb8(%rsp), %rdi
movq 0xc0(%rsp), %rsi
movq %rbx, %rdx
callq 0x4d39
subq 0xb8(%rsp), %rax
movq 0xf0(%rsp), %rcx
movsd (%rcx,%rax), %xmm0
movq 0x70(%rsp), %rax
movsd %xmm0, (%rax,%r13,8)
incq %r13
jmp 0x2b08
leaq 0x28(%rsp), %rdi
xorl %esi, %esi
callq 0x21a0
movq 0x28(%rsp), %rax
movq 0x30(%rsp), %rcx
subq 0x38(%rsp), %rax
cvtsi2sd %rax, %xmm0
subq 0x40(%rsp), %rcx
cvtsi2sd %rcx, %xmm1
divsd 0x34d0(%rip), %xmm1     # 0x6060
addsd %xmm0, %xmm1
movsd 0x68(%rsp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x68(%rsp)
leaq 0x70(%rsp), %rdi
callq 0x4798
incl %ebp
jmp 0x2add
leaq 0x1a8(%rsp), %r12
andq $0x0, (%r12)
cvtsi2sdl 0x48(%rsp), %xmm0
movsd %xmm0, 0x8(%r12)
xorl %eax, %eax
xorpd %xmm0, %xmm0
movsd %xmm0, 0x48(%rsp)
leaq 0x78de(%rip), %r13      # 0xa4c0
leaq 0x128(%rsp), %rbx
leaq 0x140(%rsp), %r15
cmpl 0x14(%rsp), %eax
je 0x2cd3
movq %rax, 0x50(%rsp)
leaq 0x38(%rsp), %rdi
xorl %esi, %esi
callq 0x21a0
leaq 0x70(%rsp), %rdi
movq 0x8(%rsp), %rsi
leaq 0xa0(%rsp), %rdx
callq 0x3568
xorl %ebp, %ebp
cmpq %rbp, %r14
je 0x2c77
movq %r12, %rdi
movq %r13, %rsi
callq 0x35f0
cvttsd2si %xmm0, %eax
cvttpd2dq %xmm0, %xmm1
cvtdq2pd %xmm1, %xmm1
subsd %xmm1, %xmm0
cltq
movq 0x170(%rsp), %rcx
movsd (%rcx,%rax,8), %xmm1
ucomisd %xmm0, %xmm1
movq %r15, %rcx
cmovbq %rbx, %rcx
movq (%rcx), %rcx
movsd (%rcx,%rax,8), %xmm0
movq 0x70(%rsp), %rax
movsd %xmm0, (%rax,%rbp,8)
incq %rbp
jmp 0x2c26
leaq 0x28(%rsp), %rdi
xorl %esi, %esi
callq 0x21a0
movq 0x28(%rsp), %rax
movq 0x30(%rsp), %rcx
subq 0x38(%rsp), %rax
cvtsi2sd %rax, %xmm0
subq 0x40(%rsp), %rcx
cvtsi2sd %rcx, %xmm1
divsd 0x33b7(%rip), %xmm1     # 0x6060
addsd %xmm0, %xmm1
movsd 0x48(%rsp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x48(%rsp)
leaq 0x70(%rsp), %rdi
callq 0x4798
movq 0x50(%rsp), %rax
incl %eax
jmp 0x2bf2
xorpd %xmm0, %xmm0
movsd %xmm0, 0x50(%rsp)
leaq 0x70(%rsp), %r15
leaq 0xa0(%rsp), %r12
leaq 0x110(%rsp), %r13
leaq 0x28(%rsp), %rbp
movl 0x14(%rsp), %ebx
subl $0x1, %ebx
jb 0x2d7b
leaq 0x38(%rsp), %rdi
xorl %esi, %esi
callq 0x21a0
movq %r15, %rdi
movq 0x8(%rsp), %rsi
movq %r12, %rdx
callq 0x3568
movq %r13, %rdi
movl 0x18(%rsp), %esi
movq %r15, %rdx
xorl %ecx, %ecx
callq 0x38d2
movq %rbp, %rdi
xorl %esi, %esi
callq 0x21a0
movq 0x28(%rsp), %rax
movq 0x30(%rsp), %rcx
subq 0x38(%rsp), %rax
cvtsi2sd %rax, %xmm0
subq 0x40(%rsp), %rcx
cvtsi2sd %rcx, %xmm1
divsd 0x3303(%rip), %xmm1     # 0x6060
addsd %xmm0, %xmm1
movsd 0x50(%rsp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x50(%rsp)
movq %r15, %rdi
callq 0x4798
jmp 0x2cfb
xorpd %xmm0, %xmm0
movsd %xmm0, 0x60(%rsp)
leaq 0x38(%rsp), %rbx
leaq 0x70(%rsp), %r15
leaq 0xa0(%rsp), %r12
leaq 0x28(%rsp), %r13
movl 0x14(%rsp), %ebp
subl $0x1, %ebp
jb 0x2e19
movq %rbx, %rdi
xorl %esi, %esi
callq 0x21a0
movq %r15, %rdi
movq 0x8(%rsp), %rsi
movq %r12, %rdx
callq 0x3568
movl 0x18(%rsp), %edi
movq %r15, %rsi
callq 0x23de
movq %r13, %rdi
xorl %esi, %esi
callq 0x21a0
movq 0x28(%rsp), %rax
movq 0x30(%rsp), %rcx
subq 0x38(%rsp), %rax
cvtsi2sd %rax, %xmm0
subq 0x40(%rsp), %rcx
cvtsi2sd %rcx, %xmm1
divsd 0x3265(%rip), %xmm1     # 0x6060
addsd %xmm0, %xmm1
movsd 0x60(%rsp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x60(%rsp)
movq %r15, %rdi
callq 0x4798
jmp 0x2da0
movq 0xd0(%rsp), %rsi
movq 0xd8(%rsp), %rdx
leaq 0x70(%rsp), %rdi
callq 0x4d72
xorl %r12d, %r12d
xorpd %xmm0, %xmm0
movsd %xmm0, 0x18(%rsp)
leaq 0xa0(%rsp), %r15
leaq 0x7671(%rip), %rbp      # 0xa4c0
leaq 0x70(%rsp), %rbx
cmpl 0x14(%rsp), %r12d
je 0x2efd
leaq 0x38(%rsp), %rdi
xorl %esi, %esi
callq 0x21a0
movq %r15, %rdi
movq 0x8(%rsp), %rsi
leaq 0x27(%rsp), %rdx
callq 0x3568
xorl %r13d, %r13d
cmpq %r13, %r14
je 0x2ea7
movq %rbx, %rdi
movq %rbp, %rsi
callq 0x3a2e
cvtsi2sd %eax, %xmm0
movq 0xa0(%rsp), %rax
movsd %xmm0, (%rax,%r13,8)
incq %r13
jmp 0x2e80
leaq 0x28(%rsp), %rdi
xorl %esi, %esi
callq 0x21a0
movq 0x28(%rsp), %rax
movq 0x30(%rsp), %rcx
subq 0x38(%rsp), %rax
cvtsi2sd %rax, %xmm0
subq 0x40(%rsp), %rcx
cvtsi2sd %rcx, %xmm1
divsd 0x3187(%rip), %xmm1     # 0x6060
addsd %xmm0, %xmm1
movsd 0x18(%rsp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x18(%rsp)
movq %r15, %rdi
callq 0x4798
incl %r12d
jmp 0x2e54
cvtsi2sdl 0x5c(%rsp), %xmm1
movsd 0x68(%rsp), %xmm0
movsd %xmm1, 0x8(%rsp)
divsd %xmm1, %xmm0
movq 0x60be(%rip), %rdi      # 0x8fd8
callq 0x2190
leaq 0x31d2(%rip), %rsi      # 0x60f8
movq %rax, %rdi
callq 0x2120
movsd 0x48(%rsp), %xmm0
divsd 0x8(%rsp), %xmm0
movq %rax, %rdi
callq 0x2190
leaq 0x31af(%rip), %rsi      # 0x60f8
movq %rax, %rdi
callq 0x2120
movsd 0x50(%rsp), %xmm0
divsd 0x8(%rsp), %xmm0
movq %rax, %rdi
callq 0x2190
leaq 0x318c(%rip), %rsi      # 0x60f8
movq %rax, %rdi
callq 0x2120
movsd 0x60(%rsp), %xmm0
divsd 0x8(%rsp), %xmm0
movq %rax, %rdi
callq 0x2190
leaq 0x3169(%rip), %rsi      # 0x60f8
movq %rax, %rdi
callq 0x2120
movsd 0x18(%rsp), %xmm0
divsd 0x8(%rsp), %xmm0
movq %rax, %rdi
callq 0x2190
movq %rax, %rdi
callq 0x2080
leaq 0x70(%rsp), %rdi
callq 0x474a
leaq 0xb8(%rsp), %rdi
callq 0x4798
leaq 0x110(%rsp), %rdi
callq 0x37aa
leaq 0xf0(%rsp), %rdi
callq 0x4798
leaq 0xd0(%rsp), %rdi
callq 0x4798
xorl %eax, %eax
addq $0x1b8, %rsp            # imm = 0x1B8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x5fcc(%rip), %rdi      # 0x8fd8
leaq 0x30b9(%rip), %rsi      # 0x60cc
callq 0x2120
movq %rax, %rdi
callq 0x2080
pushq $0x1
popq %rdi
callq 0x2140
jmp 0x3044
jmp 0x302c
movq %rax, %rbx
jmp 0x308a
jmp 0x304b
jmp 0x3035
movq %rax, %rbx
jmp 0x3060
jmp 0x3044
jmp 0x3070
jmp 0x3044
jmp 0x3070
jmp 0x3044
movq %rax, %rbx
jmp 0x307d
jmp 0x304b
movq %rax, %rbx
jmp 0x3097
movq %rax, %rbx
leaq 0xa0(%rsp), %rdi
callq 0x4798
leaq 0x70(%rsp), %rdi
callq 0x474a
jmp 0x307d
jmp 0x3070
jmp 0x3070
movq %rax, %rbx
leaq 0x70(%rsp), %rdi
callq 0x4798
leaq 0xb8(%rsp), %rdi
callq 0x4798
leaq 0x110(%rsp), %rdi
callq 0x37aa
leaq 0xf0(%rsp), %rdi
callq 0x4798
leaq 0xd0(%rsp), %rdi
callq 0x4798
movq %rbx, %rdi
callq 0x21e0
nop