]>
Commit | Line | Data |
---|---|---|
7c673cae | 1 | /////////////////////////////////////////////////////////////////////////////// |
1e59de90 TL |
2 | // Copyright Christopher Kormanyos 2002 - 2021. |
3 | // Copyright 2011 -2021 John Maddock. Distributed under the Boost | |
7c673cae FG |
4 | // Software License, Version 1.0. (See accompanying file |
5 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | // | |
7 | // This work is based on an earlier work: | |
8 | // "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations", | |
9 | // in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469 | |
10 | // | |
1e59de90 TL |
11 | // There are some "noexcept" specifications on the functions in this file. |
12 | // Unlike in pre-C++11 versions, compilers can now detect noexcept misuse | |
13 | // at compile time, allowing for simple use of it here. | |
7c673cae FG |
14 | // |
15 | ||
16 | #ifndef BOOST_MP_CPP_DEC_FLOAT_BACKEND_HPP | |
17 | #define BOOST_MP_CPP_DEC_FLOAT_BACKEND_HPP | |
18 | ||
1e59de90 TL |
19 | #include <cmath> |
20 | #include <cstdint> | |
21 | #include <cstdlib> | |
22 | #include <algorithm> | |
7c673cae | 23 | #include <array> |
1e59de90 TL |
24 | #include <initializer_list> |
25 | #include <iomanip> | |
26 | #include <string> | |
27 | #include <limits> | |
28 | #include <stdexcept> | |
29 | #include <boost/multiprecision/detail/standalone_config.hpp> | |
7c673cae | 30 | #include <boost/multiprecision/number.hpp> |
1e59de90 | 31 | #include <boost/multiprecision/detail/fpclassify.hpp> |
7c673cae | 32 | #include <boost/multiprecision/detail/dynamic_array.hpp> |
1e59de90 TL |
33 | #include <boost/multiprecision/detail/hash.hpp> |
34 | #include <boost/multiprecision/detail/float128_functions.hpp> | |
f67539c2 | 35 | #include <boost/multiprecision/detail/itos.hpp> |
1e59de90 TL |
36 | #include <boost/multiprecision/detail/static_array.hpp> |
37 | #include <boost/multiprecision/detail/tables.hpp> | |
38 | #include <boost/multiprecision/detail/no_exceptions_support.hpp> | |
39 | #include <boost/multiprecision/detail/assert.hpp> | |
7c673cae | 40 | |
1e59de90 | 41 | #ifdef BOOST_MP_MATH_AVAILABLE |
7c673cae FG |
42 | // |
43 | // Headers required for Boost.Math integration: | |
44 | // | |
45 | #include <boost/math/policies/policy.hpp> | |
46 | // | |
47 | // Some includes we need from Boost.Math, since we rely on that library to provide these functions: | |
48 | // | |
7c673cae | 49 | #include <boost/math/special_functions/acosh.hpp> |
1e59de90 | 50 | #include <boost/math/special_functions/asinh.hpp> |
7c673cae FG |
51 | #include <boost/math/special_functions/atanh.hpp> |
52 | #include <boost/math/special_functions/cbrt.hpp> | |
53 | #include <boost/math/special_functions/expm1.hpp> | |
54 | #include <boost/math/special_functions/gamma.hpp> | |
1e59de90 | 55 | #endif |
7c673cae FG |
56 | |
57 | #ifdef BOOST_MSVC | |
58 | #pragma warning(push) | |
92f5a8d4 | 59 | #pragma warning(disable : 6326) // comparison of two constants |
7c673cae FG |
60 | #endif |
61 | ||
92f5a8d4 TL |
62 | namespace boost { |
63 | namespace multiprecision { | |
64 | namespace backends { | |
7c673cae | 65 | |
1e59de90 | 66 | template <unsigned Digits10, class ExponentType = std::int32_t, class Allocator = void> |
7c673cae FG |
67 | class cpp_dec_float; |
68 | ||
92f5a8d4 | 69 | } // namespace backends |
7c673cae FG |
70 | |
71 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1e59de90 | 72 | struct number_category<backends::cpp_dec_float<Digits10, ExponentType, Allocator> > : public std::integral_constant<int, number_kind_floating_point> |
92f5a8d4 | 73 | {}; |
7c673cae | 74 | |
92f5a8d4 | 75 | namespace backends { |
7c673cae FG |
76 | |
77 | template <unsigned Digits10, class ExponentType, class Allocator> | |
78 | class cpp_dec_float | |
79 | { | |
92f5a8d4 | 80 | private: |
1e59de90 TL |
81 | // Perform some static sanity checks. |
82 | static_assert(boost::multiprecision::detail::is_signed<ExponentType>::value, | |
83 | "ExponentType must be a signed built in integer type."); | |
7c673cae | 84 | |
1e59de90 TL |
85 | static_assert(sizeof(ExponentType) > 1, |
86 | "ExponentType is too small."); | |
87 | ||
88 | static_assert(Digits10 < UINT32_C(0x80000000), | |
89 | "Digits10 exceeds the maximum."); | |
90 | ||
91 | // Private class-local constants. | |
92 | static constexpr std::int32_t cpp_dec_float_digits10_limit_lo = INT32_C(9); | |
93 | static constexpr std::int32_t cpp_dec_float_digits10_limit_hi = static_cast<std::int32_t>((std::numeric_limits<std::int32_t>::max)() - 100); | |
94 | ||
95 | static constexpr std::int32_t cpp_dec_float_elem_digits10 = INT32_C(8); | |
96 | static constexpr std::int32_t cpp_dec_float_elem_mask = INT32_C(100000000); | |
97 | ||
98 | static constexpr std::int32_t cpp_dec_float_elems_for_kara = static_cast<std::int32_t>(128 + 1); | |
7c673cae | 99 | |
92f5a8d4 | 100 | public: |
1e59de90 TL |
101 | using signed_types = std::tuple<long long> ; |
102 | using unsigned_types = std::tuple<unsigned long long>; | |
103 | using float_types = std::tuple<double, long double>; | |
104 | using exponent_type = ExponentType; | |
7c673cae | 105 | |
1e59de90 TL |
106 | // Public class-local constants. |
107 | static constexpr std::int32_t cpp_dec_float_radix = INT32_C(10); | |
108 | static constexpr std::int32_t cpp_dec_float_digits10 = ((static_cast<std::int32_t>(Digits10) < cpp_dec_float_digits10_limit_lo) ? cpp_dec_float_digits10_limit_lo : ((static_cast<std::int32_t>(Digits10) > cpp_dec_float_digits10_limit_hi) ? cpp_dec_float_digits10_limit_hi : static_cast<std::int32_t>(Digits10))); | |
109 | static constexpr exponent_type cpp_dec_float_max_exp10 = (static_cast<exponent_type>(1) << (std::numeric_limits<exponent_type>::digits - 5)); | |
110 | static constexpr exponent_type cpp_dec_float_min_exp10 = -cpp_dec_float_max_exp10; | |
111 | static constexpr exponent_type cpp_dec_float_max_exp = cpp_dec_float_max_exp10; | |
112 | static constexpr exponent_type cpp_dec_float_min_exp = cpp_dec_float_min_exp10; | |
113 | ||
114 | static_assert(cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_max_exp10 == -cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_min_exp10, "Failed exponent range check"); | |
7c673cae | 115 | |
1e59de90 | 116 | static_assert(0 == cpp_dec_float_max_exp10 % cpp_dec_float_elem_digits10, "Failed digit sanity check"); |
7c673cae | 117 | |
1e59de90 | 118 | private: |
7c673cae FG |
119 | // There are three guard limbs. |
120 | // 1) The first limb has 'play' from 1...8 decimal digits. | |
121 | // 2) The last limb also has 'play' from 1...8 decimal digits. | |
1e59de90 TL |
122 | // 3) One limb can get lost when justifying after multiply. |
123 | static constexpr std::int32_t cpp_dec_float_elem_number = static_cast<std::int32_t>(((Digits10 / cpp_dec_float_elem_digits10) + (((Digits10 % cpp_dec_float_elem_digits10) != 0) ? 1 : 0)) + 3); | |
7c673cae | 124 | |
92f5a8d4 | 125 | public: |
1e59de90 | 126 | static constexpr std::int32_t cpp_dec_float_max_digits10 = static_cast<std::int32_t>(cpp_dec_float_elem_number * cpp_dec_float_elem_digits10); |
7c673cae | 127 | |
92f5a8d4 | 128 | private: |
1e59de90 TL |
129 | using array_type = |
130 | typename std::conditional<std::is_void<Allocator>::value, | |
131 | detail::static_array <std::uint32_t, static_cast<std::uint32_t>(cpp_dec_float_elem_number)>, | |
132 | detail::dynamic_array<std::uint32_t, static_cast<std::uint32_t>(cpp_dec_float_elem_number), Allocator> >::type; | |
133 | ||
7c673cae FG |
134 | typedef enum enum_fpclass_type |
135 | { | |
136 | cpp_dec_float_finite, | |
137 | cpp_dec_float_inf, | |
138 | cpp_dec_float_NaN | |
92f5a8d4 | 139 | } fpclass_type; |
7c673cae | 140 | |
1e59de90 TL |
141 | array_type data; |
142 | exponent_type exp; | |
143 | bool neg; | |
144 | fpclass_type fpclass; | |
145 | std::int32_t prec_elem; | |
7c673cae | 146 | |
1e59de90 TL |
147 | // Private constructor from the floating-point class type. |
148 | explicit cpp_dec_float(fpclass_type c) : data(), | |
149 | exp(static_cast<exponent_type>(0)), | |
150 | neg(false), | |
151 | fpclass(c), | |
152 | prec_elem(cpp_dec_float_elem_number) {} | |
7c673cae | 153 | |
1e59de90 TL |
154 | // Constructor from an initializer_list, an optional |
155 | // (value-aligned) exponent and a Boolean sign. | |
156 | static cpp_dec_float from_lst(std::initializer_list<std::uint32_t> lst, | |
157 | const exponent_type e = 0, | |
158 | const bool n = false) | |
92f5a8d4 | 159 | { |
1e59de90 | 160 | cpp_dec_float a; |
7c673cae | 161 | |
1e59de90 TL |
162 | a.data = array_type(lst); |
163 | a.exp = e; | |
164 | a.neg = n; | |
165 | a.fpclass = cpp_dec_float_finite; | |
166 | a.prec_elem = cpp_dec_float_elem_number; | |
7c673cae | 167 | |
1e59de90 TL |
168 | return a; |
169 | } | |
f67539c2 | 170 | |
92f5a8d4 | 171 | public: |
1e59de90 TL |
172 | // Public Constructors |
173 | cpp_dec_float() noexcept(noexcept(array_type())) : data(), | |
174 | exp(static_cast<exponent_type>(0)), | |
175 | neg(false), | |
176 | fpclass(cpp_dec_float_finite), | |
177 | prec_elem(cpp_dec_float_elem_number) {} | |
7c673cae | 178 | |
92f5a8d4 | 179 | cpp_dec_float(const char* s) : data(), |
1e59de90 | 180 | exp(static_cast<exponent_type>(0)), |
92f5a8d4 TL |
181 | neg(false), |
182 | fpclass(cpp_dec_float_finite), | |
183 | prec_elem(cpp_dec_float_elem_number) | |
184 | { | |
185 | *this = s; | |
186 | } | |
7c673cae FG |
187 | |
188 | template <class I> | |
1e59de90 TL |
189 | cpp_dec_float(I i, |
190 | typename std::enable_if<boost::multiprecision::detail::is_unsigned<I>::value && (sizeof(I) <= sizeof(long long))>::type* = nullptr) | |
191 | : data(), | |
192 | exp(static_cast<exponent_type>(0)), | |
193 | neg(false), | |
194 | fpclass(cpp_dec_float_finite), | |
195 | prec_elem(cpp_dec_float_elem_number) | |
92f5a8d4 TL |
196 | { |
197 | from_unsigned_long_long(i); | |
198 | } | |
199 | ||
200 | template <class I> | |
1e59de90 TL |
201 | cpp_dec_float(I i, |
202 | typename std::enable_if<( boost::multiprecision::detail::is_signed<I>::value | |
203 | && boost::multiprecision::detail::is_integral<I>::value | |
204 | && (sizeof(I) <= sizeof(long long)))>::type* = nullptr) | |
205 | : data(), | |
206 | exp(static_cast<exponent_type>(0)), | |
207 | neg(false), | |
208 | fpclass(cpp_dec_float_finite), | |
209 | prec_elem(cpp_dec_float_elem_number) | |
92f5a8d4 TL |
210 | { |
211 | if (i < 0) | |
7c673cae | 212 | { |
92f5a8d4 TL |
213 | from_unsigned_long_long(boost::multiprecision::detail::unsigned_abs(i)); |
214 | negate(); | |
7c673cae | 215 | } |
92f5a8d4 | 216 | else |
1e59de90 | 217 | from_unsigned_long_long(static_cast<unsigned long long>(i)); |
92f5a8d4 | 218 | } |
7c673cae | 219 | |
1e59de90 TL |
220 | cpp_dec_float(const cpp_dec_float& f) noexcept(noexcept(array_type(std::declval<const array_type&>()))) |
221 | : data(f.data), | |
222 | exp(f.exp), | |
223 | neg(f.neg), | |
224 | fpclass(f.fpclass), | |
225 | prec_elem(f.prec_elem) {} | |
7c673cae FG |
226 | |
227 | template <unsigned D, class ET, class A> | |
1e59de90 TL |
228 | cpp_dec_float(const cpp_dec_float<D, ET, A>& f, typename std::enable_if<D <= Digits10>::type* = nullptr) |
229 | : data(), | |
230 | exp(f.exp), | |
231 | neg(f.neg), | |
232 | fpclass(static_cast<fpclass_type>(static_cast<int>(f.fpclass))), | |
233 | prec_elem(cpp_dec_float_elem_number) | |
7c673cae FG |
234 | { |
235 | std::copy(f.data.begin(), f.data.begin() + f.prec_elem, data.begin()); | |
236 | } | |
237 | template <unsigned D, class ET, class A> | |
1e59de90 TL |
238 | explicit cpp_dec_float(const cpp_dec_float<D, ET, A>& f, typename std::enable_if< !(D <= Digits10)>::type* = nullptr) |
239 | : data(), | |
240 | exp(f.exp), | |
241 | neg(f.neg), | |
242 | fpclass(static_cast<fpclass_type>(static_cast<int>(f.fpclass))), | |
243 | prec_elem(cpp_dec_float_elem_number) | |
7c673cae FG |
244 | { |
245 | // TODO: this doesn't round! | |
246 | std::copy(f.data.begin(), f.data.begin() + prec_elem, data.begin()); | |
247 | } | |
248 | ||
249 | template <class F> | |
1e59de90 TL |
250 | cpp_dec_float(const F val, typename std::enable_if<std::is_floating_point<F>::value |
251 | >::type* = nullptr) : data(), | |
252 | exp(static_cast<exponent_type>(0)), | |
253 | neg(false), | |
254 | fpclass(cpp_dec_float_finite), | |
255 | prec_elem(cpp_dec_float_elem_number) | |
7c673cae FG |
256 | { |
257 | *this = val; | |
258 | } | |
259 | ||
1e59de90 | 260 | cpp_dec_float(const double mantissa, const exponent_type exponent); |
7c673cae | 261 | |
92f5a8d4 | 262 | std::size_t hash() const |
7c673cae FG |
263 | { |
264 | std::size_t result = 0; | |
92f5a8d4 | 265 | for (int i = 0; i < prec_elem; ++i) |
1e59de90 TL |
266 | boost::multiprecision::detail::hash_combine(result, data[i]); |
267 | boost::multiprecision::detail::hash_combine(result, exp, neg, static_cast<std::size_t>(fpclass)); | |
7c673cae FG |
268 | return result; |
269 | } | |
270 | ||
271 | // Specific special values. | |
1e59de90 TL |
272 | static const cpp_dec_float& nan () { static const cpp_dec_float val(cpp_dec_float_NaN); return val; } |
273 | static const cpp_dec_float& inf () { static const cpp_dec_float val(cpp_dec_float_inf); return val; } | |
274 | static const cpp_dec_float& (max)() { static const cpp_dec_float val(from_lst({ std::uint32_t(1u) }, cpp_dec_float_max_exp10)); return val; } | |
275 | static const cpp_dec_float& (min)() { static const cpp_dec_float val(from_lst({ std::uint32_t(1u) }, cpp_dec_float_min_exp10)); return val; } | |
276 | static const cpp_dec_float& zero() { static const cpp_dec_float val(from_lst({ std::uint32_t(0u) })); return val; } | |
277 | static const cpp_dec_float& one () { static const cpp_dec_float val(from_lst({ std::uint32_t(1u) })); return val; } | |
278 | static const cpp_dec_float& two () { static const cpp_dec_float val(from_lst({ std::uint32_t(2u) })); return val; } | |
279 | static const cpp_dec_float& half() { static const cpp_dec_float val(from_lst({ std::uint32_t(cpp_dec_float_elem_mask / 2)}, -8)); return val; } | |
280 | ||
281 | static const cpp_dec_float& double_min() { static const cpp_dec_float val((std::numeric_limits<double>::min)()); return val; } | |
282 | static const cpp_dec_float& double_max() { static const cpp_dec_float val((std::numeric_limits<double>::max)()); return val; } | |
7c673cae FG |
283 | |
284 | static const cpp_dec_float& long_double_min() | |
285 | { | |
7c673cae | 286 | #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS |
1e59de90 | 287 | static const cpp_dec_float val(static_cast<long double>((std::numeric_limits<double>::min)())); |
7c673cae | 288 | #else |
1e59de90 | 289 | static const cpp_dec_float val((std::numeric_limits<long double>::min)()); |
7c673cae FG |
290 | #endif |
291 | return val; | |
292 | } | |
293 | ||
294 | static const cpp_dec_float& long_double_max() | |
295 | { | |
7c673cae | 296 | #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS |
1e59de90 | 297 | static const cpp_dec_float val(static_cast<long double>((std::numeric_limits<double>::max)())); |
7c673cae | 298 | #else |
1e59de90 | 299 | static const cpp_dec_float val((std::numeric_limits<long double>::max)()); |
7c673cae FG |
300 | #endif |
301 | return val; | |
302 | } | |
303 | ||
1e59de90 TL |
304 | static const cpp_dec_float& long_long_max () { static const cpp_dec_float val((std::numeric_limits<long long>::max)()); return val; } |
305 | static const cpp_dec_float& long_long_min () { static const cpp_dec_float val((std::numeric_limits<long long>::min)()); return val; } | |
306 | static const cpp_dec_float& ulong_long_max() { static const cpp_dec_float val((std::numeric_limits<unsigned long long>::max)()); return val; } | |
7c673cae FG |
307 | |
308 | static const cpp_dec_float& eps() | |
309 | { | |
1e59de90 TL |
310 | static const cpp_dec_float val |
311 | ( | |
312 | from_lst | |
313 | ( | |
314 | { | |
315 | (std::uint32_t) detail::pow10_maker((std::uint32_t) ((std::int32_t) (INT32_C(1) + (std::int32_t) (((cpp_dec_float_digits10 / cpp_dec_float_elem_digits10) + ((cpp_dec_float_digits10 % cpp_dec_float_elem_digits10) != 0 ? 1 : 0)) * cpp_dec_float_elem_digits10)) - cpp_dec_float_digits10)) | |
316 | }, | |
317 | -(exponent_type) (((cpp_dec_float_digits10 / cpp_dec_float_elem_digits10) + ((cpp_dec_float_digits10 % cpp_dec_float_elem_digits10) != 0 ? 1 : 0)) * cpp_dec_float_elem_digits10) | |
318 | ) | |
319 | ); | |
320 | ||
7c673cae FG |
321 | return val; |
322 | } | |
323 | ||
324 | // Basic operations. | |
1e59de90 | 325 | cpp_dec_float& operator=(const cpp_dec_float& v) noexcept(noexcept(std::declval<array_type&>() = std::declval<const array_type&>())) |
7c673cae | 326 | { |
92f5a8d4 TL |
327 | data = v.data; |
328 | exp = v.exp; | |
329 | neg = v.neg; | |
330 | fpclass = v.fpclass; | |
7c673cae FG |
331 | prec_elem = v.prec_elem; |
332 | return *this; | |
333 | } | |
334 | ||
335 | template <unsigned D> | |
336 | cpp_dec_float& operator=(const cpp_dec_float<D>& f) | |
337 | { | |
92f5a8d4 TL |
338 | exp = f.exp; |
339 | neg = f.neg; | |
340 | fpclass = static_cast<enum_fpclass_type>(static_cast<int>(f.fpclass)); | |
7c673cae FG |
341 | unsigned elems = (std::min)(f.prec_elem, cpp_dec_float_elem_number); |
342 | std::copy(f.data.begin(), f.data.begin() + elems, data.begin()); | |
343 | std::fill(data.begin() + elems, data.end(), 0); | |
344 | prec_elem = cpp_dec_float_elem_number; | |
345 | return *this; | |
346 | } | |
347 | ||
1e59de90 | 348 | cpp_dec_float& operator=(long long v) |
7c673cae | 349 | { |
92f5a8d4 | 350 | if (v < 0) |
7c673cae | 351 | { |
1e59de90 | 352 | from_unsigned_long_long(boost::multiprecision::detail::unsigned_abs(v)); |
7c673cae FG |
353 | negate(); |
354 | } | |
355 | else | |
356 | from_unsigned_long_long(v); | |
357 | return *this; | |
358 | } | |
359 | ||
1e59de90 | 360 | cpp_dec_float& operator=(unsigned long long v) |
7c673cae FG |
361 | { |
362 | from_unsigned_long_long(v); | |
363 | return *this; | |
364 | } | |
1e59de90 TL |
365 | #ifdef BOOST_HAS_INT128 |
366 | cpp_dec_float& operator=(int128_type v) | |
367 | { | |
368 | *this = boost::multiprecision::detail::unsigned_abs(v); | |
369 | if (v < 0) | |
370 | negate(); | |
371 | return *this; | |
372 | } | |
373 | ||
374 | cpp_dec_float& operator=(uint128_type v) | |
375 | { | |
376 | using default_ops::eval_add; | |
377 | using default_ops::eval_multiply; | |
378 | static constexpr unsigned bit_shift = sizeof(unsigned long long) * CHAR_BIT; | |
379 | static constexpr uint128_type mask = (static_cast<uint128_type>(1u) << bit_shift) - 1; | |
380 | unsigned shift = bit_shift; | |
381 | *this = static_cast<unsigned long long>(v & mask); | |
382 | v >>= bit_shift; | |
383 | while (v) | |
384 | { | |
385 | cpp_dec_float t(static_cast<unsigned long long>(v & mask)); | |
386 | eval_multiply(t, cpp_dec_float::pow2(bit_shift)); | |
387 | eval_add(*this, t); | |
388 | v >>= bit_shift; | |
389 | shift += bit_shift; | |
390 | } | |
391 | return *this; | |
392 | } | |
393 | #endif | |
7c673cae | 394 | |
f67539c2 | 395 | template <class Float> |
1e59de90 | 396 | typename std::enable_if<std::is_floating_point<Float>::value, cpp_dec_float&>::type operator=(Float v); |
7c673cae FG |
397 | |
398 | cpp_dec_float& operator=(const char* v) | |
399 | { | |
400 | rd_string(v); | |
401 | return *this; | |
402 | } | |
403 | ||
404 | cpp_dec_float& operator+=(const cpp_dec_float& v); | |
405 | cpp_dec_float& operator-=(const cpp_dec_float& v); | |
406 | cpp_dec_float& operator*=(const cpp_dec_float& v); | |
407 | cpp_dec_float& operator/=(const cpp_dec_float& v); | |
408 | ||
1e59de90 | 409 | cpp_dec_float& add_unsigned_long_long(const unsigned long long n) |
7c673cae FG |
410 | { |
411 | cpp_dec_float t; | |
412 | t.from_unsigned_long_long(n); | |
413 | return *this += t; | |
414 | } | |
415 | ||
1e59de90 | 416 | cpp_dec_float& sub_unsigned_long_long(const unsigned long long n) |
7c673cae FG |
417 | { |
418 | cpp_dec_float t; | |
419 | t.from_unsigned_long_long(n); | |
420 | return *this -= t; | |
421 | } | |
422 | ||
1e59de90 TL |
423 | cpp_dec_float& mul_unsigned_long_long(const unsigned long long n); |
424 | cpp_dec_float& div_unsigned_long_long(const unsigned long long n); | |
7c673cae FG |
425 | |
426 | // Elementary primitives. | |
92f5a8d4 | 427 | cpp_dec_float& calculate_inv(); |
7c673cae FG |
428 | cpp_dec_float& calculate_sqrt(); |
429 | ||
430 | void negate() | |
431 | { | |
92f5a8d4 | 432 | if (!iszero()) |
7c673cae FG |
433 | neg = !neg; |
434 | } | |
435 | ||
436 | // Comparison functions | |
92f5a8d4 TL |
437 | bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION() const { return (fpclass == cpp_dec_float_NaN); } |
438 | bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION() const { return (fpclass == cpp_dec_float_inf); } | |
7c673cae FG |
439 | bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION() const { return (fpclass == cpp_dec_float_finite); } |
440 | ||
92f5a8d4 | 441 | bool iszero() const |
7c673cae FG |
442 | { |
443 | return ((fpclass == cpp_dec_float_finite) && (data[0u] == 0u)); | |
444 | } | |
445 | ||
92f5a8d4 TL |
446 | bool isone() const; |
447 | bool isint() const; | |
448 | bool isneg() const { return neg; } | |
7c673cae FG |
449 | |
450 | // Operators pre-increment and pre-decrement | |
451 | cpp_dec_float& operator++() | |
452 | { | |
453 | return *this += one(); | |
454 | } | |
455 | ||
456 | cpp_dec_float& operator--() | |
457 | { | |
458 | return *this -= one(); | |
459 | } | |
460 | ||
1e59de90 | 461 | std::string str(std::intmax_t digits, std::ios_base::fmtflags f) const; |
7c673cae | 462 | |
92f5a8d4 | 463 | int compare(const cpp_dec_float& v) const; |
7c673cae FG |
464 | |
465 | template <class V> | |
92f5a8d4 | 466 | int compare(const V& v) const |
7c673cae FG |
467 | { |
468 | cpp_dec_float<Digits10, ExponentType, Allocator> t; | |
469 | t = v; | |
470 | return compare(t); | |
471 | } | |
472 | ||
473 | void swap(cpp_dec_float& v) | |
474 | { | |
475 | data.swap(v.data); | |
476 | std::swap(exp, v.exp); | |
477 | std::swap(neg, v.neg); | |
478 | std::swap(fpclass, v.fpclass); | |
479 | std::swap(prec_elem, v.prec_elem); | |
480 | } | |
481 | ||
92f5a8d4 TL |
482 | double extract_double() const; |
483 | long double extract_long_double() const; | |
1e59de90 TL |
484 | long long extract_signed_long_long() const; |
485 | unsigned long long extract_unsigned_long_long() const; | |
486 | #ifdef BOOST_HAS_INT128 | |
487 | int128_type extract_signed_int128() const; | |
488 | uint128_type extract_unsigned_int128() const; | |
489 | #endif | |
490 | void extract_parts(double& mantissa, exponent_type& exponent) const; | |
92f5a8d4 | 491 | cpp_dec_float extract_integer_part() const; |
7c673cae | 492 | |
1e59de90 | 493 | void precision(const std::int32_t prec_digits) |
7c673cae | 494 | { |
1e59de90 TL |
495 | const std::int32_t elems = |
496 | static_cast<std::int32_t>( static_cast<std::int32_t>(prec_digits / cpp_dec_float_elem_digits10) | |
497 | + (((prec_digits % cpp_dec_float_elem_digits10) != 0) ? 1 : 0)); | |
7c673cae | 498 | |
1e59de90 | 499 | prec_elem = (std::min)(cpp_dec_float_elem_number, (std::max)(elems, static_cast<std::int32_t>(2))); |
7c673cae | 500 | } |
1e59de90 TL |
501 | static cpp_dec_float pow2(long long i); |
502 | exponent_type order() const | |
7c673cae | 503 | { |
1e59de90 | 504 | const bool bo_order_is_zero = ((!(isfinite)()) || (data[0] == static_cast<std::uint32_t>(0u))); |
7c673cae FG |
505 | // |
506 | // Binary search to find the order of the leading term: | |
507 | // | |
1e59de90 | 508 | exponent_type prefix = 0; |
7c673cae | 509 | |
92f5a8d4 | 510 | if (data[0] >= 100000UL) |
7c673cae | 511 | { |
92f5a8d4 | 512 | if (data[0] >= 10000000UL) |
7c673cae | 513 | { |
92f5a8d4 | 514 | if (data[0] >= 100000000UL) |
7c673cae | 515 | { |
92f5a8d4 | 516 | if (data[0] >= 1000000000UL) |
7c673cae FG |
517 | prefix = 9; |
518 | else | |
519 | prefix = 8; | |
520 | } | |
521 | else | |
522 | prefix = 7; | |
523 | } | |
524 | else | |
525 | { | |
92f5a8d4 | 526 | if (data[0] >= 1000000UL) |
7c673cae FG |
527 | prefix = 6; |
528 | else | |
529 | prefix = 5; | |
530 | } | |
531 | } | |
532 | else | |
533 | { | |
92f5a8d4 | 534 | if (data[0] >= 1000UL) |
7c673cae | 535 | { |
92f5a8d4 | 536 | if (data[0] >= 10000UL) |
7c673cae FG |
537 | prefix = 4; |
538 | else | |
539 | prefix = 3; | |
540 | } | |
541 | else | |
542 | { | |
92f5a8d4 | 543 | if (data[0] >= 100) |
7c673cae | 544 | prefix = 2; |
92f5a8d4 | 545 | else if (data[0] >= 10) |
7c673cae FG |
546 | prefix = 1; |
547 | } | |
548 | } | |
549 | ||
1e59de90 | 550 | return (bo_order_is_zero ? static_cast<exponent_type>(0) : static_cast<exponent_type>(exp + prefix)); |
7c673cae FG |
551 | } |
552 | ||
1e59de90 | 553 | #ifndef BOOST_MP_STANDALONE |
92f5a8d4 TL |
554 | template <class Archive> |
555 | void serialize(Archive& ar, const unsigned int /*version*/) | |
7c673cae | 556 | { |
92f5a8d4 TL |
557 | for (unsigned i = 0; i < data.size(); ++i) |
558 | ar& boost::make_nvp("digit", data[i]); | |
559 | ar& boost::make_nvp("exponent", exp); | |
560 | ar& boost::make_nvp("sign", neg); | |
561 | ar& boost::make_nvp("class-type", fpclass); | |
562 | ar& boost::make_nvp("precision", prec_elem); | |
7c673cae | 563 | } |
1e59de90 | 564 | #endif |
7c673cae | 565 | |
92f5a8d4 | 566 | private: |
1e59de90 TL |
567 | static bool data_elem_is_non_zero_predicate(const std::uint32_t& d) { return (d != static_cast<std::uint32_t>(0u)); } |
568 | static bool data_elem_is_non_nine_predicate(const std::uint32_t& d) { return (d != static_cast<std::uint32_t>(cpp_dec_float::cpp_dec_float_elem_mask - 1)); } | |
7c673cae FG |
569 | static bool char_is_nonzero_predicate(const char& c) { return (c != static_cast<char>('0')); } |
570 | ||
1e59de90 TL |
571 | void from_unsigned_long_long(const unsigned long long u); |
572 | ||
573 | template <typename InputIteratorTypeLeft, | |
574 | typename InputIteratorTypeRight> | |
575 | static int compare_ranges(InputIteratorTypeLeft a, | |
576 | InputIteratorTypeRight b, | |
577 | const std::uint32_t count = cpp_dec_float_elem_number); | |
578 | ||
579 | static std::uint32_t eval_add_n( std::uint32_t* r, | |
580 | const std::uint32_t* u, | |
581 | const std::uint32_t* v, | |
582 | const std::int32_t count); | |
583 | ||
584 | static std::uint32_t eval_subtract_n( std::uint32_t* r, | |
585 | const std::uint32_t* u, | |
586 | const std::uint32_t* v, | |
587 | const std::int32_t count); | |
588 | ||
589 | static void eval_multiply_n_by_n_to_2n( std::uint32_t* r, | |
590 | const std::uint32_t* a, | |
591 | const std::uint32_t* b, | |
592 | const std::uint32_t count); | |
593 | ||
594 | static std::uint32_t mul_loop_n(std::uint32_t* const u, std::uint32_t n, const std::int32_t p); | |
595 | static std::uint32_t div_loop_n(std::uint32_t* const u, std::uint32_t n, const std::int32_t p); | |
7c673cae | 596 | |
1e59de90 TL |
597 | static void eval_multiply_kara_propagate_carry (std::uint32_t* t, const std::uint32_t n, const std::uint32_t carry); |
598 | static void eval_multiply_kara_propagate_borrow(std::uint32_t* t, const std::uint32_t n, const bool has_borrow); | |
599 | static void eval_multiply_kara_n_by_n_to_2n ( std::uint32_t* r, | |
600 | const std::uint32_t* a, | |
601 | const std::uint32_t* b, | |
602 | const std::uint32_t n, | |
603 | std::uint32_t* t); | |
7c673cae | 604 | |
1e59de90 TL |
605 | template<unsigned D> |
606 | void eval_mul_dispatch_multiplication_method( | |
607 | const cpp_dec_float<D, ExponentType, Allocator>& v, | |
608 | const std::int32_t prec_elems_for_multiply, | |
609 | const typename std::enable_if< (D == Digits10) | |
610 | && (cpp_dec_float<D, ExponentType, Allocator>::cpp_dec_float_elem_number < cpp_dec_float_elems_for_kara)>::type* = nullptr) | |
611 | { | |
612 | // Use school multiplication. | |
613 | ||
614 | using array_for_mul_result_type = | |
615 | typename std::conditional<std::is_void<Allocator>::value, | |
616 | detail::static_array <std::uint32_t, std::uint32_t(cpp_dec_float_elem_number * 2)>, | |
617 | detail::dynamic_array<std::uint32_t, std::uint32_t(cpp_dec_float_elem_number * 2), Allocator> >::type; | |
618 | ||
619 | array_for_mul_result_type result; | |
620 | ||
621 | eval_multiply_n_by_n_to_2n(result.data(), data.data(), v.data.data(), static_cast<std::uint32_t>(prec_elems_for_multiply)); | |
622 | ||
623 | // Handle a potential carry. | |
624 | if(result[0U] != static_cast<std::uint32_t>(0U)) | |
625 | { | |
626 | exp += static_cast<exponent_type>(cpp_dec_float_elem_digits10); | |
627 | ||
628 | // Shift the result of the multiplication one element to the right. | |
629 | std::copy(result.cbegin(), | |
630 | result.cbegin() + static_cast<std::ptrdiff_t>(prec_elems_for_multiply), | |
631 | data.begin()); | |
632 | } | |
633 | else | |
634 | { | |
635 | std::copy(result.cbegin() + 1, | |
636 | result.cbegin() + (std::min)(static_cast<std::int32_t>(prec_elems_for_multiply + 1), cpp_dec_float_elem_number), | |
637 | data.begin()); | |
638 | } | |
639 | } | |
640 | ||
641 | template<unsigned D> | |
642 | void eval_mul_dispatch_multiplication_method( | |
643 | const cpp_dec_float<D, ExponentType, Allocator>& v, | |
644 | const std::int32_t prec_elems_for_multiply, | |
645 | const typename std::enable_if< (D == Digits10) | |
646 | && !(cpp_dec_float<D, ExponentType, Allocator>::cpp_dec_float_elem_number < cpp_dec_float_elems_for_kara)>::type* = nullptr) | |
647 | { | |
648 | if(prec_elems_for_multiply < cpp_dec_float_elems_for_kara) | |
649 | { | |
650 | // Use school multiplication. | |
651 | ||
652 | using array_for_mul_result_type = | |
653 | typename std::conditional<std::is_void<Allocator>::value, | |
654 | detail::static_array <std::uint32_t, std::uint32_t(cpp_dec_float_elem_number * 2)>, | |
655 | detail::dynamic_array<std::uint32_t, std::uint32_t(cpp_dec_float_elem_number * 2), Allocator> >::type; | |
656 | ||
657 | array_for_mul_result_type result; | |
658 | ||
659 | eval_multiply_n_by_n_to_2n(result.data(), data.data(), v.data.data(), prec_elems_for_multiply); | |
660 | ||
661 | // Handle a potential carry. | |
662 | if(result[0U] != static_cast<std::uint32_t>(0U)) | |
663 | { | |
664 | exp += static_cast<exponent_type>(cpp_dec_float_elem_digits10); | |
665 | ||
666 | // Shift the result of the multiplication one element to the right. | |
667 | std::copy(result.cbegin(), | |
668 | result.cbegin() + static_cast<std::ptrdiff_t>(prec_elems_for_multiply), | |
669 | data.begin()); | |
670 | } | |
671 | else | |
672 | { | |
673 | std::copy(result.cbegin() + 1, | |
674 | result.cbegin() + (std::min)(static_cast<std::int32_t>(prec_elems_for_multiply + 1), cpp_dec_float_elem_number), | |
675 | data.begin()); | |
676 | } | |
677 | } | |
678 | else | |
679 | { | |
680 | // Use Karatsuba multiplication. | |
681 | ||
682 | using array_for_kara_tmp_type = | |
683 | typename std::conditional<std::is_void<Allocator>::value, | |
684 | detail::static_array <std::uint32_t, detail::a029750::a029750_as_constexpr(static_cast<std::uint32_t>(cpp_dec_float_elem_number)) * 8U>, | |
685 | detail::dynamic_array<std::uint32_t, detail::a029750::a029750_as_constexpr(static_cast<std::uint32_t>(cpp_dec_float_elem_number)) * 8U, Allocator> >::type; | |
686 | ||
687 | // Sloanes's A029747: Numbers of the form 2^k times 1, 3 or 5. | |
688 | const std::uint32_t kara_elems_for_multiply = | |
689 | detail::a029750::a029750_as_runtime_value(static_cast<std::uint32_t>(prec_elems_for_multiply)); | |
690 | ||
691 | array_for_kara_tmp_type my_kara_mul_pool; | |
692 | ||
693 | std::uint32_t* result = my_kara_mul_pool.data() + (kara_elems_for_multiply * 0U); | |
694 | std::uint32_t* t = my_kara_mul_pool.data() + (kara_elems_for_multiply * 2U); | |
695 | std::uint32_t* u_local = my_kara_mul_pool.data() + (kara_elems_for_multiply * 6U); | |
696 | std::uint32_t* v_local = my_kara_mul_pool.data() + (kara_elems_for_multiply * 7U); | |
697 | ||
698 | std::copy( data.cbegin(), data.cbegin() + prec_elems_for_multiply, u_local); | |
699 | std::copy(v.data.cbegin(), v.data.cbegin() + prec_elems_for_multiply, v_local); | |
700 | ||
701 | eval_multiply_kara_n_by_n_to_2n(result, | |
702 | u_local, | |
703 | v_local, | |
704 | kara_elems_for_multiply, | |
705 | t); | |
706 | ||
707 | // Handle a potential carry. | |
708 | if(result[0U] != static_cast<std::uint32_t>(0U)) | |
709 | { | |
710 | exp += static_cast<exponent_type>(cpp_dec_float_elem_digits10); | |
711 | ||
712 | // Shift the result of the multiplication one element to the right. | |
713 | std::copy(result, | |
714 | result + static_cast<std::ptrdiff_t>(prec_elems_for_multiply), | |
715 | data.begin()); | |
716 | } | |
717 | else | |
718 | { | |
719 | std::copy(result + 1, | |
720 | result + (std::min)(static_cast<std::int32_t>(prec_elems_for_multiply + 1), cpp_dec_float_elem_number), | |
721 | data.begin()); | |
722 | } | |
723 | } | |
724 | } | |
7c673cae FG |
725 | |
726 | bool rd_string(const char* const s); | |
727 | ||
728 | template <unsigned D, class ET, class A> | |
729 | friend class cpp_dec_float; | |
730 | }; | |
731 | ||
732 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1e59de90 | 733 | const std::int32_t cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_radix; |
7c673cae | 734 | template <unsigned Digits10, class ExponentType, class Allocator> |
1e59de90 | 735 | const std::int32_t cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_digits10_limit_lo; |
7c673cae | 736 | template <unsigned Digits10, class ExponentType, class Allocator> |
1e59de90 | 737 | const std::int32_t cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_digits10_limit_hi; |
7c673cae | 738 | template <unsigned Digits10, class ExponentType, class Allocator> |
1e59de90 | 739 | const std::int32_t cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_digits10; |
7c673cae FG |
740 | template <unsigned Digits10, class ExponentType, class Allocator> |
741 | const ExponentType cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_max_exp; | |
742 | template <unsigned Digits10, class ExponentType, class Allocator> | |
743 | const ExponentType cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_min_exp; | |
744 | template <unsigned Digits10, class ExponentType, class Allocator> | |
745 | const ExponentType cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_max_exp10; | |
746 | template <unsigned Digits10, class ExponentType, class Allocator> | |
747 | const ExponentType cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_min_exp10; | |
748 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1e59de90 | 749 | const std::int32_t cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_elem_digits10; |
7c673cae | 750 | template <unsigned Digits10, class ExponentType, class Allocator> |
1e59de90 | 751 | const std::int32_t cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_elem_number; |
7c673cae | 752 | template <unsigned Digits10, class ExponentType, class Allocator> |
1e59de90 | 753 | const std::int32_t cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_elem_mask; |
7c673cae FG |
754 | |
755 | template <unsigned Digits10, class ExponentType, class Allocator> | |
756 | cpp_dec_float<Digits10, ExponentType, Allocator>& cpp_dec_float<Digits10, ExponentType, Allocator>::operator+=(const cpp_dec_float<Digits10, ExponentType, Allocator>& v) | |
757 | { | |
92f5a8d4 | 758 | if ((isnan)()) |
7c673cae FG |
759 | { |
760 | return *this; | |
761 | } | |
762 | ||
92f5a8d4 | 763 | if ((isinf)()) |
7c673cae | 764 | { |
92f5a8d4 | 765 | if ((v.isinf)() && (isneg() != v.isneg())) |
7c673cae FG |
766 | { |
767 | *this = nan(); | |
768 | } | |
769 | return *this; | |
770 | } | |
771 | ||
92f5a8d4 | 772 | if (iszero()) |
7c673cae FG |
773 | { |
774 | return operator=(v); | |
775 | } | |
776 | ||
92f5a8d4 | 777 | if ((v.isnan)() || (v.isinf)()) |
7c673cae FG |
778 | { |
779 | *this = v; | |
780 | return *this; | |
781 | } | |
782 | ||
783 | // Get the offset for the add/sub operation. | |
1e59de90 TL |
784 | constexpr exponent_type max_delta_exp = |
785 | static_cast<exponent_type>((cpp_dec_float_elem_number - 1) * cpp_dec_float_elem_digits10); | |
7c673cae | 786 | |
1e59de90 | 787 | const exponent_type ofs_exp = static_cast<exponent_type>(exp - v.exp); |
7c673cae FG |
788 | |
789 | // Check if the operation is out of range, requiring special handling. | |
92f5a8d4 | 790 | if (v.iszero() || (ofs_exp > max_delta_exp)) |
7c673cae FG |
791 | { |
792 | // Result is *this unchanged since v is negligible compared to *this. | |
793 | return *this; | |
794 | } | |
92f5a8d4 | 795 | else if (ofs_exp < -max_delta_exp) |
7c673cae FG |
796 | { |
797 | // Result is *this = v since *this is negligible compared to v. | |
798 | return operator=(v); | |
799 | } | |
800 | ||
801 | // Do the add/sub operation. | |
802 | ||
1e59de90 TL |
803 | typename array_type::pointer p_u = data.data(); |
804 | typename array_type::const_pointer p_v = v.data.data(); | |
805 | bool b_copy = false; | |
806 | const std::int32_t ofs = static_cast<std::int32_t>(static_cast<std::int32_t>(ofs_exp) / cpp_dec_float_elem_digits10); | |
807 | array_type n_data; | |
7c673cae | 808 | |
92f5a8d4 | 809 | if (neg == v.neg) |
7c673cae FG |
810 | { |
811 | // Add v to *this, where the data array of either *this or v | |
812 | // might have to be treated with a positive, negative or zero offset. | |
813 | // The result is stored in *this. The data are added one element | |
814 | // at a time, each element with carry. | |
1e59de90 | 815 | if (ofs >= static_cast<std::int32_t>(0)) |
7c673cae | 816 | { |
1e59de90 TL |
817 | std::copy(v.data.cbegin(), v.data.cend() - static_cast<size_t>(ofs), n_data.begin() + static_cast<size_t>(ofs)); |
818 | std::fill(n_data.begin(), n_data.begin() + static_cast<size_t>(ofs), static_cast<std::uint32_t>(0u)); | |
819 | p_v = n_data.data(); | |
7c673cae FG |
820 | } |
821 | else | |
822 | { | |
1e59de90 TL |
823 | std::copy(data.cbegin(), data.cend() - static_cast<size_t>(-ofs), n_data.begin() + static_cast<size_t>(-ofs)); |
824 | std::fill(n_data.begin(), n_data.begin() + static_cast<size_t>(-ofs), static_cast<std::uint32_t>(0u)); | |
825 | p_u = n_data.data(); | |
7c673cae FG |
826 | b_copy = true; |
827 | } | |
828 | ||
829 | // Addition algorithm | |
1e59de90 | 830 | const std::uint32_t carry = eval_add_n(p_u, p_u, p_v, cpp_dec_float_elem_number); |
7c673cae | 831 | |
92f5a8d4 | 832 | if (b_copy) |
7c673cae FG |
833 | { |
834 | data = n_data; | |
92f5a8d4 | 835 | exp = v.exp; |
7c673cae FG |
836 | } |
837 | ||
838 | // There needs to be a carry into the element -1 of the array data | |
1e59de90 | 839 | if (carry != static_cast<std::uint32_t>(0u)) |
7c673cae | 840 | { |
1e59de90 | 841 | std::copy_backward(data.cbegin(), data.cend() - static_cast<std::size_t>(1u), data.end()); |
7c673cae | 842 | data[0] = carry; |
1e59de90 | 843 | exp += static_cast<exponent_type>(cpp_dec_float_elem_digits10); |
7c673cae FG |
844 | } |
845 | } | |
846 | else | |
847 | { | |
848 | // Subtract v from *this, where the data array of either *this or v | |
849 | // might have to be treated with a positive, negative or zero offset. | |
1e59de90 | 850 | if ((ofs > static_cast<std::int32_t>(0)) || ((ofs == static_cast<std::int32_t>(0)) && (compare_ranges(data.cbegin(), v.data.cbegin()) > static_cast<std::int32_t>(0)))) |
7c673cae FG |
851 | { |
852 | // In this case, |u| > |v| and ofs is positive. | |
853 | // Copy the data of v, shifted down to a lower value | |
854 | // into the data array m_n. Set the operand pointer p_v | |
855 | // to point to the copied, shifted data m_n. | |
1e59de90 TL |
856 | std::copy(v.data.cbegin(), v.data.cend() - static_cast<size_t>(ofs), n_data.begin() + static_cast<size_t>(ofs)); |
857 | std::fill(n_data.begin(), n_data.begin() + static_cast<size_t>(ofs), static_cast<std::uint32_t>(0u)); | |
858 | p_v = n_data.data(); | |
7c673cae FG |
859 | } |
860 | else | |
861 | { | |
1e59de90 | 862 | if (ofs != static_cast<std::int32_t>(0)) |
7c673cae FG |
863 | { |
864 | // In this case, |u| < |v| and ofs is negative. | |
865 | // Shift the data of u down to a lower value. | |
1e59de90 TL |
866 | std::copy_backward(data.cbegin(), data.cend() - static_cast<size_t>(-ofs), data.end()); |
867 | std::fill(data.begin(), data.begin() + static_cast<size_t>(-ofs), static_cast<std::uint32_t>(0u)); | |
7c673cae FG |
868 | } |
869 | ||
870 | // Copy the data of v into the data array n_data. | |
871 | // Set the u-pointer p_u to point to m_n and the | |
872 | // operand pointer p_v to point to the shifted | |
873 | // data m_data. | |
874 | n_data = v.data; | |
1e59de90 TL |
875 | p_u = n_data.data(); |
876 | p_v = data.data(); | |
7c673cae FG |
877 | b_copy = true; |
878 | } | |
879 | ||
7c673cae | 880 | // Subtraction algorithm |
1e59de90 | 881 | static_cast<void>(eval_subtract_n(p_u, p_u, p_v, cpp_dec_float_elem_number)); |
7c673cae | 882 | |
92f5a8d4 | 883 | if (b_copy) |
7c673cae FG |
884 | { |
885 | data = n_data; | |
92f5a8d4 TL |
886 | exp = v.exp; |
887 | neg = v.neg; | |
7c673cae FG |
888 | } |
889 | ||
890 | // Is it necessary to justify the data? | |
891 | const typename array_type::const_iterator first_nonzero_elem = std::find_if(data.begin(), data.end(), data_elem_is_non_zero_predicate); | |
892 | ||
92f5a8d4 | 893 | if (first_nonzero_elem != data.begin()) |
7c673cae | 894 | { |
92f5a8d4 | 895 | if (first_nonzero_elem == data.end()) |
7c673cae FG |
896 | { |
897 | // This result of the subtraction is exactly zero. | |
898 | // Reset the sign and the exponent. | |
899 | neg = false; | |
1e59de90 | 900 | exp = static_cast<exponent_type>(0); |
7c673cae FG |
901 | } |
902 | else | |
903 | { | |
904 | // Justify the data | |
905 | const std::size_t sj = static_cast<std::size_t>(std::distance<typename array_type::const_iterator>(data.begin(), first_nonzero_elem)); | |
906 | ||
907 | std::copy(data.begin() + static_cast<std::size_t>(sj), data.end(), data.begin()); | |
1e59de90 | 908 | std::fill(data.end() - sj, data.end(), static_cast<std::uint32_t>(0u)); |
7c673cae | 909 | |
1e59de90 | 910 | exp -= static_cast<exponent_type>(sj * static_cast<std::size_t>(cpp_dec_float_elem_digits10)); |
7c673cae FG |
911 | } |
912 | } | |
913 | } | |
914 | ||
915 | // Handle underflow. | |
92f5a8d4 | 916 | if (iszero()) |
7c673cae FG |
917 | return (*this = zero()); |
918 | ||
919 | // Check for potential overflow. | |
1e59de90 | 920 | const bool b_result_might_overflow = (exp >= static_cast<exponent_type>(cpp_dec_float_max_exp10)); |
7c673cae FG |
921 | |
922 | // Handle overflow. | |
92f5a8d4 | 923 | if (b_result_might_overflow) |
7c673cae FG |
924 | { |
925 | const bool b_result_is_neg = neg; | |
92f5a8d4 | 926 | neg = false; |
7c673cae | 927 | |
92f5a8d4 TL |
928 | if (compare((cpp_dec_float::max)()) > 0) |
929 | *this = inf(); | |
7c673cae FG |
930 | |
931 | neg = b_result_is_neg; | |
932 | } | |
933 | ||
934 | return *this; | |
935 | } | |
936 | ||
937 | template <unsigned Digits10, class ExponentType, class Allocator> | |
938 | cpp_dec_float<Digits10, ExponentType, Allocator>& cpp_dec_float<Digits10, ExponentType, Allocator>::operator-=(const cpp_dec_float<Digits10, ExponentType, Allocator>& v) | |
939 | { | |
940 | // Use *this - v = -(-*this + v). | |
941 | negate(); | |
942 | *this += v; | |
943 | negate(); | |
944 | return *this; | |
945 | } | |
946 | ||
947 | template <unsigned Digits10, class ExponentType, class Allocator> | |
948 | cpp_dec_float<Digits10, ExponentType, Allocator>& cpp_dec_float<Digits10, ExponentType, Allocator>::operator*=(const cpp_dec_float<Digits10, ExponentType, Allocator>& v) | |
949 | { | |
950 | // Evaluate the sign of the result. | |
951 | const bool b_result_is_neg = (neg != v.neg); | |
952 | ||
953 | // Artificially set the sign of the result to be positive. | |
954 | neg = false; | |
955 | ||
956 | // Handle special cases like zero, inf and NaN. | |
957 | const bool b_u_is_inf = (isinf)(); | |
958 | const bool b_v_is_inf = (v.isinf)(); | |
959 | const bool b_u_is_zero = iszero(); | |
960 | const bool b_v_is_zero = v.iszero(); | |
961 | ||
92f5a8d4 | 962 | if (((isnan)() || (v.isnan)()) || (b_u_is_inf && b_v_is_zero) || (b_v_is_inf && b_u_is_zero)) |
7c673cae FG |
963 | { |
964 | *this = nan(); | |
965 | return *this; | |
966 | } | |
967 | ||
92f5a8d4 | 968 | if (b_u_is_inf || b_v_is_inf) |
7c673cae FG |
969 | { |
970 | *this = inf(); | |
92f5a8d4 | 971 | if (b_result_is_neg) |
7c673cae FG |
972 | negate(); |
973 | return *this; | |
974 | } | |
975 | ||
92f5a8d4 | 976 | if (b_u_is_zero || b_v_is_zero) |
7c673cae FG |
977 | { |
978 | return *this = zero(); | |
979 | } | |
980 | ||
981 | // Check for potential overflow or underflow. | |
1e59de90 TL |
982 | const bool b_result_might_overflow = ((exp + v.exp) >= static_cast<exponent_type>(cpp_dec_float_max_exp10)); |
983 | const bool b_result_might_underflow = ((exp + v.exp) <= static_cast<exponent_type>(cpp_dec_float_min_exp10)); | |
7c673cae FG |
984 | |
985 | // Set the exponent of the result. | |
986 | exp += v.exp; | |
987 | ||
1e59de90 | 988 | const std::int32_t prec_mul = (std::min)(prec_elem, v.prec_elem); |
7c673cae | 989 | |
1e59de90 | 990 | eval_mul_dispatch_multiplication_method(v, prec_mul); |
7c673cae FG |
991 | |
992 | // Handle overflow. | |
92f5a8d4 | 993 | if (b_result_might_overflow && (compare((cpp_dec_float::max)()) > 0)) |
7c673cae FG |
994 | { |
995 | *this = inf(); | |
996 | } | |
997 | ||
998 | // Handle underflow. | |
92f5a8d4 | 999 | if (b_result_might_underflow && (compare((cpp_dec_float::min)()) < 0)) |
7c673cae FG |
1000 | { |
1001 | *this = zero(); | |
1002 | ||
1003 | return *this; | |
1004 | } | |
1005 | ||
1006 | // Set the sign of the result. | |
1007 | neg = b_result_is_neg; | |
1008 | ||
1009 | return *this; | |
1010 | } | |
1011 | ||
1012 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1013 | cpp_dec_float<Digits10, ExponentType, Allocator>& cpp_dec_float<Digits10, ExponentType, Allocator>::operator/=(const cpp_dec_float<Digits10, ExponentType, Allocator>& v) | |
1014 | { | |
92f5a8d4 | 1015 | if (iszero()) |
7c673cae | 1016 | { |
92f5a8d4 | 1017 | if ((v.isnan)()) |
7c673cae FG |
1018 | { |
1019 | return *this = v; | |
1020 | } | |
92f5a8d4 | 1021 | else if (v.iszero()) |
7c673cae FG |
1022 | { |
1023 | return *this = nan(); | |
1024 | } | |
1025 | } | |
1026 | ||
1e59de90 | 1027 | const bool u_and_v_are_finite_and_identical = ((isfinite)() && (fpclass == v.fpclass) && (exp == v.exp) && (compare_ranges(data.cbegin(), v.data.cbegin()) == static_cast<std::int32_t>(0))); |
7c673cae | 1028 | |
92f5a8d4 | 1029 | if (u_and_v_are_finite_and_identical) |
7c673cae | 1030 | { |
92f5a8d4 | 1031 | if (neg != v.neg) |
7c673cae FG |
1032 | { |
1033 | *this = one(); | |
1034 | negate(); | |
1035 | } | |
1036 | else | |
1037 | *this = one(); | |
1038 | return *this; | |
1039 | } | |
1040 | else | |
1041 | { | |
1042 | cpp_dec_float t(v); | |
1043 | t.calculate_inv(); | |
1044 | return operator*=(t); | |
1045 | } | |
1046 | } | |
1047 | ||
1048 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1e59de90 | 1049 | cpp_dec_float<Digits10, ExponentType, Allocator>& cpp_dec_float<Digits10, ExponentType, Allocator>::mul_unsigned_long_long(const unsigned long long n) |
7c673cae | 1050 | { |
1e59de90 | 1051 | // Multiply *this with a constant unsigned long long. |
7c673cae FG |
1052 | |
1053 | // Evaluate the sign of the result. | |
1054 | const bool b_neg = neg; | |
1055 | ||
1056 | // Artificially set the sign of the result to be positive. | |
1057 | neg = false; | |
1058 | ||
1059 | // Handle special cases like zero, inf and NaN. | |
92f5a8d4 | 1060 | const bool b_u_is_inf = (isinf)(); |
1e59de90 | 1061 | const bool b_n_is_zero = (n == static_cast<std::int32_t>(0)); |
7c673cae | 1062 | |
92f5a8d4 | 1063 | if ((isnan)() || (b_u_is_inf && b_n_is_zero)) |
7c673cae FG |
1064 | { |
1065 | return (*this = nan()); | |
1066 | } | |
1067 | ||
92f5a8d4 | 1068 | if (b_u_is_inf) |
7c673cae FG |
1069 | { |
1070 | *this = inf(); | |
92f5a8d4 | 1071 | if (b_neg) |
7c673cae FG |
1072 | negate(); |
1073 | return *this; | |
1074 | } | |
1075 | ||
92f5a8d4 | 1076 | if (iszero() || b_n_is_zero) |
7c673cae FG |
1077 | { |
1078 | // Multiplication by zero. | |
1079 | return *this = zero(); | |
1080 | } | |
1081 | ||
1e59de90 | 1082 | if (n >= static_cast<unsigned long long>(cpp_dec_float_elem_mask)) |
7c673cae FG |
1083 | { |
1084 | neg = b_neg; | |
1085 | cpp_dec_float t; | |
1086 | t = n; | |
1087 | return operator*=(t); | |
1088 | } | |
1089 | ||
1e59de90 | 1090 | if (n == static_cast<unsigned long long>(1u)) |
7c673cae FG |
1091 | { |
1092 | neg = b_neg; | |
1093 | return *this; | |
1094 | } | |
1095 | ||
1096 | // Set up the multiplication loop. | |
1e59de90 TL |
1097 | const std::uint32_t nn = static_cast<std::uint32_t>(n); |
1098 | const std::uint32_t carry = mul_loop_n(data.data(), nn, prec_elem); | |
7c673cae FG |
1099 | |
1100 | // Handle the carry and adjust the exponent. | |
1e59de90 | 1101 | if (carry != static_cast<std::uint32_t>(0u)) |
7c673cae | 1102 | { |
1e59de90 | 1103 | exp += static_cast<exponent_type>(cpp_dec_float_elem_digits10); |
7c673cae FG |
1104 | |
1105 | // Shift the result of the multiplication one element to the right. | |
1106 | std::copy_backward(data.begin(), | |
1e59de90 | 1107 | data.begin() + static_cast<std::size_t>(prec_elem - static_cast<std::int32_t>(1)), |
92f5a8d4 | 1108 | data.begin() + static_cast<std::size_t>(prec_elem)); |
7c673cae | 1109 | |
1e59de90 | 1110 | data.front() = static_cast<std::uint32_t>(carry); |
7c673cae FG |
1111 | } |
1112 | ||
1113 | // Check for potential overflow. | |
1114 | const bool b_result_might_overflow = (exp >= cpp_dec_float_max_exp10); | |
1115 | ||
1116 | // Handle overflow. | |
92f5a8d4 | 1117 | if (b_result_might_overflow && (compare((cpp_dec_float::max)()) > 0)) |
7c673cae FG |
1118 | { |
1119 | *this = inf(); | |
1120 | } | |
1121 | ||
1122 | // Set the sign. | |
1123 | neg = b_neg; | |
1124 | ||
1125 | return *this; | |
1126 | } | |
1127 | ||
1128 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1e59de90 | 1129 | cpp_dec_float<Digits10, ExponentType, Allocator>& cpp_dec_float<Digits10, ExponentType, Allocator>::div_unsigned_long_long(const unsigned long long n) |
7c673cae | 1130 | { |
1e59de90 | 1131 | // Divide *this by a constant unsigned long long. |
7c673cae FG |
1132 | |
1133 | // Evaluate the sign of the result. | |
1134 | const bool b_neg = neg; | |
1135 | ||
1136 | // Artificially set the sign of the result to be positive. | |
1137 | neg = false; | |
1138 | ||
1139 | // Handle special cases like zero, inf and NaN. | |
92f5a8d4 | 1140 | if ((isnan)()) |
7c673cae FG |
1141 | { |
1142 | return *this; | |
1143 | } | |
1144 | ||
92f5a8d4 | 1145 | if ((isinf)()) |
7c673cae FG |
1146 | { |
1147 | *this = inf(); | |
92f5a8d4 | 1148 | if (b_neg) |
7c673cae FG |
1149 | negate(); |
1150 | return *this; | |
1151 | } | |
1152 | ||
1e59de90 | 1153 | if (n == static_cast<unsigned long long>(0u)) |
7c673cae FG |
1154 | { |
1155 | // Divide by 0. | |
92f5a8d4 | 1156 | if (iszero()) |
7c673cae FG |
1157 | { |
1158 | *this = nan(); | |
1159 | return *this; | |
1160 | } | |
1161 | else | |
1162 | { | |
1163 | *this = inf(); | |
92f5a8d4 | 1164 | if (isneg()) |
7c673cae FG |
1165 | negate(); |
1166 | return *this; | |
1167 | } | |
1168 | } | |
1169 | ||
92f5a8d4 | 1170 | if (iszero()) |
7c673cae FG |
1171 | { |
1172 | return *this; | |
1173 | } | |
1174 | ||
1e59de90 | 1175 | if (n >= static_cast<unsigned long long>(cpp_dec_float_elem_mask)) |
7c673cae FG |
1176 | { |
1177 | neg = b_neg; | |
1178 | cpp_dec_float t; | |
1179 | t = n; | |
1180 | return operator/=(t); | |
1181 | } | |
1182 | ||
1e59de90 | 1183 | const std::uint32_t nn = static_cast<std::uint32_t>(n); |
7c673cae | 1184 | |
1e59de90 | 1185 | if (nn > static_cast<std::uint32_t>(1u)) |
7c673cae FG |
1186 | { |
1187 | // Do the division loop. | |
1e59de90 | 1188 | const std::uint32_t prev = div_loop_n(data.data(), nn, prec_elem); |
7c673cae FG |
1189 | |
1190 | // Determine if one leading zero is in the result data. | |
1e59de90 | 1191 | if (data[0] == static_cast<std::uint32_t>(0u)) |
7c673cae FG |
1192 | { |
1193 | // Adjust the exponent | |
1e59de90 | 1194 | exp -= static_cast<exponent_type>(cpp_dec_float_elem_digits10); |
7c673cae FG |
1195 | |
1196 | // Shift result of the division one element to the left. | |
1197 | std::copy(data.begin() + static_cast<std::size_t>(1u), | |
1e59de90 | 1198 | data.begin() + static_cast<std::size_t>(prec_elem - static_cast<std::int32_t>(1)), |
92f5a8d4 | 1199 | data.begin()); |
7c673cae | 1200 | |
1e59de90 | 1201 | data[static_cast<std::size_t>(prec_elem - static_cast<std::int32_t>(1))] = static_cast<std::uint32_t>(static_cast<std::uint64_t>(prev * static_cast<std::uint64_t>(cpp_dec_float_elem_mask)) / nn); |
7c673cae FG |
1202 | } |
1203 | } | |
1204 | ||
1205 | // Check for potential underflow. | |
1206 | const bool b_result_might_underflow = (exp <= cpp_dec_float_min_exp10); | |
1207 | ||
1208 | // Handle underflow. | |
92f5a8d4 | 1209 | if (b_result_might_underflow && (compare((cpp_dec_float::min)()) < 0)) |
7c673cae FG |
1210 | return (*this = zero()); |
1211 | ||
1212 | // Set the sign of the result. | |
1213 | neg = b_neg; | |
1214 | ||
1215 | return *this; | |
1216 | } | |
1217 | ||
1218 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1219 | cpp_dec_float<Digits10, ExponentType, Allocator>& cpp_dec_float<Digits10, ExponentType, Allocator>::calculate_inv() | |
1220 | { | |
1221 | // Compute the inverse of *this. | |
1222 | const bool b_neg = neg; | |
1223 | ||
1224 | neg = false; | |
1225 | ||
1226 | // Handle special cases like zero, inf and NaN. | |
92f5a8d4 | 1227 | if (iszero()) |
7c673cae FG |
1228 | { |
1229 | *this = inf(); | |
92f5a8d4 | 1230 | if (b_neg) |
7c673cae FG |
1231 | negate(); |
1232 | return *this; | |
1233 | } | |
1234 | ||
92f5a8d4 | 1235 | if ((isnan)()) |
7c673cae FG |
1236 | { |
1237 | return *this; | |
1238 | } | |
1239 | ||
92f5a8d4 | 1240 | if ((isinf)()) |
7c673cae FG |
1241 | { |
1242 | return *this = zero(); | |
1243 | } | |
1244 | ||
92f5a8d4 | 1245 | if (isone()) |
7c673cae | 1246 | { |
92f5a8d4 | 1247 | if (b_neg) |
7c673cae FG |
1248 | negate(); |
1249 | return *this; | |
1250 | } | |
1251 | ||
1252 | // Save the original *this. | |
1253 | cpp_dec_float<Digits10, ExponentType, Allocator> x(*this); | |
1254 | ||
1255 | // Generate the initial estimate using division. | |
1256 | // Extract the mantissa and exponent for a "manual" | |
1257 | // computation of the estimate. | |
1e59de90 TL |
1258 | double dd; |
1259 | exponent_type ne; | |
7c673cae FG |
1260 | x.extract_parts(dd, ne); |
1261 | ||
1262 | // Do the inverse estimate using double precision estimates of mantissa and exponent. | |
1263 | operator=(cpp_dec_float<Digits10, ExponentType, Allocator>(1.0 / dd, -ne)); | |
1264 | ||
1265 | // Compute the inverse of *this. Quadratically convergent Newton-Raphson iteration | |
1266 | // is used. During the iterative steps, the precision of the calculation is limited | |
1267 | // to the minimum required in order to minimize the run-time. | |
1268 | ||
1e59de90 | 1269 | constexpr std::int32_t double_digits10_minus_a_few = std::numeric_limits<double>::digits10 - 3; |
7c673cae | 1270 | |
1e59de90 | 1271 | for (std::int32_t digits = double_digits10_minus_a_few; digits <= cpp_dec_float_max_digits10; digits *= static_cast<std::int32_t>(2)) |
7c673cae FG |
1272 | { |
1273 | // Adjust precision of the terms. | |
1e59de90 TL |
1274 | precision(static_cast<std::int32_t>((digits + 10) * static_cast<std::int32_t>(2))); |
1275 | x.precision(static_cast<std::int32_t>((digits + 10) * static_cast<std::int32_t>(2))); | |
7c673cae FG |
1276 | |
1277 | // Next iteration. | |
1278 | cpp_dec_float t(*this); | |
1279 | t *= x; | |
1280 | t -= two(); | |
1281 | t.negate(); | |
1282 | *this *= t; | |
1283 | } | |
1284 | ||
1285 | neg = b_neg; | |
1286 | ||
1287 | prec_elem = cpp_dec_float_elem_number; | |
1288 | ||
1289 | return *this; | |
1290 | } | |
1291 | ||
1292 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1293 | cpp_dec_float<Digits10, ExponentType, Allocator>& cpp_dec_float<Digits10, ExponentType, Allocator>::calculate_sqrt() | |
1294 | { | |
1295 | // Compute the square root of *this. | |
1296 | ||
92f5a8d4 | 1297 | if ((isinf)() && !isneg()) |
b32b8144 FG |
1298 | { |
1299 | return *this; | |
1300 | } | |
1301 | ||
92f5a8d4 | 1302 | if (isneg() || (!(isfinite)())) |
7c673cae FG |
1303 | { |
1304 | *this = nan(); | |
b32b8144 | 1305 | errno = EDOM; |
7c673cae FG |
1306 | return *this; |
1307 | } | |
1308 | ||
92f5a8d4 | 1309 | if (iszero() || isone()) |
7c673cae FG |
1310 | { |
1311 | return *this; | |
1312 | } | |
1313 | ||
1314 | // Save the original *this. | |
1315 | cpp_dec_float<Digits10, ExponentType, Allocator> x(*this); | |
1316 | ||
1317 | // Generate the initial estimate using division. | |
1318 | // Extract the mantissa and exponent for a "manual" | |
1319 | // computation of the estimate. | |
1e59de90 TL |
1320 | double dd; |
1321 | exponent_type ne; | |
7c673cae FG |
1322 | extract_parts(dd, ne); |
1323 | ||
1324 | // Force the exponent to be an even multiple of two. | |
1e59de90 | 1325 | if ((ne % static_cast<exponent_type>(2)) != static_cast<exponent_type>(0)) |
7c673cae FG |
1326 | { |
1327 | ++ne; | |
1328 | dd /= 10.0; | |
1329 | } | |
1330 | ||
1331 | // Setup the iteration. | |
1332 | // Estimate the square root using simple manipulations. | |
1333 | const double sqd = std::sqrt(dd); | |
1334 | ||
1335 | *this = cpp_dec_float<Digits10, ExponentType, Allocator>(sqd, static_cast<ExponentType>(ne / static_cast<ExponentType>(2))); | |
1336 | ||
1337 | // Estimate 1.0 / (2.0 * x0) using simple manipulations. | |
1338 | cpp_dec_float<Digits10, ExponentType, Allocator> vi(0.5 / sqd, static_cast<ExponentType>(-ne / static_cast<ExponentType>(2))); | |
1339 | ||
1340 | // Compute the square root of x. Coupled Newton iteration | |
1341 | // as described in "Pi Unleashed" is used. During the | |
1342 | // iterative steps, the precision of the calculation is | |
1343 | // limited to the minimum required in order to minimize | |
1344 | // the run-time. | |
1345 | // | |
1e59de90 TL |
1346 | // Book reference to "Pi Unleashed: |
1347 | // https://www.springer.com/gp/book/9783642567353 | |
7c673cae | 1348 | |
1e59de90 | 1349 | constexpr std::uint32_t double_digits10_minus_a_few = std::numeric_limits<double>::digits10 - 3; |
7c673cae | 1350 | |
1e59de90 | 1351 | for (std::int32_t digits = double_digits10_minus_a_few; digits <= cpp_dec_float_max_digits10; digits *= 2) |
7c673cae FG |
1352 | { |
1353 | // Adjust precision of the terms. | |
1354 | precision((digits + 10) * 2); | |
1355 | vi.precision((digits + 10) * 2); | |
1356 | ||
1357 | // Next iteration of vi | |
1358 | cpp_dec_float t(*this); | |
1359 | t *= vi; | |
1360 | t.negate(); | |
1361 | t.mul_unsigned_long_long(2u); | |
1362 | t += one(); | |
1363 | t *= vi; | |
1364 | vi += t; | |
1365 | ||
1366 | // Next iteration of *this | |
1367 | t = *this; | |
1368 | t *= *this; | |
1369 | t.negate(); | |
1370 | t += x; | |
1371 | t *= vi; | |
1372 | *this += t; | |
1373 | } | |
1374 | ||
1375 | prec_elem = cpp_dec_float_elem_number; | |
1376 | ||
1377 | return *this; | |
1378 | } | |
1379 | ||
7c673cae FG |
1380 | template <unsigned Digits10, class ExponentType, class Allocator> |
1381 | int cpp_dec_float<Digits10, ExponentType, Allocator>::compare(const cpp_dec_float& v) const | |
1382 | { | |
1383 | // Compare v with *this. | |
1384 | // Return +1 for *this > v | |
1385 | // 0 for *this = v | |
1386 | // -1 for *this < v | |
1387 | ||
1388 | // Handle all non-finite cases. | |
92f5a8d4 | 1389 | if ((!(isfinite)()) || (!(v.isfinite)())) |
7c673cae FG |
1390 | { |
1391 | // NaN can never equal NaN. Return an implementation-dependent | |
1392 | // signed result. Also note that comparison of NaN with NaN | |
1393 | // using operators greater-than or less-than is undefined. | |
92f5a8d4 TL |
1394 | if ((isnan)() || (v.isnan)()) |
1395 | { | |
1396 | return ((isnan)() ? 1 : -1); | |
1397 | } | |
7c673cae | 1398 | |
92f5a8d4 | 1399 | if ((isinf)() && (v.isinf)()) |
7c673cae FG |
1400 | { |
1401 | // Both *this and v are infinite. They are equal if they have the same sign. | |
1402 | // Otherwise, *this is less than v if and only if *this is negative. | |
1403 | return ((neg == v.neg) ? 0 : (neg ? -1 : 1)); | |
1404 | } | |
1405 | ||
92f5a8d4 | 1406 | if ((isinf)()) |
7c673cae FG |
1407 | { |
1408 | // *this is infinite, but v is finite. | |
1409 | // So negative infinite *this is less than any finite v. | |
1410 | // Whereas positive infinite *this is greater than any finite v. | |
1411 | return (isneg() ? -1 : 1); | |
1412 | } | |
1413 | else | |
1414 | { | |
1415 | // *this is finite, and v is infinite. | |
1416 | // So any finite *this is greater than negative infinite v. | |
1417 | // Whereas any finite *this is less than positive infinite v. | |
1418 | return (v.neg ? 1 : -1); | |
1419 | } | |
1420 | } | |
1421 | ||
1422 | // And now handle all *finite* cases. | |
92f5a8d4 | 1423 | if (iszero()) |
7c673cae FG |
1424 | { |
1425 | // The value of *this is zero and v is either zero or non-zero. | |
1426 | return (v.iszero() ? 0 | |
92f5a8d4 | 1427 | : (v.neg ? 1 : -1)); |
7c673cae | 1428 | } |
92f5a8d4 | 1429 | else if (v.iszero()) |
7c673cae FG |
1430 | { |
1431 | // The value of v is zero and *this is non-zero. | |
1432 | return (neg ? -1 : 1); | |
1433 | } | |
1434 | else | |
1435 | { | |
1436 | // Both *this and v are non-zero. | |
1437 | ||
92f5a8d4 | 1438 | if (neg != v.neg) |
7c673cae FG |
1439 | { |
1440 | // The signs are different. | |
1441 | return (neg ? -1 : 1); | |
1442 | } | |
92f5a8d4 | 1443 | else if (exp != v.exp) |
7c673cae FG |
1444 | { |
1445 | // The signs are the same and the exponents are different. | |
1446 | const int val_cexpression = ((exp < v.exp) ? 1 : -1); | |
1447 | ||
1448 | return (neg ? val_cexpression : -val_cexpression); | |
1449 | } | |
1450 | else | |
1451 | { | |
1452 | // The signs are the same and the exponents are the same. | |
1453 | // Compare the data. | |
1e59de90 | 1454 | const int val_cmp_data = compare_ranges(data.cbegin(), v.data.cbegin()); |
7c673cae FG |
1455 | |
1456 | return ((!neg) ? val_cmp_data : -val_cmp_data); | |
1457 | } | |
1458 | } | |
1459 | } | |
1460 | ||
1461 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1462 | bool cpp_dec_float<Digits10, ExponentType, Allocator>::isone() const | |
1463 | { | |
1464 | // Check if the value of *this is identically 1 or very close to 1. | |
1465 | ||
1466 | const bool not_negative_and_is_finite = ((!neg) && (isfinite)()); | |
1467 | ||
92f5a8d4 | 1468 | if (not_negative_and_is_finite) |
7c673cae | 1469 | { |
1e59de90 | 1470 | if ((data[0u] == static_cast<std::uint32_t>(1u)) && (exp == static_cast<exponent_type>(0))) |
7c673cae FG |
1471 | { |
1472 | const typename array_type::const_iterator it_non_zero = std::find_if(data.begin(), data.end(), data_elem_is_non_zero_predicate); | |
1473 | return (it_non_zero == data.end()); | |
1474 | } | |
1e59de90 | 1475 | else if ((data[0u] == static_cast<std::uint32_t>(cpp_dec_float_elem_mask - 1)) && (exp == static_cast<exponent_type>(-cpp_dec_float_elem_digits10))) |
7c673cae FG |
1476 | { |
1477 | const typename array_type::const_iterator it_non_nine = std::find_if(data.begin(), data.end(), data_elem_is_non_nine_predicate); | |
1478 | return (it_non_nine == data.end()); | |
1479 | } | |
1480 | } | |
1481 | ||
1482 | return false; | |
1483 | } | |
1484 | ||
1485 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1486 | bool cpp_dec_float<Digits10, ExponentType, Allocator>::isint() const | |
1487 | { | |
92f5a8d4 TL |
1488 | if (fpclass != cpp_dec_float_finite) |
1489 | { | |
1490 | return false; | |
1491 | } | |
7c673cae | 1492 | |
92f5a8d4 TL |
1493 | if (iszero()) |
1494 | { | |
1495 | return true; | |
1496 | } | |
7c673cae | 1497 | |
1e59de90 | 1498 | if (exp < static_cast<exponent_type>(0)) |
92f5a8d4 TL |
1499 | { |
1500 | return false; | |
1501 | } // |*this| < 1. | |
7c673cae FG |
1502 | |
1503 | const typename array_type::size_type offset_decimal_part = static_cast<typename array_type::size_type>(exp / cpp_dec_float_elem_digits10) + 1u; | |
1504 | ||
92f5a8d4 | 1505 | if (offset_decimal_part >= static_cast<typename array_type::size_type>(cpp_dec_float_elem_number)) |
7c673cae FG |
1506 | { |
1507 | // The number is too large to resolve the integer part. | |
1508 | // It considered to be a pure integer. | |
1509 | return true; | |
1510 | } | |
1511 | ||
1512 | typename array_type::const_iterator it_non_zero = std::find_if(data.begin() + offset_decimal_part, data.end(), data_elem_is_non_zero_predicate); | |
1513 | ||
1514 | return (it_non_zero == data.end()); | |
1515 | } | |
1516 | ||
1517 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1518 | void cpp_dec_float<Digits10, ExponentType, Allocator>::extract_parts(double& mantissa, ExponentType& exponent) const | |
1519 | { | |
1520 | // Extract the approximate parts mantissa and base-10 exponent from the input cpp_dec_float<Digits10, ExponentType, Allocator> value x. | |
1521 | ||
1522 | // Extracts the mantissa and exponent. | |
1523 | exponent = exp; | |
1524 | ||
1e59de90 TL |
1525 | std::uint32_t p10 = static_cast<std::uint32_t>(1u); |
1526 | std::uint32_t test = data[0u]; | |
7c673cae | 1527 | |
92f5a8d4 | 1528 | for (;;) |
7c673cae | 1529 | { |
1e59de90 | 1530 | test /= static_cast<std::uint32_t>(10u); |
7c673cae | 1531 | |
1e59de90 | 1532 | if (test == static_cast<std::uint32_t>(0u)) |
7c673cae FG |
1533 | { |
1534 | break; | |
1535 | } | |
1536 | ||
1e59de90 | 1537 | p10 *= static_cast<std::uint32_t>(10u); |
7c673cae FG |
1538 | ++exponent; |
1539 | } | |
1540 | ||
1541 | // Establish the upper bound of limbs for extracting the double. | |
1e59de90 | 1542 | const int max_elem_in_double_count = static_cast<int>(static_cast<std::int32_t>(std::numeric_limits<double>::digits10) / cpp_dec_float_elem_digits10) + (static_cast<int>(static_cast<std::int32_t>(std::numeric_limits<double>::digits10) % cpp_dec_float_elem_digits10) != 0 ? 1 : 0) + 1; |
7c673cae FG |
1543 | |
1544 | // And make sure this upper bound stays within bounds of the elems. | |
1e59de90 | 1545 | const std::size_t max_elem_extract_count = static_cast<std::size_t>((std::min)(static_cast<std::int32_t>(max_elem_in_double_count), cpp_dec_float_elem_number)); |
7c673cae FG |
1546 | |
1547 | // Extract into the mantissa the first limb, extracted as a double. | |
92f5a8d4 | 1548 | mantissa = static_cast<double>(data[0]); |
7c673cae FG |
1549 | double scale = 1.0; |
1550 | ||
1551 | // Extract the rest of the mantissa piecewise from the limbs. | |
92f5a8d4 | 1552 | for (std::size_t i = 1u; i < max_elem_extract_count; i++) |
7c673cae | 1553 | { |
92f5a8d4 TL |
1554 | scale /= static_cast<double>(cpp_dec_float_elem_mask); |
1555 | mantissa += (static_cast<double>(data[i]) * scale); | |
7c673cae FG |
1556 | } |
1557 | ||
1558 | mantissa /= static_cast<double>(p10); | |
1559 | ||
92f5a8d4 TL |
1560 | if (neg) |
1561 | { | |
1562 | mantissa = -mantissa; | |
1563 | } | |
7c673cae FG |
1564 | } |
1565 | ||
1566 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1567 | double cpp_dec_float<Digits10, ExponentType, Allocator>::extract_double() const | |
1568 | { | |
1569 | // Returns the double conversion of a cpp_dec_float<Digits10, ExponentType, Allocator>. | |
1570 | ||
1571 | // Check for non-normal cpp_dec_float<Digits10, ExponentType, Allocator>. | |
92f5a8d4 | 1572 | if (!(isfinite)()) |
7c673cae | 1573 | { |
92f5a8d4 | 1574 | if ((isnan)()) |
7c673cae FG |
1575 | { |
1576 | return std::numeric_limits<double>::quiet_NaN(); | |
1577 | } | |
1578 | else | |
1579 | { | |
1580 | return ((!neg) ? std::numeric_limits<double>::infinity() | |
92f5a8d4 | 1581 | : -std::numeric_limits<double>::infinity()); |
7c673cae FG |
1582 | } |
1583 | } | |
1584 | ||
1585 | cpp_dec_float<Digits10, ExponentType, Allocator> xx(*this); | |
92f5a8d4 | 1586 | if (xx.isneg()) |
7c673cae FG |
1587 | xx.negate(); |
1588 | ||
1589 | // Check if *this cpp_dec_float<Digits10, ExponentType, Allocator> is zero. | |
92f5a8d4 | 1590 | if (iszero() || (xx.compare(double_min()) < 0)) |
7c673cae FG |
1591 | { |
1592 | return 0.0; | |
1593 | } | |
1594 | ||
1595 | // Check if *this cpp_dec_float<Digits10, ExponentType, Allocator> exceeds the maximum of double. | |
92f5a8d4 | 1596 | if (xx.compare(double_max()) > 0) |
7c673cae FG |
1597 | { |
1598 | return ((!neg) ? std::numeric_limits<double>::infinity() | |
92f5a8d4 | 1599 | : -std::numeric_limits<double>::infinity()); |
7c673cae FG |
1600 | } |
1601 | ||
1e59de90 | 1602 | return std::strtod(str(std::numeric_limits<double>::digits10 + (2 + 1), std::ios_base::scientific).c_str(), nullptr); |
7c673cae FG |
1603 | } |
1604 | ||
1605 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1606 | long double cpp_dec_float<Digits10, ExponentType, Allocator>::extract_long_double() const | |
1607 | { | |
1608 | // Returns the long double conversion of a cpp_dec_float<Digits10, ExponentType, Allocator>. | |
1609 | ||
1610 | // Check if *this cpp_dec_float<Digits10, ExponentType, Allocator> is subnormal. | |
92f5a8d4 | 1611 | if (!(isfinite)()) |
7c673cae | 1612 | { |
92f5a8d4 | 1613 | if ((isnan)()) |
7c673cae FG |
1614 | { |
1615 | return std::numeric_limits<long double>::quiet_NaN(); | |
1616 | } | |
1617 | else | |
1618 | { | |
1619 | return ((!neg) ? std::numeric_limits<long double>::infinity() | |
92f5a8d4 | 1620 | : -std::numeric_limits<long double>::infinity()); |
7c673cae FG |
1621 | } |
1622 | } | |
1623 | ||
1624 | cpp_dec_float<Digits10, ExponentType, Allocator> xx(*this); | |
92f5a8d4 | 1625 | if (xx.isneg()) |
7c673cae FG |
1626 | xx.negate(); |
1627 | ||
1628 | // Check if *this cpp_dec_float<Digits10, ExponentType, Allocator> is zero. | |
92f5a8d4 | 1629 | if (iszero() || (xx.compare(long_double_min()) < 0)) |
7c673cae FG |
1630 | { |
1631 | return static_cast<long double>(0.0); | |
1632 | } | |
1633 | ||
1634 | // Check if *this cpp_dec_float<Digits10, ExponentType, Allocator> exceeds the maximum of double. | |
92f5a8d4 | 1635 | if (xx.compare(long_double_max()) > 0) |
7c673cae FG |
1636 | { |
1637 | return ((!neg) ? std::numeric_limits<long double>::infinity() | |
92f5a8d4 | 1638 | : -std::numeric_limits<long double>::infinity()); |
7c673cae FG |
1639 | } |
1640 | ||
1e59de90 | 1641 | return std::strtold(str(std::numeric_limits<long double>::digits10 + (2 + 1), std::ios_base::scientific).c_str(), nullptr); |
7c673cae FG |
1642 | } |
1643 | ||
1644 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1e59de90 | 1645 | long long cpp_dec_float<Digits10, ExponentType, Allocator>::extract_signed_long_long() const |
7c673cae FG |
1646 | { |
1647 | // Extracts a signed long long from *this. | |
1648 | // If (x > maximum of long long) or (x < minimum of long long), | |
1649 | // then the maximum or minimum of long long is returned accordingly. | |
1650 | ||
1e59de90 | 1651 | if (exp < static_cast<exponent_type>(0)) |
7c673cae | 1652 | { |
1e59de90 | 1653 | return static_cast<long long>(0); |
7c673cae FG |
1654 | } |
1655 | ||
1656 | const bool b_neg = isneg(); | |
1657 | ||
1e59de90 | 1658 | unsigned long long val; |
7c673cae | 1659 | |
92f5a8d4 | 1660 | if ((!b_neg) && (compare(long_long_max()) > 0)) |
7c673cae | 1661 | { |
1e59de90 | 1662 | return (std::numeric_limits<long long>::max)(); |
7c673cae | 1663 | } |
92f5a8d4 | 1664 | else if (b_neg && (compare(long_long_min()) < 0)) |
7c673cae | 1665 | { |
1e59de90 | 1666 | return (std::numeric_limits<long long>::min)(); |
7c673cae FG |
1667 | } |
1668 | else | |
1669 | { | |
1e59de90 | 1670 | // Extract the data into an unsigned long long value. |
7c673cae | 1671 | cpp_dec_float<Digits10, ExponentType, Allocator> xn(extract_integer_part()); |
92f5a8d4 | 1672 | if (xn.isneg()) |
7c673cae FG |
1673 | xn.negate(); |
1674 | ||
1e59de90 | 1675 | val = static_cast<unsigned long long>(xn.data[0]); |
7c673cae | 1676 | |
1e59de90 | 1677 | const std::int32_t imax = (std::min)(static_cast<std::int32_t>(static_cast<std::int32_t>(xn.exp) / cpp_dec_float_elem_digits10), static_cast<std::int32_t>(cpp_dec_float_elem_number - static_cast<std::int32_t>(1))); |
7c673cae | 1678 | |
1e59de90 | 1679 | for (std::int32_t i = static_cast<std::int32_t>(1); i <= imax; i++) |
7c673cae | 1680 | { |
1e59de90 TL |
1681 | val *= static_cast<unsigned long long>(cpp_dec_float_elem_mask); |
1682 | val += static_cast<unsigned long long>(xn.data[static_cast<std::size_t>(i)]); | |
7c673cae FG |
1683 | } |
1684 | } | |
1685 | ||
1686 | if (!b_neg) | |
1687 | { | |
1e59de90 | 1688 | return static_cast<long long>(val); |
7c673cae FG |
1689 | } |
1690 | else | |
1691 | { | |
1692 | // This strange expression avoids a hardware trap in the corner case | |
1e59de90 | 1693 | // that val is the most negative value permitted in long long. |
7c673cae FG |
1694 | // See https://svn.boost.org/trac/boost/ticket/9740. |
1695 | // | |
1e59de90 | 1696 | long long sval = static_cast<long long>(val - 1); |
92f5a8d4 | 1697 | sval = -sval; |
7c673cae FG |
1698 | --sval; |
1699 | return sval; | |
1700 | } | |
1701 | } | |
1702 | ||
1703 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1e59de90 | 1704 | unsigned long long cpp_dec_float<Digits10, ExponentType, Allocator>::extract_unsigned_long_long() const |
7c673cae | 1705 | { |
1e59de90 TL |
1706 | // Extracts an unsigned long long from *this. |
1707 | // If x exceeds the maximum of unsigned long long, | |
1708 | // then the maximum of unsigned long long is returned. | |
1709 | // If x is negative, then the unsigned long long cast of | |
7c673cae FG |
1710 | // the long long extracted value is returned. |
1711 | ||
92f5a8d4 | 1712 | if (isneg()) |
7c673cae | 1713 | { |
1e59de90 | 1714 | return static_cast<unsigned long long>(extract_signed_long_long()); |
7c673cae FG |
1715 | } |
1716 | ||
1e59de90 | 1717 | if (exp < static_cast<exponent_type>(0)) |
7c673cae | 1718 | { |
1e59de90 | 1719 | return static_cast<unsigned long long>(0u); |
7c673cae FG |
1720 | } |
1721 | ||
1722 | const cpp_dec_float<Digits10, ExponentType, Allocator> xn(extract_integer_part()); | |
1723 | ||
1e59de90 | 1724 | unsigned long long val; |
7c673cae | 1725 | |
92f5a8d4 | 1726 | if (xn.compare(ulong_long_max()) > 0) |
7c673cae | 1727 | { |
1e59de90 | 1728 | return (std::numeric_limits<unsigned long long>::max)(); |
7c673cae FG |
1729 | } |
1730 | else | |
1731 | { | |
1e59de90 TL |
1732 | // Extract the data into an unsigned long long value. |
1733 | val = static_cast<unsigned long long>(xn.data[0]); | |
7c673cae | 1734 | |
1e59de90 | 1735 | const std::int32_t imax = (std::min)(static_cast<std::int32_t>(static_cast<std::int32_t>(xn.exp) / cpp_dec_float_elem_digits10), static_cast<std::int32_t>(cpp_dec_float_elem_number - static_cast<std::int32_t>(1))); |
7c673cae | 1736 | |
1e59de90 | 1737 | for (std::int32_t i = static_cast<std::int32_t>(1); i <= imax; i++) |
7c673cae | 1738 | { |
1e59de90 TL |
1739 | val *= static_cast<unsigned long long>(cpp_dec_float_elem_mask); |
1740 | val += static_cast<unsigned long long>(xn.data[i]); | |
7c673cae FG |
1741 | } |
1742 | } | |
1743 | ||
1744 | return val; | |
1745 | } | |
1746 | ||
1e59de90 TL |
1747 | #ifdef BOOST_HAS_INT128 |
1748 | ||
1749 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1750 | int128_type cpp_dec_float<Digits10, ExponentType, Allocator>::extract_signed_int128() const | |
1751 | { | |
1752 | // Extracts a signed __int128 from *this. | |
1753 | // If (x > maximum of __int128) or (x < minimum of __int128), | |
1754 | // then the maximum or minimum of long long is returned accordingly. | |
1755 | ||
1756 | if (exp < static_cast<exponent_type>(0)) | |
1757 | { | |
1758 | return static_cast<int128_type>(0); | |
1759 | } | |
1760 | ||
1761 | const bool b_neg = isneg(); | |
1762 | cpp_dec_float<Digits10, ExponentType, Allocator> i128max; | |
1763 | i128max = ((~static_cast<uint128_type>(0)) >> 1); | |
1764 | cpp_dec_float<Digits10, ExponentType, Allocator> i128min; | |
1765 | i128min = (-1 - static_cast<int128_type>((static_cast<uint128_type>(1) << 127) - 1)); | |
1766 | ||
1767 | uint128_type val; | |
1768 | ||
1769 | if ((!b_neg) && (compare(i128max) > 0)) | |
1770 | { | |
1771 | return ((~static_cast<uint128_type>(0)) >> 1); | |
1772 | } | |
1773 | else if (b_neg && (compare(i128min) < 0)) | |
1774 | { | |
1775 | return (-1 - static_cast<int128_type>((static_cast<uint128_type>(1) << 127) - 1)); | |
1776 | } | |
1777 | else | |
1778 | { | |
1779 | // Extract the data into an unsigned long long value. | |
1780 | cpp_dec_float<Digits10, ExponentType, Allocator> xn(extract_integer_part()); | |
1781 | if (xn.isneg()) | |
1782 | xn.negate(); | |
1783 | ||
1784 | val = static_cast<uint128_type>(xn.data[0]); | |
1785 | ||
1786 | const std::int32_t imax = (std::min)(static_cast<std::int32_t>(static_cast<std::int32_t>(xn.exp) / cpp_dec_float_elem_digits10), static_cast<std::int32_t>(cpp_dec_float_elem_number - static_cast<std::int32_t>(1))); | |
1787 | ||
1788 | for (std::int32_t i = static_cast<std::int32_t>(1); i <= imax; i++) | |
1789 | { | |
1790 | val *= static_cast<uint128_type>(cpp_dec_float_elem_mask); | |
1791 | val += static_cast<uint128_type>(xn.data[static_cast<std::size_t>(i)]); | |
1792 | } | |
1793 | } | |
1794 | ||
1795 | if (!b_neg) | |
1796 | { | |
1797 | return static_cast<int128_type>(val); | |
1798 | } | |
1799 | else | |
1800 | { | |
1801 | // This strange expression avoids a hardware trap in the corner case | |
1802 | // that val is the most negative value permitted in long long. | |
1803 | // See https://svn.boost.org/trac/boost/ticket/9740. | |
1804 | // | |
1805 | int128_type sval = static_cast<int128_type>(val - 1); | |
1806 | sval = -sval; | |
1807 | --sval; | |
1808 | return sval; | |
1809 | } | |
1810 | } | |
1811 | ||
1812 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1813 | uint128_type cpp_dec_float<Digits10, ExponentType, Allocator>::extract_unsigned_int128() const | |
1814 | { | |
1815 | // Extracts an unsigned __int128 from *this. | |
1816 | // If x exceeds the maximum of unsigned __int128, | |
1817 | // then the maximum of unsigned __int128 is returned. | |
1818 | // If x is negative, then the unsigned __int128 cast of | |
1819 | // the __int128 extracted value is returned. | |
1820 | ||
1821 | if (isneg()) | |
1822 | { | |
1823 | return static_cast<uint128_type>(extract_signed_int128()); | |
1824 | } | |
1825 | ||
1826 | if (exp < static_cast<exponent_type>(0)) | |
1827 | { | |
1828 | return 0u; | |
1829 | } | |
1830 | ||
1831 | const cpp_dec_float<Digits10, ExponentType, Allocator> xn(extract_integer_part()); | |
1832 | cpp_dec_float<Digits10, ExponentType, Allocator> i128max; | |
1833 | i128max = (~static_cast<uint128_type>(0)); | |
1834 | ||
1835 | uint128_type val; | |
1836 | ||
1837 | if (xn.compare(i128max) > 0) | |
1838 | { | |
1839 | return (~static_cast<uint128_type>(0)); | |
1840 | } | |
1841 | else | |
1842 | { | |
1843 | // Extract the data into an unsigned long long value. | |
1844 | val = static_cast<uint128_type>(xn.data[0]); | |
1845 | ||
1846 | const std::int32_t imax = (std::min)(static_cast<std::int32_t>(static_cast<std::int32_t>(xn.exp) / cpp_dec_float_elem_digits10), static_cast<std::int32_t>(cpp_dec_float_elem_number - static_cast<std::int32_t>(1))); | |
1847 | ||
1848 | for (std::int32_t i = static_cast<std::int32_t>(1); i <= imax; i++) | |
1849 | { | |
1850 | val *= static_cast<uint128_type>(cpp_dec_float_elem_mask); | |
1851 | val += static_cast<uint128_type>(xn.data[i]); | |
1852 | } | |
1853 | } | |
1854 | ||
1855 | return val; | |
1856 | } | |
1857 | ||
1858 | #endif | |
1859 | ||
7c673cae FG |
1860 | template <unsigned Digits10, class ExponentType, class Allocator> |
1861 | cpp_dec_float<Digits10, ExponentType, Allocator> cpp_dec_float<Digits10, ExponentType, Allocator>::extract_integer_part() const | |
1862 | { | |
1863 | // Compute the signed integer part of x. | |
1864 | ||
92f5a8d4 | 1865 | if (!(isfinite)()) |
7c673cae FG |
1866 | { |
1867 | return *this; | |
1868 | } | |
1869 | ||
92f5a8d4 | 1870 | if (exp < static_cast<ExponentType>(0)) |
7c673cae FG |
1871 | { |
1872 | // The absolute value of the number is smaller than 1. | |
1873 | // Thus the integer part is zero. | |
1874 | return zero(); | |
1875 | } | |
1876 | ||
1877 | // Truncate the digits from the decimal part, including guard digits | |
1878 | // that do not belong to the integer part. | |
1879 | ||
1880 | // Make a local copy. | |
1881 | cpp_dec_float<Digits10, ExponentType, Allocator> x = *this; | |
1882 | ||
1883 | // Clear out the decimal portion | |
1884 | const size_t first_clear = (static_cast<size_t>(x.exp) / static_cast<size_t>(cpp_dec_float_elem_digits10)) + 1u; | |
92f5a8d4 | 1885 | const size_t last_clear = static_cast<size_t>(cpp_dec_float_elem_number); |
7c673cae | 1886 | |
92f5a8d4 | 1887 | if (first_clear < last_clear) |
1e59de90 | 1888 | std::fill(x.data.begin() + first_clear, x.data.begin() + last_clear, static_cast<std::uint32_t>(0u)); |
7c673cae FG |
1889 | |
1890 | return x; | |
1891 | } | |
1892 | ||
1893 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1e59de90 | 1894 | std::string cpp_dec_float<Digits10, ExponentType, Allocator>::str(std::intmax_t number_of_digits, std::ios_base::fmtflags f) const |
7c673cae | 1895 | { |
92f5a8d4 | 1896 | if ((this->isinf)()) |
7c673cae | 1897 | { |
92f5a8d4 | 1898 | if (this->isneg()) |
7c673cae | 1899 | return "-inf"; |
92f5a8d4 | 1900 | else if (f & std::ios_base::showpos) |
7c673cae FG |
1901 | return "+inf"; |
1902 | else | |
1903 | return "inf"; | |
1904 | } | |
92f5a8d4 | 1905 | else if ((this->isnan)()) |
7c673cae FG |
1906 | { |
1907 | return "nan"; | |
1908 | } | |
1909 | ||
92f5a8d4 | 1910 | std::string str; |
1e59de90 TL |
1911 | std::intmax_t org_digits(number_of_digits); |
1912 | exponent_type my_exp = order(); | |
7c673cae | 1913 | |
1e59de90 TL |
1914 | if (!(f & std::ios_base::fixed) && (number_of_digits == 0)) |
1915 | number_of_digits = cpp_dec_float_max_digits10; | |
7c673cae | 1916 | |
92f5a8d4 | 1917 | if (f & std::ios_base::fixed) |
7c673cae FG |
1918 | { |
1919 | number_of_digits += my_exp + 1; | |
1920 | } | |
92f5a8d4 | 1921 | else if (f & std::ios_base::scientific) |
7c673cae FG |
1922 | ++number_of_digits; |
1923 | // Determine the number of elements needed to provide the requested digits from cpp_dec_float<Digits10, ExponentType, Allocator>. | |
1924 | const std::size_t number_of_elements = (std::min)(static_cast<std::size_t>((number_of_digits / static_cast<std::size_t>(cpp_dec_float_elem_digits10)) + 2u), | |
92f5a8d4 | 1925 | static_cast<std::size_t>(cpp_dec_float_elem_number)); |
7c673cae FG |
1926 | |
1927 | // Extract the remaining digits from cpp_dec_float<Digits10, ExponentType, Allocator> after the decimal point. | |
92f5a8d4 | 1928 | std::stringstream ss; |
f67539c2 TL |
1929 | ss.imbue(std::locale::classic()); |
1930 | ss << data[0]; | |
7c673cae | 1931 | // Extract all of the digits from cpp_dec_float<Digits10, ExponentType, Allocator>, beginning with the first data element. |
92f5a8d4 | 1932 | for (std::size_t i = static_cast<std::size_t>(1u); i < number_of_elements; i++) |
7c673cae | 1933 | { |
7c673cae FG |
1934 | ss << std::setw(static_cast<std::streamsize>(cpp_dec_float_elem_digits10)) |
1935 | << std::setfill(static_cast<char>('0')) | |
1936 | << data[i]; | |
7c673cae | 1937 | } |
92f5a8d4 | 1938 | str += ss.str(); |
7c673cae FG |
1939 | |
1940 | bool have_leading_zeros = false; | |
1941 | ||
92f5a8d4 | 1942 | if (number_of_digits == 0) |
7c673cae FG |
1943 | { |
1944 | // We only get here if the output format is "fixed" and we just need to | |
1945 | // round the first non-zero digit. | |
1946 | number_of_digits -= my_exp + 1; // reset to original value | |
1e59de90 TL |
1947 | if (number_of_digits) |
1948 | { | |
1949 | str.insert(static_cast<std::string::size_type>(0), std::string::size_type(number_of_digits), '0'); | |
1950 | have_leading_zeros = true; | |
1951 | } | |
7c673cae FG |
1952 | } |
1953 | ||
92f5a8d4 | 1954 | if (number_of_digits < 0) |
7c673cae FG |
1955 | { |
1956 | str = "0"; | |
92f5a8d4 | 1957 | if (isneg()) |
7c673cae FG |
1958 | str.insert(static_cast<std::string::size_type>(0), 1, '-'); |
1959 | boost::multiprecision::detail::format_float_string(str, 0, number_of_digits - my_exp - 1, f, this->iszero()); | |
1960 | return str; | |
1961 | } | |
1962 | else | |
1963 | { | |
1964 | // Cut the output to the size of the precision. | |
92f5a8d4 | 1965 | if (str.length() > static_cast<std::string::size_type>(number_of_digits)) |
7c673cae FG |
1966 | { |
1967 | // Get the digit after the last needed digit for rounding | |
1e59de90 | 1968 | const std::uint32_t round = static_cast<std::uint32_t>(static_cast<std::uint32_t>(str[static_cast<std::string::size_type>(number_of_digits)]) - static_cast<std::uint32_t>('0')); |
7c673cae FG |
1969 | |
1970 | bool need_round_up = round >= 5u; | |
1971 | ||
92f5a8d4 | 1972 | if (round == 5u) |
7c673cae | 1973 | { |
1e59de90 | 1974 | const std::uint32_t ix = number_of_digits == 0 ? 0 : static_cast<std::uint32_t>(static_cast<std::uint32_t>(str[static_cast<std::string::size_type>(number_of_digits - 1)]) - static_cast<std::uint32_t>('0')); |
92f5a8d4 | 1975 | if ((ix & 1u) == 0) |
7c673cae FG |
1976 | { |
1977 | // We have an even digit followed by a 5, so we might not actually need to round up | |
1978 | // if all the remaining digits are zero: | |
92f5a8d4 | 1979 | if (str.find_first_not_of('0', static_cast<std::string::size_type>(number_of_digits + 1)) == std::string::npos) |
7c673cae FG |
1980 | { |
1981 | bool all_zeros = true; | |
1982 | // No none-zero trailing digits in the string, now check whatever parts we didn't convert to the string: | |
92f5a8d4 | 1983 | for (std::size_t i = number_of_elements; i < data.size(); i++) |
7c673cae | 1984 | { |
92f5a8d4 | 1985 | if (data[i]) |
7c673cae FG |
1986 | { |
1987 | all_zeros = false; | |
1988 | break; | |
1989 | } | |
1990 | } | |
92f5a8d4 | 1991 | if (all_zeros) |
7c673cae FG |
1992 | need_round_up = false; // tie break - round to even. |
1993 | } | |
1994 | } | |
1995 | } | |
1996 | ||
1997 | // Truncate the string | |
1998 | str.erase(static_cast<std::string::size_type>(number_of_digits)); | |
1999 | ||
92f5a8d4 | 2000 | if (need_round_up) |
7c673cae | 2001 | { |
1e59de90 | 2002 | if (str.size()) |
7c673cae | 2003 | { |
1e59de90 | 2004 | std::size_t ix = static_cast<std::size_t>(str.length() - 1u); |
7c673cae | 2005 | |
1e59de90 TL |
2006 | // Every trailing 9 must be rounded up |
2007 | while (ix && (static_cast<std::int32_t>(str.at(ix)) - static_cast<std::int32_t>('0') == static_cast<std::int32_t>(9))) | |
2008 | { | |
2009 | str.at(ix) = static_cast<char>('0'); | |
2010 | --ix; | |
2011 | } | |
2012 | ||
2013 | if (!ix) | |
7c673cae | 2014 | { |
1e59de90 TL |
2015 | // There were nothing but trailing nines. |
2016 | if (static_cast<std::int32_t>(static_cast<std::int32_t>(str.at(ix)) - static_cast<std::int32_t>(0x30)) == static_cast<std::int32_t>(9)) | |
2017 | { | |
2018 | // Increment up to the next order and adjust exponent. | |
2019 | str.at(ix) = static_cast<char>('1'); | |
2020 | ++my_exp; | |
2021 | } | |
2022 | else | |
2023 | { | |
2024 | // Round up this digit. | |
2025 | ++str.at(ix); | |
2026 | } | |
7c673cae FG |
2027 | } |
2028 | else | |
2029 | { | |
1e59de90 TL |
2030 | // Round up the last digit. |
2031 | ++str[ix]; | |
7c673cae FG |
2032 | } |
2033 | } | |
2034 | else | |
2035 | { | |
1e59de90 TL |
2036 | str = "1"; |
2037 | ++my_exp; | |
7c673cae FG |
2038 | } |
2039 | } | |
2040 | } | |
2041 | } | |
2042 | ||
92f5a8d4 | 2043 | if (have_leading_zeros) |
7c673cae FG |
2044 | { |
2045 | // We need to take the zeros back out again, and correct the exponent | |
2046 | // if we rounded up: | |
92f5a8d4 | 2047 | if (str[std::string::size_type(number_of_digits - 1)] != '0') |
7c673cae FG |
2048 | { |
2049 | ++my_exp; | |
2050 | str.erase(0, std::string::size_type(number_of_digits - 1)); | |
2051 | } | |
2052 | else | |
2053 | str.erase(0, std::string::size_type(number_of_digits)); | |
2054 | } | |
2055 | ||
92f5a8d4 | 2056 | if (isneg()) |
7c673cae FG |
2057 | str.insert(static_cast<std::string::size_type>(0), 1, '-'); |
2058 | ||
2059 | boost::multiprecision::detail::format_float_string(str, my_exp, org_digits, f, this->iszero()); | |
2060 | return str; | |
2061 | } | |
2062 | ||
2063 | template <unsigned Digits10, class ExponentType, class Allocator> | |
2064 | bool cpp_dec_float<Digits10, ExponentType, Allocator>::rd_string(const char* const s) | |
2065 | { | |
2066 | #ifndef BOOST_NO_EXCEPTIONS | |
92f5a8d4 TL |
2067 | try |
2068 | { | |
7c673cae FG |
2069 | #endif |
2070 | ||
92f5a8d4 | 2071 | std::string str(s); |
7c673cae | 2072 | |
92f5a8d4 TL |
2073 | // TBD: Using several regular expressions may significantly reduce |
2074 | // the code complexity (and perhaps the run-time) of rd_string(). | |
7c673cae | 2075 | |
92f5a8d4 | 2076 | // Get a possible exponent and remove it. |
1e59de90 | 2077 | exp = static_cast<exponent_type>(0); |
7c673cae | 2078 | |
92f5a8d4 | 2079 | std::size_t pos; |
7c673cae | 2080 | |
92f5a8d4 | 2081 | if (((pos = str.find('e')) != std::string::npos) || ((pos = str.find('E')) != std::string::npos)) |
7c673cae | 2082 | { |
92f5a8d4 | 2083 | // Remove the exponent part from the string. |
1e59de90 TL |
2084 | #ifndef BOOST_MP_STANDALONE |
2085 | exp = boost::lexical_cast<exponent_type>(static_cast<const char*>(str.c_str() + (pos + 1u))); | |
2086 | #else | |
2087 | exp = static_cast<exponent_type>(std::atoll(static_cast<const char*>(str.c_str() + (pos + 1u)))); | |
2088 | #endif | |
2089 | ||
92f5a8d4 | 2090 | str = str.substr(static_cast<std::size_t>(0u), pos); |
7c673cae | 2091 | } |
7c673cae | 2092 | |
92f5a8d4 TL |
2093 | // Get a possible +/- sign and remove it. |
2094 | neg = false; | |
7c673cae | 2095 | |
92f5a8d4 TL |
2096 | if (str.size()) |
2097 | { | |
2098 | if (str[0] == '-') | |
2099 | { | |
2100 | neg = true; | |
2101 | str.erase(0, 1); | |
2102 | } | |
2103 | else if (str[0] == '+') | |
2104 | { | |
2105 | str.erase(0, 1); | |
2106 | } | |
2107 | } | |
2108 | // | |
2109 | // Special cases for infinities and NaN's: | |
2110 | // | |
2111 | if ((str == "inf") || (str == "INF") || (str == "infinity") || (str == "INFINITY")) | |
7c673cae | 2112 | { |
92f5a8d4 TL |
2113 | if (neg) |
2114 | { | |
2115 | *this = this->inf(); | |
2116 | this->negate(); | |
2117 | } | |
2118 | else | |
2119 | *this = this->inf(); | |
7c673cae FG |
2120 | return true; |
2121 | } | |
92f5a8d4 | 2122 | if ((str.size() >= 3) && ((str.substr(0, 3) == "nan") || (str.substr(0, 3) == "NAN") || (str.substr(0, 3) == "NaN"))) |
7c673cae | 2123 | { |
92f5a8d4 TL |
2124 | *this = this->nan(); |
2125 | return true; | |
7c673cae | 2126 | } |
7c673cae | 2127 | |
92f5a8d4 TL |
2128 | // Remove the leading zeros for all input types. |
2129 | const std::string::iterator fwd_it_leading_zero = std::find_if(str.begin(), str.end(), char_is_nonzero_predicate); | |
7c673cae | 2130 | |
92f5a8d4 | 2131 | if (fwd_it_leading_zero != str.begin()) |
7c673cae | 2132 | { |
92f5a8d4 TL |
2133 | if (fwd_it_leading_zero == str.end()) |
2134 | { | |
2135 | // The string contains nothing but leading zeros. | |
2136 | // This string represents zero. | |
2137 | operator=(zero()); | |
2138 | return true; | |
2139 | } | |
2140 | else | |
2141 | { | |
2142 | str.erase(str.begin(), fwd_it_leading_zero); | |
2143 | } | |
7c673cae FG |
2144 | } |
2145 | ||
92f5a8d4 TL |
2146 | // Put the input string into the standard cpp_dec_float<Digits10, ExponentType, Allocator> input form |
2147 | // aaa.bbbbE+/-n, where aaa has 1...cpp_dec_float_elem_digits10, bbbb has an | |
2148 | // even multiple of cpp_dec_float_elem_digits10 which are possibly zero padded | |
2149 | // on the right-end, and n is a signed 64-bit integer which is an | |
2150 | // even multiple of cpp_dec_float_elem_digits10. | |
7c673cae | 2151 | |
92f5a8d4 TL |
2152 | // Find a possible decimal point. |
2153 | pos = str.find(static_cast<char>('.')); | |
2154 | ||
2155 | if (pos != std::string::npos) | |
7c673cae | 2156 | { |
92f5a8d4 TL |
2157 | // Remove all trailing insignificant zeros. |
2158 | const std::string::const_reverse_iterator rit_non_zero = std::find_if(str.rbegin(), str.rend(), char_is_nonzero_predicate); | |
7c673cae | 2159 | |
92f5a8d4 TL |
2160 | if (rit_non_zero != static_cast<std::string::const_reverse_iterator>(str.rbegin())) |
2161 | { | |
1e59de90 TL |
2162 | const std::string::size_type ofs = |
2163 | static_cast<std::string::size_type> | |
2164 | ( | |
2165 | static_cast<std::ptrdiff_t>(str.length()) | |
2166 | - std::distance<std::string::const_reverse_iterator>(str.rbegin(), rit_non_zero) | |
2167 | ); | |
2168 | str.erase(str.begin() + static_cast<std::ptrdiff_t>(ofs), str.end()); | |
92f5a8d4 | 2169 | } |
7c673cae | 2170 | |
92f5a8d4 TL |
2171 | // Check if the input is identically zero. |
2172 | if (str == std::string(".")) | |
7c673cae | 2173 | { |
92f5a8d4 TL |
2174 | operator=(zero()); |
2175 | return true; | |
7c673cae FG |
2176 | } |
2177 | ||
92f5a8d4 TL |
2178 | // Remove leading significant zeros just after the decimal point |
2179 | // and adjust the exponent accordingly. | |
2180 | // Note that the while-loop operates only on strings of the form ".000abcd..." | |
2181 | // and peels away the zeros just after the decimal point. | |
2182 | if (str.at(static_cast<std::size_t>(0u)) == static_cast<char>('.')) | |
2183 | { | |
2184 | const std::string::iterator it_non_zero = std::find_if(str.begin() + 1u, str.end(), char_is_nonzero_predicate); | |
2185 | ||
2186 | std::size_t delta_exp = static_cast<std::size_t>(0u); | |
2187 | ||
2188 | if (str.at(static_cast<std::size_t>(1u)) == static_cast<char>('0')) | |
2189 | { | |
1e59de90 | 2190 | delta_exp = static_cast<std::size_t>(std::distance<std::string::const_iterator>(str.begin() + 1u, it_non_zero)); |
92f5a8d4 TL |
2191 | } |
2192 | ||
2193 | // Bring one single digit into the mantissa and adjust the exponent accordingly. | |
2194 | str.erase(str.begin(), it_non_zero); | |
2195 | str.insert(static_cast<std::string::size_type>(1u), "."); | |
1e59de90 | 2196 | exp -= static_cast<exponent_type>(delta_exp + 1u); |
92f5a8d4 TL |
2197 | } |
2198 | } | |
2199 | else | |
2200 | { | |
2201 | // Input string has no decimal point: Append decimal point. | |
2202 | str.append("."); | |
7c673cae | 2203 | } |
7c673cae | 2204 | |
92f5a8d4 | 2205 | // Shift the decimal point such that the exponent is an even multiple of cpp_dec_float_elem_digits10. |
1e59de90 TL |
2206 | std::ptrdiff_t n_shift = static_cast<std::ptrdiff_t>(0); |
2207 | const std::ptrdiff_t n_exp_rem = static_cast<std::ptrdiff_t>(exp % static_cast<exponent_type>(cpp_dec_float_elem_digits10)); | |
7c673cae | 2208 | |
1e59de90 | 2209 | if((exp % static_cast<exponent_type>(cpp_dec_float_elem_digits10)) != static_cast<exponent_type>(0)) |
92f5a8d4 | 2210 | { |
1e59de90 TL |
2211 | n_shift = ((exp < static_cast<exponent_type>(0)) |
2212 | ? static_cast<std::ptrdiff_t>(n_exp_rem + static_cast<std::ptrdiff_t>(cpp_dec_float_elem_digits10)) | |
2213 | : static_cast<std::ptrdiff_t>(n_exp_rem)); | |
92f5a8d4 | 2214 | } |
7c673cae | 2215 | |
92f5a8d4 TL |
2216 | // Make sure that there are enough digits for the decimal point shift. |
2217 | pos = str.find(static_cast<char>('.')); | |
7c673cae | 2218 | |
1e59de90 | 2219 | std::ptrdiff_t pos_plus_one = static_cast<std::ptrdiff_t>(pos + 1); |
7c673cae | 2220 | |
1e59de90 | 2221 | if ((static_cast<std::ptrdiff_t>(str.length()) - pos_plus_one) < n_shift) |
92f5a8d4 | 2222 | { |
1e59de90 | 2223 | const std::ptrdiff_t sz = static_cast<std::ptrdiff_t>(n_shift - (static_cast<std::ptrdiff_t>(str.length()) - pos_plus_one)); |
7c673cae | 2224 | |
1e59de90 | 2225 | str.append(std::string(static_cast<std::string::size_type>(sz), static_cast<char>('0'))); |
92f5a8d4 | 2226 | } |
7c673cae | 2227 | |
92f5a8d4 | 2228 | // Do the decimal point shift. |
1e59de90 | 2229 | if (n_shift != static_cast<std::ptrdiff_t>(0)) |
92f5a8d4 TL |
2230 | { |
2231 | str.insert(static_cast<std::string::size_type>(pos_plus_one + n_shift), "."); | |
7c673cae | 2232 | |
1e59de90 | 2233 | str.erase(pos, static_cast<std::ptrdiff_t>(1)); |
7c673cae | 2234 | |
1e59de90 | 2235 | exp -= static_cast<exponent_type>(n_shift); |
92f5a8d4 | 2236 | } |
7c673cae | 2237 | |
92f5a8d4 TL |
2238 | // Cut the size of the mantissa to <= cpp_dec_float_elem_digits10. |
2239 | pos = str.find(static_cast<char>('.')); | |
1e59de90 | 2240 | pos_plus_one = static_cast<std::ptrdiff_t>(pos + 1u); |
7c673cae | 2241 | |
92f5a8d4 TL |
2242 | if (pos > static_cast<std::size_t>(cpp_dec_float_elem_digits10)) |
2243 | { | |
1e59de90 TL |
2244 | const std::int32_t n_pos = static_cast<std::int32_t>(pos); |
2245 | const std::int32_t n_rem_is_zero = ((static_cast<std::int32_t>(n_pos % cpp_dec_float_elem_digits10) == static_cast<std::int32_t>(0)) ? static_cast<std::int32_t>(1) : static_cast<std::int32_t>(0)); | |
2246 | const std::int32_t n = static_cast<std::int32_t>(static_cast<std::int32_t>(n_pos / cpp_dec_float_elem_digits10) - n_rem_is_zero); | |
7c673cae | 2247 | |
1e59de90 | 2248 | str.insert(static_cast<std::size_t>(static_cast<std::int32_t>(n_pos - static_cast<std::int32_t>(n * cpp_dec_float_elem_digits10))), "."); |
7c673cae | 2249 | |
1e59de90 | 2250 | str.erase(static_cast<std::size_t>(pos_plus_one), static_cast<std::size_t>(1u)); |
7c673cae | 2251 | |
1e59de90 | 2252 | exp += static_cast<exponent_type>(static_cast<exponent_type>(n) * static_cast<exponent_type>(cpp_dec_float_elem_digits10)); |
92f5a8d4 | 2253 | } |
7c673cae | 2254 | |
92f5a8d4 TL |
2255 | // Pad the decimal part such that its value is an even |
2256 | // multiple of cpp_dec_float_elem_digits10. | |
2257 | pos = str.find(static_cast<char>('.')); | |
1e59de90 | 2258 | pos_plus_one = static_cast<std::ptrdiff_t>(pos + 1u); |
7c673cae | 2259 | |
1e59de90 TL |
2260 | // Throws an error for a strange construction like 3.14L |
2261 | if(pos != std::string::npos && (str.back() == 'L' || str.back() == 'l' || str.back() == 'u' || str.back() == 'U')) | |
2262 | { | |
2263 | BOOST_MP_THROW_EXCEPTION(std::runtime_error("Can not construct a floating point with an integer literal")); | |
2264 | } | |
7c673cae | 2265 | |
1e59de90 TL |
2266 | const std::int32_t n_dec = static_cast<std::int32_t>(static_cast<std::int32_t>(str.length() - 1u) - static_cast<std::int32_t>(pos)); |
2267 | const std::int32_t n_rem = static_cast<std::int32_t>(n_dec % cpp_dec_float_elem_digits10); | |
7c673cae | 2268 | |
1e59de90 TL |
2269 | std::int32_t n_cnt = ((n_rem != static_cast<std::int32_t>(0)) |
2270 | ? static_cast<std::int32_t>(cpp_dec_float_elem_digits10 - n_rem) | |
2271 | : static_cast<std::int32_t>(0)); | |
2272 | ||
2273 | if (n_cnt != static_cast<std::int32_t>(0)) | |
92f5a8d4 TL |
2274 | { |
2275 | str.append(static_cast<std::size_t>(n_cnt), static_cast<char>('0')); | |
2276 | } | |
7c673cae | 2277 | |
92f5a8d4 TL |
2278 | // Truncate decimal part if it is too long. |
2279 | const std::size_t max_dec = static_cast<std::size_t>((cpp_dec_float_elem_number - 1) * cpp_dec_float_elem_digits10); | |
7c673cae | 2280 | |
92f5a8d4 TL |
2281 | if (static_cast<std::size_t>(str.length() - pos) > max_dec) |
2282 | { | |
2283 | str = str.substr(static_cast<std::size_t>(0u), | |
1e59de90 | 2284 | static_cast<std::size_t>(pos_plus_one + static_cast<std::ptrdiff_t>(max_dec))); |
92f5a8d4 | 2285 | } |
7c673cae | 2286 | |
92f5a8d4 TL |
2287 | // Now the input string has the standard cpp_dec_float<Digits10, ExponentType, Allocator> input form. |
2288 | // (See the comment above.) | |
7c673cae | 2289 | |
92f5a8d4 | 2290 | // Set all the data elements to 0. |
1e59de90 | 2291 | std::fill(data.begin(), data.end(), static_cast<std::uint32_t>(0u)); |
7c673cae | 2292 | |
92f5a8d4 | 2293 | // Extract the data. |
7c673cae | 2294 | |
92f5a8d4 | 2295 | // First get the digits to the left of the decimal point... |
1e59de90 | 2296 | data[0u] = static_cast<std::uint32_t>(std::stol(str.substr(static_cast<std::size_t>(0u), pos))); |
7c673cae | 2297 | |
92f5a8d4 | 2298 | // ...then get the remaining digits to the right of the decimal point. |
1e59de90 TL |
2299 | const std::string::size_type i_end = |
2300 | ( | |
2301 | static_cast<std::string::size_type>(str.length() - static_cast<std::string::size_type>(pos_plus_one)) | |
2302 | / static_cast<std::string::size_type>(cpp_dec_float_elem_digits10) | |
2303 | ); | |
7c673cae | 2304 | |
92f5a8d4 TL |
2305 | for (std::string::size_type i = static_cast<std::string::size_type>(0u); i < i_end; i++) |
2306 | { | |
1e59de90 TL |
2307 | const std::string::const_iterator it = |
2308 | str.begin() | |
2309 | + static_cast<std::ptrdiff_t> | |
2310 | ( | |
2311 | static_cast<std::string::size_type>(pos_plus_one) | |
2312 | + static_cast<std::string::size_type>(i * static_cast<std::string::size_type>(cpp_dec_float_elem_digits10)) | |
2313 | ); | |
2314 | ||
2315 | data[i + 1u] = static_cast<std::uint32_t>(std::stol(std::string(it, it + static_cast<std::string::size_type>(cpp_dec_float_elem_digits10)))); | |
92f5a8d4 | 2316 | } |
7c673cae | 2317 | |
92f5a8d4 TL |
2318 | // Check for overflow... |
2319 | if (exp > cpp_dec_float_max_exp10) | |
2320 | { | |
2321 | const bool b_result_is_neg = neg; | |
7c673cae | 2322 | |
92f5a8d4 TL |
2323 | *this = inf(); |
2324 | if (b_result_is_neg) | |
2325 | negate(); | |
2326 | } | |
7c673cae | 2327 | |
92f5a8d4 TL |
2328 | // ...and check for underflow. |
2329 | if (exp <= cpp_dec_float_min_exp10) | |
7c673cae | 2330 | { |
92f5a8d4 TL |
2331 | if (exp == cpp_dec_float_min_exp10) |
2332 | { | |
2333 | // Check for identity with the minimum value. | |
2334 | cpp_dec_float<Digits10, ExponentType, Allocator> test = *this; | |
7c673cae | 2335 | |
1e59de90 | 2336 | test.exp = static_cast<exponent_type>(0); |
7c673cae | 2337 | |
92f5a8d4 TL |
2338 | if (test.isone()) |
2339 | { | |
2340 | *this = zero(); | |
2341 | } | |
2342 | } | |
2343 | else | |
7c673cae FG |
2344 | { |
2345 | *this = zero(); | |
2346 | } | |
2347 | } | |
7c673cae FG |
2348 | |
2349 | #ifndef BOOST_NO_EXCEPTIONS | |
2350 | } | |
1e59de90 | 2351 | #ifndef BOOST_MP_STANDALONE |
92f5a8d4 | 2352 | catch (const bad_lexical_cast&) |
1e59de90 TL |
2353 | #else |
2354 | catch (const std::exception&) | |
2355 | #endif | |
7c673cae FG |
2356 | { |
2357 | // Rethrow with better error message: | |
2358 | std::string msg = "Unable to parse the string \""; | |
2359 | msg += s; | |
2360 | msg += "\" as a floating point value."; | |
2361 | throw std::runtime_error(msg); | |
2362 | } | |
2363 | #endif | |
2364 | return true; | |
2365 | } | |
2366 | ||
2367 | template <unsigned Digits10, class ExponentType, class Allocator> | |
2368 | cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float(const double mantissa, const ExponentType exponent) | |
92f5a8d4 TL |
2369 | : data(), |
2370 | exp(static_cast<ExponentType>(0)), | |
2371 | neg(false), | |
2372 | fpclass(cpp_dec_float_finite), | |
2373 | prec_elem(cpp_dec_float_elem_number) | |
7c673cae FG |
2374 | { |
2375 | // Create *this cpp_dec_float<Digits10, ExponentType, Allocator> from a given mantissa and exponent. | |
2376 | // Note: This constructor does not maintain the full precision of double. | |
2377 | ||
2378 | const bool mantissa_is_iszero = (::fabs(mantissa) < ((std::numeric_limits<double>::min)() * (1.0 + std::numeric_limits<double>::epsilon()))); | |
2379 | ||
92f5a8d4 | 2380 | if (mantissa_is_iszero) |
7c673cae | 2381 | { |
1e59de90 | 2382 | std::fill(data.begin(), data.end(), static_cast<std::uint32_t>(0u)); |
7c673cae FG |
2383 | return; |
2384 | } | |
2385 | ||
2386 | const bool b_neg = (mantissa < 0.0); | |
2387 | ||
92f5a8d4 | 2388 | double d = ((!b_neg) ? mantissa : -mantissa); |
1e59de90 | 2389 | exponent_type e = exponent; |
7c673cae | 2390 | |
92f5a8d4 TL |
2391 | while (d > 10.0) |
2392 | { | |
2393 | d /= 10.0; | |
2394 | ++e; | |
2395 | } | |
2396 | while (d < 1.0) | |
2397 | { | |
2398 | d *= 10.0; | |
2399 | --e; | |
2400 | } | |
7c673cae | 2401 | |
1e59de90 | 2402 | std::int32_t shift = static_cast<std::int32_t>(e % static_cast<std::int32_t>(cpp_dec_float_elem_digits10)); |
7c673cae | 2403 | |
1e59de90 | 2404 | while (static_cast<std::int32_t>(shift-- % cpp_dec_float_elem_digits10) != static_cast<std::int32_t>(0)) |
7c673cae FG |
2405 | { |
2406 | d *= 10.0; | |
2407 | --e; | |
2408 | } | |
2409 | ||
2410 | exp = e; | |
2411 | neg = b_neg; | |
2412 | ||
1e59de90 | 2413 | std::fill(data.begin(), data.end(), static_cast<std::uint32_t>(0u)); |
7c673cae | 2414 | |
1e59de90 TL |
2415 | constexpr std::int32_t digit_ratio = static_cast<std::int32_t>(static_cast<std::int32_t>(std::numeric_limits<double>::digits10) / static_cast<std::int32_t>(cpp_dec_float_elem_digits10)); |
2416 | constexpr std::int32_t digit_loops = static_cast<std::int32_t>(digit_ratio + static_cast<std::int32_t>(2)); | |
7c673cae | 2417 | |
1e59de90 | 2418 | for (std::int32_t i = static_cast<std::int32_t>(0); i < digit_loops; i++) |
7c673cae | 2419 | { |
1e59de90 TL |
2420 | std::uint32_t n = static_cast<std::uint32_t>(static_cast<std::uint64_t>(d)); |
2421 | data[static_cast<std::size_t>(i)] = static_cast<std::uint32_t>(n); | |
7c673cae FG |
2422 | d -= static_cast<double>(n); |
2423 | d *= static_cast<double>(cpp_dec_float_elem_mask); | |
2424 | } | |
2425 | } | |
2426 | ||
2427 | template <unsigned Digits10, class ExponentType, class Allocator> | |
f67539c2 | 2428 | template <class Float> |
1e59de90 | 2429 | typename std::enable_if<std::is_floating_point<Float>::value, cpp_dec_float<Digits10, ExponentType, Allocator>&>::type cpp_dec_float<Digits10, ExponentType, Allocator>::operator=(Float a) |
7c673cae | 2430 | { |
1e59de90 TL |
2431 | // Christopher Kormanyos's original code used a cast to long long here, but that fails |
2432 | // when long double has more digits than a long long. | |
2433 | BOOST_MP_FLOAT128_USING | |
92f5a8d4 | 2434 | using std::floor; |
1e59de90 | 2435 | using std::frexp; |
7c673cae | 2436 | using std::ldexp; |
7c673cae | 2437 | |
92f5a8d4 | 2438 | if (a == 0) |
7c673cae FG |
2439 | return *this = zero(); |
2440 | ||
92f5a8d4 | 2441 | if (a == 1) |
7c673cae FG |
2442 | return *this = one(); |
2443 | ||
1e59de90 | 2444 | if (BOOST_MP_ISINF(a)) |
7c673cae FG |
2445 | { |
2446 | *this = inf(); | |
92f5a8d4 | 2447 | if (a < 0) |
7c673cae FG |
2448 | this->negate(); |
2449 | return *this; | |
2450 | } | |
2451 | ||
1e59de90 | 2452 | if (BOOST_MP_ISNAN(a)) |
7c673cae FG |
2453 | return *this = nan(); |
2454 | ||
92f5a8d4 | 2455 | int e; |
f67539c2 | 2456 | Float f, term; |
7c673cae FG |
2457 | *this = zero(); |
2458 | ||
2459 | f = frexp(a, &e); | |
2460 | // See https://svn.boost.org/trac/boost/ticket/10924 for an example of why this may go wrong: | |
1e59de90 | 2461 | BOOST_MP_ASSERT(!BOOST_MP_ISNAN(f) && !BOOST_MP_ISINF(f)); |
7c673cae | 2462 | |
1e59de90 | 2463 | constexpr const int shift = std::numeric_limits<int>::digits - 1; |
7c673cae | 2464 | |
92f5a8d4 | 2465 | while (f) |
7c673cae FG |
2466 | { |
2467 | // extract int sized bits from f: | |
2468 | f = ldexp(f, shift); | |
1e59de90 | 2469 | BOOST_MP_ASSERT(!BOOST_MP_ISNAN(f) && !BOOST_MP_ISINF(f)); |
7c673cae FG |
2470 | term = floor(f); |
2471 | e -= shift; | |
2472 | *this *= pow2(shift); | |
92f5a8d4 | 2473 | if (term > 0) |
7c673cae FG |
2474 | add_unsigned_long_long(static_cast<unsigned>(term)); |
2475 | else | |
2476 | sub_unsigned_long_long(static_cast<unsigned>(-term)); | |
2477 | f -= term; | |
2478 | } | |
2479 | ||
92f5a8d4 | 2480 | if (e != 0) |
7c673cae FG |
2481 | *this *= pow2(e); |
2482 | ||
2483 | return *this; | |
2484 | } | |
2485 | ||
2486 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1e59de90 | 2487 | void cpp_dec_float<Digits10, ExponentType, Allocator>::from_unsigned_long_long(const unsigned long long u) |
7c673cae | 2488 | { |
1e59de90 | 2489 | std::fill(data.begin(), data.end(), static_cast<std::uint32_t>(0u)); |
7c673cae | 2490 | |
1e59de90 | 2491 | exp = static_cast<exponent_type>(0); |
92f5a8d4 TL |
2492 | neg = false; |
2493 | fpclass = cpp_dec_float_finite; | |
7c673cae FG |
2494 | prec_elem = cpp_dec_float_elem_number; |
2495 | ||
92f5a8d4 | 2496 | if (u == 0) |
b32b8144 FG |
2497 | { |
2498 | return; | |
2499 | } | |
2500 | ||
92f5a8d4 | 2501 | std::size_t i = static_cast<std::size_t>(0u); |
7c673cae | 2502 | |
1e59de90 | 2503 | unsigned long long uu = u; |
7c673cae | 2504 | |
1e59de90 | 2505 | std::uint32_t temp[(std::numeric_limits<unsigned long long>::digits10 / static_cast<int>(cpp_dec_float_elem_digits10)) + 3] = {static_cast<std::uint32_t>(0u)}; |
7c673cae | 2506 | |
1e59de90 | 2507 | while (uu != static_cast<unsigned long long>(0u)) |
7c673cae | 2508 | { |
1e59de90 TL |
2509 | temp[i] = static_cast<std::uint32_t>(uu % static_cast<unsigned long long>(cpp_dec_float_elem_mask)); |
2510 | uu = static_cast<unsigned long long>(uu / static_cast<unsigned long long>(cpp_dec_float_elem_mask)); | |
7c673cae FG |
2511 | ++i; |
2512 | } | |
2513 | ||
92f5a8d4 | 2514 | if (i > static_cast<std::size_t>(1u)) |
7c673cae | 2515 | { |
1e59de90 | 2516 | exp += static_cast<exponent_type>((i - 1u) * static_cast<std::size_t>(cpp_dec_float_elem_digits10)); |
7c673cae FG |
2517 | } |
2518 | ||
2519 | std::reverse(temp, temp + i); | |
2520 | std::copy(temp, temp + (std::min)(i, static_cast<std::size_t>(cpp_dec_float_elem_number)), data.begin()); | |
2521 | } | |
2522 | ||
2523 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1e59de90 TL |
2524 | template <typename InputIteratorTypeLeft, typename InputIteratorTypeRight> |
2525 | int cpp_dec_float<Digits10, ExponentType, Allocator>::compare_ranges(InputIteratorTypeLeft a, | |
2526 | InputIteratorTypeRight b, | |
2527 | const std::uint32_t count) | |
7c673cae | 2528 | { |
1e59de90 TL |
2529 | using local_iterator_left_type = InputIteratorTypeLeft; |
2530 | using local_iterator_right_type = InputIteratorTypeRight; | |
2531 | ||
2532 | local_iterator_left_type begin_a(a); | |
2533 | local_iterator_left_type end_a (a + count); | |
2534 | local_iterator_right_type begin_b(b); | |
2535 | local_iterator_right_type end_b (b + count); | |
2536 | ||
2537 | const auto mismatch_pair = std::mismatch(begin_a, end_a, begin_b); | |
2538 | ||
2539 | int n_return; | |
2540 | ||
2541 | if((mismatch_pair.first != end_a) || (mismatch_pair.second != end_b)) | |
2542 | { | |
2543 | const typename std::iterator_traits<InputIteratorTypeLeft>::value_type left = *mismatch_pair.first; | |
2544 | const typename std::iterator_traits<InputIteratorTypeRight>::value_type right = *mismatch_pair.second; | |
2545 | ||
2546 | n_return = ((left > right) ? 1 : -1); | |
2547 | } | |
2548 | else | |
2549 | { | |
2550 | n_return = 0; | |
2551 | } | |
2552 | ||
2553 | return n_return; | |
2554 | } | |
2555 | ||
2556 | template <unsigned Digits10, class ExponentType, class Allocator> | |
2557 | std::uint32_t cpp_dec_float<Digits10, ExponentType, Allocator>::eval_add_n( std::uint32_t* r, | |
2558 | const std::uint32_t* u, | |
2559 | const std::uint32_t* v, | |
2560 | const std::int32_t count) | |
2561 | { | |
2562 | // Addition algorithm | |
2563 | std::uint_fast8_t carry = static_cast<std::uint_fast8_t>(0U); | |
2564 | ||
2565 | for(std::int32_t j = static_cast<std::int32_t>(count - static_cast<std::int32_t>(1)); j >= static_cast<std::int32_t>(0); --j) | |
2566 | { | |
2567 | const std::uint32_t t = static_cast<std::uint32_t>(static_cast<std::uint32_t>(u[j] + v[j]) + carry); | |
2568 | ||
2569 | carry = ((t >= static_cast<std::uint32_t>(cpp_dec_float_elem_mask)) ? static_cast<std::uint_fast8_t>(1U) | |
2570 | : static_cast<std::uint_fast8_t>(0U)); | |
2571 | ||
2572 | r[j] = static_cast<std::uint32_t>(t - ((carry != 0U) ? static_cast<std::uint32_t>(cpp_dec_float_elem_mask) | |
2573 | : static_cast<std::uint32_t>(0U))); | |
2574 | } | |
2575 | ||
2576 | return static_cast<std::uint32_t>(carry); | |
2577 | } | |
2578 | ||
2579 | template <unsigned Digits10, class ExponentType, class Allocator> | |
2580 | std::uint32_t cpp_dec_float<Digits10, ExponentType, Allocator>::eval_subtract_n( std::uint32_t* r, | |
2581 | const std::uint32_t* u, | |
2582 | const std::uint32_t* v, | |
2583 | const std::int32_t count) | |
2584 | { | |
2585 | // Subtraction algorithm | |
2586 | std::int_fast8_t borrow = static_cast<std::int_fast8_t>(0); | |
2587 | ||
2588 | for(std::uint32_t j = static_cast<std::uint32_t>(count - static_cast<std::int32_t>(1)); static_cast<std::int32_t>(j) >= static_cast<std::int32_t>(0); --j) | |
2589 | { | |
2590 | std::int32_t t = static_cast<std::int32_t>( static_cast<std::int32_t>(u[j]) | |
2591 | - static_cast<std::int32_t>(v[j])) - borrow; | |
2592 | ||
2593 | // Underflow? Borrow? | |
2594 | if(t < 0) | |
2595 | { | |
2596 | // Yes, underflow and borrow | |
2597 | t += static_cast<std::int32_t>(cpp_dec_float_elem_mask); | |
2598 | borrow = static_cast<std::int_fast8_t>(1); | |
2599 | } | |
2600 | else | |
2601 | { | |
2602 | borrow = static_cast<std::int_fast8_t>(0); | |
2603 | } | |
2604 | ||
2605 | r[j] = static_cast<std::uint32_t>(t); | |
2606 | } | |
7c673cae | 2607 | |
1e59de90 TL |
2608 | return static_cast<std::uint32_t>(borrow); |
2609 | } | |
2610 | ||
2611 | template <unsigned Digits10, class ExponentType, class Allocator> | |
2612 | void cpp_dec_float<Digits10, ExponentType, Allocator>::eval_multiply_n_by_n_to_2n( std::uint32_t* r, | |
2613 | const std::uint32_t* a, | |
2614 | const std::uint32_t* b, | |
2615 | const std::uint32_t count) | |
2616 | { | |
2617 | using local_limb_type = std::uint32_t; | |
2618 | ||
2619 | using local_double_limb_type = std::uint64_t; | |
2620 | ||
2621 | using local_reverse_iterator_type = std::reverse_iterator<local_limb_type*>; | |
2622 | ||
2623 | local_reverse_iterator_type ir(r + (count * 2)); | |
7c673cae | 2624 | |
1e59de90 TL |
2625 | local_double_limb_type carry = 0U; |
2626 | ||
2627 | for(std::int32_t j = static_cast<std::int32_t>(count - 1); j >= static_cast<std::int32_t>(1); --j) | |
7c673cae | 2628 | { |
1e59de90 | 2629 | local_double_limb_type sum = carry; |
7c673cae | 2630 | |
1e59de90 | 2631 | for(std::int32_t i = static_cast<std::int32_t>(count - 1); i >= j; --i) |
92f5a8d4 | 2632 | { |
1e59de90 TL |
2633 | sum += local_double_limb_type( |
2634 | local_double_limb_type(a[i]) * b[ static_cast<std::int32_t>(count - 1) | |
2635 | - static_cast<std::int32_t>(i - j)]); | |
92f5a8d4 | 2636 | } |
7c673cae | 2637 | |
1e59de90 TL |
2638 | carry = static_cast<local_double_limb_type>(sum / static_cast<local_limb_type> (cpp_dec_float_elem_mask)); |
2639 | *ir++ = static_cast<local_limb_type> (sum - static_cast<local_double_limb_type>(static_cast<local_double_limb_type>(carry) * static_cast<local_limb_type>(cpp_dec_float_elem_mask))); | |
7c673cae FG |
2640 | } |
2641 | ||
1e59de90 TL |
2642 | for(std::int32_t j = static_cast<std::int32_t>(count - 1); j >= static_cast<std::int32_t>(0); --j) |
2643 | { | |
2644 | local_double_limb_type sum = carry; | |
2645 | ||
2646 | for(std::int32_t i = j; i >= static_cast<std::int32_t>(0); --i) | |
2647 | { | |
2648 | sum += static_cast<local_double_limb_type>(a[j - i] * static_cast<local_double_limb_type>(b[i])); | |
2649 | } | |
2650 | ||
2651 | carry = static_cast<local_double_limb_type>(sum / static_cast<local_limb_type>(cpp_dec_float_elem_mask)); | |
2652 | *ir++ = static_cast<local_limb_type> (sum - static_cast<local_double_limb_type>(static_cast<local_double_limb_type>(carry) * static_cast<local_limb_type>(cpp_dec_float_elem_mask))); | |
2653 | } | |
2654 | ||
2655 | *ir = static_cast<local_limb_type>(carry); | |
7c673cae FG |
2656 | } |
2657 | ||
2658 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1e59de90 | 2659 | std::uint32_t cpp_dec_float<Digits10, ExponentType, Allocator>::mul_loop_n(std::uint32_t* const u, std::uint32_t n, const std::int32_t p) |
7c673cae | 2660 | { |
1e59de90 | 2661 | std::uint64_t carry = static_cast<std::uint64_t>(0u); |
7c673cae FG |
2662 | |
2663 | // Multiplication loop. | |
1e59de90 TL |
2664 | for (std::int32_t j = p - 1; j >= static_cast<std::int32_t>(0); j--) |
2665 | { | |
2666 | const std::uint64_t t = static_cast<std::uint64_t>(carry + static_cast<std::uint64_t>(u[j] * static_cast<std::uint64_t>(n))); | |
2667 | carry = static_cast<std::uint64_t>(t / static_cast<std::uint32_t>(cpp_dec_float_elem_mask)); | |
2668 | u[j] = static_cast<std::uint32_t>(t - static_cast<std::uint64_t>(static_cast<std::uint32_t>(cpp_dec_float_elem_mask) * static_cast<std::uint64_t>(carry))); | |
7c673cae | 2669 | } |
1e59de90 TL |
2670 | |
2671 | return static_cast<std::uint32_t>(carry); | |
2672 | } | |
2673 | ||
2674 | template <unsigned Digits10, class ExponentType, class Allocator> | |
2675 | std::uint32_t cpp_dec_float<Digits10, ExponentType, Allocator>::div_loop_n(std::uint32_t* const u, std::uint32_t n, const std::int32_t p) | |
2676 | { | |
2677 | std::uint64_t prev = static_cast<std::uint64_t>(0u); | |
2678 | ||
2679 | for (std::int32_t j = static_cast<std::int32_t>(0); j < p; j++) | |
2680 | { | |
2681 | const std::uint64_t t = static_cast<std::uint64_t>(u[j] + static_cast<std::uint64_t>(prev * static_cast<std::uint32_t>(cpp_dec_float_elem_mask))); | |
2682 | u[j] = static_cast<std::uint32_t>(t / n); | |
2683 | prev = static_cast<std::uint64_t>(t - static_cast<std::uint64_t>(n * static_cast<std::uint64_t>(u[j]))); | |
2684 | } | |
2685 | ||
2686 | return static_cast<std::uint32_t>(prev); | |
2687 | } | |
2688 | ||
2689 | template <unsigned Digits10, class ExponentType, class Allocator> | |
2690 | void cpp_dec_float<Digits10, ExponentType, Allocator>::eval_multiply_kara_propagate_carry(std::uint32_t* t, const std::uint32_t n, const std::uint32_t carry) | |
2691 | { | |
2692 | std::uint_fast8_t carry_out = ((carry != 0U) ? static_cast<std::uint_fast8_t>(1U) | |
2693 | : static_cast<std::uint_fast8_t>(0U)); | |
2694 | ||
2695 | using local_reverse_iterator_type = std::reverse_iterator<std::uint32_t*>; | |
2696 | ||
2697 | local_reverse_iterator_type ri_t (t + n); | |
2698 | local_reverse_iterator_type rend_t(t); | |
2699 | ||
2700 | while((carry_out != 0U) && (ri_t != rend_t)) | |
7c673cae | 2701 | { |
1e59de90 TL |
2702 | const std::uint64_t tt = *ri_t + carry_out; |
2703 | ||
2704 | carry_out = ((tt >= static_cast<std::uint32_t>(cpp_dec_float_elem_mask)) ? static_cast<std::uint_fast8_t>(1U) | |
2705 | : static_cast<std::uint_fast8_t>(0U)); | |
2706 | ||
2707 | *ri_t++ = static_cast<std::uint32_t>(tt - ((carry_out != 0U) ? static_cast<std::uint32_t>(cpp_dec_float_elem_mask) | |
2708 | : static_cast<std::uint32_t>(0U))); | |
2709 | } | |
2710 | } | |
2711 | ||
2712 | template <unsigned Digits10, class ExponentType, class Allocator> | |
2713 | void cpp_dec_float<Digits10, ExponentType, Allocator>::eval_multiply_kara_propagate_borrow(std::uint32_t* t, const std::uint32_t n, const bool has_borrow) | |
2714 | { | |
2715 | std::int_fast8_t borrow = (has_borrow ? static_cast<std::int_fast8_t>(1) | |
2716 | : static_cast<std::int_fast8_t>(0)); | |
2717 | ||
2718 | using local_reverse_iterator_type = std::reverse_iterator<std::uint32_t*>; | |
2719 | ||
2720 | local_reverse_iterator_type ri_t (t + n); | |
2721 | local_reverse_iterator_type rend_t(t); | |
2722 | ||
2723 | while((borrow != 0U) && (ri_t != rend_t)) | |
2724 | { | |
2725 | std::int32_t tt = static_cast<std::int32_t>(static_cast<std::int32_t>(*ri_t) - borrow); | |
2726 | ||
2727 | // Underflow? Borrow? | |
2728 | if(tt < 0) | |
7c673cae | 2729 | { |
1e59de90 TL |
2730 | // Yes, underflow and borrow |
2731 | tt += static_cast<std::int32_t>(cpp_dec_float_elem_mask); | |
2732 | borrow = static_cast<int_fast8_t>(1); | |
7c673cae FG |
2733 | } |
2734 | else | |
2735 | { | |
1e59de90 TL |
2736 | borrow = static_cast<int_fast8_t>(0); |
2737 | } | |
2738 | ||
2739 | *ri_t++ = static_cast<std::uint32_t>(tt); | |
2740 | } | |
2741 | } | |
2742 | ||
2743 | template <unsigned Digits10, class ExponentType, class Allocator> | |
2744 | void cpp_dec_float<Digits10, ExponentType, Allocator>::eval_multiply_kara_n_by_n_to_2n( std::uint32_t* r, | |
2745 | const std::uint32_t* a, | |
2746 | const std::uint32_t* b, | |
2747 | const std::uint32_t n, | |
2748 | std::uint32_t* t) | |
2749 | { | |
2750 | if(n <= 32U) | |
2751 | { | |
2752 | static_cast<void>(t); | |
2753 | ||
2754 | eval_multiply_n_by_n_to_2n(r, a, b, n); | |
2755 | } | |
2756 | else | |
2757 | { | |
2758 | // Based on "Algorithm 1.3 KaratsubaMultiply", Sect. 1.3.2, page 5 | |
2759 | // of R.P. Brent and P. Zimmermann, "Modern Computer Arithmetic", | |
2760 | // Cambridge University Press (2011). | |
2761 | ||
2762 | // The Karatsuba multipliation computes the product of a*b as: | |
2763 | // [b^N + b^(N/2)] a1*b1 + [b^(N/2)](a1 - a0)(b0 - b1) + [b^(N/2) + 1] a0*b0 | |
2764 | ||
2765 | // Here we visualize a and b in two components 1,0 corresponding | |
2766 | // to the high and low order parts, respectively. | |
2767 | ||
2768 | // Step 1 | |
2769 | // Calculate a1*b1 and store it in the upper-order part of r. | |
2770 | // Calculate a0*b0 and store it in the lower-order part of r. | |
2771 | // copy r to t0. | |
2772 | ||
2773 | // Step 2 | |
2774 | // Add a1*b1 (which is t2) to the middle two-quarters of r (which is r1) | |
2775 | // Add a0*b0 (which is t0) to the middle two-quarters of r (which is r1) | |
2776 | ||
2777 | // Step 3 | |
2778 | // Calculate |a1-a0| in t0 and note the sign (i.e., the borrow flag) | |
2779 | ||
2780 | // Step 4 | |
2781 | // Calculate |b0-b1| in t1 and note the sign (i.e., the borrow flag) | |
2782 | ||
2783 | // Step 5 | |
2784 | // Call kara mul to calculate |a1-a0|*|b0-b1| in (t2), | |
2785 | // while using temporary storage in t4 along the way. | |
2786 | ||
2787 | // Step 6 | |
2788 | // Check the borrow signs. If a1-a0 and b0-b1 have the same signs, | |
2789 | // then add |a1-a0|*|b0-b1| to r1, otherwise subtract it from r1. | |
2790 | ||
2791 | const std::uint_fast32_t nh = n / 2U; | |
2792 | ||
2793 | const std::uint32_t* a0 = a + nh; | |
2794 | const std::uint32_t* a1 = a + 0U; | |
2795 | ||
2796 | const std::uint32_t* b0 = b + nh; | |
2797 | const std::uint32_t* b1 = b + 0U; | |
2798 | ||
2799 | std::uint32_t* r0 = r + 0U; | |
2800 | std::uint32_t* r1 = r + nh; | |
2801 | std::uint32_t* r2 = r + n; | |
2802 | ||
2803 | std::uint32_t* t0 = t + 0U; | |
2804 | std::uint32_t* t1 = t + nh; | |
2805 | std::uint32_t* t2 = t + n; | |
2806 | std::uint32_t* t4 = t + (n + n); | |
2807 | ||
2808 | // Step 1 | |
2809 | eval_multiply_kara_n_by_n_to_2n(r0, a1, b1, nh, t); | |
2810 | eval_multiply_kara_n_by_n_to_2n(r2, a0, b0, nh, t); | |
2811 | std::copy(r0, r0 + (2U * n), t0); | |
2812 | ||
2813 | // Step 2 | |
2814 | std::uint32_t carry; | |
2815 | carry = eval_add_n(r1, r1, t0, n); | |
2816 | eval_multiply_kara_propagate_carry(r0, nh, carry); | |
2817 | carry = eval_add_n(r1, r1, t2, n); | |
2818 | eval_multiply_kara_propagate_carry(r0, nh, carry); | |
2819 | ||
2820 | // Step 3 | |
2821 | const int cmp_result_a1a0 = compare_ranges(a1, a0, nh); | |
2822 | ||
2823 | if(cmp_result_a1a0 == 1) | |
2824 | static_cast<void>(eval_subtract_n(t0, a1, a0, nh)); | |
2825 | else if(cmp_result_a1a0 == -1) | |
2826 | static_cast<void>(eval_subtract_n(t0, a0, a1, nh)); | |
2827 | ||
2828 | // Step 4 | |
2829 | const int cmp_result_b0b1 = compare_ranges(b0, b1, nh); | |
2830 | ||
2831 | if(cmp_result_b0b1 == 1) | |
2832 | static_cast<void>(eval_subtract_n(t1, b0, b1, nh)); | |
2833 | else if(cmp_result_b0b1 == -1) | |
2834 | static_cast<void>(eval_subtract_n(t1, b1, b0, nh)); | |
2835 | ||
2836 | // Step 5 | |
2837 | eval_multiply_kara_n_by_n_to_2n(t2, t0, t1, nh, t4); | |
2838 | ||
2839 | // Step 6 | |
2840 | if((cmp_result_a1a0 * cmp_result_b0b1) == 1) | |
2841 | { | |
2842 | carry = eval_add_n(r1, r1, t2, n); | |
2843 | ||
2844 | eval_multiply_kara_propagate_carry(r0, nh, carry); | |
2845 | } | |
2846 | else if((cmp_result_a1a0 * cmp_result_b0b1) == -1) | |
2847 | { | |
2848 | const bool has_borrow = eval_subtract_n(r1, r1, t2, n); | |
2849 | ||
2850 | eval_multiply_kara_propagate_borrow(r0, nh, has_borrow); | |
7c673cae FG |
2851 | } |
2852 | } | |
2853 | } | |
2854 | ||
1e59de90 TL |
2855 | template <unsigned Digits10, class ExponentType, class Allocator> |
2856 | cpp_dec_float<Digits10, ExponentType, Allocator> cpp_dec_float<Digits10, ExponentType, Allocator>::pow2(const long long p) | |
2857 | { | |
2858 | static const std::array<cpp_dec_float<Digits10, ExponentType, Allocator>, 256u> local_pow2_data = | |
2859 | {{ | |
2860 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 29u, 38735877u, 5571876u, 99218413u, 43055614u, 19454666u, 38919302u, 18803771u, 87926569u, 60431486u, 36817932u, 12890625u }, -40 ), | |
2861 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 58u, 77471754u, 11143753u, 98436826u, 86111228u, 38909332u, 77838604u, 37607543u, 75853139u, 20862972u, 73635864u, 25781250u }, -40 ), | |
2862 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 117u, 54943508u, 22287507u, 96873653u, 72222456u, 77818665u, 55677208u, 75215087u, 51706278u, 41725945u, 47271728u, 51562500u }, -40 ), | |
2863 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 235u, 9887016u, 44575015u, 93747307u, 44444913u, 55637331u, 11354417u, 50430175u, 3412556u, 83451890u, 94543457u, 3125000u }, -40 ), | |
2864 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 470u, 19774032u, 89150031u, 87494614u, 88889827u, 11274662u, 22708835u, 860350u, 6825113u, 66903781u, 89086914u, 6250000u }, -40 ), | |
2865 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 940u, 39548065u, 78300063u, 74989229u, 77779654u, 22549324u, 45417670u, 1720700u, 13650227u, 33807563u, 78173828u, 12500000u }, -40 ), | |
2866 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1880u, 79096131u, 56600127u, 49978459u, 55559308u, 45098648u, 90835340u, 3441400u, 27300454u, 67615127u, 56347656u, 25000000u }, -40 ), | |
2867 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 3761u, 58192263u, 13200254u, 99956919u, 11118616u, 90197297u, 81670680u, 6882800u, 54600909u, 35230255u, 12695312u, 50000000u }, -40 ), | |
2868 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 7523u, 16384526u, 26400509u, 99913838u, 22237233u, 80394595u, 63341360u, 13765601u, 9201818u, 70460510u, 25390625u }, -40 ), | |
2869 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 15046u, 32769052u, 52801019u, 99827676u, 44474467u, 60789191u, 26682720u, 27531202u, 18403637u, 40921020u, 50781250u }, -40 ), | |
2870 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 30092u, 65538105u, 5602039u, 99655352u, 88948935u, 21578382u, 53365440u, 55062404u, 36807274u, 81842041u, 1562500u }, -40 ), | |
2871 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 60185u, 31076210u, 11204079u, 99310705u, 77897870u, 43156765u, 6730881u, 10124808u, 73614549u, 63684082u, 3125000u }, -40 ), | |
2872 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 120370u, 62152420u, 22408159u, 98621411u, 55795740u, 86313530u, 13461762u, 20249617u, 47229099u, 27368164u, 6250000u }, -40 ), | |
2873 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 240741u, 24304840u, 44816319u, 97242823u, 11591481u, 72627060u, 26923524u, 40499234u, 94458198u, 54736328u, 12500000u }, -40 ), | |
2874 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 481482u, 48609680u, 89632639u, 94485646u, 23182963u, 45254120u, 53847048u, 80998469u, 88916397u, 9472656u, 25000000u }, -40 ), | |
2875 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 962964u, 97219361u, 79265279u, 88971292u, 46365926u, 90508241u, 7694097u, 61996939u, 77832794u, 18945312u, 50000000u }, -40 ), | |
2876 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1925929u, 94438723u, 58530559u, 77942584u, 92731853u, 81016482u, 15388195u, 23993879u, 55665588u, 37890625u }, -40 ), | |
2877 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 3851859u, 88877447u, 17061119u, 55885169u, 85463707u, 62032964u, 30776390u, 47987759u, 11331176u, 75781250u }, -40 ), | |
2878 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 7703719u, 77754894u, 34122239u, 11770339u, 70927415u, 24065928u, 61552780u, 95975518u, 22662353u, 51562500u }, -40 ), | |
2879 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 15407439u, 55509788u, 68244478u, 23540679u, 41854830u, 48131857u, 23105561u, 91951036u, 45324707u, 3125000u }, -40 ), | |
2880 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 30814879u, 11019577u, 36488956u, 47081358u, 83709660u, 96263714u, 46211123u, 83902072u, 90649414u, 6250000u }, -40 ), | |
2881 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 61629758u, 22039154u, 72977912u, 94162717u, 67419321u, 92527428u, 92422247u, 67804145u, 81298828u, 12500000u }, -40 ), | |
2882 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1u, 23259516u, 44078309u, 45955825u, 88325435u, 34838643u, 85054857u, 84844495u, 35608291u, 62597656u, 25000000u }, -32 ), | |
2883 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 2u, 46519032u, 88156618u, 91911651u, 76650870u, 69677287u, 70109715u, 69688990u, 71216583u, 25195312u, 50000000u }, -32 ), | |
2884 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 4u, 93038065u, 76313237u, 83823303u, 53301741u, 39354575u, 40219431u, 39377981u, 42433166u, 50390625u }, -32 ), | |
2885 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 9u, 86076131u, 52626475u, 67646607u, 6603482u, 78709150u, 80438862u, 78755962u, 84866333u, 781250u }, -32 ), | |
2886 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 19u, 72152263u, 5252951u, 35293214u, 13206965u, 57418301u, 60877725u, 57511925u, 69732666u, 1562500u }, -32 ), | |
2887 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 39u, 44304526u, 10505902u, 70586428u, 26413931u, 14836603u, 21755451u, 15023851u, 39465332u, 3125000u }, -32 ), | |
2888 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 78u, 88609052u, 21011805u, 41172856u, 52827862u, 29673206u, 43510902u, 30047702u, 78930664u, 6250000u }, -32 ), | |
2889 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 157u, 77218104u, 42023610u, 82345713u, 5655724u, 59346412u, 87021804u, 60095405u, 57861328u, 12500000u }, -32 ), | |
2890 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 315u, 54436208u, 84047221u, 64691426u, 11311449u, 18692825u, 74043609u, 20190811u, 15722656u, 25000000u }, -32 ), | |
2891 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 631u, 8872417u, 68094443u, 29382852u, 22622898u, 37385651u, 48087218u, 40381622u, 31445312u, 50000000u }, -32 ), | |
2892 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1262u, 17744835u, 36188886u, 58765704u, 45245796u, 74771302u, 96174436u, 80763244u, 62890625u }, -32 ), | |
2893 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 2524u, 35489670u, 72377773u, 17531408u, 90491593u, 49542605u, 92348873u, 61526489u, 25781250u }, -32 ), | |
2894 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 5048u, 70979341u, 44755546u, 35062817u, 80983186u, 99085211u, 84697747u, 23052978u, 51562500u }, -32 ), | |
2895 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 10097u, 41958682u, 89511092u, 70125635u, 61966373u, 98170423u, 69395494u, 46105957u, 3125000u }, -32 ), | |
2896 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 20194u, 83917365u, 79022185u, 40251271u, 23932747u, 96340847u, 38790988u, 92211914u, 6250000u }, -32 ), | |
2897 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 40389u, 67834731u, 58044370u, 80502542u, 47865495u, 92681694u, 77581977u, 84423828u, 12500000u }, -32 ), | |
2898 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 80779u, 35669463u, 16088741u, 61005084u, 95730991u, 85363389u, 55163955u, 68847656u, 25000000u }, -32 ), | |
2899 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 161558u, 71338926u, 32177483u, 22010169u, 91461983u, 70726779u, 10327911u, 37695312u, 50000000u }, -32 ), | |
2900 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 323117u, 42677852u, 64354966u, 44020339u, 82923967u, 41453558u, 20655822u, 75390625u }, -32 ), | |
2901 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 646234u, 85355705u, 28709932u, 88040679u, 65847934u, 82907116u, 41311645u, 50781250u }, -32 ), | |
2902 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1292469u, 70711410u, 57419865u, 76081359u, 31695869u, 65814232u, 82623291u, 1562500u }, -32 ), | |
2903 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 2584939u, 41422821u, 14839731u, 52162718u, 63391739u, 31628465u, 65246582u, 3125000u }, -32 ), | |
2904 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 5169878u, 82845642u, 29679463u, 4325437u, 26783478u, 63256931u, 30493164u, 6250000u }, -32 ), | |
2905 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 10339757u, 65691284u, 59358926u, 8650874u, 53566957u, 26513862u, 60986328u, 12500000u }, -32 ), | |
2906 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 20679515u, 31382569u, 18717852u, 17301749u, 7133914u, 53027725u, 21972656u, 25000000u }, -32 ), | |
2907 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 41359030u, 62765138u, 37435704u, 34603498u, 14267829u, 6055450u, 43945312u, 50000000u }, -32 ), | |
2908 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 82718061u, 25530276u, 74871408u, 69206996u, 28535658u, 12110900u, 87890625u }, -32 ), | |
2909 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1u, 65436122u, 51060553u, 49742817u, 38413992u, 57071316u, 24221801u, 75781250u }, -24 ), | |
2910 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 3u, 30872245u, 2121106u, 99485634u, 76827985u, 14142632u, 48443603u, 51562500u }, -24 ), | |
2911 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 6u, 61744490u, 4242213u, 98971269u, 53655970u, 28285264u, 96887207u, 3125000u }, -24 ), | |
2912 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 13u, 23488980u, 8484427u, 97942539u, 7311940u, 56570529u, 93774414u, 6250000u }, -24 ), | |
2913 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 26u, 46977960u, 16968855u, 95885078u, 14623881u, 13141059u, 87548828u, 12500000u }, -24 ), | |
2914 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 52u, 93955920u, 33937711u, 91770156u, 29247762u, 26282119u, 75097656u, 25000000u }, -24 ), | |
2915 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 105u, 87911840u, 67875423u, 83540312u, 58495524u, 52564239u, 50195312u, 50000000u }, -24 ), | |
2916 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 211u, 75823681u, 35750847u, 67080625u, 16991049u, 5128479u, 390625u }, -24 ), | |
2917 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 423u, 51647362u, 71501695u, 34161250u, 33982098u, 10256958u, 781250u }, -24 ), | |
2918 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 847u, 3294725u, 43003390u, 68322500u, 67964196u, 20513916u, 1562500u }, -24 ), | |
2919 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1694u, 6589450u, 86006781u, 36645001u, 35928392u, 41027832u, 3125000u }, -24 ), | |
2920 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 3388u, 13178901u, 72013562u, 73290002u, 71856784u, 82055664u, 6250000u }, -24 ), | |
2921 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 6776u, 26357803u, 44027125u, 46580005u, 43713569u, 64111328u, 12500000u }, -24 ), | |
2922 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 13552u, 52715606u, 88054250u, 93160010u, 87427139u, 28222656u, 25000000u }, -24 ), | |
2923 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 27105u, 5431213u, 76108501u, 86320021u, 74854278u, 56445312u, 50000000u }, -24 ), | |
2924 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 54210u, 10862427u, 52217003u, 72640043u, 49708557u, 12890625u }, -24 ), | |
2925 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 108420u, 21724855u, 4434007u, 45280086u, 99417114u, 25781250u }, -24 ), | |
2926 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 216840u, 43449710u, 8868014u, 90560173u, 98834228u, 51562500u }, -24 ), | |
2927 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 433680u, 86899420u, 17736029u, 81120347u, 97668457u, 3125000u }, -24 ), | |
2928 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 867361u, 73798840u, 35472059u, 62240695u, 95336914u, 6250000u }, -24 ), | |
2929 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1734723u, 47597680u, 70944119u, 24481391u, 90673828u, 12500000u }, -24 ), | |
2930 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 3469446u, 95195361u, 41888238u, 48962783u, 81347656u, 25000000u }, -24 ), | |
2931 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 6938893u, 90390722u, 83776476u, 97925567u, 62695312u, 50000000u }, -24 ), | |
2932 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 13877787u, 80781445u, 67552953u, 95851135u, 25390625u }, -24 ), | |
2933 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 27755575u, 61562891u, 35105907u, 91702270u, 50781250u }, -24 ), | |
2934 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 55511151u, 23125782u, 70211815u, 83404541u, 1562500u }, -24 ), | |
2935 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1u, 11022302u, 46251565u, 40423631u, 66809082u, 3125000u }, -16 ), | |
2936 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 2u, 22044604u, 92503130u, 80847263u, 33618164u, 6250000u }, -16 ), | |
2937 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 4u, 44089209u, 85006261u, 61694526u, 67236328u, 12500000u }, -16 ), | |
2938 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 8u, 88178419u, 70012523u, 23389053u, 34472656u, 25000000u }, -16 ), | |
2939 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 17u, 76356839u, 40025046u, 46778106u, 68945312u, 50000000u }, -16 ), | |
2940 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 35u, 52713678u, 80050092u, 93556213u, 37890625u }, -16 ), | |
2941 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 71u, 5427357u, 60100185u, 87112426u, 75781250u }, -16 ), | |
2942 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 142u, 10854715u, 20200371u, 74224853u, 51562500u }, -16 ), | |
2943 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 284u, 21709430u, 40400743u, 48449707u, 3125000u }, -16 ), | |
2944 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 568u, 43418860u, 80801486u, 96899414u, 6250000u }, -16 ), | |
2945 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1136u, 86837721u, 61602973u, 93798828u, 12500000u }, -16 ), | |
2946 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 2273u, 73675443u, 23205947u, 87597656u, 25000000u }, -16 ), | |
2947 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 4547u, 47350886u, 46411895u, 75195312u, 50000000u }, -16 ), | |
2948 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 9094u, 94701772u, 92823791u, 50390625u }, -16 ), | |
2949 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 18189u, 89403545u, 85647583u, 781250u }, -16 ), | |
2950 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 36379u, 78807091u, 71295166u, 1562500u }, -16 ), | |
2951 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 72759u, 57614183u, 42590332u, 3125000u }, -16 ), | |
2952 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 145519u, 15228366u, 85180664u, 6250000u }, -16 ), | |
2953 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 291038u, 30456733u, 70361328u, 12500000u }, -16 ), | |
2954 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 582076u, 60913467u, 40722656u, 25000000u }, -16 ), | |
2955 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1164153u, 21826934u, 81445312u, 50000000u }, -16 ), | |
2956 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 2328306u, 43653869u, 62890625u }, -16 ), | |
2957 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 4656612u, 87307739u, 25781250u }, -16 ), | |
2958 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 9313225u, 74615478u, 51562500u }, -16 ), | |
2959 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 18626451u, 49230957u, 3125000u }, -16 ), | |
2960 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 37252902u, 98461914u, 6250000u }, -16 ), | |
2961 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 74505805u, 96923828u, 12500000u }, -16 ), | |
2962 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1u, 49011611u, 93847656u, 25000000u }, -8 ), | |
2963 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 2u, 98023223u, 87695312u, 50000000u }, -8 ), | |
2964 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 5u, 96046447u, 75390625u }, -8 ), | |
2965 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 11u, 92092895u, 50781250u }, -8 ), | |
2966 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 23u, 84185791u, 1562500u }, -8 ), | |
2967 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 47u, 68371582u, 3125000u }, -8 ), | |
2968 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 95u, 36743164u, 6250000u }, -8 ), | |
2969 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 190u, 73486328u, 12500000u }, -8 ), | |
2970 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 381u, 46972656u, 25000000u }, -8 ), | |
2971 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 762u, 93945312u, 50000000u }, -8 ), | |
2972 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1525u, 87890625u }, -8 ), | |
2973 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 3051u, 75781250u }, -8 ), | |
2974 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 6103u, 51562500u }, -8 ), | |
2975 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 12207u, 3125000u }, -8 ), | |
2976 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 24414u, 6250000u }, -8 ), | |
2977 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 48828u, 12500000u }, -8 ), | |
2978 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 97656u, 25000000u }, -8 ), | |
2979 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 195312u, 50000000u }, -8 ), | |
2980 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 390625u }, -8 ), | |
2981 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 781250u }, -8 ), | |
2982 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1562500u }, -8 ), | |
2983 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 3125000u }, -8 ), | |
2984 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 6250000u }, -8 ), | |
2985 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 12500000u }, -8 ), | |
2986 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 25000000u }, -8 ), | |
2987 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 50000000u }, -8 ), | |
2988 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1u }, 0 ), | |
2989 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 2u }, 0 ), | |
2990 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 4u }, 0 ), | |
2991 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 8u }, 0 ), | |
2992 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 16u }, 0 ), | |
2993 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 32u }, 0 ), | |
2994 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 64u }, 0 ), | |
2995 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 128u }, 0 ), | |
2996 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 256u }, 0 ), | |
2997 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 512u }, 0 ), | |
2998 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1024u }, 0 ), | |
2999 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 2048u }, 0 ), | |
3000 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 4096u }, 0 ), | |
3001 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 8192u }, 0 ), | |
3002 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 16384u }, 0 ), | |
3003 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 32768u }, 0 ), | |
3004 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 65536u }, 0 ), | |
3005 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 131072u }, 0 ), | |
3006 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 262144u }, 0 ), | |
3007 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 524288u }, 0 ), | |
3008 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1048576u }, 0 ), | |
3009 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 2097152u }, 0 ), | |
3010 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 4194304u }, 0 ), | |
3011 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 8388608u }, 0 ), | |
3012 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 16777216u }, 0 ), | |
3013 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 33554432u }, 0 ), | |
3014 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 67108864u }, 0 ), | |
3015 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1u, 34217728u }, 8 ), | |
3016 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 2u, 68435456u }, 8 ), | |
3017 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 5u, 36870912u }, 8 ), | |
3018 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 10u, 73741824u }, 8 ), | |
3019 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 21u, 47483648u }, 8 ), | |
3020 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 42u, 94967296u }, 8 ), | |
3021 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 85u, 89934592u }, 8 ), | |
3022 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 171u, 79869184u }, 8 ), | |
3023 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 343u, 59738368u }, 8 ), | |
3024 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 687u, 19476736u }, 8 ), | |
3025 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1374u, 38953472u }, 8 ), | |
3026 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 2748u, 77906944u }, 8 ), | |
3027 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 5497u, 55813888u }, 8 ), | |
3028 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 10995u, 11627776u }, 8 ), | |
3029 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 21990u, 23255552u }, 8 ), | |
3030 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 43980u, 46511104u }, 8 ), | |
3031 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 87960u, 93022208u }, 8 ), | |
3032 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 175921u, 86044416u }, 8 ), | |
3033 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 351843u, 72088832u }, 8 ), | |
3034 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 703687u, 44177664u }, 8 ), | |
3035 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1407374u, 88355328u }, 8 ), | |
3036 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 2814749u, 76710656u }, 8 ), | |
3037 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 5629499u, 53421312u }, 8 ), | |
3038 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 11258999u, 6842624u }, 8 ), | |
3039 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 22517998u, 13685248u }, 8 ), | |
3040 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 45035996u, 27370496u }, 8 ), | |
3041 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 90071992u, 54740992u }, 8 ), | |
3042 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1u, 80143985u, 9481984u }, 16 ), | |
3043 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 3u, 60287970u, 18963968u }, 16 ), | |
3044 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 7u, 20575940u, 37927936u }, 16 ), | |
3045 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 14u, 41151880u, 75855872u }, 16 ), | |
3046 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 28u, 82303761u, 51711744u }, 16 ), | |
3047 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 57u, 64607523u, 3423488u }, 16 ), | |
3048 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 115u, 29215046u, 6846976u }, 16 ), | |
3049 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 230u, 58430092u, 13693952u }, 16 ), | |
3050 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 461u, 16860184u, 27387904u }, 16 ), | |
3051 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 922u, 33720368u, 54775808u }, 16 ), | |
3052 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1844u, 67440737u, 9551616u }, 16 ), | |
3053 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 3689u, 34881474u, 19103232u }, 16 ), | |
3054 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 7378u, 69762948u, 38206464u }, 16 ), | |
3055 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 14757u, 39525896u, 76412928u }, 16 ), | |
3056 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 29514u, 79051793u, 52825856u }, 16 ), | |
3057 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 59029u, 58103587u, 5651712u }, 16 ), | |
3058 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 118059u, 16207174u, 11303424u }, 16 ), | |
3059 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 236118u, 32414348u, 22606848u }, 16 ), | |
3060 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 472236u, 64828696u, 45213696u }, 16 ), | |
3061 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 944473u, 29657392u, 90427392u }, 16 ), | |
3062 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1888946u, 59314785u, 80854784u }, 16 ), | |
3063 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 3777893u, 18629571u, 61709568u }, 16 ), | |
3064 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 7555786u, 37259143u, 23419136u }, 16 ), | |
3065 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 15111572u, 74518286u, 46838272u }, 16 ), | |
3066 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 30223145u, 49036572u, 93676544u }, 16 ), | |
3067 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 60446290u, 98073145u, 87353088u }, 16 ), | |
3068 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1u, 20892581u, 96146291u, 74706176u }, 24 ), | |
3069 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 2u, 41785163u, 92292583u, 49412352u }, 24 ), | |
3070 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 4u, 83570327u, 84585166u, 98824704u }, 24 ), | |
3071 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 9u, 67140655u, 69170333u, 97649408u }, 24 ), | |
3072 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 19u, 34281311u, 38340667u, 95298816u }, 24 ), | |
3073 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 38u, 68562622u, 76681335u, 90597632u }, 24 ), | |
3074 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 77u, 37125245u, 53362671u, 81195264u }, 24 ), | |
3075 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 154u, 74250491u, 6725343u, 62390528u }, 24 ), | |
3076 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 309u, 48500982u, 13450687u, 24781056u }, 24 ), | |
3077 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 618u, 97001964u, 26901374u, 49562112u }, 24 ), | |
3078 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1237u, 94003928u, 53802748u, 99124224u }, 24 ), | |
3079 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 2475u, 88007857u, 7605497u, 98248448u }, 24 ), | |
3080 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 4951u, 76015714u, 15210995u, 96496896u }, 24 ), | |
3081 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 9903u, 52031428u, 30421991u, 92993792u }, 24 ), | |
3082 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 19807u, 4062856u, 60843983u, 85987584u }, 24 ), | |
3083 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 39614u, 8125713u, 21687967u, 71975168u }, 24 ), | |
3084 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 79228u, 16251426u, 43375935u, 43950336u }, 24 ), | |
3085 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 158456u, 32502852u, 86751870u, 87900672u }, 24 ), | |
3086 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 316912u, 65005705u, 73503741u, 75801344u }, 24 ), | |
3087 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 633825u, 30011411u, 47007483u, 51602688u }, 24 ), | |
3088 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1267650u, 60022822u, 94014967u, 3205376u }, 24 ), | |
3089 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 2535301u, 20045645u, 88029934u, 6410752u }, 24 ), | |
3090 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 5070602u, 40091291u, 76059868u, 12821504u }, 24 ), | |
3091 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 10141204u, 80182583u, 52119736u, 25643008u }, 24 ), | |
3092 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 20282409u, 60365167u, 4239472u, 51286016u }, 24 ), | |
3093 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 40564819u, 20730334u, 8478945u, 2572032u }, 24 ), | |
3094 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 81129638u, 41460668u, 16957890u, 5144064u }, 24 ), | |
3095 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1u, 62259276u, 82921336u, 33915780u, 10288128u }, 32 ), | |
3096 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 3u, 24518553u, 65842672u, 67831560u, 20576256u }, 32 ), | |
3097 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 6u, 49037107u, 31685345u, 35663120u, 41152512u }, 32 ), | |
3098 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 12u, 98074214u, 63370690u, 71326240u, 82305024u }, 32 ), | |
3099 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 25u, 96148429u, 26741381u, 42652481u, 64610048u }, 32 ), | |
3100 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 51u, 92296858u, 53482762u, 85304963u, 29220096u }, 32 ), | |
3101 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 103u, 84593717u, 6965525u, 70609926u, 58440192u }, 32 ), | |
3102 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 207u, 69187434u, 13931051u, 41219853u, 16880384u }, 32 ), | |
3103 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 415u, 38374868u, 27862102u, 82439706u, 33760768u }, 32 ), | |
3104 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 830u, 76749736u, 55724205u, 64879412u, 67521536u }, 32 ), | |
3105 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1661u, 53499473u, 11448411u, 29758825u, 35043072u }, 32 ), | |
3106 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 3323u, 6998946u, 22896822u, 59517650u, 70086144u }, 32 ), | |
3107 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 6646u, 13997892u, 45793645u, 19035301u, 40172288u }, 32 ), | |
3108 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 13292u, 27995784u, 91587290u, 38070602u, 80344576u }, 32 ), | |
3109 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 26584u, 55991569u, 83174580u, 76141205u, 60689152u }, 32 ), | |
3110 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 53169u, 11983139u, 66349161u, 52282411u, 21378304u }, 32 ), | |
3111 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 106338u, 23966279u, 32698323u, 4564822u, 42756608u }, 32 ), | |
3112 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 212676u, 47932558u, 65396646u, 9129644u, 85513216u }, 32 ), | |
3113 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 425352u, 95865117u, 30793292u, 18259289u, 71026432u }, 32 ), | |
3114 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 850705u, 91730234u, 61586584u, 36518579u, 42052864u }, 32 ), | |
3115 | cpp_dec_float<Digits10, ExponentType, Allocator>::from_lst( { 1701411u, 83460469u, 23173168u, 73037158u, 84105728u }, 32 ), | |
3116 | }}; | |
3117 | ||
3118 | cpp_dec_float<Digits10, ExponentType, Allocator> t; | |
3119 | ||
3120 | if(p < -128L) | |
3121 | default_ops::detail::pow_imp(t, cpp_dec_float<Digits10, ExponentType, Allocator>::half(), static_cast<unsigned long long>(-p), std::integral_constant<bool, false>()); | |
3122 | else if ((p >= -128L) && (p <= 127L)) | |
3123 | t = local_pow2_data[std::size_t(p + 128)]; | |
3124 | else | |
3125 | default_ops::detail::pow_imp(t, cpp_dec_float<Digits10, ExponentType, Allocator>::two(), static_cast<unsigned long long>(p), std::integral_constant<bool, false>()); | |
3126 | ||
3127 | return t; | |
3128 | } | |
3129 | ||
7c673cae FG |
3130 | template <unsigned Digits10, class ExponentType, class Allocator> |
3131 | inline void eval_add(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& o) | |
3132 | { | |
3133 | result += o; | |
3134 | } | |
3135 | template <unsigned Digits10, class ExponentType, class Allocator> | |
3136 | inline void eval_subtract(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& o) | |
3137 | { | |
3138 | result -= o; | |
3139 | } | |
3140 | template <unsigned Digits10, class ExponentType, class Allocator> | |
3141 | inline void eval_multiply(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& o) | |
3142 | { | |
3143 | result *= o; | |
3144 | } | |
3145 | template <unsigned Digits10, class ExponentType, class Allocator> | |
3146 | inline void eval_divide(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& o) | |
3147 | { | |
3148 | result /= o; | |
3149 | } | |
3150 | ||
3151 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1e59de90 | 3152 | inline void eval_add(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const unsigned long long& o) |
7c673cae FG |
3153 | { |
3154 | result.add_unsigned_long_long(o); | |
3155 | } | |
3156 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1e59de90 | 3157 | inline void eval_subtract(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const unsigned long long& o) |
7c673cae FG |
3158 | { |
3159 | result.sub_unsigned_long_long(o); | |
3160 | } | |
3161 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1e59de90 | 3162 | inline void eval_multiply(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const unsigned long long& o) |
7c673cae FG |
3163 | { |
3164 | result.mul_unsigned_long_long(o); | |
3165 | } | |
3166 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1e59de90 | 3167 | inline void eval_divide(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const unsigned long long& o) |
7c673cae FG |
3168 | { |
3169 | result.div_unsigned_long_long(o); | |
3170 | } | |
3171 | ||
3172 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1e59de90 | 3173 | inline void eval_add(cpp_dec_float<Digits10, ExponentType, Allocator>& result, long long o) |
7c673cae | 3174 | { |
92f5a8d4 | 3175 | if (o < 0) |
7c673cae FG |
3176 | result.sub_unsigned_long_long(boost::multiprecision::detail::unsigned_abs(o)); |
3177 | else | |
3178 | result.add_unsigned_long_long(o); | |
3179 | } | |
3180 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1e59de90 | 3181 | inline void eval_subtract(cpp_dec_float<Digits10, ExponentType, Allocator>& result, long long o) |
7c673cae | 3182 | { |
92f5a8d4 | 3183 | if (o < 0) |
7c673cae FG |
3184 | result.add_unsigned_long_long(boost::multiprecision::detail::unsigned_abs(o)); |
3185 | else | |
3186 | result.sub_unsigned_long_long(o); | |
3187 | } | |
3188 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1e59de90 | 3189 | inline void eval_multiply(cpp_dec_float<Digits10, ExponentType, Allocator>& result, long long o) |
7c673cae | 3190 | { |
92f5a8d4 | 3191 | if (o < 0) |
7c673cae FG |
3192 | { |
3193 | result.mul_unsigned_long_long(boost::multiprecision::detail::unsigned_abs(o)); | |
3194 | result.negate(); | |
3195 | } | |
3196 | else | |
3197 | result.mul_unsigned_long_long(o); | |
3198 | } | |
3199 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1e59de90 | 3200 | inline void eval_divide(cpp_dec_float<Digits10, ExponentType, Allocator>& result, long long o) |
7c673cae | 3201 | { |
92f5a8d4 | 3202 | if (o < 0) |
7c673cae FG |
3203 | { |
3204 | result.div_unsigned_long_long(boost::multiprecision::detail::unsigned_abs(o)); | |
3205 | result.negate(); | |
3206 | } | |
3207 | else | |
1e59de90 | 3208 | result.div_unsigned_long_long(static_cast<unsigned long long>(o)); |
7c673cae FG |
3209 | } |
3210 | ||
3211 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1e59de90 | 3212 | inline void eval_convert_to(unsigned long long* result, const cpp_dec_float<Digits10, ExponentType, Allocator>& val) |
7c673cae FG |
3213 | { |
3214 | *result = val.extract_unsigned_long_long(); | |
3215 | } | |
3216 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1e59de90 | 3217 | inline void eval_convert_to(long long* result, const cpp_dec_float<Digits10, ExponentType, Allocator>& val) |
7c673cae FG |
3218 | { |
3219 | *result = val.extract_signed_long_long(); | |
3220 | } | |
1e59de90 TL |
3221 | #ifdef BOOST_HAS_INT128 |
3222 | template <unsigned Digits10, class ExponentType, class Allocator> | |
3223 | inline void eval_convert_to(uint128_type* result, const cpp_dec_float<Digits10, ExponentType, Allocator>& val) | |
3224 | { | |
3225 | *result = val.extract_unsigned_int128(); | |
3226 | } | |
3227 | template <unsigned Digits10, class ExponentType, class Allocator> | |
3228 | inline void eval_convert_to(int128_type* result, const cpp_dec_float<Digits10, ExponentType, Allocator>& val) | |
3229 | { | |
3230 | *result = val.extract_signed_int128(); | |
3231 | } | |
3232 | #endif | |
7c673cae | 3233 | template <unsigned Digits10, class ExponentType, class Allocator> |
f67539c2 | 3234 | inline void eval_convert_to(long double* result, const cpp_dec_float<Digits10, ExponentType, Allocator>& val) |
7c673cae FG |
3235 | { |
3236 | *result = val.extract_long_double(); | |
3237 | } | |
f67539c2 TL |
3238 | template <unsigned Digits10, class ExponentType, class Allocator> |
3239 | inline void eval_convert_to(double* result, const cpp_dec_float<Digits10, ExponentType, Allocator>& val) | |
3240 | { | |
3241 | *result = val.extract_double(); | |
3242 | } | |
1e59de90 TL |
3243 | #if defined(BOOST_HAS_FLOAT128) |
3244 | template <unsigned Digits10, class ExponentType, class Allocator> | |
3245 | inline void eval_convert_to(float128_type* result, const cpp_dec_float<Digits10, ExponentType, Allocator>& val) | |
3246 | { | |
3247 | *result = float128_procs::strtoflt128(val.str(0, std::ios_base::scientific).c_str(), nullptr); | |
3248 | } | |
3249 | #endif | |
7c673cae FG |
3250 | |
3251 | // | |
3252 | // Non member function support: | |
3253 | // | |
3254 | template <unsigned Digits10, class ExponentType, class Allocator> | |
3255 | inline int eval_fpclassify(const cpp_dec_float<Digits10, ExponentType, Allocator>& x) | |
3256 | { | |
92f5a8d4 | 3257 | if ((x.isinf)()) |
7c673cae | 3258 | return FP_INFINITE; |
92f5a8d4 | 3259 | if ((x.isnan)()) |
7c673cae | 3260 | return FP_NAN; |
92f5a8d4 | 3261 | if (x.iszero()) |
7c673cae FG |
3262 | return FP_ZERO; |
3263 | return FP_NORMAL; | |
3264 | } | |
3265 | ||
3266 | template <unsigned Digits10, class ExponentType, class Allocator> | |
3267 | inline void eval_abs(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& x) | |
3268 | { | |
3269 | result = x; | |
92f5a8d4 | 3270 | if (x.isneg()) |
7c673cae FG |
3271 | result.negate(); |
3272 | } | |
3273 | ||
3274 | template <unsigned Digits10, class ExponentType, class Allocator> | |
3275 | inline void eval_fabs(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& x) | |
3276 | { | |
3277 | result = x; | |
92f5a8d4 | 3278 | if (x.isneg()) |
7c673cae FG |
3279 | result.negate(); |
3280 | } | |
3281 | ||
3282 | template <unsigned Digits10, class ExponentType, class Allocator> | |
3283 | inline void eval_sqrt(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& x) | |
3284 | { | |
3285 | result = x; | |
3286 | result.calculate_sqrt(); | |
3287 | } | |
3288 | ||
3289 | template <unsigned Digits10, class ExponentType, class Allocator> | |
3290 | inline void eval_floor(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& x) | |
3291 | { | |
3292 | result = x; | |
92f5a8d4 | 3293 | if (!(x.isfinite)() || x.isint()) |
7c673cae | 3294 | { |
92f5a8d4 | 3295 | if ((x.isnan)()) |
b32b8144 | 3296 | errno = EDOM; |
7c673cae FG |
3297 | return; |
3298 | } | |
3299 | ||
92f5a8d4 | 3300 | if (x.isneg()) |
7c673cae FG |
3301 | result -= cpp_dec_float<Digits10, ExponentType, Allocator>::one(); |
3302 | result = result.extract_integer_part(); | |
3303 | } | |
3304 | ||
3305 | template <unsigned Digits10, class ExponentType, class Allocator> | |
3306 | inline void eval_ceil(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& x) | |
3307 | { | |
3308 | result = x; | |
92f5a8d4 | 3309 | if (!(x.isfinite)() || x.isint()) |
7c673cae | 3310 | { |
92f5a8d4 | 3311 | if ((x.isnan)()) |
b32b8144 | 3312 | errno = EDOM; |
7c673cae FG |
3313 | return; |
3314 | } | |
3315 | ||
92f5a8d4 | 3316 | if (!x.isneg()) |
7c673cae FG |
3317 | result += cpp_dec_float<Digits10, ExponentType, Allocator>::one(); |
3318 | result = result.extract_integer_part(); | |
3319 | } | |
3320 | ||
3321 | template <unsigned Digits10, class ExponentType, class Allocator> | |
3322 | inline void eval_trunc(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& x) | |
3323 | { | |
92f5a8d4 | 3324 | if (x.isint() || !(x.isfinite)()) |
7c673cae FG |
3325 | { |
3326 | result = x; | |
92f5a8d4 | 3327 | if ((x.isnan)()) |
b32b8144 | 3328 | errno = EDOM; |
7c673cae FG |
3329 | return; |
3330 | } | |
3331 | result = x.extract_integer_part(); | |
3332 | } | |
3333 | ||
3334 | template <unsigned Digits10, class ExponentType, class Allocator> | |
3335 | inline ExponentType eval_ilogb(const cpp_dec_float<Digits10, ExponentType, Allocator>& val) | |
3336 | { | |
92f5a8d4 | 3337 | if (val.iszero()) |
1e59de90 | 3338 | return (std::numeric_limits<typename cpp_dec_float<Digits10, ExponentType, Allocator>::exponent_type>::min)(); |
92f5a8d4 | 3339 | if ((val.isinf)()) |
b32b8144 | 3340 | return INT_MAX; |
92f5a8d4 | 3341 | if ((val.isnan)()) |
b32b8144 FG |
3342 | #ifdef FP_ILOGBNAN |
3343 | return FP_ILOGBNAN; | |
3344 | #else | |
3345 | return INT_MAX; | |
3346 | #endif | |
7c673cae FG |
3347 | // Set result, to the exponent of val: |
3348 | return val.order(); | |
3349 | } | |
3350 | template <unsigned Digits10, class ExponentType, class Allocator, class ArgType> | |
3351 | inline void eval_scalbn(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& val, ArgType e_) | |
3352 | { | |
3353 | using default_ops::eval_multiply; | |
1e59de90 | 3354 | const typename cpp_dec_float<Digits10, ExponentType, Allocator>::exponent_type e = static_cast<typename cpp_dec_float<Digits10, ExponentType, Allocator>::exponent_type>(e_); |
7c673cae FG |
3355 | cpp_dec_float<Digits10, ExponentType, Allocator> t(1.0, e); |
3356 | eval_multiply(result, val, t); | |
3357 | } | |
3358 | ||
3359 | template <unsigned Digits10, class ExponentType, class Allocator, class ArgType> | |
3360 | inline void eval_ldexp(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& x, ArgType e) | |
3361 | { | |
1e59de90 | 3362 | const long long the_exp = static_cast<long long>(e); |
7c673cae | 3363 | |
1e59de90 TL |
3364 | if ((the_exp > (std::numeric_limits<typename cpp_dec_float<Digits10, ExponentType, Allocator>::exponent_type>::max)()) || (the_exp < (std::numeric_limits<typename cpp_dec_float<Digits10, ExponentType, Allocator>::exponent_type>::min)())) |
3365 | BOOST_MP_THROW_EXCEPTION(std::runtime_error(std::string("Exponent value is out of range."))); | |
7c673cae FG |
3366 | |
3367 | result = x; | |
3368 | ||
1e59de90 TL |
3369 | if ((the_exp > static_cast<long long>(-std::numeric_limits<long long>::digits)) && (the_exp < static_cast<long long>(0))) |
3370 | result.div_unsigned_long_long(1ULL << static_cast<long long>(-the_exp)); | |
3371 | else if ((the_exp < static_cast<long long>(std::numeric_limits<long long>::digits)) && (the_exp > static_cast<long long>(0))) | |
7c673cae | 3372 | result.mul_unsigned_long_long(1ULL << the_exp); |
1e59de90 | 3373 | else if (the_exp != static_cast<long long>(0)) |
20effc67 TL |
3374 | { |
3375 | if ((the_exp < cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_min_exp / 2) && (x.order() > 0)) | |
3376 | { | |
1e59de90 | 3377 | long long half_exp = e / 2; |
20effc67 TL |
3378 | cpp_dec_float<Digits10, ExponentType, Allocator> t = cpp_dec_float<Digits10, ExponentType, Allocator>::pow2(half_exp); |
3379 | result *= t; | |
3380 | if (2 * half_exp != e) | |
3381 | t *= 2; | |
3382 | result *= t; | |
3383 | } | |
3384 | else | |
3385 | result *= cpp_dec_float<Digits10, ExponentType, Allocator>::pow2(e); | |
3386 | } | |
7c673cae FG |
3387 | } |
3388 | ||
3389 | template <unsigned Digits10, class ExponentType, class Allocator> | |
3390 | inline void eval_frexp(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& x, ExponentType* e) | |
3391 | { | |
3392 | result = x; | |
7c673cae | 3393 | |
92f5a8d4 | 3394 | if (result.iszero() || (result.isinf)() || (result.isnan)()) |
7c673cae FG |
3395 | { |
3396 | *e = 0; | |
3397 | return; | |
3398 | } | |
3399 | ||
92f5a8d4 | 3400 | if (result.isneg()) |
b32b8144 FG |
3401 | result.negate(); |
3402 | ||
1e59de90 | 3403 | typename cpp_dec_float<Digits10, ExponentType, Allocator>::exponent_type t = result.order(); |
7c673cae | 3404 | BOOST_MP_USING_ABS |
1e59de90 | 3405 | if (abs(t) < ((std::numeric_limits<typename cpp_dec_float<Digits10, ExponentType, Allocator>::exponent_type>::max)() / 1000)) |
7c673cae FG |
3406 | { |
3407 | t *= 1000; | |
3408 | t /= 301; | |
3409 | } | |
3410 | else | |
3411 | { | |
3412 | t /= 301; | |
3413 | t *= 1000; | |
3414 | } | |
3415 | ||
3416 | result *= cpp_dec_float<Digits10, ExponentType, Allocator>::pow2(-t); | |
3417 | ||
92f5a8d4 | 3418 | if (result.iszero() || (result.isinf)() || (result.isnan)()) |
7c673cae FG |
3419 | { |
3420 | // pow2 overflowed, slip the calculation up: | |
3421 | result = x; | |
92f5a8d4 | 3422 | if (result.isneg()) |
7c673cae FG |
3423 | result.negate(); |
3424 | t /= 2; | |
3425 | result *= cpp_dec_float<Digits10, ExponentType, Allocator>::pow2(-t); | |
3426 | } | |
3427 | BOOST_MP_USING_ABS | |
92f5a8d4 | 3428 | if (abs(result.order()) > 5) |
7c673cae FG |
3429 | { |
3430 | // If our first estimate doesn't get close enough then try recursion until we do: | |
1e59de90 TL |
3431 | typename cpp_dec_float<Digits10, ExponentType, Allocator>::exponent_type e2; |
3432 | cpp_dec_float<Digits10, ExponentType, Allocator> r2; | |
7c673cae FG |
3433 | eval_frexp(r2, result, &e2); |
3434 | // overflow protection: | |
1e59de90 TL |
3435 | if ((t > 0) && (e2 > 0) && (t > (std::numeric_limits<typename cpp_dec_float<Digits10, ExponentType, Allocator>::exponent_type>::max)() - e2)) |
3436 | BOOST_MP_THROW_EXCEPTION(std::runtime_error("Exponent is too large to be represented as a power of 2.")); | |
3437 | if ((t < 0) && (e2 < 0) && (t < (std::numeric_limits<typename cpp_dec_float<Digits10, ExponentType, Allocator>::exponent_type>::min)() - e2)) | |
3438 | BOOST_MP_THROW_EXCEPTION(std::runtime_error("Exponent is too large to be represented as a power of 2.")); | |
7c673cae FG |
3439 | t += e2; |
3440 | result = r2; | |
3441 | } | |
3442 | ||
92f5a8d4 | 3443 | while (result.compare(cpp_dec_float<Digits10, ExponentType, Allocator>::one()) >= 0) |
7c673cae FG |
3444 | { |
3445 | result /= cpp_dec_float<Digits10, ExponentType, Allocator>::two(); | |
3446 | ++t; | |
3447 | } | |
92f5a8d4 | 3448 | while (result.compare(cpp_dec_float<Digits10, ExponentType, Allocator>::half()) < 0) |
7c673cae FG |
3449 | { |
3450 | result *= cpp_dec_float<Digits10, ExponentType, Allocator>::two(); | |
3451 | --t; | |
3452 | } | |
3453 | *e = t; | |
92f5a8d4 | 3454 | if (x.isneg()) |
7c673cae FG |
3455 | result.negate(); |
3456 | } | |
3457 | ||
3458 | template <unsigned Digits10, class ExponentType, class Allocator> | |
1e59de90 | 3459 | inline typename std::enable_if< !std::is_same<ExponentType, int>::value>::type eval_frexp(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& x, int* e) |
7c673cae | 3460 | { |
1e59de90 | 3461 | typename cpp_dec_float<Digits10, ExponentType, Allocator>::exponent_type t; |
7c673cae | 3462 | eval_frexp(result, x, &t); |
92f5a8d4 | 3463 | if ((t > (std::numeric_limits<int>::max)()) || (t < (std::numeric_limits<int>::min)())) |
1e59de90 | 3464 | BOOST_MP_THROW_EXCEPTION(std::runtime_error("Exponent is outside the range of an int")); |
7c673cae FG |
3465 | *e = static_cast<int>(t); |
3466 | } | |
3467 | ||
3468 | template <unsigned Digits10, class ExponentType, class Allocator> | |
3469 | inline bool eval_is_zero(const cpp_dec_float<Digits10, ExponentType, Allocator>& val) | |
3470 | { | |
3471 | return val.iszero(); | |
3472 | } | |
3473 | template <unsigned Digits10, class ExponentType, class Allocator> | |
3474 | inline int eval_get_sign(const cpp_dec_float<Digits10, ExponentType, Allocator>& val) | |
3475 | { | |
3476 | return val.iszero() ? 0 : val.isneg() ? -1 : 1; | |
3477 | } | |
3478 | ||
3479 | template <unsigned Digits10, class ExponentType, class Allocator> | |
3480 | inline std::size_t hash_value(const cpp_dec_float<Digits10, ExponentType, Allocator>& val) | |
3481 | { | |
3482 | return val.hash(); | |
3483 | } | |
3484 | ||
3485 | } // namespace backends | |
3486 | ||
3487 | using boost::multiprecision::backends::cpp_dec_float; | |
3488 | ||
1e59de90 TL |
3489 | using cpp_dec_float_50 = number<cpp_dec_float<50> > ; |
3490 | using cpp_dec_float_100 = number<cpp_dec_float<100> >; | |
7c673cae | 3491 | |
92f5a8d4 | 3492 | namespace detail { |
7c673cae | 3493 | |
20effc67 TL |
3494 | template <unsigned Digits10, class ExponentType, class Allocator> |
3495 | struct transcendental_reduction_type<boost::multiprecision::backends::cpp_dec_float<Digits10, ExponentType, Allocator> > | |
3496 | { | |
3497 | // | |
3498 | // The type used for trigonometric reduction needs 3 times the precision of the base type. | |
3499 | // This is double the precision of the original type, plus the largest exponent supported. | |
3500 | // As a practical measure the largest argument supported is 1/eps, as supporting larger | |
3501 | // arguments requires the division of argument by PI/2 to also be done at higher precision, | |
3502 | // otherwise the result (an integer) can not be represented exactly. | |
3503 | // | |
3504 | // See ARGUMENT REDUCTION FOR HUGE ARGUMENTS. K C Ng. | |
3505 | // | |
1e59de90 | 3506 | using type = boost::multiprecision::backends::cpp_dec_float<Digits10 * 3, ExponentType, Allocator>; |
20effc67 TL |
3507 | }; |
3508 | ||
92f5a8d4 | 3509 | } // namespace detail |
7c673cae | 3510 | |
7c673cae | 3511 | |
92f5a8d4 | 3512 | }} // namespace boost::multiprecision |
7c673cae | 3513 | |
92f5a8d4 TL |
3514 | namespace std { |
3515 | template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates> | |
3516 | class numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> > | |
7c673cae | 3517 | { |
92f5a8d4 | 3518 | public: |
1e59de90 TL |
3519 | static constexpr bool is_specialized = true; |
3520 | static constexpr bool is_signed = true; | |
3521 | static constexpr bool is_integer = false; | |
3522 | static constexpr bool is_exact = false; | |
3523 | static constexpr bool is_bounded = true; | |
3524 | static constexpr bool is_modulo = false; | |
3525 | static constexpr bool is_iec559 = false; | |
3526 | static constexpr int digits = boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_digits10; | |
3527 | static constexpr int digits10 = boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_digits10; | |
3528 | static constexpr int max_digits10 = boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_max_digits10; | |
3529 | static constexpr typename boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::exponent_type min_exponent = boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_min_exp; // Type differs from int. | |
3530 | static constexpr typename boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::exponent_type min_exponent10 = boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_min_exp10; // Type differs from int. | |
3531 | static constexpr typename boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::exponent_type max_exponent = boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_max_exp; // Type differs from int. | |
3532 | static constexpr typename boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::exponent_type max_exponent10 = boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_max_exp10; // Type differs from int. | |
3533 | static constexpr int radix = boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_radix; | |
3534 | static constexpr std::float_round_style round_style = std::round_indeterminate; | |
3535 | static constexpr bool has_infinity = true; | |
3536 | static constexpr bool has_quiet_NaN = true; | |
3537 | static constexpr bool has_signaling_NaN = false; | |
3538 | static constexpr std::float_denorm_style has_denorm = std::denorm_absent; | |
3539 | static constexpr bool has_denorm_loss = false; | |
3540 | static constexpr bool traps = false; | |
3541 | static constexpr bool tinyness_before = false; | |
3542 | ||
3543 | static constexpr boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates>(min)() { return (boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::min)(); } | |
3544 | static constexpr boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates>(max)() { return (boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::max)(); } | |
3545 | static constexpr boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> lowest() { return boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::zero(); } | |
3546 | static constexpr boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> epsilon() { return boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::eps(); } | |
3547 | static constexpr boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> round_error() { return 0.5L; } | |
3548 | static constexpr boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> infinity() { return boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::inf(); } | |
3549 | static constexpr boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> quiet_NaN() { return boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::nan(); } | |
3550 | static constexpr boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> signaling_NaN() { return boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::zero(); } | |
3551 | static constexpr boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> denorm_min() { return boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::zero(); } | |
92f5a8d4 | 3552 | }; |
7c673cae | 3553 | |
7c673cae | 3554 | template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 3555 | constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::digits; |
7c673cae | 3556 | template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 3557 | constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::digits10; |
7c673cae | 3558 | template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 3559 | constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::max_digits10; |
7c673cae | 3560 | template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 3561 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::is_signed; |
7c673cae | 3562 | template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 3563 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::is_integer; |
7c673cae | 3564 | template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 3565 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::is_exact; |
7c673cae | 3566 | template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 3567 | constexpr int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::radix; |
7c673cae | 3568 | template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 3569 | constexpr typename boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::exponent_type numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::min_exponent; |
7c673cae | 3570 | template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 3571 | constexpr typename boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::exponent_type numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::min_exponent10; |
7c673cae | 3572 | template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 3573 | constexpr typename boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::exponent_type numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::max_exponent; |
7c673cae | 3574 | template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 3575 | constexpr typename boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::exponent_type numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::max_exponent10; |
7c673cae | 3576 | template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 3577 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::has_infinity; |
7c673cae | 3578 | template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 3579 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::has_quiet_NaN; |
7c673cae | 3580 | template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 3581 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::has_signaling_NaN; |
7c673cae | 3582 | template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 3583 | constexpr float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::has_denorm; |
7c673cae | 3584 | template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 3585 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::has_denorm_loss; |
7c673cae | 3586 | template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 3587 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::is_iec559; |
7c673cae | 3588 | template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 3589 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::is_bounded; |
7c673cae | 3590 | template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 3591 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::is_modulo; |
7c673cae | 3592 | template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 3593 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::traps; |
7c673cae | 3594 | template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 3595 | constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::tinyness_before; |
7c673cae | 3596 | template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates> |
1e59de90 | 3597 | constexpr float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::round_style; |
7c673cae | 3598 | |
92f5a8d4 | 3599 | } // namespace std |
7c673cae | 3600 | |
1e59de90 | 3601 | #ifdef BOOST_MP_MATH_AVAILABLE |
92f5a8d4 TL |
3602 | namespace boost { |
3603 | namespace math { | |
7c673cae | 3604 | |
92f5a8d4 | 3605 | namespace policies { |
7c673cae FG |
3606 | |
3607 | template <unsigned Digits10, class ExponentType, class Allocator, class Policy, boost::multiprecision::expression_template_option ExpressionTemplates> | |
92f5a8d4 | 3608 | struct precision<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates>, Policy> |
7c673cae FG |
3609 | { |
3610 | // Define a local copy of cpp_dec_float_digits10 because it might differ | |
3611 | // from the template parameter Digits10 for small or large digit counts. | |
1e59de90 | 3612 | static constexpr std::int32_t cpp_dec_float_digits10 = boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_digits10; |
7c673cae | 3613 | |
1e59de90 TL |
3614 | using precision_type = typename Policy::precision_type ; |
3615 | using digits_2 = digits2<((cpp_dec_float_digits10 + 1LL) * 1000LL) / 301LL>; | |
3616 | using type = typename std::conditional< | |
92f5a8d4 TL |
3617 | ((digits_2::value <= precision_type::value) || (Policy::precision_type::value <= 0)), |
3618 | // Default case, full precision for RealType: | |
3619 | digits_2, | |
3620 | // User customized precision: | |
1e59de90 | 3621 | precision_type>::type; |
7c673cae FG |
3622 | }; |
3623 | ||
92f5a8d4 | 3624 | } |
7c673cae | 3625 | |
92f5a8d4 | 3626 | }} // namespace boost::math::policies |
1e59de90 | 3627 | #endif |
7c673cae FG |
3628 | |
3629 | #ifdef BOOST_MSVC | |
3630 | #pragma warning(pop) | |
3631 | #endif | |
3632 | ||
3633 | #endif |