// File: /workspace/github_c_makefile_star2_O0/zpole[P]IICV/vl/kmeans.c
// Function: vl_kmeans_refine_centers_ann_f
static double
VL_XCAT(_vl_kmeans_refine_centers_ann_, SFX)
(VlKMeans * self,
 TYPE const * data,
 vl_size numData)
{
  vl_size c, d, x, iteration ;
  double initialEnergy = VL_INFINITY_D ;
  double previousEnergy = VL_INFINITY_D ;
  double energy ;

  vl_uint32 * permutations = NULL ;
  vl_size * numSeenSoFar = NULL ;
  VlRand * rand = vl_get_rand () ;
  vl_size totNumRestartedCenters = 0 ;
  vl_size numRestartedCenters = 0 ;

  vl_uint32 * assignments = vl_malloc (sizeof(vl_uint32) * numData) ;
  vl_size * clusterMasses = vl_malloc (sizeof(vl_size) * numData) ;
  TYPE * distances = vl_malloc (sizeof(TYPE) * numData) ;

  if (self->distance == VlDistanceL1) {
    permutations = vl_malloc(sizeof(vl_uint32) * numData * self->dimension) ;
    numSeenSoFar = vl_malloc(sizeof(vl_size) * self->numCenters) ;
    VL_XCAT(_vl_kmeans_sort_data_helper_, SFX)(self, permutations, data, numData) ;
  }

  for (energy = VL_INFINITY_D,
       iteration = 0;
       1 ;
       ++ iteration) {

    /* assign data to cluters */
    VL_XCAT(_vl_kmeans_quantize_ann_, SFX)(self, assignments, distances, data, numData, iteration > 0) ;

    /* compute energy */
    energy = 0 ;
    for (x = 0 ; x < numData ; ++x) energy += distances[x] ;
    if (self->verbosity) {
      VL_PRINTF("kmeans: ANN iter %d: energy = %g\n", iteration,
                energy) ;
    }

    /* check termination conditions */
    if (iteration >= self->maxNumIterations) {
      if (self->verbosity) {
        VL_PRINTF("kmeans: ANN terminating because the maximum number of iterations has been reached\n") ;
      }
      break ;
    }
    if (energy == previousEnergy) {
      if (self->verbosity) {
        VL_PRINTF("kmeans: ANN terminating because the algorithm fully converged\n") ;
      }
      break ;
    }
    
    if (iteration == 0) {
      initialEnergy = energy ;
    } else {
      double eps = (previousEnergy - energy) / (initialEnergy - energy) ;
      if (eps < self->minEnergyVariation) {
        if (self->verbosity) {
          VL_PRINTF("kmeans: ANN terminating because the energy relative variation was less than %f\n", self->minEnergyVariation) ;
        }
        break ;
      }
    }

    /* begin next iteration */
    previousEnergy = energy ;

    /* update clusters */
    memset(clusterMasses, 0, sizeof(vl_size) * numData) ;
    for (x = 0 ; x < numData ; ++x) {
      clusterMasses[assignments[x]] ++ ;
    }

    numRestartedCenters = 0 ;
    switch (self->distance) {
      case VlDistanceL2:
        memset(self->centers, 0, sizeof(TYPE) * self->dimension * self->numCenters) ;
        for (x = 0 ; x < numData ; ++x) {
          TYPE * cpt = (TYPE*)self->centers + assignments[x] * self->dimension ;
          TYPE const * xpt = data + x * self->dimension ;
          for (d = 0 ; d < self->dimension ; ++d) {
            cpt[d] += xpt[d] ;
          }
        }
        for (c = 0 ; c < self->numCenters ; ++c) {
          TYPE * cpt = (TYPE*)self->centers + c * self->dimension ;
          if (clusterMasses[c] > 0) {
            TYPE mass = clusterMasses[c] ;
            for (d = 0 ; d < self->dimension ; ++d) {
              cpt[d] /= mass ;
            }
          } else {
            vl_uindex x = vl_rand_uindex(rand, numData) ;
            numRestartedCenters ++ ;
            for (d = 0 ; d < self->dimension ; ++d) {
              cpt[d] = data[x * self->dimension + d] ;
            }
          }
        }
        break ;
      case VlDistanceL1:
        for (d = 0 ; d < self->dimension ; ++d) {
          vl_uint32 * perm = permutations + d * numData ;
          memset(numSeenSoFar, 0, sizeof(vl_size) * self->numCenters) ;
          for (x = 0; x < numData ; ++x) {
            c = assignments[perm[x]] ;
            if (2 * numSeenSoFar[c] < clusterMasses[c]) {
              ((TYPE*)self->centers) [d + c * self->dimension] =
                data [d + perm[x] * self->dimension] ;
            }
            numSeenSoFar[c] ++ ;
          }
          /* restart the centers as required  */
          for (c = 0 ; c < self->numCenters ; ++c) {
            if (clusterMasses[c] == 0) {
              TYPE * cpt = (TYPE*)self->centers + c * self->dimension ;
              vl_uindex x = vl_rand_uindex(rand, numData) ;
              numRestartedCenters ++ ;
              for (d = 0 ; d < self->dimension ; ++d) {
                cpt[d] = data[x * self->dimension + d] ;
              }
            }
          }
        }
        break ;
      default:
        VL_PRINT("bad distance set: %d\n",self->distance);
        abort();
    } /* done compute centers */

    totNumRestartedCenters += numRestartedCenters ;
    if (self->verbosity && numRestartedCenters) {
      VL_PRINTF("kmeans: ANN iter %d: restarted %d centers\n", iteration,
                numRestartedCenters) ;
    }
  }

  if (permutations) {
    vl_free(permutations) ;
  }
  if (numSeenSoFar) {
    vl_free(numSeenSoFar) ;
  }

  vl_free(distances) ;
  vl_free(assignments) ;
  vl_free(clusterMasses) ;
  return energy ;
}

// Assembly:
subq $0xe8, %rsp
movq %rdi, 0xe0(%rsp)
movq %rsi, 0xd8(%rsp)
movq %rdx, 0xd0(%rsp)
movsd 0x26759(%rip), %xmm0    # 0x59a20
movsd %xmm0, 0xa8(%rsp)
movsd 0x26748(%rip), %xmm0    # 0x59a20
movsd %xmm0, 0xa0(%rsp)
movq $0x0, 0x90(%rsp)
movq $0x0, 0x88(%rsp)
callq 0x9a20
movq %rax, 0x80(%rsp)
movq $0x0, 0x78(%rsp)
movq $0x0, 0x70(%rsp)
movq 0xd0(%rsp), %rdi
shlq $0x2, %rdi
callq 0x9660
movq %rax, 0x68(%rsp)
movq 0xd0(%rsp), %rdi
shlq $0x3, %rdi
callq 0x9660
movq %rax, 0x60(%rsp)
movq 0xd0(%rsp), %rdi
shlq $0x2, %rdi
callq 0x9660
movq %rax, 0x58(%rsp)
movq 0xe0(%rsp), %rax
cmpl $0x0, 0x30(%rax)
jne 0x333d0
movq 0xd0(%rsp), %rdi
shlq $0x2, %rdi
movq 0xe0(%rsp), %rax
imulq 0x8(%rax), %rdi
callq 0x9660
movq %rax, 0x90(%rsp)
movq 0xe0(%rsp), %rax
movq 0x10(%rax), %rdi
shlq $0x3, %rdi
callq 0x9660
movq %rax, 0x88(%rsp)
movq 0xe0(%rsp), %rdi
movq 0x90(%rsp), %rsi
movq 0xd8(%rsp), %rdx
movq 0xd0(%rsp), %rcx
callq 0x33d30
movsd 0x26648(%rip), %xmm0    # 0x59a20
movsd %xmm0, 0x98(%rsp)
movq $0x0, 0xb0(%rsp)
movb $0x1, %al
testb $0x1, %al
jne 0x333f8
jmp 0x33cc6
movq 0xe0(%rsp), %rdi
movq 0x68(%rsp), %rsi
movq 0x58(%rsp), %rdx
movq 0xd8(%rsp), %rcx
movq 0xd0(%rsp), %r8
cmpq $0x0, 0xb0(%rsp)
seta %al
andb $0x1, %al
movzbl %al, %r9d
callq 0x2fec0
xorps %xmm0, %xmm0
movsd %xmm0, 0x98(%rsp)
movq $0x0, 0xb8(%rsp)
movq 0xb8(%rsp), %rax
cmpq 0xd0(%rsp), %rax
jae 0x33499
movq 0x58(%rsp), %rax
movq 0xb8(%rsp), %rcx
movss (%rax,%rcx,4), %xmm0
cvtss2sd %xmm0, %xmm0
addsd 0x98(%rsp), %xmm0
movsd %xmm0, 0x98(%rsp)
movq 0xb8(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xb8(%rsp)
jmp 0x33449
movq 0xe0(%rsp), %rax
cmpl $0x0, 0x50(%rax)
je 0x334cb
callq 0x91a0
movq %rax, %rcx
movq 0xb0(%rsp), %rsi
movsd 0x98(%rsp), %xmm0
leaq 0x269bf(%rip), %rdi     # 0x59e86
movb $0x1, %al
callq *%rcx
movq 0xb0(%rsp), %rax
movq 0xe0(%rsp), %rcx
cmpq 0x38(%rcx), %rax
jb 0x33507
movq 0xe0(%rsp), %rax
cmpl $0x0, 0x50(%rax)
je 0x33502
callq 0x91a0
movq %rax, %rcx
leaq 0x269aa(%rip), %rdi     # 0x59ea8
movb $0x0, %al
callq *%rcx
jmp 0x33cc6
movsd 0x98(%rsp), %xmm0
ucomisd 0xa0(%rsp), %xmm0
jne 0x33543
jp 0x33543
movq 0xe0(%rsp), %rax
cmpl $0x0, 0x50(%rax)
je 0x3353e
callq 0x91a0
movq %rax, %rcx
leaq 0x269c1(%rip), %rdi     # 0x59efb
movb $0x0, %al
callq *%rcx
jmp 0x33cc6
cmpq $0x0, 0xb0(%rsp)
jne 0x33562
movsd 0x98(%rsp), %xmm0
movsd %xmm0, 0xa8(%rsp)
jmp 0x335de
movsd 0xa0(%rsp), %xmm0
subsd 0x98(%rsp), %xmm0
movsd 0xa8(%rsp), %xmm1
subsd 0x98(%rsp), %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, 0x50(%rsp)
movsd 0x50(%rsp), %xmm1
movq 0xe0(%rsp), %rax
movsd 0x40(%rax), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x335dc
movq 0xe0(%rsp), %rax
cmpl $0x0, 0x50(%rax)
je 0x335d7
callq 0x91a0
movq %rax, %rcx
movq 0xe0(%rsp), %rax
movsd 0x40(%rax), %xmm0
leaq 0x2657b(%rip), %rdi     # 0x59b4e
movb $0x1, %al
callq *%rcx
jmp 0x33cc6
jmp 0x335de
movsd 0x98(%rsp), %xmm0
movsd %xmm0, 0xa0(%rsp)
movq 0x60(%rsp), %rdi
movq 0xd0(%rsp), %rdx
shlq $0x3, %rdx
xorl %esi, %esi
callq 0x9480
movq $0x0, 0xb8(%rsp)
movq 0xb8(%rsp), %rax
cmpq 0xd0(%rsp), %rax
jae 0x3365d
movq 0x60(%rsp), %rax
movq 0x68(%rsp), %rcx
movq 0xb8(%rsp), %rdx
movl (%rcx,%rdx,4), %ecx
movq (%rax,%rcx,8), %rdx
addq $0x1, %rdx
movq %rdx, (%rax,%rcx,8)
movq 0xb8(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xb8(%rsp)
jmp 0x33614
movq $0x0, 0x70(%rsp)
movq 0xe0(%rsp), %rax
movl 0x30(%rax), %eax
movl %eax, 0xc(%rsp)
testl %eax, %eax
je 0x33994
jmp 0x3367f
movl 0xc(%rsp), %eax
subl $0x1, %eax
jne 0x33c43
jmp 0x3368e
movq 0xe0(%rsp), %rax
movq 0x58(%rax), %rdi
movq 0xe0(%rsp), %rax
movq 0x8(%rax), %rdx
shlq $0x2, %rdx
movq 0xe0(%rsp), %rax
imulq 0x10(%rax), %rdx
xorl %esi, %esi
callq 0x9480
movq $0x0, 0xb8(%rsp)
movq 0xb8(%rsp), %rax
cmpq 0xd0(%rsp), %rax
jae 0x337ba
movq 0xe0(%rsp), %rax
movq 0x58(%rax), %rax
movq 0x68(%rsp), %rcx
movq 0xb8(%rsp), %rdx
movl (%rcx,%rdx,4), %ecx
movq 0xe0(%rsp), %rdx
imulq 0x8(%rdx), %rcx
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, 0x48(%rsp)
movq 0xd8(%rsp), %rax
movq 0xb8(%rsp), %rcx
movq 0xe0(%rsp), %rdx
imulq 0x8(%rdx), %rcx
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, 0x40(%rsp)
movq $0x0, 0xc0(%rsp)
movq 0xc0(%rsp), %rax
movq 0xe0(%rsp), %rcx
cmpq 0x8(%rcx), %rax
jae 0x3379f
movq 0x40(%rsp), %rax
movq 0xc0(%rsp), %rcx
movss (%rax,%rcx,4), %xmm0
movq 0x48(%rsp), %rax
movq 0xc0(%rsp), %rcx
addss (%rax,%rcx,4), %xmm0
movss %xmm0, (%rax,%rcx,4)
movq 0xc0(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xc0(%rsp)
jmp 0x3374a
jmp 0x337a1
movq 0xb8(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xb8(%rsp)
jmp 0x336ca
movq $0x0, 0xc8(%rsp)
movq 0xc8(%rsp), %rax
movq 0xe0(%rsp), %rcx
cmpq 0x10(%rcx), %rax
jae 0x3398f
movq 0xe0(%rsp), %rax
movq 0x58(%rax), %rax
movq 0xc8(%rsp), %rcx
movq 0xe0(%rsp), %rdx
imulq 0x8(%rdx), %rcx
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, 0x38(%rsp)
movq 0x60(%rsp), %rax
movq 0xc8(%rsp), %rcx
cmpq $0x0, (%rax,%rcx,8)
jbe 0x338d9
movq 0x60(%rsp), %rax
movq 0xc8(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, %rdx
shrq %rdx
movl %eax, %ecx
andl $0x1, %ecx
orq %rdx, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
cvtsi2ss %rax, %xmm1
movss %xmm1, 0x4(%rsp)
testq %rax, %rax
movss %xmm0, 0x8(%rsp)
js 0x3386f
movss 0x4(%rsp), %xmm0
movss %xmm0, 0x8(%rsp)
movss 0x8(%rsp), %xmm0
movss %xmm0, 0x34(%rsp)
movq $0x0, 0xc0(%rsp)
movq 0xc0(%rsp), %rax
movq 0xe0(%rsp), %rcx
cmpq 0x8(%rcx), %rax
jae 0x338d4
movss 0x34(%rsp), %xmm1
movq 0x38(%rsp), %rax
movq 0xc0(%rsp), %rcx
movss (%rax,%rcx,4), %xmm0
divss %xmm1, %xmm0
movss %xmm0, (%rax,%rcx,4)
movq 0xc0(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xc0(%rsp)
jmp 0x33887
jmp 0x33974
movq 0x80(%rsp), %rdi
movq 0xd0(%rsp), %rsi
callq 0x30770
movq %rax, 0x28(%rsp)
movq 0x70(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x70(%rsp)
movq $0x0, 0xc0(%rsp)
movq 0xc0(%rsp), %rax
movq 0xe0(%rsp), %rcx
cmpq 0x8(%rcx), %rax
jae 0x33972
movq 0xd8(%rsp), %rax
movq 0x28(%rsp), %rcx
movq 0xe0(%rsp), %rdx
imulq 0x8(%rdx), %rcx
addq 0xc0(%rsp), %rcx
movss (%rax,%rcx,4), %xmm0
movq 0x38(%rsp), %rax
movq 0xc0(%rsp), %rcx
movss %xmm0, (%rax,%rcx,4)
movq 0xc0(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xc0(%rsp)
jmp 0x3390d
jmp 0x33974
jmp 0x33976
movq 0xc8(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xc8(%rsp)
jmp 0x337c6
jmp 0x33c66
movq $0x0, 0xc0(%rsp)
movq 0xc0(%rsp), %rax
movq 0xe0(%rsp), %rcx
cmpq 0x8(%rcx), %rax
jae 0x33c41
movq 0x90(%rsp), %rax
movq 0xc0(%rsp), %rcx
imulq 0xd0(%rsp), %rcx
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, 0x20(%rsp)
movq 0x88(%rsp), %rdi
movq 0xe0(%rsp), %rax
movq 0x10(%rax), %rdx
shlq $0x3, %rdx
xorl %esi, %esi
callq 0x9480
movq $0x0, 0xb8(%rsp)
movq 0xb8(%rsp), %rax
cmpq 0xd0(%rsp), %rax
jae 0x33b05
movq 0x68(%rsp), %rax
movq 0x20(%rsp), %rcx
movq 0xb8(%rsp), %rdx
movl (%rcx,%rdx,4), %ecx
movl (%rax,%rcx,4), %eax
movq %rax, 0xc8(%rsp)
movq 0x88(%rsp), %rax
movq 0xc8(%rsp), %rcx
movq (%rax,%rcx,8), %rax
shlq %rax
movq 0x60(%rsp), %rcx
movq 0xc8(%rsp), %rdx
cmpq (%rcx,%rdx,8), %rax
jae 0x33ad0
movq 0xd8(%rsp), %rax
movq 0xc0(%rsp), %rcx
movq 0x20(%rsp), %rdx
movq 0xb8(%rsp), %rsi
movl (%rdx,%rsi,4), %edx
movq 0xe0(%rsp), %rsi
imulq 0x8(%rsi), %rdx
addq %rdx, %rcx
movss (%rax,%rcx,4), %xmm0
movq 0xe0(%rsp), %rax
movq 0x58(%rax), %rax
movq 0xc0(%rsp), %rcx
movq 0xc8(%rsp), %rdx
movq 0xe0(%rsp), %rsi
imulq 0x8(%rsi), %rdx
addq %rdx, %rcx
movss %xmm0, (%rax,%rcx,4)
movq 0x88(%rsp), %rax
movq 0xc8(%rsp), %rcx
movq (%rax,%rcx,8), %rdx
addq $0x1, %rdx
movq %rdx, (%rax,%rcx,8)
movq 0xb8(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xb8(%rsp)
jmp 0x33a0a
movq $0x0, 0xc8(%rsp)
movq 0xc8(%rsp), %rax
movq 0xe0(%rsp), %rcx
cmpq 0x10(%rcx), %rax
jae 0x33c26
movq 0x60(%rsp), %rax
movq 0xc8(%rsp), %rcx
cmpq $0x0, (%rax,%rcx,8)
jne 0x33c0b
movq 0xe0(%rsp), %rax
movq 0x58(%rax), %rax
movq 0xc8(%rsp), %rcx
movq 0xe0(%rsp), %rdx
imulq 0x8(%rdx), %rcx
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, 0x18(%rsp)
movq 0x80(%rsp), %rdi
movq 0xd0(%rsp), %rsi
callq 0x30770
movq %rax, 0x10(%rsp)
movq 0x70(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x70(%rsp)
movq $0x0, 0xc0(%rsp)
movq 0xc0(%rsp), %rax
movq 0xe0(%rsp), %rcx
cmpq 0x8(%rcx), %rax
jae 0x33c09
movq 0xd8(%rsp), %rax
movq 0x10(%rsp), %rcx
movq 0xe0(%rsp), %rdx
imulq 0x8(%rdx), %rcx
addq 0xc0(%rsp), %rcx
movss (%rax,%rcx,4), %xmm0
movq 0x18(%rsp), %rax
movq 0xc0(%rsp), %rcx
movss %xmm0, (%rax,%rcx,4)
movq 0xc0(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xc0(%rsp)
jmp 0x33ba4
jmp 0x33c0b
jmp 0x33c0d
movq 0xc8(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xc8(%rsp)
jmp 0x33b11
jmp 0x33c28
movq 0xc0(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xc0(%rsp)
jmp 0x339a0
jmp 0x33c66
callq 0x91a0
movq %rax, %rcx
movq 0xe0(%rsp), %rax
movl 0x30(%rax), %esi
leaq 0x262dd(%rip), %rdi     # 0x59f3a
movb $0x0, %al
callq *%rcx
callq 0x90b0
movq 0x70(%rsp), %rax
addq 0x78(%rsp), %rax
movq %rax, 0x78(%rsp)
movq 0xe0(%rsp), %rax
cmpl $0x0, 0x50(%rax)
je 0x33cab
cmpq $0x0, 0x70(%rsp)
je 0x33cab
callq 0x91a0
movq %rax, %rcx
movq 0xb0(%rsp), %rsi
movq 0x70(%rsp), %rdx
leaq 0x262a9(%rip), %rdi     # 0x59f50
movb $0x0, %al
callq *%rcx
jmp 0x33cad
movq 0xb0(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xb0(%rsp)
jmp 0x333ed
cmpq $0x0, 0x90(%rsp)
je 0x33cde
movq 0x90(%rsp), %rdi
callq 0x9620
cmpq $0x0, 0x88(%rsp)
je 0x33cf6
movq 0x88(%rsp), %rdi
callq 0x9620
movq 0x58(%rsp), %rdi
callq 0x9620
movq 0x68(%rsp), %rdi
callq 0x9620
movq 0x60(%rsp), %rdi
callq 0x9620
movsd 0x98(%rsp), %xmm0
addq $0xe8, %rsp
retq
nopw %cs:(%rax,%rax)