// File: /workspace/github_cpp_makefile_star2_O2/CominLab[P]QCluster/em.cc
// Function: hard_em(int, int, int, double**, double**, double*, double**, double*, int, double**, int*, double*, int, char, int)
int hard_em(int K, int N, int row_length, double** data, 
		double **quality, double *expected_qual, double **quality_1, double *expected_freq,
		int num_nt, double** data_1, int* assignment, double *Z, 
		int num_trials, char dist_type, int verbose)
{
	// Allocate matrices for centroids, distances, assignment and the 
	// vector for the number of members
	double**  centroids = new double*[K];
	centroids[0] = new double[row_length*K];
	for(int k=1; k<K; ++k) {
		centroids[k] = centroids[0] + k*row_length;
	} // K*row_length matrix for centroid locations

	double**  centroids_tilde = new double*[K];
	centroids_tilde[0] = new double[row_length*K];
	for(int k=1; k<K; ++k) {
		centroids_tilde[k] = centroids_tilde[0] + k*row_length;
	} // K*row_length matrix for X_tilde vars for centroids

	int* tmp_assignment = new int[N];
	int *numMembers = new int[K];  // number of members in each cluster
	double** tmp_data = new double*[N];
	double** tmp_data_1 = new double*[N];

	// call clustering routine
	double min_distortion = 0;
	for (int t=0; t<num_trials; t++) {
		if (verbose > 0) {
			cerr<<"Calling EM routine, attempt "<<t+1<<endl;
		}
		double distortion =	em_routine(K, N, row_length, data, quality, 
				expected_qual, quality_1, expected_freq, num_nt, data_1,
				tmp_assignment, numMembers, centroids, centroids_tilde,
				tmp_data, tmp_data_1, dist_type, verbose);
		if (verbose > 0) {
			cerr<<"Resulting distortion: "<<distortion<<endl;
		}
		if (!t || (distortion < min_distortion)) {
			if (verbose > 0) {
				cerr<<"Updating best partitioning and minimal distortion"<<endl;
			}
			min_distortion = distortion;
			memcpy(assignment, tmp_assignment, N*sizeof(*assignment));
		}
	}
	if (verbose > 0) {
		cerr<<"Resulting minimal distortion: "<<min_distortion<<endl;
	}
	//evaluate confidence if using KL with raw counts
	if (dist_type == 'k') {
		eval_confidence(K, N, row_length, data, centroids, Z, quality, expected_qual, expected_freq);
	}
	// delete allocated arrays
	delete[] centroids[0];
	delete[] centroids;
	delete[] centroids_tilde[0];
	delete[] centroids_tilde;
	delete[] numMembers;
	delete[] tmp_data;
	delete[] tmp_data_1;
	delete[] tmp_assignment;

	// return the number of clusters
	return count_num_clusters(N, assignment);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xe8, %rsp
movq %r9, 0x38(%rsp)
movq %r8, 0x48(%rsp)
movq %rcx, 0x30(%rsp)
movl %edx, %ebp
movl %esi, 0x8(%rsp)
movslq %edi, %r14
leaq (,%r14,8), %rbx
testl %r14d, %r14d
pushq $-0x1
popq %r12
movq %rbx, 0xc0(%rsp)
cmovsq %r12, %rbx
movq %rbx, %rdi
callq 0x2030
movq %rax, %r15
movl %ebp, %eax
movq %r14, 0x20(%rsp)
imull %r14d, %eax
leaq (,%rax,8), %r14
testl %eax, %eax
cmovsq %r12, %r14
movq %r14, %rdi
callq 0x2030
movq %r15, 0x10(%rsp)
movq %rax, (%r15)
movl %ebp, 0xc(%rsp)
movslq %ebp, %r12
leaq (,%r12,8), %r15
movq %rax, 0xb0(%rsp)
leaq (%rax,%r12,8), %rax
pushq $0x1
popq %rcx
movq 0x10(%rsp), %rdx
cmpq 0x20(%rsp), %rcx
jge 0x3994
movq %rax, (%rdx,%rcx,8)
incq %rcx
addq %r15, %rax
jmp 0x3981
movq %rbx, %rdi
callq 0x2030
movq %rax, %rbx
movq %r14, %rdi
callq 0x2030
movq %rbx, 0x28(%rsp)
movq %rax, (%rbx)
movq %rax, 0xb8(%rsp)
leaq (%rax,%r12,8), %rax
pushq $0x1
popq %rcx
movq 0x48(%rsp), %r12
movq 0x28(%rsp), %rdx
cmpq 0x20(%rsp), %rcx
jge 0x39db
movq %rax, (%rdx,%rcx,8)
incq %rcx
addq %r15, %rax
jmp 0x39c8
movl 0x8(%rsp), %ecx
movslq %ecx, %rax
xorl %ebp, %ebp
testl %eax, %eax
movl $0x0, %r13d
cmovgl %ecx, %r13d
leaq (,%rax,8), %rdx
testl %eax, %eax
pushq $-0x1
popq %rbx
cmovsq %rbx, %rdx
movq %rdx, 0x58(%rsp)
movq %rax, %rdi
shlq $0x2, %rdi
testl %eax, %eax
movq %rdi, 0x80(%rsp)
cmovsq %rbx, %rdi
callq 0x2030
movq %rax, %r14
movq 0x20(%rsp), %rax
leaq (,%rax,4), %rdi
testl %eax, %eax
movq %rdi, 0x88(%rsp)
cmovsq %rbx, %rdi
movl $0x0, %ebx
cmovgl %eax, %ebx
callq 0x2030
movq %rax, %r15
movq 0x58(%rsp), %rdi
callq 0x2030
movq %rax, 0xa0(%rsp)
movq 0x58(%rsp), %rdi
callq 0x2030
movq %rax, 0x98(%rsp)
movl 0x150(%rsp), %eax
testl %eax, %eax
cmovlel %ebp, %eax
movl %eax, 0x7c(%rsp)
movq %rbx, 0x18(%rsp)
negq %rbx
xorpd %xmm0, %xmm0
movsd %xmm0, 0x40(%rsp)
movsbl 0x158(%rsp), %eax
movl %eax, 0x78(%rsp)
movq %r15, 0x60(%rsp)
movq %rbx, 0xd0(%rsp)
cmpl 0x7c(%rsp), %ebp
je 0x400c
cmpl $0x0, 0x160(%rsp)
jle 0x3ae7
movq 0x7528(%rip), %rdi      # 0xaff0
leaq 0x4061(%rip), %rsi      # 0x7b30
callq 0x21e0
leal 0x1(%rbp), %esi
movq %rax, %rdi
callq 0x2300
movq %rax, %rdi
callq 0x2100
movq %rbp, 0xc8(%rsp)
movq 0x58(%rsp), %rbx
movq %rbx, %rdi
callq 0x2030
movq %rax, %rbp
movq %rbx, %rdi
callq 0x2030
movq %rax, 0x68(%rsp)
andq $0x0, 0x70(%rsp)
movl 0x8(%rsp), %edi
callq 0x3770
movl 0x78(%rsp), %edi
leaq 0xe0(%rsp), %rsi
leaq 0xd8(%rsp), %rdx
callq 0x3868
movq 0xd8(%rsp), %rax
movq %rax, 0xa8(%rsp)
movq 0xe0(%rsp), %rax
movq %rax, 0x50(%rsp)
cmpl $0x0, 0x160(%rsp)
jle 0x3b76
movq 0x748e(%rip), %rdi      # 0xaff0
leaq 0x404c(%rip), %rsi      # 0x7bb5
callq 0x21e0
movq %rax, %rdi
callq 0x2100
movq %r14, %rdi
xorl %esi, %esi
movq 0x80(%rsp), %rdx
callq 0x2130
movq 0x60(%rsp), %rdi
movl $0xff, %esi
movq 0x88(%rsp), %rdx
callq 0x2130
xorl %ebx, %ebx
movl 0x8(%rsp), %r15d
cmpq %rbx, 0x18(%rsp)
je 0x3c1f
callq 0x20a0
cltd
idivl %r15d
movslq %edx, %rax
movq 0x30(%rsp), %rcx
leaq (%rcx,%rax,8), %rdx
movq 0x138(%rsp), %rcx
leaq (%rcx,%rax,8), %r8
movq 0x10(%rsp), %rcx
movq (%rcx,%rbx,8), %r9
leaq (%r12,%rax,8), %r10
movq 0x120(%rsp), %rcx
leaq (%rcx,%rax,8), %rax
subq $0x8, %rsp
pushq $0x1
popq %rdi
movl 0x14(%rsp), %esi
movl 0x138(%rsp), %ecx
pushq 0x130(%rsp)
pushq %rax
pushq 0x50(%rsp)
pushq %r10
movq 0x50(%rsp), %rax
pushq (%rax,%rbx,8)
callq *0xd8(%rsp)
addq $0x30, %rsp
incq %rbx
jmp 0x3ba6
xorl %r15d, %r15d
xorl %eax, %eax
movq %rax, 0x90(%rsp)
cmpq %r13, %r15
jne 0x3c68
movq 0x60(%rsp), %r15
movq %r15, %rdi
xorl %esi, %esi
movq 0x88(%rsp), %rdx
callq 0x2130
xorl %eax, %eax
movq 0xd0(%rsp), %rdx
cmpq %rax, %r13
je 0x3cf2
movslq (%r14,%rax,4), %rcx
incl (%r15,%rcx,4)
incq %rax
jmp 0x3c52
xorl %r12d, %r12d
pushq $-0x1
popq %rbx
movsd 0x3e92(%rip), %xmm0     # 0x7b08
cmpq %r12, 0x18(%rsp)
je 0x3d46
movq 0x10(%rsp), %rax
movq (%rax,%r12,8), %rdi
movq 0x30(%rsp), %rax
movq (%rax,%r15,8), %rsi
movq 0x28(%rsp), %rax
movq (%rax,%r12,8), %rcx
movq 0x48(%rsp), %rax
movq (%rax,%r15,8), %r8
subq $0x8, %rsp
movl 0x14(%rsp), %edx
movq 0x40(%rsp), %r9
pushq 0x130(%rsp)
movsd %xmm0, 0x10(%rsp)
callq *0x60(%rsp)
movsd 0x10(%rsp), %xmm1
addq $0x10, %rsp
cmpl $-0x1, %ebx
sete %al
ucomisd %xmm0, %xmm1
seta %cl
orb %al, %cl
movl %r12d, %eax
testb %cl, %cl
jne 0x3ce5
movl %ebx, %eax
jne 0x3ceb
movapd %xmm1, %xmm0
incq %r12
movl %eax, %ebx
jmp 0x3c76
pushq $-0x1
popq %rax
leaq (%rdx,%rax), %rcx
cmpq $-0x1, %rcx
je 0x3d6a
leaq 0x1(%rax), %rbx
cmpl $0x0, 0x4(%r15,%rax,4)
movq %rbx, %rax
jne 0x3cf5
cmpl $0x0, 0x160(%rsp)
jle 0x3d33
movq 0x72d1(%rip), %rdi      # 0xaff0
leaq 0x3eb9(%rip), %rsi      # 0x7bdf
callq 0x21e0
movq %rax, %rdi
callq 0x2100
callq 0x3857
movl 0x8(%rsp), %edi
callq 0x3770
jmp 0x3eba
movb $0x1, %al
testb $0x1, 0x90(%rsp)
jne 0x3d59
cmpl %ebx, (%r14,%r15,4)
setne %al
movl %ebx, (%r14,%r15,4)
incq %r15
movq 0x48(%rsp), %r12
jmp 0x3c24
xorpd %xmm0, %xmm0
xorl %ebx, %ebx
cmpq %rbx, %r13
movsd %xmm0, (%rsp)
je 0x3dd1
movslq (%r14,%rbx,4), %rax
movq 0x10(%rsp), %rcx
movq (%rcx,%rax,8), %rdi
movq 0x30(%rsp), %rcx
movq (%rcx,%rbx,8), %rsi
movq 0x28(%rsp), %rcx
movq (%rcx,%rax,8), %rcx
movq (%r12,%rbx,8), %r8
subq $0x8, %rsp
movl 0x14(%rsp), %edx
movq 0x40(%rsp), %r9
pushq 0x130(%rsp)
callq *0x60(%rsp)
addq $0x10, %rsp
movsd (%rsp), %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, (%rsp)
movsd (%rsp), %xmm0
incq %rbx
jmp 0x3d70
movsd %xmm0, 0x70(%rsp)
testb $0x1, 0x90(%rsp)
je 0x3ed2
movl 0x8(%rsp), %edi
movq %r14, %rdx
leaq 0x70(%rsp), %rcx
callq 0x37c7
testb %al, %al
movq 0x30(%rsp), %rbx
jne 0x3f10
xorl %r15d, %r15d
cmpq 0x18(%rsp), %r15
je 0x3eb5
xorl %eax, %eax
xorl %edi, %edi
movq 0xa0(%rsp), %rdx
movq 0x98(%rsp), %r8
movq 0x138(%rsp), %rsi
movq 0x120(%rsp), %r9
movq 0x68(%rsp), %r10
cmpq %rax, %r13
je 0x3e73
movl (%r14,%rax,4), %ecx
cmpq %rcx, %r15
jne 0x3e6e
movq (%rbx,%rax,8), %rcx
movslq %edi, %rdi
movq %rcx, (%rdx,%rdi,8)
movq (%rsi,%rax,8), %rcx
movq %rcx, (%r8,%rdi,8)
movq (%r12,%rax,8), %rcx
movq %rcx, (%rbp,%rdi,8)
movq (%r9,%rax,8), %rcx
movq %rcx, (%r10,%rdi,8)
incl %edi
incq %rax
jmp 0x3e3a
movq 0x10(%rsp), %rax
movq (%rax,%r15,8), %r9
subq $0x8, %rsp
movl 0x14(%rsp), %esi
movl 0x138(%rsp), %ecx
pushq 0x130(%rsp)
pushq %r10
pushq 0x50(%rsp)
pushq %rbp
movq 0x50(%rsp), %rax
pushq (%rax,%r15,8)
callq *0xd8(%rsp)
addq $0x30, %rsp
incq %r15
jmp 0x3e06
movq 0x18(%rsp), %rbx
xorl %r15d, %r15d
movl $0x0, %eax
cmpq 0x20(%rsp), %rbx
jge 0x3c24
jmp 0x3b51
cmpl $0x0, 0x160(%rsp)
jle 0x3ef7
movq 0x710d(%rip), %rdi      # 0xaff0
leaq 0x3d10(%rip), %rsi      # 0x7bfa
callq 0x21e0
movq %rax, %rdi
callq 0x2100
callq 0x3857
movq %rbp, %rdi
callq 0x2250
movq 0x68(%rsp), %rdi
callq 0x2250
jmp 0x3f57
cmpl $0x0, 0x160(%rsp)
jle 0x3f35
movq 0x70cf(%rip), %rdi      # 0xaff0
leaq 0x3cf0(%rip), %rsi      # 0x7c18
callq 0x21e0
movq %rax, %rdi
callq 0x2100
callq 0x3857
movq %rbp, %rdi
callq 0x2250
movq 0x68(%rsp), %rdi
callq 0x2250
movsd 0x70(%rsp), %xmm0
movsd %xmm0, (%rsp)
cmpl $0x0, 0x160(%rsp)
movq 0xc8(%rsp), %rbp
jle 0x3fc8
movq 0x7080(%rip), %rdi      # 0xaff0
leaq 0x3bd6(%rip), %rsi      # 0x7b4d
callq 0x21e0
movq %rax, %rdi
movsd (%rsp), %xmm0
callq 0x22e0
movq %rax, %rdi
callq 0x2100
movsd (%rsp), %xmm1
testl %ebp, %ebp
je 0x3fa6
movsd 0x40(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x4005
movq 0x7043(%rip), %rdi      # 0xaff0
leaq 0x3bb0(%rip), %rsi      # 0x7b64
callq 0x21e0
movq %rax, %rdi
callq 0x2100
movsd (%rsp), %xmm1
jmp 0x3fdd
testl %ebp, %ebp
movsd (%rsp), %xmm1
je 0x3fdd
movsd 0x40(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x4005
movsd %xmm1, (%rsp)
movq 0x140(%rsp), %rdi
movq %r14, %rsi
movq 0x80(%rsp), %rdx
callq 0x2190
movsd (%rsp), %xmm0
movsd %xmm0, 0x40(%rsp)
incl %ebp
jmp 0x3aad
cmpl $0x0, 0x160(%rsp)
jle 0x403f
movq 0x6fd3(%rip), %rdi      # 0xaff0
leaq 0x3b72(%rip), %rsi      # 0x7b96
callq 0x21e0
movq %rax, %rdi
movsd 0x40(%rsp), %xmm0
callq 0x22e0
movq %rax, %rdi
callq 0x2100
cmpb $0x6b, 0x158(%rsp)
movq 0xb0(%rsp), %rdi
jne 0x4188
xorl %ebx, %ebx
movq 0x148(%rsp), %rbp
cmpq %r13, %rbx
je 0x417b
movq %rbx, %r15
imulq 0x20(%rsp), %r15
xorl %r12d, %r12d
cmpq %r12, 0x18(%rsp)
je 0x40bf
movq 0x10(%rsp), %rax
movq (%rax,%r12,8), %rdi
movq 0x30(%rsp), %rax
movq (%rax,%rbx,8), %rsi
movq 0x48(%rsp), %rax
movq (%rax,%rbx,8), %r8
subq $0x8, %rsp
movl 0x14(%rsp), %edx
xorl %ecx, %ecx
movq 0x40(%rsp), %r9
pushq 0x130(%rsp)
callq 0x4295
popq %rax
popq %rcx
movsd %xmm0, (%rbp,%r12,8)
incq %r12
jmp 0x4074
movq 0x148(%rsp), %rax
movsd (%rax,%r15,8), %xmm3
pushq $0x1
popq %rax
cmpq 0x20(%rsp), %rax
jge 0x40ea
movsd (%rbp,%rax,8), %xmm0
minsd %xmm3, %xmm0
incq %rax
movapd %xmm0, %xmm3
jmp 0x40d0
xorpd %xmm2, %xmm2
xorl %r15d, %r15d
movsd %xmm3, 0x50(%rsp)
cmpq %r15, 0x18(%rsp)
je 0x4148
movsd (%rbp,%r15,8), %xmm0
subsd %xmm3, %xmm0
xorpd %xmm1, %xmm1
ucomisd 0x39fb(%rip), %xmm0     # 0x7b10
ja 0x4138
xorpd 0x3a01(%rip), %xmm0     # 0x7b20
movsd %xmm2, (%rsp)
callq 0x2330
movsd 0x50(%rsp), %xmm3
movsd (%rsp), %xmm2
movapd %xmm0, %xmm1
movsd %xmm1, (%rbp,%r15,8)
addsd %xmm1, %xmm2
incq %r15
jmp 0x40f7
xorl %eax, %eax
movq 0x60(%rsp), %r15
cmpq %rax, 0x18(%rsp)
je 0x416b
movsd (%rbp,%rax,8), %xmm0
divsd %xmm2, %xmm0
movsd %xmm0, (%rbp,%rax,8)
incq %rax
jmp 0x414f
incq %rbx
addq 0xc0(%rsp), %rbp
jmp 0x405f
movq 0x10(%rsp), %rax
movq (%rax), %rdi
testq %rdi, %rdi
je 0x418d
callq 0x2250
movq 0x10(%rsp), %rdi
callq 0x2250
movq 0xb8(%rsp), %rdi
callq 0x2250
movq 0x28(%rsp), %rdi
callq 0x2250
movq %r15, %rdi
callq 0x2250
movq 0xa0(%rsp), %rdi
callq 0x2250
movq 0x98(%rsp), %rdi
callq 0x2250
movq %r14, %rdi
callq 0x2250
xorl %eax, %eax
xorl %ecx, %ecx
movq 0x140(%rsp), %rsi
cmpq %rax, %r13
je 0x41f6
movl (%rsi,%rax,4), %edx
cmpl %ecx, %edx
cmovgl %edx, %ecx
incq %rax
jmp 0x41e4
movl %ecx, %r15d
leaq 0x4(,%r15,4), %r14
movq %r14, %rdi
callq 0x2030
movq %rax, %rbx
xorl %r12d, %r12d
movq %rax, %rdi
xorl %esi, %esi
movq %r14, %rdx
callq 0x2130
movq 0x140(%rsp), %rcx
cmpq %r12, %r13
je 0x4239
movslq (%rcx,%r12,4), %rax
movl $0x1, (%rbx,%rax,4)
incq %r12
jmp 0x4224
incq %r15
xorl %eax, %eax
xorl %ebp, %ebp
cmpq %rax, %r15
je 0x424d
addl (%rbx,%rax,4), %ebp
incq %rax
jmp 0x4240
movq %rbx, %rdi
callq 0x2250
movl %ebp, %eax
addq $0xe8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nopl (%rax)