Chris@102
|
1 ///////////////////////////////////////////////////////////////
|
Chris@102
|
2 // Copyright 2013 John Maddock. Distributed under the Boost
|
Chris@102
|
3 // Software License, Version 1.0. (See accompanying file
|
Chris@102
|
4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
|
Chris@102
|
5
|
Chris@102
|
6 #ifndef BOOST_MATH_CPP_BIN_FLOAT_HPP
|
Chris@102
|
7 #define BOOST_MATH_CPP_BIN_FLOAT_HPP
|
Chris@102
|
8
|
Chris@102
|
9 #include <boost/multiprecision/cpp_int.hpp>
|
Chris@102
|
10 #include <boost/multiprecision/integer.hpp>
|
Chris@102
|
11 #include <boost/math/special_functions/trunc.hpp>
|
Chris@102
|
12 #include <boost/multiprecision/detail/float_string_cvt.hpp>
|
Chris@102
|
13
|
Chris@102
|
14 namespace boost{ namespace multiprecision{ namespace backends{
|
Chris@102
|
15
|
Chris@102
|
16 enum digit_base_type
|
Chris@102
|
17 {
|
Chris@102
|
18 digit_base_2 = 2,
|
Chris@102
|
19 digit_base_10 = 10
|
Chris@102
|
20 };
|
Chris@102
|
21
|
Chris@102
|
22 #ifdef BOOST_MSVC
|
Chris@102
|
23 #pragma warning(push)
|
Chris@102
|
24 #pragma warning(disable:4522) // multiple assignment operators specified
|
Chris@102
|
25 #endif
|
Chris@102
|
26
|
Chris@102
|
27 namespace detail{
|
Chris@102
|
28
|
Chris@102
|
29 template <class U>
|
Chris@102
|
30 inline typename enable_if_c<is_unsigned<U>::value, bool>::type is_negative(U) { return false; }
|
Chris@102
|
31 template <class S>
|
Chris@102
|
32 inline typename disable_if_c<is_unsigned<S>::value, bool>::type is_negative(S s) { return s < 0; }
|
Chris@102
|
33
|
Chris@102
|
34 }
|
Chris@102
|
35
|
Chris@102
|
36 template <unsigned Digits, digit_base_type DigitBase = digit_base_10, class Allocator = void, class Exponent = int, Exponent MinExponent = 0, Exponent MaxExponent = 0>
|
Chris@102
|
37 class cpp_bin_float
|
Chris@102
|
38 {
|
Chris@102
|
39 public:
|
Chris@102
|
40 static const unsigned bit_count = DigitBase == digit_base_2 ? Digits : (Digits * 1000uL) / 301uL + ((Digits * 1000uL) % 301 ? 2u : 1u);
|
Chris@102
|
41 typedef cpp_int_backend<is_void<Allocator>::value ? bit_count : 0, bit_count, is_void<Allocator>::value ? unsigned_magnitude : signed_magnitude, unchecked, Allocator> rep_type;
|
Chris@102
|
42 typedef cpp_int_backend<is_void<Allocator>::value ? 2 * bit_count : 0, 2 * bit_count, is_void<Allocator>::value ? unsigned_magnitude : signed_magnitude, unchecked, Allocator> double_rep_type;
|
Chris@102
|
43
|
Chris@102
|
44 typedef typename rep_type::signed_types signed_types;
|
Chris@102
|
45 typedef typename rep_type::unsigned_types unsigned_types;
|
Chris@102
|
46 typedef boost::mpl::list<double, long double> float_types;
|
Chris@102
|
47 typedef Exponent exponent_type;
|
Chris@102
|
48
|
Chris@102
|
49 static const exponent_type max_exponent_limit = boost::integer_traits<exponent_type>::const_max - 2 * static_cast<exponent_type>(bit_count);
|
Chris@102
|
50 static const exponent_type min_exponent_limit = boost::integer_traits<exponent_type>::const_min + 2 * static_cast<exponent_type>(bit_count);
|
Chris@102
|
51
|
Chris@102
|
52 BOOST_STATIC_ASSERT_MSG(MinExponent >= min_exponent_limit, "Template parameter MinExponent is too negative for our internal logic to function correctly, sorry!");
|
Chris@102
|
53 BOOST_STATIC_ASSERT_MSG(MaxExponent <= max_exponent_limit, "Template parameter MaxExponent is too large for our internal logic to function correctly, sorry!");
|
Chris@102
|
54 BOOST_STATIC_ASSERT_MSG(MinExponent <= 0, "Template parameter MinExponent can not be positive!");
|
Chris@102
|
55 BOOST_STATIC_ASSERT_MSG(MaxExponent >= 0, "Template parameter MaxExponent can not be negative!");
|
Chris@102
|
56
|
Chris@102
|
57 static const exponent_type max_exponent = MaxExponent == 0 ? max_exponent_limit : MaxExponent;
|
Chris@102
|
58 static const exponent_type min_exponent = MinExponent == 0 ? min_exponent_limit : MinExponent;
|
Chris@102
|
59
|
Chris@102
|
60 static const exponent_type exponent_zero = max_exponent + 1;
|
Chris@102
|
61 static const exponent_type exponent_infinity = max_exponent + 2;
|
Chris@102
|
62 static const exponent_type exponent_nan = max_exponent + 3;
|
Chris@102
|
63
|
Chris@102
|
64 private:
|
Chris@102
|
65
|
Chris@102
|
66 rep_type m_data;
|
Chris@102
|
67 exponent_type m_exponent;
|
Chris@102
|
68 bool m_sign;
|
Chris@102
|
69 public:
|
Chris@102
|
70 cpp_bin_float() BOOST_NOEXCEPT_IF(noexcept(rep_type())) : m_data(), m_exponent(exponent_nan), m_sign(false) {}
|
Chris@102
|
71
|
Chris@102
|
72 cpp_bin_float(const cpp_bin_float &o) BOOST_NOEXCEPT_IF(noexcept(rep_type(std::declval<const rep_type&>())))
|
Chris@102
|
73 : m_data(o.m_data), m_exponent(o.m_exponent), m_sign(o.m_sign) {}
|
Chris@102
|
74
|
Chris@102
|
75 template <unsigned D, digit_base_type B, class A, class E, E MinE, E MaxE>
|
Chris@102
|
76 cpp_bin_float(const cpp_bin_float<D, B, A, E, MinE, MaxE> &o, typename boost::enable_if_c<(bit_count >= cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count)>::type const* = 0)
|
Chris@102
|
77 : m_exponent(o.exponent()), m_sign(o.sign())
|
Chris@102
|
78 {
|
Chris@102
|
79 typename cpp_bin_float<D, B, A, E, MinE, MaxE>::rep_type b(o.bits());
|
Chris@102
|
80 this->sign() = o.sign();
|
Chris@102
|
81 this->exponent() = o.exponent() + (int)bit_count - (int)cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count;
|
Chris@102
|
82 copy_and_round(*this, b);
|
Chris@102
|
83 }
|
Chris@102
|
84
|
Chris@102
|
85 template <unsigned D, digit_base_type B, class A, class E, E MinE, E MaxE>
|
Chris@102
|
86 explicit cpp_bin_float(const cpp_bin_float<D, B, A, E, MinE, MaxE> &o, typename boost::disable_if_c<(bit_count >= cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count)>::type const* = 0)
|
Chris@102
|
87 : m_exponent(o.exponent()), m_sign(o.sign())
|
Chris@102
|
88 {
|
Chris@102
|
89 typename cpp_bin_float<D, B, A, E, MinE, MaxE>::rep_type b(o.bits());
|
Chris@102
|
90 this->sign() = o.sign();
|
Chris@102
|
91 this->exponent() = o.exponent() - (int)(cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count - bit_count);
|
Chris@102
|
92 copy_and_round(*this, b);
|
Chris@102
|
93 }
|
Chris@102
|
94
|
Chris@102
|
95 template <class Float>
|
Chris@102
|
96 cpp_bin_float(const Float& f,
|
Chris@102
|
97 typename boost::enable_if_c<
|
Chris@102
|
98 (number_category<Float>::value == number_kind_floating_point)
|
Chris@102
|
99 && (std::numeric_limits<Float>::digits <= (int)bit_count)
|
Chris@102
|
100 && (std::numeric_limits<Float>::radix == 2)
|
Chris@102
|
101 >::type const* = 0)
|
Chris@102
|
102 : m_data(), m_exponent(0), m_sign(false)
|
Chris@102
|
103 {
|
Chris@102
|
104 this->assign_float(f);
|
Chris@102
|
105 }
|
Chris@102
|
106
|
Chris@102
|
107 cpp_bin_float& operator=(const cpp_bin_float &o) BOOST_NOEXCEPT_IF(noexcept(std::declval<rep_type&>() = std::declval<const rep_type&>()))
|
Chris@102
|
108 {
|
Chris@102
|
109 m_data = o.m_data;
|
Chris@102
|
110 m_exponent = o.m_exponent;
|
Chris@102
|
111 m_sign = o.m_sign;
|
Chris@102
|
112 return *this;
|
Chris@102
|
113 }
|
Chris@102
|
114
|
Chris@102
|
115 template <unsigned D, digit_base_type B, class A, class E, E MinE, E MaxE>
|
Chris@102
|
116 cpp_bin_float& operator=(const cpp_bin_float<D, B, A, E, MinE, MaxE> &o)
|
Chris@102
|
117 {
|
Chris@102
|
118 typename cpp_bin_float<D, B, A, E, MinE, MaxE>::rep_type b(o.bits());
|
Chris@102
|
119 this->exponent() = o.exponent() + (int)bit_count - (int)cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count;
|
Chris@102
|
120 this->sign() = o.sign();
|
Chris@102
|
121 copy_and_round(*this, b);
|
Chris@102
|
122 return *this;
|
Chris@102
|
123 }
|
Chris@102
|
124
|
Chris@102
|
125 template <class Float>
|
Chris@102
|
126 typename boost::enable_if_c<
|
Chris@102
|
127 (number_category<Float>::value == number_kind_floating_point)
|
Chris@102
|
128 && (std::numeric_limits<Float>::digits <= (int)bit_count)
|
Chris@102
|
129 && (std::numeric_limits<Float>::radix == 2), cpp_bin_float&>::type operator=(const Float& f)
|
Chris@102
|
130 {
|
Chris@102
|
131 return assign_float(f);
|
Chris@102
|
132 }
|
Chris@102
|
133
|
Chris@102
|
134 template <class Float>
|
Chris@102
|
135 typename boost::enable_if_c<is_floating_point<Float>::value, cpp_bin_float&>::type assign_float(Float f)
|
Chris@102
|
136 {
|
Chris@102
|
137 BOOST_MATH_STD_USING
|
Chris@102
|
138 using default_ops::eval_add;
|
Chris@102
|
139 typedef typename boost::multiprecision::detail::canonical<int, cpp_bin_float>::type bf_int_type;
|
Chris@102
|
140
|
Chris@102
|
141 switch((boost::math::fpclassify)(f))
|
Chris@102
|
142 {
|
Chris@102
|
143 case FP_ZERO:
|
Chris@102
|
144 m_data = limb_type(0);
|
Chris@102
|
145 m_sign = false;
|
Chris@102
|
146 m_exponent = exponent_zero;
|
Chris@102
|
147 return *this;
|
Chris@102
|
148 case FP_NAN:
|
Chris@102
|
149 m_data = limb_type(0);
|
Chris@102
|
150 m_sign = false;
|
Chris@102
|
151 m_exponent = exponent_nan;
|
Chris@102
|
152 return *this;
|
Chris@102
|
153 case FP_INFINITE:
|
Chris@102
|
154 m_data = limb_type(0);
|
Chris@102
|
155 m_sign = false;
|
Chris@102
|
156 m_exponent = exponent_infinity;
|
Chris@102
|
157 return *this;
|
Chris@102
|
158 }
|
Chris@102
|
159 if(f < 0)
|
Chris@102
|
160 {
|
Chris@102
|
161 *this = -f;
|
Chris@102
|
162 this->negate();
|
Chris@102
|
163 return *this;
|
Chris@102
|
164 }
|
Chris@102
|
165
|
Chris@102
|
166 typedef typename mpl::front<unsigned_types>::type ui_type;
|
Chris@102
|
167 m_data = static_cast<ui_type>(0u);
|
Chris@102
|
168 m_sign = false;
|
Chris@102
|
169 m_exponent = 0;
|
Chris@102
|
170
|
Chris@102
|
171 static const int bits = sizeof(int) * CHAR_BIT - 1;
|
Chris@102
|
172 int e;
|
Chris@102
|
173 f = frexp(f, &e);
|
Chris@102
|
174 while(f)
|
Chris@102
|
175 {
|
Chris@102
|
176 f = ldexp(f, bits);
|
Chris@102
|
177 e -= bits;
|
Chris@102
|
178 #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
|
Chris@102
|
179 int ipart = itrunc(f);
|
Chris@102
|
180 #else
|
Chris@102
|
181 int ipart = static_cast<int>(f);
|
Chris@102
|
182 #endif
|
Chris@102
|
183 f -= ipart;
|
Chris@102
|
184 m_exponent += bits;
|
Chris@102
|
185 cpp_bin_float t;
|
Chris@102
|
186 t = static_cast<bf_int_type>(ipart);
|
Chris@102
|
187 eval_add(*this, t);
|
Chris@102
|
188 }
|
Chris@102
|
189 m_exponent += static_cast<Exponent>(e);
|
Chris@102
|
190 return *this;
|
Chris@102
|
191 }
|
Chris@102
|
192
|
Chris@102
|
193 template <class Float>
|
Chris@102
|
194 typename boost::enable_if_c<
|
Chris@102
|
195 (number_category<Float>::value == number_kind_floating_point)
|
Chris@102
|
196 && !is_floating_point<Float>::value
|
Chris@102
|
197 /*&& (std::numeric_limits<number<Float> >::radix == 2)*/,
|
Chris@102
|
198 cpp_bin_float&>::type assign_float(Float f)
|
Chris@102
|
199 {
|
Chris@102
|
200 BOOST_MATH_STD_USING
|
Chris@102
|
201 using default_ops::eval_add;
|
Chris@102
|
202 using default_ops::eval_get_sign;
|
Chris@102
|
203 using default_ops::eval_convert_to;
|
Chris@102
|
204 using default_ops::eval_subtract;
|
Chris@102
|
205
|
Chris@102
|
206 typedef typename boost::multiprecision::detail::canonical<int, Float>::type f_int_type;
|
Chris@102
|
207 typedef typename boost::multiprecision::detail::canonical<int, cpp_bin_float>::type bf_int_type;
|
Chris@102
|
208
|
Chris@102
|
209 switch(eval_fpclassify(f))
|
Chris@102
|
210 {
|
Chris@102
|
211 case FP_ZERO:
|
Chris@102
|
212 m_data = limb_type(0);
|
Chris@102
|
213 m_sign = false;
|
Chris@102
|
214 m_exponent = exponent_zero;
|
Chris@102
|
215 return *this;
|
Chris@102
|
216 case FP_NAN:
|
Chris@102
|
217 m_data = limb_type(0);
|
Chris@102
|
218 m_sign = false;
|
Chris@102
|
219 m_exponent = exponent_nan;
|
Chris@102
|
220 return *this;
|
Chris@102
|
221 case FP_INFINITE:
|
Chris@102
|
222 m_data = limb_type(0);
|
Chris@102
|
223 m_sign = false;
|
Chris@102
|
224 m_exponent = exponent_infinity;
|
Chris@102
|
225 return *this;
|
Chris@102
|
226 }
|
Chris@102
|
227 if(eval_get_sign(f) < 0)
|
Chris@102
|
228 {
|
Chris@102
|
229 f.negate();
|
Chris@102
|
230 *this = f;
|
Chris@102
|
231 this->negate();
|
Chris@102
|
232 return *this;
|
Chris@102
|
233 }
|
Chris@102
|
234
|
Chris@102
|
235 typedef typename mpl::front<unsigned_types>::type ui_type;
|
Chris@102
|
236 m_data = static_cast<ui_type>(0u);
|
Chris@102
|
237 m_sign = false;
|
Chris@102
|
238 m_exponent = 0;
|
Chris@102
|
239
|
Chris@102
|
240 static const int bits = sizeof(int) * CHAR_BIT - 1;
|
Chris@102
|
241 int e;
|
Chris@102
|
242 eval_frexp(f, f, &e);
|
Chris@102
|
243 while(eval_get_sign(f) != 0)
|
Chris@102
|
244 {
|
Chris@102
|
245 eval_ldexp(f, f, bits);
|
Chris@102
|
246 e -= bits;
|
Chris@102
|
247 int ipart;
|
Chris@102
|
248 eval_convert_to(&ipart, f);
|
Chris@102
|
249 eval_subtract(f, static_cast<f_int_type>(ipart));
|
Chris@102
|
250 m_exponent += bits;
|
Chris@102
|
251 eval_add(*this, static_cast<bf_int_type>(ipart));
|
Chris@102
|
252 }
|
Chris@102
|
253 m_exponent += e;
|
Chris@102
|
254 if(m_exponent > max_exponent)
|
Chris@102
|
255 m_exponent = exponent_infinity;
|
Chris@102
|
256 if(m_exponent < min_exponent)
|
Chris@102
|
257 {
|
Chris@102
|
258 m_data = limb_type(0u);
|
Chris@102
|
259 m_exponent = exponent_zero;
|
Chris@102
|
260 m_sign = false;
|
Chris@102
|
261 }
|
Chris@102
|
262 else if(eval_get_sign(m_data) == 0)
|
Chris@102
|
263 {
|
Chris@102
|
264 m_exponent = exponent_zero;
|
Chris@102
|
265 m_sign = false;
|
Chris@102
|
266 }
|
Chris@102
|
267 return *this;
|
Chris@102
|
268 }
|
Chris@102
|
269
|
Chris@102
|
270 template <class I>
|
Chris@102
|
271 typename boost::enable_if<is_integral<I>, cpp_bin_float&>::type operator=(const I& i)
|
Chris@102
|
272 {
|
Chris@102
|
273 using default_ops::eval_bit_test;
|
Chris@102
|
274 if(!i)
|
Chris@102
|
275 {
|
Chris@102
|
276 m_data = static_cast<limb_type>(0);
|
Chris@102
|
277 m_exponent = exponent_zero;
|
Chris@102
|
278 m_sign = false;
|
Chris@102
|
279 }
|
Chris@102
|
280 else
|
Chris@102
|
281 {
|
Chris@102
|
282 typedef typename make_unsigned<I>::type ui_type;
|
Chris@102
|
283 ui_type fi = static_cast<ui_type>(boost::multiprecision::detail::unsigned_abs(i));
|
Chris@102
|
284 typedef typename boost::multiprecision::detail::canonical<ui_type, rep_type>::type ar_type;
|
Chris@102
|
285 m_data = static_cast<ar_type>(fi);
|
Chris@102
|
286 unsigned shift = msb(fi);
|
Chris@102
|
287 if(shift >= bit_count)
|
Chris@102
|
288 {
|
Chris@102
|
289 m_exponent = static_cast<Exponent>(shift);
|
Chris@102
|
290 m_data = static_cast<ar_type>(fi >> (shift + 1 - bit_count));
|
Chris@102
|
291 }
|
Chris@102
|
292 else
|
Chris@102
|
293 {
|
Chris@102
|
294 m_exponent = static_cast<Exponent>(shift);
|
Chris@102
|
295 eval_left_shift(m_data, bit_count - shift - 1);
|
Chris@102
|
296 }
|
Chris@102
|
297 BOOST_ASSERT(eval_bit_test(m_data, bit_count-1));
|
Chris@102
|
298 m_sign = detail::is_negative(i);
|
Chris@102
|
299 }
|
Chris@102
|
300 return *this;
|
Chris@102
|
301 }
|
Chris@102
|
302
|
Chris@102
|
303 cpp_bin_float& operator=(const char *s);
|
Chris@102
|
304
|
Chris@102
|
305 void swap(cpp_bin_float &o) BOOST_NOEXCEPT
|
Chris@102
|
306 {
|
Chris@102
|
307 m_data.swap(o.m_data);
|
Chris@102
|
308 std::swap(m_exponent, o.m_exponent);
|
Chris@102
|
309 std::swap(m_sign, o.m_sign);
|
Chris@102
|
310 }
|
Chris@102
|
311
|
Chris@102
|
312 std::string str(std::streamsize dig, std::ios_base::fmtflags f) const;
|
Chris@102
|
313
|
Chris@102
|
314 void negate()
|
Chris@102
|
315 {
|
Chris@102
|
316 if((m_exponent != exponent_zero) && (m_exponent != exponent_nan))
|
Chris@102
|
317 m_sign = !m_sign;
|
Chris@102
|
318 }
|
Chris@102
|
319
|
Chris@102
|
320 int compare(const cpp_bin_float &o) const BOOST_NOEXCEPT
|
Chris@102
|
321 {
|
Chris@102
|
322 if(m_sign != o.m_sign)
|
Chris@102
|
323 return m_sign ? -1 : 1;
|
Chris@102
|
324 int result;
|
Chris@102
|
325 if(m_exponent == exponent_nan)
|
Chris@102
|
326 return -1;
|
Chris@102
|
327 else if(m_exponent != o.m_exponent)
|
Chris@102
|
328 {
|
Chris@102
|
329 if(m_exponent == exponent_zero)
|
Chris@102
|
330 result = -1;
|
Chris@102
|
331 else if(o.m_exponent == exponent_zero)
|
Chris@102
|
332 result = 1;
|
Chris@102
|
333 else
|
Chris@102
|
334 result = m_exponent > o.m_exponent ? 1 : -1;
|
Chris@102
|
335 }
|
Chris@102
|
336 else
|
Chris@102
|
337 result = m_data.compare(o.m_data);
|
Chris@102
|
338 if(m_sign)
|
Chris@102
|
339 result = -result;
|
Chris@102
|
340 return result;
|
Chris@102
|
341 }
|
Chris@102
|
342 template <class A>
|
Chris@102
|
343 int compare(const A& o) const BOOST_NOEXCEPT
|
Chris@102
|
344 {
|
Chris@102
|
345 cpp_bin_float b;
|
Chris@102
|
346 b = o;
|
Chris@102
|
347 return compare(b);
|
Chris@102
|
348 }
|
Chris@102
|
349
|
Chris@102
|
350 rep_type& bits() { return m_data; }
|
Chris@102
|
351 const rep_type& bits()const { return m_data; }
|
Chris@102
|
352 exponent_type& exponent() { return m_exponent; }
|
Chris@102
|
353 const exponent_type& exponent()const { return m_exponent; }
|
Chris@102
|
354 bool& sign() { return m_sign; }
|
Chris@102
|
355 const bool& sign()const { return m_sign; }
|
Chris@102
|
356 void check_invariants()
|
Chris@102
|
357 {
|
Chris@102
|
358 using default_ops::eval_bit_test;
|
Chris@102
|
359 using default_ops::eval_is_zero;
|
Chris@102
|
360 if((m_exponent <= max_exponent) && (m_exponent >= min_exponent))
|
Chris@102
|
361 {
|
Chris@102
|
362 BOOST_ASSERT(eval_bit_test(m_data, bit_count - 1));
|
Chris@102
|
363 }
|
Chris@102
|
364 else
|
Chris@102
|
365 {
|
Chris@102
|
366 BOOST_ASSERT(m_exponent > max_exponent);
|
Chris@102
|
367 BOOST_ASSERT(m_exponent <= exponent_nan);
|
Chris@102
|
368 BOOST_ASSERT(eval_is_zero(m_data));
|
Chris@102
|
369 }
|
Chris@102
|
370 }
|
Chris@102
|
371 template<class Archive>
|
Chris@102
|
372 void serialize(Archive & ar, const unsigned int /*version*/)
|
Chris@102
|
373 {
|
Chris@102
|
374 ar & m_data;
|
Chris@102
|
375 ar & m_exponent;
|
Chris@102
|
376 ar & m_sign;
|
Chris@102
|
377 }
|
Chris@102
|
378 };
|
Chris@102
|
379
|
Chris@102
|
380 #ifdef BOOST_MSVC
|
Chris@102
|
381 #pragma warning(pop)
|
Chris@102
|
382 #endif
|
Chris@102
|
383
|
Chris@102
|
384 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class Int>
|
Chris@102
|
385 inline void copy_and_round(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, Int &arg)
|
Chris@102
|
386 {
|
Chris@102
|
387 // Precondition: exponent of res must have been set before this function is called
|
Chris@102
|
388 // as we may need to adjust it based on how many cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count in arg are set.
|
Chris@102
|
389 using default_ops::eval_msb;
|
Chris@102
|
390 using default_ops::eval_lsb;
|
Chris@102
|
391 using default_ops::eval_left_shift;
|
Chris@102
|
392 using default_ops::eval_bit_test;
|
Chris@102
|
393 using default_ops::eval_right_shift;
|
Chris@102
|
394 using default_ops::eval_increment;
|
Chris@102
|
395 using default_ops::eval_get_sign;
|
Chris@102
|
396
|
Chris@102
|
397 // cancellation may have resulted in arg being all zeros:
|
Chris@102
|
398 if(eval_get_sign(arg) == 0)
|
Chris@102
|
399 {
|
Chris@102
|
400 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
|
Chris@102
|
401 res.sign() = false;
|
Chris@102
|
402 res.bits() = static_cast<limb_type>(0u);
|
Chris@102
|
403 return;
|
Chris@102
|
404 }
|
Chris@102
|
405 int msb = eval_msb(arg);
|
Chris@102
|
406 if(static_cast<int>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) > msb + 1)
|
Chris@102
|
407 {
|
Chris@102
|
408 // Must have had cancellation in subtraction, shift left and copy:
|
Chris@102
|
409 res.bits() = arg;
|
Chris@102
|
410 eval_left_shift(res.bits(), cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - msb - 1);
|
Chris@102
|
411 res.exponent() -= static_cast<Exponent>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - msb - 1);
|
Chris@102
|
412 }
|
Chris@102
|
413 else if(static_cast<int>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) < msb + 1)
|
Chris@102
|
414 {
|
Chris@102
|
415 // We have more cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count than we need, so round as required,
|
Chris@102
|
416 // first get the rounding bit:
|
Chris@102
|
417 bool roundup = eval_bit_test(arg, msb - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count);
|
Chris@102
|
418 // Then check for a tie:
|
Chris@102
|
419 if(roundup && (msb - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count == eval_lsb(arg)))
|
Chris@102
|
420 {
|
Chris@102
|
421 // Ties round towards even:
|
Chris@102
|
422 if(!eval_bit_test(arg, msb - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 1))
|
Chris@102
|
423 roundup = false;
|
Chris@102
|
424 }
|
Chris@102
|
425 // Shift off the cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count we don't need:
|
Chris@102
|
426 eval_right_shift(arg, msb - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 1);
|
Chris@102
|
427 res.exponent() += static_cast<Exponent>(msb - (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 1);
|
Chris@102
|
428 if(roundup)
|
Chris@102
|
429 {
|
Chris@102
|
430 eval_increment(arg);
|
Chris@102
|
431 if(eval_bit_test(arg, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count))
|
Chris@102
|
432 {
|
Chris@102
|
433 // This happens very very rairly:
|
Chris@102
|
434 eval_right_shift(arg, 1u);
|
Chris@102
|
435 ++res.exponent();
|
Chris@102
|
436 }
|
Chris@102
|
437 }
|
Chris@102
|
438 res.bits() = arg;
|
Chris@102
|
439 }
|
Chris@102
|
440 else
|
Chris@102
|
441 {
|
Chris@102
|
442 res.bits() = arg;
|
Chris@102
|
443 }
|
Chris@102
|
444 BOOST_ASSERT((eval_msb(res.bits()) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1));
|
Chris@102
|
445
|
Chris@102
|
446 if(res.exponent() > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
|
Chris@102
|
447 {
|
Chris@102
|
448 // Overflow:
|
Chris@102
|
449 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
|
Chris@102
|
450 res.bits() = static_cast<limb_type>(0u);
|
Chris@102
|
451 }
|
Chris@102
|
452 else if(res.exponent() < cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent)
|
Chris@102
|
453 {
|
Chris@102
|
454 // Underflow:
|
Chris@102
|
455 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
|
Chris@102
|
456 res.bits() = static_cast<limb_type>(0u);
|
Chris@102
|
457 res.sign() = false;
|
Chris@102
|
458 }
|
Chris@102
|
459 }
|
Chris@102
|
460
|
Chris@102
|
461 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
Chris@102
|
462 inline void do_eval_add(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &b)
|
Chris@102
|
463 {
|
Chris@102
|
464 using default_ops::eval_add;
|
Chris@102
|
465 using default_ops::eval_bit_test;
|
Chris@102
|
466
|
Chris@102
|
467 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type dt;
|
Chris@102
|
468
|
Chris@102
|
469 // Special cases first:
|
Chris@102
|
470 switch(a.exponent())
|
Chris@102
|
471 {
|
Chris@102
|
472 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
Chris@102
|
473 res = b;
|
Chris@102
|
474 if(res.sign())
|
Chris@102
|
475 res.negate();
|
Chris@102
|
476 return;
|
Chris@102
|
477 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
Chris@102
|
478 if(b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan)
|
Chris@102
|
479 res = b;
|
Chris@102
|
480 else
|
Chris@102
|
481 res = a;
|
Chris@102
|
482 return; // result is still infinite.
|
Chris@102
|
483 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
Chris@102
|
484 res = a;
|
Chris@102
|
485 return; // result is still a NaN.
|
Chris@102
|
486 }
|
Chris@102
|
487 switch(b.exponent())
|
Chris@102
|
488 {
|
Chris@102
|
489 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
Chris@102
|
490 res = a;
|
Chris@102
|
491 return;
|
Chris@102
|
492 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
Chris@102
|
493 res = b;
|
Chris@102
|
494 if(res.sign())
|
Chris@102
|
495 res.negate();
|
Chris@102
|
496 return; // result is infinite.
|
Chris@102
|
497 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
Chris@102
|
498 res = b;
|
Chris@102
|
499 return; // result is a NaN.
|
Chris@102
|
500 }
|
Chris@102
|
501
|
Chris@102
|
502 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type e_diff = a.exponent() - b.exponent();
|
Chris@102
|
503 bool s = a.sign();
|
Chris@102
|
504 if(e_diff >= 0)
|
Chris@102
|
505 {
|
Chris@102
|
506 dt = a.bits();
|
Chris@102
|
507 if(e_diff < (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
|
Chris@102
|
508 {
|
Chris@102
|
509 eval_left_shift(dt, e_diff);
|
Chris@102
|
510 res.exponent() = a.exponent() - e_diff;
|
Chris@102
|
511 eval_add(dt, b.bits());
|
Chris@102
|
512 }
|
Chris@102
|
513 else
|
Chris@102
|
514 res.exponent() = a.exponent();
|
Chris@102
|
515 }
|
Chris@102
|
516 else
|
Chris@102
|
517 {
|
Chris@102
|
518 dt= b.bits();
|
Chris@102
|
519 if(-e_diff < (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
|
Chris@102
|
520 {
|
Chris@102
|
521 eval_left_shift(dt, -e_diff);
|
Chris@102
|
522 res.exponent() = b.exponent() + e_diff;
|
Chris@102
|
523 eval_add(dt, a.bits());
|
Chris@102
|
524 }
|
Chris@102
|
525 else
|
Chris@102
|
526 res.exponent() = b.exponent();
|
Chris@102
|
527 }
|
Chris@102
|
528
|
Chris@102
|
529 copy_and_round(res, dt);
|
Chris@102
|
530 res.check_invariants();
|
Chris@102
|
531 if(res.sign() != s)
|
Chris@102
|
532 res.negate();
|
Chris@102
|
533 }
|
Chris@102
|
534
|
Chris@102
|
535 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
Chris@102
|
536 inline void do_eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &b)
|
Chris@102
|
537 {
|
Chris@102
|
538 using default_ops::eval_subtract;
|
Chris@102
|
539 using default_ops::eval_bit_test;
|
Chris@102
|
540
|
Chris@102
|
541 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type dt;
|
Chris@102
|
542
|
Chris@102
|
543 // Special cases first:
|
Chris@102
|
544 switch(a.exponent())
|
Chris@102
|
545 {
|
Chris@102
|
546 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
Chris@102
|
547 if(b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan)
|
Chris@102
|
548 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
|
Chris@102
|
549 else
|
Chris@102
|
550 {
|
Chris@102
|
551 res = b;
|
Chris@102
|
552 if(!res.sign())
|
Chris@102
|
553 res.negate();
|
Chris@102
|
554 }
|
Chris@102
|
555 return;
|
Chris@102
|
556 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
Chris@102
|
557 if((b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan) || (b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity))
|
Chris@102
|
558 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
|
Chris@102
|
559 else
|
Chris@102
|
560 res = a;
|
Chris@102
|
561 return;
|
Chris@102
|
562 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
Chris@102
|
563 res = a;
|
Chris@102
|
564 return; // result is still a NaN.
|
Chris@102
|
565 }
|
Chris@102
|
566 switch(b.exponent())
|
Chris@102
|
567 {
|
Chris@102
|
568 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
Chris@102
|
569 res = a;
|
Chris@102
|
570 return;
|
Chris@102
|
571 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
Chris@102
|
572 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan;
|
Chris@102
|
573 res.sign() = false;
|
Chris@102
|
574 res.bits() = static_cast<limb_type>(0u);
|
Chris@102
|
575 return; // result is a NaN.
|
Chris@102
|
576 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
Chris@102
|
577 res = b;
|
Chris@102
|
578 return; // result is still a NaN.
|
Chris@102
|
579 }
|
Chris@102
|
580
|
Chris@102
|
581 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type e_diff = a.exponent() - b.exponent();
|
Chris@102
|
582 bool s = a.sign();
|
Chris@102
|
583 if((e_diff > 0) || ((e_diff == 0) && a.bits().compare(b.bits()) >= 0))
|
Chris@102
|
584 {
|
Chris@102
|
585 dt = a.bits();
|
Chris@102
|
586 if(e_diff < (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
|
Chris@102
|
587 {
|
Chris@102
|
588 eval_left_shift(dt, e_diff);
|
Chris@102
|
589 res.exponent() = a.exponent() - e_diff;
|
Chris@102
|
590 eval_subtract(dt, b.bits());
|
Chris@102
|
591 }
|
Chris@102
|
592 else
|
Chris@102
|
593 res.exponent() = a.exponent();
|
Chris@102
|
594 }
|
Chris@102
|
595 else
|
Chris@102
|
596 {
|
Chris@102
|
597 dt = b.bits();
|
Chris@102
|
598 if(-e_diff < (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
|
Chris@102
|
599 {
|
Chris@102
|
600 eval_left_shift(dt, -e_diff);
|
Chris@102
|
601 res.exponent() = b.exponent() + e_diff;
|
Chris@102
|
602 eval_subtract(dt, a.bits());
|
Chris@102
|
603 }
|
Chris@102
|
604 else
|
Chris@102
|
605 res.exponent() = b.exponent();
|
Chris@102
|
606 s = !s;
|
Chris@102
|
607 }
|
Chris@102
|
608
|
Chris@102
|
609 copy_and_round(res, dt);
|
Chris@102
|
610 if(res.sign() != s)
|
Chris@102
|
611 res.negate();
|
Chris@102
|
612 res.check_invariants();
|
Chris@102
|
613 }
|
Chris@102
|
614
|
Chris@102
|
615 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
Chris@102
|
616 inline void eval_add(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &b)
|
Chris@102
|
617 {
|
Chris@102
|
618 if(a.sign() == b.sign())
|
Chris@102
|
619 do_eval_add(res, a, b);
|
Chris@102
|
620 else
|
Chris@102
|
621 do_eval_subtract(res, a, b);
|
Chris@102
|
622 }
|
Chris@102
|
623
|
Chris@102
|
624 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
Chris@102
|
625 inline void eval_add(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a)
|
Chris@102
|
626 {
|
Chris@102
|
627 return eval_add(res, res, a);
|
Chris@102
|
628 }
|
Chris@102
|
629
|
Chris@102
|
630 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
Chris@102
|
631 inline void eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &b)
|
Chris@102
|
632 {
|
Chris@102
|
633 if(a.sign() != b.sign())
|
Chris@102
|
634 do_eval_add(res, a, b);
|
Chris@102
|
635 else
|
Chris@102
|
636 do_eval_subtract(res, a, b);
|
Chris@102
|
637 }
|
Chris@102
|
638
|
Chris@102
|
639 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
Chris@102
|
640 inline void eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a)
|
Chris@102
|
641 {
|
Chris@102
|
642 return eval_subtract(res, res, a);
|
Chris@102
|
643 }
|
Chris@102
|
644
|
Chris@102
|
645 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
Chris@102
|
646 inline void eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &b)
|
Chris@102
|
647 {
|
Chris@102
|
648 using default_ops::eval_bit_test;
|
Chris@102
|
649 using default_ops::eval_multiply;
|
Chris@102
|
650
|
Chris@102
|
651 // Special cases first:
|
Chris@102
|
652 switch(a.exponent())
|
Chris@102
|
653 {
|
Chris@102
|
654 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
Chris@102
|
655 if(b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan)
|
Chris@102
|
656 res = b;
|
Chris@102
|
657 else
|
Chris@102
|
658 res = a;
|
Chris@102
|
659 return;
|
Chris@102
|
660 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
Chris@102
|
661 switch(b.exponent())
|
Chris@102
|
662 {
|
Chris@102
|
663 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
Chris@102
|
664 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
|
Chris@102
|
665 break;
|
Chris@102
|
666 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
Chris@102
|
667 res = b;
|
Chris@102
|
668 break;
|
Chris@102
|
669 default:
|
Chris@102
|
670 res = a;
|
Chris@102
|
671 break;
|
Chris@102
|
672 }
|
Chris@102
|
673 return;
|
Chris@102
|
674 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
Chris@102
|
675 res = a;
|
Chris@102
|
676 return;
|
Chris@102
|
677 }
|
Chris@102
|
678 if(b.exponent() > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
|
Chris@102
|
679 {
|
Chris@102
|
680 res = b;
|
Chris@102
|
681 return;
|
Chris@102
|
682 }
|
Chris@102
|
683 if((a.exponent() > 0) && (b.exponent() > 0))
|
Chris@102
|
684 {
|
Chris@102
|
685 if(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent + 2 - a.exponent() < b.exponent())
|
Chris@102
|
686 {
|
Chris@102
|
687 // We will certainly overflow:
|
Chris@102
|
688 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
|
Chris@102
|
689 res.sign() = a.sign() != b.sign();
|
Chris@102
|
690 res.bits() = static_cast<limb_type>(0u);
|
Chris@102
|
691 return;
|
Chris@102
|
692 }
|
Chris@102
|
693 }
|
Chris@102
|
694 if((a.exponent() < 0) && (b.exponent() < 0))
|
Chris@102
|
695 {
|
Chris@102
|
696 if(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent - 2 - a.exponent() > b.exponent())
|
Chris@102
|
697 {
|
Chris@102
|
698 // We will certainly underflow:
|
Chris@102
|
699 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
|
Chris@102
|
700 res.sign() = false;
|
Chris@102
|
701 res.bits() = static_cast<limb_type>(0u);
|
Chris@102
|
702 return;
|
Chris@102
|
703 }
|
Chris@102
|
704 }
|
Chris@102
|
705
|
Chris@102
|
706 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type dt;
|
Chris@102
|
707 eval_multiply(dt, a.bits(), b.bits());
|
Chris@102
|
708 res.exponent() = a.exponent() + b.exponent() - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 1;
|
Chris@102
|
709 copy_and_round(res, dt);
|
Chris@102
|
710 res.check_invariants();
|
Chris@102
|
711 res.sign() = a.sign() != b.sign();
|
Chris@102
|
712 }
|
Chris@102
|
713
|
Chris@102
|
714 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
Chris@102
|
715 inline void eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a)
|
Chris@102
|
716 {
|
Chris@102
|
717 eval_multiply(res, res, a);
|
Chris@102
|
718 }
|
Chris@102
|
719
|
Chris@102
|
720 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class U>
|
Chris@102
|
721 inline typename enable_if_c<is_unsigned<U>::value>::type eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const U &b)
|
Chris@102
|
722 {
|
Chris@102
|
723 using default_ops::eval_bit_test;
|
Chris@102
|
724 using default_ops::eval_multiply;
|
Chris@102
|
725
|
Chris@102
|
726 // Special cases first:
|
Chris@102
|
727 switch(a.exponent())
|
Chris@102
|
728 {
|
Chris@102
|
729 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
Chris@102
|
730 res = a;
|
Chris@102
|
731 return;
|
Chris@102
|
732 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
Chris@102
|
733 if(b == 0)
|
Chris@102
|
734 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
|
Chris@102
|
735 else
|
Chris@102
|
736 res = a;
|
Chris@102
|
737 return;
|
Chris@102
|
738 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
Chris@102
|
739 res = a;
|
Chris@102
|
740 return;
|
Chris@102
|
741 }
|
Chris@102
|
742
|
Chris@102
|
743 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type dt;
|
Chris@102
|
744 typedef typename boost::multiprecision::detail::canonical<U, typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type>::type canon_ui_type;
|
Chris@102
|
745 eval_multiply(dt, a.bits(), static_cast<canon_ui_type>(b));
|
Chris@102
|
746 res.exponent() = a.exponent();
|
Chris@102
|
747 copy_and_round(res, dt);
|
Chris@102
|
748 res.check_invariants();
|
Chris@102
|
749 res.sign() = a.sign();
|
Chris@102
|
750 }
|
Chris@102
|
751
|
Chris@102
|
752 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class U>
|
Chris@102
|
753 inline typename enable_if_c<is_unsigned<U>::value>::type eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const U &b)
|
Chris@102
|
754 {
|
Chris@102
|
755 eval_multiply(res, res, b);
|
Chris@102
|
756 }
|
Chris@102
|
757
|
Chris@102
|
758 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class S>
|
Chris@102
|
759 inline typename enable_if_c<is_signed<S>::value>::type eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const S &b)
|
Chris@102
|
760 {
|
Chris@102
|
761 typedef typename make_unsigned<S>::type ui_type;
|
Chris@102
|
762 eval_multiply(res, a, static_cast<ui_type>(boost::multiprecision::detail::unsigned_abs(b)));
|
Chris@102
|
763 if(b < 0)
|
Chris@102
|
764 res.negate();
|
Chris@102
|
765 }
|
Chris@102
|
766
|
Chris@102
|
767 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class S>
|
Chris@102
|
768 inline typename enable_if_c<is_signed<S>::value>::type eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const S &b)
|
Chris@102
|
769 {
|
Chris@102
|
770 eval_multiply(res, res, b);
|
Chris@102
|
771 }
|
Chris@102
|
772
|
Chris@102
|
773 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
Chris@102
|
774 inline void eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &u, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &v)
|
Chris@102
|
775 {
|
Chris@102
|
776 using default_ops::eval_subtract;
|
Chris@102
|
777 using default_ops::eval_qr;
|
Chris@102
|
778 using default_ops::eval_bit_test;
|
Chris@102
|
779 using default_ops::eval_get_sign;
|
Chris@102
|
780 using default_ops::eval_increment;
|
Chris@102
|
781
|
Chris@102
|
782 //
|
Chris@102
|
783 // Special cases first:
|
Chris@102
|
784 //
|
Chris@102
|
785 switch(u.exponent())
|
Chris@102
|
786 {
|
Chris@102
|
787 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
Chris@102
|
788 switch(v.exponent())
|
Chris@102
|
789 {
|
Chris@102
|
790 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
Chris@102
|
791 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
Chris@102
|
792 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
|
Chris@102
|
793 return;
|
Chris@102
|
794 }
|
Chris@102
|
795 res = u;
|
Chris@102
|
796 return;
|
Chris@102
|
797 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
Chris@102
|
798 switch(v.exponent())
|
Chris@102
|
799 {
|
Chris@102
|
800 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
Chris@102
|
801 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
Chris@102
|
802 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
|
Chris@102
|
803 return;
|
Chris@102
|
804 }
|
Chris@102
|
805 res = u;
|
Chris@102
|
806 return;
|
Chris@102
|
807 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
Chris@102
|
808 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
|
Chris@102
|
809 return;
|
Chris@102
|
810 }
|
Chris@102
|
811 switch(v.exponent())
|
Chris@102
|
812 {
|
Chris@102
|
813 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
Chris@102
|
814 {
|
Chris@102
|
815 bool s = u.sign() != v.sign();
|
Chris@102
|
816 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
|
Chris@102
|
817 res.sign() = s;
|
Chris@102
|
818 return;
|
Chris@102
|
819 }
|
Chris@102
|
820 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
Chris@102
|
821 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
|
Chris@102
|
822 res.bits() = limb_type(0);
|
Chris@102
|
823 res.sign() = false;
|
Chris@102
|
824 return;
|
Chris@102
|
825 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
Chris@102
|
826 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
|
Chris@102
|
827 return;
|
Chris@102
|
828 }
|
Chris@102
|
829
|
Chris@102
|
830 // We can scale u and v so that both are integers, then perform integer
|
Chris@102
|
831 // division to obtain quotient q and remainder r, such that:
|
Chris@102
|
832 //
|
Chris@102
|
833 // q * v + r = u
|
Chris@102
|
834 //
|
Chris@102
|
835 // and hense:
|
Chris@102
|
836 //
|
Chris@102
|
837 // q + r/v = u/v
|
Chris@102
|
838 //
|
Chris@102
|
839 // From this, assuming q has cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count
|
Chris@102
|
840 // bits we only need to determine whether
|
Chris@102
|
841 // r/v is less than, equal to, or greater than 0.5 to determine rounding -
|
Chris@102
|
842 // this we can do with a shift and comparison.
|
Chris@102
|
843 //
|
Chris@102
|
844 // We can set the exponent and sign of the result up front:
|
Chris@102
|
845 //
|
Chris@102
|
846 res.exponent() = u.exponent() - v.exponent() - 1;
|
Chris@102
|
847 res.sign() = u.sign() != v.sign();
|
Chris@102
|
848 //
|
Chris@102
|
849 // Now get the quotient and remainder:
|
Chris@102
|
850 //
|
Chris@102
|
851 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type t(u.bits()), t2(v.bits()), q, r;
|
Chris@102
|
852 eval_left_shift(t, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count);
|
Chris@102
|
853 eval_qr(t, t2, q, r);
|
Chris@102
|
854 //
|
Chris@102
|
855 // We now have either "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count"
|
Chris@102
|
856 // or "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count+1" significant
|
Chris@102
|
857 // bits in q.
|
Chris@102
|
858 //
|
Chris@102
|
859 static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT;
|
Chris@102
|
860 if(eval_bit_test(q, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count))
|
Chris@102
|
861 {
|
Chris@102
|
862 //
|
Chris@102
|
863 // OK we have cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count+1 bits,
|
Chris@102
|
864 // so we already have rounding info,
|
Chris@102
|
865 // we just need to changes things if the last bit is 1 and either the
|
Chris@102
|
866 // remainder is non-zero (ie we do not have a tie) or the quotient would
|
Chris@102
|
867 // be odd if it were shifted to the correct number of bits (ie a tiebreak).
|
Chris@102
|
868 //
|
Chris@102
|
869 BOOST_ASSERT((eval_msb(q) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count));
|
Chris@102
|
870 if((q.limbs()[0] & 1u) && (eval_get_sign(r) || (q.limbs()[0] & 2u)))
|
Chris@102
|
871 {
|
Chris@102
|
872 eval_increment(q);
|
Chris@102
|
873 }
|
Chris@102
|
874 }
|
Chris@102
|
875 else
|
Chris@102
|
876 {
|
Chris@102
|
877 //
|
Chris@102
|
878 // We have exactly "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count" bits in q.
|
Chris@102
|
879 // Get rounding info, which we can get by comparing 2r with v.
|
Chris@102
|
880 // We want to call copy_and_round to handle rounding and general cleanup,
|
Chris@102
|
881 // so we'll left shift q and add some fake digits on the end to represent
|
Chris@102
|
882 // how we'll be rounding.
|
Chris@102
|
883 //
|
Chris@102
|
884 BOOST_ASSERT((eval_msb(q) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1));
|
Chris@102
|
885 static const unsigned lshift = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count < limb_bits ? 2 : limb_bits;
|
Chris@102
|
886 eval_left_shift(q, lshift);
|
Chris@102
|
887 res.exponent() -= lshift;
|
Chris@102
|
888 eval_left_shift(r, 1u);
|
Chris@102
|
889 int c = r.compare(v.bits());
|
Chris@102
|
890 if(c == 0)
|
Chris@102
|
891 q.limbs()[0] |= static_cast<limb_type>(1u) << (lshift - 1);
|
Chris@102
|
892 else if(c > 0)
|
Chris@102
|
893 q.limbs()[0] |= (static_cast<limb_type>(1u) << (lshift - 1)) + static_cast<limb_type>(1u);
|
Chris@102
|
894 }
|
Chris@102
|
895 copy_and_round(res, q);
|
Chris@102
|
896 }
|
Chris@102
|
897
|
Chris@102
|
898 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
Chris@102
|
899 inline void eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
|
Chris@102
|
900 {
|
Chris@102
|
901 eval_divide(res, res, arg);
|
Chris@102
|
902 }
|
Chris@102
|
903
|
Chris@102
|
904 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class U>
|
Chris@102
|
905 inline typename enable_if_c<is_unsigned<U>::value>::type eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &u, const U &v)
|
Chris@102
|
906 {
|
Chris@102
|
907 using default_ops::eval_subtract;
|
Chris@102
|
908 using default_ops::eval_qr;
|
Chris@102
|
909 using default_ops::eval_bit_test;
|
Chris@102
|
910 using default_ops::eval_get_sign;
|
Chris@102
|
911 using default_ops::eval_increment;
|
Chris@102
|
912
|
Chris@102
|
913 //
|
Chris@102
|
914 // Special cases first:
|
Chris@102
|
915 //
|
Chris@102
|
916 switch(u.exponent())
|
Chris@102
|
917 {
|
Chris@102
|
918 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
Chris@102
|
919 if(v == 0)
|
Chris@102
|
920 {
|
Chris@102
|
921 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
|
Chris@102
|
922 return;
|
Chris@102
|
923 }
|
Chris@102
|
924 res = u;
|
Chris@102
|
925 return;
|
Chris@102
|
926 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
Chris@102
|
927 res = u;
|
Chris@102
|
928 return;
|
Chris@102
|
929 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
Chris@102
|
930 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
|
Chris@102
|
931 return;
|
Chris@102
|
932 }
|
Chris@102
|
933 if(v == 0)
|
Chris@102
|
934 {
|
Chris@102
|
935 bool s = u.sign();
|
Chris@102
|
936 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
|
Chris@102
|
937 res.sign() = s;
|
Chris@102
|
938 return;
|
Chris@102
|
939 }
|
Chris@102
|
940
|
Chris@102
|
941 // We can scale u and v so that both are integers, then perform integer
|
Chris@102
|
942 // division to obtain quotient q and remainder r, such that:
|
Chris@102
|
943 //
|
Chris@102
|
944 // q * v + r = u
|
Chris@102
|
945 //
|
Chris@102
|
946 // and hense:
|
Chris@102
|
947 //
|
Chris@102
|
948 // q + r/v = u/v
|
Chris@102
|
949 //
|
Chris@102
|
950 // From this, assuming q has "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count" cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count, we only need to determine whether
|
Chris@102
|
951 // r/v is less than, equal to, or greater than 0.5 to determine rounding -
|
Chris@102
|
952 // this we can do with a shift and comparison.
|
Chris@102
|
953 //
|
Chris@102
|
954 // We can set the exponent and sign of the result up front:
|
Chris@102
|
955 //
|
Chris@102
|
956 int gb = msb(v);
|
Chris@102
|
957 res.exponent() = u.exponent() - static_cast<Exponent>(gb) - static_cast<Exponent>(1);
|
Chris@102
|
958 res.sign() = u.sign();
|
Chris@102
|
959 //
|
Chris@102
|
960 // Now get the quotient and remainder:
|
Chris@102
|
961 //
|
Chris@102
|
962 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type t(u.bits()), q, r;
|
Chris@102
|
963 eval_left_shift(t, gb + 1);
|
Chris@102
|
964 eval_qr(t, number<typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type>::canonical_value(v), q, r);
|
Chris@102
|
965 //
|
Chris@102
|
966 // We now have either "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count" or "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count+1" significant cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count in q.
|
Chris@102
|
967 //
|
Chris@102
|
968 static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT;
|
Chris@102
|
969 if(eval_bit_test(q, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count))
|
Chris@102
|
970 {
|
Chris@102
|
971 //
|
Chris@102
|
972 // OK we have cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count+1 cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count, so we already have rounding info,
|
Chris@102
|
973 // we just need to changes things if the last bit is 1 and the
|
Chris@102
|
974 // remainder is non-zero (ie we do not have a tie).
|
Chris@102
|
975 //
|
Chris@102
|
976 BOOST_ASSERT((eval_msb(q) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count));
|
Chris@102
|
977 if((q.limbs()[0] & 1u) && eval_get_sign(r))
|
Chris@102
|
978 {
|
Chris@102
|
979 eval_increment(q);
|
Chris@102
|
980 }
|
Chris@102
|
981 }
|
Chris@102
|
982 else
|
Chris@102
|
983 {
|
Chris@102
|
984 //
|
Chris@102
|
985 // We have exactly "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count" cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count in q.
|
Chris@102
|
986 // Get rounding info, which we can get by comparing 2r with v.
|
Chris@102
|
987 // We want to call copy_and_round to handle rounding and general cleanup,
|
Chris@102
|
988 // so we'll left shift q and add some fake cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count on the end to represent
|
Chris@102
|
989 // how we'll be rounding.
|
Chris@102
|
990 //
|
Chris@102
|
991 BOOST_ASSERT((eval_msb(q) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1));
|
Chris@102
|
992 static const unsigned lshift = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count < limb_bits ? 2 : limb_bits;
|
Chris@102
|
993 eval_left_shift(q, lshift);
|
Chris@102
|
994 res.exponent() -= lshift;
|
Chris@102
|
995 eval_left_shift(r, 1u);
|
Chris@102
|
996 int c = r.compare(number<typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type>::canonical_value(v));
|
Chris@102
|
997 if(c == 0)
|
Chris@102
|
998 q.limbs()[0] |= static_cast<limb_type>(1u) << (lshift - 1);
|
Chris@102
|
999 else if(c > 0)
|
Chris@102
|
1000 q.limbs()[0] |= (static_cast<limb_type>(1u) << (lshift - 1)) + static_cast<limb_type>(1u);
|
Chris@102
|
1001 }
|
Chris@102
|
1002 copy_and_round(res, q);
|
Chris@102
|
1003 }
|
Chris@102
|
1004
|
Chris@102
|
1005 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class U>
|
Chris@102
|
1006 inline typename enable_if_c<is_unsigned<U>::value>::type eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const U &v)
|
Chris@102
|
1007 {
|
Chris@102
|
1008 eval_divide(res, res, v);
|
Chris@102
|
1009 }
|
Chris@102
|
1010
|
Chris@102
|
1011 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class S>
|
Chris@102
|
1012 inline typename enable_if_c<is_signed<S>::value>::type eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &u, const S &v)
|
Chris@102
|
1013 {
|
Chris@102
|
1014 typedef typename make_unsigned<S>::type ui_type;
|
Chris@102
|
1015 eval_divide(res, u, static_cast<ui_type>(boost::multiprecision::detail::unsigned_abs(v)));
|
Chris@102
|
1016 if(v < 0)
|
Chris@102
|
1017 res.negate();
|
Chris@102
|
1018 }
|
Chris@102
|
1019
|
Chris@102
|
1020 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class S>
|
Chris@102
|
1021 inline typename enable_if_c<is_signed<S>::value>::type eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const S &v)
|
Chris@102
|
1022 {
|
Chris@102
|
1023 eval_divide(res, res, v);
|
Chris@102
|
1024 }
|
Chris@102
|
1025
|
Chris@102
|
1026 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
Chris@102
|
1027 inline int eval_get_sign(const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
|
Chris@102
|
1028 {
|
Chris@102
|
1029 return arg.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero ? 0 : arg.sign() ? -1 : 1;
|
Chris@102
|
1030 }
|
Chris@102
|
1031
|
Chris@102
|
1032 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
Chris@102
|
1033 inline bool eval_is_zero(const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
|
Chris@102
|
1034 {
|
Chris@102
|
1035 return arg.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
|
Chris@102
|
1036 }
|
Chris@102
|
1037
|
Chris@102
|
1038 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
Chris@102
|
1039 inline bool eval_eq(const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &b)
|
Chris@102
|
1040 {
|
Chris@102
|
1041 return (a.exponent() == b.exponent())
|
Chris@102
|
1042 && (a.sign() == b.sign())
|
Chris@102
|
1043 && (a.bits().compare(b.bits()) == 0)
|
Chris@102
|
1044 && (a.exponent() != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan);
|
Chris@102
|
1045 }
|
Chris@102
|
1046
|
Chris@102
|
1047 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
Chris@102
|
1048 inline void eval_convert_to(long long *res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
|
Chris@102
|
1049 {
|
Chris@102
|
1050 switch(arg.exponent())
|
Chris@102
|
1051 {
|
Chris@102
|
1052 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
Chris@102
|
1053 *res = 0;
|
Chris@102
|
1054 return;
|
Chris@102
|
1055 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
Chris@102
|
1056 BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
|
Chris@102
|
1057 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
Chris@102
|
1058 *res = (std::numeric_limits<long long>::max)();
|
Chris@102
|
1059 if(arg.sign())
|
Chris@102
|
1060 *res = -*res;
|
Chris@102
|
1061 return;
|
Chris@102
|
1062 }
|
Chris@102
|
1063 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::rep_type man(arg.bits());
|
Chris@102
|
1064 typename mpl::if_c<sizeof(typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type) < sizeof(int), int, typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type>::type shift
|
Chris@102
|
1065 = (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 - arg.exponent();
|
Chris@102
|
1066 if(shift > (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1)
|
Chris@102
|
1067 {
|
Chris@102
|
1068 *res = 0;
|
Chris@102
|
1069 return;
|
Chris@102
|
1070 }
|
Chris@102
|
1071 if(arg.sign() && (arg.compare((std::numeric_limits<long long>::min)()) <= 0))
|
Chris@102
|
1072 {
|
Chris@102
|
1073 *res = (std::numeric_limits<long long>::min)();
|
Chris@102
|
1074 return;
|
Chris@102
|
1075 }
|
Chris@102
|
1076 else if(!arg.sign() && (arg.compare((std::numeric_limits<long long>::max)()) >= 0))
|
Chris@102
|
1077 {
|
Chris@102
|
1078 *res = (std::numeric_limits<long long>::max)();
|
Chris@102
|
1079 return;
|
Chris@102
|
1080 }
|
Chris@102
|
1081 eval_right_shift(man, shift);
|
Chris@102
|
1082 eval_convert_to(res, man);
|
Chris@102
|
1083 if(arg.sign())
|
Chris@102
|
1084 {
|
Chris@102
|
1085 *res = -*res;
|
Chris@102
|
1086 }
|
Chris@102
|
1087 }
|
Chris@102
|
1088
|
Chris@102
|
1089 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
Chris@102
|
1090 inline void eval_convert_to(unsigned long long *res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
|
Chris@102
|
1091 {
|
Chris@102
|
1092 switch(arg.exponent())
|
Chris@102
|
1093 {
|
Chris@102
|
1094 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
Chris@102
|
1095 *res = 0;
|
Chris@102
|
1096 return;
|
Chris@102
|
1097 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
Chris@102
|
1098 BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
|
Chris@102
|
1099 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
Chris@102
|
1100 *res = (std::numeric_limits<unsigned long long>::max)();
|
Chris@102
|
1101 return;
|
Chris@102
|
1102 }
|
Chris@102
|
1103 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::rep_type man(arg.bits());
|
Chris@102
|
1104 typename mpl::if_c<sizeof(typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type) < sizeof(int), int, typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type>::type shift
|
Chris@102
|
1105 = (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 - arg.exponent();
|
Chris@102
|
1106 if(shift > (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1)
|
Chris@102
|
1107 {
|
Chris@102
|
1108 *res = 0;
|
Chris@102
|
1109 return;
|
Chris@102
|
1110 }
|
Chris@102
|
1111 else if(shift < 0)
|
Chris@102
|
1112 {
|
Chris@102
|
1113 // TODO: what if we have fewer cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count than a long long?
|
Chris@102
|
1114 *res = (std::numeric_limits<long long>::max)();
|
Chris@102
|
1115 return;
|
Chris@102
|
1116 }
|
Chris@102
|
1117 eval_right_shift(man, shift);
|
Chris@102
|
1118 eval_convert_to(res, man);
|
Chris@102
|
1119 }
|
Chris@102
|
1120
|
Chris@102
|
1121 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
Chris@102
|
1122 inline void eval_convert_to(long double *res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
|
Chris@102
|
1123 {
|
Chris@102
|
1124 switch(arg.exponent())
|
Chris@102
|
1125 {
|
Chris@102
|
1126 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
Chris@102
|
1127 *res = 0;
|
Chris@102
|
1128 return;
|
Chris@102
|
1129 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
Chris@102
|
1130 *res = std::numeric_limits<long double>::quiet_NaN();
|
Chris@102
|
1131 return;
|
Chris@102
|
1132 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
Chris@102
|
1133 *res = (std::numeric_limits<long double>::infinity)();
|
Chris@102
|
1134 if(arg.sign())
|
Chris@102
|
1135 *res = -*res;
|
Chris@102
|
1136 return;
|
Chris@102
|
1137 }
|
Chris@102
|
1138 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type e = arg.exponent();
|
Chris@102
|
1139 e -= cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1;
|
Chris@102
|
1140 *res = std::ldexp(static_cast<long double>(*arg.bits().limbs()), e);
|
Chris@102
|
1141 for(unsigned i = 1; i < arg.bits().size(); ++i)
|
Chris@102
|
1142 {
|
Chris@102
|
1143 e += sizeof(*arg.bits().limbs()) * CHAR_BIT;
|
Chris@102
|
1144 *res += std::ldexp(static_cast<long double>(arg.bits().limbs()[i]), e);
|
Chris@102
|
1145 }
|
Chris@102
|
1146 if(arg.sign())
|
Chris@102
|
1147 *res = -*res;
|
Chris@102
|
1148 }
|
Chris@102
|
1149
|
Chris@102
|
1150 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
Chris@102
|
1151 inline void eval_frexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg, Exponent *e)
|
Chris@102
|
1152 {
|
Chris@102
|
1153 switch(arg.exponent())
|
Chris@102
|
1154 {
|
Chris@102
|
1155 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
Chris@102
|
1156 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
Chris@102
|
1157 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
Chris@102
|
1158 *e = 0;
|
Chris@102
|
1159 res = arg;
|
Chris@102
|
1160 return;
|
Chris@102
|
1161 }
|
Chris@102
|
1162 res = arg;
|
Chris@102
|
1163 *e = arg.exponent() + 1;
|
Chris@102
|
1164 res.exponent() = -1;
|
Chris@102
|
1165 }
|
Chris@102
|
1166
|
Chris@102
|
1167 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class I>
|
Chris@102
|
1168 inline void eval_frexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg, I *pe)
|
Chris@102
|
1169 {
|
Chris@102
|
1170 Exponent e;
|
Chris@102
|
1171 eval_frexp(res, arg, &e);
|
Chris@102
|
1172 if((e > (std::numeric_limits<I>::max)()) || (e < (std::numeric_limits<I>::min)()))
|
Chris@102
|
1173 {
|
Chris@102
|
1174 BOOST_THROW_EXCEPTION(std::runtime_error("Exponent was outside of the range of the argument type to frexp."));
|
Chris@102
|
1175 }
|
Chris@102
|
1176 *pe = static_cast<I>(e);
|
Chris@102
|
1177 }
|
Chris@102
|
1178
|
Chris@102
|
1179 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
Chris@102
|
1180 inline void eval_ldexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg, Exponent e)
|
Chris@102
|
1181 {
|
Chris@102
|
1182 switch(arg.exponent())
|
Chris@102
|
1183 {
|
Chris@102
|
1184 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
Chris@102
|
1185 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
Chris@102
|
1186 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
Chris@102
|
1187 res = arg;
|
Chris@102
|
1188 return;
|
Chris@102
|
1189 }
|
Chris@102
|
1190 if((e > 0) && (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent - e < arg.exponent()))
|
Chris@102
|
1191 {
|
Chris@102
|
1192 // Overflow:
|
Chris@102
|
1193 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
|
Chris@102
|
1194 res.sign() = arg.sign();
|
Chris@102
|
1195 }
|
Chris@102
|
1196 else if((e < 0) && (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent - e > arg.exponent()))
|
Chris@102
|
1197 {
|
Chris@102
|
1198 // Underflow:
|
Chris@102
|
1199 res = limb_type(0);
|
Chris@102
|
1200 }
|
Chris@102
|
1201 else
|
Chris@102
|
1202 {
|
Chris@102
|
1203 res = arg;
|
Chris@102
|
1204 res.exponent() += e;
|
Chris@102
|
1205 }
|
Chris@102
|
1206 }
|
Chris@102
|
1207
|
Chris@102
|
1208 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class I>
|
Chris@102
|
1209 inline typename enable_if_c<is_unsigned<I>::value>::type eval_ldexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg, I e)
|
Chris@102
|
1210 {
|
Chris@102
|
1211 typedef typename make_signed<I>::type si_type;
|
Chris@102
|
1212 if(e > static_cast<I>((std::numeric_limits<si_type>::max)()))
|
Chris@102
|
1213 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
|
Chris@102
|
1214 else
|
Chris@102
|
1215 eval_ldexp(res, arg, static_cast<si_type>(e));
|
Chris@102
|
1216 }
|
Chris@102
|
1217
|
Chris@102
|
1218 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class I>
|
Chris@102
|
1219 inline typename enable_if_c<is_signed<I>::value>::type eval_ldexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg, I e)
|
Chris@102
|
1220 {
|
Chris@102
|
1221 if((e > (std::numeric_limits<Exponent>::max)()) || (e < (std::numeric_limits<Exponent>::min)()))
|
Chris@102
|
1222 {
|
Chris@102
|
1223 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
|
Chris@102
|
1224 if(e < 0)
|
Chris@102
|
1225 res.negate();
|
Chris@102
|
1226 }
|
Chris@102
|
1227 else
|
Chris@102
|
1228 eval_ldexp(res, arg, static_cast<Exponent>(e));
|
Chris@102
|
1229 }
|
Chris@102
|
1230
|
Chris@102
|
1231 /*
|
Chris@102
|
1232 * Sign manipulation
|
Chris@102
|
1233 */
|
Chris@102
|
1234
|
Chris@102
|
1235 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
Chris@102
|
1236 inline void eval_abs(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
|
Chris@102
|
1237 {
|
Chris@102
|
1238 res = arg;
|
Chris@102
|
1239 res.sign() = false;
|
Chris@102
|
1240 }
|
Chris@102
|
1241
|
Chris@102
|
1242 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
Chris@102
|
1243 inline void eval_fabs(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
|
Chris@102
|
1244 {
|
Chris@102
|
1245 res = arg;
|
Chris@102
|
1246 res.sign() = false;
|
Chris@102
|
1247 }
|
Chris@102
|
1248
|
Chris@102
|
1249 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
Chris@102
|
1250 inline int eval_fpclassify(const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
|
Chris@102
|
1251 {
|
Chris@102
|
1252 switch(arg.exponent())
|
Chris@102
|
1253 {
|
Chris@102
|
1254 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
Chris@102
|
1255 return FP_ZERO;
|
Chris@102
|
1256 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
Chris@102
|
1257 return FP_INFINITE;
|
Chris@102
|
1258 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
Chris@102
|
1259 return FP_NAN;
|
Chris@102
|
1260 }
|
Chris@102
|
1261 return FP_NORMAL;
|
Chris@102
|
1262 }
|
Chris@102
|
1263
|
Chris@102
|
1264 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
Chris@102
|
1265 inline void eval_sqrt(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
|
Chris@102
|
1266 {
|
Chris@102
|
1267 using default_ops::eval_integer_sqrt;
|
Chris@102
|
1268 using default_ops::eval_bit_test;
|
Chris@102
|
1269 using default_ops::eval_increment;
|
Chris@102
|
1270 switch(arg.exponent())
|
Chris@102
|
1271 {
|
Chris@102
|
1272 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
Chris@102
|
1273 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
Chris@102
|
1274 res = arg;
|
Chris@102
|
1275 return;
|
Chris@102
|
1276 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
Chris@102
|
1277 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
|
Chris@102
|
1278 return;
|
Chris@102
|
1279 }
|
Chris@102
|
1280 if(arg.sign())
|
Chris@102
|
1281 {
|
Chris@102
|
1282 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
|
Chris@102
|
1283 return;
|
Chris@102
|
1284 }
|
Chris@102
|
1285
|
Chris@102
|
1286 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type t(arg.bits()), r, s;
|
Chris@102
|
1287 eval_left_shift(t, arg.exponent() & 1 ? cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count : cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1);
|
Chris@102
|
1288 eval_integer_sqrt(s, r, t);
|
Chris@102
|
1289
|
Chris@102
|
1290 if(!eval_bit_test(s, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count))
|
Chris@102
|
1291 {
|
Chris@102
|
1292 // We have exactly the right number of cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count in the result, round as required:
|
Chris@102
|
1293 if(s.compare(r) < 0)
|
Chris@102
|
1294 {
|
Chris@102
|
1295 eval_increment(s);
|
Chris@102
|
1296 }
|
Chris@102
|
1297 }
|
Chris@102
|
1298 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type ae = arg.exponent();
|
Chris@102
|
1299 res.exponent() = ae / 2;
|
Chris@102
|
1300 if((ae & 1) && (ae < 0))
|
Chris@102
|
1301 --res.exponent();
|
Chris@102
|
1302 copy_and_round(res, s);
|
Chris@102
|
1303 }
|
Chris@102
|
1304
|
Chris@102
|
1305 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
Chris@102
|
1306 inline void eval_floor(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
|
Chris@102
|
1307 {
|
Chris@102
|
1308 using default_ops::eval_increment;
|
Chris@102
|
1309 switch(arg.exponent())
|
Chris@102
|
1310 {
|
Chris@102
|
1311 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
Chris@102
|
1312 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
Chris@102
|
1313 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
Chris@102
|
1314 res = arg;
|
Chris@102
|
1315 return;
|
Chris@102
|
1316 }
|
Chris@102
|
1317 typename mpl::if_c<sizeof(typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type) < sizeof(int), int, typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type>::type shift =
|
Chris@102
|
1318 (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - arg.exponent() - 1;
|
Chris@102
|
1319 if((arg.exponent() > (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent) || (shift <= 0))
|
Chris@102
|
1320 {
|
Chris@102
|
1321 // Either arg is already an integer, or a special value:
|
Chris@102
|
1322 res = arg;
|
Chris@102
|
1323 return;
|
Chris@102
|
1324 }
|
Chris@102
|
1325 if(shift >= (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
|
Chris@102
|
1326 {
|
Chris@102
|
1327 res = static_cast<signed_limb_type>(arg.sign() ? -1 : 0);
|
Chris@102
|
1328 return;
|
Chris@102
|
1329 }
|
Chris@102
|
1330 bool fractional = (int)eval_lsb(arg.bits()) < shift;
|
Chris@102
|
1331 res = arg;
|
Chris@102
|
1332 eval_right_shift(res.bits(), shift);
|
Chris@102
|
1333 if(fractional && res.sign())
|
Chris@102
|
1334 {
|
Chris@102
|
1335 eval_increment(res.bits());
|
Chris@102
|
1336 if(eval_msb(res.bits()) != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 - shift)
|
Chris@102
|
1337 {
|
Chris@102
|
1338 // Must have extended result by one bit in the increment:
|
Chris@102
|
1339 --shift;
|
Chris@102
|
1340 ++res.exponent();
|
Chris@102
|
1341 }
|
Chris@102
|
1342 }
|
Chris@102
|
1343 eval_left_shift(res.bits(), shift);
|
Chris@102
|
1344 }
|
Chris@102
|
1345
|
Chris@102
|
1346 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
Chris@102
|
1347 inline void eval_ceil(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg)
|
Chris@102
|
1348 {
|
Chris@102
|
1349 using default_ops::eval_increment;
|
Chris@102
|
1350 switch(arg.exponent())
|
Chris@102
|
1351 {
|
Chris@102
|
1352 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
|
Chris@102
|
1353 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
|
Chris@102
|
1354 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
|
Chris@102
|
1355 res = arg;
|
Chris@102
|
1356 return;
|
Chris@102
|
1357 }
|
Chris@102
|
1358 typename mpl::if_c<sizeof(typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type) < sizeof(int), int, typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type>::type shift = (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - arg.exponent() - 1;
|
Chris@102
|
1359 if((arg.exponent() > (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent) || (shift <= 0))
|
Chris@102
|
1360 {
|
Chris@102
|
1361 // Either arg is already an integer, or a special value:
|
Chris@102
|
1362 res = arg;
|
Chris@102
|
1363 return;
|
Chris@102
|
1364 }
|
Chris@102
|
1365 if(shift >= (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
|
Chris@102
|
1366 {
|
Chris@102
|
1367 res = static_cast<signed_limb_type>(arg.sign() ? 0 : 1);
|
Chris@102
|
1368 return;
|
Chris@102
|
1369 }
|
Chris@102
|
1370 bool fractional = (int)eval_lsb(arg.bits()) < shift;
|
Chris@102
|
1371 res = arg;
|
Chris@102
|
1372 eval_right_shift(res.bits(), shift);
|
Chris@102
|
1373 if(fractional && !res.sign())
|
Chris@102
|
1374 {
|
Chris@102
|
1375 eval_increment(res.bits());
|
Chris@102
|
1376 if(eval_msb(res.bits()) != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 - shift)
|
Chris@102
|
1377 {
|
Chris@102
|
1378 // Must have extended result by one bit in the increment:
|
Chris@102
|
1379 --shift;
|
Chris@102
|
1380 ++res.exponent();
|
Chris@102
|
1381 }
|
Chris@102
|
1382 }
|
Chris@102
|
1383 eval_left_shift(res.bits(), shift);
|
Chris@102
|
1384 }
|
Chris@102
|
1385
|
Chris@102
|
1386 } // namespace backends
|
Chris@102
|
1387
|
Chris@102
|
1388 #ifdef BOOST_NO_SFINAE_EXPR
|
Chris@102
|
1389
|
Chris@102
|
1390 namespace detail{
|
Chris@102
|
1391
|
Chris@102
|
1392 template<unsigned D1, backends::digit_base_type B1, class A1, class E1, E1 M1, E1 M2, unsigned D2, backends::digit_base_type B2, class A2, class E2, E2 M3, E2 M4>
|
Chris@102
|
1393 struct is_explicitly_convertible<backends::cpp_bin_float<D1, B1, A1, E1, M1, M2>, backends::cpp_bin_float<D2, B2, A2, E2, M3, M4> > : public mpl::true_ {};
|
Chris@102
|
1394
|
Chris@102
|
1395 }
|
Chris@102
|
1396 #endif
|
Chris@102
|
1397
|
Chris@102
|
1398
|
Chris@102
|
1399 using backends::cpp_bin_float;
|
Chris@102
|
1400 using backends::digit_base_2;
|
Chris@102
|
1401 using backends::digit_base_10;
|
Chris@102
|
1402
|
Chris@102
|
1403 template<unsigned Digits, backends::digit_base_type DigitBase, class Exponent, Exponent MinE, Exponent MaxE, class Allocator>
|
Chris@102
|
1404 struct number_category<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > : public boost::mpl::int_<boost::multiprecision::number_kind_floating_point>{};
|
Chris@102
|
1405
|
Chris@102
|
1406 template<unsigned Digits, backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
Chris@102
|
1407 struct expression_template_default<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> >
|
Chris@102
|
1408 {
|
Chris@102
|
1409 static const expression_template_option value = is_void<Allocator>::value ? et_off : et_on;
|
Chris@102
|
1410 };
|
Chris@102
|
1411
|
Chris@102
|
1412 typedef number<backends::cpp_bin_float<50> > cpp_bin_float_50;
|
Chris@102
|
1413 typedef number<backends::cpp_bin_float<100> > cpp_bin_float_100;
|
Chris@102
|
1414
|
Chris@102
|
1415 typedef number<backends::cpp_bin_float<24, backends::digit_base_2, void, boost::int16_t, -126, 127>, et_off> cpp_bin_float_single;
|
Chris@102
|
1416 typedef number<backends::cpp_bin_float<53, backends::digit_base_2, void, boost::int16_t, -1022, 1023>, et_off> cpp_bin_float_double;
|
Chris@102
|
1417 typedef number<backends::cpp_bin_float<64, backends::digit_base_2, void, boost::int16_t, -16382, 16383>, et_off> cpp_bin_float_double_extended;
|
Chris@102
|
1418 typedef number<backends::cpp_bin_float<113, backends::digit_base_2, void, boost::int16_t, -16382, 16383>, et_off> cpp_bin_float_quad;
|
Chris@102
|
1419
|
Chris@102
|
1420 }} // namespaces
|
Chris@102
|
1421
|
Chris@102
|
1422 #include <boost/multiprecision/cpp_bin_float/io.hpp>
|
Chris@102
|
1423 #include <boost/multiprecision/cpp_bin_float/transcendental.hpp>
|
Chris@102
|
1424
|
Chris@102
|
1425 namespace std{
|
Chris@102
|
1426
|
Chris@102
|
1427 //
|
Chris@102
|
1428 // numeric_limits [partial] specializations for the types declared in this header:
|
Chris@102
|
1429 //
|
Chris@102
|
1430 template<unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@102
|
1431 class numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >
|
Chris@102
|
1432 {
|
Chris@102
|
1433 typedef boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> number_type;
|
Chris@102
|
1434 public:
|
Chris@102
|
1435 BOOST_STATIC_CONSTEXPR bool is_specialized = true;
|
Chris@102
|
1436 static number_type (min)()
|
Chris@102
|
1437 {
|
Chris@102
|
1438 initializer.do_nothing();
|
Chris@102
|
1439 static std::pair<bool, number_type> value;
|
Chris@102
|
1440 if(!value.first)
|
Chris@102
|
1441 {
|
Chris@102
|
1442 value.first = true;
|
Chris@102
|
1443 value.second = 1u;
|
Chris@102
|
1444 value.second.backend().exponent() = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent;
|
Chris@102
|
1445 }
|
Chris@102
|
1446 return value.second;
|
Chris@102
|
1447 }
|
Chris@102
|
1448 static number_type (max)()
|
Chris@102
|
1449 {
|
Chris@102
|
1450 initializer.do_nothing();
|
Chris@102
|
1451 static std::pair<bool, number_type> value;
|
Chris@102
|
1452 if(!value.first)
|
Chris@102
|
1453 {
|
Chris@102
|
1454 value.first = true;
|
Chris@102
|
1455 eval_complement(value.second.backend().bits(), value.second.backend().bits());
|
Chris@102
|
1456 value.second.backend().exponent() = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent;
|
Chris@102
|
1457 }
|
Chris@102
|
1458 return value.second;
|
Chris@102
|
1459 }
|
Chris@102
|
1460 BOOST_STATIC_CONSTEXPR number_type lowest()
|
Chris@102
|
1461 {
|
Chris@102
|
1462 return -(max)();
|
Chris@102
|
1463 }
|
Chris@102
|
1464 BOOST_STATIC_CONSTEXPR int digits = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count;
|
Chris@102
|
1465 BOOST_STATIC_CONSTEXPR int digits10 = digits * 301 / 1000;
|
Chris@102
|
1466 // Is this really correct???
|
Chris@102
|
1467 BOOST_STATIC_CONSTEXPR int max_digits10 = digits10 + 2;
|
Chris@102
|
1468 BOOST_STATIC_CONSTEXPR bool is_signed = true;
|
Chris@102
|
1469 BOOST_STATIC_CONSTEXPR bool is_integer = false;
|
Chris@102
|
1470 BOOST_STATIC_CONSTEXPR bool is_exact = false;
|
Chris@102
|
1471 BOOST_STATIC_CONSTEXPR int radix = 2;
|
Chris@102
|
1472 static number_type epsilon()
|
Chris@102
|
1473 {
|
Chris@102
|
1474 initializer.do_nothing();
|
Chris@102
|
1475 static std::pair<bool, number_type> value;
|
Chris@102
|
1476 if(!value.first)
|
Chris@102
|
1477 {
|
Chris@102
|
1478 value.first = true;
|
Chris@102
|
1479 value.second = 1;
|
Chris@102
|
1480 value.second = ldexp(value.second, 1 - (int)digits);
|
Chris@102
|
1481 }
|
Chris@102
|
1482 return value.second;
|
Chris@102
|
1483 }
|
Chris@102
|
1484 // What value should this be????
|
Chris@102
|
1485 static number_type round_error()
|
Chris@102
|
1486 {
|
Chris@102
|
1487 // returns 0.5
|
Chris@102
|
1488 initializer.do_nothing();
|
Chris@102
|
1489 static std::pair<bool, number_type> value;
|
Chris@102
|
1490 if(!value.first)
|
Chris@102
|
1491 {
|
Chris@102
|
1492 value.first = true;
|
Chris@102
|
1493 value.second = 1;
|
Chris@102
|
1494 value.second = ldexp(value.second, -1);
|
Chris@102
|
1495 }
|
Chris@102
|
1496 return value.second;
|
Chris@102
|
1497 }
|
Chris@102
|
1498 BOOST_STATIC_CONSTEXPR typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type min_exponent = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent;
|
Chris@102
|
1499 BOOST_STATIC_CONSTEXPR typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type min_exponent10 = (min_exponent / 1000) * 301L;
|
Chris@102
|
1500 BOOST_STATIC_CONSTEXPR typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type max_exponent = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent;
|
Chris@102
|
1501 BOOST_STATIC_CONSTEXPR typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type max_exponent10 = (max_exponent / 1000) * 301L;
|
Chris@102
|
1502 BOOST_STATIC_CONSTEXPR bool has_infinity = true;
|
Chris@102
|
1503 BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = true;
|
Chris@102
|
1504 BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false;
|
Chris@102
|
1505 BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent;
|
Chris@102
|
1506 BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false;
|
Chris@102
|
1507 static number_type infinity()
|
Chris@102
|
1508 {
|
Chris@102
|
1509 // returns epsilon/2
|
Chris@102
|
1510 initializer.do_nothing();
|
Chris@102
|
1511 static std::pair<bool, number_type> value;
|
Chris@102
|
1512 if(!value.first)
|
Chris@102
|
1513 {
|
Chris@102
|
1514 value.first = true;
|
Chris@102
|
1515 value.second.backend().exponent() = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
|
Chris@102
|
1516 }
|
Chris@102
|
1517 return value.second;
|
Chris@102
|
1518 }
|
Chris@102
|
1519 static number_type quiet_NaN()
|
Chris@102
|
1520 {
|
Chris@102
|
1521 return number_type();
|
Chris@102
|
1522 }
|
Chris@102
|
1523 BOOST_STATIC_CONSTEXPR number_type signaling_NaN()
|
Chris@102
|
1524 {
|
Chris@102
|
1525 return number_type(0);
|
Chris@102
|
1526 }
|
Chris@102
|
1527 BOOST_STATIC_CONSTEXPR number_type denorm_min() { return number_type(0); }
|
Chris@102
|
1528 BOOST_STATIC_CONSTEXPR bool is_iec559 = false;
|
Chris@102
|
1529 BOOST_STATIC_CONSTEXPR bool is_bounded = true;
|
Chris@102
|
1530 BOOST_STATIC_CONSTEXPR bool is_modulo = false;
|
Chris@102
|
1531 BOOST_STATIC_CONSTEXPR bool traps = true;
|
Chris@102
|
1532 BOOST_STATIC_CONSTEXPR bool tinyness_before = false;
|
Chris@102
|
1533 BOOST_STATIC_CONSTEXPR float_round_style round_style = round_to_nearest;
|
Chris@102
|
1534 private:
|
Chris@102
|
1535 struct data_initializer
|
Chris@102
|
1536 {
|
Chris@102
|
1537 data_initializer()
|
Chris@102
|
1538 {
|
Chris@102
|
1539 std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::epsilon();
|
Chris@102
|
1540 std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::round_error();
|
Chris@102
|
1541 (std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::min)();
|
Chris@102
|
1542 (std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::max)();
|
Chris@102
|
1543 std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity();
|
Chris@102
|
1544 std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN();
|
Chris@102
|
1545 }
|
Chris@102
|
1546 void do_nothing()const{}
|
Chris@102
|
1547 };
|
Chris@102
|
1548 static const data_initializer initializer;
|
Chris@102
|
1549 };
|
Chris@102
|
1550
|
Chris@102
|
1551 template<unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@102
|
1552 const typename numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::data_initializer numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::initializer;
|
Chris@102
|
1553
|
Chris@102
|
1554 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
|
Chris@102
|
1555
|
Chris@102
|
1556 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@102
|
1557 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::digits;
|
Chris@102
|
1558 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@102
|
1559 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::digits10;
|
Chris@102
|
1560 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@102
|
1561 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::max_digits10;
|
Chris@102
|
1562 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@102
|
1563 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_signed;
|
Chris@102
|
1564 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@102
|
1565 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_integer;
|
Chris@102
|
1566 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@102
|
1567 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_exact;
|
Chris@102
|
1568 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@102
|
1569 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::radix;
|
Chris@102
|
1570 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@102
|
1571 BOOST_CONSTEXPR_OR_CONST typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::min_exponent;
|
Chris@102
|
1572 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@102
|
1573 BOOST_CONSTEXPR_OR_CONST typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::min_exponent10;
|
Chris@102
|
1574 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@102
|
1575 BOOST_CONSTEXPR_OR_CONST typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::max_exponent;
|
Chris@102
|
1576 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@102
|
1577 BOOST_CONSTEXPR_OR_CONST typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::max_exponent10;
|
Chris@102
|
1578 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@102
|
1579 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_infinity;
|
Chris@102
|
1580 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@102
|
1581 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_quiet_NaN;
|
Chris@102
|
1582 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@102
|
1583 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_signaling_NaN;
|
Chris@102
|
1584 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@102
|
1585 BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_denorm;
|
Chris@102
|
1586 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@102
|
1587 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_denorm_loss;
|
Chris@102
|
1588 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@102
|
1589 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_iec559;
|
Chris@102
|
1590 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@102
|
1591 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_bounded;
|
Chris@102
|
1592 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@102
|
1593 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_modulo;
|
Chris@102
|
1594 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@102
|
1595 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::traps;
|
Chris@102
|
1596 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@102
|
1597 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::tinyness_before;
|
Chris@102
|
1598 template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@102
|
1599 BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::round_style;
|
Chris@102
|
1600
|
Chris@102
|
1601 #endif
|
Chris@102
|
1602
|
Chris@102
|
1603 } // namespace std
|
Chris@102
|
1604
|
Chris@102
|
1605 #endif
|