From ce3354335c63facc219b2ef92fd33bb2b8c2f041 Mon Sep 17 00:00:00 2001 From: John Maddock Date: Tue, 4 Sep 2012 08:20:26 +0000 Subject: [PATCH] Allow mixed precision binary operations. Add tests for basic mixed precision usage. [SVN r80394] --- include/boost/multiprecision/cpp_int.hpp | 9 +- .../multiprecision/detail/default_ops.hpp | 106 +-- .../boost/multiprecision/detail/et_ops.hpp | 691 ++++++++++++++++++ .../boost/multiprecision/detail/no_et_ops.hpp | 90 +-- .../multiprecision/detail/number_base.hpp | 644 +--------------- .../multiprecision/detail/number_compare.hpp | 205 +++--- include/boost/multiprecision/gmp.hpp | 14 +- include/boost/multiprecision/mpfr.hpp | 6 +- include/boost/multiprecision/number.hpp | 44 +- include/boost/multiprecision/tommath.hpp | 14 +- test/test_arithmetic.cpp | 86 ++- 11 files changed, 1045 insertions(+), 864 deletions(-) create mode 100644 include/boost/multiprecision/detail/et_ops.hpp diff --git a/include/boost/multiprecision/cpp_int.hpp b/include/boost/multiprecision/cpp_int.hpp index 39458f29..17d97b72 100644 --- a/include/boost/multiprecision/cpp_int.hpp +++ b/include/boost/multiprecision/cpp_int.hpp @@ -3202,13 +3202,8 @@ public: static number_type val; if(!init) { - boost::multiprecision::limb_type l = ~static_cast(0); - unsigned c = MinBits / backend_type::limb_bits + (MinBits % backend_type::limb_bits ? 1 : 0); - for(unsigned i = 0; i < c; ++i) - { - val <<= backend_type::limb_bits; - val |= l; - } + boost::multiprecision::number, ExpressionTemplates> t(0); + val = ~t; init = true; } return val; diff --git a/include/boost/multiprecision/detail/default_ops.hpp b/include/boost/multiprecision/detail/default_ops.hpp index 5029bf47..66f9731e 100644 --- a/include/boost/multiprecision/detail/default_ops.hpp +++ b/include/boost/multiprecision/detail/default_ops.hpp @@ -38,7 +38,7 @@ namespace boost{ namespace multiprecision{ namespace default_ops{ // of each depending on whether the backend can be directly constructed from type V: // template -inline typename enable_if_c::value && !is_convertible::value >::type +inline typename enable_if_c >::value && !is_convertible::value >::type eval_add(T& result, V const& v) { T t; @@ -46,14 +46,14 @@ inline typename enable_if_c::value && !is_convertible::va eval_add(result, t); } template -inline typename enable_if_c::value && is_convertible::value >::type +inline typename enable_if_c >::value && is_convertible::value >::type eval_add(T& result, V const& v) { T t(v); eval_add(result, t); } template -inline typename enable_if_c::value && !is_convertible::value>::type +inline typename enable_if_c >::value && !is_convertible::value>::type eval_subtract(T& result, V const& v) { T t; @@ -61,14 +61,14 @@ inline typename enable_if_c::value && !is_convertible::va eval_subtract(result, t); } template -inline typename enable_if_c::value && is_convertible::value>::type +inline typename enable_if_c >::value && is_convertible::value>::type eval_subtract(T& result, V const& v) { T t(v); eval_subtract(result, t); } template -inline typename enable_if_c::value && !is_convertible::value>::type +inline typename enable_if_c >::value && !is_convertible::value>::type eval_multiply(T& result, V const& v) { T t; @@ -76,14 +76,14 @@ inline typename enable_if_c::value && !is_convertible::va eval_multiply(result, t); } template -inline typename enable_if_c::value && is_convertible::value>::type +inline typename enable_if_c >::value && is_convertible::value>::type eval_multiply(T& result, V const& v) { T t(v); eval_multiply(result, t); } template -inline typename enable_if_c::value && !is_convertible::value>::type +inline typename enable_if_c >::value && !is_convertible::value>::type eval_divide(T& result, V const& v) { T t; @@ -91,14 +91,14 @@ inline typename enable_if_c::value && !is_convertible::va eval_divide(result, t); } template -inline typename enable_if_c::value && is_convertible::value>::type +inline typename enable_if_c >::value && is_convertible::value>::type eval_divide(T& result, V const& v) { T t(v); eval_divide(result, t); } template -inline typename enable_if_c::value && !is_convertible::value>::type +inline typename enable_if_c >::value && !is_convertible::value>::type eval_modulus(T& result, V const& v) { T t; @@ -106,14 +106,14 @@ inline typename enable_if_c::value && !is_convertible::va eval_modulus(result, t); } template -inline typename enable_if_c::value && is_convertible::value>::type +inline typename enable_if_c >::value&& is_convertible::value>::type eval_modulus(T& result, V const& v) { T t(v); eval_modulus(result, t); } template -inline typename enable_if_c::value && !is_convertible::value>::type +inline typename enable_if_c >::value && !is_convertible::value>::type eval_bitwise_and(T& result, V const& v) { T t; @@ -121,14 +121,14 @@ inline typename enable_if_c::value && !is_convertible::va eval_bitwise_and(result, t); } template -inline typename enable_if_c::value && is_convertible::value>::type +inline typename enable_if_c >::value && is_convertible::value>::type eval_bitwise_and(T& result, V const& v) { T t(v); eval_bitwise_and(result, t); } template -inline typename enable_if_c::value && !is_convertible::value>::type +inline typename enable_if_c >::value && !is_convertible::value>::type eval_bitwise_or(T& result, V const& v) { T t; @@ -136,14 +136,14 @@ inline typename enable_if_c::value && !is_convertible::va eval_bitwise_or(result, t); } template -inline typename enable_if_c::value && is_convertible::value>::type +inline typename enable_if_c >::value && is_convertible::value>::type eval_bitwise_or(T& result, V const& v) { T t(v); eval_bitwise_or(result, t); } template -inline typename enable_if_c::value && !is_convertible::value>::type +inline typename enable_if_c >::value && !is_convertible::value>::type eval_bitwise_xor(T& result, V const& v) { T t; @@ -151,7 +151,7 @@ inline typename enable_if_c::value && !is_convertible::va eval_bitwise_xor(result, t); } template -inline typename enable_if_c::value && is_convertible::value>::type +inline typename enable_if_c >::value && is_convertible::value>::type eval_bitwise_xor(T& result, V const& v) { T t(v); @@ -159,7 +159,7 @@ inline typename enable_if_c::value && is_convertible::val } template -inline typename enable_if_c::value && !is_convertible::value>::type +inline typename enable_if_c >::value && !is_convertible::value>::type eval_complement(T& result, V const& v) { T t; @@ -167,7 +167,7 @@ inline typename enable_if_c::value && !is_convertible::va eval_complement(result, t); } template -inline typename enable_if_c::value && is_convertible::value>::type +inline typename enable_if_c >::value && is_convertible::value>::type eval_complement(T& result, V const& v) { T t(v); @@ -195,20 +195,20 @@ inline void eval_add(T& t, const T& u, const T& v) } } template -inline typename enable_if_c::value && !is_convertible::value>::type eval_add(T& t, const T& u, const U& v) +inline typename enable_if_c >::value && !is_convertible::value>::type eval_add(T& t, const T& u, const U& v) { T vv; vv = v; eval_add(t, u, vv); } template -inline typename enable_if_c::value && is_convertible::value>::type eval_add(T& t, const T& u, const U& v) +inline typename enable_if_c >::value && is_convertible::value>::type eval_add(T& t, const T& u, const U& v) { T vv(v); eval_add(t, u, vv); } template -inline typename enable_if_c::value>::type eval_add(T& t, const U& u, const T& v) +inline typename enable_if_c >::value>::type eval_add(T& t, const U& u, const T& v) { eval_add(t, v, u); } @@ -232,20 +232,20 @@ inline void eval_subtract(T& t, const T& u, const T& v) } } template -inline typename enable_if_c::value && !is_convertible::value>::type eval_subtract(T& t, const T& u, const U& v) +inline typename enable_if_c >::value && !is_convertible::value>::type eval_subtract(T& t, const T& u, const U& v) { T vv; vv = v; eval_subtract(t, u, vv); } template -inline typename enable_if_c::value && is_convertible::value>::type eval_subtract(T& t, const T& u, const U& v) +inline typename enable_if_c >::value && is_convertible::value>::type eval_subtract(T& t, const T& u, const U& v) { T vv(v); eval_subtract(t, u, vv); } template -inline typename enable_if_c::value>::type eval_subtract(T& t, const U& u, const T& v) +inline typename enable_if_c >::value>::type eval_subtract(T& t, const U& u, const T& v) { eval_subtract(t, v, u); t.negate(); @@ -269,20 +269,20 @@ inline void eval_multiply(T& t, const T& u, const T& v) } } template -inline typename enable_if_c::value && !is_convertible::value>::type eval_multiply(T& t, const T& u, const U& v) +inline typename enable_if_c >::value && !is_convertible::value>::type eval_multiply(T& t, const T& u, const U& v) { T vv; vv = v; eval_multiply(t, u, vv); } template -inline typename enable_if_c::value && is_convertible::value>::type eval_multiply(T& t, const T& u, const U& v) +inline typename enable_if_c >::value && is_convertible::value>::type eval_multiply(T& t, const T& u, const U& v) { T vv(v); eval_multiply(t, u, vv); } template -inline typename enable_if_c::value>::type eval_multiply(T& t, const U& u, const T& v) +inline typename enable_if_c >::value>::type eval_multiply(T& t, const U& u, const T& v) { eval_multiply(t, v, u); } @@ -305,27 +305,27 @@ inline void eval_divide(T& t, const T& u, const T& v) } } template -inline typename enable_if_c::value && !is_convertible::value>::type eval_divide(T& t, const T& u, const U& v) +inline typename enable_if_c >::value && !is_convertible::value>::type eval_divide(T& t, const T& u, const U& v) { T vv; vv = v; eval_divide(t, u, vv); } template -inline typename enable_if_c::value && is_convertible::value>::type eval_divide(T& t, const T& u, const U& v) +inline typename enable_if_c >::value && is_convertible::value>::type eval_divide(T& t, const T& u, const U& v) { T vv(v); eval_divide(t, u, vv); } template -inline typename enable_if_c::value && !is_convertible::value>::type eval_divide(T& t, const U& u, const T& v) +inline typename enable_if_c >::value && !is_convertible::value>::type eval_divide(T& t, const U& u, const T& v) { T uu; uu = u; eval_divide(t, uu, v); } template -inline typename enable_if_c::value && is_convertible::value>::type eval_divide(T& t, const U& u, const T& v) +inline typename enable_if_c >::value && is_convertible::value>::type eval_divide(T& t, const U& u, const T& v) { T uu(u); eval_divide(t, uu, v); @@ -350,27 +350,27 @@ inline void eval_modulus(T& t, const T& u, const T& v) } } template -inline typename enable_if_c::value && !is_convertible::value>::type eval_modulus(T& t, const T& u, const U& v) +inline typename enable_if_c >::value && !is_convertible::value>::type eval_modulus(T& t, const T& u, const U& v) { T vv; vv = v; eval_modulus(t, u, vv); } template -inline typename enable_if_c::value && is_convertible::value>::type eval_modulus(T& t, const T& u, const U& v) +inline typename enable_if_c >::value && is_convertible::value>::type eval_modulus(T& t, const T& u, const U& v) { T vv(v); eval_modulus(t, u, vv); } template -inline typename enable_if_c::value && !is_convertible::value>::type eval_modulus(T& t, const U& u, const T& v) +inline typename enable_if_c >::value && !is_convertible::value>::type eval_modulus(T& t, const U& u, const T& v) { T uu; uu = u; eval_modulus(t, uu, v); } template -inline typename enable_if_c::value && is_convertible::value>::type eval_modulus(T& t, const U& u, const T& v) +inline typename enable_if_c >::value && is_convertible::value>::type eval_modulus(T& t, const U& u, const T& v) { T uu(u); eval_modulus(t, uu, v); @@ -394,20 +394,20 @@ inline void eval_bitwise_and(T& t, const T& u, const T& v) } } template -inline typename enable_if_c::value && !is_convertible::value>::type eval_bitwise_and(T& t, const T& u, const U& v) +inline typename enable_if_c >::value && !is_convertible::value>::type eval_bitwise_and(T& t, const T& u, const U& v) { T vv; vv = v; eval_bitwise_and(t, u, vv); } template -inline typename enable_if_c::value && is_convertible::value>::type eval_bitwise_and(T& t, const T& u, const U& v) +inline typename enable_if_c >::value && is_convertible::value>::type eval_bitwise_and(T& t, const T& u, const U& v) { T vv(v); eval_bitwise_and(t, u, vv); } template -inline typename enable_if_c::value>::type eval_bitwise_and(T& t, const U& u, const T& v) +inline typename enable_if_c >::value>::type eval_bitwise_and(T& t, const U& u, const T& v) { eval_bitwise_and(t, v, u); } @@ -430,20 +430,20 @@ inline void eval_bitwise_or(T& t, const T& u, const T& v) } } template -inline typename enable_if_c::value && !is_convertible::value>::type eval_bitwise_or(T& t, const T& u, const U& v) +inline typename enable_if_c >::value && !is_convertible::value>::type eval_bitwise_or(T& t, const T& u, const U& v) { T vv; vv = v; eval_bitwise_or(t, u, vv); } template -inline typename enable_if_c::value && is_convertible::value>::type eval_bitwise_or(T& t, const T& u, const U& v) +inline typename enable_if_c >::value && is_convertible::value>::type eval_bitwise_or(T& t, const T& u, const U& v) { T vv(v); eval_bitwise_or(t, u, vv); } template -inline typename enable_if_c::value>::type eval_bitwise_or(T& t, const U& u, const T& v) +inline typename enable_if_c >::value>::type eval_bitwise_or(T& t, const U& u, const T& v) { eval_bitwise_or(t, v, u); } @@ -466,20 +466,20 @@ inline void eval_bitwise_xor(T& t, const T& u, const T& v) } } template -inline typename enable_if_c::value && !is_convertible::value>::type eval_bitwise_xor(T& t, const T& u, const U& v) +inline typename enable_if_c >::value && !is_convertible::value>::type eval_bitwise_xor(T& t, const T& u, const U& v) { T vv; vv = v; eval_bitwise_xor(t, u, vv); } template -inline typename enable_if_c::value && is_convertible::value>::type eval_bitwise_xor(T& t, const T& u, const U& v) +inline typename enable_if_c >::value && is_convertible::value>::type eval_bitwise_xor(T& t, const T& u, const U& v) { T vv(v); eval_bitwise_xor(t, u, vv); } template -inline typename enable_if_c::value>::type eval_bitwise_xor(T& t, const U& u, const T& v) +inline typename enable_if_c >::value>::type eval_bitwise_xor(T& t, const U& u, const T& v) { eval_bitwise_xor(t, v, u); } @@ -580,13 +580,28 @@ struct calculate_next_larger_type >::type type; }; +template +inline bool check_in_range(const T& t) +{ + // Can t fit in an R? + if(std::numeric_limits::is_specialized && std::numeric_limits::is_bounded && (t > (std::numeric_limits::max)())) + return true; + return false; +} + +template +inline bool check_in_range(const terminal&) +{ + return false; +} + template inline void eval_convert_to(R* result, const B& backend) { typedef typename calculate_next_larger_type::type next_type; next_type n; eval_convert_to(&n, backend); - if(std::numeric_limits::is_specialized && (n > (std::numeric_limits::max)())) + if(check_in_range(n)) { *result = (std::numeric_limits::max)(); } @@ -1617,6 +1632,7 @@ inline multiprecision::number sinhc_pi(const multi // This has to come last of all: // #include +#include #endif diff --git a/include/boost/multiprecision/detail/et_ops.hpp b/include/boost/multiprecision/detail/et_ops.hpp new file mode 100644 index 00000000..35886a9b --- /dev/null +++ b/include/boost/multiprecision/detail/et_ops.hpp @@ -0,0 +1,691 @@ +/////////////////////////////////////////////////////////////////////////////// +// Copyright 2011 John Maddock. Distributed under the Boost +// Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_MP_ET_OPS_HPP +#define BOOST_MP_ET_OPS_HPP + +namespace boost{ namespace multiprecision{ + +// +// Non-member operators for number: +// +// Unary operators first: +// +template +inline const number& operator + (const number& v) { return v; } +template +inline const detail::expression& operator + (const detail::expression& v) { return v; } +template +inline detail::expression > operator - (const number& v) { return detail::expression >(v); } +template +inline detail::expression > operator - (const detail::expression& v) { return detail::expression >(v); } +template +inline detail::expression > operator ~ (const number& v) { return detail::expression >(v); } +template +inline detail::expression > operator ~ (const detail::expression& v) { return detail::expression >(v); } +// +// Then addition: +// +template +inline detail::expression, number > + operator + (const number& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline typename enable_if >, detail::expression, V > >::type + operator + (const number& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if >, detail::expression > >::type + operator + (const V& a, const number& b) +{ + return detail::expression >(a, b); +} +template +inline detail::expression, detail::expression > + operator + (const number& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline detail::expression, number > + operator + (const detail::expression& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline detail::expression, detail::expression > + operator + (const detail::expression& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression, V > >::type + operator + (const detail::expression& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression > >::type + operator + (const V& a, const detail::expression& b) +{ + return detail::expression >(a, b); +} +// +// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries: +// +template +inline detail::expression, typename detail::expression::left_type > + operator + (const number& a, const detail::expression& b) +{ + return detail::expression, typename detail::expression::left_type >(a, b.left_ref()); +} +template +inline detail::expression, typename detail::expression::left_type > + operator + (const detail::expression& a, const number& b) +{ + return detail::expression, typename detail::expression::left_type >(b, a.left_ref()); +} +template +inline detail::expression, number > + operator + (const number& a, const detail::expression >& b) +{ + return detail::expression, number >(a, b.left_ref()); +} +template +inline detail::expression, number > + operator + (const detail::expression >& a, const number& b) +{ + return detail::expression, number >(b, a.left_ref()); +} +template +inline typename enable_if >, detail::expression > >::type + operator + (const detail::expression >& a, const V& b) +{ + return detail::expression >(b, a.left_ref()); +} +template +inline typename enable_if, number >, detail::expression, number > >::type + operator + (const detail::expression >& a, const number& b) +{ + return detail::expression, number >(b, a.left_ref()); +} +template +inline typename enable_if, number >, detail::expression, number > >::type + operator + (const number& a, const detail::expression >& b) +{ + return detail::expression, number >(a, b.left_ref()); +} +template +inline detail::expression, number > > + operator + (const detail::expression >& a, const detail::expression >& b) +{ + return detail::expression, number > >(detail::expression, number >(a.left_ref(), b.left_ref())); +} +// +// Subtraction: +// +template +inline detail::expression, number > + operator - (const number& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline typename enable_if >, detail::expression, V > >::type + operator - (const number& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if >, detail::expression > >::type + operator - (const V& a, const number& b) +{ + return detail::expression >(a, b); +} +template +inline detail::expression, detail::expression > + operator - (const number& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline detail::expression, number > + operator - (const detail::expression& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline detail::expression, detail::expression > + operator - (const detail::expression& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression, V > >::type + operator - (const detail::expression& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression > >::type + operator - (const V& a, const detail::expression& b) +{ + return detail::expression >(a, b); +} +// +// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries: +// +template +inline detail::expression, typename detail::expression::left_type > + operator - (const number& a, const detail::expression& b) +{ + return detail::expression, typename detail::expression::left_type >(a, b.left_ref()); +} +template +inline detail::expression, typename detail::expression::left_type > > + operator - (const detail::expression& a, const number& b) +{ + return detail::expression, typename detail::expression::left_type > >( + detail::expression, typename detail::expression::left_type >(b, a.left_ref())); +} +template +inline detail::expression, number > + operator - (const number& a, const detail::expression >& b) +{ + return detail::expression, number >(a, b.left_ref()); +} +template +inline detail::expression, number > > + operator - (const detail::expression >& a, const number& b) +{ + return detail::expression, number > >( + detail::expression, number >(b, a.left_ref())); +} +template +inline typename enable_if >, detail::expression, V > > >::type + operator - (const detail::expression >& a, const V& b) +{ + return detail::expression, V > >(detail::expression, V >(a.left_ref(), b)); +} +template +inline typename enable_if, number >, detail::expression, number > > >::type + operator - (const detail::expression >& a, const number& b) +{ + return detail::expression, number > >(detail::expression, number >(a.left_ref(), b)); +} +template +inline typename enable_if >, detail::expression > >::type + operator - (const V& a, const detail::expression >& b) +{ + return detail::expression >(a, b.left_ref()); +} +template +inline typename enable_if, number >, detail::expression, number > >::type + operator - (const number& a, const detail::expression >& b) +{ + return detail::expression, number >(a, b.left_ref()); +} +// +// Multiplication: +// +template +inline detail::expression, number > + operator * (const number& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline typename enable_if >, detail::expression, V > >::type + operator * (const number& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if >, detail::expression > >::type + operator * (const V& a, const number& b) +{ + return detail::expression >(a, b); +} +template +inline detail::expression, detail::expression > + operator * (const number& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline detail::expression, number > + operator * (const detail::expression& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline detail::expression, detail::expression > + operator * (const detail::expression& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression, V > >::type + operator * (const detail::expression& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression > >::type + operator * (const V& a, const detail::expression& b) +{ + return detail::expression >(a, b); +} +// +// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries: +// +template +inline detail::expression, typename detail::expression::left_type > > + operator * (const number& a, const detail::expression& b) +{ + return detail::expression, typename detail::expression::left_type > >( + detail::expression, typename detail::expression::left_type > (a, b.left_ref())); +} +template +inline detail::expression, typename detail::expression::left_type > > + operator * (const detail::expression& a, const number& b) +{ + return detail::expression, typename detail::expression::left_type > >( + detail::expression, typename detail::expression::left_type >(b, a.left_ref())); +} +template +inline detail::expression, number > > + operator * (const number& a, const detail::expression >& b) +{ + return detail::expression, number > >( + detail::expression, number >(a, b.left_ref())); +} +template +inline detail::expression, number > > + operator * (const detail::expression >& a, const number& b) +{ + return detail::expression, number > >( + detail::expression, number >(b, a.left_ref())); +} +template +inline typename enable_if >, detail::expression, V > > >::type + operator * (const detail::expression >& a, const V& b) +{ + return detail::expression, V > > ( + detail::expression, V >(a.left_ref(), b)); +} +template +inline typename enable_if, number >, detail::expression, number > > >::type + operator * (const detail::expression >& a, const number& b) +{ + return detail::expression, number > > ( + detail::expression, number >(a.left_ref(), b)); +} +template +inline typename enable_if >, detail::expression, V > > >::type + operator * (const V& a, const detail::expression >& b) +{ + return detail::expression, V > >( + detail::expression, V >(b.left_ref(), a)); +} +template +inline typename enable_if, number >, detail::expression, number > > >::type + operator * (const number& a, const detail::expression >& b) +{ + return detail::expression, number > >( + detail::expression, number >(b.left_ref(), a)); +} +// +// Division: +// +template +inline detail::expression, number > + operator / (const number& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline typename enable_if >, detail::expression, V > >::type + operator / (const number& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if >, detail::expression > >::type + operator / (const V& a, const number& b) +{ + return detail::expression >(a, b); +} +template +inline detail::expression, detail::expression > + operator / (const number& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline detail::expression, number > + operator / (const detail::expression& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline detail::expression, detail::expression > + operator / (const detail::expression& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression, V > >::type + operator / (const detail::expression& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression > >::type + operator / (const V& a, const detail::expression& b) +{ + return detail::expression >(a, b); +} +// +// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries: +// +template +inline detail::expression, typename detail::expression::left_type > > + operator / (const number& a, const detail::expression& b) +{ + return detail::expression, typename detail::expression::left_type > >( + detail::expression, typename detail::expression::left_type >(a, b.left_ref())); +} +template +inline detail::expression::left_type, number > > + operator / (const detail::expression& a, const number& b) +{ + return detail::expression::left_type, number > >( + detail::expression::left_type, number >(a.left_ref(), b)); +} +template +inline detail::expression, number > > + operator / (const number& a, const detail::expression >& b) +{ + return detail::expression, number > >( + detail::expression, number >(a, b.left_ref())); +} +template +inline detail::expression, number > > + operator / (const detail::expression >& a, const number& b) +{ + return detail::expression, number > >( + detail::expression, number >(a.left_ref(), b)); +} +template +inline typename enable_if >, detail::expression, V > > >::type + operator / (const detail::expression >& a, const V& b) +{ + return detail::expression, V > >( + detail::expression, V>(a.left_ref(), b)); +} +template +inline typename enable_if, number >, detail::expression, number > > >::type + operator / (const detail::expression >& a, const number& b) +{ + return detail::expression, number > >( + detail::expression, number >(a.left_ref(), b)); +} +template +inline typename enable_if >, detail::expression > > >::type + operator / (const V& a, const detail::expression >& b) +{ + return detail::expression > >( + detail::expression >(a, b.left_ref())); +} +template +inline typename enable_if, number >, detail::expression, number > > >::type + operator / (const number& a, const detail::expression >& b) +{ + return detail::expression, number > >( + detail::expression, number >(a, b.left_ref())); +} +// +// Modulus: +// +template +inline detail::expression, number > + operator % (const number& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline typename enable_if >, detail::expression, V > >::type + operator % (const number& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if >, detail::expression > >::type + operator % (const V& a, const number& b) +{ + return detail::expression >(a, b); +} +template +inline detail::expression, detail::expression > + operator % (const number& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline detail::expression, number > + operator % (const detail::expression& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline detail::expression, detail::expression > + operator % (const detail::expression& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression, V > >::type + operator % (const detail::expression& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression > >::type + operator % (const V& a, const detail::expression& b) +{ + return detail::expression >(a, b); +} +// +// Left shift: +// +template +inline typename enable_if, detail::expression, I > >::type + operator << (const number& a, const I& b) +{ + return detail::expression, I>(a, b); +} +template +inline typename enable_if, detail::expression, I> >::type + operator << (const detail::expression& a, const I& b) +{ + return detail::expression, I>(a, b); +} +// +// Right shift: +// +template +inline typename enable_if, detail::expression, I > >::type + operator >> (const number& a, const I& b) +{ + return detail::expression, I>(a, b); +} +template +inline typename enable_if, detail::expression, I> >::type + operator >> (const detail::expression& a, const I& b) +{ + return detail::expression, I>(a, b); +} +// +// Bitwise AND: +// +template +inline detail::expression, number > + operator & (const number& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline typename enable_if >, detail::expression, V > >::type + operator & (const number& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if >, detail::expression > >::type + operator & (const V& a, const number& b) +{ + return detail::expression >(a, b); +} +template +inline detail::expression, detail::expression > + operator & (const number& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline detail::expression, number > + operator & (const detail::expression& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline detail::expression, detail::expression > + operator & (const detail::expression& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression, V > >::type + operator & (const detail::expression& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression > >::type + operator & (const V& a, const detail::expression& b) +{ + return detail::expression >(a, b); +} +// +// Bitwise OR: +// +template +inline detail::expression, number > + operator| (const number& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline typename enable_if >, detail::expression, V > >::type + operator| (const number& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if >, detail::expression > >::type + operator| (const V& a, const number& b) +{ + return detail::expression >(a, b); +} +template +inline detail::expression, detail::expression > + operator| (const number& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline detail::expression, number > + operator| (const detail::expression& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline detail::expression, detail::expression > + operator| (const detail::expression& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression, V > >::type + operator| (const detail::expression& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression > >::type + operator| (const V& a, const detail::expression& b) +{ + return detail::expression >(a, b); +} +// +// Bitwise XOR: +// +template +inline detail::expression, number > + operator^ (const number& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline typename enable_if >, detail::expression, V > >::type + operator^ (const number& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if >, detail::expression > >::type + operator^ (const V& a, const number& b) +{ + return detail::expression >(a, b); +} +template +inline detail::expression, detail::expression > + operator^ (const number& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline detail::expression, number > + operator^ (const detail::expression& a, const number& b) +{ + return detail::expression, number >(a, b); +} +template +inline detail::expression, detail::expression > + operator^ (const detail::expression& a, const detail::expression& b) +{ + return detail::expression, detail::expression >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression, V > >::type + operator^ (const detail::expression& a, const V& b) +{ + return detail::expression, V >(a, b); +} +template +inline typename enable_if::result_type>, detail::expression > >::type + operator^ (const V& a, const detail::expression& b) +{ + return detail::expression >(a, b); +} + +}} // namespaces + +#endif diff --git a/include/boost/multiprecision/detail/no_et_ops.hpp b/include/boost/multiprecision/detail/no_et_ops.hpp index 282f4fea..18728ea0 100644 --- a/include/boost/multiprecision/detail/no_et_ops.hpp +++ b/include/boost/multiprecision/detail/no_et_ops.hpp @@ -43,20 +43,18 @@ template inline typename enable_if >, number >::type operator + (const number& a, const V& b) { - typedef typename detail::canonical::type canonical_type; number result; using default_ops::eval_add; - eval_add(result.backend(), a.backend(), static_cast(b)); + eval_add(result.backend(), a.backend(), number::canonical_value(b)); return BOOST_MP_MOVE(result); } template inline typename enable_if >, number >::type operator + (const V& a, const number& b) { - typedef typename detail::canonical::type canonical_type; number result; using default_ops::eval_add; - eval_add(result.backend(), b.backend(), static_cast(a)); + eval_add(result.backend(), b.backend(), number::canonical_value(a)); return BOOST_MP_MOVE(result); } // @@ -74,20 +72,18 @@ template inline typename enable_if >, number >::type operator - (const number& a, const V& b) { - typedef typename detail::canonical::type canonical_type; number result; using default_ops::eval_subtract; - eval_subtract(result.backend(), a.backend(), static_cast(b)); + eval_subtract(result.backend(), a.backend(), number::canonical_value(b)); return BOOST_MP_MOVE(result); } template inline typename enable_if >, number >::type operator - (const V& a, const number& b) { - typedef typename detail::canonical::type canonical_type; number result; using default_ops::eval_subtract; - eval_subtract(result.backend(), static_cast(a), b.backend()); + eval_subtract(result.backend(), number::canonical_value(a), b.backend()); return BOOST_MP_MOVE(result); } // @@ -105,20 +101,18 @@ template inline typename enable_if >, number >::type operator * (const number& a, const V& b) { - typedef typename detail::canonical::type canonical_type; number result; using default_ops::eval_multiply; - eval_multiply(result.backend(), a.backend(), static_cast(b)); + eval_multiply(result.backend(), a.backend(), number::canonical_value(b)); return BOOST_MP_MOVE(result); } template inline typename enable_if >, number >::type operator * (const V& a, const number& b) { - typedef typename detail::canonical::type canonical_type; number result; using default_ops::eval_multiply; - eval_multiply(result.backend(), b.backend(), static_cast(a)); + eval_multiply(result.backend(), b.backend(), number::canonical_value(a)); return BOOST_MP_MOVE(result); } // @@ -136,20 +130,18 @@ template inline typename enable_if >, number >::type operator / (const number& a, const V& b) { - typedef typename detail::canonical::type canonical_type; number result; using default_ops::eval_divide; - eval_divide(result.backend(), a.backend(), static_cast(b)); + eval_divide(result.backend(), a.backend(), number::canonical_value(b)); return BOOST_MP_MOVE(result); } template inline typename enable_if >, number >::type operator / (const V& a, const number& b) { - typedef typename detail::canonical::type canonical_type; number result; using default_ops::eval_divide; - eval_divide(result.backend(), static_cast(a), b.backend()); + eval_divide(result.backend(), number::canonical_value(a), b.backend()); return BOOST_MP_MOVE(result); } // @@ -167,20 +159,18 @@ template inline typename enable_if >, number >::type operator % (const number& a, const V& b) { - typedef typename detail::canonical::type canonical_type; number result; using default_ops::eval_modulus; - eval_modulus(result.backend(), a.backend(), static_cast(b)); + eval_modulus(result.backend(), a.backend(), number::canonical_value(b)); return BOOST_MP_MOVE(result); } template inline typename enable_if >, number >::type operator % (const V& a, const number& b) { - typedef typename detail::canonical::type canonical_type; number result; using default_ops::eval_modulus; - eval_modulus(result.backend(), static_cast(a), b.backend()); + eval_modulus(result.backend(), number::canonical_value(a), b.backend()); return BOOST_MP_MOVE(result); } // @@ -198,20 +188,18 @@ template inline typename enable_if >, number >::type operator | (const number& a, const V& b) { - typedef typename detail::canonical::type canonical_type; number result; using default_ops::eval_bitwise_or; - eval_bitwise_or(result.backend(), a.backend(), static_cast(b)); + eval_bitwise_or(result.backend(), a.backend(), number::canonical_value(b)); return BOOST_MP_MOVE(result); } template inline typename enable_if >, number >::type operator | (const V& a, const number& b) { - typedef typename detail::canonical::type canonical_type; number result; using default_ops::eval_bitwise_or; - eval_bitwise_or(result.backend(), b.backend(), static_cast(a)); + eval_bitwise_or(result.backend(), b.backend(), number::canonical_value(a)); return BOOST_MP_MOVE(result); } // @@ -229,20 +217,18 @@ template inline typename enable_if >, number >::type operator ^ (const number& a, const V& b) { - typedef typename detail::canonical::type canonical_type; number result; using default_ops::eval_bitwise_xor; - eval_bitwise_xor(result.backend(), a.backend(), static_cast(b)); + eval_bitwise_xor(result.backend(), a.backend(), number::canonical_value(b)); return BOOST_MP_MOVE(result); } template inline typename enable_if >, number >::type operator ^ (const V& a, const number& b) { - typedef typename detail::canonical::type canonical_type; number result; using default_ops::eval_bitwise_xor; - eval_bitwise_xor(result.backend(), b.backend(), static_cast(a)); + eval_bitwise_xor(result.backend(), b.backend(), number::canonical_value(a)); return BOOST_MP_MOVE(result); } // @@ -260,20 +246,18 @@ template inline typename enable_if >, number >::type operator & (const number& a, const V& b) { - typedef typename detail::canonical::type canonical_type; number result; using default_ops::eval_bitwise_and; - eval_bitwise_and(result.backend(), a.backend(), static_cast(b)); + eval_bitwise_and(result.backend(), a.backend(), number::canonical_value(b)); return BOOST_MP_MOVE(result); } template inline typename enable_if >, number >::type operator & (const V& a, const number& b) { - typedef typename detail::canonical::type canonical_type; number result; using default_ops::eval_bitwise_and; - eval_bitwise_and(result.backend(), b.backend(), static_cast(a)); + eval_bitwise_and(result.backend(), b.backend(), number::canonical_value(a)); return BOOST_MP_MOVE(result); } // @@ -352,18 +336,16 @@ template inline typename enable_if >, number >::type operator + (number&& a, const V& b) { - typedef typename detail::canonical::type canonical_type; using default_ops::eval_add; - eval_add(a.backend(), static_cast(b)); + eval_add(a.backend(), number::canonical_value(b)); return static_cast&&>(a); } template inline typename enable_if >, number >::type operator + (const V& a, number&& b) { - typedef typename detail::canonical::type canonical_type; using default_ops::eval_add; - eval_add(b.backend(), static_cast(a)); + eval_add(b.backend(), number::canonical_value(a)); return static_cast&&>(b); } // @@ -395,18 +377,16 @@ template inline typename enable_if >, number >::type operator - (number&& a, const V& b) { - typedef typename detail::canonical::type canonical_type; using default_ops::eval_subtract; - eval_subtract(a.backend(), static_cast(b)); + eval_subtract(a.backend(), number::canonical_value(b)); return static_cast&&>(a); } template inline typename enable_if >, number >::type operator - (const V& a, number&& b) { - typedef typename detail::canonical::type canonical_type; using default_ops::eval_subtract; - eval_subtract(b.backend(), static_cast(a)); + eval_subtract(b.backend(), number::canonical_value(a)); b.backend().negate(); return static_cast&&>(b); } @@ -438,18 +418,16 @@ template inline typename enable_if >, number >::type operator * (number&& a, const V& b) { - typedef typename detail::canonical::type canonical_type; using default_ops::eval_multiply; - eval_multiply(a.backend(), static_cast(b)); + eval_multiply(a.backend(), number::canonical_value(b)); return static_cast&&>(a); } template inline typename enable_if >, number >::type operator * (const V& a, number&& b) { - typedef typename detail::canonical::type canonical_type; using default_ops::eval_multiply; - eval_multiply(b.backend(), static_cast(a)); + eval_multiply(b.backend(), number::canonical_value(a)); return static_cast&&>(b); } // @@ -466,9 +444,8 @@ template inline typename enable_if >, number >::type operator / (number&& a, const V& b) { - typedef typename detail::canonical::type canonical_type; using default_ops::eval_divide; - eval_divide(a.backend(), static_cast(b)); + eval_divide(a.backend(), number::canonical_value(b)); return static_cast&&>(a); } // @@ -485,9 +462,8 @@ template inline typename enable_if >, number >::type operator % (number&& a, const V& b) { - typedef typename detail::canonical::type canonical_type; using default_ops::eval_modulus; - eval_modulus(a.backend(), static_cast(b)); + eval_modulus(a.backend(), number::canonical_value(b)); return static_cast&&>(a); } // @@ -518,18 +494,16 @@ template inline typename enable_if >, number >::type operator | (number&& a, const V& b) { - typedef typename detail::canonical::type canonical_type; using default_ops::eval_bitwise_or; - eval_bitwise_or(a.backend(), static_cast(b)); + eval_bitwise_or(a.backend(), number::canonical_value(b)); return static_cast&&>(a); } template inline typename enable_if >, number >::type operator | (const V& a, number&& b) { - typedef typename detail::canonical::type canonical_type; using default_ops::eval_bitwise_or; - eval_bitwise_or(b.backend(), static_cast(a)); + eval_bitwise_or(b.backend(), number::canonical_value(a)); return static_cast&&>(b); } // @@ -560,18 +534,16 @@ template inline typename enable_if >, number >::type operator ^ (number&& a, const V& b) { - typedef typename detail::canonical::type canonical_type; using default_ops::eval_bitwise_xor; - eval_bitwise_xor(a.backend(), static_cast(b)); + eval_bitwise_xor(a.backend(), number::canonical_value(b)); return static_cast&&>(a); } template inline typename enable_if >, number >::type operator ^ (const V& a, number&& b) { - typedef typename detail::canonical::type canonical_type; using default_ops::eval_bitwise_xor; - eval_bitwise_xor(b.backend(), static_cast(a)); + eval_bitwise_xor(b.backend(), number::canonical_value(a)); return static_cast&&>(b); } // @@ -602,18 +574,16 @@ template inline typename enable_if >, number >::type operator & (number&& a, const V& b) { - typedef typename detail::canonical::type canonical_type; using default_ops::eval_bitwise_and; - eval_bitwise_and(a.backend(), static_cast(b)); + eval_bitwise_and(a.backend(), number::canonical_value(b)); return static_cast&&>(a); } template inline typename enable_if >, number >::type operator & (const V& a, number&& b) { - typedef typename detail::canonical::type canonical_type; using default_ops::eval_bitwise_and; - eval_bitwise_and(b.backend(), static_cast(a)); + eval_bitwise_and(b.backend(), number::canonical_value(a)); return static_cast&&>(b); } // diff --git a/include/boost/multiprecision/detail/number_base.hpp b/include/boost/multiprecision/detail/number_base.hpp index e5b46e6e..8721991c 100644 --- a/include/boost/multiprecision/detail/number_base.hpp +++ b/include/boost/multiprecision/detail/number_base.hpp @@ -41,7 +41,7 @@ template struct is_compatible_arithmetic_type : public mpl::bool_< is_convertible::value - && !is_number::value + && !is_same::value && !is_number_expression::value> {}; @@ -221,6 +221,16 @@ struct combine_expression, number type; }; +template +struct combine_expression, number > +{ + typedef typename mpl::if_c< + is_convertible, number >::value, + number, + number + >::type type; +}; + template struct arg_type { @@ -619,638 +629,6 @@ void check_shift_range(V, const mpl::false_&, const mpl::false_&) BOOST_NOEXCEPT } // namespace detail -// -// Non-member operators for number: -// -// Unary operators first: -// -template -inline const number& operator + (const number& v) { return v; } -template -inline const detail::expression& operator + (const detail::expression& v) { return v; } -template -inline detail::expression > operator - (const number& v) { return detail::expression >(v); } -template -inline detail::expression > operator - (const detail::expression& v) { return detail::expression >(v); } -template -inline detail::expression > operator ~ (const number& v) { return detail::expression >(v); } -template -inline detail::expression > operator ~ (const detail::expression& v) { return detail::expression >(v); } -// -// Then addition: -// -template -inline detail::expression, number > - operator + (const number& a, const number& b) -{ - return detail::expression, number >(a, b); -} -template -inline typename enable_if >, detail::expression, V > >::type - operator + (const number& a, const V& b) -{ - return detail::expression, V >(a, b); -} -template -inline typename enable_if >, detail::expression > >::type - operator + (const V& a, const number& b) -{ - return detail::expression >(a, b); -} -template -inline detail::expression, detail::expression > - operator + (const number& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); -} -template -inline detail::expression, number > - operator + (const detail::expression& a, const number& b) -{ - return detail::expression, number >(a, b); -} -template -inline detail::expression, detail::expression > - operator + (const detail::expression& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); -} -template -inline typename enable_if::result_type>, detail::expression, V > >::type - operator + (const detail::expression& a, const V& b) -{ - return detail::expression, V >(a, b); -} -template -inline typename enable_if::result_type>, detail::expression > >::type - operator + (const V& a, const detail::expression& b) -{ - return detail::expression >(a, b); -} -// -// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries: -// -template -inline detail::expression, typename detail::expression::left_type > - operator + (const number& a, const detail::expression& b) -{ - return detail::expression, typename detail::expression::left_type >(a, b.left_ref()); -} -template -inline detail::expression, typename detail::expression::left_type > - operator + (const detail::expression& a, const number& b) -{ - return detail::expression, typename detail::expression::left_type >(b, a.left_ref()); -} -template -inline detail::expression, number > - operator + (const number& a, const detail::expression >& b) -{ - return detail::expression, number >(a, b.left_ref()); -} -template -inline detail::expression, number > - operator + (const detail::expression >& a, const number& b) -{ - return detail::expression, number >(b, a.left_ref()); -} -template -inline typename enable_if >, detail::expression > >::type - operator + (const detail::expression >& a, const V& b) -{ - return detail::expression >(b, a.left_ref()); -} -template -inline typename enable_if >, detail::expression > >::type - operator + (const V& a, const detail::expression >& b) -{ - return detail::expression >(a, b.left_ref()); -} -template -inline detail::expression, number > > - operator + (const detail::expression >& a, const detail::expression >& b) -{ - return detail::expression, number > >(detail::expression, number >(a.left_ref(), b.left_ref())); -} -// -// Subtraction: -// -template -inline detail::expression, number > - operator - (const number& a, const number& b) -{ - return detail::expression, number >(a, b); -} -template -inline typename enable_if >, detail::expression, V > >::type - operator - (const number& a, const V& b) -{ - return detail::expression, V >(a, b); -} -template -inline typename enable_if >, detail::expression > >::type - operator - (const V& a, const number& b) -{ - return detail::expression >(a, b); -} -template -inline detail::expression, detail::expression > - operator - (const number& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); -} -template -inline detail::expression, number > - operator - (const detail::expression& a, const number& b) -{ - return detail::expression, number >(a, b); -} -template -inline detail::expression, detail::expression > - operator - (const detail::expression& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); -} -template -inline typename enable_if::result_type>, detail::expression, V > >::type - operator - (const detail::expression& a, const V& b) -{ - return detail::expression, V >(a, b); -} -template -inline typename enable_if::result_type>, detail::expression > >::type - operator - (const V& a, const detail::expression& b) -{ - return detail::expression >(a, b); -} -// -// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries: -// -template -inline detail::expression, typename detail::expression::left_type > - operator - (const number& a, const detail::expression& b) -{ - return detail::expression, typename detail::expression::left_type >(a, b.left_ref()); -} -template -inline detail::expression, typename detail::expression::left_type > > - operator - (const detail::expression& a, const number& b) -{ - return detail::expression, typename detail::expression::left_type > >( - detail::expression, typename detail::expression::left_type >(b, a.left_ref())); -} -template -inline detail::expression, number > - operator - (const number& a, const detail::expression >& b) -{ - return detail::expression, number >(a, b.left_ref()); -} -template -inline detail::expression, number > > - operator - (const detail::expression >& a, const number& b) -{ - return detail::expression, number > >( - detail::expression, number >(b, a.left_ref())); -} -template -inline typename enable_if >, detail::expression, V > > >::type - operator - (const detail::expression >& a, const V& b) -{ - return detail::expression, V > >(detail::expression, V >(a.left_ref(), b)); -} -template -inline typename enable_if >, detail::expression > >::type - operator - (const V& a, const detail::expression >& b) -{ - return detail::expression >(a, b.left_ref()); -} -// -// Multiplication: -// -template -inline detail::expression, number > - operator * (const number& a, const number& b) -{ - return detail::expression, number >(a, b); -} -template -inline typename enable_if >, detail::expression, V > >::type - operator * (const number& a, const V& b) -{ - return detail::expression, V >(a, b); -} -template -inline typename enable_if >, detail::expression > >::type - operator * (const V& a, const number& b) -{ - return detail::expression >(a, b); -} -template -inline detail::expression, detail::expression > - operator * (const number& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); -} -template -inline detail::expression, number > - operator * (const detail::expression& a, const number& b) -{ - return detail::expression, number >(a, b); -} -template -inline detail::expression, detail::expression > - operator * (const detail::expression& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); -} -template -inline typename enable_if::result_type>, detail::expression, V > >::type - operator * (const detail::expression& a, const V& b) -{ - return detail::expression, V >(a, b); -} -template -inline typename enable_if::result_type>, detail::expression > >::type - operator * (const V& a, const detail::expression& b) -{ - return detail::expression >(a, b); -} -// -// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries: -// -template -inline detail::expression, typename detail::expression::left_type > > - operator * (const number& a, const detail::expression& b) -{ - return detail::expression, typename detail::expression::left_type > >( - detail::expression, typename detail::expression::left_type > (a, b.left_ref())); -} -template -inline detail::expression, typename detail::expression::left_type > > - operator * (const detail::expression& a, const number& b) -{ - return detail::expression, typename detail::expression::left_type > >( - detail::expression, typename detail::expression::left_type >(b, a.left_ref())); -} -template -inline detail::expression, number > > - operator * (const number& a, const detail::expression >& b) -{ - return detail::expression, number > >( - detail::expression, number >(a, b.left_ref())); -} -template -inline detail::expression, number > > - operator * (const detail::expression >& a, const number& b) -{ - return detail::expression, number > >( - detail::expression, number >(b, a.left_ref())); -} -template -inline typename enable_if >, detail::expression, V > > >::type - operator * (const detail::expression >& a, const V& b) -{ - return detail::expression, V > > ( - detail::expression, V >(a.left_ref(), b)); -} -template -inline typename enable_if >, detail::expression, V > > >::type - operator * (const V& a, const detail::expression >& b) -{ - return detail::expression, V > >( - detail::expression, V >(b.left_ref(), a)); -} -// -// Division: -// -template -inline detail::expression, number > - operator / (const number& a, const number& b) -{ - return detail::expression, number >(a, b); -} -template -inline typename enable_if >, detail::expression, V > >::type - operator / (const number& a, const V& b) -{ - return detail::expression, V >(a, b); -} -template -inline typename enable_if >, detail::expression > >::type - operator / (const V& a, const number& b) -{ - return detail::expression >(a, b); -} -template -inline detail::expression, detail::expression > - operator / (const number& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); -} -template -inline detail::expression, number > - operator / (const detail::expression& a, const number& b) -{ - return detail::expression, number >(a, b); -} -template -inline detail::expression, detail::expression > - operator / (const detail::expression& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); -} -template -inline typename enable_if::result_type>, detail::expression, V > >::type - operator / (const detail::expression& a, const V& b) -{ - return detail::expression, V >(a, b); -} -template -inline typename enable_if::result_type>, detail::expression > >::type - operator / (const V& a, const detail::expression& b) -{ - return detail::expression >(a, b); -} -// -// Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries: -// -template -inline detail::expression, typename detail::expression::left_type > > - operator / (const number& a, const detail::expression& b) -{ - return detail::expression, typename detail::expression::left_type > >( - detail::expression, typename detail::expression::left_type >(a, b.left_ref())); -} -template -inline detail::expression::left_type, number > > - operator / (const detail::expression& a, const number& b) -{ - return detail::expression::left_type, number > >( - detail::expression::left_type, number >(a.left_ref(), b)); -} -template -inline detail::expression, number > > - operator / (const number& a, const detail::expression >& b) -{ - return detail::expression, number > >( - detail::expression, number >(a, b.left_ref())); -} -template -inline detail::expression, number > > - operator / (const detail::expression >& a, const number& b) -{ - return detail::expression, number > >( - detail::expression, number >(a.left_ref(), b)); -} -template -inline typename enable_if >, detail::expression, V > > >::type - operator / (const detail::expression >& a, const V& b) -{ - return detail::expression, V > >( - detail::expression, V>(a.left_ref(), b)); -} -template -inline typename enable_if >, detail::expression > > >::type - operator / (const V& a, const detail::expression >& b) -{ - return detail::expression > >( - detail::expression >(a, b.left_ref())); -} -// -// Modulus: -// -template -inline detail::expression, number > - operator % (const number& a, const number& b) -{ - return detail::expression, number >(a, b); -} -template -inline typename enable_if >, detail::expression, V > >::type - operator % (const number& a, const V& b) -{ - return detail::expression, V >(a, b); -} -template -inline typename enable_if >, detail::expression > >::type - operator % (const V& a, const number& b) -{ - return detail::expression >(a, b); -} -template -inline detail::expression, detail::expression > - operator % (const number& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); -} -template -inline detail::expression, number > - operator % (const detail::expression& a, const number& b) -{ - return detail::expression, number >(a, b); -} -template -inline detail::expression, detail::expression > - operator % (const detail::expression& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); -} -template -inline typename enable_if::result_type>, detail::expression, V > >::type - operator % (const detail::expression& a, const V& b) -{ - return detail::expression, V >(a, b); -} -template -inline typename enable_if::result_type>, detail::expression > >::type - operator % (const V& a, const detail::expression& b) -{ - return detail::expression >(a, b); -} -// -// Left shift: -// -template -inline typename enable_if, detail::expression, I > >::type - operator << (const number& a, const I& b) -{ - return detail::expression, I>(a, b); -} -template -inline typename enable_if, detail::expression, I> >::type - operator << (const detail::expression& a, const I& b) -{ - return detail::expression, I>(a, b); -} -// -// Right shift: -// -template -inline typename enable_if, detail::expression, I > >::type - operator >> (const number& a, const I& b) -{ - return detail::expression, I>(a, b); -} -template -inline typename enable_if, detail::expression, I> >::type - operator >> (const detail::expression& a, const I& b) -{ - return detail::expression, I>(a, b); -} -// -// Bitwise AND: -// -template -inline detail::expression, number > - operator & (const number& a, const number& b) -{ - return detail::expression, number >(a, b); -} -template -inline typename enable_if >, detail::expression, V > >::type - operator & (const number& a, const V& b) -{ - return detail::expression, V >(a, b); -} -template -inline typename enable_if >, detail::expression > >::type - operator & (const V& a, const number& b) -{ - return detail::expression >(a, b); -} -template -inline detail::expression, detail::expression > - operator & (const number& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); -} -template -inline detail::expression, number > - operator & (const detail::expression& a, const number& b) -{ - return detail::expression, number >(a, b); -} -template -inline detail::expression, detail::expression > - operator & (const detail::expression& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); -} -template -inline typename enable_if::result_type>, detail::expression, V > >::type - operator & (const detail::expression& a, const V& b) -{ - return detail::expression, V >(a, b); -} -template -inline typename enable_if::result_type>, detail::expression > >::type - operator & (const V& a, const detail::expression& b) -{ - return detail::expression >(a, b); -} -// -// Bitwise OR: -// -template -inline detail::expression, number > - operator| (const number& a, const number& b) -{ - return detail::expression, number >(a, b); -} -template -inline typename enable_if >, detail::expression, V > >::type - operator| (const number& a, const V& b) -{ - return detail::expression, V >(a, b); -} -template -inline typename enable_if >, detail::expression > >::type - operator| (const V& a, const number& b) -{ - return detail::expression >(a, b); -} -template -inline detail::expression, detail::expression > - operator| (const number& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); -} -template -inline detail::expression, number > - operator| (const detail::expression& a, const number& b) -{ - return detail::expression, number >(a, b); -} -template -inline detail::expression, detail::expression > - operator| (const detail::expression& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); -} -template -inline typename enable_if::result_type>, detail::expression, V > >::type - operator| (const detail::expression& a, const V& b) -{ - return detail::expression, V >(a, b); -} -template -inline typename enable_if::result_type>, detail::expression > >::type - operator| (const V& a, const detail::expression& b) -{ - return detail::expression >(a, b); -} -// -// Bitwise XOR: -// -template -inline detail::expression, number > - operator^ (const number& a, const number& b) -{ - return detail::expression, number >(a, b); -} -template -inline typename enable_if >, detail::expression, V > >::type - operator^ (const number& a, const V& b) -{ - return detail::expression, V >(a, b); -} -template -inline typename enable_if >, detail::expression > >::type - operator^ (const V& a, const number& b) -{ - return detail::expression >(a, b); -} -template -inline detail::expression, detail::expression > - operator^ (const number& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); -} -template -inline detail::expression, number > - operator^ (const detail::expression& a, const number& b) -{ - return detail::expression, number >(a, b); -} -template -inline detail::expression, detail::expression > - operator^ (const detail::expression& a, const detail::expression& b) -{ - return detail::expression, detail::expression >(a, b); -} -template -inline typename enable_if::result_type>, detail::expression, V > >::type - operator^ (const detail::expression& a, const V& b) -{ - return detail::expression, V >(a, b); -} -template -inline typename enable_if::result_type>, detail::expression > >::type - operator^ (const V& a, const detail::expression& b) -{ - return detail::expression >(a, b); -} - // // Traits class, lets us know what kind of number we have, defaults to a floating point type: // diff --git a/include/boost/multiprecision/detail/number_compare.hpp b/include/boost/multiprecision/detail/number_compare.hpp index 1450508f..afeabbb3 100644 --- a/include/boost/multiprecision/detail/number_compare.hpp +++ b/include/boost/multiprecision/detail/number_compare.hpp @@ -19,14 +19,21 @@ inline bool eval_eq(const B& a, const B& b) { return a.compare(b) == 0; } +// +// For the default version which compares to some arbitrary type convertible to +// our number type, we don't know what value the ExpressionTemplates parameter to +// class number should be. We generally prefer ExpressionTemplates to be enabled +// in case type A is itself an expression template, but we need to test both options +// with is_convertible in case A has an implicit conversion operator to number. +// This is the case with many uBlas types for example. +// template inline bool eval_eq(const B& a, const A& b) { - typedef typename mpl::if_< - is_convertible >, - number, - number - >::type mp_type; + typedef typename mpl::if_c< + is_convertible >::value, + number, + number >::type mp_type; mp_type t(b); return eval_eq(a, t.backend()); } @@ -39,11 +46,10 @@ inline bool eval_lt(const B& a, const B& b) template inline bool eval_lt(const B& a, const A& b) { - typedef typename mpl::if_< - is_convertible >, - number, - number - >::type mp_type; + typedef typename mpl::if_c< + is_convertible >::value, + number, + number >::type mp_type; mp_type t(b); return eval_lt(a, t.backend()); } @@ -56,15 +62,38 @@ inline bool eval_gt(const B& a, const B& b) template inline bool eval_gt(const B& a, const A& b) { - typedef typename mpl::if_< - is_convertible >, - number, - number - >::type mp_type; + typedef typename mpl::if_c< + is_convertible >::value, + number, + number >::type mp_type; mp_type t(b); return eval_gt(a, t.backend()); } +} // namespace default_ops + +namespace detail{ + +template +struct is_valid_mixed_compare : public mpl::false_ {}; + +template +struct is_valid_mixed_compare, Val> : public is_convertible> {}; +/* +template +struct is_valid_mixed_compare > : public is_convertible> {}; +*/ +template +struct is_valid_mixed_compare, number > : public mpl::false_ {}; + +template +struct is_valid_mixed_compare, expression > + : public mpl::bool_, number >::value> {}; + +template +struct is_valid_mixed_compare, number > + : public mpl::bool_, number >::value> {}; + } template @@ -74,13 +103,13 @@ inline bool operator == (const number& a, const nu return eval_eq(a.backend(), b.backend()); } template -inline typename enable_if_c<(is_convertible >::value && !is_number_expression::value && !is_number::value), bool>::type +inline typename enable_if_c, Arithmetic>::value, bool>::type operator == (const number& a, const Arithmetic& b) { - typedef typename detail::canonical::type ct; using default_ops::eval_eq; - return eval_eq(a.backend(), ct(b)); + return eval_eq(a.backend(), number::canonical_value(b)); } +/* template inline typename enable_if, typename detail::expression::result_type>, bool>::type operator == (const number& a, const detail::expression& b) @@ -89,24 +118,24 @@ inline typename enable_if, typename typename detail::expression::result_type t(b); return eval_eq(a.backend(), t.backend()); } +*/ template -inline typename enable_if_c<(is_convertible >::value && !is_number_expression::value && !is_number::value), bool>::type +inline typename enable_if_c, Arithmetic>::value, bool>::type operator == (const Arithmetic& a, const number& b) { - typedef typename detail::canonical::type ct; using default_ops::eval_eq; - return eval_eq(b.backend(), ct(a)); + return eval_eq(b.backend(), number::canonical_value(a)); } template -inline typename enable_if_c<(is_convertible::result_type>::value && !is_number_expression::value && !is_number::value), bool>::type +inline typename enable_if_c::result_type, Arithmetic>::value, bool>::type operator == (const Arithmetic& a, const detail::expression& b) { typedef typename detail::expression::result_type result_type; - typedef typename detail::canonical::type ct; using default_ops::eval_eq; result_type t(b); - return eval_eq(t.backend(), ct(a)); + return eval_eq(t.backend(), result_type::canonical_value(a)); } +/* template inline typename enable_if, typename detail::expression::result_type>, bool>::type operator == (const detail::expression& a, const number& b) @@ -114,16 +143,15 @@ inline typename enable_if, typename using default_ops::eval_eq; typename detail::expression::result_type t(a); return eval_eq(t.backend(), b.backend()); -} +}*/ template -inline typename enable_if_c<(is_convertible::result_type>::value && !is_number_expression::value && !is_number::value), bool>::type +inline typename enable_if_c::result_type, Arithmetic>::value, bool>::type operator == (const detail::expression& a, const Arithmetic& b) { typedef typename detail::expression::result_type result_type; - typedef typename detail::canonical::type ct; using default_ops::eval_eq; result_type t(a); - return eval_eq(t.backend(), ct(b)); + return eval_eq(t.backend(), result_type::canonical_value(b)); } template inline typename enable_if::result_type, typename detail::expression::result_type>, bool>::type @@ -142,13 +170,13 @@ inline bool operator != (const number& a, const nu return !eval_eq(a.backend(), b.backend()); } template -inline typename enable_if_c<(is_convertible >::value && !is_number_expression::value && !is_number::value), bool>::type +inline typename enable_if_c, Arithmetic>::value, bool>::type operator != (const number& a, const Arithmetic& b) { - typedef typename detail::canonical::type ct; using default_ops::eval_eq; - return !eval_eq(a.backend(), ct(b)); + return !eval_eq(a.backend(), number::canonical_value(b)); } +/* template inline typename enable_if, typename detail::expression::result_type>, bool>::type operator != (const number& a, const detail::expression& b) @@ -157,24 +185,24 @@ inline typename enable_if, typename typename detail::expression::result_type t(b); return !eval_eq(a.backend(), t.backend()); } +*/ template -inline typename enable_if_c<(is_convertible >::value && !is_number_expression::value && !is_number::value), bool>::type +inline typename enable_if_c, Arithmetic>::value, bool>::type operator != (const Arithmetic& a, const number& b) { - typedef typename detail::canonical::type ct; using default_ops::eval_eq; - return !eval_eq(b.backend(), ct(a)); + return !eval_eq(b.backend(), number::canonical_value(a)); } template -inline typename enable_if_c<(is_convertible::result_type>::value && !is_number_expression::value && !is_number::value), bool>::type +inline typename enable_if_c::result_type, Arithmetic>::value, bool>::type operator != (const Arithmetic& a, const detail::expression& b) { typedef typename detail::expression::result_type result_type; - typedef typename detail::canonical::type ct; using default_ops::eval_eq; result_type t(b); - return !eval_eq(t.backend(), ct(a)); + return !eval_eq(t.backend(), result_type::canonical_value(a)); } +/* template inline typename enable_if, typename detail::expression::result_type>, bool>::type operator != (const detail::expression& a, const number& b) @@ -182,16 +210,15 @@ inline typename enable_if, typename using default_ops::eval_eq; typename detail::expression::result_type t(a); return !eval_eq(t.backend(), b.backend()); -} +}*/ template -inline typename enable_if_c<(is_convertible::result_type>::value && !is_number_expression::value && !is_number::value), bool>::type +inline typename enable_if_c::result_type, Arithmetic>::value, bool>::type operator != (const detail::expression& a, const Arithmetic& b) { typedef typename detail::expression::result_type result_type; - typedef typename detail::canonical::type ct; using default_ops::eval_eq; result_type t(a); - return !eval_eq(t.backend(), ct(b)); + return !eval_eq(t.backend(), result_type::canonical_value(b)); } template inline typename enable_if::result_type, typename detail::expression::result_type>, bool>::type @@ -210,13 +237,13 @@ inline bool operator < (const number& a, const num return eval_lt(a.backend(), b.backend()); } template -inline typename enable_if_c<(is_convertible >::value && !is_number_expression::value && !is_number::value), bool>::type +inline typename enable_if_c, Arithmetic>::value, bool>::type operator < (const number& a, const Arithmetic& b) { - typedef typename detail::canonical::type ct; using default_ops::eval_lt; - return eval_lt(a.backend(), ct(b)); + return eval_lt(a.backend(), number::canonical_value(b)); } +/* template inline typename enable_if, typename detail::expression::result_type>, bool>::type operator < (const number& a, const detail::expression& b) @@ -225,24 +252,24 @@ inline typename enable_if, typename typename detail::expression::result_type t(b); return eval_lt(a.backend(), t.backend()); } +*/ template -inline typename enable_if_c<(is_convertible >::value && !is_number_expression::value && !is_number::value), bool>::type +inline typename enable_if_c, Arithmetic>::value, bool>::type operator < (const Arithmetic& a, const number& b) { - typedef typename detail::canonical::type ct; using default_ops::eval_gt; - return eval_gt(b.backend(), ct(a)); + return eval_gt(b.backend(), number::canonical_value(a)); } template -inline typename enable_if_c<(is_convertible::result_type>::value && !is_number_expression::value && !is_number::value), bool>::type +inline typename enable_if_c::result_type, Arithmetic>::value, bool>::type operator < (const Arithmetic& a, const detail::expression& b) { typedef typename detail::expression::result_type result_type; - typedef typename detail::canonical::type ct; using default_ops::eval_gt; result_type t(b); - return eval_gt(t.backend(), ct(a)); + return eval_gt(t.backend(), result_type::canonical_value(a)); } +/* template inline typename enable_if, typename detail::expression::result_type>, bool>::type operator < (const detail::expression& a, const number& b) @@ -251,15 +278,15 @@ inline typename enable_if, typename typename detail::expression::result_type t(a); return eval_lt(t.backend(), b.backend()); } +*/ template -inline typename enable_if_c<(is_convertible::result_type>::value && !is_number_expression::value && !is_number::value), bool>::type +inline typename enable_if_c::result_type, Arithmetic>::value, bool>::type operator < (const detail::expression& a, const Arithmetic& b) { typedef typename detail::expression::result_type result_type; - typedef typename detail::canonical::type ct; using default_ops::eval_lt; result_type t(a); - return eval_lt(t.backend(), ct(b)); + return eval_lt(t.backend(), result_type::canonical_value(b)); } template inline typename enable_if::result_type, typename detail::expression::result_type>, bool>::type @@ -278,13 +305,13 @@ inline bool operator > (const number& a, const num return eval_gt(a.backend(), b.backend()); } template -inline typename enable_if_c<(is_convertible >::value && !is_number_expression::value && !is_number::value), bool>::type +inline typename enable_if_c, Arithmetic>::value, bool>::type operator > (const number& a, const Arithmetic& b) { - typedef typename detail::canonical::type ct; using default_ops::eval_gt; - return eval_gt(a.backend(), ct(b)); + return eval_gt(a.backend(), number::canonical_value(b)); } +/* template inline typename enable_if, typename detail::expression::result_type>, bool>::type operator > (const number& a, const detail::expression& b) @@ -293,24 +320,24 @@ inline typename enable_if, typename typename detail::expression::result_type t(b); return eval_gt(a.backend(), t.backend()); } +*/ template -inline typename enable_if_c<(is_convertible >::value && !is_number_expression::value && !is_number::value), bool>::type +inline typename enable_if_c, Arithmetic>::value, bool>::type operator > (const Arithmetic& a, const number& b) { - typedef typename detail::canonical::type ct; using default_ops::eval_lt; - return eval_lt(b.backend(), ct(a)); + return eval_lt(b.backend(), number::canonical_value(a)); } template -inline typename enable_if_c<(is_convertible::result_type>::value && !is_number_expression::value && !is_number::value), bool>::type +inline typename enable_if_c::result_type, Arithmetic>::value, bool>::type operator > (const Arithmetic& a, const detail::expression& b) { typedef typename detail::expression::result_type result_type; - typedef typename detail::canonical::type ct; using default_ops::eval_lt; result_type t(b); - return eval_lt(t.backend(), ct(a)); + return eval_lt(t.backend(), result_type::canonical_value(a)); } +/* template inline typename enable_if, typename detail::expression::result_type>, bool>::type operator > (const detail::expression& a, const number& b) @@ -319,15 +346,15 @@ inline typename enable_if, typename typename detail::expression::result_type t(a); return eval_gt(t.backend(), b.backend()); } +*/ template -inline typename enable_if_c<(is_convertible::result_type>::value && !is_number_expression::value && !is_number::value), bool>::type +inline typename enable_if_c::result_type, Arithmetic>::value, bool>::type operator > (const detail::expression& a, const Arithmetic& b) { typedef typename detail::expression::result_type result_type; - typedef typename detail::canonical::type ct; using default_ops::eval_gt; result_type t(a); - return eval_gt(t.backend(), ct(b)); + return eval_gt(t.backend(), result_type::canonical_value(b)); } template inline typename enable_if::result_type, typename detail::expression::result_type>, bool>::type @@ -346,13 +373,13 @@ inline bool operator <= (const number& a, const nu return !eval_gt(a.backend(), b.backend()); } template -inline typename enable_if_c<(is_convertible >::value && !is_number_expression::value && !is_number::value), bool>::type +inline typename enable_if_c, Arithmetic>::value, bool>::type operator <= (const number& a, const Arithmetic& b) { - typedef typename detail::canonical::type ct; using default_ops::eval_gt; - return !eval_gt(a.backend(), ct(b)); + return !eval_gt(a.backend(), number::canonical_value(b)); } +/* template inline typename enable_if, typename detail::expression::result_type>, bool>::type operator <= (const number& a, const detail::expression& b) @@ -361,24 +388,24 @@ inline typename enable_if, typename typename detail::expression::result_type t(b); return !eval_gt(a.backend(), t.backend()); } +*/ template -inline typename enable_if_c<(is_convertible >::value && !is_number_expression::value && !is_number::value), bool>::type +inline typename enable_if_c, Arithmetic>::value, bool>::type operator <= (const Arithmetic& a, const number& b) { - typedef typename detail::canonical::type ct; using default_ops::eval_lt; - return !eval_lt(b.backend(), ct(a)); + return !eval_lt(b.backend(), number::canonical_value(a)); } template -inline typename enable_if_c<(is_convertible::result_type>::value && !is_number_expression::value && !is_number::value), bool>::type +inline typename enable_if_c::result_type, Arithmetic>::value, bool>::type operator <= (const Arithmetic& a, const detail::expression& b) { typedef typename detail::expression::result_type result_type; - typedef typename detail::canonical::type ct; using default_ops::eval_lt; result_type t(b); - return !eval_lt(t.backend(), ct(a)); + return !eval_lt(t.backend(), result_type::canonical_value(a)); } +/* template inline typename enable_if, typename detail::expression::result_type>, bool>::type operator <= (const detail::expression& a, const number& b) @@ -387,15 +414,15 @@ inline typename enable_if, typename typename detail::expression::result_type t(a); return !eval_gt(t.backend(), b.backend()); } +*/ template -inline typename enable_if_c<(is_convertible::result_type>::value && !is_number_expression::value && !is_number::value), bool>::type +inline typename enable_if_c::result_type, Arithmetic>::value, bool>::type operator <= (const detail::expression& a, const Arithmetic& b) { typedef typename detail::expression::result_type result_type; - typedef typename detail::canonical::type ct; using default_ops::eval_gt; result_type t(a); - return !eval_gt(t.backend(), ct(b)); + return !eval_gt(t.backend(), result_type::canonical_value(b)); } template inline typename enable_if::result_type, typename detail::expression::result_type>, bool>::type @@ -414,13 +441,13 @@ inline bool operator >= (const number& a, const nu return !eval_lt(a.backend(), b.backend()); } template -inline typename enable_if_c<(is_convertible >::value && !is_number_expression::value && !is_number::value), bool>::type +inline typename enable_if_c, Arithmetic>::value, bool>::type operator >= (const number& a, const Arithmetic& b) { - typedef typename detail::canonical::type ct; using default_ops::eval_lt; - return !eval_lt(a.backend(), ct(b)); + return !eval_lt(a.backend(), number::canonical_value(b)); } +/* template inline typename enable_if, typename detail::expression::result_type>, bool>::type operator >= (const number& a, const detail::expression& b) @@ -429,24 +456,24 @@ inline typename enable_if, typename typename detail::expression::result_type t(b); return !eval_lt(a.backend(), t.backend()); } +*/ template -inline typename enable_if_c<(is_convertible >::value && !is_number_expression::value && !is_number::value), bool>::type +inline typename enable_if_c, Arithmetic>::value, bool>::type operator >= (const Arithmetic& a, const number& b) { - typedef typename detail::canonical::type ct; using default_ops::eval_gt; - return !eval_gt(b.backend(), ct(a)); + return !eval_gt(b.backend(), number::canonical_value(a)); } template -inline typename enable_if_c<(is_convertible::result_type>::value && !is_number_expression::value && !is_number::value), bool>::type +inline typename enable_if_c::result_type, Arithmetic>::value, bool>::type operator >= (const Arithmetic& a, const detail::expression& b) { typedef typename detail::expression::result_type result_type; - typedef typename detail::canonical::type ct; using default_ops::eval_gt; result_type t(b); - return !eval_gt(t.backend(), ct(a)); + return !eval_gt(t.backend(), result_type::canonical_value(a)); } +/* template inline typename enable_if, typename detail::expression::result_type>, bool>::type operator >= (const detail::expression& a, const number& b) @@ -455,15 +482,15 @@ inline typename enable_if, typename typename detail::expression::result_type t(a); return !eval_lt(t.backend(), b.backend()); } +*/ template -inline typename enable_if_c<(is_convertible::result_type>::value && !is_number_expression::value && !is_number::value), bool>::type +inline typename enable_if_c::result_type, Arithmetic>::value, bool>::type operator >= (const detail::expression& a, const Arithmetic& b) { typedef typename detail::expression::result_type result_type; - typedef typename detail::canonical::type ct; using default_ops::eval_lt; result_type t(a); - return !eval_lt(t.backend(), ct(b)); + return !eval_lt(t.backend(), result_type::canonical_value(b)); } template inline typename enable_if::result_type, typename detail::expression::result_type>, bool>::type diff --git a/include/boost/multiprecision/gmp.hpp b/include/boost/multiprecision/gmp.hpp index 719bb41c..ba59df2c 100644 --- a/include/boost/multiprecision/gmp.hpp +++ b/include/boost/multiprecision/gmp.hpp @@ -331,7 +331,7 @@ struct gmp_float_imp return mpf_cmp_ui(m_data, i); } template - int compare(V v)const + typename enable_if, int>::type compare(V v)const { gmp_float d; d = v; @@ -552,17 +552,17 @@ struct gmp_float<0> : public detail::gmp_float_imp<0> }; template -inline typename disable_if, T>, bool>::type eval_eq(const gmp_float& a, const T& b) BOOST_NOEXCEPT +inline typename enable_if_c::value, bool>::type eval_eq(const gmp_float& a, const T& b) BOOST_NOEXCEPT { return a.compare(b) == 0; } template -inline typename disable_if, T>, bool>::type eval_lt(const gmp_float& a, const T& b) BOOST_NOEXCEPT +inline typename enable_if_c::value, bool>::type eval_lt(const gmp_float& a, const T& b) BOOST_NOEXCEPT { return a.compare(b) < 0; } template -inline typename disable_if, T>, bool>::type eval_gt(const gmp_float& a, const T& b) BOOST_NOEXCEPT +inline typename enable_if_c::value, bool>::type eval_gt(const gmp_float& a, const T& b) BOOST_NOEXCEPT { return a.compare(b) > 0; } @@ -1265,17 +1265,17 @@ protected: }; template -inline typename disable_if, bool>::type eval_eq(const gmp_int& a, const T& b) +inline typename enable_if, bool>::type eval_eq(const gmp_int& a, const T& b) { return a.compare(b) == 0; } template -inline typename disable_if, bool>::type eval_lt(const gmp_int& a, const T& b) +inline typename enable_if, bool>::type eval_lt(const gmp_int& a, const T& b) { return a.compare(b) < 0; } template -inline typename disable_if, bool>::type eval_gt(const gmp_int& a, const T& b) +inline typename enable_if, bool>::type eval_gt(const gmp_int& a, const T& b) { return a.compare(b) > 0; } diff --git a/include/boost/multiprecision/mpfr.hpp b/include/boost/multiprecision/mpfr.hpp index cdbb8cfb..b3e4f14e 100644 --- a/include/boost/multiprecision/mpfr.hpp +++ b/include/boost/multiprecision/mpfr.hpp @@ -594,17 +594,17 @@ struct mpfr_float_backend<0> : public detail::mpfr_float_imp<0> }; template -inline typename disable_if, T>, bool>::type eval_eq(const mpfr_float_backend& a, const T& b) BOOST_NOEXCEPT +inline typename enable_if, bool>::type eval_eq(const mpfr_float_backend& a, const T& b) BOOST_NOEXCEPT { return a.compare(b) == 0; } template -inline typename disable_if, T>, bool>::type eval_lt(const mpfr_float_backend& a, const T& b) BOOST_NOEXCEPT +inline typename enable_if, bool>::type eval_lt(const mpfr_float_backend& a, const T& b) BOOST_NOEXCEPT { return a.compare(b) < 0; } template -inline typename disable_if, T>, bool>::type eval_gt(const mpfr_float_backend& a, const T& b) BOOST_NOEXCEPT +inline typename enable_if, bool>::type eval_gt(const mpfr_float_backend& a, const T& b) BOOST_NOEXCEPT { return a.compare(b) > 0; } diff --git a/include/boost/multiprecision/number.hpp b/include/boost/multiprecision/number.hpp index a8fa5f44..e61372d9 100644 --- a/include/boost/multiprecision/number.hpp +++ b/include/boost/multiprecision/number.hpp @@ -161,7 +161,7 @@ public: return *this; } template - typename disable_if, number& >::type + typename disable_if, number& >::type assign(const number& v) { // @@ -540,12 +540,28 @@ public: { return m_backend.str(digits, f); } +private: + template + void convert_to_imp(T* result)const + { + using default_ops::eval_convert_to; + eval_convert_to(result, m_backend); + } + template + void convert_to_imp(number* result)const + { + result->assign(*this); + } + void convert_to_imp(std::string* result)const + { + *result = this->str(); + } +public: template T convert_to()const { - using default_ops::eval_convert_to; T result; - eval_convert_to(&result, m_backend); + convert_to_imp(&result); return result; } #ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS @@ -1553,6 +1569,20 @@ private: BOOST_FORCEINLINE BOOST_CONSTEXPR bool is_realy_self(const Val&)const BOOST_NOEXCEPT{ return false; } BOOST_FORCEINLINE BOOST_CONSTEXPR bool is_realy_self(const self_type& v)const BOOST_NOEXCEPT{ return &v == this; } + static BOOST_FORCEINLINE BOOST_CONSTEXPR const Backend& function_arg_value(const self_type& v) BOOST_NOEXCEPT { return v.backend(); } + template + static BOOST_FORCEINLINE BOOST_CONSTEXPR const V& function_arg_value(const V& v) BOOST_NOEXCEPT { return v; } + template + static BOOST_FORCEINLINE const A1& function_arg_value(const detail::expression& exp) BOOST_NOEXCEPT { return exp.value(); } + template + static BOOST_FORCEINLINE BOOST_CONSTEXPR const Backend& function_arg_value(const detail::expression, A2, A3, A4>& exp) BOOST_NOEXCEPT { return exp.value().backend(); } + Backend m_backend; + +public: + // + // These shouldn't really need to be public, or even member functions, but it makes implementing + // the non-member operators way easier if they are: + // static BOOST_FORCEINLINE BOOST_CONSTEXPR const Backend& canonical_value(const self_type& v) BOOST_NOEXCEPT { return v.m_backend; } template static BOOST_FORCEINLINE BOOST_CONSTEXPR const B2& canonical_value(const number& v) BOOST_NOEXCEPT { return v.backend(); } @@ -1564,14 +1594,6 @@ private: canonical_value(const V& v) BOOST_NOEXCEPT { return v; } static BOOST_FORCEINLINE typename detail::canonical::type canonical_value(const std::string& v) BOOST_NOEXCEPT { return v.c_str(); } - static BOOST_FORCEINLINE BOOST_CONSTEXPR const Backend& function_arg_value(const self_type& v) BOOST_NOEXCEPT { return v.backend(); } - template - static BOOST_FORCEINLINE BOOST_CONSTEXPR const V& function_arg_value(const V& v) BOOST_NOEXCEPT { return v; } - template - static BOOST_FORCEINLINE const A1& function_arg_value(const detail::expression& exp) BOOST_NOEXCEPT { return exp.value(); } - template - static BOOST_FORCEINLINE BOOST_CONSTEXPR const Backend& function_arg_value(const detail::expression, A2, A3, A4>& exp) BOOST_NOEXCEPT { return exp.value().backend(); } - Backend m_backend; }; template diff --git a/include/boost/multiprecision/tommath.hpp b/include/boost/multiprecision/tommath.hpp index 6eb8e973..6aef3e63 100644 --- a/include/boost/multiprecision/tommath.hpp +++ b/include/boost/multiprecision/tommath.hpp @@ -32,6 +32,11 @@ inline void check_tommath_result(unsigned v) } +struct tommath_int; + +void eval_multiply(tommath_int& t, const tommath_int& o); +void eval_add(tommath_int& t, const tommath_int& o); + struct tommath_int { typedef mpl::list signed_types; @@ -186,8 +191,6 @@ struct tommath_int // // We don't use libtommath's own routine because it doesn't error check the input :-( // - using default_ops::eval_multiply; - using default_ops::eval_add; if(m_data.dp == 0) detail::check_tommath_result(mp_init(&m_data)); std::size_t n = s ? std::strlen(s) : 0; @@ -279,8 +282,11 @@ struct tommath_int break; } } - eval_multiply(*this, block_mult); - eval_add(*this, block); + tommath_int t; + t = block_mult; + eval_multiply(*this, t); + t = block; + eval_add(*this, t); } } } diff --git a/test/test_arithmetic.cpp b/test/test_arithmetic.cpp index feb05b87..4a3e83b4 100644 --- a/test/test_arithmetic.cpp +++ b/test/test_arithmetic.cpp @@ -119,15 +119,31 @@ bool isfloat(double){ return true; } bool isfloat(long double){ return true; } template bool isfloat(T){ return false; } +namespace detail{ + +template +typename boost::disable_if, T>::type abs(T v) +{ + return v < 0 ? -v : v; +} +template +typename boost::enable_if, T>::type abs(T v) +{ + return v; +} + +} + #define BOOST_TEST_CLOSE(x, y, tol)\ + using std::abs; using detail::abs;\ if(x == 0){\ BOOST_TEST(y == 0); }\ else if(!isfloat(x)){\ BOOST_TEST(x == y); }\ - else if((x != y) && (::fabsl(static_cast((x-y)/x)) > tol))\ + else if((x != y) && (abs((x-y)/x) > tol))\ {\ BOOST_ERROR("Expected tolerance was exceeded: ");\ - BOOST_LIGHTWEIGHT_TEST_OSTREAM << std::setprecision(34) << "(x-y)/x = " << ::fabsl(static_cast((x-y)/x)) \ + BOOST_LIGHTWEIGHT_TEST_OSTREAM << std::setprecision(34) << "(x-y)/x = " << abs((x-y)/x) \ << " tolerance = " << tol << std::endl;\ } @@ -141,6 +157,58 @@ struct is_twos_complement_integer : public boost #define BOOST_TEST_EQUAL(a, b) BOOST_TEST((a) == (b)) + +template +struct related_type +{ + typedef T type; +}; + +#ifdef TEST_MPQ +template <> +struct related_type +{ + typedef boost::multiprecision::mpz_int type; +}; +#endif +#if defined(TEST_MPF_50) || defined(TEST_MPF) +template +struct related_type > > +{ + typedef boost::multiprecision::number< boost::multiprecision::gmp_float > type; +}; +template <> +struct related_type +{ + typedef boost::multiprecision::mpz_int type; +}; +#endif +#ifdef TEST_CPP_DEC_FLOAT +template +struct related_type > > +{ + typedef boost::multiprecision::number< boost::multiprecision::cpp_dec_float > type; +}; +#endif +#if defined(TEST_MPFR_50) || defined(TEST_MPFR) +template +struct related_type > > +{ + typedef boost::multiprecision::number< boost::multiprecision::mpfr_float_backend > type; +}; +#endif +#if defined(TEST_CPP_INT_1) || defined(TEST_CPP_INT_2) || defined(TEST_CPP_INT_3) || defined(TEST_CPP_INT_BR) +template <> +struct related_type +{ + typedef boost::multiprecision::int256_t type; +}; +template +struct related_type, ET> > +{ + typedef boost::multiprecision::number, ET> type; +}; +#endif template void test_comparisons(Val, Val, const boost::mpl::false_) {} @@ -836,7 +904,8 @@ void test_negative_mixed(boost::mpl::true_ const&) Real >::type simple_cast_type; std::cout << "Testing mixed arithmetic with type: " << typeid(Real).name() << " and " << typeid(Num).name() << std::endl; - Num n1 = -static_cast(1uLL << (std::numeric_limits::digits - 1)); + static const int left_shift = std::numeric_limits::digits - 1; + Num n1 = -static_cast(1uLL << ((left_shift < 63) && (left_shift > 0) ? left_shift : 10)); Num n2 = -1; Num n3 = 0; Num n4 = -20; @@ -1047,11 +1116,12 @@ void test_mixed(const boost::mpl::true_&) Real >::type simple_cast_type; - if(std::numeric_limits::digits < std::numeric_limits::digits) + if(std::numeric_limits::is_specialized && std::numeric_limits::is_bounded && std::numeric_limits::digits < std::numeric_limits::digits) return; std::cout << "Testing mixed arithmetic with type: " << typeid(Real).name() << " and " << typeid(Num).name() << std::endl; - Num n1 = static_cast(1uLL << (std::numeric_limits::digits - 1)); + static const int left_shift = std::numeric_limits::digits - 1; + Num n1 = static_cast(1uLL << ((left_shift < 63) && (left_shift > 0) ? left_shift : 10)); Num n2 = 1; Num n3 = 0; Num n4 = 20; @@ -1198,6 +1268,12 @@ void test() test_mixed(tag); test_mixed(tag); test_mixed(tag); + + typedef typename related_type::type related_type; + boost::mpl::bool_::value && !boost::is_same::value> tag2; + + test_mixed(tag2); + #endif // // Integer only functions: