// File: /workspace/github_cpp_makefile_star2_O2/btbujiangjun[P]abcdl/src/cnn/Layer.cpp
// Function: abcdl::cnn::ConvolutionLayer::backward(abcdl::cnn::Layer*, abcdl::cnn::Layer*)
void ConvolutionLayer::backward(Layer* pre_layer, Layer* back_layer){
    if(back_layer->get_layer_type() == abcdl::framework::OUTPUT){
        size_t size = this->_rows * this->_cols;
        real*  data = back_layer->get_delta(0).data();
        abcdl::algebra::Mat delta(this->_rows, this->_cols);
        
        //recover multiply mat
        for(size_t i = 0; i != this->_out_channel_size; i++){
            memcpy(delta.data(), &data[i * size], sizeof(real) * size);
            this->set_delta(i, delta);
        }
    }else if(back_layer->get_layer_type() == abcdl::framework::SUBSAMPLING){
        SubSamplingLayer* sub_layer = (SubSamplingLayer*)back_layer;
        size_t scale = sub_layer->get_scale();
        abcdl::algebra::Mat delta;
        abcdl::algebra::Mat back_delta;
        for(size_t i = 0; i != this->_out_channel_size; i++){
            _activate_func->derivative(delta, this->get_activation(i));
            back_delta = back_layer->get_delta(i);
            //subsampling layer reduced matrix dim, so recover it by expand function
            back_delta.expand(scale, scale);
            //back layer error sharing
            back_delta /= scale * scale;
            //delta_l = derivative_sigmoid * delta_l+1(recover dim)
            delta *= back_delta;

            this->set_delta(i, delta);
	    }
    }

    for(size_t i = 0; i != this->_out_channel_size; i++){
        abcdl::algebra::Mat weight;
        for(size_t j = 0; j != pre_layer->get_out_channel_size(); j++){
            _helper.convn(weight, pre_layer->get_activation(j), this->get_delta(i), _stride, abcdl::algebra::VALID);
            this->set_delta_weight(j, i, weight);
            this->set_batch_weight(j, i, weight);
        }

        this->_delta_bias->set_data(this->get_delta(i).sum(), i, 0);
    }
    this->_batch_bias->operator+=(*this->_delta_bias);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78, %rsp
movq %rsi, %r14
movq %rdi, %rbx
movq %rdx, 0x10(%rsp)
movl 0x28(%rdx), %eax
cmpl $0x2, %eax
movq %rsi, 0x20(%rsp)
je 0x13044
cmpl $0x4, %eax
jne 0x13143
movq 0x10(%rbx), %r15
imulq 0x8(%rbx), %r15
xorl %r12d, %r12d
movq 0x10(%rsp), %rdi
xorl %esi, %esi
callq 0x1396a
movq 0x10(%rax), %r13
movq 0x8(%rbx), %rsi
movq 0x10(%rbx), %rdx
leaq 0x28(%rsp), %rbp
movq %rbp, %rdi
callq 0x165ea
shlq $0x2, %r15
cmpq 0x20(%rbx), %r12
je 0x13139
movq 0x38(%rsp), %rdi
movq %r13, %rsi
movq %r15, %rdx
callq 0x8250
movq %rbx, %rdi
movq %r12, %rsi
movq %rbp, %rdx
callq 0x139f8
incq %r12
addq %r15, %r13
jmp 0x13014
movq 0x10(%rsp), %rax
movq 0xd0(%rax), %r12
leaq 0x28(%rsp), %rdi
callq 0x165d0
leaq 0x50(%rsp), %rdi
callq 0x165d0
movq %r12, %rax
imulq %r12, %rax
testq %rax, %rax
js 0x13077
cvtsi2ss %rax, %xmm0
jmp 0x1308c
movq %rax, %rcx
shrq %rcx
andl $0x1, %eax
orq %rcx, %rax
cvtsi2ss %rax, %xmm0
addss %xmm0, %xmm0
movss %xmm0, 0xc(%rsp)
xorl %r13d, %r13d
leaq 0x28(%rsp), %rbp
leaq 0x50(%rsp), %r15
cmpq 0x20(%rbx), %r13
je 0x1312f
movq 0xe0(%rbx), %r14
movq %rbx, %rdi
movq %r13, %rsi
callq 0x13864
movq (%r14), %rcx
movq %r14, %rdi
movq %rbp, %rsi
movq %rax, %rdx
callq *0x18(%rcx)
movq 0x10(%rsp), %rdi
movq %r13, %rsi
callq 0x1396a
movq %r15, %rdi
movq %rax, %rsi
callq 0x1c67e
movq %r15, %rdi
movq %r12, %rsi
movq %r12, %rdx
callq 0x225c2
movss 0xc(%rsp), %xmm0
movss %xmm0, 0x1c(%rsp)
movq %r15, %rdi
leaq 0x1c(%rsp), %rsi
callq 0x1d684
movq %rbp, %rdi
movq %r15, %rsi
callq 0x1d21c
movq %rbx, %rdi
movq %r13, %rsi
movq %rbp, %rdx
callq 0x139f8
incq %r13
movq 0x20(%rsp), %r14
jmp 0x1309f
leaq 0x50(%rsp), %rdi
callq 0x167fa
leaq 0x28(%rsp), %rdi
callq 0x167fa
leaq 0x30(%rbx), %r15
xorl %r12d, %r12d
leaq 0x28(%rsp), %r13
cmpq 0x20(%rbx), %r12
je 0x1320c
movq %r13, %rdi
callq 0x165d0
xorl %ebp, %ebp
cmpq 0x20(%r14), %rbp
je 0x131ca
movq %r14, %rdi
movq %rbp, %rsi
callq 0x13864
movq %rax, %r14
movq %rbx, %rdi
movq %r12, %rsi
callq 0x1396a
movq 0xd0(%rbx), %r8
movq %r15, %rdi
movq %r13, %rsi
movq %r14, %rdx
movq %rax, %rcx
pushq $0x1
popq %r9
callq 0x27698
movq %rbx, %rdi
movq %rbp, %rsi
movq %r12, %rdx
movq %r13, %rcx
callq 0x13c22
movq %rbx, %rdi
movq %rbp, %rsi
movq %r12, %rdx
movq %r13, %rcx
callq 0x13cc4
incq %rbp
movq 0x20(%rsp), %r14
jmp 0x13163
movq 0x90(%rbx), %rbp
movq %rbx, %rdi
movq %r12, %rsi
callq 0x1396a
movq %rax, %rdi
callq 0x22a68
movss %xmm0, 0x50(%rsp)
movq %rbp, %rdi
leaq 0x50(%rsp), %rsi
movq %r12, %rdx
xorl %ecx, %ecx
callq 0x13d6a
movq %r13, %rdi
callq 0x167fa
incq %r12
jmp 0x1314f
movq 0x90(%rbx), %rsi
movq 0xb0(%rbx), %rdi
callq 0x1c9c4
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x13245
jmp 0x13234
jmp 0x13245
movq %rax, %rbx
leaq 0x50(%rsp), %rdi
callq 0x167fa
jmp 0x13248
jmp 0x13245
movq %rax, %rbx
leaq 0x28(%rsp), %rdi
callq 0x167fa
movq %rbx, %rdi
callq 0x84f0