// File: gkosae[P]ArduinoNeuralNet/neuralnet.cpp
// Function: NeuralNet::backpropagateErrors()
void NeuralNet::backpropagateErrors() {
    // Calculate delta (backpropagating error) for output layer
    unsigned short output_layer_size = layers.back().size();

    for(auto i = 0; i < output_layer_size; ++i) {

        layers.back().neurons.at(i).delta = (actual_output.at(current_sample).at(i) -
                                             expected_output.at(current_sample).at(i)) *
                                             layers.back().neurons.at(i).sigmoidPrime();
    }

    unsigned short number_of_hidden_layers = layers.size() - 2;

    for(auto i = number_of_hidden_layers; i > 0 ; --i) {

      unsigned short current_layer_size = layers.at(i).size();
      unsigned short next_layer_size = layers.at(i+1).size();

      for(auto j = 0; j < current_layer_size; ++j) {

          double delta = 0;
          for(auto k = 0; k <  next_layer_size; k++) {
              delta += (layers.at(i+1).neurons.at(k).delta *
                        layers.at(i+1).neurons.at(k).weights.at(j) *
                        layers.at(i).neurons.at(j).sigmoidPrime());
          }

          layers.at(i).neurons.at(j).delta = delta;
      }
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rdi
movq %rdi, -0x38(%rbp)
addq $0x18, %rdi
callq 0x8310
movq %rax, %rdi
callq 0x8220
movw %ax, -0xa(%rbp)
movl $0x0, -0x10(%rbp)
movl -0x10(%rbp), %eax
movzwl -0xa(%rbp), %ecx
cmpl %ecx, %eax
jge 0x62c6
movq -0x38(%rbp), %rax
movq %rax, %rdi
addq $0x30, %rdi
movl 0x78(%rax), %eax
movl %eax, %esi
callq 0x8170
movq %rax, %rdi
movslq -0x10(%rbp), %rsi
callq 0x2b10
movq %rax, %rcx
movq -0x38(%rbp), %rax
movsd (%rcx), %xmm0
movsd %xmm0, -0x50(%rbp)
movq %rax, %rdi
addq $0x48, %rdi
movl 0x78(%rax), %eax
movl %eax, %esi
callq 0x8170
movq %rax, %rdi
movslq -0x10(%rbp), %rsi
callq 0x2b10
movsd -0x50(%rbp), %xmm0
movq -0x38(%rbp), %rdi
subsd (%rax), %xmm0
movsd %xmm0, -0x48(%rbp)
addq $0x18, %rdi
callq 0x8310
movq %rax, %rdi
addq $0x18, %rdi
movslq -0x10(%rbp), %rsi
callq 0x8240
movq %rax, %rdi
callq 0x8350
movq -0x38(%rbp), %rdi
movaps %xmm0, %xmm1
movsd -0x48(%rbp), %xmm0
mulsd %xmm1, %xmm0
movsd %xmm0, -0x40(%rbp)
addq $0x18, %rdi
callq 0x8310
movq %rax, %rdi
addq $0x18, %rdi
movslq -0x10(%rbp), %rsi
callq 0x8240
movsd -0x40(%rbp), %xmm0
movsd %xmm0, 0x38(%rax)
movl -0x10(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x10(%rbp)
jmp 0x61f0
movq -0x38(%rbp), %rdi
addq $0x18, %rdi
callq 0x82e0
subq $0x2, %rax
movw %ax, -0x12(%rbp)
movw -0x12(%rbp), %ax
movw %ax, -0x14(%rbp)
movzwl -0x14(%rbp), %eax
cmpl $0x0, %eax
jle 0x6487
movq -0x38(%rbp), %rdi
addq $0x18, %rdi
movzwl -0x14(%rbp), %eax
movl %eax, %esi
callq 0x8280
movq %rax, %rdi
callq 0x8220
movq -0x38(%rbp), %rdi
movw %ax, -0x16(%rbp)
addq $0x18, %rdi
movzwl -0x14(%rbp), %eax
addl $0x1, %eax
movslq %eax, %rsi
callq 0x8280
movq %rax, %rdi
callq 0x8220
movw %ax, -0x18(%rbp)
movl $0x0, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
movzwl -0x16(%rbp), %ecx
cmpl %ecx, %eax
jge 0x6474
xorps %xmm0, %xmm0
movsd %xmm0, -0x28(%rbp)
movl $0x0, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
movzwl -0x18(%rbp), %ecx
cmpl %ecx, %eax
jge 0x642f
movq -0x38(%rbp), %rdi
addq $0x18, %rdi
movzwl -0x14(%rbp), %eax
addl $0x1, %eax
movslq %eax, %rsi
callq 0x8280
movq %rax, %rdi
addq $0x18, %rdi
movslq -0x2c(%rbp), %rsi
callq 0x8240
movq -0x38(%rbp), %rdi
movsd 0x38(%rax), %xmm0
movsd %xmm0, -0x60(%rbp)
addq $0x18, %rdi
movzwl -0x14(%rbp), %eax
addl $0x1, %eax
movslq %eax, %rsi
callq 0x8280
movq %rax, %rdi
addq $0x18, %rdi
movslq -0x2c(%rbp), %rsi
callq 0x8240
movq %rax, %rdi
addq $0x20, %rdi
movslq -0x1c(%rbp), %rsi
callq 0x2b10
movsd -0x60(%rbp), %xmm0
movq -0x38(%rbp), %rdi
mulsd (%rax), %xmm0
movsd %xmm0, -0x58(%rbp)
addq $0x18, %rdi
movzwl -0x14(%rbp), %eax
movl %eax, %esi
callq 0x8280
movq %rax, %rdi
addq $0x18, %rdi
movslq -0x1c(%rbp), %rsi
callq 0x8240
movq %rax, %rdi
callq 0x8350
movaps %xmm0, %xmm2
movsd -0x58(%rbp), %xmm0
movsd -0x28(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0x28(%rbp)
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x6357
movq -0x38(%rbp), %rdi
movsd -0x28(%rbp), %xmm0
movsd %xmm0, -0x68(%rbp)
addq $0x18, %rdi
movzwl -0x14(%rbp), %eax
movl %eax, %esi
callq 0x8280
movq %rax, %rdi
addq $0x18, %rdi
movslq -0x1c(%rbp), %rsi
callq 0x8240
movsd -0x68(%rbp), %xmm0
movsd %xmm0, 0x38(%rax)
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x6339
jmp 0x6476
movw -0x14(%rbp), %ax
addw $-0x1, %ax
movw %ax, -0x14(%rbp)
jmp 0x62e3
addq $0x70, %rsp
popq %rbp
retq
nopl (%rax)