// File: tomfunkhouser[P]gaps/pkgs/png/pngwrite.c
// Function: png_set_filter_heuristics
void PNGAPI
png_set_filter_heuristics(png_structp png_ptr, int heuristic_method,
   int num_weights, png_doublep filter_weights,
   png_doublep filter_costs)
{
   int i;

   png_debug(1, "in png_set_filter_heuristics");

   if (png_ptr == NULL)
      return;
   if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST)
   {
      png_warning(png_ptr, "Unknown filter heuristic method");
      return;
   }

   if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT)
   {
      heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED;
   }

   if (num_weights < 0 || filter_weights == NULL ||
      heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED)
   {
      num_weights = 0;
   }

   png_ptr->num_prev_filters = (png_byte)num_weights;
   png_ptr->heuristic_method = (png_byte)heuristic_method;

   if (num_weights > 0)
   {
      if (png_ptr->prev_filters == NULL)
      {
         png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr,
            (png_uint_32)(png_sizeof(png_byte) * num_weights));

         /* To make sure that the weighting starts out fairly */
         for (i = 0; i < num_weights; i++)
         {
            png_ptr->prev_filters[i] = 255;
         }
      }

      if (png_ptr->filter_weights == NULL)
      {
         png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr,
            (png_uint_32)(png_sizeof(png_uint_16) * num_weights));

         png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr,
            (png_uint_32)(png_sizeof(png_uint_16) * num_weights));
         for (i = 0; i < num_weights; i++)
         {
            png_ptr->inv_filter_weights[i] =
            png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
         }
      }

      for (i = 0; i < num_weights; i++)
      {
         if (filter_weights[i] < 0.0)
         {
            png_ptr->inv_filter_weights[i] =
            png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
         }
         else
         {
            png_ptr->inv_filter_weights[i] =
               (png_uint_16)((double)PNG_WEIGHT_FACTOR*filter_weights[i]+0.5);
            png_ptr->filter_weights[i] =
               (png_uint_16)((double)PNG_WEIGHT_FACTOR/filter_weights[i]+0.5);
         }
      }
   }

   /* If, in the future, there are other filter methods, this would
    * need to be based on png_ptr->filter.
    */
   if (png_ptr->filter_costs == NULL)
   {
      png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr,
         (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST));

      png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr,
         (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST));

      for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
      {
         png_ptr->inv_filter_costs[i] =
         png_ptr->filter_costs[i] = PNG_COST_FACTOR;
      }
   }

   /* Here is where we set the relative costs of the different filters.  We
    * should take the desired compression level into account when setting
    * the costs, so that Paeth, for instance, has a high relative cost at low
    * compression levels, while it has a lower relative cost at higher
    * compression settings.  The filter types are in order of increasing
    * relative cost, so it would be possible to do this with an algorithm.
    */
   for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
   {
      if (filter_costs == NULL || filter_costs[i] < 0.0)
      {
         png_ptr->inv_filter_costs[i] =
         png_ptr->filter_costs[i] = PNG_COST_FACTOR;
      }
      else if (filter_costs[i] >= 1.0)
      {
         png_ptr->inv_filter_costs[i] =
            (png_uint_16)((double)PNG_COST_FACTOR / filter_costs[i] + 0.5);
         png_ptr->filter_costs[i] =
            (png_uint_16)((double)PNG_COST_FACTOR * filter_costs[i] + 0.5);
      }
   }
}

// Assembly:
subq $0x28, %rsp
movq %rdi, 0x20(%rsp)
movl %esi, 0x1c(%rsp)
movl %edx, 0x18(%rsp)
movq %rcx, 0x10(%rsp)
movq %r8, 0x8(%rsp)
cmpq $0x0, 0x20(%rsp)
jne 0x1049d8
jmp 0x104de7
cmpl $0x3, 0x1c(%rsp)
jl 0x1049f5
movq 0x20(%rsp), %rdi
leaq 0x34b1c(%rip), %rsi     # 0x139507
callq 0x113940
jmp 0x104de7
cmpl $0x0, 0x1c(%rsp)
jne 0x104a04
movl $0x1, 0x1c(%rsp)
cmpl $0x0, 0x18(%rsp)
jl 0x104a1a
cmpq $0x0, 0x10(%rsp)
je 0x104a1a
cmpl $0x1, 0x1c(%rsp)
jne 0x104a22
movl $0x0, 0x18(%rsp)
movl 0x18(%rsp), %eax
movb %al, %cl
movq 0x20(%rsp), %rax
movb %cl, 0x3a1(%rax)
movl 0x1c(%rsp), %eax
movb %al, %cl
movq 0x20(%rsp), %rax
movb %cl, 0x3a0(%rax)
cmpl $0x0, 0x18(%rsp)
jle 0x104c45
movq 0x20(%rsp), %rax
cmpq $0x0, 0x3a8(%rax)
jne 0x104aba
movq 0x20(%rsp), %rdi
movslq 0x18(%rsp), %rax
shlq $0x0, %rax
movl %eax, %eax
movl %eax, %esi
callq 0x1135b0
movq %rax, %rcx
movq 0x20(%rsp), %rax
movq %rcx, 0x3a8(%rax)
movl $0x0, 0x4(%rsp)
movl 0x4(%rsp), %eax
cmpl 0x18(%rsp), %eax
jge 0x104ab8
movq 0x20(%rsp), %rax
movq 0x3a8(%rax), %rax
movslq 0x4(%rsp), %rcx
movb $-0x1, (%rax,%rcx)
movl 0x4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4(%rsp)
jmp 0x104a8c
jmp 0x104aba
movq 0x20(%rsp), %rax
cmpq $0x0, 0x3b0(%rax)
jne 0x104b66
movq 0x20(%rsp), %rdi
movslq 0x18(%rsp), %rax
shlq %rax
movl %eax, %eax
movl %eax, %esi
callq 0x1135b0
movq %rax, %rcx
movq 0x20(%rsp), %rax
movq %rcx, 0x3b0(%rax)
movq 0x20(%rsp), %rdi
movslq 0x18(%rsp), %rax
shlq %rax
movl %eax, %eax
movl %eax, %esi
callq 0x1135b0
movq %rax, %rcx
movq 0x20(%rsp), %rax
movq %rcx, 0x3b8(%rax)
movl $0x0, 0x4(%rsp)
movl 0x4(%rsp), %eax
cmpl 0x18(%rsp), %eax
jge 0x104b64
movq 0x20(%rsp), %rax
movq 0x3b0(%rax), %rax
movslq 0x4(%rsp), %rcx
movw $0x100, (%rax,%rcx,2)   # imm = 0x100
movq 0x20(%rsp), %rax
movq 0x3b8(%rax), %rax
movslq 0x4(%rsp), %rcx
movw $0x100, (%rax,%rcx,2)   # imm = 0x100
movl 0x4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4(%rsp)
jmp 0x104b1f
jmp 0x104b66
movl $0x0, 0x4(%rsp)
movl 0x4(%rsp), %eax
cmpl 0x18(%rsp), %eax
jge 0x104c43
movq 0x10(%rsp), %rax
movslq 0x4(%rsp), %rcx
xorps %xmm0, %xmm0
ucomisd (%rax,%rcx,8), %xmm0
jbe 0x104bc0
movq 0x20(%rsp), %rax
movq 0x3b0(%rax), %rax
movslq 0x4(%rsp), %rcx
movw $0x100, (%rax,%rcx,2)   # imm = 0x100
movq 0x20(%rsp), %rax
movq 0x3b8(%rax), %rax
movslq 0x4(%rsp), %rcx
movw $0x100, (%rax,%rcx,2)   # imm = 0x100
jmp 0x104c31
movq 0x10(%rsp), %rax
movslq 0x4(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm2
movsd 0x347a1(%rip), %xmm0    # 0x139378
mulsd %xmm0, %xmm2
movsd 0x2e42d(%rip), %xmm1    # 0x133010
addsd %xmm1, %xmm2
cvttsd2si %xmm2, %eax
movw %ax, %dx
movq 0x20(%rsp), %rax
movq 0x3b8(%rax), %rax
movw %dx, (%rax,%rcx,2)
movq 0x10(%rsp), %rax
movslq 0x4(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm2
divsd %xmm2, %xmm0
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movw %ax, %dx
movq 0x20(%rsp), %rax
movq 0x3b0(%rax), %rax
movslq 0x4(%rsp), %rcx
movw %dx, (%rax,%rcx,2)
jmp 0x104c33
movl 0x4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4(%rsp)
jmp 0x104b6e
jmp 0x104c45
movq 0x20(%rsp), %rax
cmpq $0x0, 0x3c0(%rax)
jne 0x104ce0
movq 0x20(%rsp), %rdi
movl $0xa, %esi
callq 0x1135b0
movq %rax, %rcx
movq 0x20(%rsp), %rax
movq %rcx, 0x3c0(%rax)
movq 0x20(%rsp), %rdi
movl $0xa, %esi
callq 0x1135b0
movq %rax, %rcx
movq 0x20(%rsp), %rax
movq %rcx, 0x3c8(%rax)
movl $0x0, 0x4(%rsp)
cmpl $0x5, 0x4(%rsp)
jge 0x104cde
movq 0x20(%rsp), %rax
movq 0x3c0(%rax), %rax
movslq 0x4(%rsp), %rcx
movw $0x8, (%rax,%rcx,2)
movq 0x20(%rsp), %rax
movq 0x3c8(%rax), %rax
movslq 0x4(%rsp), %rcx
movw $0x8, (%rax,%rcx,2)
movl 0x4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4(%rsp)
jmp 0x104c9c
jmp 0x104ce0
movl $0x0, 0x4(%rsp)
cmpl $0x5, 0x4(%rsp)
jge 0x104de7
cmpq $0x0, 0x8(%rsp)
je 0x104d0f
movq 0x8(%rsp), %rax
movslq 0x4(%rsp), %rcx
xorps %xmm0, %xmm0
ucomisd (%rax,%rcx,8), %xmm0
jbe 0x104d42
movq 0x20(%rsp), %rax
movq 0x3c0(%rax), %rax
movslq 0x4(%rsp), %rcx
movw $0x8, (%rax,%rcx,2)
movq 0x20(%rsp), %rax
movq 0x3c8(%rax), %rax
movslq 0x4(%rsp), %rcx
movw $0x8, (%rax,%rcx,2)
jmp 0x104dd5
movq 0x8(%rsp), %rax
movslq 0x4(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
movsd 0x2e2af(%rip), %xmm1    # 0x133008
ucomisd %xmm1, %xmm0
jb 0x104dd3
movq 0x8(%rsp), %rax
movslq 0x4(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm1
movsd 0x2e482(%rip), %xmm2    # 0x1331f8
movaps %xmm2, %xmm0
divsd %xmm1, %xmm0
movsd 0x2e28b(%rip), %xmm1    # 0x133010
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movw %ax, %dx
movq 0x20(%rsp), %rax
movq 0x3c8(%rax), %rax
movw %dx, (%rax,%rcx,2)
movq 0x8(%rsp), %rax
movslq 0x4(%rsp), %rcx
movsd (%rax,%rcx,8), %xmm0
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
cvttsd2si %xmm0, %eax
movw %ax, %dx
movq 0x20(%rsp), %rax
movq 0x3c0(%rax), %rax
movslq 0x4(%rsp), %rcx
movw %dx, (%rax,%rcx,2)
jmp 0x104dd5
jmp 0x104dd7
movl 0x4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4(%rsp)
jmp 0x104ce8
addq $0x28, %rsp
retq
nopl (%rax)