// File: /workspace/github_c_makefile_star2_O0/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
movq %rsp, %rbp
subq $0xe0, %rsp
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0xb8(%rbp)
movq (%rax), %rcx
movl 0x8(%rcx), %ecx
movl %ecx, -0x14(%rbp)
movq (%rax), %rax
movl 0x28(%rax), %eax
movl %eax, -0x18(%rbp)
movl $0x0, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
cmpl -0x18(%rbp), %eax
jge 0x9eec7
movq -0xb8(%rbp), %rax
movq (%rax), %rcx
movq 0x20(%rcx), %rcx
movslq -0x1c(%rbp), %rdx
movl (%rcx,%rdx,4), %ecx
movl %ecx, -0x20(%rbp)
movl 0x28(%rax), %eax
addl -0x20(%rbp), %eax
movl %eax, -0x24(%rbp)
cmpl $0x0, -0x24(%rbp)
jge 0x9e8db
jmp 0x9eeb9
movq -0xb8(%rbp), %rcx
movl -0x24(%rbp), %eax
cmpl 0x10(%rcx), %eax
jle 0x9e8ef
jmp 0x9eec7
jmp 0x9e8f1
movl $0x0, -0x28(%rbp)
movl -0x28(%rbp), %eax
cmpl -0x18(%rbp), %eax
jge 0x9eeb7
movq -0xb8(%rbp), %rax
movq (%rax), %rcx
movq 0x20(%rcx), %rcx
movslq -0x28(%rbp), %rdx
movl (%rcx,%rdx,4), %ecx
movl %ecx, -0x2c(%rbp)
movl 0x24(%rax), %eax
addl -0x2c(%rbp), %eax
movl %eax, -0x30(%rbp)
cmpl $0x0, -0x30(%rbp)
jge 0x9e930
jmp 0x9eea9
movq -0xb8(%rbp), %rcx
movl -0x30(%rbp), %eax
cmpl 0x10(%rcx), %eax
jle 0x9e944
jmp 0x9eeb7
jmp 0x9e946
movl $0x0, -0x34(%rbp)
movl -0x34(%rbp), %eax
cmpl -0x18(%rbp), %eax
jge 0x9eea7
movq -0xb8(%rbp), %rax
movq (%rax), %rcx
movq 0x20(%rcx), %rcx
movslq -0x34(%rbp), %rdx
movl (%rcx,%rdx,4), %ecx
movl %ecx, -0x38(%rbp)
movl 0x20(%rax), %eax
addl -0x38(%rbp), %eax
movl %eax, -0x3c(%rbp)
cmpl $0x0, -0x3c(%rbp)
jge 0x9e985
jmp 0x9ee99
movq -0xb8(%rbp), %rcx
movl -0x3c(%rbp), %eax
cmpl 0x10(%rcx), %eax
jle 0x9e999
jmp 0x9eea7
jmp 0x9e99b
movq -0xb8(%rbp), %rax
movl -0x3c(%rbp), %esi
movl -0x30(%rbp), %edx
movl -0x24(%rbp), %ecx
movq (%rax), %rax
movb 0x18(%rax), %al
leaq -0x48(%rbp), %rdi
xorl %r8d, %r8d
andb $0x1, %al
movzbl %al, %r9d
callq 0xa2010
movq -0xb8(%rbp), %rax
movq (%rax), %rax
cmpl $0x2, (%rax)
jne 0x9ea01
movq -0xb8(%rbp), %rdi
movq %rdi, %rdx
addq $0xc8, %rdx
movq %rdi, %rcx
addq $0xa0, %rcx
leaq -0x48(%rbp), %rsi
callq 0x9efa0
testb $0x1, %al
jne 0x9e9ff
jmp 0x9ee99
jmp 0x9ea30
movq -0xb8(%rbp), %rdi
movq %rdi, %rdx
addq $0xc8, %rdx
movq %rdi, %rcx
addq $0xa0, %rcx
leaq -0x48(%rbp), %rsi
callq 0x9f490
testb $0x1, %al
jne 0x9ea2e
jmp 0x9ee99
jmp 0x9ea30
movq -0xb8(%rbp), %rax
movq (%rax), %rax
cmpl $0x0, (%rax)
jne 0x9ea4c
movl $0x2, %eax
movl %eax, -0xbc(%rbp)
jmp 0x9ea6b
movl -0x38(%rbp), %edx
orl -0x2c(%rbp), %edx
orl -0x20(%rbp), %edx
movl $0x2, %eax
movl $0x4, %ecx
cmpl $0x0, %edx
cmovel %ecx, %eax
movl %eax, -0xbc(%rbp)
movl -0xbc(%rbp), %eax
movl %eax, -0x4c(%rbp)
movl $0x0, -0x50(%rbp)
movl -0x50(%rbp), %eax
cmpl -0x4c(%rbp), %eax
jae 0x9ee97
movq -0xb8(%rbp), %rsi
movq %rsi, %rax
addq $0xa0, %rax
addq $0xc, %rax
movq %rax, -0x58(%rbp)
movl 0xa4(%rsi), %eax
movl %eax, %ecx
leaq 0x1a192(%rip), %rax     # 0xb8c40
shlq $0x4, %rcx
addq %rcx, %rax
movq %rax, -0x60(%rbp)
movl $0x0, -0x64(%rbp)
movl $0x0, -0x68(%rbp)
movl $0x0, -0x6c(%rbp)
addq $0xa0, %rsi
leaq -0x70(%rbp), %rdi
callq 0xa2070
movl $0x0, -0x74(%rbp)
movl -0x74(%rbp), %eax
cmpl -0x14(%rbp), %eax
jae 0x9eb7e
movq -0x58(%rbp), %rax
movq %rax, %rcx
addq $0x1, %rcx
movq %rcx, -0x58(%rbp)
movzbl (%rax), %eax
movl %eax, -0x78(%rbp)
movq -0x60(%rbp), %rax
movl -0x78(%rbp), %ecx
movl (%rax,%rcx,4), %eax
movl %eax, -0x7c(%rbp)
movzbl -0x70(%rbp), %edi
addl -0x7c(%rbp), %edi
xorl %esi, %esi
movl $0xff, %edx
callq 0xa1aa0
movzbl -0x70(%rbp), %ecx
subl %ecx, %eax
addl -0x64(%rbp), %eax
movl %eax, -0x64(%rbp)
movzbl -0x6f(%rbp), %edi
addl -0x7c(%rbp), %edi
xorl %esi, %esi
movl $0xff, %edx
callq 0xa1aa0
movzbl -0x6f(%rbp), %ecx
subl %ecx, %eax
addl -0x68(%rbp), %eax
movl %eax, -0x68(%rbp)
movzbl -0x6e(%rbp), %edi
addl -0x7c(%rbp), %edi
xorl %esi, %esi
movl $0xff, %edx
callq 0xa1aa0
movzbl -0x6e(%rbp), %ecx
subl %ecx, %eax
addl -0x6c(%rbp), %eax
movl %eax, -0x6c(%rbp)
movl -0x74(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x74(%rbp)
jmp 0x9eae5
cmpl $0x0, -0x64(%rbp)
jne 0x9eb95
cmpl $0x0, -0x68(%rbp)
jne 0x9eb95
cmpl $0x0, -0x6c(%rbp)
jne 0x9eb95
jmp 0x9ee97
movq -0xb8(%rbp), %rdi
cvtsi2ssl -0x64(%rbp), %xmm0
movl -0x14(%rbp), %eax
cvtsi2ss %rax, %xmm1
divss %xmm1, %xmm0
movss %xmm0, -0x80(%rbp)
cvtsi2ssl -0x68(%rbp), %xmm0
movl -0x14(%rbp), %eax
cvtsi2ss %rax, %xmm1
divss %xmm1, %xmm0
movss %xmm0, -0x84(%rbp)
cvtsi2ssl -0x6c(%rbp), %xmm0
movl -0x14(%rbp), %eax
cvtsi2ss %rax, %xmm1
divss %xmm1, %xmm0
movss %xmm0, -0x88(%rbp)
addq $0x14, %rdi
movq %rdi, -0xd0(%rbp)
xorl %esi, %esi
movl %esi, -0xd4(%rbp)
callq 0xa2130
movl -0xd4(%rbp), %esi
movq -0xb8(%rbp), %rax
movss -0x80(%rbp), %xmm1
subss %xmm1, %xmm0
movl 0x10(%rax), %edx
cvtsi2ss %edx, %xmm1
mulss %xmm1, %xmm0
movss 0x179b3(%rip), %xmm1    # 0xb65d8
movss %xmm1, -0xc4(%rbp)
divss %xmm1, %xmm0
movss 0x1798f(%rip), %xmm1    # 0xb65c8
movss %xmm1, -0xc0(%rbp)
addss %xmm1, %xmm0
cvttss2si %xmm0, %rax
movl %eax, %edi
callq 0xa1aa0
movq -0xd0(%rbp), %rdi
movl %eax, -0x8c(%rbp)
movl $0x1, %esi
callq 0xa2130
movl -0xd4(%rbp), %esi
movss -0xc4(%rbp), %xmm2
movss -0xc0(%rbp), %xmm1
movq -0xb8(%rbp), %rax
movss -0x84(%rbp), %xmm3
subss %xmm3, %xmm0
movl 0x10(%rax), %edx
cvtsi2ss %edx, %xmm3
mulss %xmm3, %xmm0
divss %xmm2, %xmm0
addss %xmm1, %xmm0
cvttss2si %xmm0, %rax
movl %eax, %edi
callq 0xa1aa0
movq -0xd0(%rbp), %rdi
movl %eax, -0x90(%rbp)
movl $0x2, %esi
callq 0xa2130
movss -0xc4(%rbp), %xmm2
movss -0xc0(%rbp), %xmm1
movq -0xb8(%rbp), %rax
movss -0x88(%rbp), %xmm3
subss %xmm3, %xmm0
cvtsi2ssl 0x10(%rax), %xmm3
mulss %xmm3, %xmm0
divss %xmm2, %xmm0
addss %xmm1, %xmm0
cvttss2si %xmm0, %rcx
movl %ecx, %edi
movl 0x10(%rax), %edx
xorl %esi, %esi
callq 0xa1aa0
movl %eax, -0x94(%rbp)
movb $0x0, -0x95(%rbp)
movl -0x3c(%rbp), %eax
cmpl -0x8c(%rbp), %eax
jne 0x9ed46
movl -0x30(%rbp), %eax
cmpl -0x90(%rbp), %eax
jne 0x9ed46
movl -0x24(%rbp), %eax
cmpl -0x94(%rbp), %eax
jne 0x9ed46
movb $0x1, -0x95(%rbp)
jmp 0x9edd8
movq -0xb8(%rbp), %rcx
movl -0x8c(%rbp), %eax
movzbl 0xa0(%rcx), %ecx
cmpl %ecx, %eax
jne 0x9ed97
movq -0xb8(%rbp), %rcx
movl -0x90(%rbp), %eax
movzbl 0xa1(%rcx), %ecx
cmpl %ecx, %eax
jne 0x9ed97
movq -0xb8(%rbp), %rcx
movl -0x94(%rbp), %eax
movzbl 0xa2(%rcx), %ecx
cmpl %ecx, %eax
jne 0x9ed97
movb $0x1, -0x95(%rbp)
jmp 0x9edd6
movq -0xb8(%rbp), %rax
movl 0x20(%rax), %eax
cmpl -0x8c(%rbp), %eax
jne 0x9edd4
movq -0xb8(%rbp), %rax
movl 0x24(%rax), %eax
cmpl -0x90(%rbp), %eax
jne 0x9edd4
movq -0xb8(%rbp), %rax
movl 0x28(%rax), %eax
cmpl -0x94(%rbp), %eax
jne 0x9edd4
movb $0x1, -0x95(%rbp)
jmp 0x9edd6
jmp 0x9edd8
testb $0x1, -0x95(%rbp)
je 0x9ede6
jmp 0x9ee97
movq -0xb8(%rbp), %rax
movl -0x8c(%rbp), %esi
movl -0x90(%rbp), %edx
movl -0x94(%rbp), %ecx
movq (%rax), %rax
movb 0x18(%rax), %al
leaq -0xa4(%rbp), %rdi
xorl %r8d, %r8d
andb $0x1, %al
movzbl %al, %r9d
callq 0xa2010
movq -0xb8(%rbp), %rax
movq (%rax), %rax
cmpl $0x2, (%rax)
jne 0x9ee58
movq -0xb8(%rbp), %rdi
movq %rdi, %rdx
addq $0xc8, %rdx
movq %rdi, %rcx
addq $0xa0, %rcx
leaq -0xa4(%rbp), %rsi
callq 0x9efa0
testb $0x1, %al
jne 0x9ee56
jmp 0x9ee97
jmp 0x9ee87
movq -0xb8(%rbp), %rdi
movq %rdi, %rdx
addq $0xc8, %rdx
movq %rdi, %rcx
addq $0xa0, %rcx
leaq -0xa4(%rbp), %rsi
callq 0x9f490
testb $0x1, %al
jne 0x9ee85
jmp 0x9ee97
jmp 0x9ee87
jmp 0x9ee89
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
jmp 0x9ea7b
jmp 0x9ee99
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x9e94d
jmp 0x9eea9
movl -0x28(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x28(%rbp)
jmp 0x9e8f8
jmp 0x9eeb9
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x9e8a3
movq -0xb8(%rbp), %rax
testb $0x1, 0xc0(%rax)
jne 0x9eef3
movq -0xb8(%rbp), %rax
movq 0x8(%rax), %rax
movl $0xffffffff, %ecx       # imm = 0xFFFFFFFF
movq %rcx, (%rax)
movb $0x0, -0x1(%rbp)
jmp 0x9ef86
movq -0xb8(%rbp), %rax
movq %rax, %rcx
addq $0xa0, %rcx
addq $0xc, %rcx
movq %rcx, -0xb0(%rbp)
movq 0xb8(%rax), %rdx
movq 0x8(%rax), %rcx
movq %rdx, (%rcx)
movq %rax, %rsi
addq $0xa0, %rsi
movq 0x8(%rax), %rdi
addq $0x8, %rdi
callq 0xa1ff0
movq -0xb8(%rbp), %rax
movb 0xa8(%rax), %dl
movq 0x8(%rax), %rcx
andb $0x1, %dl
movb %dl, 0x20(%rcx)
movl 0xa4(%rax), %edx
movq 0x8(%rax), %rcx
movl %edx, 0xc(%rcx)
movq 0x8(%rax), %rax
movq 0x18(%rax), %rdi
movq -0xb0(%rbp), %rsi
movl -0x14(%rbp), %eax
movl %eax, %edx
callq 0x60c0
movq -0xb8(%rbp), %rax
movl -0x14(%rbp), %ecx
movq 0x8(%rax), %rax
movl %ecx, 0x10(%rax)
movb $0x1, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0xe0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)