fixed_point (deprecated)  rev.2
Binary Fixed-Point Arithmetic Library in C++
numeric.h
1 
2 // Copyright John McFarlane 2015 - 2017.
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file ../LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 
9 
10 #ifndef SG14_NUMERIC_H
11 #define SG14_NUMERIC_H
12 
13 #include <sg14/num_traits.h>
14 
15 #include <limits.h>
16 
18 namespace sg14 {
19 
21  // sg14::trailing_bits
22 
23  namespace _numeric_impl {
24  template<class Integer>
25  constexpr int trailing_bits_positive(Integer value, int mask_bits = sizeof(Integer)*CHAR_BIT/2)
26  {
27  return ((value & ((Integer{1} << mask_bits)-1))==0)
28  ? mask_bits+trailing_bits_positive(value/(Integer{1} << mask_bits), mask_bits)
29  : (mask_bits>1)
30  ? trailing_bits_positive(value, mask_bits/2)
31  : 0;
32  }
33 
34  template<class Integer, class Enable = void>
35  struct trailing_bits {
36  static constexpr int f(Integer value)
37  {
38  return value ? trailing_bits_positive(value) : 0;
39  }
40  };
41 
42  template<class Integer>
43  struct trailing_bits<Integer, _impl::enable_if_t<std::numeric_limits<Integer>::is_signed>> {
44  static constexpr int f(Integer value)
45  {
46  // Most negative number is not exploited;
47  // thus negating the result or subtracting it from something else
48  // will less likely result in overflow.
49  return (value>0)
50  ? trailing_bits_positive(value)
51  : (value<0)
52  ? trailing_bits_positive(-value)
53  : 0;
54  }
55  };
56  }
57 
58  template<class Integer>
59  constexpr int trailing_bits(Integer value)
60  {
61  return _numeric_impl::trailing_bits<Integer>::f(value);
62  }
63 
65  // sg14::used_bits
66 
67  namespace _numeric_impl {
68  template<class Integer>
69  constexpr int used_bits_positive(Integer value, int mask_bits = sizeof(Integer)*CHAR_BIT/2)
70  {
71  return (value>=(Integer{1} << mask_bits))
72  ? mask_bits+used_bits_positive(value/(Integer{1} << mask_bits), mask_bits)
73  : (mask_bits>1)
74  ? used_bits_positive(value, mask_bits/2)
75  : 1;
76  }
77  }
78 
79  namespace _impl {
80  template<class Integer>
81  constexpr int used_bits_symmetric(Integer value)
82  {
83  // Most negative number is not exploited;
84  // thus negating the result or subtracting it from something else
85  // will less likely result in overflow.
86  return (value>0)
87  ? _numeric_impl::used_bits_positive<Integer>(value)
88  : (value<0)
89 #if defined(_MSC_VER)
90 #pragma warning(push)
91 #pragma warning(disable: 4146)
92 #endif
93  ? _numeric_impl::used_bits_positive<Integer>(-value)
94 #if defined(_MSC_VER)
95 #pragma warning(pop)
96 #endif
97  : 0;
98  }
99  }
100 
101  namespace _numeric_impl {
102  struct used_bits {
103  template<class Integer>
104  constexpr _impl::enable_if_t<!std::numeric_limits<Integer>::is_signed, int> operator()(Integer value) const
105  {
106  return value ? used_bits_positive(value) : 0;
107  }
108 
109  template<class Integer, class = _impl::enable_if_t<std::numeric_limits<Integer>::is_signed, int>>
110  constexpr int operator()(Integer value) const
111  {
112  // Most negative number is not exploited;
113  // thus negating the result or subtracting it from something else
114  // will less likely result in overflow.
115  return (value>0)
116  ? used_bits_positive(value)
117  : (value==0)
118  ? 0
119  : used_bits()(Integer(-1)-value);
120  }
121  };
122  }
123 
124  template<class Integer>
125  constexpr int used_bits(Integer value)
126  {
127  return for_rep<int>(_numeric_impl::used_bits(), value);
128  }
129 
131  // sg14::leading_bits
132 
133 #if !defined(_MSC_VER) && !defined(SG14_DISABLE_GCC_BUILTINS)
134  constexpr int leading_bits(int value)
135  {
136  return (value>0)
137  ? __builtin_clz(value)-1
138  : digits<int>::value-used_bits(value);
139  }
140 #endif
141 
142  template<class Integer>
143  constexpr int leading_bits(const Integer& value)
144  {
145  return digits<Integer>::value-used_bits(value);
146  }
147 }
148 
149 #endif // SG14_NUMERIC_H
study group 14 of the C++ working group
Definition: const_integer.h:22