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

source code of boost/libs/multiprecision/include/boost/multiprecision/cpp_bin_float.hpp