// File: gkosae[P]ArduinoNeuralNet/neuralnet.cpp
// Function: NeuralNet::train(std::vector<std::vector<double, std::allocator<double>>, std::allocator<std::vector<double, std::allocator<double>>>>, std::vector<std::vector<double, std::allocator<double>>, std::allocator<std::vector<double, std::allocator<double>>>>, double, double, long)
void NeuralNet::train(vector<vector<double>> input_samples,
                             vector<vector<double>> output_samples,
                             double learn_rate,
                             double new_lambda,
                             long max_iter)
{
    input_data = input_samples;
    expected_output = output_samples;
    actual_output = std::vector<vector<double>>(input_data.size());

    lambda = new_lambda;
    learning_rate = learn_rate;
    max_iteration_number = max_iter;

    double overall_error = 0;
    unsigned int number_of_samples = input_data.size();
    unsigned int iteration_number = 0;

    do
    {
        for(current_sample = 0; current_sample <  number_of_samples; ++current_sample) {
          feed(input_data.at(current_sample));
          forward();

          actual_output.at(current_sample) = getOutputs();
          updateWeights();
        }

        overall_error = calculateOverallError();
        ++iteration_number;

        #ifdef VERBOSE
            std::cout << "Current error = " << overall_error << "\n";
        #endif
    } while (overall_error > minimum_error && iteration_number < max_iteration_number);

    #ifdef VERBOSE
    std::cout << "\nTRAINING RESULTS" << "\n"
              << "Overall error: " << overall_error << "\n"
              << "Total number of iterations: " << iteration_number << "\n\n";
    #endif

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xe0, %rsp
movq %rdx, -0xc0(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movsd %xmm0, -0x20(%rbp)
movsd %xmm1, -0x28(%rbp)
movq %rcx, -0x30(%rbp)
movq -0x8(%rbp), %rdi
movq %rdi, -0xc8(%rbp)
addq $0x60, %rdi
movq %rdi, -0xb8(%rbp)
callq 0x7d70
movq -0xc8(%rbp), %rdi
movq -0xc0(%rbp), %rsi
addq $0x48, %rdi
callq 0x7d70
movq -0xb8(%rbp), %rdi
callq 0x7fc0
movq %rax, -0xb0(%rbp)
leaq -0x49(%rbp), %rdi
movq %rdi, -0xa8(%rbp)
callq 0x7ff0
movq -0xb0(%rbp), %rsi
movq -0xa8(%rbp), %rdx
leaq -0x48(%rbp), %rdi
callq 0x8010
jmp 0x5b7a
movq -0xc8(%rbp), %rdi
addq $0x30, %rdi
leaq -0x48(%rbp), %rsi
callq 0x8080
leaq -0x48(%rbp), %rdi
callq 0x80b0
leaq -0x49(%rbp), %rdi
callq 0x8110
movq -0xc8(%rbp), %rdi
movsd -0x28(%rbp), %xmm0
movsd %xmm0, 0x80(%rdi)
movsd -0x20(%rbp), %xmm0
movsd %xmm0, 0x8(%rdi)
movq -0x30(%rbp), %rax
movq %rax, 0x10(%rdi)
xorps %xmm0, %xmm0
movsd %xmm0, -0x68(%rbp)
addq $0x60, %rdi
callq 0x7fc0
movl %eax, -0x6c(%rbp)
movl $0x0, -0x70(%rbp)
movq -0xc8(%rbp), %rax
movl $0x0, 0x78(%rax)
movq -0xc8(%rbp), %rax
movl 0x78(%rax), %eax
cmpl -0x6c(%rbp), %eax
jae 0x5d25
movq -0xc8(%rbp), %rax
movq %rax, %rdi
addq $0x60, %rdi
movl 0x78(%rax), %eax
movl %eax, %esi
callq 0x8170
movq %rax, %rsi
leaq -0x88(%rbp), %rdi
movq %rdi, -0xd0(%rbp)
callq 0x4730
movq -0xc8(%rbp), %rdi
movq -0xd0(%rbp), %rsi
callq 0x8130
jmp 0x5c45
leaq -0x88(%rbp), %rdi
callq 0x2990
movq -0xc8(%rbp), %rdi
callq 0x5e40
movq -0xc8(%rbp), %rsi
leaq -0xa0(%rbp), %rdi
callq 0x81b0
movq -0xc8(%rbp), %rax
movq %rax, %rdi
addq $0x30, %rdi
movl 0x78(%rax), %eax
movl %eax, %esi
callq 0x8170
movq %rax, -0xd8(%rbp)
jmp 0x5c91
movq -0xd8(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
callq 0x2960
leaq -0xa0(%rbp), %rdi
callq 0x2990
movq -0xc8(%rbp), %rdi
callq 0x6030
movq -0xc8(%rbp), %rax
movl 0x78(%rax), %ecx
addl $0x1, %ecx
movl %ecx, 0x78(%rax)
jmp 0x5bef
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x49(%rbp), %rdi
callq 0x8110
jmp 0x5e2c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0x88(%rbp), %rdi
callq 0x2990
jmp 0x5e2c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x58(%rbp)
movl %eax, -0x5c(%rbp)
leaq -0xa0(%rbp), %rdi
callq 0x2990
jmp 0x5e2c
movq -0xc8(%rbp), %rdi
callq 0x6060
movsd %xmm0, -0x68(%rbp)
movl -0x70(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x70(%rbp)
movq 0xf292(%rip), %rdi      # 0x14fd8
leaq 0x83cb(%rip), %rsi      # 0xe118
callq 0x2190
movq %rax, %rdi
movsd -0x68(%rbp), %xmm0
callq 0x2350
movq %rax, %rdi
leaq 0x8517(%rip), %rsi      # 0xe280
callq 0x2190
movq -0xc8(%rbp), %rcx
movsd -0x68(%rbp), %xmm0
xorl %eax, %eax
ucomisd (%rcx), %xmm0
movb %al, -0xd9(%rbp)
jbe 0x5d9f
movq -0xc8(%rbp), %rcx
movl -0x70(%rbp), %eax
cmpq 0x10(%rcx), %rax
setl %al
movb %al, -0xd9(%rbp)
movb -0xd9(%rbp), %al
testb $0x1, %al
jne 0x5be1
movq 0xf224(%rip), %rdi      # 0x14fd8
leaq 0x836e(%rip), %rsi      # 0xe129
callq 0x2190
movq %rax, %rdi
leaq 0x84b6(%rip), %rsi      # 0xe280
callq 0x2190
movq %rax, %rdi
leaq 0x8362(%rip), %rsi      # 0xe13b
callq 0x2190
movq %rax, %rdi
movsd -0x68(%rbp), %xmm0
callq 0x2350
movq %rax, %rdi
leaq 0x848b(%rip), %rsi      # 0xe280
callq 0x2190
movq %rax, %rdi
leaq 0x8347(%rip), %rsi      # 0xe14b
callq 0x2190
movq %rax, %rdi
movl -0x70(%rbp), %esi
callq 0x2240
movq %rax, %rdi
leaq 0x8461(%rip), %rsi      # 0xe27f
callq 0x2190
addq $0xe0, %rsp
popq %rbp
retq
movq -0x58(%rbp), %rdi
callq 0x2310
nopw %cs:(%rax,%rax)