bitmask.hpp

Back to Bit operations

pastel/sys/bit/

#ifndef PASTELSYS_BITMASK_HPP
#define PASTELSYS_BITMASK_HPP

#include "pastel/sys/bit/bitmask.h"
#include "pastel/sys/ensure.h"
#include "pastel/sys/integer/finite_integer_concept.h"

namespace Pastel
{

    template <
        typename Finite_Integer,
        Requires<
            Models<Finite_Integer, Finite_Integer_Concept>
        >
    >
    Finite_Integer singleBitMask(integer bit)
    {
        PENSURE_OP(bit, >=, 0);

        // C++ standard:
        // If E1 has an unsigned type, the value of the result is 
        // E1 × 2^E2, reduced modulo one more than the maximum value 
        // representable in the result type. 

        // So the shift is defined even when endBit equals or exceeds 
        // the number of bits.

        // However, such a left-shift used to be implementation-defined.
        // Indeed, Visual Studio 2013 still gives a warning about this.

        if (bit >= bits(Finite_Integer()))
        {
            return 0;
        }

        return (Finite_Integer)1 << bit;
    }

    template <
        typename Finite_Integer,
        Requires<
            Models<Finite_Integer, Finite_Integer_Concept>
        >
    >
    Finite_Integer bitMask(integer endBit)
    {
        PENSURE_OP(endBit, >=, 0);

        if (endBit >= bits(Finite_Integer()))
        {
            return -1;
        }

        // See the documentation for the singleBitMask().
        return ((Finite_Integer)1 << endBit) - (Finite_Integer)1;
    }

    template <
        typename Finite_Integer,
        Requires<
            Models<Finite_Integer, Finite_Integer_Concept>
        >
    >
    Finite_Integer bitMask(integer beginBit, integer endBit)
    {
        PENSURE_OP(beginBit, >=, 0);
        PENSURE_OP(beginBit, <=, endBit);

        // See the documentation for the singleBitMask().
        return bitMask<Finite_Integer>(endBit) ^ bitMask<Finite_Integer>(beginBit);
    }

}

#endif