diff --git a/doc/reference_number.qbk b/doc/reference_number.qbk index 455def21f..3707f76e5 100644 --- a/doc/reference_number.qbk +++ b/doc/reference_number.qbk @@ -262,8 +262,8 @@ bool miller_rabin_test(const ``['number-or-expression-template-type]``& n, unsigned trials); // Rational number support: - typename component_type<``['number-or-expression-template-type]``>::type numerator (const ``['number-or-expression-template-type]``&); - typename component_type<``['number-or-expression-template-type]``>::type denominator(const ``['number-or-expression-template-type]``&); + typename component_type<``['number-or-expression-template-type]``>::type const& numerator (const ``['number-or-expression-template-type]``&); + typename component_type<``['number-or-expression-template-type]``>::type const& denominator(const ``['number-or-expression-template-type]``&); }} // namespaces @@ -817,11 +817,15 @@ to ensure accuracy. [h4 Rational Number Functions] - typename component_type<``['number-or-expression-template-type]``>::type numerator (const ``['number-or-expression-template-type]``&); - typename component_type<``['number-or-expression-template-type]``>::type denominator(const ``['number-or-expression-template-type]``&); + typename component_type<``['number-or-expression-template-type]``>::type const& numerator (const ``['number-or-expression-template-type]``&); + typename component_type<``['number-or-expression-template-type]``>::type const& denominator(const ``['number-or-expression-template-type]``&); These functions return the numerator and denominator of a rational number respectively. +The returned value is by reference wherever possible. However, there are a few types, most notably where the number uses +`logged_adaptor` or `debug_adaptor` where this is not possible and the result is a temporary returned by value. As a result +code should *never* rely on a reference being returned. + [h4 Boost.Math Interoperability Support] namespace boost{ namespace math{ diff --git a/doc/tutorial_boost_rational.qbk b/doc/tutorial_boost_rational.qbk index af54bc2b6..e221c0c33 100644 --- a/doc/tutorial_boost_rational.qbk +++ b/doc/tutorial_boost_rational.qbk @@ -8,43 +8,10 @@ http://www.boost.org/LICENSE_1_0.txt). ] -[section:tommath_rational tommath_rational] +[section:br Use With Boost.Rational] -`#include ` +All of the integer types in this library can be used as template arguments to `boost::rational`. - namespace boost{ namespace multiprecision{ +Note that using the library in this way largely negates the effect of the expression templates in `number`. - typedef rational_adpater tommath_rational; - typedef number tom_rational; - - }} // namespaces - -The `tommath_rational` back-end is used via the typedef `boost::multiprecision::tom_rational`. It acts as a thin wrapper around -`boost::rational` -to provide a rational number type that is a drop-in replacement for the native C++ number types, but with unlimited precision. - -The advantage of using this type rather than `boost::rational` directly, is that it is expression-template enabled, -greatly reducing the number of temporaries created in complex expressions. - -There are also non-member functions: - - tom_int numerator(const tom_rational&); - tom_int denominator(const tom_rational&); - -which return the numerator and denominator of the number. - -Things you should know when using this type: - -* Default constructed `tom_rational`s have the value zero (this the inherited Boost.Rational behavior). -* Division by zero results in a `std::overflow_error` being thrown. -* Conversion from a string results in a `std::runtime_error` being thrown if the string can not be -interpreted as a valid rational number. -* No changes are made to [tommath]'s global state, so this type can safely coexist with other [tommath] code. -* Performance of this type has been found to be pretty poor - this need further investigation - but it appears that Boost.Rational -needs some improvement in this area. - -[h5 Example:] - -[mp_rat_eg] - -[endsect] [/section:tommath_rational tommath_rational] +[endsect] [/section:br Use With Boost.Rational] diff --git a/doc/tutorial_cpp_rational.qbk b/doc/tutorial_cpp_rational.qbk index cb9357143..5ea76357e 100644 --- a/doc/tutorial_cpp_rational.qbk +++ b/doc/tutorial_cpp_rational.qbk @@ -30,8 +30,8 @@ There is also a two argument constructor that accepts a numerator and denominato There are also non-member functions: - cpp_int numerator(const cpp_rational&); - cpp_int denominator(const cpp_rational&); + cpp_int const& numerator(const cpp_rational&); + cpp_int const& denominator(const cpp_rational&); which return the numerator and denominator of the number. diff --git a/doc/tutorial_gmp_rational.qbk b/doc/tutorial_gmp_rational.qbk index dedd8ccff..b856c13b1 100644 --- a/doc/tutorial_gmp_rational.qbk +++ b/doc/tutorial_gmp_rational.qbk @@ -33,8 +33,8 @@ There is also a two-argument constructor that accepts a numerator and denominato There are also non-member functions: - mpz_int numerator(const mpq_rational&); - mpz_int denominator(const mpq_rational&); + mpz_int const& numerator(const mpq_rational&); + mpz_int const& denominator(const mpq_rational&); which return the numerator and denominator of the number. diff --git a/doc/tutorial_rational_adaptor.qbk b/doc/tutorial_rational_adaptor.qbk index de3751641..02627a106 100644 --- a/doc/tutorial_rational_adaptor.qbk +++ b/doc/tutorial_rational_adaptor.qbk @@ -12,7 +12,7 @@ namespace boost{ namespace multiprecision{ - template + template ::value> class rational_adpater; }} diff --git a/doc/tutorial_tommath_rational.qbk b/doc/tutorial_tommath_rational.qbk index af54bc2b6..3f71cb4ce 100644 --- a/doc/tutorial_tommath_rational.qbk +++ b/doc/tutorial_tommath_rational.qbk @@ -28,8 +28,8 @@ greatly reducing the number of temporaries created in complex expressions. There are also non-member functions: - tom_int numerator(const tom_rational&); - tom_int denominator(const tom_rational&); + tom_int const& numerator(const tom_rational&); + tom_int const& denominator(const tom_rational&); which return the numerator and denominator of the number. diff --git a/include/boost/multiprecision/fwd.hpp b/include/boost/multiprecision/fwd.hpp index dfcf0453b..5d42d0d9b 100644 --- a/include/boost/multiprecision/fwd.hpp +++ b/include/boost/multiprecision/fwd.hpp @@ -121,7 +121,7 @@ namespace boost { template <> struct mpfr_float_backend<0, allocate_stack>; - template + template ::value> struct rational_adaptor; struct tommath_int; diff --git a/include/boost/multiprecision/gmp.hpp b/include/boost/multiprecision/gmp.hpp index fca973123..d68f53cdd 100644 --- a/include/boost/multiprecision/gmp.hpp +++ b/include/boost/multiprecision/gmp.hpp @@ -3270,20 +3270,35 @@ struct component_type > { using type = number; }; - +// +// The following code breaks C++'s strict aliasing rules, but works +// because we are casting between (references to) two layout-compatible types. +// We do this for performance reasons to avoid making an unnecessary copy +// (which involves two expensive memory allocations). +// If this causes issues down the road, then we will revert to the old +// return-by-value approach. +// template -inline number numerator(const number& val) +inline const number& numerator(const number& val) { +#if 0 number result; mpz_set(result.backend().data(), (mpq_numref(val.backend().data()))); return result; +#endif + static_assert(sizeof(number) == sizeof(*mpq_numref(val.backend().data())), "Size sanity check failed"); + return reinterpret_cast&>(*mpq_numref(val.backend().data())); } template -inline number denominator(const number& val) +inline const number& denominator(const number& val) { +#if 0 number result; mpz_set(result.backend().data(), (mpq_denref(val.backend().data()))); return result; +#endif + static_assert(sizeof(number) == sizeof(*mpq_numref(val.backend().data())), "Size sanity check failed"); + return reinterpret_cast&>(*mpq_denref(val.backend().data())); } namespace detail { diff --git a/include/boost/multiprecision/rational_adaptor.hpp b/include/boost/multiprecision/rational_adaptor.hpp index 7953a1085..36b10d022 100644 --- a/include/boost/multiprecision/rational_adaptor.hpp +++ b/include/boost/multiprecision/rational_adaptor.hpp @@ -15,7 +15,7 @@ namespace boost { namespace multiprecision { namespace backends { -template +template struct rational_adaptor { // @@ -63,7 +63,7 @@ struct rational_adaptor using default_ops::eval_divide; using default_ops::eval_get_sign; - int s = eval_get_sign(m_denom); + int s = eval_get_sign(m_denom.backend()); if(s == 0) { @@ -71,18 +71,18 @@ struct rational_adaptor } else if (s < 0) { - m_num.negate(); - m_denom.negate(); + m_num.backend().negate(); + m_denom.backend().negate(); } Backend g, t; - eval_gcd(g, m_num, m_denom); + eval_gcd(g, m_num.backend(), m_denom.backend()); if (!eval_eq(g, one())) { - eval_divide(t, m_num, g); - m_num.swap(t); - eval_divide(t, m_denom, g); - m_denom = std::move(t); + eval_divide(t, m_num.backend(), g); + m_num.backend().swap(t); + eval_divide(t, m_denom.backend(), g); + m_denom.backend() = std::move(t); } } @@ -139,8 +139,8 @@ struct rational_adaptor template inline typename std::enable_if::value, rational_adaptor&>::type operator=(const Arithmetic& i) { - m_num = i; - m_denom = one(); + m_num.backend() = i; + m_denom.backend() = one(); return *this; } rational_adaptor& operator=(const char* s) @@ -230,8 +230,8 @@ struct rational_adaptor void swap(rational_adaptor& o) { - m_num.swap(o.m_num); - m_denom.swap(o.m_denom); + m_num.backend().swap(o.m_num.backend()); + m_denom.backend().swap(o.m_denom.backend()); } std::string str(std::streamsize digits, std::ios_base::fmtflags f) const { @@ -249,7 +249,7 @@ struct rational_adaptor } void negate() { - m_num.negate(); + m_num.backend().negate(); } int compare(const rational_adaptor& o) const { @@ -300,10 +300,15 @@ struct rational_adaptor return compare(t); } - Backend& num() { return m_num; } - const Backend& num()const { return m_num; } - Backend& denom() { return m_denom; } - const Backend& denom()const { return m_denom; } + Backend& num() { return m_num.backend(); } + const Backend& num()const { return m_num.backend(); } + Backend& denom() { return m_denom.backend(); } + const Backend& denom()const { return m_denom.backend(); } + + number& nnum() { return m_num; } + const number& nnum()const { return m_num; } + number& ndenom() { return m_denom; } + const number& ndenom()const { return m_denom; } #ifndef BOOST_MP_STANDALONE template @@ -334,7 +339,7 @@ struct rational_adaptor #endif // BOOST_MP_STANDALONE private: - Backend m_num, m_denom; + number m_num, m_denom; }; // @@ -356,28 +361,28 @@ is_minus_one(const T& val) // // Required non-members: // -template -inline void eval_add(rational_adaptor& a, const rational_adaptor& b) +template +inline void eval_add(rational_adaptor& a, const rational_adaptor& b) { eval_add_subtract_imp(a, a, b, true); } -template -inline void eval_subtract(rational_adaptor& a, const rational_adaptor& b) +template +inline void eval_subtract(rational_adaptor& a, const rational_adaptor& b) { eval_add_subtract_imp(a, a, b, false); } -template -inline void eval_multiply(rational_adaptor& a, const rational_adaptor& b) +template +inline void eval_multiply(rational_adaptor& a, const rational_adaptor& b) { eval_multiply_imp(a, a, b.num(), b.denom()); } -template -void eval_divide(rational_adaptor& a, const rational_adaptor& b) +template +void eval_divide(rational_adaptor& a, const rational_adaptor& b) { using default_ops::eval_divide; - rational_adaptor t; + rational_adaptor t; eval_divide(t, a, b); a = std::move(t); } @@ -403,8 +408,8 @@ inline typename std::enable_if<(number_category::value != number_kind_integer *result /= d; } -template -inline typename std::enable_if::value == number_kind_integer>::type eval_convert_to(R* result, const rational_adaptor& backend) +template +inline typename std::enable_if::value == number_kind_integer>::type eval_convert_to(R* result, const rational_adaptor& backend) { using default_ops::eval_divide; using default_ops::eval_convert_to; @@ -416,8 +421,8 @@ inline typename std::enable_if::value == number_kind_integer> // // Hashing support, not strictly required, but it is used in our tests: // -template -inline std::size_t hash_value(const rational_adaptor& arg) +template +inline std::size_t hash_value(const rational_adaptor& arg) { std::size_t result = hash_value(arg.num()); std::size_t result2 = hash_value(arg.denom()); @@ -427,8 +432,8 @@ inline std::size_t hash_value(const rational_adaptor& arg) // // assign_components: // -template -void assign_components(rational_adaptor& result, Backend const& a, Backend const& b) +template +void assign_components(rational_adaptor& result, Backend const& a, Backend const& b) { using default_ops::eval_gcd; using default_ops::eval_divide; @@ -442,7 +447,7 @@ void assign_components(rational_adaptor& result, Backend const& a, Back } Backend g; eval_gcd(g, a, b); - if (eval_eq(g, rational_adaptor::one())) + if (eval_eq(g, rational_adaptor::one())) { result.num() = a; result.denom() = b; @@ -461,8 +466,8 @@ void assign_components(rational_adaptor& result, Backend const& a, Back // // Again for arithmetic types, overload for whatever arithmetic types are directly supported: // -template -inline void assign_components(rational_adaptor& result, const Arithmetic1& a, typename std::enable_if::value && std::is_arithmetic::value, const Arithmetic2&>::type b) +template +inline void assign_components(rational_adaptor& result, const Arithmetic1& a, typename std::enable_if::value && std::is_arithmetic::value, const Arithmetic2&>::type b) { using default_ops::eval_gcd; using default_ops::eval_divide; @@ -476,7 +481,7 @@ inline void assign_components(rational_adaptor& result, const Arithmeti Backend g; result.num() = a; eval_gcd(g, result.num(), b); - if (eval_eq(g, rational_adaptor::one())) + if (eval_eq(g, rational_adaptor::one())) { result.denom() = b; } @@ -491,8 +496,8 @@ inline void assign_components(rational_adaptor& result, const Arithmeti result.denom().negate(); } } -template -inline void assign_components(rational_adaptor& result, const Arithmetic1& a, typename std::enable_if::value || !std::is_arithmetic::value, const Arithmetic2&>::type b) +template +inline void assign_components(rational_adaptor& result, const Arithmetic1& a, typename std::enable_if::value || !std::is_arithmetic::value, const Arithmetic2&>::type b) { using default_ops::eval_gcd; using default_ops::eval_divide; @@ -508,7 +513,7 @@ inline void assign_components(rational_adaptor& result, const Arithmeti } eval_gcd(g, result.num(), result.denom()); - if (!eval_eq(g, rational_adaptor::one())) + if (!eval_eq(g, rational_adaptor::one())) { eval_divide(result.num(), g); eval_divide(result.denom(), g); @@ -522,48 +527,48 @@ inline void assign_components(rational_adaptor& result, const Arithmeti // // Optional comparison operators: // -template -inline bool eval_is_zero(const rational_adaptor& arg) +template +inline bool eval_is_zero(const rational_adaptor& arg) { using default_ops::eval_is_zero; return eval_is_zero(arg.num()); } -template -inline int eval_get_sign(const rational_adaptor& arg) +template +inline int eval_get_sign(const rational_adaptor& arg) { using default_ops::eval_get_sign; return eval_get_sign(arg.num()); } -template -inline bool eval_eq(const rational_adaptor& a, const rational_adaptor& b) +template +inline bool eval_eq(const rational_adaptor& a, const rational_adaptor& b) { using default_ops::eval_eq; return eval_eq(a.num(), b.num()) && eval_eq(a.denom(), b.denom()); } -template +template inline typename std::enable_if::value&& std::is_integral::value, bool>::type - eval_eq(const rational_adaptor& a, Arithmetic b) + eval_eq(const rational_adaptor& a, Arithmetic b) { using default_ops::eval_eq; - return eval_eq(a.denom(), rational_adaptor::one()) && eval_eq(a.num(), b); + return eval_eq(a.denom(), rational_adaptor::one()) && eval_eq(a.num(), b); } -template +template inline typename std::enable_if::value&& std::is_integral::value, bool>::type - eval_eq(Arithmetic b, const rational_adaptor& a) + eval_eq(Arithmetic b, const rational_adaptor& a) { using default_ops::eval_eq; - return eval_eq(a.denom(), rational_adaptor::one()) && eval_eq(a.num(), b); + return eval_eq(a.denom(), rational_adaptor::one()) && eval_eq(a.num(), b); } // // Arithmetic operations, starting with addition: // -template -void eval_add_subtract_imp(rational_adaptor& result, const Arithmetic& arg, bool isaddition) +template +void eval_add_subtract_imp(rational_adaptor& result, const Arithmetic& arg, bool isaddition) { using default_ops::eval_multiply; using default_ops::eval_divide; @@ -582,7 +587,7 @@ void eval_add_subtract_imp(rational_adaptor& result, const Arithmetic& // /* eval_gcd(t, result.num(), result.denom()); - if (!eval_eq(t, rational_adaptor::one()) != 0) + if (!eval_eq(t, rational_adaptor::one()) != 0) { Backend t2; eval_divide(t2, result.num(), t); @@ -593,22 +598,22 @@ void eval_add_subtract_imp(rational_adaptor& result, const Arithmetic& */ } -template +template inline typename std::enable_if::value && (std::is_integral::value || std::is_same::value)>::type - eval_add(rational_adaptor& result, const Arithmetic& arg) + eval_add(rational_adaptor& result, const Arithmetic& arg) { eval_add_subtract_imp(result, arg, true); } -template +template inline typename std::enable_if::value && (std::is_integral::value || std::is_same::value)>::type - eval_subtract(rational_adaptor& result, const Arithmetic& arg) + eval_subtract(rational_adaptor& result, const Arithmetic& arg) { eval_add_subtract_imp(result, arg, false); } -template -void eval_add_subtract_imp(rational_adaptor& result, const rational_adaptor& a, const rational_adaptor& b, bool isaddition) +template +void eval_add_subtract_imp(rational_adaptor& result, const rational_adaptor& a, const rational_adaptor& b, bool isaddition) { using default_ops::eval_eq; using default_ops::eval_multiply; @@ -637,7 +642,7 @@ void eval_add_subtract_imp(rational_adaptor& result, const rational_ada // // Do we have gcd > 1: // - if (!eval_eq(gcd, rational_adaptor::one())) + if (!eval_eq(gcd, rational_adaptor::one())) { // // Scale the denominators by gcd, and put the results in t1 and t2: @@ -660,7 +665,7 @@ void eval_add_subtract_imp(rational_adaptor& result, const rational_ada // Get the gcd of gcd and our numerator (t3): // eval_gcd(t4, t3, gcd); - if (eval_eq(t4, rational_adaptor::one())) + if (eval_eq(t4, rational_adaptor::one())) { result.num() = t3; eval_multiply(result.denom(), t1, a.denom()); @@ -696,19 +701,19 @@ void eval_add_subtract_imp(rational_adaptor& result, const rational_ada } -template -inline void eval_add(rational_adaptor& result, const rational_adaptor& a, const rational_adaptor& b) +template +inline void eval_add(rational_adaptor& result, const rational_adaptor& a, const rational_adaptor& b) { eval_add_subtract_imp(result, a, b, true); } -template -inline void eval_subtract(rational_adaptor& result, const rational_adaptor& a, const rational_adaptor& b) +template +inline void eval_subtract(rational_adaptor& result, const rational_adaptor& a, const rational_adaptor& b) { eval_add_subtract_imp(result, a, b, false); } -template -void eval_add_subtract_imp(rational_adaptor& result, const rational_adaptor& a, const Arithmetic& b, bool isaddition) +template +void eval_add_subtract_imp(rational_adaptor& result, const rational_adaptor& a, const Arithmetic& b, bool isaddition) { using default_ops::eval_add; using default_ops::eval_subtract; @@ -739,15 +744,15 @@ void eval_add_subtract_imp(rational_adaptor& result, const rational_ada // and gcd(a + bm, b) = gcd(a, b) = 1 // } -template +template inline typename std::enable_if::value && (std::is_integral::value || std::is_same::value)>::type - eval_add(rational_adaptor& result, const rational_adaptor& a, const Arithmetic& b) + eval_add(rational_adaptor& result, const rational_adaptor& a, const Arithmetic& b) { eval_add_subtract_imp(result, a, b, true); } -template +template inline typename std::enable_if::value && (std::is_integral::value || std::is_same::value)>::type - eval_subtract(rational_adaptor& result, const rational_adaptor& a, const Arithmetic& b) + eval_subtract(rational_adaptor& result, const rational_adaptor& a, const Arithmetic& b) { eval_add_subtract_imp(result, a, b, false); } @@ -755,8 +760,8 @@ inline typename std::enable_if::value & // // Multiplication: // -template -void eval_multiply_imp(rational_adaptor& result, const rational_adaptor& a, const Backend& b_num, const Backend& b_denom) +template +void eval_multiply_imp(rational_adaptor& result, const rational_adaptor& a, const Backend& b_num, const Backend& b_denom) { using default_ops::eval_multiply; using default_ops::eval_divide; @@ -770,8 +775,8 @@ void eval_multiply_imp(rational_adaptor& result, const rational_adaptor // // Unit gcd's are the most likely case: // - bool b_left = eval_eq(gcd_left, rational_adaptor::one()); - bool b_right = eval_eq(gcd_right, rational_adaptor::one()); + bool b_left = eval_eq(gcd_left, rational_adaptor::one()); + bool b_right = eval_eq(gcd_right, rational_adaptor::one()); if (b_left && b_right) { @@ -811,8 +816,8 @@ void eval_multiply_imp(rational_adaptor& result, const rational_adaptor } } -template -void eval_multiply(rational_adaptor& result, const rational_adaptor& a, const rational_adaptor& b) +template +void eval_multiply(rational_adaptor& result, const rational_adaptor& a, const rational_adaptor& b) { using default_ops::eval_multiply; @@ -826,7 +831,7 @@ void eval_multiply(rational_adaptor& result, const rational_adaptor +template void eval_multiply_imp(Backend& result_num, Backend& result_denom, Arithmetic arg) { if (arg == 0) @@ -907,21 +912,21 @@ void eval_multiply_imp(Backend& result_num, Backend& result_denom, Backend arg) } } -template +template inline typename std::enable_if::value && (std::is_integral::value || std::is_same::value)>::type - eval_multiply(rational_adaptor& result, const Arithmetic& arg) + eval_multiply(rational_adaptor& result, const Arithmetic& arg) { eval_multiply_imp(result.num(), result.denom(), arg); } -template +template typename std::enable_if::value && std::is_integral::value>::type - eval_multiply_imp(rational_adaptor& result, const Backend& a_num, const Backend& a_denom, Arithmetic b) + eval_multiply_imp(rational_adaptor& result, const Backend& a_num, const Backend& a_denom, Arithmetic b) { if (b == 0) { - result.num() = rational_adaptor::zero(); - result.denom() = rational_adaptor::one(); + result.num() = rational_adaptor::zero(); + result.denom() = rational_adaptor::one(); return; } else if (b == 1) @@ -955,17 +960,17 @@ typename std::enable_if::value && std:: else result.denom() = a_denom; } -template -inline void eval_multiply_imp(rational_adaptor& result, const Backend& a_num, const Backend& a_denom, const Backend& b) +template +inline void eval_multiply_imp(rational_adaptor& result, const Backend& a_num, const Backend& a_denom, const Backend& b) { result.num() = a_num; result.denom() = a_denom; eval_multiply_imp(result.num(), result.denom(), b); } -template +template inline typename std::enable_if::value && (std::is_integral::value || std::is_same::value)>::type - eval_multiply(rational_adaptor& result, const rational_adaptor& a, const Arithmetic& b) + eval_multiply(rational_adaptor& result, const rational_adaptor& a, const Arithmetic& b) { if (&result == &a) return eval_multiply(result, b); @@ -973,9 +978,9 @@ inline typename std::enable_if::value & eval_multiply_imp(result, a.num(), a.denom(), b); } -template +template inline typename std::enable_if::value && (std::is_integral::value || std::is_same::value)>::type - eval_multiply(rational_adaptor& result, const Arithmetic& b, const rational_adaptor& a) + eval_multiply(rational_adaptor& result, const Arithmetic& b, const rational_adaptor& a) { return eval_multiply(result, a, b); } @@ -983,8 +988,8 @@ inline typename std::enable_if::value & // // Division: // -template -inline void eval_divide(rational_adaptor& result, const rational_adaptor& a, const rational_adaptor& b) +template +inline void eval_divide(rational_adaptor& result, const rational_adaptor& a, const rational_adaptor& b) { using default_ops::eval_multiply; using default_ops::eval_get_sign; @@ -997,20 +1002,20 @@ inline void eval_divide(rational_adaptor& result, const rational_adapto if (&a == &b) { // Huh? Really? - result.num() = result.denom() = rational_adaptor::one(); + result.num() = result.denom() = rational_adaptor::one(); return; } if (&result == &b) { - rational_adaptor t(b); + rational_adaptor t(b); return eval_divide(result, a, t); } eval_multiply_imp(result, a, b.denom(), b.num()); } -template +template inline typename std::enable_if::value && (std::is_integral::value || std::is_same::value)>::type - eval_divide(rational_adaptor& result, const Arithmetic& b, const rational_adaptor& a) + eval_divide(rational_adaptor& result, const Arithmetic& b, const rational_adaptor& a) { using default_ops::eval_get_sign; @@ -1034,9 +1039,9 @@ inline typename std::enable_if::value & } } -template +template typename std::enable_if::value && std::is_integral::value>::type -eval_divide(rational_adaptor& result, Arithmetic arg) +eval_divide(rational_adaptor& result, Arithmetic arg) { if (arg == 0) { @@ -1079,8 +1084,8 @@ eval_divide(rational_adaptor& result, Arithmetic arg) result.num() = std::move(t); } } -template -void eval_divide(rational_adaptor& result, const rational_adaptor& a, Backend arg) +template +void eval_divide(rational_adaptor& result, const rational_adaptor& a, Backend arg) { using default_ops::eval_multiply; using default_ops::eval_gcd; @@ -1095,7 +1100,7 @@ void eval_divide(rational_adaptor& result, const rational_adaptor::one()) || (eval_get_sign(a) == 0)) + else if (eval_eq(a, rational_adaptor::one()) || (eval_get_sign(a) == 0)) { if (&result != &a) result = a; @@ -1104,7 +1109,7 @@ void eval_divide(rational_adaptor& result, const rational_adaptor::one()); + bool has_unit_gcd = eval_eq(gcd, rational_adaptor::one()); if (!has_unit_gcd) { eval_divide(u_arg, arg, gcd); @@ -1131,15 +1136,15 @@ void eval_divide(rational_adaptor& result, const rational_adaptor -void eval_divide(rational_adaptor& result, Backend arg) +template +void eval_divide(rational_adaptor& result, Backend arg) { eval_divide(result, result, arg); } -template +template typename std::enable_if::value && std::is_integral::value>::type - eval_divide(rational_adaptor& result, const rational_adaptor& a, Arithmetic arg) + eval_divide(rational_adaptor& result, const rational_adaptor& a, Arithmetic arg) { if (&result == &a) return eval_divide(result, arg); @@ -1193,14 +1198,14 @@ typename std::enable_if::value && std:: // // Increment and decrement: // -template -inline void eval_increment(rational_adaptor& arg) +template +inline void eval_increment(rational_adaptor& arg) { using default_ops::eval_add; eval_add(arg.num(), arg.denom()); } -template -inline void eval_decrement(rational_adaptor& arg) +template +inline void eval_decrement(rational_adaptor& arg) { using default_ops::eval_subtract; eval_subtract(arg.num(), arg.denom()); @@ -1209,8 +1214,8 @@ inline void eval_decrement(rational_adaptor& arg) // // abs: // -template -inline void eval_abs(rational_adaptor& result, const rational_adaptor& arg) +template +inline void eval_abs(rational_adaptor& result, const rational_adaptor& arg) { using default_ops::eval_abs; eval_abs(result.num(), arg.num()); @@ -1228,29 +1233,29 @@ inline void eval_abs(rational_adaptor& result, const rational_adaptor -struct number_category > : public std::integral_constant +template +struct number_category > : public std::integral_constant {}; template -struct component_type, ExpressionTemplates> > +struct component_type, ExpressionTemplates> > { typedef number type; }; template -inline number numerator(const number, ET>& val) +inline const number& numerator(const number, ET>& val) { - return val.backend().num(); + return val.backend().nnum(); } template -inline number denominator(const number, ET>& val) +inline const number& denominator(const number, ET>& val) { - return val.backend().denom(); + return val.backend().ndenom(); } -template -struct is_unsigned_number > : public is_unsigned_number +template +struct is_unsigned_number > : public is_unsigned_number {};