    // Copyright (C) 2013  Davis E. King (davis@dlib.net)
    // License: Boost Software License   See LICENSE.txt for the full license.
    #ifndef DLIB_COUNT_BiTS_Hh_
    #define DLIB_COUNT_BiTS_Hh_

    #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);
        }

    // ----------------------------------------------------------------------------------------

        template <
            typename T
            >
        T hamming_distance (
            const std::pair<T,T>& a,
            const std::pair<T,T>& b
        )
        /*!
            requires
                - T is an unsigned integral type or a std::pair that, recursively, eventually
                  contains unsigned integral types.
            ensures
                - returns the number of bits which differ between a and b.
        !*/
        {
            return hamming_distance(a.first,b.first) + hamming_distance(a.second, b.second);
        }

    // ----------------------------------------------------------------------------------------

    }

    #endif // DLIB_COUNT_BiTS_Hh_