// File: tomfunkhouser[P]gaps/pkgs/jpeg/jquant2.c
// Function: find_best_colors
LOCAL(void)
find_best_colors (j_decompress_ptr cinfo, int minc0, int minc1, int minc2,
		  int numcolors, JSAMPLE colorlist[], JSAMPLE bestcolor[])
/* Find the closest colormap entry for each cell in the update box,
 * given the list of candidate colors prepared by find_nearby_colors.
 * Return the indexes of the closest entries in the bestcolor[] array.
 * This routine uses Thomas' incremental distance calculation method to
 * find the distance from a colormap entry to successive cells in the box.
 */
{
  int ic0, ic1, ic2;
  int i, icolor;
  register INT32 * bptr;	/* pointer into bestdist[] array */
  JSAMPLE * cptr;		/* pointer into bestcolor[] array */
  INT32 dist0, dist1;		/* initial distance values */
  register INT32 dist2;		/* current distance in inner loop */
  INT32 xx0, xx1;		/* distance increments */
  register INT32 xx2;
  INT32 inc0, inc1, inc2;	/* initial values for increments */
  /* This array holds the distance to the nearest-so-far color for each cell */
  INT32 bestdist[BOX_C0_ELEMS * BOX_C1_ELEMS * BOX_C2_ELEMS];

  /* Initialize best-distance for each cell of the update box */
  bptr = bestdist;
  for (i = BOX_C0_ELEMS*BOX_C1_ELEMS*BOX_C2_ELEMS-1; i >= 0; i--)
    *bptr++ = 0x7FFFFFFFL;
  
  /* For each color selected by find_nearby_colors,
   * compute its distance to the center of each cell in the box.
   * If that's less than best-so-far, update best distance and color number.
   */
  
  /* Nominal steps between cell centers ("x" in Thomas article) */
#define STEP_C0  ((1 << C0_SHIFT) * C0_SCALE)
#define STEP_C1  ((1 << C1_SHIFT) * C1_SCALE)
#define STEP_C2  ((1 << C2_SHIFT) * C2_SCALE)
  
  for (i = 0; i < numcolors; i++) {
    icolor = GETJSAMPLE(colorlist[i]);
    /* Compute (square of) distance from minc0/c1/c2 to this color */
    inc0 = (minc0 - GETJSAMPLE(cinfo->colormap[0][icolor])) * C0_SCALE;
    dist0 = inc0*inc0;
    inc1 = (minc1 - GETJSAMPLE(cinfo->colormap[1][icolor])) * C1_SCALE;
    dist0 += inc1*inc1;
    inc2 = (minc2 - GETJSAMPLE(cinfo->colormap[2][icolor])) * C2_SCALE;
    dist0 += inc2*inc2;
    /* Form the initial difference increments */
    inc0 = inc0 * (2 * STEP_C0) + STEP_C0 * STEP_C0;
    inc1 = inc1 * (2 * STEP_C1) + STEP_C1 * STEP_C1;
    inc2 = inc2 * (2 * STEP_C2) + STEP_C2 * STEP_C2;
    /* Now loop over all cells in box, updating distance per Thomas method */
    bptr = bestdist;
    cptr = bestcolor;
    xx0 = inc0;
    for (ic0 = BOX_C0_ELEMS-1; ic0 >= 0; ic0--) {
      dist1 = dist0;
      xx1 = inc1;
      for (ic1 = BOX_C1_ELEMS-1; ic1 >= 0; ic1--) {
	dist2 = dist1;
	xx2 = inc2;
	for (ic2 = BOX_C2_ELEMS-1; ic2 >= 0; ic2--) {
	  if (dist2 < *bptr) {
	    *bptr = dist2;
	    *cptr = (JSAMPLE) icolor;
	  }
	  dist2 += xx2;
	  xx2 += 2 * STEP_C2 * STEP_C2;
	  bptr++;
	  cptr++;
	}
	dist1 += xx1;
	xx1 += 2 * STEP_C1 * STEP_C1;
      }
      dist0 += xx0;
      xx0 += 2 * STEP_C0 * STEP_C0;
    }
  }
}

// Assembly:
subq $0x418, %rsp            # imm = 0x418
movq 0x420(%rsp), %rax
movq %rdi, 0x410(%rsp)
movl %esi, 0x40c(%rsp)
movl %edx, 0x408(%rsp)
movl %ecx, 0x404(%rsp)
movl %r8d, 0x400(%rsp)
movq %r9, 0x3f8(%rsp)
leaq -0x80(%rsp), %rax
movq %rax, 0x3d8(%rsp)
movl $0x7f, 0x3e8(%rsp)
cmpl $0x0, 0x3e8(%rsp)
jl 0xf814f
movq 0x3d8(%rsp), %rax
movq %rax, %rcx
addq $0x8, %rcx
movq %rcx, 0x3d8(%rsp)
movq $0x7fffffff, (%rax)     # imm = 0x7FFFFFFF
movl 0x3e8(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0x3e8(%rsp)
jmp 0xf8114
movl $0x0, 0x3e8(%rsp)
movl 0x3e8(%rsp), %eax
cmpl 0x400(%rsp), %eax
jge 0xf84c9
movq 0x3f8(%rsp), %rax
movslq 0x3e8(%rsp), %rcx
movzbl (%rax,%rcx), %eax
movl %eax, 0x3e4(%rsp)
movl 0x40c(%rsp), %eax
movq 0x410(%rsp), %rcx
movq 0xa0(%rcx), %rcx
movq (%rcx), %rcx
movslq 0x3e4(%rsp), %rdx
movzbl (%rcx,%rdx), %ecx
subl %ecx, %eax
shll %eax
cltq
movq %rax, 0x398(%rsp)
movq 0x398(%rsp), %rax
imulq 0x398(%rsp), %rax
movq %rax, 0x3c8(%rsp)
movl 0x408(%rsp), %eax
movq 0x410(%rsp), %rcx
movq 0xa0(%rcx), %rcx
movq 0x8(%rcx), %rcx
movslq 0x3e4(%rsp), %rdx
movzbl (%rcx,%rdx), %ecx
subl %ecx, %eax
imull $0x3, %eax, %eax
cltq
movq %rax, 0x390(%rsp)
movq 0x390(%rsp), %rax
imulq 0x390(%rsp), %rax
addq 0x3c8(%rsp), %rax
movq %rax, 0x3c8(%rsp)
movl 0x404(%rsp), %eax
movq 0x410(%rsp), %rcx
movq 0xa0(%rcx), %rcx
movq 0x10(%rcx), %rcx
movslq 0x3e4(%rsp), %rdx
movzbl (%rcx,%rdx), %ecx
subl %ecx, %eax
shll $0x0, %eax
cltq
movq %rax, 0x388(%rsp)
movq 0x388(%rsp), %rax
imulq 0x388(%rsp), %rax
addq 0x3c8(%rsp), %rax
movq %rax, 0x3c8(%rsp)
movq 0x398(%rsp), %rax
shlq $0x5, %rax
addq $0x100, %rax            # imm = 0x100
movq %rax, 0x398(%rsp)
imulq $0x18, 0x390(%rsp), %rax
addq $0x90, %rax
movq %rax, 0x390(%rsp)
movq 0x388(%rsp), %rax
shlq $0x4, %rax
addq $0x40, %rax
movq %rax, 0x388(%rsp)
leaq -0x80(%rsp), %rax
movq %rax, 0x3d8(%rsp)
movq 0x420(%rsp), %rax
movq %rax, 0x3d0(%rsp)
movq 0x398(%rsp), %rax
movq %rax, 0x3b0(%rsp)
movl $0x3, 0x3f4(%rsp)
cmpl $0x0, 0x3f4(%rsp)
jl 0xf84b1
movq 0x3c8(%rsp), %rax
movq %rax, 0x3c0(%rsp)
movq 0x390(%rsp), %rax
movq %rax, 0x3a8(%rsp)
movl $0x7, 0x3f0(%rsp)
cmpl $0x0, 0x3f0(%rsp)
jl 0xf846d
movq 0x3c0(%rsp), %rax
movq %rax, 0x3b8(%rsp)
movq 0x388(%rsp), %rax
movq %rax, 0x3a0(%rsp)
movl $0x3, 0x3ec(%rsp)
cmpl $0x0, 0x3ec(%rsp)
jl 0xf8429
movq 0x3b8(%rsp), %rax
movq 0x3d8(%rsp), %rcx
cmpq (%rcx), %rax
jge 0xf83bd
movq 0x3b8(%rsp), %rcx
movq 0x3d8(%rsp), %rax
movq %rcx, (%rax)
movl 0x3e4(%rsp), %eax
movb %al, %cl
movq 0x3d0(%rsp), %rax
movb %cl, (%rax)
movq 0x3a0(%rsp), %rax
addq 0x3b8(%rsp), %rax
movq %rax, 0x3b8(%rsp)
movq 0x3a0(%rsp), %rax
addq $0x80, %rax
movq %rax, 0x3a0(%rsp)
movq 0x3d8(%rsp), %rax
addq $0x8, %rax
movq %rax, 0x3d8(%rsp)
movq 0x3d0(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x3d0(%rsp)
movl 0x3ec(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0x3ec(%rsp)
jmp 0xf8374
movq 0x3a8(%rsp), %rax
addq 0x3c0(%rsp), %rax
movq %rax, 0x3c0(%rsp)
movq 0x3a8(%rsp), %rax
addq $0x120, %rax            # imm = 0x120
movq %rax, 0x3a8(%rsp)
movl 0x3f0(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0x3f0(%rsp)
jmp 0xf833b
movq 0x3b0(%rsp), %rax
addq 0x3c8(%rsp), %rax
movq %rax, 0x3c8(%rsp)
movq 0x3b0(%rsp), %rax
addq $0x200, %rax            # imm = 0x200
movq %rax, 0x3b0(%rsp)
movl 0x3f4(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0x3f4(%rsp)
jmp 0xf8302
jmp 0xf84b3
movl 0x3e8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3e8(%rsp)
jmp 0xf815a
addq $0x418, %rsp            # imm = 0x418
retq
nopw %cs:(%rax,%rax)
nopl (%rax,%rax)