-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathleading_one.hpp
55 lines (47 loc) · 2.1 KB
/
leading_one.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#ifndef __LEADING_ONE_HPP__
#define __LEADING_ONE_HPP__
// Use template meta-programming to compute the position of the leading one of
// an unsigned int.
// To get the position of the leading one of 'val', use leading_one<val>::value.
// A struct with bool field 'value' that is true if val has a 1 at position N,
// otherwise value is false
template <unsigned N, unsigned val> struct one_at_N {
static bool const value = 1 << N & val;
};
// A struct that will have an unsigned field 'value' giving the position of the
// leading one in val. It does this using recursion and three different versions
// of the struct. The struct also has boolean field 'zero' which is true if val
// is zero, in which case 'value' should be ignored.
template <unsigned N, unsigned val, typename T = void> struct find_leading_one;
// This struct is used if the bit at position N is a 1, and sets value to N.
template <unsigned N, unsigned val>
struct find_leading_one<
N, val,
typename std::enable_if<one_at_N<N, val>::value && val != 0>::type> {
static unsigned const value = N;
static bool const zero = false;
};
// This struct is used if the bit at position N is a 0, and recursively sets
// value to find_leading_one<N-1, val>::value.
template <unsigned N, unsigned val>
struct find_leading_one<
N, val,
typename std::enable_if<!one_at_N<N, val>::value && val != 0>::type> {
static unsigned const value = find_leading_one<N - 1, val>::value;
static bool const zero = false;
};
// This struct is used if val is zero, and sets 'zero' to true.
template <unsigned N> struct find_leading_one<N, 0, void> {
static unsigned const value = 0;
static bool const zero = true;
};
// The struct to be used to get the leading one of 'val'. The field 'value' gets
// set to the position of the leading one of 'val', unless 'val' is zero, in
// which case the field 'zero' is true.
template <unsigned val> struct leading_one {
static unsigned const value =
find_leading_one<sizeof(unsigned) * 8 - 1, val>::value;
static bool const zero =
find_leading_one<sizeof(unsigned) * 8 - 1, val>::zero;
};
#endif