// File: CK7[P]abawaca/src/ClusterSeparatorBySensitivitySpecificity.cpp
// Function: ClusterSeparatorBySensitivitySpecificity::separate_dimension(unsigned long)
void ClusterSeparatorBySensitivitySpecificity::separate_dimension(size_t dimension_index)
{
	semaphore.wait();
	const Dimension& dimension = clustering_db.get_dimension(dimension_index);
	const set<double>& values = dimension.get_values();
	int values_checked = 0;
	// Initialize - curr_cluster1 will have no points while curr_cluster2 will have all dps
	Cluster 						curr_cluster1(scaf_db);
	Cluster 						curr_cluster2(scaf_db);
	ClusterSeparatorBySensitivitySpecificity::ClusterStats	curr_cluster_stats1(curr_cluster1, scaf_db);
	ClusterSeparatorBySensitivitySpecificity::ClusterStats	curr_cluster_stats2(curr_cluster2, scaf_db);
	vector<Dimension::DataPoint>				dps;
	set<size_t> 						useful_scafs;

	for(vector<Dimension::DataPoint>::const_iterator vit = dimension.begin(); vit!=dimension.end(); vit++) {
		curr_cluster_stats2.add_dp(vit->dp);
		dps.push_back(*vit);
		if(scaf_db.ndps(scaf_db.dp2scaf(vit->dp)) > 1) {
			useful_scafs.insert(scaf_db.dp2scaf(vit->dp));
			curr_cluster_stats2.assign_scaf(scaf_db.dp2scaf(vit->dp));
		}
	}

	sort(dps.begin(), dps.end(), comp_by_value);
	ClusterSeparatorBySensitivitySpecificity::ClusteringResult	best_dimension_separation;

	for(auto vit=dps.begin(); vit!=dps.end();) {
		double value = vit->value;
		while(vit!=dps.end() && vit->value==value) {
			size_t scaf = scaf_db.dp2scaf(vit->dp);
			size_t scaf_total_ndps = scaf_db.ndps(scaf);

			curr_cluster_stats1.add_dp(vit->dp);
			curr_cluster_stats2.remove_dp(vit->dp);
			if(curr_cluster_stats2.get_cluster().assigned(scaf) && (scaf_total_ndps >= 2) && (2*curr_cluster_stats1.get_cluster().ndps(scaf) > scaf_total_ndps)) {
				curr_cluster_stats1.assign_scaf(scaf);
				curr_cluster_stats2.unassign_scaf(scaf);
			}
			vit++;
		}

		// Now do what we actually need to do in this specific class
		this->separate_specific(curr_cluster_stats1, curr_cluster_stats2, dimension_index, value, best_dimension_separation);
	}

	// Only a single access to the variables common to all threads
	unique_lock<mutex> lck(update_mtx);

	if(best_dimension_separation.is_better(*best_separation))
		best_separation->copy(best_dimension_separation);

	semaphore.notify();
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x390, %rsp            # imm = 0x390
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x2e8(%rbp)
movq 0xe0(%rax), %rdi
callq 0x28420
movq -0x2e8(%rbp), %rax
movq 0x18(%rax), %rdi
movq -0x10(%rbp), %rsi
callq 0x1e9d0
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rdi
callq 0x28480
movq %rax, %rcx
movq -0x2e8(%rbp), %rax
movq %rcx, -0x20(%rbp)
movl $0x0, -0x24(%rbp)
movq 0x8(%rax), %rsi
leaq -0xc8(%rbp), %rdi
callq 0xac40
movq -0x2e8(%rbp), %rax
movq 0x8(%rax), %rsi
leaq -0x168(%rbp), %rdi
callq 0xac40
jmp 0x27aa9
movq -0x2e8(%rbp), %rax
movq 0x8(%rax), %rdx
leaq -0x1a0(%rbp), %rdi
leaq -0xc8(%rbp), %rsi
callq 0x28490
jmp 0x27ac9
movq -0x2e8(%rbp), %rax
movq 0x8(%rax), %rdx
leaq -0x1c8(%rbp), %rdi
leaq -0x168(%rbp), %rsi
callq 0x28490
jmp 0x27ae9
leaq -0x1e0(%rbp), %rdi
callq 0x1cca0
leaq -0x210(%rbp), %rdi
callq 0xefa0
movq -0x18(%rbp), %rdi
callq 0x24aa0
movq %rax, -0x2f0(%rbp)
jmp 0x27b13
movq -0x2f0(%rbp), %rax
movq %rax, -0x218(%rbp)
movq -0x18(%rbp), %rdi
callq 0x24b10
movq %rax, -0x2f8(%rbp)
jmp 0x27b33
movq -0x2f8(%rbp), %rax
movq %rax, -0x220(%rbp)
leaq -0x218(%rbp), %rdi
leaq -0x220(%rbp), %rsi
callq 0x24ad0
testb $0x1, %al
jne 0x27b5d
jmp 0x27d28
leaq -0x218(%rbp), %rdi
callq 0x24b40
movq (%rax), %rsi
leaq -0x1c8(%rbp), %rdi
callq 0x274a0
jmp 0x27b7a
leaq -0x218(%rbp), %rdi
callq 0x28560
movq %rax, %rsi
leaq -0x1e0(%rbp), %rdi
callq 0x284f0
jmp 0x27b97
movq -0x2e8(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x308(%rbp)
leaq -0x218(%rbp), %rdi
callq 0x24b40
movq -0x308(%rbp), %rdi
movq (%rax), %rsi
callq 0x13a40
movq %rax, -0x300(%rbp)
jmp 0x27bcd
movq -0x300(%rbp), %rsi
movq -0x308(%rbp), %rdi
callq 0x13b50
movq %rax, -0x310(%rbp)
jmp 0x27be9
movq -0x310(%rbp), %rax
cmpq $0x1, %rax
jbe 0x27d0c
movq -0x2e8(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x320(%rbp)
leaq -0x218(%rbp), %rdi
callq 0x24b40
movq -0x320(%rbp), %rdi
movq (%rax), %rsi
callq 0x13a40
movq %rax, -0x318(%rbp)
jmp 0x27c30
movq -0x318(%rbp), %rax
movq %rax, -0x228(%rbp)
leaq -0x210(%rbp), %rdi
leaq -0x228(%rbp), %rsi
callq 0x28580
movb %dl, -0x329(%rbp)
movq %rax, -0x328(%rbp)
jmp 0x27c60
movq -0x2e8(%rbp), %rax
movb -0x329(%rbp), %cl
movq -0x328(%rbp), %rdx
movq %rdx, -0x238(%rbp)
movb %cl, -0x230(%rbp)
movq 0x8(%rax), %rax
movq %rax, -0x340(%rbp)
leaq -0x218(%rbp), %rdi
callq 0x24b40
movq -0x340(%rbp), %rdi
movq (%rax), %rsi
callq 0x13a40
movq %rax, -0x338(%rbp)
jmp 0x27cb0
movq -0x338(%rbp), %rsi
leaq -0x1c8(%rbp), %rdi
callq 0x27600
jmp 0x27cc5
jmp 0x27d0c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x170(%rbp)
movl %eax, -0x174(%rbp)
jmp 0x28101
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x170(%rbp)
movl %eax, -0x174(%rbp)
jmp 0x280f5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x170(%rbp)
movl %eax, -0x174(%rbp)
jmp 0x280dd
jmp 0x27d0e
leaq -0x218(%rbp), %rdi
xorl %esi, %esi
callq 0x24b60
movq %rax, -0x240(%rbp)
jmp 0x27b21
leaq -0x1e0(%rbp), %rdi
movq %rdi, -0x348(%rbp)
callq 0x1e270
movq -0x348(%rbp), %rdi
movq %rax, -0x248(%rbp)
callq 0x1e0f0
movq %rax, -0x250(%rbp)
movq -0x248(%rbp), %rdi
movq -0x250(%rbp), %rsi
leaq -0x25aa(%rip), %rdx     # 0x257c0
callq 0x285d0
jmp 0x27d71
leaq -0x298(%rbp), %rdi
callq 0xb8b0
jmp 0x27d7f
leaq -0x1e0(%rbp), %rdi
callq 0x1e270
movq %rax, -0x2a0(%rbp)
leaq -0x1e0(%rbp), %rdi
callq 0x1e0f0
movq %rax, -0x2a8(%rbp)
leaq -0x2a0(%rbp), %rdi
leaq -0x2a8(%rbp), %rsi
callq 0x28620
testb $0x1, %al
jne 0x27dc1
jmp 0x27ff7
leaq -0x2a0(%rbp), %rdi
callq 0x28660
movsd 0x8(%rax), %xmm0
movsd %xmm0, -0x2b0(%rbp)
leaq -0x1e0(%rbp), %rdi
callq 0x1e0f0
movq %rax, -0x2b8(%rbp)
leaq -0x2a0(%rbp), %rdi
leaq -0x2b8(%rbp), %rsi
callq 0x28620
movb %al, %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, -0x349(%rbp)
jne 0x27e11
jmp 0x27e38
leaq -0x2a0(%rbp), %rdi
callq 0x28660
movsd 0x8(%rax), %xmm0
ucomisd -0x2b0(%rbp), %xmm0
sete %al
setnp %cl
andb %cl, %al
movb %al, -0x349(%rbp)
movb -0x349(%rbp), %al
testb $0x1, %al
jne 0x27e47
jmp 0x27fc3
movq -0x2e8(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x360(%rbp)
leaq -0x2a0(%rbp), %rdi
callq 0x28660
movq -0x360(%rbp), %rdi
movq (%rax), %rsi
callq 0x13a40
movq %rax, -0x358(%rbp)
jmp 0x27e7d
movq -0x2e8(%rbp), %rax
movq -0x358(%rbp), %rcx
movq %rcx, -0x2c0(%rbp)
movq 0x8(%rax), %rdi
movq -0x2c0(%rbp), %rsi
callq 0x13b50
movq %rax, -0x368(%rbp)
jmp 0x27eab
movq -0x368(%rbp), %rax
movq %rax, -0x2c8(%rbp)
leaq -0x2a0(%rbp), %rdi
callq 0x28660
movq (%rax), %rsi
leaq -0x1a0(%rbp), %rdi
callq 0x274a0
jmp 0x27ed6
leaq -0x2a0(%rbp), %rdi
callq 0x28660
movq (%rax), %rsi
leaq -0x1c8(%rbp), %rdi
callq 0x27550
jmp 0x27ef3
leaq -0x1c8(%rbp), %rdi
callq 0x28680
movq %rax, -0x370(%rbp)
jmp 0x27f08
movq -0x370(%rbp), %rdi
movq -0x2c0(%rbp), %rsi
callq 0x26830
movb %al, -0x371(%rbp)
jmp 0x27f23
movb -0x371(%rbp), %al
testb $0x1, %al
jne 0x27f2f
jmp 0x27fa9
cmpq $0x2, -0x2c8(%rbp)
jb 0x27fa9
leaq -0x1a0(%rbp), %rdi
callq 0x28680
movq %rax, -0x380(%rbp)
jmp 0x27f4e
movq -0x380(%rbp), %rdi
movq -0x2c0(%rbp), %rsi
callq 0x24930
movq %rax, -0x388(%rbp)
jmp 0x27f6a
movq -0x388(%rbp), %rax
shlq %rax
cmpq -0x2c8(%rbp), %rax
jbe 0x27fa9
movq -0x2c0(%rbp), %rsi
leaq -0x1a0(%rbp), %rdi
callq 0x27600
jmp 0x27f92
movq -0x2c0(%rbp), %rsi
leaq -0x1c8(%rbp), %rdi
callq 0x27700
jmp 0x27fa7
jmp 0x27fa9
leaq -0x2a0(%rbp), %rdi
xorl %esi, %esi
callq 0x286a0
movq %rax, -0x2d0(%rbp)
jmp 0x27dda
movq -0x2e8(%rbp), %rdi
movq -0x10(%rbp), %rcx
movsd -0x2b0(%rbp), %xmm0
leaq -0x1a0(%rbp), %rsi
leaq -0x1c8(%rbp), %rdx
leaq -0x298(%rbp), %r8
callq 0x28120
jmp 0x27ff2
jmp 0x27d92
movq -0x2e8(%rbp), %rsi
addq $0xb8, %rsi
leaq -0x2e0(%rbp), %rdi
callq 0x286e0
jmp 0x28013
movq -0x2e8(%rbp), %rax
movq 0xa8(%rax), %rsi
leaq -0x298(%rbp), %rdi
callq 0xbb70
movb %al, -0x389(%rbp)
jmp 0x28035
movb -0x389(%rbp), %al
testb $0x1, %al
jne 0x28041
jmp 0x28083
movq -0x2e8(%rbp), %rax
movq 0xa8(%rax), %rdi
movq (%rdi), %rax
movq 0x8(%rax), %rax
leaq -0x298(%rbp), %rsi
callq *%rax
jmp 0x28061
jmp 0x28083
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x170(%rbp)
movl %eax, -0x174(%rbp)
leaq -0x2e0(%rbp), %rdi
callq 0x28770
jmp 0x280dd
movq -0x2e8(%rbp), %rax
movq 0xe0(%rax), %rdi
callq 0x28720
jmp 0x28098
leaq -0x2e0(%rbp), %rdi
callq 0x28770
leaq -0x210(%rbp), %rdi
callq 0xc190
leaq -0x1e0(%rbp), %rdi
callq 0x1ce90
leaq -0x168(%rbp), %rdi
callq 0xa610
leaq -0xc8(%rbp), %rdi
callq 0xa610
addq $0x390, %rsp            # imm = 0x390
popq %rbp
retq
leaq -0x210(%rbp), %rdi
callq 0xc190
leaq -0x1e0(%rbp), %rdi
callq 0x1ce90
leaq -0x168(%rbp), %rdi
callq 0xa610
leaq -0xc8(%rbp), %rdi
callq 0xa610
movq -0x170(%rbp), %rdi
callq 0x5750
nopl (%rax)