00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef __INVERT_BITS_HH
00018 # define __INVERT_BITS_HH
00019
00020 # include "bin_pow.hh"
00021 # include "static_bin_log.hh"
00022 # include <type_traits>
00023
00024 namespace fast {
00025 template <typename integral_type, int size, int width, integral_type pattern>
00026 struct repeat_pattern_recurse {
00027 enum: integral_type {
00028 value = (integral_type)repeat_pattern_recurse<integral_type,
00029 size,
00030 2*width,
00031 pattern |
00032 (pattern << width)>::value
00033 };
00034 };
00035
00036 template <typename integral_type, int size, integral_type pattern>
00037 struct repeat_pattern_recurse<integral_type, size, size, pattern> {
00038 enum: integral_type { value = pattern };
00039 };
00040
00041 template <typename integral_type, int width, integral_type pattern>
00042 struct repeat_pattern:
00043 public repeat_pattern_recurse<integral_type, sizeof(integral_type)<<3,
00044 width, pattern>
00045 {};
00046
00047 template <typename integral_type, int N>
00048 struct inversion_helper {
00049 enum: integral_type
00050 { shift = 1 << (N-1),
00051 smallpattern = ((integral_type)bin_pow_pow<integral_type, N>::value-1)
00052 << shift,
00053 pattern = repeat_pattern<integral_type, 2*shift, smallpattern>::value
00054 };
00055 static void step(integral_type& v) {
00056 integral_type l = v << shift;
00057 v >>= shift;
00058 v = (l & pattern)
00059 | (v & (pattern >> shift));
00060 inversion_helper<integral_type, N-1>::step(v);
00061 }
00062 };
00063
00064 template <typename integral_type>
00065 struct inversion_helper<integral_type, 0> {
00066 static void step(integral_type&) {}
00067 };
00068
00069 template <typename integral_type>
00070 inline void invert_bits(integral_type& v) {
00071 static_assert(std::is_integral<integral_type>::value,
00072 "Cannot invert bits on non integral types.");
00073 static_assert(sizeof(integral_type) ==
00074 1<< static_bin_log<integral_type,
00075 sizeof(integral_type)>::value,
00076 "Type size is not a power of two.");
00077
00078 inversion_helper<integral_type,
00079 static_bin_log<integral_type,
00080 sizeof(integral_type)<<3>::value>::step(v);
00081 }
00082 }
00083
00084 #endif