00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef __BIN_LOG_HH
00018 # define __BIN_LOG_HH
00019
00020 # include "bin_pow.hh"
00021 # include "static_bin_log.hh"
00022 # include <type_traits>
00023
00024 namespace fast {
00025
00026 template <typename integral_type, int N>
00027 struct bin_log_helper {
00028 enum: integral_type {
00029 shift = 1 << (N-1),
00030 pattern = ((integral_type)bin_pow_pow<integral_type, N>::value-1)
00031 << shift
00032 };
00033 static void step(integral_type& v, integral_type& r) {
00034 if (v & pattern) {
00035 v >>= shift;
00036 r |= shift;
00037 }
00038 bin_log_helper<integral_type, N-1>::step(v, r);
00039 }
00040 };
00041
00042 template <typename integral_type>
00043 struct bin_log_helper<integral_type, 0> {
00044 static void step(integral_type&, integral_type&) {
00045 }
00046 };
00047
00048 template <typename integral_type>
00049 integral_type bin_log(integral_type v) {
00050 static_assert(std::is_integral<integral_type>::value,
00051 "Cannot use non integral types.");
00052 static_assert(sizeof(integral_type) ==
00053 1<< static_bin_log<integral_type,
00054 sizeof(integral_type)>::value,
00055 "Type size is not a power of two.");
00056
00057 integral_type r = 0;
00058 bin_log_helper<integral_type,
00059 static_bin_log<integral_type,
00060 sizeof(integral_type)<<3>::value>::step(v, r);
00061 return r;
00062 }
00063
00064 }
00065
00066 #endif