void testKnnSmooth() {
  const int trace = 0;
  unsigned nObs;
  unsigned nDims;
  double *inputsP;
  double *targetsP;
  makeData(&nObs, &nDims, &inputsP, &targetsP);
  {
    const unsigned k = 1;
    double expected[] = {0.0, 1.0, 2.0, 3.0};
    for (unsigned queryIndex = 0; queryIndex < nObs; queryIndex++) {
      double estimate =
          Knn_smooth(nObs, nDims, inputsP, targetsP, k, queryIndex);
      if (trace)
        printf("queryIndex=%u\n", queryIndex);
      UnitTest_expect_eq_double((expected[queryIndex]), (estimate), (1e-10),
                                __func__, 205);
    }
  }
  {
    const unsigned k = 2;
    double expected[] = {0.5, 0.5, 1.5, 2.5};
    for (unsigned queryIndex = 0; queryIndex < nObs; queryIndex++) {
      double estimate =
          Knn_smooth(nObs, nDims, inputsP, targetsP, k, queryIndex);
      if (trace)
        printf("queryIndex=%u\n", queryIndex);
      UnitTest_expect_eq_double((expected[queryIndex]), (estimate), (1e-10),
                                __func__, 219);
    }
  }
  {
    const unsigned k = 3;
    double expected[] = {1.0, 1.0, 2.0, 2.0};
    for (unsigned queryIndex = 0; queryIndex < nObs; queryIndex++) {
      double estimate =
          Knn_smooth(nObs, nDims, inputsP, targetsP, k, queryIndex);
      if (trace)
        printf("queryIndex=%u\n", queryIndex);
      UnitTest_expect_eq_double((expected[queryIndex]), (estimate), (1e-10),
                                __func__, 233);
    }
  }
}


x86 assembly (clang, -O0):
<testKnnSmooth>:
push   %rbp
mov    %rsp,%rbp
sub    $0xe0,%rsp
movl   $0x0,-0x4(%rbp)
lea    -0x8(%rbp),%rdi
lea    -0xc(%rbp),%rsi
lea    -0x18(%rbp),%rdx
lea    -0x20(%rbp),%rcx
mov    $0x0,%al
call   1040 <makeData@plt>
movl   $0x1,-0x24(%rbp)
mov    0xea9(%rip),%rax
mov    %rax,-0x50(%rbp)
mov    0xea6(%rip),%rax
mov    %rax,-0x48(%rbp)
mov    0xea3(%rip),%rax
mov    %rax,-0x40(%rbp)
mov    0xea0(%rip),%rax
mov    %rax,-0x38(%rbp)
movl   $0x0,-0x54(%rbp)
mov    -0x54(%rbp),%eax
cmp    -0x8(%rbp),%eax
jae    11fe <testKnnSmooth+0xce>
mov    -0x8(%rbp),%edi
mov    -0xc(%rbp),%esi
mov    -0x18(%rbp),%rdx
mov    -0x20(%rbp),%rcx
mov    -0x54(%rbp),%r9d
mov    $0x1,%r8d
mov    $0x0,%al
call   1030 <Knn_smooth@plt>
cvtsi2sd %eax,%xmm0
movsd  %xmm0,-0x60(%rbp)
mov    -0x54(%rbp),%eax
movsd  -0x50(%rbp,%rax,8),%xmm0
movsd  -0x60(%rbp),%xmm1
movsd  0xe23(%rip),%xmm2
lea    0xe8c(%rip),%rdi
mov    $0xcd,%esi
mov    $0x3,%al
call   1050 <UnitTest_expect_eq_double@plt>
mov    -0x54(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x54(%rbp)
jmp    1193 <testKnnSmooth+0x63>
movl   $0x2,-0x64(%rbp)
mov    0xe24(%rip),%rax
mov    %rax,-0x90(%rbp)
mov    0xe1e(%rip),%rax
mov    %rax,-0x88(%rbp)
mov    0xe18(%rip),%rax
mov    %rax,-0x80(%rbp)
mov    0xe15(%rip),%rax
mov    %rax,-0x78(%rbp)
movl   $0x0,-0x94(%rbp)
mov    -0x94(%rbp),%eax
cmp    -0x8(%rbp),%eax
jae    12c4 <testKnnSmooth+0x194>
mov    -0x8(%rbp),%edi
mov    -0xc(%rbp),%esi
mov    -0x18(%rbp),%rdx
mov    -0x20(%rbp),%rcx
mov    -0x94(%rbp),%r9d
mov    $0x2,%r8d
mov    $0x0,%al
call   1030 <Knn_smooth@plt>
cvtsi2sd %eax,%xmm0
movsd  %xmm0,-0xa0(%rbp)
ff
mov    -0x94(%rbp),%eax
movsd  -0x90(%rbp,%rax,8),%xmm0
ff ff
movsd  -0xa0(%rbp),%xmm1
ff
movsd  0xd63(%rip),%xmm2
lea    0xdcc(%rip),%rdi
mov    $0xdb,%esi
mov    $0x3,%al
call   1050 <UnitTest_expect_eq_double@plt>
mov    -0x94(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x94(%rbp)
jmp    1241 <testKnnSmooth+0x111>
movl   $0x3,-0xa4(%rbp)
mov    0xd7b(%rip),%rax
mov    %rax,-0xd0(%rbp)
mov    0xd75(%rip),%rax
mov    %rax,-0xc8(%rbp)
mov    0xd6f(%rip),%rax
mov    %rax,-0xc0(%rbp)
mov    0xd69(%rip),%rax
mov    %rax,-0xb8(%rbp)
movl   $0x0,-0xd4(%rbp)
mov    -0xd4(%rbp),%eax
cmp    -0x8(%rbp),%eax
jae    1393 <testKnnSmooth+0x263>
mov    -0x8(%rbp),%edi
mov    -0xc(%rbp),%esi
mov    -0x18(%rbp),%rdx
mov    -0x20(%rbp),%rcx
mov    -0xd4(%rbp),%r9d
mov    $0x3,%r8d
mov    $0x0,%al
call   1030 <Knn_smooth@plt>
cvtsi2sd %eax,%xmm0
movsd  %xmm0,-0xe0(%rbp)
ff
mov    -0xd4(%rbp),%eax
movsd  -0xd0(%rbp,%rax,8),%xmm0
ff ff
movsd  -0xe0(%rbp),%xmm1
ff
movsd  0xc94(%rip),%xmm2
lea    0xcfd(%rip),%rdi
mov    $0xe9,%esi
mov    $0x3,%al
call   1050 <UnitTest_expect_eq_double@plt>
mov    -0xd4(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0xd4(%rbp)
jmp    1310 <testKnnSmooth+0x1e0>
add    $0xe0,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<testKnnSmooth>:
push   %r15
push   %r14
push   %rbx
sub    $0x20,%rsp
lea    0x8(%rsp),%rdi
lea    0xc(%rsp),%rsi
lea    0x18(%rsp),%rdx
lea    0x10(%rsp),%rcx
xor    %eax,%eax
call   1040 <makeData@plt>
mov    0x8(%rsp),%edi
test   %edi,%edi
je     12a2 <testKnnSmooth+0x172>
lea    0xea9(%rip),%r15
lea    0xf02(%rip),%r14
xor    %ebx,%ebx
mov    0xc(%rsp),%esi
mov    0x18(%rsp),%rdx
mov    0x10(%rsp),%rcx
mov    $0x1,%r8d
mov    %ebx,%r9d
xor    %eax,%eax
call   1030 <Knn_smooth@plt>
xorps  %xmm1,%xmm1
cvtsi2sd %eax,%xmm1
movsd  (%r15),%xmm0
movsd  0xe5e(%rip),%xmm2
mov    %r14,%rdi
mov    $0xcd,%esi
mov    $0x3,%al
call   1050 <UnitTest_expect_eq_double@plt>
add    $0x1,%rbx
mov    0x8(%rsp),%edi
add    $0x8,%r15
cmp    %rdi,%rbx
jb     1170 <testKnnSmooth+0x40>
test   %edi,%edi
je     12a2 <testKnnSmooth+0x172>
lea    0xe5f(%rip),%r15
lea    0xe98(%rip),%r14
xor    %ebx,%ebx
nopw   0x0(%rax,%rax,1)
mov    0xc(%rsp),%esi
mov    0x18(%rsp),%rdx
mov    0x10(%rsp),%rcx
mov    $0x2,%r8d
mov    %ebx,%r9d
xor    %eax,%eax
call   1030 <Knn_smooth@plt>
xorps  %xmm1,%xmm1
cvtsi2sd %eax,%xmm1
movsd  (%r15),%xmm0
movsd  0xdee(%rip),%xmm2
mov    %r14,%rdi
mov    $0xdb,%esi
mov    $0x3,%al
call   1050 <UnitTest_expect_eq_double@plt>
add    $0x1,%rbx
mov    0x8(%rsp),%edi
add    $0x8,%r15
cmp    %rdi,%rbx
jb     11e0 <testKnnSmooth+0xb0>
test   %edi,%edi
je     12a2 <testKnnSmooth+0x172>
lea    0xe13(%rip),%r15
lea    0xe2c(%rip),%r14
xor    %ebx,%ebx
cs nopw 0x0(%rax,%rax,1)
mov    0xc(%rsp),%esi
mov    0x18(%rsp),%rdx
mov    0x10(%rsp),%rcx
mov    $0x3,%r8d
mov    %ebx,%r9d
xor    %eax,%eax
call   1030 <Knn_smooth@plt>
xorps  %xmm1,%xmm1
cvtsi2sd %eax,%xmm1
movsd  (%r15),%xmm0
movsd  0xd7e(%rip),%xmm2
mov    %r14,%rdi
mov    $0xe9,%esi
mov    $0x3,%al
call   1050 <UnitTest_expect_eq_double@plt>
add    $0x1,%rbx
mov    0x8(%rsp),%edi
add    $0x8,%r15
cmp    %rdi,%rbx
jb     1250 <testKnnSmooth+0x120>
add    $0x20,%rsp
pop    %rbx
pop    %r14
pop    %r15
ret

LLVM IR (-O0):
@__const.testKnnSmooth.expected = [4 x double] [double 0.000000e+00, double 1.000000e+00, double 2.000000e+00, double 3.000000e+00]
@__func__.testKnnSmooth = [14 x i8] c"testKnnSmooth\00"
@__const.testKnnSmooth.expected.1 = [4 x double] [double 5.000000e-01, double 5.000000e-01, double 1.500000e+00, double 2.500000e+00]
@__const.testKnnSmooth.expected.2 = [4 x double] [double 1.000000e+00, double 1.000000e+00, double 2.000000e+00, double 2.000000e+00]
define void @testKnnSmooth() {
%1 = alloca i32
%2 = alloca i32
%3 = alloca i32
%4 = alloca double*
%5 = alloca double*
%6 = alloca i32
%7 = alloca [4 x double]
%8 = alloca i32
%9 = alloca double
%10 = alloca i32
%11 = alloca [4 x double]
%12 = alloca i32
%13 = alloca double
%14 = alloca i32
%15 = alloca [4 x double]
%16 = alloca i32
%17 = alloca double
store i32 0, i32* %1
%18 = call i32 (i32*, i32*, double**, double**, ...) bitcast (i32 (...)* @makeData to i32 (i32*, i32*, double**, double**, ...)*)(i32* %2, i32* %3, double** %4, double** %5)
store i32 1, i32* %6
%19 = bitcast [4 x double]* %7 to i8*
store i32 0, i32* %8
br label %20
20: ; preds = %38, %0
%21 = load i32, i32* %8
%22 = load i32, i32* %2
%23 = icmp ult i32 %21, %22
br i1 %23, label %24, label %41
24: ; preds = %20
%25 = load i32, i32* %2
%26 = load i32, i32* %3
%27 = load double*, double** %4
%28 = load double*, double** %5
%29 = load i32, i32* %8
%30 = call i32 (i32, i32, double*, double*, i32, i32, ...) bitcast (i32 (...)* @Knn_smooth to i32 (i32, i32, double*, double*, i32, i32, ...)*)(i32 %25, i32 %26, double* %27, double* %28, i32 1, i32 %29)
%31 = sitofp i32 %30 to double
store double %31, double* %9
%32 = load i32, i32* %8
%33 = zext i32 %32 to i64
%34 = getelementptr inbounds [4 x double], [4 x double]* %7, i64 0, i64 %33
%35 = load double, double* %34
%36 = load double, double* %9
%37 = call i32 (double, double, double, i8*, i32, ...) bitcast (i32 (...)* @UnitTest_expect_eq_double to i32 (double, double, double, i8*, i32, ...)*)(double %35, double %36, double 1.000000e-10, i8* getelementptr inbounds ([14 x i8], [14 x i8]* @__func__.testKnnSmooth, i64 0, i64 0), i32 205)
br label %38
38: ; preds = %24
%39 = load i32, i32* %8
%40 = add i32 %39, 1
store i32 %40, i32* %8
br label %20
41: ; preds = %20
store i32 2, i32* %10
%42 = bitcast [4 x double]* %11 to i8*
store i32 0, i32* %12
br label %43
43: ; preds = %61, %41
%44 = load i32, i32* %12
%45 = load i32, i32* %2
%46 = icmp ult i32 %44, %45
br i1 %46, label %47, label %64
47: ; preds = %43
%48 = load i32, i32* %2
%49 = load i32, i32* %3
%50 = load double*, double** %4
%51 = load double*, double** %5
%52 = load i32, i32* %12
%53 = call i32 (i32, i32, double*, double*, i32, i32, ...) bitcast (i32 (...)* @Knn_smooth to i32 (i32, i32, double*, double*, i32, i32, ...)*)(i32 %48, i32 %49, double* %50, double* %51, i32 2, i32 %52)
%54 = sitofp i32 %53 to double
store double %54, double* %13
%55 = load i32, i32* %12
%56 = zext i32 %55 to i64
%57 = getelementptr inbounds [4 x double], [4 x double]* %11, i64 0, i64 %56
%58 = load double, double* %57
%59 = load double, double* %13
%60 = call i32 (double, double, double, i8*, i32, ...) bitcast (i32 (...)* @UnitTest_expect_eq_double to i32 (double, double, double, i8*, i32, ...)*)(double %58, double %59, double 1.000000e-10, i8* getelementptr inbounds ([14 x i8], [14 x i8]* @__func__.testKnnSmooth, i64 0, i64 0), i32 219)
br label %61
61: ; preds = %47
%62 = load i32, i32* %12
%63 = add i32 %62, 1
store i32 %63, i32* %12
br label %43
64: ; preds = %43
store i32 3, i32* %14
%65 = bitcast [4 x double]* %15 to i8*
store i32 0, i32* %16
br label %66
66: ; preds = %84, %64
%67 = load i32, i32* %16
%68 = load i32, i32* %2
%69 = icmp ult i32 %67, %68
br i1 %69, label %70, label %87
70: ; preds = %66
%71 = load i32, i32* %2
%72 = load i32, i32* %3
%73 = load double*, double** %4
%74 = load double*, double** %5
%75 = load i32, i32* %16
%76 = call i32 (i32, i32, double*, double*, i32, i32, ...) bitcast (i32 (...)* @Knn_smooth to i32 (i32, i32, double*, double*, i32, i32, ...)*)(i32 %71, i32 %72, double* %73, double* %74, i32 3, i32 %75)
%77 = sitofp i32 %76 to double
store double %77, double* %17
%78 = load i32, i32* %16
%79 = zext i32 %78 to i64
%80 = getelementptr inbounds [4 x double], [4 x double]* %15, i64 0, i64 %79
%81 = load double, double* %80
%82 = load double, double* %17
%83 = call i32 (double, double, double, i8*, i32, ...) bitcast (i32 (...)* @UnitTest_expect_eq_double to i32 (double, double, double, i8*, i32, ...)*)(double %81, double %82, double 1.000000e-10, i8* getelementptr inbounds ([14 x i8], [14 x i8]* @__func__.testKnnSmooth, i64 0, i64 0), i32 233)
br label %84
84: ; preds = %70
%85 = load i32, i32* %16
%86 = add i32 %85, 1
store i32 %86, i32* %16
br label %66
87: ; preds = %66
ret void
}

LLVM IR (-O2):
@__const.testKnnSmooth.expected = [4 x double] [double 0.000000e+00, double 1.000000e+00, double 2.000000e+00, double 3.000000e+00]
@__func__.testKnnSmooth = [14 x i8] c"testKnnSmooth\00"
@__const.testKnnSmooth.expected.1 = [4 x double] [double 5.000000e-01, double 5.000000e-01, double 1.500000e+00, double 2.500000e+00]
@__const.testKnnSmooth.expected.2 = [4 x double] [double 1.000000e+00, double 1.000000e+00, double 2.000000e+00, double 2.000000e+00]
define void @testKnnSmooth() {
%1 = alloca i32
%2 = alloca i32
%3 = alloca double*
%4 = alloca double*
%5 = bitcast i32* %1 to i8*
%6 = bitcast i32* %2 to i8*
%7 = bitcast double** %3 to i8*
%8 = bitcast double** %4 to i8*
%9 = call i32 (i32*, i32*, double**, double**, ...) bitcast (i32 (...)* @makeData to i32 (i32*, i32*, double**, double**, ...)*)(i32* %1, i32* %2, double** %3, double** %4)
%10 = load i32, i32* %1
%11 = icmp eq i32 %10, 0
br i1 %11, label %48, label %14
12: ; preds = %14
%13 = icmp eq i32 %27, 0
br i1 %13, label %48, label %32
14: ; preds = %0, %14
%15 = phi i64 [ %26, %14 ], [ 0, %0 ]
%16 = phi i32 [ %27, %14 ], [ %10, %0 ]
%17 = load i32, i32* %2
%18 = load double*, double** %3
%19 = load double*, double** %4
%20 = trunc i64 %15 to i32
%21 = call i32 (i32, i32, double*, double*, i32, i32, ...) bitcast (i32 (...)* @Knn_smooth to i32 (i32, i32, double*, double*, i32, i32, ...)*)(i32 %16, i32 %17, double* %18, double* %19, i32 1, i32 %20)
%22 = sitofp i32 %21 to double
%23 = getelementptr inbounds [4 x double], [4 x double]* @__const.testKnnSmooth.expected, i64 0, i64 %15
%24 = load double, double* %23
%25 = call i32 (double, double, double, i8*, i32, ...) bitcast (i32 (...)* @UnitTest_expect_eq_double to i32 (double, double, double, i8*, i32, ...)*)(double %24, double %22, double 1.000000e-10, i8* getelementptr inbounds ([14 x i8], [14 x i8]* @__func__.testKnnSmooth, i64 0, i64 0), i32 205)
%26 = add nuw nsw i64 %15, 1
%27 = load i32, i32* %1
%28 = zext i32 %27 to i64
%29 = icmp ult i64 %26, %28
br i1 %29, label %14, label %12
30: ; preds = %32
%31 = icmp eq i32 %45, 0
br i1 %31, label %48, label %49
32: ; preds = %12, %32
%33 = phi i64 [ %44, %32 ], [ 0, %12 ]
%34 = phi i32 [ %45, %32 ], [ %27, %12 ]
%35 = load i32, i32* %2
%36 = load double*, double** %3
%37 = load double*, double** %4
%38 = trunc i64 %33 to i32
%39 = call i32 (i32, i32, double*, double*, i32, i32, ...) bitcast (i32 (...)* @Knn_smooth to i32 (i32, i32, double*, double*, i32, i32, ...)*)(i32 %34, i32 %35, double* %36, double* %37, i32 2, i32 %38)
%40 = sitofp i32 %39 to double
%41 = getelementptr inbounds [4 x double], [4 x double]* @__const.testKnnSmooth.expected.1, i64 0, i64 %33
%42 = load double, double* %41
%43 = call i32 (double, double, double, i8*, i32, ...) bitcast (i32 (...)* @UnitTest_expect_eq_double to i32 (double, double, double, i8*, i32, ...)*)(double %42, double %40, double 1.000000e-10, i8* getelementptr inbounds ([14 x i8], [14 x i8]* @__func__.testKnnSmooth, i64 0, i64 0), i32 219)
%44 = add nuw nsw i64 %33, 1
%45 = load i32, i32* %1
%46 = zext i32 %45 to i64
%47 = icmp ult i64 %44, %46
br i1 %47, label %32, label %30
48: ; preds = %49, %0, %12, %30
ret void
49: ; preds = %30, %49
%50 = phi i64 [ %61, %49 ], [ 0, %30 ]
%51 = phi i32 [ %62, %49 ], [ %45, %30 ]
%52 = load i32, i32* %2
%53 = load double*, double** %3
%54 = load double*, double** %4
%55 = trunc i64 %50 to i32
%56 = call i32 (i32, i32, double*, double*, i32, i32, ...) bitcast (i32 (...)* @Knn_smooth to i32 (i32, i32, double*, double*, i32, i32, ...)*)(i32 %51, i32 %52, double* %53, double* %54, i32 3, i32 %55)
%57 = sitofp i32 %56 to double
%58 = getelementptr inbounds [4 x double], [4 x double]* @__const.testKnnSmooth.expected.2, i64 0, i64 %50
%59 = load double, double* %58
%60 = call i32 (double, double, double, i8*, i32, ...) bitcast (i32 (...)* @UnitTest_expect_eq_double to i32 (double, double, double, i8*, i32, ...)*)(double %59, double %57, double 1.000000e-10, i8* getelementptr inbounds ([14 x i8], [14 x i8]* @__func__.testKnnSmooth, i64 0, i64 0), i32 233)
%61 = add nuw nsw i64 %50, 1
%62 = load i32, i32* %1
%63 = zext i32 %62 to i64
%64 = icmp ult i64 %61, %63
br i1 %64, label %49, label %48
}