// File: sebastienmeyer2[P]mst-clustering/src/kmeans.cpp
// Function: Cloud::silhouette()
double Cloud::silhouette()
{
    /*!
     * @brief Computes the silhouette of this cloud 
     * 
     * @return The silhouette of this cloud
     */

	double silhouette = 0.0;

	// we compute a and b which are respectively the 
	// average distance to points of the same cluster 
	// and min of average distances to foreign clusters
	double* a = new double [n] ();
	double* b = new double [n] ();
	double* s = new double [n] ();

	for (int i = 0; i < this->n; i ++){
		double* distPointClusters = new double [k] ();
		int* clustersSize = new int [k] ();
		
		for (int j = 0; j < this->n; j ++){
			if (j != i){
				int pointLabel = points[j].label;
				clustersSize[pointLabel] += 1;

				distPointClusters[pointLabel] += std::sqrt(points[i].distance(&(points[j])));
			}
		}

		double minDist = DBL_MAX;
		for (int j = 0; j < this->k; j ++){
			if (clustersSize[j] > 0){
				distPointClusters[j] /= clustersSize[j];

				if (j != points[i].label && distPointClusters[j] < minDist) {
					minDist = distPointClusters[j];
				}
			}
		}

		a[i] = distPointClusters[points[i].label];
		b[i] = 0.0;
		if (minDist < DBL_MAX){
			b[i] = minDist;
		}

		delete[] distPointClusters;
		distPointClusters = NULL;
		delete[] clustersSize;
		clustersSize = NULL;

		s[i] = (b[i] - a[i]) / (std::max(a[i], b[i]));
	}

	for (int i = 0; i < this->n; i ++){
		silhouette += s[i];
	}
	silhouette /= this->n;

	return silhouette;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xd0, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x70(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x10(%rbp)
movslq 0x4(%rax), %rax
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
movq %rdi, -0x90(%rbp)
callq 0xa030
movq -0x90(%rbp), %rdx
movq %rax, %rdi
movq %rdi, -0x88(%rbp)
xorl %esi, %esi
callq 0xa3a0
movq -0x88(%rbp), %rcx
movq -0x70(%rbp), %rax
movq %rcx, -0x18(%rbp)
movslq 0x4(%rax), %rax
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
movq %rdi, -0x80(%rbp)
callq 0xa030
movq -0x80(%rbp), %rdx
movq %rax, %rdi
movq %rdi, -0x78(%rbp)
xorl %esi, %esi
callq 0xa3a0
movq -0x78(%rbp), %rcx
movq -0x70(%rbp), %rax
movq %rcx, -0x20(%rbp)
movslq 0x4(%rax), %rax
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
movq %rdi, -0x68(%rbp)
callq 0xa030
movq -0x68(%rbp), %rdx
movq %rax, %rdi
movq %rdi, -0x60(%rbp)
xorl %esi, %esi
callq 0xa3a0
movq -0x60(%rbp), %rax
movq %rax, -0x28(%rbp)
movl $0x0, -0x2c(%rbp)
movq -0x70(%rbp), %rcx
movl -0x2c(%rbp), %eax
cmpl 0x4(%rcx), %eax
jge 0x33e48
movq -0x70(%rbp), %rax
movslq 0x8(%rax), %rax
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
movq %rdi, -0xb0(%rbp)
callq 0xa030
movq -0xb0(%rbp), %rdx
movq %rax, %rdi
movq %rdi, -0xa8(%rbp)
xorl %esi, %esi
callq 0xa3a0
movq -0xa8(%rbp), %rcx
movq -0x70(%rbp), %rax
movq %rcx, -0x38(%rbp)
movslq 0x8(%rax), %rax
movl $0x4, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
movq %rdi, -0xa0(%rbp)
callq 0xa030
movq -0xa0(%rbp), %rdx
movq %rax, %rdi
movq %rdi, -0x98(%rbp)
xorl %esi, %esi
callq 0xa3a0
movq -0x98(%rbp), %rax
movq %rax, -0x40(%rbp)
movl $0x0, -0x44(%rbp)
movq -0x70(%rbp), %rcx
movl -0x44(%rbp), %eax
cmpl 0x4(%rcx), %eax
jge 0x33c88
movl -0x44(%rbp), %eax
cmpl -0x2c(%rbp), %eax
je 0x33c78
movq -0x70(%rbp), %rax
movq 0x10(%rax), %rcx
movslq -0x44(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rcx
movl 0x8(%rcx), %ecx
movl %ecx, -0x48(%rbp)
movq -0x40(%rbp), %rcx
movslq -0x48(%rbp), %rdx
movl (%rcx,%rdx,4), %esi
addl $0x1, %esi
movl %esi, (%rcx,%rdx,4)
movq 0x10(%rax), %rdi
movslq -0x2c(%rbp), %rcx
shlq $0x4, %rcx
addq %rcx, %rdi
movq 0x10(%rax), %rsi
movslq -0x44(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rsi
callq 0xb660
callq 0xa5d0
movq -0x38(%rbp), %rax
movslq -0x48(%rbp), %rcx
addsd (%rax,%rcx,8), %xmm0
movsd %xmm0, (%rax,%rcx,8)
jmp 0x33c7a
movl -0x44(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x44(%rbp)
jmp 0x33c00
movsd 0x3b08(%rip), %xmm0     # 0x37798
movsd %xmm0, -0x50(%rbp)
movl $0x0, -0x54(%rbp)
movq -0x70(%rbp), %rcx
movl -0x54(%rbp), %eax
cmpl 0x8(%rcx), %eax
jge 0x33d34
movq -0x40(%rbp), %rax
movslq -0x54(%rbp), %rcx
cmpl $0x0, (%rax,%rcx,4)
jle 0x33d24
movq -0x70(%rbp), %rcx
movq -0x40(%rbp), %rax
movslq -0x54(%rbp), %rdx
cvtsi2sdl (%rax,%rdx,4), %xmm1
movq -0x38(%rbp), %rax
movslq -0x54(%rbp), %rdx
movsd (%rax,%rdx,8), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, (%rax,%rdx,8)
movl -0x54(%rbp), %eax
movq 0x10(%rcx), %rcx
movslq -0x2c(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rcx
cmpl 0x8(%rcx), %eax
je 0x33d22
movq -0x38(%rbp), %rax
movslq -0x54(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm1
movsd -0x50(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x33d22
movq -0x38(%rbp), %rax
movslq -0x54(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movsd %xmm0, -0x50(%rbp)
jmp 0x33d24
jmp 0x33d26
movl -0x54(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x54(%rbp)
jmp 0x33c9c
movq -0x70(%rbp), %rcx
movq -0x38(%rbp), %rax
movq 0x10(%rcx), %rcx
movslq -0x2c(%rbp), %rdx
shlq $0x4, %rdx
addq %rdx, %rcx
movslq 0x8(%rcx), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x18(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movq -0x20(%rbp), %rax
movslq -0x2c(%rbp), %rcx
xorps %xmm0, %xmm0
movsd %xmm0, (%rax,%rcx,8)
movsd 0x3a1f(%rip), %xmm0     # 0x37798
ucomisd -0x50(%rbp), %xmm0
jbe 0x33d92
movsd -0x50(%rbp), %xmm0
movq -0x20(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movq -0x38(%rbp), %rax
movq %rax, -0xb8(%rbp)
cmpq $0x0, %rax
je 0x33daf
movq -0xb8(%rbp), %rdi
callq 0xaa00
movq $0x0, -0x38(%rbp)
movq -0x40(%rbp), %rax
movq %rax, -0xc0(%rbp)
cmpq $0x0, %rax
je 0x33dd4
movq -0xc0(%rbp), %rdi
callq 0xaa00
movq $0x0, -0x40(%rbp)
movq -0x20(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x18(%rbp), %rax
movslq -0x2c(%rbp), %rcx
subsd (%rax,%rcx,8), %xmm0
movsd %xmm0, -0xc8(%rbp)
movq -0x18(%rbp), %rdi
movslq -0x2c(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
movq -0x20(%rbp), %rsi
movslq -0x2c(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rsi
callq 0x248b0
movsd -0xc8(%rbp), %xmm0
divsd (%rax), %xmm0
movq -0x28(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movsd %xmm0, (%rax,%rcx,8)
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x2c(%rbp)
jmp 0x33b43
movl $0x0, -0x58(%rbp)
movq -0x70(%rbp), %rcx
movl -0x58(%rbp), %eax
cmpl 0x4(%rcx), %eax
jge 0x33e7d
movq -0x28(%rbp), %rax
movslq -0x58(%rbp), %rcx
movsd (%rax,%rcx,8), %xmm0
addsd -0x10(%rbp), %xmm0
movsd %xmm0, -0x10(%rbp)
movl -0x58(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x58(%rbp)
jmp 0x33e4f
movq -0x70(%rbp), %rax
cvtsi2sdl 0x4(%rax), %xmm1
movsd -0x10(%rbp), %xmm0
divsd %xmm1, %xmm0
movsd %xmm0, -0x10(%rbp)
movsd -0x10(%rbp), %xmm0
addq $0xd0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
nopl (%rax)