Commit e341600f authored by Davis King's avatar Davis King

Added count_bits() and hamming_distance()

parent 2f61fe09
// Copyright (C) 2013 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_COUNT_BiTS_H__
#define DLIB_COUNT_BiTS_H__
#include "../algs.h"
#include <climits>
namespace dlib
{
// ----------------------------------------------------------------------------------------
template <
typename T
>
T count_bits (
T v
)
/*!
requires
- T is an unsigned integral type
ensures
- returns the number of bits in v which are set to 1.
!*/
{
COMPILE_TIME_ASSERT(is_unsigned_type<T>::value && sizeof(T) <= 8);
// This bit of bit trickery is from:
// http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSet64
v = v - ((v >> 1) & (T)~(T)0/3);
v = (v & (T)~(T)0/15*3) + ((v >> 2) & (T)~(T)0/15*3);
v = (v + (v >> 4)) & (T)~(T)0/255*15;
return (T)(v * ((T)~(T)0/255)) >> (sizeof(T) - 1) * CHAR_BIT;
}
// ----------------------------------------------------------------------------------------
template <
typename T
>
T hamming_distance (
const T& a,
const T& b
)
/*!
requires
- T is an unsigned integral type
ensures
- returns the number of bits which differ between a and b.
!*/
{
return count_bits(a^b);
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_COUNT_BiTS_H__
// Copyright (C) 2013 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_COUNT_BiTS_ABSTRACT_H__
#ifdef DLIB_COUNT_BiTS_ABSTRACT_H__
namespace dlib
{
// ----------------------------------------------------------------------------------------
template <
typename T
>
T count_bits (
T v
);
/*!
requires
- T is an unsigned integral type
ensures
- returns the number of bits in v which are set to 1.
!*/
// ----------------------------------------------------------------------------------------
template <
typename T
>
T hamming_distance (
const T& a,
const T& b
);
/*!
requires
- T is an unsigned integral type
ensures
- returns the number of bits which differ between a and b. (I.e. returns
count_bits(a^b).)
!*/
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_COUNT_BiTS_ABSTRACT_H__
......@@ -6,6 +6,7 @@
#include "general_hash/hash.h"
#include "general_hash/random_hashing.h"
#include "general_hash/count_bits.h"
#endif // DLIB_HASh_
......
......@@ -205,6 +205,55 @@ namespace
}
}
// ----------------------------------------------------------------------------------------
uint64 slow_count_bits ( uint64 v)
{
uint64 count = 0;
for (int i = 0; i < 64; ++i)
{
if (v&1)
++count;
v >>= 1;
}
return count;
}
uint32 slow_count_bits ( uint32 v)
{
uint32 count = 0;
for (int i = 0; i < 32; ++i)
{
if (v&1)
++count;
v >>= 1;
}
return count;
}
// ----------------------------------------------------------------------------------------
void test_hamming_stuff()
{
dlib::rand rnd;
for (int i = 0; i < 10000; ++i)
{
uint32 v = rnd.get_random_32bit_number();
uint64 v2 = rnd.get_random_64bit_number();
DLIB_TEST(slow_count_bits(v) == count_bits(v));
DLIB_TEST(slow_count_bits(v2) == count_bits(v2));
}
DLIB_TEST(hamming_distance((uint32)0x1F, (uint32)0x0F) == 1);
DLIB_TEST(hamming_distance((uint32)0x1F, (uint32)0x1F) == 0);
DLIB_TEST(hamming_distance((uint32)0x1F, (uint32)0x19) == 2);
DLIB_TEST(hamming_distance((uint32)0x2F, (uint32)0x19) == 4);
}
// ----------------------------------------------------------------------------------------
class test_hash : public tester
{
public:
......@@ -219,6 +268,8 @@ namespace
{
print_spinner();
test_hamming_stuff();
murmur_hash_test();
murmur_hash_128_test();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment