// File: /workspace/github_cpp_makefile_star2_O2/UCBASiCS[P]SPRIGHT/src/main.cpp
// Function: main
int main(int argc, char** argv)
{
    // Sets a random seed for each run of SPRIGHT.
    srand48((long int) time (NULL));
    
    // Configurations are set through the command line arguments
    Config* configurations = new Config(argc, argv);
    // This is here measuring how long it takes to generate the input and output
    Chrono* mChrono = new Chrono();

    // Input object
    Input* input;
    // Output object
    Output* output;
     
    // In the experiment mode, program uses randomly generated input and
    // compare the SPRIGHT output to the input.
    // In the customized mode, program takes input from a file and outputs
    // the recovered signal to a file. 
    // Note that input and output to SPRIGHT is made modular and for using SPRIGHT
    // in other applications changing these objects would be enough.
    if ( configurations->isExperimentMode() )
    {
	   input  = new ExperimentInput(mChrono, configurations);
	   // output = new CustomizedOutput(mChrono, configurations);
	   output = new ExperimentOutput(mChrono, configurations, dynamic_cast<ExperimentInput*>(input));
    }
    else
    {
	   input  = new CustomizedInput(mChrono, configurations);    
	   output = new CustomizedOutput(mChrono, configurations);
    }

    SPRIGHT* spright = new SPRIGHT(configurations, input, output);
    
    if (!configurations->isHelpDisplayed())
    {
        // the number of iterations entered by the user
        int iterations = configurations->getIterations();

        configurations->display();

        // do the required number of iterations
        for (int iteration=0; iteration<iterations; iteration++)
        {
            input->process( spright->getDelays() );
            spright->process();

            if (configurations->isVerbose())
                std::cout << std::endl << "### Iteration "<< iteration << " results ###" << std::endl;
            output->process();
        }

        spright->displayResults();

        if ( configurations->isExperimentMode() )
        {
            std::cout << std::setprecision(3) << std::scientific << mChrono->average("Input") << " -> signal generation time"  << std::endl;
        }
    }

    std::cout << std::endl;
	
    delete spright;

    exit(EXIT_SUCCESS);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x58, %rsp
movq %rsi, %rbx
movl %edi, %ebp
xorl %edi, %edi
callq 0x3240
movq %rax, %rdi
callq 0x3430
movl $0xd0, %edi
callq 0x3260
movq %rax, %r14
movq %rax, %rdi
movl %ebp, %esi
movq %rbx, %rdx
callq 0x5df0
movl $0xa0, %edi
callq 0x3260
movq %rax, %rbx
movq %rax, %rdi
callq 0xb63c
movq %r14, %rdi
callq 0x6708
testb %al, %al
je 0xb3e8
movl $0xd8, %edi
callq 0x3260
movq %rax, %r12
movq %rax, %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x82c8
movl $0x160, %edi            # imm = 0x160
callq 0x3260
movq %rax, %r13
leaq 0x880c(%rip), %rsi      # 0x13bd0
leaq 0x88c5(%rip), %rdx      # 0x13c90
movq %r12, %rdi
xorl %ecx, %ecx
callq 0x32a0
movq %r13, %rdi
movq %rbx, %rsi
movq %r14, %rdx
movq %rax, %rcx
callq 0x8e64
jmp 0xb41c
movl $0x80, %edi
callq 0x3260
movq %rax, %r12
movq %rax, %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x7554
pushq $0x20
popq %rdi
callq 0x3260
movq %rax, %r13
movq %rax, %rdi
movq %rbx, %rsi
movq %r14, %rdx
callq 0x7e6c
pushq $0x38
popq %rdi
callq 0x3260
movq %rax, %rbp
movq %rax, %rdi
movq %r14, %rsi
movq %r12, %rdx
movq %r13, %rcx
callq 0xba04
movq %r14, %rdi
callq 0x6fcc
testb %al, %al
jne 0xb5a3
movq %rbp, 0x10(%rsp)
movq %rbx, 0x18(%rsp)
movq %r14, %rdi
callq 0x670c
movl %eax, %ebx
movq %r14, 0x8(%rsp)
movq %r14, %rdi
callq 0x681c
xorl %ebp, %ebp
testl %ebx, %ebx
cmovlel %ebp, %ebx
leaq 0x40(%rsp), %r14
movq 0x10(%rsp), %r15
cmpl %ebp, %ebx
je 0xb505
movq %r14, %rdi
movq %r15, %rsi
callq 0xbecc
movq (%r12), %rax
movq %r12, %rdi
movq %r14, %rsi
callq *0x20(%rax)
movq %r14, %rdi
callq 0x41c6
movq %r15, %rdi
callq 0xbb38
movq 0x8(%rsp), %rdi
callq 0x67fc
testb %al, %al
je 0xb4f4
movq 0x8b11(%rip), %rdi      # 0x13fd0
callq 0x3110
movq %rax, %rdi
leaq 0x1aa1(%rip), %rsi      # 0xcf6f
callq 0x3250
movq %rax, %rdi
movl %ebp, %esi
callq 0x3470
movq %rax, %rdi
leaq 0x1a97(%rip), %rsi      # 0xcf7e
callq 0x3250
movq %rax, %rdi
callq 0x3110
movq (%r13), %rax
movq %r13, %rdi
callq *0x10(%rax)
incl %ebp
jmp 0xb47a
movq 0x10(%rsp), %rbp
movq %rbp, %rdi
callq 0xbbe2
movq 0x8(%rsp), %rdi
callq 0x6708
testb %al, %al
movq 0x18(%rsp), %rbx
je 0xb5a3
movq 0x8aa4(%rip), %rdx      # 0x13fd0
movq (%rdx), %rax
movq -0x18(%rax), %rcx
movq $0x3, 0x8(%rdx,%rcx)
movq -0x18(%rax), %rax
movl $0xfffffefb, %ecx       # imm = 0xFFFFFEFB
andl 0x18(%rdx,%rax), %ecx
orl $0x100, %ecx            # imm = 0x100
movl %ecx, 0x18(%rdx,%rax)
leaq 0x16f1(%rip), %rsi      # 0xcc4b
leaq 0x20(%rsp), %rdi
leaq 0x7(%rsp), %rdx
callq 0x3fb6
leaq 0x20(%rsp), %rsi
movq %rbx, %rdi
callq 0x5850
movq 0x8a53(%rip), %rdi      # 0x13fd0
callq 0x3400
leaq 0x1a02(%rip), %rsi      # 0xcf8b
movq %rax, %rdi
callq 0x3250
movq %rax, %rdi
callq 0x3110
leaq 0x20(%rsp), %rdi
callq 0x30f0
movq 0x8a26(%rip), %rdi      # 0x13fd0
callq 0x3110
movq %rbp, %rdi
callq 0xbab2
pushq $0x38
popq %rsi
movq %rbp, %rdi
callq 0x3270
xorl %edi, %edi
callq 0x32e0
movq %rax, %rbx
leaq 0x20(%rsp), %rdi
callq 0x30f0
jmp 0xb633
movq %rax, %rbx
jmp 0xb633
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
callq 0x41c6
jmp 0xb633
movq %rax, %rbx
pushq $0x38
popq %rsi
movq %rbp, %rdi
jmp 0xb62e
movq %rax, %rbx
pushq $0x20
popq %rsi
jmp 0xb607
movq %rax, %rbx
movl $0x160, %esi            # imm = 0x160
movq %r13, %rdi
jmp 0xb62e
movq %rax, %rbx
movl $0x80, %esi
jmp 0xb61e
movq %rax, %rbx
movl $0xd8, %esi
movq %r12, %rdi
jmp 0xb62e
movq %rax, %rbx
movl $0xd0, %esi
movq %r14, %rdi
callq 0x3270
movq %rbx, %rdi
callq 0x3490
nop