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