int main(int argc, char **argv) {
  unsigned long N = 3;
  double **weightVectors = (double **)malloc(N * sizeof(double *));
  unsigned long i = 0;
  unsigned long j = 0;
  for (i = 0; i < 3; i++)
    weightVectors[i] = (double *)malloc(3 * sizeof(double));
  for (i = 0; i < N; i++)
    for (j = 0; j < 3; weightVectors[i][j++] = i)
      ;
  double **learnSamples = (double **)malloc(N * sizeof(double *));
  for (i = 0; i < 3; i++)
    learnSamples[i] = (double *)malloc(3 * sizeof(double));
  for (i = 0; i < N; i++)
    for (j = 0; j < 3; learnSamples[i][j++] = i)
      ;
  printMat(weightVectors, N, 3);
  printMat(learnSamples, N, 3);
  double learnFactor = 1;
  double margin = 0.1;
  kernel_perceptron(weightVectors, N, learnSamples, N, learnFactor, margin, 3);
  for (i = 0; i < N; i++) {
    free(learnSamples[i]);
    free(weightVectors);
  }
  return 0;
}


x86 assembly (clang, -O0):
<main>:
push   %rbp
mov    %rsp,%rbp
sub    $0x50,%rsp
movl   $0x0,-0x4(%rbp)
mov    %edi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
movq   $0x3,-0x18(%rbp)
mov    -0x18(%rbp),%rdi
shl    $0x3,%rdi
call   1050 <malloc@plt>
mov    %rax,-0x20(%rbp)
movq   $0x0,-0x28(%rbp)
movq   $0x0,-0x30(%rbp)
movq   $0x0,-0x28(%rbp)
cmpq   $0x3,-0x28(%rbp)
jae    11bc <main+0x7c>
mov    $0x18,%edi
call   1050 <malloc@plt>
mov    %rax,%rdx
mov    -0x20(%rbp),%rax
mov    -0x28(%rbp),%rcx
mov    %rdx,(%rax,%rcx,8)
mov    -0x28(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x28(%rbp)
jmp    1187 <main+0x47>
movq   $0x0,-0x28(%rbp)
mov    -0x28(%rbp),%rax
cmp    -0x18(%rbp),%rax
jae    124c <main+0x10c>
movq   $0x0,-0x30(%rbp)
cmpq   $0x3,-0x30(%rbp)
jae    1236 <main+0xf6>
jmp    11ea <main+0xaa>
movaps 0xe1f(%rip),%xmm1
movq   -0x28(%rbp),%xmm0
punpckldq %xmm1,%xmm0
movapd 0xe1e(%rip),%xmm1
subpd  %xmm1,%xmm0
movaps %xmm0,%xmm1
unpckhpd %xmm0,%xmm0
addsd  %xmm1,%xmm0
mov    -0x20(%rbp),%rax
mov    -0x28(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
mov    -0x30(%rbp),%rcx
mov    %rcx,%rdx
add    $0x1,%rdx
mov    %rdx,-0x30(%rbp)
movsd  %xmm0,(%rax,%rcx,8)
jmp    11da <main+0x9a>
jmp    123b <main+0xfb>
mov    -0x28(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x28(%rbp)
jmp    11c4 <main+0x84>
mov    -0x18(%rbp),%rdi
shl    $0x3,%rdi
call   1050 <malloc@plt>
mov    %rax,-0x38(%rbp)
movq   $0x0,-0x28(%rbp)
cmpq   $0x3,-0x28(%rbp)
jae    129a <main+0x15a>
mov    $0x18,%edi
call   1050 <malloc@plt>
mov    %rax,%rdx
mov    -0x38(%rbp),%rax
mov    -0x28(%rbp),%rcx
mov    %rdx,(%rax,%rcx,8)
mov    -0x28(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x28(%rbp)
jmp    1265 <main+0x125>
movq   $0x0,-0x28(%rbp)
mov    -0x28(%rbp),%rax
cmp    -0x18(%rbp),%rax
jae    132a <main+0x1ea>
movq   $0x0,-0x30(%rbp)
cmpq   $0x3,-0x30(%rbp)
jae    1314 <main+0x1d4>
jmp    12c8 <main+0x188>
movaps 0xd41(%rip),%xmm1
movq   -0x28(%rbp),%xmm0
punpckldq %xmm1,%xmm0
movapd 0xd40(%rip),%xmm1
subpd  %xmm1,%xmm0
movaps %xmm0,%xmm1
unpckhpd %xmm0,%xmm0
addsd  %xmm1,%xmm0
mov    -0x38(%rbp),%rax
mov    -0x28(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
mov    -0x30(%rbp),%rcx
mov    %rcx,%rdx
add    $0x1,%rdx
mov    %rdx,-0x30(%rbp)
movsd  %xmm0,(%rax,%rcx,8)
jmp    12b8 <main+0x178>
jmp    1319 <main+0x1d9>
mov    -0x28(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x28(%rbp)
jmp    12a2 <main+0x162>
mov    -0x20(%rbp),%rdi
mov    -0x18(%rbp),%rsi
mov    $0x3,%edx
mov    $0x0,%al
call   1040 <printMat@plt>
mov    -0x38(%rbp),%rdi
mov    -0x18(%rbp),%rsi
mov    $0x3,%edx
mov    $0x0,%al
call   1040 <printMat@plt>
movsd  0xcae(%rip),%xmm0
movsd  %xmm0,-0x40(%rbp)
movsd  0xc99(%rip),%xmm0
movsd  %xmm0,-0x48(%rbp)
mov    -0x20(%rbp),%rdi
mov    -0x18(%rbp),%rsi
mov    -0x38(%rbp),%rdx
mov    -0x18(%rbp),%rcx
movsd  -0x40(%rbp),%xmm0
movsd  -0x48(%rbp),%xmm1
mov    $0x3,%r8d
mov    $0x2,%al
call   1060 <kernel_perceptron@plt>
movq   $0x0,-0x28(%rbp)
mov    -0x28(%rbp),%rax
cmp    -0x18(%rbp),%rax
jae    13d4 <main+0x294>
mov    -0x38(%rbp),%rax
mov    -0x28(%rbp),%rcx
mov    (%rax,%rcx,8),%rdi
call   1030 <free@plt>
mov    -0x20(%rbp),%rdi
call   1030 <free@plt>
mov    -0x28(%rbp),%rax
add    $0x1,%rax
mov    %rax,-0x28(%rbp)
jmp    139b <main+0x25b>
xor    %eax,%eax
add    $0x50,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<main>:
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
mov    $0x18,%edi
call   1060 <malloc@plt>
mov    %rax,%r14
mov    $0x1,%edi
mov    $0x18,%esi
call   1050 <calloc@plt>
mov    %rax,(%r14)
mov    $0x18,%edi
call   1060 <malloc@plt>
mov    %rax,%rbx
mov    %rax,0x8(%r14)
mov    $0x18,%edi
call   1060 <malloc@plt>
mov    %rax,0x10(%r14)
movaps 0xe62(%rip),%xmm0
movups %xmm0,(%rbx)
movabs $0x3ff0000000000000,%r12
mov    %r12,0x10(%rbx)
movaps 0xe5a(%rip),%xmm0
movups %xmm0,(%rax)
movabs $0x4000000000000000,%r13
mov    %r13,0x10(%rax)
mov    $0x18,%edi
call   1060 <malloc@plt>
mov    %rax,%r15
mov    $0x1,%edi
mov    $0x18,%esi
call   1050 <calloc@plt>
mov    %rax,(%r15)
mov    $0x18,%edi
call   1060 <malloc@plt>
mov    %rax,%rbx
mov    %rax,0x8(%r15)
mov    $0x18,%edi
call   1060 <malloc@plt>
mov    %rax,0x10(%r15)
movaps 0xdf4(%rip),%xmm0
movups %xmm0,(%rbx)
mov    %r12,0x10(%rbx)
movaps 0xdf6(%rip),%xmm0
movups %xmm0,(%rax)
mov    %r13,0x10(%rax)
mov    $0x3,%esi
mov    %r14,%rdi
mov    $0x3,%edx
xor    %eax,%eax
call   1040 <printMat@plt>
mov    $0x3,%esi
mov    %r15,%rdi
mov    $0x3,%edx
xor    %eax,%eax
call   1040 <printMat@plt>
movsd  0xdcf(%rip),%xmm0
movsd  0xdcf(%rip),%xmm1
mov    $0x3,%esi
mov    $0x3,%ecx
mov    %r14,%rdi
mov    %r15,%rdx
mov    $0x3,%r8d
mov    $0x2,%al
call   1070 <kernel_perceptron@plt>
mov    (%r15),%rdi
call   1030 <free@plt>
mov    %r14,%rdi
call   1030 <free@plt>
mov    0x8(%r15),%rdi
call   1030 <free@plt>
mov    %r14,%rdi
call   1030 <free@plt>
mov    0x10(%r15),%rdi
call   1030 <free@plt>
mov    %r14,%rdi
call   1030 <free@plt>
xor    %eax,%eax
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
ret

LLVM IR (-O0):
define i32 @main(i32 %0, i8** %1) {
%3 = alloca i32
%4 = alloca i32
%5 = alloca i8**
%6 = alloca i64
%7 = alloca double**
%8 = alloca i64
%9 = alloca i64
%10 = alloca double**
%11 = alloca double
%12 = alloca double
store i32 0, i32* %3
store i32 %0, i32* %4
store i8** %1, i8*** %5
store i64 3, i64* %6
%13 = load i64, i64* %6
%14 = mul i64 %13, 8
%15 = call i8* @malloc(i64 %14)
%16 = bitcast i8* %15 to double**
store double** %16, double*** %7
store i64 0, i64* %8
store i64 0, i64* %9
store i64 0, i64* %8
br label %17
17: ; preds = %26, %2
%18 = load i64, i64* %8
%19 = icmp ult i64 %18, 3
br i1 %19, label %20, label %29
20: ; preds = %17
%21 = call i8* @malloc(i64 24)
%22 = bitcast i8* %21 to double*
%23 = load double**, double*** %7
%24 = load i64, i64* %8
%25 = getelementptr inbounds double*, double** %23, i64 %24
store double* %22, double** %25
br label %26
26: ; preds = %20
%27 = load i64, i64* %8
%28 = add i64 %27, 1
store i64 %28, i64* %8
br label %17
29: ; preds = %17
store i64 0, i64* %8
br label %30
30: ; preds = %50, %29
%31 = load i64, i64* %8
%32 = load i64, i64* %6
%33 = icmp ult i64 %31, %32
br i1 %33, label %34, label %53
34: ; preds = %30
store i64 0, i64* %9
br label %35
35: ; preds = %39, %34
%36 = load i64, i64* %9
%37 = icmp ult i64 %36, 3
br i1 %37, label %38, label %49
38: ; preds = %35
br label %39
39: ; preds = %38
%40 = load i64, i64* %8
%41 = uitofp i64 %40 to double
%42 = load double**, double*** %7
%43 = load i64, i64* %8
%44 = getelementptr inbounds double*, double** %42, i64 %43
%45 = load double*, double** %44
%46 = load i64, i64* %9
%47 = add i64 %46, 1
store i64 %47, i64* %9
%48 = getelementptr inbounds double, double* %45, i64 %46
store double %41, double* %48
br label %35
49: ; preds = %35
br label %50
50: ; preds = %49
%51 = load i64, i64* %8
%52 = add i64 %51, 1
store i64 %52, i64* %8
br label %30
53: ; preds = %30
%54 = load i64, i64* %6
%55 = mul i64 %54, 8
%56 = call i8* @malloc(i64 %55)
%57 = bitcast i8* %56 to double**
store double** %57, double*** %10
store i64 0, i64* %8
br label %58
58: ; preds = %67, %53
%59 = load i64, i64* %8
%60 = icmp ult i64 %59, 3
br i1 %60, label %61, label %70
61: ; preds = %58
%62 = call i8* @malloc(i64 24)
%63 = bitcast i8* %62 to double*
%64 = load double**, double*** %10
%65 = load i64, i64* %8
%66 = getelementptr inbounds double*, double** %64, i64 %65
store double* %63, double** %66
br label %67
67: ; preds = %61
%68 = load i64, i64* %8
%69 = add i64 %68, 1
store i64 %69, i64* %8
br label %58
70: ; preds = %58
store i64 0, i64* %8
br label %71
71: ; preds = %91, %70
%72 = load i64, i64* %8
%73 = load i64, i64* %6
%74 = icmp ult i64 %72, %73
br i1 %74, label %75, label %94
75: ; preds = %71
store i64 0, i64* %9
br label %76
76: ; preds = %80, %75
%77 = load i64, i64* %9
%78 = icmp ult i64 %77, 3
br i1 %78, label %79, label %90
79: ; preds = %76
br label %80
80: ; preds = %79
%81 = load i64, i64* %8
%82 = uitofp i64 %81 to double
%83 = load double**, double*** %10
%84 = load i64, i64* %8
%85 = getelementptr inbounds double*, double** %83, i64 %84
%86 = load double*, double** %85
%87 = load i64, i64* %9
%88 = add i64 %87, 1
store i64 %88, i64* %9
%89 = getelementptr inbounds double, double* %86, i64 %87
store double %82, double* %89
br label %76
90: ; preds = %76
br label %91
91: ; preds = %90
%92 = load i64, i64* %8
%93 = add i64 %92, 1
store i64 %93, i64* %8
br label %71
94: ; preds = %71
%95 = load double**, double*** %7
%96 = load i64, i64* %6
%97 = call i32 (double**, i64, i32, ...) bitcast (i32 (...)* @printMat to i32 (double**, i64, i32, ...)*)(double** %95, i64 %96, i32 3)
%98 = load double**, double*** %10
%99 = load i64, i64* %6
%100 = call i32 (double**, i64, i32, ...) bitcast (i32 (...)* @printMat to i32 (double**, i64, i32, ...)*)(double** %98, i64 %99, i32 3)
store double 1.000000e+00, double* %11
store double 1.000000e-01, double* %12
%101 = load double**, double*** %7
%102 = load i64, i64* %6
%103 = load double**, double*** %10
%104 = load i64, i64* %6
%105 = load double, double* %11
%106 = load double, double* %12
%107 = call i32 (double**, i64, double**, i64, double, double, i32, ...) bitcast (i32 (...)* @kernel_perceptron to i32 (double**, i64, double**, i64, double, double, i32, ...)*)(double** %101, i64 %102, double** %103, i64 %104, double %105, double %106, i32 3)
store i64 0, i64* %8
br label %108
108: ; preds = %120, %94
%109 = load i64, i64* %8
%110 = load i64, i64* %6
%111 = icmp ult i64 %109, %110
br i1 %111, label %112, label %123
112: ; preds = %108
%113 = load double**, double*** %10
%114 = load i64, i64* %8
%115 = getelementptr inbounds double*, double** %113, i64 %114
%116 = load double*, double** %115
%117 = bitcast double* %116 to i8*
%118 = load double**, double*** %7
%119 = bitcast double** %118 to i8*
br label %120
120: ; preds = %112
%121 = load i64, i64* %8
%122 = add i64 %121, 1
store i64 %122, i64* %8
br label %108
123: ; preds = %108
ret i32 0
}

LLVM IR (-O2):
define i32 @main(i32 %0, i8** nocapture readnone %1) {
%3 = tail call dereferenceable_or_null(24) i8* @malloc(i64 24)
%4 = bitcast i8* %3 to double**
%5 = call dereferenceable_or_null(24) i8* @calloc(i64 1, i64 24)
%6 = bitcast i8* %3 to i8**
store i8* %5, i8** %6
%7 = tail call dereferenceable_or_null(24) i8* @malloc(i64 24)
%8 = getelementptr inbounds double*, double** %4, i64 1
%9 = bitcast double** %8 to i8**
store i8* %7, i8** %9
%10 = tail call dereferenceable_or_null(24) i8* @malloc(i64 24)
%11 = getelementptr inbounds double*, double** %4, i64 2
%12 = bitcast double** %11 to i8**
store i8* %10, i8** %12
%13 = bitcast i8* %7 to double*
%14 = bitcast i8* %7 to <2 x double>*
store <2 x double> <double 1.000000e+00, double 1.000000e+00>, <2 x double>* %14
%15 = getelementptr inbounds double, double* %13, i64 2
store double 1.000000e+00, double* %15
%16 = bitcast i8* %10 to double*
%17 = bitcast i8* %10 to <2 x double>*
store <2 x double> <double 2.000000e+00, double 2.000000e+00>, <2 x double>* %17
%18 = getelementptr inbounds double, double* %16, i64 2
store double 2.000000e+00, double* %18
%19 = tail call dereferenceable_or_null(24) i8* @malloc(i64 24)
%20 = bitcast i8* %19 to double**
%21 = call dereferenceable_or_null(24) i8* @calloc(i64 1, i64 24)
%22 = bitcast i8* %19 to i8**
store i8* %21, i8** %22
%23 = tail call dereferenceable_or_null(24) i8* @malloc(i64 24)
%24 = getelementptr inbounds double*, double** %20, i64 1
%25 = bitcast double** %24 to i8**
store i8* %23, i8** %25
%26 = tail call dereferenceable_or_null(24) i8* @malloc(i64 24)
%27 = getelementptr inbounds double*, double** %20, i64 2
%28 = bitcast double** %27 to i8**
store i8* %26, i8** %28
%29 = bitcast i8* %23 to double*
%30 = bitcast i8* %23 to <2 x double>*
store <2 x double> <double 1.000000e+00, double 1.000000e+00>, <2 x double>* %30
%31 = getelementptr inbounds double, double* %29, i64 2
store double 1.000000e+00, double* %31
%32 = bitcast i8* %26 to double*
%33 = bitcast i8* %26 to <2 x double>*
store <2 x double> <double 2.000000e+00, double 2.000000e+00>, <2 x double>* %33
%34 = getelementptr inbounds double, double* %32, i64 2
store double 2.000000e+00, double* %34
%35 = tail call i32 (double**, i64, i32, ...) bitcast (i32 (...)* @printMat to i32 (double**, i64, i32, ...)*)(double** %4, i64 3, i32 3)
%36 = tail call i32 (double**, i64, i32, ...) bitcast (i32 (...)* @printMat to i32 (double**, i64, i32, ...)*)(double** %20, i64 3, i32 3)
%37 = tail call i32 (double**, i64, double**, i64, double, double, i32, ...) bitcast (i32 (...)* @kernel_perceptron to i32 (double**, i64, double**, i64, double, double, i32, ...)*)(double** %4, i64 3, double** %20, i64 3, double 1.000000e+00, double 1.000000e-01, i32 3)
%38 = load i8*, i8** %22
tail call void @free(i8* %38)
tail call void @free(i8* %3)
%39 = load i8*, i8** %25
tail call void @free(i8* %39)
tail call void @free(i8* %3)
%40 = load i8*, i8** %28
tail call void @free(i8* %40)
tail call void @free(i8* %3)
ret i32 0
}