/////////////////////////////////////////////////////////////////////////////// // 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. // Note that these *must* return by value, even though that's somewhat against // existing practice. The issue is that in C++11 land one could easily and legitimately // write: // auto x = +1234_my_user_defined_suffix; // which would result in a dangling-reference-to-temporary if unary + returned a reference // to it's argument. While return-by-value is obviously inefficient in other situations // the reality is that no one ever uses unary operator+ anyway...! // template inline BOOST_CONSTEXPR const number operator + (const number& v) { return v; } template inline BOOST_CONSTEXPR const detail::expression operator + (const detail::expression& v) { return v; } template inline detail::expression > operator - (const number& v) { BOOST_STATIC_ASSERT_MSG(is_signed_number::value, "Negating an unsigned type results in ill-defined behavior."); return detail::expression >(v); } template inline detail::expression > operator - (const detail::expression& v) { BOOST_STATIC_ASSERT_MSG((is_signed_number::result_type>::value), "Negating an unsigned type results in ill-defined behavior."); return detail::expression >(v); } template inline typename enable_if_c::value == number_kind_integer, detail::expression > >::type operator ~ (const number& v) { return detail::expression >(v); } template inline typename enable_if_c::result_type>::value == number_kind_integer, detail::expression > >::type 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); } // // Fused multiply add: // template inline typename enable_if::result_type>, detail::expression::left_type, typename detail::expression::right_type, V> >::type operator + (const V& a, const detail::expression& b) { return detail::expression::left_type, typename detail::expression::right_type, V>(b.left(), b.right(), a); } template inline typename enable_if::result_type>, detail::expression::left_type, typename detail::expression::right_type, V> >::type operator + (const detail::expression& a, const V& b) { return detail::expression::left_type, typename detail::expression::right_type, V>(a.left(), a.right(), b); } template inline detail::expression::left_type, typename detail::expression::right_type, number > operator + (const number& a, const detail::expression& b) { return detail::expression::left_type, typename detail::expression::right_type, number >(b.left(), b.right(), a); } template inline detail::expression::left_type, typename detail::expression::right_type, number > operator + (const detail::expression& a, const number& b) { return detail::expression::left_type, typename detail::expression::right_type, number >(a.left(), a.right(), b); } // // Fused multiply subtract: // template inline typename enable_if::result_type>, detail::expression::left_type, typename detail::expression::right_type, V> > >::type operator - (const V& a, const detail::expression& b) { return detail::expression::left_type, typename detail::expression::right_type, V> > (detail::expression::left_type, typename detail::expression::right_type, V>(b.left(), b.right(), a)); } template inline typename enable_if::result_type>, detail::expression::left_type, typename detail::expression::right_type, V> >::type operator - (const detail::expression& a, const V& b) { return detail::expression::left_type, typename detail::expression::right_type, V>(a.left(), a.right(), b); } template inline detail::expression::left_type, typename detail::expression::right_type, number > > operator - (const number& a, const detail::expression& b) { return detail::expression::left_type, typename detail::expression::right_type, number > > (detail::expression::left_type, typename detail::expression::right_type, number >(b.left(), b.right(), a)); } template inline detail::expression::left_type, typename detail::expression::right_type, number > operator - (const detail::expression& a, const number& b) { return detail::expression::left_type, typename detail::expression::right_type, number >(a.left(), a.right(), b); } // // Repeat operator for negated arguments: propagate the negation to the top level to avoid temporaries: // template inline detail::expression, Arg1> operator + (const number& a, const detail::expression& b) { return detail::expression, Arg1>(a, b.left_ref()); } template inline detail::expression, Arg1> operator + (const detail::expression& a, const number& b) { return detail::expression, Arg1>(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, Arg1> operator - (const number& a, const detail::expression& b) { return detail::expression, Arg1>(a, b.left_ref()); } template inline detail::expression, Arg1> > operator - (const detail::expression& a, const number& b) { return detail::expression, Arg1> >( detail::expression, Arg1>(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, Arg1> > operator * (const number& a, const detail::expression& b) { return detail::expression, Arg1> >( detail::expression, Arg1> (a, b.left_ref())); } template inline detail::expression, Arg1> > operator * (const detail::expression& a, const number& b) { return detail::expression, Arg1> >( detail::expression, Arg1>(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, Arg1> > operator / (const number& a, const detail::expression& b) { return detail::expression, Arg1> >( detail::expression, Arg1>(a, b.left_ref())); } template inline detail::expression > > operator / (const detail::expression& a, const number& b) { return detail::expression > >( detail::expression >(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 typename enable_if_c::value == number_kind_integer, detail::expression, number > >::type operator % (const number& a, const number& b) { return detail::expression, number >(a, b); } template inline typename enable_if_c >::value && (number_category::value == number_kind_integer), detail::expression, V > >::type operator % (const number& a, const V& b) { return detail::expression, V >(a, b); } template inline typename enable_if_c >::value && (number_category::value == number_kind_integer), detail::expression > >::type operator % (const V& a, const number& b) { return detail::expression >(a, b); } template inline typename enable_if_c::value == number_kind_integer, detail::expression, detail::expression > >::type operator % (const number& a, const detail::expression& b) { return detail::expression, detail::expression >(a, b); } template inline typename enable_if_c::value == number_kind_integer, detail::expression, number > >::type operator % (const detail::expression& a, const number& b) { return detail::expression, number >(a, b); } template inline typename enable_if_c::result_type>::value == number_kind_integer, detail::expression, detail::expression > >::type operator % (const detail::expression& a, const detail::expression& b) { return detail::expression, detail::expression >(a, b); } template inline typename enable_if_c::result_type>::value && (number_category::result_type>::value == number_kind_integer), detail::expression, V > >::type operator % (const detail::expression& a, const V& b) { return detail::expression, V >(a, b); } template inline typename enable_if_c::result_type>::value && (number_category::result_type>::value == number_kind_integer), detail::expression > >::type operator % (const V& a, const detail::expression& b) { return detail::expression >(a, b); } // // Left shift: // template inline typename enable_if_c::value && (number_category::value == number_kind_integer), detail::expression, I > >::type operator << (const number& a, const I& b) { return detail::expression, I>(a, b); } template inline typename enable_if_c::value && (number_category::result_type>::value == number_kind_integer), 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_c::value && (number_category::value == number_kind_integer), detail::expression, I > >::type operator >> (const number& a, const I& b) { return detail::expression, I>(a, b); } template inline typename enable_if_c::value && (number_category::result_type>::value == number_kind_integer), detail::expression, I> >::type operator >> (const detail::expression& a, const I& b) { return detail::expression, I>(a, b); } // // Bitwise AND: // template inline typename enable_if_c::value == number_kind_integer, detail::expression, number > >::type operator & (const number& a, const number& b) { return detail::expression, number >(a, b); } template inline typename enable_if_c >::value && (number_category::value == number_kind_integer), detail::expression, V > >::type operator & (const number& a, const V& b) { return detail::expression, V >(a, b); } template inline typename enable_if_c >::value && (number_category::value == number_kind_integer), detail::expression > >::type operator & (const V& a, const number& b) { return detail::expression >(a, b); } template inline typename enable_if_c::value == number_kind_integer, detail::expression, detail::expression > >::type operator & (const number& a, const detail::expression& b) { return detail::expression, detail::expression >(a, b); } template inline typename enable_if_c::value == number_kind_integer, detail::expression, number > >::type operator & (const detail::expression& a, const number& b) { return detail::expression, number >(a, b); } template inline typename enable_if_c::result_type>::value == number_kind_integer, detail::expression, detail::expression > >::type operator & (const detail::expression& a, const detail::expression& b) { return detail::expression, detail::expression >(a, b); } template inline typename enable_if_c::result_type>::value && (number_category::result_type>::value == number_kind_integer), detail::expression, V > >::type operator & (const detail::expression& a, const V& b) { return detail::expression, V >(a, b); } template inline typename enable_if_c::result_type>::value && (number_category::result_type>::value == number_kind_integer), detail::expression > >::type operator & (const V& a, const detail::expression& b) { return detail::expression >(a, b); } // // Bitwise OR: // template inline typename enable_if_c::value == number_kind_integer, detail::expression, number > >::type operator| (const number& a, const number& b) { return detail::expression, number >(a, b); } template inline typename enable_if_c >::value && (number_category::value == number_kind_integer), detail::expression, V > >::type operator| (const number& a, const V& b) { return detail::expression, V >(a, b); } template inline typename enable_if_c >::value && (number_category::value == number_kind_integer), detail::expression > >::type operator| (const V& a, const number& b) { return detail::expression >(a, b); } template inline typename enable_if_c::value == number_kind_integer, detail::expression, detail::expression > >::type operator| (const number& a, const detail::expression& b) { return detail::expression, detail::expression >(a, b); } template inline typename enable_if_c::value == number_kind_integer, detail::expression, number > >::type operator| (const detail::expression& a, const number& b) { return detail::expression, number >(a, b); } template inline typename enable_if_c::result_type>::value == number_kind_integer, detail::expression, detail::expression > >::type operator| (const detail::expression& a, const detail::expression& b) { return detail::expression, detail::expression >(a, b); } template inline typename enable_if_c::result_type>::value && (number_category::result_type>::value == number_kind_integer), detail::expression, V > >::type operator| (const detail::expression& a, const V& b) { return detail::expression, V >(a, b); } template inline typename enable_if_c::result_type>::value && (number_category::result_type>::value == number_kind_integer), detail::expression > >::type operator| (const V& a, const detail::expression& b) { return detail::expression >(a, b); } // // Bitwise XOR: // template inline typename enable_if_c::value == number_kind_integer, detail::expression, number > >::type operator^ (const number& a, const number& b) { return detail::expression, number >(a, b); } template inline typename enable_if_c >::value && (number_category::value == number_kind_integer), detail::expression, V > >::type operator^ (const number& a, const V& b) { return detail::expression, V >(a, b); } template inline typename enable_if_c >::value && (number_category::value == number_kind_integer), detail::expression > >::type operator^ (const V& a, const number& b) { return detail::expression >(a, b); } template inline typename enable_if_c::value == number_kind_integer, detail::expression, detail::expression > >::type operator^ (const number& a, const detail::expression& b) { return detail::expression, detail::expression >(a, b); } template inline typename enable_if_c::value == number_kind_integer, detail::expression, number > >::type operator^ (const detail::expression& a, const number& b) { return detail::expression, number >(a, b); } template inline typename enable_if_c::result_type>::value == number_kind_integer, detail::expression, detail::expression > >::type operator^ (const detail::expression& a, const detail::expression& b) { return detail::expression, detail::expression >(a, b); } template inline typename enable_if_c::result_type>::value && (number_category::result_type>::value == number_kind_integer), detail::expression, V > >::type operator^ (const detail::expression& a, const V& b) { return detail::expression, V >(a, b); } template inline typename enable_if_c::result_type>::value && (number_category::result_type>::value == number_kind_integer), detail::expression > >::type operator^ (const V& a, const detail::expression& b) { return detail::expression >(a, b); } }} // namespaces #endif