Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@rmartinho
Forked from bananu7/bit_ops.cpp
Created April 24, 2013 22:44
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rmartinho/5456207 to your computer and use it in GitHub Desktop.
Save rmartinho/5456207 to your computer and use it in GitHub Desktop.
Bit twiddling tools. I got tired of primitive stuff like & and |
template <int Size>
struct uint_least : uint_least<Size+1> {};
template <>
struct uint_least<8> : identity<u8> {};
template <>
struct uint_least<16> : identity<u16> {};
template <>
struct uint_least<32> : identity<u32> {};
template <>
struct uint_least<64> : identity<u64> {};
template <int Size>
using UintLeast = typename uint_least<Size>::type;
template <int Size>
struct uint {
public:
using value_type = UintLeast<Size>;
constexpr uint() : value{} {}
constexpr uint(value_type value);
constexpr operator value_type() const { return value; }
private:
value_type value;
};
using bit = uint<1>;
template <int Size>
constexpr uint<Size> zigamorph() {
return -1;
}
namespace detail {
// this is here to avoid warnings about shifts larger than width
constexpr u64 shift_right(u64 value, int n) {
return n == 64? 0 : (value << n);
}
template <int Size>
struct zigamorph {
static constexpr UintLeast<Size> get() {
return shift_right(1, Size) - 1;
}
};
} // namespace detail
template <int Size>
constexpr uint<Size>::uint(value_type value)
: value(value & detail::zigamorph<Size>::get()) {}
template <int First, int Last = First>
constexpr uint<Last-First+1> bits(u64 value) {
return (value >> First) & zigamorph<Last-First+1>();
}
template <int N>
constexpr uint<N> bitfield(uint<N> u) { return u; }
template <int Head, int... Tail>
constexpr uint<sum<Head, Tail...>::value> bitfield(uint<Head> head, uint<Tail>... tail) {
return (u64(head) << sum<Tail...>::value) | bitfield(tail...);
}
template <int First, int Last = First, typename Uint>
constexpr Uint with_bits(Uint u, uint<Last-First+1> b) {
return bitfield(bits<0,First-1>(u), b, bits<Last+1,63>(u));
}
template <typename Uint>
constexpr Uint set_bit(Uint u, u8 bit) {
return u | (1 << bit);
}
template <typename Uint>
constexpr Uint clear_bit(Uint u, u8 bit) {
return u & ~(1 << bit);
}
template <typename Uint>
constexpr Uint toggle_bit(Uint u, u8 bit) {
return u ^ (1 << bit);
}
template <typename Uint>
constexpr bool is_bit_set(Uint u, u8 bit) {
return u & (1 << bit);
}
template <typename Uint>
constexpr bool has_flags(Uint u, Uint mask) {
return (u & mask) == mask;
}
template <typename Uint>
constexpr Uint set_flags(Uint u, Uint mask) {
return u | mask;
}
template <typename Uint>
constexpr bool clear_flags(Uint u, Uint mask) {
return u & ~mask;
}
template <typename Uint>
constexpr bool toggle_flags(Uint u, Uint mask) {
return u ^ mask;
}
template <int Align, typename Uint>
constexpr Uint align_backward(Uint u) {
return u & ~zigamorph<Align>();
}
template <int Align, typename Uint>
constexpr Uint align_forward(Uint u) {
return align_backward<Align>(u + zigamorph<Align>());
}
constexpr bool is_power_of_two(u32 n) {
return n && !(n & (n-1));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment