Chris@102
|
1 ///////////////////////////////////////////////////////////////
|
Chris@102
|
2 // Copyright 2013 John Maddock. Distributed under the Boost
|
Chris@102
|
3 // Software License, Version 1.0. (See accompanying file
|
Chris@102
|
4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
|
Chris@102
|
5
|
Chris@102
|
6 #ifndef BOOST_MP_CPP_BIN_FLOAT_IO_HPP
|
Chris@102
|
7 #define BOOST_MP_CPP_BIN_FLOAT_IO_HPP
|
Chris@102
|
8
|
Chris@102
|
9 namespace boost{ namespace multiprecision{ namespace cpp_bf_io_detail{
|
Chris@102
|
10
|
Chris@102
|
11 //
|
Chris@102
|
12 // Multiplies a by b and shifts the result so it fits inside max_bits bits,
|
Chris@102
|
13 // returns by how much the result was shifted.
|
Chris@102
|
14 //
|
Chris@102
|
15 template <class I>
|
Chris@102
|
16 inline I restricted_multiply(cpp_int& result, const cpp_int& a, const cpp_int& b, I max_bits, boost::int64_t& error)
|
Chris@102
|
17 {
|
Chris@102
|
18 result = a * b;
|
Chris@102
|
19 I gb = msb(result);
|
Chris@102
|
20 I rshift = 0;
|
Chris@102
|
21 if(gb > max_bits)
|
Chris@102
|
22 {
|
Chris@102
|
23 rshift = gb - max_bits;
|
Chris@102
|
24 I lb = lsb(result);
|
Chris@102
|
25 int roundup = 0;
|
Chris@102
|
26 // The error rate increases by the error of both a and b,
|
Chris@102
|
27 // this may be overly pessimistic in many case as we're assuming
|
Chris@102
|
28 // that a and b have the same level of uncertainty...
|
Chris@102
|
29 if(lb < rshift)
|
Chris@102
|
30 error = error ? error * 2 : 1;
|
Chris@102
|
31 if(rshift)
|
Chris@102
|
32 {
|
Chris@102
|
33 BOOST_ASSERT(rshift < INT_MAX);
|
Chris@102
|
34 if(bit_test(result, static_cast<unsigned>(rshift - 1)))
|
Chris@102
|
35 {
|
Chris@102
|
36 if(lb == rshift - 1)
|
Chris@102
|
37 roundup = 1;
|
Chris@102
|
38 else
|
Chris@102
|
39 roundup = 2;
|
Chris@102
|
40 }
|
Chris@102
|
41 result >>= rshift;
|
Chris@102
|
42 }
|
Chris@102
|
43 if((roundup == 2) || ((roundup == 1) && (result.backend().limbs()[0] & 1)))
|
Chris@102
|
44 ++result;
|
Chris@102
|
45 }
|
Chris@102
|
46 return rshift;
|
Chris@102
|
47 }
|
Chris@102
|
48 //
|
Chris@102
|
49 // Computes a^e shifted to the right so it fits in max_bits, returns how far
|
Chris@102
|
50 // to the right we are shifted.
|
Chris@102
|
51 //
|
Chris@102
|
52 template <class I>
|
Chris@102
|
53 inline I restricted_pow(cpp_int& result, const cpp_int& a, I e, I max_bits, boost::int64_t& error)
|
Chris@102
|
54 {
|
Chris@102
|
55 BOOST_ASSERT(&result != &a);
|
Chris@102
|
56 I exp = 0;
|
Chris@102
|
57 if(e == 1)
|
Chris@102
|
58 {
|
Chris@102
|
59 result = a;
|
Chris@102
|
60 return exp;
|
Chris@102
|
61 }
|
Chris@102
|
62 else if(e == 2)
|
Chris@102
|
63 {
|
Chris@102
|
64 return restricted_multiply(result, a, a, max_bits, error);
|
Chris@102
|
65 }
|
Chris@102
|
66 else if(e == 3)
|
Chris@102
|
67 {
|
Chris@102
|
68 exp = restricted_multiply(result, a, a, max_bits, error);
|
Chris@102
|
69 exp += restricted_multiply(result, result, a, max_bits, error);
|
Chris@102
|
70 return exp;
|
Chris@102
|
71 }
|
Chris@102
|
72 I p = e / 2;
|
Chris@102
|
73 exp = restricted_pow(result, a, p, max_bits, error);
|
Chris@102
|
74 exp *= 2;
|
Chris@102
|
75 exp += restricted_multiply(result, result, result, max_bits, error);
|
Chris@102
|
76 if(e & 1)
|
Chris@102
|
77 exp += restricted_multiply(result, result, a, max_bits, error);
|
Chris@102
|
78 return exp;
|
Chris@102
|
79 }
|
Chris@102
|
80
|
Chris@102
|
81 inline int get_round_mode(const cpp_int& what, boost::int64_t location, boost::int64_t error)
|
Chris@102
|
82 {
|
Chris@102
|
83 //
|
Chris@102
|
84 // Can we round what at /location/, if the error in what is /error/ in
|
Chris@102
|
85 // units of 0.5ulp. Return:
|
Chris@102
|
86 //
|
Chris@102
|
87 // -1: Can't round.
|
Chris@102
|
88 // 0: leave as is.
|
Chris@102
|
89 // 1: tie.
|
Chris@102
|
90 // 2: round up.
|
Chris@102
|
91 //
|
Chris@102
|
92 BOOST_ASSERT(location >= 0);
|
Chris@102
|
93 BOOST_ASSERT(location < INT_MAX);
|
Chris@102
|
94 boost::int64_t error_radius = error & 1 ? (1 + error) / 2 : error / 2;
|
Chris@102
|
95 if(error_radius && ((int)msb(error_radius) >= location))
|
Chris@102
|
96 return -1;
|
Chris@102
|
97 if(bit_test(what, static_cast<unsigned>(location)))
|
Chris@102
|
98 {
|
Chris@102
|
99 if((int)lsb(what) == location)
|
Chris@102
|
100 return error ? -1 : 1; // Either a tie or can't round depending on whether we have any error
|
Chris@102
|
101 if(!error)
|
Chris@102
|
102 return 2; // no error, round up.
|
Chris@102
|
103 cpp_int t = what - error_radius;
|
Chris@102
|
104 if((int)lsb(t) >= location)
|
Chris@102
|
105 return -1;
|
Chris@102
|
106 return 2;
|
Chris@102
|
107 }
|
Chris@102
|
108 else if(error)
|
Chris@102
|
109 {
|
Chris@102
|
110 cpp_int t = what + error_radius;
|
Chris@102
|
111 return bit_test(t, static_cast<unsigned>(location)) ? -1 : 0;
|
Chris@102
|
112 }
|
Chris@102
|
113 return 0;
|
Chris@102
|
114 }
|
Chris@102
|
115
|
Chris@102
|
116 inline int get_round_mode(cpp_int& r, cpp_int& d, boost::int64_t error, const cpp_int& q)
|
Chris@102
|
117 {
|
Chris@102
|
118 //
|
Chris@102
|
119 // Lets suppose we have an inexact division by d+delta, where the true
|
Chris@102
|
120 // value for the divisor is d, and with |delta| <= error/2, then
|
Chris@102
|
121 // we have calculated q and r such that:
|
Chris@102
|
122 //
|
Chris@102
|
123 // n r
|
Chris@102
|
124 // --- = q + -----------
|
Chris@102
|
125 // d + error d + error
|
Chris@102
|
126 //
|
Chris@102
|
127 // Rearranging for n / d we get:
|
Chris@102
|
128 //
|
Chris@102
|
129 // n delta*q + r
|
Chris@102
|
130 // --- = q + -------------
|
Chris@102
|
131 // d d
|
Chris@102
|
132 //
|
Chris@102
|
133 // So rounding depends on whether 2r + error * q > d.
|
Chris@102
|
134 //
|
Chris@102
|
135 // We return:
|
Chris@102
|
136 // 0 = down down.
|
Chris@102
|
137 // 1 = tie.
|
Chris@102
|
138 // 2 = round up.
|
Chris@102
|
139 // -1 = couldn't decide.
|
Chris@102
|
140 //
|
Chris@102
|
141 r <<= 1;
|
Chris@102
|
142 int c = r.compare(d);
|
Chris@102
|
143 if(c == 0)
|
Chris@102
|
144 return error ? -1 : 1;
|
Chris@102
|
145 if(c > 0)
|
Chris@102
|
146 {
|
Chris@102
|
147 if(error)
|
Chris@102
|
148 {
|
Chris@102
|
149 r -= error * q;
|
Chris@102
|
150 return r.compare(d) > 0 ? 2 : -1;
|
Chris@102
|
151 }
|
Chris@102
|
152 return 2;
|
Chris@102
|
153 }
|
Chris@102
|
154 if(error)
|
Chris@102
|
155 {
|
Chris@102
|
156 r += error * q;
|
Chris@102
|
157 return r.compare(d) < 0 ? 0 : -1;
|
Chris@102
|
158 }
|
Chris@102
|
159 return 0;
|
Chris@102
|
160 }
|
Chris@102
|
161
|
Chris@102
|
162 } // namespace
|
Chris@102
|
163
|
Chris@102
|
164 namespace backends{
|
Chris@102
|
165
|
Chris@102
|
166 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
Chris@102
|
167 cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>& cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::operator=(const char *s)
|
Chris@102
|
168 {
|
Chris@102
|
169 cpp_int n;
|
Chris@102
|
170 boost::intmax_t decimal_exp = 0;
|
Chris@102
|
171 boost::intmax_t digits_seen = 0;
|
Chris@102
|
172 static const boost::intmax_t max_digits_seen = 4 + (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count * 301L) / 1000;
|
Chris@102
|
173 bool ss = false;
|
Chris@102
|
174 //
|
Chris@102
|
175 // Extract the sign:
|
Chris@102
|
176 //
|
Chris@102
|
177 if(*s == '-')
|
Chris@102
|
178 {
|
Chris@102
|
179 ss = true;
|
Chris@102
|
180 ++s;
|
Chris@102
|
181 }
|
Chris@102
|
182 else if(*s == '+')
|
Chris@102
|
183 ++s;
|
Chris@102
|
184 //
|
Chris@102
|
185 // Special cases first:
|
Chris@102
|
186 //
|
Chris@102
|
187 if((std::strcmp(s, "nan") == 0) || (std::strcmp(s, "NaN") == 0) || (std::strcmp(s, "NAN") == 0))
|
Chris@102
|
188 {
|
Chris@102
|
189 return *this = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend();
|
Chris@102
|
190 }
|
Chris@102
|
191 if((std::strcmp(s, "inf") == 0) || (std::strcmp(s, "Inf") == 0) || (std::strcmp(s, "INF") == 0) || (std::strcmp(s, "infinity") == 0) || (std::strcmp(s, "Infinity") == 0) || (std::strcmp(s, "INFINITY") == 0))
|
Chris@102
|
192 {
|
Chris@102
|
193 *this = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend();
|
Chris@102
|
194 if(ss)
|
Chris@102
|
195 negate();
|
Chris@102
|
196 return *this;
|
Chris@102
|
197 }
|
Chris@102
|
198 //
|
Chris@102
|
199 // Digits before the point:
|
Chris@102
|
200 //
|
Chris@102
|
201 while(*s && (*s >= '0') && (*s <= '9'))
|
Chris@102
|
202 {
|
Chris@102
|
203 n *= 10u;
|
Chris@102
|
204 n += *s - '0';
|
Chris@102
|
205 if(digits_seen || (*s != '0'))
|
Chris@102
|
206 ++digits_seen;
|
Chris@102
|
207 ++s;
|
Chris@102
|
208 }
|
Chris@102
|
209 // The decimal point (we really should localise this!!)
|
Chris@102
|
210 if(*s && (*s == '.'))
|
Chris@102
|
211 ++s;
|
Chris@102
|
212 //
|
Chris@102
|
213 // Digits after the point:
|
Chris@102
|
214 //
|
Chris@102
|
215 while(*s && (*s >= '0') && (*s <= '9'))
|
Chris@102
|
216 {
|
Chris@102
|
217 n *= 10u;
|
Chris@102
|
218 n += *s - '0';
|
Chris@102
|
219 --decimal_exp;
|
Chris@102
|
220 if(digits_seen || (*s != '0'))
|
Chris@102
|
221 ++digits_seen;
|
Chris@102
|
222 ++s;
|
Chris@102
|
223 if(digits_seen > max_digits_seen)
|
Chris@102
|
224 break;
|
Chris@102
|
225 }
|
Chris@102
|
226 //
|
Chris@102
|
227 // Digits we're skipping:
|
Chris@102
|
228 //
|
Chris@102
|
229 while(*s && (*s >= '0') && (*s <= '9'))
|
Chris@102
|
230 ++s;
|
Chris@102
|
231 //
|
Chris@102
|
232 // See if there's an exponent:
|
Chris@102
|
233 //
|
Chris@102
|
234 if(*s && ((*s == 'e') || (*s == 'E')))
|
Chris@102
|
235 {
|
Chris@102
|
236 ++s;
|
Chris@102
|
237 boost::intmax_t e = 0;
|
Chris@102
|
238 bool es = false;
|
Chris@102
|
239 if(*s && (*s == '-'))
|
Chris@102
|
240 {
|
Chris@102
|
241 es = true;
|
Chris@102
|
242 ++s;
|
Chris@102
|
243 }
|
Chris@102
|
244 else if(*s && (*s == '+'))
|
Chris@102
|
245 ++s;
|
Chris@102
|
246 while(*s && (*s >= '0') && (*s <= '9'))
|
Chris@102
|
247 {
|
Chris@102
|
248 e *= 10u;
|
Chris@102
|
249 e += *s - '0';
|
Chris@102
|
250 ++s;
|
Chris@102
|
251 }
|
Chris@102
|
252 if(es)
|
Chris@102
|
253 e = -e;
|
Chris@102
|
254 decimal_exp += e;
|
Chris@102
|
255 }
|
Chris@102
|
256 if(*s)
|
Chris@102
|
257 {
|
Chris@102
|
258 //
|
Chris@102
|
259 // Oops unexpected input at the end of the number:
|
Chris@102
|
260 //
|
Chris@102
|
261 BOOST_THROW_EXCEPTION(std::runtime_error("Unable to parse string as a valid floating point number."));
|
Chris@102
|
262 }
|
Chris@102
|
263 if(n == 0)
|
Chris@102
|
264 {
|
Chris@102
|
265 // Result is necessarily zero:
|
Chris@102
|
266 *this = static_cast<limb_type>(0u);
|
Chris@102
|
267 return *this;
|
Chris@102
|
268 }
|
Chris@102
|
269
|
Chris@102
|
270 static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT;
|
Chris@102
|
271 //
|
Chris@102
|
272 // Set our working precision - this is heuristic based, we want
|
Chris@102
|
273 // a value as small as possible > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count to avoid large computations
|
Chris@102
|
274 // and excessive memory usage, but we also want to avoid having to
|
Chris@102
|
275 // up the computation and start again at a higher precision.
|
Chris@102
|
276 // So we round cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count up to the nearest whole number of limbs, and add
|
Chris@102
|
277 // one limb for good measure. This works very well for small exponents,
|
Chris@102
|
278 // but for larger exponents we may may need to restart, we could add some
|
Chris@102
|
279 // extra precision right from the start for larger exponents, but this
|
Chris@102
|
280 // seems to be slightly slower in the *average* case:
|
Chris@102
|
281 //
|
Chris@102
|
282 #ifdef BOOST_MP_STRESS_IO
|
Chris@102
|
283 boost::intmax_t max_bits = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 32;
|
Chris@102
|
284 #else
|
Chris@102
|
285 boost::intmax_t max_bits = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count % limb_bits ? limb_bits - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count % limb_bits : 0) + limb_bits;
|
Chris@102
|
286 #endif
|
Chris@102
|
287 boost::int64_t error = 0;
|
Chris@102
|
288 boost::intmax_t calc_exp = 0;
|
Chris@102
|
289 boost::intmax_t final_exponent = 0;
|
Chris@102
|
290
|
Chris@102
|
291 if(decimal_exp >= 0)
|
Chris@102
|
292 {
|
Chris@102
|
293 // Nice and simple, the result is an integer...
|
Chris@102
|
294 do
|
Chris@102
|
295 {
|
Chris@102
|
296 cpp_int t;
|
Chris@102
|
297 if(decimal_exp)
|
Chris@102
|
298 {
|
Chris@102
|
299 calc_exp = boost::multiprecision::cpp_bf_io_detail::restricted_pow(t, cpp_int(5), decimal_exp, max_bits, error);
|
Chris@102
|
300 calc_exp += boost::multiprecision::cpp_bf_io_detail::restricted_multiply(t, t, n, max_bits, error);
|
Chris@102
|
301 }
|
Chris@102
|
302 else
|
Chris@102
|
303 t = n;
|
Chris@102
|
304 final_exponent = (boost::int64_t)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 + decimal_exp + calc_exp;
|
Chris@102
|
305 int rshift = msb(t) - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 1;
|
Chris@102
|
306 if(rshift > 0)
|
Chris@102
|
307 {
|
Chris@102
|
308 final_exponent += rshift;
|
Chris@102
|
309 int roundup = boost::multiprecision::cpp_bf_io_detail::get_round_mode(t, rshift - 1, error);
|
Chris@102
|
310 t >>= rshift;
|
Chris@102
|
311 if((roundup == 2) || ((roundup == 1) && t.backend().limbs()[0] & 1))
|
Chris@102
|
312 ++t;
|
Chris@102
|
313 else if(roundup < 0)
|
Chris@102
|
314 {
|
Chris@102
|
315 #ifdef BOOST_MP_STRESS_IO
|
Chris@102
|
316 max_bits += 32;
|
Chris@102
|
317 #else
|
Chris@102
|
318 max_bits *= 2;
|
Chris@102
|
319 #endif
|
Chris@102
|
320 error = 0;
|
Chris@102
|
321 continue;
|
Chris@102
|
322 }
|
Chris@102
|
323 }
|
Chris@102
|
324 else
|
Chris@102
|
325 {
|
Chris@102
|
326 BOOST_ASSERT(!error);
|
Chris@102
|
327 }
|
Chris@102
|
328 if(final_exponent > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
|
Chris@102
|
329 {
|
Chris@102
|
330 exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent;
|
Chris@102
|
331 final_exponent -= cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent;
|
Chris@102
|
332 }
|
Chris@102
|
333 else if(final_exponent < cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent)
|
Chris@102
|
334 {
|
Chris@102
|
335 // Underflow:
|
Chris@102
|
336 exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent;
|
Chris@102
|
337 final_exponent -= cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent;
|
Chris@102
|
338 }
|
Chris@102
|
339 else
|
Chris@102
|
340 {
|
Chris@102
|
341 exponent() = static_cast<Exponent>(final_exponent);
|
Chris@102
|
342 final_exponent = 0;
|
Chris@102
|
343 }
|
Chris@102
|
344 copy_and_round(*this, t.backend());
|
Chris@102
|
345 break;
|
Chris@102
|
346 }
|
Chris@102
|
347 while(true);
|
Chris@102
|
348
|
Chris@102
|
349 if(ss != sign())
|
Chris@102
|
350 negate();
|
Chris@102
|
351 }
|
Chris@102
|
352 else
|
Chris@102
|
353 {
|
Chris@102
|
354 // Result is the ratio of two integers: we need to organise the
|
Chris@102
|
355 // division so as to produce at least an N-bit result which we can
|
Chris@102
|
356 // round according to the remainder.
|
Chris@102
|
357 //cpp_int d = pow(cpp_int(5), -decimal_exp);
|
Chris@102
|
358 do
|
Chris@102
|
359 {
|
Chris@102
|
360 cpp_int d;
|
Chris@102
|
361 calc_exp = boost::multiprecision::cpp_bf_io_detail::restricted_pow(d, cpp_int(5), -decimal_exp, max_bits, error);
|
Chris@102
|
362 int shift = (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - msb(n) + msb(d);
|
Chris@102
|
363 final_exponent = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 + decimal_exp - calc_exp;
|
Chris@102
|
364 if(shift > 0)
|
Chris@102
|
365 {
|
Chris@102
|
366 n <<= shift;
|
Chris@102
|
367 final_exponent -= static_cast<Exponent>(shift);
|
Chris@102
|
368 }
|
Chris@102
|
369 cpp_int q, r;
|
Chris@102
|
370 divide_qr(n, d, q, r);
|
Chris@102
|
371 int gb = msb(q);
|
Chris@102
|
372 BOOST_ASSERT((gb >= static_cast<int>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) - 1));
|
Chris@102
|
373 //
|
Chris@102
|
374 // Check for rounding conditions we have to
|
Chris@102
|
375 // handle ourselves:
|
Chris@102
|
376 //
|
Chris@102
|
377 int roundup = 0;
|
Chris@102
|
378 if(gb == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1)
|
Chris@102
|
379 {
|
Chris@102
|
380 // Exactly the right number of bits, use the remainder to round:
|
Chris@102
|
381 roundup = boost::multiprecision::cpp_bf_io_detail::get_round_mode(r, d, error, q);
|
Chris@102
|
382 }
|
Chris@102
|
383 else if(bit_test(q, gb - (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) && ((int)lsb(q) == (gb - (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)))
|
Chris@102
|
384 {
|
Chris@102
|
385 // Too many bits in q and the bits in q indicate a tie, but we can break that using r,
|
Chris@102
|
386 // note that the radius of error in r is error/2 * q:
|
Chris@102
|
387 int shift = gb - (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 1;
|
Chris@102
|
388 q >>= shift;
|
Chris@102
|
389 final_exponent += static_cast<Exponent>(shift);
|
Chris@102
|
390 BOOST_ASSERT((msb(q) >= cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1));
|
Chris@102
|
391 if(error && (r < (error / 2) * q))
|
Chris@102
|
392 roundup = -1;
|
Chris@102
|
393 else if(error && (r + (error / 2) * q >= d))
|
Chris@102
|
394 roundup = -1;
|
Chris@102
|
395 else
|
Chris@102
|
396 roundup = r ? 2 : 1;
|
Chris@102
|
397 }
|
Chris@102
|
398 else if(error && (((error / 2) * q + r >= d) || (r < (error / 2) * q)))
|
Chris@102
|
399 {
|
Chris@102
|
400 // We might have been rounding up, or got the wrong quotient: can't tell!
|
Chris@102
|
401 roundup = -1;
|
Chris@102
|
402 }
|
Chris@102
|
403 if(roundup < 0)
|
Chris@102
|
404 {
|
Chris@102
|
405 #ifdef BOOST_MP_STRESS_IO
|
Chris@102
|
406 max_bits += 32;
|
Chris@102
|
407 #else
|
Chris@102
|
408 max_bits *= 2;
|
Chris@102
|
409 #endif
|
Chris@102
|
410 error = 0;
|
Chris@102
|
411 if(shift > 0)
|
Chris@102
|
412 {
|
Chris@102
|
413 n >>= shift;
|
Chris@102
|
414 final_exponent += static_cast<Exponent>(shift);
|
Chris@102
|
415 }
|
Chris@102
|
416 continue;
|
Chris@102
|
417 }
|
Chris@102
|
418 else if((roundup == 2) || ((roundup == 1) && q.backend().limbs()[0] & 1))
|
Chris@102
|
419 ++q;
|
Chris@102
|
420 if(final_exponent > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
|
Chris@102
|
421 {
|
Chris@102
|
422 // Overflow:
|
Chris@102
|
423 exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent;
|
Chris@102
|
424 final_exponent -= cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent;
|
Chris@102
|
425 }
|
Chris@102
|
426 else if(final_exponent < cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent)
|
Chris@102
|
427 {
|
Chris@102
|
428 // Underflow:
|
Chris@102
|
429 exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent;
|
Chris@102
|
430 final_exponent -= cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent;
|
Chris@102
|
431 }
|
Chris@102
|
432 else
|
Chris@102
|
433 {
|
Chris@102
|
434 exponent() = static_cast<Exponent>(final_exponent);
|
Chris@102
|
435 final_exponent = 0;
|
Chris@102
|
436 }
|
Chris@102
|
437 copy_and_round(*this, q.backend());
|
Chris@102
|
438 if(ss != sign())
|
Chris@102
|
439 negate();
|
Chris@102
|
440 break;
|
Chris@102
|
441 }
|
Chris@102
|
442 while(true);
|
Chris@102
|
443 }
|
Chris@102
|
444 //
|
Chris@102
|
445 // Check for scaling and/or over/under-flow:
|
Chris@102
|
446 //
|
Chris@102
|
447 final_exponent += exponent();
|
Chris@102
|
448 if(final_exponent > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
|
Chris@102
|
449 {
|
Chris@102
|
450 // Overflow:
|
Chris@102
|
451 exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity;
|
Chris@102
|
452 bits() = limb_type(0);
|
Chris@102
|
453 }
|
Chris@102
|
454 else if(final_exponent < cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent)
|
Chris@102
|
455 {
|
Chris@102
|
456 // Underflow:
|
Chris@102
|
457 exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero;
|
Chris@102
|
458 bits() = limb_type(0);
|
Chris@102
|
459 sign() = 0;
|
Chris@102
|
460 }
|
Chris@102
|
461 else
|
Chris@102
|
462 {
|
Chris@102
|
463 exponent() = static_cast<Exponent>(final_exponent);
|
Chris@102
|
464 }
|
Chris@102
|
465 return *this;
|
Chris@102
|
466 }
|
Chris@102
|
467
|
Chris@102
|
468 template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE>
|
Chris@102
|
469 std::string cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::str(std::streamsize dig, std::ios_base::fmtflags f) const
|
Chris@102
|
470 {
|
Chris@102
|
471 if(dig == 0)
|
Chris@102
|
472 dig = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::max_digits10;
|
Chris@102
|
473
|
Chris@102
|
474 bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific;
|
Chris@102
|
475 bool fixed = !scientific && (f & std::ios_base::fixed);
|
Chris@102
|
476
|
Chris@102
|
477 std::string s;
|
Chris@102
|
478
|
Chris@102
|
479 if(exponent() <= cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent)
|
Chris@102
|
480 {
|
Chris@102
|
481 // How far to left-shift in order to demormalise the mantissa:
|
Chris@102
|
482 boost::intmax_t shift = (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - exponent() - 1;
|
Chris@102
|
483 boost::intmax_t digits_wanted = static_cast<int>(dig);
|
Chris@102
|
484 boost::intmax_t base10_exp = exponent() >= 0 ? static_cast<boost::intmax_t>(std::floor(0.30103 * exponent())) : static_cast<boost::intmax_t>(std::ceil(0.30103 * exponent()));
|
Chris@102
|
485 //
|
Chris@102
|
486 // For fixed formatting we want /dig/ digits after the decimal point,
|
Chris@102
|
487 // so if the exponent is zero, allowing for the one digit before the
|
Chris@102
|
488 // decimal point, we want 1 + dig digits etc.
|
Chris@102
|
489 //
|
Chris@102
|
490 if(fixed)
|
Chris@102
|
491 digits_wanted += 1 + base10_exp;
|
Chris@102
|
492 if(scientific)
|
Chris@102
|
493 digits_wanted += 1;
|
Chris@102
|
494 if(digits_wanted < -1)
|
Chris@102
|
495 {
|
Chris@102
|
496 // Fixed precision, no significant digits, and nothing to round!
|
Chris@102
|
497 s = "0";
|
Chris@102
|
498 if(sign())
|
Chris@102
|
499 s.insert(static_cast<std::string::size_type>(0), 1, '-');
|
Chris@102
|
500 boost::multiprecision::detail::format_float_string(s, base10_exp, dig, f, true);
|
Chris@102
|
501 return s;
|
Chris@102
|
502 }
|
Chris@102
|
503 //
|
Chris@102
|
504 // power10 is the base10 exponent we need to multiply/divide by in order
|
Chris@102
|
505 // to convert our denormalised number to an integer with the right number of digits:
|
Chris@102
|
506 //
|
Chris@102
|
507 boost::intmax_t power10 = digits_wanted - base10_exp - 1;
|
Chris@102
|
508 //
|
Chris@102
|
509 // If we calculate 5^power10 rather than 10^power10 we need to move
|
Chris@102
|
510 // 2^power10 into /shift/
|
Chris@102
|
511 //
|
Chris@102
|
512 shift -= power10;
|
Chris@102
|
513 cpp_int i;
|
Chris@102
|
514 int roundup = 0; // 0=no rounding, 1=tie, 2=up
|
Chris@102
|
515 static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT;
|
Chris@102
|
516 //
|
Chris@102
|
517 // Set our working precision - this is heuristic based, we want
|
Chris@102
|
518 // a value as small as possible > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count to avoid large computations
|
Chris@102
|
519 // and excessive memory usage, but we also want to avoid having to
|
Chris@102
|
520 // up the computation and start again at a higher precision.
|
Chris@102
|
521 // So we round cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count up to the nearest whole number of limbs, and add
|
Chris@102
|
522 // one limb for good measure. This works very well for small exponents,
|
Chris@102
|
523 // but for larger exponents we add a few extra limbs to max_bits:
|
Chris@102
|
524 //
|
Chris@102
|
525 #ifdef BOOST_MP_STRESS_IO
|
Chris@102
|
526 boost::intmax_t max_bits = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 32;
|
Chris@102
|
527 #else
|
Chris@102
|
528 boost::intmax_t max_bits = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count % limb_bits ? limb_bits - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count % limb_bits : 0) + limb_bits;
|
Chris@102
|
529 if(power10)
|
Chris@102
|
530 max_bits += (msb(boost::multiprecision::detail::abs(power10)) / 8) * limb_bits;
|
Chris@102
|
531 #endif
|
Chris@102
|
532 do
|
Chris@102
|
533 {
|
Chris@102
|
534 boost::int64_t error = 0;
|
Chris@102
|
535 boost::intmax_t calc_exp = 0;
|
Chris@102
|
536 //
|
Chris@102
|
537 // Our integer result is: bits() * 2^-shift * 5^power10
|
Chris@102
|
538 //
|
Chris@102
|
539 i = bits();
|
Chris@102
|
540 if(shift < 0)
|
Chris@102
|
541 {
|
Chris@102
|
542 if(power10 >= 0)
|
Chris@102
|
543 {
|
Chris@102
|
544 // We go straight to the answer with all integer arithmetic,
|
Chris@102
|
545 // the result is always exact and never needs rounding:
|
Chris@102
|
546 BOOST_ASSERT(power10 <= (boost::intmax_t)INT_MAX);
|
Chris@102
|
547 i <<= -shift;
|
Chris@102
|
548 if(power10)
|
Chris@102
|
549 i *= pow(cpp_int(5), static_cast<unsigned>(power10));
|
Chris@102
|
550 }
|
Chris@102
|
551 else if(power10 < 0)
|
Chris@102
|
552 {
|
Chris@102
|
553 cpp_int d;
|
Chris@102
|
554 calc_exp = boost::multiprecision::cpp_bf_io_detail::restricted_pow(d, cpp_int(5), -power10, max_bits, error);
|
Chris@102
|
555 shift += calc_exp;
|
Chris@102
|
556 BOOST_ASSERT(shift < 0); // Must still be true!
|
Chris@102
|
557 i <<= -shift;
|
Chris@102
|
558 cpp_int r;
|
Chris@102
|
559 divide_qr(i, d, i, r);
|
Chris@102
|
560 roundup = boost::multiprecision::cpp_bf_io_detail::get_round_mode(r, d, error, i);
|
Chris@102
|
561 if(roundup < 0)
|
Chris@102
|
562 {
|
Chris@102
|
563 #ifdef BOOST_MP_STRESS_IO
|
Chris@102
|
564 max_bits += 32;
|
Chris@102
|
565 #else
|
Chris@102
|
566 max_bits *= 2;
|
Chris@102
|
567 #endif
|
Chris@102
|
568 shift = (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - exponent() - 1 - power10;
|
Chris@102
|
569 continue;
|
Chris@102
|
570 }
|
Chris@102
|
571 }
|
Chris@102
|
572 }
|
Chris@102
|
573 else
|
Chris@102
|
574 {
|
Chris@102
|
575 //
|
Chris@102
|
576 // Our integer is bits() * 2^-shift * 10^power10
|
Chris@102
|
577 //
|
Chris@102
|
578 if(power10 > 0)
|
Chris@102
|
579 {
|
Chris@102
|
580 if(power10)
|
Chris@102
|
581 {
|
Chris@102
|
582 cpp_int t;
|
Chris@102
|
583 calc_exp = boost::multiprecision::cpp_bf_io_detail::restricted_pow(t, cpp_int(5), power10, max_bits, error);
|
Chris@102
|
584 calc_exp += boost::multiprecision::cpp_bf_io_detail::restricted_multiply(i, i, t, max_bits, error);
|
Chris@102
|
585 shift -= calc_exp;
|
Chris@102
|
586 }
|
Chris@102
|
587 if((shift < 0) || ((shift == 0) && error))
|
Chris@102
|
588 {
|
Chris@102
|
589 // We only get here if we were asked for a crazy number of decimal digits -
|
Chris@102
|
590 // more than are present in a 2^max_bits number.
|
Chris@102
|
591 #ifdef BOOST_MP_STRESS_IO
|
Chris@102
|
592 max_bits += 32;
|
Chris@102
|
593 #else
|
Chris@102
|
594 max_bits *= 2;
|
Chris@102
|
595 #endif
|
Chris@102
|
596 shift = (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - exponent() - 1 - power10;
|
Chris@102
|
597 continue;
|
Chris@102
|
598 }
|
Chris@102
|
599 if(shift)
|
Chris@102
|
600 {
|
Chris@102
|
601 roundup = boost::multiprecision::cpp_bf_io_detail::get_round_mode(i, shift - 1, error);
|
Chris@102
|
602 if(roundup < 0)
|
Chris@102
|
603 {
|
Chris@102
|
604 #ifdef BOOST_MP_STRESS_IO
|
Chris@102
|
605 max_bits += 32;
|
Chris@102
|
606 #else
|
Chris@102
|
607 max_bits *= 2;
|
Chris@102
|
608 #endif
|
Chris@102
|
609 shift = (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - exponent() - 1 - power10;
|
Chris@102
|
610 continue;
|
Chris@102
|
611 }
|
Chris@102
|
612 i >>= shift;
|
Chris@102
|
613 }
|
Chris@102
|
614 }
|
Chris@102
|
615 else
|
Chris@102
|
616 {
|
Chris@102
|
617 // We're right shifting, *and* dividing by 5^-power10,
|
Chris@102
|
618 // so 5^-power10 can never be that large or we'd simply
|
Chris@102
|
619 // get zero as a result, and that case is already handled above:
|
Chris@102
|
620 cpp_int r;
|
Chris@102
|
621 BOOST_ASSERT(-power10 < INT_MAX);
|
Chris@102
|
622 cpp_int d = pow(cpp_int(5), static_cast<unsigned>(-power10));
|
Chris@102
|
623 d <<= shift;
|
Chris@102
|
624 divide_qr(i, d, i, r);
|
Chris@102
|
625 r <<= 1;
|
Chris@102
|
626 int c = r.compare(d);
|
Chris@102
|
627 roundup = c < 0 ? 0 : c == 0 ? 1 : 2;
|
Chris@102
|
628 }
|
Chris@102
|
629 }
|
Chris@102
|
630 s = i.str(0, std::ios_base::fmtflags(0));
|
Chris@102
|
631 //
|
Chris@102
|
632 // Check if we got the right number of digits, this
|
Chris@102
|
633 // is really a test of whether we calculated the
|
Chris@102
|
634 // decimal exponent correctly:
|
Chris@102
|
635 //
|
Chris@102
|
636 boost::intmax_t digits_got = i ? static_cast<boost::intmax_t>(s.size()) : 0;
|
Chris@102
|
637 if(digits_got != digits_wanted)
|
Chris@102
|
638 {
|
Chris@102
|
639 base10_exp += digits_got - digits_wanted;
|
Chris@102
|
640 if(fixed)
|
Chris@102
|
641 digits_wanted = digits_got; // strange but true.
|
Chris@102
|
642 power10 = digits_wanted - base10_exp - 1;
|
Chris@102
|
643 shift = (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - exponent() - 1 - power10;
|
Chris@102
|
644 if(fixed)
|
Chris@102
|
645 break;
|
Chris@102
|
646 roundup = 0;
|
Chris@102
|
647 }
|
Chris@102
|
648 else
|
Chris@102
|
649 break;
|
Chris@102
|
650 }
|
Chris@102
|
651 while(true);
|
Chris@102
|
652 //
|
Chris@102
|
653 // Check whether we need to round up: note that we could equally round up
|
Chris@102
|
654 // the integer /i/ above, but since we need to perform the rounding *after*
|
Chris@102
|
655 // the conversion to a string and the digit count check, we might as well
|
Chris@102
|
656 // do it here:
|
Chris@102
|
657 //
|
Chris@102
|
658 if((roundup == 2) || ((roundup == 1) && ((s[s.size() - 1] - '0') & 1)))
|
Chris@102
|
659 {
|
Chris@102
|
660 boost::multiprecision::detail::round_string_up_at(s, static_cast<int>(s.size() - 1), base10_exp);
|
Chris@102
|
661 }
|
Chris@102
|
662
|
Chris@102
|
663 if(sign())
|
Chris@102
|
664 s.insert(static_cast<std::string::size_type>(0), 1, '-');
|
Chris@102
|
665
|
Chris@102
|
666 boost::multiprecision::detail::format_float_string(s, base10_exp, dig, f, false);
|
Chris@102
|
667 }
|
Chris@102
|
668 else
|
Chris@102
|
669 {
|
Chris@102
|
670 switch(exponent())
|
Chris@102
|
671 {
|
Chris@102
|
672 case exponent_zero:
|
Chris@102
|
673 s = "0";
|
Chris@102
|
674 boost::multiprecision::detail::format_float_string(s, 0, dig, f, true);
|
Chris@102
|
675 break;
|
Chris@102
|
676 case exponent_nan:
|
Chris@102
|
677 s = "nan";
|
Chris@102
|
678 break;
|
Chris@102
|
679 case exponent_infinity:
|
Chris@102
|
680 s = sign() ? "-inf" : f & std::ios_base::showpos ? "+inf" : "inf";
|
Chris@102
|
681 break;
|
Chris@102
|
682 }
|
Chris@102
|
683 }
|
Chris@102
|
684 return s;
|
Chris@102
|
685 }
|
Chris@102
|
686
|
Chris@102
|
687 }}} // namespaces
|
Chris@102
|
688
|
Chris@102
|
689 #endif
|
Chris@102
|
690
|