// File: /workspace/github_cpp_makefile_star2_O2/leonn[P]neuralNet/source/neural-net.cpp
// Function: main
int main(int argc, char *argv[]){
    srand(time(NULL));
    TrainingData trainData(argv[1]);

    // e.g., { 3, 2, 1 }
    vector<unsigned> topology;

    vector<vector<double>> inputValsA, targetValuesA;
    vector<double> inputVals, targetValues, resultValues;

    int trainingPass = 0;
    int epochs=0;
    bool test=false;
    bool testFile=false;
    long double minError=atof(argv[2]);
    int maxEpochs=atoi(argv[3]);

    ofstream trainingDataOutput;
    ofstream trainingDataGlobalOutput;
    ofstream testDataOutput;
    TrainingData *testDataInput;

    trainingDataOutput.open(argv[4]);
    trainingDataGlobalOutput.open(argv[5]);

    if(argc>6){
        if(!strcmp(argv[6],"-t")){
        testDataOutput.open(argv[7]);
        test=true;
        }
        else if(!strcmp(argv[6],"-tf")){
            testDataInput=new TrainingData(argv[7]);
            testDataOutput.open(argv[8]);
            testFile=true;
        }
    }

    long double eta,momentum;
    string transferFunction;

    trainData.getTopology(topology);
    trainData.getEta(eta);
    trainData.getMomentum(momentum);
    trainData.getTransferFunction(transferFunction);

    //Load trainning data from file
    while (!trainData.isEof()) {
        trainingPass++;

        // Get new input data and feed it forward:
        if (trainData.getNextInputs(inputVals) != topology[0])
            break;
        inputValsA.push_back(inputVals);

        // Train the net what the outputs should have been:
        trainData.getTargetOutputs(targetValues);
        assert(targetValues.size() == topology.back());
        targetValuesA.push_back(targetValues);
    }

    Net net(topology,transferFunction);
    long double recentAverageError;
    long double globalError;

    do {
        globalError=0.0;

        for (int i = 0; i < trainingPass; i++){
            // Get new input data and feed it forward:
            net.feedForward(inputValsA[i]);

            // Collect the net's actual output results:
            net.getResults(resultValues);

            // Train the net what the outputs should have been:
            net.backPropagation(targetValuesA[i],eta,momentum);

            // Report how well the training is working, average over recent samples:
            recentAverageError=net.getRecentAverageError();
            globalError+=recentAverageError;
            trainingDataOutput <<recentAverageError<<endl;
        }
        globalError/=trainingPass;
        trainingDataGlobalOutput <<globalError<<endl;
        epochs++;

    } while(round(globalError, minError) > minError && epochs < maxEpochs);

    trainingDataOutput.close();
    trainingDataGlobalOutput.close();

    if (test){
         for (int i = 0; i < trainingPass; i++){
            // Get new input data and feed it forward:][]
            net.feedForward(inputValsA[i]);
            showVectorValues("Input:", inputValsA[i], testDataOutput);

            showVectorValues("Target_Output:", targetValuesA[i], testDataOutput);

            // Collect the net's actual output results:
            net.getResults(resultValues);
            showTestVectorValues("Output:", resultValues, testDataOutput);
        }
    }

    if (testFile){
        trainingPass=0;
        //clear trainning data vectors
        inputValsA.clear();
        targetValuesA.clear();
        inputVals.clear();
        targetValues.clear();
        resultValues.clear();

        //Load trainning data from file
        while (!testDataInput->isEof()) {
            trainingPass++;

            // Get new input data and feed it forward:
            if (testDataInput->getNextInputs(inputVals) != topology[0])
                break;
            inputValsA.push_back(inputVals);

            // Train the net what the outputs should have been:
            testDataInput->getTargetOutputs(targetValues);
            assert(targetValues.size() == topology.back());
            targetValuesA.push_back(targetValues);
        }

        for (int i = 0; i < trainingPass; i++){
            // Get new input data and feed it forward:][]
            net.feedForward(inputValsA[i]);
            showVectorValues("Input:", inputValsA[i],testDataOutput);

            showVectorValues("Target_Output:", targetValuesA[i],testDataOutput);

            // Collect the net's actual output results:
            net.getResults(resultValues);
            showVectorValues("Output:", resultValues,testDataOutput);
        }
    }

    testDataOutput.close();
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xab8, %rsp            # imm = 0xAB8
movq %rsi, %r15
movl %edi, %ebx
xorl %edi, %edi
callq 0x21c0
movl %eax, %edi
callq 0x21e0
movq 0x8(%r15), %rsi
leaq -0x200(%rbp), %rdi
leaq -0x8c8(%rbp), %rdx
callq 0x20b0
leaq -0x6c8(%rbp), %rdi
leaq -0x200(%rbp), %rsi
callq 0x4904
leaq -0x200(%rbp), %rdi
callq 0x20e0
xorpd %xmm0, %xmm0
movapd %xmm0, -0xe0(%rbp)
andq $0x0, -0xd0(%rbp)
movapd %xmm0, -0xa0(%rbp)
andq $0x0, -0x90(%rbp)
movapd %xmm0, -0xc0(%rbp)
andq $0x0, -0xb0(%rbp)
movapd %xmm0, -0x100(%rbp)
andq $0x0, -0xf0(%rbp)
movapd %xmm0, -0x60(%rbp)
andq $0x0, -0x50(%rbp)
movapd %xmm0, -0x80(%rbp)
andq $0x0, -0x70(%rbp)
movq 0x10(%r15), %rdi
callq 0x2230
movsd %xmm0, -0x118(%rbp)
movsd %xmm0, -0x130(%rbp)
fldl -0x130(%rbp)
fstpt -0x40(%rbp)
movq 0x18(%r15), %rdi
callq 0x22b0
movl %eax, -0xa4(%rbp)
leaq -0x8c8(%rbp), %rdi
callq 0x2300
leaq -0xac8(%rbp), %rdi
callq 0x2300
leaq -0x4c0(%rbp), %rdi
callq 0x2300
movq 0x20(%r15), %rsi
leaq -0x8c8(%rbp), %rdi
pushq $0x10
popq %rdx
callq 0x2030
movq 0x28(%r15), %rsi
leaq -0xac8(%rbp), %rdi
pushq $0x10
popq %rdx
callq 0x2030
cmpl $0x7, %ebx
jl 0x33e0
movq 0x30(%r15), %rdi
cmpb $0x2d, (%rdi)
jne 0x33cc
cmpb $0x74, 0x1(%rdi)
jne 0x33cc
cmpb $0x0, 0x2(%rdi)
je 0x3a10
leaq 0x1d1f(%rip), %rsi      # 0x50f2
callq 0x2260
testl %eax, %eax
je 0x39ab
movl $0x0, -0x30(%rbp)
movl $0x0, -0x34(%rbp)
leaq -0x150(%rbp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movb $0x0, (%rax)
leaq -0x6c8(%rbp), %rdi
leaq -0xe0(%rbp), %rsi
callq 0x450e
leaq -0x6c8(%rbp), %rdi
leaq -0x1c0(%rbp), %rsi
callq 0x462e
leaq -0x6c8(%rbp), %rdi
leaq -0x1b0(%rbp), %rsi
callq 0x4812
leaq -0x6c8(%rbp), %rdi
leaq -0x160(%rbp), %rsi
callq 0x4720
xorl %r15d, %r15d
leaq -0x6c8(%rbp), %rbx
leaq -0x100(%rbp), %r14
leaq -0x60(%rbp), %r12
leaq -0xc0(%rbp), %r13
movq %rbx, %rdi
callq 0x44f8
testb %al, %al
jne 0x34d7
movq %rbx, %rdi
movq %r14, %rsi
callq 0x493c
movq -0xe0(%rbp), %rcx
cmpl (%rcx), %eax
jne 0x34d4
leaq -0xa0(%rbp), %rdi
movq %r14, %rsi
callq 0x3bd4
movq %rbx, %rdi
movq %r12, %rsi
callq 0x4a6a
movq -0x58(%rbp), %rax
subq -0x60(%rbp), %rax
sarq $0x3, %rax
movq -0xd8(%rbp), %rcx
movl -0x4(%rcx), %ecx
cmpq %rcx, %rax
jne 0x3a34
incl %r15d
movq %r13, %rdi
movq %r12, %rsi
callq 0x3bd4
jmp 0x3469
incl %r15d
leaq -0x1a0(%rbp), %rdi
leaq -0xe0(%rbp), %rsi
leaq -0x160(%rbp), %rdx
callq 0x2570
movl %r15d, -0xa8(%rbp)
fildl -0xa8(%rbp)
fstpt -0x13c(%rbp)
fld1
fldt -0x40(%rbp)
fdivrp %st, %st(1)
fstpt -0x10c(%rbp)
movl %r15d, %eax
imulq $0x18, %rax, %r13
xorl %eax, %eax
leaq -0x1a0(%rbp), %r12
leaq -0x1b0(%rbp), %r14
leaq -0x8c8(%rbp), %r15
movq %rax, -0x120(%rbp)
xorl %ebx, %ebx
fldz
fstpt -0x40(%rbp)
cmpq %rbx, %r13
je 0x35b9
movq -0xa0(%rbp), %rsi
addq %rbx, %rsi
movq %r12, %rdi
callq 0x26c4
fldz
fstp %st(0)
movq %r12, %rdi
leaq -0x80(%rbp), %rsi
callq 0x299c
fldz
fstp %st(0)
movq -0xc0(%rbp), %rsi
addq %rbx, %rsi
movq %r12, %rdi
leaq -0x1c0(%rbp), %rdx
movq %r14, %rcx
callq 0x27d8
fldz
fstp %st(0)
movq %r12, %rdi
callq 0x2a16
fldt -0x40(%rbp)
fadd %st(1), %st
fstpt -0x40(%rbp)
fstpt (%rsp)
movq %r15, %rdi
callq 0x2100
fldz
fstp %st(0)
movq %rax, %rdi
callq 0x20f0
fldz
fstp %st(0)
addq $0x18, %rbx
jmp 0x353d
fldt -0x13c(%rbp)
fldt -0x40(%rbp)
fdivp %st, %st(1)
fld %st(0)
fstpt -0x40(%rbp)
fstpt (%rsp)
leaq -0xac8(%rbp), %rdi
callq 0x2100
movq %rax, %rdi
callq 0x20f0
fldt -0x10c(%rbp)
fldt -0x40(%rbp)
fmulp %st, %st(1)
fadds 0x1a2f(%rip)            # 0x5020
fstpt (%rsp)
callq 0x2110
fldt -0x10c(%rbp)
fdivrp %st, %st(1)
fstpl -0x128(%rbp)
movsd -0x128(%rbp), %xmm0
ucomisd -0x118(%rbp), %xmm0
movq -0x120(%rbp), %rax
jbe 0x362e
incl %eax
cmpl -0xa4(%rbp), %eax
jl 0x352f
leaq -0x8c8(%rbp), %rdi
callq 0x2270
leaq -0xac8(%rbp), %rdi
callq 0x2270
cmpb $0x0, -0x34(%rbp)
je 0x3736
xorl %r12d, %r12d
leaq -0x2a0(%rbp), %r14
leaq -0x280(%rbp), %rbx
cmpq %r12, %r13
je 0x3736
movq -0xa0(%rbp), %rsi
addq %r12, %rsi
leaq -0x1a0(%rbp), %rdi
callq 0x26c4
leaq -0x2c0(%rbp), %r15
movq %r15, %rdi
leaq 0x1ab9(%rip), %rsi      # 0x514a
leaq -0x29(%rbp), %rdx
callq 0x20b0
movq -0xa0(%rbp), %rsi
addq %r12, %rsi
movq %r15, %rdi
leaq -0x4c0(%rbp), %rdx
callq 0x311c
movq %r15, %rdi
callq 0x20e0
movq %r14, %rdi
leaq 0x1a8c(%rip), %rsi      # 0x5151
leaq -0x29(%rbp), %rdx
callq 0x20b0
movq -0xc0(%rbp), %rsi
addq %r12, %rsi
movq %r14, %rdi
leaq -0x4c0(%rbp), %rdx
callq 0x311c
movq %r14, %rdi
callq 0x20e0
leaq -0x1a0(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x299c
movq %rbx, %rdi
leaq 0x1a4f(%rip), %rsi      # 0x5158
leaq -0x29(%rbp), %rdx
callq 0x20b0
movq %rbx, %rdi
leaq -0x80(%rbp), %rsi
leaq -0x4c0(%rbp), %rdx
callq 0x3192
movq %rbx, %rdi
callq 0x20e0
addq $0x18, %r12
jmp 0x3661
cmpb $0x0, -0x30(%rbp)
je 0x3901
leaq -0xa0(%rbp), %rdi
callq 0x3c10
leaq -0xc0(%rbp), %rdi
callq 0x3c10
movq -0x100(%rbp), %rax
cmpq %rax, -0xf8(%rbp)
je 0x376f
movq %rax, -0xf8(%rbp)
movq -0x60(%rbp), %rax
cmpq %rax, -0x58(%rbp)
je 0x377d
movq %rax, -0x58(%rbp)
movq -0x80(%rbp), %rax
cmpq %rax, -0x78(%rbp)
je 0x378b
movq %rax, -0x78(%rbp)
xorl %r13d, %r13d
leaq -0x100(%rbp), %rbx
leaq -0xa0(%rbp), %r14
leaq -0x60(%rbp), %r15
leaq -0xc0(%rbp), %r12
movq -0x48(%rbp), %rdi
callq 0x44f8
testb %al, %al
jne 0x3814
movq -0x48(%rbp), %rdi
movq %rbx, %rsi
callq 0x493c
movq -0xe0(%rbp), %rcx
cmpl (%rcx), %eax
jne 0x3811
movq %r14, %rdi
movq %rbx, %rsi
callq 0x3bd4
movq -0x48(%rbp), %rdi
movq %r15, %rsi
callq 0x4a6a
movq -0x58(%rbp), %rax
subq -0x60(%rbp), %rax
sarq $0x3, %rax
movq -0xd8(%rbp), %rcx
movl -0x4(%rcx), %ecx
cmpq %rcx, %rax
jne 0x3a51
incl %r13d
movq %r12, %rdi
movq %r15, %rsi
callq 0x3bd4
jmp 0x37a7
incl %r13d
movl %r13d, %eax
imulq $0x18, %rax, %rax
movq %rax, -0x40(%rbp)
xorl %r15d, %r15d
leaq -0x4c0(%rbp), %r13
leaq -0x240(%rbp), %r14
leaq -0x220(%rbp), %rbx
cmpq %r15, -0x40(%rbp)
je 0x3901
movq -0xa0(%rbp), %rsi
addq %r15, %rsi
leaq -0x1a0(%rbp), %rdi
callq 0x26c4
leaq -0x260(%rbp), %r12
movq %r12, %rdi
leaq 0x18e2(%rip), %rsi      # 0x514a
leaq -0x29(%rbp), %rdx
callq 0x20b0
movq -0xa0(%rbp), %rsi
addq %r15, %rsi
movq %r12, %rdi
movq %r13, %rdx
callq 0x311c
movq %r12, %rdi
callq 0x20e0
movq %r14, %rdi
leaq 0x18b9(%rip), %rsi      # 0x5151
leaq -0x29(%rbp), %rdx
callq 0x20b0
movq -0xc0(%rbp), %rsi
addq %r15, %rsi
movq %r14, %rdi
movq %r13, %rdx
callq 0x311c
movq %r14, %rdi
callq 0x20e0
leaq -0x1a0(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x299c
movq %rbx, %rdi
leaq 0x1880(%rip), %rsi      # 0x5158
leaq -0x29(%rbp), %rdx
callq 0x20b0
movq %rbx, %rdi
leaq -0x80(%rbp), %rsi
movq %r13, %rdx
callq 0x311c
movq %rbx, %rdi
callq 0x20e0
addq $0x18, %r15
jmp 0x3837
leaq -0x4c0(%rbp), %rdi
callq 0x2270
leaq -0x180(%rbp), %rdi
callq 0x2a70
leaq -0x160(%rbp), %rdi
callq 0x20e0
leaq -0x4c0(%rbp), %rdi
callq 0x2290
leaq -0xac8(%rbp), %rdi
callq 0x2290
leaq -0x8c8(%rbp), %rdi
callq 0x2290
leaq -0x80(%rbp), %rdi
callq 0x3c98
leaq -0x60(%rbp), %rdi
callq 0x3c98
leaq -0x100(%rbp), %rdi
callq 0x3c98
leaq -0xc0(%rbp), %rdi
callq 0x3c1e
leaq -0xa0(%rbp), %rdi
callq 0x3c1e
leaq -0xe0(%rbp), %rdi
callq 0x3c4a
leaq -0x6c8(%rbp), %rdi
callq 0x2060
xorl %eax, %eax
addq $0xab8, %rsp            # imm = 0xAB8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0x208, %edi            # imm = 0x208
callq 0x2200
movq %rax, -0x48(%rbp)
movq 0x38(%r15), %rsi
leaq -0x1e0(%rbp), %rdi
leaq -0x1a0(%rbp), %rdx
callq 0x20b0
leaq -0x1e0(%rbp), %rsi
movq -0x48(%rbp), %rdi
callq 0x4904
leaq -0x1e0(%rbp), %rdi
callq 0x20e0
movq 0x40(%r15), %rsi
leaq -0x4c0(%rbp), %rdi
pushq $0x10
popq %rdx
callq 0x2030
movb $0x1, %al
movl %eax, -0x30(%rbp)
movl $0x0, -0x34(%rbp)
jmp 0x33ee
movq 0x38(%r15), %rsi
leaq -0x4c0(%rbp), %rdi
pushq $0x10
popq %rdx
callq 0x2030
movb $0x1, %al
movl %eax, -0x34(%rbp)
movl $0x0, -0x30(%rbp)
jmp 0x33ee
leaq 0x16bb(%rip), %rdi      # 0x50f6
leaq 0x16db(%rip), %rsi      # 0x511d
leaq 0x16ea(%rip), %rcx      # 0x5133
pushq $0x52
popq %rdx
callq 0x2160
leaq 0x169e(%rip), %rdi      # 0x50f6
leaq 0x16be(%rip), %rsi      # 0x511d
leaq 0x16cd(%rip), %rcx      # 0x5133
movl $0x97, %edx
callq 0x2160
movq %rax, %r14
leaq -0x1e0(%rbp), %rdi
callq 0x20e0
jmp 0x3a84
movq %rax, %r14
movq -0x48(%rbp), %rdi
callq 0x21d0
jmp 0x3b5a
jmp 0x3b38
movq %rax, %r14
jmp 0x3b66
movq %rax, %r14
jmp 0x3b72
movq %rax, %r14
jmp 0x3b7e
movq %rax, %r14
leaq -0x200(%rbp), %rdi
callq 0x20e0
jmp 0x3bcc
movq %rax, %r14
jmp 0x3bcc
movq %rax, %r14
jmp 0x3b5a
jmp 0x3b3f
jmp 0x3b38
jmp 0x3b3f
movq %rax, %r14
leaq -0x220(%rbp), %rdi
jmp 0x3b29
jmp 0x3b3f
movq %rax, %r14
leaq -0x260(%rbp), %rdi
jmp 0x3b29
jmp 0x3b3f
movq %rax, %r14
leaq -0x240(%rbp), %rdi
jmp 0x3b29
jmp 0x3b3f
movq %rax, %r14
leaq -0x280(%rbp), %rdi
jmp 0x3b29
jmp 0x3b3f
movq %rax, %r14
leaq -0x2c0(%rbp), %rdi
jmp 0x3b29
jmp 0x3b3f
movq %rax, %r14
leaq -0x2a0(%rbp), %rdi
callq 0x20e0
jmp 0x3b42
jmp 0x3b3f
jmp 0x3b3f
jmp 0x3b3f
jmp 0x3b3f
movq %rax, %r14
jmp 0x3b4e
fstp %st(0)
movq %rax, %r14
leaq -0x180(%rbp), %rdi
callq 0x2a70
leaq -0x160(%rbp), %rdi
callq 0x20e0
leaq -0x4c0(%rbp), %rdi
callq 0x2290
leaq -0xac8(%rbp), %rdi
callq 0x2290
leaq -0x8c8(%rbp), %rdi
callq 0x2290
leaq -0x80(%rbp), %rdi
callq 0x3c98
leaq -0x60(%rbp), %rdi
callq 0x3c98
leaq -0x100(%rbp), %rdi
callq 0x3c98
leaq -0xc0(%rbp), %rdi
callq 0x3c1e
leaq -0xa0(%rbp), %rdi
callq 0x3c1e
leaq -0xe0(%rbp), %rdi
callq 0x3c4a
leaq -0x6c8(%rbp), %rdi
callq 0x2060
movq %r14, %rdi
callq 0x2320