Imported Upstream version 1.64.0
[platform/upstream/boost.git] / boost / multiprecision / number.hpp
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_EXTENDED_REAL_HPP
7 #define BOOST_MATH_EXTENDED_REAL_HPP
8
9 #include <boost/cstdint.hpp>
10 #include <boost/mpl/max.hpp>
11 #include <boost/mpl/plus.hpp>
12 #include <boost/mpl/or.hpp>
13 #include <boost/mpl/find_if.hpp>
14 #include <boost/assert.hpp>
15 #include <boost/type_traits/remove_pointer.hpp>
16 #include <boost/type_traits/is_signed.hpp>
17 #include <boost/type_traits/is_unsigned.hpp>
18 #include <boost/type_traits/is_floating_point.hpp>
19 #include <boost/type_traits/is_integral.hpp>
20 #include <boost/type_traits/make_unsigned.hpp>
21 #include <boost/throw_exception.hpp>
22 #include <boost/multiprecision/detail/generic_interconvert.hpp>
23 #include <boost/multiprecision/detail/number_compare.hpp>
24 #include <boost/multiprecision/traits/is_restricted_conversion.hpp>
25 #include <istream>  // stream operators
26 #include <cstdio>   // EOF
27 #include <cctype>   // isspace
28
29 namespace boost{ namespace multiprecision{
30
31 #ifdef BOOST_MSVC
32 // warning C4127: conditional expression is constant
33 // warning C4714: function marked as __forceinline not inlined
34 #pragma warning(push)
35 #pragma warning(disable:4127 4714 6326)
36 #endif
37
38 template <class Backend, expression_template_option ExpressionTemplates>
39 class number
40 {
41    typedef number<Backend, ExpressionTemplates> self_type;
42 public:
43    typedef Backend backend_type;
44    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number() BOOST_MP_NOEXCEPT_IF(noexcept(Backend())) {}
45    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const number& e) BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval<Backend const&>()))) : m_backend(e.m_backend){}
46    template <class V>
47    BOOST_MP_FORCEINLINE number(const V& v, typename boost::enable_if_c<
48             (boost::is_arithmetic<V>::value || is_same<std::string, V>::value || is_convertible<V, const char*>::value)
49             && !is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value
50             && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value
51          >::type* = 0)
52    {
53       m_backend = canonical_value(v);
54    }
55    template <class V>
56    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const V& v, typename boost::enable_if_c<
57             is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value
58             && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value
59    >::type* = 0) 
60 #ifndef BOOST_INTEL
61           BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval<typename detail::canonical<V, Backend>::type const&>())))
62 #endif
63       : m_backend(canonical_value(v)) {}
64    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const number& e, unsigned digits10) 
65       BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval<Backend const&>(), std::declval<unsigned>())))
66       : m_backend(e.m_backend, digits10){}
67    template <class V>
68    explicit BOOST_MP_FORCEINLINE number(const V& v, typename boost::enable_if_c<
69             (boost::is_arithmetic<V>::value || is_same<std::string, V>::value || is_convertible<V, const char*>::value)
70             && !detail::is_explicitly_convertible<typename detail::canonical<V, Backend>::type, Backend>::value
71             && detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value
72          >::type* = 0) 
73          BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<Backend&>() = std::declval<typename detail::canonical<V, Backend>::type const&>()))
74    {
75       m_backend = canonical_value(v);
76    }
77    template <class V>
78    explicit BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const V& v, typename boost::enable_if_c<
79             detail::is_explicitly_convertible<typename detail::canonical<V, Backend>::type, Backend>::value
80             && (detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value
81                 || !is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value)
82          >::type* = 0)
83          BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval<typename detail::canonical<V, Backend>::type const&>())))
84       : m_backend(canonical_value(v)) {}
85    /*
86    //
87    // This conflicts with component based initialization (for rational and complex types)
88    // which is arguably more useful.  Disabled for now.
89    //
90    template <class V>
91    number(V v, unsigned digits10, typename boost::enable_if<mpl::or_<boost::is_arithmetic<V>, is_same<std::string, V>, is_convertible<V, const char*> > >::type* dummy1 = 0)
92    {
93       m_backend.precision(digits10);
94       m_backend = canonical_value(v);
95    }
96    */
97    template<expression_template_option ET>
98    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(const number<Backend, ET>& val)
99       BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval<Backend const&>()))) : m_backend(val.backend()) {}
100
101    template <class Other, expression_template_option ET>
102    BOOST_MP_FORCEINLINE number(const number<Other, ET>& val,
103          typename boost::enable_if_c<(boost::is_convertible<Other, Backend>::value && !detail::is_restricted_conversion<Other, Backend>::value)>::type* = 0)
104       BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval<Other const&>())))
105       : m_backend(val.backend()) {}
106
107    template <class Other, expression_template_option ET>
108    explicit number(const number<Other, ET>& val, typename boost::enable_if_c<
109          (!detail::is_explicitly_convertible<Other, Backend>::value)
110          >::type* = 0)
111    {
112       //
113       // Attempt a generic interconvertion:
114       //
115       using detail::generic_interconvert;
116       generic_interconvert(backend(), val.backend(), number_category<Backend>(), number_category<Other>());
117    }
118    template <class Other, expression_template_option ET>
119    explicit BOOST_MP_FORCEINLINE number(const number<Other, ET>& val, typename boost::enable_if_c<
120          (detail::is_explicitly_convertible<Other, Backend>::value
121             && (detail::is_restricted_conversion<Other, Backend>::value || !boost::is_convertible<Other, Backend>::value))
122          >::type* = 0) BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval<Other const&>())))
123       : m_backend(val.backend()) {}
124
125    template <class V>
126    BOOST_MP_FORCEINLINE number(V v1, V v2, typename boost::enable_if<mpl::or_<boost::is_arithmetic<V>, is_same<std::string, V>, is_convertible<V, const char*> > >::type* = 0)
127    {
128       using default_ops::assign_components;
129       assign_components(m_backend, canonical_value(v1), canonical_value(v2));
130    }
131    template <class Other, expression_template_option ET>
132    BOOST_MP_FORCEINLINE number(const number<Other, ET>& v1, const number<Other, ET>& v2, typename boost::enable_if<boost::is_convertible<Other, Backend> >::type* = 0)
133    {
134       using default_ops::assign_components;
135       assign_components(m_backend, v1.backend(), v2.backend());
136    }
137
138    template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
139    typename boost::enable_if<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>, number&>::type operator=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
140    {
141       typedef typename is_same<number, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::type tag_type;
142       do_assign(e, tag_type());
143       return *this;
144    }
145    template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
146    number& assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
147    {
148       typedef typename is_same<number, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::type tag_type;
149       do_assign(e, tag_type());
150       return *this;
151    }
152
153    BOOST_MP_FORCEINLINE number& operator=(const number& e)
154       BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<Backend&>() = std::declval<Backend const&>()))
155    {
156       m_backend = e.m_backend;
157       return *this;
158    }
159
160    template <class V>
161    BOOST_MP_FORCEINLINE typename boost::enable_if<is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
162       operator=(const V& v)
163       BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<Backend&>() = std::declval<const typename detail::canonical<V, Backend>::type&>()))
164    {
165       m_backend = canonical_value(v);
166       return *this;
167    }
168    template <class V>
169    BOOST_MP_FORCEINLINE number<Backend, ExpressionTemplates>& assign(const V& v)
170       BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<Backend&>() = std::declval<const typename detail::canonical<V, Backend>::type&>()))
171    {
172       m_backend = canonical_value(v);
173       return *this;
174    }
175    template <class Other, expression_template_option ET>
176    typename boost::disable_if<boost::multiprecision::detail::is_explicitly_convertible<Other, Backend>, number<Backend, ExpressionTemplates>& >::type
177       assign(const number<Other, ET>& v)
178    {
179       //
180       // Attempt a generic interconvertion:
181       //
182       using detail::generic_interconvert;
183       generic_interconvert(backend(), v.backend(), number_category<Backend>(), number_category<Other>());
184       return *this;
185    }
186
187    template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
188    number(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, typename boost::enable_if_c<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value>::type* = 0)
189    {
190       *this = e;
191    }
192    template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
193    explicit number(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e,
194       typename boost::enable_if_c<!is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value
195       && boost::multiprecision::detail::is_explicitly_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value>::type* = 0)
196    {
197       assign(e);
198    }
199
200 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
201    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR number(number&& r)
202       BOOST_MP_NOEXCEPT_IF(noexcept(Backend(std::declval<Backend>())))
203       : m_backend(static_cast<Backend&&>(r.m_backend)){}
204    BOOST_MP_FORCEINLINE number& operator=(number&& r) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<Backend&>() = std::declval<Backend>()))
205    {
206       m_backend = static_cast<Backend&&>(r.m_backend);
207       return *this;
208    }
209 #endif
210
211    number& operator+=(const self_type& val)
212    {
213       do_add(detail::expression<detail::terminal, self_type>(val), detail::terminal());
214       return *this;
215    }
216
217    template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
218    typename boost::enable_if<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>, number&>::type operator+=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
219    {
220       // Create a copy if e contains this, but not if we're just doing a
221       //    x += x
222       if(contains_self(e) && !is_self(e))
223       {
224          self_type temp(e);
225          do_add(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
226       }
227       else
228       {
229          do_add(e, tag());
230       }
231       return *this;
232    }
233
234    template <class Arg1, class Arg2, class Arg3, class Arg4>
235    number& operator+=(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& e)
236    {
237       //
238       // Fused multiply-add:
239       //
240       using default_ops::eval_multiply_add;
241       eval_multiply_add(m_backend, canonical_value(e.left_ref()), canonical_value(e.right_ref()));
242       return *this;
243    }
244
245    template <class V>
246    typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
247       operator+=(const V& v)
248    {
249       using default_ops::eval_add;
250       eval_add(m_backend, canonical_value(v));
251       return *this;
252    }
253
254    number& operator-=(const self_type& val)
255    {
256       do_subtract(detail::expression<detail::terminal, self_type>(val), detail::terminal());
257       return *this;
258    }
259
260    template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
261    typename boost::enable_if<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>, number&>::type operator-=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
262    {
263       // Create a copy if e contains this:
264       if(contains_self(e))
265       {
266          self_type temp(e);
267          do_subtract(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
268       }
269       else
270       {
271          do_subtract(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
272       }
273       return *this;
274    }
275
276    template <class V>
277    typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
278       operator-=(const V& v)
279    {
280       using default_ops::eval_subtract;
281       eval_subtract(m_backend, canonical_value(v));
282       return *this;
283    }
284
285    template <class Arg1, class Arg2, class Arg3, class Arg4>
286    number& operator-=(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& e)
287    {
288       //
289       // Fused multiply-subtract:
290       //
291       using default_ops::eval_multiply_subtract;
292       eval_multiply_subtract(m_backend, canonical_value(e.left_ref()), canonical_value(e.right_ref()));
293       return *this;
294    }
295
296
297    number& operator *= (const self_type& e)
298    {
299       do_multiplies(detail::expression<detail::terminal, self_type>(e), detail::terminal());
300       return *this;
301    }
302
303    template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
304    typename boost::enable_if<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>, number&>::type operator*=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
305    {
306       // Create a temporary if the RHS references *this, but not
307       // if we're just doing an   x *= x;
308       if(contains_self(e) && !is_self(e))
309       {
310          self_type temp(e);
311          do_multiplies(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
312       }
313       else
314       {
315          do_multiplies(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
316       }
317       return *this;
318    }
319
320    template <class V>
321    typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
322       operator*=(const V& v)
323    {
324       using default_ops::eval_multiply;
325       eval_multiply(m_backend, canonical_value(v));
326       return *this;
327    }
328
329    number& operator%=(const self_type& e)
330    {
331       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
332       do_modulus(detail::expression<detail::terminal, self_type>(e), detail::terminal());
333       return *this;
334    }
335    template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
336    typename boost::enable_if<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>, number&>::type operator%=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
337    {
338       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
339       // Create a temporary if the RHS references *this:
340       if(contains_self(e))
341       {
342          self_type temp(e);
343          do_modulus(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
344       }
345       else
346       {
347          do_modulus(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
348       }
349       return *this;
350    }
351    template <class V>
352    typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
353       operator%=(const V& v)
354    {
355       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
356       using default_ops::eval_modulus;
357       eval_modulus(m_backend, canonical_value(v));
358       return *this;
359    }
360
361    //
362    // These operators are *not* proto-ized.
363    // The issue is that the increment/decrement must happen
364    // even if the result of the operator *is never used*.
365    // Possibly we could modify our expression wrapper to
366    // execute the increment/decrement on destruction, but
367    // correct implementation will be tricky, so defered for now...
368    //
369    BOOST_MP_FORCEINLINE number& operator++()
370    {
371       using default_ops::eval_increment;
372       eval_increment(m_backend);
373       return *this;
374    }
375
376    BOOST_MP_FORCEINLINE number& operator--()
377    {
378       using default_ops::eval_decrement;
379       eval_decrement(m_backend);
380       return *this;
381    }
382
383    inline number operator++(int)
384    {
385       using default_ops::eval_increment;
386       self_type temp(*this);
387       eval_increment(m_backend);
388       return BOOST_MP_MOVE(temp);
389    }
390
391    inline number operator--(int)
392    {
393       using default_ops::eval_decrement;
394       self_type temp(*this);
395       eval_decrement(m_backend);
396       return BOOST_MP_MOVE(temp);
397    }
398
399    template <class V>
400    BOOST_MP_FORCEINLINE typename boost::enable_if<is_integral<V>, number&>::type operator <<= (V val)
401    {
402       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The left-shift operation is only valid for integer types");
403       detail::check_shift_range(val, mpl::bool_<(sizeof(V) > sizeof(std::size_t))>(), is_signed<V>());
404       eval_left_shift(m_backend, static_cast<std::size_t>(canonical_value(val)));
405       return *this;
406    }
407
408    template <class V>
409    BOOST_MP_FORCEINLINE typename boost::enable_if<is_integral<V>, number&>::type operator >>= (V val)
410    {
411       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The right-shift operation is only valid for integer types");
412       detail::check_shift_range(val, mpl::bool_<(sizeof(V) > sizeof(std::size_t))>(), is_signed<V>());
413       eval_right_shift(m_backend, static_cast<std::size_t>(canonical_value(val)));
414       return *this;
415    }
416
417    BOOST_MP_FORCEINLINE number& operator /= (const self_type& e)
418    {
419       do_divide(detail::expression<detail::terminal, self_type>(e), detail::terminal());
420       return *this;
421    }
422
423    template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
424    typename boost::enable_if<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>, number&>::type operator/=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
425    {
426       // Create a temporary if the RHS references *this:
427       if(contains_self(e))
428       {
429          self_type temp(e);
430          do_divide(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
431       }
432       else
433       {
434          do_divide(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
435       }
436       return *this;
437    }
438
439    template <class V>
440    BOOST_MP_FORCEINLINE typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
441       operator/=(const V& v)
442    {
443       using default_ops::eval_divide;
444       eval_divide(m_backend, canonical_value(v));
445       return *this;
446    }
447
448    BOOST_MP_FORCEINLINE number& operator&=(const self_type& e)
449    {
450       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
451       do_bitwise_and(detail::expression<detail::terminal, self_type>(e), detail::terminal());
452       return *this;
453    }
454
455    template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
456    typename boost::enable_if<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>, number&>::type operator&=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
457    {
458       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
459       // Create a temporary if the RHS references *this, but not
460       // if we're just doing an   x &= x;
461       if(contains_self(e) && !is_self(e))
462       {
463          self_type temp(e);
464          do_bitwise_and(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
465       }
466       else
467       {
468          do_bitwise_and(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
469       }
470       return *this;
471    }
472
473    template <class V>
474    BOOST_MP_FORCEINLINE typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
475       operator&=(const V& v)
476    {
477       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
478       using default_ops::eval_bitwise_and;
479       eval_bitwise_and(m_backend, canonical_value(v));
480       return *this;
481    }
482
483    BOOST_MP_FORCEINLINE number& operator|=(const self_type& e)
484    {
485       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
486       do_bitwise_or(detail::expression<detail::terminal, self_type>(e), detail::terminal());
487       return *this;
488    }
489
490    template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
491    typename boost::enable_if<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>, number&>::type operator|=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
492    {
493       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
494       // Create a temporary if the RHS references *this, but not
495       // if we're just doing an   x |= x;
496       if(contains_self(e) && !is_self(e))
497       {
498          self_type temp(e);
499          do_bitwise_or(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
500       }
501       else
502       {
503          do_bitwise_or(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
504       }
505       return *this;
506    }
507
508    template <class V>
509    BOOST_MP_FORCEINLINE typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
510       operator|=(const V& v)
511    {
512       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
513       using default_ops::eval_bitwise_or;
514       eval_bitwise_or(m_backend, canonical_value(v));
515       return *this;
516    }
517
518    BOOST_MP_FORCEINLINE number& operator^=(const self_type& e)
519    {
520       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
521       do_bitwise_xor(detail::expression<detail::terminal, self_type>(e), detail::terminal());
522       return *this;
523    }
524
525    template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
526    typename boost::enable_if<is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>, number&>::type operator^=(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
527    {
528       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
529       if(contains_self(e))
530       {
531          self_type temp(e);
532          do_bitwise_xor(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
533       }
534       else
535       {
536          do_bitwise_xor(e, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::tag_type());
537       }
538       return *this;
539    }
540
541    template <class V>
542    BOOST_MP_FORCEINLINE typename boost::enable_if<boost::is_convertible<V, self_type>, number<Backend, ExpressionTemplates>& >::type
543       operator^=(const V& v)
544    {
545       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
546       using default_ops::eval_bitwise_xor;
547       eval_bitwise_xor(m_backend, canonical_value(v));
548       return *this;
549    }
550    //
551    // swap:
552    //
553    BOOST_MP_FORCEINLINE void swap(self_type& other) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<Backend>().swap(std::declval<Backend&>())))
554    {
555       m_backend.swap(other.backend());
556    }
557    //
558    // Zero and sign:
559    //
560    BOOST_MP_FORCEINLINE bool is_zero()const
561    {
562       using default_ops::eval_is_zero;
563       return eval_is_zero(m_backend);
564    }
565    BOOST_MP_FORCEINLINE int sign()const
566    {
567       using default_ops::eval_get_sign;
568       return eval_get_sign(m_backend);
569    }
570    //
571    // String conversion functions:
572    //
573    std::string str(std::streamsize digits = 0, std::ios_base::fmtflags f = std::ios_base::fmtflags(0))const
574    {
575       return m_backend.str(digits, f);
576    }
577    template<class Archive>
578    void serialize(Archive & ar, const unsigned int /*version*/)
579    {
580       ar & m_backend;
581    }
582 private:
583    template <class T>
584    void convert_to_imp(T* result)const
585    {
586       using default_ops::eval_convert_to;
587       eval_convert_to(result, m_backend);
588    }
589    template <class B2, expression_template_option ET>
590    void convert_to_imp(number<B2, ET>* result)const
591    {
592       result->assign(*this);
593    }
594    void convert_to_imp(std::string* result)const
595    {
596       *result = this->str();
597    }
598 public:
599    template <class T>
600    T convert_to()const
601    {
602       T result;
603       convert_to_imp(&result);
604       return result;
605    }
606    //
607    // Use in boolean context, and explicit conversion operators:
608    //
609 #ifndef BOOST_MP_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
610 #  if (defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 7)) || (defined(BOOST_INTEL) && (BOOST_INTEL <= 1500))
611    //
612    // Horrible workaround for gcc-4.6.x which always prefers the template
613    // operator bool() rather than the non-template operator when converting to
614    // an arithmetic type:
615    //
616    template <class T, typename boost::enable_if<is_same<T, bool>, int>::type = 0>
617    explicit operator T ()const
618    {
619       using default_ops::eval_is_zero;
620       return !eval_is_zero(backend());
621    }
622    template <class T, typename boost::disable_if_c<is_same<T, bool>::value || is_void<T>::value, int>::type = 0>
623    explicit operator T ()const
624    {
625       return this->template convert_to<T>();
626    }
627 #  else
628    template <class T>
629    explicit operator T()const
630    {
631       return this->template convert_to<T>();
632    }
633    BOOST_MP_FORCEINLINE explicit operator bool()const
634    {
635       return !is_zero();
636    }
637 #if BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40800)
638    BOOST_MP_FORCEINLINE explicit operator void()const {}
639 #endif
640 #  endif
641 #else
642    typedef bool (self_type::*unmentionable_type)()const;
643
644    BOOST_MP_FORCEINLINE operator unmentionable_type()const
645    {
646       return is_zero() ? 0 : &self_type::is_zero;
647    }
648 #endif
649    //
650    // Default precision:
651    //
652    static unsigned default_precision() BOOST_NOEXCEPT
653    {
654       return Backend::default_precision();
655    }
656    static void default_precision(unsigned digits10)
657    {
658       Backend::default_precision(digits10);
659    }
660    unsigned precision()const BOOST_NOEXCEPT
661    {
662       return m_backend.precision();
663    }
664    void precision(unsigned digits10)
665    {
666       m_backend.precision(digits10);
667    }
668    //
669    // Comparison:
670    //
671    BOOST_MP_FORCEINLINE int compare(const number<Backend, ExpressionTemplates>& o)const
672       BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<Backend>().compare(std::declval<Backend>())))
673    {
674       return m_backend.compare(o.m_backend);
675    }
676    template <class V>
677    BOOST_MP_FORCEINLINE typename boost::enable_if<is_arithmetic<V>, int>::type compare(const V& o)const
678    {
679       using default_ops::eval_get_sign;
680       if(o == 0)
681          return eval_get_sign(m_backend);
682       return m_backend.compare(canonical_value(o));
683    }
684    BOOST_MP_FORCEINLINE Backend& backend() BOOST_NOEXCEPT
685    {
686       return m_backend;
687    }
688    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const Backend& backend()const BOOST_NOEXCEPT
689    {
690       return m_backend;
691    }
692 private:
693    template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
694    void do_assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, const mpl::true_&)
695    {
696       do_assign(e, tag());
697    }
698    template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
699    void do_assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, const mpl::false_&)
700    {
701       // The result of the expression isn't the same type as this -
702       // create a temporary result and assign it to *this:
703       typedef typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type temp_type;
704       temp_type t(e);
705       this->assign(t);
706    }
707
708
709    template <class Exp>
710    void do_assign(const Exp& e, const detail::add_immediates&)
711    {
712       using default_ops::eval_add;
713       eval_add(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
714    }
715    template <class Exp>
716    void do_assign(const Exp& e, const detail::subtract_immediates&)
717    {
718       using default_ops::eval_subtract;
719       eval_subtract(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
720    }
721    template <class Exp>
722    void do_assign(const Exp& e, const detail::multiply_immediates&)
723    {
724       using default_ops::eval_multiply;
725       eval_multiply(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
726    }
727    template <class Exp>
728    void do_assign(const Exp& e, const detail::multiply_add&)
729    {
730       using default_ops::eval_multiply_add;
731       eval_multiply_add(m_backend, canonical_value(e.left().value()), canonical_value(e.middle().value()), canonical_value(e.right().value()));
732    }
733    template <class Exp>
734    void do_assign(const Exp& e, const detail::multiply_subtract&)
735    {
736       using default_ops::eval_multiply_subtract;
737       eval_multiply_subtract(m_backend, canonical_value(e.left().value()), canonical_value(e.middle().value()), canonical_value(e.right().value()));
738    }
739
740    template <class Exp>
741    void do_assign(const Exp& e, const detail::divide_immediates&)
742    {
743       using default_ops::eval_divide;
744       eval_divide(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
745    }
746
747    template <class Exp>
748    void do_assign(const Exp& e, const detail::negate&)
749    {
750       typedef typename Exp::left_type left_type;
751       do_assign(e.left(), typename left_type::tag_type());
752       m_backend.negate();
753    }
754    template <class Exp>
755    void do_assign(const Exp& e, const detail::plus&)
756    {
757       typedef typename Exp::left_type left_type;
758       typedef typename Exp::right_type right_type;
759
760       static int const left_depth = left_type::depth;
761       static int const right_depth = right_type::depth;
762
763       bool bl = contains_self(e.left());
764       bool br = contains_self(e.right());
765
766       if(bl && br)
767       {
768          self_type temp(e);
769          temp.m_backend.swap(this->m_backend);
770       }
771       else if(bl && is_self(e.left()))
772       {
773          // Ignore the left node, it's *this, just add the right:
774          do_add(e.right(), typename right_type::tag_type());
775       }
776       else if(br && is_self(e.right()))
777       {
778          // Ignore the right node, it's *this, just add the left:
779          do_add(e.left(), typename left_type::tag_type());
780       }
781       else if(!br && (bl || (left_depth >= right_depth)))
782       { // br is always false, but if bl is true we must take the this branch:
783          do_assign(e.left(), typename left_type::tag_type());
784          do_add(e.right(), typename right_type::tag_type());
785       }
786       else
787       {
788          do_assign(e.right(), typename right_type::tag_type());
789          do_add(e.left(), typename left_type::tag_type());
790       }
791    }
792    template <class Exp>
793    void do_assign(const Exp& e, const detail::minus&)
794    {
795       typedef typename Exp::left_type left_type;
796       typedef typename Exp::right_type right_type;
797
798       static int const left_depth = left_type::depth;
799       static int const right_depth = right_type::depth;
800
801       bool bl = contains_self(e.left());
802       bool br = contains_self(e.right());
803
804       if(bl && br)
805       {
806          self_type temp(e);
807          temp.m_backend.swap(this->m_backend);
808       }
809       else if(bl && is_self(e.left()))
810       {
811          // Ignore the left node, it's *this, just subtract the right:
812          do_subtract(e.right(), typename right_type::tag_type());
813       }
814       else if(br && is_self(e.right()))
815       {
816          // Ignore the right node, it's *this, just subtract the left and negate the result:
817          do_subtract(e.left(), typename left_type::tag_type());
818          m_backend.negate();
819       }
820       else if(!br && (bl || (left_depth >= right_depth)))
821       { // br is always false, but if bl is true we must take the this branch:
822          do_assign(e.left(), typename left_type::tag_type());
823          do_subtract(e.right(), typename right_type::tag_type());
824       }
825       else
826       {
827          do_assign(e.right(), typename right_type::tag_type());
828          do_subtract(e.left(), typename left_type::tag_type());
829          m_backend.negate();
830       }
831    }
832    template <class Exp>
833    void do_assign(const Exp& e, const detail::multiplies&)
834    {
835       typedef typename Exp::left_type left_type;
836       typedef typename Exp::right_type right_type;
837
838       static int const left_depth = left_type::depth;
839       static int const right_depth = right_type::depth;
840
841       bool bl = contains_self(e.left());
842       bool br = contains_self(e.right());
843
844       if(bl && br)
845       {
846          self_type temp(e);
847          temp.m_backend.swap(this->m_backend);
848       }
849       else if(bl && is_self(e.left()))
850       {
851          // Ignore the left node, it's *this, just add the right:
852          do_multiplies(e.right(), typename right_type::tag_type());
853       }
854       else if(br && is_self(e.right()))
855       {
856          // Ignore the right node, it's *this, just add the left:
857          do_multiplies(e.left(), typename left_type::tag_type());
858       }
859       else if(!br && (bl || (left_depth >= right_depth)))
860       { // br is always false, but if bl is true we must take the this branch:
861          do_assign(e.left(), typename left_type::tag_type());
862          do_multiplies(e.right(), typename right_type::tag_type());
863       }
864       else
865       {
866          do_assign(e.right(), typename right_type::tag_type());
867          do_multiplies(e.left(), typename left_type::tag_type());
868       }
869    }
870    template <class Exp>
871    void do_assign(const Exp& e, const detail::divides&)
872    {
873       typedef typename Exp::left_type left_type;
874       typedef typename Exp::right_type right_type;
875
876       bool bl = contains_self(e.left());
877       bool br = contains_self(e.right());
878
879       if(bl && is_self(e.left()))
880       {
881          // Ignore the left node, it's *this, just add the right:
882          do_divide(e.right(), typename right_type::tag_type());
883       }
884       else if(br)
885       {
886          self_type temp(e);
887          temp.m_backend.swap(this->m_backend);
888       }
889       else
890       {
891          do_assign(e.left(), typename left_type::tag_type());
892          do_divide(e.right(), typename right_type::tag_type());
893       }
894    }
895    template <class Exp>
896    void do_assign(const Exp& e, const detail::modulus&)
897    {
898       //
899       // This operation is only valid for integer backends:
900       //
901       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
902
903       typedef typename Exp::left_type left_type;
904       typedef typename Exp::right_type right_type;
905
906       bool bl = contains_self(e.left());
907       bool br = contains_self(e.right());
908
909       if(bl && is_self(e.left()))
910       {
911          // Ignore the left node, it's *this, just add the right:
912          do_modulus(e.right(), typename right_type::tag_type());
913       }
914       else if(br)
915       {
916          self_type temp(e);
917          temp.m_backend.swap(this->m_backend);
918       }
919       else
920       {
921          do_assign(e.left(), typename left_type::tag_type());
922          do_modulus(e.right(), typename right_type::tag_type());
923       }
924    }
925    template <class Exp>
926    void do_assign(const Exp& e, const detail::modulus_immediates&)
927    {
928       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
929       using default_ops::eval_modulus;
930       eval_modulus(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
931    }
932
933    template <class Exp>
934    void do_assign(const Exp& e, const detail::bitwise_and&)
935    {
936       //
937       // This operation is only valid for integer backends:
938       //
939       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
940
941       typedef typename Exp::left_type left_type;
942       typedef typename Exp::right_type right_type;
943
944       static int const left_depth = left_type::depth;
945       static int const right_depth = right_type::depth;
946
947       bool bl = contains_self(e.left());
948       bool br = contains_self(e.right());
949
950       if(bl && is_self(e.left()))
951       {
952          // Ignore the left node, it's *this, just add the right:
953          do_bitwise_and(e.right(), typename right_type::tag_type());
954       }
955       else if(br && is_self(e.right()))
956       {
957          do_bitwise_and(e.left(), typename left_type::tag_type());
958       }
959       else if(!br && (bl || (left_depth >= right_depth)))
960       {
961          do_assign(e.left(), typename left_type::tag_type());
962          do_bitwise_and(e.right(), typename right_type::tag_type());
963       }
964       else
965       {
966          do_assign(e.right(), typename right_type::tag_type());
967          do_bitwise_and(e.left(), typename left_type::tag_type());
968       }
969    }
970    template <class Exp>
971    void do_assign(const Exp& e, const detail::bitwise_and_immediates&)
972    {
973       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
974       using default_ops::eval_bitwise_and;
975       eval_bitwise_and(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
976    }
977
978    template <class Exp>
979    void do_assign(const Exp& e, const detail::bitwise_or&)
980    {
981       //
982       // This operation is only valid for integer backends:
983       //
984       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
985
986       typedef typename Exp::left_type left_type;
987       typedef typename Exp::right_type right_type;
988
989       static int const left_depth = left_type::depth;
990       static int const right_depth = right_type::depth;
991
992       bool bl = contains_self(e.left());
993       bool br = contains_self(e.right());
994
995       if(bl && is_self(e.left()))
996       {
997          // Ignore the left node, it's *this, just add the right:
998          do_bitwise_or(e.right(), typename right_type::tag_type());
999       }
1000       else if(br && is_self(e.right()))
1001       {
1002          do_bitwise_or(e.left(), typename left_type::tag_type());
1003       }
1004       else if(!br && (bl || (left_depth >= right_depth)))
1005       {
1006          do_assign(e.left(), typename left_type::tag_type());
1007          do_bitwise_or(e.right(), typename right_type::tag_type());
1008       }
1009       else
1010       {
1011          do_assign(e.right(), typename right_type::tag_type());
1012          do_bitwise_or(e.left(), typename left_type::tag_type());
1013       }
1014    }
1015    template <class Exp>
1016    void do_assign(const Exp& e, const detail::bitwise_or_immediates&)
1017    {
1018       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
1019       using default_ops::eval_bitwise_or;
1020       eval_bitwise_or(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
1021    }
1022
1023    template <class Exp>
1024    void do_assign(const Exp& e, const detail::bitwise_xor&)
1025    {
1026       //
1027       // This operation is only valid for integer backends:
1028       //
1029       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
1030
1031       typedef typename Exp::left_type left_type;
1032       typedef typename Exp::right_type right_type;
1033
1034       static int const left_depth = left_type::depth;
1035       static int const right_depth = right_type::depth;
1036
1037       bool bl = contains_self(e.left());
1038       bool br = contains_self(e.right());
1039
1040       if(bl && is_self(e.left()))
1041       {
1042          // Ignore the left node, it's *this, just add the right:
1043          do_bitwise_xor(e.right(), typename right_type::tag_type());
1044       }
1045       else if(br && is_self(e.right()))
1046       {
1047          do_bitwise_xor(e.left(), typename left_type::tag_type());
1048       }
1049       else if(!br && (bl || (left_depth >= right_depth)))
1050       {
1051          do_assign(e.left(), typename left_type::tag_type());
1052          do_bitwise_xor(e.right(), typename right_type::tag_type());
1053       }
1054       else
1055       {
1056          do_assign(e.right(), typename right_type::tag_type());
1057          do_bitwise_xor(e.left(), typename left_type::tag_type());
1058       }
1059    }
1060    template <class Exp>
1061    void do_assign(const Exp& e, const detail::bitwise_xor_immediates&)
1062    {
1063       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "Bitwise operations are only valid for integer types");
1064       using default_ops::eval_bitwise_xor;
1065       eval_bitwise_xor(m_backend, canonical_value(e.left().value()), canonical_value(e.right().value()));
1066    }
1067    template <class Exp>
1068    void do_assign(const Exp& e, const detail::terminal&)
1069    {
1070       if(!is_self(e))
1071       {
1072          m_backend = canonical_value(e.value());
1073       }
1074    }
1075    template <class Exp>
1076    void do_assign(const Exp& e, const detail::function&)
1077    {
1078       typedef typename Exp::arity tag_type;
1079       do_assign_function(e, tag_type());
1080    }
1081    template <class Exp>
1082    void do_assign(const Exp& e, const detail::shift_left&)
1083    {
1084       // We can only shift by an integer value, not an arbitrary expression:
1085       typedef typename Exp::left_type left_type;
1086       typedef typename Exp::right_type right_type;
1087       typedef typename right_type::arity right_arity;
1088       BOOST_STATIC_ASSERT_MSG(right_arity::value == 0, "The left shift operator requires an integer value for the shift operand.");
1089       typedef typename right_type::result_type right_value_type;
1090       BOOST_STATIC_ASSERT_MSG(is_integral<right_value_type>::value, "The left shift operator requires an integer value for the shift operand.");
1091       typedef typename left_type::tag_type tag_type;
1092       do_assign_left_shift(e.left(), canonical_value(e.right().value()), tag_type());
1093    }
1094
1095    template <class Exp>
1096    void do_assign(const Exp& e, const detail::shift_right&)
1097    {
1098       // We can only shift by an integer value, not an arbitrary expression:
1099       typedef typename Exp::left_type left_type;
1100       typedef typename Exp::right_type right_type;
1101       typedef typename right_type::arity right_arity;
1102       BOOST_STATIC_ASSERT_MSG(right_arity::value == 0, "The left shift operator requires an integer value for the shift operand.");
1103       typedef typename right_type::result_type right_value_type;
1104       BOOST_STATIC_ASSERT_MSG(is_integral<right_value_type>::value, "The left shift operator requires an integer value for the shift operand.");
1105       typedef typename left_type::tag_type tag_type;
1106       do_assign_right_shift(e.left(), canonical_value(e.right().value()), tag_type());
1107    }
1108
1109    template <class Exp>
1110    void do_assign(const Exp& e, const detail::bitwise_complement&)
1111    {
1112       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ~ operation is only valid for integer types");
1113       using default_ops::eval_complement;
1114       self_type temp(e.left());
1115       eval_complement(m_backend, temp.backend());
1116    }
1117
1118    template <class Exp>
1119    void do_assign(const Exp& e, const detail::complement_immediates&)
1120    {
1121       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ~ operation is only valid for integer types");
1122       using default_ops::eval_complement;
1123       eval_complement(m_backend, canonical_value(e.left().value()));
1124    }
1125
1126    template <class Exp, class Val>
1127    void do_assign_right_shift(const Exp& e, const Val& val, const detail::terminal&)
1128    {
1129       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The right shift operation is only valid for integer types");
1130       using default_ops::eval_right_shift;
1131       detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), is_signed<Val>());
1132       eval_right_shift(m_backend, canonical_value(e.value()), static_cast<std::size_t>(val));
1133    }
1134
1135    template <class Exp, class Val>
1136    void do_assign_left_shift(const Exp& e, const Val& val, const detail::terminal&)
1137    {
1138       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The left shift operation is only valid for integer types");
1139       using default_ops::eval_left_shift;
1140       detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), is_signed<Val>());
1141       eval_left_shift(m_backend, canonical_value(e.value()), static_cast<std::size_t>(val));
1142    }
1143
1144    template <class Exp, class Val, class Tag>
1145    void do_assign_right_shift(const Exp& e, const Val& val, const Tag&)
1146    {
1147       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The right shift operation is only valid for integer types");
1148       using default_ops::eval_right_shift;
1149       self_type temp(e);
1150       detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), is_signed<Val>());
1151       eval_right_shift(m_backend, temp.backend(), static_cast<std::size_t>(val));
1152    }
1153
1154    template <class Exp, class Val, class Tag>
1155    void do_assign_left_shift(const Exp& e, const Val& val, const Tag&)
1156    {
1157       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The left shift operation is only valid for integer types");
1158       using default_ops::eval_left_shift;
1159       self_type temp(e);
1160       detail::check_shift_range(val, mpl::bool_<(sizeof(Val) > sizeof(std::size_t))>(), is_signed<Val>());
1161       eval_left_shift(m_backend, temp.backend(), static_cast<std::size_t>(val));
1162    }
1163
1164    template <class Exp>
1165    void do_assign_function(const Exp& e, const mpl::int_<1>&)
1166    {
1167       e.left().value()(&m_backend);
1168    }
1169    template <class Exp>
1170    void do_assign_function(const Exp& e, const mpl::int_<2>&)
1171    {
1172       typedef typename Exp::right_type right_type;
1173       typedef typename right_type::tag_type tag_type;
1174       do_assign_function_1(e.left().value(), e.right_ref(), tag_type());
1175    }
1176    template <class F, class Exp>
1177    void do_assign_function_1(const F& f, const Exp& val, const detail::terminal&)
1178    {
1179       f(m_backend, function_arg_value(val));
1180    }
1181    template <class F, class Exp, class Tag>
1182    void do_assign_function_1(const F& f, const Exp& val, const Tag&)
1183    {
1184       number t(val);
1185       f(m_backend, t.backend());
1186    }
1187    template <class Exp>
1188    void do_assign_function(const Exp& e, const mpl::int_<3>&)
1189    {
1190       typedef typename Exp::middle_type middle_type;
1191       typedef typename middle_type::tag_type tag_type;
1192       typedef typename Exp::right_type end_type;
1193       typedef typename end_type::tag_type end_tag;
1194       do_assign_function_2(e.left().value(), e.middle_ref(), e.right_ref(), tag_type(), end_tag());
1195    }
1196    template <class F, class Exp1, class Exp2>
1197    void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const detail::terminal&, const detail::terminal&)
1198    {
1199       f(m_backend, function_arg_value(val1), function_arg_value(val2));
1200    }
1201    template <class F, class Exp1, class Exp2, class Tag1>
1202    void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const Tag1&, const detail::terminal&)
1203    {
1204       self_type temp1(val1);
1205       f(m_backend, BOOST_MP_MOVE(temp1.backend()), function_arg_value(val2));
1206    }
1207    template <class F, class Exp1, class Exp2, class Tag2>
1208    void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const detail::terminal&, const Tag2&)
1209    {
1210       self_type temp2(val2);
1211       f(m_backend, function_arg_value(val1), BOOST_MP_MOVE(temp2.backend()));
1212    }
1213    template <class F, class Exp1, class Exp2, class Tag1, class Tag2>
1214    void do_assign_function_2(const F& f, const Exp1& val1, const Exp2& val2, const Tag1&, const Tag2&)
1215    {
1216       self_type temp1(val1);
1217       self_type temp2(val2);
1218       f(m_backend, BOOST_MP_MOVE(temp1.backend()), BOOST_MP_MOVE(temp2.backend()));
1219    }
1220
1221    template <class Exp>
1222    void do_assign_function(const Exp& e, const mpl::int_<4>&)
1223    {
1224       typedef typename Exp::left_middle_type left_type;
1225       typedef typename left_type::tag_type left_tag_type;
1226       typedef typename Exp::right_middle_type middle_type;
1227       typedef typename middle_type::tag_type middle_tag_type;
1228       typedef typename Exp::right_type right_type;
1229       typedef typename right_type::tag_type right_tag_type;
1230       do_assign_function_3a(e.left().value(), e.left_middle_ref(), e.right_middle_ref(), e.right_ref(), left_tag_type(), middle_tag_type(), right_tag_type());
1231    }
1232    template <class F, class Exp1, class Exp2, class Exp3, class Tag2, class Tag3>
1233    void do_assign_function_3a(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const detail::terminal&, const Tag2& t2, const Tag3& t3)
1234    {
1235       do_assign_function_3b(f, val1, val2, val3, t2, t3);
1236    }
1237    template <class F, class Exp1, class Exp2, class Exp3, class Tag1, class Tag2, class Tag3>
1238    void do_assign_function_3a(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag1&, const Tag2& t2, const Tag3& t3)
1239    {
1240       number t(val1);
1241       do_assign_function_3b(f, BOOST_MP_MOVE(t), val2, val3, t2, t3);
1242    }
1243    template <class F, class Exp1, class Exp2, class Exp3, class Tag3>
1244    void do_assign_function_3b(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const detail::terminal&, const Tag3& t3)
1245    {
1246       do_assign_function_3c(f, val1, val2, val3, t3);
1247    }
1248    template <class F, class Exp1, class Exp2, class Exp3, class Tag2, class Tag3>
1249    void do_assign_function_3b(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag2& /*t2*/, const Tag3& t3)
1250    {
1251       number t(val2);
1252       do_assign_function_3c(f, val1, BOOST_MP_MOVE(t), val3, t3);
1253    }
1254    template <class F, class Exp1, class Exp2, class Exp3>
1255    void do_assign_function_3c(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const detail::terminal&)
1256    {
1257       f(m_backend, function_arg_value(val1), function_arg_value(val2), function_arg_value(val3));
1258    }
1259    template <class F, class Exp1, class Exp2, class Exp3, class Tag3>
1260    void do_assign_function_3c(const F& f, const Exp1& val1, const Exp2& val2, const Exp3& val3, const Tag3& /*t3*/)
1261    {
1262       number t(val3);
1263       do_assign_function_3c(f, val1, val2, BOOST_MP_MOVE(t), detail::terminal());
1264    }
1265
1266    template <class Exp>
1267    void do_add(const Exp& e, const detail::terminal&)
1268    {
1269       using default_ops::eval_add;
1270       eval_add(m_backend, canonical_value(e.value()));
1271    }
1272
1273    template <class Exp>
1274    void do_add(const Exp& e, const detail::negate&)
1275    {
1276       typedef typename Exp::left_type left_type;
1277       do_subtract(e.left(), typename left_type::tag_type());
1278    }
1279
1280    template <class Exp>
1281    void do_add(const Exp& e, const detail::plus&)
1282    {
1283       typedef typename Exp::left_type left_type;
1284       typedef typename Exp::right_type right_type;
1285       do_add(e.left(), typename left_type::tag_type());
1286       do_add(e.right(), typename right_type::tag_type());
1287    }
1288
1289    template <class Exp>
1290    void do_add(const Exp& e, const detail::minus&)
1291    {
1292       typedef typename Exp::left_type left_type;
1293       typedef typename Exp::right_type right_type;
1294       do_add(e.left(), typename left_type::tag_type());
1295       do_subtract(e.right(), typename right_type::tag_type());
1296    }
1297
1298    template <class Exp, class unknown>
1299    void do_add(const Exp& e, const unknown&)
1300    {
1301       self_type temp(e);
1302       do_add(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
1303    }
1304
1305    template <class Exp>
1306    void do_add(const Exp& e, const detail::add_immediates&)
1307    {
1308       using default_ops::eval_add;
1309       eval_add(m_backend, canonical_value(e.left().value()));
1310       eval_add(m_backend, canonical_value(e.right().value()));
1311    }
1312    template <class Exp>
1313    void do_add(const Exp& e, const detail::subtract_immediates&)
1314    {
1315       using default_ops::eval_add;
1316       using default_ops::eval_subtract;
1317       eval_add(m_backend, canonical_value(e.left().value()));
1318       eval_subtract(m_backend, canonical_value(e.right().value()));
1319    }
1320    template <class Exp>
1321    void do_subtract(const Exp& e, const detail::terminal&)
1322    {
1323       using default_ops::eval_subtract;
1324       eval_subtract(m_backend, canonical_value(e.value()));
1325    }
1326
1327    template <class Exp>
1328    void do_subtract(const Exp& e, const detail::negate&)
1329    {
1330       typedef typename Exp::left_type left_type;
1331       do_add(e.left(), typename left_type::tag_type());
1332    }
1333
1334    template <class Exp>
1335    void do_subtract(const Exp& e, const detail::plus&)
1336    {
1337       typedef typename Exp::left_type left_type;
1338       typedef typename Exp::right_type right_type;
1339       do_subtract(e.left(), typename left_type::tag_type());
1340       do_subtract(e.right(), typename right_type::tag_type());
1341    }
1342
1343    template <class Exp>
1344    void do_subtract(const Exp& e, const detail::minus&)
1345    {
1346       typedef typename Exp::left_type left_type;
1347       typedef typename Exp::right_type right_type;
1348       do_subtract(e.left(), typename left_type::tag_type());
1349       do_add(e.right(), typename right_type::tag_type());
1350    }
1351    template <class Exp>
1352    void do_subtract(const Exp& e, const detail::add_immediates&)
1353    {
1354       using default_ops::eval_subtract;
1355       eval_subtract(m_backend, canonical_value(e.left().value()));
1356       eval_subtract(m_backend, canonical_value(e.right().value()));
1357    }
1358    template <class Exp>
1359    void do_subtract(const Exp& e, const detail::subtract_immediates&)
1360    {
1361       using default_ops::eval_add;
1362       using default_ops::eval_subtract;
1363       eval_subtract(m_backend, canonical_value(e.left().value()));
1364       eval_add(m_backend, canonical_value(e.right().value()));
1365    }
1366    template <class Exp, class unknown>
1367    void do_subtract(const Exp& e, const unknown&)
1368    {
1369       self_type temp(e);
1370       do_subtract(detail::expression<detail::terminal, self_type>(temp), detail::terminal());
1371    }
1372
1373    template <class Exp>
1374    void do_multiplies(const Exp& e, const detail::terminal&)
1375    {
1376       using default_ops::eval_multiply;
1377       eval_multiply(m_backend, canonical_value(e.value()));
1378    }
1379
1380    template <class Exp>
1381    void do_multiplies(const Exp& e, const detail::negate&)
1382    {
1383       typedef typename Exp::left_type left_type;
1384       do_multiplies(e.left(), typename left_type::tag_type());
1385       m_backend.negate();
1386    }
1387
1388    template <class Exp>
1389    void do_multiplies(const Exp& e, const detail::multiplies&)
1390    {
1391       typedef typename Exp::left_type left_type;
1392       typedef typename Exp::right_type right_type;
1393       do_multiplies(e.left(), typename left_type::tag_type());
1394       do_multiplies(e.right(), typename right_type::tag_type());
1395    }
1396    //
1397    // This rearrangement is disabled for integer types, the test on sizeof(Exp) is simply to make
1398    // the disable_if dependent on the template argument (the size of 1 can never occur in practice).
1399    //
1400    template <class Exp>
1401    typename boost::disable_if_c<boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1>::type 
1402       do_multiplies(const Exp& e, const detail::divides&)
1403    {
1404       typedef typename Exp::left_type left_type;
1405       typedef typename Exp::right_type right_type;
1406       do_multiplies(e.left(), typename left_type::tag_type());
1407       do_divide(e.right(), typename right_type::tag_type());
1408    }
1409
1410    template <class Exp>
1411    void do_multiplies(const Exp& e, const detail::multiply_immediates&)
1412    {
1413       using default_ops::eval_multiply;
1414       eval_multiply(m_backend, canonical_value(e.left().value()));
1415       eval_multiply(m_backend, canonical_value(e.right().value()));
1416    }
1417    //
1418    // This rearrangement is disabled for integer types, the test on sizeof(Exp) is simply to make
1419    // the disable_if dependent on the template argument (the size of 1 can never occur in practice).
1420    //
1421    template <class Exp>
1422    typename boost::disable_if_c<boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1>::type
1423       do_multiplies(const Exp& e, const detail::divide_immediates&)
1424    {
1425       using default_ops::eval_multiply;
1426       using default_ops::eval_divide;
1427       eval_multiply(m_backend, canonical_value(e.left().value()));
1428       eval_divide(m_backend, canonical_value(e.right().value()));
1429    }
1430    template <class Exp, class unknown>
1431    void do_multiplies(const Exp& e, const unknown&)
1432    {
1433       using default_ops::eval_multiply;
1434       self_type temp(e);
1435       eval_multiply(m_backend, temp.m_backend);
1436    }
1437
1438    template <class Exp>
1439    void do_divide(const Exp& e, const detail::terminal&)
1440    {
1441       using default_ops::eval_divide;
1442       eval_divide(m_backend, canonical_value(e.value()));
1443    }
1444
1445    template <class Exp>
1446    void do_divide(const Exp& e, const detail::negate&)
1447    {
1448       typedef typename Exp::left_type left_type;
1449       do_divide(e.left(), typename left_type::tag_type());
1450       m_backend.negate();
1451    }
1452    //
1453    // This rearrangement is disabled for integer types, the test on sizeof(Exp) is simply to make
1454    // the disable_if dependent on the template argument (the size of 1 can never occur in practice).
1455    //
1456    template <class Exp>
1457    typename boost::disable_if_c<boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1>::type
1458       do_divide(const Exp& e, const detail::multiplies&)
1459    {
1460       typedef typename Exp::left_type left_type;
1461       typedef typename Exp::right_type right_type;
1462       do_divide(e.left(), typename left_type::tag_type());
1463       do_divide(e.right(), typename right_type::tag_type());
1464    }
1465    //
1466    // This rearrangement is disabled for integer types, the test on sizeof(Exp) is simply to make
1467    // the disable_if dependent on the template argument (the size of 1 can never occur in practice).
1468    //
1469    template <class Exp>
1470    typename boost::disable_if_c<boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1>::type
1471       do_divide(const Exp& e, const detail::divides&)
1472    {
1473       typedef typename Exp::left_type left_type;
1474       typedef typename Exp::right_type right_type;
1475       do_divide(e.left(), typename left_type::tag_type());
1476       do_multiplies(e.right(), typename right_type::tag_type());
1477    }
1478    //
1479    // This rearrangement is disabled for integer types, the test on sizeof(Exp) is simply to make
1480    // the disable_if dependent on the template argument (the size of 1 can never occur in practice).
1481    //
1482    template <class Exp>
1483    typename boost::disable_if_c<boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1>::type
1484       do_divides(const Exp& e, const detail::multiply_immediates&)
1485    {
1486       using default_ops::eval_divide;
1487       eval_divide(m_backend, canonical_value(e.left().value()));
1488       eval_divide(m_backend, canonical_value(e.right().value()));
1489    }
1490    //
1491    // This rearrangement is disabled for integer types, the test on sizeof(Exp) is simply to make
1492    // the disable_if dependent on the template argument (the size of 1 can never occur in practice).
1493    //
1494    template <class Exp>
1495    typename boost::disable_if_c<boost::multiprecision::number_category<self_type>::value == boost::multiprecision::number_kind_integer || sizeof(Exp) == 1>::type
1496       do_divides(const Exp& e, const detail::divide_immediates&)
1497    {
1498       using default_ops::eval_multiply;
1499       using default_ops::eval_divide;
1500       eval_divide(m_backend, canonical_value(e.left().value()));
1501       mutiply(m_backend, canonical_value(e.right().value()));
1502    }
1503
1504    template <class Exp, class unknown>
1505    void do_divide(const Exp& e, const unknown&)
1506    {
1507       using default_ops::eval_multiply;
1508       self_type temp(e);
1509       eval_divide(m_backend, temp.m_backend);
1510    }
1511
1512    template <class Exp>
1513    void do_modulus(const Exp& e, const detail::terminal&)
1514    {
1515       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
1516       using default_ops::eval_modulus;
1517       eval_modulus(m_backend, canonical_value(e.value()));
1518    }
1519
1520    template <class Exp, class Unknown>
1521    void do_modulus(const Exp& e, const Unknown&)
1522    {
1523       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The modulus operation is only valid for integer types");
1524       using default_ops::eval_modulus;
1525       self_type temp(e);
1526       eval_modulus(m_backend, canonical_value(temp));
1527    }
1528
1529    template <class Exp>
1530    void do_bitwise_and(const Exp& e, const detail::terminal&)
1531    {
1532       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
1533       using default_ops::eval_bitwise_and;
1534       eval_bitwise_and(m_backend, canonical_value(e.value()));
1535    }
1536    template <class Exp>
1537    void do_bitwise_and(const Exp& e, const detail::bitwise_and&)
1538    {
1539       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
1540       typedef typename Exp::left_type left_type;
1541       typedef typename Exp::right_type right_type;
1542       do_bitwise_and(e.left(), typename left_type::tag_type());
1543       do_bitwise_and(e.right(), typename right_type::tag_type());
1544    }
1545    template <class Exp, class unknown>
1546    void do_bitwise_and(const Exp& e, const unknown&)
1547    {
1548       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise & operation is only valid for integer types");
1549       using default_ops::eval_bitwise_and;
1550       self_type temp(e);
1551       eval_bitwise_and(m_backend, temp.m_backend);
1552    }
1553
1554    template <class Exp>
1555    void do_bitwise_or(const Exp& e, const detail::terminal&)
1556    {
1557       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
1558       using default_ops::eval_bitwise_or;
1559       eval_bitwise_or(m_backend, canonical_value(e.value()));
1560    }
1561    template <class Exp>
1562    void do_bitwise_or(const Exp& e, const detail::bitwise_or&)
1563    {
1564       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
1565       typedef typename Exp::left_type left_type;
1566       typedef typename Exp::right_type right_type;
1567       do_bitwise_or(e.left(), typename left_type::tag_type());
1568       do_bitwise_or(e.right(), typename right_type::tag_type());
1569    }
1570    template <class Exp, class unknown>
1571    void do_bitwise_or(const Exp& e, const unknown&)
1572    {
1573       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise | operation is only valid for integer types");
1574       using default_ops::eval_bitwise_or;
1575       self_type temp(e);
1576       eval_bitwise_or(m_backend, temp.m_backend);
1577    }
1578
1579    template <class Exp>
1580    void do_bitwise_xor(const Exp& e, const detail::terminal&)
1581    {
1582       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
1583       using default_ops::eval_bitwise_xor;
1584       eval_bitwise_xor(m_backend, canonical_value(e.value()));
1585    }
1586    template <class Exp>
1587    void do_bitwise_xor(const Exp& e, const detail::bitwise_xor&)
1588    {
1589       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
1590       typedef typename Exp::left_type left_type;
1591       typedef typename Exp::right_type right_type;
1592       do_bitwise_xor(e.left(), typename left_type::tag_type());
1593       do_bitwise_xor(e.right(), typename right_type::tag_type());
1594    }
1595    template <class Exp, class unknown>
1596    void do_bitwise_xor(const Exp& e, const unknown&)
1597    {
1598       BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_integer, "The bitwise ^ operation is only valid for integer types");
1599       using default_ops::eval_bitwise_xor;
1600       self_type temp(e);
1601       eval_bitwise_xor(m_backend, temp.m_backend);
1602    }
1603
1604    // Tests if the expression contains a reference to *this:
1605    template <class Exp>
1606    BOOST_MP_FORCEINLINE bool contains_self(const Exp& e)const BOOST_NOEXCEPT
1607    {
1608       return contains_self(e, typename Exp::arity());
1609    }
1610    template <class Exp>
1611    BOOST_MP_FORCEINLINE bool contains_self(const Exp& e, mpl::int_<0> const&)const BOOST_NOEXCEPT
1612    {
1613       return is_realy_self(e.value());
1614    }
1615    template <class Exp>
1616    BOOST_MP_FORCEINLINE bool contains_self(const Exp& e, mpl::int_<1> const&)const BOOST_NOEXCEPT
1617    {
1618       typedef typename Exp::left_type child_type;
1619       return contains_self(e.left(), typename child_type::arity());
1620    }
1621    template <class Exp>
1622    BOOST_MP_FORCEINLINE bool contains_self(const Exp& e, mpl::int_<2> const&)const BOOST_NOEXCEPT
1623    {
1624       typedef typename Exp::left_type child0_type;
1625       typedef typename Exp::right_type child1_type;
1626       return contains_self(e.left(), typename child0_type::arity())
1627          || contains_self(e.right(), typename child1_type::arity());
1628    }
1629    template <class Exp>
1630    BOOST_MP_FORCEINLINE bool contains_self(const Exp& e, mpl::int_<3> const&)const BOOST_NOEXCEPT
1631    {
1632       typedef typename Exp::left_type child0_type;
1633       typedef typename Exp::middle_type child1_type;
1634       typedef typename Exp::right_type child2_type;
1635       return contains_self(e.left(), typename child0_type::arity())
1636          || contains_self(e.middle(), typename child1_type::arity())
1637          || contains_self(e.right(), typename child2_type::arity());
1638    }
1639
1640    // Test if the expression is a reference to *this:
1641    template <class Exp>
1642    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool is_self(const Exp& e)const BOOST_NOEXCEPT
1643    {
1644       return is_self(e, typename Exp::arity());
1645    }
1646    template <class Exp>
1647    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool is_self(const Exp& e, mpl::int_<0> const&)const BOOST_NOEXCEPT
1648    {
1649       return is_realy_self(e.value());
1650    }
1651    template <class Exp, int v>
1652    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool is_self(const Exp&, mpl::int_<v> const&)const BOOST_NOEXCEPT
1653    {
1654       return false;
1655    }
1656
1657    template <class Val>
1658    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool is_realy_self(const Val&)const BOOST_NOEXCEPT{ return false; }
1659    BOOST_MP_FORCEINLINE BOOST_CONSTEXPR bool is_realy_self(const self_type& v)const BOOST_NOEXCEPT{ return &v == this; }
1660
1661    static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const Backend& function_arg_value(const self_type& v) BOOST_NOEXCEPT {  return v.backend();  }
1662    template <class V>
1663    static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const V& function_arg_value(const V& v) BOOST_NOEXCEPT {  return v;  }
1664    template <class A1, class A2, class A3, class A4>
1665    static BOOST_MP_FORCEINLINE const A1& function_arg_value(const detail::expression<detail::terminal, A1, A2, A3, A4>& exp) BOOST_NOEXCEPT { return exp.value(); }
1666    template <class A2, class A3, class A4>
1667    static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const Backend& function_arg_value(const detail::expression<detail::terminal, number<Backend>, A2, A3, A4>& exp) BOOST_NOEXCEPT { return exp.value().backend(); }
1668    Backend m_backend;
1669
1670 public:
1671    //
1672    // These shouldn't really need to be public, or even member functions, but it makes implementing
1673    // the non-member operators way easier if they are:
1674    //
1675    static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const Backend& canonical_value(const self_type& v) BOOST_NOEXCEPT {  return v.m_backend;  }
1676    template <class B2, expression_template_option ET>
1677    static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR const B2& canonical_value(const number<B2, ET>& v) BOOST_NOEXCEPT {  return v.backend();  }
1678    template <class V>
1679    static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR typename boost::disable_if<is_same<typename detail::canonical<V, Backend>::type, V>, typename detail::canonical<V, Backend>::type>::type
1680       canonical_value(const V& v) BOOST_NOEXCEPT {  return static_cast<typename detail::canonical<V, Backend>::type>(v);  }
1681    template <class V>
1682    static BOOST_MP_FORCEINLINE BOOST_CONSTEXPR typename boost::enable_if<is_same<typename detail::canonical<V, Backend>::type, V>, const V&>::type
1683       canonical_value(const V& v) BOOST_NOEXCEPT {  return v;  }
1684    static BOOST_MP_FORCEINLINE typename detail::canonical<std::string, Backend>::type canonical_value(const std::string& v) BOOST_NOEXCEPT {  return v.c_str();  }
1685
1686 };
1687
1688 template <class Backend, expression_template_option ExpressionTemplates>
1689 inline std::ostream& operator << (std::ostream& os, const number<Backend, ExpressionTemplates>& r)
1690 {
1691    std::streamsize d = os.precision();
1692    std::string s = r.str(d, os.flags());
1693    std::streamsize ss = os.width();
1694    if(ss > static_cast<std::streamsize>(s.size()))
1695    {
1696       char fill = os.fill();
1697       if((os.flags() & std::ios_base::left) == std::ios_base::left)
1698          s.append(static_cast<std::string::size_type>(ss - s.size()), fill);
1699       else
1700          s.insert(static_cast<std::string::size_type>(0), static_cast<std::string::size_type>(ss - s.size()), fill);
1701    }
1702    return os << s;
1703 }
1704
1705 namespace detail{
1706
1707 template <class tag, class A1, class A2, class A3, class A4>
1708 inline std::ostream& operator << (std::ostream& os, const expression<tag, A1, A2, A3, A4>& r)
1709 {
1710    typedef typename expression<tag, A1, A2, A3, A4>::result_type value_type;
1711    value_type temp(r);
1712    return os << temp;
1713 }
1714 //
1715 // What follows is the input streaming code: this is not "proper" iostream code at all
1716 // but that's fiendishly hard to write when dealing with multiple backends all
1717 // with different requirements... yes we could deligate this to the backend author...
1718 // but we really want backends to be EASY to write!
1719 // For now just pull in all the characters that could possibly form the number
1720 // and let the backend's string parser make use of it.  This fixes most use cases
1721 // including CSV type formats such as those used by the Random lib.
1722 //
1723 inline std::string read_string_while(std::istream& is, std::string const& permitted_chars)
1724 {
1725    std::ios_base::iostate state = std::ios_base::goodbit;
1726    const std::istream::sentry sentry_check(is);
1727    std::string result;
1728
1729    if(sentry_check)
1730    {
1731       int c = is.rdbuf()->sgetc();
1732
1733       for(;; c = is.rdbuf()->snextc())
1734          if(std::istream::traits_type::eq_int_type(std::istream::traits_type::eof(), c))
1735          { // end of file:
1736             state |= std::ios_base::eofbit;
1737             break;
1738          }
1739          else if(permitted_chars.find_first_of(std::istream::traits_type::to_char_type(c)) == std::string::npos)
1740          {
1741             // Invalid numeric character, stop reading:
1742             //is.rdbuf()->sputbackc(static_cast<char>(c));
1743             break;
1744          }
1745          else
1746          {
1747             result.append(1, std::istream::traits_type::to_char_type(c));
1748          }
1749    }
1750
1751    if(!result.size())
1752       state |= std::ios_base::failbit;
1753    is.setstate(state);
1754    return result;
1755 }
1756
1757 } // namespace detail
1758
1759 template <class Backend, expression_template_option ExpressionTemplates>
1760 inline std::istream& operator >> (std::istream& is, number<Backend, ExpressionTemplates>& r)
1761 {
1762    bool hex_format = (is.flags() & std::ios_base::hex) == std::ios_base::hex;
1763    bool oct_format = (is.flags() & std::ios_base::oct) == std::ios_base::oct;
1764    std::string s;
1765    switch(boost::multiprecision::number_category<number<Backend, ExpressionTemplates> >::value)
1766    {
1767    case boost::multiprecision::number_kind_integer:
1768       if(oct_format)
1769          s = detail::read_string_while(is, "+-01234567");
1770       else if(hex_format)
1771          s = detail::read_string_while(is, "+-xXabcdefABCDEF0123456789");
1772       else
1773          s = detail::read_string_while(is, "+-0123456789");
1774       break;
1775    case boost::multiprecision::number_kind_floating_point:
1776       s = detail::read_string_while(is, "+-eE.0123456789infINFnanNANinfinityINFINITY");
1777       break;
1778    default:
1779       is >> s;
1780    }
1781    if(s.size())
1782    {
1783       if(hex_format && (number_category<Backend>::value == number_kind_integer) && ((s[0] != '0') || (s[1] != 'x')))
1784          s.insert(s.find_first_not_of("+-"), "0x");
1785       if(oct_format && (number_category<Backend>::value == number_kind_integer) && (s[0] != '0'))
1786          s.insert(s.find_first_not_of("+-"), "0");
1787       r.assign(s);
1788    }
1789    else if(!is.fail())
1790       is.setstate(std::istream::failbit);
1791    return is;
1792 }
1793
1794 template <class Backend, expression_template_option ExpressionTemplates>
1795 BOOST_MP_FORCEINLINE void swap(number<Backend, ExpressionTemplates>& a, number<Backend, ExpressionTemplates>& b) 
1796    BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<number<Backend, ExpressionTemplates>&>() = std::declval<number<Backend, ExpressionTemplates>&>()))
1797 {
1798    a.swap(b);
1799 }
1800 //
1801 // Boost.Hash support, just call hash_value for the backend, which may or may not be supported:
1802 //
1803 template <class Backend, expression_template_option ExpressionTemplates>
1804 inline std::size_t hash_value(const number<Backend, ExpressionTemplates>& val)
1805 {
1806    return hash_value(val.backend());
1807 }
1808
1809 }  // namespace multiprecision
1810
1811 template <class T>
1812 class rational;
1813
1814 template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
1815 inline std::istream& operator >> (std::istream& is, rational<multiprecision::number<Backend, ExpressionTemplates> >& r)
1816 {
1817    std::string s1;
1818    multiprecision::number<Backend, ExpressionTemplates> v1, v2;
1819    char c;
1820    bool have_hex = false;
1821    bool hex_format = (is.flags() & std::ios_base::hex) == std::ios_base::hex;
1822    bool oct_format = (is.flags() & std::ios_base::oct) == std::ios_base::oct;
1823
1824    while((EOF != (c = static_cast<char>(is.peek()))) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F'))))
1825    {
1826       if(c == 'x' || c == 'X')
1827          have_hex = true;
1828       s1.append(1, c);
1829       is.get();
1830    }
1831    if(hex_format && ((s1[0] != '0') || (s1[1] != 'x')))
1832       s1.insert(static_cast<std::string::size_type>(0), "0x");
1833    if(oct_format && (s1[0] != '0'))
1834       s1.insert(static_cast<std::string::size_type>(0), "0");
1835    v1.assign(s1);
1836    s1.erase();
1837    if(c == '/')
1838    {
1839       is.get();
1840       while((EOF != (c = static_cast<char>(is.peek()))) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F'))))
1841       {
1842          if(c == 'x' || c == 'X')
1843             have_hex = true;
1844          s1.append(1, c);
1845          is.get();
1846       }
1847       if(hex_format && ((s1[0] != '0') || (s1[1] != 'x')))
1848          s1.insert(static_cast<std::string::size_type>(0), "0x");
1849       if(oct_format && (s1[0] != '0'))
1850          s1.insert(static_cast<std::string::size_type>(0), "0");
1851       v2.assign(s1);
1852    }
1853    else
1854       v2 = 1;
1855    r.assign(v1, v2);
1856    return is;
1857 }
1858
1859 template <class T, multiprecision::expression_template_option ExpressionTemplates>
1860 inline multiprecision::number<T, ExpressionTemplates> numerator(const rational<multiprecision::number<T, ExpressionTemplates> >& a)
1861 {
1862    return a.numerator();
1863 }
1864
1865 template <class T, multiprecision::expression_template_option ExpressionTemplates>
1866 inline multiprecision::number<T, ExpressionTemplates> denominator(const rational<multiprecision::number<T, ExpressionTemplates> >& a)
1867 {
1868    return a.denominator();
1869 }
1870
1871 namespace multiprecision
1872 {
1873
1874 template <class I>
1875 struct component_type<boost::rational<I> >
1876 {
1877    typedef I type;
1878 };
1879
1880 }
1881
1882 #ifdef BOOST_MSVC
1883 #pragma warning(pop)
1884 #endif
1885
1886 } // namespaces
1887
1888 #ifndef BOOST_NO_CXX11_HDR_FUNCTIONAL
1889
1890 #include <functional>
1891
1892 namespace std {
1893
1894    template <class Backend, boost::multiprecision::expression_template_option ExpressionTemplates>
1895    struct hash<boost::multiprecision::number<Backend, ExpressionTemplates> >
1896    {
1897       std::size_t operator()(const boost::multiprecision::number<Backend, ExpressionTemplates>& val)const { return hash_value(val); }
1898    };
1899
1900 }
1901
1902 #endif
1903
1904 #include <boost/multiprecision/detail/ublas_interop.hpp>
1905
1906 #endif