// File: tomfunkhouser[P]gaps/pkgs/jpeg/jquant2.c
// Function: median_cut
LOCAL(int)
median_cut (j_decompress_ptr cinfo, boxptr boxlist, int numboxes,
	    int desired_colors)
/* Repeatedly select and split the largest box until we have enough boxes */
{
  int n,lb;
  int c0,c1,c2,cmax;
  register boxptr b1,b2;

  while (numboxes < desired_colors) {
    /* Select box to split.
     * Current algorithm: by population for first half, then by volume.
     */
    if (numboxes*2 <= desired_colors) {
      b1 = find_biggest_color_pop(boxlist, numboxes);
    } else {
      b1 = find_biggest_volume(boxlist, numboxes);
    }
    if (b1 == NULL)		/* no splittable boxes left! */
      break;
    b2 = &boxlist[numboxes];	/* where new box will go */
    /* Copy the color bounds to the new box. */
    b2->c0max = b1->c0max; b2->c1max = b1->c1max; b2->c2max = b1->c2max;
    b2->c0min = b1->c0min; b2->c1min = b1->c1min; b2->c2min = b1->c2min;
    /* Choose which axis to split the box on.
     * Current algorithm: longest scaled axis.
     * See notes in update_box about scaling distances.
     */
    c0 = ((b1->c0max - b1->c0min) << C0_SHIFT) * C0_SCALE;
    c1 = ((b1->c1max - b1->c1min) << C1_SHIFT) * C1_SCALE;
    c2 = ((b1->c2max - b1->c2min) << C2_SHIFT) * C2_SCALE;
    /* We want to break any ties in favor of green, then red, blue last.
     * This code does the right thing for R,G,B or B,G,R color orders only.
     */
#if RGB_RED == 0
    cmax = c1; n = 1;
    if (c0 > cmax) { cmax = c0; n = 0; }
    if (c2 > cmax) { n = 2; }
#else
    cmax = c1; n = 1;
    if (c2 > cmax) { cmax = c2; n = 2; }
    if (c0 > cmax) { n = 0; }
#endif
    /* Choose split point along selected axis, and update box bounds.
     * Current algorithm: split at halfway point.
     * (Since the box has been shrunk to minimum volume,
     * any split will produce two nonempty subboxes.)
     * Note that lb value is max for lower box, so must be < old max.
     */
    switch (n) {
    case 0:
      lb = (b1->c0max + b1->c0min) / 2;
      b1->c0max = lb;
      b2->c0min = lb+1;
      break;
    case 1:
      lb = (b1->c1max + b1->c1min) / 2;
      b1->c1max = lb;
      b2->c1min = lb+1;
      break;
    case 2:
      lb = (b1->c2max + b1->c2min) / 2;
      b1->c2max = lb;
      b2->c2min = lb+1;
      break;
    }
    /* Update stats for boxes */
    update_box(cinfo, b1);
    update_box(cinfo, b2);
    numboxes++;
  }
  return numboxes;
}

// Assembly:
subq $0x48, %rsp
movq %rdi, 0x40(%rsp)
movq %rsi, 0x38(%rsp)
movl %edx, 0x34(%rsp)
movl %ecx, 0x30(%rsp)
movl 0x34(%rsp), %eax
cmpl 0x30(%rsp), %eax
jge 0xf73ad
movl 0x34(%rsp), %eax
shll %eax
cmpl 0x30(%rsp), %eax
jg 0xf7195
movq 0x38(%rsp), %rdi
movl 0x34(%rsp), %esi
callq 0xf7610
movq %rax, 0x10(%rsp)
jmp 0xf71a8
movq 0x38(%rsp), %rdi
movl 0x34(%rsp), %esi
callq 0xf76a0
movq %rax, 0x10(%rsp)
cmpq $0x0, 0x10(%rsp)
jne 0xf71b5
jmp 0xf73ad
movq 0x38(%rsp), %rax
movslq 0x34(%rsp), %rcx
imulq $0x28, %rcx, %rcx
addq %rcx, %rax
movq %rax, 0x8(%rsp)
movq 0x10(%rsp), %rax
movl 0x4(%rax), %ecx
movq 0x8(%rsp), %rax
movl %ecx, 0x4(%rax)
movq 0x10(%rsp), %rax
movl 0xc(%rax), %ecx
movq 0x8(%rsp), %rax
movl %ecx, 0xc(%rax)
movq 0x10(%rsp), %rax
movl 0x14(%rax), %ecx
movq 0x8(%rsp), %rax
movl %ecx, 0x14(%rax)
movq 0x10(%rsp), %rax
movl (%rax), %ecx
movq 0x8(%rsp), %rax
movl %ecx, (%rax)
movq 0x10(%rsp), %rax
movl 0x8(%rax), %ecx
movq 0x8(%rsp), %rax
movl %ecx, 0x8(%rax)
movq 0x10(%rsp), %rax
movl 0x10(%rax), %ecx
movq 0x8(%rsp), %rax
movl %ecx, 0x10(%rax)
movq 0x10(%rsp), %rax
movl 0x4(%rax), %eax
movq 0x10(%rsp), %rcx
subl (%rcx), %eax
shll $0x3, %eax
shll %eax
movl %eax, 0x24(%rsp)
movq 0x10(%rsp), %rax
movl 0xc(%rax), %eax
movq 0x10(%rsp), %rcx
subl 0x8(%rcx), %eax
shll $0x2, %eax
imull $0x3, %eax, %eax
movl %eax, 0x20(%rsp)
movq 0x10(%rsp), %rax
movl 0x14(%rax), %eax
movq 0x10(%rsp), %rcx
subl 0x10(%rcx), %eax
shll $0x3, %eax
shll $0x0, %eax
movl %eax, 0x1c(%rsp)
movl 0x20(%rsp), %eax
movl %eax, 0x18(%rsp)
movl $0x1, 0x2c(%rsp)
movl 0x24(%rsp), %eax
cmpl 0x18(%rsp), %eax
jle 0xf729f
movl 0x24(%rsp), %eax
movl %eax, 0x18(%rsp)
movl $0x0, 0x2c(%rsp)
movl 0x1c(%rsp), %eax
cmpl 0x18(%rsp), %eax
jle 0xf72b1
movl $0x2, 0x2c(%rsp)
movl 0x2c(%rsp), %eax
movl %eax, 0x4(%rsp)
testl %eax, %eax
je 0xf72d8
jmp 0xf72bf
movl 0x4(%rsp), %eax
subl $0x1, %eax
je 0xf730f
jmp 0xf72ca
movl 0x4(%rsp), %eax
subl $0x2, %eax
je 0xf7348
jmp 0xf737f
movq 0x10(%rsp), %rax
movl 0x4(%rax), %eax
movq 0x10(%rsp), %rcx
addl (%rcx), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, 0x28(%rsp)
movl 0x28(%rsp), %ecx
movq 0x10(%rsp), %rax
movl %ecx, 0x4(%rax)
movl 0x28(%rsp), %ecx
addl $0x1, %ecx
movq 0x8(%rsp), %rax
movl %ecx, (%rax)
jmp 0xf737f
movq 0x10(%rsp), %rax
movl 0xc(%rax), %eax
movq 0x10(%rsp), %rcx
addl 0x8(%rcx), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, 0x28(%rsp)
movl 0x28(%rsp), %ecx
movq 0x10(%rsp), %rax
movl %ecx, 0xc(%rax)
movl 0x28(%rsp), %ecx
addl $0x1, %ecx
movq 0x8(%rsp), %rax
movl %ecx, 0x8(%rax)
jmp 0xf737f
movq 0x10(%rsp), %rax
movl 0x14(%rax), %eax
movq 0x10(%rsp), %rcx
addl 0x10(%rcx), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, 0x28(%rsp)
movl 0x28(%rsp), %ecx
movq 0x10(%rsp), %rax
movl %ecx, 0x14(%rax)
movl 0x28(%rsp), %ecx
addl $0x1, %ecx
movq 0x8(%rsp), %rax
movl %ecx, 0x10(%rax)
movq 0x40(%rsp), %rdi
movq 0x10(%rsp), %rsi
callq 0xf6a80
movq 0x40(%rsp), %rdi
movq 0x8(%rsp), %rsi
callq 0xf6a80
movl 0x34(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x34(%rsp)
jmp 0xf7166
movl 0x34(%rsp), %eax
addq $0x48, %rsp
retq
nopw %cs:(%rax,%rax)