// File: /workspace/github_cpp_makefile_star2_O3/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 $0x1c8, %rsp            # imm = 0x1C8
movq %rsi, %r14
movq %rdi, %rbx
movq %rdx, 0x8(%rsp)
movl 0x28(%rdx), %eax
cmpl $0x2, %eax
je 0x144a6
cmpl $0x4, %eax
jne 0x145a8
movq 0x10(%rbx), %r15
imulq 0x8(%rbx), %r15
movq 0x8(%rsp), %rdi
xorl %esi, %esi
callq 0x151aa
movq 0x10(%rax), %r12
movq 0x8(%rbx), %rsi
movq 0x10(%rbx), %rdx
leaq 0x40(%rsp), %rdi
callq 0x181d6
cmpq $0x0, 0x20(%rbx)
je 0x1459e
shlq $0x2, %r15
xorl %r13d, %r13d
leaq 0x40(%rsp), %rbp
movq 0x50(%rsp), %rdi
movq %r12, %rsi
movq %r15, %rdx
callq 0x8270
movq %rbx, %rdi
movq %r13, %rsi
movq %rbp, %rdx
callq 0x15242
incq %r13
addq %r15, %r12
cmpq 0x20(%rbx), %r13
jne 0x14477
jmp 0x1459e
movq 0x8(%rsp), %rax
movq 0xd0(%rax), %r12
leaq 0x40(%rsp), %rdi
callq 0x181b8
leaq 0x18(%rsp), %rdi
callq 0x181b8
cmpq $0x0, 0x20(%rbx)
je 0x14594
movq %r12, %rax
imulq %r12, %rax
testq %rax, %rax
js 0x144e4
cvtsi2ss %rax, %xmm0
jmp 0x144f9
movq %rax, %rcx
shrq %rcx
andl $0x1, %eax
orq %rcx, %rax
cvtsi2ss %rax, %xmm0
addss %xmm0, %xmm0
movss %xmm0, 0x4(%rsp)
xorl %r13d, %r13d
leaq 0x18(%rsp), %r15
movq 0xe0(%rbx), %rbp
movq %rbx, %rdi
movq %r13, %rsi
callq 0x15092
movq (%rbp), %rcx
movq %rbp, %rdi
leaq 0x40(%rsp), %rsi
movq %rax, %rdx
callq *0x18(%rcx)
movq 0x8(%rsp), %rdi
movq %r13, %rsi
callq 0x151aa
movq %r15, %rdi
movq %rax, %rsi
callq 0x1fe8e
movq %r15, %rdi
movq %r12, %rsi
movq %r12, %rdx
callq 0x294fc
movss 0x4(%rsp), %xmm0
movss %xmm0, 0x14(%rsp)
movq %r15, %rdi
leaq 0x14(%rsp), %rsi
callq 0x219f0
leaq 0x40(%rsp), %rdi
movq %r15, %rsi
callq 0x2128a
movq %rbx, %rdi
movq %r13, %rsi
leaq 0x40(%rsp), %rdx
callq 0x15242
incq %r13
cmpq 0x20(%rbx), %r13
jne 0x14507
leaq 0x18(%rsp), %rdi
callq 0x1840e
leaq 0x40(%rsp), %rdi
callq 0x1840e
cmpq $0x0, 0x20(%rbx)
je 0x14796
leaq 0x30(%rbx), %rax
movq %rax, 0x8(%rsp)
xorl %r12d, %r12d
leaq 0x18(%rsp), %r13
movq %r13, %rdi
callq 0x181b8
cmpq $0x0, 0x20(%r14)
je 0x146ff
xorl %ebp, %ebp
movq %r14, %rdi
movq %rbp, %rsi
callq 0x15092
movq %rax, %r15
movq %rbx, %rdi
movq %r12, %rsi
callq 0x151aa
movq 0xd0(%rbx), %r8
movq 0x8(%rsp), %rdi
movq %r13, %rsi
movq %r15, %rdx
movq %rax, %rcx
movl $0x1, %r9d
callq 0x3047a
cmpq %rbp, 0x18(%rbx)
jbe 0x14675
movq 0x20(%rbx), %rax
cmpq %r12, %rax
jbe 0x14675
imulq %rbp, %rax
shlq $0x3, %rax
addq 0x78(%rbx), %rax
movq (%rax,%r12,8), %rdi
movq %r13, %rsi
callq 0x1fe8e
cmpq %rbp, 0x18(%rbx)
jbe 0x146ba
movq 0x20(%rbx), %rax
cmpq %r12, %rax
jbe 0x146ba
imulq %rbp, %rax
shlq $0x3, %rax
addq 0x98(%rbx), %rax
movq (%rax,%r12,8), %rdi
movq %r13, %rsi
callq 0x20394
incq %rbp
cmpq 0x20(%r14), %rbp
jne 0x145d9
jmp 0x146ff
leaq 0x40(%rsp), %rdi
leaq 0x257b7(%rip), %rsi     # 0x39e38
movl $0x62, %edx
movl $0x3, %ecx
callq 0x37222
movl $0x54, %edx
leaq 0x40(%rsp), %r15
movq %r15, %rdi
leaq 0x2583b(%rip), %rsi     # 0x39edf
callq 0x8350
movq %r15, %rdi
callq 0x3744a
movq 0x20(%rbx), %rax
jmp 0x14621
leaq 0x40(%rsp), %rdi
leaq 0x25772(%rip), %rsi     # 0x39e38
movl $0x6f, %edx
movl $0x3, %ecx
callq 0x37222
movl $0x54, %edx
leaq 0x40(%rsp), %r15
movq %r15, %rdi
leaq 0x257f6(%rip), %rsi     # 0x39edf
callq 0x8350
movq %r15, %rdi
callq 0x3744a
movq 0x20(%rbx), %rax
jmp 0x14648
movq 0x90(%rbx), %r15
movq %rbx, %rdi
movq %r12, %rsi
callq 0x151aa
movq %rax, %rdi
callq 0x29bb0
movss %xmm0, 0x4(%rsp)
movq 0x8(%r15), %rax
movq %rax, %rbp
imulq %r12, %rbp
imulq (%r15), %rax
cmpq %rax, %rbp
jae 0x14759
movq 0x10(%r15), %rax
movss 0x4(%rsp), %xmm0
movss %xmm0, (%rax,%rbp,4)
movq %r13, %rdi
callq 0x1840e
incq %r12
cmpq 0x20(%rbx), %r12
jne 0x145c4
jmp 0x14796
leaq 0x40(%rsp), %rdi
leaq 0x257df(%rip), %rsi     # 0x39f44
movl $0x50, %edx
movl $0x3, %ecx
callq 0x37222
movl $0x1f, %edx
leaq 0x40(%rsp), %rdi
leaq 0x257d8(%rip), %rsi     # 0x39f5d
callq 0x8350
leaq 0x40(%rsp), %rdi
callq 0x3744a
jmp 0x14733
movq 0x90(%rbx), %rsi
movq 0xb0(%rbx), %rdi
callq 0x20394
addq $0x1c8, %rsp            # imm = 0x1C8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x147bf
jmp 0x147bf
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
callq 0x3744a
jmp 0x147f0
jmp 0x147d2
jmp 0x147d9
movq %rax, %rbx
jmp 0x147e6
jmp 0x147ed
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
callq 0x1840e
leaq 0x40(%rsp), %rdi
jmp 0x147f5
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
callq 0x1840e
movq %rbx, %rdi
callq 0x8500