// File: FreeSlave[P]vhlt/hlrad/loadtextures.cpp
// Function: CQ_SelectPartition(cq_node_s*)
static void CQ_SelectPartition (cq_node_t *node)
{
	CQ_VectorClear (node->centerofpoints);
	for (int i = 0; i < node->numpoints; i++)
	{
		CQ_VectorAdd (node->centerofpoints, node->refpoints[i], node->centerofpoints);
	}
	CQ_VectorScale (node->centerofpoints, 1 / (double)node->numpoints, node->centerofpoints);

	node->needsplit = false;
	for (int k = 0; k < CQ_DIM; k++)
	{
		double count;
		double counts[256];
		double sum[CQ_DIM];
		double sums[256][CQ_DIM];

		double bucketsums[256][CQ_DIM];
		int bucketsizes[256];

		const unsigned char (*nodepoints)[CQ_DIM] = node->refpoints;
		const int nodenumpoints = node->numpoints;

		memset (bucketsums, 0, 256 * sizeof (double [CQ_DIM]));
		memset (bucketsizes, 0, 256 * sizeof (int));
		for (int i = 0; i < nodenumpoints; i++)
		{
			int j = nodepoints[i][k];
			bucketsizes[j]++;
			CQ_VectorAdd (bucketsums[j], nodepoints[i], bucketsums[j]);
		}
		
		int min = 256;
		int max = -1;
		count = 0;
		CQ_VectorClear (sum);
		for (int j = 0; j < 256; j++)
		{
			counts[j] = count;
			CQ_VectorCopy (sum, sums[j]);
			count += bucketsizes[j];
			CQ_VectorAdd (sum, bucketsums[j], sum);
			if (bucketsizes[j] > 0)
			{
				if (j < min)
				{
					min = j;
				}
				if (j > max)
				{
					max = j;
				}
			}
		}
		if (max < min)
		{
			Error ("CQ_SelectPartition: internal error");
		}
		// sweep along the axis and find the plane that maximize square error reduction
		for (int j = min + 1; j < max + 1; j++)
		{
			double priority = 0; // the decrease in total square deviation
			priority -= CQ_DotProduct (sum, sum) / count;
			priority += CQ_DotProduct (sums[j], sums[j]) / counts[j];
			double remain[CQ_DIM];
			CQ_VectorSubtract (sum, sums[j], remain); // sums and counts are precise (have no round-off error)
			priority += CQ_DotProduct (remain, remain) / (count - counts[j]);
			if (node->needsplit == false ||
				priority > node->splitpriority + 0.1 ||
				priority >= node->splitpriority - 0.1
				&& fabs (counts[j] - count / 2) < fabs (node->bestsplitter.numpoints[0] - count / 2))
			{
				node->needsplit = true;
				node->splitpriority = priority;
				node->bestsplitter.axis = k;
				node->bestsplitter.dist = j;
				node->bestsplitter.numpoints[0] = counts[j];
				node->bestsplitter.numpoints[1] = count - counts[j];
			}
		}
	}
}

// Assembly:
subq $0x3c88, %rsp           # imm = 0x3C88
movq %rdi, 0x3c80(%rsp)
movq 0x3c80(%rsp), %rdi
addq $0x30, %rdi
callq 0x49bd0
movl $0x0, 0x3c7c(%rsp)
movl 0x3c7c(%rsp), %eax
movq 0x3c80(%rsp), %rcx
cmpl 0x20(%rcx), %eax
jge 0x494fa
movq 0x3c80(%rsp), %rdi
addq $0x30, %rdi
movq 0x3c80(%rsp), %rax
movq 0x28(%rax), %rsi
movslq 0x3c7c(%rsp), %rax
imulq $0x3, %rax, %rax
addq %rax, %rsi
movq 0x3c80(%rsp), %rdx
addq $0x30, %rdx
callq 0x49c10
movl 0x3c7c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3c7c(%rsp)
jmp 0x4949b
movq 0x3c80(%rsp), %rdi
addq $0x30, %rdi
movq 0x3c80(%rsp), %rax
cvtsi2sdl 0x20(%rax), %xmm1
movsd 0x23ccd(%rip), %xmm0    # 0x6d1e8
divsd %xmm1, %xmm0
movq 0x3c80(%rsp), %rsi
addq $0x30, %rsi
callq 0x49c70
movq 0x3c80(%rsp), %rax
movb $0x0, 0x48(%rax)
movl $0x0, 0x3c78(%rsp)
cmpl $0x3, 0x3c78(%rsp)
jge 0x499b2
movq 0x3c80(%rsp), %rax
movq 0x28(%rax), %rax
movq %rax, 0x48(%rsp)
movq 0x3c80(%rsp), %rax
movl 0x20(%rax), %eax
movl %eax, 0x44(%rsp)
leaq 0x450(%rsp), %rdi
xorl %esi, %esi
movl $0x1800, %edx           # imm = 0x1800
callq 0x41b0
leaq 0x50(%rsp), %rdi
xorl %esi, %esi
movl $0x400, %edx            # imm = 0x400
callq 0x41b0
movl $0x0, 0x40(%rsp)
movl 0x40(%rsp), %eax
cmpl 0x44(%rsp), %eax
jge 0x4962b
movq 0x48(%rsp), %rax
movslq 0x40(%rsp), %rcx
imulq $0x3, %rcx, %rcx
addq %rcx, %rax
movslq 0x3c78(%rsp), %rcx
movzbl (%rax,%rcx), %eax
movl %eax, 0x3c(%rsp)
movslq 0x3c(%rsp), %rax
movl 0x50(%rsp,%rax,4), %ecx
addl $0x1, %ecx
movl %ecx, 0x50(%rsp,%rax,4)
movslq 0x3c(%rsp), %rax
leaq 0x450(%rsp), %rdi
imulq $0x18, %rax, %rax
addq %rax, %rdi
movq 0x48(%rsp), %rsi
movslq 0x40(%rsp), %rax
imulq $0x3, %rax, %rax
addq %rax, %rsi
movslq 0x3c(%rsp), %rax
leaq 0x450(%rsp), %rdx
imulq $0x18, %rax, %rax
addq %rax, %rdx
callq 0x49c10
movl 0x40(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x40(%rsp)
jmp 0x495a2
movl $0x100, 0x38(%rsp)      # imm = 0x100
movl $0xffffffff, 0x34(%rsp) # imm = 0xFFFFFFFF
xorps %xmm0, %xmm0
movsd %xmm0, 0x3c70(%rsp)
leaq 0x3450(%rsp), %rdi
callq 0x49bd0
movl $0x0, 0x30(%rsp)
cmpl $0x100, 0x30(%rsp)      # imm = 0x100
jge 0x4972c
movsd 0x3c70(%rsp), %xmm0
movslq 0x30(%rsp), %rax
movsd %xmm0, 0x3470(%rsp,%rax,8)
leaq 0x3450(%rsp), %rdi
movslq 0x30(%rsp), %rax
leaq 0x1c50(%rsp), %rsi
imulq $0x18, %rax, %rax
addq %rax, %rsi
callq 0x49cd0
movslq 0x30(%rsp), %rax
cvtsi2sdl 0x50(%rsp,%rax,4), %xmm0
addsd 0x3c70(%rsp), %xmm0
movsd %xmm0, 0x3c70(%rsp)
leaq 0x3450(%rsp), %rdi
movslq 0x30(%rsp), %rax
leaq 0x450(%rsp), %rsi
imulq $0x18, %rax, %rax
addq %rax, %rsi
leaq 0x3450(%rsp), %rdx
callq 0x49d20
movslq 0x30(%rsp), %rax
cmpl $0x0, 0x50(%rsp,%rax,4)
jle 0x4971a
movl 0x30(%rsp), %eax
cmpl 0x38(%rsp), %eax
jge 0x49706
movl 0x30(%rsp), %eax
movl %eax, 0x38(%rsp)
movl 0x30(%rsp), %eax
cmpl 0x34(%rsp), %eax
jle 0x49718
movl 0x30(%rsp), %eax
movl %eax, 0x34(%rsp)
jmp 0x4971a
jmp 0x4971c
movl 0x30(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x30(%rsp)
jmp 0x4965c
movl 0x34(%rsp), %eax
cmpl 0x38(%rsp), %eax
jge 0x49744
leaq 0x253a6(%rip), %rdi     # 0x6eae3
movb $0x0, %al
callq 0xb580
movl 0x38(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2c(%rsp)
movl 0x2c(%rsp), %eax
movl 0x34(%rsp), %ecx
addl $0x1, %ecx
cmpl %ecx, %eax
jge 0x4999a
xorps %xmm0, %xmm0
movsd %xmm0, 0x20(%rsp)
leaq 0x3450(%rsp), %rdi
leaq 0x3450(%rsp), %rsi
callq 0x49d80
movaps %xmm0, %xmm1
divsd 0x3c70(%rsp), %xmm1
movsd 0x20(%rsp), %xmm0
subsd %xmm1, %xmm0
movsd %xmm0, 0x20(%rsp)
movslq 0x2c(%rsp), %rax
leaq 0x1c50(%rsp), %rdi
imulq $0x18, %rax, %rax
addq %rax, %rdi
movslq 0x2c(%rsp), %rax
leaq 0x1c50(%rsp), %rsi
imulq $0x18, %rax, %rax
addq %rax, %rsi
callq 0x49d80
movslq 0x2c(%rsp), %rax
divsd 0x3470(%rsp,%rax,8), %xmm0
addsd 0x20(%rsp), %xmm0
movsd %xmm0, 0x20(%rsp)
leaq 0x3450(%rsp), %rdi
movslq 0x2c(%rsp), %rax
leaq 0x1c50(%rsp), %rsi
imulq $0x18, %rax, %rax
addq %rax, %rsi
movq %rsp, %rdx
callq 0x49df0
movq %rsp, %rdi
movq %rsp, %rsi
callq 0x49d80
movsd 0x3c70(%rsp), %xmm1
movslq 0x2c(%rsp), %rax
subsd 0x3470(%rsp,%rax,8), %xmm1
divsd %xmm1, %xmm0
addsd 0x20(%rsp), %xmm0
movsd %xmm0, 0x20(%rsp)
movq 0x3c80(%rsp), %rax
movb 0x48(%rax), %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
je 0x49909
movsd 0x20(%rsp), %xmm0
movq 0x3c80(%rsp), %rax
movsd 0x23f90(%rip), %xmm1    # 0x6d7f8
addsd 0x68(%rax), %xmm1
ucomisd %xmm1, %xmm0
ja 0x49909
movsd 0x20(%rsp), %xmm0
movq 0x3c80(%rsp), %rax
movsd 0x68(%rax), %xmm1
movsd 0x23f66(%rip), %xmm2    # 0x6d7f8
subsd %xmm2, %xmm1
ucomisd %xmm1, %xmm0
jb 0x49988
movslq 0x2c(%rsp), %rax
movsd 0x3470(%rsp,%rax,8), %xmm1
movsd 0x3c70(%rsp), %xmm0
movsd 0x24379(%rip), %xmm2    # 0x6dc38
divsd %xmm2, %xmm0
subsd %xmm0, %xmm1
movaps 0x23fa2(%rip), %xmm0    # 0x6d870
pand %xmm0, %xmm1
movq 0x3c80(%rsp), %rax
movsd 0x58(%rax), %xmm0
movsd 0x3c70(%rsp), %xmm2
movsd 0x24348(%rip), %xmm3    # 0x6dc38
divsd %xmm3, %xmm2
subsd %xmm2, %xmm0
movaps 0x23f71(%rip), %xmm2    # 0x6d870
pand %xmm2, %xmm0
ucomisd %xmm1, %xmm0
jbe 0x49988
movq 0x3c80(%rsp), %rax
movb $0x1, 0x48(%rax)
movsd 0x20(%rsp), %xmm0
movq 0x3c80(%rsp), %rax
movsd %xmm0, 0x68(%rax)
movl 0x3c78(%rsp), %ecx
movq 0x3c80(%rsp), %rax
movl %ecx, 0x50(%rax)
movl 0x2c(%rsp), %ecx
movq 0x3c80(%rsp), %rax
movl %ecx, 0x54(%rax)
movslq 0x2c(%rsp), %rax
movsd 0x3470(%rsp,%rax,8), %xmm0
movq 0x3c80(%rsp), %rax
movsd %xmm0, 0x58(%rax)
movsd 0x3c70(%rsp), %xmm0
movslq 0x2c(%rsp), %rax
subsd 0x3470(%rsp,%rax,8), %xmm0
movq 0x3c80(%rsp), %rax
movsd %xmm0, 0x60(%rax)
jmp 0x4998a
movl 0x2c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2c(%rsp)
jmp 0x4974f
jmp 0x4999c
movl 0x3c78(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3c78(%rsp)
jmp 0x49547
addq $0x3c88, %rsp           # imm = 0x3C88
retq
nopw (%rax,%rax)