1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright 2011 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_0.txt)
5
6 #ifndef BOOST_MATH_BIG_NUM_BASE_HPP
7 #define BOOST_MATH_BIG_NUM_BASE_HPP
8
9 #include <limits>
10 #include <boost/utility/enable_if.hpp>
11 #include <boost/type_traits/is_convertible.hpp>
12 #include <boost/type_traits/decay.hpp>
13 #ifdef BOOST_MSVC
14 # pragma warning(push)
15 # pragma warning(disable:4307)
16 #endif
17 #include <boost/lexical_cast.hpp>
18 #ifdef BOOST_MSVC
19 # pragma warning(pop)
20 #endif
21
22 #if defined(NDEBUG) && !defined(_DEBUG)
23 # define BOOST_MP_FORCEINLINE BOOST_FORCEINLINE
24 #else
25 # define BOOST_MP_FORCEINLINE inline
26 #endif
27
28 #if defined(BOOST_GCC) && (BOOST_GCC <= 40700)
29 # define BOOST_MP_NOEXCEPT_IF(x)
30 #else
31 # define BOOST_MP_NOEXCEPT_IF(x) BOOST_NOEXCEPT_IF(x)
32 #endif
33
34 #ifdef BOOST_MSVC
35 # pragma warning(push)
36 # pragma warning(disable:6326)
37 #endif
38
39 namespace boost{
40 namespace multiprecision{
41
42 enum expression_template_option
43 {
44 et_off = 0,
45 et_on = 1
46 };
47
48 template <class Backend>
49 struct expression_template_default
50 {
51 static const expression_template_option value = et_on;
52 };
53
54 template <class Backend, expression_template_option ExpressionTemplates = expression_template_default<Backend>::value>
55 class number;
56
57 template <class T>
58 struct is_number : public mpl::false_ {};
59
60 template <class Backend, expression_template_option ExpressionTemplates>
61 struct is_number<number<Backend, ExpressionTemplates> > : public mpl::true_ {};
62
63 namespace detail{
64
65 // Forward-declare an expression wrapper
66 template<class tag, class Arg1 = void, class Arg2 = void, class Arg3 = void, class Arg4 = void>
67 struct expression;
68
69 } // namespace detail
70
71 template <class T>
72 struct is_number_expression : public mpl::false_ {};
73
74 template<class tag, class Arg1, class Arg2, class Arg3, class Arg4>
75 struct is_number_expression<detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > : public mpl::true_ {};
76
77 template <class T, class Num>
78 struct is_compatible_arithmetic_type
79 : public mpl::bool_<
80 is_convertible<T, Num>::value
81 && !is_same<T, Num>::value
82 && !is_number_expression<T>::value>
83 {};
84
85 namespace detail{
86 //
87 // Workaround for missing abs(boost::long_long_type) and abs(__int128) on some compilers:
88 //
89 template <class T>
abs(T t)90 BOOST_CONSTEXPR typename enable_if_c<(is_signed<T>::value || is_floating_point<T>::value), T>::type abs(T t) BOOST_NOEXCEPT
91 {
92 // This strange expression avoids a hardware trap in the corner case
93 // that val is the most negative value permitted in boost::long_long_type.
94 // See https://svn.boost.org/trac/boost/ticket/9740.
95 return t < 0 ? T(1u) + T(-(t + 1)) : t;
96 }
97 template <class T>
abs(T t)98 BOOST_CONSTEXPR typename enable_if_c<(is_unsigned<T>::value), T>::type abs(T t) BOOST_NOEXCEPT
99 {
100 return t;
101 }
102
103 #define BOOST_MP_USING_ABS using boost::multiprecision::detail::abs;
104
105 template <class T>
unsigned_abs(T t)106 BOOST_CONSTEXPR typename enable_if_c<(is_signed<T>::value || is_floating_point<T>::value), typename make_unsigned<T>::type>::type unsigned_abs(T t) BOOST_NOEXCEPT
107 {
108 // This strange expression avoids a hardware trap in the corner case
109 // that val is the most negative value permitted in boost::long_long_type.
110 // See https://svn.boost.org/trac/boost/ticket/9740.
111 return t < 0 ? static_cast<typename make_unsigned<T>::type>(1u) + static_cast<typename make_unsigned<T>::type>(-(t + 1)) : static_cast<typename make_unsigned<T>::type>(t);
112 }
113 template <class T>
unsigned_abs(T t)114 BOOST_CONSTEXPR typename enable_if_c<(is_unsigned<T>::value), T>::type unsigned_abs(T t) BOOST_NOEXCEPT
115 {
116 return t;
117 }
118
119 //
120 // Move support:
121 //
122 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
123 # define BOOST_MP_MOVE(x) std::move(x)
124 #else
125 # define BOOST_MP_MOVE(x) x
126 #endif
127
128 template <class T>
129 struct bits_of
130 {
131 BOOST_STATIC_ASSERT(is_integral<T>::value || is_enum<T>::value || std::numeric_limits<T>::is_specialized);
132 static const unsigned value =
133 std::numeric_limits<T>::is_specialized ?
134 std::numeric_limits<T>::digits
135 : sizeof(T) * CHAR_BIT - (is_signed<T>::value ? 1 : 0);
136 };
137
138 template <int b>
139 struct has_enough_bits
140 {
141 template <class T>
142 struct type : public mpl::bool_<bits_of<T>::value>= b>{};
143 };
144
145 template <class Val, class Backend, class Tag>
146 struct canonical_imp
147 {
148 typedef typename remove_cv<typename decay<const Val>::type>::type type;
149 };
150 template <class B, class Backend, class Tag>
151 struct canonical_imp<number<B, et_on>, Backend, Tag>
152 {
153 typedef B type;
154 };
155 template <class B, class Backend, class Tag>
156 struct canonical_imp<number<B, et_off>, Backend, Tag>
157 {
158 typedef B type;
159 };
160 #ifdef __SUNPRO_CC
161 template <class B, class Backend>
162 struct canonical_imp<number<B, et_on>, Backend, mpl::int_<3> >
163 {
164 typedef B type;
165 };
166 template <class B, class Backend>
167 struct canonical_imp<number<B, et_off>, Backend, mpl::int_<3> >
168 {
169 typedef B type;
170 };
171 #endif
172 template <class Val, class Backend>
173 struct canonical_imp<Val, Backend, mpl::int_<0> >
174 {
175 typedef typename has_enough_bits<bits_of<Val>::value>::template type<mpl::_> pred_type;
176 typedef typename mpl::find_if<
177 typename Backend::signed_types,
178 pred_type
179 >::type iter_type;
180 typedef typename mpl::deref<iter_type>::type type;
181 };
182 template <class Val, class Backend>
183 struct canonical_imp<Val, Backend, mpl::int_<1> >
184 {
185 typedef typename has_enough_bits<bits_of<Val>::value>::template type<mpl::_> pred_type;
186 typedef typename mpl::find_if<
187 typename Backend::unsigned_types,
188 pred_type
189 >::type iter_type;
190 typedef typename mpl::deref<iter_type>::type type;
191 };
192 template <class Val, class Backend>
193 struct canonical_imp<Val, Backend, mpl::int_<2> >
194 {
195 typedef typename has_enough_bits<bits_of<Val>::value>::template type<mpl::_> pred_type;
196 typedef typename mpl::find_if<
197 typename Backend::float_types,
198 pred_type
199 >::type iter_type;
200 typedef typename mpl::deref<iter_type>::type type;
201 };
202 template <class Val, class Backend>
203 struct canonical_imp<Val, Backend, mpl::int_<3> >
204 {
205 typedef const char* type;
206 };
207
208 template <class Val, class Backend>
209 struct canonical
210 {
211 typedef typename mpl::if_<
212 is_signed<Val>,
213 mpl::int_<0>,
214 typename mpl::if_<
215 is_unsigned<Val>,
216 mpl::int_<1>,
217 typename mpl::if_<
218 is_floating_point<Val>,
219 mpl::int_<2>,
220 typename mpl::if_<
221 mpl::or_<
222 is_convertible<Val, const char*>,
223 is_same<Val, std::string>
224 >,
225 mpl::int_<3>,
226 mpl::int_<4>
227 >::type
228 >::type
229 >::type
230 >::type tag_type;
231
232 typedef typename canonical_imp<Val, Backend, tag_type>::type type;
233 };
234
235 struct terminal{};
236 struct negate{};
237 struct plus{};
238 struct minus{};
239 struct multiplies{};
240 struct divides{};
241 struct modulus{};
242 struct shift_left{};
243 struct shift_right{};
244 struct bitwise_and{};
245 struct bitwise_or{};
246 struct bitwise_xor{};
247 struct bitwise_complement{};
248 struct add_immediates{};
249 struct subtract_immediates{};
250 struct multiply_immediates{};
251 struct divide_immediates{};
252 struct modulus_immediates{};
253 struct bitwise_and_immediates{};
254 struct bitwise_or_immediates{};
255 struct bitwise_xor_immediates{};
256 struct complement_immediates{};
257 struct function{};
258 struct multiply_add{};
259 struct multiply_subtract{};
260
261 template <class T>
262 struct backend_type;
263
264 template <class T, expression_template_option ExpressionTemplates>
265 struct backend_type<number<T, ExpressionTemplates> >
266 {
267 typedef T type;
268 };
269
270 template <class tag, class A1, class A2, class A3, class A4>
271 struct backend_type<expression<tag, A1, A2, A3, A4> >
272 {
273 typedef typename backend_type<typename expression<tag, A1, A2, A3, A4>::result_type>::type type;
274 };
275
276
277 template <class T1, class T2>
278 struct combine_expression
279 {
280 #ifdef BOOST_NO_CXX11_DECLTYPE
281 typedef typename mpl::if_c<(sizeof(T1() + T2()) == sizeof(T1)), T1, T2>::type type;
282 #else
283 typedef decltype(T1() + T2()) type;
284 #endif
285 };
286
287 template <class T1, expression_template_option ExpressionTemplates, class T2>
288 struct combine_expression<number<T1, ExpressionTemplates>, T2>
289 {
290 typedef number<T1, ExpressionTemplates> type;
291 };
292
293 template <class T1, class T2, expression_template_option ExpressionTemplates>
294 struct combine_expression<T1, number<T2, ExpressionTemplates> >
295 {
296 typedef number<T2, ExpressionTemplates> type;
297 };
298
299 template <class T, expression_template_option ExpressionTemplates>
300 struct combine_expression<number<T, ExpressionTemplates>, number<T, ExpressionTemplates> >
301 {
302 typedef number<T, ExpressionTemplates> type;
303 };
304
305 template <class T1, expression_template_option ExpressionTemplates1, class T2, expression_template_option ExpressionTemplates2>
306 struct combine_expression<number<T1, ExpressionTemplates1>, number<T2, ExpressionTemplates2> >
307 {
308 typedef typename mpl::if_c<
309 is_convertible<number<T2, ExpressionTemplates2>, number<T1, ExpressionTemplates2> >::value,
310 number<T1, ExpressionTemplates1>,
311 number<T2, ExpressionTemplates2>
312 >::type type;
313 };
314
315 template <class T>
316 struct arg_type
317 {
318 typedef expression<terminal, T> type;
319 };
320
321 template <class Tag, class Arg1, class Arg2, class Arg3, class Arg4>
322 struct arg_type<expression<Tag, Arg1, Arg2, Arg3, Arg4> >
323 {
324 typedef expression<Tag, Arg1, Arg2, Arg3, Arg4> type;
325 };
326
327 struct unmentionable
328 {
procboost::multiprecision::detail::unmentionable329 unmentionable* proc(){ return 0; }
330 };
331
332 typedef unmentionable* (unmentionable::*unmentionable_type)();
333
334 template <class T>
335 struct expression_storage
336 {
337 typedef const T& type;
338 };
339
340 template <class T>
341 struct expression_storage<T*>
342 {
343 typedef T* type;
344 };
345
346 template <class T>
347 struct expression_storage<const T*>
348 {
349 typedef const T* type;
350 };
351
352 template <class tag, class A1, class A2, class A3, class A4>
353 struct expression_storage<expression<tag, A1, A2, A3, A4> >
354 {
355 typedef expression<tag, A1, A2, A3, A4> type;
356 };
357
358 template<class tag, class Arg1>
359 struct expression<tag, Arg1, void, void, void>
360 {
361 typedef mpl::int_<1> arity;
362 typedef typename arg_type<Arg1>::type left_type;
363 typedef typename left_type::result_type left_result_type;
364 typedef typename left_type::result_type result_type;
365 typedef tag tag_type;
366
expressionboost::multiprecision::detail::expression367 explicit expression(const Arg1& a) : arg(a) {}
368
leftboost::multiprecision::detail::expression369 left_type left()const { return left_type(arg); }
370
left_refboost::multiprecision::detail::expression371 const Arg1& left_ref()const BOOST_NOEXCEPT { return arg; }
372
373 static const unsigned depth = left_type::depth + 1;
374 #ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
operator boolboost::multiprecision::detail::expression375 explicit operator bool()const
376 {
377 result_type r(*this);
378 return static_cast<bool>(r);
379 }
380 #else
operator unmentionable_typeboost::multiprecision::detail::expression381 operator unmentionable_type()const
382 {
383 result_type r(*this);
384 return r ? &unmentionable::proc : 0;
385 }
386 #endif
387
388 private:
389 typename expression_storage<Arg1>::type arg;
390 expression& operator=(const expression&);
391 };
392
393 template<class Arg1>
394 struct expression<terminal, Arg1, void, void, void>
395 {
396 typedef mpl::int_<0> arity;
397 typedef Arg1 result_type;
398 typedef terminal tag_type;
399
expressionboost::multiprecision::detail::expression400 explicit expression(const Arg1& a) : arg(a) {}
401
valueboost::multiprecision::detail::expression402 const Arg1& value()const BOOST_NOEXCEPT { return arg; }
403
404 static const unsigned depth = 0;
405
406 #ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
operator boolboost::multiprecision::detail::expression407 explicit operator bool()const
408 {
409 return static_cast<bool>(arg);
410 }
411 #else
operator unmentionable_typeboost::multiprecision::detail::expression412 operator unmentionable_type()const
413 {
414 return arg ? &unmentionable::proc : 0;
415 }
416 #endif
417
418 private:
419 typename expression_storage<Arg1>::type arg;
420 expression& operator=(const expression&);
421 };
422
423 template <class tag, class Arg1, class Arg2>
424 struct expression<tag, Arg1, Arg2, void, void>
425 {
426 typedef mpl::int_<2> arity;
427 typedef typename arg_type<Arg1>::type left_type;
428 typedef typename arg_type<Arg2>::type right_type;
429 typedef typename left_type::result_type left_result_type;
430 typedef typename right_type::result_type right_result_type;
431 typedef typename combine_expression<left_result_type, right_result_type>::type result_type;
432 typedef tag tag_type;
433
expressionboost::multiprecision::detail::expression434 expression(const Arg1& a1, const Arg2& a2) : arg1(a1), arg2(a2) {}
435
leftboost::multiprecision::detail::expression436 left_type left()const { return left_type(arg1); }
rightboost::multiprecision::detail::expression437 right_type right()const { return right_type(arg2); }
left_refboost::multiprecision::detail::expression438 const Arg1& left_ref()const BOOST_NOEXCEPT { return arg1; }
right_refboost::multiprecision::detail::expression439 const Arg2& right_ref()const BOOST_NOEXCEPT { return arg2; }
440
441 #ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
operator boolboost::multiprecision::detail::expression442 explicit operator bool()const
443 {
444 result_type r(*this);
445 return static_cast<bool>(r);
446 }
447 #else
operator unmentionable_typeboost::multiprecision::detail::expression448 operator unmentionable_type()const
449 {
450 result_type r(*this);
451 return r ? &unmentionable::proc : 0;
452 }
453 #endif
454 static const unsigned left_depth = left_type::depth + 1;
455 static const unsigned right_depth = right_type::depth + 1;
456 static const unsigned depth = left_depth > right_depth ? left_depth : right_depth;
457 private:
458 typename expression_storage<Arg1>::type arg1;
459 typename expression_storage<Arg2>::type arg2;
460 expression& operator=(const expression&);
461 };
462
463 template <class tag, class Arg1, class Arg2, class Arg3>
464 struct expression<tag, Arg1, Arg2, Arg3, void>
465 {
466 typedef mpl::int_<3> arity;
467 typedef typename arg_type<Arg1>::type left_type;
468 typedef typename arg_type<Arg2>::type middle_type;
469 typedef typename arg_type<Arg3>::type right_type;
470 typedef typename left_type::result_type left_result_type;
471 typedef typename middle_type::result_type middle_result_type;
472 typedef typename right_type::result_type right_result_type;
473 typedef typename combine_expression<
474 left_result_type,
475 typename combine_expression<right_result_type, middle_result_type>::type
476 >::type result_type;
477 typedef tag tag_type;
478
expressionboost::multiprecision::detail::expression479 expression(const Arg1& a1, const Arg2& a2, const Arg3& a3) : arg1(a1), arg2(a2), arg3(a3) {}
480
leftboost::multiprecision::detail::expression481 left_type left()const { return left_type(arg1); }
middleboost::multiprecision::detail::expression482 middle_type middle()const { return middle_type(arg2); }
rightboost::multiprecision::detail::expression483 right_type right()const { return right_type(arg3); }
left_refboost::multiprecision::detail::expression484 const Arg1& left_ref()const BOOST_NOEXCEPT { return arg1; }
middle_refboost::multiprecision::detail::expression485 const Arg2& middle_ref()const BOOST_NOEXCEPT { return arg2; }
right_refboost::multiprecision::detail::expression486 const Arg3& right_ref()const BOOST_NOEXCEPT { return arg3; }
487
488 #ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
operator boolboost::multiprecision::detail::expression489 explicit operator bool()const
490 {
491 result_type r(*this);
492 return static_cast<bool>(r);
493 }
494 #else
operator unmentionable_typeboost::multiprecision::detail::expression495 operator unmentionable_type()const
496 {
497 result_type r(*this);
498 return r ? &unmentionable::proc : 0;
499 }
500 #endif
501 static const unsigned left_depth = left_type::depth + 1;
502 static const unsigned middle_depth = middle_type::depth + 1;
503 static const unsigned right_depth = right_type::depth + 1;
504 static const unsigned depth = left_depth > right_depth ? (left_depth > middle_depth ? left_depth : middle_depth) : (right_depth > middle_depth ? right_depth : middle_depth);
505 private:
506 typename expression_storage<Arg1>::type arg1;
507 typename expression_storage<Arg2>::type arg2;
508 typename expression_storage<Arg3>::type arg3;
509 expression& operator=(const expression&);
510 };
511
512 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
513 struct expression
514 {
515 typedef mpl::int_<4> arity;
516 typedef typename arg_type<Arg1>::type left_type;
517 typedef typename arg_type<Arg2>::type left_middle_type;
518 typedef typename arg_type<Arg3>::type right_middle_type;
519 typedef typename arg_type<Arg4>::type right_type;
520 typedef typename left_type::result_type left_result_type;
521 typedef typename left_middle_type::result_type left_middle_result_type;
522 typedef typename right_middle_type::result_type right_middle_result_type;
523 typedef typename right_type::result_type right_result_type;
524 typedef typename combine_expression<
525 typename combine_expression<
526 typename combine_expression<left_result_type, left_middle_result_type>::type,
527 right_middle_result_type
528 >::type,
529 right_result_type
530 >::type result_type;
531 typedef tag tag_type;
532
expressionboost::multiprecision::detail::expression533 expression(const Arg1& a1, const Arg2& a2, const Arg3& a3, const Arg4& a4) : arg1(a1), arg2(a2), arg3(a3), arg4(a4) {}
534
leftboost::multiprecision::detail::expression535 left_type left()const { return left_type(arg1); }
left_middleboost::multiprecision::detail::expression536 left_middle_type left_middle()const { return left_middle_type(arg2); }
right_middleboost::multiprecision::detail::expression537 right_middle_type right_middle()const { return right_middle_type(arg3); }
rightboost::multiprecision::detail::expression538 right_type right()const { return right_type(arg4); }
left_refboost::multiprecision::detail::expression539 const Arg1& left_ref()const BOOST_NOEXCEPT { return arg1; }
left_middle_refboost::multiprecision::detail::expression540 const Arg2& left_middle_ref()const BOOST_NOEXCEPT { return arg2; }
right_middle_refboost::multiprecision::detail::expression541 const Arg3& right_middle_ref()const BOOST_NOEXCEPT { return arg3; }
right_refboost::multiprecision::detail::expression542 const Arg4& right_ref()const BOOST_NOEXCEPT { return arg4; }
543
544 #ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
operator boolboost::multiprecision::detail::expression545 explicit operator bool()const
546 {
547 result_type r(*this);
548 return static_cast<bool>(r);
549 }
550 #else
operator unmentionable_typeboost::multiprecision::detail::expression551 operator unmentionable_type()const
552 {
553 result_type r(*this);
554 return r ? &unmentionable::proc : 0;
555 }
556 #endif
557 static const unsigned left_depth = left_type::depth + 1;
558 static const unsigned left_middle_depth = left_middle_type::depth + 1;
559 static const unsigned right_middle_depth = right_middle_type::depth + 1;
560 static const unsigned right_depth = right_type::depth + 1;
561
562 static const unsigned left_max_depth = left_depth > left_middle_depth ? left_depth : left_middle_depth;
563 static const unsigned right_max_depth = right_depth > right_middle_depth ? right_depth : right_middle_depth;
564
565 static const unsigned depth = left_max_depth > right_max_depth ? left_max_depth : right_max_depth;
566 private:
567 typename expression_storage<Arg1>::type arg1;
568 typename expression_storage<Arg2>::type arg2;
569 typename expression_storage<Arg3>::type arg3;
570 typename expression_storage<Arg4>::type arg4;
571 expression& operator=(const expression&);
572 };
573
574 template <class T>
575 struct digits2
576 {
577 BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
578 BOOST_STATIC_ASSERT((std::numeric_limits<T>::radix == 2) || (std::numeric_limits<T>::radix == 10));
579 // If we really have so many digits that this fails, then we're probably going to hit other problems anyway:
580 BOOST_STATIC_ASSERT(LONG_MAX / 1000 > (std::numeric_limits<T>::digits + 1));
581 static const long value = std::numeric_limits<T>::radix == 10 ? (((std::numeric_limits<T>::digits + 1) * 1000L) / 301L) : std::numeric_limits<T>::digits;
582 };
583
584 #ifndef BOOST_MP_MIN_EXPONENT_DIGITS
585 #ifdef _MSC_VER
586 # define BOOST_MP_MIN_EXPONENT_DIGITS 2
587 #else
588 # define BOOST_MP_MIN_EXPONENT_DIGITS 2
589 #endif
590 #endif
591
592 template <class S>
format_float_string(S & str,boost::intmax_t my_exp,boost::intmax_t digits,std::ios_base::fmtflags f,bool iszero)593 void format_float_string(S& str, boost::intmax_t my_exp, boost::intmax_t digits, std::ios_base::fmtflags f, bool iszero)
594 {
595 typedef typename S::size_type size_type;
596 bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific;
597 bool fixed = (f & std::ios_base::fixed) == std::ios_base::fixed;
598 bool showpoint = (f & std::ios_base::showpoint) == std::ios_base::showpoint;
599 bool showpos = (f & std::ios_base::showpos) == std::ios_base::showpos;
600
601 bool neg = str.size() && (str[0] == '-');
602
603 if(neg)
604 str.erase(0, 1);
605
606 if(digits == 0)
607 {
608 digits = (std::max)(str.size(), size_type(16));
609 }
610
611 if(iszero || str.empty() || (str.find_first_not_of('0') == S::npos))
612 {
613 // We will be printing zero, even though the value might not
614 // actually be zero (it just may have been rounded to zero).
615 str = "0";
616 if(scientific || fixed)
617 {
618 str.append(1, '.');
619 str.append(size_type(digits), '0');
620 if(scientific)
621 str.append("e+00");
622 }
623 else
624 {
625 if(showpoint)
626 {
627 str.append(1, '.');
628 if(digits > 1)
629 str.append(size_type(digits - 1), '0');
630 }
631 }
632 if(neg)
633 str.insert(static_cast<std::string::size_type>(0), 1, '-');
634 else if(showpos)
635 str.insert(static_cast<std::string::size_type>(0), 1, '+');
636 return;
637 }
638
639 if(!fixed && !scientific && !showpoint)
640 {
641 //
642 // Suppress trailing zeros:
643 //
644 std::string::iterator pos = str.end();
645 while(pos != str.begin() && *--pos == '0'){}
646 if(pos != str.end())
647 ++pos;
648 str.erase(pos, str.end());
649 if(str.empty())
650 str = '0';
651 }
652 else if(!fixed || (my_exp >= 0))
653 {
654 //
655 // Pad out the end with zero's if we need to:
656 //
657 boost::intmax_t chars = str.size();
658 chars = digits - chars;
659 if(scientific)
660 ++chars;
661 if(chars > 0)
662 {
663 str.append(static_cast<std::string::size_type>(chars), '0');
664 }
665 }
666
667 if(fixed || (!scientific && (my_exp >= -4) && (my_exp < digits)))
668 {
669 if(1 + my_exp > static_cast<boost::intmax_t>(str.size()))
670 {
671 // Just pad out the end with zeros:
672 str.append(static_cast<std::string::size_type>(1 + my_exp - str.size()), '0');
673 if(showpoint || fixed)
674 str.append(".");
675 }
676 else if(my_exp + 1 < static_cast<boost::intmax_t>(str.size()))
677 {
678 if(my_exp < 0)
679 {
680 str.insert(static_cast<std::string::size_type>(0), static_cast<std::string::size_type>(-1 - my_exp), '0');
681 str.insert(static_cast<std::string::size_type>(0), "0.");
682 }
683 else
684 {
685 // Insert the decimal point:
686 str.insert(static_cast<std::string::size_type>(my_exp + 1), 1, '.');
687 }
688 }
689 else if(showpoint || fixed) // we have exactly the digits we require to left of the point
690 str += ".";
691
692 if(fixed)
693 {
694 // We may need to add trailing zeros:
695 boost::intmax_t l = str.find('.') + 1;
696 l = digits - (str.size() - l);
697 if(l > 0)
698 str.append(size_type(l), '0');
699 }
700 }
701 else
702 {
703 BOOST_MP_USING_ABS
704 // Scientific format:
705 if(showpoint || (str.size() > 1))
706 str.insert(static_cast<std::string::size_type>(1u), 1, '.');
707 str.append(static_cast<std::string::size_type>(1u), 'e');
708 S e = boost::lexical_cast<S>(abs(my_exp));
709 if(e.size() < BOOST_MP_MIN_EXPONENT_DIGITS)
710 e.insert(static_cast<std::string::size_type>(0), BOOST_MP_MIN_EXPONENT_DIGITS - e.size(), '0');
711 if(my_exp < 0)
712 e.insert(static_cast<std::string::size_type>(0), 1, '-');
713 else
714 e.insert(static_cast<std::string::size_type>(0), 1, '+');
715 str.append(e);
716 }
717 if(neg)
718 str.insert(static_cast<std::string::size_type>(0), 1, '-');
719 else if(showpos)
720 str.insert(static_cast<std::string::size_type>(0), 1, '+');
721 }
722
723 template <class V>
check_shift_range(V val,const mpl::true_ &,const mpl::true_ &)724 void check_shift_range(V val, const mpl::true_&, const mpl::true_&)
725 {
726 if(val > (std::numeric_limits<std::size_t>::max)())
727 BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a value greater than std::numeric_limits<std::size_t>::max()."));
728 if(val < 0)
729 BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value."));
730 }
731 template <class V>
check_shift_range(V val,const mpl::false_ &,const mpl::true_ &)732 void check_shift_range(V val, const mpl::false_&, const mpl::true_&)
733 {
734 if(val < 0)
735 BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value."));
736 }
737 template <class V>
check_shift_range(V val,const mpl::true_ &,const mpl::false_ &)738 void check_shift_range(V val, const mpl::true_&, const mpl::false_&)
739 {
740 if(val > (std::numeric_limits<std::size_t>::max)())
741 BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a value greater than std::numeric_limits<std::size_t>::max()."));
742 }
743 template <class V>
check_shift_range(V,const mpl::false_ &,const mpl::false_ &)744 void check_shift_range(V, const mpl::false_&, const mpl::false_&) BOOST_NOEXCEPT{}
745
746 } // namespace detail
747
748 //
749 // Traits class, lets us know what kind of number we have, defaults to a floating point type:
750 //
751 enum number_category_type
752 {
753 number_kind_unknown = -1,
754 number_kind_integer = 0,
755 number_kind_floating_point = 1,
756 number_kind_rational = 2,
757 number_kind_fixed_point = 3
758 };
759
760 template <class Num>
761 struct number_category : public mpl::int_<std::numeric_limits<Num>::is_integer ? number_kind_integer : (std::numeric_limits<Num>::max_exponent ? number_kind_floating_point : number_kind_unknown)> {};
762 template <class Backend, expression_template_option ExpressionTemplates>
763 struct number_category<number<Backend, ExpressionTemplates> > : public number_category<Backend>{};
764 template <class tag, class A1, class A2, class A3, class A4>
765 struct number_category<detail::expression<tag, A1, A2, A3, A4> > : public number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>{};
766
767 template <class T>
768 struct component_type;
769 template <class T, expression_template_option ExpressionTemplates>
770 struct component_type<number<T, ExpressionTemplates> > : public component_type<T>{};
771 template <class tag, class A1, class A2, class A3, class A4>
772 struct component_type<detail::expression<tag, A1, A2, A3, A4> > : public component_type<typename detail::expression<tag, A1, A2, A3, A4>::result_type>{};
773
774 template <class T>
775 struct is_unsigned_number : public mpl::false_{};
776 template <class Backend, expression_template_option ExpressionTemplates>
777 struct is_unsigned_number<number<Backend, ExpressionTemplates> > : public is_unsigned_number<Backend> {};
778 template <class T>
779 struct is_signed_number : public mpl::bool_<!is_unsigned_number<T>::value> {};
780 template <class T>
781 struct is_interval_number : public mpl::false_ {};
782 template <class Backend, expression_template_option ExpressionTemplates>
783 struct is_interval_number<number<Backend, ExpressionTemplates> > : public is_interval_number<Backend>{};
784
785 }} // namespaces
786
787 namespace boost{ namespace math{ namespace tools{
788
789 template <class T>
790 struct promote_arg;
791
792 template <class tag, class A1, class A2, class A3, class A4>
793 struct promote_arg<boost::multiprecision::detail::expression<tag, A1, A2, A3, A4> >
794 {
795 typedef typename boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type type;
796 };
797
798 template <class R, class B, boost::multiprecision::expression_template_option ET>
real_cast(const boost::multiprecision::number<B,ET> & val)799 inline R real_cast(const boost::multiprecision::number<B, ET>& val)
800 {
801 return val.template convert_to<R>();
802 }
803
804 template <class R, class tag, class A1, class A2, class A3, class A4>
real_cast(const boost::multiprecision::detail::expression<tag,A1,A2,A3,A4> & val)805 inline R real_cast(const boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>& val)
806 {
807 typedef typename boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type val_type;
808 return val_type(val).template convert_to<R>();
809 }
810
811
812 }
813
814 namespace constants{
815
816 template <class T>
817 struct is_explicitly_convertible_from_string;
818
819 template <class B, boost::multiprecision::expression_template_option ET>
820 struct is_explicitly_convertible_from_string<boost::multiprecision::number<B, ET> >
821 {
822 static const bool value = true;
823 };
824
825 }
826
827 }}
828
829 #ifdef BOOST_MSVC
830 # pragma warning(pop)
831 #endif
832
833 #endif // BOOST_MATH_BIG_NUM_BASE_HPP
834
835
836