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