// File: btbujiangjun[P]abcdl/src/fnn/Layer.cpp
// Function: abcdl::fnn::FullConnLayer::backward(abcdl::fnn::Layer*, abcdl::fnn::Layer*)
void FullConnLayer::backward(Layer* pre_layer, Layer* next_layer){
    //δ_l = ( (w_l+1).T .* δ_l+1 ) * Derivative(a_l)
    abcdl::algebra::Mat activate_derivative;
    _activate_func->derivative(activate_derivative, this->_activate_data);
    _delta_bias   = _helper.dot(next_layer->get_delta_bias(), next_layer->get_weight().Ts()) * activate_derivative;

    /*
     * Derivative(Cw) = a_in * δ_out
     * a_in = a_l-1, δ_out = mat
     * activations include input layer, so l-1 is i.
     */
    this->_delta_weight   = _helper.dot(pre_layer->get_activate_data().Ts(), this->_delta_bias);

    this->_batch_bias     += this->_delta_bias;
    this->_batch_weight   += this->_delta_weight;
}

// Assembly:
subq $0x158, %rsp            # imm = 0x158
movq %rdi, 0x150(%rsp)
movq %rsi, 0x148(%rsp)
movq %rdx, 0x140(%rsp)
movq 0x150(%rsp), %rax
movq %rax, 0x30(%rsp)
leaq 0x118(%rsp), %rdi
movq %rdi, 0x38(%rsp)
callq 0x33a40
movq 0x30(%rsp), %rdx
movq 0x38(%rsp), %rsi
movq 0x168(%rdx), %rdi
addq $0xa0, %rdx
movq (%rdi), %rax
movq 0x18(%rax), %rax
callq *%rax
jmp 0x271a1
movq 0x30(%rsp), %rax
addq $0x20, %rax
movq %rax, 0x20(%rsp)
movq 0x140(%rsp), %rdi
callq 0x27c30
movq %rax, 0x28(%rsp)
jmp 0x271c3
movq 0x140(%rsp), %rdi
callq 0x27c50
movq %rax, 0x18(%rsp)
jmp 0x271d7
movq 0x18(%rsp), %rsi
leaq 0x90(%rsp), %rdi
callq 0x35830
jmp 0x271eb
movq 0x28(%rsp), %rdx
movq 0x20(%rsp), %rsi
leaq 0xb8(%rsp), %rdi
leaq 0x90(%rsp), %rcx
callq 0x6a250
jmp 0x2720c
leaq 0xe0(%rsp), %rdi
leaq 0xb8(%rsp), %rsi
leaq 0x118(%rsp), %rdx
callq 0x443f0
jmp 0x2722b
movq 0x30(%rsp), %rdi
addq $0xf0, %rdi
leaq 0xe0(%rsp), %rsi
callq 0x429a0
jmp 0x27246
leaq 0xe0(%rsp), %rdi
callq 0x33e80
leaq 0xb8(%rsp), %rdi
callq 0x33e80
leaq 0x90(%rsp), %rdi
callq 0x33e80
movq 0x30(%rsp), %rax
addq $0x20, %rax
movq %rax, 0x8(%rsp)
movq 0x148(%rsp), %rdi
callq 0x27c10
movq %rax, 0x10(%rsp)
jmp 0x2728f
movq 0x10(%rsp), %rsi
leaq 0x40(%rsp), %rdi
callq 0x35830
jmp 0x272a0
movq 0x8(%rsp), %rsi
movq 0x30(%rsp), %rcx
addq $0xf0, %rcx
leaq 0x68(%rsp), %rdi
leaq 0x40(%rsp), %rdx
callq 0x6a250
jmp 0x272c2
movq 0x30(%rsp), %rdi
addq $0xc8, %rdi
leaq 0x68(%rsp), %rsi
callq 0x429a0
jmp 0x272da
leaq 0x68(%rsp), %rdi
callq 0x33e80
leaq 0x40(%rsp), %rdi
callq 0x33e80
movq 0x30(%rsp), %rdi
movq %rdi, %rsi
addq $0xf0, %rsi
addq $0x140, %rdi            # imm = 0x140
callq 0x432b0
jmp 0x2730b
movq 0x30(%rsp), %rdi
movq %rdi, %rsi
addq $0xc8, %rsi
addq $0x118, %rdi            # imm = 0x118
callq 0x432b0
jmp 0x27328
leaq 0x118(%rsp), %rdi
callq 0x33e80
addq $0x158, %rsp            # imm = 0x158
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x110(%rsp)
movl %eax, 0x10c(%rsp)
jmp 0x273fd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x110(%rsp)
movl %eax, 0x10c(%rsp)
jmp 0x273b0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x110(%rsp)
movl %eax, 0x10c(%rsp)
jmp 0x273a3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x110(%rsp)
movl %eax, 0x10c(%rsp)
leaq 0xe0(%rsp), %rdi
callq 0x33e80
leaq 0xb8(%rsp), %rdi
callq 0x33e80
leaq 0x90(%rsp), %rdi
callq 0x33e80
jmp 0x273fd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x110(%rsp)
movl %eax, 0x10c(%rsp)
jmp 0x273f3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x110(%rsp)
movl %eax, 0x10c(%rsp)
leaq 0x68(%rsp), %rdi
callq 0x33e80
leaq 0x40(%rsp), %rdi
callq 0x33e80
leaq 0x118(%rsp), %rdi
callq 0x33e80
movq 0x110(%rsp), %rdi
callq 0x9700
nopw (%rax,%rax)