// File: cjlin1[P]liblinear/linear.cpp
// Function: group_classes(problem const*, int*, int**, int**, int**, int*)
static void group_classes(const problem *prob, int *nr_class_ret, int **label_ret, int **start_ret, int **count_ret, int *perm)
{
	int l = prob->l;
	int max_nr_class = 16;
	int nr_class = 0;
	int *label = Malloc(int,max_nr_class);
	int *count = Malloc(int,max_nr_class);
	int *data_label = Malloc(int,l);
	int i;

	for(i=0;i<l;i++)
	{
		int this_label = (int)prob->y[i];
		int j;
		for(j=0;j<nr_class;j++)
		{
			if(this_label == label[j])
			{
				++count[j];
				break;
			}
		}
		data_label[i] = j;
		if(j == nr_class)
		{
			if(nr_class == max_nr_class)
			{
				max_nr_class *= 2;
				label = (int *)realloc(label,max_nr_class*sizeof(int));
				count = (int *)realloc(count,max_nr_class*sizeof(int));
			}
			label[nr_class] = this_label;
			count[nr_class] = 1;
			++nr_class;
		}
	}

	//
	// Labels are ordered by their first occurrence in the training set.
	// However, for two-class sets with -1/+1 labels and -1 appears first,
	// we swap labels to ensure that internally the binary SVM has positive data corresponding to the +1 instances.
	//
	if (nr_class == 2 && label[0] == -1 && label[1] == 1)
	{
		swap(label[0],label[1]);
		swap(count[0],count[1]);
		for(i=0;i<l;i++)
		{
			if(data_label[i] == 0)
				data_label[i] = 1;
			else
				data_label[i] = 0;
		}
	}

	int *start = Malloc(int,nr_class);
	start[0] = 0;
	for(i=1;i<nr_class;i++)
		start[i] = start[i-1]+count[i-1];
	for(i=0;i<l;i++)
	{
		perm[start[data_label[i]]] = i;
		++start[data_label[i]];
	}
	start[0] = 0;
	for(i=1;i<nr_class;i++)
		start[i] = start[i-1]+count[i-1];

	*nr_class_ret = nr_class;
	*label_ret = label;
	*start_ret = start;
	*count_ret = count;
	free(data_label);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq %r8, -0x28(%rbp)
movq %r9, -0x30(%rbp)
movq -0x8(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x34(%rbp)
movl $0x10, -0x38(%rbp)
movl $0x0, -0x3c(%rbp)
movslq -0x38(%rbp), %rdi
shlq $0x2, %rdi
callq 0x21c0
movq %rax, -0x48(%rbp)
movslq -0x38(%rbp), %rdi
shlq $0x2, %rdi
callq 0x21c0
movq %rax, -0x50(%rbp)
movslq -0x34(%rbp), %rdi
shlq $0x2, %rdi
callq 0x21c0
movq %rax, -0x58(%rbp)
movl $0x0, -0x5c(%rbp)
movl -0x5c(%rbp), %eax
cmpl -0x34(%rbp), %eax
jge 0x9656
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movslq -0x5c(%rbp), %rcx
cvttsd2si (%rax,%rcx,8), %eax
movl %eax, -0x60(%rbp)
movl $0x0, -0x64(%rbp)
movl -0x64(%rbp), %eax
cmpl -0x3c(%rbp), %eax
jge 0x95d0
movl -0x60(%rbp), %eax
movq -0x48(%rbp), %rcx
movslq -0x64(%rbp), %rdx
cmpl (%rcx,%rdx,4), %eax
jne 0x95c3
movq -0x50(%rbp), %rax
movslq -0x64(%rbp), %rcx
movl (%rax,%rcx,4), %edx
addl $0x1, %edx
movl %edx, (%rax,%rcx,4)
jmp 0x95d0
jmp 0x95c5
movl -0x64(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x64(%rbp)
jmp 0x9598
movl -0x64(%rbp), %edx
movq -0x58(%rbp), %rax
movslq -0x5c(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movl -0x64(%rbp), %eax
cmpl -0x3c(%rbp), %eax
jne 0x9646
movl -0x3c(%rbp), %eax
cmpl -0x38(%rbp), %eax
jne 0x9620
movl -0x38(%rbp), %eax
shll %eax
movl %eax, -0x38(%rbp)
movq -0x48(%rbp), %rdi
movslq -0x38(%rbp), %rsi
shlq $0x2, %rsi
callq 0x2230
movq %rax, -0x48(%rbp)
movq -0x50(%rbp), %rdi
movslq -0x38(%rbp), %rsi
shlq $0x2, %rsi
callq 0x2230
movq %rax, -0x50(%rbp)
movl -0x60(%rbp), %edx
movq -0x48(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movq -0x50(%rbp), %rax
movslq -0x3c(%rbp), %rcx
movl $0x1, (%rax,%rcx,4)
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c(%rbp)
jmp 0x9648
movl -0x5c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x5c(%rbp)
jmp 0x9571
cmpl $0x2, -0x3c(%rbp)
jne 0x96e1
movq -0x48(%rbp), %rax
cmpl $-0x1, (%rax)
jne 0x96e1
movq -0x48(%rbp), %rax
cmpl $0x1, 0x4(%rax)
jne 0x96e1
movq -0x48(%rbp), %rdi
movq -0x48(%rbp), %rsi
addq $0x4, %rsi
callq 0x70b0
movq -0x50(%rbp), %rdi
movq -0x50(%rbp), %rsi
addq $0x4, %rsi
callq 0x70b0
movl $0x0, -0x5c(%rbp)
movl -0x5c(%rbp), %eax
cmpl -0x34(%rbp), %eax
jge 0x96df
movq -0x58(%rbp), %rax
movslq -0x5c(%rbp), %rcx
cmpl $0x0, (%rax,%rcx,4)
jne 0x96c3
movq -0x58(%rbp), %rax
movslq -0x5c(%rbp), %rcx
movl $0x1, (%rax,%rcx,4)
jmp 0x96d2
movq -0x58(%rbp), %rax
movslq -0x5c(%rbp), %rcx
movl $0x0, (%rax,%rcx,4)
jmp 0x96d4
movl -0x5c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x5c(%rbp)
jmp 0x969c
jmp 0x96e1
movslq -0x3c(%rbp), %rdi
shlq $0x2, %rdi
callq 0x21c0
movq %rax, -0x70(%rbp)
movq -0x70(%rbp), %rax
movl $0x0, (%rax)
movl $0x1, -0x5c(%rbp)
movl -0x5c(%rbp), %eax
cmpl -0x3c(%rbp), %eax
jge 0x9741
movq -0x70(%rbp), %rax
movl -0x5c(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movl (%rax,%rcx,4), %edx
movq -0x50(%rbp), %rax
movl -0x5c(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
addl (%rax,%rcx,4), %edx
movq -0x70(%rbp), %rax
movslq -0x5c(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movl -0x5c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x5c(%rbp)
jmp 0x9703
movl $0x0, -0x5c(%rbp)
movl -0x5c(%rbp), %eax
cmpl -0x34(%rbp), %eax
jge 0x9792
movl -0x5c(%rbp), %edx
movq -0x30(%rbp), %rax
movq -0x70(%rbp), %rcx
movq -0x58(%rbp), %rsi
movslq -0x5c(%rbp), %rdi
movslq (%rsi,%rdi,4), %rsi
movslq (%rcx,%rsi,4), %rcx
movl %edx, (%rax,%rcx,4)
movq -0x70(%rbp), %rax
movq -0x58(%rbp), %rcx
movslq -0x5c(%rbp), %rdx
movslq (%rcx,%rdx,4), %rcx
movl (%rax,%rcx,4), %edx
addl $0x1, %edx
movl %edx, (%rax,%rcx,4)
movl -0x5c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x5c(%rbp)
jmp 0x9748
movq -0x70(%rbp), %rax
movl $0x0, (%rax)
movl $0x1, -0x5c(%rbp)
movl -0x5c(%rbp), %eax
cmpl -0x3c(%rbp), %eax
jge 0x97e1
movq -0x70(%rbp), %rax
movl -0x5c(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movl (%rax,%rcx,4), %edx
movq -0x50(%rbp), %rax
movl -0x5c(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
addl (%rax,%rcx,4), %edx
movq -0x70(%rbp), %rax
movslq -0x5c(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movl -0x5c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x5c(%rbp)
jmp 0x97a3
movl -0x3c(%rbp), %ecx
movq -0x10(%rbp), %rax
movl %ecx, (%rax)
movq -0x48(%rbp), %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
movq -0x70(%rbp), %rcx
movq -0x20(%rbp), %rax
movq %rcx, (%rax)
movq -0x50(%rbp), %rcx
movq -0x28(%rbp), %rax
movq %rcx, (%rax)
movq -0x58(%rbp), %rdi
callq 0x2180
addq $0x70, %rsp
popq %rbp
retq
nopw (%rax,%rax)