// File: /workspace/github_c_makefile_star2_O3/jonof[P]jftekwar/jfbuild/src/rg_etc1.cpp
// Function: rg_etc1::etc1_optimizer::compute()
bool etc1_optimizer::compute()
   {
      const uint n = m_pParams->m_num_src_pixels;
      const int scan_delta_size = m_pParams->m_scan_delta_size;
      
      // Scan through a subset of the 3D lattice centered around the avg block color trying each 3D (555 or 444) lattice point as a potential block color.
      // Each time a better solution is found try to refine the current solution's block color based of the current selectors and intensity table index.
      for (int zdi = 0; zdi < scan_delta_size; zdi++)
      {
         const int zd = m_pParams->m_pScan_deltas[zdi];
         const int mbb = m_bb + zd;
         if (mbb < 0) continue; else if (mbb > m_limit) break;
         
         for (int ydi = 0; ydi < scan_delta_size; ydi++)
         {
            const int yd = m_pParams->m_pScan_deltas[ydi];
            const int mbg = m_bg + yd;
            if (mbg < 0) continue; else if (mbg > m_limit) break;

            for (int xdi = 0; xdi < scan_delta_size; xdi++)
            {
               const int xd = m_pParams->m_pScan_deltas[xdi];
               const int mbr = m_br + xd;
               if (mbr < 0) continue; else if (mbr > m_limit) break;
      
               etc1_solution_coordinates coords(mbr, mbg, mbb, 0, m_pParams->m_use_color4);
               if (m_pParams->m_quality == cHighQuality)
               {
                  if (!evaluate_solution(coords, m_trial_solution, &m_best_solution))
                     continue;
               }
               else
               {
                  if (!evaluate_solution_fast(coords, m_trial_solution, &m_best_solution))
                     continue;
               }
               
               // Now we have the input block, the avg. color of the input pixels, a set of trial selector indices, and the block color+intensity index.
               // Now, for each component, attempt to refine the current solution by solving a simple linear equation. For example, for 4 colors:
               // The goal is:
               // pixel0 - (block_color+inten_table[selector0]) + pixel1 - (block_color+inten_table[selector1]) + pixel2 - (block_color+inten_table[selector2]) + pixel3 - (block_color+inten_table[selector3]) = 0
               // Rearranging this:
               // (pixel0 + pixel1 + pixel2 + pixel3) - (block_color+inten_table[selector0]) - (block_color+inten_table[selector1]) - (block_color+inten_table[selector2]) - (block_color+inten_table[selector3]) = 0
               // (pixel0 + pixel1 + pixel2 + pixel3) - block_color - inten_table[selector0] - block_color-inten_table[selector1] - block_color-inten_table[selector2] - block_color-inten_table[selector3] = 0
               // (pixel0 + pixel1 + pixel2 + pixel3) - 4*block_color - inten_table[selector0] - inten_table[selector1] - inten_table[selector2] - inten_table[selector3] = 0
               // (pixel0 + pixel1 + pixel2 + pixel3) - 4*block_color - (inten_table[selector0] + inten_table[selector1] + inten_table[selector2] + inten_table[selector3]) = 0
               // (pixel0 + pixel1 + pixel2 + pixel3)/4 - block_color - (inten_table[selector0] + inten_table[selector1] + inten_table[selector2] + inten_table[selector3])/4 = 0
               // block_color = (pixel0 + pixel1 + pixel2 + pixel3)/4 - (inten_table[selector0] + inten_table[selector1] + inten_table[selector2] + inten_table[selector3])/4
               // So what this means:
               // optimal_block_color = avg_input - avg_inten_delta
               // So the optimal block color can be computed by taking the average block color and subtracting the current average of the intensity delta.
               // Unfortunately, optimal_block_color must then be quantized to 555 or 444 so it's not always possible to improve matters using this formula.
               // Also, the above formula is for unclamped intensity deltas. The actual implementation takes into account clamping.

               const uint max_refinement_trials = (m_pParams->m_quality == cLowQuality) ? 2 : (((xd | yd | zd) == 0) ? 4 : 2);
               for (uint refinement_trial = 0; refinement_trial < max_refinement_trials; refinement_trial++)
               {
                  const uint8* pSelectors = m_best_solution.m_selectors;
                  const int* pInten_table = g_etc1_inten_tables[m_best_solution.m_coords.m_inten_table];

                  int delta_sum_r = 0, delta_sum_g = 0, delta_sum_b = 0;
                  const color_quad_u8 base_color(m_best_solution.m_coords.get_scaled_color());
                  for (uint r = 0; r < n; r++)
                  {
                     const uint s = *pSelectors++;
                     const int yd = pInten_table[s];
                     // Compute actual delta being applied to each pixel, taking into account clamping.
                     delta_sum_r += rg_etc1::clamp<int>(base_color.r + yd, 0, 255) - base_color.r;
                     delta_sum_g += rg_etc1::clamp<int>(base_color.g + yd, 0, 255) - base_color.g;
                     delta_sum_b += rg_etc1::clamp<int>(base_color.b + yd, 0, 255) - base_color.b;
                  }
                  if ((!delta_sum_r) && (!delta_sum_g) && (!delta_sum_b))
                     break;
                  const float avg_delta_r_f = static_cast<float>(delta_sum_r) / n;
                  const float avg_delta_g_f = static_cast<float>(delta_sum_g) / n;
                  const float avg_delta_b_f = static_cast<float>(delta_sum_b) / n;
                  const int br1 = rg_etc1::clamp<int>(static_cast<uint>((m_avg_color[0] - avg_delta_r_f) * m_limit / 255.0f + .5f), 0, m_limit);
                  const int bg1 = rg_etc1::clamp<int>(static_cast<uint>((m_avg_color[1] - avg_delta_g_f) * m_limit / 255.0f + .5f), 0, m_limit);
                  const int bb1 = rg_etc1::clamp<int>(static_cast<uint>((m_avg_color[2] - avg_delta_b_f) * m_limit / 255.0f + .5f), 0, m_limit);
                  
                  bool skip = false;
                  
                  if ((mbr == br1) && (mbg == bg1) && (mbb == bb1))
                     skip = true;
                  else if ((br1 == m_best_solution.m_coords.m_unscaled_color.r) && (bg1 == m_best_solution.m_coords.m_unscaled_color.g) && (bb1 == m_best_solution.m_coords.m_unscaled_color.b))
                     skip = true;
                  else if ((m_br == br1) && (m_bg == bg1) && (m_bb == bb1))
                     skip = true;

                  if (skip)
                     break;

                  etc1_solution_coordinates coords1(br1, bg1, bb1, 0, m_pParams->m_use_color4);
                  if (m_pParams->m_quality == cHighQuality)
                  {
                     if (!evaluate_solution(coords1, m_trial_solution, &m_best_solution)) 
                        break;
                  }
                  else
                  {
                     if (!evaluate_solution_fast(coords1, m_trial_solution, &m_best_solution))
                        break;
                  }

               }  // refinement_trial

            } // xdi
         } // ydi
      } // zdi

      if (!m_best_solution.m_valid)
      {
         m_pResult->m_error = cUINT32_MAX;
         return false;
      }
      
      const uint8* pSelectors = m_best_solution.m_selectors;

#ifdef RG_ETC1_BUILD_DEBUG
      {
         color_quad_u8 block_colors[4];
         m_best_solution.m_coords.get_block_colors(block_colors);

         const color_quad_u8* pSrc_pixels = m_pParams->m_pSrc_pixels;
         uint64 actual_error = 0;
         for (uint i = 0; i < n; i++)
            actual_error += pSrc_pixels[i].squared_distance_rgb(block_colors[pSelectors[i]]);
         
         RG_ETC1_ASSERT(actual_error == m_best_solution.m_error);
      }
#endif      
      
      m_pResult->m_error = m_best_solution.m_error;

      m_pResult->m_block_color_unscaled = m_best_solution.m_coords.m_unscaled_color;
      m_pResult->m_block_color4 = m_best_solution.m_coords.m_color4;
      
      m_pResult->m_block_inten_table = m_best_solution.m_coords.m_inten_table;
      memcpy(m_pResult->m_pSelectors, pSelectors, n);
      m_pResult->m_n = n;

      return true;
   }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movq %rdi, %rbx
movq (%rdi), %rax
movl 0x8(%rax), %r14d
movslq 0x28(%rax), %rax
movq %rax, 0x48(%rsp)
testq %rax, %rax
jle 0x6a85d
leaq 0xc8(%rbx), %rax
movq %rax, 0x30(%rsp)
leaq 0xa0(%rbx), %rax
movq %rax, 0x28(%rsp)
movl %r14d, %eax
cvtsi2ss %rax, %xmm0
movaps %xmm0, 0x80(%rsp)
shufps $0x0, %xmm0, %xmm0      # xmm0 = xmm0[0,0,0,0]
movaps %xmm0, 0x70(%rsp)
movl $0xff, %r13d
movq $0x0, 0x38(%rsp)
movq (%rbx), %rax
movq 0x20(%rax), %rax
movq 0x38(%rsp), %rcx
movl (%rax,%rcx,4), %eax
movl 0x28(%rbx), %ecx
movl %eax, 0x54(%rsp)
addl %eax, %ecx
movl %ecx, 0x4(%rsp)
js 0x6a845
movl 0x4(%rsp), %eax
cmpl 0x10(%rbx), %eax
jg 0x6a85d
cmpl %r13d, %eax
movl $0xff, %ecx
cmovbl %eax, %ecx
movl %ecx, 0x58(%rsp)
movq $0x0, 0x40(%rsp)
movq (%rbx), %rax
movq 0x20(%rax), %rax
movq 0x40(%rsp), %rcx
movl (%rax,%rcx,4), %eax
movl 0x24(%rbx), %ecx
movl %eax, (%rsp)
addl %eax, %ecx
movl %ecx, 0x8(%rsp)
js 0x6a82d
movl 0x8(%rsp), %eax
cmpl 0x10(%rbx), %eax
jg 0x6a845
cmpl %r13d, %eax
movl $0xff, %ecx
cmovbl %eax, %ecx
movl %ecx, 0x5c(%rsp)
movl (%rsp), %eax
orl 0x54(%rsp), %eax
movl %eax, (%rsp)
xorl %edx, %edx
movq (%rbx), %rax
movq 0x20(%rax), %rcx
movl (%rcx,%rdx,4), %ebp
movl 0x20(%rbx), %r15d
addl %ebp, %r15d
js 0x6a81f
cmpl 0x10(%rbx), %r15d
jg 0x6a82d
movq %rdx, 0x68(%rsp)
movb 0x18(%rax), %cl
cmpl %r13d, %r15d
movl $0xff, %edx
cmovbl %r15d, %edx
movb %dl, 0x1c(%rsp)
movl 0x5c(%rsp), %edx
movb %dl, 0x1d(%rsp)
movl 0x58(%rsp), %edx
movb %dl, 0x1e(%rsp)
movb $-0x1, 0x1f(%rsp)
movl $0x0, 0x20(%rsp)
movb %cl, 0x24(%rsp)
cmpl $0x2, (%rax)
jne 0x6a4a9
movq %rbx, %rdi
leaq 0x1c(%rsp), %rsi
movq 0x30(%rsp), %rdx
movq 0x28(%rsp), %rcx
callq 0x6a8d4
jmp 0x6a4c0
movq %rbx, %rdi
leaq 0x1c(%rsp), %rsi
movq 0x30(%rsp), %rdx
movq 0x28(%rsp), %rcx
callq 0x6ac70
testb %al, %al
je 0x6a81a
movq (%rbx), %rax
xorl %ecx, %ecx
orl (%rsp), %ebp
sete %cl
cmpl $0x0, (%rax)
leal 0x2(%rcx,%rcx), %ecx
movl $0x2, %eax
cmovel %eax, %ecx
movl %ecx, 0x60(%rsp)
xorl %ebp, %ebp
movzbl 0xa0(%rbx), %eax
cmpb $0x1, 0xa8(%rbx)
movl %eax, 0x64(%rsp)
jne 0x6a530
movzbl 0xa1(%rbx), %ecx
movd %eax, %xmm0
movl %ecx, 0xc(%rsp)
movd %ecx, %xmm1
punpckldq %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1]
movdqa %xmm0, %xmm1
pslld $0x4, %xmm1
por %xmm0, %xmm1
movzbl 0xa2(%rbx), %edx
movl %edx, %esi
shll $0x4, %esi
orl %edx, %esi
jmp 0x6a56c
movzbl 0xa1(%rbx), %ecx
movd %eax, %xmm1
movl %ecx, 0xc(%rsp)
movd %ecx, %xmm0
punpckldq %xmm0, %xmm1    # xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1]
movdqa %xmm1, %xmm0
psrld $0x2, %xmm0
pslld $0x3, %xmm1
por %xmm0, %xmm1
movzbl 0xa2(%rbx), %edx
movl %edx, %ecx
shrl $0x2, %ecx
movl %edx, %esi
shll $0x3, %esi
orl %ecx, %esi
movl %r15d, %eax
cmpl %r13d, %esi
cmovael %r13d, %esi
testl %r14d, %r14d
je 0x6a63c
movl 0xa4(%rbx), %r8d
shlq $0x4, %r8
leaq 0x127cf(%rip), %rcx     # 0x7cd60
addq %rcx, %r8
movdqa %xmm1, %xmm0
pxor 0x9b50(%rip), %xmm0     # 0x740f0
pcmpgtd 0x120b8(%rip), %xmm0    # 0x7c660
movdqa %xmm0, %xmm2
pandn %xmm1, %xmm2
psrld $0x18, %xmm0
por %xmm2, %xmm0
movd %xmm0, %r9d
pshufd $0x55, %xmm0, %xmm1     # xmm1 = xmm0[1,1,1,1]
movd %xmm1, %r10d
pxor %xmm1, %xmm1
xorl %r11d, %r11d
xorl %edi, %edi
movzbl 0xac(%rbx,%r11), %ecx
movl (%r8,%rcx,4), %r12d
leal (%r12,%r9), %ecx
cmpl %r13d, %ecx
cmovgel %r13d, %ecx
testl %ecx, %ecx
jg 0x6a5ef
xorl %ecx, %ecx
leal (%r12,%r10), %r15d
cmpl %r13d, %r15d
cmovgel %r13d, %r15d
testl %r15d, %r15d
jg 0x6a602
xorl %r15d, %r15d
addl %esi, %r12d
cmpl %r13d, %r12d
cmovgel %r13d, %r12d
testl %r12d, %r12d
jg 0x6a614
xorl %r12d, %r12d
psubd %xmm0, %xmm1
movd %r15d, %xmm3
movd %ecx, %xmm2
punpckldq %xmm3, %xmm2    # xmm2 = xmm2[0],xmm3[0],xmm2[1],xmm3[1]
paddd %xmm1, %xmm2
subl %esi, %edi
addl %r12d, %edi
incq %r11
movdqa %xmm2, %xmm1
cmpl %r11d, %r14d
jne 0x6a5d1
jmp 0x6a642
xorl %edi, %edi
pxor %xmm2, %xmm2
pshufd $0x50, %xmm2, %xmm0     # xmm0 = xmm2[0,0,1,1]
pcmpeqd 0xd271(%rip), %xmm0     # 0x778c0
movmskpd %xmm0, %ecx
xorl $0x3, %ecx
testb $0x1, %cl
movl %eax, %r15d
jne 0x6a66a
shrb %cl
jne 0x6a66a
testl %edi, %edi
je 0x6a81a
xorps %xmm0, %xmm0
cvtsi2ss %edi, %xmm0
cvtdq2ps %xmm2, %xmm3
divps 0x70(%rsp), %xmm3
divss 0x80(%rsp), %xmm0
movl 0x10(%rbx), %esi
xorps %xmm2, %xmm2
cvtsi2ss %esi, %xmm2
movsd 0x14(%rbx), %xmm1
subps %xmm3, %xmm1
movss 0x1c(%rbx), %xmm3
subss %xmm0, %xmm3
mulss %xmm2, %xmm3
shufps $0x0, %xmm2, %xmm2      # xmm2 = xmm2[0,0,0,0]
mulps %xmm1, %xmm2
divps 0x100f1(%rip), %xmm2    # 0x7a7a0
addps 0x11fba(%rip), %xmm2    # 0x7c670
cvttps2dq %xmm2, %xmm0
movdqa %xmm0, %xmm1
psrad $0x1f, %xmm1
subps 0x11fb6(%rip), %xmm2    # 0x7c680
cvttps2dq %xmm2, %xmm2
pand %xmm1, %xmm2
por %xmm0, %xmm2
movd %esi, %xmm0
pshufd $0x50, %xmm0, %xmm1     # xmm1 = xmm0[0,0,1,1]
movdqa %xmm1, %xmm4
pcmpgtd %xmm2, %xmm4
pxor %xmm0, %xmm0
pcmpgtd %xmm2, %xmm0
pand %xmm4, %xmm2
pandn %xmm1, %xmm4
por %xmm2, %xmm4
pandn %xmm4, %xmm0
pshufd $0x55, %xmm0, %xmm1     # xmm1 = xmm0[1,1,1,1]
movd %xmm1, %edi
divss 0xfe90(%rip), %xmm3     # 0x7a5a0
addss 0xfe70(%rip), %xmm3     # 0x7a588
cvttss2si %xmm3, %rcx
movd %xmm0, %r8d
cmpl %esi, %ecx
cmovll %ecx, %esi
testl %ecx, %ecx
movl $0x0, %ecx
cmovsl %ecx, %esi
cmpl %r8d, %r15d
jne 0x6a746
cmpl %edi, 0x8(%rsp)
jne 0x6a746
cmpl %esi, 0x4(%rsp)
je 0x6a81a
cmpl 0x64(%rsp), %r8d
jne 0x6a761
movzbl 0xc(%rsp), %eax
cmpl %eax, %edi
jne 0x6a761
movzbl %dl, %eax
cmpl %eax, %esi
je 0x6a81a
movq 0x20(%rbx), %xmm1
pcmpeqd %xmm0, %xmm1
pshufd $0x50, %xmm1, %xmm0     # xmm0 = xmm1[0,0,1,1]
movmskpd %xmm0, %eax
testb $0x1, %al
je 0x6a784
shrb %al
je 0x6a784
cmpl %esi, 0x28(%rbx)
je 0x6a81a
movq (%rbx), %rax
testl %r8d, %r8d
movl $0x0, %edx
cmovlel %edx, %r8d
movb 0x18(%rax), %cl
cmpl %r13d, %r8d
cmovgel %r13d, %r8d
movb %r8b, 0x10(%rsp)
testl %edi, %edi
cmovlel %edx, %edi
cmpl %r13d, %edi
cmovgel %r13d, %edi
movb %dil, 0x11(%rsp)
testl %esi, %esi
cmovlel %edx, %esi
cmpl %r13d, %esi
cmovgel %r13d, %esi
movb %sil, 0x12(%rsp)
movb $-0x1, 0x13(%rsp)
movl $0x0, 0x14(%rsp)
movb %cl, 0x18(%rsp)
cmpl $0x2, (%rax)
jne 0x6a7f3
movq %rbx, %rdi
leaq 0x10(%rsp), %rsi
movq 0x30(%rsp), %rdx
movq 0x28(%rsp), %rcx
callq 0x6a8d4
jmp 0x6a80a
movq %rbx, %rdi
leaq 0x10(%rsp), %rsi
movq 0x30(%rsp), %rdx
movq 0x28(%rsp), %rcx
callq 0x6ac70
testb %al, %al
je 0x6a81a
incl %ebp
cmpl 0x60(%rsp), %ebp
jne 0x6a4e8
movq 0x68(%rsp), %rdx
incq %rdx
cmpq 0x48(%rsp), %rdx
jne 0x6a431
movq 0x40(%rsp), %rcx
incq %rcx
movq %rcx, 0x40(%rsp)
cmpq 0x48(%rsp), %rcx
jne 0x6a3e8
movq 0x38(%rsp), %rcx
incq %rcx
movq %rcx, 0x38(%rsp)
cmpq 0x48(%rsp), %rcx
jne 0x6a3a1
movb 0xc0(%rbx), %bpl
testb %bpl, %bpl
je 0x6a8b3
leaq 0xac(%rbx), %rsi
movq 0x8(%rbx), %rax
movq 0xb8(%rbx), %rcx
movq %rcx, (%rax)
movl 0xa0(%rbx), %ecx
movl %ecx, 0x8(%rax)
movb 0xa8(%rbx), %al
movq 0x8(%rbx), %rcx
movb %al, 0x20(%rcx)
movl 0xa4(%rbx), %eax
movl %eax, 0xc(%rcx)
movq 0x18(%rcx), %rdi
movq %r14, %rdx
callq 0x60c0
movq 0x8(%rbx), %rax
movl %r14d, 0x10(%rax)
jmp 0x6a8bf
movq 0x8(%rbx), %rax
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
movq %rcx, (%rax)
movl %ebp, %eax
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop