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/is_constructible.hpp>
13 #include <boost/type_traits/decay.hpp>
14 #ifdef BOOST_MSVC
15 #  pragma warning(push)
16 #  pragma warning(disable:4307)
17 #endif
18 #include <boost/lexical_cast.hpp>
19 #ifdef BOOST_MSVC
20 #  pragma warning(pop)
21 #endif
22 
23 #if defined(NDEBUG) && !defined(_DEBUG)
24 #  define BOOST_MP_FORCEINLINE BOOST_FORCEINLINE
25 #else
26 #  define BOOST_MP_FORCEINLINE inline
27 #endif
28 
29 #if (defined(BOOST_GCC) && (BOOST_GCC <= 40700)) || BOOST_WORKAROUND(__SUNPRO_CC, < 0x5140)
30 #  define BOOST_MP_NOEXCEPT_IF(x)
31 #else
32 #  define BOOST_MP_NOEXCEPT_IF(x) BOOST_NOEXCEPT_IF(x)
33 #endif
34 
35 #if defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS) || BOOST_WORKAROUND(__SUNPRO_CC, < 0x5140)
36 #define BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
37 #endif
38 
39 //
40 // Thread local storage:
41 // Note fails on Mingw, see https://sourceforge.net/p/mingw-w64/bugs/527/
42 //
43 #if !defined(BOOST_NO_CXX11_THREAD_LOCAL) && !defined(BOOST_INTEL) && !defined(__MINGW32__)
44 #  define BOOST_MP_THREAD_LOCAL thread_local
45 #else
46 #  define BOOST_MP_THREAD_LOCAL
47 #endif
48 
49 #ifdef BOOST_MSVC
50 #  pragma warning(push)
51 #  pragma warning(disable:6326)
52 #endif
53 
54 namespace boost{
55    namespace multiprecision{
56 
57 enum expression_template_option
58 {
59    et_off  = 0,
60    et_on   = 1
61 };
62 
63 template <class Backend>
64 struct expression_template_default
65 {
66    static const expression_template_option value = et_on;
67 };
68 
69 template <class Backend, expression_template_option ExpressionTemplates = expression_template_default<Backend>::value>
70 class number;
71 
72 template <class T>
73 struct is_number : public mpl::false_ {};
74 
75 template <class Backend, expression_template_option ExpressionTemplates>
76 struct is_number<number<Backend, ExpressionTemplates> > : public mpl::true_ {};
77 
78 template <class T>
79 struct is_et_number : public mpl::false_ {};
80 
81 template <class Backend>
82 struct is_et_number<number<Backend, et_on> > : public mpl::true_ {};
83 
84 template <class T>
85 struct is_no_et_number : public mpl::false_ {};
86 
87 template <class Backend>
88 struct is_no_et_number<number<Backend, et_off> > : public mpl::true_ {};
89 
90 namespace detail{
91 
92 // Forward-declare an expression wrapper
93 template<class tag, class Arg1 = void, class Arg2 = void, class Arg3 = void, class Arg4 = void>
94 struct expression;
95 
96 } // namespace detail
97 
98 template <class T>
99 struct is_number_expression : public mpl::false_ {};
100 
101 template<class tag, class Arg1, class Arg2, class Arg3, class Arg4>
102 struct is_number_expression<detail::expression<tag, Arg1, Arg2, Arg3, Arg4> > : public mpl::true_ {};
103 
104 template <class T, class Num>
105 struct is_compatible_arithmetic_type
106    : public mpl::bool_<
107          is_convertible<T, Num>::value
108          && !is_same<T, Num>::value
109          && !is_number_expression<T>::value>
110 {};
111 
112 namespace detail{
113 //
114 // Workaround for missing abs(boost::long_long_type) and abs(__int128) on some compilers:
115 //
116 template <class T>
abs(T t)117 BOOST_CONSTEXPR typename enable_if_c<(is_signed<T>::value || is_floating_point<T>::value), T>::type abs(T t) BOOST_NOEXCEPT
118 {
119    // This strange expression avoids a hardware trap in the corner case
120    // that val is the most negative value permitted in boost::long_long_type.
121    // See https://svn.boost.org/trac/boost/ticket/9740.
122    return t < 0 ? T(1u) + T(-(t + 1)) : t;
123 }
124 template <class T>
abs(T t)125 BOOST_CONSTEXPR typename enable_if_c<(is_unsigned<T>::value), T>::type abs(T t) BOOST_NOEXCEPT
126 {
127    return t;
128 }
129 
130 #define BOOST_MP_USING_ABS using boost::multiprecision::detail::abs;
131 
132 template <class T>
unsigned_abs(T t)133 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
134 {
135    // This strange expression avoids a hardware trap in the corner case
136    // that val is the most negative value permitted in boost::long_long_type.
137    // See https://svn.boost.org/trac/boost/ticket/9740.
138    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);
139 }
140 template <class T>
unsigned_abs(T t)141 BOOST_CONSTEXPR typename enable_if_c<(is_unsigned<T>::value), T>::type unsigned_abs(T t) BOOST_NOEXCEPT
142 {
143    return t;
144 }
145 
146 //
147 // Move support:
148 //
149 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
150 #  define BOOST_MP_MOVE(x) std::move(x)
151 #else
152 #  define BOOST_MP_MOVE(x) x
153 #endif
154 
155 template <class T>
156 struct bits_of
157 {
158    BOOST_STATIC_ASSERT(is_integral<T>::value || is_enum<T>::value || std::numeric_limits<T>::is_specialized);
159    static const unsigned value =
160       std::numeric_limits<T>::is_specialized ?
161          std::numeric_limits<T>::digits
162          : sizeof(T) * CHAR_BIT - (is_signed<T>::value ? 1 : 0);
163 };
164 
165 #if defined(_GLIBCXX_USE_FLOAT128) && defined(BOOST_GCC) && !defined(__STRICT_ANSI__)
166 template<> struct bits_of<__float128> { static const unsigned value = 113; };
167 #endif
168 
169 template <int b>
170 struct has_enough_bits
171 {
172    template <class T>
173    struct type : public mpl::bool_<bits_of<T>::value>= b>{};
174 };
175 
176 template <class Val, class Backend, class Tag>
177 struct canonical_imp
178 {
179    typedef typename remove_cv<typename decay<const Val>::type>::type type;
180 };
181 template <class B, class Backend, class Tag>
182 struct canonical_imp<number<B, et_on>, Backend, Tag>
183 {
184    typedef B type;
185 };
186 template <class B, class Backend, class Tag>
187 struct canonical_imp<number<B, et_off>, Backend, Tag>
188 {
189    typedef B type;
190 };
191 #ifdef __SUNPRO_CC
192 template <class B, class Backend>
193 struct canonical_imp<number<B, et_on>, Backend, mpl::int_<3> >
194 {
195    typedef B type;
196 };
197 template <class B, class Backend>
198 struct canonical_imp<number<B, et_off>, Backend, mpl::int_<3> >
199 {
200    typedef B type;
201 };
202 #endif
203 template <class Val, class Backend>
204 struct canonical_imp<Val, Backend, mpl::int_<0> >
205 {
206    typedef typename has_enough_bits<bits_of<Val>::value>::template type<mpl::_> pred_type;
207    typedef typename mpl::find_if<
208       typename Backend::signed_types,
209       pred_type
210    >::type iter_type;
211    typedef typename mpl::end<typename Backend::signed_types>::type end_type;
212    typedef typename mpl::eval_if<boost::is_same<iter_type, end_type>, mpl::identity<Val>, mpl::deref<iter_type> >::type type;
213 };
214 template <class Val, class Backend>
215 struct canonical_imp<Val, Backend, mpl::int_<1> >
216 {
217    typedef typename has_enough_bits<bits_of<Val>::value>::template type<mpl::_> pred_type;
218    typedef typename mpl::find_if<
219       typename Backend::unsigned_types,
220       pred_type
221    >::type iter_type;
222    typedef typename mpl::end<typename Backend::unsigned_types>::type end_type;
223    typedef typename mpl::eval_if<boost::is_same<iter_type, end_type>, mpl::identity<Val>, mpl::deref<iter_type> >::type type;
224 };
225 template <class Val, class Backend>
226 struct canonical_imp<Val, Backend, mpl::int_<2> >
227 {
228    typedef typename has_enough_bits<bits_of<Val>::value>::template type<mpl::_> pred_type;
229    typedef typename mpl::find_if<
230       typename Backend::float_types,
231       pred_type
232    >::type iter_type;
233    typedef typename mpl::end<typename Backend::float_types>::type end_type;
234    typedef typename mpl::eval_if<boost::is_same<iter_type, end_type>, mpl::identity<Val>, mpl::deref<iter_type> >::type type;
235 };
236 template <class Val, class Backend>
237 struct canonical_imp<Val, Backend, mpl::int_<3> >
238 {
239    typedef const char* type;
240 };
241 
242 template <class Val, class Backend>
243 struct canonical
244 {
245    typedef typename mpl::if_<
246       is_signed<Val>,
247       mpl::int_<0>,
248       typename mpl::if_<
249          is_unsigned<Val>,
250          mpl::int_<1>,
251          typename mpl::if_<
252             is_floating_point<Val>,
253             mpl::int_<2>,
254             typename mpl::if_<
255                mpl::or_<
256                   is_convertible<Val, const char*>,
257                   is_same<Val, std::string>
258                >,
259                mpl::int_<3>,
260                mpl::int_<4>
261             >::type
262          >::type
263       >::type
264    >::type tag_type;
265 
266    typedef typename canonical_imp<Val, Backend, tag_type>::type type;
267 };
268 
269 struct terminal{};
270 struct negate{};
271 struct plus{};
272 struct minus{};
273 struct multiplies{};
274 struct divides{};
275 struct modulus{};
276 struct shift_left{};
277 struct shift_right{};
278 struct bitwise_and{};
279 struct bitwise_or{};
280 struct bitwise_xor{};
281 struct bitwise_complement{};
282 struct add_immediates{};
283 struct subtract_immediates{};
284 struct multiply_immediates{};
285 struct divide_immediates{};
286 struct modulus_immediates{};
287 struct bitwise_and_immediates{};
288 struct bitwise_or_immediates{};
289 struct bitwise_xor_immediates{};
290 struct complement_immediates{};
291 struct function{};
292 struct multiply_add{};
293 struct multiply_subtract{};
294 
295 template <class T>
296 struct backend_type;
297 
298 template <class T, expression_template_option ExpressionTemplates>
299 struct backend_type<number<T, ExpressionTemplates> >
300 {
301    typedef T type;
302 };
303 
304 template <class tag, class A1, class A2, class A3, class A4>
305 struct backend_type<expression<tag, A1, A2, A3, A4> >
306 {
307    typedef typename backend_type<typename expression<tag, A1, A2, A3, A4>::result_type>::type type;
308 };
309 
310 
311 template <class T1, class T2>
312 struct combine_expression
313 {
314 #ifdef BOOST_NO_CXX11_DECLTYPE
315    typedef typename mpl::if_c<(sizeof(T1() + T2()) == sizeof(T1)), T1, T2>::type type;
316 #else
317    typedef decltype(T1() + T2()) type;
318 #endif
319 };
320 
321 template <class T1, expression_template_option ExpressionTemplates, class T2>
322 struct combine_expression<number<T1, ExpressionTemplates>, T2>
323 {
324    typedef number<T1, ExpressionTemplates> type;
325 };
326 
327 template <class T1, class T2, expression_template_option ExpressionTemplates>
328 struct combine_expression<T1, number<T2, ExpressionTemplates> >
329 {
330    typedef number<T2, ExpressionTemplates> type;
331 };
332 
333 template <class T, expression_template_option ExpressionTemplates>
334 struct combine_expression<number<T, ExpressionTemplates>, number<T, ExpressionTemplates> >
335 {
336    typedef number<T, ExpressionTemplates> type;
337 };
338 
339 template <class T1, expression_template_option ExpressionTemplates1, class T2, expression_template_option ExpressionTemplates2>
340 struct combine_expression<number<T1, ExpressionTemplates1>, number<T2, ExpressionTemplates2> >
341 {
342    typedef typename mpl::if_c<
343       is_convertible<number<T2, ExpressionTemplates2>, number<T1, ExpressionTemplates2> >::value,
344       number<T1, ExpressionTemplates1>,
345       number<T2, ExpressionTemplates2>
346       >::type type;
347 };
348 
349 template <class T>
350 struct arg_type
351 {
352    typedef expression<terminal, T> type;
353 };
354 
355 template <class Tag, class Arg1, class Arg2, class Arg3, class Arg4>
356 struct arg_type<expression<Tag, Arg1, Arg2, Arg3, Arg4> >
357 {
358    typedef expression<Tag, Arg1, Arg2, Arg3, Arg4> type;
359 };
360 
361 struct unmentionable
362 {
procboost::multiprecision::detail::unmentionable363    unmentionable* proc(){ return 0; }
364 };
365 
366 typedef unmentionable* (unmentionable::*unmentionable_type)();
367 
368 template <class T, bool b>
369 struct expression_storage_base
370 {
371    typedef const T& type;
372 };
373 
374 template <class T>
375 struct expression_storage_base<T, true>
376 {
377    typedef T type;
378 };
379 
380 template <class T>
381 struct expression_storage : public expression_storage_base<T, boost::is_arithmetic<T>::value> {};
382 
383 template <class T>
384 struct expression_storage<T*>
385 {
386    typedef T* type;
387 };
388 
389 template <class T>
390 struct expression_storage<const T*>
391 {
392    typedef const T* type;
393 };
394 
395 template <class tag, class A1, class A2, class A3, class A4>
396 struct expression_storage<expression<tag, A1, A2, A3, A4> >
397 {
398    typedef expression<tag, A1, A2, A3, A4> type;
399 };
400 
401 template<class tag, class Arg1>
402 struct expression<tag, Arg1, void, void, void>
403 {
404    typedef mpl::int_<1> arity;
405    typedef typename arg_type<Arg1>::type left_type;
406    typedef typename left_type::result_type left_result_type;
407    typedef typename left_type::result_type result_type;
408    typedef tag tag_type;
409 
expressionboost::multiprecision::detail::expression410    explicit expression(const Arg1& a) : arg(a) {}
411 
leftboost::multiprecision::detail::expression412    left_type left()const { return left_type(arg); }
413 
left_refboost::multiprecision::detail::expression414    const Arg1& left_ref()const BOOST_NOEXCEPT { return arg; }
415 
416    static const unsigned depth = left_type::depth + 1;
417 #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
418 #  if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
419    //
420    // Horrible workaround for gcc-4.6.x which always prefers the template
421    // operator bool() rather than the non-template operator when converting to
422    // an arithmetic type:
423    //
424    template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
operator Tboost::multiprecision::detail::expression425    explicit operator T ()const
426    {
427       result_type r(*this);
428       return static_cast<bool>(r);
429    }
430    template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
operator Tboost::multiprecision::detail::expression431    explicit operator T ()const
432    {
433       return static_cast<T>(static_cast<result_type>(*this));
434    }
435 #  else
436    template <class T
437 #ifndef __SUNPRO_CC
438 , typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value, int>::type = 0
439 #endif
440 >
operator Tboost::multiprecision::detail::expression441    explicit operator T()const
442    {
443       return static_cast<T>(static_cast<result_type>(*this));
444    }
operator boolboost::multiprecision::detail::expression445    BOOST_MP_FORCEINLINE explicit operator bool()const
446    {
447       result_type r(*this);
448       return static_cast<bool>(r);
449    }
450 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
operator voidboost::multiprecision::detail::expression451    BOOST_MP_FORCEINLINE explicit operator void()const {}
452 #endif
453 #  endif
454 #else
operator unmentionable_typeboost::multiprecision::detail::expression455    operator unmentionable_type()const
456    {
457       result_type r(*this);
458       return r ? &unmentionable::proc : 0;
459    }
460 #endif
461 
462    template <class T>
convert_toboost::multiprecision::detail::expression463    T convert_to()
464    {
465       result_type r(*this);
466       return r.template convert_to<T>();
467    }
468 
469 private:
470    typename expression_storage<Arg1>::type arg;
471    expression& operator=(const expression&);
472 };
473 
474 template<class Arg1>
475 struct expression<terminal, Arg1, void, void, void>
476 {
477    typedef mpl::int_<0> arity;
478    typedef Arg1 result_type;
479    typedef terminal tag_type;
480 
expressionboost::multiprecision::detail::expression481    explicit expression(const Arg1& a) : arg(a) {}
482 
valueboost::multiprecision::detail::expression483    const Arg1& value()const BOOST_NOEXCEPT { return arg; }
484 
485    static const unsigned depth = 0;
486 
487 #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
488 #  if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
489    //
490    // Horrible workaround for gcc-4.6.x which always prefers the template
491    // operator bool() rather than the non-template operator when converting to
492    // an arithmetic type:
493    //
494    template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
operator Tboost::multiprecision::detail::expression495    explicit operator T ()const
496    {
497       result_type r(*this);
498       return static_cast<bool>(r);
499 }
500    template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
operator Tboost::multiprecision::detail::expression501    explicit operator T ()const
502    {
503       return static_cast<T>(static_cast<result_type>(*this));
504    }
505 #  else
506    template <class T
507 #ifndef __SUNPRO_CC
508 , typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value, int>::type = 0
509 #endif
510 >
operator Tboost::multiprecision::detail::expression511    explicit operator T()const
512    {
513       return static_cast<T>(static_cast<result_type>(*this));
514    }
operator boolboost::multiprecision::detail::expression515    BOOST_MP_FORCEINLINE explicit operator bool()const
516    {
517       result_type r(*this);
518       return static_cast<bool>(r);
519    }
520 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
operator voidboost::multiprecision::detail::expression521    BOOST_MP_FORCEINLINE explicit operator void()const {}
522 #endif
523 #  endif
524 #else
operator unmentionable_typeboost::multiprecision::detail::expression525    operator unmentionable_type()const
526    {
527       return arg ? &unmentionable::proc : 0;
528    }
529 #endif
530 
531    template <class T>
convert_toboost::multiprecision::detail::expression532    T convert_to()
533    {
534       result_type r(*this);
535       return r.template convert_to<T>();
536    }
537 
538 private:
539    typename expression_storage<Arg1>::type arg;
540    expression& operator=(const expression&);
541 };
542 
543 template <class tag, class Arg1, class Arg2>
544 struct expression<tag, Arg1, Arg2, void, void>
545 {
546    typedef mpl::int_<2> arity;
547    typedef typename arg_type<Arg1>::type left_type;
548    typedef typename arg_type<Arg2>::type right_type;
549    typedef typename left_type::result_type left_result_type;
550    typedef typename right_type::result_type right_result_type;
551    typedef typename combine_expression<left_result_type, right_result_type>::type result_type;
552    typedef tag tag_type;
553 
expressionboost::multiprecision::detail::expression554    expression(const Arg1& a1, const Arg2& a2) : arg1(a1), arg2(a2) {}
555 
leftboost::multiprecision::detail::expression556    left_type left()const { return left_type(arg1); }
rightboost::multiprecision::detail::expression557    right_type right()const { return right_type(arg2); }
left_refboost::multiprecision::detail::expression558    const Arg1& left_ref()const BOOST_NOEXCEPT { return arg1; }
right_refboost::multiprecision::detail::expression559    const Arg2& right_ref()const BOOST_NOEXCEPT { return arg2; }
560 
561 #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
562 #  if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
563       //
564       // Horrible workaround for gcc-4.6.x which always prefers the template
565       // operator bool() rather than the non-template operator when converting to
566       // an arithmetic type:
567       //
568       template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
operator Tboost::multiprecision::detail::expression569    explicit operator T ()const
570    {
571       result_type r(*this);
572       return static_cast<bool>(r);
573 }
574    template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
operator Tboost::multiprecision::detail::expression575    explicit operator T ()const
576    {
577       return static_cast<T>(static_cast<result_type>(*this));
578    }
579 #  else
580    template <class T
581 #ifndef __SUNPRO_CC
582 , typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value, int>::type = 0
583 #endif
584 >
operator Tboost::multiprecision::detail::expression585    explicit operator T()const
586    {
587       return static_cast<T>(static_cast<result_type>(*this));
588    }
operator boolboost::multiprecision::detail::expression589    BOOST_MP_FORCEINLINE explicit operator bool()const
590    {
591       result_type r(*this);
592       return static_cast<bool>(r);
593    }
594 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
operator voidboost::multiprecision::detail::expression595    BOOST_MP_FORCEINLINE explicit operator void()const {}
596 #endif
597 #  endif
598 #else
operator unmentionable_typeboost::multiprecision::detail::expression599    operator unmentionable_type()const
600    {
601       result_type r(*this);
602       return r ? &unmentionable::proc : 0;
603    }
604 #endif
605    template <class T>
convert_toboost::multiprecision::detail::expression606    T convert_to()
607    {
608       result_type r(*this);
609       return r.template convert_to<T>();
610    }
611 
612    static const unsigned left_depth = left_type::depth + 1;
613    static const unsigned right_depth = right_type::depth + 1;
614    static const unsigned depth = left_depth > right_depth ? left_depth : right_depth;
615 private:
616    typename expression_storage<Arg1>::type arg1;
617    typename expression_storage<Arg2>::type arg2;
618    expression& operator=(const expression&);
619 };
620 
621 template <class tag, class Arg1, class Arg2, class Arg3>
622 struct expression<tag, Arg1, Arg2, Arg3, void>
623 {
624    typedef mpl::int_<3> arity;
625    typedef typename arg_type<Arg1>::type left_type;
626    typedef typename arg_type<Arg2>::type middle_type;
627    typedef typename arg_type<Arg3>::type right_type;
628    typedef typename left_type::result_type left_result_type;
629    typedef typename middle_type::result_type middle_result_type;
630    typedef typename right_type::result_type right_result_type;
631    typedef typename combine_expression<
632       left_result_type,
633       typename combine_expression<right_result_type, middle_result_type>::type
634    >::type result_type;
635    typedef tag tag_type;
636 
expressionboost::multiprecision::detail::expression637    expression(const Arg1& a1, const Arg2& a2, const Arg3& a3) : arg1(a1), arg2(a2), arg3(a3) {}
638 
leftboost::multiprecision::detail::expression639    left_type left()const { return left_type(arg1); }
middleboost::multiprecision::detail::expression640    middle_type middle()const { return middle_type(arg2); }
rightboost::multiprecision::detail::expression641    right_type right()const { return right_type(arg3); }
left_refboost::multiprecision::detail::expression642    const Arg1& left_ref()const BOOST_NOEXCEPT { return arg1; }
middle_refboost::multiprecision::detail::expression643    const Arg2& middle_ref()const BOOST_NOEXCEPT { return arg2; }
right_refboost::multiprecision::detail::expression644    const Arg3& right_ref()const BOOST_NOEXCEPT { return arg3; }
645 
646 #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
647 #  if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
648       //
649       // Horrible workaround for gcc-4.6.x which always prefers the template
650       // operator bool() rather than the non-template operator when converting to
651       // an arithmetic type:
652       //
653       template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
operator Tboost::multiprecision::detail::expression654    explicit operator T ()const
655    {
656       result_type r(*this);
657       return static_cast<bool>(r);
658 }
659    template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
operator Tboost::multiprecision::detail::expression660    explicit operator T ()const
661    {
662       return static_cast<T>(static_cast<result_type>(*this));
663    }
664 #  else
665    template <class T
666 #ifndef __SUNPRO_CC
667 , typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value, int>::type = 0
668 #endif
669 >
operator Tboost::multiprecision::detail::expression670    explicit operator T()const
671    {
672       return static_cast<T>(static_cast<result_type>(*this));
673    }
operator boolboost::multiprecision::detail::expression674    BOOST_MP_FORCEINLINE explicit operator bool()const
675    {
676       result_type r(*this);
677       return static_cast<bool>(r);
678    }
679 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
operator voidboost::multiprecision::detail::expression680    BOOST_MP_FORCEINLINE explicit operator void()const {}
681 #endif
682 #  endif
683 #else
operator unmentionable_typeboost::multiprecision::detail::expression684    operator unmentionable_type()const
685    {
686       result_type r(*this);
687       return r ? &unmentionable::proc : 0;
688    }
689 #endif
690    template <class T>
convert_toboost::multiprecision::detail::expression691    T convert_to()
692    {
693       result_type r(*this);
694       return r.template convert_to<T>();
695    }
696 
697    static const unsigned left_depth = left_type::depth + 1;
698    static const unsigned middle_depth = middle_type::depth + 1;
699    static const unsigned right_depth = right_type::depth + 1;
700    static const unsigned depth = left_depth > right_depth ? (left_depth > middle_depth ? left_depth : middle_depth) : (right_depth > middle_depth ? right_depth : middle_depth);
701 private:
702    typename expression_storage<Arg1>::type arg1;
703    typename expression_storage<Arg2>::type arg2;
704    typename expression_storage<Arg3>::type arg3;
705    expression& operator=(const expression&);
706 };
707 
708 template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
709 struct expression
710 {
711    typedef mpl::int_<4> arity;
712    typedef typename arg_type<Arg1>::type left_type;
713    typedef typename arg_type<Arg2>::type left_middle_type;
714    typedef typename arg_type<Arg3>::type right_middle_type;
715    typedef typename arg_type<Arg4>::type right_type;
716    typedef typename left_type::result_type left_result_type;
717    typedef typename left_middle_type::result_type left_middle_result_type;
718    typedef typename right_middle_type::result_type right_middle_result_type;
719    typedef typename right_type::result_type right_result_type;
720    typedef typename combine_expression<
721       left_result_type,
722       typename combine_expression<
723          left_middle_result_type,
724          typename combine_expression<right_middle_result_type, right_result_type>::type
725       >::type
726    >::type result_type;
727    typedef tag tag_type;
728 
expressionboost::multiprecision::detail::expression729    expression(const Arg1& a1, const Arg2& a2, const Arg3& a3, const Arg4& a4) : arg1(a1), arg2(a2), arg3(a3), arg4(a4) {}
730 
leftboost::multiprecision::detail::expression731    left_type left()const { return left_type(arg1); }
left_middleboost::multiprecision::detail::expression732    left_middle_type left_middle()const { return left_middle_type(arg2); }
right_middleboost::multiprecision::detail::expression733    right_middle_type right_middle()const { return right_middle_type(arg3); }
rightboost::multiprecision::detail::expression734    right_type right()const { return right_type(arg4); }
left_refboost::multiprecision::detail::expression735    const Arg1& left_ref()const BOOST_NOEXCEPT { return arg1; }
left_middle_refboost::multiprecision::detail::expression736    const Arg2& left_middle_ref()const BOOST_NOEXCEPT { return arg2; }
right_middle_refboost::multiprecision::detail::expression737    const Arg3& right_middle_ref()const BOOST_NOEXCEPT { return arg3; }
right_refboost::multiprecision::detail::expression738    const Arg4& right_ref()const BOOST_NOEXCEPT { return arg4; }
739 
740 #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
741 #  if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7) && !defined(__clang__)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
742       //
743       // Horrible workaround for gcc-4.6.x which always prefers the template
744       // operator bool() rather than the non-template operator when converting to
745       // an arithmetic type:
746       //
747       template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
operator Tboost::multiprecision::detail::expression748    explicit operator T ()const
749    {
750       result_type r(*this);
751       return static_cast<bool>(r);
752 }
753    template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value || is_number<T>::value, int>::type = 0>
operator Tboost::multiprecision::detail::expression754    explicit operator T ()const
755    {
756       return static_cast<T>(static_cast<result_type>(*this));
757    }
758 #  else
759    template <class T
760 #ifndef __SUNPRO_CC
761 , typename boost::disable_if_c<is_number<T>::value || is_constructible<T const&, result_type>::value, int>::type = 0
762 #endif
763 >
operator Tboost::multiprecision::detail::expression764    explicit operator T()const
765    {
766       return static_cast<T>(static_cast<result_type>(*this));
767    }
operator boolboost::multiprecision::detail::expression768    BOOST_MP_FORCEINLINE explicit operator bool()const
769    {
770       result_type r(*this);
771       return static_cast<bool>(r);
772    }
773 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
operator voidboost::multiprecision::detail::expression774    BOOST_MP_FORCEINLINE explicit operator void()const {}
775 #endif
776 #  endif
777 #else
operator unmentionable_typeboost::multiprecision::detail::expression778    operator unmentionable_type()const
779    {
780       result_type r(*this);
781       return r ? &unmentionable::proc : 0;
782    }
783 #endif
784    template <class T>
convert_toboost::multiprecision::detail::expression785    T convert_to()
786    {
787       result_type r(*this);
788       return r.template convert_to<T>();
789    }
790 
791    static const unsigned left_depth = left_type::depth + 1;
792    static const unsigned left_middle_depth = left_middle_type::depth + 1;
793    static const unsigned right_middle_depth = right_middle_type::depth + 1;
794    static const unsigned right_depth = right_type::depth + 1;
795 
796    static const unsigned left_max_depth = left_depth > left_middle_depth ? left_depth : left_middle_depth;
797    static const unsigned right_max_depth = right_depth > right_middle_depth ? right_depth : right_middle_depth;
798 
799    static const unsigned depth = left_max_depth > right_max_depth ? left_max_depth : right_max_depth;
800 private:
801    typename expression_storage<Arg1>::type arg1;
802    typename expression_storage<Arg2>::type arg2;
803    typename expression_storage<Arg3>::type arg3;
804    typename expression_storage<Arg4>::type arg4;
805    expression& operator=(const expression&);
806 };
807 
808 template <class T>
809 struct digits2
810 {
811    BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
812    BOOST_STATIC_ASSERT((std::numeric_limits<T>::radix == 2) || (std::numeric_limits<T>::radix == 10));
813    // If we really have so many digits that this fails, then we're probably going to hit other problems anyway:
814    BOOST_STATIC_ASSERT(LONG_MAX / 1000 > (std::numeric_limits<T>::digits + 1));
815    static const long m_value = std::numeric_limits<T>::radix == 10 ?  (((std::numeric_limits<T>::digits + 1) * 1000L) / 301L) : std::numeric_limits<T>::digits;
valueboost::multiprecision::detail::digits2816    static inline BOOST_CONSTEXPR long value()BOOST_NOEXCEPT { return m_value; }
817 };
818 
819 #ifndef BOOST_MP_MIN_EXPONENT_DIGITS
820 #ifdef _MSC_VER
821 #  define BOOST_MP_MIN_EXPONENT_DIGITS 2
822 #else
823 #  define BOOST_MP_MIN_EXPONENT_DIGITS 2
824 #endif
825 #endif
826 
827 template <class S>
format_float_string(S & str,boost::intmax_t my_exp,boost::intmax_t digits,std::ios_base::fmtflags f,bool iszero)828 void format_float_string(S& str, boost::intmax_t my_exp, boost::intmax_t digits, std::ios_base::fmtflags f, bool iszero)
829 {
830    typedef typename S::size_type size_type;
831    bool scientific = (f & std::ios_base::scientific) == std::ios_base::scientific;
832    bool fixed      = (f & std::ios_base::fixed) == std::ios_base::fixed;
833    bool showpoint  = (f & std::ios_base::showpoint) == std::ios_base::showpoint;
834    bool showpos     = (f & std::ios_base::showpos) == std::ios_base::showpos;
835 
836    bool neg = str.size() && (str[0] == '-');
837 
838    if(neg)
839       str.erase(0, 1);
840 
841    if(digits == 0)
842    {
843       digits = (std::max)(str.size(), size_type(16));
844    }
845 
846    if(iszero || str.empty() || (str.find_first_not_of('0') == S::npos))
847    {
848       // We will be printing zero, even though the value might not
849       // actually be zero (it just may have been rounded to zero).
850       str = "0";
851       if(scientific || fixed)
852       {
853          str.append(1, '.');
854          str.append(size_type(digits), '0');
855          if(scientific)
856             str.append("e+00");
857       }
858       else
859       {
860          if(showpoint)
861          {
862             str.append(1, '.');
863             if(digits > 1)
864                str.append(size_type(digits - 1), '0');
865          }
866       }
867       if(neg)
868          str.insert(static_cast<std::string::size_type>(0), 1, '-');
869       else if(showpos)
870          str.insert(static_cast<std::string::size_type>(0), 1, '+');
871       return;
872    }
873 
874    if(!fixed && !scientific && !showpoint)
875    {
876       //
877       // Suppress trailing zeros:
878       //
879       std::string::iterator pos = str.end();
880       while(pos != str.begin() && *--pos == '0'){}
881       if(pos != str.end())
882          ++pos;
883       str.erase(pos, str.end());
884       if(str.empty())
885          str = '0';
886    }
887    else if(!fixed || (my_exp >= 0))
888    {
889       //
890       // Pad out the end with zero's if we need to:
891       //
892       boost::intmax_t chars = str.size();
893       chars = digits - chars;
894       if(scientific)
895          ++chars;
896       if(chars > 0)
897       {
898          str.append(static_cast<std::string::size_type>(chars), '0');
899       }
900    }
901 
902    if(fixed || (!scientific && (my_exp >= -4) && (my_exp < digits)))
903    {
904       if(1 + my_exp > static_cast<boost::intmax_t>(str.size()))
905       {
906          // Just pad out the end with zeros:
907          str.append(static_cast<std::string::size_type>(1 + my_exp - str.size()), '0');
908          if(showpoint || fixed)
909             str.append(".");
910       }
911       else if(my_exp + 1 < static_cast<boost::intmax_t>(str.size()))
912       {
913          if(my_exp < 0)
914          {
915             str.insert(static_cast<std::string::size_type>(0), static_cast<std::string::size_type>(-1 - my_exp), '0');
916             str.insert(static_cast<std::string::size_type>(0), "0.");
917          }
918          else
919          {
920             // Insert the decimal point:
921             str.insert(static_cast<std::string::size_type>(my_exp + 1), 1, '.');
922          }
923       }
924       else if(showpoint || fixed) // we have exactly the digits we require to left of the point
925          str += ".";
926 
927       if(fixed)
928       {
929          // We may need to add trailing zeros:
930          boost::intmax_t l = str.find('.') + 1;
931          l = digits - (str.size() - l);
932          if(l > 0)
933             str.append(size_type(l), '0');
934       }
935    }
936    else
937    {
938       BOOST_MP_USING_ABS
939       // Scientific format:
940       if(showpoint || (str.size() > 1))
941          str.insert(static_cast<std::string::size_type>(1u), 1, '.');
942       str.append(static_cast<std::string::size_type>(1u), 'e');
943       S e = boost::lexical_cast<S>(abs(my_exp));
944       if(e.size() < BOOST_MP_MIN_EXPONENT_DIGITS)
945          e.insert(static_cast<std::string::size_type>(0), BOOST_MP_MIN_EXPONENT_DIGITS - e.size(), '0');
946       if(my_exp < 0)
947          e.insert(static_cast<std::string::size_type>(0), 1, '-');
948       else
949          e.insert(static_cast<std::string::size_type>(0), 1, '+');
950       str.append(e);
951    }
952    if(neg)
953       str.insert(static_cast<std::string::size_type>(0), 1, '-');
954    else if(showpos)
955       str.insert(static_cast<std::string::size_type>(0), 1, '+');
956 }
957 
958 template <class V>
check_shift_range(V val,const mpl::true_ &,const mpl::true_ &)959 void check_shift_range(V val, const mpl::true_&, const mpl::true_&)
960 {
961    if(val > (std::numeric_limits<std::size_t>::max)())
962       BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a value greater than std::numeric_limits<std::size_t>::max()."));
963    if(val < 0)
964       BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value."));
965 }
966 template <class V>
check_shift_range(V val,const mpl::false_ &,const mpl::true_ &)967 void check_shift_range(V val, const mpl::false_&, const mpl::true_&)
968 {
969    if(val < 0)
970       BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a negative value."));
971 }
972 template <class V>
check_shift_range(V val,const mpl::true_ &,const mpl::false_ &)973 void check_shift_range(V val, const mpl::true_&, const mpl::false_&)
974 {
975    if(val > (std::numeric_limits<std::size_t>::max)())
976       BOOST_THROW_EXCEPTION(std::out_of_range("Can not shift by a value greater than std::numeric_limits<std::size_t>::max()."));
977 }
978 template <class V>
check_shift_range(V,const mpl::false_ &,const mpl::false_ &)979 void check_shift_range(V, const mpl::false_&, const mpl::false_&) BOOST_NOEXCEPT{}
980 
981 } // namespace detail
982 
983 //
984 // Traits class, lets us know what kind of number we have, defaults to a floating point type:
985 //
986 enum number_category_type
987 {
988    number_kind_unknown = -1,
989    number_kind_integer = 0,
990    number_kind_floating_point = 1,
991    number_kind_rational = 2,
992    number_kind_fixed_point = 3
993 };
994 
995 template <class Num>
996 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)> {};
997 template <class Backend, expression_template_option ExpressionTemplates>
998 struct number_category<number<Backend, ExpressionTemplates> > : public number_category<Backend>{};
999 template <class tag, class A1, class A2, class A3, class A4>
1000 struct number_category<detail::expression<tag, A1, A2, A3, A4> > : public number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>{};
1001 //
1002 // Specializations for types which do not always have numberic_limits specializations:
1003 //
1004 #ifdef BOOST_HAS_INT128
1005 template <>
1006 struct number_category<__int128> : public mpl::int_<number_kind_integer> {};
1007 template <>
1008 struct number_category<unsigned __int128> : public mpl::int_<number_kind_integer> {};
1009 #endif
1010 #ifdef BOOST_HAS_FLOAT128
1011 template <>
1012 struct number_category<__float128> : public mpl::int_<number_kind_floating_point> {};
1013 #endif
1014 
1015 template <class T>
1016 struct component_type;
1017 template <class T, expression_template_option ExpressionTemplates>
1018 struct component_type<number<T, ExpressionTemplates> > : public component_type<T>{};
1019 template <class tag, class A1, class A2, class A3, class A4>
1020 struct component_type<detail::expression<tag, A1, A2, A3, A4> > : public component_type<typename detail::expression<tag, A1, A2, A3, A4>::result_type>{};
1021 
1022 template <class T>
1023 struct is_unsigned_number : public mpl::false_{};
1024 template <class Backend, expression_template_option ExpressionTemplates>
1025 struct is_unsigned_number<number<Backend, ExpressionTemplates> > : public is_unsigned_number<Backend> {};
1026 template <class T>
1027 struct is_signed_number : public mpl::bool_<!is_unsigned_number<T>::value> {};
1028 template <class T>
1029 struct is_interval_number : public mpl::false_ {};
1030 template <class Backend, expression_template_option ExpressionTemplates>
1031 struct is_interval_number<number<Backend, ExpressionTemplates> > : public is_interval_number<Backend>{};
1032 
1033 }} // namespaces
1034 
1035 namespace boost{ namespace math{ namespace tools{
1036 
1037 template <class T>
1038 struct promote_arg;
1039 
1040 template <class tag, class A1, class A2, class A3, class A4>
1041 struct promote_arg<boost::multiprecision::detail::expression<tag, A1, A2, A3, A4> >
1042 {
1043    typedef typename boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type type;
1044 };
1045 
1046 template <class R, class B, boost::multiprecision::expression_template_option ET>
real_cast(const boost::multiprecision::number<B,ET> & val)1047 inline R real_cast(const boost::multiprecision::number<B, ET>& val)
1048 {
1049    return val.template convert_to<R>();
1050 }
1051 
1052 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)1053 inline R real_cast(const boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>& val)
1054 {
1055    typedef typename boost::multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type val_type;
1056    return val_type(val).template convert_to<R>();
1057 }
1058 
1059 
1060 }
1061 
1062 namespace constants{
1063 
1064    template <class T>
1065    struct is_explicitly_convertible_from_string;
1066 
1067    template <class B, boost::multiprecision::expression_template_option ET>
1068    struct is_explicitly_convertible_from_string<boost::multiprecision::number<B, ET> >
1069    {
1070       static const bool value = true;
1071    };
1072 
1073 }
1074 
1075 }}
1076 
1077 #ifdef BOOST_MSVC
1078 #  pragma warning(pop)
1079 #endif
1080 
1081 #endif // BOOST_MATH_BIG_NUM_BASE_HPP
1082 
1083 
1084