]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/multiprecision/cpp_bin_float.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / multiprecision / cpp_bin_float.hpp
CommitLineData
7c673cae
FG
1///////////////////////////////////////////////////////////////
2// Copyright 2013 John Maddock. Distributed under the Boost
3// Software License, Version 1.0. (See accompanying file
92f5a8d4 4// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
7c673cae
FG
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>
20effc67 13#include <boost/multiprecision/traits/max_digits10.hpp>
7c673cae
FG
14
15//
16// Some includes we need from Boost.Math, since we rely on that library to provide these functions:
17//
18#include <boost/math/special_functions/asinh.hpp>
19#include <boost/math/special_functions/acosh.hpp>
20#include <boost/math/special_functions/atanh.hpp>
21#include <boost/math/special_functions/cbrt.hpp>
22#include <boost/math/special_functions/expm1.hpp>
23#include <boost/math/special_functions/gamma.hpp>
24
b32b8144
FG
25#ifdef BOOST_HAS_FLOAT128
26#include <quadmath.h>
27#endif
28
92f5a8d4
TL
29namespace boost {
30namespace multiprecision {
31namespace backends {
7c673cae
FG
32
33enum digit_base_type
34{
92f5a8d4 35 digit_base_2 = 2,
7c673cae
FG
36 digit_base_10 = 10
37};
38
39#ifdef BOOST_MSVC
40#pragma warning(push)
92f5a8d4 41#pragma warning(disable : 4522 6326) // multiple assignment operators specified, comparison of two constants
7c673cae
FG
42#endif
43
92f5a8d4 44namespace detail {
7c673cae
FG
45
46template <class U>
47inline typename enable_if_c<is_unsigned<U>::value, bool>::type is_negative(U) { return false; }
48template <class S>
49inline typename disable_if_c<is_unsigned<S>::value, bool>::type is_negative(S s) { return s < 0; }
50
92f5a8d4
TL
51template <class Float, int, bool = number_category<Float>::value == number_kind_floating_point>
52struct is_cpp_bin_float_implicitly_constructible_from_type
53{
54 static const bool value = false;
55};
56
57template <class Float, int bit_count>
58struct is_cpp_bin_float_implicitly_constructible_from_type<Float, bit_count, true>
59{
60 static const bool value = (std::numeric_limits<Float>::digits <= (int)bit_count) && (std::numeric_limits<Float>::radix == 2) && std::numeric_limits<Float>::is_specialized
61#ifdef BOOST_HAS_FLOAT128
62 && !boost::is_same<Float, __float128>::value
63#endif
64 && (is_floating_point<Float>::value || is_number<Float>::value);
65};
66
67template <class Float, int, bool = number_category<Float>::value == number_kind_floating_point>
68struct is_cpp_bin_float_explicitly_constructible_from_type
69{
70 static const bool value = false;
71};
72
73template <class Float, int bit_count>
74struct is_cpp_bin_float_explicitly_constructible_from_type<Float, bit_count, true>
75{
76 static const bool value = (std::numeric_limits<Float>::digits > (int)bit_count) && (std::numeric_limits<Float>::radix == 2) && std::numeric_limits<Float>::is_specialized
77#ifdef BOOST_HAS_FLOAT128
78 && !boost::is_same<Float, __float128>::value
79#endif
80 ;
81};
82
83} // namespace detail
7c673cae
FG
84
85template <unsigned Digits, digit_base_type DigitBase = digit_base_10, class Allocator = void, class Exponent = int, Exponent MinExponent = 0, Exponent MaxExponent = 0>
86class cpp_bin_float
87{
92f5a8d4
TL
88 public:
89 static const unsigned bit_count = DigitBase == digit_base_2 ? Digits : (Digits * 1000uL) / 301uL + (((Digits * 1000uL) % 301) ? 2u : 1u);
90 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;
7c673cae
FG
91 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;
92
92f5a8d4
TL
93 typedef typename rep_type::signed_types signed_types;
94 typedef typename rep_type::unsigned_types unsigned_types;
95 typedef boost::mpl::list<float, double, long double> float_types;
96 typedef Exponent exponent_type;
7c673cae
FG
97
98 static const exponent_type max_exponent_limit = boost::integer_traits<exponent_type>::const_max - 2 * static_cast<exponent_type>(bit_count);
99 static const exponent_type min_exponent_limit = boost::integer_traits<exponent_type>::const_min + 2 * static_cast<exponent_type>(bit_count);
100
101 BOOST_STATIC_ASSERT_MSG(MinExponent >= min_exponent_limit, "Template parameter MinExponent is too negative for our internal logic to function correctly, sorry!");
102 BOOST_STATIC_ASSERT_MSG(MaxExponent <= max_exponent_limit, "Template parameter MaxExponent is too large for our internal logic to function correctly, sorry!");
103 BOOST_STATIC_ASSERT_MSG(MinExponent <= 0, "Template parameter MinExponent can not be positive!");
104 BOOST_STATIC_ASSERT_MSG(MaxExponent >= 0, "Template parameter MaxExponent can not be negative!");
105
106 static const exponent_type max_exponent = MaxExponent == 0 ? max_exponent_limit : MaxExponent;
107 static const exponent_type min_exponent = MinExponent == 0 ? min_exponent_limit : MinExponent;
108
92f5a8d4 109 static const exponent_type exponent_zero = max_exponent + 1;
7c673cae 110 static const exponent_type exponent_infinity = max_exponent + 2;
92f5a8d4 111 static const exponent_type exponent_nan = max_exponent + 3;
7c673cae 112
92f5a8d4
TL
113 private:
114 rep_type m_data;
7c673cae 115 exponent_type m_exponent;
92f5a8d4
TL
116 bool m_sign;
117
118 public:
7c673cae
FG
119 cpp_bin_float() BOOST_MP_NOEXCEPT_IF(noexcept(rep_type())) : m_data(), m_exponent(exponent_zero), m_sign(false) {}
120
92f5a8d4
TL
121 cpp_bin_float(const cpp_bin_float& o) BOOST_MP_NOEXCEPT_IF(noexcept(rep_type(std::declval<const rep_type&>())))
122 : m_data(o.m_data), m_exponent(o.m_exponent), m_sign(o.m_sign) {}
7c673cae
FG
123
124 template <unsigned D, digit_base_type B, class A, class E, E MinE, E MaxE>
92f5a8d4 125 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)
7c673cae
FG
126 {
127 *this = o;
128 }
129 template <unsigned D, digit_base_type B, class A, class E, E MinE, E MaxE>
92f5a8d4
TL
130 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)
131 : m_exponent(o.exponent()), m_sign(o.sign())
7c673cae
FG
132 {
133 *this = o;
134 }
135 template <class Float>
92f5a8d4
TL
136 cpp_bin_float(const Float& f,
137 typename boost::enable_if_c<detail::is_cpp_bin_float_implicitly_constructible_from_type<Float, bit_count>::value>::type const* = 0)
138 : m_data(), m_exponent(0), m_sign(false)
7c673cae
FG
139 {
140 this->assign_float(f);
141 }
142
143 template <class Float>
144 explicit cpp_bin_float(const Float& f,
92f5a8d4
TL
145 typename boost::enable_if_c<detail::is_cpp_bin_float_explicitly_constructible_from_type<Float, bit_count>::value>::type const* = 0)
146 : m_data(), m_exponent(0), m_sign(false)
b32b8144
FG
147 {
148 this->assign_float(f);
149 }
150#ifdef BOOST_HAS_FLOAT128
151 template <class Float>
152 cpp_bin_float(const Float& f,
92f5a8d4
TL
153 typename boost::enable_if_c<
154 boost::is_same<Float, __float128>::value && ((int)bit_count >= 113)>::type const* = 0)
155 : m_data(), m_exponent(0), m_sign(false)
7c673cae
FG
156 {
157 this->assign_float(f);
158 }
b32b8144
FG
159 template <class Float>
160 explicit cpp_bin_float(const Float& f,
92f5a8d4
TL
161 typename boost::enable_if_c<
162 boost::is_same<Float, __float128>::value && ((int)bit_count < 113)>::type const* = 0)
163 : m_data(), m_exponent(0), m_sign(false)
b32b8144
FG
164 {
165 this->assign_float(f);
166 }
167#endif
92f5a8d4 168 cpp_bin_float& operator=(const cpp_bin_float& o) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<rep_type&>() = std::declval<const rep_type&>()))
7c673cae 169 {
92f5a8d4 170 m_data = o.m_data;
7c673cae 171 m_exponent = o.m_exponent;
92f5a8d4 172 m_sign = o.m_sign;
7c673cae
FG
173 return *this;
174 }
175
176 template <unsigned D, digit_base_type B, class A, class E, E MinE, E MaxE>
92f5a8d4 177 cpp_bin_float& operator=(const cpp_bin_float<D, B, A, E, MinE, MaxE>& f)
7c673cae 178 {
92f5a8d4 179 switch (eval_fpclassify(f))
7c673cae
FG
180 {
181 case FP_ZERO:
92f5a8d4
TL
182 m_data = limb_type(0);
183 m_sign = f.sign();
7c673cae
FG
184 m_exponent = exponent_zero;
185 break;
186 case FP_NAN:
92f5a8d4
TL
187 m_data = limb_type(0);
188 m_sign = false;
7c673cae 189 m_exponent = exponent_nan;
92f5a8d4
TL
190 break;
191 ;
7c673cae 192 case FP_INFINITE:
92f5a8d4
TL
193 m_data = limb_type(0);
194 m_sign = f.sign();
7c673cae
FG
195 m_exponent = exponent_infinity;
196 break;
197 default:
198 typename cpp_bin_float<D, B, A, E, MinE, MaxE>::rep_type b(f.bits());
11fdf7f2 199 this->exponent() = f.exponent() + (E)bit_count - (E)cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count;
92f5a8d4 200 this->sign() = f.sign();
7c673cae
FG
201 copy_and_round(*this, b);
202 }
203 return *this;
204 }
b32b8144 205#ifdef BOOST_HAS_FLOAT128
7c673cae
FG
206 template <class Float>
207 typename boost::enable_if_c<
92f5a8d4
TL
208 (number_category<Float>::value == number_kind_floating_point)
209 //&& (std::numeric_limits<Float>::digits <= (int)bit_count)
210 && ((std::numeric_limits<Float>::radix == 2) || (boost::is_same<Float, __float128>::value)),
211 cpp_bin_float&>::type
212 operator=(const Float& f)
b32b8144
FG
213#else
214 template <class Float>
215 typename boost::enable_if_c<
92f5a8d4
TL
216 (number_category<Float>::value == number_kind_floating_point)
217 //&& (std::numeric_limits<Float>::digits <= (int)bit_count)
218 && (std::numeric_limits<Float>::radix == 2),
219 cpp_bin_float&>::type
220 operator=(const Float& f)
b32b8144 221#endif
7c673cae
FG
222 {
223 return assign_float(f);
224 }
225
b32b8144
FG
226#ifdef BOOST_HAS_FLOAT128
227 template <class Float>
92f5a8d4 228 typename boost::enable_if_c<boost::is_same<Float, __float128>::value, cpp_bin_float&>::type assign_float(Float f)
b32b8144
FG
229 {
230 using default_ops::eval_add;
231 typedef typename boost::multiprecision::detail::canonical<int, cpp_bin_float>::type bf_int_type;
92f5a8d4 232 if (f == 0)
b32b8144 233 {
92f5a8d4
TL
234 m_data = limb_type(0);
235 m_sign = (signbitq(f) > 0);
b32b8144
FG
236 m_exponent = exponent_zero;
237 return *this;
238 }
92f5a8d4 239 else if (isnanq(f))
b32b8144 240 {
92f5a8d4
TL
241 m_data = limb_type(0);
242 m_sign = false;
b32b8144
FG
243 m_exponent = exponent_nan;
244 return *this;
245 }
92f5a8d4 246 else if (isinfq(f))
b32b8144 247 {
92f5a8d4
TL
248 m_data = limb_type(0);
249 m_sign = (f < 0);
b32b8144
FG
250 m_exponent = exponent_infinity;
251 return *this;
252 }
92f5a8d4 253 if (f < 0)
b32b8144
FG
254 {
255 *this = -f;
256 this->negate();
257 return *this;
258 }
259
260 typedef typename mpl::front<unsigned_types>::type ui_type;
92f5a8d4
TL
261 m_data = static_cast<ui_type>(0u);
262 m_sign = false;
b32b8144
FG
263 m_exponent = 0;
264
265 static const int bits = sizeof(int) * CHAR_BIT - 1;
92f5a8d4 266 int e;
b32b8144 267 f = frexpq(f, &e);
92f5a8d4 268 while (f)
b32b8144
FG
269 {
270 f = ldexpq(f, bits);
271 e -= bits;
272 int ipart = (int)truncq(f);
273 f -= ipart;
274 m_exponent += bits;
275 cpp_bin_float t;
276 t = static_cast<bf_int_type>(ipart);
277 eval_add(*this, t);
278 }
279 m_exponent += static_cast<Exponent>(e);
280 return *this;
281 }
282#endif
283#ifdef BOOST_HAS_FLOAT128
284 template <class Float>
285 typename boost::enable_if_c<is_floating_point<Float>::value && !is_same<Float, __float128>::value, cpp_bin_float&>::type assign_float(Float f)
286#else
7c673cae
FG
287 template <class Float>
288 typename boost::enable_if_c<is_floating_point<Float>::value, cpp_bin_float&>::type assign_float(Float f)
b32b8144 289#endif
7c673cae
FG
290 {
291 BOOST_MATH_STD_USING
292 using default_ops::eval_add;
293 typedef typename boost::multiprecision::detail::canonical<int, cpp_bin_float>::type bf_int_type;
294
92f5a8d4 295 switch ((boost::math::fpclassify)(f))
7c673cae
FG
296 {
297 case FP_ZERO:
92f5a8d4
TL
298 m_data = limb_type(0);
299 m_sign = ((boost::math::signbit)(f) > 0);
7c673cae
FG
300 m_exponent = exponent_zero;
301 return *this;
302 case FP_NAN:
92f5a8d4
TL
303 m_data = limb_type(0);
304 m_sign = false;
7c673cae
FG
305 m_exponent = exponent_nan;
306 return *this;
307 case FP_INFINITE:
92f5a8d4
TL
308 m_data = limb_type(0);
309 m_sign = (f < 0);
7c673cae
FG
310 m_exponent = exponent_infinity;
311 return *this;
312 }
92f5a8d4 313 if (f < 0)
7c673cae
FG
314 {
315 *this = -f;
316 this->negate();
317 return *this;
318 }
319
320 typedef typename mpl::front<unsigned_types>::type ui_type;
92f5a8d4
TL
321 m_data = static_cast<ui_type>(0u);
322 m_sign = false;
7c673cae
FG
323 m_exponent = 0;
324
325 static const int bits = sizeof(int) * CHAR_BIT - 1;
92f5a8d4 326 int e;
7c673cae 327 f = frexp(f, &e);
92f5a8d4 328 while (f)
7c673cae
FG
329 {
330 f = ldexp(f, bits);
331 e -= bits;
332#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
333 int ipart = itrunc(f);
334#else
335 int ipart = static_cast<int>(f);
336#endif
337 f -= ipart;
338 m_exponent += bits;
339 cpp_bin_float t;
340 t = static_cast<bf_int_type>(ipart);
341 eval_add(*this, t);
342 }
343 m_exponent += static_cast<Exponent>(e);
344 return *this;
345 }
346
347 template <class Float>
348 typename boost::enable_if_c<
92f5a8d4
TL
349 (number_category<Float>::value == number_kind_floating_point) && !boost::is_floating_point<Float>::value && (number_category<Float>::value == number_kind_floating_point),
350 cpp_bin_float&>::type
351 assign_float(Float f)
7c673cae
FG
352 {
353 BOOST_MATH_STD_USING
354 using default_ops::eval_add;
7c673cae 355 using default_ops::eval_convert_to;
92f5a8d4 356 using default_ops::eval_get_sign;
7c673cae
FG
357 using default_ops::eval_subtract;
358
92f5a8d4 359 typedef typename boost::multiprecision::detail::canonical<int, Float>::type f_int_type;
7c673cae
FG
360 typedef typename boost::multiprecision::detail::canonical<int, cpp_bin_float>::type bf_int_type;
361
92f5a8d4 362 switch (eval_fpclassify(f))
7c673cae
FG
363 {
364 case FP_ZERO:
92f5a8d4
TL
365 m_data = limb_type(0);
366 m_sign = (eval_get_sign(f) > 0);
7c673cae
FG
367 m_exponent = exponent_zero;
368 return *this;
369 case FP_NAN:
92f5a8d4
TL
370 m_data = limb_type(0);
371 m_sign = false;
7c673cae
FG
372 m_exponent = exponent_nan;
373 return *this;
374 case FP_INFINITE:
92f5a8d4
TL
375 m_data = limb_type(0);
376 m_sign = eval_get_sign(f) < 0;
7c673cae
FG
377 m_exponent = exponent_infinity;
378 return *this;
379 }
92f5a8d4 380 if (eval_get_sign(f) < 0)
7c673cae
FG
381 {
382 f.negate();
20effc67 383 assign_float(f);
7c673cae
FG
384 this->negate();
385 return *this;
386 }
387
388 typedef typename mpl::front<unsigned_types>::type ui_type;
92f5a8d4
TL
389 m_data = static_cast<ui_type>(0u);
390 m_sign = false;
7c673cae
FG
391 m_exponent = 0;
392
393 static const int bits = sizeof(int) * CHAR_BIT - 1;
92f5a8d4 394 int e;
7c673cae 395 eval_frexp(f, f, &e);
92f5a8d4 396 while (eval_get_sign(f) != 0)
7c673cae
FG
397 {
398 eval_ldexp(f, f, bits);
399 e -= bits;
400 int ipart;
401 eval_convert_to(&ipart, f);
402 eval_subtract(f, static_cast<f_int_type>(ipart));
403 m_exponent += bits;
404 eval_add(*this, static_cast<bf_int_type>(ipart));
405 }
406 m_exponent += e;
92f5a8d4 407 if (m_exponent > max_exponent)
7c673cae 408 m_exponent = exponent_infinity;
92f5a8d4 409 if (m_exponent < min_exponent)
7c673cae 410 {
92f5a8d4 411 m_data = limb_type(0u);
7c673cae 412 m_exponent = exponent_zero;
92f5a8d4 413 m_sign = (eval_get_sign(f) > 0);
7c673cae 414 }
92f5a8d4 415 else if (eval_get_sign(m_data) == 0)
7c673cae
FG
416 {
417 m_exponent = exponent_zero;
92f5a8d4 418 m_sign = (eval_get_sign(f) > 0);
7c673cae
FG
419 }
420 return *this;
421 }
92f5a8d4
TL
422 template <class B, expression_template_option et>
423 cpp_bin_float& assign_float(const number<B, et>& f)
424 {
425 return assign_float(f.backend());
426 }
427
7c673cae
FG
428 template <class I>
429 typename boost::enable_if<is_integral<I>, cpp_bin_float&>::type operator=(const I& i)
430 {
431 using default_ops::eval_bit_test;
92f5a8d4 432 if (!i)
7c673cae 433 {
92f5a8d4 434 m_data = static_cast<limb_type>(0);
7c673cae 435 m_exponent = exponent_zero;
92f5a8d4 436 m_sign = false;
7c673cae
FG
437 }
438 else
439 {
92f5a8d4
TL
440 typedef typename make_unsigned<I>::type ui_type;
441 ui_type fi = static_cast<ui_type>(boost::multiprecision::detail::unsigned_abs(i));
7c673cae 442 typedef typename boost::multiprecision::detail::canonical<ui_type, rep_type>::type ar_type;
92f5a8d4 443 m_data = static_cast<ar_type>(fi);
7c673cae 444 unsigned shift = msb(fi);
92f5a8d4 445 if (shift >= bit_count)
7c673cae
FG
446 {
447 m_exponent = static_cast<Exponent>(shift);
92f5a8d4 448 m_data = static_cast<ar_type>(fi >> (shift + 1 - bit_count));
7c673cae
FG
449 }
450 else
451 {
452 m_exponent = static_cast<Exponent>(shift);
453 eval_left_shift(m_data, bit_count - shift - 1);
454 }
92f5a8d4 455 BOOST_ASSERT(eval_bit_test(m_data, bit_count - 1));
7c673cae
FG
456 m_sign = detail::is_negative(i);
457 }
458 return *this;
459 }
460
92f5a8d4 461 cpp_bin_float& operator=(const char* s);
7c673cae 462
92f5a8d4 463 void swap(cpp_bin_float& o) BOOST_NOEXCEPT
7c673cae
FG
464 {
465 m_data.swap(o.m_data);
466 std::swap(m_exponent, o.m_exponent);
467 std::swap(m_sign, o.m_sign);
468 }
469
470 std::string str(std::streamsize dig, std::ios_base::fmtflags f) const;
471
472 void negate()
473 {
92f5a8d4 474 if (m_exponent != exponent_nan)
7c673cae
FG
475 m_sign = !m_sign;
476 }
477
92f5a8d4 478 int compare(const cpp_bin_float& o) const BOOST_NOEXCEPT
7c673cae 479 {
92f5a8d4 480 if (m_sign != o.m_sign)
7c673cae
FG
481 return (m_exponent == exponent_zero) && (m_exponent == o.m_exponent) ? 0 : m_sign ? -1 : 1;
482 int result;
92f5a8d4 483 if (m_exponent == exponent_nan)
7c673cae 484 return -1;
92f5a8d4 485 else if (m_exponent != o.m_exponent)
7c673cae 486 {
92f5a8d4 487 if (m_exponent == exponent_zero)
7c673cae 488 result = -1;
92f5a8d4 489 else if (o.m_exponent == exponent_zero)
7c673cae 490 result = 1;
92f5a8d4 491 else
7c673cae
FG
492 result = m_exponent > o.m_exponent ? 1 : -1;
493 }
494 else
495 result = m_data.compare(o.m_data);
92f5a8d4 496 if (m_sign)
7c673cae
FG
497 result = -result;
498 return result;
499 }
500 template <class A>
501 int compare(const A& o) const BOOST_NOEXCEPT
502 {
503 cpp_bin_float b;
504 b = o;
505 return compare(b);
506 }
507
92f5a8d4
TL
508 rep_type& bits() { return m_data; }
509 const rep_type& bits() const { return m_data; }
510 exponent_type& exponent() { return m_exponent; }
511 const exponent_type& exponent() const { return m_exponent; }
512 bool& sign() { return m_sign; }
513 const bool& sign() const { return m_sign; }
514 void check_invariants()
7c673cae
FG
515 {
516 using default_ops::eval_bit_test;
517 using default_ops::eval_is_zero;
92f5a8d4 518 if ((m_exponent <= max_exponent) && (m_exponent >= min_exponent))
7c673cae
FG
519 {
520 BOOST_ASSERT(eval_bit_test(m_data, bit_count - 1));
521 }
522 else
523 {
524 BOOST_ASSERT(m_exponent > max_exponent);
525 BOOST_ASSERT(m_exponent <= exponent_nan);
526 BOOST_ASSERT(eval_is_zero(m_data));
527 }
528 }
92f5a8d4
TL
529 template <class Archive>
530 void serialize(Archive& ar, const unsigned int /*version*/)
7c673cae 531 {
92f5a8d4
TL
532 ar& boost::make_nvp("data", m_data);
533 ar& boost::make_nvp("exponent", m_exponent);
534 ar& boost::make_nvp("sign", m_sign);
7c673cae
FG
535 }
536};
537
538#ifdef BOOST_MSVC
539#pragma warning(pop)
540#endif
541
542template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class Int>
92f5a8d4 543inline void copy_and_round(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, Int& arg, int bits_to_keep = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
7c673cae
FG
544{
545 // Precondition: exponent of res must have been set before this function is called
b32b8144 546 // as we may need to adjust it based on how many bits_to_keep in arg are set.
7c673cae 547 using default_ops::eval_bit_test;
7c673cae 548 using default_ops::eval_get_sign;
92f5a8d4
TL
549 using default_ops::eval_increment;
550 using default_ops::eval_left_shift;
551 using default_ops::eval_lsb;
552 using default_ops::eval_msb;
553 using default_ops::eval_right_shift;
7c673cae
FG
554
555 // cancellation may have resulted in arg being all zeros:
92f5a8d4 556 if (eval_get_sign(arg) == 0)
7c673cae
FG
557 {
558 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
92f5a8d4
TL
559 res.sign() = false;
560 res.bits() = static_cast<limb_type>(0u);
7c673cae
FG
561 return;
562 }
563 int msb = eval_msb(arg);
92f5a8d4 564 if (static_cast<int>(bits_to_keep) > msb + 1)
7c673cae 565 {
b32b8144
FG
566 // Must have had cancellation in subtraction,
567 // or be converting from a narrower type, so shift left:
7c673cae 568 res.bits() = arg;
b32b8144
FG
569 eval_left_shift(res.bits(), bits_to_keep - msb - 1);
570 res.exponent() -= static_cast<Exponent>(bits_to_keep - msb - 1);
7c673cae 571 }
92f5a8d4 572 else if (static_cast<int>(bits_to_keep) < msb + 1)
7c673cae 573 {
92f5a8d4 574 // We have more bits_to_keep than we need, so round as required,
7c673cae 575 // first get the rounding bit:
b32b8144 576 bool roundup = eval_bit_test(arg, msb - bits_to_keep);
7c673cae 577 // Then check for a tie:
92f5a8d4 578 if (roundup && (msb - bits_to_keep == (int)eval_lsb(arg)))
7c673cae
FG
579 {
580 // Ties round towards even:
92f5a8d4 581 if (!eval_bit_test(arg, msb - bits_to_keep + 1))
7c673cae
FG
582 roundup = false;
583 }
b32b8144
FG
584 // Shift off the bits_to_keep we don't need:
585 eval_right_shift(arg, msb - bits_to_keep + 1);
586 res.exponent() += static_cast<Exponent>(msb - bits_to_keep + 1);
92f5a8d4 587 if (roundup)
7c673cae
FG
588 {
589 eval_increment(arg);
92f5a8d4 590 if (bits_to_keep)
7c673cae 591 {
92f5a8d4 592 if (eval_bit_test(arg, bits_to_keep))
b32b8144
FG
593 {
594 // This happens very very rairly, all the bits left after
595 // truncation must be 1's and we're rounding up an order of magnitude:
596 eval_right_shift(arg, 1u);
597 ++res.exponent();
598 }
599 }
600 else
601 {
602 // We get here when bits_to_keep is zero but we're rounding up,
603 // as a result we end up with a single digit that is a 1:
604 ++bits_to_keep;
7c673cae
FG
605 }
606 }
92f5a8d4 607 if (bits_to_keep != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
b32b8144
FG
608 {
609 // Normalize result when we're rounding to fewer bits than we can hold, only happens in conversions
610 // to narrower types:
611 eval_left_shift(arg, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - bits_to_keep);
612 res.exponent() -= static_cast<Exponent>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - bits_to_keep);
613 }
7c673cae
FG
614 res.bits() = arg;
615 }
616 else
617 {
618 res.bits() = arg;
619 }
92f5a8d4 620 if (!bits_to_keep && !res.bits().limbs()[0])
b32b8144
FG
621 {
622 // We're keeping zero bits and did not round up, so result is zero:
623 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
624 return;
625 }
626 // Result must be normalized:
627 BOOST_ASSERT(((int)eval_msb(res.bits()) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1));
7c673cae 628
92f5a8d4 629 if (res.exponent() > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
7c673cae
FG
630 {
631 // Overflow:
632 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
92f5a8d4 633 res.bits() = static_cast<limb_type>(0u);
7c673cae 634 }
92f5a8d4 635 else if (res.exponent() < cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent)
7c673cae
FG
636 {
637 // Underflow:
638 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
92f5a8d4 639 res.bits() = static_cast<limb_type>(0u);
7c673cae
FG
640 }
641}
642
643template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
92f5a8d4 644inline 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)
7c673cae 645{
92f5a8d4 646 if (a.exponent() < b.exponent())
7c673cae
FG
647 {
648 bool s = a.sign();
649 do_eval_add(res, b, a);
92f5a8d4 650 if (res.sign() != s)
7c673cae
FG
651 res.negate();
652 return;
653 }
654
655 using default_ops::eval_add;
656 using default_ops::eval_bit_test;
657
658 typedef typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type exponent_type;
659
660 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type dt;
661
662 // Special cases first:
92f5a8d4 663 switch (a.exponent())
7c673cae
FG
664 {
665 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
666 {
92f5a8d4
TL
667 bool s = a.sign();
668 res = b;
7c673cae
FG
669 res.sign() = s;
670 return;
671 }
672 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
92f5a8d4 673 if (b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan)
7c673cae
FG
674 res = b;
675 else
676 res = a;
677 return; // result is still infinite.
678 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
679 res = a;
680 return; // result is still a NaN.
681 }
92f5a8d4 682 switch (b.exponent())
7c673cae
FG
683 {
684 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
685 res = a;
686 return;
687 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
688 res = b;
92f5a8d4 689 if (res.sign())
7c673cae
FG
690 res.negate();
691 return; // result is infinite.
692 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
693 res = b;
694 return; // result is a NaN.
695 }
696
697 BOOST_STATIC_ASSERT(boost::integer_traits<exponent_type>::const_max - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent);
698
699 bool s = a.sign();
92f5a8d4
TL
700 dt = a.bits();
701 if (a.exponent() > (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + b.exponent())
7c673cae
FG
702 {
703 res.exponent() = a.exponent();
704 }
705 else
706 {
707 exponent_type e_diff = a.exponent() - b.exponent();
708 BOOST_ASSERT(e_diff >= 0);
709 eval_left_shift(dt, e_diff);
710 res.exponent() = a.exponent() - e_diff;
711 eval_add(dt, b.bits());
712 }
92f5a8d4 713
7c673cae
FG
714 copy_and_round(res, dt);
715 res.check_invariants();
92f5a8d4 716 if (res.sign() != s)
7c673cae
FG
717 res.negate();
718}
719
720template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
92f5a8d4 721inline 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)
7c673cae 722{
7c673cae 723 using default_ops::eval_bit_test;
b32b8144 724 using default_ops::eval_decrement;
92f5a8d4 725 using default_ops::eval_subtract;
7c673cae
FG
726
727 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type dt;
92f5a8d4 728
7c673cae 729 // Special cases first:
92f5a8d4 730 switch (a.exponent())
7c673cae
FG
731 {
732 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
92f5a8d4 733 if (b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan)
7c673cae
FG
734 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
735 else
736 {
737 bool s = a.sign();
92f5a8d4
TL
738 res = b;
739 if (res.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero)
7c673cae 740 res.sign() = false;
92f5a8d4 741 else if (res.sign() == s)
7c673cae
FG
742 res.negate();
743 }
744 return;
745 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
92f5a8d4 746 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))
7c673cae
FG
747 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
748 else
749 res = a;
750 return;
751 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
752 res = a;
753 return; // result is still a NaN.
754 }
92f5a8d4 755 switch (b.exponent())
7c673cae
FG
756 {
757 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
758 res = a;
759 return;
760 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
761 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
92f5a8d4
TL
762 res.sign() = !a.sign();
763 res.bits() = static_cast<limb_type>(0u);
7c673cae
FG
764 return; // result is a NaN.
765 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
766 res = b;
767 return; // result is still a NaN.
768 }
769
770 bool s = a.sign();
92f5a8d4 771 if ((a.exponent() > b.exponent()) || ((a.exponent() == b.exponent()) && a.bits().compare(b.bits()) >= 0))
7c673cae
FG
772 {
773 dt = a.bits();
92f5a8d4 774 if (a.exponent() <= (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + b.exponent())
7c673cae
FG
775 {
776 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type e_diff = a.exponent() - b.exponent();
777 eval_left_shift(dt, e_diff);
778 res.exponent() = a.exponent() - e_diff;
779 eval_subtract(dt, b.bits());
780 }
92f5a8d4 781 else if (a.exponent() == (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + b.exponent() + 1)
b32b8144 782 {
20effc67
TL
783 if ((eval_lsb(a.bits()) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1)
784 && (eval_lsb(b.bits()) != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1))
b32b8144
FG
785 {
786 eval_left_shift(dt, 1);
787 eval_decrement(dt);
788 res.exponent() = a.exponent() - 1;
789 }
790 else
791 res.exponent() = a.exponent();
792 }
7c673cae
FG
793 else
794 res.exponent() = a.exponent();
795 }
796 else
797 {
798 dt = b.bits();
92f5a8d4 799 if (b.exponent() <= (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + a.exponent())
7c673cae
FG
800 {
801 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type e_diff = a.exponent() - b.exponent();
802 eval_left_shift(dt, -e_diff);
803 res.exponent() = b.exponent() + e_diff;
804 eval_subtract(dt, a.bits());
805 }
92f5a8d4 806 else if (b.exponent() == (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + a.exponent() + 1)
b32b8144 807 {
20effc67
TL
808 if ((eval_lsb(a.bits()) != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1)
809 && eval_lsb(b.bits()))
b32b8144
FG
810 {
811 eval_left_shift(dt, 1);
812 eval_decrement(dt);
813 res.exponent() = b.exponent() - 1;
814 }
815 else
816 res.exponent() = b.exponent();
817 }
7c673cae
FG
818 else
819 res.exponent() = b.exponent();
820 s = !s;
821 }
92f5a8d4 822
7c673cae 823 copy_and_round(res, dt);
92f5a8d4 824 if (res.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero)
7c673cae 825 res.sign() = false;
92f5a8d4 826 else if (res.sign() != s)
7c673cae
FG
827 res.negate();
828 res.check_invariants();
829}
830
831template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
92f5a8d4 832inline 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)
7c673cae 833{
92f5a8d4 834 if (a.sign() == b.sign())
7c673cae
FG
835 do_eval_add(res, a, b);
836 else
837 do_eval_subtract(res, a, b);
838}
839
840template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
92f5a8d4 841inline void eval_add(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& a)
7c673cae
FG
842{
843 return eval_add(res, res, a);
844}
845
846template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
92f5a8d4 847inline 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)
7c673cae 848{
92f5a8d4 849 if (a.sign() != b.sign())
7c673cae
FG
850 do_eval_add(res, a, b);
851 else
852 do_eval_subtract(res, a, b);
853}
854
855template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
92f5a8d4 856inline void eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& a)
7c673cae
FG
857{
858 return eval_subtract(res, res, a);
859}
860
861template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
92f5a8d4 862inline 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)
7c673cae
FG
863{
864 using default_ops::eval_bit_test;
865 using default_ops::eval_multiply;
866
867 // Special cases first:
92f5a8d4 868 switch (a.exponent())
7c673cae
FG
869 {
870 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
871 {
92f5a8d4 872 if (b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan)
7c673cae 873 res = b;
92f5a8d4 874 else if (b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity)
7c673cae
FG
875 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
876 else
877 {
92f5a8d4
TL
878 bool s = a.sign() != b.sign();
879 res = a;
7c673cae
FG
880 res.sign() = s;
881 }
882 return;
883 }
884 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
92f5a8d4 885 switch (b.exponent())
7c673cae
FG
886 {
887 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
888 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
889 break;
890 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
891 res = b;
892 break;
893 default:
92f5a8d4
TL
894 bool s = a.sign() != b.sign();
895 res = a;
7c673cae
FG
896 res.sign() = s;
897 break;
898 }
899 return;
900 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
901 res = a;
902 return;
903 }
92f5a8d4 904 if (b.exponent() > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
7c673cae 905 {
92f5a8d4
TL
906 bool s = a.sign() != b.sign();
907 res = b;
7c673cae
FG
908 res.sign() = s;
909 return;
910 }
92f5a8d4 911 if ((a.exponent() > 0) && (b.exponent() > 0))
7c673cae 912 {
92f5a8d4 913 if (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent + 2 - a.exponent() < b.exponent())
7c673cae
FG
914 {
915 // We will certainly overflow:
92f5a8d4 916 bool s = a.sign() != b.sign();
7c673cae 917 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
92f5a8d4
TL
918 res.sign() = s;
919 res.bits() = static_cast<limb_type>(0u);
7c673cae
FG
920 return;
921 }
922 }
92f5a8d4 923 if ((a.exponent() < 0) && (b.exponent() < 0))
7c673cae 924 {
92f5a8d4 925 if (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent - 2 - a.exponent() > b.exponent())
7c673cae
FG
926 {
927 // We will certainly underflow:
928 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
92f5a8d4
TL
929 res.sign() = a.sign() != b.sign();
930 res.bits() = static_cast<limb_type>(0u);
7c673cae
FG
931 return;
932 }
933 }
934
935 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type dt;
936 eval_multiply(dt, a.bits(), b.bits());
11fdf7f2 937 res.exponent() = a.exponent() + b.exponent() - (Exponent)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 1;
7c673cae
FG
938 copy_and_round(res, dt);
939 res.check_invariants();
940 res.sign() = a.sign() != b.sign();
941}
942
943template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
92f5a8d4 944inline void eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& a)
7c673cae
FG
945{
946 eval_multiply(res, res, a);
947}
948
949template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class U>
92f5a8d4 950inline 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)
7c673cae
FG
951{
952 using default_ops::eval_bit_test;
953 using default_ops::eval_multiply;
954
955 // Special cases first:
92f5a8d4 956 switch (a.exponent())
7c673cae
FG
957 {
958 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
959 {
92f5a8d4
TL
960 bool s = a.sign();
961 res = a;
7c673cae
FG
962 res.sign() = s;
963 return;
964 }
965 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
92f5a8d4 966 if (b == 0)
7c673cae
FG
967 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
968 else
969 res = a;
970 return;
971 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
972 res = a;
973 return;
974 }
975
92f5a8d4 976 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type dt;
7c673cae
FG
977 typedef typename boost::multiprecision::detail::canonical<U, typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type>::type canon_ui_type;
978 eval_multiply(dt, a.bits(), static_cast<canon_ui_type>(b));
979 res.exponent() = a.exponent();
980 copy_and_round(res, dt);
981 res.check_invariants();
982 res.sign() = a.sign();
983}
984
985template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class U>
92f5a8d4 986inline typename enable_if_c<is_unsigned<U>::value>::type eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const U& b)
7c673cae
FG
987{
988 eval_multiply(res, res, b);
989}
990
991template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class S>
92f5a8d4 992inline 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)
7c673cae
FG
993{
994 typedef typename make_unsigned<S>::type ui_type;
995 eval_multiply(res, a, static_cast<ui_type>(boost::multiprecision::detail::unsigned_abs(b)));
92f5a8d4 996 if (b < 0)
7c673cae
FG
997 res.negate();
998}
999
1000template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class S>
92f5a8d4 1001inline typename enable_if_c<is_signed<S>::value>::type eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const S& b)
7c673cae
FG
1002{
1003 eval_multiply(res, res, b);
1004}
1005
1006template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
92f5a8d4 1007inline 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)
7c673cae
FG
1008{
1009#ifdef BOOST_MSVC
1010#pragma warning(push)
92f5a8d4 1011#pragma warning(disable : 6326) // comparison of two constants
7c673cae 1012#endif
7c673cae
FG
1013 using default_ops::eval_bit_test;
1014 using default_ops::eval_get_sign;
1015 using default_ops::eval_increment;
92f5a8d4
TL
1016 using default_ops::eval_qr;
1017 using default_ops::eval_subtract;
7c673cae
FG
1018
1019 //
1020 // Special cases first:
1021 //
92f5a8d4 1022 switch (u.exponent())
7c673cae
FG
1023 {
1024 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
1025 {
92f5a8d4 1026 switch (v.exponent())
7c673cae
FG
1027 {
1028 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
1029 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
1030 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
1031 return;
1032 }
92f5a8d4
TL
1033 bool s = u.sign() != v.sign();
1034 res = u;
7c673cae
FG
1035 res.sign() = s;
1036 return;
1037 }
1038 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
1039 {
92f5a8d4 1040 switch (v.exponent())
7c673cae
FG
1041 {
1042 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
1043 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
1044 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
1045 return;
1046 }
92f5a8d4
TL
1047 bool s = u.sign() != v.sign();
1048 res = u;
7c673cae
FG
1049 res.sign() = s;
1050 return;
1051 }
1052 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
1053 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
1054 return;
1055 }
92f5a8d4 1056 switch (v.exponent())
7c673cae
FG
1057 {
1058 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
92f5a8d4
TL
1059 {
1060 bool s = u.sign() != v.sign();
1061 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
7c673cae
FG
1062 res.sign() = s;
1063 return;
92f5a8d4 1064 }
7c673cae
FG
1065 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
1066 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
92f5a8d4
TL
1067 res.bits() = limb_type(0);
1068 res.sign() = u.sign() != v.sign();
7c673cae
FG
1069 return;
1070 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
1071 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
1072 return;
1073 }
1074
1075 // We can scale u and v so that both are integers, then perform integer
1076 // division to obtain quotient q and remainder r, such that:
1077 //
1078 // q * v + r = u
1079 //
1080 // and hense:
1081 //
1082 // q + r/v = u/v
1083 //
92f5a8d4 1084 // From this, assuming q has cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count
7c673cae 1085 // bits we only need to determine whether
92f5a8d4 1086 // r/v is less than, equal to, or greater than 0.5 to determine rounding -
7c673cae
FG
1087 // this we can do with a shift and comparison.
1088 //
1089 // We can set the exponent and sign of the result up front:
1090 //
92f5a8d4 1091 if ((v.exponent() < 0) && (u.exponent() > 0))
7c673cae
FG
1092 {
1093 // Check for overflow:
92f5a8d4 1094 if (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent + v.exponent() < u.exponent() - 1)
7c673cae
FG
1095 {
1096 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
92f5a8d4
TL
1097 res.sign() = u.sign() != v.sign();
1098 res.bits() = static_cast<limb_type>(0u);
7c673cae
FG
1099 return;
1100 }
1101 }
92f5a8d4 1102 else if ((v.exponent() > 0) && (u.exponent() < 0))
7c673cae
FG
1103 {
1104 // Check for underflow:
92f5a8d4 1105 if (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent + v.exponent() > u.exponent())
7c673cae
FG
1106 {
1107 // We will certainly underflow:
1108 res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
92f5a8d4
TL
1109 res.sign() = u.sign() != v.sign();
1110 res.bits() = static_cast<limb_type>(0u);
7c673cae
FG
1111 return;
1112 }
1113 }
1114 res.exponent() = u.exponent() - v.exponent() - 1;
92f5a8d4 1115 res.sign() = u.sign() != v.sign();
7c673cae
FG
1116 //
1117 // Now get the quotient and remainder:
1118 //
1119 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type t(u.bits()), t2(v.bits()), q, r;
1120 eval_left_shift(t, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count);
1121 eval_qr(t, t2, q, r);
1122 //
92f5a8d4
TL
1123 // We now have either "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count"
1124 // or "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count+1" significant
7c673cae
FG
1125 // bits in q.
1126 //
1127 static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT;
92f5a8d4 1128 if (eval_bit_test(q, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count))
7c673cae
FG
1129 {
1130 //
92f5a8d4 1131 // OK we have cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count+1 bits,
7c673cae
FG
1132 // so we already have rounding info,
1133 // we just need to changes things if the last bit is 1 and either the
1134 // remainder is non-zero (ie we do not have a tie) or the quotient would
1135 // be odd if it were shifted to the correct number of bits (ie a tiebreak).
1136 //
1137 BOOST_ASSERT((eval_msb(q) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count));
92f5a8d4 1138 if ((q.limbs()[0] & 1u) && (eval_get_sign(r) || (q.limbs()[0] & 2u)))
7c673cae
FG
1139 {
1140 eval_increment(q);
1141 }
1142 }
1143 else
1144 {
1145 //
1146 // We have exactly "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count" bits in q.
1147 // Get rounding info, which we can get by comparing 2r with v.
1148 // We want to call copy_and_round to handle rounding and general cleanup,
1149 // so we'll left shift q and add some fake digits on the end to represent
1150 // how we'll be rounding.
1151 //
1152 BOOST_ASSERT((eval_msb(q) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1));
1153 static const unsigned lshift = (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count < limb_bits) ? 2 : limb_bits;
1154 eval_left_shift(q, lshift);
1155 res.exponent() -= lshift;
1156 eval_left_shift(r, 1u);
1157 int c = r.compare(v.bits());
92f5a8d4 1158 if (c == 0)
7c673cae 1159 q.limbs()[0] |= static_cast<limb_type>(1u) << (lshift - 1);
92f5a8d4 1160 else if (c > 0)
7c673cae
FG
1161 q.limbs()[0] |= (static_cast<limb_type>(1u) << (lshift - 1)) + static_cast<limb_type>(1u);
1162 }
1163 copy_and_round(res, q);
1164#ifdef BOOST_MSVC
1165#pragma warning(pop)
1166#endif
1167}
1168
1169template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
92f5a8d4 1170inline void eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
7c673cae
FG
1171{
1172 eval_divide(res, res, arg);
1173}
1174
1175template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class U>
92f5a8d4 1176inline 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)
7c673cae
FG
1177{
1178#ifdef BOOST_MSVC
1179#pragma warning(push)
92f5a8d4 1180#pragma warning(disable : 6326) // comparison of two constants
7c673cae 1181#endif
7c673cae
FG
1182 using default_ops::eval_bit_test;
1183 using default_ops::eval_get_sign;
1184 using default_ops::eval_increment;
92f5a8d4
TL
1185 using default_ops::eval_qr;
1186 using default_ops::eval_subtract;
7c673cae
FG
1187
1188 //
1189 // Special cases first:
1190 //
92f5a8d4 1191 switch (u.exponent())
7c673cae
FG
1192 {
1193 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
1194 {
92f5a8d4 1195 if (v == 0)
7c673cae
FG
1196 {
1197 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
1198 return;
1199 }
92f5a8d4
TL
1200 bool s = u.sign() != (v < 0);
1201 res = u;
7c673cae
FG
1202 res.sign() = s;
1203 return;
1204 }
1205 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
1206 res = u;
1207 return;
1208 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
1209 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
1210 return;
1211 }
92f5a8d4 1212 if (v == 0)
7c673cae 1213 {
92f5a8d4
TL
1214 bool s = u.sign();
1215 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
7c673cae
FG
1216 res.sign() = s;
1217 return;
1218 }
1219
1220 // We can scale u and v so that both are integers, then perform integer
1221 // division to obtain quotient q and remainder r, such that:
1222 //
1223 // q * v + r = u
1224 //
1225 // and hense:
1226 //
1227 // q + r/v = u/v
1228 //
1229 // 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
92f5a8d4 1230 // r/v is less than, equal to, or greater than 0.5 to determine rounding -
7c673cae
FG
1231 // this we can do with a shift and comparison.
1232 //
1233 // We can set the exponent and sign of the result up front:
1234 //
92f5a8d4 1235 int gb = msb(v);
7c673cae 1236 res.exponent() = u.exponent() - static_cast<Exponent>(gb) - static_cast<Exponent>(1);
92f5a8d4 1237 res.sign() = u.sign();
7c673cae
FG
1238 //
1239 // Now get the quotient and remainder:
1240 //
1241 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type t(u.bits()), q, r;
1242 eval_left_shift(t, gb + 1);
1243 eval_qr(t, number<typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type>::canonical_value(v), q, r);
1244 //
1245 // 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.
1246 //
1247 static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT;
92f5a8d4 1248 if (eval_bit_test(q, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count))
7c673cae
FG
1249 {
1250 //
1251 // 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,
1252 // we just need to changes things if the last bit is 1 and the
1253 // remainder is non-zero (ie we do not have a tie).
1254 //
1255 BOOST_ASSERT((eval_msb(q) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count));
92f5a8d4 1256 if ((q.limbs()[0] & 1u) && eval_get_sign(r))
7c673cae
FG
1257 {
1258 eval_increment(q);
1259 }
1260 }
1261 else
1262 {
1263 //
1264 // 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.
1265 // Get rounding info, which we can get by comparing 2r with v.
1266 // We want to call copy_and_round to handle rounding and general cleanup,
1267 // 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
1268 // how we'll be rounding.
1269 //
1270 BOOST_ASSERT((eval_msb(q) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1));
1271 static const unsigned lshift = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count < limb_bits ? 2 : limb_bits;
1272 eval_left_shift(q, lshift);
1273 res.exponent() -= lshift;
1274 eval_left_shift(r, 1u);
1275 int c = r.compare(number<typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type>::canonical_value(v));
92f5a8d4 1276 if (c == 0)
7c673cae 1277 q.limbs()[0] |= static_cast<limb_type>(1u) << (lshift - 1);
92f5a8d4 1278 else if (c > 0)
7c673cae
FG
1279 q.limbs()[0] |= (static_cast<limb_type>(1u) << (lshift - 1)) + static_cast<limb_type>(1u);
1280 }
1281 copy_and_round(res, q);
1282#ifdef BOOST_MSVC
1283#pragma warning(pop)
1284#endif
1285}
1286
1287template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class U>
92f5a8d4 1288inline typename enable_if_c<is_unsigned<U>::value>::type eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const U& v)
7c673cae
FG
1289{
1290 eval_divide(res, res, v);
1291}
1292
1293template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class S>
92f5a8d4 1294inline 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)
7c673cae
FG
1295{
1296 typedef typename make_unsigned<S>::type ui_type;
1297 eval_divide(res, u, static_cast<ui_type>(boost::multiprecision::detail::unsigned_abs(v)));
92f5a8d4 1298 if (v < 0)
7c673cae
FG
1299 res.negate();
1300}
1301
1302template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class S>
92f5a8d4 1303inline typename enable_if_c<is_signed<S>::value>::type eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const S& v)
7c673cae
FG
1304{
1305 eval_divide(res, res, v);
1306}
1307
1308template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
92f5a8d4 1309inline int eval_get_sign(const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
7c673cae
FG
1310{
1311 return arg.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero ? 0 : arg.sign() ? -1 : 1;
1312}
1313
1314template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
92f5a8d4 1315inline bool eval_is_zero(const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
7c673cae
FG
1316{
1317 return arg.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
1318}
1319
1320template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
92f5a8d4 1321inline bool eval_eq(const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& a, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& b)
7c673cae 1322{
92f5a8d4 1323 if (a.exponent() == b.exponent())
7c673cae 1324 {
92f5a8d4 1325 if (a.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero)
7c673cae 1326 return true;
92f5a8d4 1327 return (a.sign() == b.sign()) && (a.bits().compare(b.bits()) == 0) && (a.exponent() != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan);
7c673cae
FG
1328 }
1329 return false;
1330}
1331
1332template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
92f5a8d4 1333inline void eval_convert_to(boost::long_long_type* res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
7c673cae 1334{
92f5a8d4 1335 switch (arg.exponent())
7c673cae
FG
1336 {
1337 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
1338 *res = 0;
1339 return;
1340 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
1341 BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
1342 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
1343 *res = (std::numeric_limits<boost::long_long_type>::max)();
92f5a8d4 1344 if (arg.sign())
7c673cae
FG
1345 *res = -*res;
1346 return;
1347 }
92f5a8d4
TL
1348 typedef 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_type;
1349 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::rep_type man(arg.bits());
1350 shift_type shift = (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 - arg.exponent();
1351 if (shift > (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1)
7c673cae
FG
1352 {
1353 *res = 0;
1354 return;
1355 }
92f5a8d4 1356 if (arg.sign() && (arg.compare((std::numeric_limits<boost::long_long_type>::min)()) <= 0))
7c673cae
FG
1357 {
1358 *res = (std::numeric_limits<boost::long_long_type>::min)();
1359 return;
1360 }
92f5a8d4 1361 else if (!arg.sign() && (arg.compare((std::numeric_limits<boost::long_long_type>::max)()) >= 0))
7c673cae
FG
1362 {
1363 *res = (std::numeric_limits<boost::long_long_type>::max)();
1364 return;
1365 }
11fdf7f2
TL
1366
1367 if (shift < 0)
1368 {
1369 if (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - shift <= std::numeric_limits<boost::long_long_type>::digits)
1370 {
1371 // We have more bits in long_long_type than the float, so it's OK to left shift:
1372 eval_convert_to(res, man);
1373 *res <<= -shift;
1374 }
1375 else
1376 {
1377 *res = (std::numeric_limits<boost::long_long_type>::max)();
1378 return;
1379 }
1380 }
1381 else
1382 {
1383 eval_right_shift(man, shift);
1384 eval_convert_to(res, man);
1385 }
92f5a8d4 1386 if (arg.sign())
7c673cae
FG
1387 {
1388 *res = -*res;
1389 }
1390}
1391
1392template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
92f5a8d4 1393inline void eval_convert_to(boost::ulong_long_type* res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
7c673cae 1394{
92f5a8d4 1395 switch (arg.exponent())
7c673cae
FG
1396 {
1397 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
1398 *res = 0;
1399 return;
1400 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
1401 BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer."));
1402 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
1403 *res = (std::numeric_limits<boost::ulong_long_type>::max)();
1404 return;
1405 }
92f5a8d4
TL
1406 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::rep_type man(arg.bits());
1407 typedef 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_type;
1408 shift_type shift = (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 - arg.exponent();
1409 if (shift > (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1)
7c673cae
FG
1410 {
1411 *res = 0;
1412 return;
1413 }
92f5a8d4 1414 else if (shift < 0)
7c673cae 1415 {
11fdf7f2
TL
1416 if (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - shift <= std::numeric_limits<boost::ulong_long_type>::digits)
1417 {
1418 // We have more bits in ulong_long_type than the float, so it's OK to left shift:
1419 eval_convert_to(res, man);
1420 *res <<= -shift;
1421 return;
1422 }
1423 *res = (std::numeric_limits<boost::ulong_long_type>::max)();
7c673cae
FG
1424 return;
1425 }
1426 eval_right_shift(man, shift);
1427 eval_convert_to(res, man);
1428}
1429
1430template <class Float, unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
92f5a8d4 1431inline typename boost::enable_if_c<boost::is_float<Float>::value>::type eval_convert_to(Float* res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& original_arg)
7c673cae 1432{
92f5a8d4
TL
1433 typedef cpp_bin_float<std::numeric_limits<Float>::digits, digit_base_2, void, Exponent, MinE, MaxE> conv_type;
1434 typedef typename common_type<typename conv_type::exponent_type, int>::type common_exp_type;
b32b8144
FG
1435 //
1436 // Special cases first:
1437 //
92f5a8d4 1438 switch (original_arg.exponent())
7c673cae 1439 {
b32b8144 1440 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
7c673cae 1441 *res = 0;
92f5a8d4 1442 if (original_arg.sign())
7c673cae
FG
1443 *res = -*res;
1444 return;
b32b8144 1445 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
7c673cae
FG
1446 *res = std::numeric_limits<Float>::quiet_NaN();
1447 return;
b32b8144 1448 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
7c673cae 1449 *res = (std::numeric_limits<Float>::infinity)();
92f5a8d4 1450 if (original_arg.sign())
7c673cae
FG
1451 *res = -*res;
1452 return;
1453 }
b32b8144
FG
1454 //
1455 // Check for super large exponent that must be converted to infinity:
1456 //
92f5a8d4 1457 if (original_arg.exponent() > std::numeric_limits<Float>::max_exponent)
7c673cae 1458 {
b32b8144 1459 *res = std::numeric_limits<Float>::has_infinity ? std::numeric_limits<Float>::infinity() : (std::numeric_limits<Float>::max)();
92f5a8d4 1460 if (original_arg.sign())
b32b8144 1461 *res = -*res;
7c673cae
FG
1462 return;
1463 }
b32b8144 1464 //
92f5a8d4 1465 // Figure out how many digits we will have in our result,
b32b8144
FG
1466 // allowing for a possibly denormalized result:
1467 //
1468 common_exp_type digits_to_round_to = std::numeric_limits<Float>::digits;
92f5a8d4 1469 if (original_arg.exponent() < std::numeric_limits<Float>::min_exponent - 1)
7c673cae 1470 {
b32b8144
FG
1471 common_exp_type diff = original_arg.exponent();
1472 diff -= std::numeric_limits<Float>::min_exponent - 1;
1473 digits_to_round_to += diff;
7c673cae 1474 }
92f5a8d4 1475 if (digits_to_round_to < 0)
7c673cae 1476 {
b32b8144
FG
1477 // Result must be zero:
1478 *res = 0;
92f5a8d4 1479 if (original_arg.sign())
b32b8144
FG
1480 *res = -*res;
1481 return;
1482 }
1483 //
1484 // Perform rounding first, then afterwards extract the digits:
1485 //
1486 cpp_bin_float<std::numeric_limits<Float>::digits, digit_base_2, Allocator, Exponent, MinE, MaxE> arg;
92f5a8d4 1487 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::rep_type bits(original_arg.bits());
b32b8144
FG
1488 arg.exponent() = original_arg.exponent();
1489 copy_and_round(arg, bits, (int)digits_to_round_to);
1490 common_exp_type e = arg.exponent();
1491 e -= cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1;
92f5a8d4
TL
1492 static const unsigned limbs_needed = std::numeric_limits<Float>::digits / (sizeof(*arg.bits().limbs()) * CHAR_BIT) + (std::numeric_limits<Float>::digits % (sizeof(*arg.bits().limbs()) * CHAR_BIT) ? 1 : 0);
1493 unsigned first_limb_needed = arg.bits().size() - limbs_needed;
1494 *res = 0;
b32b8144 1495 e += first_limb_needed * sizeof(*arg.bits().limbs()) * CHAR_BIT;
92f5a8d4 1496 while (first_limb_needed < arg.bits().size())
b32b8144
FG
1497 {
1498 *res += std::ldexp(static_cast<Float>(arg.bits().limbs()[first_limb_needed]), static_cast<int>(e));
1499 ++first_limb_needed;
7c673cae 1500 e += sizeof(*arg.bits().limbs()) * CHAR_BIT;
7c673cae 1501 }
92f5a8d4 1502 if (original_arg.sign())
7c673cae
FG
1503 *res = -*res;
1504}
1505
1506template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
92f5a8d4 1507inline 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)
7c673cae 1508{
92f5a8d4 1509 switch (arg.exponent())
7c673cae
FG
1510 {
1511 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
1512 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
1513 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
92f5a8d4 1514 *e = 0;
7c673cae
FG
1515 res = arg;
1516 return;
1517 }
92f5a8d4
TL
1518 res = arg;
1519 *e = arg.exponent() + 1;
7c673cae
FG
1520 res.exponent() = -1;
1521}
1522
1523template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class I>
92f5a8d4 1524inline 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)
7c673cae
FG
1525{
1526 Exponent e;
1527 eval_frexp(res, arg, &e);
92f5a8d4 1528 if ((e > (std::numeric_limits<I>::max)()) || (e < (std::numeric_limits<I>::min)()))
7c673cae
FG
1529 {
1530 BOOST_THROW_EXCEPTION(std::runtime_error("Exponent was outside of the range of the argument type to frexp."));
1531 }
1532 *pe = static_cast<I>(e);
1533}
1534
1535template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
92f5a8d4 1536inline 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)
7c673cae 1537{
92f5a8d4 1538 switch (arg.exponent())
7c673cae
FG
1539 {
1540 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
1541 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
1542 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
1543 res = arg;
1544 return;
1545 }
92f5a8d4 1546 if ((e > 0) && (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent - e < arg.exponent()))
7c673cae
FG
1547 {
1548 // Overflow:
92f5a8d4 1549 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
7c673cae
FG
1550 res.sign() = arg.sign();
1551 }
92f5a8d4 1552 else if ((e < 0) && (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent - e > arg.exponent()))
7c673cae
FG
1553 {
1554 // Underflow:
1555 res = limb_type(0);
1556 }
1557 else
1558 {
1559 res = arg;
1560 res.exponent() += e;
1561 }
1562}
1563
1564template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class I>
92f5a8d4 1565inline 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)
7c673cae
FG
1566{
1567 typedef typename make_signed<I>::type si_type;
92f5a8d4 1568 if (e > static_cast<I>((std::numeric_limits<si_type>::max)()))
7c673cae
FG
1569 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
1570 else
1571 eval_ldexp(res, arg, static_cast<si_type>(e));
1572}
1573
1574template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class I>
92f5a8d4 1575inline 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)
7c673cae 1576{
92f5a8d4 1577 if ((e > (std::numeric_limits<Exponent>::max)()) || (e < (std::numeric_limits<Exponent>::min)()))
7c673cae
FG
1578 {
1579 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
92f5a8d4 1580 if (e < 0)
7c673cae
FG
1581 res.negate();
1582 }
1583 else
1584 eval_ldexp(res, arg, static_cast<Exponent>(e));
1585}
1586
1587/*
1588* Sign manipulation
1589*/
1590
1591template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
92f5a8d4 1592inline void eval_abs(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
7c673cae 1593{
92f5a8d4 1594 res = arg;
7c673cae
FG
1595 res.sign() = false;
1596}
1597
1598template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
92f5a8d4 1599inline void eval_fabs(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
7c673cae 1600{
92f5a8d4 1601 res = arg;
7c673cae
FG
1602 res.sign() = false;
1603}
1604
1605template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
92f5a8d4 1606inline int eval_fpclassify(const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
7c673cae 1607{
92f5a8d4 1608 switch (arg.exponent())
7c673cae
FG
1609 {
1610 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
1611 return FP_ZERO;
1612 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
1613 return FP_INFINITE;
1614 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
1615 return FP_NAN;
1616 }
1617 return FP_NORMAL;
1618}
1619
1620template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
92f5a8d4 1621inline void eval_sqrt(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
7c673cae 1622{
7c673cae
FG
1623 using default_ops::eval_bit_test;
1624 using default_ops::eval_increment;
92f5a8d4
TL
1625 using default_ops::eval_integer_sqrt;
1626 switch (arg.exponent())
7c673cae 1627 {
7c673cae 1628 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
b32b8144
FG
1629 errno = EDOM;
1630 // fallthrough...
1631 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
7c673cae
FG
1632 res = arg;
1633 return;
1634 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
92f5a8d4 1635 if (arg.sign())
b32b8144 1636 {
92f5a8d4 1637 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
b32b8144
FG
1638 errno = EDOM;
1639 }
7c673cae
FG
1640 else
1641 res = arg;
1642 return;
1643 }
92f5a8d4 1644 if (arg.sign())
7c673cae 1645 {
92f5a8d4 1646 res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
b32b8144 1647 errno = EDOM;
7c673cae
FG
1648 return;
1649 }
1650
1651 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type t(arg.bits()), r, s;
1652 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);
1653 eval_integer_sqrt(s, r, t);
1654
92f5a8d4 1655 if (!eval_bit_test(s, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count))
7c673cae
FG
1656 {
1657 // We have exactly the right number of cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count in the result, round as required:
92f5a8d4 1658 if (s.compare(r) < 0)
7c673cae
FG
1659 {
1660 eval_increment(s);
1661 }
1662 }
1663 typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type ae = arg.exponent();
92f5a8d4 1664 res.exponent() = ae / 2;
20effc67 1665 res.sign() = false;
92f5a8d4 1666 if ((ae & 1) && (ae < 0))
7c673cae
FG
1667 --res.exponent();
1668 copy_and_round(res, s);
1669}
1670
1671template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
92f5a8d4 1672inline void eval_floor(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
7c673cae
FG
1673{
1674 using default_ops::eval_increment;
92f5a8d4 1675 switch (arg.exponent())
7c673cae 1676 {
7c673cae 1677 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
b32b8144
FG
1678 errno = EDOM;
1679 // fallthrough...
1680 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
7c673cae
FG
1681 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
1682 res = arg;
1683 return;
1684 }
92f5a8d4
TL
1685 typedef 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_type;
1686 shift_type shift =
1687 (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - arg.exponent() - 1;
1688 if ((arg.exponent() > (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent) || (shift <= 0))
7c673cae
FG
1689 {
1690 // Either arg is already an integer, or a special value:
1691 res = arg;
1692 return;
1693 }
92f5a8d4 1694 if (shift >= (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
7c673cae
FG
1695 {
1696 res = static_cast<signed_limb_type>(arg.sign() ? -1 : 0);
1697 return;
1698 }
11fdf7f2 1699 bool fractional = (shift_type)eval_lsb(arg.bits()) < shift;
92f5a8d4 1700 res = arg;
7c673cae 1701 eval_right_shift(res.bits(), shift);
92f5a8d4 1702 if (fractional && res.sign())
7c673cae
FG
1703 {
1704 eval_increment(res.bits());
92f5a8d4 1705 if (eval_msb(res.bits()) != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 - shift)
7c673cae
FG
1706 {
1707 // Must have extended result by one bit in the increment:
1708 --shift;
1709 ++res.exponent();
1710 }
1711 }
1712 eval_left_shift(res.bits(), shift);
1713}
1714
1715template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
92f5a8d4 1716inline void eval_ceil(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg)
7c673cae
FG
1717{
1718 using default_ops::eval_increment;
92f5a8d4 1719 switch (arg.exponent())
7c673cae 1720 {
b32b8144
FG
1721 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity:
1722 errno = EDOM;
1723 // fallthrough...
7c673cae
FG
1724 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero:
1725 case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan:
7c673cae
FG
1726 res = arg;
1727 return;
1728 }
92f5a8d4
TL
1729 typedef 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_type;
1730 shift_type shift = (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - arg.exponent() - 1;
1731 if ((arg.exponent() > (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent) || (shift <= 0))
7c673cae
FG
1732 {
1733 // Either arg is already an integer, or a special value:
1734 res = arg;
1735 return;
1736 }
92f5a8d4 1737 if (shift >= (shift_type)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)
7c673cae 1738 {
92f5a8d4
TL
1739 bool s = arg.sign(); // takes care of signed zeros
1740 res = static_cast<signed_limb_type>(arg.sign() ? 0 : 1);
7c673cae
FG
1741 res.sign() = s;
1742 return;
1743 }
11fdf7f2 1744 bool fractional = (shift_type)eval_lsb(arg.bits()) < shift;
92f5a8d4 1745 res = arg;
7c673cae 1746 eval_right_shift(res.bits(), shift);
92f5a8d4 1747 if (fractional && !res.sign())
7c673cae
FG
1748 {
1749 eval_increment(res.bits());
92f5a8d4 1750 if (eval_msb(res.bits()) != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 - shift)
7c673cae
FG
1751 {
1752 // Must have extended result by one bit in the increment:
1753 --shift;
1754 ++res.exponent();
1755 }
1756 }
1757 eval_left_shift(res.bits(), shift);
1758}
1759
92f5a8d4 1760template <unsigned D1, backends::digit_base_type B1, class A1, class E1, E1 M1, E1 M2>
b32b8144
FG
1761int eval_signbit(const cpp_bin_float<D1, B1, A1, E1, M1, M2>& val)
1762{
1763 return val.sign();
1764}
1765
92f5a8d4 1766template <unsigned D1, backends::digit_base_type B1, class A1, class E1, E1 M1, E1 M2>
7c673cae
FG
1767inline std::size_t hash_value(const cpp_bin_float<D1, B1, A1, E1, M1, M2>& val)
1768{
1769 std::size_t result = hash_value(val.bits());
1770 boost::hash_combine(result, val.exponent());
1771 boost::hash_combine(result, val.sign());
1772 return result;
1773}
1774
7c673cae
FG
1775} // namespace backends
1776
92f5a8d4 1777namespace detail {
7c673cae 1778
20effc67
TL
1779template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinExponent, Exponent MaxExponent>
1780struct transcendental_reduction_type<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinExponent, MaxExponent> >
1781{
1782 //
1783 // The type used for trigonometric reduction needs 3 times the precision of the base type.
1784 // This is double the precision of the original type, plus the largest exponent supported.
1785 // As a practical measure the largest argument supported is 1/eps, as supporting larger
1786 // arguments requires the division of argument by PI/2 to also be done at higher precision,
1787 // otherwise the result (an integer) can not be represented exactly.
1788 //
1789 // See ARGUMENT REDUCTION FOR HUGE ARGUMENTS. K C Ng.
1790 //
1791 typedef boost::multiprecision::backends::cpp_bin_float<
1792 boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinExponent, MaxExponent>::bit_count * 3,
1793 boost::multiprecision::backends::digit_base_2,
1794 Allocator, Exponent, MinExponent, MaxExponent> type;
1795};
1796
1797#ifdef BOOST_NO_SFINAE_EXPR
1798
92f5a8d4
TL
1799template <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>
1800struct 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_
1801{};
1802template <class FloatT, unsigned D2, backends::digit_base_type B2, class A2, class E2, E2 M3, E2 M4>
1803struct is_explicitly_convertible<FloatT, backends::cpp_bin_float<D2, B2, A2, E2, M3, M4> > : public boost::is_floating_point<FloatT>
1804{};
7c673cae 1805
7c673cae
FG
1806#endif
1807
20effc67
TL
1808} // namespace detail
1809
92f5a8d4 1810template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Exponent, Exponent MinE, Exponent MaxE, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
7c673cae 1811inline boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates>
92f5a8d4
TL
1812 copysign BOOST_PREVENT_MACRO_SUBSTITUTION(
1813 const boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates>& a,
1814 const boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates>& b)
7c673cae
FG
1815{
1816 boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> res(a);
1817 res.backend().sign() = b.backend().sign();
1818 return res;
1819}
1820
1821using backends::cpp_bin_float;
7c673cae 1822using backends::digit_base_10;
92f5a8d4 1823using backends::digit_base_2;
7c673cae 1824
92f5a8d4
TL
1825template <unsigned Digits, backends::digit_base_type DigitBase, class Exponent, Exponent MinE, Exponent MaxE, class Allocator>
1826struct number_category<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > : public boost::mpl::int_<boost::multiprecision::number_kind_floating_point>
1827{};
7c673cae 1828
92f5a8d4 1829template <unsigned Digits, backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
7c673cae
FG
1830struct expression_template_default<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> >
1831{
1832 static const expression_template_option value = is_void<Allocator>::value ? et_off : et_on;
1833};
1834
92f5a8d4 1835typedef number<backends::cpp_bin_float<50> > cpp_bin_float_50;
7c673cae
FG
1836typedef number<backends::cpp_bin_float<100> > cpp_bin_float_100;
1837
92f5a8d4
TL
1838typedef number<backends::cpp_bin_float<24, backends::digit_base_2, void, boost::int16_t, -126, 127>, et_off> cpp_bin_float_single;
1839typedef number<backends::cpp_bin_float<53, backends::digit_base_2, void, boost::int16_t, -1022, 1023>, et_off> cpp_bin_float_double;
1840typedef number<backends::cpp_bin_float<64, backends::digit_base_2, void, boost::int16_t, -16382, 16383>, et_off> cpp_bin_float_double_extended;
1841typedef number<backends::cpp_bin_float<113, backends::digit_base_2, void, boost::int16_t, -16382, 16383>, et_off> cpp_bin_float_quad;
1842typedef number<backends::cpp_bin_float<237, backends::digit_base_2, void, boost::int32_t, -262142, 262143>, et_off> cpp_bin_float_oct;
7c673cae
FG
1843
1844} // namespace multiprecision
1845
1846namespace math {
1847
92f5a8d4
TL
1848using boost::multiprecision::copysign;
1849using boost::multiprecision::signbit;
7c673cae
FG
1850
1851} // namespace math
1852
1853} // namespace boost
1854
1855#include <boost/multiprecision/cpp_bin_float/io.hpp>
1856#include <boost/multiprecision/cpp_bin_float/transcendental.hpp>
1857
92f5a8d4 1858namespace std {
7c673cae
FG
1859
1860//
1861// numeric_limits [partial] specializations for the types declared in this header:
1862//
92f5a8d4 1863template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
7c673cae
FG
1864class numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >
1865{
1866 typedef boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> number_type;
92f5a8d4
TL
1867
1868 public:
7c673cae 1869 BOOST_STATIC_CONSTEXPR bool is_specialized = true;
92f5a8d4 1870 static number_type(min)()
7c673cae
FG
1871 {
1872 initializer.do_nothing();
1873 static std::pair<bool, number_type> value;
92f5a8d4 1874 if (!value.first)
7c673cae
FG
1875 {
1876 value.first = true;
11fdf7f2 1877 typedef typename boost::mpl::front<typename number_type::backend_type::unsigned_types>::type ui_type;
92f5a8d4 1878 value.second.backend() = ui_type(1u);
7c673cae
FG
1879 value.second.backend().exponent() = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent;
1880 }
1881 return value.second;
1882 }
92f5a8d4 1883 static number_type(max)()
7c673cae
FG
1884 {
1885 initializer.do_nothing();
1886 static std::pair<bool, number_type> value;
92f5a8d4 1887 if (!value.first)
7c673cae
FG
1888 {
1889 value.first = true;
92f5a8d4 1890 if (boost::is_void<Allocator>::value)
11fdf7f2
TL
1891 eval_complement(value.second.backend().bits(), value.second.backend().bits());
1892 else
1893 {
92f5a8d4 1894 // We jump through hoops here using the backend type directly just to keep VC12 happy
11fdf7f2
TL
1895 // (ie compiler workaround, for very strange compiler bug):
1896 using boost::multiprecision::default_ops::eval_add;
1897 using boost::multiprecision::default_ops::eval_decrement;
1898 using boost::multiprecision::default_ops::eval_left_shift;
92f5a8d4 1899 typedef typename number_type::backend_type::rep_type int_backend_type;
11fdf7f2 1900 typedef typename boost::mpl::front<typename int_backend_type::unsigned_types>::type ui_type;
92f5a8d4 1901 int_backend_type i;
11fdf7f2
TL
1902 i = ui_type(1u);
1903 eval_left_shift(i, boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1);
1904 int_backend_type j(i);
1905 eval_decrement(i);
1906 eval_add(j, i);
1907 value.second.backend().bits() = j;
1908 }
7c673cae
FG
1909 value.second.backend().exponent() = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent;
1910 }
1911 return value.second;
1912 }
1913 BOOST_STATIC_CONSTEXPR number_type lowest()
1914 {
1915 return -(max)();
1916 }
92f5a8d4 1917 BOOST_STATIC_CONSTEXPR int digits = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count;
20effc67 1918 BOOST_STATIC_CONSTEXPR int digits10 = boost::multiprecision::detail::calc_digits10<digits>::value;
7c673cae 1919 // Is this really correct???
20effc67 1920 BOOST_STATIC_CONSTEXPR int max_digits10 = boost::multiprecision::detail::calc_max_digits10<digits>::value;
92f5a8d4
TL
1921 BOOST_STATIC_CONSTEXPR bool is_signed = true;
1922 BOOST_STATIC_CONSTEXPR bool is_integer = false;
1923 BOOST_STATIC_CONSTEXPR bool is_exact = false;
1924 BOOST_STATIC_CONSTEXPR int radix = 2;
1925 static number_type epsilon()
7c673cae
FG
1926 {
1927 initializer.do_nothing();
1928 static std::pair<bool, number_type> value;
92f5a8d4 1929 if (!value.first)
7c673cae 1930 {
11fdf7f2
TL
1931 // We jump through hoops here just to keep VC12 happy (ie compiler workaround, for very strange compiler bug):
1932 typedef typename boost::mpl::front<typename number_type::backend_type::unsigned_types>::type ui_type;
92f5a8d4 1933 value.first = true;
11fdf7f2 1934 value.second.backend() = ui_type(1u);
92f5a8d4 1935 value.second = ldexp(value.second, 1 - (int)digits);
7c673cae
FG
1936 }
1937 return value.second;
1938 }
1939 // What value should this be????
1940 static number_type round_error()
1941 {
1942 // returns 0.5
1943 initializer.do_nothing();
1944 static std::pair<bool, number_type> value;
92f5a8d4 1945 if (!value.first)
7c673cae
FG
1946 {
1947 value.first = true;
11fdf7f2
TL
1948 // We jump through hoops here just to keep VC12 happy (ie compiler workaround, for very strange compiler bug):
1949 typedef typename boost::mpl::front<typename number_type::backend_type::unsigned_types>::type ui_type;
1950 value.second.backend() = ui_type(1u);
92f5a8d4 1951 value.second = ldexp(value.second, -1);
7c673cae
FG
1952 }
1953 return value.second;
1954 }
92f5a8d4
TL
1955 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;
1956 BOOST_STATIC_CONSTEXPR typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type min_exponent10 = (min_exponent / 1000) * 301L;
1957 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;
1958 BOOST_STATIC_CONSTEXPR typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type max_exponent10 = (max_exponent / 1000) * 301L;
1959 BOOST_STATIC_CONSTEXPR bool has_infinity = true;
1960 BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = true;
1961 BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false;
1962 BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent;
1963 BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false;
1964 static number_type infinity()
7c673cae
FG
1965 {
1966 initializer.do_nothing();
1967 static std::pair<bool, number_type> value;
92f5a8d4 1968 if (!value.first)
7c673cae 1969 {
92f5a8d4 1970 value.first = true;
7c673cae
FG
1971 value.second.backend().exponent() = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
1972 }
1973 return value.second;
1974 }
1975 static number_type quiet_NaN()
1976 {
1977 initializer.do_nothing();
1978 static std::pair<bool, number_type> value;
92f5a8d4 1979 if (!value.first)
7c673cae 1980 {
92f5a8d4 1981 value.first = true;
7c673cae
FG
1982 value.second.backend().exponent() = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan;
1983 }
1984 return value.second;
1985 }
1986 BOOST_STATIC_CONSTEXPR number_type signaling_NaN()
1987 {
1988 return number_type(0);
1989 }
1990 BOOST_STATIC_CONSTEXPR number_type denorm_min() { return number_type(0); }
92f5a8d4
TL
1991 BOOST_STATIC_CONSTEXPR bool is_iec559 = false;
1992 BOOST_STATIC_CONSTEXPR bool is_bounded = true;
1993 BOOST_STATIC_CONSTEXPR bool is_modulo = false;
1994 BOOST_STATIC_CONSTEXPR bool traps = true;
1995 BOOST_STATIC_CONSTEXPR bool tinyness_before = false;
7c673cae 1996 BOOST_STATIC_CONSTEXPR float_round_style round_style = round_to_nearest;
92f5a8d4
TL
1997
1998 private:
7c673cae
FG
1999 struct data_initializer
2000 {
2001 data_initializer()
2002 {
2003 std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::epsilon();
2004 std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::round_error();
2005 (std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::min)();
2006 (std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::max)();
2007 std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity();
2008 std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN();
2009 }
92f5a8d4 2010 void do_nothing() const {}
7c673cae
FG
2011 };
2012 static const data_initializer initializer;
2013};
2014
92f5a8d4 2015template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
7c673cae
FG
2016const 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;
2017
2018#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
2019
2020template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2021BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::digits;
2022template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2023BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::digits10;
2024template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2025BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::max_digits10;
2026template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2027BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_signed;
2028template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2029BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_integer;
2030template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2031BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_exact;
2032template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2033BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::radix;
2034template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2035BOOST_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;
2036template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2037BOOST_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;
2038template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2039BOOST_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;
2040template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2041BOOST_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;
2042template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2043BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_infinity;
2044template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2045BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_quiet_NaN;
2046template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2047BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_signaling_NaN;
2048template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2049BOOST_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;
2050template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2051BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_denorm_loss;
2052template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2053BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_iec559;
2054template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2055BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_bounded;
2056template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2057BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_modulo;
2058template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2059BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::traps;
2060template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2061BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::tinyness_before;
2062template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates>
2063BOOST_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;
2064
2065#endif
2066
2067} // namespace std
2068
2069#endif