double matching_distance_bool(const char *u, const char *v, int n) {
  int i = 0;
  int nft = 0, ntf = 0;
  for (i = 0; i < n; i++) {
    ntf += (u[i] && !v[i]);
    nft += (!u[i] && v[i]);
  }
  return (double)(ntf + nft) / (double)(n);
}


x86 assembly (clang, -O0):
<matching_distance_bool>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
movl   $0x0,-0x18(%rbp)
movl   $0x0,-0x1c(%rbp)
movl   $0x0,-0x20(%rbp)
movl   $0x0,-0x18(%rbp)
mov    -0x18(%rbp),%eax
cmp    -0x14(%rbp),%eax
jge    11bb <matching_distance_bool+0xbb>
mov    -0x8(%rbp),%rax
movslq -0x18(%rbp),%rcx
movsbl (%rax,%rcx,1),%ecx
xor    %eax,%eax
cmp    $0x0,%ecx
mov    %al,-0x21(%rbp)
je     1165 <matching_distance_bool+0x65>
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
cmpb   $0x0,(%rax,%rcx,1)
setne  %al
xor    $0xff,%al
mov    %al,-0x21(%rbp)
mov    -0x21(%rbp),%al
and    $0x1,%al
movzbl %al,%eax
add    -0x20(%rbp),%eax
mov    %eax,-0x20(%rbp)
mov    -0x8(%rbp),%rcx
movslq -0x18(%rbp),%rdx
xor    %eax,%eax
cmpb   $0x0,(%rcx,%rdx,1)
mov    %al,-0x22(%rbp)
jne    119f <matching_distance_bool+0x9f>
mov    -0x10(%rbp),%rax
movslq -0x18(%rbp),%rcx
movsbl (%rax,%rcx,1),%eax
cmp    $0x0,%eax
setne  %al
mov    %al,-0x22(%rbp)
mov    -0x22(%rbp),%al
and    $0x1,%al
movzbl %al,%eax
add    -0x1c(%rbp),%eax
mov    %eax,-0x1c(%rbp)
mov    -0x18(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x18(%rbp)
jmp    112b <matching_distance_bool+0x2b>
mov    -0x20(%rbp),%eax
add    -0x1c(%rbp),%eax
cvtsi2sd %eax,%xmm0
cvtsi2sdl -0x14(%rbp),%xmm1
divsd  %xmm1,%xmm0
pop    %rbp
ret

x86 assembly (clang, -O2):
<matching_distance_bool>:
test   %edx,%edx
jle    111a <matching_distance_bool+0x1a>
push   %rbp
push   %rbx
mov    %edx,%r8d
cmp    $0x8,%edx
jae    1123 <matching_distance_bool+0x23>
xor    %r9d,%r9d
xor    %ecx,%ecx
xor    %ebp,%ebp
jmp    1280 <matching_distance_bool+0x180>
xorpd  %xmm0,%xmm0
jmp    12bc <matching_distance_bool+0x1bc>
mov    %r8d,%r9d
and    $0xfffffff8,%r9d
pxor   %xmm8,%xmm8
xor    %eax,%eax
pcmpeqd %xmm9,%xmm9
movdqa 0xec1(%rip),%xmm10
pxor   %xmm11,%xmm11
pxor   %xmm12,%xmm12
pxor   %xmm14,%xmm14
pxor   %xmm13,%xmm13
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
movd   (%rdi,%rax,1),%xmm7
movd   0x4(%rdi,%rax,1),%xmm2
pcmpeqb %xmm8,%xmm7
movdqa %xmm7,%xmm5
punpcklbw %xmm5,%xmm5
punpcklwd %xmm5,%xmm5
pxor   %xmm9,%xmm7
punpcklbw %xmm7,%xmm7
punpcklwd %xmm7,%xmm7
pcmpeqb %xmm8,%xmm2
movdqa %xmm2,%xmm3
punpcklbw %xmm3,%xmm3
punpcklwd %xmm3,%xmm3
pxor   %xmm9,%xmm2
punpcklbw %xmm2,%xmm2
punpcklwd %xmm2,%xmm2
movd   (%rsi,%rax,1),%xmm4
movd   0x4(%rsi,%rax,1),%xmm6
pcmpeqb %xmm8,%xmm4
movdqa %xmm4,%xmm0
punpcklbw %xmm0,%xmm0
punpcklwd %xmm0,%xmm0
pcmpeqb %xmm8,%xmm6
movdqa %xmm6,%xmm1
punpcklbw %xmm1,%xmm1
punpcklwd %xmm1,%xmm1
pxor   %xmm9,%xmm4
punpcklbw %xmm4,%xmm4
punpcklwd %xmm4,%xmm4
pxor   %xmm9,%xmm6
punpcklbw %xmm6,%xmm6
punpcklwd %xmm6,%xmm6
pand   %xmm10,%xmm0
pand   %xmm7,%xmm0
paddd  %xmm0,%xmm11
pand   %xmm10,%xmm1
pand   %xmm2,%xmm1
paddd  %xmm1,%xmm12
pand   %xmm10,%xmm5
pand   %xmm4,%xmm5
paddd  %xmm5,%xmm14
pand   %xmm10,%xmm3
pand   %xmm6,%xmm3
paddd  %xmm3,%xmm13
add    $0x8,%rax
cmp    %rax,%r9
jne    1160 <matching_distance_bool+0x60>
paddd  %xmm14,%xmm13
pshufd $0xee,%xmm13,%xmm0
paddd  %xmm13,%xmm0
pshufd $0x55,%xmm0,%xmm1
paddd  %xmm0,%xmm1
movd   %xmm1,%ebp
paddd  %xmm11,%xmm12
pshufd $0xee,%xmm12,%xmm0
paddd  %xmm12,%xmm0
pshufd $0x55,%xmm0,%xmm1
paddd  %xmm0,%xmm1
movd   %xmm1,%ecx
cmp    %r8,%r9
je     12b1 <matching_distance_bool+0x1b1>
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
cmpb   $0x0,(%rdi,%r9,1)
sete   %r10b
setne  %r11b
cmpb   $0x0,(%rsi,%r9,1)
sete   %bl
setne  %al
and    %r11b,%bl
movzbl %bl,%ebx
add    %ebx,%ecx
and    %r10b,%al
movzbl %al,%eax
add    %eax,%ebp
add    $0x1,%r9
cmp    %r9,%r8
jne    1280 <matching_distance_bool+0x180>
add    %ebp,%ecx
xorps  %xmm0,%xmm0
cvtsi2sd %ecx,%xmm0
pop    %rbx
pop    %rbp
xorps  %xmm1,%xmm1
cvtsi2sd %edx,%xmm1
divsd  %xmm1,%xmm0
ret

LLVM IR (-O0):
define double @matching_distance_bool(i8* %0, i8* %1, i32 %2) {
%4 = alloca i8*
%5 = alloca i8*
%6 = alloca i32
%7 = alloca i32
%8 = alloca i32
%9 = alloca i32
store i8* %0, i8** %4
store i8* %1, i8** %5
store i32 %2, i32* %6
store i32 0, i32* %7
store i32 0, i32* %8
store i32 0, i32* %9
store i32 0, i32* %7
br label %10
10: ; preds = %54, %3
%11 = load i32, i32* %7
%12 = load i32, i32* %6
%13 = icmp slt i32 %11, %12
br i1 %13, label %14, label %57
14: ; preds = %10
%15 = load i8*, i8** %4
%16 = load i32, i32* %7
%17 = sext i32 %16 to i64
%18 = getelementptr inbounds i8, i8* %15, i64 %17
%19 = load i8, i8* %18
%20 = sext i8 %19 to i32
%21 = icmp ne i32 %20, 0
br i1 %21, label %22, label %30
22: ; preds = %14
%23 = load i8*, i8** %5
%24 = load i32, i32* %7
%25 = sext i32 %24 to i64
%26 = getelementptr inbounds i8, i8* %23, i64 %25
%27 = load i8, i8* %26
%28 = icmp ne i8 %27, 0
%29 = xor i1 %28, true
br label %30
30: ; preds = %22, %14
%31 = phi i1 [ false, %14 ], [ %29, %22 ]
%32 = zext i1 %31 to i32
%33 = load i32, i32* %9
%34 = add nsw i32 %33, %32
store i32 %34, i32* %9
%35 = load i8*, i8** %4
%36 = load i32, i32* %7
%37 = sext i32 %36 to i64
%38 = getelementptr inbounds i8, i8* %35, i64 %37
%39 = load i8, i8* %38
%40 = icmp ne i8 %39, 0
br i1 %40, label %49, label %41
41: ; preds = %30
%42 = load i8*, i8** %5
%43 = load i32, i32* %7
%44 = sext i32 %43 to i64
%45 = getelementptr inbounds i8, i8* %42, i64 %44
%46 = load i8, i8* %45
%47 = sext i8 %46 to i32
%48 = icmp ne i32 %47, 0
br label %49
49: ; preds = %41, %30
%50 = phi i1 [ false, %30 ], [ %48, %41 ]
%51 = zext i1 %50 to i32
%52 = load i32, i32* %8
%53 = add nsw i32 %52, %51
store i32 %53, i32* %8
br label %54
54: ; preds = %49
%55 = load i32, i32* %7
%56 = add nsw i32 %55, 1
store i32 %56, i32* %7
br label %10
57: ; preds = %10
%58 = load i32, i32* %9
%59 = load i32, i32* %8
%60 = add nsw i32 %58, %59
%61 = sitofp i32 %60 to double
%62 = load i32, i32* %6
%63 = sitofp i32 %62 to double
%64 = fdiv double %61, %63
ret double %64
}

LLVM IR (-O2):
define double @matching_distance_bool(i8* nocapture %0, i8* nocapture %1, i32 %2) {
%4 = icmp sgt i32 %2, 0
br i1 %4, label %5, label %85
5: ; preds = %3
%6 = zext i32 %2 to i64
%7 = icmp ult i32 %2, 8
br i1 %7, label %56, label %8
8: ; preds = %5
%9 = and i64 %6, 4294967288
br label %10
10: ; preds = %10, %8
%11 = phi i64 [ 0, %8 ], [ %48, %10 ]
%12 = phi <4 x i32> [ zeroinitializer, %8 ], [ %40, %10 ]
%13 = phi <4 x i32> [ zeroinitializer, %8 ], [ %41, %10 ]
%14 = phi <4 x i32> [ zeroinitializer, %8 ], [ %46, %10 ]
%15 = phi <4 x i32> [ zeroinitializer, %8 ], [ %47, %10 ]
%16 = getelementptr inbounds i8, i8* %0, i64 %11
%17 = bitcast i8* %16 to <4 x i8>*
%18 = load <4 x i8>, <4 x i8>* %17
%19 = getelementptr inbounds i8, i8* %16, i64 4
%20 = bitcast i8* %19 to <4 x i8>*
%21 = load <4 x i8>, <4 x i8>* %20
%22 = icmp eq <4 x i8> %18, zeroinitializer
%23 = icmp eq <4 x i8> %21, zeroinitializer
%24 = getelementptr inbounds i8, i8* %1, i64 %11
%25 = bitcast i8* %24 to <4 x i8>*
%26 = load <4 x i8>, <4 x i8>* %25
%27 = getelementptr inbounds i8, i8* %24, i64 4
%28 = bitcast i8* %27 to <4 x i8>*
%29 = load <4 x i8>, <4 x i8>* %28
%30 = icmp eq <4 x i8> %26, zeroinitializer
%31 = icmp eq <4 x i8> %29, zeroinitializer
%32 = icmp ne <4 x i8> %26, zeroinitializer
%33 = icmp ne <4 x i8> %29, zeroinitializer
%34 = xor <4 x i1> %22, <i1 true, i1 true, i1 true, i1 true>
%35 = xor <4 x i1> %23, <i1 true, i1 true, i1 true, i1 true>
%36 = select <4 x i1> %34, <4 x i1> %30, <4 x i1> zeroinitializer
%37 = select <4 x i1> %35, <4 x i1> %31, <4 x i1> zeroinitializer
%38 = zext <4 x i1> %36 to <4 x i32>
%39 = zext <4 x i1> %37 to <4 x i32>
%40 = add <4 x i32> %12, %38
%41 = add <4 x i32> %13, %39
%42 = select <4 x i1> %22, <4 x i1> %32, <4 x i1> zeroinitializer
%43 = select <4 x i1> %23, <4 x i1> %33, <4 x i1> zeroinitializer
%44 = zext <4 x i1> %42 to <4 x i32>
%45 = zext <4 x i1> %43 to <4 x i32>
%46 = add <4 x i32> %14, %44
%47 = add <4 x i32> %15, %45
%48 = add nuw i64 %11, 8
%49 = icmp eq i64 %48, %9
br i1 %49, label %50, label %10
50: ; preds = %10
%51 = add <4 x i32> %47, %46
%52 = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> %51)
%53 = add <4 x i32> %41, %40
%54 = call i32 @llvm.vector.reduce.add.v4i32(<4 x i32> %53)
%55 = icmp eq i64 %9, %6
br i1 %55, label %80, label %56
56: ; preds = %5, %50
%57 = phi i64 [ 0, %5 ], [ %9, %50 ]
%58 = phi i32 [ 0, %5 ], [ %54, %50 ]
%59 = phi i32 [ 0, %5 ], [ %52, %50 ]
br label %60
60: ; preds = %56, %60
%61 = phi i64 [ %78, %60 ], [ %57, %56 ]
%62 = phi i32 [ %74, %60 ], [ %58, %56 ]
%63 = phi i32 [ %77, %60 ], [ %59, %56 ]
%64 = getelementptr inbounds i8, i8* %0, i64 %61
%65 = load i8, i8* %64
%66 = icmp eq i8 %65, 0
%67 = getelementptr inbounds i8, i8* %1, i64 %61
%68 = load i8, i8* %67
%69 = icmp eq i8 %68, 0
%70 = icmp ne i8 %68, 0
%71 = xor i1 %66, true
%72 = select i1 %71, i1 %69, i1 false
%73 = zext i1 %72 to i32
%74 = add nuw nsw i32 %62, %73
%75 = select i1 %66, i1 %70, i1 false
%76 = zext i1 %75 to i32
%77 = add nuw nsw i32 %63, %76
%78 = add nuw nsw i64 %61, 1
%79 = icmp eq i64 %78, %6
br i1 %79, label %80, label %60
80: ; preds = %60, %50
%81 = phi i32 [ %54, %50 ], [ %74, %60 ]
%82 = phi i32 [ %52, %50 ], [ %77, %60 ]
%83 = add nuw nsw i32 %81, %82
%84 = sitofp i32 %83 to double
br label %85
85: ; preds = %80, %3
%86 = phi double [ %84, %80 ], [ 0.000000e+00, %3 ]
%87 = sitofp i32 %2 to double
%88 = fdiv double %86, %87
ret double %88
}