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 | |
43 | namespace boost { |
44 | namespace multiprecision { |
45 | namespace 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 | |
52 | namespace detail { |
53 | |
54 | template <class U> |
55 | inline typename std::enable_if<boost::multiprecision::detail::is_unsigned<U>::value, bool>::type is_negative(U) { return false; } |
56 | template <class S> |
57 | inline typename std::enable_if< !boost::multiprecision::detail::is_unsigned<S>::value, bool>::type is_negative(S s) { return s < 0; } |
58 | |
59 | template <class Float, std::ptrdiff_t, bool = number_category<Float>::value == number_kind_floating_point> |
60 | struct is_cpp_bin_float_implicitly_constructible_from_type |
61 | { |
62 | static constexpr bool value = false; |
63 | }; |
64 | |
65 | template <class Float, std::ptrdiff_t bit_count> |
66 | struct 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 | |
75 | template <class Float, std::ptrdiff_t, bool = number_category<Float>::value == number_kind_floating_point> |
76 | struct is_cpp_bin_float_explicitly_constructible_from_type |
77 | { |
78 | static constexpr bool value = false; |
79 | }; |
80 | |
81 | template <class Float, std::ptrdiff_t bit_count> |
82 | struct 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 | |
93 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinExponent, Exponent MaxExponent> |
94 | class 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 | |
665 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class Int> |
666 | inline 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 | |
766 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class BinFloat2, class BinFloat3> |
767 | inline 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 | |
844 | template <class BinFloat1, class BinFloat2, class BinFloat3> |
845 | inline 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 | |
955 | template <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> |
958 | inline 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 | |
968 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, |
969 | class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2> |
970 | inline 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 | |
976 | template <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> |
979 | inline 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 | |
989 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, |
990 | class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2> |
991 | inline 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 | |
997 | template <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> |
1000 | inline 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 | |
1083 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, |
1084 | class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2> |
1085 | inline 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 | |
1091 | template <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> |
1093 | inline 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 | |
1130 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class U> |
1131 | inline 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 | |
1136 | template <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> |
1138 | inline 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 | |
1147 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class S> |
1148 | inline 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 | |
1153 | template <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> |
1156 | inline 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 | |
1322 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, |
1323 | class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2> |
1324 | inline 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 | |
1330 | template <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> |
1332 | inline 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 | |
1446 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class U> |
1447 | inline 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 | |
1452 | template <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> |
1454 | inline 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 | |
1463 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class S> |
1464 | inline 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 | |
1469 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> |
1470 | inline 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 | |
1475 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> |
1476 | inline 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 | |
1481 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> |
1482 | inline bool eval_eq(const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& a, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& b) |
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 | |
1493 | template <class I, unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> |
1494 | inline 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 | |
1559 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> |
1560 | inline 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 |
1566 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> |
1567 | inline 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 | |
1573 | template <class I, unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> |
1574 | inline 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 | |
1614 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> |
1615 | inline 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 |
1621 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> |
1622 | inline 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 | |
1628 | template <class Float, unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> |
1629 | inline 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 | |
1729 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> |
1730 | inline void eval_frexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg, Exponent* e) |
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 | |
1746 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class I> |
1747 | inline void eval_frexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg, I* pe) |
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 | |
1758 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> |
1759 | inline void eval_ldexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg, Exponent e) |
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 | |
1787 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class I> |
1788 | inline 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 | |
1797 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class I> |
1798 | inline 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 | |
1814 | template <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> |
1816 | inline 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 | } |
1821 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> |
1822 | inline void eval_abs(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg) |
1823 | { |
1824 | res = arg; |
1825 | res.sign() = false; |
1826 | } |
1827 | |
1828 | template <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> |
1830 | inline 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 | } |
1835 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> |
1836 | inline void eval_fabs(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg) |
1837 | { |
1838 | res = arg; |
1839 | res.sign() = false; |
1840 | } |
1841 | |
1842 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> |
1843 | inline 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 | |
1857 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> |
1858 | inline void eval_sqrt(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg) |
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 | |
1908 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> |
1909 | inline void eval_floor(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg) |
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 | |
1956 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> |
1957 | inline void eval_ceil(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& arg) |
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 | |
2001 | template <unsigned D1, backends::digit_base_type B1, class A1, class E1, E1 M1, E1 M2> |
2002 | int eval_signbit(const cpp_bin_float<D1, B1, A1, E1, M1, M2>& val) |
2003 | { |
2004 | return val.sign(); |
2005 | } |
2006 | |
2007 | template <unsigned D1, backends::digit_base_type B1, class A1, class E1, E1 M1, E1 M2> |
2008 | inline 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 | |
2017 | namespace detail { |
2018 | |
2019 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinExponent, Exponent MaxExponent> |
2020 | struct 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 |
2037 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinExponent, Exponent MaxExponent> |
2038 | struct is_convertible_arithmetic<int128_type, boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinExponent, MaxExponent> > : public std::true_type |
2039 | {}; |
2040 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinExponent, Exponent MaxExponent> |
2041 | struct 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 | |
2047 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Exponent, Exponent MinE, Exponent MaxE, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates> |
2048 | inline 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 | |
2058 | template <unsigned Digits, backends::digit_base_type DigitBase, class Exponent, Exponent MinE, Exponent MaxE, class Allocator> |
2059 | struct number_category<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > : public std::integral_constant<int, boost::multiprecision::number_kind_floating_point> |
2060 | {}; |
2061 | |
2062 | template <unsigned Digits, backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class Allocator2, class Exponent2, Exponent MinE2, Exponent MaxE2> |
2063 | struct 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 | |
2068 | namespace math { |
2069 | |
2070 | using boost::multiprecision::copysign; |
2071 | using 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 | |
2080 | namespace std { |
2081 | |
2082 | // |
2083 | // numeric_limits [partial] specializations for the types declared in this header: |
2084 | // |
2085 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> |
2086 | class 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 | |
2239 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> |
2240 | constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::digits; |
2241 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> |
2242 | constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::digits10; |
2243 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> |
2244 | constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::max_digits10; |
2245 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> |
2246 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_signed; |
2247 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> |
2248 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_integer; |
2249 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> |
2250 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_exact; |
2251 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> |
2252 | constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::radix; |
2253 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> |
2254 | constexpr 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; |
2255 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> |
2256 | constexpr 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; |
2257 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> |
2258 | constexpr 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; |
2259 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> |
2260 | constexpr 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; |
2261 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> |
2262 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_infinity; |
2263 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> |
2264 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_quiet_NaN; |
2265 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> |
2266 | constexpr 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 |
2271 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> |
2272 | constexpr 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 |
2276 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> |
2277 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_denorm_loss; |
2278 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> |
2279 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_iec559; |
2280 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> |
2281 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_bounded; |
2282 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> |
2283 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_modulo; |
2284 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> |
2285 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::traps; |
2286 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> |
2287 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::tinyness_before; |
2288 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> |
2289 | constexpr 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 | |