// File: /workspace/github_cpp_makefile_star2_O1/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 0x1473c
cmpl $0x4, %eax
jne 0x1483e
movq 0x10(%rbx), %r15
imulq 0x8(%rbx), %r15
movq 0x8(%rsp), %rdi
xorl %esi, %esi
callq 0x1543e
movq 0x10(%rax), %r12
movq 0x8(%rbx), %rsi
movq 0x10(%rbx), %rdx
leaq 0x40(%rsp), %rdi
callq 0x1845e
cmpq $0x0, 0x20(%rbx)
je 0x14834
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 0x154d2
incq %r13
addq %r15, %r12
cmpq 0x20(%rbx), %r13
jne 0x1470d
jmp 0x14834
movq 0x8(%rsp), %rax
movq 0xd0(%rax), %r12
leaq 0x40(%rsp), %rdi
callq 0x18440
leaq 0x18(%rsp), %rdi
callq 0x18440
cmpq $0x0, 0x20(%rbx)
je 0x1482a
movq %r12, %rax
imulq %r12, %rax
testq %rax, %rax
js 0x1477a
cvtsi2ss %rax, %xmm0
jmp 0x1478f
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 0x15328
movq (%rbp), %rcx
movq %rbp, %rdi
leaq 0x40(%rsp), %rsi
movq %rax, %rdx
callq *0x18(%rcx)
movq 0x8(%rsp), %rdi
movq %r13, %rsi
callq 0x1543e
movq %r15, %rdi
movq %rax, %rsi
callq 0x20172
movq %r15, %rdi
movq %r12, %rsi
movq %r12, %rdx
callq 0x29672
movss 0x4(%rsp), %xmm0
movss %xmm0, 0x14(%rsp)
movq %r15, %rdi
leaq 0x14(%rsp), %rsi
callq 0x21c64
leaq 0x40(%rsp), %rdi
movq %r15, %rsi
callq 0x2151a
movq %rbx, %rdi
movq %r13, %rsi
leaq 0x40(%rsp), %rdx
callq 0x154d2
incq %r13
cmpq 0x20(%rbx), %r13
jne 0x1479d
leaq 0x18(%rsp), %rdi
callq 0x18696
leaq 0x40(%rsp), %rdi
callq 0x18696
cmpq $0x0, 0x20(%rbx)
je 0x14a26
leaq 0x30(%rbx), %rax
movq %rax, 0x8(%rsp)
xorl %r12d, %r12d
leaq 0x18(%rsp), %r13
movq %r13, %rdi
callq 0x18440
cmpq $0x0, 0x20(%r14)
je 0x1498f
xorl %ebp, %ebp
movq %r14, %rdi
movq %rbp, %rsi
callq 0x15328
movq %rax, %r15
movq %rbx, %rdi
movq %r12, %rsi
callq 0x1543e
movq 0xd0(%rbx), %r8
movq 0x8(%rsp), %rdi
movq %r13, %rsi
movq %r15, %rdx
movq %rax, %rcx
movl $0x1, %r9d
callq 0x3067e
cmpq %rbp, 0x18(%rbx)
jbe 0x1490d
cmpq %r12, 0x20(%rbx)
jbe 0x1490d
movq 0x20(%rbx), %rax
imulq %rbp, %rax
shlq $0x3, %rax
addq 0x78(%rbx), %rax
movq (%rax,%r12,8), %rdi
movq %r13, %rsi
callq 0x20172
cmpq %rbp, 0x18(%rbx)
jbe 0x1494e
cmpq %r12, 0x20(%rbx)
jbe 0x1494e
movq 0x20(%rbx), %rax
imulq %rbp, %rax
shlq $0x3, %rax
addq 0x98(%rbx), %rax
movq (%rax,%r12,8), %rdi
movq %r13, %rsi
callq 0x20660
incq %rbp
cmpq 0x20(%r14), %rbp
jne 0x1486f
jmp 0x1498f
leaq 0x40(%rsp), %rdi
leaq 0x2551f(%rip), %rsi     # 0x39e38
movl $0x62, %edx
movl $0x3, %ecx
callq 0x373d6
movl $0x54, %edx
leaq 0x40(%rsp), %r15
movq %r15, %rdi
leaq 0x255a3(%rip), %rsi     # 0x39edf
callq 0x8350
movq %r15, %rdi
callq 0x375fe
jmp 0x148b4
leaq 0x40(%rsp), %rdi
leaq 0x254de(%rip), %rsi     # 0x39e38
movl $0x6f, %edx
movl $0x3, %ecx
callq 0x373d6
movl $0x54, %edx
leaq 0x40(%rsp), %r15
movq %r15, %rdi
leaq 0x25562(%rip), %rsi     # 0x39edf
callq 0x8350
movq %r15, %rdi
callq 0x375fe
jmp 0x148dc
movq 0x90(%rbx), %r15
movq %rbx, %rdi
movq %r12, %rsi
callq 0x1543e
movq %rax, %rdi
callq 0x29d20
movss %xmm0, 0x4(%rsp)
movq 0x8(%r15), %rax
movq %rax, %rbp
imulq %r12, %rbp
imulq (%r15), %rax
cmpq %rax, %rbp
jae 0x149e9
movq 0x10(%r15), %rax
movss 0x4(%rsp), %xmm0
movss %xmm0, (%rax,%rbp,4)
movq %r13, %rdi
callq 0x18696
incq %r12
cmpq 0x20(%rbx), %r12
jne 0x1485a
jmp 0x14a26
leaq 0x40(%rsp), %rdi
leaq 0x2554f(%rip), %rsi     # 0x39f44
movl $0x50, %edx
movl $0x3, %ecx
callq 0x373d6
movl $0x1f, %edx
leaq 0x40(%rsp), %rdi
leaq 0x25548(%rip), %rsi     # 0x39f5d
callq 0x8350
leaq 0x40(%rsp), %rdi
callq 0x375fe
jmp 0x149c3
movq 0x90(%rbx), %rsi
movq 0xb0(%rbx), %rdi
callq 0x20660
addq $0x1c8, %rsp            # imm = 0x1C8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
jmp 0x14a4f
jmp 0x14a4f
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
callq 0x375fe
jmp 0x14a80
jmp 0x14a62
jmp 0x14a69
movq %rax, %rbx
jmp 0x14a76
jmp 0x14a7d
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
callq 0x18696
leaq 0x40(%rsp), %rdi
jmp 0x14a85
movq %rax, %rbx
leaq 0x18(%rsp), %rdi
callq 0x18696
movq %rbx, %rdi
callq 0x8500