Chris@16
|
1 ///////////////////////////////////////////////////////////////////////////////
|
Chris@101
|
2 // Copyright Christopher Kormanyos 2002 - 2013.
|
Chris@101
|
3 // Copyright 2011 -2013 John Maddock. Distributed under the Boost
|
Chris@101
|
4 // Software License, Version 1.0. (See accompanying file
|
Chris@101
|
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
6 //
|
Chris@16
|
7 // This work is based on an earlier work:
|
Chris@16
|
8 // "Algorithm 910: A Portable C++ Multiple-Precision System for Special-Function Calculations",
|
Chris@16
|
9 // in ACM TOMS, {VOL 37, ISSUE 4, (February 2011)} (C) ACM, 2011. http://doi.acm.org/10.1145/1916461.1916469
|
Chris@16
|
10 //
|
Chris@16
|
11 // Note that there are no "noexcept" specifications on the functions in this file: there are too many
|
Chris@101
|
12 // calls to lexical_cast (and similar) to easily analyse the code for correctness. So until compilers
|
Chris@16
|
13 // can detect noexcept misuse at compile time, the only realistic option is to simply not use it here.
|
Chris@16
|
14 //
|
Chris@16
|
15
|
Chris@16
|
16 #ifndef BOOST_MP_CPP_DEC_FLOAT_BACKEND_HPP
|
Chris@16
|
17 #define BOOST_MP_CPP_DEC_FLOAT_BACKEND_HPP
|
Chris@16
|
18
|
Chris@16
|
19 #include <boost/config.hpp>
|
Chris@16
|
20 #include <boost/cstdint.hpp>
|
Chris@16
|
21 #include <limits>
|
Chris@16
|
22 #ifndef BOOST_NO_CXX11_HDR_ARRAY
|
Chris@16
|
23 #include <array>
|
Chris@16
|
24 #else
|
Chris@16
|
25 #include <boost/array.hpp>
|
Chris@16
|
26 #endif
|
Chris@16
|
27 #include <boost/cstdint.hpp>
|
Chris@16
|
28 #include <boost/multiprecision/number.hpp>
|
Chris@16
|
29 #include <boost/multiprecision/detail/big_lanczos.hpp>
|
Chris@16
|
30 #include <boost/multiprecision/detail/dynamic_array.hpp>
|
Chris@16
|
31
|
Chris@16
|
32 //
|
Chris@16
|
33 // Headers required for Boost.Math integration:
|
Chris@16
|
34 //
|
Chris@16
|
35 #include <boost/math/policies/policy.hpp>
|
Chris@16
|
36
|
Chris@16
|
37 namespace boost{
|
Chris@16
|
38 namespace multiprecision{
|
Chris@16
|
39 namespace backends{
|
Chris@16
|
40
|
Chris@16
|
41 template <unsigned Digits10, class ExponentType = boost::int32_t, class Allocator = void>
|
Chris@16
|
42 class cpp_dec_float;
|
Chris@16
|
43
|
Chris@16
|
44 } // namespace
|
Chris@16
|
45
|
Chris@16
|
46 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@16
|
47 struct number_category<backends::cpp_dec_float<Digits10, ExponentType, Allocator> > : public mpl::int_<number_kind_floating_point>{};
|
Chris@16
|
48
|
Chris@16
|
49 namespace backends{
|
Chris@16
|
50
|
Chris@16
|
51 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@16
|
52 class cpp_dec_float
|
Chris@16
|
53 {
|
Chris@16
|
54 private:
|
Chris@16
|
55 static const boost::int32_t cpp_dec_float_digits10_setting = Digits10;
|
Chris@16
|
56
|
Chris@16
|
57 // We need at least 16-bits in the exponent type to do anything sensible:
|
Chris@16
|
58 BOOST_STATIC_ASSERT_MSG(boost::is_signed<ExponentType>::value, "ExponentType must be a signed built in integer type.");
|
Chris@16
|
59 BOOST_STATIC_ASSERT_MSG(sizeof(ExponentType) > 1, "ExponentType is too small.");
|
Chris@16
|
60
|
Chris@16
|
61 public:
|
Chris@101
|
62 typedef mpl::list<long long> signed_types;
|
Chris@101
|
63 typedef mpl::list<unsigned long long> unsigned_types;
|
Chris@101
|
64 typedef mpl::list<long double> float_types;
|
Chris@101
|
65 typedef ExponentType exponent_type;
|
Chris@101
|
66
|
Chris@101
|
67 static const boost::int32_t cpp_dec_float_radix = 10L;
|
Chris@16
|
68 static const boost::int32_t cpp_dec_float_digits10_limit_lo = 9L;
|
Chris@16
|
69 static const boost::int32_t cpp_dec_float_digits10_limit_hi = boost::integer_traits<boost::int32_t>::const_max - 100;
|
Chris@101
|
70 static const boost::int32_t cpp_dec_float_digits10 = ((cpp_dec_float_digits10_setting < cpp_dec_float_digits10_limit_lo) ? cpp_dec_float_digits10_limit_lo : ((cpp_dec_float_digits10_setting > cpp_dec_float_digits10_limit_hi) ? cpp_dec_float_digits10_limit_hi : cpp_dec_float_digits10_setting));
|
Chris@101
|
71 static const ExponentType cpp_dec_float_max_exp10 = (static_cast<ExponentType>(1) << (std::numeric_limits<ExponentType>::digits - 5));
|
Chris@101
|
72 static const ExponentType cpp_dec_float_min_exp10 = -cpp_dec_float_max_exp10;
|
Chris@101
|
73 static const ExponentType cpp_dec_float_max_exp = cpp_dec_float_max_exp10;
|
Chris@101
|
74 static const ExponentType cpp_dec_float_min_exp = cpp_dec_float_min_exp10;
|
Chris@16
|
75
|
Chris@16
|
76 BOOST_STATIC_ASSERT((cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_max_exp10 == -cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_min_exp10));
|
Chris@16
|
77
|
Chris@16
|
78 private:
|
Chris@16
|
79 static const boost::int32_t cpp_dec_float_elem_digits10 = 8L;
|
Chris@101
|
80 static const boost::int32_t cpp_dec_float_elem_mask = 100000000L;
|
Chris@16
|
81
|
Chris@16
|
82 BOOST_STATIC_ASSERT(0 == cpp_dec_float_max_exp10 % cpp_dec_float_elem_digits10);
|
Chris@16
|
83
|
Chris@16
|
84 // There are three guard limbs.
|
Chris@16
|
85 // 1) The first limb has 'play' from 1...8 decimal digits.
|
Chris@16
|
86 // 2) The last limb also has 'play' from 1...8 decimal digits.
|
Chris@16
|
87 // 3) One limb can get lost when justifying after multiply,
|
Chris@101
|
88 // as only half of the triangle is multiplied and a carry
|
Chris@101
|
89 // from below is missing.
|
Chris@16
|
90 static const boost::int32_t cpp_dec_float_elem_number_request = static_cast<boost::int32_t>((cpp_dec_float_digits10 / cpp_dec_float_elem_digits10) + (((cpp_dec_float_digits10 % cpp_dec_float_elem_digits10) != 0) ? 1 : 0));
|
Chris@16
|
91
|
Chris@16
|
92 // The number of elements needed (with a minimum of two) plus three added guard limbs.
|
Chris@16
|
93 static const boost::int32_t cpp_dec_float_elem_number = static_cast<boost::int32_t>(((cpp_dec_float_elem_number_request < 2L) ? 2L : cpp_dec_float_elem_number_request) + 3L);
|
Chris@16
|
94
|
Chris@16
|
95 public:
|
Chris@16
|
96 static const boost::int32_t cpp_dec_float_total_digits10 = static_cast<boost::int32_t>(cpp_dec_float_elem_number * cpp_dec_float_elem_digits10);
|
Chris@16
|
97
|
Chris@16
|
98 private:
|
Chris@16
|
99
|
Chris@16
|
100 typedef enum enum_fpclass_type
|
Chris@16
|
101 {
|
Chris@16
|
102 cpp_dec_float_finite,
|
Chris@16
|
103 cpp_dec_float_inf,
|
Chris@16
|
104 cpp_dec_float_NaN
|
Chris@16
|
105 }
|
Chris@16
|
106 fpclass_type;
|
Chris@16
|
107
|
Chris@16
|
108 #ifndef BOOST_NO_CXX11_HDR_ARRAY
|
Chris@16
|
109 typedef typename mpl::if_<is_void<Allocator>,
|
Chris@16
|
110 std::array<boost::uint32_t, cpp_dec_float_elem_number>,
|
Chris@16
|
111 detail::dynamic_array<boost::uint32_t, cpp_dec_float_elem_number, Allocator>
|
Chris@16
|
112 >::type array_type;
|
Chris@16
|
113 #else
|
Chris@16
|
114 typedef typename mpl::if_<is_void<Allocator>,
|
Chris@16
|
115 boost::array<boost::uint32_t, cpp_dec_float_elem_number>,
|
Chris@16
|
116 detail::dynamic_array<boost::uint32_t, cpp_dec_float_elem_number, Allocator>
|
Chris@16
|
117 >::type array_type;
|
Chris@16
|
118 #endif
|
Chris@16
|
119
|
Chris@101
|
120 array_type data;
|
Chris@101
|
121 ExponentType exp;
|
Chris@101
|
122 bool neg;
|
Chris@101
|
123 fpclass_type fpclass;
|
Chris@101
|
124 boost::int32_t prec_elem;
|
Chris@16
|
125
|
Chris@16
|
126 //
|
Chris@16
|
127 // Special values constructor:
|
Chris@16
|
128 //
|
Chris@101
|
129 cpp_dec_float(fpclass_type c) :
|
Chris@16
|
130 data(),
|
Chris@101
|
131 exp (static_cast<ExponentType>(0)),
|
Chris@101
|
132 neg (false),
|
Chris@101
|
133 fpclass (c),
|
Chris@16
|
134 prec_elem(cpp_dec_float_elem_number) { }
|
Chris@16
|
135
|
Chris@16
|
136 //
|
Chris@16
|
137 // Static data initializer:
|
Chris@16
|
138 //
|
Chris@16
|
139 struct initializer
|
Chris@16
|
140 {
|
Chris@16
|
141 initializer()
|
Chris@16
|
142 {
|
Chris@101
|
143 cpp_dec_float<Digits10, ExponentType, Allocator>::nan();
|
Chris@101
|
144 cpp_dec_float<Digits10, ExponentType, Allocator>::inf();
|
Chris@16
|
145 (cpp_dec_float<Digits10, ExponentType, Allocator>::min)();
|
Chris@16
|
146 (cpp_dec_float<Digits10, ExponentType, Allocator>::max)();
|
Chris@101
|
147 cpp_dec_float<Digits10, ExponentType, Allocator>::zero();
|
Chris@101
|
148 cpp_dec_float<Digits10, ExponentType, Allocator>::one();
|
Chris@101
|
149 cpp_dec_float<Digits10, ExponentType, Allocator>::two();
|
Chris@101
|
150 cpp_dec_float<Digits10, ExponentType, Allocator>::half();
|
Chris@101
|
151 cpp_dec_float<Digits10, ExponentType, Allocator>::double_min();
|
Chris@101
|
152 cpp_dec_float<Digits10, ExponentType, Allocator>::double_max();
|
Chris@101
|
153 cpp_dec_float<Digits10, ExponentType, Allocator>::long_double_max();
|
Chris@101
|
154 cpp_dec_float<Digits10, ExponentType, Allocator>::long_double_min();
|
Chris@101
|
155 cpp_dec_float<Digits10, ExponentType, Allocator>::long_long_max();
|
Chris@101
|
156 cpp_dec_float<Digits10, ExponentType, Allocator>::long_long_min();
|
Chris@101
|
157 cpp_dec_float<Digits10, ExponentType, Allocator>::ulong_long_max();
|
Chris@101
|
158 cpp_dec_float<Digits10, ExponentType, Allocator>::eps();
|
Chris@101
|
159 cpp_dec_float<Digits10, ExponentType, Allocator>::pow2(0);
|
Chris@16
|
160 }
|
Chris@16
|
161 void do_nothing(){}
|
Chris@16
|
162 };
|
Chris@16
|
163
|
Chris@16
|
164 static initializer init;
|
Chris@16
|
165
|
Chris@16
|
166 public:
|
Chris@16
|
167 // Constructors
|
Chris@101
|
168 cpp_dec_float() BOOST_NOEXCEPT_IF(noexcept(array_type())) :
|
Chris@16
|
169 data(),
|
Chris@101
|
170 exp (static_cast<ExponentType>(0)),
|
Chris@101
|
171 neg (false),
|
Chris@101
|
172 fpclass (cpp_dec_float_finite),
|
Chris@16
|
173 prec_elem(cpp_dec_float_elem_number) { }
|
Chris@16
|
174
|
Chris@101
|
175 cpp_dec_float(const char* s) :
|
Chris@16
|
176 data(),
|
Chris@101
|
177 exp (static_cast<ExponentType>(0)),
|
Chris@101
|
178 neg (false),
|
Chris@101
|
179 fpclass (cpp_dec_float_finite),
|
Chris@101
|
180 prec_elem(cpp_dec_float_elem_number)
|
Chris@16
|
181 {
|
Chris@16
|
182 *this = s;
|
Chris@16
|
183 }
|
Chris@16
|
184
|
Chris@16
|
185 template<class I>
|
Chris@101
|
186 cpp_dec_float(I i, typename enable_if<is_unsigned<I> >::type* = 0) :
|
Chris@16
|
187 data(),
|
Chris@101
|
188 exp (static_cast<ExponentType>(0)),
|
Chris@101
|
189 neg (false),
|
Chris@101
|
190 fpclass (cpp_dec_float_finite),
|
Chris@101
|
191 prec_elem(cpp_dec_float_elem_number)
|
Chris@16
|
192 {
|
Chris@16
|
193 from_unsigned_long_long(i);
|
Chris@16
|
194 }
|
Chris@16
|
195
|
Chris@16
|
196 template <class I>
|
Chris@101
|
197 cpp_dec_float(I i, typename enable_if<is_signed<I> >::type* = 0) :
|
Chris@16
|
198 data(),
|
Chris@101
|
199 exp (static_cast<ExponentType>(0)),
|
Chris@101
|
200 neg (false),
|
Chris@101
|
201 fpclass (cpp_dec_float_finite),
|
Chris@101
|
202 prec_elem(cpp_dec_float_elem_number)
|
Chris@16
|
203 {
|
Chris@16
|
204 if(i < 0)
|
Chris@16
|
205 {
|
Chris@101
|
206 from_unsigned_long_long(boost::multiprecision::detail::unsigned_abs(i));
|
Chris@16
|
207 negate();
|
Chris@16
|
208 }
|
Chris@16
|
209 else
|
Chris@16
|
210 from_unsigned_long_long(i);
|
Chris@16
|
211 }
|
Chris@16
|
212
|
Chris@101
|
213 cpp_dec_float(const cpp_dec_float& f) BOOST_NOEXCEPT_IF(noexcept(array_type(std::declval<const array_type&>()))) :
|
Chris@101
|
214 data (f.data),
|
Chris@101
|
215 exp (f.exp),
|
Chris@101
|
216 neg (f.neg),
|
Chris@101
|
217 fpclass (f.fpclass),
|
Chris@16
|
218 prec_elem(f.prec_elem) { }
|
Chris@16
|
219
|
Chris@16
|
220 template <unsigned D, class ET, class A>
|
Chris@101
|
221 cpp_dec_float(const cpp_dec_float<D, ET, A>& f, typename enable_if_c<D <= Digits10>::type* = 0) :
|
Chris@16
|
222 data(),
|
Chris@101
|
223 exp (f.exp),
|
Chris@101
|
224 neg (f.neg),
|
Chris@101
|
225 fpclass (static_cast<fpclass_type>(static_cast<int>(f.fpclass))),
|
Chris@16
|
226 prec_elem(cpp_dec_float_elem_number)
|
Chris@16
|
227 {
|
Chris@16
|
228 std::copy(f.data.begin(), f.data.begin() + f.prec_elem, data.begin());
|
Chris@16
|
229 }
|
Chris@16
|
230 template <unsigned D, class ET, class A>
|
Chris@101
|
231 explicit cpp_dec_float(const cpp_dec_float<D, ET, A>& f, typename disable_if_c<D <= Digits10>::type* = 0) :
|
Chris@16
|
232 data(),
|
Chris@101
|
233 exp (f.exp),
|
Chris@101
|
234 neg (f.neg),
|
Chris@101
|
235 fpclass (static_cast<fpclass_type>(static_cast<int>(f.fpclass))),
|
Chris@16
|
236 prec_elem(cpp_dec_float_elem_number)
|
Chris@16
|
237 {
|
Chris@16
|
238 // TODO: this doesn't round!
|
Chris@16
|
239 std::copy(f.data.begin(), f.data.begin() + prec_elem, data.begin());
|
Chris@16
|
240 }
|
Chris@16
|
241
|
Chris@16
|
242 template <class F>
|
Chris@101
|
243 cpp_dec_float(const F val, typename enable_if<is_floating_point<F> >::type* = 0) :
|
Chris@16
|
244 data(),
|
Chris@101
|
245 exp (static_cast<ExponentType>(0)),
|
Chris@101
|
246 neg (false),
|
Chris@101
|
247 fpclass (cpp_dec_float_finite),
|
Chris@101
|
248 prec_elem(cpp_dec_float_elem_number)
|
Chris@16
|
249 {
|
Chris@16
|
250 *this = val;
|
Chris@16
|
251 }
|
Chris@16
|
252
|
Chris@101
|
253 cpp_dec_float(const double mantissa, const ExponentType exponent);
|
Chris@16
|
254
|
Chris@16
|
255 // Specific special values.
|
Chris@101
|
256 static const cpp_dec_float& nan()
|
Chris@16
|
257 {
|
Chris@16
|
258 static const cpp_dec_float val(cpp_dec_float_NaN);
|
Chris@16
|
259 init.do_nothing();
|
Chris@16
|
260 return val;
|
Chris@16
|
261 }
|
Chris@101
|
262
|
Chris@101
|
263 static const cpp_dec_float& inf()
|
Chris@16
|
264 {
|
Chris@16
|
265 static const cpp_dec_float val(cpp_dec_float_inf);
|
Chris@16
|
266 init.do_nothing();
|
Chris@16
|
267 return val;
|
Chris@16
|
268 }
|
Chris@101
|
269
|
Chris@16
|
270 static const cpp_dec_float& (max)()
|
Chris@16
|
271 {
|
Chris@16
|
272 init.do_nothing();
|
Chris@101
|
273 static cpp_dec_float val_max = std::string("1.0e" + boost::lexical_cast<std::string>(cpp_dec_float_max_exp10)).c_str();
|
Chris@16
|
274 return val_max;
|
Chris@16
|
275 }
|
Chris@16
|
276
|
Chris@16
|
277 static const cpp_dec_float& (min)()
|
Chris@16
|
278 {
|
Chris@16
|
279 init.do_nothing();
|
Chris@101
|
280 static cpp_dec_float val_min = std::string("1.0e" + boost::lexical_cast<std::string>(cpp_dec_float_min_exp10)).c_str();
|
Chris@16
|
281 return val_min;
|
Chris@16
|
282 }
|
Chris@101
|
283
|
Chris@101
|
284 static const cpp_dec_float& zero()
|
Chris@16
|
285 {
|
Chris@16
|
286 init.do_nothing();
|
Chris@16
|
287 static cpp_dec_float val(static_cast<unsigned long long>(0u));
|
Chris@16
|
288 return val;
|
Chris@16
|
289 }
|
Chris@101
|
290
|
Chris@101
|
291 static const cpp_dec_float& one()
|
Chris@16
|
292 {
|
Chris@16
|
293 init.do_nothing();
|
Chris@16
|
294 static cpp_dec_float val(static_cast<unsigned long long>(1u));
|
Chris@16
|
295 return val;
|
Chris@16
|
296 }
|
Chris@101
|
297
|
Chris@101
|
298 static const cpp_dec_float& two()
|
Chris@16
|
299 {
|
Chris@16
|
300 init.do_nothing();
|
Chris@16
|
301 static cpp_dec_float val(static_cast<unsigned long long>(2u));
|
Chris@16
|
302 return val;
|
Chris@16
|
303 }
|
Chris@101
|
304
|
Chris@101
|
305 static const cpp_dec_float& half()
|
Chris@16
|
306 {
|
Chris@16
|
307 init.do_nothing();
|
Chris@16
|
308 static cpp_dec_float val(0.5L);
|
Chris@16
|
309 return val;
|
Chris@16
|
310 }
|
Chris@101
|
311
|
Chris@101
|
312 static const cpp_dec_float& double_min()
|
Chris@16
|
313 {
|
Chris@16
|
314 init.do_nothing();
|
Chris@16
|
315 static cpp_dec_float val(static_cast<long double>((std::numeric_limits<double>::min)()));
|
Chris@16
|
316 return val;
|
Chris@16
|
317 }
|
Chris@101
|
318
|
Chris@101
|
319 static const cpp_dec_float& double_max()
|
Chris@16
|
320 {
|
Chris@16
|
321 init.do_nothing();
|
Chris@16
|
322 static cpp_dec_float val(static_cast<long double>((std::numeric_limits<double>::max)()));
|
Chris@16
|
323 return val;
|
Chris@16
|
324 }
|
Chris@101
|
325
|
Chris@101
|
326 static const cpp_dec_float& long_double_min()
|
Chris@16
|
327 {
|
Chris@16
|
328 init.do_nothing();
|
Chris@101
|
329 #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
|
Chris@101
|
330 static cpp_dec_float val(static_cast<long double>((std::numeric_limits<double>::min)()));
|
Chris@101
|
331 #else
|
Chris@16
|
332 static cpp_dec_float val((std::numeric_limits<long double>::min)());
|
Chris@101
|
333 #endif
|
Chris@16
|
334 return val;
|
Chris@16
|
335 }
|
Chris@101
|
336
|
Chris@101
|
337 static const cpp_dec_float& long_double_max()
|
Chris@16
|
338 {
|
Chris@16
|
339 init.do_nothing();
|
Chris@101
|
340 #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
|
Chris@101
|
341 static cpp_dec_float val(static_cast<long double>((std::numeric_limits<double>::max)()));
|
Chris@101
|
342 #else
|
Chris@16
|
343 static cpp_dec_float val((std::numeric_limits<long double>::max)());
|
Chris@101
|
344 #endif
|
Chris@16
|
345 return val;
|
Chris@16
|
346 }
|
Chris@101
|
347
|
Chris@101
|
348 static const cpp_dec_float& long_long_max()
|
Chris@16
|
349 {
|
Chris@16
|
350 init.do_nothing();
|
Chris@16
|
351 static cpp_dec_float val((std::numeric_limits<long long>::max)());
|
Chris@16
|
352 return val;
|
Chris@16
|
353 }
|
Chris@101
|
354
|
Chris@101
|
355 static const cpp_dec_float& long_long_min()
|
Chris@16
|
356 {
|
Chris@16
|
357 init.do_nothing();
|
Chris@16
|
358 static cpp_dec_float val((std::numeric_limits<long long>::min)());
|
Chris@16
|
359 return val;
|
Chris@16
|
360 }
|
Chris@101
|
361
|
Chris@101
|
362 static const cpp_dec_float& ulong_long_max()
|
Chris@16
|
363 {
|
Chris@16
|
364 init.do_nothing();
|
Chris@16
|
365 static cpp_dec_float val((std::numeric_limits<unsigned long long>::max)());
|
Chris@16
|
366 return val;
|
Chris@16
|
367 }
|
Chris@101
|
368
|
Chris@101
|
369 static const cpp_dec_float& eps()
|
Chris@16
|
370 {
|
Chris@16
|
371 init.do_nothing();
|
Chris@101
|
372 static cpp_dec_float val(1.0, 1 - static_cast<int>(cpp_dec_float_digits10));
|
Chris@16
|
373 return val;
|
Chris@16
|
374 }
|
Chris@16
|
375
|
Chris@16
|
376 // Basic operations.
|
Chris@101
|
377 cpp_dec_float& operator=(const cpp_dec_float& v) BOOST_NOEXCEPT_IF(noexcept(std::declval<array_type&>() = std::declval<const array_type&>()))
|
Chris@16
|
378 {
|
Chris@16
|
379 data = v.data;
|
Chris@16
|
380 exp = v.exp;
|
Chris@16
|
381 neg = v.neg;
|
Chris@16
|
382 fpclass = v.fpclass;
|
Chris@16
|
383 prec_elem = v.prec_elem;
|
Chris@16
|
384 return *this;
|
Chris@16
|
385 }
|
Chris@101
|
386
|
Chris@16
|
387 template <unsigned D>
|
Chris@101
|
388 cpp_dec_float& operator=(const cpp_dec_float<D>& f)
|
Chris@101
|
389 {
|
Chris@16
|
390 exp = f.exp;
|
Chris@16
|
391 neg = f.neg;
|
Chris@16
|
392 fpclass = static_cast<enum_fpclass_type>(static_cast<int>(f.fpclass));
|
Chris@16
|
393 unsigned elems = (std::min)(f.prec_elem, cpp_dec_float_elem_number);
|
Chris@16
|
394 std::copy(f.data.begin(), f.data.begin() + elems, data.begin());
|
Chris@16
|
395 std::fill(data.begin() + elems, data.end(), 0);
|
Chris@16
|
396 prec_elem = cpp_dec_float_elem_number;
|
Chris@16
|
397 return *this;
|
Chris@16
|
398 }
|
Chris@101
|
399
|
Chris@101
|
400 cpp_dec_float& operator=(long long v)
|
Chris@16
|
401 {
|
Chris@16
|
402 if(v < 0)
|
Chris@16
|
403 {
|
Chris@16
|
404 from_unsigned_long_long(-v);
|
Chris@16
|
405 negate();
|
Chris@16
|
406 }
|
Chris@16
|
407 else
|
Chris@16
|
408 from_unsigned_long_long(v);
|
Chris@16
|
409 return *this;
|
Chris@16
|
410 }
|
Chris@101
|
411
|
Chris@101
|
412 cpp_dec_float& operator=(unsigned long long v)
|
Chris@16
|
413 {
|
Chris@16
|
414 from_unsigned_long_long(v);
|
Chris@16
|
415 return *this;
|
Chris@16
|
416 }
|
Chris@101
|
417
|
Chris@101
|
418 cpp_dec_float& operator=(long double v);
|
Chris@101
|
419
|
Chris@101
|
420 cpp_dec_float& operator=(const char* v)
|
Chris@16
|
421 {
|
Chris@16
|
422 rd_string(v);
|
Chris@16
|
423 return *this;
|
Chris@16
|
424 }
|
Chris@16
|
425
|
Chris@101
|
426 cpp_dec_float& operator+=(const cpp_dec_float& v);
|
Chris@101
|
427 cpp_dec_float& operator-=(const cpp_dec_float& v);
|
Chris@101
|
428 cpp_dec_float& operator*=(const cpp_dec_float& v);
|
Chris@101
|
429 cpp_dec_float& operator/=(const cpp_dec_float& v);
|
Chris@101
|
430
|
Chris@101
|
431 cpp_dec_float& add_unsigned_long_long(const unsigned long long n)
|
Chris@16
|
432 {
|
Chris@16
|
433 cpp_dec_float t;
|
Chris@16
|
434 t.from_unsigned_long_long(n);
|
Chris@16
|
435 return *this += t;
|
Chris@16
|
436 }
|
Chris@101
|
437
|
Chris@101
|
438 cpp_dec_float& sub_unsigned_long_long(const unsigned long long n)
|
Chris@16
|
439 {
|
Chris@16
|
440 cpp_dec_float t;
|
Chris@16
|
441 t.from_unsigned_long_long(n);
|
Chris@16
|
442 return *this -= t;
|
Chris@16
|
443 }
|
Chris@101
|
444
|
Chris@16
|
445 cpp_dec_float& mul_unsigned_long_long(const unsigned long long n);
|
Chris@16
|
446 cpp_dec_float& div_unsigned_long_long(const unsigned long long n);
|
Chris@16
|
447
|
Chris@16
|
448 // Elementary primitives.
|
Chris@101
|
449 cpp_dec_float& calculate_inv ();
|
Chris@101
|
450 cpp_dec_float& calculate_sqrt();
|
Chris@101
|
451
|
Chris@101
|
452 void negate()
|
Chris@101
|
453 {
|
Chris@16
|
454 if(!iszero())
|
Chris@16
|
455 neg = !neg;
|
Chris@16
|
456 }
|
Chris@16
|
457
|
Chris@16
|
458 // Comparison functions
|
Chris@101
|
459 bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION() const { return (fpclass == cpp_dec_float_NaN); }
|
Chris@101
|
460 bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION() const { return (fpclass == cpp_dec_float_inf); }
|
Chris@101
|
461 bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION() const { return (fpclass == cpp_dec_float_finite); }
|
Chris@101
|
462
|
Chris@101
|
463 bool iszero () const
|
Chris@16
|
464 {
|
Chris@16
|
465 return ((fpclass == cpp_dec_float_finite) && (data[0u] == 0u));
|
Chris@16
|
466 }
|
Chris@101
|
467
|
Chris@101
|
468 bool isone () const;
|
Chris@101
|
469 bool isint () const;
|
Chris@101
|
470 bool isneg () const { return neg; }
|
Chris@16
|
471
|
Chris@16
|
472 // Operators pre-increment and pre-decrement
|
Chris@101
|
473 cpp_dec_float& operator++()
|
Chris@16
|
474 {
|
Chris@16
|
475 return *this += one();
|
Chris@16
|
476 }
|
Chris@101
|
477
|
Chris@101
|
478 cpp_dec_float& operator--()
|
Chris@16
|
479 {
|
Chris@16
|
480 return *this -= one();
|
Chris@16
|
481 }
|
Chris@16
|
482
|
Chris@16
|
483 std::string str(boost::intmax_t digits, std::ios_base::fmtflags f)const;
|
Chris@16
|
484
|
Chris@101
|
485 int compare(const cpp_dec_float& v)const;
|
Chris@101
|
486
|
Chris@16
|
487 template <class V>
|
Chris@101
|
488 int compare(const V& v)const
|
Chris@16
|
489 {
|
Chris@16
|
490 cpp_dec_float<Digits10, ExponentType, Allocator> t;
|
Chris@16
|
491 t = v;
|
Chris@16
|
492 return compare(t);
|
Chris@16
|
493 }
|
Chris@16
|
494
|
Chris@101
|
495 void swap(cpp_dec_float& v)
|
Chris@16
|
496 {
|
Chris@16
|
497 data.swap(v.data);
|
Chris@16
|
498 std::swap(exp, v.exp);
|
Chris@16
|
499 std::swap(neg, v.neg);
|
Chris@16
|
500 std::swap(fpclass, v.fpclass);
|
Chris@16
|
501 std::swap(prec_elem, v.prec_elem);
|
Chris@16
|
502 }
|
Chris@16
|
503
|
Chris@101
|
504 double extract_double() const;
|
Chris@101
|
505 long double extract_long_double() const;
|
Chris@101
|
506 signed long long extract_signed_long_long() const;
|
Chris@101
|
507 unsigned long long extract_unsigned_long_long() const;
|
Chris@101
|
508 void extract_parts(double& mantissa, ExponentType& exponent) const;
|
Chris@101
|
509 cpp_dec_float extract_integer_part() const;
|
Chris@101
|
510
|
Chris@101
|
511 void precision(const boost::int32_t prec_digits)
|
Chris@16
|
512 {
|
Chris@16
|
513 if(prec_digits >= cpp_dec_float_total_digits10)
|
Chris@16
|
514 {
|
Chris@16
|
515 prec_elem = cpp_dec_float_elem_number;
|
Chris@16
|
516 }
|
Chris@16
|
517 else
|
Chris@16
|
518 {
|
Chris@101
|
519 const boost::int32_t elems = static_cast<boost::int32_t>( static_cast<boost::int32_t>( (prec_digits + (cpp_dec_float_elem_digits10 / 2)) / cpp_dec_float_elem_digits10)
|
Chris@101
|
520 + static_cast<boost::int32_t>(((prec_digits % cpp_dec_float_elem_digits10) != 0) ? 1 : 0));
|
Chris@16
|
521
|
Chris@16
|
522 prec_elem = (std::min)(cpp_dec_float_elem_number, (std::max)(elems, static_cast<boost::int32_t>(2)));
|
Chris@16
|
523 }
|
Chris@16
|
524 }
|
Chris@16
|
525 static cpp_dec_float pow2(long long i);
|
Chris@101
|
526 ExponentType order()const
|
Chris@16
|
527 {
|
Chris@16
|
528 const bool bo_order_is_zero = ((!(isfinite)()) || (data[0] == static_cast<boost::uint32_t>(0u)));
|
Chris@16
|
529 //
|
Chris@16
|
530 // Binary search to find the order of the leading term:
|
Chris@16
|
531 //
|
Chris@16
|
532 ExponentType prefix = 0;
|
Chris@16
|
533
|
Chris@16
|
534 if(data[0] >= 100000UL)
|
Chris@16
|
535 {
|
Chris@16
|
536 if(data[0] >= 10000000UL)
|
Chris@16
|
537 {
|
Chris@16
|
538 if(data[0] >= 100000000UL)
|
Chris@16
|
539 {
|
Chris@16
|
540 if(data[0] >= 1000000000UL)
|
Chris@16
|
541 prefix = 9;
|
Chris@16
|
542 else
|
Chris@16
|
543 prefix = 8;
|
Chris@16
|
544 }
|
Chris@16
|
545 else
|
Chris@16
|
546 prefix = 7;
|
Chris@16
|
547 }
|
Chris@16
|
548 else
|
Chris@16
|
549 {
|
Chris@16
|
550 if(data[0] >= 1000000UL)
|
Chris@16
|
551 prefix = 6;
|
Chris@16
|
552 else
|
Chris@16
|
553 prefix = 5;
|
Chris@16
|
554 }
|
Chris@16
|
555 }
|
Chris@16
|
556 else
|
Chris@16
|
557 {
|
Chris@16
|
558 if(data[0] >= 1000UL)
|
Chris@16
|
559 {
|
Chris@16
|
560 if(data[0] >= 10000UL)
|
Chris@16
|
561 prefix = 4;
|
Chris@16
|
562 else
|
Chris@16
|
563 prefix = 3;
|
Chris@16
|
564 }
|
Chris@16
|
565 else
|
Chris@16
|
566 {
|
Chris@16
|
567 if(data[0] >= 100)
|
Chris@16
|
568 prefix = 2;
|
Chris@16
|
569 else if(data[0] >= 10)
|
Chris@16
|
570 prefix = 1;
|
Chris@16
|
571 }
|
Chris@16
|
572 }
|
Chris@16
|
573
|
Chris@16
|
574 return (bo_order_is_zero ? static_cast<ExponentType>(0) : static_cast<ExponentType>(exp + prefix));
|
Chris@16
|
575 }
|
Chris@16
|
576
|
Chris@16
|
577 template<class Archive>
|
Chris@16
|
578 void serialize(Archive & ar, const unsigned int /*version*/)
|
Chris@16
|
579 {
|
Chris@16
|
580 for(unsigned i = 0; i < data.size(); ++i)
|
Chris@16
|
581 ar & data[i];
|
Chris@16
|
582 ar & exp;
|
Chris@16
|
583 ar & neg;
|
Chris@16
|
584 ar & fpclass;
|
Chris@16
|
585 ar & prec_elem;
|
Chris@16
|
586 }
|
Chris@16
|
587
|
Chris@16
|
588 private:
|
Chris@101
|
589 static bool data_elem_is_non_zero_predicate(const boost::uint32_t& d) { return (d != static_cast<boost::uint32_t>(0u)); }
|
Chris@101
|
590 static bool data_elem_is_non_nine_predicate(const boost::uint32_t& d) { return (d != static_cast<boost::uint32_t>(cpp_dec_float::cpp_dec_float_elem_mask - 1)); }
|
Chris@101
|
591 static bool char_is_nonzero_predicate(const char& c) { return (c != static_cast<char>('0')); }
|
Chris@101
|
592
|
Chris@101
|
593 void from_unsigned_long_long(const unsigned long long u);
|
Chris@101
|
594
|
Chris@101
|
595 int cmp_data(const array_type& vd) const;
|
Chris@101
|
596
|
Chris@101
|
597
|
Chris@101
|
598 static boost::uint32_t mul_loop_uv(boost::uint32_t* const u, const boost::uint32_t* const v, const boost::int32_t p);
|
Chris@101
|
599 static boost::uint32_t mul_loop_n (boost::uint32_t* const u, boost::uint32_t n, const boost::int32_t p);
|
Chris@101
|
600 static boost::uint32_t div_loop_n (boost::uint32_t* const u, boost::uint32_t n, const boost::int32_t p);
|
Chris@16
|
601
|
Chris@16
|
602 bool rd_string(const char* const s);
|
Chris@16
|
603
|
Chris@16
|
604 template <unsigned D, class ET, class A>
|
Chris@16
|
605 friend class cpp_dec_float;
|
Chris@16
|
606 };
|
Chris@16
|
607
|
Chris@16
|
608 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@16
|
609 typename cpp_dec_float<Digits10, ExponentType, Allocator>::initializer cpp_dec_float<Digits10, ExponentType, Allocator>::init;
|
Chris@16
|
610
|
Chris@16
|
611 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@16
|
612 const boost::int32_t cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_radix;
|
Chris@16
|
613 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@16
|
614 const boost::int32_t cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_digits10_setting;
|
Chris@16
|
615 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@16
|
616 const boost::int32_t cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_digits10_limit_lo;
|
Chris@16
|
617 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@16
|
618 const boost::int32_t cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_digits10_limit_hi;
|
Chris@16
|
619 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@16
|
620 const boost::int32_t cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_digits10;
|
Chris@16
|
621 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@16
|
622 const ExponentType cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_max_exp;
|
Chris@16
|
623 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@16
|
624 const ExponentType cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_min_exp;
|
Chris@16
|
625 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@16
|
626 const ExponentType cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_max_exp10;
|
Chris@16
|
627 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@16
|
628 const ExponentType cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_min_exp10;
|
Chris@16
|
629 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@16
|
630 const boost::int32_t cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_elem_digits10;
|
Chris@16
|
631 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@16
|
632 const boost::int32_t cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_elem_number_request;
|
Chris@16
|
633 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@16
|
634 const boost::int32_t cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_elem_number;
|
Chris@16
|
635 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@16
|
636 const boost::int32_t cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_elem_mask;
|
Chris@16
|
637
|
Chris@16
|
638 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@16
|
639 cpp_dec_float<Digits10, ExponentType, Allocator>& cpp_dec_float<Digits10, ExponentType, Allocator>::operator+=(const cpp_dec_float<Digits10, ExponentType, Allocator>& v)
|
Chris@16
|
640 {
|
Chris@16
|
641 if((isnan)())
|
Chris@16
|
642 {
|
Chris@16
|
643 return *this;
|
Chris@16
|
644 }
|
Chris@16
|
645
|
Chris@16
|
646 if((isinf)())
|
Chris@16
|
647 {
|
Chris@16
|
648 if((v.isinf)() && (isneg() != v.isneg()))
|
Chris@16
|
649 {
|
Chris@16
|
650 *this = nan();
|
Chris@16
|
651 }
|
Chris@16
|
652 return *this;
|
Chris@16
|
653 }
|
Chris@16
|
654
|
Chris@16
|
655 if(iszero())
|
Chris@16
|
656 {
|
Chris@16
|
657 return operator=(v);
|
Chris@16
|
658 }
|
Chris@16
|
659
|
Chris@16
|
660 // Get the offset for the add/sub operation.
|
Chris@16
|
661 static const ExponentType max_delta_exp = static_cast<ExponentType>((cpp_dec_float_elem_number - 1) * cpp_dec_float_elem_digits10);
|
Chris@16
|
662
|
Chris@16
|
663 const ExponentType ofs_exp = static_cast<ExponentType>(exp - v.exp);
|
Chris@16
|
664
|
Chris@16
|
665 // Check if the operation is out of range, requiring special handling.
|
Chris@16
|
666 if(v.iszero() || (ofs_exp > max_delta_exp))
|
Chris@16
|
667 {
|
Chris@16
|
668 // Result is *this unchanged since v is negligible compared to *this.
|
Chris@16
|
669 return *this;
|
Chris@16
|
670 }
|
Chris@16
|
671 else if(ofs_exp < -max_delta_exp)
|
Chris@16
|
672 {
|
Chris@16
|
673 // Result is *this = v since *this is negligible compared to v.
|
Chris@16
|
674 return operator=(v);
|
Chris@16
|
675 }
|
Chris@16
|
676
|
Chris@16
|
677 // Do the add/sub operation.
|
Chris@16
|
678
|
Chris@101
|
679 typename array_type::iterator p_u = data.begin();
|
Chris@101
|
680 typename array_type::const_iterator p_v = v.data.begin();
|
Chris@101
|
681 bool b_copy = false;
|
Chris@101
|
682 const boost::int32_t ofs = static_cast<boost::int32_t>(static_cast<boost::int32_t>(ofs_exp) / cpp_dec_float_elem_digits10);
|
Chris@101
|
683 array_type n_data;
|
Chris@16
|
684
|
Chris@16
|
685 if(neg == v.neg)
|
Chris@16
|
686 {
|
Chris@16
|
687 // Add v to *this, where the data array of either *this or v
|
Chris@16
|
688 // might have to be treated with a positive, negative or zero offset.
|
Chris@16
|
689 // The result is stored in *this. The data are added one element
|
Chris@16
|
690 // at a time, each element with carry.
|
Chris@16
|
691 if(ofs >= static_cast<boost::int32_t>(0))
|
Chris@16
|
692 {
|
Chris@16
|
693 std::copy(v.data.begin(), v.data.end() - static_cast<size_t>(ofs), n_data.begin() + static_cast<size_t>(ofs));
|
Chris@16
|
694 std::fill(n_data.begin(), n_data.begin() + static_cast<size_t>(ofs), static_cast<boost::uint32_t>(0u));
|
Chris@16
|
695 p_v = n_data.begin();
|
Chris@16
|
696 }
|
Chris@16
|
697 else
|
Chris@16
|
698 {
|
Chris@16
|
699 std::copy(data.begin(), data.end() - static_cast<size_t>(-ofs), n_data.begin() + static_cast<size_t>(-ofs));
|
Chris@16
|
700 std::fill(n_data.begin(), n_data.begin() + static_cast<size_t>(-ofs), static_cast<boost::uint32_t>(0u));
|
Chris@16
|
701 p_u = n_data.begin();
|
Chris@16
|
702 b_copy = true;
|
Chris@16
|
703 }
|
Chris@16
|
704
|
Chris@16
|
705 // Addition algorithm
|
Chris@16
|
706 boost::uint32_t carry = static_cast<boost::uint32_t>(0u);
|
Chris@16
|
707
|
Chris@16
|
708 for(boost::int32_t j = static_cast<boost::int32_t>(cpp_dec_float_elem_number - static_cast<boost::int32_t>(1)); j >= static_cast<boost::int32_t>(0); j--)
|
Chris@16
|
709 {
|
Chris@16
|
710 boost::uint32_t t = static_cast<boost::uint32_t>(static_cast<boost::uint32_t>(p_u[j] + p_v[j]) + carry);
|
Chris@101
|
711 carry = t / static_cast<boost::uint32_t>(cpp_dec_float_elem_mask);
|
Chris@101
|
712 p_u[j] = static_cast<boost::uint32_t>(t - static_cast<boost::uint32_t>(carry * static_cast<boost::uint32_t>(cpp_dec_float_elem_mask)));
|
Chris@16
|
713 }
|
Chris@16
|
714
|
Chris@16
|
715 if(b_copy)
|
Chris@16
|
716 {
|
Chris@16
|
717 data = n_data;
|
Chris@101
|
718 exp = v.exp;
|
Chris@16
|
719 }
|
Chris@16
|
720
|
Chris@16
|
721 // There needs to be a carry into the element -1 of the array data
|
Chris@16
|
722 if(carry != static_cast<boost::uint32_t>(0u))
|
Chris@16
|
723 {
|
Chris@16
|
724 std::copy_backward(data.begin(), data.end() - static_cast<std::size_t>(1u), data.end());
|
Chris@16
|
725 data[0] = carry;
|
Chris@16
|
726 exp += static_cast<ExponentType>(cpp_dec_float_elem_digits10);
|
Chris@16
|
727 }
|
Chris@16
|
728 }
|
Chris@16
|
729 else
|
Chris@16
|
730 {
|
Chris@16
|
731 // Subtract v from *this, where the data array of either *this or v
|
Chris@16
|
732 // might have to be treated with a positive, negative or zero offset.
|
Chris@16
|
733 if((ofs > static_cast<boost::int32_t>(0))
|
Chris@101
|
734 || ( (ofs == static_cast<boost::int32_t>(0))
|
Chris@16
|
735 && (cmp_data(v.data) > static_cast<boost::int32_t>(0)))
|
Chris@16
|
736 )
|
Chris@16
|
737 {
|
Chris@16
|
738 // In this case, |u| > |v| and ofs is positive.
|
Chris@16
|
739 // Copy the data of v, shifted down to a lower value
|
Chris@16
|
740 // into the data array m_n. Set the operand pointer p_v
|
Chris@16
|
741 // to point to the copied, shifted data m_n.
|
Chris@16
|
742 std::copy(v.data.begin(), v.data.end() - static_cast<size_t>(ofs), n_data.begin() + static_cast<size_t>(ofs));
|
Chris@16
|
743 std::fill(n_data.begin(), n_data.begin() + static_cast<size_t>(ofs), static_cast<boost::uint32_t>(0u));
|
Chris@16
|
744 p_v = n_data.begin();
|
Chris@16
|
745 }
|
Chris@16
|
746 else
|
Chris@16
|
747 {
|
Chris@16
|
748 if(ofs != static_cast<boost::int32_t>(0))
|
Chris@16
|
749 {
|
Chris@16
|
750 // In this case, |u| < |v| and ofs is negative.
|
Chris@16
|
751 // Shift the data of u down to a lower value.
|
Chris@16
|
752 std::copy_backward(data.begin(), data.end() - static_cast<size_t>(-ofs), data.end());
|
Chris@16
|
753 std::fill(data.begin(), data.begin() + static_cast<size_t>(-ofs), static_cast<boost::uint32_t>(0u));
|
Chris@16
|
754 }
|
Chris@16
|
755
|
Chris@16
|
756 // Copy the data of v into the data array n_data.
|
Chris@16
|
757 // Set the u-pointer p_u to point to m_n and the
|
Chris@16
|
758 // operand pointer p_v to point to the shifted
|
Chris@16
|
759 // data m_data.
|
Chris@16
|
760 n_data = v.data;
|
Chris@101
|
761 p_u = n_data.begin();
|
Chris@101
|
762 p_v = data.begin();
|
Chris@16
|
763 b_copy = true;
|
Chris@16
|
764 }
|
Chris@16
|
765
|
Chris@16
|
766 boost::int32_t j;
|
Chris@16
|
767
|
Chris@16
|
768 // Subtraction algorithm
|
Chris@16
|
769 boost::int32_t borrow = static_cast<boost::int32_t>(0);
|
Chris@16
|
770
|
Chris@16
|
771 for(j = static_cast<boost::int32_t>(cpp_dec_float_elem_number - static_cast<boost::int32_t>(1)); j >= static_cast<boost::int32_t>(0); j--)
|
Chris@16
|
772 {
|
Chris@101
|
773 boost::int32_t t = static_cast<boost::int32_t>(static_cast<boost::int32_t>( static_cast<boost::int32_t>(p_u[j])
|
Chris@16
|
774 - static_cast<boost::int32_t>(p_v[j])) - borrow);
|
Chris@16
|
775
|
Chris@16
|
776 // Underflow? Borrow?
|
Chris@16
|
777 if(t < static_cast<boost::int32_t>(0))
|
Chris@16
|
778 {
|
Chris@16
|
779 // Yes, underflow and borrow
|
Chris@101
|
780 t += static_cast<boost::int32_t>(cpp_dec_float_elem_mask);
|
Chris@16
|
781 borrow = static_cast<boost::int32_t>(1);
|
Chris@16
|
782 }
|
Chris@16
|
783 else
|
Chris@16
|
784 {
|
Chris@16
|
785 borrow = static_cast<boost::int32_t>(0);
|
Chris@16
|
786 }
|
Chris@16
|
787
|
Chris@16
|
788 p_u[j] = static_cast<boost::uint32_t>(static_cast<boost::uint32_t>(t) % static_cast<boost::uint32_t>(cpp_dec_float_elem_mask));
|
Chris@16
|
789 }
|
Chris@16
|
790
|
Chris@16
|
791 if(b_copy)
|
Chris@16
|
792 {
|
Chris@16
|
793 data = n_data;
|
Chris@101
|
794 exp = v.exp;
|
Chris@101
|
795 neg = v.neg;
|
Chris@16
|
796 }
|
Chris@16
|
797
|
Chris@16
|
798 // Is it necessary to justify the data?
|
Chris@16
|
799 const typename array_type::const_iterator first_nonzero_elem = std::find_if(data.begin(), data.end(), data_elem_is_non_zero_predicate);
|
Chris@16
|
800
|
Chris@16
|
801 if(first_nonzero_elem != data.begin())
|
Chris@16
|
802 {
|
Chris@16
|
803 if(first_nonzero_elem == data.end())
|
Chris@16
|
804 {
|
Chris@16
|
805 // This result of the subtraction is exactly zero.
|
Chris@16
|
806 // Reset the sign and the exponent.
|
Chris@16
|
807 neg = false;
|
Chris@16
|
808 exp = static_cast<ExponentType>(0);
|
Chris@16
|
809 }
|
Chris@16
|
810 else
|
Chris@16
|
811 {
|
Chris@16
|
812 // Justify the data
|
Chris@16
|
813 const std::size_t sj = static_cast<std::size_t>(std::distance<typename array_type::const_iterator>(data.begin(), first_nonzero_elem));
|
Chris@16
|
814
|
Chris@16
|
815 std::copy(data.begin() + static_cast<std::size_t>(sj), data.end(), data.begin());
|
Chris@16
|
816 std::fill(data.end() - sj, data.end(), static_cast<boost::uint32_t>(0u));
|
Chris@16
|
817
|
Chris@16
|
818 exp -= static_cast<ExponentType>(sj * static_cast<std::size_t>(cpp_dec_float_elem_digits10));
|
Chris@16
|
819 }
|
Chris@16
|
820 }
|
Chris@16
|
821 }
|
Chris@16
|
822
|
Chris@101
|
823 // Handle underflow.
|
Chris@101
|
824 if(iszero())
|
Chris@101
|
825 return (*this = zero());
|
Chris@101
|
826
|
Chris@101
|
827 // Check for potential overflow.
|
Chris@101
|
828 const bool b_result_might_overflow = (exp >= static_cast<ExponentType>(cpp_dec_float_max_exp10));
|
Chris@101
|
829
|
Chris@101
|
830 // Handle overflow.
|
Chris@101
|
831 if(b_result_might_overflow)
|
Chris@16
|
832 {
|
Chris@16
|
833 const bool b_result_is_neg = neg;
|
Chris@101
|
834 neg = false;
|
Chris@101
|
835
|
Chris@101
|
836 if(compare((cpp_dec_float::max)()) > 0)
|
Chris@101
|
837 *this = inf();
|
Chris@101
|
838
|
Chris@101
|
839 neg = b_result_is_neg;
|
Chris@16
|
840 }
|
Chris@16
|
841
|
Chris@16
|
842 return *this;
|
Chris@16
|
843 }
|
Chris@16
|
844
|
Chris@16
|
845 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
846 cpp_dec_float<Digits10, ExponentType, Allocator>& cpp_dec_float<Digits10, ExponentType, Allocator>::operator-=(const cpp_dec_float<Digits10, ExponentType, Allocator>& v)
|
Chris@16
|
847 {
|
Chris@16
|
848 // Use *this - v = -(-*this + v).
|
Chris@16
|
849 negate();
|
Chris@16
|
850 *this += v;
|
Chris@16
|
851 negate();
|
Chris@16
|
852 return *this;
|
Chris@16
|
853 }
|
Chris@16
|
854
|
Chris@16
|
855 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
856 cpp_dec_float<Digits10, ExponentType, Allocator>& cpp_dec_float<Digits10, ExponentType, Allocator>::operator*=(const cpp_dec_float<Digits10, ExponentType, Allocator>& v)
|
Chris@16
|
857 {
|
Chris@16
|
858 // Evaluate the sign of the result.
|
Chris@16
|
859 const bool b_result_is_neg = (neg != v.neg);
|
Chris@16
|
860
|
Chris@16
|
861 // Artificially set the sign of the result to be positive.
|
Chris@16
|
862 neg = false;
|
Chris@16
|
863
|
Chris@16
|
864 // Handle special cases like zero, inf and NaN.
|
Chris@101
|
865 const bool b_u_is_inf = (isinf)();
|
Chris@16
|
866 const bool b_v_is_inf = (v.isinf)();
|
Chris@101
|
867 const bool b_u_is_zero = iszero();
|
Chris@16
|
868 const bool b_v_is_zero = v.iszero();
|
Chris@16
|
869
|
Chris@16
|
870 if( ((isnan)() || (v.isnan)())
|
Chris@16
|
871 || (b_u_is_inf && b_v_is_zero)
|
Chris@16
|
872 || (b_v_is_inf && b_u_is_zero)
|
Chris@16
|
873 )
|
Chris@16
|
874 {
|
Chris@16
|
875 *this = nan();
|
Chris@16
|
876 return *this;
|
Chris@16
|
877 }
|
Chris@16
|
878
|
Chris@16
|
879 if(b_u_is_inf || b_v_is_inf)
|
Chris@16
|
880 {
|
Chris@16
|
881 *this = inf();
|
Chris@16
|
882 if(b_result_is_neg)
|
Chris@16
|
883 negate();
|
Chris@16
|
884 return *this;
|
Chris@16
|
885 }
|
Chris@16
|
886
|
Chris@16
|
887 if(b_u_is_zero || b_v_is_zero)
|
Chris@16
|
888 {
|
Chris@16
|
889 return *this = zero();
|
Chris@16
|
890 }
|
Chris@16
|
891
|
Chris@101
|
892 // Check for potential overflow or underflow.
|
Chris@101
|
893 const bool b_result_might_overflow = ((exp + v.exp) >= static_cast<ExponentType>(cpp_dec_float_max_exp10));
|
Chris@101
|
894 const bool b_result_might_underflow = ((exp + v.exp) <= static_cast<ExponentType>(cpp_dec_float_min_exp10));
|
Chris@16
|
895
|
Chris@16
|
896 // Set the exponent of the result.
|
Chris@16
|
897 exp += v.exp;
|
Chris@16
|
898
|
Chris@16
|
899 const boost::int32_t prec_mul = (std::min)(prec_elem, v.prec_elem);
|
Chris@16
|
900
|
Chris@16
|
901 const boost::uint32_t carry = mul_loop_uv(data.data(), v.data.data(), prec_mul);
|
Chris@16
|
902
|
Chris@16
|
903 // Handle a potential carry.
|
Chris@16
|
904 if(carry != static_cast<boost::uint32_t>(0u))
|
Chris@16
|
905 {
|
Chris@16
|
906 exp += cpp_dec_float_elem_digits10;
|
Chris@16
|
907
|
Chris@16
|
908 // Shift the result of the multiplication one element to the right...
|
Chris@16
|
909 std::copy_backward(data.begin(),
|
Chris@16
|
910 data.begin() + static_cast<std::size_t>(prec_elem - static_cast<boost::int32_t>(1)),
|
Chris@16
|
911 data.begin() + static_cast<std::size_t>(prec_elem));
|
Chris@16
|
912
|
Chris@16
|
913 // ... And insert the carry.
|
Chris@16
|
914 data.front() = carry;
|
Chris@16
|
915 }
|
Chris@16
|
916
|
Chris@101
|
917 // Handle overflow.
|
Chris@101
|
918 if(b_result_might_overflow && (compare((cpp_dec_float::max)()) > 0))
|
Chris@101
|
919 {
|
Chris@101
|
920 *this = inf();
|
Chris@101
|
921 }
|
Chris@101
|
922
|
Chris@101
|
923 // Handle underflow.
|
Chris@101
|
924 if(b_result_might_underflow && (compare((cpp_dec_float::min)()) < 0))
|
Chris@101
|
925 {
|
Chris@101
|
926 *this = zero();
|
Chris@101
|
927
|
Chris@101
|
928 return *this;
|
Chris@101
|
929 }
|
Chris@101
|
930
|
Chris@16
|
931 // Set the sign of the result.
|
Chris@16
|
932 neg = b_result_is_neg;
|
Chris@16
|
933
|
Chris@16
|
934 return *this;
|
Chris@16
|
935 }
|
Chris@16
|
936
|
Chris@16
|
937 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
938 cpp_dec_float<Digits10, ExponentType, Allocator>& cpp_dec_float<Digits10, ExponentType, Allocator>::operator/=(const cpp_dec_float<Digits10, ExponentType, Allocator>& v)
|
Chris@16
|
939 {
|
Chris@101
|
940 const bool u_and_v_are_finite_and_identical = ( (isfinite)()
|
Chris@16
|
941 && (fpclass == v.fpclass)
|
Chris@101
|
942 && (exp == v.exp)
|
Chris@16
|
943 && (cmp_data(v.data) == static_cast<boost::int32_t>(0)));
|
Chris@16
|
944
|
Chris@16
|
945 if(u_and_v_are_finite_and_identical)
|
Chris@16
|
946 {
|
Chris@16
|
947 if(neg != v.neg)
|
Chris@16
|
948 {
|
Chris@16
|
949 *this = one();
|
Chris@16
|
950 negate();
|
Chris@16
|
951 }
|
Chris@16
|
952 else
|
Chris@16
|
953 *this = one();
|
Chris@16
|
954 return *this;
|
Chris@16
|
955 }
|
Chris@16
|
956 else
|
Chris@16
|
957 {
|
Chris@16
|
958 if(iszero())
|
Chris@16
|
959 {
|
Chris@16
|
960 if((v.isnan)() || v.iszero())
|
Chris@16
|
961 {
|
Chris@16
|
962 return *this = v;
|
Chris@16
|
963 }
|
Chris@16
|
964 return *this;
|
Chris@16
|
965 }
|
Chris@16
|
966 cpp_dec_float t(v);
|
Chris@16
|
967 t.calculate_inv();
|
Chris@16
|
968 return operator*=(t);
|
Chris@16
|
969 }
|
Chris@16
|
970 }
|
Chris@16
|
971
|
Chris@16
|
972 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
973 cpp_dec_float<Digits10, ExponentType, Allocator>& cpp_dec_float<Digits10, ExponentType, Allocator>::mul_unsigned_long_long(const unsigned long long n)
|
Chris@16
|
974 {
|
Chris@16
|
975 // Multiply *this with a constant unsigned long long.
|
Chris@16
|
976
|
Chris@16
|
977 // Evaluate the sign of the result.
|
Chris@16
|
978 const bool b_neg = neg;
|
Chris@16
|
979
|
Chris@16
|
980 // Artificially set the sign of the result to be positive.
|
Chris@16
|
981 neg = false;
|
Chris@16
|
982
|
Chris@16
|
983 // Handle special cases like zero, inf and NaN.
|
Chris@101
|
984 const bool b_u_is_inf = (isinf)();
|
Chris@16
|
985 const bool b_n_is_zero = (n == static_cast<boost::int32_t>(0));
|
Chris@16
|
986
|
Chris@16
|
987 if((isnan)() || (b_u_is_inf && b_n_is_zero))
|
Chris@16
|
988 {
|
Chris@16
|
989 return (*this = nan());
|
Chris@16
|
990 }
|
Chris@16
|
991
|
Chris@16
|
992 if(b_u_is_inf)
|
Chris@16
|
993 {
|
Chris@16
|
994 *this = inf();
|
Chris@16
|
995 if(b_neg)
|
Chris@16
|
996 negate();
|
Chris@16
|
997 return *this;
|
Chris@16
|
998 }
|
Chris@16
|
999
|
Chris@16
|
1000 if(iszero() || b_n_is_zero)
|
Chris@16
|
1001 {
|
Chris@16
|
1002 // Multiplication by zero.
|
Chris@16
|
1003 return *this = zero();
|
Chris@16
|
1004 }
|
Chris@16
|
1005
|
Chris@16
|
1006 if(n >= static_cast<unsigned long long>(cpp_dec_float_elem_mask))
|
Chris@16
|
1007 {
|
Chris@16
|
1008 neg = b_neg;
|
Chris@16
|
1009 cpp_dec_float t;
|
Chris@16
|
1010 t = n;
|
Chris@16
|
1011 return operator*=(t);
|
Chris@16
|
1012 }
|
Chris@16
|
1013
|
Chris@16
|
1014 if(n == static_cast<unsigned long long>(1u))
|
Chris@16
|
1015 {
|
Chris@16
|
1016 neg = b_neg;
|
Chris@16
|
1017 return *this;
|
Chris@16
|
1018 }
|
Chris@16
|
1019
|
Chris@16
|
1020 // Set up the multiplication loop.
|
Chris@16
|
1021 const boost::uint32_t nn = static_cast<boost::uint32_t>(n);
|
Chris@16
|
1022 const boost::uint32_t carry = mul_loop_n(data.data(), nn, prec_elem);
|
Chris@16
|
1023
|
Chris@16
|
1024 // Handle the carry and adjust the exponent.
|
Chris@16
|
1025 if(carry != static_cast<boost::uint32_t>(0u))
|
Chris@16
|
1026 {
|
Chris@16
|
1027 exp += static_cast<ExponentType>(cpp_dec_float_elem_digits10);
|
Chris@16
|
1028
|
Chris@16
|
1029 // Shift the result of the multiplication one element to the right.
|
Chris@16
|
1030 std::copy_backward(data.begin(),
|
Chris@16
|
1031 data.begin() + static_cast<std::size_t>(prec_elem - static_cast<boost::int32_t>(1)),
|
Chris@16
|
1032 data.begin() + static_cast<std::size_t>(prec_elem));
|
Chris@16
|
1033
|
Chris@16
|
1034 data.front() = static_cast<boost::uint32_t>(carry);
|
Chris@16
|
1035 }
|
Chris@16
|
1036
|
Chris@101
|
1037 // Check for potential overflow.
|
Chris@101
|
1038 const bool b_result_might_overflow = (exp >= cpp_dec_float_max_exp10);
|
Chris@101
|
1039
|
Chris@101
|
1040 // Handle overflow.
|
Chris@101
|
1041 if(b_result_might_overflow && (compare((cpp_dec_float::max)()) > 0))
|
Chris@16
|
1042 {
|
Chris@16
|
1043 *this = inf();
|
Chris@16
|
1044 }
|
Chris@16
|
1045
|
Chris@16
|
1046 // Set the sign.
|
Chris@16
|
1047 neg = b_neg;
|
Chris@16
|
1048
|
Chris@16
|
1049 return *this;
|
Chris@16
|
1050 }
|
Chris@16
|
1051
|
Chris@16
|
1052 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
1053 cpp_dec_float<Digits10, ExponentType, Allocator>& cpp_dec_float<Digits10, ExponentType, Allocator>::div_unsigned_long_long(const unsigned long long n)
|
Chris@16
|
1054 {
|
Chris@16
|
1055 // Divide *this by a constant unsigned long long.
|
Chris@16
|
1056
|
Chris@16
|
1057 // Evaluate the sign of the result.
|
Chris@16
|
1058 const bool b_neg = neg;
|
Chris@16
|
1059
|
Chris@16
|
1060 // Artificially set the sign of the result to be positive.
|
Chris@16
|
1061 neg = false;
|
Chris@16
|
1062
|
Chris@16
|
1063 // Handle special cases like zero, inf and NaN.
|
Chris@16
|
1064 if((isnan)())
|
Chris@16
|
1065 {
|
Chris@16
|
1066 return *this;
|
Chris@16
|
1067 }
|
Chris@16
|
1068
|
Chris@16
|
1069 if((isinf)())
|
Chris@16
|
1070 {
|
Chris@16
|
1071 *this = inf();
|
Chris@16
|
1072 if(b_neg)
|
Chris@16
|
1073 negate();
|
Chris@16
|
1074 return *this;
|
Chris@16
|
1075 }
|
Chris@16
|
1076
|
Chris@16
|
1077 if(n == static_cast<unsigned long long>(0u))
|
Chris@16
|
1078 {
|
Chris@16
|
1079 // Divide by 0.
|
Chris@16
|
1080 if(iszero())
|
Chris@16
|
1081 {
|
Chris@16
|
1082 *this = nan();
|
Chris@16
|
1083 return *this;
|
Chris@16
|
1084 }
|
Chris@16
|
1085 else
|
Chris@16
|
1086 {
|
Chris@16
|
1087 *this = inf();
|
Chris@16
|
1088 if(isneg())
|
Chris@16
|
1089 negate();
|
Chris@16
|
1090 return *this;
|
Chris@16
|
1091 }
|
Chris@16
|
1092 }
|
Chris@16
|
1093
|
Chris@16
|
1094 if(iszero())
|
Chris@16
|
1095 {
|
Chris@16
|
1096 return *this;
|
Chris@16
|
1097 }
|
Chris@16
|
1098
|
Chris@16
|
1099 if(n >= static_cast<unsigned long long>(cpp_dec_float_elem_mask))
|
Chris@16
|
1100 {
|
Chris@16
|
1101 neg = b_neg;
|
Chris@16
|
1102 cpp_dec_float t;
|
Chris@16
|
1103 t = n;
|
Chris@16
|
1104 return operator/=(t);
|
Chris@16
|
1105 }
|
Chris@16
|
1106
|
Chris@16
|
1107 const boost::uint32_t nn = static_cast<boost::uint32_t>(n);
|
Chris@16
|
1108
|
Chris@16
|
1109 if(nn > static_cast<boost::uint32_t>(1u))
|
Chris@16
|
1110 {
|
Chris@16
|
1111 // Do the division loop.
|
Chris@16
|
1112 const boost::uint32_t prev = div_loop_n(data.data(), nn, prec_elem);
|
Chris@16
|
1113
|
Chris@16
|
1114 // Determine if one leading zero is in the result data.
|
Chris@16
|
1115 if(data[0] == static_cast<boost::uint32_t>(0u))
|
Chris@16
|
1116 {
|
Chris@16
|
1117 // Adjust the exponent
|
Chris@16
|
1118 exp -= static_cast<ExponentType>(cpp_dec_float_elem_digits10);
|
Chris@16
|
1119
|
Chris@16
|
1120 // Shift result of the division one element to the left.
|
Chris@16
|
1121 std::copy(data.begin() + static_cast<std::size_t>(1u),
|
Chris@16
|
1122 data.begin() + static_cast<std::size_t>(prec_elem - static_cast<boost::int32_t>(1)),
|
Chris@16
|
1123 data.begin());
|
Chris@16
|
1124
|
Chris@16
|
1125 data[prec_elem - static_cast<boost::int32_t>(1)] = static_cast<boost::uint32_t>(static_cast<boost::uint64_t>(prev * static_cast<boost::uint64_t>(cpp_dec_float_elem_mask)) / nn);
|
Chris@16
|
1126 }
|
Chris@16
|
1127 }
|
Chris@16
|
1128
|
Chris@101
|
1129 // Check for potential underflow.
|
Chris@101
|
1130 const bool b_result_might_underflow = (exp <= cpp_dec_float_min_exp10);
|
Chris@101
|
1131
|
Chris@101
|
1132 // Handle underflow.
|
Chris@101
|
1133 if(b_result_might_underflow && (compare((cpp_dec_float::min)()) < 0))
|
Chris@101
|
1134 return (*this = zero());
|
Chris@16
|
1135
|
Chris@16
|
1136 // Set the sign of the result.
|
Chris@16
|
1137 neg = b_neg;
|
Chris@16
|
1138
|
Chris@101
|
1139 return *this;
|
Chris@16
|
1140 }
|
Chris@16
|
1141
|
Chris@16
|
1142 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
1143 cpp_dec_float<Digits10, ExponentType, Allocator>& cpp_dec_float<Digits10, ExponentType, Allocator>::calculate_inv()
|
Chris@16
|
1144 {
|
Chris@16
|
1145 // Compute the inverse of *this.
|
Chris@16
|
1146 const bool b_neg = neg;
|
Chris@16
|
1147
|
Chris@16
|
1148 neg = false;
|
Chris@16
|
1149
|
Chris@16
|
1150 // Handle special cases like zero, inf and NaN.
|
Chris@16
|
1151 if(iszero())
|
Chris@16
|
1152 {
|
Chris@16
|
1153 *this = inf();
|
Chris@16
|
1154 if(b_neg)
|
Chris@16
|
1155 negate();
|
Chris@16
|
1156 return *this;
|
Chris@16
|
1157 }
|
Chris@16
|
1158
|
Chris@16
|
1159 if((isnan)())
|
Chris@16
|
1160 {
|
Chris@16
|
1161 return *this;
|
Chris@16
|
1162 }
|
Chris@16
|
1163
|
Chris@16
|
1164 if((isinf)())
|
Chris@16
|
1165 {
|
Chris@16
|
1166 return *this = zero();
|
Chris@16
|
1167 }
|
Chris@16
|
1168
|
Chris@16
|
1169 if(isone())
|
Chris@16
|
1170 {
|
Chris@16
|
1171 if(b_neg)
|
Chris@16
|
1172 negate();
|
Chris@16
|
1173 return *this;
|
Chris@16
|
1174 }
|
Chris@16
|
1175
|
Chris@16
|
1176 // Save the original *this.
|
Chris@16
|
1177 cpp_dec_float<Digits10, ExponentType, Allocator> x(*this);
|
Chris@16
|
1178
|
Chris@16
|
1179 // Generate the initial estimate using division.
|
Chris@16
|
1180 // Extract the mantissa and exponent for a "manual"
|
Chris@16
|
1181 // computation of the estimate.
|
Chris@16
|
1182 double dd;
|
Chris@101
|
1183 ExponentType ne;
|
Chris@16
|
1184 x.extract_parts(dd, ne);
|
Chris@16
|
1185
|
Chris@16
|
1186 // Do the inverse estimate using double precision estimates of mantissa and exponent.
|
Chris@16
|
1187 operator=(cpp_dec_float<Digits10, ExponentType, Allocator>(1.0 / dd, -ne));
|
Chris@16
|
1188
|
Chris@16
|
1189 // Compute the inverse of *this. Quadratically convergent Newton-Raphson iteration
|
Chris@16
|
1190 // is used. During the iterative steps, the precision of the calculation is limited
|
Chris@16
|
1191 // to the minimum required in order to minimize the run-time.
|
Chris@16
|
1192
|
Chris@16
|
1193 static const boost::int32_t double_digits10_minus_a_few = std::numeric_limits<double>::digits10 - 3;
|
Chris@16
|
1194
|
Chris@16
|
1195 for(boost::int32_t digits = double_digits10_minus_a_few; digits <= cpp_dec_float_total_digits10; digits *= static_cast<boost::int32_t>(2))
|
Chris@16
|
1196 {
|
Chris@16
|
1197 // Adjust precision of the terms.
|
Chris@16
|
1198 precision(static_cast<boost::int32_t>((digits + 10) * static_cast<boost::int32_t>(2)));
|
Chris@16
|
1199 x.precision(static_cast<boost::int32_t>((digits + 10) * static_cast<boost::int32_t>(2)));
|
Chris@16
|
1200
|
Chris@16
|
1201 // Next iteration.
|
Chris@16
|
1202 cpp_dec_float t(*this);
|
Chris@16
|
1203 t *= x;
|
Chris@16
|
1204 t -= two();
|
Chris@16
|
1205 t.negate();
|
Chris@16
|
1206 *this *= t;
|
Chris@16
|
1207 }
|
Chris@16
|
1208
|
Chris@16
|
1209 neg = b_neg;
|
Chris@16
|
1210
|
Chris@16
|
1211 prec_elem = cpp_dec_float_elem_number;
|
Chris@16
|
1212
|
Chris@16
|
1213 return *this;
|
Chris@16
|
1214 }
|
Chris@16
|
1215
|
Chris@16
|
1216 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
1217 cpp_dec_float<Digits10, ExponentType, Allocator>& cpp_dec_float<Digits10, ExponentType, Allocator>::calculate_sqrt()
|
Chris@16
|
1218 {
|
Chris@16
|
1219 // Compute the square root of *this.
|
Chris@16
|
1220
|
Chris@16
|
1221 if(isneg() || (!(isfinite)()))
|
Chris@16
|
1222 {
|
Chris@16
|
1223 *this = nan();
|
Chris@16
|
1224 return *this;
|
Chris@16
|
1225 }
|
Chris@16
|
1226
|
Chris@16
|
1227 if(iszero() || isone())
|
Chris@16
|
1228 {
|
Chris@16
|
1229 return *this;
|
Chris@16
|
1230 }
|
Chris@16
|
1231
|
Chris@16
|
1232 // Save the original *this.
|
Chris@16
|
1233 cpp_dec_float<Digits10, ExponentType, Allocator> x(*this);
|
Chris@16
|
1234
|
Chris@16
|
1235 // Generate the initial estimate using division.
|
Chris@16
|
1236 // Extract the mantissa and exponent for a "manual"
|
Chris@16
|
1237 // computation of the estimate.
|
Chris@16
|
1238 double dd;
|
Chris@101
|
1239 ExponentType ne;
|
Chris@16
|
1240 extract_parts(dd, ne);
|
Chris@16
|
1241
|
Chris@16
|
1242 // Force the exponent to be an even multiple of two.
|
Chris@16
|
1243 if((ne % static_cast<ExponentType>(2)) != static_cast<ExponentType>(0))
|
Chris@16
|
1244 {
|
Chris@16
|
1245 ++ne;
|
Chris@16
|
1246 dd /= 10.0;
|
Chris@16
|
1247 }
|
Chris@16
|
1248
|
Chris@16
|
1249 // Setup the iteration.
|
Chris@16
|
1250 // Estimate the square root using simple manipulations.
|
Chris@16
|
1251 const double sqd = std::sqrt(dd);
|
Chris@16
|
1252
|
Chris@16
|
1253 *this = cpp_dec_float<Digits10, ExponentType, Allocator>(sqd, static_cast<ExponentType>(ne / static_cast<ExponentType>(2)));
|
Chris@16
|
1254
|
Chris@16
|
1255 // Estimate 1.0 / (2.0 * x0) using simple manipulations.
|
Chris@16
|
1256 cpp_dec_float<Digits10, ExponentType, Allocator> vi(0.5 / sqd, static_cast<ExponentType>(-ne / static_cast<ExponentType>(2)));
|
Chris@16
|
1257
|
Chris@16
|
1258 // Compute the square root of x. Coupled Newton iteration
|
Chris@16
|
1259 // as described in "Pi Unleashed" is used. During the
|
Chris@16
|
1260 // iterative steps, the precision of the calculation is
|
Chris@16
|
1261 // limited to the minimum required in order to minimize
|
Chris@16
|
1262 // the run-time.
|
Chris@16
|
1263 //
|
Chris@16
|
1264 // Book references:
|
Chris@16
|
1265 // http://www.jjj.de/pibook/pibook.html
|
Chris@16
|
1266 // http://www.amazon.com/exec/obidos/tg/detail/-/3540665722/qid=1035535482/sr=8-7/ref=sr_8_7/104-3357872-6059916?v=glance&n=507846
|
Chris@16
|
1267
|
Chris@16
|
1268 static const boost::uint32_t double_digits10_minus_a_few = std::numeric_limits<double>::digits10 - 3;
|
Chris@16
|
1269
|
Chris@16
|
1270 for(boost::int32_t digits = double_digits10_minus_a_few; digits <= cpp_dec_float_total_digits10; digits *= 2u)
|
Chris@16
|
1271 {
|
Chris@16
|
1272 // Adjust precision of the terms.
|
Chris@16
|
1273 precision((digits + 10) * 2);
|
Chris@16
|
1274 vi.precision((digits + 10) * 2);
|
Chris@16
|
1275
|
Chris@16
|
1276 // Next iteration of vi
|
Chris@16
|
1277 cpp_dec_float t(*this);
|
Chris@16
|
1278 t *= vi;
|
Chris@16
|
1279 t.negate();
|
Chris@16
|
1280 t.mul_unsigned_long_long(2u);
|
Chris@16
|
1281 t += one();
|
Chris@16
|
1282 t *= vi;
|
Chris@16
|
1283 vi += t;
|
Chris@16
|
1284
|
Chris@16
|
1285 // Next iteration of *this
|
Chris@16
|
1286 t = *this;
|
Chris@16
|
1287 t *= *this;
|
Chris@16
|
1288 t.negate();
|
Chris@16
|
1289 t += x;
|
Chris@16
|
1290 t *= vi;
|
Chris@16
|
1291 *this += t;
|
Chris@16
|
1292 }
|
Chris@16
|
1293
|
Chris@16
|
1294 prec_elem = cpp_dec_float_elem_number;
|
Chris@16
|
1295
|
Chris@16
|
1296 return *this;
|
Chris@16
|
1297 }
|
Chris@16
|
1298
|
Chris@16
|
1299 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
1300 int cpp_dec_float<Digits10, ExponentType, Allocator>::cmp_data(const array_type& vd) const
|
Chris@16
|
1301 {
|
Chris@16
|
1302 // Compare the data of *this with those of v.
|
Chris@101
|
1303 // Return +1 for *this > v
|
Chris@101
|
1304 // 0 for *this = v
|
Chris@101
|
1305 // -1 for *this < v
|
Chris@16
|
1306
|
Chris@16
|
1307 const std::pair<typename array_type::const_iterator, typename array_type::const_iterator> mismatch_pair = std::mismatch(data.begin(), data.end(), vd.begin());
|
Chris@16
|
1308
|
Chris@16
|
1309 const bool is_equal = ((mismatch_pair.first == data.end()) && (mismatch_pair.second == vd.end()));
|
Chris@16
|
1310
|
Chris@16
|
1311 if(is_equal)
|
Chris@16
|
1312 {
|
Chris@16
|
1313 return 0;
|
Chris@16
|
1314 }
|
Chris@16
|
1315 else
|
Chris@16
|
1316 {
|
Chris@16
|
1317 return ((*mismatch_pair.first > *mismatch_pair.second) ? 1 : -1);
|
Chris@16
|
1318 }
|
Chris@16
|
1319 }
|
Chris@16
|
1320
|
Chris@16
|
1321 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
1322 int cpp_dec_float<Digits10, ExponentType, Allocator>::compare(const cpp_dec_float& v) const
|
Chris@16
|
1323 {
|
Chris@16
|
1324 // Compare v with *this.
|
Chris@101
|
1325 // Return +1 for *this > v
|
Chris@101
|
1326 // 0 for *this = v
|
Chris@101
|
1327 // -1 for *this < v
|
Chris@16
|
1328
|
Chris@16
|
1329 // Handle all non-finite cases.
|
Chris@16
|
1330 if((!(isfinite)()) || (!(v.isfinite)()))
|
Chris@16
|
1331 {
|
Chris@16
|
1332 // NaN can never equal NaN. Return an implementation-dependent
|
Chris@16
|
1333 // signed result. Also note that comparison of NaN with NaN
|
Chris@16
|
1334 // using operators greater-than or less-than is undefined.
|
Chris@16
|
1335 if((isnan)() || (v.isnan)()) { return ((isnan)() ? 1 : -1); }
|
Chris@16
|
1336
|
Chris@16
|
1337 if((isinf)() && (v.isinf)())
|
Chris@16
|
1338 {
|
Chris@16
|
1339 // Both *this and v are infinite. They are equal if they have the same sign.
|
Chris@16
|
1340 // Otherwise, *this is less than v if and only if *this is negative.
|
Chris@16
|
1341 return ((neg == v.neg) ? 0 : (neg ? -1 : 1));
|
Chris@16
|
1342 }
|
Chris@16
|
1343
|
Chris@16
|
1344 if((isinf)())
|
Chris@16
|
1345 {
|
Chris@16
|
1346 // *this is infinite, but v is finite.
|
Chris@16
|
1347 // So negative infinite *this is less than any finite v.
|
Chris@16
|
1348 // Whereas positive infinite *this is greater than any finite v.
|
Chris@16
|
1349 return (isneg() ? -1 : 1);
|
Chris@16
|
1350 }
|
Chris@16
|
1351 else
|
Chris@16
|
1352 {
|
Chris@16
|
1353 // *this is finite, and v is infinite.
|
Chris@16
|
1354 // So any finite *this is greater than negative infinite v.
|
Chris@16
|
1355 // Whereas any finite *this is less than positive infinite v.
|
Chris@16
|
1356 return (v.neg ? 1 : -1);
|
Chris@16
|
1357 }
|
Chris@16
|
1358 }
|
Chris@16
|
1359
|
Chris@16
|
1360 // And now handle all *finite* cases.
|
Chris@16
|
1361 if(iszero())
|
Chris@16
|
1362 {
|
Chris@16
|
1363 // The value of *this is zero and v is either zero or non-zero.
|
Chris@16
|
1364 return (v.iszero() ? 0
|
Chris@16
|
1365 : (v.neg ? 1 : -1));
|
Chris@16
|
1366 }
|
Chris@16
|
1367 else if(v.iszero())
|
Chris@16
|
1368 {
|
Chris@16
|
1369 // The value of v is zero and *this is non-zero.
|
Chris@16
|
1370 return (neg ? -1 : 1);
|
Chris@16
|
1371 }
|
Chris@16
|
1372 else
|
Chris@16
|
1373 {
|
Chris@16
|
1374 // Both *this and v are non-zero.
|
Chris@16
|
1375
|
Chris@16
|
1376 if(neg != v.neg)
|
Chris@16
|
1377 {
|
Chris@16
|
1378 // The signs are different.
|
Chris@16
|
1379 return (neg ? -1 : 1);
|
Chris@16
|
1380 }
|
Chris@16
|
1381 else if(exp != v.exp)
|
Chris@16
|
1382 {
|
Chris@16
|
1383 // The signs are the same and the exponents are different.
|
Chris@16
|
1384 const int val_cexpression = ((exp < v.exp) ? 1 : -1);
|
Chris@16
|
1385
|
Chris@16
|
1386 return (neg ? val_cexpression : -val_cexpression);
|
Chris@16
|
1387 }
|
Chris@16
|
1388 else
|
Chris@16
|
1389 {
|
Chris@16
|
1390 // The signs are the same and the exponents are the same.
|
Chris@16
|
1391 // Compare the data.
|
Chris@16
|
1392 const int val_cmp_data = cmp_data(v.data);
|
Chris@16
|
1393
|
Chris@16
|
1394 return ((!neg) ? val_cmp_data : -val_cmp_data);
|
Chris@16
|
1395 }
|
Chris@16
|
1396 }
|
Chris@16
|
1397 }
|
Chris@16
|
1398
|
Chris@16
|
1399 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
1400 bool cpp_dec_float<Digits10, ExponentType, Allocator>::isone() const
|
Chris@16
|
1401 {
|
Chris@16
|
1402 // Check if the value of *this is identically 1 or very close to 1.
|
Chris@16
|
1403
|
Chris@16
|
1404 const bool not_negative_and_is_finite = ((!neg) && (isfinite)());
|
Chris@16
|
1405
|
Chris@16
|
1406 if(not_negative_and_is_finite)
|
Chris@16
|
1407 {
|
Chris@16
|
1408 if((data[0u] == static_cast<boost::uint32_t>(1u)) && (exp == static_cast<ExponentType>(0)))
|
Chris@16
|
1409 {
|
Chris@16
|
1410 const typename array_type::const_iterator it_non_zero = std::find_if(data.begin(), data.end(), data_elem_is_non_zero_predicate);
|
Chris@16
|
1411 return (it_non_zero == data.end());
|
Chris@16
|
1412 }
|
Chris@16
|
1413 else if((data[0u] == static_cast<boost::uint32_t>(cpp_dec_float_elem_mask - 1)) && (exp == static_cast<ExponentType>(-cpp_dec_float_elem_digits10)))
|
Chris@16
|
1414 {
|
Chris@16
|
1415 const typename array_type::const_iterator it_non_nine = std::find_if(data.begin(), data.end(), data_elem_is_non_nine_predicate);
|
Chris@16
|
1416 return (it_non_nine == data.end());
|
Chris@16
|
1417 }
|
Chris@16
|
1418 }
|
Chris@16
|
1419
|
Chris@16
|
1420 return false;
|
Chris@16
|
1421 }
|
Chris@16
|
1422
|
Chris@16
|
1423 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
1424 bool cpp_dec_float<Digits10, ExponentType, Allocator>::isint() const
|
Chris@16
|
1425 {
|
Chris@16
|
1426 if(fpclass != cpp_dec_float_finite) { return false; }
|
Chris@16
|
1427
|
Chris@16
|
1428 if(iszero()) { return true; }
|
Chris@16
|
1429
|
Chris@16
|
1430 if(exp < static_cast<ExponentType>(0)) { return false; } // |*this| < 1.
|
Chris@16
|
1431
|
Chris@16
|
1432 const typename array_type::size_type offset_decimal_part = static_cast<typename array_type::size_type>(exp / cpp_dec_float_elem_digits10) + 1u;
|
Chris@16
|
1433
|
Chris@16
|
1434 if(offset_decimal_part >= static_cast<typename array_type::size_type>(cpp_dec_float_elem_number))
|
Chris@16
|
1435 {
|
Chris@16
|
1436 // The number is too large to resolve the integer part.
|
Chris@16
|
1437 // It considered to be a pure integer.
|
Chris@16
|
1438 return true;
|
Chris@16
|
1439 }
|
Chris@16
|
1440
|
Chris@16
|
1441 typename array_type::const_iterator it_non_zero = std::find_if(data.begin() + offset_decimal_part, data.end(), data_elem_is_non_zero_predicate);
|
Chris@16
|
1442
|
Chris@16
|
1443 return (it_non_zero == data.end());
|
Chris@16
|
1444 }
|
Chris@16
|
1445
|
Chris@16
|
1446 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
1447 void cpp_dec_float<Digits10, ExponentType, Allocator>::extract_parts(double& mantissa, ExponentType& exponent) const
|
Chris@16
|
1448 {
|
Chris@16
|
1449 // Extract the approximate parts mantissa and base-10 exponent from the input cpp_dec_float<Digits10, ExponentType, Allocator> value x.
|
Chris@16
|
1450
|
Chris@16
|
1451 // Extracts the mantissa and exponent.
|
Chris@16
|
1452 exponent = exp;
|
Chris@16
|
1453
|
Chris@101
|
1454 boost::uint32_t p10 = static_cast<boost::uint32_t>(1u);
|
Chris@16
|
1455 boost::uint32_t test = data[0u];
|
Chris@16
|
1456
|
Chris@16
|
1457 for(;;)
|
Chris@16
|
1458 {
|
Chris@16
|
1459 test /= static_cast<boost::uint32_t>(10u);
|
Chris@16
|
1460
|
Chris@16
|
1461 if(test == static_cast<boost::uint32_t>(0u))
|
Chris@16
|
1462 {
|
Chris@16
|
1463 break;
|
Chris@16
|
1464 }
|
Chris@16
|
1465
|
Chris@16
|
1466 p10 *= static_cast<boost::uint32_t>(10u);
|
Chris@16
|
1467 ++exponent;
|
Chris@16
|
1468 }
|
Chris@16
|
1469
|
Chris@16
|
1470 // Establish the upper bound of limbs for extracting the double.
|
Chris@101
|
1471 const int max_elem_in_double_count = static_cast<int>(static_cast<boost::int32_t>(std::numeric_limits<double>::digits10) / cpp_dec_float_elem_digits10)
|
Chris@16
|
1472 + (static_cast<int>(static_cast<boost::int32_t>(std::numeric_limits<double>::digits10) % cpp_dec_float_elem_digits10) != 0 ? 1 : 0)
|
Chris@16
|
1473 + 1;
|
Chris@16
|
1474
|
Chris@16
|
1475 // And make sure this upper bound stays within bounds of the elems.
|
Chris@16
|
1476 const std::size_t max_elem_extract_count = static_cast<std::size_t>((std::min)(static_cast<boost::int32_t>(max_elem_in_double_count), cpp_dec_float_elem_number));
|
Chris@16
|
1477
|
Chris@16
|
1478 // Extract into the mantissa the first limb, extracted as a double.
|
Chris@16
|
1479 mantissa = static_cast<double>(data[0]);
|
Chris@16
|
1480 double scale = 1.0;
|
Chris@16
|
1481
|
Chris@16
|
1482 // Extract the rest of the mantissa piecewise from the limbs.
|
Chris@16
|
1483 for(std::size_t i = 1u; i < max_elem_extract_count; i++)
|
Chris@16
|
1484 {
|
Chris@16
|
1485 scale /= static_cast<double>(cpp_dec_float_elem_mask);
|
Chris@16
|
1486 mantissa += (static_cast<double>(data[i]) * scale);
|
Chris@16
|
1487 }
|
Chris@16
|
1488
|
Chris@16
|
1489 mantissa /= static_cast<double>(p10);
|
Chris@16
|
1490
|
Chris@16
|
1491 if(neg) { mantissa = -mantissa; }
|
Chris@16
|
1492 }
|
Chris@16
|
1493
|
Chris@16
|
1494 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
1495 double cpp_dec_float<Digits10, ExponentType, Allocator>::extract_double() const
|
Chris@16
|
1496 {
|
Chris@16
|
1497 // Returns the double conversion of a cpp_dec_float<Digits10, ExponentType, Allocator>.
|
Chris@16
|
1498
|
Chris@16
|
1499 // Check for non-normal cpp_dec_float<Digits10, ExponentType, Allocator>.
|
Chris@16
|
1500 if(!(isfinite)())
|
Chris@16
|
1501 {
|
Chris@16
|
1502 if((isnan)())
|
Chris@16
|
1503 {
|
Chris@16
|
1504 return std::numeric_limits<double>::quiet_NaN();
|
Chris@16
|
1505 }
|
Chris@16
|
1506 else
|
Chris@16
|
1507 {
|
Chris@101
|
1508 return ((!neg) ? std::numeric_limits<double>::infinity()
|
Chris@16
|
1509 : -std::numeric_limits<double>::infinity());
|
Chris@16
|
1510 }
|
Chris@16
|
1511 }
|
Chris@16
|
1512
|
Chris@16
|
1513 cpp_dec_float<Digits10, ExponentType, Allocator> xx(*this);
|
Chris@16
|
1514 if(xx.isneg())
|
Chris@16
|
1515 xx.negate();
|
Chris@16
|
1516
|
Chris@16
|
1517 // Check if *this cpp_dec_float<Digits10, ExponentType, Allocator> is zero.
|
Chris@16
|
1518 if(iszero() || (xx.compare(double_min()) < 0))
|
Chris@16
|
1519 {
|
Chris@16
|
1520 return 0.0;
|
Chris@16
|
1521 }
|
Chris@16
|
1522
|
Chris@16
|
1523 // Check if *this cpp_dec_float<Digits10, ExponentType, Allocator> exceeds the maximum of double.
|
Chris@16
|
1524 if(xx.compare(double_max()) > 0)
|
Chris@16
|
1525 {
|
Chris@101
|
1526 return ((!neg) ? std::numeric_limits<double>::infinity()
|
Chris@16
|
1527 : -std::numeric_limits<double>::infinity());
|
Chris@16
|
1528 }
|
Chris@16
|
1529
|
Chris@16
|
1530 std::stringstream ss;
|
Chris@16
|
1531
|
Chris@16
|
1532 ss << str(std::numeric_limits<double>::digits10 + (2 + 1), std::ios_base::scientific);
|
Chris@16
|
1533
|
Chris@16
|
1534 double d;
|
Chris@16
|
1535 ss >> d;
|
Chris@16
|
1536
|
Chris@16
|
1537 return d;
|
Chris@16
|
1538 }
|
Chris@16
|
1539
|
Chris@16
|
1540 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
1541 long double cpp_dec_float<Digits10, ExponentType, Allocator>::extract_long_double() const
|
Chris@16
|
1542 {
|
Chris@16
|
1543 // Returns the long double conversion of a cpp_dec_float<Digits10, ExponentType, Allocator>.
|
Chris@16
|
1544
|
Chris@16
|
1545 // Check if *this cpp_dec_float<Digits10, ExponentType, Allocator> is subnormal.
|
Chris@16
|
1546 if(!(isfinite)())
|
Chris@16
|
1547 {
|
Chris@16
|
1548 if((isnan)())
|
Chris@16
|
1549 {
|
Chris@16
|
1550 return std::numeric_limits<long double>::quiet_NaN();
|
Chris@16
|
1551 }
|
Chris@16
|
1552 else
|
Chris@16
|
1553 {
|
Chris@101
|
1554 return ((!neg) ? std::numeric_limits<long double>::infinity()
|
Chris@16
|
1555 : -std::numeric_limits<long double>::infinity());
|
Chris@16
|
1556 }
|
Chris@16
|
1557 }
|
Chris@16
|
1558
|
Chris@16
|
1559 cpp_dec_float<Digits10, ExponentType, Allocator> xx(*this);
|
Chris@16
|
1560 if(xx.isneg())
|
Chris@16
|
1561 xx.negate();
|
Chris@16
|
1562
|
Chris@16
|
1563 // Check if *this cpp_dec_float<Digits10, ExponentType, Allocator> is zero.
|
Chris@16
|
1564 if(iszero() || (xx.compare(long_double_min()) < 0))
|
Chris@16
|
1565 {
|
Chris@16
|
1566 return static_cast<long double>(0.0);
|
Chris@16
|
1567 }
|
Chris@16
|
1568
|
Chris@16
|
1569 // Check if *this cpp_dec_float<Digits10, ExponentType, Allocator> exceeds the maximum of double.
|
Chris@16
|
1570 if(xx.compare(long_double_max()) > 0)
|
Chris@16
|
1571 {
|
Chris@101
|
1572 return ((!neg) ? std::numeric_limits<long double>::infinity()
|
Chris@16
|
1573 : -std::numeric_limits<long double>::infinity());
|
Chris@16
|
1574 }
|
Chris@16
|
1575
|
Chris@16
|
1576 std::stringstream ss;
|
Chris@16
|
1577
|
Chris@16
|
1578 ss << str(std::numeric_limits<long double>::digits10 + (2 + 1), std::ios_base::scientific);
|
Chris@16
|
1579
|
Chris@16
|
1580 long double ld;
|
Chris@16
|
1581 ss >> ld;
|
Chris@16
|
1582
|
Chris@16
|
1583 return ld;
|
Chris@16
|
1584 }
|
Chris@16
|
1585
|
Chris@16
|
1586 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
1587 signed long long cpp_dec_float<Digits10, ExponentType, Allocator>::extract_signed_long_long() const
|
Chris@16
|
1588 {
|
Chris@16
|
1589 // Extracts a signed long long from *this.
|
Chris@16
|
1590 // If (x > maximum of signed long long) or (x < minimum of signed long long),
|
Chris@16
|
1591 // then the maximum or minimum of signed long long is returned accordingly.
|
Chris@16
|
1592
|
Chris@16
|
1593 if(exp < static_cast<ExponentType>(0))
|
Chris@16
|
1594 {
|
Chris@16
|
1595 return static_cast<signed long long>(0);
|
Chris@16
|
1596 }
|
Chris@16
|
1597
|
Chris@16
|
1598 const bool b_neg = isneg();
|
Chris@16
|
1599
|
Chris@16
|
1600 unsigned long long val;
|
Chris@16
|
1601
|
Chris@16
|
1602 if((!b_neg) && (compare(long_long_max()) > 0))
|
Chris@16
|
1603 {
|
Chris@16
|
1604 return (std::numeric_limits<signed long long>::max)();
|
Chris@16
|
1605 }
|
Chris@101
|
1606 else if(b_neg && (compare(long_long_min()) < 0))
|
Chris@16
|
1607 {
|
Chris@16
|
1608 return (std::numeric_limits<signed long long>::min)();
|
Chris@16
|
1609 }
|
Chris@16
|
1610 else
|
Chris@16
|
1611 {
|
Chris@16
|
1612 // Extract the data into an unsigned long long value.
|
Chris@16
|
1613 cpp_dec_float<Digits10, ExponentType, Allocator> xn(extract_integer_part());
|
Chris@16
|
1614 if(xn.isneg())
|
Chris@16
|
1615 xn.negate();
|
Chris@16
|
1616
|
Chris@16
|
1617 val = static_cast<unsigned long long>(xn.data[0]);
|
Chris@16
|
1618
|
Chris@16
|
1619 const boost::int32_t imax = (std::min)(static_cast<boost::int32_t>(static_cast<boost::int32_t>(xn.exp) / cpp_dec_float_elem_digits10), static_cast<boost::int32_t>(cpp_dec_float_elem_number - static_cast<boost::int32_t>(1)));
|
Chris@16
|
1620
|
Chris@16
|
1621 for(boost::int32_t i = static_cast<boost::int32_t>(1); i <= imax; i++)
|
Chris@16
|
1622 {
|
Chris@16
|
1623 val *= static_cast<unsigned long long>(cpp_dec_float_elem_mask);
|
Chris@16
|
1624 val += static_cast<unsigned long long>(xn.data[i]);
|
Chris@16
|
1625 }
|
Chris@16
|
1626 }
|
Chris@16
|
1627
|
Chris@101
|
1628 if (!b_neg)
|
Chris@101
|
1629 {
|
Chris@101
|
1630 return static_cast<signed long long>(val);
|
Chris@101
|
1631 }
|
Chris@101
|
1632 else
|
Chris@101
|
1633 {
|
Chris@101
|
1634 // This strange expression avoids a hardware trap in the corner case
|
Chris@101
|
1635 // that val is the most negative value permitted in long long.
|
Chris@101
|
1636 // See https://svn.boost.org/trac/boost/ticket/9740.
|
Chris@101
|
1637 //
|
Chris@101
|
1638 signed long long sval = static_cast<signed long long>(val - 1);
|
Chris@101
|
1639 sval = -sval;
|
Chris@101
|
1640 --sval;
|
Chris@101
|
1641 return sval;
|
Chris@101
|
1642 }
|
Chris@16
|
1643 }
|
Chris@16
|
1644
|
Chris@16
|
1645 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
1646 unsigned long long cpp_dec_float<Digits10, ExponentType, Allocator>::extract_unsigned_long_long() const
|
Chris@16
|
1647 {
|
Chris@16
|
1648 // Extracts an unsigned long long from *this.
|
Chris@16
|
1649 // If x exceeds the maximum of unsigned long long,
|
Chris@16
|
1650 // then the maximum of unsigned long long is returned.
|
Chris@16
|
1651 // If x is negative, then the unsigned long long cast of
|
Chris@16
|
1652 // the signed long long extracted value is returned.
|
Chris@16
|
1653
|
Chris@16
|
1654 if(isneg())
|
Chris@16
|
1655 {
|
Chris@16
|
1656 return static_cast<unsigned long long>(extract_signed_long_long());
|
Chris@16
|
1657 }
|
Chris@16
|
1658
|
Chris@16
|
1659 if(exp < static_cast<ExponentType>(0))
|
Chris@16
|
1660 {
|
Chris@16
|
1661 return static_cast<unsigned long long>(0u);
|
Chris@16
|
1662 }
|
Chris@16
|
1663
|
Chris@16
|
1664 const cpp_dec_float<Digits10, ExponentType, Allocator> xn(extract_integer_part());
|
Chris@16
|
1665
|
Chris@16
|
1666 unsigned long long val;
|
Chris@16
|
1667
|
Chris@16
|
1668 if(xn.compare(ulong_long_max()) > 0)
|
Chris@16
|
1669 {
|
Chris@16
|
1670 return (std::numeric_limits<unsigned long long>::max)();
|
Chris@16
|
1671 }
|
Chris@16
|
1672 else
|
Chris@16
|
1673 {
|
Chris@16
|
1674 // Extract the data into an unsigned long long value.
|
Chris@16
|
1675 val = static_cast<unsigned long long>(xn.data[0]);
|
Chris@16
|
1676
|
Chris@16
|
1677 const boost::int32_t imax = (std::min)(static_cast<boost::int32_t>(static_cast<boost::int32_t>(xn.exp) / cpp_dec_float_elem_digits10), static_cast<boost::int32_t>(cpp_dec_float_elem_number - static_cast<boost::int32_t>(1)));
|
Chris@16
|
1678
|
Chris@16
|
1679 for(boost::int32_t i = static_cast<boost::int32_t>(1); i <= imax; i++)
|
Chris@16
|
1680 {
|
Chris@16
|
1681 val *= static_cast<unsigned long long>(cpp_dec_float_elem_mask);
|
Chris@16
|
1682 val += static_cast<unsigned long long>(xn.data[i]);
|
Chris@16
|
1683 }
|
Chris@16
|
1684 }
|
Chris@16
|
1685
|
Chris@16
|
1686 return val;
|
Chris@16
|
1687 }
|
Chris@16
|
1688
|
Chris@16
|
1689 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
1690 cpp_dec_float<Digits10, ExponentType, Allocator> cpp_dec_float<Digits10, ExponentType, Allocator>::extract_integer_part() const
|
Chris@16
|
1691 {
|
Chris@16
|
1692 // Compute the signed integer part of x.
|
Chris@16
|
1693
|
Chris@16
|
1694 if(!(isfinite)())
|
Chris@16
|
1695 {
|
Chris@16
|
1696 return *this;
|
Chris@16
|
1697 }
|
Chris@16
|
1698
|
Chris@16
|
1699 if(exp < static_cast<ExponentType>(0))
|
Chris@16
|
1700 {
|
Chris@16
|
1701 // The absolute value of the number is smaller than 1.
|
Chris@16
|
1702 // Thus the integer part is zero.
|
Chris@16
|
1703 return zero();
|
Chris@16
|
1704 }
|
Chris@16
|
1705
|
Chris@16
|
1706 // Truncate the digits from the decimal part, including guard digits
|
Chris@16
|
1707 // that do not belong to the integer part.
|
Chris@16
|
1708
|
Chris@16
|
1709 // Make a local copy.
|
Chris@16
|
1710 cpp_dec_float<Digits10, ExponentType, Allocator> x = *this;
|
Chris@16
|
1711
|
Chris@16
|
1712 // Clear out the decimal portion
|
Chris@16
|
1713 const size_t first_clear = (static_cast<size_t>(x.exp) / static_cast<size_t>(cpp_dec_float_elem_digits10)) + 1u;
|
Chris@101
|
1714 const size_t last_clear = static_cast<size_t>(cpp_dec_float_elem_number);
|
Chris@16
|
1715
|
Chris@16
|
1716 if(first_clear < last_clear)
|
Chris@16
|
1717 std::fill(x.data.begin() + first_clear, x.data.begin() + last_clear, static_cast<boost::uint32_t>(0u));
|
Chris@16
|
1718
|
Chris@16
|
1719 return x;
|
Chris@16
|
1720 }
|
Chris@16
|
1721
|
Chris@16
|
1722 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@16
|
1723 std::string cpp_dec_float<Digits10, ExponentType, Allocator>::str(boost::intmax_t number_of_digits, std::ios_base::fmtflags f) const
|
Chris@16
|
1724 {
|
Chris@16
|
1725 if((this->isinf)())
|
Chris@16
|
1726 {
|
Chris@16
|
1727 if(this->isneg())
|
Chris@16
|
1728 return "-inf";
|
Chris@16
|
1729 else if(f & std::ios_base::showpos)
|
Chris@16
|
1730 return "+inf";
|
Chris@101
|
1731 else
|
Chris@16
|
1732 return "inf";
|
Chris@16
|
1733 }
|
Chris@16
|
1734 else if((this->isnan)())
|
Chris@16
|
1735 {
|
Chris@16
|
1736 return "nan";
|
Chris@16
|
1737 }
|
Chris@16
|
1738
|
Chris@16
|
1739 std::string str;
|
Chris@16
|
1740 boost::intmax_t org_digits(number_of_digits);
|
Chris@16
|
1741 ExponentType my_exp = order();
|
Chris@101
|
1742
|
Chris@16
|
1743 if(number_of_digits == 0)
|
Chris@16
|
1744 number_of_digits = cpp_dec_float_total_digits10;
|
Chris@101
|
1745
|
Chris@16
|
1746 if(f & std::ios_base::fixed)
|
Chris@16
|
1747 {
|
Chris@16
|
1748 number_of_digits += my_exp + 1;
|
Chris@16
|
1749 }
|
Chris@16
|
1750 else if(f & std::ios_base::scientific)
|
Chris@16
|
1751 ++number_of_digits;
|
Chris@16
|
1752 // Determine the number of elements needed to provide the requested digits from cpp_dec_float<Digits10, ExponentType, Allocator>.
|
Chris@16
|
1753 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),
|
Chris@16
|
1754 static_cast<std::size_t>(cpp_dec_float_elem_number));
|
Chris@16
|
1755
|
Chris@16
|
1756 // Extract the remaining digits from cpp_dec_float<Digits10, ExponentType, Allocator> after the decimal point.
|
Chris@16
|
1757 str = boost::lexical_cast<std::string>(data[0]);
|
Chris@16
|
1758
|
Chris@16
|
1759 // Extract all of the digits from cpp_dec_float<Digits10, ExponentType, Allocator>, beginning with the first data element.
|
Chris@16
|
1760 for(std::size_t i = static_cast<std::size_t>(1u); i < number_of_elements; i++)
|
Chris@16
|
1761 {
|
Chris@16
|
1762 std::stringstream ss;
|
Chris@16
|
1763
|
Chris@16
|
1764 ss << std::setw(static_cast<std::streamsize>(cpp_dec_float_elem_digits10))
|
Chris@16
|
1765 << std::setfill(static_cast<char>('0'))
|
Chris@16
|
1766 << data[i];
|
Chris@16
|
1767
|
Chris@16
|
1768 str += ss.str();
|
Chris@16
|
1769 }
|
Chris@101
|
1770
|
Chris@16
|
1771 bool have_leading_zeros = false;
|
Chris@101
|
1772
|
Chris@16
|
1773 if(number_of_digits == 0)
|
Chris@16
|
1774 {
|
Chris@16
|
1775 // We only get here if the output format is "fixed" and we just need to
|
Chris@16
|
1776 // round the first non-zero digit.
|
Chris@101
|
1777 number_of_digits -= my_exp + 1; // reset to original value
|
Chris@101
|
1778 str.insert(static_cast<std::string::size_type>(0), std::string::size_type(number_of_digits), '0');
|
Chris@16
|
1779 have_leading_zeros = true;
|
Chris@16
|
1780 }
|
Chris@101
|
1781
|
Chris@16
|
1782 if(number_of_digits < 0)
|
Chris@16
|
1783 {
|
Chris@16
|
1784 str = "0";
|
Chris@16
|
1785 if(isneg())
|
Chris@101
|
1786 str.insert(static_cast<std::string::size_type>(0), 1, '-');
|
Chris@16
|
1787 boost::multiprecision::detail::format_float_string(str, 0, number_of_digits - my_exp - 1, f, this->iszero());
|
Chris@16
|
1788 return str;
|
Chris@16
|
1789 }
|
Chris@16
|
1790 else
|
Chris@16
|
1791 {
|
Chris@16
|
1792 // Cut the output to the size of the precision.
|
Chris@16
|
1793 if(str.length() > static_cast<std::string::size_type>(number_of_digits))
|
Chris@16
|
1794 {
|
Chris@16
|
1795 // Get the digit after the last needed digit for rounding
|
Chris@16
|
1796 const boost::uint32_t round = static_cast<boost::uint32_t>(static_cast<boost::uint32_t>(str[static_cast<std::string::size_type>(number_of_digits)]) - static_cast<boost::uint32_t>('0'));
|
Chris@16
|
1797
|
Chris@16
|
1798 bool need_round_up = round >= 5u;
|
Chris@16
|
1799
|
Chris@16
|
1800 if(round == 5u)
|
Chris@16
|
1801 {
|
Chris@16
|
1802 const boost::uint32_t ix = static_cast<boost::uint32_t>(static_cast<boost::uint32_t>(str[static_cast<std::string::size_type>(number_of_digits - 1)]) - static_cast<boost::uint32_t>('0'));
|
Chris@16
|
1803 if((ix & 1u) == 0)
|
Chris@16
|
1804 {
|
Chris@16
|
1805 // We have an even digit followed by a 5, so we might not actually need to round up
|
Chris@16
|
1806 // if all the remaining digits are zero:
|
Chris@16
|
1807 if(str.find_first_not_of('0', static_cast<std::string::size_type>(number_of_digits + 1)) == std::string::npos)
|
Chris@16
|
1808 {
|
Chris@16
|
1809 bool all_zeros = true;
|
Chris@16
|
1810 // No none-zero trailing digits in the string, now check whatever parts we didn't convert to the string:
|
Chris@16
|
1811 for(std::size_t i = number_of_elements; i < data.size(); i++)
|
Chris@16
|
1812 {
|
Chris@16
|
1813 if(data[i])
|
Chris@16
|
1814 {
|
Chris@16
|
1815 all_zeros = false;
|
Chris@16
|
1816 break;
|
Chris@16
|
1817 }
|
Chris@16
|
1818 }
|
Chris@16
|
1819 if(all_zeros)
|
Chris@101
|
1820 need_round_up = false; // tie break - round to even.
|
Chris@16
|
1821 }
|
Chris@16
|
1822 }
|
Chris@16
|
1823 }
|
Chris@16
|
1824
|
Chris@16
|
1825 // Truncate the string
|
Chris@16
|
1826 str.erase(static_cast<std::string::size_type>(number_of_digits));
|
Chris@16
|
1827
|
Chris@16
|
1828 if(need_round_up)
|
Chris@16
|
1829 {
|
Chris@16
|
1830 std::size_t ix = static_cast<std::size_t>(str.length() - 1u);
|
Chris@16
|
1831
|
Chris@16
|
1832 // Every trailing 9 must be rounded up
|
Chris@16
|
1833 while(ix && (static_cast<boost::int32_t>(str.at(ix)) - static_cast<boost::int32_t>('0') == static_cast<boost::int32_t>(9)))
|
Chris@16
|
1834 {
|
Chris@16
|
1835 str.at(ix) = static_cast<char>('0');
|
Chris@16
|
1836 --ix;
|
Chris@16
|
1837 }
|
Chris@16
|
1838
|
Chris@16
|
1839 if(!ix)
|
Chris@16
|
1840 {
|
Chris@16
|
1841 // There were nothing but trailing nines.
|
Chris@16
|
1842 if(static_cast<boost::int32_t>(static_cast<boost::int32_t>(str.at(ix)) - static_cast<boost::int32_t>(0x30)) == static_cast<boost::int32_t>(9))
|
Chris@16
|
1843 {
|
Chris@16
|
1844 // Increment up to the next order and adjust exponent.
|
Chris@16
|
1845 str.at(ix) = static_cast<char>('1');
|
Chris@16
|
1846 ++my_exp;
|
Chris@16
|
1847 }
|
Chris@16
|
1848 else
|
Chris@16
|
1849 {
|
Chris@16
|
1850 // Round up this digit.
|
Chris@16
|
1851 ++str.at(ix);
|
Chris@16
|
1852 }
|
Chris@16
|
1853 }
|
Chris@16
|
1854 else
|
Chris@16
|
1855 {
|
Chris@16
|
1856 // Round up the last digit.
|
Chris@16
|
1857 ++str[ix];
|
Chris@16
|
1858 }
|
Chris@16
|
1859 }
|
Chris@16
|
1860 }
|
Chris@16
|
1861 }
|
Chris@101
|
1862
|
Chris@16
|
1863 if(have_leading_zeros)
|
Chris@16
|
1864 {
|
Chris@16
|
1865 // We need to take the zeros back out again, and correct the exponent
|
Chris@16
|
1866 // if we rounded up:
|
Chris@16
|
1867 if(str[std::string::size_type(number_of_digits - 1)] != '0')
|
Chris@16
|
1868 {
|
Chris@16
|
1869 ++my_exp;
|
Chris@16
|
1870 str.erase(0, std::string::size_type(number_of_digits - 1));
|
Chris@16
|
1871 }
|
Chris@16
|
1872 else
|
Chris@16
|
1873 str.erase(0, std::string::size_type(number_of_digits));
|
Chris@16
|
1874 }
|
Chris@101
|
1875
|
Chris@16
|
1876 if(isneg())
|
Chris@101
|
1877 str.insert(static_cast<std::string::size_type>(0), 1, '-');
|
Chris@101
|
1878
|
Chris@16
|
1879 boost::multiprecision::detail::format_float_string(str, my_exp, org_digits, f, this->iszero());
|
Chris@16
|
1880 return str;
|
Chris@16
|
1881 }
|
Chris@16
|
1882
|
Chris@16
|
1883 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@16
|
1884 bool cpp_dec_float<Digits10, ExponentType, Allocator>::rd_string(const char* const s)
|
Chris@16
|
1885 {
|
Chris@16
|
1886 try{
|
Chris@16
|
1887
|
Chris@16
|
1888 std::string str(s);
|
Chris@16
|
1889
|
Chris@16
|
1890 // TBD: Using several regular expressions may significantly reduce
|
Chris@16
|
1891 // the code complexity (and perhaps the run-time) of rd_string().
|
Chris@16
|
1892
|
Chris@16
|
1893 // Get a possible exponent and remove it.
|
Chris@16
|
1894 exp = static_cast<ExponentType>(0);
|
Chris@16
|
1895
|
Chris@16
|
1896 std::size_t pos;
|
Chris@16
|
1897
|
Chris@101
|
1898 if( ((pos = str.find('e')) != std::string::npos)
|
Chris@16
|
1899 || ((pos = str.find('E')) != std::string::npos)
|
Chris@16
|
1900 )
|
Chris@16
|
1901 {
|
Chris@16
|
1902 // Remove the exponent part from the string.
|
Chris@16
|
1903 exp = boost::lexical_cast<ExponentType>(static_cast<const char*>(str.c_str() + (pos + 1u)));
|
Chris@16
|
1904 str = str.substr(static_cast<std::size_t>(0u), pos);
|
Chris@16
|
1905 }
|
Chris@16
|
1906
|
Chris@16
|
1907 // Get a possible +/- sign and remove it.
|
Chris@16
|
1908 neg = false;
|
Chris@16
|
1909
|
Chris@16
|
1910 if(str.size())
|
Chris@16
|
1911 {
|
Chris@16
|
1912 if(str[0] == '-')
|
Chris@16
|
1913 {
|
Chris@16
|
1914 neg = true;
|
Chris@16
|
1915 str.erase(0, 1);
|
Chris@16
|
1916 }
|
Chris@16
|
1917 else if(str[0] == '+')
|
Chris@16
|
1918 {
|
Chris@16
|
1919 str.erase(0, 1);
|
Chris@16
|
1920 }
|
Chris@16
|
1921 }
|
Chris@16
|
1922 //
|
Chris@16
|
1923 // Special cases for infinities and NaN's:
|
Chris@16
|
1924 //
|
Chris@16
|
1925 if((str == "inf") || (str == "INF") || (str == "infinity") || (str == "INFINITY"))
|
Chris@16
|
1926 {
|
Chris@16
|
1927 if(neg)
|
Chris@16
|
1928 {
|
Chris@16
|
1929 *this = this->inf();
|
Chris@16
|
1930 this->negate();
|
Chris@16
|
1931 }
|
Chris@16
|
1932 else
|
Chris@16
|
1933 *this = this->inf();
|
Chris@16
|
1934 return true;
|
Chris@16
|
1935 }
|
Chris@16
|
1936 if((str.size() >= 3) && ((str.substr(0, 3) == "nan") || (str.substr(0, 3) == "NAN") || (str.substr(0, 3) == "NaN")))
|
Chris@16
|
1937 {
|
Chris@16
|
1938 *this = this->nan();
|
Chris@16
|
1939 return true;
|
Chris@16
|
1940 }
|
Chris@16
|
1941
|
Chris@16
|
1942 // Remove the leading zeros for all input types.
|
Chris@16
|
1943 const std::string::iterator fwd_it_leading_zero = std::find_if(str.begin(), str.end(), char_is_nonzero_predicate);
|
Chris@16
|
1944
|
Chris@16
|
1945 if(fwd_it_leading_zero != str.begin())
|
Chris@16
|
1946 {
|
Chris@16
|
1947 if(fwd_it_leading_zero == str.end())
|
Chris@16
|
1948 {
|
Chris@16
|
1949 // The string contains nothing but leading zeros.
|
Chris@16
|
1950 // This string represents zero.
|
Chris@16
|
1951 operator=(zero());
|
Chris@16
|
1952 return true;
|
Chris@16
|
1953 }
|
Chris@16
|
1954 else
|
Chris@16
|
1955 {
|
Chris@16
|
1956 str.erase(str.begin(), fwd_it_leading_zero);
|
Chris@16
|
1957 }
|
Chris@16
|
1958 }
|
Chris@16
|
1959
|
Chris@16
|
1960 // Put the input string into the standard cpp_dec_float<Digits10, ExponentType, Allocator> input form
|
Chris@16
|
1961 // aaa.bbbbE+/-n, where aaa has 1...cpp_dec_float_elem_digits10, bbbb has an
|
Chris@16
|
1962 // even multiple of cpp_dec_float_elem_digits10 which are possibly zero padded
|
Chris@16
|
1963 // on the right-end, and n is a signed 64-bit integer which is an
|
Chris@16
|
1964 // even multiple of cpp_dec_float_elem_digits10.
|
Chris@16
|
1965
|
Chris@16
|
1966 // Find a possible decimal point.
|
Chris@16
|
1967 pos = str.find(static_cast<char>('.'));
|
Chris@16
|
1968
|
Chris@16
|
1969 if(pos != std::string::npos)
|
Chris@16
|
1970 {
|
Chris@16
|
1971 // Remove all trailing insignificant zeros.
|
Chris@16
|
1972 const std::string::const_reverse_iterator rit_non_zero = std::find_if(str.rbegin(), str.rend(), char_is_nonzero_predicate);
|
Chris@16
|
1973
|
Chris@101
|
1974 if(rit_non_zero != static_cast<std::string::const_reverse_iterator>(str.rbegin()))
|
Chris@16
|
1975 {
|
Chris@16
|
1976 const std::string::size_type ofs = str.length() - std::distance<std::string::const_reverse_iterator>(str.rbegin(), rit_non_zero);
|
Chris@16
|
1977 str.erase(str.begin() + ofs, str.end());
|
Chris@16
|
1978 }
|
Chris@16
|
1979
|
Chris@16
|
1980 // Check if the input is identically zero.
|
Chris@16
|
1981 if(str == std::string("."))
|
Chris@16
|
1982 {
|
Chris@16
|
1983 operator=(zero());
|
Chris@16
|
1984 return true;
|
Chris@16
|
1985 }
|
Chris@16
|
1986
|
Chris@16
|
1987 // Remove leading significant zeros just after the decimal point
|
Chris@16
|
1988 // and adjust the exponent accordingly.
|
Chris@16
|
1989 // Note that the while-loop operates only on strings of the form ".000abcd..."
|
Chris@16
|
1990 // and peels away the zeros just after the decimal point.
|
Chris@16
|
1991 if(str.at(static_cast<std::size_t>(0u)) == static_cast<char>('.'))
|
Chris@16
|
1992 {
|
Chris@16
|
1993 const std::string::iterator it_non_zero = std::find_if(str.begin() + 1u, str.end(), char_is_nonzero_predicate);
|
Chris@16
|
1994
|
Chris@16
|
1995 std::size_t delta_exp = static_cast<std::size_t>(0u);
|
Chris@16
|
1996
|
Chris@16
|
1997 if(str.at(static_cast<std::size_t>(1u)) == static_cast<char>('0'))
|
Chris@16
|
1998 {
|
Chris@16
|
1999 delta_exp = std::distance<std::string::const_iterator>(str.begin() + 1u, it_non_zero);
|
Chris@16
|
2000 }
|
Chris@16
|
2001
|
Chris@16
|
2002 // Bring one single digit into the mantissa and adjust the exponent accordingly.
|
Chris@16
|
2003 str.erase(str.begin(), it_non_zero);
|
Chris@101
|
2004 str.insert(static_cast<std::string::size_type>(1u), ".");
|
Chris@16
|
2005 exp -= static_cast<ExponentType>(delta_exp + 1u);
|
Chris@16
|
2006 }
|
Chris@16
|
2007 }
|
Chris@16
|
2008 else
|
Chris@16
|
2009 {
|
Chris@16
|
2010 // Input string has no decimal point: Append decimal point.
|
Chris@16
|
2011 str.append(".");
|
Chris@16
|
2012 }
|
Chris@16
|
2013
|
Chris@16
|
2014 // Shift the decimal point such that the exponent is an even multiple of cpp_dec_float_elem_digits10.
|
Chris@101
|
2015 std::size_t n_shift = static_cast<std::size_t>(0u);
|
Chris@16
|
2016 const std::size_t n_exp_rem = static_cast<std::size_t>(exp % static_cast<ExponentType>(cpp_dec_float_elem_digits10));
|
Chris@16
|
2017
|
Chris@16
|
2018 if((exp % static_cast<ExponentType>(cpp_dec_float_elem_digits10)) != static_cast<ExponentType>(0))
|
Chris@16
|
2019 {
|
Chris@16
|
2020 n_shift = ((exp < static_cast<ExponentType>(0))
|
Chris@16
|
2021 ? static_cast<std::size_t>(n_exp_rem + static_cast<std::size_t>(cpp_dec_float_elem_digits10))
|
Chris@16
|
2022 : static_cast<std::size_t>(n_exp_rem));
|
Chris@16
|
2023 }
|
Chris@16
|
2024
|
Chris@16
|
2025 // Make sure that there are enough digits for the decimal point shift.
|
Chris@16
|
2026 pos = str.find(static_cast<char>('.'));
|
Chris@16
|
2027
|
Chris@16
|
2028 std::size_t pos_plus_one = static_cast<std::size_t>(pos + 1u);
|
Chris@16
|
2029
|
Chris@16
|
2030 if((str.length() - pos_plus_one) < n_shift)
|
Chris@16
|
2031 {
|
Chris@16
|
2032 const std::size_t sz = static_cast<std::size_t>(n_shift - (str.length() - pos_plus_one));
|
Chris@16
|
2033
|
Chris@16
|
2034 str.append(std::string(sz, static_cast<char>('0')));
|
Chris@16
|
2035 }
|
Chris@16
|
2036
|
Chris@16
|
2037 // Do the decimal point shift.
|
Chris@16
|
2038 if(n_shift != static_cast<std::size_t>(0u))
|
Chris@16
|
2039 {
|
Chris@101
|
2040 str.insert(static_cast<std::string::size_type>(pos_plus_one + n_shift), ".");
|
Chris@101
|
2041
|
Chris@101
|
2042 str.erase(pos, static_cast<std::string::size_type>(1u));
|
Chris@16
|
2043
|
Chris@16
|
2044 exp -= static_cast<ExponentType>(n_shift);
|
Chris@16
|
2045 }
|
Chris@16
|
2046
|
Chris@16
|
2047 // Cut the size of the mantissa to <= cpp_dec_float_elem_digits10.
|
Chris@101
|
2048 pos = str.find(static_cast<char>('.'));
|
Chris@16
|
2049 pos_plus_one = static_cast<std::size_t>(pos + 1u);
|
Chris@16
|
2050
|
Chris@16
|
2051 if(pos > static_cast<std::size_t>(cpp_dec_float_elem_digits10))
|
Chris@16
|
2052 {
|
Chris@101
|
2053 const boost::int32_t n_pos = static_cast<boost::int32_t>(pos);
|
Chris@16
|
2054 const boost::int32_t n_rem_is_zero = ((static_cast<boost::int32_t>(n_pos % cpp_dec_float_elem_digits10) == static_cast<boost::int32_t>(0)) ? static_cast<boost::int32_t>(1) : static_cast<boost::int32_t>(0));
|
Chris@101
|
2055 const boost::int32_t n = static_cast<boost::int32_t>(static_cast<boost::int32_t>(n_pos / cpp_dec_float_elem_digits10) - n_rem_is_zero);
|
Chris@16
|
2056
|
Chris@16
|
2057 str.insert(static_cast<std::size_t>(static_cast<boost::int32_t>(n_pos - static_cast<boost::int32_t>(n * cpp_dec_float_elem_digits10))), ".");
|
Chris@16
|
2058
|
Chris@16
|
2059 str.erase(pos_plus_one, static_cast<std::size_t>(1u));
|
Chris@16
|
2060
|
Chris@16
|
2061 exp += static_cast<ExponentType>(static_cast<ExponentType>(n) * static_cast<ExponentType>(cpp_dec_float_elem_digits10));
|
Chris@16
|
2062 }
|
Chris@16
|
2063
|
Chris@16
|
2064 // Pad the decimal part such that its value is an even
|
Chris@16
|
2065 // multiple of cpp_dec_float_elem_digits10.
|
Chris@101
|
2066 pos = str.find(static_cast<char>('.'));
|
Chris@16
|
2067 pos_plus_one = static_cast<std::size_t>(pos + 1u);
|
Chris@16
|
2068
|
Chris@16
|
2069 const boost::int32_t n_dec = static_cast<boost::int32_t>(static_cast<boost::int32_t>(str.length() - 1u) - static_cast<boost::int32_t>(pos));
|
Chris@16
|
2070 const boost::int32_t n_rem = static_cast<boost::int32_t>(n_dec % cpp_dec_float_elem_digits10);
|
Chris@101
|
2071
|
Chris@101
|
2072 boost::int32_t n_cnt = ((n_rem != static_cast<boost::int32_t>(0))
|
Chris@101
|
2073 ? static_cast<boost::int32_t>(cpp_dec_float_elem_digits10 - n_rem)
|
Chris@101
|
2074 : static_cast<boost::int32_t>(0));
|
Chris@16
|
2075
|
Chris@16
|
2076 if(n_cnt != static_cast<boost::int32_t>(0))
|
Chris@16
|
2077 {
|
Chris@16
|
2078 str.append(static_cast<std::size_t>(n_cnt), static_cast<char>('0'));
|
Chris@16
|
2079 }
|
Chris@16
|
2080
|
Chris@16
|
2081 // Truncate decimal part if it is too long.
|
Chris@16
|
2082 const std::size_t max_dec = static_cast<std::size_t>((cpp_dec_float_elem_number - 1) * cpp_dec_float_elem_digits10);
|
Chris@16
|
2083
|
Chris@16
|
2084 if(static_cast<std::size_t>(str.length() - pos) > max_dec)
|
Chris@16
|
2085 {
|
Chris@16
|
2086 str = str.substr(static_cast<std::size_t>(0u),
|
Chris@16
|
2087 static_cast<std::size_t>(pos_plus_one + max_dec));
|
Chris@16
|
2088 }
|
Chris@16
|
2089
|
Chris@16
|
2090 // Now the input string has the standard cpp_dec_float<Digits10, ExponentType, Allocator> input form.
|
Chris@16
|
2091 // (See the comment above.)
|
Chris@16
|
2092
|
Chris@16
|
2093 // Set all the data elements to 0.
|
Chris@16
|
2094 std::fill(data.begin(), data.end(), static_cast<boost::uint32_t>(0u));
|
Chris@16
|
2095
|
Chris@16
|
2096 // Extract the data.
|
Chris@16
|
2097
|
Chris@16
|
2098 // First get the digits to the left of the decimal point...
|
Chris@16
|
2099 data[0u] = boost::lexical_cast<boost::uint32_t>(str.substr(static_cast<std::size_t>(0u), pos));
|
Chris@16
|
2100
|
Chris@16
|
2101 // ...then get the remaining digits to the right of the decimal point.
|
Chris@16
|
2102 const std::string::size_type i_end = ((str.length() - pos_plus_one) / static_cast<std::string::size_type>(cpp_dec_float_elem_digits10));
|
Chris@16
|
2103
|
Chris@16
|
2104 for(std::string::size_type i = static_cast<std::string::size_type>(0u); i < i_end; i++)
|
Chris@16
|
2105 {
|
Chris@101
|
2106 const std::string::const_iterator it = str.begin()
|
Chris@16
|
2107 + pos_plus_one
|
Chris@16
|
2108 + (i * static_cast<std::string::size_type>(cpp_dec_float_elem_digits10));
|
Chris@16
|
2109
|
Chris@16
|
2110 data[i + 1u] = boost::lexical_cast<boost::uint32_t>(std::string(it, it + static_cast<std::string::size_type>(cpp_dec_float_elem_digits10)));
|
Chris@16
|
2111 }
|
Chris@16
|
2112
|
Chris@16
|
2113 // Check for overflow...
|
Chris@16
|
2114 if(exp > cpp_dec_float_max_exp10)
|
Chris@16
|
2115 {
|
Chris@16
|
2116 const bool b_result_is_neg = neg;
|
Chris@16
|
2117
|
Chris@16
|
2118 *this = inf();
|
Chris@16
|
2119 if(b_result_is_neg)
|
Chris@16
|
2120 negate();
|
Chris@16
|
2121 }
|
Chris@16
|
2122
|
Chris@16
|
2123 // ...and check for underflow.
|
Chris@16
|
2124 if(exp <= cpp_dec_float_min_exp10)
|
Chris@16
|
2125 {
|
Chris@16
|
2126 if(exp == cpp_dec_float_min_exp10)
|
Chris@16
|
2127 {
|
Chris@16
|
2128 // Check for identity with the minimum value.
|
Chris@16
|
2129 cpp_dec_float<Digits10, ExponentType, Allocator> test = *this;
|
Chris@16
|
2130
|
Chris@16
|
2131 test.exp = static_cast<ExponentType>(0);
|
Chris@16
|
2132
|
Chris@16
|
2133 if(test.isone())
|
Chris@16
|
2134 {
|
Chris@16
|
2135 *this = zero();
|
Chris@16
|
2136 }
|
Chris@16
|
2137 }
|
Chris@16
|
2138 else
|
Chris@16
|
2139 {
|
Chris@16
|
2140 *this = zero();
|
Chris@16
|
2141 }
|
Chris@16
|
2142 }
|
Chris@16
|
2143
|
Chris@16
|
2144 }
|
Chris@16
|
2145 catch(const bad_lexical_cast&)
|
Chris@16
|
2146 {
|
Chris@16
|
2147 // Rethrow with better error message:
|
Chris@16
|
2148 std::string msg = "Unable to parse the string \"";
|
Chris@16
|
2149 msg += s;
|
Chris@16
|
2150 msg += "\" as a floating point value.";
|
Chris@16
|
2151 throw std::runtime_error(msg);
|
Chris@16
|
2152 }
|
Chris@16
|
2153
|
Chris@16
|
2154 return true;
|
Chris@16
|
2155 }
|
Chris@16
|
2156
|
Chris@16
|
2157 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2158 cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float(const double mantissa, const ExponentType exponent)
|
Chris@101
|
2159 : data (),
|
Chris@101
|
2160 exp (static_cast<ExponentType>(0)),
|
Chris@101
|
2161 neg (false),
|
Chris@101
|
2162 fpclass (cpp_dec_float_finite),
|
Chris@16
|
2163 prec_elem(cpp_dec_float_elem_number)
|
Chris@16
|
2164 {
|
Chris@16
|
2165 // Create *this cpp_dec_float<Digits10, ExponentType, Allocator> from a given mantissa and exponent.
|
Chris@16
|
2166 // Note: This constructor does not maintain the full precision of double.
|
Chris@16
|
2167
|
Chris@16
|
2168 const bool mantissa_is_iszero = (::fabs(mantissa) < ((std::numeric_limits<double>::min)() * (1.0 + std::numeric_limits<double>::epsilon())));
|
Chris@16
|
2169
|
Chris@16
|
2170 if(mantissa_is_iszero)
|
Chris@16
|
2171 {
|
Chris@16
|
2172 std::fill(data.begin(), data.end(), static_cast<boost::uint32_t>(0u));
|
Chris@16
|
2173 return;
|
Chris@16
|
2174 }
|
Chris@16
|
2175
|
Chris@16
|
2176 const bool b_neg = (mantissa < 0.0);
|
Chris@16
|
2177
|
Chris@16
|
2178 double d = ((!b_neg) ? mantissa : -mantissa);
|
Chris@101
|
2179 ExponentType e = exponent;
|
Chris@16
|
2180
|
Chris@16
|
2181 while(d > 10.0) { d /= 10.0; ++e; }
|
Chris@101
|
2182 while(d < 1.0) { d *= 10.0; --e; }
|
Chris@16
|
2183
|
Chris@16
|
2184 boost::int32_t shift = static_cast<boost::int32_t>(e % static_cast<boost::int32_t>(cpp_dec_float_elem_digits10));
|
Chris@16
|
2185
|
Chris@16
|
2186 while(static_cast<boost::int32_t>(shift-- % cpp_dec_float_elem_digits10) != static_cast<boost::int32_t>(0))
|
Chris@16
|
2187 {
|
Chris@16
|
2188 d *= 10.0;
|
Chris@16
|
2189 --e;
|
Chris@16
|
2190 }
|
Chris@16
|
2191
|
Chris@16
|
2192 exp = e;
|
Chris@16
|
2193 neg = b_neg;
|
Chris@16
|
2194
|
Chris@16
|
2195 std::fill(data.begin(), data.end(), static_cast<boost::uint32_t>(0u));
|
Chris@16
|
2196
|
Chris@16
|
2197 static const boost::int32_t digit_ratio = static_cast<boost::int32_t>(static_cast<boost::int32_t>(std::numeric_limits<double>::digits10) / static_cast<boost::int32_t>(cpp_dec_float_elem_digits10));
|
Chris@16
|
2198 static const boost::int32_t digit_loops = static_cast<boost::int32_t>(digit_ratio + static_cast<boost::int32_t>(2));
|
Chris@16
|
2199
|
Chris@16
|
2200 for(boost::int32_t i = static_cast<boost::int32_t>(0); i < digit_loops; i++)
|
Chris@16
|
2201 {
|
Chris@16
|
2202 boost::uint32_t n = static_cast<boost::uint32_t>(static_cast<boost::uint64_t>(d));
|
Chris@101
|
2203 data[i] = static_cast<boost::uint32_t>(n);
|
Chris@101
|
2204 d -= static_cast<double>(n);
|
Chris@101
|
2205 d *= static_cast<double>(cpp_dec_float_elem_mask);
|
Chris@16
|
2206 }
|
Chris@16
|
2207 }
|
Chris@16
|
2208
|
Chris@16
|
2209 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@16
|
2210 cpp_dec_float<Digits10, ExponentType, Allocator>& cpp_dec_float<Digits10, ExponentType, Allocator>::operator= (long double a)
|
Chris@16
|
2211 {
|
Chris@16
|
2212 // Christopher Kormanyos's original code used a cast to long long here, but that fails
|
Chris@16
|
2213 // when long double has more digits than a long long.
|
Chris@16
|
2214 using std::frexp;
|
Chris@16
|
2215 using std::ldexp;
|
Chris@16
|
2216 using std::floor;
|
Chris@16
|
2217
|
Chris@101
|
2218 if(a == 0)
|
Chris@16
|
2219 return *this = zero();
|
Chris@101
|
2220
|
Chris@101
|
2221 if(a == 1)
|
Chris@16
|
2222 return *this = one();
|
Chris@16
|
2223
|
Chris@16
|
2224 if((boost::math::isinf)(a))
|
Chris@16
|
2225 return *this = inf();
|
Chris@101
|
2226
|
Chris@16
|
2227 if((boost::math::isnan)(a))
|
Chris@16
|
2228 return *this = nan();
|
Chris@16
|
2229
|
Chris@16
|
2230 int e;
|
Chris@16
|
2231 long double f, term;
|
Chris@16
|
2232 *this = zero();
|
Chris@16
|
2233
|
Chris@16
|
2234 f = frexp(a, &e);
|
Chris@101
|
2235 // See https://svn.boost.org/trac/boost/ticket/10924 for an example of why this may go wrong:
|
Chris@101
|
2236 BOOST_ASSERT((boost::math::isfinite)(f));
|
Chris@16
|
2237
|
Chris@16
|
2238 static const int shift = std::numeric_limits<int>::digits - 1;
|
Chris@16
|
2239
|
Chris@16
|
2240 while(f)
|
Chris@16
|
2241 {
|
Chris@16
|
2242 // extract int sized bits from f:
|
Chris@16
|
2243 f = ldexp(f, shift);
|
Chris@101
|
2244 BOOST_ASSERT((boost::math::isfinite)(f));
|
Chris@16
|
2245 term = floor(f);
|
Chris@16
|
2246 e -= shift;
|
Chris@16
|
2247 *this *= pow2(shift);
|
Chris@16
|
2248 if(term > 0)
|
Chris@16
|
2249 add_unsigned_long_long(static_cast<unsigned>(term));
|
Chris@16
|
2250 else
|
Chris@16
|
2251 sub_unsigned_long_long(static_cast<unsigned>(-term));
|
Chris@16
|
2252 f -= term;
|
Chris@16
|
2253 }
|
Chris@101
|
2254
|
Chris@16
|
2255 if(e != 0)
|
Chris@16
|
2256 *this *= pow2(e);
|
Chris@101
|
2257
|
Chris@16
|
2258 return *this;
|
Chris@16
|
2259 }
|
Chris@16
|
2260
|
Chris@16
|
2261 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2262 void cpp_dec_float<Digits10, ExponentType, Allocator>::from_unsigned_long_long(const unsigned long long u)
|
Chris@16
|
2263 {
|
Chris@16
|
2264 std::fill(data.begin(), data.end(), static_cast<boost::uint32_t>(0u));
|
Chris@16
|
2265
|
Chris@16
|
2266 exp = static_cast<ExponentType>(0);
|
Chris@16
|
2267 neg = false;
|
Chris@16
|
2268 fpclass = cpp_dec_float_finite;
|
Chris@16
|
2269 prec_elem = cpp_dec_float_elem_number;
|
Chris@16
|
2270
|
Chris@16
|
2271 std::size_t i =static_cast<std::size_t>(0u);
|
Chris@16
|
2272
|
Chris@16
|
2273 unsigned long long uu = u;
|
Chris@16
|
2274
|
Chris@16
|
2275 boost::uint32_t temp[(std::numeric_limits<unsigned long long>::digits10 / static_cast<int>(cpp_dec_float_elem_digits10)) + 3] = { static_cast<boost::uint32_t>(0u) };
|
Chris@16
|
2276
|
Chris@16
|
2277 while(uu != static_cast<unsigned long long>(0u))
|
Chris@16
|
2278 {
|
Chris@16
|
2279 temp[i] = static_cast<boost::uint32_t>(uu % static_cast<unsigned long long>(cpp_dec_float_elem_mask));
|
Chris@16
|
2280 uu = static_cast<unsigned long long>(uu / static_cast<unsigned long long>(cpp_dec_float_elem_mask));
|
Chris@16
|
2281 ++i;
|
Chris@16
|
2282 }
|
Chris@16
|
2283
|
Chris@16
|
2284 if(i > static_cast<std::size_t>(1u))
|
Chris@16
|
2285 {
|
Chris@16
|
2286 exp += static_cast<ExponentType>((i - 1u) * static_cast<std::size_t>(cpp_dec_float_elem_digits10));
|
Chris@16
|
2287 }
|
Chris@16
|
2288
|
Chris@16
|
2289 std::reverse(temp, temp + i);
|
Chris@16
|
2290 std::copy(temp, temp + (std::min)(i, static_cast<std::size_t>(cpp_dec_float_elem_number)), data.begin());
|
Chris@16
|
2291 }
|
Chris@16
|
2292
|
Chris@16
|
2293 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2294 boost::uint32_t cpp_dec_float<Digits10, ExponentType, Allocator>::mul_loop_uv(boost::uint32_t* const u, const boost::uint32_t* const v, const boost::int32_t p)
|
Chris@16
|
2295 {
|
Chris@16
|
2296 //
|
Chris@101
|
2297 // There is a limit on how many limbs this algorithm can handle without dropping digits
|
Chris@101
|
2298 // due to overflow in the carry, it is:
|
Chris@16
|
2299 //
|
Chris@101
|
2300 // FLOOR( (2^64 - 1) / (10^8 * 10^8) ) == 1844
|
Chris@16
|
2301 //
|
Chris@16
|
2302 BOOST_STATIC_ASSERT_MSG(cpp_dec_float_elem_number < 1800, "Too many limbs in the data type for the multiplication algorithm - unsupported precision in cpp_dec_float.");
|
Chris@16
|
2303
|
Chris@16
|
2304 boost::uint64_t carry = static_cast<boost::uint64_t>(0u);
|
Chris@16
|
2305
|
Chris@16
|
2306 for(boost::int32_t j = static_cast<boost::int32_t>(p - 1u); j >= static_cast<boost::int32_t>(0); j--)
|
Chris@16
|
2307 {
|
Chris@16
|
2308 boost::uint64_t sum = carry;
|
Chris@16
|
2309
|
Chris@16
|
2310 for(boost::int32_t i = j; i >= static_cast<boost::int32_t>(0); i--)
|
Chris@16
|
2311 {
|
Chris@16
|
2312 sum += static_cast<boost::uint64_t>(u[j - i] * static_cast<boost::uint64_t>(v[i]));
|
Chris@16
|
2313 }
|
Chris@16
|
2314
|
Chris@101
|
2315 u[j] = static_cast<boost::uint32_t>(sum % static_cast<boost::uint32_t>(cpp_dec_float_elem_mask));
|
Chris@16
|
2316 carry = static_cast<boost::uint64_t>(sum / static_cast<boost::uint32_t>(cpp_dec_float_elem_mask));
|
Chris@16
|
2317 }
|
Chris@16
|
2318
|
Chris@16
|
2319 return static_cast<boost::uint32_t>(carry);
|
Chris@16
|
2320 }
|
Chris@16
|
2321
|
Chris@16
|
2322 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2323 boost::uint32_t cpp_dec_float<Digits10, ExponentType, Allocator>::mul_loop_n(boost::uint32_t* const u, boost::uint32_t n, const boost::int32_t p)
|
Chris@16
|
2324 {
|
Chris@16
|
2325 boost::uint64_t carry = static_cast<boost::uint64_t>(0u);
|
Chris@16
|
2326
|
Chris@16
|
2327 // Multiplication loop.
|
Chris@16
|
2328 for(boost::int32_t j = p - 1; j >= static_cast<boost::int32_t>(0); j--)
|
Chris@16
|
2329 {
|
Chris@16
|
2330 const boost::uint64_t t = static_cast<boost::uint64_t>(carry + static_cast<boost::uint64_t>(u[j] * static_cast<boost::uint64_t>(n)));
|
Chris@101
|
2331 carry = static_cast<boost::uint64_t>(t / static_cast<boost::uint32_t>(cpp_dec_float_elem_mask));
|
Chris@101
|
2332 u[j] = static_cast<boost::uint32_t>(t - static_cast<boost::uint64_t>(static_cast<boost::uint32_t>(cpp_dec_float_elem_mask) * static_cast<boost::uint64_t>(carry)));
|
Chris@16
|
2333 }
|
Chris@16
|
2334
|
Chris@16
|
2335 return static_cast<boost::uint32_t>(carry);
|
Chris@16
|
2336 }
|
Chris@16
|
2337
|
Chris@16
|
2338 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2339 boost::uint32_t cpp_dec_float<Digits10, ExponentType, Allocator>::div_loop_n(boost::uint32_t* const u, boost::uint32_t n, const boost::int32_t p)
|
Chris@16
|
2340 {
|
Chris@16
|
2341 boost::uint64_t prev = static_cast<boost::uint64_t>(0u);
|
Chris@16
|
2342
|
Chris@16
|
2343 for(boost::int32_t j = static_cast<boost::int32_t>(0); j < p; j++)
|
Chris@16
|
2344 {
|
Chris@16
|
2345 const boost::uint64_t t = static_cast<boost::uint64_t>(u[j] + static_cast<boost::uint64_t>(prev * static_cast<boost::uint32_t>(cpp_dec_float_elem_mask)));
|
Chris@101
|
2346 u[j] = static_cast<boost::uint32_t>(t / n);
|
Chris@101
|
2347 prev = static_cast<boost::uint64_t>(t - static_cast<boost::uint64_t>(n * static_cast<boost::uint64_t>(u[j])));
|
Chris@16
|
2348 }
|
Chris@16
|
2349
|
Chris@16
|
2350 return static_cast<boost::uint32_t>(prev);
|
Chris@16
|
2351 }
|
Chris@16
|
2352
|
Chris@16
|
2353 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@16
|
2354 cpp_dec_float<Digits10, ExponentType, Allocator> cpp_dec_float<Digits10, ExponentType, Allocator>::pow2(const long long p)
|
Chris@16
|
2355 {
|
Chris@16
|
2356 // Create a static const table of p^2 for -128 < p < +128.
|
Chris@16
|
2357 // Note: The size of this table must be odd-numbered and
|
Chris@16
|
2358 // symmetric about 0.
|
Chris@16
|
2359 init.do_nothing();
|
Chris@16
|
2360 static const boost::array<cpp_dec_float<Digits10, ExponentType, Allocator>, 255u> p2_data =
|
Chris@16
|
2361 {{
|
Chris@16
|
2362 cpp_dec_float("5.877471754111437539843682686111228389093327783860437607543758531392086297273635864257812500000000000e-39"),
|
Chris@16
|
2363 cpp_dec_float("1.175494350822287507968736537222245677818665556772087521508751706278417259454727172851562500000000000e-38"),
|
Chris@16
|
2364 cpp_dec_float("2.350988701644575015937473074444491355637331113544175043017503412556834518909454345703125000000000000e-38"),
|
Chris@16
|
2365 cpp_dec_float("4.701977403289150031874946148888982711274662227088350086035006825113669037818908691406250000000000000e-38"),
|
Chris@16
|
2366 cpp_dec_float("9.403954806578300063749892297777965422549324454176700172070013650227338075637817382812500000000000000e-38"),
|
Chris@16
|
2367 cpp_dec_float("1.880790961315660012749978459555593084509864890835340034414002730045467615127563476562500000000000000e-37"),
|
Chris@16
|
2368 cpp_dec_float("3.761581922631320025499956919111186169019729781670680068828005460090935230255126953125000000000000000e-37"),
|
Chris@16
|
2369 cpp_dec_float("7.523163845262640050999913838222372338039459563341360137656010920181870460510253906250000000000000000e-37"),
|
Chris@16
|
2370 cpp_dec_float("1.504632769052528010199982767644474467607891912668272027531202184036374092102050781250000000000000000e-36"),
|
Chris@16
|
2371 cpp_dec_float("3.009265538105056020399965535288948935215783825336544055062404368072748184204101562500000000000000000e-36"),
|
Chris@16
|
2372 cpp_dec_float("6.018531076210112040799931070577897870431567650673088110124808736145496368408203125000000000000000000e-36"),
|
Chris@16
|
2373 cpp_dec_float("1.203706215242022408159986214115579574086313530134617622024961747229099273681640625000000000000000000e-35"),
|
Chris@16
|
2374 cpp_dec_float("2.407412430484044816319972428231159148172627060269235244049923494458198547363281250000000000000000000e-35"),
|
Chris@16
|
2375 cpp_dec_float("4.814824860968089632639944856462318296345254120538470488099846988916397094726562500000000000000000000e-35"),
|
Chris@16
|
2376 cpp_dec_float("9.629649721936179265279889712924636592690508241076940976199693977832794189453125000000000000000000000e-35"),
|
Chris@16
|
2377 cpp_dec_float("1.925929944387235853055977942584927318538101648215388195239938795566558837890625000000000000000000000e-34"),
|
Chris@16
|
2378 cpp_dec_float("3.851859888774471706111955885169854637076203296430776390479877591133117675781250000000000000000000000e-34"),
|
Chris@16
|
2379 cpp_dec_float("7.703719777548943412223911770339709274152406592861552780959755182266235351562500000000000000000000000e-34"),
|
Chris@16
|
2380 cpp_dec_float("1.540743955509788682444782354067941854830481318572310556191951036453247070312500000000000000000000000e-33"),
|
Chris@16
|
2381 cpp_dec_float("3.081487911019577364889564708135883709660962637144621112383902072906494140625000000000000000000000000e-33"),
|
Chris@16
|
2382 cpp_dec_float("6.162975822039154729779129416271767419321925274289242224767804145812988281250000000000000000000000000e-33"),
|
Chris@16
|
2383 cpp_dec_float("1.232595164407830945955825883254353483864385054857848444953560829162597656250000000000000000000000000e-32"),
|
Chris@16
|
2384 cpp_dec_float("2.465190328815661891911651766508706967728770109715696889907121658325195312500000000000000000000000000e-32"),
|
Chris@16
|
2385 cpp_dec_float("4.930380657631323783823303533017413935457540219431393779814243316650390625000000000000000000000000000e-32"),
|
Chris@16
|
2386 cpp_dec_float("9.860761315262647567646607066034827870915080438862787559628486633300781250000000000000000000000000000e-32"),
|
Chris@16
|
2387 cpp_dec_float("1.972152263052529513529321413206965574183016087772557511925697326660156250000000000000000000000000000e-31"),
|
Chris@16
|
2388 cpp_dec_float("3.944304526105059027058642826413931148366032175545115023851394653320312500000000000000000000000000000e-31"),
|
Chris@16
|
2389 cpp_dec_float("7.888609052210118054117285652827862296732064351090230047702789306640625000000000000000000000000000000e-31"),
|
Chris@16
|
2390 cpp_dec_float("1.577721810442023610823457130565572459346412870218046009540557861328125000000000000000000000000000000e-30"),
|
Chris@16
|
2391 cpp_dec_float("3.155443620884047221646914261131144918692825740436092019081115722656250000000000000000000000000000000e-30"),
|
Chris@16
|
2392 cpp_dec_float("6.310887241768094443293828522262289837385651480872184038162231445312500000000000000000000000000000000e-30"),
|
Chris@16
|
2393 cpp_dec_float("1.262177448353618888658765704452457967477130296174436807632446289062500000000000000000000000000000000e-29"),
|
Chris@16
|
2394 cpp_dec_float("2.524354896707237777317531408904915934954260592348873615264892578125000000000000000000000000000000000e-29"),
|
Chris@16
|
2395 cpp_dec_float("5.048709793414475554635062817809831869908521184697747230529785156250000000000000000000000000000000000e-29"),
|
Chris@16
|
2396 cpp_dec_float("1.009741958682895110927012563561966373981704236939549446105957031250000000000000000000000000000000000e-28"),
|
Chris@16
|
2397 cpp_dec_float("2.019483917365790221854025127123932747963408473879098892211914062500000000000000000000000000000000000e-28"),
|
Chris@16
|
2398 cpp_dec_float("4.038967834731580443708050254247865495926816947758197784423828125000000000000000000000000000000000000e-28"),
|
Chris@16
|
2399 cpp_dec_float("8.077935669463160887416100508495730991853633895516395568847656250000000000000000000000000000000000000e-28"),
|
Chris@16
|
2400 cpp_dec_float("1.615587133892632177483220101699146198370726779103279113769531250000000000000000000000000000000000000e-27"),
|
Chris@16
|
2401 cpp_dec_float("3.231174267785264354966440203398292396741453558206558227539062500000000000000000000000000000000000000e-27"),
|
Chris@16
|
2402 cpp_dec_float("6.462348535570528709932880406796584793482907116413116455078125000000000000000000000000000000000000000e-27"),
|
Chris@16
|
2403 cpp_dec_float("1.292469707114105741986576081359316958696581423282623291015625000000000000000000000000000000000000000e-26"),
|
Chris@16
|
2404 cpp_dec_float("2.584939414228211483973152162718633917393162846565246582031250000000000000000000000000000000000000000e-26"),
|
Chris@16
|
2405 cpp_dec_float("5.169878828456422967946304325437267834786325693130493164062500000000000000000000000000000000000000000e-26"),
|
Chris@16
|
2406 cpp_dec_float("1.033975765691284593589260865087453566957265138626098632812500000000000000000000000000000000000000000e-25"),
|
Chris@16
|
2407 cpp_dec_float("2.067951531382569187178521730174907133914530277252197265625000000000000000000000000000000000000000000e-25"),
|
Chris@16
|
2408 cpp_dec_float("4.135903062765138374357043460349814267829060554504394531250000000000000000000000000000000000000000000e-25"),
|
Chris@16
|
2409 cpp_dec_float("8.271806125530276748714086920699628535658121109008789062500000000000000000000000000000000000000000000e-25"),
|
Chris@16
|
2410 cpp_dec_float("1.654361225106055349742817384139925707131624221801757812500000000000000000000000000000000000000000000e-24"),
|
Chris@16
|
2411 cpp_dec_float("3.308722450212110699485634768279851414263248443603515625000000000000000000000000000000000000000000000e-24"),
|
Chris@16
|
2412 cpp_dec_float("6.617444900424221398971269536559702828526496887207031250000000000000000000000000000000000000000000000e-24"),
|
Chris@16
|
2413 cpp_dec_float("1.323488980084844279794253907311940565705299377441406250000000000000000000000000000000000000000000000e-23"),
|
Chris@16
|
2414 cpp_dec_float("2.646977960169688559588507814623881131410598754882812500000000000000000000000000000000000000000000000e-23"),
|
Chris@16
|
2415 cpp_dec_float("5.293955920339377119177015629247762262821197509765625000000000000000000000000000000000000000000000000e-23"),
|
Chris@16
|
2416 cpp_dec_float("1.058791184067875423835403125849552452564239501953125000000000000000000000000000000000000000000000000e-22"),
|
Chris@16
|
2417 cpp_dec_float("2.117582368135750847670806251699104905128479003906250000000000000000000000000000000000000000000000000e-22"),
|
Chris@16
|
2418 cpp_dec_float("4.235164736271501695341612503398209810256958007812500000000000000000000000000000000000000000000000000e-22"),
|
Chris@16
|
2419 cpp_dec_float("8.470329472543003390683225006796419620513916015625000000000000000000000000000000000000000000000000000e-22"),
|
Chris@16
|
2420 cpp_dec_float("1.694065894508600678136645001359283924102783203125000000000000000000000000000000000000000000000000000e-21"),
|
Chris@16
|
2421 cpp_dec_float("3.388131789017201356273290002718567848205566406250000000000000000000000000000000000000000000000000000e-21"),
|
Chris@16
|
2422 cpp_dec_float("6.776263578034402712546580005437135696411132812500000000000000000000000000000000000000000000000000000e-21"),
|
Chris@16
|
2423 cpp_dec_float("1.355252715606880542509316001087427139282226562500000000000000000000000000000000000000000000000000000e-20"),
|
Chris@16
|
2424 cpp_dec_float("2.710505431213761085018632002174854278564453125000000000000000000000000000000000000000000000000000000e-20"),
|
Chris@16
|
2425 cpp_dec_float("5.421010862427522170037264004349708557128906250000000000000000000000000000000000000000000000000000000e-20"),
|
Chris@16
|
2426 cpp_dec_float("1.084202172485504434007452800869941711425781250000000000000000000000000000000000000000000000000000000e-19"),
|
Chris@16
|
2427 cpp_dec_float("2.168404344971008868014905601739883422851562500000000000000000000000000000000000000000000000000000000e-19"),
|
Chris@16
|
2428 cpp_dec_float("4.336808689942017736029811203479766845703125000000000000000000000000000000000000000000000000000000000e-19"),
|
Chris@16
|
2429 cpp_dec_float("8.673617379884035472059622406959533691406250000000000000000000000000000000000000000000000000000000000e-19"),
|
Chris@16
|
2430 cpp_dec_float("1.734723475976807094411924481391906738281250000000000000000000000000000000000000000000000000000000000e-18"),
|
Chris@16
|
2431 cpp_dec_float("3.469446951953614188823848962783813476562500000000000000000000000000000000000000000000000000000000000e-18"),
|
Chris@16
|
2432 cpp_dec_float("6.938893903907228377647697925567626953125000000000000000000000000000000000000000000000000000000000000e-18"),
|
Chris@16
|
2433 cpp_dec_float("1.387778780781445675529539585113525390625000000000000000000000000000000000000000000000000000000000000e-17"),
|
Chris@16
|
2434 cpp_dec_float("2.775557561562891351059079170227050781250000000000000000000000000000000000000000000000000000000000000e-17"),
|
Chris@16
|
2435 cpp_dec_float("5.551115123125782702118158340454101562500000000000000000000000000000000000000000000000000000000000000e-17"),
|
Chris@16
|
2436 cpp_dec_float("1.110223024625156540423631668090820312500000000000000000000000000000000000000000000000000000000000000e-16"),
|
Chris@16
|
2437 cpp_dec_float("2.220446049250313080847263336181640625000000000000000000000000000000000000000000000000000000000000000e-16"),
|
Chris@16
|
2438 cpp_dec_float("4.440892098500626161694526672363281250000000000000000000000000000000000000000000000000000000000000000e-16"),
|
Chris@16
|
2439 cpp_dec_float("8.881784197001252323389053344726562500000000000000000000000000000000000000000000000000000000000000000e-16"),
|
Chris@16
|
2440 cpp_dec_float("1.776356839400250464677810668945312500000000000000000000000000000000000000000000000000000000000000000e-15"),
|
Chris@16
|
2441 cpp_dec_float("3.552713678800500929355621337890625000000000000000000000000000000000000000000000000000000000000000000e-15"),
|
Chris@16
|
2442 cpp_dec_float("7.105427357601001858711242675781250000000000000000000000000000000000000000000000000000000000000000000e-15"),
|
Chris@16
|
2443 cpp_dec_float("1.421085471520200371742248535156250000000000000000000000000000000000000000000000000000000000000000000e-14"),
|
Chris@16
|
2444 cpp_dec_float("2.842170943040400743484497070312500000000000000000000000000000000000000000000000000000000000000000000e-14"),
|
Chris@16
|
2445 cpp_dec_float("5.684341886080801486968994140625000000000000000000000000000000000000000000000000000000000000000000000e-14"),
|
Chris@16
|
2446 cpp_dec_float("1.136868377216160297393798828125000000000000000000000000000000000000000000000000000000000000000000000e-13"),
|
Chris@16
|
2447 cpp_dec_float("2.273736754432320594787597656250000000000000000000000000000000000000000000000000000000000000000000000e-13"),
|
Chris@16
|
2448 cpp_dec_float("4.547473508864641189575195312500000000000000000000000000000000000000000000000000000000000000000000000e-13"),
|
Chris@16
|
2449 cpp_dec_float("9.094947017729282379150390625000000000000000000000000000000000000000000000000000000000000000000000000e-13"),
|
Chris@16
|
2450 cpp_dec_float("1.818989403545856475830078125000000000000000000000000000000000000000000000000000000000000000000000000e-12"),
|
Chris@16
|
2451 cpp_dec_float("3.637978807091712951660156250000000000000000000000000000000000000000000000000000000000000000000000000e-12"),
|
Chris@16
|
2452 cpp_dec_float("7.275957614183425903320312500000000000000000000000000000000000000000000000000000000000000000000000000e-12"),
|
Chris@16
|
2453 cpp_dec_float("1.455191522836685180664062500000000000000000000000000000000000000000000000000000000000000000000000000e-11"),
|
Chris@16
|
2454 cpp_dec_float("2.910383045673370361328125000000000000000000000000000000000000000000000000000000000000000000000000000e-11"),
|
Chris@16
|
2455 cpp_dec_float("5.820766091346740722656250000000000000000000000000000000000000000000000000000000000000000000000000000e-11"),
|
Chris@16
|
2456 cpp_dec_float("1.164153218269348144531250000000000000000000000000000000000000000000000000000000000000000000000000000e-10"),
|
Chris@16
|
2457 cpp_dec_float("2.328306436538696289062500000000000000000000000000000000000000000000000000000000000000000000000000000e-10"),
|
Chris@16
|
2458 cpp_dec_float("4.656612873077392578125000000000000000000000000000000000000000000000000000000000000000000000000000000e-10"),
|
Chris@16
|
2459 cpp_dec_float("9.313225746154785156250000000000000000000000000000000000000000000000000000000000000000000000000000000e-10"),
|
Chris@16
|
2460 cpp_dec_float("1.862645149230957031250000000000000000000000000000000000000000000000000000000000000000000000000000000e-9"),
|
Chris@16
|
2461 cpp_dec_float("3.725290298461914062500000000000000000000000000000000000000000000000000000000000000000000000000000000e-9"),
|
Chris@16
|
2462 cpp_dec_float("7.450580596923828125000000000000000000000000000000000000000000000000000000000000000000000000000000000e-9"),
|
Chris@16
|
2463 cpp_dec_float("1.490116119384765625000000000000000000000000000000000000000000000000000000000000000000000000000000000e-8"),
|
Chris@16
|
2464 cpp_dec_float("2.980232238769531250000000000000000000000000000000000000000000000000000000000000000000000000000000000e-8"),
|
Chris@16
|
2465 cpp_dec_float("5.960464477539062500000000000000000000000000000000000000000000000000000000000000000000000000000000000e-8"),
|
Chris@16
|
2466 cpp_dec_float("1.192092895507812500000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7"),
|
Chris@16
|
2467 cpp_dec_float("2.384185791015625000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7"),
|
Chris@16
|
2468 cpp_dec_float("4.768371582031250000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7"),
|
Chris@16
|
2469 cpp_dec_float("9.536743164062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-7"),
|
Chris@16
|
2470 cpp_dec_float("1.907348632812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6"),
|
Chris@16
|
2471 cpp_dec_float("3.814697265625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6"),
|
Chris@16
|
2472 cpp_dec_float("7.629394531250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e-6"),
|
Chris@16
|
2473 cpp_dec_float("0.000015258789062500000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
|
Chris@16
|
2474 cpp_dec_float("0.000030517578125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
|
Chris@16
|
2475 cpp_dec_float("0.000061035156250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
|
Chris@16
|
2476 cpp_dec_float("0.000122070312500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
|
Chris@16
|
2477 cpp_dec_float("0.000244140625000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
|
Chris@16
|
2478 cpp_dec_float("0.000488281250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
|
Chris@16
|
2479 cpp_dec_float("0.000976562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
|
Chris@16
|
2480 cpp_dec_float("0.001953125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
|
Chris@16
|
2481 cpp_dec_float("0.003906250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
|
Chris@16
|
2482 cpp_dec_float("0.007812500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
|
Chris@16
|
2483 cpp_dec_float("0.01562500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
|
Chris@16
|
2484 cpp_dec_float("0.03125000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
|
Chris@16
|
2485 cpp_dec_float("0.06250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
|
Chris@16
|
2486 cpp_dec_float("0.125"),
|
Chris@16
|
2487 cpp_dec_float("0.25"),
|
Chris@16
|
2488 cpp_dec_float("0.5"),
|
Chris@16
|
2489 one(),
|
Chris@16
|
2490 two(),
|
Chris@16
|
2491 cpp_dec_float(static_cast<unsigned long long>(4)),
|
Chris@16
|
2492 cpp_dec_float(static_cast<unsigned long long>(8)),
|
Chris@16
|
2493 cpp_dec_float(static_cast<unsigned long long>(16)),
|
Chris@16
|
2494 cpp_dec_float(static_cast<unsigned long long>(32)),
|
Chris@16
|
2495 cpp_dec_float(static_cast<unsigned long long>(64)),
|
Chris@16
|
2496 cpp_dec_float(static_cast<unsigned long long>(128)),
|
Chris@16
|
2497 cpp_dec_float(static_cast<unsigned long long>(256)),
|
Chris@16
|
2498 cpp_dec_float(static_cast<unsigned long long>(512)),
|
Chris@16
|
2499 cpp_dec_float(static_cast<unsigned long long>(1024)),
|
Chris@16
|
2500 cpp_dec_float(static_cast<unsigned long long>(2048)),
|
Chris@16
|
2501 cpp_dec_float(static_cast<unsigned long long>(4096)),
|
Chris@16
|
2502 cpp_dec_float(static_cast<unsigned long long>(8192)),
|
Chris@16
|
2503 cpp_dec_float(static_cast<unsigned long long>(16384)),
|
Chris@16
|
2504 cpp_dec_float(static_cast<unsigned long long>(32768)),
|
Chris@16
|
2505 cpp_dec_float(static_cast<unsigned long long>(65536)),
|
Chris@16
|
2506 cpp_dec_float(static_cast<unsigned long long>(131072)),
|
Chris@16
|
2507 cpp_dec_float(static_cast<unsigned long long>(262144)),
|
Chris@16
|
2508 cpp_dec_float(static_cast<unsigned long long>(524288)),
|
Chris@16
|
2509 cpp_dec_float(static_cast<boost::uint64_t>(1uL << 20u)),
|
Chris@16
|
2510 cpp_dec_float(static_cast<boost::uint64_t>(1uL << 21u)),
|
Chris@16
|
2511 cpp_dec_float(static_cast<boost::uint64_t>(1uL << 22u)),
|
Chris@16
|
2512 cpp_dec_float(static_cast<boost::uint64_t>(1uL << 23u)),
|
Chris@16
|
2513 cpp_dec_float(static_cast<boost::uint64_t>(1uL << 24u)),
|
Chris@16
|
2514 cpp_dec_float(static_cast<boost::uint64_t>(1uL << 25u)),
|
Chris@16
|
2515 cpp_dec_float(static_cast<boost::uint64_t>(1uL << 26u)),
|
Chris@16
|
2516 cpp_dec_float(static_cast<boost::uint64_t>(1uL << 27u)),
|
Chris@16
|
2517 cpp_dec_float(static_cast<boost::uint64_t>(1uL << 28u)),
|
Chris@16
|
2518 cpp_dec_float(static_cast<boost::uint64_t>(1uL << 29u)),
|
Chris@16
|
2519 cpp_dec_float(static_cast<boost::uint64_t>(1uL << 30u)),
|
Chris@16
|
2520 cpp_dec_float(static_cast<boost::uint64_t>(1uL << 31u)),
|
Chris@16
|
2521 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 32u)),
|
Chris@16
|
2522 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 33u)),
|
Chris@16
|
2523 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 34u)),
|
Chris@16
|
2524 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 35u)),
|
Chris@16
|
2525 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 36u)),
|
Chris@16
|
2526 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 37u)),
|
Chris@16
|
2527 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 38u)),
|
Chris@16
|
2528 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 39u)),
|
Chris@16
|
2529 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 40u)),
|
Chris@16
|
2530 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 41u)),
|
Chris@16
|
2531 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 42u)),
|
Chris@16
|
2532 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 43u)),
|
Chris@16
|
2533 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 44u)),
|
Chris@16
|
2534 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 45u)),
|
Chris@16
|
2535 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 46u)),
|
Chris@16
|
2536 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 47u)),
|
Chris@16
|
2537 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 48u)),
|
Chris@16
|
2538 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 49u)),
|
Chris@16
|
2539 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 50u)),
|
Chris@16
|
2540 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 51u)),
|
Chris@16
|
2541 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 52u)),
|
Chris@16
|
2542 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 53u)),
|
Chris@16
|
2543 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 54u)),
|
Chris@16
|
2544 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 55u)),
|
Chris@16
|
2545 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 56u)),
|
Chris@16
|
2546 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 57u)),
|
Chris@16
|
2547 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 58u)),
|
Chris@16
|
2548 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 59u)),
|
Chris@16
|
2549 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 60u)),
|
Chris@16
|
2550 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 61u)),
|
Chris@16
|
2551 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 62u)),
|
Chris@16
|
2552 cpp_dec_float(static_cast<boost::uint64_t>(1uLL << 63u)),
|
Chris@16
|
2553 cpp_dec_float("1.844674407370955161600000000000000000000000000000000000000000000000000000000000000000000000000000000e19"),
|
Chris@16
|
2554 cpp_dec_float("3.689348814741910323200000000000000000000000000000000000000000000000000000000000000000000000000000000e19"),
|
Chris@16
|
2555 cpp_dec_float("7.378697629483820646400000000000000000000000000000000000000000000000000000000000000000000000000000000e19"),
|
Chris@16
|
2556 cpp_dec_float("1.475739525896764129280000000000000000000000000000000000000000000000000000000000000000000000000000000e20"),
|
Chris@16
|
2557 cpp_dec_float("2.951479051793528258560000000000000000000000000000000000000000000000000000000000000000000000000000000e20"),
|
Chris@16
|
2558 cpp_dec_float("5.902958103587056517120000000000000000000000000000000000000000000000000000000000000000000000000000000e20"),
|
Chris@16
|
2559 cpp_dec_float("1.180591620717411303424000000000000000000000000000000000000000000000000000000000000000000000000000000e21"),
|
Chris@16
|
2560 cpp_dec_float("2.361183241434822606848000000000000000000000000000000000000000000000000000000000000000000000000000000e21"),
|
Chris@16
|
2561 cpp_dec_float("4.722366482869645213696000000000000000000000000000000000000000000000000000000000000000000000000000000e21"),
|
Chris@16
|
2562 cpp_dec_float("9.444732965739290427392000000000000000000000000000000000000000000000000000000000000000000000000000000e21"),
|
Chris@16
|
2563 cpp_dec_float("1.888946593147858085478400000000000000000000000000000000000000000000000000000000000000000000000000000e22"),
|
Chris@16
|
2564 cpp_dec_float("3.777893186295716170956800000000000000000000000000000000000000000000000000000000000000000000000000000e22"),
|
Chris@16
|
2565 cpp_dec_float("7.555786372591432341913600000000000000000000000000000000000000000000000000000000000000000000000000000e22"),
|
Chris@16
|
2566 cpp_dec_float("1.511157274518286468382720000000000000000000000000000000000000000000000000000000000000000000000000000e23"),
|
Chris@16
|
2567 cpp_dec_float("3.022314549036572936765440000000000000000000000000000000000000000000000000000000000000000000000000000e23"),
|
Chris@16
|
2568 cpp_dec_float("6.044629098073145873530880000000000000000000000000000000000000000000000000000000000000000000000000000e23"),
|
Chris@16
|
2569 cpp_dec_float("1.208925819614629174706176000000000000000000000000000000000000000000000000000000000000000000000000000e24"),
|
Chris@16
|
2570 cpp_dec_float("2.417851639229258349412352000000000000000000000000000000000000000000000000000000000000000000000000000e24"),
|
Chris@16
|
2571 cpp_dec_float("4.835703278458516698824704000000000000000000000000000000000000000000000000000000000000000000000000000e24"),
|
Chris@16
|
2572 cpp_dec_float("9.671406556917033397649408000000000000000000000000000000000000000000000000000000000000000000000000000e24"),
|
Chris@16
|
2573 cpp_dec_float("1.934281311383406679529881600000000000000000000000000000000000000000000000000000000000000000000000000e25"),
|
Chris@16
|
2574 cpp_dec_float("3.868562622766813359059763200000000000000000000000000000000000000000000000000000000000000000000000000e25"),
|
Chris@16
|
2575 cpp_dec_float("7.737125245533626718119526400000000000000000000000000000000000000000000000000000000000000000000000000e25"),
|
Chris@16
|
2576 cpp_dec_float("1.547425049106725343623905280000000000000000000000000000000000000000000000000000000000000000000000000e26"),
|
Chris@16
|
2577 cpp_dec_float("3.094850098213450687247810560000000000000000000000000000000000000000000000000000000000000000000000000e26"),
|
Chris@16
|
2578 cpp_dec_float("6.189700196426901374495621120000000000000000000000000000000000000000000000000000000000000000000000000e26"),
|
Chris@16
|
2579 cpp_dec_float("1.237940039285380274899124224000000000000000000000000000000000000000000000000000000000000000000000000e27"),
|
Chris@16
|
2580 cpp_dec_float("2.475880078570760549798248448000000000000000000000000000000000000000000000000000000000000000000000000e27"),
|
Chris@16
|
2581 cpp_dec_float("4.951760157141521099596496896000000000000000000000000000000000000000000000000000000000000000000000000e27"),
|
Chris@16
|
2582 cpp_dec_float("9.903520314283042199192993792000000000000000000000000000000000000000000000000000000000000000000000000e27"),
|
Chris@16
|
2583 cpp_dec_float("1.980704062856608439838598758400000000000000000000000000000000000000000000000000000000000000000000000e28"),
|
Chris@16
|
2584 cpp_dec_float("3.961408125713216879677197516800000000000000000000000000000000000000000000000000000000000000000000000e28"),
|
Chris@16
|
2585 cpp_dec_float("7.922816251426433759354395033600000000000000000000000000000000000000000000000000000000000000000000000e28"),
|
Chris@16
|
2586 cpp_dec_float("1.584563250285286751870879006720000000000000000000000000000000000000000000000000000000000000000000000e29"),
|
Chris@16
|
2587 cpp_dec_float("3.169126500570573503741758013440000000000000000000000000000000000000000000000000000000000000000000000e29"),
|
Chris@16
|
2588 cpp_dec_float("6.338253001141147007483516026880000000000000000000000000000000000000000000000000000000000000000000000e29"),
|
Chris@16
|
2589 cpp_dec_float("1.267650600228229401496703205376000000000000000000000000000000000000000000000000000000000000000000000e30"),
|
Chris@16
|
2590 cpp_dec_float("2.535301200456458802993406410752000000000000000000000000000000000000000000000000000000000000000000000e30"),
|
Chris@16
|
2591 cpp_dec_float("5.070602400912917605986812821504000000000000000000000000000000000000000000000000000000000000000000000e30"),
|
Chris@16
|
2592 cpp_dec_float("1.014120480182583521197362564300800000000000000000000000000000000000000000000000000000000000000000000e31"),
|
Chris@16
|
2593 cpp_dec_float("2.028240960365167042394725128601600000000000000000000000000000000000000000000000000000000000000000000e31"),
|
Chris@16
|
2594 cpp_dec_float("4.056481920730334084789450257203200000000000000000000000000000000000000000000000000000000000000000000e31"),
|
Chris@16
|
2595 cpp_dec_float("8.112963841460668169578900514406400000000000000000000000000000000000000000000000000000000000000000000e31"),
|
Chris@16
|
2596 cpp_dec_float("1.622592768292133633915780102881280000000000000000000000000000000000000000000000000000000000000000000e32"),
|
Chris@16
|
2597 cpp_dec_float("3.245185536584267267831560205762560000000000000000000000000000000000000000000000000000000000000000000e32"),
|
Chris@16
|
2598 cpp_dec_float("6.490371073168534535663120411525120000000000000000000000000000000000000000000000000000000000000000000e32"),
|
Chris@16
|
2599 cpp_dec_float("1.298074214633706907132624082305024000000000000000000000000000000000000000000000000000000000000000000e33"),
|
Chris@16
|
2600 cpp_dec_float("2.596148429267413814265248164610048000000000000000000000000000000000000000000000000000000000000000000e33"),
|
Chris@16
|
2601 cpp_dec_float("5.192296858534827628530496329220096000000000000000000000000000000000000000000000000000000000000000000e33"),
|
Chris@16
|
2602 cpp_dec_float("1.038459371706965525706099265844019200000000000000000000000000000000000000000000000000000000000000000e34"),
|
Chris@16
|
2603 cpp_dec_float("2.076918743413931051412198531688038400000000000000000000000000000000000000000000000000000000000000000e34"),
|
Chris@16
|
2604 cpp_dec_float("4.153837486827862102824397063376076800000000000000000000000000000000000000000000000000000000000000000e34"),
|
Chris@16
|
2605 cpp_dec_float("8.307674973655724205648794126752153600000000000000000000000000000000000000000000000000000000000000000e34"),
|
Chris@16
|
2606 cpp_dec_float("1.661534994731144841129758825350430720000000000000000000000000000000000000000000000000000000000000000e35"),
|
Chris@16
|
2607 cpp_dec_float("3.323069989462289682259517650700861440000000000000000000000000000000000000000000000000000000000000000e35"),
|
Chris@16
|
2608 cpp_dec_float("6.646139978924579364519035301401722880000000000000000000000000000000000000000000000000000000000000000e35"),
|
Chris@16
|
2609 cpp_dec_float("1.329227995784915872903807060280344576000000000000000000000000000000000000000000000000000000000000000e36"),
|
Chris@16
|
2610 cpp_dec_float("2.658455991569831745807614120560689152000000000000000000000000000000000000000000000000000000000000000e36"),
|
Chris@16
|
2611 cpp_dec_float("5.316911983139663491615228241121378304000000000000000000000000000000000000000000000000000000000000000e36"),
|
Chris@16
|
2612 cpp_dec_float("1.063382396627932698323045648224275660800000000000000000000000000000000000000000000000000000000000000e37"),
|
Chris@16
|
2613 cpp_dec_float("2.126764793255865396646091296448551321600000000000000000000000000000000000000000000000000000000000000e37"),
|
Chris@16
|
2614 cpp_dec_float("4.253529586511730793292182592897102643200000000000000000000000000000000000000000000000000000000000000e37"),
|
Chris@16
|
2615 cpp_dec_float("8.507059173023461586584365185794205286400000000000000000000000000000000000000000000000000000000000000e37"),
|
Chris@16
|
2616 cpp_dec_float("1.701411834604692317316873037158841057280000000000000000000000000000000000000000000000000000000000000e38")
|
Chris@16
|
2617 }};
|
Chris@16
|
2618
|
Chris@16
|
2619 if((p > static_cast<long long>(-128)) && (p < static_cast<long long>(+128)))
|
Chris@16
|
2620 {
|
Chris@16
|
2621 return p2_data[static_cast<std::size_t>(p + ((p2_data.size() - 1u) / 2u))];
|
Chris@16
|
2622 }
|
Chris@16
|
2623 else
|
Chris@16
|
2624 {
|
Chris@16
|
2625 // Compute and return 2^p.
|
Chris@16
|
2626 if(p < static_cast<long long>(0))
|
Chris@16
|
2627 {
|
Chris@16
|
2628 return pow2(static_cast<long long>(-p)).calculate_inv();
|
Chris@16
|
2629 }
|
Chris@16
|
2630 else
|
Chris@16
|
2631 {
|
Chris@16
|
2632 cpp_dec_float<Digits10, ExponentType, Allocator> t;
|
Chris@16
|
2633 default_ops::detail::pow_imp(t, two(), p, mpl::true_());
|
Chris@16
|
2634 return t;
|
Chris@16
|
2635 }
|
Chris@16
|
2636 }
|
Chris@16
|
2637 }
|
Chris@16
|
2638
|
Chris@16
|
2639
|
Chris@16
|
2640 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2641 inline void eval_add(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& o)
|
Chris@16
|
2642 {
|
Chris@16
|
2643 result += o;
|
Chris@16
|
2644 }
|
Chris@16
|
2645 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2646 inline void eval_subtract(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& o)
|
Chris@16
|
2647 {
|
Chris@16
|
2648 result -= o;
|
Chris@16
|
2649 }
|
Chris@16
|
2650 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2651 inline void eval_multiply(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& o)
|
Chris@16
|
2652 {
|
Chris@16
|
2653 result *= o;
|
Chris@16
|
2654 }
|
Chris@16
|
2655 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2656 inline void eval_divide(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& o)
|
Chris@16
|
2657 {
|
Chris@16
|
2658 result /= o;
|
Chris@16
|
2659 }
|
Chris@16
|
2660
|
Chris@16
|
2661 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2662 inline void eval_add(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const unsigned long long& o)
|
Chris@16
|
2663 {
|
Chris@16
|
2664 result.add_unsigned_long_long(o);
|
Chris@16
|
2665 }
|
Chris@16
|
2666 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2667 inline void eval_subtract(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const unsigned long long& o)
|
Chris@16
|
2668 {
|
Chris@16
|
2669 result.sub_unsigned_long_long(o);
|
Chris@16
|
2670 }
|
Chris@16
|
2671 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2672 inline void eval_multiply(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const unsigned long long& o)
|
Chris@16
|
2673 {
|
Chris@16
|
2674 result.mul_unsigned_long_long(o);
|
Chris@16
|
2675 }
|
Chris@16
|
2676 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2677 inline void eval_divide(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const unsigned long long& o)
|
Chris@16
|
2678 {
|
Chris@16
|
2679 result.div_unsigned_long_long(o);
|
Chris@16
|
2680 }
|
Chris@16
|
2681
|
Chris@16
|
2682 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2683 inline void eval_add(cpp_dec_float<Digits10, ExponentType, Allocator>& result, long long o)
|
Chris@16
|
2684 {
|
Chris@16
|
2685 if(o < 0)
|
Chris@101
|
2686 result.sub_unsigned_long_long(boost::multiprecision::detail::unsigned_abs(o));
|
Chris@16
|
2687 else
|
Chris@16
|
2688 result.add_unsigned_long_long(o);
|
Chris@16
|
2689 }
|
Chris@16
|
2690 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2691 inline void eval_subtract(cpp_dec_float<Digits10, ExponentType, Allocator>& result, long long o)
|
Chris@16
|
2692 {
|
Chris@16
|
2693 if(o < 0)
|
Chris@101
|
2694 result.add_unsigned_long_long(boost::multiprecision::detail::unsigned_abs(o));
|
Chris@16
|
2695 else
|
Chris@16
|
2696 result.sub_unsigned_long_long(o);
|
Chris@16
|
2697 }
|
Chris@16
|
2698 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2699 inline void eval_multiply(cpp_dec_float<Digits10, ExponentType, Allocator>& result, long long o)
|
Chris@16
|
2700 {
|
Chris@16
|
2701 if(o < 0)
|
Chris@16
|
2702 {
|
Chris@101
|
2703 result.mul_unsigned_long_long(boost::multiprecision::detail::unsigned_abs(o));
|
Chris@16
|
2704 result.negate();
|
Chris@16
|
2705 }
|
Chris@16
|
2706 else
|
Chris@16
|
2707 result.mul_unsigned_long_long(o);
|
Chris@16
|
2708 }
|
Chris@16
|
2709 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2710 inline void eval_divide(cpp_dec_float<Digits10, ExponentType, Allocator>& result, long long o)
|
Chris@16
|
2711 {
|
Chris@16
|
2712 if(o < 0)
|
Chris@16
|
2713 {
|
Chris@101
|
2714 result.div_unsigned_long_long(boost::multiprecision::detail::unsigned_abs(o));
|
Chris@16
|
2715 result.negate();
|
Chris@16
|
2716 }
|
Chris@16
|
2717 else
|
Chris@16
|
2718 result.div_unsigned_long_long(o);
|
Chris@16
|
2719 }
|
Chris@16
|
2720
|
Chris@16
|
2721 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2722 inline void eval_convert_to(unsigned long long* result, const cpp_dec_float<Digits10, ExponentType, Allocator>& val)
|
Chris@16
|
2723 {
|
Chris@16
|
2724 *result = val.extract_unsigned_long_long();
|
Chris@16
|
2725 }
|
Chris@16
|
2726 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2727 inline void eval_convert_to(long long* result, const cpp_dec_float<Digits10, ExponentType, Allocator>& val)
|
Chris@16
|
2728 {
|
Chris@16
|
2729 *result = val.extract_signed_long_long();
|
Chris@16
|
2730 }
|
Chris@16
|
2731 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@16
|
2732 inline void eval_convert_to(long double* result, cpp_dec_float<Digits10, ExponentType, Allocator>& val)
|
Chris@16
|
2733 {
|
Chris@16
|
2734 *result = val.extract_long_double();
|
Chris@16
|
2735 }
|
Chris@16
|
2736
|
Chris@16
|
2737 //
|
Chris@16
|
2738 // Non member function support:
|
Chris@16
|
2739 //
|
Chris@16
|
2740 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2741 inline int eval_fpclassify(const cpp_dec_float<Digits10, ExponentType, Allocator>& x)
|
Chris@16
|
2742 {
|
Chris@16
|
2743 if((x.isinf)())
|
Chris@16
|
2744 return FP_INFINITE;
|
Chris@16
|
2745 if((x.isnan)())
|
Chris@16
|
2746 return FP_NAN;
|
Chris@16
|
2747 if(x.iszero())
|
Chris@16
|
2748 return FP_ZERO;
|
Chris@16
|
2749 return FP_NORMAL;
|
Chris@16
|
2750 }
|
Chris@16
|
2751
|
Chris@16
|
2752 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2753 inline void eval_abs(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& x)
|
Chris@16
|
2754 {
|
Chris@16
|
2755 result = x;
|
Chris@16
|
2756 if(x.isneg())
|
Chris@16
|
2757 result.negate();
|
Chris@16
|
2758 }
|
Chris@16
|
2759
|
Chris@16
|
2760 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2761 inline void eval_fabs(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& x)
|
Chris@16
|
2762 {
|
Chris@16
|
2763 result = x;
|
Chris@16
|
2764 if(x.isneg())
|
Chris@16
|
2765 result.negate();
|
Chris@16
|
2766 }
|
Chris@16
|
2767
|
Chris@16
|
2768 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2769 inline void eval_sqrt(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& x)
|
Chris@16
|
2770 {
|
Chris@16
|
2771 result = x;
|
Chris@16
|
2772 result.calculate_sqrt();
|
Chris@16
|
2773 }
|
Chris@16
|
2774
|
Chris@16
|
2775 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2776 inline void eval_floor(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& x)
|
Chris@16
|
2777 {
|
Chris@16
|
2778 result = x;
|
Chris@101
|
2779 if(!(x.isfinite)() || x.isint())
|
Chris@101
|
2780 {
|
Chris@101
|
2781 return;
|
Chris@16
|
2782 }
|
Chris@16
|
2783
|
Chris@16
|
2784 if(x.isneg())
|
Chris@16
|
2785 result -= cpp_dec_float<Digits10, ExponentType, Allocator>::one();
|
Chris@16
|
2786 result = result.extract_integer_part();
|
Chris@16
|
2787 }
|
Chris@16
|
2788
|
Chris@16
|
2789 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2790 inline void eval_ceil(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& x)
|
Chris@16
|
2791 {
|
Chris@16
|
2792 result = x;
|
Chris@101
|
2793 if(!(x.isfinite)() || x.isint())
|
Chris@101
|
2794 {
|
Chris@101
|
2795 return;
|
Chris@16
|
2796 }
|
Chris@16
|
2797
|
Chris@16
|
2798 if(!x.isneg())
|
Chris@16
|
2799 result += cpp_dec_float<Digits10, ExponentType, Allocator>::one();
|
Chris@16
|
2800 result = result.extract_integer_part();
|
Chris@16
|
2801 }
|
Chris@16
|
2802
|
Chris@16
|
2803 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@16
|
2804 inline void eval_trunc(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& x)
|
Chris@16
|
2805 {
|
Chris@101
|
2806 if(!(x.isfinite)())
|
Chris@101
|
2807 {
|
Chris@16
|
2808 result = boost::math::policies::raise_rounding_error("boost::multiprecision::trunc<%1%>(%1%)", 0, number<cpp_dec_float<Digits10, ExponentType, Allocator> >(x), number<cpp_dec_float<Digits10, ExponentType, Allocator> >(x), boost::math::policies::policy<>()).backend();
|
Chris@16
|
2809 return;
|
Chris@16
|
2810 }
|
Chris@16
|
2811 else if(x.isint())
|
Chris@16
|
2812 {
|
Chris@16
|
2813 result = x;
|
Chris@16
|
2814 return;
|
Chris@16
|
2815 }
|
Chris@16
|
2816 result = x.extract_integer_part();
|
Chris@16
|
2817 }
|
Chris@16
|
2818
|
Chris@101
|
2819 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2820 inline ExponentType eval_ilogb(const cpp_dec_float<Digits10, ExponentType, Allocator>& val)
|
Chris@101
|
2821 {
|
Chris@101
|
2822 // Set result, to the exponent of val:
|
Chris@101
|
2823 return val.order();
|
Chris@101
|
2824 }
|
Chris@16
|
2825 template <unsigned Digits10, class ExponentType, class Allocator, class ArgType>
|
Chris@101
|
2826 inline void eval_scalbn(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& val, ArgType e_)
|
Chris@101
|
2827 {
|
Chris@101
|
2828 using default_ops::eval_multiply;
|
Chris@101
|
2829 const ExponentType e = e_;
|
Chris@101
|
2830 cpp_dec_float<Digits10, ExponentType, Allocator> t(1.0, e);
|
Chris@101
|
2831 eval_multiply(result, val, t);
|
Chris@101
|
2832 }
|
Chris@101
|
2833
|
Chris@101
|
2834 template <unsigned Digits10, class ExponentType, class Allocator, class ArgType>
|
Chris@101
|
2835 inline void eval_ldexp(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& x, ArgType e)
|
Chris@16
|
2836 {
|
Chris@16
|
2837 const long long the_exp = static_cast<long long>(e);
|
Chris@16
|
2838
|
Chris@16
|
2839 if((the_exp > (std::numeric_limits<ExponentType>::max)()) || (the_exp < (std::numeric_limits<ExponentType>::min)()))
|
Chris@16
|
2840 BOOST_THROW_EXCEPTION(std::runtime_error(std::string("Exponent value is out of range.")));
|
Chris@16
|
2841
|
Chris@16
|
2842 result = x;
|
Chris@16
|
2843
|
Chris@101
|
2844 if ((the_exp > static_cast<long long>(-std::numeric_limits<long long>::digits)) && (the_exp < static_cast<long long>(0)))
|
Chris@16
|
2845 result.div_unsigned_long_long(1ULL << static_cast<long long>(-the_exp));
|
Chris@16
|
2846 else if((the_exp < static_cast<long long>( std::numeric_limits<long long>::digits)) && (the_exp > static_cast<long long>(0)))
|
Chris@16
|
2847 result.mul_unsigned_long_long(1ULL << the_exp);
|
Chris@16
|
2848 else if(the_exp != static_cast<long long>(0))
|
Chris@16
|
2849 result *= cpp_dec_float<Digits10, ExponentType, Allocator>::pow2(e);
|
Chris@16
|
2850 }
|
Chris@16
|
2851
|
Chris@16
|
2852 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@16
|
2853 inline void eval_frexp(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& x, ExponentType* e)
|
Chris@16
|
2854 {
|
Chris@16
|
2855 result = x;
|
Chris@16
|
2856 if(result.isneg())
|
Chris@16
|
2857 result.negate();
|
Chris@16
|
2858
|
Chris@16
|
2859 if(result.iszero())
|
Chris@16
|
2860 {
|
Chris@16
|
2861 *e = 0;
|
Chris@16
|
2862 return;
|
Chris@16
|
2863 }
|
Chris@16
|
2864
|
Chris@16
|
2865 ExponentType t = result.order();
|
Chris@16
|
2866 BOOST_MP_USING_ABS
|
Chris@16
|
2867 if(abs(t) < ((std::numeric_limits<ExponentType>::max)() / 1000))
|
Chris@16
|
2868 {
|
Chris@16
|
2869 t *= 1000;
|
Chris@16
|
2870 t /= 301;
|
Chris@16
|
2871 }
|
Chris@16
|
2872 else
|
Chris@16
|
2873 {
|
Chris@16
|
2874 t /= 301;
|
Chris@16
|
2875 t *= 1000;
|
Chris@16
|
2876 }
|
Chris@16
|
2877
|
Chris@16
|
2878 result *= cpp_dec_float<Digits10, ExponentType, Allocator>::pow2(-t);
|
Chris@16
|
2879
|
Chris@16
|
2880 if(result.iszero() || (result.isinf)() || (result.isnan)())
|
Chris@16
|
2881 {
|
Chris@16
|
2882 // pow2 overflowed, slip the calculation up:
|
Chris@16
|
2883 result = x;
|
Chris@16
|
2884 if(result.isneg())
|
Chris@16
|
2885 result.negate();
|
Chris@16
|
2886 t /= 2;
|
Chris@16
|
2887 result *= cpp_dec_float<Digits10, ExponentType, Allocator>::pow2(-t);
|
Chris@16
|
2888 }
|
Chris@16
|
2889 BOOST_MP_USING_ABS
|
Chris@16
|
2890 if(abs(result.order()) > 5)
|
Chris@16
|
2891 {
|
Chris@16
|
2892 // If our first estimate doesn't get close enough then try recursion until we do:
|
Chris@16
|
2893 ExponentType e2;
|
Chris@16
|
2894 cpp_dec_float<Digits10, ExponentType, Allocator> r2;
|
Chris@16
|
2895 eval_frexp(r2, result, &e2);
|
Chris@16
|
2896 // overflow protection:
|
Chris@16
|
2897 if((t > 0) && (e2 > 0) && (t > (std::numeric_limits<ExponentType>::max)() - e2))
|
Chris@16
|
2898 BOOST_THROW_EXCEPTION(std::runtime_error("Exponent is too large to be represented as a power of 2."));
|
Chris@16
|
2899 if((t < 0) && (e2 < 0) && (t < (std::numeric_limits<ExponentType>::min)() - e2))
|
Chris@16
|
2900 BOOST_THROW_EXCEPTION(std::runtime_error("Exponent is too large to be represented as a power of 2."));
|
Chris@16
|
2901 t += e2;
|
Chris@16
|
2902 result = r2;
|
Chris@16
|
2903 }
|
Chris@16
|
2904
|
Chris@16
|
2905 while(result.compare(cpp_dec_float<Digits10, ExponentType, Allocator>::one()) >= 0)
|
Chris@16
|
2906 {
|
Chris@16
|
2907 result /= cpp_dec_float<Digits10, ExponentType, Allocator>::two();
|
Chris@16
|
2908 ++t;
|
Chris@16
|
2909 }
|
Chris@16
|
2910 while(result.compare(cpp_dec_float<Digits10, ExponentType, Allocator>::half()) < 0)
|
Chris@16
|
2911 {
|
Chris@16
|
2912 result *= cpp_dec_float<Digits10, ExponentType, Allocator>::two();
|
Chris@16
|
2913 --t;
|
Chris@16
|
2914 }
|
Chris@16
|
2915 *e = t;
|
Chris@16
|
2916 if(x.isneg())
|
Chris@16
|
2917 result.negate();
|
Chris@16
|
2918 }
|
Chris@16
|
2919
|
Chris@16
|
2920 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@16
|
2921 inline typename disable_if<is_same<ExponentType, int> >::type eval_frexp(cpp_dec_float<Digits10, ExponentType, Allocator>& result, const cpp_dec_float<Digits10, ExponentType, Allocator>& x, int* e)
|
Chris@16
|
2922 {
|
Chris@16
|
2923 ExponentType t;
|
Chris@16
|
2924 eval_frexp(result, x, &t);
|
Chris@16
|
2925 if((t > (std::numeric_limits<int>::max)()) || (t < (std::numeric_limits<int>::min)()))
|
Chris@16
|
2926 BOOST_THROW_EXCEPTION(std::runtime_error("Exponent is outside the range of an int"));
|
Chris@16
|
2927 *e = static_cast<int>(t);
|
Chris@16
|
2928 }
|
Chris@16
|
2929
|
Chris@16
|
2930 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2931 inline bool eval_is_zero(const cpp_dec_float<Digits10, ExponentType, Allocator>& val)
|
Chris@16
|
2932 {
|
Chris@16
|
2933 return val.iszero();
|
Chris@16
|
2934 }
|
Chris@16
|
2935 template <unsigned Digits10, class ExponentType, class Allocator>
|
Chris@101
|
2936 inline int eval_get_sign(const cpp_dec_float<Digits10, ExponentType, Allocator>& val)
|
Chris@16
|
2937 {
|
Chris@16
|
2938 return val.iszero() ? 0 : val.isneg() ? -1 : 1;
|
Chris@16
|
2939 }
|
Chris@16
|
2940
|
Chris@16
|
2941 } // namespace backends
|
Chris@16
|
2942
|
Chris@16
|
2943 using boost::multiprecision::backends::cpp_dec_float;
|
Chris@16
|
2944
|
Chris@16
|
2945
|
Chris@16
|
2946 typedef number<cpp_dec_float<50> > cpp_dec_float_50;
|
Chris@16
|
2947 typedef number<cpp_dec_float<100> > cpp_dec_float_100;
|
Chris@16
|
2948
|
Chris@16
|
2949 #ifdef BOOST_NO_SFINAE_EXPR
|
Chris@16
|
2950
|
Chris@16
|
2951 namespace detail{
|
Chris@16
|
2952
|
Chris@16
|
2953 template<unsigned D1, class E1, class A1, unsigned D2, class E2, class A2>
|
Chris@16
|
2954 struct is_explicitly_convertible<cpp_dec_float<D1, E1, A1>, cpp_dec_float<D2, E2, A2> > : public mpl::true_ {};
|
Chris@16
|
2955
|
Chris@16
|
2956 }
|
Chris@16
|
2957
|
Chris@16
|
2958 #endif
|
Chris@16
|
2959
|
Chris@16
|
2960
|
Chris@16
|
2961 }}
|
Chris@16
|
2962
|
Chris@16
|
2963 namespace std
|
Chris@16
|
2964 {
|
Chris@101
|
2965 template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
2966 class numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >
|
Chris@16
|
2967 {
|
Chris@16
|
2968 public:
|
Chris@101
|
2969 BOOST_STATIC_CONSTEXPR bool is_specialized = true;
|
Chris@101
|
2970 BOOST_STATIC_CONSTEXPR bool is_signed = true;
|
Chris@101
|
2971 BOOST_STATIC_CONSTEXPR bool is_integer = false;
|
Chris@101
|
2972 BOOST_STATIC_CONSTEXPR bool is_exact = false;
|
Chris@101
|
2973 BOOST_STATIC_CONSTEXPR bool is_bounded = true;
|
Chris@101
|
2974 BOOST_STATIC_CONSTEXPR bool is_modulo = false;
|
Chris@101
|
2975 BOOST_STATIC_CONSTEXPR bool is_iec559 = false;
|
Chris@101
|
2976 BOOST_STATIC_CONSTEXPR int digits = boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_digits10;
|
Chris@101
|
2977 BOOST_STATIC_CONSTEXPR int digits10 = boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_digits10;
|
Chris@101
|
2978 BOOST_STATIC_CONSTEXPR int max_digits10 = boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_total_digits10;
|
Chris@101
|
2979 BOOST_STATIC_CONSTEXPR ExponentType min_exponent = boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_min_exp; // Type differs from int.
|
Chris@101
|
2980 BOOST_STATIC_CONSTEXPR ExponentType min_exponent10 = boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_min_exp10; // Type differs from int.
|
Chris@101
|
2981 BOOST_STATIC_CONSTEXPR ExponentType max_exponent = boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_max_exp; // Type differs from int.
|
Chris@101
|
2982 BOOST_STATIC_CONSTEXPR ExponentType max_exponent10 = boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_max_exp10; // Type differs from int.
|
Chris@101
|
2983 BOOST_STATIC_CONSTEXPR int radix = boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_radix;
|
Chris@101
|
2984 BOOST_STATIC_CONSTEXPR std::float_round_style round_style = std::round_indeterminate;
|
Chris@101
|
2985 BOOST_STATIC_CONSTEXPR bool has_infinity = true;
|
Chris@101
|
2986 BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = true;
|
Chris@101
|
2987 BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false;
|
Chris@101
|
2988 BOOST_STATIC_CONSTEXPR std::float_denorm_style has_denorm = std::denorm_absent;
|
Chris@101
|
2989 BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false;
|
Chris@101
|
2990 BOOST_STATIC_CONSTEXPR bool traps = false;
|
Chris@101
|
2991 BOOST_STATIC_CONSTEXPR bool tinyness_before = false;
|
Chris@101
|
2992
|
Chris@101
|
2993 BOOST_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)(); }
|
Chris@101
|
2994 BOOST_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)(); }
|
Chris@101
|
2995 BOOST_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(); }
|
Chris@101
|
2996 BOOST_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(); }
|
Chris@101
|
2997 BOOST_STATIC_CONSTEXPR boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> round_error () { return 0.5L; }
|
Chris@101
|
2998 BOOST_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(); }
|
Chris@101
|
2999 BOOST_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(); }
|
Chris@101
|
3000 BOOST_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(); }
|
Chris@101
|
3001 BOOST_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(); }
|
Chris@16
|
3002 };
|
Chris@16
|
3003
|
Chris@16
|
3004 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
|
Chris@16
|
3005
|
Chris@16
|
3006 template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
3007 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::digits;
|
Chris@16
|
3008 template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
3009 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::digits10;
|
Chris@16
|
3010 template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
3011 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::max_digits10;
|
Chris@16
|
3012 template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
3013 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::is_signed;
|
Chris@16
|
3014 template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
3015 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::is_integer;
|
Chris@16
|
3016 template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
3017 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::is_exact;
|
Chris@16
|
3018 template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
3019 BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::radix;
|
Chris@16
|
3020 template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
3021 BOOST_CONSTEXPR_OR_CONST ExponentType numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::min_exponent;
|
Chris@16
|
3022 template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
3023 BOOST_CONSTEXPR_OR_CONST ExponentType numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::min_exponent10;
|
Chris@16
|
3024 template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
3025 BOOST_CONSTEXPR_OR_CONST ExponentType numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::max_exponent;
|
Chris@16
|
3026 template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
3027 BOOST_CONSTEXPR_OR_CONST ExponentType numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::max_exponent10;
|
Chris@16
|
3028 template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
3029 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::has_infinity;
|
Chris@16
|
3030 template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
3031 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::has_quiet_NaN;
|
Chris@16
|
3032 template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
3033 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::has_signaling_NaN;
|
Chris@16
|
3034 template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
3035 BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::has_denorm;
|
Chris@16
|
3036 template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
3037 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::has_denorm_loss;
|
Chris@16
|
3038 template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
3039 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::is_iec559;
|
Chris@16
|
3040 template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
3041 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::is_bounded;
|
Chris@16
|
3042 template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
3043 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::is_modulo;
|
Chris@16
|
3044 template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
3045 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::traps;
|
Chris@16
|
3046 template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
3047 BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::tinyness_before;
|
Chris@16
|
3048 template <unsigned Digits10, class ExponentType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
3049 BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates> >::round_style;
|
Chris@16
|
3050
|
Chris@16
|
3051 #endif
|
Chris@16
|
3052 }
|
Chris@16
|
3053
|
Chris@16
|
3054 namespace boost{ namespace math{
|
Chris@16
|
3055
|
Chris@16
|
3056 namespace policies{
|
Chris@16
|
3057
|
Chris@16
|
3058 template <unsigned Digits10, class ExponentType, class Allocator, class Policy, boost::multiprecision::expression_template_option ExpressionTemplates>
|
Chris@16
|
3059 struct precision< boost::multiprecision::number<boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>, ExpressionTemplates>, Policy>
|
Chris@16
|
3060 {
|
Chris@16
|
3061 // Define a local copy of cpp_dec_float_digits10 because it might differ
|
Chris@16
|
3062 // from the template parameter Digits10 for small or large digit counts.
|
Chris@16
|
3063 static const boost::int32_t cpp_dec_float_digits10 = boost::multiprecision::cpp_dec_float<Digits10, ExponentType, Allocator>::cpp_dec_float_digits10;
|
Chris@16
|
3064
|
Chris@16
|
3065 typedef typename Policy::precision_type precision_type;
|
Chris@16
|
3066 typedef digits2<((cpp_dec_float_digits10 + 1LL) * 1000LL) / 301LL> digits_2;
|
Chris@16
|
3067 typedef typename mpl::if_c<
|
Chris@101
|
3068 ((digits_2::value <= precision_type::value)
|
Chris@16
|
3069 || (Policy::precision_type::value <= 0)),
|
Chris@16
|
3070 // Default case, full precision for RealType:
|
Chris@16
|
3071 digits_2,
|
Chris@101
|
3072 // User customized precision:
|
Chris@16
|
3073 precision_type
|
Chris@16
|
3074 >::type type;
|
Chris@16
|
3075 };
|
Chris@16
|
3076
|
Chris@16
|
3077 } // namespace policies
|
Chris@16
|
3078
|
Chris@16
|
3079 }} // namespaces boost::math
|
Chris@16
|
3080
|
Chris@16
|
3081 #endif
|