float neighbours_distance(unsigned int *a, unsigned int sa, unsigned int *b,
                          unsigned int sb) {
  unsigned int i = 0, j = 0, in = 0, u;
  if ((sa == sb) && sa == 0) {
    return 1.0;
  }
  u = sa + sb;
  while (i < sa && j < sb) {
    if (a[i] == b[j]) {
      in++;
      u--;
      i++;
      j++;
    } else if (a[i] < b[j]) {
      j++;
    } else {
      i++;
    }
  }
  return 1.0 - (float)in / u;
}


x86 assembly (clang, -O0):
<neighbours_distance>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x10(%rbp)
mov    %esi,-0x14(%rbp)
mov    %rdx,-0x20(%rbp)
mov    %ecx,-0x24(%rbp)
movl   $0x0,-0x28(%rbp)
movl   $0x0,-0x2c(%rbp)
movl   $0x0,-0x30(%rbp)
mov    -0x14(%rbp),%eax
cmp    -0x24(%rbp),%eax
jne    114f <neighbours_distance+0x4f>
cmpl   $0x0,-0x14(%rbp)
jne    114f <neighbours_distance+0x4f>
movss  0xec3(%rip),%xmm0
movss  %xmm0,-0x4(%rbp)
jmp    1230 <neighbours_distance+0x130>
mov    -0x14(%rbp),%eax
add    -0x24(%rbp),%eax
mov    %eax,-0x34(%rbp)
mov    -0x28(%rbp),%ecx
xor    %eax,%eax
cmp    -0x14(%rbp),%ecx
mov    %al,-0x35(%rbp)
jae    1175 <neighbours_distance+0x75>
mov    -0x2c(%rbp),%eax
cmp    -0x24(%rbp),%eax
setb   %al
mov    %al,-0x35(%rbp)
mov    -0x35(%rbp),%al
test   $0x1,%al
jne    1185 <neighbours_distance+0x85>
jmp    1203 <neighbours_distance+0x103>
mov    -0x10(%rbp),%rax
mov    -0x28(%rbp),%ecx
mov    (%rax,%rcx,4),%eax
mov    -0x20(%rbp),%rcx
mov    -0x2c(%rbp),%edx
cmp    (%rcx,%rdx,4),%eax
jne    11c8 <neighbours_distance+0xc8>
mov    -0x30(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x30(%rbp)
mov    -0x34(%rbp),%eax
add    $0xffffffff,%eax
mov    %eax,-0x34(%rbp)
mov    -0x28(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x28(%rbp)
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    11fe <neighbours_distance+0xfe>
mov    -0x10(%rbp),%rax
mov    -0x28(%rbp),%ecx
mov    (%rax,%rcx,4),%eax
mov    -0x20(%rbp),%rcx
mov    -0x2c(%rbp),%edx
cmp    (%rcx,%rdx,4),%eax
jae    11f0 <neighbours_distance+0xf0>
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    11f9 <neighbours_distance+0xf9>
mov    -0x28(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x28(%rbp)
jmp    11fe <neighbours_distance+0xfe>
jmp    1158 <neighbours_distance+0x58>
mov    -0x30(%rbp),%eax
cvtsi2ss %rax,%xmm0
mov    -0x34(%rbp),%eax
cvtsi2ss %rax,%xmm1
divss  %xmm1,%xmm0
cvtss2sd %xmm0,%xmm1
movsd  0xddd(%rip),%xmm0
subsd  %xmm1,%xmm0
cvtsd2ss %xmm0,%xmm0
movss  %xmm0,-0x4(%rbp)
movss  -0x4(%rbp),%xmm0
pop    %rbp
ret

x86 assembly (clang, -O2):
<neighbours_distance>:
push   %rbx
mov    %ecx,%eax
or     %esi,%eax
je     118d <neighbours_distance+0x8d>
lea    (%rcx,%rsi,1),%r8d
xor    %r9d,%r9d
test   %esi,%esi
je     116b <neighbours_distance+0x6b>
test   %ecx,%ecx
je     116b <neighbours_distance+0x6b>
xor    %r9d,%r9d
xor    %r10d,%r10d
xor    %r11d,%r11d
jmp    113e <neighbours_distance+0x3e>
cs nopw 0x0(%rax,%rax,1)
nop
add    $0x1,%r11d
cmp    %esi,%r11d
jae    116b <neighbours_distance+0x6b>
cmp    %ecx,%r10d
jae    116b <neighbours_distance+0x6b>
mov    %r11d,%eax
mov    %r10d,%ebx
mov    (%rdx,%rbx,4),%ebx
cmp    %ebx,(%rdi,%rax,4)
jne    1160 <neighbours_distance+0x60>
add    $0x1,%r9d
add    $0xffffffff,%r8d
add    $0x1,%r11d
jmp    1162 <neighbours_distance+0x62>
nopw   0x0(%rax,%rax,1)
jae    1130 <neighbours_distance+0x30>
add    $0x1,%r10d
cmp    %esi,%r11d
jb     1139 <neighbours_distance+0x39>
mov    %r9d,%eax
cvtsi2ss %rax,%xmm1
mov    %r8d,%eax
cvtsi2ss %rax,%xmm0
divss  %xmm0,%xmm1
movss  0xe79(%rip),%xmm0
subss  %xmm1,%xmm0
pop    %rbx
ret
movss  0xe6b(%rip),%xmm0
pop    %rbx
ret

LLVM IR (-O0):
define float @neighbours_distance(i32* %0, i32 %1, i32* %2, i32 %3) {
%5 = alloca float
%6 = alloca i32*
%7 = alloca i32
%8 = alloca i32*
%9 = alloca i32
%10 = alloca i32
%11 = alloca i32
%12 = alloca i32
%13 = alloca i32
store i32* %0, i32** %6
store i32 %1, i32* %7
store i32* %2, i32** %8
store i32 %3, i32* %9
store i32 0, i32* %10
store i32 0, i32* %11
store i32 0, i32* %12
%14 = load i32, i32* %7
%15 = load i32, i32* %9
%16 = icmp eq i32 %14, %15
br i1 %16, label %17, label %21
17: ; preds = %4
%18 = load i32, i32* %7
%19 = icmp eq i32 %18, 0
br i1 %19, label %20, label %21
20: ; preds = %17
store float 1.000000e+00, float* %5
br label %85
21: ; preds = %17, %4
%22 = load i32, i32* %7
%23 = load i32, i32* %9
%24 = add i32 %22, %23
store i32 %24, i32* %13
br label %25
25: ; preds = %75, %21
%26 = load i32, i32* %10
%27 = load i32, i32* %7
%28 = icmp ult i32 %26, %27
br i1 %28, label %29, label %33
29: ; preds = %25
%30 = load i32, i32* %11
%31 = load i32, i32* %9
%32 = icmp ult i32 %30, %31
br label %33
33: ; preds = %29, %25
%34 = phi i1 [ false, %25 ], [ %32, %29 ]
br i1 %34, label %35, label %76
35: ; preds = %33
%36 = load i32*, i32** %6
%37 = load i32, i32* %10
%38 = zext i32 %37 to i64
%39 = getelementptr inbounds i32, i32* %36, i64 %38
%40 = load i32, i32* %39
%41 = load i32*, i32** %8
%42 = load i32, i32* %11
%43 = zext i32 %42 to i64
%44 = getelementptr inbounds i32, i32* %41, i64 %43
%45 = load i32, i32* %44
%46 = icmp eq i32 %40, %45
br i1 %46, label %47, label %56
47: ; preds = %35
%48 = load i32, i32* %12
%49 = add i32 %48, 1
store i32 %49, i32* %12
%50 = load i32, i32* %13
%51 = add i32 %50, -1
store i32 %51, i32* %13
%52 = load i32, i32* %10
%53 = add i32 %52, 1
store i32 %53, i32* %10
%54 = load i32, i32* %11
%55 = add i32 %54, 1
store i32 %55, i32* %11
br label %75
56: ; preds = %35
%57 = load i32*, i32** %6
%58 = load i32, i32* %10
%59 = zext i32 %58 to i64
%60 = getelementptr inbounds i32, i32* %57, i64 %59
%61 = load i32, i32* %60
%62 = load i32*, i32** %8
%63 = load i32, i32* %11
%64 = zext i32 %63 to i64
%65 = getelementptr inbounds i32, i32* %62, i64 %64
%66 = load i32, i32* %65
%67 = icmp ult i32 %61, %66
br i1 %67, label %68, label %71
68: ; preds = %56
%69 = load i32, i32* %11
%70 = add i32 %69, 1
store i32 %70, i32* %11
br label %74
71: ; preds = %56
%72 = load i32, i32* %10
%73 = add i32 %72, 1
store i32 %73, i32* %10
br label %74
74: ; preds = %71, %68
br label %75
75: ; preds = %74, %47
br label %25
76: ; preds = %33
%77 = load i32, i32* %12
%78 = uitofp i32 %77 to float
%79 = load i32, i32* %13
%80 = uitofp i32 %79 to float
%81 = fdiv float %78, %80
%82 = fpext float %81 to double
%83 = fsub double 1.000000e+00, %82
%84 = fptrunc double %83 to float
store float %84, float* %5
br label %85
85: ; preds = %76, %20
%86 = load float, float* %5
ret float %86
}

LLVM IR (-O2):
define float @neighbours_distance(i32* nocapture %0, i32 %1, i32* nocapture %2, i32 %3) {
%5 = or i32 %3, %1
%6 = icmp eq i32 %5, 0
br i1 %6, label %50, label %7
7: ; preds = %4
%8 = add i32 %3, %1
%9 = icmp ne i32 %1, 0
%10 = icmp ne i32 %3, 0
%11 = and i1 %9, %10
br i1 %11, label %12, label %43
12: ; preds = %7, %35
%13 = phi i32 [ %39, %35 ], [ %8, %7 ]
%14 = phi i32 [ %38, %35 ], [ 0, %7 ]
%15 = phi i32 [ %37, %35 ], [ 0, %7 ]
%16 = phi i32 [ %36, %35 ], [ 0, %7 ]
%17 = zext i32 %16 to i64
%18 = getelementptr inbounds i32, i32* %0, i64 %17
%19 = load i32, i32* %18
%20 = zext i32 %15 to i64
%21 = getelementptr inbounds i32, i32* %2, i64 %20
%22 = load i32, i32* %21
%23 = icmp eq i32 %19, %22
br i1 %23, label %24, label %29
24: ; preds = %12
%25 = add i32 %14, 1
%26 = add i32 %13, -1
%27 = add nuw i32 %16, 1
%28 = add nuw i32 %15, 1
br label %35
29: ; preds = %12
%30 = icmp ult i32 %19, %22
br i1 %30, label %31, label %33
31: ; preds = %29
%32 = add nuw i32 %15, 1
br label %35
33: ; preds = %29
%34 = add nuw i32 %16, 1
br label %35
35: ; preds = %31, %33, %24
%36 = phi i32 [ %27, %24 ], [ %16, %31 ], [ %34, %33 ]
%37 = phi i32 [ %28, %24 ], [ %32, %31 ], [ %15, %33 ]
%38 = phi i32 [ %25, %24 ], [ %14, %31 ], [ %14, %33 ]
%39 = phi i32 [ %26, %24 ], [ %13, %31 ], [ %13, %33 ]
%40 = icmp ult i32 %36, %1
%41 = icmp ult i32 %37, %3
%42 = select i1 %40, i1 %41, i1 false
br i1 %42, label %12, label %43
43: ; preds = %35, %7
%44 = phi i32 [ 0, %7 ], [ %38, %35 ]
%45 = phi i32 [ %8, %7 ], [ %39, %35 ]
%46 = uitofp i32 %44 to float
%47 = uitofp i32 %45 to float
%48 = fdiv float %46, %47
%49 = fsub float 1.000000e+00, %48
br label %50
50: ; preds = %4, %43
%51 = phi float [ %49, %43 ], [ 1.000000e+00, %4 ]
ret float %51
}