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

  vl_uint32 * assignments = vl_malloc (sizeof(vl_uint32) * numData) ;
  vl_size * clusterMasses = vl_malloc (sizeof(vl_size) * numData) ;
  vl_uint32 * permutations = NULL ;
  vl_size * numSeenSoFar = NULL ;
  VlRand * rand = vl_get_rand () ;
  vl_size totNumRestartedCenters = 0 ;
  vl_size numRestartedCenters = 0 ;

  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_, SFX)(self, assignments, distances, data, numData) ;

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

    /* check termination conditions */
    if (iteration >= self->maxNumIterations) {
      if (self->verbosity) {
        VL_PRINTF("kmeans: Lloyd terminating because maximum number of iterations reached\n") ;
      }
      break ;
    }
    if (energy == previousEnergy) {
      if (self->verbosity) {
        VL_PRINTF("kmeans: Lloyd 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:
        abort();
    } /* done compute centers */

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

  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 0x29159(%rip), %xmm0    # 0x59a20
movsd %xmm0, 0xa8(%rsp)
movsd 0x29148(%rip), %xmm0    # 0x59a20
movsd %xmm0, 0xa0(%rsp)
movq 0xd0(%rsp), %rdi
shlq $0x2, %rdi
callq 0x9660
movq %rax, 0x90(%rsp)
movq 0xd0(%rsp), %rdi
shlq $0x2, %rdi
callq 0x9660
movq %rax, 0x88(%rsp)
movq 0xd0(%rsp), %rdi
shlq $0x3, %rdi
callq 0x9660
movq %rax, 0x80(%rsp)
movq $0x0, 0x78(%rsp)
movq $0x0, 0x70(%rsp)
callq 0x9a20
movq %rax, 0x68(%rsp)
movq $0x0, 0x60(%rsp)
movq $0x0, 0x58(%rsp)
movq 0xe0(%rsp), %rax
cmpl $0x0, 0x30(%rax)
jne 0x309c7
movq 0xd0(%rsp), %rdi
shlq $0x2, %rdi
movq 0xe0(%rsp), %rax
imulq 0x8(%rax), %rdi
callq 0x9660
movq %rax, 0x78(%rsp)
movq 0xe0(%rsp), %rax
movq 0x10(%rax), %rdi
shlq $0x3, %rdi
callq 0x9660
movq %rax, 0x70(%rsp)
movq 0xe0(%rsp), %rdi
movq 0x78(%rsp), %rsi
movq 0xd8(%rsp), %rdx
movq 0xd0(%rsp), %rcx
callq 0x33d30
movsd 0x29051(%rip), %xmm0    # 0x59a20
movsd %xmm0, 0x98(%rsp)
movq $0x0, 0xb0(%rsp)
movb $0x1, %al
testb $0x1, %al
jne 0x309ef
jmp 0x3129f
movq 0xe0(%rsp), %rdi
movq 0x88(%rsp), %rsi
movq 0x90(%rsp), %rdx
movq 0xd8(%rsp), %rcx
movq 0xd0(%rsp), %r8
callq 0x2fb20
xorps %xmm0, %xmm0
movsd %xmm0, 0x98(%rsp)
movq $0x0, 0xb8(%rsp)
movq 0xb8(%rsp), %rax
cmpq 0xd0(%rsp), %rax
jae 0x30a87
movq 0x90(%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 0x30a34
movq 0xe0(%rsp), %rax
cmpl $0x0, 0x50(%rax)
je 0x30ab9
callq 0x91a0
movq %rax, %rcx
movq 0xb0(%rsp), %rsi
movsd 0x98(%rsp), %xmm0
leaq 0x28fec(%rip), %rdi     # 0x59aa1
movb $0x1, %al
callq *%rcx
movq 0xb0(%rsp), %rax
movq 0xe0(%rsp), %rcx
cmpq 0x38(%rcx), %rax
jb 0x30af5
movq 0xe0(%rsp), %rax
cmpl $0x0, 0x50(%rax)
je 0x30af0
callq 0x91a0
movq %rax, %rcx
leaq 0x28fd9(%rip), %rdi     # 0x59ac5
movb $0x0, %al
callq *%rcx
jmp 0x3129f
movsd 0x98(%rsp), %xmm0
ucomisd 0xa8(%rsp), %xmm0
jne 0x30b31
jp 0x30b31
movq 0xe0(%rsp), %rax
cmpl $0x0, 0x50(%rax)
je 0x30b2c
callq 0x91a0
movq %rax, %rcx
leaq 0x28fe5(%rip), %rdi     # 0x59b0d
movb $0x0, %al
callq *%rcx
jmp 0x3129f
cmpq $0x0, 0xb0(%rsp)
jne 0x30b50
movsd 0x98(%rsp), %xmm0
movsd %xmm0, 0xa0(%rsp)
jmp 0x30bcc
movsd 0xa8(%rsp), %xmm0
subsd 0x98(%rsp), %xmm0
movsd 0xa0(%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 0x30bca
movq 0xe0(%rsp), %rax
cmpl $0x0, 0x50(%rax)
je 0x30bc5
callq 0x91a0
movq %rax, %rcx
movq 0xe0(%rsp), %rax
movsd 0x40(%rax), %xmm0
leaq 0x28f8d(%rip), %rdi     # 0x59b4e
movb $0x1, %al
callq *%rcx
jmp 0x3129f
jmp 0x30bcc
movsd 0x98(%rsp), %xmm0
movsd %xmm0, 0xa8(%rsp)
movq 0x80(%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 0x30c54
movq 0x80(%rsp), %rax
movq 0x88(%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 0x30c05
movq $0x0, 0x58(%rsp)
movq 0xe0(%rsp), %rax
movl 0x30(%rax), %eax
movl %eax, 0xc(%rsp)
testl %eax, %eax
je 0x30f91
jmp 0x30c76
movl 0xc(%rsp), %eax
subl $0x1, %eax
jne 0x3123a
jmp 0x30c85
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 0x30db4
movq 0xe0(%rsp), %rax
movq 0x58(%rax), %rax
movq 0x88(%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 0x30d99
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 0x30d44
jmp 0x30d9b
movq 0xb8(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xb8(%rsp)
jmp 0x30cc1
movq $0x0, 0xc8(%rsp)
movq 0xc8(%rsp), %rax
movq 0xe0(%rsp), %rcx
cmpq 0x10(%rcx), %rax
jae 0x30f8c
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 0x80(%rsp), %rax
movq 0xc8(%rsp), %rcx
cmpq $0x0, (%rax,%rcx,8)
jbe 0x30ed9
movq 0x80(%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 0x30e6f
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 0x30ed4
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 0x30e87
jmp 0x30f71
movq 0x68(%rsp), %rdi
movq 0xd0(%rsp), %rsi
callq 0x30770
movq %rax, 0x28(%rsp)
movq 0x58(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x58(%rsp)
movq $0x0, 0xc0(%rsp)
movq 0xc0(%rsp), %rax
movq 0xe0(%rsp), %rcx
cmpq 0x8(%rcx), %rax
jae 0x30f6f
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 0x30f0a
jmp 0x30f71
jmp 0x30f73
movq 0xc8(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xc8(%rsp)
jmp 0x30dc0
jmp 0x3123f
movq $0x0, 0xc0(%rsp)
movq 0xc0(%rsp), %rax
movq 0xe0(%rsp), %rcx
cmpq 0x8(%rcx), %rax
jae 0x31238
movq 0x78(%rsp), %rax
movq 0xc0(%rsp), %rcx
imulq 0xd0(%rsp), %rcx
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, 0x20(%rsp)
movq 0x70(%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 0x310fc
movq 0x88(%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 0x70(%rsp), %rax
movq 0xc8(%rsp), %rcx
movq (%rax,%rcx,8), %rax
shlq %rax
movq 0x80(%rsp), %rcx
movq 0xc8(%rsp), %rdx
cmpq (%rcx,%rdx,8), %rax
jae 0x310ca
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 0x70(%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 0x31001
movq $0x0, 0xc8(%rsp)
movq 0xc8(%rsp), %rax
movq 0xe0(%rsp), %rcx
cmpq 0x10(%rcx), %rax
jae 0x3121d
movq 0x80(%rsp), %rax
movq 0xc8(%rsp), %rcx
cmpq $0x0, (%rax,%rcx,8)
jne 0x31202
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 0x68(%rsp), %rdi
movq 0xd0(%rsp), %rsi
callq 0x30770
movq %rax, 0x10(%rsp)
movq 0x58(%rsp), %rax
addq $0x1, %rax
movq %rax, 0x58(%rsp)
movq $0x0, 0xc0(%rsp)
movq 0xc0(%rsp), %rax
movq 0xe0(%rsp), %rcx
cmpq 0x8(%rcx), %rax
jae 0x31200
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 0x3119b
jmp 0x31202
jmp 0x31204
movq 0xc8(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xc8(%rsp)
jmp 0x31108
jmp 0x3121f
movq 0xc0(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xc0(%rsp)
jmp 0x30f9d
jmp 0x3123f
callq 0x90b0
movq 0x58(%rsp), %rax
addq 0x60(%rsp), %rax
movq %rax, 0x60(%rsp)
movq 0xe0(%rsp), %rax
cmpl $0x0, 0x50(%rax)
je 0x31284
cmpq $0x0, 0x58(%rsp)
je 0x31284
callq 0x91a0
movq %rax, %rcx
movq 0xb0(%rsp), %rsi
movq 0x58(%rsp), %rdx
leaq 0x2891e(%rip), %rdi     # 0x59b9e
movb $0x0, %al
callq *%rcx
jmp 0x31286
movq 0xb0(%rsp), %rax
addq $0x1, %rax
movq %rax, 0xb0(%rsp)
jmp 0x309e4
cmpq $0x0, 0x78(%rsp)
je 0x312b1
movq 0x78(%rsp), %rdi
callq 0x9620
cmpq $0x0, 0x70(%rsp)
je 0x312c3
movq 0x70(%rsp), %rdi
callq 0x9620
movq 0x90(%rsp), %rdi
callq 0x9620
movq 0x88(%rsp), %rdi
callq 0x9620
movq 0x80(%rsp), %rdi
callq 0x9620
movsd 0x98(%rsp), %xmm0
addq $0xe8, %rsp
retq
nopl (%rax,%rax)