// File: /workspace/github_c_makefile_star2_O0/jonof[P]jftekwar/jfbuild/libsquish/squish.cpp
// Function: squish::ComputeBlockWMSE(unsigned char const*, unsigned char const*, unsigned int, unsigned int, double&, double&)
static void ComputeBlockWMSE(u8 const *original, u8 const *compressed, unsigned int w, unsigned int h, double &cmse, double &amse)
{
    // Computes the MSE for the block and weights it by the variance of the original block.
    // If the variance of the original block is less than 4 (i.e. a standard deviation of 1 per channel)
    // then the block is close to being a single colour. Quantisation errors in single colour blocks
    // are easier to see than similar errors in blocks that contain more colours, particularly when there
    // are many such blocks in a large area (eg a blue sky background) as they cause banding.  Given that
    // banding is easier to see than small errors in "complex" blocks, we weight the errors by a factor
    // of 5. This implies that images with large, single colour areas will have a higher potential WMSE
    // than images with lots of detail.

    cmse = amse = 0;
    unsigned int sum_p[4];  // per channel sum of pixels
    unsigned int sum_p2[4]; // per channel sum of pixels squared
    memset(sum_p, 0, sizeof(sum_p));
    memset(sum_p2, 0, sizeof(sum_p2));
    for( unsigned int py = 0; py < 4; ++py )
    {
        for( unsigned int px = 0; px < 4; ++px )
        {
            if( px < w && py < h )
            {
                double pixelCMSE = 0;
                for( int i = 0; i < 3; ++i )
                {
                    pixelCMSE += ErrorSq(original[i], compressed[i]);
                    sum_p[i] += original[i];
                    sum_p2[i] += (unsigned int)original[i]*original[i];
                }
                if( original[3] == 0 && compressed[3] == 0 )
                    pixelCMSE = 0; // transparent in both, so colour is inconsequential
                amse += ErrorSq(original[3], compressed[3]);
                cmse += pixelCMSE;
                sum_p[3] += original[3];
                sum_p2[3] += (unsigned int)original[3]*original[3];
            }
            original += 4;
            compressed += 4;
        }
    }
    unsigned int variance = 0;
    for( int i = 0; i < 4; ++i )
        variance += w*h*sum_p2[i] - sum_p[i]*sum_p[i];
    if( variance < 4 * w * w * h * h )
    {
        amse *= 5;
        cmse *= 5;
    }
}

// Assembly:
subq $0x68, %rsp
movq %rdi, 0x60(%rsp)
movq %rsi, 0x58(%rsp)
movl %edx, 0x54(%rsp)
movl %ecx, 0x50(%rsp)
movq %r8, 0x48(%rsp)
movq %r9, 0x40(%rsp)
movq 0x40(%rsp), %rax
xorps %xmm0, %xmm0
movsd %xmm0, (%rax)
movq 0x48(%rsp), %rax
xorps %xmm0, %xmm0
movsd %xmm0, (%rax)
leaq 0x30(%rsp), %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0x62d0
leaq 0x20(%rsp), %rdi
xorl %esi, %esi
movl $0x10, %edx
callq 0x62d0
movl $0x0, 0x1c(%rsp)
cmpl $0x4, 0x1c(%rsp)
jae 0xa429f
movl $0x0, 0x18(%rsp)
cmpl $0x4, 0x18(%rsp)
jae 0xa428d
movl 0x18(%rsp), %eax
cmpl 0x54(%rsp), %eax
jae 0xa4261
movl 0x1c(%rsp), %eax
cmpl 0x50(%rsp), %eax
jae 0xa4261
xorps %xmm0, %xmm0
movsd %xmm0, 0x10(%rsp)
movl $0x0, 0xc(%rsp)
cmpl $0x3, 0xc(%rsp)
jge 0xa41cf
movq 0x60(%rsp), %rax
movslq 0xc(%rsp), %rcx
movzbl (%rax,%rcx), %eax
cvtsi2sd %eax, %xmm0
movq 0x58(%rsp), %rax
movzbl (%rax,%rcx), %eax
cvtsi2sd %eax, %xmm1
callq 0xa43a0
addsd 0x10(%rsp), %xmm0
movsd %xmm0, 0x10(%rsp)
movq 0x60(%rsp), %rax
movslq 0xc(%rsp), %rcx
movzbl (%rax,%rcx), %ecx
movslq 0xc(%rsp), %rax
addl 0x30(%rsp,%rax,4), %ecx
movl %ecx, 0x30(%rsp,%rax,4)
movq 0x60(%rsp), %rax
movslq 0xc(%rsp), %rcx
movzbl (%rax,%rcx), %ecx
movq 0x60(%rsp), %rax
movslq 0xc(%rsp), %rdx
movzbl (%rax,%rdx), %eax
imull %eax, %ecx
movslq 0xc(%rsp), %rax
addl 0x20(%rsp,%rax,4), %ecx
movl %ecx, 0x20(%rsp,%rax,4)
movl 0xc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xc(%rsp)
jmp 0xa413d
movq 0x60(%rsp), %rax
movzbl 0x3(%rax), %eax
cmpl $0x0, %eax
jne 0xa41f4
movq 0x58(%rsp), %rax
movzbl 0x3(%rax), %eax
cmpl $0x0, %eax
jne 0xa41f4
xorps %xmm0, %xmm0
movsd %xmm0, 0x10(%rsp)
movq 0x60(%rsp), %rax
movzbl 0x3(%rax), %eax
cvtsi2sd %eax, %xmm0
movq 0x58(%rsp), %rax
movzbl 0x3(%rax), %eax
cvtsi2sd %eax, %xmm1
callq 0xa43a0
movq 0x40(%rsp), %rax
addsd (%rax), %xmm0
movsd %xmm0, (%rax)
movsd 0x10(%rsp), %xmm0
movq 0x48(%rsp), %rax
addsd (%rax), %xmm0
movsd %xmm0, (%rax)
movq 0x60(%rsp), %rax
movzbl 0x3(%rax), %eax
addl 0x3c(%rsp), %eax
movl %eax, 0x3c(%rsp)
movq 0x60(%rsp), %rax
movzbl 0x3(%rax), %eax
movq 0x60(%rsp), %rcx
movzbl 0x3(%rcx), %ecx
imull %ecx, %eax
addl 0x2c(%rsp), %eax
movl %eax, 0x2c(%rsp)
movq 0x60(%rsp), %rax
addq $0x4, %rax
movq %rax, 0x60(%rsp)
movq 0x58(%rsp), %rax
addq $0x4, %rax
movq %rax, 0x58(%rsp)
movl 0x18(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x18(%rsp)
jmp 0xa4105
jmp 0xa428f
movl 0x1c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1c(%rsp)
jmp 0xa40f2
movl $0x0, 0x8(%rsp)
movl $0x0, 0x4(%rsp)
cmpl $0x4, 0x4(%rsp)
jge 0xa42f3
movl 0x54(%rsp), %eax
imull 0x50(%rsp), %eax
movslq 0x4(%rsp), %rcx
imull 0x20(%rsp,%rcx,4), %eax
movslq 0x4(%rsp), %rcx
movl 0x30(%rsp,%rcx,4), %ecx
movslq 0x4(%rsp), %rdx
imull 0x30(%rsp,%rdx,4), %ecx
subl %ecx, %eax
addl 0x8(%rsp), %eax
movl %eax, 0x8(%rsp)
movl 0x4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4(%rsp)
jmp 0xa42af
movl 0x8(%rsp), %eax
movl 0x54(%rsp), %ecx
shll $0x2, %ecx
imull 0x54(%rsp), %ecx
imull 0x50(%rsp), %ecx
imull 0x50(%rsp), %ecx
cmpl %ecx, %eax
jae 0xa433b
movq 0x40(%rsp), %rax
movsd 0x1629a(%rip), %xmm0    # 0xba5b8
mulsd (%rax), %xmm0
movsd %xmm0, (%rax)
movq 0x48(%rsp), %rax
movsd 0x16285(%rip), %xmm0    # 0xba5b8
mulsd (%rax), %xmm0
movsd %xmm0, (%rax)
addq $0x68, %rsp
retq