// File: xbai0624[P]dnn/src/ConstructLayer.cpp
// Function: ConstructLayer::GetSigmaSquareFor2DLayer(std::vector<Images, std::allocator<Images>>&, Images&, Images&)
void ConstructLayer::GetSigmaSquareFor2DLayer(std::vector<Images> &source, Images &mu, Images &sigma_square)
{
    // get \sigma_B^2
    // --- 2D layer

    double batch_size = source.size();
    assert(batch_size > 0);
    int nKernel = source[0].OutputImageFromKernel.size();
    assert(nKernel > 0);
    int _n = mu.OutputImageFromKernel.size();
    assert(_n == nKernel);

    auto dim = mu.OutputImageFromKernel[0].Dimension();
    assert(dim.first == 1 && dim.second == 1);

    sigma_square.OutputImageFromKernel.clear();

    for(int i=0;i<nKernel;i++)
    {
        double average = (mu.OutputImageFromKernel[i])[0][0];
        Matrix tmp(dim, 0);
        auto kernel_image_dim = source[0].OutputImageFromKernel[i].Dimension();

        for(int ii=0;ii<(int)batch_size;ii++)
        {
            Matrix diff = source[ii].OutputImageFromKernel[i] - average;
            diff = diff^diff;
            tmp = tmp + diff.SumInSection(0, kernel_image_dim.first, 0, kernel_image_dim.second);
        }

        tmp  = tmp/batch_size / (double)kernel_image_dim.first / (double)kernel_image_dim.second; // = tmp / n / (p x q)
        tmp = tmp * batch_size / (batch_size - 1.0); // Var[x]^2 = E(\sigma)^2 * m / (m-1)

        sigma_square.OutputImageFromKernel.push_back(tmp);
    }
}

// Assembly:
subq $0x188, %rsp            # imm = 0x188
movq %rdi, 0x180(%rsp)
movq %rsi, 0x178(%rsp)
movq %rdx, 0x170(%rsp)
movq %rcx, 0x168(%rsp)
movq 0x178(%rsp), %rdi
callq 0x1ff40
movq %rax, %xmm0
movaps 0x40860(%rip), %xmm1    # 0x52060
punpckldq %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
movapd 0x40864(%rip), %xmm1    # 0x52070
subpd %xmm1, %xmm0
movaps %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm1, %xmm0
movsd %xmm0, 0x160(%rsp)
movsd 0x160(%rsp), %xmm0
xorps %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jbe 0x11838
jmp 0x11857
leaq 0x411d4(%rip), %rdi     # 0x52a13
leaq 0x4098c(%rip), %rsi     # 0x521d2
movl $0x7cc, %edx            # imm = 0x7CC
leaq 0x41263(%rip), %rcx     # 0x52ab5
callq 0x4170
movq 0x178(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x1fd40
movq %rax, %rdi
callq 0x1f9c0
movl %eax, 0x15c(%rsp)
cmpl $0x0, 0x15c(%rsp)
jle 0x11883
jmp 0x118a2
leaq 0x4128c(%rip), %rdi     # 0x52b16
leaq 0x40941(%rip), %rsi     # 0x521d2
movl $0x7ce, %edx            # imm = 0x7CE
leaq 0x41218(%rip), %rcx     # 0x52ab5
callq 0x4170
movq 0x170(%rsp), %rdi
callq 0x1f9c0
movl %eax, 0x158(%rsp)
movl 0x158(%rsp), %eax
cmpl 0x15c(%rsp), %eax
jne 0x118c8
jmp 0x118e7
leaq 0x41253(%rip), %rdi     # 0x52b22
leaq 0x408fc(%rip), %rsi     # 0x521d2
movl $0x7d0, %edx            # imm = 0x7D0
leaq 0x411d3(%rip), %rcx     # 0x52ab5
callq 0x4170
movq 0x170(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x1f9e0
movq %rax, %rdi
callq 0x3bae0
movq %rax, 0x148(%rsp)
movq %rdx, 0x150(%rsp)
xorl %eax, %eax
cmpq $0x1, 0x148(%rsp)
movb %al, 0x2f(%rsp)
jne 0x11931
cmpq $0x1, 0x150(%rsp)
sete %al
movb %al, 0x2f(%rsp)
movb 0x2f(%rsp), %al
testb $0x1, %al
jne 0x1193b
jmp 0x1193d
jmp 0x1195c
leaq 0x411ec(%rip), %rdi     # 0x52b30
leaq 0x40887(%rip), %rsi     # 0x521d2
movl $0x7d3, %edx            # imm = 0x7D3
leaq 0x4115e(%rip), %rcx     # 0x52ab5
callq 0x4170
movq 0x168(%rsp), %rdi
callq 0x1fa00
movl $0x0, 0x144(%rsp)
movl 0x144(%rsp), %eax
cmpl 0x15c(%rsp), %eax
jge 0x11e23
movq 0x170(%rsp), %rdi
movslq 0x144(%rsp), %rsi
callq 0x1f9e0
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
movq %rsi, 0x10(%rsp)
callq 0x3be50
movq 0x10(%rsp), %rsi
movq %rax, %rdi
callq 0x1fd60
movsd (%rax), %xmm0
movsd %xmm0, 0x138(%rsp)
movups 0x148(%rsp), %xmm0
movaps %xmm0, 0x110(%rsp)
movq 0x110(%rsp), %rsi
movq 0x118(%rsp), %rdx
leaq 0x120(%rsp), %rdi
xorps %xmm0, %xmm0
callq 0x3b680
movq 0x10(%rsp), %rsi
movq 0x178(%rsp), %rdi
callq 0x1fd40
movq %rax, %rdi
movslq 0x144(%rsp), %rsi
callq 0x1f9e0
movq %rax, %rdi
callq 0x3bae0
movq %rdx, 0x18(%rsp)
movq %rax, 0x20(%rsp)
jmp 0x11a2e
movq 0x18(%rsp), %rax
movq 0x20(%rsp), %rcx
movq %rcx, 0x100(%rsp)
movq %rax, 0x108(%rsp)
movl $0x0, 0xf0(%rsp)
movl 0xf0(%rsp), %eax
cvttsd2si 0x160(%rsp), %ecx
cmpl %ecx, %eax
jge 0x11bfe
movq 0x178(%rsp), %rdi
movslq 0xf0(%rsp), %rsi
callq 0x1fd40
movq %rax, %rdi
movslq 0x144(%rsp), %rsi
callq 0x1f9e0
movq %rax, %rsi
movsd 0x138(%rsp), %xmm0
leaq 0xd8(%rsp), %rdi
callq 0x3ce60
jmp 0x11aab
leaq 0xc0(%rsp), %rdi
leaq 0xd8(%rsp), %rdx
movq %rdx, %rsi
callq 0x3c680
jmp 0x11ac5
leaq 0xd8(%rsp), %rdi
leaq 0xc0(%rsp), %rsi
callq 0x1fa20
jmp 0x11adc
leaq 0xc0(%rsp), %rdi
callq 0x3bb80
movq 0x100(%rsp), %rdx
movq 0x108(%rsp), %r8
xorl %eax, %eax
movl %eax, %ecx
leaq 0xd8(%rsp), %rdi
movq %rcx, %rsi
callq 0x407f0
movsd %xmm0, 0x8(%rsp)
jmp 0x11b15
movsd 0x8(%rsp), %xmm0
leaq 0xa8(%rsp), %rdi
leaq 0x120(%rsp), %rsi
callq 0x3ca80
jmp 0x11b32
leaq 0x120(%rsp), %rdi
leaq 0xa8(%rsp), %rsi
callq 0x1fa20
jmp 0x11b49
leaq 0xa8(%rsp), %rdi
callq 0x3bb80
leaq 0xd8(%rsp), %rdi
callq 0x3bb80
movl 0xf0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xf0(%rsp)
jmp 0x11a53
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xf8(%rsp)
movl %eax, 0xf4(%rsp)
jmp 0x11e14
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xf8(%rsp)
movl %eax, 0xf4(%rsp)
jmp 0x11bec
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xf8(%rsp)
movl %eax, 0xf4(%rsp)
leaq 0xc0(%rsp), %rdi
callq 0x3bb80
jmp 0x11bec
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xf8(%rsp)
movl %eax, 0xf4(%rsp)
leaq 0xa8(%rsp), %rdi
callq 0x3bb80
leaq 0xd8(%rsp), %rdi
callq 0x3bb80
jmp 0x11e14
movsd 0x160(%rsp), %xmm0
leaq 0x60(%rsp), %rdi
leaq 0x120(%rsp), %rsi
callq 0x3d140
jmp 0x11c1b
movaps 0x4043e(%rip), %xmm1    # 0x52060
movq 0x100(%rsp), %xmm0
punpckldq %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
movapd 0x40439(%rip), %xmm1    # 0x52070
subpd %xmm1, %xmm0
movaps %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm1, %xmm0
leaq 0x78(%rsp), %rdi
leaq 0x60(%rsp), %rsi
callq 0x3d140
jmp 0x11c57
movaps 0x40402(%rip), %xmm1    # 0x52060
movq 0x108(%rsp), %xmm0
punpckldq %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
movapd 0x403fd(%rip), %xmm1    # 0x52070
subpd %xmm1, %xmm0
movaps %xmm0, %xmm1
unpckhpd %xmm0, %xmm0            # xmm0 = xmm0[1,1]
addsd %xmm1, %xmm0
leaq 0x90(%rsp), %rdi
leaq 0x78(%rsp), %rsi
callq 0x3d140
jmp 0x11c96
leaq 0x120(%rsp), %rdi
leaq 0x90(%rsp), %rsi
callq 0x1fa20
jmp 0x11cad
leaq 0x90(%rsp), %rdi
callq 0x3bb80
leaq 0x78(%rsp), %rdi
callq 0x3bb80
leaq 0x60(%rsp), %rdi
callq 0x3bb80
movsd 0x160(%rsp), %xmm0
leaq 0x30(%rsp), %rdi
leaq 0x120(%rsp), %rsi
callq 0x3cfd0
jmp 0x11ceb
movsd 0x160(%rsp), %xmm0
movsd 0x4032c(%rip), %xmm1    # 0x52028
addsd %xmm1, %xmm0
leaq 0x48(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0x3d140
jmp 0x11d11
leaq 0x120(%rsp), %rdi
leaq 0x48(%rsp), %rsi
callq 0x1fa20
jmp 0x11d25
leaq 0x48(%rsp), %rdi
callq 0x3bb80
leaq 0x30(%rsp), %rdi
callq 0x3bb80
movq 0x168(%rsp), %rdi
leaq 0x120(%rsp), %rsi
callq 0x1fa50
jmp 0x11d50
leaq 0x120(%rsp), %rdi
callq 0x3bb80
movl 0x144(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x144(%rsp)
jmp 0x11974
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xf8(%rsp)
movl %eax, 0xf4(%rsp)
jmp 0x11dca
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xf8(%rsp)
movl %eax, 0xf4(%rsp)
jmp 0x11dc0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xf8(%rsp)
movl %eax, 0xf4(%rsp)
leaq 0x90(%rsp), %rdi
callq 0x3bb80
leaq 0x78(%rsp), %rdi
callq 0x3bb80
leaq 0x60(%rsp), %rdi
callq 0x3bb80
jmp 0x11e14
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xf8(%rsp)
movl %eax, 0xf4(%rsp)
jmp 0x11e0a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xf8(%rsp)
movl %eax, 0xf4(%rsp)
leaq 0x48(%rsp), %rdi
callq 0x3bb80
leaq 0x30(%rsp), %rdi
callq 0x3bb80
leaq 0x120(%rsp), %rdi
callq 0x3bb80
jmp 0x11e2b
addq $0x188, %rsp            # imm = 0x188
retq
movq 0xf8(%rsp), %rdi
callq 0x43f0
nopl (%rax,%rax)