aboutsummaryrefslogtreecommitdiffstats
path: root/vespalib/src/vespa/vespalib/util/binary_hamming_distance.cpp
blob: cbf940c9f0c953e24941be38a070a189683f80de (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include "binary_hamming_distance.h"
#include <cstdint>

namespace vespalib {

size_t binary_hamming_distance(const void *lhs, const void *rhs, size_t sz) {
    uintptr_t addr_a = (uintptr_t) lhs;
    uintptr_t addr_b = (uintptr_t) rhs;
    size_t sum = 0;
    size_t i = 0;
    static_assert(sizeof(uint64_t) == 8);
    bool aligned = ((addr_a & 0x7) == 0) && ((addr_b & 0x7) == 0);
    if (__builtin_expect(aligned, true)) {
        const uint64_t *words_a = static_cast<const uint64_t *>(lhs);
        const uint64_t *words_b = static_cast<const uint64_t *>(rhs);
        for (; i * 8 + 7 < sz; ++i) {
            uint64_t xor_bits = words_a[i] ^ words_b[i];
            sum += __builtin_popcountl(xor_bits);
        }
    }
    if (__builtin_expect((i * 8 < sz), false)) {
        const uint8_t *bytes_a = static_cast<const uint8_t *>(lhs);
        const uint8_t *bytes_b = static_cast<const uint8_t *>(rhs);
        for (i *= 8; i < sz; ++i) {
            uint64_t xor_bits = bytes_a[i] ^ bytes_b[i];
            sum += __builtin_popcountl(xor_bits);
        }
    }
    return sum;
};

}