// File: CK7[P]abawaca/src/ClusterSeparator.cpp
// Function: ClusterSeparator::separate()
bool ClusterSeparator::separate()
{
	// Start by cleaning everything from previous runs
	if(this->cluster1 != NULL)
		delete(this->cluster1);
	if(this->cluster2 != NULL)
		delete(this->cluster2);
	this->cluster1 = this->cluster2 = NULL;
	this->best_separation->reset();
	this->raw_dps_cluster1.clear();
	this->raw_dps_cluster2.clear();

/*	for(size_t dimension_index=1; dimension_index<=clustering_db.ndimensions(); dimension_index++) {
		this->separate_dimension(dimension_index);
	}*/
	thread*	threads = new thread[clustering_db.ndimensions()];
	for(size_t dimension_index=1; dimension_index<=clustering_db.ndimensions(); dimension_index++) {
		threads[dimension_index-1] = thread(call_separate_dimension, this, dimension_index);
	}
	for(auto i=0; i<clustering_db.ndimensions(); i++)
		threads[i].join();
	delete[] (threads);

	this->reconstruct_best_clusters();

	// If no significant separation was found simply return false
	if(cluster1 == NULL)
		return false;

	// Before switching datapoints between the clusters keep the original sets
	for(auto sit = cluster1->dps_begin(); sit != cluster1->dps_end(); sit++)
		raw_dps_cluster1.insert(*sit);
	for(auto sit = cluster2->dps_begin(); sit != cluster2->dps_end(); sit++)
		raw_dps_cluster2.insert(*sit);

	// Now decide, for each scaffold, to which cluster it belongs. Cluster1 will contain all scaffolds that have at least half
	// of their datapoints in it, cluster2 will contain the rest
	for(auto mit = cluster1->scafs_begin(); mit != cluster1->scafs_end(); mit++)
		if(2*mit->second >= scaf_db.ndps(mit->first)) {
			cluster1->add_assigned_scaf(mit->first);
		}
	for(auto mit = cluster2->scafs_begin(); mit != cluster2->scafs_end(); mit++)
		if(2*mit->second > scaf_db.ndps(mit->first)) {
			cluster2->add_assigned_scaf(mit->first);
		}

	// Now move the datapoints based on their scaffold assignment
	set<size_t> dps;
	for(auto sit = cluster1->dps_begin(); sit != cluster1->dps_end(); sit++)
		if(!cluster1->assigned(scaf_db.dp2scaf(*sit)))
			dps.insert(*sit);

	for(auto sit = dps.begin(); sit != dps.end(); sit++) {
		*cluster1 -= *sit;
		*cluster2 += *sit;
	}

	dps.clear();
	for(auto sit = cluster2->dps_begin(); sit != cluster2->dps_end(); sit++)
		if(!cluster2->assigned(scaf_db.dp2scaf(*sit)))
			dps.insert(*sit);

	for(auto sit = dps.begin(); sit != dps.end(); sit++) {
		*cluster1 += *sit;
		*cluster2 -= *sit;
	}

	// Check again if the resulting clusters are sufficiently large.
	if((cluster1->ndps() < this->cluster_ndps_threshold) || (cluster2->ndps() < this->cluster_ndps_threshold)) {
		delete(cluster1);
		cluster1 = NULL;
		delete(cluster2);
		cluster2 = NULL;
		best_separation->reset();
		return false;
	}

	return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x2d0, %rsp            # imm = 0x2D0
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x188(%rbp)
cmpq $0x0, 0x28(%rax)
je 0x25b23
movq -0x188(%rbp), %rax
movq 0x28(%rax), %rax
movq %rax, -0x190(%rbp)
cmpq $0x0, %rax
je 0x25b21
movq -0x190(%rbp), %rdi
callq 0xa610
movq -0x190(%rbp), %rdi
callq 0x53a0
jmp 0x25b23
movq -0x188(%rbp), %rax
cmpq $0x0, 0x30(%rax)
je 0x25b63
movq -0x188(%rbp), %rax
movq 0x30(%rax), %rax
movq %rax, -0x198(%rbp)
cmpq $0x0, %rax
je 0x25b61
movq -0x198(%rbp), %rdi
callq 0xa610
movq -0x198(%rbp), %rdi
callq 0x53a0
jmp 0x25b63
movq -0x188(%rbp), %rax
movq $0x0, 0x30(%rax)
movq $0x0, 0x28(%rax)
movq 0xa8(%rax), %rdi
movq (%rdi), %rax
callq *(%rax)
movq -0x188(%rbp), %rdi
addq $0x38, %rdi
callq 0x26660
movq -0x188(%rbp), %rdi
addq $0x70, %rdi
callq 0x26660
movq -0x188(%rbp), %rax
movq 0x18(%rax), %rdi
callq 0x20620
movq %rax, -0x1a8(%rbp)
movl $0x8, %ecx
mulq %rcx
movq %rax, %rdi
seto %cl
addq $0x8, %rdi
setb %al
orb %al, %cl
movq $-0x1, %rax
testb $0x1, %cl
cmovneq %rax, %rdi
callq 0x5040
movq %rax, %rcx
movq -0x1a8(%rbp), %rax
movq %rax, (%rcx)
addq $0x8, %rcx
movq %rcx, -0x1a0(%rbp)
cmpq $0x0, %rax
je 0x25c5c
movq -0x1a0(%rbp), %rax
movq -0x1a8(%rbp), %rdx
shlq $0x3, %rdx
movq %rax, %rcx
addq %rdx, %rcx
movq %rcx, -0x1b8(%rbp)
movq %rax, -0x1b0(%rbp)
movq -0x1b0(%rbp), %rdi
movq %rdi, -0x1c0(%rbp)
callq 0x26680
movq -0x1c0(%rbp), %rax
movq -0x1b8(%rbp), %rcx
addq $0x8, %rax
cmpq %rcx, %rax
movq %rax, -0x1b0(%rbp)
jne 0x25c2b
movq -0x1a0(%rbp), %rax
movq %rax, -0x18(%rbp)
movq $0x1, -0x20(%rbp)
movq -0x188(%rbp), %rax
movq -0x20(%rbp), %rcx
movq %rcx, -0x1c8(%rbp)
movq 0x18(%rax), %rdi
callq 0x20620
movq %rax, %rcx
movq -0x1c8(%rbp), %rax
cmpq %rcx, %rax
ja 0x25cef
movq -0x188(%rbp), %rax
movq %rax, -0x30(%rbp)
leaq -0x28(%rbp), %rdi
leaq -0x44f(%rip), %rsi      # 0x25860
leaq -0x30(%rbp), %rdx
leaq -0x20(%rbp), %rcx
callq 0x266a0
movq -0x18(%rbp), %rdi
movq -0x20(%rbp), %rax
subq $0x1, %rax
shlq $0x3, %rax
addq %rax, %rdi
leaq -0x28(%rbp), %rsi
callq 0x26760
leaq -0x28(%rbp), %rdi
callq 0x267a0
movq -0x20(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x20(%rbp)
jmp 0x25c6f
movl $0x0, -0x34(%rbp)
movq -0x188(%rbp), %rax
movslq -0x34(%rbp), %rcx
movq %rcx, -0x1d0(%rbp)
movq 0x18(%rax), %rdi
callq 0x20620
movq %rax, %rcx
movq -0x1d0(%rbp), %rax
cmpq %rcx, %rax
jae 0x25d3f
movq -0x18(%rbp), %rdi
movslq -0x34(%rbp), %rax
shlq $0x3, %rax
addq %rax, %rdi
callq 0x56f0
movl -0x34(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x34(%rbp)
jmp 0x25cf6
movq -0x18(%rbp), %rax
movq %rax, -0x1d8(%rbp)
cmpq $0x0, %rax
je 0x25dbc
movq -0x1d8(%rbp), %rcx
movq %rcx, %rax
addq $-0x8, %rax
movq %rax, -0x1e8(%rbp)
movq -0x8(%rcx), %rdx
shlq $0x3, %rdx
movq %rcx, %rax
addq %rdx, %rax
cmpq %rax, %rcx
movq %rax, -0x1e0(%rbp)
je 0x25db0
movq -0x1e0(%rbp), %rdi
addq $-0x8, %rdi
movq %rdi, -0x1f0(%rbp)
callq 0x267a0
movq -0x1d8(%rbp), %rcx
movq -0x1f0(%rbp), %rax
cmpq %rcx, %rax
movq %rax, -0x1e0(%rbp)
jne 0x25d7f
movq -0x1e8(%rbp), %rdi
callq 0x5540
movq -0x188(%rbp), %rdi
callq 0x25890
movq -0x188(%rbp), %rax
cmpq $0x0, 0x28(%rax)
jne 0x25ddf
movb $0x0, -0x1(%rbp)
jmp 0x265b1
movq -0x188(%rbp), %rax
movq 0x28(%rax), %rdi
callq 0xa1a0
movq %rax, -0x40(%rbp)
movq -0x188(%rbp), %rax
movq 0x28(%rax), %rdi
callq 0xa200
movq %rax, -0x48(%rbp)
leaq -0x40(%rbp), %rdi
leaq -0x48(%rbp), %rsi
callq 0xa1d0
testb $0x1, %al
jne 0x25e1a
jmp 0x25e5c
movq -0x188(%rbp), %rax
addq $0x38, %rax
movq %rax, -0x1f8(%rbp)
leaq -0x40(%rbp), %rdi
callq 0xa310
movq -0x1f8(%rbp), %rdi
movq %rax, %rsi
callq 0x209e0
movq %rax, -0x58(%rbp)
movb %dl, -0x50(%rbp)
leaq -0x40(%rbp), %rdi
xorl %esi, %esi
callq 0xa340
movq %rax, -0x60(%rbp)
jmp 0x25df3
movq -0x188(%rbp), %rax
movq 0x30(%rax), %rdi
callq 0xa1a0
movq %rax, -0x68(%rbp)
movq -0x188(%rbp), %rax
movq 0x30(%rax), %rdi
callq 0xa200
movq %rax, -0x70(%rbp)
leaq -0x68(%rbp), %rdi
leaq -0x70(%rbp), %rsi
callq 0xa1d0
testb $0x1, %al
jne 0x25e97
jmp 0x25edc
movq -0x188(%rbp), %rax
addq $0x70, %rax
movq %rax, -0x200(%rbp)
leaq -0x68(%rbp), %rdi
callq 0xa310
movq -0x200(%rbp), %rdi
movq %rax, %rsi
callq 0x209e0
movq %rax, -0x80(%rbp)
movb %dl, -0x78(%rbp)
leaq -0x68(%rbp), %rdi
xorl %esi, %esi
callq 0xa340
movq %rax, -0x88(%rbp)
jmp 0x25e70
movq -0x188(%rbp), %rax
movq 0x28(%rax), %rdi
callq 0x267d0
movq %rax, -0x90(%rbp)
movq -0x188(%rbp), %rax
movq 0x28(%rax), %rdi
callq 0x26800
movq %rax, -0x98(%rbp)
leaq -0x90(%rbp), %rdi
leaq -0x98(%rbp), %rsi
callq 0x218d0
testb $0x1, %al
jne 0x25f26
jmp 0x25fc8
leaq -0x90(%rbp), %rdi
callq 0x1d0c0
movq %rax, %rcx
movq -0x188(%rbp), %rax
movq 0x8(%rcx), %rcx
shlq %rcx
movq %rcx, -0x208(%rbp)
movq 0x8(%rax), %rax
movq %rax, -0x210(%rbp)
leaq -0x90(%rbp), %rdi
callq 0x1d0c0
movq -0x210(%rbp), %rdi
movq (%rax), %rsi
callq 0x13b50
movq %rax, %rcx
movq -0x208(%rbp), %rax
cmpq %rcx, %rax
jb 0x25fac
movq -0x188(%rbp), %rax
movq 0x28(%rax), %rax
movq %rax, -0x218(%rbp)
leaq -0x90(%rbp), %rdi
callq 0x1d0c0
movq -0x218(%rbp), %rdi
movq (%rax), %rsi
callq 0xac90
jmp 0x25fae
leaq -0x90(%rbp), %rdi
xorl %esi, %esi
callq 0x24650
movq %rax, -0xa0(%rbp)
jmp 0x25ef3
movq -0x188(%rbp), %rax
movq 0x30(%rax), %rdi
callq 0x267d0
movq %rax, -0xa8(%rbp)
movq -0x188(%rbp), %rax
movq 0x30(%rax), %rdi
callq 0x26800
movq %rax, -0xb0(%rbp)
leaq -0xa8(%rbp), %rdi
leaq -0xb0(%rbp), %rsi
callq 0x218d0
testb $0x1, %al
jne 0x26012
jmp 0x260b4
leaq -0xa8(%rbp), %rdi
callq 0x1d0c0
movq %rax, %rcx
movq -0x188(%rbp), %rax
movq 0x8(%rcx), %rcx
shlq %rcx
movq %rcx, -0x220(%rbp)
movq 0x8(%rax), %rax
movq %rax, -0x228(%rbp)
leaq -0xa8(%rbp), %rdi
callq 0x1d0c0
movq -0x228(%rbp), %rdi
movq (%rax), %rsi
callq 0x13b50
movq %rax, %rcx
movq -0x220(%rbp), %rax
cmpq %rcx, %rax
jbe 0x26098
movq -0x188(%rbp), %rax
movq 0x30(%rax), %rax
movq %rax, -0x230(%rbp)
leaq -0xa8(%rbp), %rdi
callq 0x1d0c0
movq -0x230(%rbp), %rdi
movq (%rax), %rsi
callq 0xac90
jmp 0x2609a
leaq -0xa8(%rbp), %rdi
xorl %esi, %esi
callq 0x24650
movq %rax, -0xb8(%rbp)
jmp 0x25fdf
leaq -0xe8(%rbp), %rdi
callq 0xefa0
movq -0x188(%rbp), %rax
movq 0x28(%rax), %rdi
callq 0xa1a0
movq %rax, -0x238(%rbp)
jmp 0x260d9
movq -0x238(%rbp), %rax
movq %rax, -0xf0(%rbp)
movq -0x188(%rbp), %rax
movq 0x28(%rax), %rdi
callq 0xa200
movq %rax, -0x240(%rbp)
jmp 0x26100
movq -0x240(%rbp), %rax
movq %rax, -0x108(%rbp)
leaq -0xf0(%rbp), %rdi
leaq -0x108(%rbp), %rsi
callq 0xa1d0
testb $0x1, %al
jne 0x2612a
jmp 0x26217
movq -0x188(%rbp), %rax
movq 0x8(%rax), %rcx
movq %rcx, -0x250(%rbp)
movq 0x28(%rax), %rax
movq %rax, -0x258(%rbp)
leaq -0xf0(%rbp), %rdi
callq 0xa310
movq -0x250(%rbp), %rdi
movq (%rax), %rsi
callq 0x13a40
movq %rax, -0x248(%rbp)
jmp 0x2616b
movq -0x248(%rbp), %rsi
movq -0x258(%rbp), %rdi
callq 0x26830
movb %al, -0x259(%rbp)
jmp 0x26186
movb -0x259(%rbp), %al
testb $0x1, %al
jne 0x261fb
jmp 0x26192
leaq -0xf0(%rbp), %rdi
callq 0xa310
movq %rax, %rsi
leaq -0xe8(%rbp), %rdi
callq 0xf050
movb %dl, -0x269(%rbp)
movq %rax, -0x268(%rbp)
jmp 0x261bc
movb -0x269(%rbp), %al
movq -0x268(%rbp), %rcx
movq %rcx, -0x118(%rbp)
movb %al, -0x110(%rbp)
jmp 0x261fb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xf8(%rbp)
movl %eax, -0xfc(%rbp)
leaq -0xe8(%rbp), %rdi
callq 0xc190
jmp 0x265bf
jmp 0x261fd
leaq -0xf0(%rbp), %rdi
xorl %esi, %esi
callq 0xa340
movq %rax, -0x120(%rbp)
jmp 0x260e7
leaq -0xe8(%rbp), %rdi
callq 0xa8e0
movq %rax, -0x128(%rbp)
leaq -0xe8(%rbp), %rdi
callq 0xa910
movq %rax, -0x130(%rbp)
leaq -0x128(%rbp), %rdi
leaq -0x130(%rbp), %rsi
callq 0xa3a0
testb $0x1, %al
jne 0x26256
jmp 0x262ba
leaq -0x128(%rbp), %rdi
callq 0xa400
movq %rax, %rcx
movq -0x188(%rbp), %rax
movq (%rcx), %rsi
movq 0x28(%rax), %rdi
callq 0x249b0
jmp 0x2627a
leaq -0x128(%rbp), %rdi
callq 0xa400
movq %rax, %rcx
movq -0x188(%rbp), %rax
movq (%rcx), %rsi
movq 0x30(%rax), %rdi
callq 0x24800
jmp 0x2629e
jmp 0x262a0
leaq -0x128(%rbp), %rdi
xorl %esi, %esi
callq 0xa420
movq %rax, -0x138(%rbp)
jmp 0x2622a
leaq -0xe8(%rbp), %rdi
callq 0x26880
movq -0x188(%rbp), %rax
movq 0x30(%rax), %rdi
callq 0xa1a0
movq %rax, -0x278(%rbp)
jmp 0x262df
movq -0x278(%rbp), %rax
movq %rax, -0x140(%rbp)
movq -0x188(%rbp), %rax
movq 0x30(%rax), %rdi
callq 0xa200
movq %rax, -0x280(%rbp)
jmp 0x26306
movq -0x280(%rbp), %rax
movq %rax, -0x148(%rbp)
leaq -0x140(%rbp), %rdi
leaq -0x148(%rbp), %rsi
callq 0xa1d0
testb $0x1, %al
jne 0x26330
jmp 0x263f8
movq -0x188(%rbp), %rax
movq 0x8(%rax), %rcx
movq %rcx, -0x290(%rbp)
movq 0x30(%rax), %rax
movq %rax, -0x298(%rbp)
leaq -0x140(%rbp), %rdi
callq 0xa310
movq -0x290(%rbp), %rdi
movq (%rax), %rsi
callq 0x13a40
movq %rax, -0x288(%rbp)
jmp 0x26371
movq -0x288(%rbp), %rsi
movq -0x298(%rbp), %rdi
callq 0x26830
movb %al, -0x299(%rbp)
jmp 0x2638c
movb -0x299(%rbp), %al
testb $0x1, %al
jne 0x263dc
jmp 0x26398
leaq -0x140(%rbp), %rdi
callq 0xa310
movq %rax, %rsi
leaq -0xe8(%rbp), %rdi
callq 0xf050
movb %dl, -0x2a9(%rbp)
movq %rax, -0x2a8(%rbp)
jmp 0x263c2
movb -0x2a9(%rbp), %al
movq -0x2a8(%rbp), %rcx
movq %rcx, -0x158(%rbp)
movb %al, -0x150(%rbp)
jmp 0x263de
leaq -0x140(%rbp), %rdi
xorl %esi, %esi
callq 0xa340
movq %rax, -0x160(%rbp)
jmp 0x262ed
leaq -0xe8(%rbp), %rdi
callq 0xa8e0
movq %rax, -0x168(%rbp)
leaq -0xe8(%rbp), %rdi
callq 0xa910
movq %rax, -0x170(%rbp)
leaq -0x168(%rbp), %rdi
leaq -0x170(%rbp), %rsi
callq 0xa3a0
testb $0x1, %al
jne 0x26437
jmp 0x2649b
leaq -0x168(%rbp), %rdi
callq 0xa400
movq %rax, %rcx
movq -0x188(%rbp), %rax
movq (%rcx), %rsi
movq 0x28(%rax), %rdi
callq 0x24800
jmp 0x2645b
leaq -0x168(%rbp), %rdi
callq 0xa400
movq %rax, %rcx
movq -0x188(%rbp), %rax
movq (%rcx), %rsi
movq 0x30(%rax), %rdi
callq 0x249b0
jmp 0x2647f
jmp 0x26481
leaq -0x168(%rbp), %rdi
xorl %esi, %esi
callq 0xa420
movq %rax, -0x178(%rbp)
jmp 0x2640b
movq -0x188(%rbp), %rax
movq 0x28(%rax), %rdi
callq 0xa030
movq %rax, -0x2b8(%rbp)
jmp 0x264b4
movq -0x2b8(%rbp), %rax
movq -0x188(%rbp), %rcx
cmpq 0xb0(%rcx), %rax
jb 0x264ff
movq -0x188(%rbp), %rax
movq 0x30(%rax), %rdi
callq 0xa030
movq %rax, -0x2c0(%rbp)
jmp 0x264e4
movq -0x2c0(%rbp), %rax
movq -0x188(%rbp), %rcx
cmpq 0xb0(%rcx), %rax
jae 0x26597
movq -0x188(%rbp), %rax
movq 0x28(%rax), %rax
movq %rax, -0x2c8(%rbp)
cmpq $0x0, %rax
je 0x2652f
movq -0x2c8(%rbp), %rdi
callq 0xa610
movq -0x2c8(%rbp), %rdi
callq 0x53a0
movq -0x188(%rbp), %rax
movq $0x0, 0x28(%rax)
movq 0x30(%rax), %rax
movq %rax, -0x2d0(%rbp)
cmpq $0x0, %rax
je 0x26567
movq -0x2d0(%rbp), %rdi
callq 0xa610
movq -0x2d0(%rbp), %rdi
callq 0x53a0
movq -0x188(%rbp), %rax
movq $0x0, 0x30(%rax)
movq 0xa8(%rax), %rdi
movq (%rdi), %rax
movq (%rax), %rax
callq *%rax
jmp 0x26587
movb $0x0, -0x1(%rbp)
movl $0x1, -0x17c(%rbp)
jmp 0x265a5
movb $0x1, -0x1(%rbp)
movl $0x1, -0x17c(%rbp)
leaq -0xe8(%rbp), %rdi
callq 0xc190
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x2d0, %rsp            # imm = 0x2D0
popq %rbp
retq
movq -0xf8(%rbp), %rdi
callq 0x5750
nopl (%rax,%rax)