// File: theolepage[P]prophecy/src/model/model.hh
// Function: Model<float>::train(std::vector<Matrix<float>, std::allocator<Matrix<float>>>&, std::vector<Matrix<float>, std::allocator<Matrix<float>>>&, int, int)
void train(std::vector<Matrix<T>>& x,
                std::vector<Matrix<T>>& y,
                int epochs,
                int batch_size)
    {
        if (!compiled_)
            throw "Model has not been compiled.";

        for (int epoch = 0; epoch < epochs; epoch++)
        {
            // Determine batches
            int i = 0;
            int nb_batches = ceil(x.size() / batch_size);
            for (int batch = 0; batch < nb_batches; batch++)
            {
                // For each batch, compute delta weights and biases
                for (int k = 0; k < batch_size && i < static_cast<int>(x.size()); k++)
                {
                    layers_[0]->feedforward(x[i], true);
                    layers_[layers_.size() - 1]->backpropagation(&y[i]);
                    ++i;
                }

                // At the end of batch, update weights_ and biases_
                for (size_t l = 1; l < layers_.size(); l++)
                {
                    auto layer = std::dynamic_pointer_cast<HiddenLayer<T>>(layers_[l]);
                    layer->update(learning_rate_);
                }
            }
        }
    }

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xc0, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movl %ecx, -0x1c(%rbp)
movl %r8d, -0x20(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x88(%rbp)
testb $0x1, 0x8(%rax)
jne 0x2f66
movl $0x8, %edi
callq 0x20a0
movq %rax, %rdi
leaq 0x7315(%rip), %rax      # 0xa268
movq %rax, (%rdi)
movq 0xd053(%rip), %rsi      # 0xffb0
xorl %eax, %eax
movl %eax, %edx
callq 0x21f0
movl $0x0, -0x24(%rbp)
movl -0x24(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jge 0x31ba
movl $0x0, -0x28(%rbp)
movq -0x10(%rbp), %rdi
callq 0x31d0
movslq -0x20(%rbp), %rcx
xorl %edx, %edx
divq %rcx
movq %rax, %xmm0
movaps 0x7082(%rip), %xmm1     # 0xa020
punpckldq %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
movapd 0x7086(%rip), %xmm1     # 0xa030
subpd %xmm1, %xmm0
movaps %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm1, %xmm0
callq 0x2040
cvttsd2si %xmm0, %eax
movl %eax, -0x2c(%rbp)
movl $0x0, -0x30(%rbp)
movl -0x30(%rbp), %eax
cmpl -0x2c(%rbp), %eax
jge 0x31aa
movl $0x0, -0x34(%rbp)
movl -0x34(%rbp), %ecx
xorl %eax, %eax
cmpl -0x20(%rbp), %ecx
movb %al, -0x89(%rbp)
jge 0x3015
movl -0x28(%rbp), %eax
movl %eax, -0x90(%rbp)
movq -0x10(%rbp), %rdi
callq 0x31d0
movq %rax, %rcx
movl -0x90(%rbp), %eax
cmpl %ecx, %eax
setl %al
movb %al, -0x89(%rbp)
movb -0x89(%rbp), %al
testb $0x1, %al
jne 0x3024
jmp 0x30ea
movq -0x88(%rbp), %rdi
addq $0x10, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x9390
movq %rax, %rdi
callq 0x7270
movq %rax, -0xa8(%rbp)
movq -0x10(%rbp), %rdi
movslq -0x28(%rbp), %rsi
callq 0x94f0
movq -0xa8(%rbp), %rsi
movq %rax, %rdx
movq (%rsi), %rax
leaq -0x58(%rbp), %rdi
movl $0x1, %ecx
callq *0x10(%rax)
leaq -0x58(%rbp), %rdi
callq 0x34d0
movq -0x88(%rbp), %rdi
movq %rdi, %rax
addq $0x10, %rax
movq %rax, -0xa0(%rbp)
addq $0x10, %rdi
callq 0x6930
movq -0xa0(%rbp), %rdi
movq %rax, %rsi
subq $0x1, %rsi
callq 0x9390
movq %rax, %rdi
callq 0x7270
movq %rax, -0x98(%rbp)
movq -0x18(%rbp), %rdi
movslq -0x28(%rbp), %rsi
callq 0x94f0
movq -0x98(%rbp), %rdi
movq %rax, %rsi
movq (%rdi), %rax
callq *0x18(%rax)
movl -0x28(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x28(%rbp)
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x2fdf
movq $0x1, -0x60(%rbp)
movq -0x88(%rbp), %rdi
movq -0x60(%rbp), %rax
movq %rax, -0xb0(%rbp)
addq $0x10, %rdi
callq 0x6930
movq %rax, %rcx
movq -0xb0(%rbp), %rax
cmpq %rcx, %rax
jae 0x319a
movq -0x88(%rbp), %rdi
addq $0x10, %rdi
movq -0x60(%rbp), %rsi
callq 0x9390
movq %rax, %rsi
leaq -0x70(%rbp), %rdi
movq %rdi, -0xb8(%rbp)
callq 0x8980
movq -0xb8(%rbp), %rdi
callq 0x8cb0
movq %rax, %rdi
movq -0x88(%rbp), %rax
movss 0xc(%rax), %xmm0
movq (%rdi), %rax
movq 0x28(%rax), %rax
callq *%rax
jmp 0x3169
leaq -0x70(%rbp), %rdi
callq 0x8d60
movq -0x60(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x60(%rbp)
jmp 0x30f2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x78(%rbp)
movl %eax, -0x7c(%rbp)
leaq -0x70(%rbp), %rdi
callq 0x8d60
jmp 0x31c3
jmp 0x319c
movl -0x30(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x30(%rbp)
jmp 0x2fcc
jmp 0x31ac
movl -0x24(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x24(%rbp)
jmp 0x2f6d
addq $0xc0, %rsp
popq %rbp
retq
movq -0x78(%rbp), %rdi
callq 0x2200
nopl (%rax)