fixed_point (deprecated)  rev.2
Binary Fixed-Point Arithmetic Library in C++
fixed_point_extras.h
1 
2 // Copyright John McFarlane 2015 - 2016.
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 
11 
12 #if !defined(SG14_FIXED_POINT_EXTRAS_H)
13 #define SG14_FIXED_POINT_EXTRAS_H 1
14 
15 #include "fixed_point_type.h"
16 
17 #include <cmath>
18 #include <istream>
19 
21 namespace sg14 {
22 
24  // sg14::_impl::set_rep<fixed_point<>>
25 
26  namespace _impl {
27  template<class Rep, int Exponent>
28  struct get_rep<fixed_point<Rep, Exponent>> {
29  using type = Rep;
30  };
31 
32  template<class OldRep, int Exponent, class NewRep>
33  struct set_rep<fixed_point<OldRep, Exponent>, NewRep> {
34  using type = fixed_point<NewRep, Exponent>;
35  };
36  }
37 
39  // numeric traits
40 
41  template<class Rep, int Exponent>
42  struct digits<fixed_point<Rep, Exponent>> : digits<Rep> {
43  };
44 
45  template<class Rep, int Exponent, _digits_type MinNumBits>
46  struct set_digits<fixed_point<Rep, Exponent>, MinNumBits> {
47  using type = fixed_point<set_digits_t<Rep, MinNumBits>, Exponent>;
48  };
49 
50  template<class Rep, int Exponent, class Value>
51  struct from_value<fixed_point<Rep, Exponent>, Value> {
52  using type = fixed_point<Value>;
53  };
54 
56  // sg14::abs
57 
58  template<class Rep, int Exponent>
59  constexpr auto abs(const fixed_point<Rep, Exponent>& x) noexcept
60  -> decltype(-x)
61  {
62  return (x >= 0) ? static_cast<decltype(-x)>(x) : -x;
63  }
64 
66  // sg14::sqrt helper functions
67 
68  namespace _impl {
69  namespace fp {
70  namespace extras {
71  template<class Rep>
72  constexpr Rep sqrt_bit(Rep n, Rep bit)
73  {
74  return (bit>n) ? sqrt_bit<Rep>(n, bit >> 2) : bit;
75  }
76 
77  template<class Rep>
78  constexpr Rep sqrt_bit(Rep n)
79  {
80  return sqrt_bit<Rep>(n, Rep(1) << ((digits<Rep>::value + is_signed<Rep>::value) - 2));
81  }
82 
83  template<class Rep>
84  constexpr Rep sqrt_solve3(
85  Rep n,
86  Rep bit,
87  Rep result)
88  {
89  return (bit!=Rep{0})
90  ? (n>=result+bit)
91  ? sqrt_solve3<Rep>(
92  static_cast<Rep>(n-(result+bit)),
93  bit >> 2,
94  static_cast<Rep>((result >> 1)+bit))
95  : sqrt_solve3<Rep>(n, bit >> 2, result >> 1)
96  : result;
97  }
98 
99  template<class Rep>
100  constexpr Rep sqrt_solve1(Rep n)
101  {
102  return sqrt_solve3<Rep>(n, sqrt_bit<Rep>(n), Rep{0});
103  }
104  }
105  }
106  }
107 
109  // sg14::sqrt
110 
124 
125  // https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_.28base_2.29
126  // ?
127  template<class Rep, int Exponent>
128  constexpr fixed_point <Rep, Exponent>
130  {
131  using widened_type = fixed_point<set_digits_t<Rep, digits<Rep>::value*2>, Exponent*2>;
132  return
133 #if defined(SG14_EXCEPTIONS_ENABLED)
134  (x<fixed_point<Rep, Exponent>(0))
135  ? throw std::invalid_argument("cannot represent square root of negative value") :
136 #endif
138  static_cast<Rep>(_impl::fp::extras::sqrt_solve1(widened_type{x}.data())));
139  }
140 
142  // sg14::trig
143  //
144  // Placeholder implementations fall back on <cmath> functions which is slow
145  // due to conversion to and from floating-point types; also inconvenient as
146  // many <cmath> functions are not constexpr.
147 
148  namespace _impl {
149  namespace fp {
150  namespace extras {
151  template<class Rep, int Exponent, _impl::fp::float_of_same_size<Rep>(* F)(
152  _impl::fp::float_of_same_size<Rep>)>
154  crib(const fixed_point <Rep, Exponent>& x) noexcept
155  {
156  using floating_point = _impl::fp::float_of_same_size<Rep>;
157  return static_cast<fixed_point<Rep, Exponent>>(F(static_cast<floating_point>(x)));
158  }
159  }
160  }
161  }
162 
163  template<class Rep, int Exponent>
165  sin(const fixed_point <Rep, Exponent>& x) noexcept
166  {
167  return _impl::fp::extras::crib<Rep, Exponent, std::sin>(x);
168  }
169 
170  template<class Rep, int Exponent>
172  cos(const fixed_point <Rep, Exponent>& x) noexcept
173  {
174  return _impl::fp::extras::crib<Rep, Exponent, std::cos>(x);
175  }
176 
177  template<class Rep, int Exponent>
179  exp(const fixed_point <Rep, Exponent>& x) noexcept
180  {
181  return _impl::fp::extras::crib<Rep, Exponent, std::exp>(x);
182  }
183 
184  template<class Rep, int Exponent>
186  pow(const fixed_point <Rep, Exponent>& x) noexcept
187  {
188  return _impl::fp::extras::crib<Rep, Exponent, std::pow>(x);
189  }
190 
192  // sg14::fixed_point streaming - (placeholder implementation)
193 
194  template<class Rep, int Exponent>
195  ::std::ostream& operator<<(::std::ostream& out, const fixed_point <Rep, Exponent>& fp)
196  {
197  return out << static_cast<long double>(fp);
198  }
199 
200  template<class Rep, int Exponent>
201  ::std::istream& operator>>(::std::istream& in, fixed_point <Rep, Exponent>& fp)
202  {
203  long double ld;
204  in >> ld;
205  fp = ld;
206  return in;
207  }
208 }
209 
210 namespace std {
212  // std::numeric_limits for sg14::fixed_point
213 
214  // note: some members are guessed,
215  // some are temporary (assuming rounding style, traps etc.)
216  // and some are undefined
217  template<class Rep, int Exponent>
218  struct numeric_limits<sg14::fixed_point<Rep, Exponent>>
219  : std::numeric_limits<sg14::_impl::number_base<sg14::fixed_point<Rep, Exponent>, Rep>> {
220  // fixed-point-specific helpers
221  using _value_type = sg14::fixed_point<Rep, Exponent>;
222  using _rep = typename _value_type::rep;
223  using _rep_numeric_limits = numeric_limits<_rep>;
224 
225  // standard members
226 
227  static constexpr _value_type min() noexcept
228  {
229  return _value_type::from_data(_rep{1});
230  }
231 
232  static constexpr _value_type max() noexcept
233  {
234  return _value_type::from_data(_rep_numeric_limits::max());
235  }
236 
237  static constexpr _value_type lowest() noexcept
238  {
239  return _value_type::from_data(_rep_numeric_limits::lowest());
240  }
241 
242  static constexpr bool is_integer = false;
243 
244  static constexpr _value_type epsilon() noexcept
245  {
246  return _value_type::from_data(_rep{1});
247  }
248 
249  static constexpr _value_type round_error() noexcept
250  {
251  return _value_type::from_data(_rep{0});
252  }
253 
254  static constexpr _value_type infinity() noexcept
255  {
256  return _value_type::from_data(_rep{0});
257  }
258 
259  static constexpr _value_type quiet_NaN() noexcept
260  {
261  return _value_type::from_data(_rep{0});
262  }
263 
264  static constexpr _value_type signaling_NaN() noexcept
265  {
266  return _value_type::from_data(_rep{0});
267  }
268 
269  static constexpr _value_type denorm_min() noexcept
270  {
271  return _value_type::from_data(_rep{1});
272  }
273  };
274 }
275 
276 #endif // SG14_FIXED_POINT_EXTRAS_H
constexpr fixed_point< Rep, Exponent > sqrt(const fixed_point< Rep, Exponent > &x)
calculates the square root of a fixed_point value
Definition: fixed_point_extras.h:129
STL namespace.
static constexpr fixed_point from_data(rep const &r)
creates an instance given the underlying representation value
Definition: fixed_point_type.h:190
literal real number approximation that uses fixed-point arithmetic
Definition: fixed_point_type.h:20
study group 14 of the C++ working group
Definition: const_integer.h:22