#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */

/* Variables and functions */
double DBL_MAX;
double stub1(void const *, void const *);
double stub2(void const *, void const *);
int NNQuery(void *key, void *base, size_t n, size_t size,
            double (*dst)(const void *, const void *)) {
  int mid = -1;
  double d = -1;
  int low = 0;
  int high = n;
  double minDist = DBL_MAX;
  int minIdx = -1;
  char *cbase = base;
  char *ckey = key;
  if (high == 0)
    return (-1);
  while (low <= high) {
    mid = ((low + high) / 2);
    if (mid >= n)
      break;
    d = (*dst)(&cbase[mid * size], ckey);
    if (d < 0) {
      d = -d;
    }
    if (d < minDist) {
      minDist = d;
      minIdx = mid;
    }
    d = (*dst)(&cbase[mid * size], ckey);
    if (d < 0) {
      high = mid - 1;
    } else if (d > 0) {
      low = mid + 1;
    } else {
      return (minIdx);
    }
  }
  return (minIdx);
}


x86 assembly (clang, -O0):
<NNQuery>:
push   %rbp
mov    %rsp,%rbp
sub    $0x70,%rsp
mov    %rdi,-0x10(%rbp)
mov    %rsi,-0x18(%rbp)
mov    %rdx,-0x20(%rbp)
mov    %rcx,-0x28(%rbp)
mov    %r8,-0x30(%rbp)
movl   $0xffffffff,-0x34(%rbp)
movsd  0xed5(%rip),%xmm0
movsd  %xmm0,-0x40(%rbp)
movl   $0x0,-0x44(%rbp)
mov    -0x20(%rbp),%rax
mov    %eax,-0x48(%rbp)
mov    0x2e9b(%rip),%rax
movsd  (%rax),%xmm0
movsd  %xmm0,-0x50(%rbp)
movl   $0xffffffff,-0x54(%rbp)
mov    -0x18(%rbp),%rax
mov    %rax,-0x60(%rbp)
mov    -0x10(%rbp),%rax
mov    %rax,-0x68(%rbp)
cmpl   $0x0,-0x48(%rbp)
jne    117b <NNQuery+0x7b>
movl   $0xffffffff,-0x4(%rbp)
jmp    1298 <NNQuery+0x198>
jmp    1180 <NNQuery+0x80>
mov    -0x44(%rbp),%eax
cmp    -0x48(%rbp),%eax
jg     1292 <NNQuery+0x192>
mov    -0x44(%rbp),%eax
add    -0x48(%rbp),%eax
mov    $0x2,%ecx
cltd
idiv   %ecx
mov    %eax,-0x34(%rbp)
movslq -0x34(%rbp),%rax
cmp    -0x20(%rbp),%rax
jb     11b0 <NNQuery+0xb0>
jmp    1292 <NNQuery+0x192>
mov    -0x30(%rbp),%rax
mov    -0x60(%rbp),%rdi
movslq -0x34(%rbp),%rcx
imul   -0x28(%rbp),%rcx
add    %rcx,%rdi
mov    -0x68(%rbp),%rsi
call   *%rax
movsd  %xmm0,-0x40(%rbp)
xorps  %xmm0,%xmm0
ucomisd -0x40(%rbp),%xmm0
jbe    11fe <NNQuery+0xfe>
movsd  -0x40(%rbp),%xmm0
movq   %xmm0,%rax
movabs $0x8000000000000000,%rcx
xor    %rcx,%rax
movq   %rax,%xmm0
movsd  %xmm0,-0x40(%rbp)
movsd  -0x40(%rbp),%xmm1
movsd  -0x50(%rbp),%xmm0
ucomisd %xmm1,%xmm0
jbe    1222 <NNQuery+0x122>
movsd  -0x40(%rbp),%xmm0
movsd  %xmm0,-0x50(%rbp)
mov    -0x34(%rbp),%eax
mov    %eax,-0x54(%rbp)
mov    -0x30(%rbp),%rax
mov    -0x60(%rbp),%rdi
movslq -0x34(%rbp),%rcx
imul   -0x28(%rbp),%rcx
add    %rcx,%rdi
mov    -0x68(%rbp),%rsi
call   *%rax
movsd  %xmm0,-0x40(%rbp)
xorps  %xmm0,%xmm0
ucomisd -0x40(%rbp),%xmm0
jbe    125d <NNQuery+0x15d>
mov    -0x34(%rbp),%eax
sub    $0x1,%eax
mov    %eax,-0x48(%rbp)
jmp    128d <NNQuery+0x18d>
movsd  -0x40(%rbp),%xmm0
xorps  %xmm1,%xmm1
ucomisd %xmm1,%xmm0
jbe    127d <NNQuery+0x17d>
mov    -0x34(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x44(%rbp)
jmp    1288 <NNQuery+0x188>
mov    -0x54(%rbp),%eax
mov    %eax,-0x4(%rbp)
jmp    1298 <NNQuery+0x198>
jmp    128d <NNQuery+0x18d>
jmp    1180 <NNQuery+0x80>
mov    -0x54(%rbp),%eax
mov    %eax,-0x4(%rbp)
mov    -0x4(%rbp),%eax
add    $0x70,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<NNQuery>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x58,%rsp
mov    %r8,0x28(%rsp)
mov    %rcx,0x20(%rsp)
mov    %rsi,0x18(%rsp)
mov    %rdi,0x10(%rsp)
test   %edx,%edx
jle    122a <NNQuery+0x12a>
mov    0x2eaf(%rip),%rax
movsd  (%rax),%xmm0
movsd  %xmm0,(%rsp)
xor    %ecx,%ecx
mov    $0xffffffff,%r12d
mov    %edx,%esi
mov    %rdx,0x8(%rsp)
mov    0x10(%rsp),%r15
mov    0x28(%rsp),%rbp
jmp    1189 <NNQuery+0x89>
cs nopw 0x0(%rax,%rax,1)
nop
add    $0xffffffff,%r13d
mov    %r13d,%esi
mov    0x38(%rsp),%rcx
movapd 0x40(%rsp),%xmm0
minsd  (%rsp),%xmm0
movsd  %xmm0,(%rsp)
cmp    %esi,%ecx
mov    0x8(%rsp),%rdx
jg     1230 <NNQuery+0x130>
lea    (%rsi,%rcx,1),%eax
mov    %eax,%r13d
shr    $0x1f,%r13d
add    %eax,%r13d
sar    %r13d
movslq %r13d,%rbx
cmp    %rdx,%rbx
jae    1230 <NNQuery+0x130>
mov    %rsi,0x30(%rsp)
mov    %rcx,0x38(%rsp)
mov    %rbx,%r14
imul   0x20(%rsp),%r14
add    0x18(%rsp),%r14
mov    %r14,%rdi
mov    %r15,%rsi
call   *%rbp
movapd %xmm0,%xmm1
xorpd  0xe2f(%rip),%xmm1
movapd %xmm0,%xmm2
cmpltsd 0xe32(%rip),%xmm2
andpd  %xmm2,%xmm1
andnpd %xmm0,%xmm2
orpd   %xmm1,%xmm2
movsd  (%rsp),%xmm0
movapd %xmm2,0x40(%rsp)
ucomisd %xmm2,%xmm0
cmova  %ebx,%r12d
mov    %r14,%rdi
mov    %r15,%rsi
call   *%rbp
xorpd  %xmm1,%xmm1
ucomisd %xmm0,%xmm1
ja     1160 <NNQuery+0x60>
ucomisd %xmm1,%xmm0
jbe    1230 <NNQuery+0x130>
add    $0x1,%r13d
mov    %r13d,%ecx
mov    0x30(%rsp),%rsi
jmp    116c <NNQuery+0x6c>
mov    $0xffffffff,%r12d
mov    %r12d,%eax
add    $0x58,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
@DBL_MAX = global double 0.000000e+00
define i32 @NNQuery(i8* %0, i8* %1, i64 %2, i64 %3, double (i8*, i8*)* %4) {
%6 = alloca i32
%7 = alloca i8*
%8 = alloca i8*
%9 = alloca i64
%10 = alloca i64
%11 = alloca double (i8*, i8*)*
%12 = alloca i32
%13 = alloca double
%14 = alloca i32
%15 = alloca i32
%16 = alloca double
%17 = alloca i32
%18 = alloca i8*
%19 = alloca i8*
store i8* %0, i8** %7
store i8* %1, i8** %8
store i64 %2, i64* %9
store i64 %3, i64* %10
store double (i8*, i8*)* %4, double (i8*, i8*)** %11
store i32 -1, i32* %12
store double -1.000000e+00, double* %13
store i32 0, i32* %14
%20 = load i64, i64* %9
%21 = trunc i64 %20 to i32
store i32 %21, i32* %15
%22 = load double, double* @DBL_MAX
store double %22, double* %16
store i32 -1, i32* %17
%23 = load i8*, i8** %8
store i8* %23, i8** %18
%24 = load i8*, i8** %7
store i8* %24, i8** %19
%25 = load i32, i32* %15
%26 = icmp eq i32 %25, 0
br i1 %26, label %27, label %28
27: ; preds = %5
store i32 -1, i32* %6
br label %92
28: ; preds = %5
br label %29
29: ; preds = %89, %28
%30 = load i32, i32* %14
%31 = load i32, i32* %15
%32 = icmp sle i32 %30, %31
br i1 %32, label %33, label %90
33: ; preds = %29
%34 = load i32, i32* %14
%35 = load i32, i32* %15
%36 = add nsw i32 %34, %35
%37 = sdiv i32 %36, 2
store i32 %37, i32* %12
%38 = load i32, i32* %12
%39 = sext i32 %38 to i64
%40 = load i64, i64* %9
%41 = icmp uge i64 %39, %40
br i1 %41, label %42, label %43
42: ; preds = %33
br label %90
43: ; preds = %33
%44 = load double (i8*, i8*)*, double (i8*, i8*)** %11
%45 = load i8*, i8** %18
%46 = load i32, i32* %12
%47 = sext i32 %46 to i64
%48 = load i64, i64* %10
%49 = mul i64 %47, %48
%50 = getelementptr inbounds i8, i8* %45, i64 %49
%51 = load i8*, i8** %19
%52 = call double %44(i8* %50, i8* %51)
store double %52, double* %13
%53 = load double, double* %13
%54 = fcmp olt double %53, 0.000000e+00
br i1 %54, label %55, label %58
55: ; preds = %43
%56 = load double, double* %13
%57 = fneg double %56
store double %57, double* %13
br label %58
58: ; preds = %55, %43
%59 = load double, double* %13
%60 = load double, double* %16
%61 = fcmp olt double %59, %60
br i1 %61, label %62, label %65
62: ; preds = %58
%63 = load double, double* %13
store double %63, double* %16
%64 = load i32, i32* %12
store i32 %64, i32* %17
br label %65
65: ; preds = %62, %58
%66 = load double (i8*, i8*)*, double (i8*, i8*)** %11
%67 = load i8*, i8** %18
%68 = load i32, i32* %12
%69 = sext i32 %68 to i64
%70 = load i64, i64* %10
%71 = mul i64 %69, %70
%72 = getelementptr inbounds i8, i8* %67, i64 %71
%73 = load i8*, i8** %19
%74 = call double %66(i8* %72, i8* %73)
store double %74, double* %13
%75 = load double, double* %13
%76 = fcmp olt double %75, 0.000000e+00
br i1 %76, label %77, label %80
77: ; preds = %65
%78 = load i32, i32* %12
%79 = sub nsw i32 %78, 1
store i32 %79, i32* %15
br label %89
80: ; preds = %65
%81 = load double, double* %13
%82 = fcmp ogt double %81, 0.000000e+00
br i1 %82, label %83, label %86
83: ; preds = %80
%84 = load i32, i32* %12
%85 = add nsw i32 %84, 1
store i32 %85, i32* %14
br label %88
86: ; preds = %80
%87 = load i32, i32* %17
store i32 %87, i32* %6
br label %92
88: ; preds = %83
br label %89
89: ; preds = %88, %77
br label %29
90: ; preds = %42, %29
%91 = load i32, i32* %17
store i32 %91, i32* %6
br label %92
92: ; preds = %90, %86, %27
%93 = load i32, i32* %6
ret i32 %93
}

LLVM IR (-O2):
@DBL_MAX = global double 0.000000e+00
define i32 @NNQuery(i8* %0, i8* %1, i64 %2, i64 %3, double (i8*, i8*)* nocapture %4) {
%6 = trunc i64 %2 to i32
%7 = icmp slt i32 %6, 1
br i1 %7, label %41, label %8
8: ; preds = %5
%9 = load double, double* @DBL_MAX
br label %10
10: ; preds = %8, %37
%11 = phi i32 [ %28, %37 ], [ -1, %8 ]
%12 = phi double [ %27, %37 ], [ %9, %8 ]
%13 = phi i32 [ %39, %37 ], [ %6, %8 ]
%14 = phi i32 [ %38, %37 ], [ 0, %8 ]
%15 = add nsw i32 %13, %14
%16 = sdiv i32 %15, 2
%17 = sext i32 %16 to i64
%18 = icmp ult i64 %17, %2
br i1 %18, label %19, label %41
19: ; preds = %10
%20 = mul i64 %17, %3
%21 = getelementptr inbounds i8, i8* %1, i64 %20
%22 = tail call double %4(i8* %21, i8* %0)
%23 = fcmp olt double %22, 0.000000e+00
%24 = fneg double %22
%25 = select i1 %23, double %24, double %22
%26 = fcmp olt double %25, %12
%27 = select i1 %26, double %25, double %12
%28 = select i1 %26, i32 %16, i32 %11
%29 = tail call double %4(i8* %21, i8* %0)
%30 = fcmp olt double %29, 0.000000e+00
br i1 %30, label %31, label %33
31: ; preds = %19
%32 = add nsw i32 %16, -1
br label %37
33: ; preds = %19
%34 = fcmp ogt double %29, 0.000000e+00
br i1 %34, label %35, label %41
35: ; preds = %33
%36 = add nsw i32 %16, 1
br label %37
37: ; preds = %35, %31
%38 = phi i32 [ %14, %31 ], [ %36, %35 ]
%39 = phi i32 [ %32, %31 ], [ %13, %35 ]
%40 = icmp sgt i32 %38, %39
br i1 %40, label %41, label %10
41: ; preds = %33, %10, %37, %5
%42 = phi i32 [ -1, %5 ], [ %28, %33 ], [ %11, %10 ], [ %28, %37 ]
ret i32 %42
}