// File: /workspace/github_c_makefile_star2_O1/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 $0x78, %rsp
movq %rdi, %rbx
movq (%rdi), %rax
movl 0x8(%rax), %r14d
movslq 0x28(%rax), %rdx
testq %rdx, %rdx
jle 0x68b03
leaq 0xc8(%rbx), %rax
movq %rax, 0x30(%rsp)
leaq 0xa0(%rbx), %rax
movq %rax, 0x28(%rsp)
movl %r14d, %eax
cvtsi2ss %rax, %xmm0
movss %xmm0, 0x48(%rsp)
movl $0xff, %r15d
xorl %ecx, %ecx
movq %rdx, 0x68(%rsp)
movq (%rbx), %rax
movq 0x20(%rax), %rax
movq %rcx, 0x58(%rsp)
movl (%rax,%rcx,4), %eax
movl 0x28(%rbx), %esi
movl %eax, 0x38(%rsp)
addl %eax, %esi
js 0x686a7
movl 0x10(%rbx), %ecx
xorl %eax, %eax
cmpl %ecx, %esi
setg %cl
jle 0x686b1
movb %cl, %al
addl %eax, %eax
jmp 0x68aee
movl $0x4, %eax
jmp 0x68aee
cmpl %r15d, %esi
movl $0xff, %eax
movl %esi, 0x44(%rsp)
cmovll %esi, %eax
movl %eax, 0x3c(%rsp)
xorl %ecx, %ecx
movq (%rbx), %rax
movq 0x20(%rax), %rax
movq %rcx, 0x60(%rsp)
movl (%rax,%rcx,4), %eax
movl 0x24(%rbx), %esi
movl %eax, 0x8(%rsp)
addl %eax, %esi
js 0x68acd
movl $0x5, %ecx
movl %esi, 0xc(%rsp)
cmpl 0x10(%rbx), %esi
jg 0x68ad2
movl 0xc(%rsp), %eax
cmpl %r15d, %eax
movl $0xff, %ecx
cmovll %eax, %ecx
movl %ecx, 0x40(%rsp)
movl 0x8(%rsp), %eax
orl 0x38(%rsp), %eax
movl %eax, 0x8(%rsp)
xorl %esi, %esi
movq (%rbx), %rax
movq 0x20(%rax), %rcx
movl (%rcx,%rsi,4), %r13d
movl 0x20(%rbx), %ebp
addl %r13d, %ebp
js 0x6878f
movl $0x8, %r12d
cmpl 0x10(%rbx), %ebp
jg 0x68ab2
movq %rsi, 0x70(%rsp)
movb 0x18(%rax), %cl
cmpl %r15d, %ebp
movl $0xff, %edx
cmovll %ebp, %edx
movb %dl, 0x1c(%rsp)
movl 0x40(%rsp), %edx
movb %dl, 0x1d(%rsp)
movl 0x3c(%rsp), %edx
movb %dl, 0x1e(%rsp)
movb $-0x1, 0x1f(%rsp)
movl $0x0, 0x20(%rsp)
movb %cl, 0x24(%rsp)
cmpl $0x2, (%rax)
jne 0x6879a
movq %rbx, %rdi
leaq 0x1c(%rsp), %rsi
movq 0x30(%rsp), %rdx
movq 0x28(%rsp), %rcx
callq 0x68b76
jmp 0x687b1
movl $0xa, %r12d
jmp 0x68ab2
movq %rbx, %rdi
leaq 0x1c(%rsp), %rsi
movq 0x30(%rsp), %rdx
movq 0x28(%rsp), %rcx
callq 0x68ef4
movl $0xa, %r12d
testb %al, %al
je 0x68aa8
movq (%rbx), %rax
xorl %ecx, %ecx
orl 0x8(%rsp), %r13d
sete %cl
cmpl $0x0, (%rax)
leal 0x2(%rcx,%rcx), %ecx
movl $0x2, %eax
cmovel %eax, %ecx
movl %ecx, 0x4c(%rsp)
xorl %r13d, %r13d
movl %ebp, 0x50(%rsp)
movzbl 0xa0(%rbx), %esi
cmpb $0x1, 0xa8(%rbx)
movl %r13d, 0x54(%rsp)
jne 0x68820
movl %esi, %ecx
shll $0x4, %ecx
orl %esi, %ecx
movzbl 0xa1(%rbx), %edx
movl %edx, %eax
shll $0x4, %eax
orl %edx, %eax
movzbl 0xa2(%rbx), %esi
movl %esi, %edx
shll $0x4, %edx
orl %esi, %edx
jmp 0x6884e
movl %esi, %eax
shrl $0x2, %eax
shll $0x3, %esi
orl %eax, %esi
movzbl 0xa1(%rbx), %eax
movl %eax, %ecx
shrl $0x2, %ecx
shll $0x3, %eax
orl %ecx, %eax
movzbl 0xa2(%rbx), %edx
movl %edx, %ecx
shrl $0x2, %ecx
shll $0x3, %edx
orl %ecx, %edx
movl %esi, %ecx
xorl %r12d, %r12d
movl $0x0, %esi
movl $0x0, %edi
movl $0x0, %r8d
testl %r14d, %r14d
je 0x688f8
movl 0xa4(%rbx), %r9d
shlq $0x4, %r9
leaq 0x13034(%rip), %rsi     # 0x7b8b0
addq %rsi, %r9
cmpl %r15d, %edx
cmovgel %r15d, %edx
cmpl %r15d, %eax
cmovgel %r15d, %eax
cmpl %r15d, %ecx
cmovgel %r15d, %ecx
xorl %r10d, %r10d
xorl %r8d, %r8d
xorl %edi, %edi
xorl %esi, %esi
movzbl 0xac(%rbx,%r10), %r11d
movl (%r9,%r11,4), %r11d
leal (%r11,%rcx), %r13d
cmpl %r15d, %r13d
cmovgel %r15d, %r13d
testl %r13d, %r13d
jg 0x688be
xorl %r13d, %r13d
leal (%r11,%rax), %ebp
cmpl %r15d, %ebp
cmovgel %r15d, %ebp
testl %ebp, %ebp
jg 0x688cf
xorl %ebp, %ebp
addl %edx, %r11d
cmpl %r15d, %r11d
cmovgel %r15d, %r11d
testl %r11d, %r11d
jg 0x688e1
xorl %r11d, %r11d
subl %ecx, %r8d
addl %r13d, %r8d
subl %eax, %edi
addl %ebp, %edi
subl %edx, %esi
addl %r11d, %esi
incq %r10
cmpl %r10d, %r14d
jne 0x6889e
testl %r8d, %r8d
movl 0x50(%rsp), %r9d
movl 0x54(%rsp), %r13d
jne 0x68913
testl %edi, %edi
jne 0x68913
testl %esi, %esi
je 0x68aa8
cvtsi2ss %r8d, %xmm1
cvtsi2ss %edi, %xmm2
cvtsi2ss %esi, %xmm0
movss 0x48(%rsp), %xmm4
divss %xmm4, %xmm1
movss 0x14(%rbx), %xmm3
subss %xmm1, %xmm3
movl 0x10(%rbx), %eax
xorps %xmm1, %xmm1
cvtsi2ss %eax, %xmm1
mulss %xmm1, %xmm3
movss 0x1096b(%rip), %xmm5    # 0x792b4
divss %xmm5, %xmm3
movss 0x10953(%rip), %xmm6    # 0x792a8
addss %xmm6, %xmm3
cvttss2si %xmm3, %rdx
cmpl %eax, %edx
movl %eax, %ecx
cmovll %edx, %ecx
xorl %r12d, %r12d
testl %edx, %edx
cmovsl %r12d, %ecx
divss %xmm4, %xmm2
movss 0x18(%rbx), %xmm3
subss %xmm2, %xmm3
mulss %xmm1, %xmm3
divss %xmm5, %xmm3
addss %xmm6, %xmm3
cvttss2si %xmm3, %rsi
cmpl %eax, %esi
movl %eax, %edx
cmovll %esi, %edx
testl %esi, %esi
cmovsl %r12d, %edx
divss %xmm4, %xmm0
movss 0x1c(%rbx), %xmm2
subss %xmm0, %xmm2
mulss %xmm1, %xmm2
divss %xmm5, %xmm2
addss %xmm6, %xmm2
cvttss2si %xmm2, %rsi
cmpl %eax, %esi
cmovll %esi, %eax
testl %esi, %esi
cmovsl %r12d, %eax
cmpl %ecx, %r9d
jne 0x689d7
cmpl %edx, 0xc(%rsp)
jne 0x689d7
cmpl %eax, 0x44(%rsp)
je 0x68aa8
movzbl 0xa0(%rbx), %esi
cmpl %esi, %ecx
jne 0x689fc
movzbl 0xa1(%rbx), %esi
cmpl %esi, %edx
jne 0x689fc
movzbl 0xa2(%rbx), %esi
cmpl %esi, %eax
je 0x68aa8
cmpl %ecx, 0x20(%rbx)
jne 0x68a0f
cmpl %edx, 0x24(%rbx)
jne 0x68a0f
cmpl %eax, 0x28(%rbx)
je 0x68aa8
movq (%rbx), %rsi
testl %ecx, %ecx
movl $0x0, %r8d
cmovlel %r8d, %ecx
movb 0x18(%rsi), %dil
cmpl %r15d, %ecx
cmovgel %r15d, %ecx
movb %cl, 0x10(%rsp)
testl %edx, %edx
cmovlel %r8d, %edx
cmpl %r15d, %edx
cmovgel %r15d, %edx
movb %dl, 0x11(%rsp)
testl %eax, %eax
cmovlel %r8d, %eax
cmpl %r15d, %eax
cmovgel %r15d, %eax
movb %al, 0x12(%rsp)
movb $-0x1, 0x13(%rsp)
movl $0x0, 0x14(%rsp)
movb %dil, 0x18(%rsp)
cmpl $0x2, (%rsi)
jne 0x68a7f
movq %rbx, %rdi
leaq 0x10(%rsp), %rsi
movq 0x30(%rsp), %rdx
movq 0x28(%rsp), %rcx
callq 0x68b76
jmp 0x68a96
movq %rbx, %rdi
leaq 0x10(%rsp), %rsi
movq 0x30(%rsp), %rdx
movq 0x28(%rsp), %rcx
callq 0x68ef4
testb %al, %al
je 0x68aa8
incl %r13d
cmpl 0x4c(%rsp), %r13d
jne 0x687e6
movq 0x68(%rsp), %rdx
movq 0x70(%rsp), %rsi
xorl %ecx, %ecx
cmpl $0xa, %r12d
je 0x68abf
testl %r12d, %r12d
jne 0x68ad2
incq %rsi
cmpq %rdx, %rsi
jne 0x68717
jmp 0x68ad2
movl $0x7, %ecx
xorl %eax, %eax
cmpl $0x7, %ecx
je 0x68add
testl %ecx, %ecx
jne 0x68aee
movq 0x60(%rsp), %rcx
incq %rcx
cmpq %rdx, %rcx
jne 0x686c6
testb $0x3, %al
movq 0x58(%rsp), %rcx
jne 0x68b03
incq %rcx
cmpq %rdx, %rcx
jne 0x68678
movb 0xc0(%rbx), %bpl
testb %bpl, %bpl
je 0x68b59
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 0x68b65
movq 0x8(%rbx), %rax
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
movq %rcx, (%rax)
movl %ebp, %eax
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq