]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /////////////////////////////////////////////////////////////// |
2 | // Copyright 2013 John Maddock. Distributed under the Boost | |
3 | // Software License, Version 1.0. (See accompanying file | |
4 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ | |
5 | ||
6 | #ifndef BOOST_MATH_CPP_BIN_FLOAT_HPP | |
7 | #define BOOST_MATH_CPP_BIN_FLOAT_HPP | |
8 | ||
9 | #include <boost/multiprecision/cpp_int.hpp> | |
10 | #include <boost/multiprecision/integer.hpp> | |
11 | #include <boost/math/special_functions/trunc.hpp> | |
12 | #include <boost/multiprecision/detail/float_string_cvt.hpp> | |
13 | ||
14 | // | |
15 | // Some includes we need from Boost.Math, since we rely on that library to provide these functions: | |
16 | // | |
17 | #include <boost/math/special_functions/asinh.hpp> | |
18 | #include <boost/math/special_functions/acosh.hpp> | |
19 | #include <boost/math/special_functions/atanh.hpp> | |
20 | #include <boost/math/special_functions/cbrt.hpp> | |
21 | #include <boost/math/special_functions/expm1.hpp> | |
22 | #include <boost/math/special_functions/gamma.hpp> | |
23 | ||
24 | namespace boost{ namespace multiprecision{ namespace backends{ | |
25 | ||
26 | enum digit_base_type | |
27 | { | |
28 | digit_base_2 = 2, | |
29 | digit_base_10 = 10 | |
30 | }; | |
31 | ||
32 | #ifdef BOOST_MSVC | |
33 | #pragma warning(push) | |
34 | #pragma warning(disable:4522 6326) // multiple assignment operators specified, comparison of two constants | |
35 | #endif | |
36 | ||
37 | namespace detail{ | |
38 | ||
39 | template <class U> | |
40 | inline typename enable_if_c<is_unsigned<U>::value, bool>::type is_negative(U) { return false; } | |
41 | template <class S> | |
42 | inline typename disable_if_c<is_unsigned<S>::value, bool>::type is_negative(S s) { return s < 0; } | |
43 | ||
44 | } | |
45 | ||
46 | template <unsigned Digits, digit_base_type DigitBase = digit_base_10, class Allocator = void, class Exponent = int, Exponent MinExponent = 0, Exponent MaxExponent = 0> | |
47 | class cpp_bin_float | |
48 | { | |
49 | public: | |
50 | static const unsigned bit_count = DigitBase == digit_base_2 ? Digits : (Digits * 1000uL) / 301uL + (((Digits * 1000uL) % 301) ? 2u : 1u); | |
51 | typedef cpp_int_backend<is_void<Allocator>::value ? bit_count : 0, bit_count, is_void<Allocator>::value ? unsigned_magnitude : signed_magnitude, unchecked, Allocator> rep_type; | |
52 | typedef cpp_int_backend<is_void<Allocator>::value ? 2 * bit_count : 0, 2 * bit_count, is_void<Allocator>::value ? unsigned_magnitude : signed_magnitude, unchecked, Allocator> double_rep_type; | |
53 | ||
54 | typedef typename rep_type::signed_types signed_types; | |
55 | typedef typename rep_type::unsigned_types unsigned_types; | |
56 | typedef boost::mpl::list<float, double, long double> float_types; | |
57 | typedef Exponent exponent_type; | |
58 | ||
59 | static const exponent_type max_exponent_limit = boost::integer_traits<exponent_type>::const_max - 2 * static_cast<exponent_type>(bit_count); | |
60 | static const exponent_type min_exponent_limit = boost::integer_traits<exponent_type>::const_min + 2 * static_cast<exponent_type>(bit_count); | |
61 | ||
62 | BOOST_STATIC_ASSERT_MSG(MinExponent >= min_exponent_limit, "Template parameter MinExponent is too negative for our internal logic to function correctly, sorry!"); | |
63 | BOOST_STATIC_ASSERT_MSG(MaxExponent <= max_exponent_limit, "Template parameter MaxExponent is too large for our internal logic to function correctly, sorry!"); | |
64 | BOOST_STATIC_ASSERT_MSG(MinExponent <= 0, "Template parameter MinExponent can not be positive!"); | |
65 | BOOST_STATIC_ASSERT_MSG(MaxExponent >= 0, "Template parameter MaxExponent can not be negative!"); | |
66 | ||
67 | static const exponent_type max_exponent = MaxExponent == 0 ? max_exponent_limit : MaxExponent; | |
68 | static const exponent_type min_exponent = MinExponent == 0 ? min_exponent_limit : MinExponent; | |
69 | ||
70 | static const exponent_type exponent_zero = max_exponent + 1; | |
71 | static const exponent_type exponent_infinity = max_exponent + 2; | |
72 | static const exponent_type exponent_nan = max_exponent + 3; | |
73 | ||
74 | private: | |
75 | ||
76 | rep_type m_data; | |
77 | exponent_type m_exponent; | |
78 | bool m_sign; | |
79 | public: | |
80 | cpp_bin_float() BOOST_MP_NOEXCEPT_IF(noexcept(rep_type())) : m_data(), m_exponent(exponent_zero), m_sign(false) {} | |
81 | ||
82 | cpp_bin_float(const cpp_bin_float &o) BOOST_MP_NOEXCEPT_IF(noexcept(rep_type(std::declval<const rep_type&>()))) | |
83 | : m_data(o.m_data), m_exponent(o.m_exponent), m_sign(o.m_sign) {} | |
84 | ||
85 | template <unsigned D, digit_base_type B, class A, class E, E MinE, E MaxE> | |
86 | cpp_bin_float(const cpp_bin_float<D, B, A, E, MinE, MaxE> &o, typename boost::enable_if_c<(bit_count >= cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count)>::type const* = 0) | |
87 | { | |
88 | *this = o; | |
89 | } | |
90 | template <unsigned D, digit_base_type B, class A, class E, E MinE, E MaxE> | |
91 | explicit cpp_bin_float(const cpp_bin_float<D, B, A, E, MinE, MaxE> &o, typename boost::disable_if_c<(bit_count >= cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count)>::type const* = 0) | |
92 | : m_exponent(o.exponent()), m_sign(o.sign()) | |
93 | { | |
94 | *this = o; | |
95 | } | |
96 | template <class Float> | |
97 | cpp_bin_float(const Float& f, | |
98 | typename boost::enable_if_c< | |
99 | (number_category<Float>::value == number_kind_floating_point) | |
100 | && (std::numeric_limits<Float>::digits <= (int)bit_count) | |
101 | && (std::numeric_limits<Float>::radix == 2) | |
102 | >::type const* = 0) | |
103 | : m_data(), m_exponent(0), m_sign(false) | |
104 | { | |
105 | this->assign_float(f); | |
106 | } | |
107 | ||
108 | template <class Float> | |
109 | explicit cpp_bin_float(const Float& f, | |
110 | typename boost::enable_if_c< | |
111 | (number_category<Float>::value == number_kind_floating_point) | |
112 | && (std::numeric_limits<Float>::digits > (int)bit_count) | |
113 | && (std::numeric_limits<Float>::radix == 2) | |
114 | >::type const* = 0) | |
115 | : m_data(), m_exponent(0), m_sign(false) | |
116 | { | |
117 | this->assign_float(f); | |
118 | } | |
119 | ||
120 | cpp_bin_float& operator=(const cpp_bin_float &o) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<rep_type&>() = std::declval<const rep_type&>())) | |
121 | { | |
122 | m_data = o.m_data; | |
123 | m_exponent = o.m_exponent; | |
124 | m_sign = o.m_sign; | |
125 | return *this; | |
126 | } | |
127 | ||
128 | template <unsigned D, digit_base_type B, class A, class E, E MinE, E MaxE> | |
129 | cpp_bin_float& operator=(const cpp_bin_float<D, B, A, E, MinE, MaxE> &f) | |
130 | { | |
131 | switch(eval_fpclassify(f)) | |
132 | { | |
133 | case FP_ZERO: | |
134 | m_data = limb_type(0); | |
135 | m_sign = f.sign(); | |
136 | m_exponent = exponent_zero; | |
137 | break; | |
138 | case FP_NAN: | |
139 | m_data = limb_type(0); | |
140 | m_sign = false; | |
141 | m_exponent = exponent_nan; | |
142 | break;; | |
143 | case FP_INFINITE: | |
144 | m_data = limb_type(0); | |
145 | m_sign = f.sign(); | |
146 | m_exponent = exponent_infinity; | |
147 | break; | |
148 | default: | |
149 | typename cpp_bin_float<D, B, A, E, MinE, MaxE>::rep_type b(f.bits()); | |
150 | this->exponent() = f.exponent() + (int)bit_count - (int)cpp_bin_float<D, B, A, E, MinE, MaxE>::bit_count; | |
151 | this->sign() = f.sign(); | |
152 | copy_and_round(*this, b); | |
153 | } | |
154 | return *this; | |
155 | } | |
156 | ||
157 | template <class Float> | |
158 | typename boost::enable_if_c< | |
159 | (number_category<Float>::value == number_kind_floating_point) | |
160 | //&& (std::numeric_limits<Float>::digits <= (int)bit_count) | |
161 | && (std::numeric_limits<Float>::radix == 2), cpp_bin_float&>::type operator=(const Float& f) | |
162 | { | |
163 | return assign_float(f); | |
164 | } | |
165 | ||
166 | template <class Float> | |
167 | typename boost::enable_if_c<is_floating_point<Float>::value, cpp_bin_float&>::type assign_float(Float f) | |
168 | { | |
169 | BOOST_MATH_STD_USING | |
170 | using default_ops::eval_add; | |
171 | typedef typename boost::multiprecision::detail::canonical<int, cpp_bin_float>::type bf_int_type; | |
172 | ||
173 | switch((boost::math::fpclassify)(f)) | |
174 | { | |
175 | case FP_ZERO: | |
176 | m_data = limb_type(0); | |
177 | m_sign = ((boost::math::signbit)(f) > 0); | |
178 | m_exponent = exponent_zero; | |
179 | return *this; | |
180 | case FP_NAN: | |
181 | m_data = limb_type(0); | |
182 | m_sign = false; | |
183 | m_exponent = exponent_nan; | |
184 | return *this; | |
185 | case FP_INFINITE: | |
186 | m_data = limb_type(0); | |
187 | m_sign = (f < 0); | |
188 | m_exponent = exponent_infinity; | |
189 | return *this; | |
190 | } | |
191 | if(f < 0) | |
192 | { | |
193 | *this = -f; | |
194 | this->negate(); | |
195 | return *this; | |
196 | } | |
197 | ||
198 | typedef typename mpl::front<unsigned_types>::type ui_type; | |
199 | m_data = static_cast<ui_type>(0u); | |
200 | m_sign = false; | |
201 | m_exponent = 0; | |
202 | ||
203 | static const int bits = sizeof(int) * CHAR_BIT - 1; | |
204 | int e; | |
205 | f = frexp(f, &e); | |
206 | while(f) | |
207 | { | |
208 | f = ldexp(f, bits); | |
209 | e -= bits; | |
210 | #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS | |
211 | int ipart = itrunc(f); | |
212 | #else | |
213 | int ipart = static_cast<int>(f); | |
214 | #endif | |
215 | f -= ipart; | |
216 | m_exponent += bits; | |
217 | cpp_bin_float t; | |
218 | t = static_cast<bf_int_type>(ipart); | |
219 | eval_add(*this, t); | |
220 | } | |
221 | m_exponent += static_cast<Exponent>(e); | |
222 | return *this; | |
223 | } | |
224 | ||
225 | template <class Float> | |
226 | typename boost::enable_if_c< | |
227 | (number_category<Float>::value == number_kind_floating_point) | |
228 | && !boost::is_floating_point<Float>::value | |
229 | /*&& (std::numeric_limits<number<Float> >::radix == 2)*/, | |
230 | cpp_bin_float&>::type assign_float(Float f) | |
231 | { | |
232 | BOOST_MATH_STD_USING | |
233 | using default_ops::eval_add; | |
234 | using default_ops::eval_get_sign; | |
235 | using default_ops::eval_convert_to; | |
236 | using default_ops::eval_subtract; | |
237 | ||
238 | typedef typename boost::multiprecision::detail::canonical<int, Float>::type f_int_type; | |
239 | typedef typename boost::multiprecision::detail::canonical<int, cpp_bin_float>::type bf_int_type; | |
240 | ||
241 | switch(eval_fpclassify(f)) | |
242 | { | |
243 | case FP_ZERO: | |
244 | m_data = limb_type(0); | |
245 | m_sign = ((boost::math::signbit)(f) > 0); | |
246 | m_exponent = exponent_zero; | |
247 | return *this; | |
248 | case FP_NAN: | |
249 | m_data = limb_type(0); | |
250 | m_sign = false; | |
251 | m_exponent = exponent_nan; | |
252 | return *this; | |
253 | case FP_INFINITE: | |
254 | m_data = limb_type(0); | |
255 | m_sign = (f < 0); | |
256 | m_exponent = exponent_infinity; | |
257 | return *this; | |
258 | } | |
259 | if(eval_get_sign(f) < 0) | |
260 | { | |
261 | f.negate(); | |
262 | *this = f; | |
263 | this->negate(); | |
264 | return *this; | |
265 | } | |
266 | ||
267 | typedef typename mpl::front<unsigned_types>::type ui_type; | |
268 | m_data = static_cast<ui_type>(0u); | |
269 | m_sign = false; | |
270 | m_exponent = 0; | |
271 | ||
272 | static const int bits = sizeof(int) * CHAR_BIT - 1; | |
273 | int e; | |
274 | eval_frexp(f, f, &e); | |
275 | while(eval_get_sign(f) != 0) | |
276 | { | |
277 | eval_ldexp(f, f, bits); | |
278 | e -= bits; | |
279 | int ipart; | |
280 | eval_convert_to(&ipart, f); | |
281 | eval_subtract(f, static_cast<f_int_type>(ipart)); | |
282 | m_exponent += bits; | |
283 | eval_add(*this, static_cast<bf_int_type>(ipart)); | |
284 | } | |
285 | m_exponent += e; | |
286 | if(m_exponent > max_exponent) | |
287 | m_exponent = exponent_infinity; | |
288 | if(m_exponent < min_exponent) | |
289 | { | |
290 | m_data = limb_type(0u); | |
291 | m_exponent = exponent_zero; | |
292 | m_sign = ((boost::math::signbit)(f) > 0); | |
293 | } | |
294 | else if(eval_get_sign(m_data) == 0) | |
295 | { | |
296 | m_exponent = exponent_zero; | |
297 | m_sign = ((boost::math::signbit)(f) > 0); | |
298 | } | |
299 | return *this; | |
300 | } | |
301 | ||
302 | template <class I> | |
303 | typename boost::enable_if<is_integral<I>, cpp_bin_float&>::type operator=(const I& i) | |
304 | { | |
305 | using default_ops::eval_bit_test; | |
306 | if(!i) | |
307 | { | |
308 | m_data = static_cast<limb_type>(0); | |
309 | m_exponent = exponent_zero; | |
310 | m_sign = false; | |
311 | } | |
312 | else | |
313 | { | |
314 | typedef typename make_unsigned<I>::type ui_type; | |
315 | ui_type fi = static_cast<ui_type>(boost::multiprecision::detail::unsigned_abs(i)); | |
316 | typedef typename boost::multiprecision::detail::canonical<ui_type, rep_type>::type ar_type; | |
317 | m_data = static_cast<ar_type>(fi); | |
318 | unsigned shift = msb(fi); | |
319 | if(shift >= bit_count) | |
320 | { | |
321 | m_exponent = static_cast<Exponent>(shift); | |
322 | m_data = static_cast<ar_type>(fi >> (shift + 1 - bit_count)); | |
323 | } | |
324 | else | |
325 | { | |
326 | m_exponent = static_cast<Exponent>(shift); | |
327 | eval_left_shift(m_data, bit_count - shift - 1); | |
328 | } | |
329 | BOOST_ASSERT(eval_bit_test(m_data, bit_count-1)); | |
330 | m_sign = detail::is_negative(i); | |
331 | } | |
332 | return *this; | |
333 | } | |
334 | ||
335 | cpp_bin_float& operator=(const char *s); | |
336 | ||
337 | void swap(cpp_bin_float &o) BOOST_NOEXCEPT | |
338 | { | |
339 | m_data.swap(o.m_data); | |
340 | std::swap(m_exponent, o.m_exponent); | |
341 | std::swap(m_sign, o.m_sign); | |
342 | } | |
343 | ||
344 | std::string str(std::streamsize dig, std::ios_base::fmtflags f) const; | |
345 | ||
346 | void negate() | |
347 | { | |
348 | if(m_exponent != exponent_nan) | |
349 | m_sign = !m_sign; | |
350 | } | |
351 | ||
352 | int compare(const cpp_bin_float &o) const BOOST_NOEXCEPT | |
353 | { | |
354 | if(m_sign != o.m_sign) | |
355 | return (m_exponent == exponent_zero) && (m_exponent == o.m_exponent) ? 0 : m_sign ? -1 : 1; | |
356 | int result; | |
357 | if(m_exponent == exponent_nan) | |
358 | return -1; | |
359 | else if(m_exponent != o.m_exponent) | |
360 | { | |
361 | if(m_exponent == exponent_zero) | |
362 | result = -1; | |
363 | else if(o.m_exponent == exponent_zero) | |
364 | result = 1; | |
365 | else | |
366 | result = m_exponent > o.m_exponent ? 1 : -1; | |
367 | } | |
368 | else | |
369 | result = m_data.compare(o.m_data); | |
370 | if(m_sign) | |
371 | result = -result; | |
372 | return result; | |
373 | } | |
374 | template <class A> | |
375 | int compare(const A& o) const BOOST_NOEXCEPT | |
376 | { | |
377 | cpp_bin_float b; | |
378 | b = o; | |
379 | return compare(b); | |
380 | } | |
381 | ||
382 | rep_type& bits() { return m_data; } | |
383 | const rep_type& bits()const { return m_data; } | |
384 | exponent_type& exponent() { return m_exponent; } | |
385 | const exponent_type& exponent()const { return m_exponent; } | |
386 | bool& sign() { return m_sign; } | |
387 | const bool& sign()const { return m_sign; } | |
388 | void check_invariants() | |
389 | { | |
390 | using default_ops::eval_bit_test; | |
391 | using default_ops::eval_is_zero; | |
392 | if((m_exponent <= max_exponent) && (m_exponent >= min_exponent)) | |
393 | { | |
394 | BOOST_ASSERT(eval_bit_test(m_data, bit_count - 1)); | |
395 | } | |
396 | else | |
397 | { | |
398 | BOOST_ASSERT(m_exponent > max_exponent); | |
399 | BOOST_ASSERT(m_exponent <= exponent_nan); | |
400 | BOOST_ASSERT(eval_is_zero(m_data)); | |
401 | } | |
402 | } | |
403 | template<class Archive> | |
404 | void serialize(Archive & ar, const unsigned int /*version*/) | |
405 | { | |
406 | ar & m_data; | |
407 | ar & m_exponent; | |
408 | ar & m_sign; | |
409 | } | |
410 | }; | |
411 | ||
412 | #ifdef BOOST_MSVC | |
413 | #pragma warning(pop) | |
414 | #endif | |
415 | ||
416 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class Int> | |
417 | inline void copy_and_round(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, Int &arg) | |
418 | { | |
419 | // Precondition: exponent of res must have been set before this function is called | |
420 | // as we may need to adjust it based on how many cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count in arg are set. | |
421 | using default_ops::eval_msb; | |
422 | using default_ops::eval_lsb; | |
423 | using default_ops::eval_left_shift; | |
424 | using default_ops::eval_bit_test; | |
425 | using default_ops::eval_right_shift; | |
426 | using default_ops::eval_increment; | |
427 | using default_ops::eval_get_sign; | |
428 | ||
429 | // cancellation may have resulted in arg being all zeros: | |
430 | if(eval_get_sign(arg) == 0) | |
431 | { | |
432 | res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero; | |
433 | res.sign() = false; | |
434 | res.bits() = static_cast<limb_type>(0u); | |
435 | return; | |
436 | } | |
437 | int msb = eval_msb(arg); | |
438 | if(static_cast<int>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) > msb + 1) | |
439 | { | |
440 | // Must have had cancellation in subtraction, shift left and copy: | |
441 | res.bits() = arg; | |
442 | eval_left_shift(res.bits(), cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - msb - 1); | |
443 | res.exponent() -= static_cast<Exponent>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - msb - 1); | |
444 | } | |
445 | else if(static_cast<int>(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) < msb + 1) | |
446 | { | |
447 | // We have more cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count than we need, so round as required, | |
448 | // first get the rounding bit: | |
449 | bool roundup = eval_bit_test(arg, msb - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count); | |
450 | // Then check for a tie: | |
451 | if(roundup && (msb - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count == eval_lsb(arg))) | |
452 | { | |
453 | // Ties round towards even: | |
454 | if(!eval_bit_test(arg, msb - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 1)) | |
455 | roundup = false; | |
456 | } | |
457 | // Shift off the cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count we don't need: | |
458 | eval_right_shift(arg, msb - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 1); | |
459 | res.exponent() += static_cast<Exponent>(msb - (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 1); | |
460 | if(roundup) | |
461 | { | |
462 | eval_increment(arg); | |
463 | if(eval_bit_test(arg, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)) | |
464 | { | |
465 | // This happens very very rairly: | |
466 | eval_right_shift(arg, 1u); | |
467 | ++res.exponent(); | |
468 | } | |
469 | } | |
470 | res.bits() = arg; | |
471 | } | |
472 | else | |
473 | { | |
474 | res.bits() = arg; | |
475 | } | |
476 | BOOST_ASSERT((eval_msb(res.bits()) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1)); | |
477 | ||
478 | if(res.exponent() > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent) | |
479 | { | |
480 | // Overflow: | |
481 | res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity; | |
482 | res.bits() = static_cast<limb_type>(0u); | |
483 | } | |
484 | else if(res.exponent() < cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent) | |
485 | { | |
486 | // Underflow: | |
487 | res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero; | |
488 | res.bits() = static_cast<limb_type>(0u); | |
489 | } | |
490 | } | |
491 | ||
492 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> | |
493 | inline void do_eval_add(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &b) | |
494 | { | |
495 | if(a.exponent() < b.exponent()) | |
496 | { | |
497 | bool s = a.sign(); | |
498 | do_eval_add(res, b, a); | |
499 | if(res.sign() != s) | |
500 | res.negate(); | |
501 | return; | |
502 | } | |
503 | ||
504 | using default_ops::eval_add; | |
505 | using default_ops::eval_bit_test; | |
506 | ||
507 | typedef typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type exponent_type; | |
508 | ||
509 | typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type dt; | |
510 | ||
511 | // Special cases first: | |
512 | switch(a.exponent()) | |
513 | { | |
514 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero: | |
515 | { | |
516 | bool s = a.sign(); | |
517 | res = b; | |
518 | res.sign() = s; | |
519 | return; | |
520 | } | |
521 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity: | |
522 | if(b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan) | |
523 | res = b; | |
524 | else | |
525 | res = a; | |
526 | return; // result is still infinite. | |
527 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan: | |
528 | res = a; | |
529 | return; // result is still a NaN. | |
530 | } | |
531 | switch(b.exponent()) | |
532 | { | |
533 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero: | |
534 | res = a; | |
535 | return; | |
536 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity: | |
537 | res = b; | |
538 | if(res.sign()) | |
539 | res.negate(); | |
540 | return; // result is infinite. | |
541 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan: | |
542 | res = b; | |
543 | return; // result is a NaN. | |
544 | } | |
545 | ||
546 | BOOST_STATIC_ASSERT(boost::integer_traits<exponent_type>::const_max - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent); | |
547 | ||
548 | bool s = a.sign(); | |
549 | dt = a.bits(); | |
550 | if(a.exponent() > (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + b.exponent()) | |
551 | { | |
552 | res.exponent() = a.exponent(); | |
553 | } | |
554 | else | |
555 | { | |
556 | exponent_type e_diff = a.exponent() - b.exponent(); | |
557 | BOOST_ASSERT(e_diff >= 0); | |
558 | eval_left_shift(dt, e_diff); | |
559 | res.exponent() = a.exponent() - e_diff; | |
560 | eval_add(dt, b.bits()); | |
561 | } | |
562 | ||
563 | copy_and_round(res, dt); | |
564 | res.check_invariants(); | |
565 | if(res.sign() != s) | |
566 | res.negate(); | |
567 | } | |
568 | ||
569 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> | |
570 | inline void do_eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &b) | |
571 | { | |
572 | using default_ops::eval_subtract; | |
573 | using default_ops::eval_bit_test; | |
574 | ||
575 | typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type dt; | |
576 | ||
577 | // Special cases first: | |
578 | switch(a.exponent()) | |
579 | { | |
580 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero: | |
581 | if(b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan) | |
582 | res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend(); | |
583 | else | |
584 | { | |
585 | bool s = a.sign(); | |
586 | res = b; | |
587 | if(res.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero) | |
588 | res.sign() = false; | |
589 | else if(res.sign() == s) | |
590 | res.negate(); | |
591 | } | |
592 | return; | |
593 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity: | |
594 | if((b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan) || (b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity)) | |
595 | res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend(); | |
596 | else | |
597 | res = a; | |
598 | return; | |
599 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan: | |
600 | res = a; | |
601 | return; // result is still a NaN. | |
602 | } | |
603 | switch(b.exponent()) | |
604 | { | |
605 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero: | |
606 | res = a; | |
607 | return; | |
608 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity: | |
609 | res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity; | |
610 | res.sign() = !a.sign(); | |
611 | res.bits() = static_cast<limb_type>(0u); | |
612 | return; // result is a NaN. | |
613 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan: | |
614 | res = b; | |
615 | return; // result is still a NaN. | |
616 | } | |
617 | ||
618 | bool s = a.sign(); | |
619 | if((a.exponent() > b.exponent()) || ((a.exponent() == b.exponent()) && a.bits().compare(b.bits()) >= 0)) | |
620 | { | |
621 | dt = a.bits(); | |
622 | if(a.exponent() <= (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + b.exponent()) | |
623 | { | |
624 | typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type e_diff = a.exponent() - b.exponent(); | |
625 | eval_left_shift(dt, e_diff); | |
626 | res.exponent() = a.exponent() - e_diff; | |
627 | eval_subtract(dt, b.bits()); | |
628 | } | |
629 | else | |
630 | res.exponent() = a.exponent(); | |
631 | } | |
632 | else | |
633 | { | |
634 | dt = b.bits(); | |
635 | if(b.exponent() <= a.exponent() + (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) | |
636 | { | |
637 | typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type e_diff = a.exponent() - b.exponent(); | |
638 | eval_left_shift(dt, -e_diff); | |
639 | res.exponent() = b.exponent() + e_diff; | |
640 | eval_subtract(dt, a.bits()); | |
641 | } | |
642 | else | |
643 | res.exponent() = b.exponent(); | |
644 | s = !s; | |
645 | } | |
646 | ||
647 | copy_and_round(res, dt); | |
648 | if(res.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero) | |
649 | res.sign() = false; | |
650 | else if(res.sign() != s) | |
651 | res.negate(); | |
652 | res.check_invariants(); | |
653 | } | |
654 | ||
655 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> | |
656 | inline void eval_add(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &b) | |
657 | { | |
658 | if(a.sign() == b.sign()) | |
659 | do_eval_add(res, a, b); | |
660 | else | |
661 | do_eval_subtract(res, a, b); | |
662 | } | |
663 | ||
664 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> | |
665 | inline void eval_add(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a) | |
666 | { | |
667 | return eval_add(res, res, a); | |
668 | } | |
669 | ||
670 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> | |
671 | inline void eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &b) | |
672 | { | |
673 | if(a.sign() != b.sign()) | |
674 | do_eval_add(res, a, b); | |
675 | else | |
676 | do_eval_subtract(res, a, b); | |
677 | } | |
678 | ||
679 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> | |
680 | inline void eval_subtract(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a) | |
681 | { | |
682 | return eval_subtract(res, res, a); | |
683 | } | |
684 | ||
685 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> | |
686 | inline void eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &b) | |
687 | { | |
688 | using default_ops::eval_bit_test; | |
689 | using default_ops::eval_multiply; | |
690 | ||
691 | // Special cases first: | |
692 | switch(a.exponent()) | |
693 | { | |
694 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero: | |
695 | { | |
696 | if(b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan) | |
697 | res = b; | |
698 | else if(b.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity) | |
699 | res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend(); | |
700 | else | |
701 | { | |
702 | bool s = a.sign() != b.sign(); | |
703 | res = a; | |
704 | res.sign() = s; | |
705 | } | |
706 | return; | |
707 | } | |
708 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity: | |
709 | switch(b.exponent()) | |
710 | { | |
711 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero: | |
712 | res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend(); | |
713 | break; | |
714 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan: | |
715 | res = b; | |
716 | break; | |
717 | default: | |
718 | bool s = a.sign() != b.sign(); | |
719 | res = a; | |
720 | res.sign() = s; | |
721 | break; | |
722 | } | |
723 | return; | |
724 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan: | |
725 | res = a; | |
726 | return; | |
727 | } | |
728 | if(b.exponent() > cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent) | |
729 | { | |
730 | bool s = a.sign() != b.sign(); | |
731 | res = b; | |
732 | res.sign() = s; | |
733 | return; | |
734 | } | |
735 | if((a.exponent() > 0) && (b.exponent() > 0)) | |
736 | { | |
737 | if(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent + 2 - a.exponent() < b.exponent()) | |
738 | { | |
739 | // We will certainly overflow: | |
740 | bool s = a.sign() != b.sign(); | |
741 | res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity; | |
742 | res.sign() = s; | |
743 | res.bits() = static_cast<limb_type>(0u); | |
744 | return; | |
745 | } | |
746 | } | |
747 | if((a.exponent() < 0) && (b.exponent() < 0)) | |
748 | { | |
749 | if(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent - 2 - a.exponent() > b.exponent()) | |
750 | { | |
751 | // We will certainly underflow: | |
752 | res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero; | |
753 | res.sign() = a.sign() != b.sign(); | |
754 | res.bits() = static_cast<limb_type>(0u); | |
755 | return; | |
756 | } | |
757 | } | |
758 | ||
759 | typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type dt; | |
760 | eval_multiply(dt, a.bits(), b.bits()); | |
761 | res.exponent() = a.exponent() + b.exponent() - cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count + 1; | |
762 | copy_and_round(res, dt); | |
763 | res.check_invariants(); | |
764 | res.sign() = a.sign() != b.sign(); | |
765 | } | |
766 | ||
767 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> | |
768 | inline void eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a) | |
769 | { | |
770 | eval_multiply(res, res, a); | |
771 | } | |
772 | ||
773 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class U> | |
774 | inline typename enable_if_c<is_unsigned<U>::value>::type eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const U &b) | |
775 | { | |
776 | using default_ops::eval_bit_test; | |
777 | using default_ops::eval_multiply; | |
778 | ||
779 | // Special cases first: | |
780 | switch(a.exponent()) | |
781 | { | |
782 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero: | |
783 | { | |
784 | bool s = a.sign(); | |
785 | res = a; | |
786 | res.sign() = s; | |
787 | return; | |
788 | } | |
789 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity: | |
790 | if(b == 0) | |
791 | res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend(); | |
792 | else | |
793 | res = a; | |
794 | return; | |
795 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan: | |
796 | res = a; | |
797 | return; | |
798 | } | |
799 | ||
800 | typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type dt; | |
801 | typedef typename boost::multiprecision::detail::canonical<U, typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type>::type canon_ui_type; | |
802 | eval_multiply(dt, a.bits(), static_cast<canon_ui_type>(b)); | |
803 | res.exponent() = a.exponent(); | |
804 | copy_and_round(res, dt); | |
805 | res.check_invariants(); | |
806 | res.sign() = a.sign(); | |
807 | } | |
808 | ||
809 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class U> | |
810 | inline typename enable_if_c<is_unsigned<U>::value>::type eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const U &b) | |
811 | { | |
812 | eval_multiply(res, res, b); | |
813 | } | |
814 | ||
815 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class S> | |
816 | inline typename enable_if_c<is_signed<S>::value>::type eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, const S &b) | |
817 | { | |
818 | typedef typename make_unsigned<S>::type ui_type; | |
819 | eval_multiply(res, a, static_cast<ui_type>(boost::multiprecision::detail::unsigned_abs(b))); | |
820 | if(b < 0) | |
821 | res.negate(); | |
822 | } | |
823 | ||
824 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class S> | |
825 | inline typename enable_if_c<is_signed<S>::value>::type eval_multiply(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const S &b) | |
826 | { | |
827 | eval_multiply(res, res, b); | |
828 | } | |
829 | ||
830 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> | |
831 | inline void eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &u, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &v) | |
832 | { | |
833 | #ifdef BOOST_MSVC | |
834 | #pragma warning(push) | |
835 | #pragma warning(disable:6326) // comparison of two constants | |
836 | #endif | |
837 | using default_ops::eval_subtract; | |
838 | using default_ops::eval_qr; | |
839 | using default_ops::eval_bit_test; | |
840 | using default_ops::eval_get_sign; | |
841 | using default_ops::eval_increment; | |
842 | ||
843 | // | |
844 | // Special cases first: | |
845 | // | |
846 | switch(u.exponent()) | |
847 | { | |
848 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero: | |
849 | { | |
850 | switch(v.exponent()) | |
851 | { | |
852 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero: | |
853 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan: | |
854 | res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend(); | |
855 | return; | |
856 | } | |
857 | bool s = u.sign() != v.sign(); | |
858 | res = u; | |
859 | res.sign() = s; | |
860 | return; | |
861 | } | |
862 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity: | |
863 | { | |
864 | switch(v.exponent()) | |
865 | { | |
866 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity: | |
867 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan: | |
868 | res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend(); | |
869 | return; | |
870 | } | |
871 | bool s = u.sign() != v.sign(); | |
872 | res = u; | |
873 | res.sign() = s; | |
874 | return; | |
875 | } | |
876 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan: | |
877 | res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend(); | |
878 | return; | |
879 | } | |
880 | switch(v.exponent()) | |
881 | { | |
882 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero: | |
883 | { | |
884 | bool s = u.sign() != v.sign(); | |
885 | res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend(); | |
886 | res.sign() = s; | |
887 | return; | |
888 | } | |
889 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity: | |
890 | res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero; | |
891 | res.bits() = limb_type(0); | |
892 | res.sign() = u.sign() != v.sign(); | |
893 | return; | |
894 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan: | |
895 | res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend(); | |
896 | return; | |
897 | } | |
898 | ||
899 | // We can scale u and v so that both are integers, then perform integer | |
900 | // division to obtain quotient q and remainder r, such that: | |
901 | // | |
902 | // q * v + r = u | |
903 | // | |
904 | // and hense: | |
905 | // | |
906 | // q + r/v = u/v | |
907 | // | |
908 | // From this, assuming q has cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count | |
909 | // bits we only need to determine whether | |
910 | // r/v is less than, equal to, or greater than 0.5 to determine rounding - | |
911 | // this we can do with a shift and comparison. | |
912 | // | |
913 | // We can set the exponent and sign of the result up front: | |
914 | // | |
915 | if((v.exponent() < 0) && (u.exponent() > 0)) | |
916 | { | |
917 | // Check for overflow: | |
918 | if(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent + v.exponent() < u.exponent() - 1) | |
919 | { | |
920 | res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity; | |
921 | res.sign() = u.sign() != v.sign(); | |
922 | res.bits() = static_cast<limb_type>(0u); | |
923 | return; | |
924 | } | |
925 | } | |
926 | else if((v.exponent() > 0) && (u.exponent() < 0)) | |
927 | { | |
928 | // Check for underflow: | |
929 | if(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent + v.exponent() > u.exponent()) | |
930 | { | |
931 | // We will certainly underflow: | |
932 | res.exponent() = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero; | |
933 | res.sign() = u.sign() != v.sign(); | |
934 | res.bits() = static_cast<limb_type>(0u); | |
935 | return; | |
936 | } | |
937 | } | |
938 | res.exponent() = u.exponent() - v.exponent() - 1; | |
939 | res.sign() = u.sign() != v.sign(); | |
940 | // | |
941 | // Now get the quotient and remainder: | |
942 | // | |
943 | typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type t(u.bits()), t2(v.bits()), q, r; | |
944 | eval_left_shift(t, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count); | |
945 | eval_qr(t, t2, q, r); | |
946 | // | |
947 | // We now have either "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count" | |
948 | // or "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count+1" significant | |
949 | // bits in q. | |
950 | // | |
951 | static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT; | |
952 | if(eval_bit_test(q, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)) | |
953 | { | |
954 | // | |
955 | // OK we have cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count+1 bits, | |
956 | // so we already have rounding info, | |
957 | // we just need to changes things if the last bit is 1 and either the | |
958 | // remainder is non-zero (ie we do not have a tie) or the quotient would | |
959 | // be odd if it were shifted to the correct number of bits (ie a tiebreak). | |
960 | // | |
961 | BOOST_ASSERT((eval_msb(q) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)); | |
962 | if((q.limbs()[0] & 1u) && (eval_get_sign(r) || (q.limbs()[0] & 2u))) | |
963 | { | |
964 | eval_increment(q); | |
965 | } | |
966 | } | |
967 | else | |
968 | { | |
969 | // | |
970 | // We have exactly "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count" bits in q. | |
971 | // Get rounding info, which we can get by comparing 2r with v. | |
972 | // We want to call copy_and_round to handle rounding and general cleanup, | |
973 | // so we'll left shift q and add some fake digits on the end to represent | |
974 | // how we'll be rounding. | |
975 | // | |
976 | BOOST_ASSERT((eval_msb(q) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1)); | |
977 | static const unsigned lshift = (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count < limb_bits) ? 2 : limb_bits; | |
978 | eval_left_shift(q, lshift); | |
979 | res.exponent() -= lshift; | |
980 | eval_left_shift(r, 1u); | |
981 | int c = r.compare(v.bits()); | |
982 | if(c == 0) | |
983 | q.limbs()[0] |= static_cast<limb_type>(1u) << (lshift - 1); | |
984 | else if(c > 0) | |
985 | q.limbs()[0] |= (static_cast<limb_type>(1u) << (lshift - 1)) + static_cast<limb_type>(1u); | |
986 | } | |
987 | copy_and_round(res, q); | |
988 | #ifdef BOOST_MSVC | |
989 | #pragma warning(pop) | |
990 | #endif | |
991 | } | |
992 | ||
993 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> | |
994 | inline void eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg) | |
995 | { | |
996 | eval_divide(res, res, arg); | |
997 | } | |
998 | ||
999 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class U> | |
1000 | inline typename enable_if_c<is_unsigned<U>::value>::type eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &u, const U &v) | |
1001 | { | |
1002 | #ifdef BOOST_MSVC | |
1003 | #pragma warning(push) | |
1004 | #pragma warning(disable:6326) // comparison of two constants | |
1005 | #endif | |
1006 | using default_ops::eval_subtract; | |
1007 | using default_ops::eval_qr; | |
1008 | using default_ops::eval_bit_test; | |
1009 | using default_ops::eval_get_sign; | |
1010 | using default_ops::eval_increment; | |
1011 | ||
1012 | // | |
1013 | // Special cases first: | |
1014 | // | |
1015 | switch(u.exponent()) | |
1016 | { | |
1017 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero: | |
1018 | { | |
1019 | if(v == 0) | |
1020 | { | |
1021 | res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend(); | |
1022 | return; | |
1023 | } | |
1024 | bool s = u.sign() != (v < 0); | |
1025 | res = u; | |
1026 | res.sign() = s; | |
1027 | return; | |
1028 | } | |
1029 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity: | |
1030 | res = u; | |
1031 | return; | |
1032 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan: | |
1033 | res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend(); | |
1034 | return; | |
1035 | } | |
1036 | if(v == 0) | |
1037 | { | |
1038 | bool s = u.sign(); | |
1039 | res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend(); | |
1040 | res.sign() = s; | |
1041 | return; | |
1042 | } | |
1043 | ||
1044 | // We can scale u and v so that both are integers, then perform integer | |
1045 | // division to obtain quotient q and remainder r, such that: | |
1046 | // | |
1047 | // q * v + r = u | |
1048 | // | |
1049 | // and hense: | |
1050 | // | |
1051 | // q + r/v = u/v | |
1052 | // | |
1053 | // From this, assuming q has "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count" cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count, we only need to determine whether | |
1054 | // r/v is less than, equal to, or greater than 0.5 to determine rounding - | |
1055 | // this we can do with a shift and comparison. | |
1056 | // | |
1057 | // We can set the exponent and sign of the result up front: | |
1058 | // | |
1059 | int gb = msb(v); | |
1060 | res.exponent() = u.exponent() - static_cast<Exponent>(gb) - static_cast<Exponent>(1); | |
1061 | res.sign() = u.sign(); | |
1062 | // | |
1063 | // Now get the quotient and remainder: | |
1064 | // | |
1065 | typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type t(u.bits()), q, r; | |
1066 | eval_left_shift(t, gb + 1); | |
1067 | eval_qr(t, number<typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type>::canonical_value(v), q, r); | |
1068 | // | |
1069 | // We now have either "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count" or "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count+1" significant cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count in q. | |
1070 | // | |
1071 | static const unsigned limb_bits = sizeof(limb_type) * CHAR_BIT; | |
1072 | if(eval_bit_test(q, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)) | |
1073 | { | |
1074 | // | |
1075 | // OK we have cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count+1 cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count, so we already have rounding info, | |
1076 | // we just need to changes things if the last bit is 1 and the | |
1077 | // remainder is non-zero (ie we do not have a tie). | |
1078 | // | |
1079 | BOOST_ASSERT((eval_msb(q) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)); | |
1080 | if((q.limbs()[0] & 1u) && eval_get_sign(r)) | |
1081 | { | |
1082 | eval_increment(q); | |
1083 | } | |
1084 | } | |
1085 | else | |
1086 | { | |
1087 | // | |
1088 | // We have exactly "cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count" cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count in q. | |
1089 | // Get rounding info, which we can get by comparing 2r with v. | |
1090 | // We want to call copy_and_round to handle rounding and general cleanup, | |
1091 | // so we'll left shift q and add some fake cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count on the end to represent | |
1092 | // how we'll be rounding. | |
1093 | // | |
1094 | BOOST_ASSERT((eval_msb(q) == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1)); | |
1095 | static const unsigned lshift = cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count < limb_bits ? 2 : limb_bits; | |
1096 | eval_left_shift(q, lshift); | |
1097 | res.exponent() -= lshift; | |
1098 | eval_left_shift(r, 1u); | |
1099 | int c = r.compare(number<typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type>::canonical_value(v)); | |
1100 | if(c == 0) | |
1101 | q.limbs()[0] |= static_cast<limb_type>(1u) << (lshift - 1); | |
1102 | else if(c > 0) | |
1103 | q.limbs()[0] |= (static_cast<limb_type>(1u) << (lshift - 1)) + static_cast<limb_type>(1u); | |
1104 | } | |
1105 | copy_and_round(res, q); | |
1106 | #ifdef BOOST_MSVC | |
1107 | #pragma warning(pop) | |
1108 | #endif | |
1109 | } | |
1110 | ||
1111 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class U> | |
1112 | inline typename enable_if_c<is_unsigned<U>::value>::type eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const U &v) | |
1113 | { | |
1114 | eval_divide(res, res, v); | |
1115 | } | |
1116 | ||
1117 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class S> | |
1118 | inline typename enable_if_c<is_signed<S>::value>::type eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &u, const S &v) | |
1119 | { | |
1120 | typedef typename make_unsigned<S>::type ui_type; | |
1121 | eval_divide(res, u, static_cast<ui_type>(boost::multiprecision::detail::unsigned_abs(v))); | |
1122 | if(v < 0) | |
1123 | res.negate(); | |
1124 | } | |
1125 | ||
1126 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class S> | |
1127 | inline typename enable_if_c<is_signed<S>::value>::type eval_divide(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const S &v) | |
1128 | { | |
1129 | eval_divide(res, res, v); | |
1130 | } | |
1131 | ||
1132 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> | |
1133 | inline int eval_get_sign(const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg) | |
1134 | { | |
1135 | return arg.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero ? 0 : arg.sign() ? -1 : 1; | |
1136 | } | |
1137 | ||
1138 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> | |
1139 | inline bool eval_is_zero(const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg) | |
1140 | { | |
1141 | return arg.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero; | |
1142 | } | |
1143 | ||
1144 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> | |
1145 | inline bool eval_eq(const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &a, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &b) | |
1146 | { | |
1147 | if(a.exponent() == b.exponent()) | |
1148 | { | |
1149 | if(a.exponent() == cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero) | |
1150 | return true; | |
1151 | return (a.sign() == b.sign()) | |
1152 | && (a.bits().compare(b.bits()) == 0) | |
1153 | && (a.exponent() != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan); | |
1154 | } | |
1155 | return false; | |
1156 | } | |
1157 | ||
1158 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> | |
1159 | inline void eval_convert_to(boost::long_long_type *res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg) | |
1160 | { | |
1161 | switch(arg.exponent()) | |
1162 | { | |
1163 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero: | |
1164 | *res = 0; | |
1165 | return; | |
1166 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan: | |
1167 | BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer.")); | |
1168 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity: | |
1169 | *res = (std::numeric_limits<boost::long_long_type>::max)(); | |
1170 | if(arg.sign()) | |
1171 | *res = -*res; | |
1172 | return; | |
1173 | } | |
1174 | typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::rep_type man(arg.bits()); | |
1175 | typename mpl::if_c<sizeof(typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type) < sizeof(int), int, typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type>::type shift | |
1176 | = (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 - arg.exponent(); | |
1177 | if(shift > (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1) | |
1178 | { | |
1179 | *res = 0; | |
1180 | return; | |
1181 | } | |
1182 | if(arg.sign() && (arg.compare((std::numeric_limits<boost::long_long_type>::min)()) <= 0)) | |
1183 | { | |
1184 | *res = (std::numeric_limits<boost::long_long_type>::min)(); | |
1185 | return; | |
1186 | } | |
1187 | else if(!arg.sign() && (arg.compare((std::numeric_limits<boost::long_long_type>::max)()) >= 0)) | |
1188 | { | |
1189 | *res = (std::numeric_limits<boost::long_long_type>::max)(); | |
1190 | return; | |
1191 | } | |
1192 | eval_right_shift(man, shift); | |
1193 | eval_convert_to(res, man); | |
1194 | if(arg.sign()) | |
1195 | { | |
1196 | *res = -*res; | |
1197 | } | |
1198 | } | |
1199 | ||
1200 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> | |
1201 | inline void eval_convert_to(boost::ulong_long_type *res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg) | |
1202 | { | |
1203 | switch(arg.exponent()) | |
1204 | { | |
1205 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero: | |
1206 | *res = 0; | |
1207 | return; | |
1208 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan: | |
1209 | BOOST_THROW_EXCEPTION(std::runtime_error("Could not convert NaN to integer.")); | |
1210 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity: | |
1211 | *res = (std::numeric_limits<boost::ulong_long_type>::max)(); | |
1212 | return; | |
1213 | } | |
1214 | typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::rep_type man(arg.bits()); | |
1215 | typename mpl::if_c<sizeof(typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type) < sizeof(int), int, typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type>::type shift | |
1216 | = (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 - arg.exponent(); | |
1217 | if(shift > (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1) | |
1218 | { | |
1219 | *res = 0; | |
1220 | return; | |
1221 | } | |
1222 | else if(shift < 0) | |
1223 | { | |
1224 | // TODO: what if we have fewer cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count than a boost::long_long_type? | |
1225 | *res = (std::numeric_limits<boost::long_long_type>::max)(); | |
1226 | return; | |
1227 | } | |
1228 | eval_right_shift(man, shift); | |
1229 | eval_convert_to(res, man); | |
1230 | } | |
1231 | ||
1232 | template <class Float, unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> | |
1233 | inline typename boost::enable_if_c<boost::is_float<Float>::value>::type eval_convert_to(Float *res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &original_arg) | |
1234 | { | |
1235 | // | |
1236 | // Perform rounding first, then afterwards extract the digits: | |
1237 | // | |
1238 | typedef cpp_bin_float<std::numeric_limits<Float>::digits, digit_base_2, void, Exponent, MinE, MaxE> conv_type; | |
1239 | typedef typename common_type<typename conv_type::exponent_type, int>::type common_exp_type; | |
1240 | conv_type arg(original_arg); | |
1241 | switch(arg.exponent()) | |
1242 | { | |
1243 | case conv_type::exponent_zero: | |
1244 | *res = 0; | |
1245 | if(arg.sign()) | |
1246 | *res = -*res; | |
1247 | return; | |
1248 | case conv_type::exponent_nan: | |
1249 | *res = std::numeric_limits<Float>::quiet_NaN(); | |
1250 | return; | |
1251 | case conv_type::exponent_infinity: | |
1252 | *res = (std::numeric_limits<Float>::infinity)(); | |
1253 | if(arg.sign()) | |
1254 | *res = -*res; | |
1255 | return; | |
1256 | } | |
1257 | common_exp_type e = arg.exponent(); | |
1258 | static const common_exp_type min_exp_limit = std::numeric_limits<Float>::min_exponent | |
1259 | - (common_exp_type)cpp_bin_float<std::numeric_limits<Float>::digits, digit_base_2, void, Exponent, MinE, MaxE>::bit_count - std::numeric_limits<Float>::digits - 2; | |
1260 | e -= cpp_bin_float<std::numeric_limits<Float>::digits, digit_base_2, void, Exponent, MinE, MaxE>::bit_count - 1; | |
1261 | if(e < min_exp_limit) | |
1262 | { | |
1263 | *res = 0; | |
1264 | return; | |
1265 | } | |
1266 | if(e > std::numeric_limits<Float>::max_exponent) | |
1267 | { | |
1268 | *res = std::numeric_limits<Float>::has_infinity ? std::numeric_limits<Float>::infinity() : (std::numeric_limits<Float>::max)(); | |
1269 | return; | |
1270 | } | |
1271 | ||
1272 | *res = std::ldexp(static_cast<Float>(*arg.bits().limbs()), static_cast<int>(e)); | |
1273 | for(unsigned i = 1; i < arg.bits().size(); ++i) | |
1274 | { | |
1275 | e += sizeof(*arg.bits().limbs()) * CHAR_BIT; | |
1276 | *res += std::ldexp(static_cast<Float>(arg.bits().limbs()[i]), static_cast<int>(e)); | |
1277 | } | |
1278 | if(arg.sign()) | |
1279 | *res = -*res; | |
1280 | } | |
1281 | ||
1282 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> | |
1283 | inline void eval_frexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg, Exponent *e) | |
1284 | { | |
1285 | switch(arg.exponent()) | |
1286 | { | |
1287 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero: | |
1288 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan: | |
1289 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity: | |
1290 | *e = 0; | |
1291 | res = arg; | |
1292 | return; | |
1293 | } | |
1294 | res = arg; | |
1295 | *e = arg.exponent() + 1; | |
1296 | res.exponent() = -1; | |
1297 | } | |
1298 | ||
1299 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class I> | |
1300 | inline void eval_frexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg, I *pe) | |
1301 | { | |
1302 | Exponent e; | |
1303 | eval_frexp(res, arg, &e); | |
1304 | if((e > (std::numeric_limits<I>::max)()) || (e < (std::numeric_limits<I>::min)())) | |
1305 | { | |
1306 | BOOST_THROW_EXCEPTION(std::runtime_error("Exponent was outside of the range of the argument type to frexp.")); | |
1307 | } | |
1308 | *pe = static_cast<I>(e); | |
1309 | } | |
1310 | ||
1311 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> | |
1312 | inline void eval_ldexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg, Exponent e) | |
1313 | { | |
1314 | switch(arg.exponent()) | |
1315 | { | |
1316 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero: | |
1317 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan: | |
1318 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity: | |
1319 | res = arg; | |
1320 | return; | |
1321 | } | |
1322 | if((e > 0) && (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent - e < arg.exponent())) | |
1323 | { | |
1324 | // Overflow: | |
1325 | res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend(); | |
1326 | res.sign() = arg.sign(); | |
1327 | } | |
1328 | else if((e < 0) && (cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent - e > arg.exponent())) | |
1329 | { | |
1330 | // Underflow: | |
1331 | res = limb_type(0); | |
1332 | } | |
1333 | else | |
1334 | { | |
1335 | res = arg; | |
1336 | res.exponent() += e; | |
1337 | } | |
1338 | } | |
1339 | ||
1340 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class I> | |
1341 | inline typename enable_if_c<is_unsigned<I>::value>::type eval_ldexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg, I e) | |
1342 | { | |
1343 | typedef typename make_signed<I>::type si_type; | |
1344 | if(e > static_cast<I>((std::numeric_limits<si_type>::max)())) | |
1345 | res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend(); | |
1346 | else | |
1347 | eval_ldexp(res, arg, static_cast<si_type>(e)); | |
1348 | } | |
1349 | ||
1350 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, class I> | |
1351 | inline typename enable_if_c<is_signed<I>::value>::type eval_ldexp(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg, I e) | |
1352 | { | |
1353 | if((e > (std::numeric_limits<Exponent>::max)()) || (e < (std::numeric_limits<Exponent>::min)())) | |
1354 | { | |
1355 | res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity().backend(); | |
1356 | if(e < 0) | |
1357 | res.negate(); | |
1358 | } | |
1359 | else | |
1360 | eval_ldexp(res, arg, static_cast<Exponent>(e)); | |
1361 | } | |
1362 | ||
1363 | /* | |
1364 | * Sign manipulation | |
1365 | */ | |
1366 | ||
1367 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> | |
1368 | inline void eval_abs(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg) | |
1369 | { | |
1370 | res = arg; | |
1371 | res.sign() = false; | |
1372 | } | |
1373 | ||
1374 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> | |
1375 | inline void eval_fabs(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg) | |
1376 | { | |
1377 | res = arg; | |
1378 | res.sign() = false; | |
1379 | } | |
1380 | ||
1381 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> | |
1382 | inline int eval_fpclassify(const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg) | |
1383 | { | |
1384 | switch(arg.exponent()) | |
1385 | { | |
1386 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero: | |
1387 | return FP_ZERO; | |
1388 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity: | |
1389 | return FP_INFINITE; | |
1390 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan: | |
1391 | return FP_NAN; | |
1392 | } | |
1393 | return FP_NORMAL; | |
1394 | } | |
1395 | ||
1396 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> | |
1397 | inline void eval_sqrt(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg) | |
1398 | { | |
1399 | using default_ops::eval_integer_sqrt; | |
1400 | using default_ops::eval_bit_test; | |
1401 | using default_ops::eval_increment; | |
1402 | switch(arg.exponent()) | |
1403 | { | |
1404 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero: | |
1405 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan: | |
1406 | res = arg; | |
1407 | return; | |
1408 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity: | |
1409 | if(arg.sign()) | |
1410 | res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend(); | |
1411 | else | |
1412 | res = arg; | |
1413 | return; | |
1414 | } | |
1415 | if(arg.sign()) | |
1416 | { | |
1417 | res = std::numeric_limits<number<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN().backend(); | |
1418 | return; | |
1419 | } | |
1420 | ||
1421 | typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::double_rep_type t(arg.bits()), r, s; | |
1422 | eval_left_shift(t, arg.exponent() & 1 ? cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count : cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1); | |
1423 | eval_integer_sqrt(s, r, t); | |
1424 | ||
1425 | if(!eval_bit_test(s, cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count)) | |
1426 | { | |
1427 | // We have exactly the right number of cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count in the result, round as required: | |
1428 | if(s.compare(r) < 0) | |
1429 | { | |
1430 | eval_increment(s); | |
1431 | } | |
1432 | } | |
1433 | typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type ae = arg.exponent(); | |
1434 | res.exponent() = ae / 2; | |
1435 | if((ae & 1) && (ae < 0)) | |
1436 | --res.exponent(); | |
1437 | copy_and_round(res, s); | |
1438 | } | |
1439 | ||
1440 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> | |
1441 | inline void eval_floor(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg) | |
1442 | { | |
1443 | using default_ops::eval_increment; | |
1444 | switch(arg.exponent()) | |
1445 | { | |
1446 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero: | |
1447 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan: | |
1448 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity: | |
1449 | res = arg; | |
1450 | return; | |
1451 | } | |
1452 | typename mpl::if_c<sizeof(typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type) < sizeof(int), int, typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type>::type shift = | |
1453 | (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - arg.exponent() - 1; | |
1454 | if((arg.exponent() > (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent) || (shift <= 0)) | |
1455 | { | |
1456 | // Either arg is already an integer, or a special value: | |
1457 | res = arg; | |
1458 | return; | |
1459 | } | |
1460 | if(shift >= (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) | |
1461 | { | |
1462 | res = static_cast<signed_limb_type>(arg.sign() ? -1 : 0); | |
1463 | return; | |
1464 | } | |
1465 | bool fractional = (int)eval_lsb(arg.bits()) < shift; | |
1466 | res = arg; | |
1467 | eval_right_shift(res.bits(), shift); | |
1468 | if(fractional && res.sign()) | |
1469 | { | |
1470 | eval_increment(res.bits()); | |
1471 | if(eval_msb(res.bits()) != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 - shift) | |
1472 | { | |
1473 | // Must have extended result by one bit in the increment: | |
1474 | --shift; | |
1475 | ++res.exponent(); | |
1476 | } | |
1477 | } | |
1478 | eval_left_shift(res.bits(), shift); | |
1479 | } | |
1480 | ||
1481 | template <unsigned Digits, digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> | |
1482 | inline void eval_ceil(cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &res, const cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> &arg) | |
1483 | { | |
1484 | using default_ops::eval_increment; | |
1485 | switch(arg.exponent()) | |
1486 | { | |
1487 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_zero: | |
1488 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan: | |
1489 | case cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity: | |
1490 | res = arg; | |
1491 | return; | |
1492 | } | |
1493 | typename mpl::if_c<sizeof(typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type) < sizeof(int), int, typename cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type>::type shift = (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - arg.exponent() - 1; | |
1494 | if((arg.exponent() > (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent) || (shift <= 0)) | |
1495 | { | |
1496 | // Either arg is already an integer, or a special value: | |
1497 | res = arg; | |
1498 | return; | |
1499 | } | |
1500 | if(shift >= (int)cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count) | |
1501 | { | |
1502 | bool s = arg.sign(); // takes care of signed zeros | |
1503 | res = static_cast<signed_limb_type>(arg.sign() ? 0 : 1); | |
1504 | res.sign() = s; | |
1505 | return; | |
1506 | } | |
1507 | bool fractional = (int)eval_lsb(arg.bits()) < shift; | |
1508 | res = arg; | |
1509 | eval_right_shift(res.bits(), shift); | |
1510 | if(fractional && !res.sign()) | |
1511 | { | |
1512 | eval_increment(res.bits()); | |
1513 | if(eval_msb(res.bits()) != cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count - 1 - shift) | |
1514 | { | |
1515 | // Must have extended result by one bit in the increment: | |
1516 | --shift; | |
1517 | ++res.exponent(); | |
1518 | } | |
1519 | } | |
1520 | eval_left_shift(res.bits(), shift); | |
1521 | } | |
1522 | ||
1523 | template<unsigned D1, backends::digit_base_type B1, class A1, class E1, E1 M1, E1 M2> | |
1524 | inline std::size_t hash_value(const cpp_bin_float<D1, B1, A1, E1, M1, M2>& val) | |
1525 | { | |
1526 | std::size_t result = hash_value(val.bits()); | |
1527 | boost::hash_combine(result, val.exponent()); | |
1528 | boost::hash_combine(result, val.sign()); | |
1529 | return result; | |
1530 | } | |
1531 | ||
1532 | ||
1533 | } // namespace backends | |
1534 | ||
1535 | #ifdef BOOST_NO_SFINAE_EXPR | |
1536 | ||
1537 | namespace detail{ | |
1538 | ||
1539 | template<unsigned D1, backends::digit_base_type B1, class A1, class E1, E1 M1, E1 M2, unsigned D2, backends::digit_base_type B2, class A2, class E2, E2 M3, E2 M4> | |
1540 | struct is_explicitly_convertible<backends::cpp_bin_float<D1, B1, A1, E1, M1, M2>, backends::cpp_bin_float<D2, B2, A2, E2, M3, M4> > : public mpl::true_ {}; | |
1541 | template<class FloatT, unsigned D2, backends::digit_base_type B2, class A2, class E2, E2 M3, E2 M4> | |
1542 | struct is_explicitly_convertible<FloatT, backends::cpp_bin_float<D2, B2, A2, E2, M3, M4> > : public boost::is_floating_point<FloatT> {}; | |
1543 | ||
1544 | } | |
1545 | #endif | |
1546 | ||
1547 | template<unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Exponent, Exponent MinE, Exponent MaxE, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates> | |
1548 | inline int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates>& arg) | |
1549 | { | |
1550 | return arg.backend().sign(); | |
1551 | } | |
1552 | ||
1553 | template<unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Exponent, Exponent MinE, Exponent MaxE, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates> | |
1554 | inline boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> | |
1555 | copysign BOOST_PREVENT_MACRO_SUBSTITUTION( | |
1556 | const boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates>& a, | |
1557 | const boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates>& b) | |
1558 | { | |
1559 | boost::multiprecision::number<boost::multiprecision::backends::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> res(a); | |
1560 | res.backend().sign() = b.backend().sign(); | |
1561 | return res; | |
1562 | } | |
1563 | ||
1564 | using backends::cpp_bin_float; | |
1565 | using backends::digit_base_2; | |
1566 | using backends::digit_base_10; | |
1567 | ||
1568 | template<unsigned Digits, backends::digit_base_type DigitBase, class Exponent, Exponent MinE, Exponent MaxE, class Allocator> | |
1569 | struct number_category<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > : public boost::mpl::int_<boost::multiprecision::number_kind_floating_point>{}; | |
1570 | ||
1571 | template<unsigned Digits, backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE> | |
1572 | struct expression_template_default<cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > | |
1573 | { | |
1574 | static const expression_template_option value = is_void<Allocator>::value ? et_off : et_on; | |
1575 | }; | |
1576 | ||
1577 | typedef number<backends::cpp_bin_float<50> > cpp_bin_float_50; | |
1578 | typedef number<backends::cpp_bin_float<100> > cpp_bin_float_100; | |
1579 | ||
1580 | typedef number<backends::cpp_bin_float<24, backends::digit_base_2, void, boost::int16_t, -126, 127>, et_off> cpp_bin_float_single; | |
1581 | typedef number<backends::cpp_bin_float<53, backends::digit_base_2, void, boost::int16_t, -1022, 1023>, et_off> cpp_bin_float_double; | |
1582 | typedef number<backends::cpp_bin_float<64, backends::digit_base_2, void, boost::int16_t, -16382, 16383>, et_off> cpp_bin_float_double_extended; | |
1583 | typedef number<backends::cpp_bin_float<113, backends::digit_base_2, void, boost::int16_t, -16382, 16383>, et_off> cpp_bin_float_quad; | |
1584 | ||
1585 | } // namespace multiprecision | |
1586 | ||
1587 | namespace math { | |
1588 | ||
1589 | using boost::multiprecision::signbit; | |
1590 | using boost::multiprecision::copysign; | |
1591 | ||
1592 | } // namespace math | |
1593 | ||
1594 | } // namespace boost | |
1595 | ||
1596 | #include <boost/multiprecision/cpp_bin_float/io.hpp> | |
1597 | #include <boost/multiprecision/cpp_bin_float/transcendental.hpp> | |
1598 | ||
1599 | namespace std{ | |
1600 | ||
1601 | // | |
1602 | // numeric_limits [partial] specializations for the types declared in this header: | |
1603 | // | |
1604 | template<unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> | |
1605 | class numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> > | |
1606 | { | |
1607 | typedef boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> number_type; | |
1608 | public: | |
1609 | BOOST_STATIC_CONSTEXPR bool is_specialized = true; | |
1610 | static number_type (min)() | |
1611 | { | |
1612 | initializer.do_nothing(); | |
1613 | static std::pair<bool, number_type> value; | |
1614 | if(!value.first) | |
1615 | { | |
1616 | value.first = true; | |
1617 | value.second = 1u; | |
1618 | value.second.backend().exponent() = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent; | |
1619 | } | |
1620 | return value.second; | |
1621 | } | |
1622 | static number_type (max)() | |
1623 | { | |
1624 | initializer.do_nothing(); | |
1625 | static std::pair<bool, number_type> value; | |
1626 | if(!value.first) | |
1627 | { | |
1628 | value.first = true; | |
1629 | eval_complement(value.second.backend().bits(), value.second.backend().bits()); | |
1630 | value.second.backend().exponent() = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent; | |
1631 | } | |
1632 | return value.second; | |
1633 | } | |
1634 | BOOST_STATIC_CONSTEXPR number_type lowest() | |
1635 | { | |
1636 | return -(max)(); | |
1637 | } | |
1638 | BOOST_STATIC_CONSTEXPR int digits = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::bit_count; | |
1639 | BOOST_STATIC_CONSTEXPR int digits10 = (digits - 1) * 301 / 1000; | |
1640 | // Is this really correct??? | |
1641 | BOOST_STATIC_CONSTEXPR int max_digits10 = (digits * 301 / 1000) + 3; | |
1642 | BOOST_STATIC_CONSTEXPR bool is_signed = true; | |
1643 | BOOST_STATIC_CONSTEXPR bool is_integer = false; | |
1644 | BOOST_STATIC_CONSTEXPR bool is_exact = false; | |
1645 | BOOST_STATIC_CONSTEXPR int radix = 2; | |
1646 | static number_type epsilon() | |
1647 | { | |
1648 | initializer.do_nothing(); | |
1649 | static std::pair<bool, number_type> value; | |
1650 | if(!value.first) | |
1651 | { | |
1652 | value.first = true; | |
1653 | value.second = 1; | |
1654 | value.second = ldexp(value.second, 1 - (int)digits); | |
1655 | } | |
1656 | return value.second; | |
1657 | } | |
1658 | // What value should this be???? | |
1659 | static number_type round_error() | |
1660 | { | |
1661 | // returns 0.5 | |
1662 | initializer.do_nothing(); | |
1663 | static std::pair<bool, number_type> value; | |
1664 | if(!value.first) | |
1665 | { | |
1666 | value.first = true; | |
1667 | value.second = 1; | |
1668 | value.second = ldexp(value.second, -1); | |
1669 | } | |
1670 | return value.second; | |
1671 | } | |
1672 | BOOST_STATIC_CONSTEXPR typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type min_exponent = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::min_exponent; | |
1673 | BOOST_STATIC_CONSTEXPR typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type min_exponent10 = (min_exponent / 1000) * 301L; | |
1674 | BOOST_STATIC_CONSTEXPR typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type max_exponent = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::max_exponent; | |
1675 | BOOST_STATIC_CONSTEXPR typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type max_exponent10 = (max_exponent / 1000) * 301L; | |
1676 | BOOST_STATIC_CONSTEXPR bool has_infinity = true; | |
1677 | BOOST_STATIC_CONSTEXPR bool has_quiet_NaN = true; | |
1678 | BOOST_STATIC_CONSTEXPR bool has_signaling_NaN = false; | |
1679 | BOOST_STATIC_CONSTEXPR float_denorm_style has_denorm = denorm_absent; | |
1680 | BOOST_STATIC_CONSTEXPR bool has_denorm_loss = false; | |
1681 | static number_type infinity() | |
1682 | { | |
1683 | initializer.do_nothing(); | |
1684 | static std::pair<bool, number_type> value; | |
1685 | if(!value.first) | |
1686 | { | |
1687 | value.first = true; | |
1688 | value.second.backend().exponent() = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_infinity; | |
1689 | } | |
1690 | return value.second; | |
1691 | } | |
1692 | static number_type quiet_NaN() | |
1693 | { | |
1694 | initializer.do_nothing(); | |
1695 | static std::pair<bool, number_type> value; | |
1696 | if(!value.first) | |
1697 | { | |
1698 | value.first = true; | |
1699 | value.second.backend().exponent() = boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_nan; | |
1700 | } | |
1701 | return value.second; | |
1702 | } | |
1703 | BOOST_STATIC_CONSTEXPR number_type signaling_NaN() | |
1704 | { | |
1705 | return number_type(0); | |
1706 | } | |
1707 | BOOST_STATIC_CONSTEXPR number_type denorm_min() { return number_type(0); } | |
1708 | BOOST_STATIC_CONSTEXPR bool is_iec559 = false; | |
1709 | BOOST_STATIC_CONSTEXPR bool is_bounded = true; | |
1710 | BOOST_STATIC_CONSTEXPR bool is_modulo = false; | |
1711 | BOOST_STATIC_CONSTEXPR bool traps = true; | |
1712 | BOOST_STATIC_CONSTEXPR bool tinyness_before = false; | |
1713 | BOOST_STATIC_CONSTEXPR float_round_style round_style = round_to_nearest; | |
1714 | private: | |
1715 | struct data_initializer | |
1716 | { | |
1717 | data_initializer() | |
1718 | { | |
1719 | std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::epsilon(); | |
1720 | std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::round_error(); | |
1721 | (std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::min)(); | |
1722 | (std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::max)(); | |
1723 | std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::infinity(); | |
1724 | std::numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE> > >::quiet_NaN(); | |
1725 | } | |
1726 | void do_nothing()const{} | |
1727 | }; | |
1728 | static const data_initializer initializer; | |
1729 | }; | |
1730 | ||
1731 | template<unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> | |
1732 | const typename numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::data_initializer numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::initializer; | |
1733 | ||
1734 | #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION | |
1735 | ||
1736 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> | |
1737 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::digits; | |
1738 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> | |
1739 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::digits10; | |
1740 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> | |
1741 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::max_digits10; | |
1742 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> | |
1743 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_signed; | |
1744 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> | |
1745 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_integer; | |
1746 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> | |
1747 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_exact; | |
1748 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> | |
1749 | BOOST_CONSTEXPR_OR_CONST int numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::radix; | |
1750 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> | |
1751 | BOOST_CONSTEXPR_OR_CONST typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::min_exponent; | |
1752 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> | |
1753 | BOOST_CONSTEXPR_OR_CONST typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::min_exponent10; | |
1754 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> | |
1755 | BOOST_CONSTEXPR_OR_CONST typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::max_exponent; | |
1756 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> | |
1757 | BOOST_CONSTEXPR_OR_CONST typename boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>::exponent_type numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::max_exponent10; | |
1758 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> | |
1759 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_infinity; | |
1760 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> | |
1761 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_quiet_NaN; | |
1762 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> | |
1763 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_signaling_NaN; | |
1764 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> | |
1765 | BOOST_CONSTEXPR_OR_CONST float_denorm_style numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_denorm; | |
1766 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> | |
1767 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::has_denorm_loss; | |
1768 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> | |
1769 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_iec559; | |
1770 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> | |
1771 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_bounded; | |
1772 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> | |
1773 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::is_modulo; | |
1774 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> | |
1775 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::traps; | |
1776 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> | |
1777 | BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::tinyness_before; | |
1778 | template <unsigned Digits, boost::multiprecision::backends::digit_base_type DigitBase, class Allocator, class Exponent, Exponent MinE, Exponent MaxE, boost::multiprecision::expression_template_option ExpressionTemplates> | |
1779 | BOOST_CONSTEXPR_OR_CONST float_round_style numeric_limits<boost::multiprecision::number<boost::multiprecision::cpp_bin_float<Digits, DigitBase, Allocator, Exponent, MinE, MaxE>, ExpressionTemplates> >::round_style; | |
1780 | ||
1781 | #endif | |
1782 | ||
1783 | } // namespace std | |
1784 | ||
1785 | #endif |