Correct and improve 2-arg pass through constructors.

Correct ET operators for pre-C++17.
Add test case for allocator usage.
This commit is contained in:
jzmaddock
2021-09-25 08:48:03 +01:00
parent 43f8469f20
commit b80a573602
8 changed files with 742 additions and 250 deletions
@@ -77,6 +77,18 @@ struct complex_adaptor
m_real = val.real();
m_imag = val.imag();
}
template <class T, class U>
complex_adaptor(const T& a, const U& b, typename std::enable_if<std::is_constructible<Backend, T const&>::value&& std::is_constructible<Backend, U const&>::value>::type const* = nullptr)
: m_real(a), m_imag(b) {}
template <class T, class U>
complex_adaptor(T&& a, const U& b, typename std::enable_if<std::is_constructible<Backend, T>::value&& std::is_constructible<Backend, U>::value>::type const* = nullptr)
: m_real(static_cast<T&&>(a)), m_imag(b) {}
template <class T, class U>
complex_adaptor(T&& a, U&& b, typename std::enable_if<std::is_constructible<Backend, T>::value&& std::is_constructible<Backend, U>::value>::type const* = nullptr)
: m_real(static_cast<T&&>(a)), m_imag(static_cast<U&&>(b)) {}
template <class T, class U>
complex_adaptor(const T& a, U&& b, typename std::enable_if<std::is_constructible<Backend, T>::value&& std::is_constructible<Backend, U>::value>::type const* = nullptr)
: m_real(a), m_imag(static_cast<U&&>(b)) {}
complex_adaptor& operator=(const complex_adaptor& o)
{
+339 -225
View File
@@ -142,18 +142,21 @@ operator+(const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3
}
template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
std::is_same<typename detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET> >::value,
typename detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
operator+(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
BOOST_IF_CONSTEXPR(std::is_same<typename detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET> >::value)
{
a += b;
return static_cast<number<B, et_on>&&>(a);
}
else
{
return detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
a += b;
return static_cast<number<B, et_on>&&>(a);
}
template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
!std::is_same<typename detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET> >::value,
typename detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
operator+(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::plus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
@@ -164,18 +167,21 @@ operator+(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
std::is_same<typename detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type, number<B, ET>>::value,
typename detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type>::type
operator+(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
{
BOOST_IF_CONSTEXPR(std::is_same<typename detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type, number<B, ET>>::value)
{
b += a;
return static_cast<number<B, et_on>&&>(b);
}
else
{
return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
}
b += a;
return static_cast<number<B, et_on>&&>(b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
!std::is_same<typename detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type, number<B, ET>>::value,
typename detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type>::type
operator+(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
{
return detail::expression<detail::plus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
@@ -221,18 +227,21 @@ operator+(const number<B, ET>& a, const detail::expression<detail::multiply_imme
}
template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
std::is_same<typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type, number<B, ET>>::value,
typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type>::type
operator+(number<B, ET>&& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
{
BOOST_IF_CONSTEXPR(std::is_same<typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type, number<B, ET>>::value)
{
a += b;
return static_cast<number<B, et_on>&&>(a);
}
else
{
return detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >(b.left(), b.right(), a);
}
a += b;
return static_cast<number<B, et_on>&&>(a);
}
template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
!std::is_same<typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type, number<B, ET>>::value,
typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type>::type
operator+(number<B, ET>&& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >(b.left(), b.right(), a);
}
template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
@@ -243,18 +252,21 @@ operator+(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3
}
template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
std::is_same<typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type, number<B, ET>>::value,
typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type>::type
operator+(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
{
BOOST_IF_CONSTEXPR(std::is_same<typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type, number<B, ET>>::value)
{
b += a;
return static_cast<number<B, et_on>&&>(b);
}
else
{
return detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >(a.left(), a.right(), b);
}
b += a;
return static_cast<number<B, et_on>&&>(b);
}
template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
!std::is_same<typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type, number<B, ET>>::value,
typename detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >::result_type>::type
operator+(const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
{
return detail::expression<detail::multiply_add, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >(a.left(), a.right(), b);
}
//
@@ -282,18 +294,21 @@ operator-(const number<B, ET>& a, const detail::expression<detail::multiply_imme
}
template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> > >::result_type
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
std::is_same<typename detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> > >::result_type, number<B, ET>>::value,
typename detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> > >::result_type>::type
operator-(number<B, ET>&& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
{
BOOST_IF_CONSTEXPR(std::is_same<typename detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> > >::result_type, number<B, ET>>::value)
{
a -= b;
return static_cast<number<B, et_on>&&>(a);
}
else
{
return detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> > >(detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >(b.left(), b.right(), a));
}
a -= b;
return static_cast<number<B, et_on>&&>(a);
}
template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
!std::is_same<typename detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> > >::result_type, number<B, ET>>::value,
typename detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> > >::result_type>::type
operator-(number<B, ET>&& a, const detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::negate, detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> > >(detail::expression<detail::multiply_subtract, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::left_type, typename detail::expression<detail::multiply_immediates, Arg1, Arg2, Arg3, Arg4>::right_type, number<B, ET> >(b.left(), b.right(), a));
}
template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
@@ -321,18 +336,21 @@ operator+(const number<B, ET>& a, const detail::expression<detail::negate, Arg1,
}
template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
std::is_same<typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type, number<B, ET>>::value,
typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type>::type
operator+(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
{
BOOST_IF_CONSTEXPR(std::is_same<typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type, number<B, ET>>::value)
{
a -= b.left_ref();
return static_cast<number<B, et_on>&&>(a);
}
else
{
return detail::expression<detail::minus, number<B, ET>, Arg1>(a, b.left_ref());
}
a -= b.left_ref();
return static_cast<number<B, et_on>&&>(a);
}
template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
!std::is_same<typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type, number<B, ET>>::value,
typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type>::type
operator+(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::minus, number<B, ET>, Arg1>(a, b.left_ref());
}
template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
@@ -343,18 +361,21 @@ operator+(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, c
}
template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
std::is_same<typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type, number<B, ET>>::value,
typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type>::type
operator+(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
{
BOOST_IF_CONSTEXPR(std::is_same<typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type, number<B, ET>>::value)
{
b -= a.left_ref();
return static_cast<number<B, et_on>&&>(b);
}
else
{
return detail::expression<detail::minus, number<B, ET>, Arg1>(b, a.left_ref());
}
b -= a.left_ref();
return static_cast<number<B, et_on>&&>(b);
}
template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
!std::is_same<typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type, number<B, ET>>::value,
typename detail::expression<detail::minus, number<B, ET>, Arg1>::result_type>::type
operator+(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
{
return detail::expression<detail::minus, number<B, ET>, Arg1>(b, a.left_ref());
}
template <class B>
@@ -506,18 +527,21 @@ operator-(const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3
}
template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
std::is_same<typename detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET>>::value,
typename detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
operator-(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
BOOST_IF_CONSTEXPR(std::is_same<typename detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET>>::value)
{
a -= b;
return static_cast<number<B, et_on>&&>(a);
}
else
{
return detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
a -= b;
return static_cast<number<B, et_on>&&>(a);
}
template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
!std::is_same<typename detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET>>::value,
typename detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
operator-(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::minus, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
@@ -528,19 +552,22 @@ operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
std::is_same<typename detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type, number<B, ET>>::value,
typename detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type>::type
operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
{
BOOST_IF_CONSTEXPR(std::is_same<typename detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type, number<B, ET>>::value)
{
b -= a;
b.backend().negate();
return static_cast<number<B, et_on>&&>(b);
}
else
{
return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
}
b -= a;
b.backend().negate();
return static_cast<number<B, et_on>&&>(b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
!std::is_same<typename detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type, number<B, ET>>::value,
typename detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type>::type
operator-(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
{
return detail::expression<detail::minus, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
@@ -572,16 +599,21 @@ operator-(const number<B, ET>& a, const detail::expression<detail::negate, Arg1,
}
template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::plus, number<B, ET>, Arg1>::result_type
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
std::is_same<typename detail::expression<detail::plus, number<B, ET>, Arg1>::result_type, number<B, ET>>::value,
typename detail::expression<detail::plus, number<B, ET>, Arg1>::result_type>::type
operator-(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
{
BOOST_IF_CONSTEXPR(std::is_same<typename detail::expression<detail::plus, number<B, ET>, Arg1>::result_type, number<B, ET>>::value)
{
a += b.left_ref();
return static_cast<number<B, et_on>&&>(a);
}
else
return detail::expression<detail::plus, number<B, ET>, Arg1>(a, b.left_ref());
a += b.left_ref();
return static_cast<number<B, et_on>&&>(a);
}
template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
!std::is_same<typename detail::expression<detail::plus, number<B, ET>, Arg1>::result_type, number<B, ET>>::value,
typename detail::expression<detail::plus, number<B, ET>, Arg1>::result_type>::type
operator-(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::plus, number<B, ET>, Arg1>(a, b.left_ref());
}
template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
@@ -593,17 +625,22 @@ operator-(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, c
}
template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >::result_type
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
std::is_same<typename detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >::result_type, number<B, ET>>::value,
typename detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >::result_type>::type
operator-(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
{
BOOST_IF_CONSTEXPR(std::is_same<typename detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >::result_type, number<B, ET>>::value)
{
b += a.left_ref();
b.backend().negate();
return static_cast<number<B, et_on>&&>(b);
}
else
return detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >(detail::expression<detail::plus, number<B, ET>, Arg1>(b, a.left_ref()));
b += a.left_ref();
b.backend().negate();
return static_cast<number<B, et_on>&&>(b);
}
template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
!std::is_same<typename detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >::result_type, number<B, ET>>::value,
typename detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >::result_type>::type
operator-(const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
{
return detail::expression<detail::negate, detail::expression<detail::plus, number<B, ET>, Arg1> >(detail::expression<detail::plus, number<B, ET>, Arg1>(b, a.left_ref()));
}
template <class B>
@@ -631,18 +668,23 @@ operator-(const detail::expression<detail::negate, number<B, et_on> >& a, const
}
template <class B>
inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >::result_type
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
std::is_same<typename detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >::result_type, number<B, et_on>>::value,
typename detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >::result_type>::type
operator-(const detail::expression<detail::negate, number<B, et_on> >& a, number<B, et_on>&& b)
{
BOOST_IF_CONSTEXPR(std::is_same<typename detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >::result_type, number<B, et_on>>::value)
{
using default_ops::eval_add;
eval_add(b.backend(), a.left_ref().backend());
b.backend().negate();
return static_cast<number<B, et_on>&&>(b);
}
else
return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >(
using default_ops::eval_add;
eval_add(b.backend(), a.left_ref().backend());
b.backend().negate();
return static_cast<number<B, et_on>&&>(b);
}
template <class B>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
!std::is_same<typename detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >::result_type, number<B, et_on>>::value,
typename detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >::result_type>::type
operator-(const detail::expression<detail::negate, number<B, et_on> >& a, number<B, et_on>&& b)
{
return detail::expression<detail::negate, detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> > >(
detail::expression<detail::add_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref()));
}
@@ -761,16 +803,21 @@ operator*(const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3
}
template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
std::is_same<typename detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET>>::value,
typename detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
operator*(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
BOOST_IF_CONSTEXPR(std::is_same<typename detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET>>::value)
{
a *= b;
return static_cast<number<B, et_on>&&>(a);
}
else
return detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
a *= b;
return static_cast<number<B, et_on>&&>(a);
}
template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
!std::is_same<typename detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET>>::value,
typename detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
operator*(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::multiplies, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
@@ -781,16 +828,21 @@ operator*(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
std::is_same<typename detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type, number<B, ET>>::value,
typename detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type>::type
operator*(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
{
BOOST_IF_CONSTEXPR(std::is_same<typename detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type, number<B, ET>>::value)
{
b *= a;
return static_cast<number<B, et_on>&&>(b);
}
else
return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
b *= a;
return static_cast<number<B, et_on>&&>(b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
!std::is_same<typename detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type, number<B, ET>>::value,
typename detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >::result_type>::type
operator*(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, ET>&& b)
{
return detail::expression<detail::multiplies, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
@@ -855,17 +907,22 @@ operator*(const number<B, et_on>& a, const detail::expression<detail::negate, nu
}
template <class B>
inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
std::is_same<typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type, number<B, et_on>>::value,
typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type>::type
operator*(number<B, et_on>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
{
BOOST_IF_CONSTEXPR(std::is_same<typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type, number<B, et_on>>::value)
{
a *= b.left_ref();
a.backend().negate();
return static_cast<number<B, et_on>&&>(a);
}
else
return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >(
a *= b.left_ref();
a.backend().negate();
return static_cast<number<B, et_on>&&>(a);
}
template <class B>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
!std::is_same<typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type, number<B, et_on>>::value,
typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type>::type
operator*(number<B, et_on>&& a, const detail::expression<detail::negate, number<B, et_on> >& b)
{
return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >(
detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(a, b.left_ref()));
}
@@ -878,17 +935,22 @@ operator*(const detail::expression<detail::negate, number<B, et_on> >& a, const
}
template <class B>
inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
std::is_same<typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type, number<B, et_on>>::value,
typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type>::type
operator*(const detail::expression<detail::negate, number<B, et_on> >& a, number<B, et_on>&& b)
{
BOOST_IF_CONSTEXPR(std::is_same<typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type, number<B, et_on>>::value)
{
b *= a.left_ref();
b.backend().negate();
return static_cast<number<B, et_on>&&>(b);
}
else
return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >(
b *= a.left_ref();
b.backend().negate();
return static_cast<number<B, et_on>&&>(b);
}
template <class B>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
!std::is_same<typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type, number<B, et_on>>::value,
typename detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >::result_type>::type
operator*(const detail::expression<detail::negate, number<B, et_on> >& a, number<B, et_on>&& b)
{
return detail::expression<detail::negate, detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> > >(
detail::expression<detail::multiply_immediates, number<B, et_on>, number<B, et_on> >(b, a.left_ref()));
}
@@ -1002,16 +1064,21 @@ operator/(const number<B, ET>& a, const detail::expression<tag, Arg1, Arg2, Arg3
return detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
inline BOOST_MP_CXX14_CONSTEXPR typename detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
std::is_same<typename detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET>>::value,
typename detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
operator/(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
BOOST_IF_CONSTEXPR(std::is_same<typename detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET>>::value)
{
a /= b;
return static_cast<number<B, ET>&&>(a);
}
else
return detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
a /= b;
return static_cast<number<B, ET>&&>(a);
}
template <class B, expression_template_option ET, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
!std::is_same<typename detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, ET>>::value,
typename detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
operator/(number<B, ET>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::divides, number<B, ET>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
inline BOOST_MP_CXX14_CONSTEXPR detail::expression<detail::divides, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, ET> >
@@ -1054,17 +1121,22 @@ operator/(const number<B, ET>& a, const detail::expression<detail::negate, Arg1,
detail::expression<detail::divides, number<B, ET>, Arg1>(a, b.left_ref()));
}
template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
inline typename detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >::result_type
inline typename std::enable_if<
std::is_same<typename detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >::result_type, number<B, ET>>::value,
typename detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >::result_type>::type
operator/(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
{
BOOST_IF_CONSTEXPR(std::is_same<typename detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >::result_type, number<B, ET>>::value)
{
a /= b.left_ref();
a.backend().negate();
return static_cast<number<B, ET>&&>(a);
}
else
return detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >(
a /= b.left_ref();
a.backend().negate();
return static_cast<number<B, ET>&&>(a);
}
template <class B, expression_template_option ET, class Arg1, class Arg2, class Arg3, class Arg4>
inline typename std::enable_if<
!std::is_same<typename detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >::result_type, number<B, ET>>::value,
typename detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >::result_type>::type
operator/(number<B, ET>&& a, const detail::expression<detail::negate, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::negate, detail::expression<detail::divides, number<B, ET>, Arg1> >(
detail::expression<detail::divides, number<B, ET>, Arg1>(a, b.left_ref()));
}
template <class Arg1, class Arg2, class Arg3, class Arg4, class B, expression_template_option ET>
@@ -1225,17 +1297,23 @@ operator%(const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, A
return detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
std::is_same<typename detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
&& number_category<B>::value == number_kind_integer,
typename detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type >::type
operator%(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
BOOST_IF_CONSTEXPR(std::is_same<typename detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value)
{
a %= b;
return static_cast<number<B, et_on>&&>(a);
}
else
return detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
a %= b;
return static_cast<number<B, et_on>&&>(a);
}
template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
!std::is_same<typename detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
&& number_category<B>::value == number_kind_integer,
typename detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type >::type
operator%(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::modulus, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
@@ -1399,17 +1477,23 @@ operator&(const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, A
return detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
std::is_same<typename detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
&& number_category<B>::value == number_kind_integer,
typename detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type >::type
operator&(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
BOOST_IF_CONSTEXPR(std::is_same<typename detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value)
{
a &= b;
return static_cast<number<B, et_on>&&>(a);
}
else
return detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
a &= b;
return static_cast<number<B, et_on>&&>(a);
}
template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
!std::is_same<typename detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
&& number_category<B>::value == number_kind_integer,
typename detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type >::type
operator&(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::bitwise_and, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
@@ -1419,17 +1503,23 @@ operator&(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number
return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
std::is_same<typename detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type, number<B, et_on>>::value
&& number_category<B>::value == number_kind_integer,
typename detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type >::type
operator&(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
{
BOOST_IF_CONSTEXPR(std::is_same<typename detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type, number<B, et_on>>::value)
{
b &= a;
return static_cast<number<B, et_on>&&>(b);
}
else
return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
b &= a;
return static_cast<number<B, et_on>&&>(b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
!std::is_same<typename detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type, number<B, et_on>>::value
&& number_category<B>::value == number_kind_integer,
typename detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type >::type
operator&(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
{
return detail::expression<detail::bitwise_and, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
@@ -1529,17 +1619,23 @@ operator|(const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, A
return detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
std::is_same<typename detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
&& number_category<B>::value == number_kind_integer,
typename detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
operator|(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
BOOST_IF_CONSTEXPR(std::is_same<typename detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value)
{
a |= b;
return static_cast<number<B, et_on>&&>(a);
}
else
return detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
a |= b;
return static_cast<number<B, et_on>&&>(a);
}
template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
!std::is_same<typename detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
&& number_category<B>::value == number_kind_integer,
typename detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
operator|(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::bitwise_or, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
@@ -1549,17 +1645,23 @@ operator|(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number
return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
std::is_same<typename detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type, number<B, et_on>>::value
&& number_category<B>::value == number_kind_integer,
typename detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type>::type
operator|(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
{
BOOST_IF_CONSTEXPR(std::is_same<typename detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type, number<B, et_on>>::value)
{
b |= a;
return static_cast<number<B, et_on>&&>(b);
}
else
return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
b |= a;
return static_cast<number<B, et_on>&&>(b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
!std::is_same<typename detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type, number<B, et_on>>::value
&& number_category<B>::value == number_kind_integer,
typename detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type>::type
operator|(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
{
return detail::expression<detail::bitwise_or, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
@@ -1659,17 +1761,23 @@ operator^(const number<B, et_on>& a, const detail::expression<tag, Arg1, Arg2, A
return detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
std::is_same<typename detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
&& number_category<B>::value == number_kind_integer,
typename detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
operator^(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
BOOST_IF_CONSTEXPR(std::is_same<typename detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value)
{
a ^= b;
return static_cast<number<B, et_on>&&>(a);
}
else
return detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
a ^= b;
return static_cast<number<B, et_on>&&>(a);
}
template <class B, class tag, class Arg1, class Arg2, class Arg3, class Arg4>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
!std::is_same<typename detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type, number<B, et_on>>::value
&& number_category<B>::value == number_kind_integer,
typename detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >::result_type>::type
operator^(number<B, et_on>&& a, const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& b)
{
return detail::expression<detail::bitwise_xor, number<B, et_on>, detail::expression<tag, Arg1, Arg2, Arg3, Arg4> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
@@ -1679,17 +1787,23 @@ operator^(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, const number
return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer,
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
std::is_same<typename detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type, number<B, et_on>>::value
&& number_category<B>::value == number_kind_integer,
typename detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type>::type
operator^(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
{
BOOST_IF_CONSTEXPR(std::is_same<typename detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type, number<B, et_on>>::value)
{
b ^= a;
return static_cast<number<B, et_on>&&>(b);
}
else
return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
b ^= a;
return static_cast<number<B, et_on>&&>(b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class B>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<
!std::is_same<typename detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type, number<B, et_on>>::value
&& number_category<B>::value == number_kind_integer,
typename detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >::result_type>::type
operator^(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& a, number<B, et_on>&& b)
{
return detail::expression<detail::bitwise_xor, detail::expression<tag, Arg1, Arg2, Arg3, Arg4>, number<B, et_on> >(a, b);
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4, class tag2, class Arg1b, class Arg2b, class Arg3b, class Arg4b>
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value == number_kind_integer,
+182
View File
@@ -2227,6 +2227,20 @@ struct gmp_rational
mpz_init_set(&m_data[0]._mp_den, b.data());
mpq_canonicalize(m_data);
}
gmp_rational(const gmp_int& a, gmp_int&& b)
{
mpz_init_set(&m_data[0]._mp_num, a.data());
m_data[0]._mp_den = b.data()[0];
mpq_canonicalize(m_data);
b.data()[0]._mp_d = nullptr;
}
gmp_rational(gmp_int&& a, const gmp_int& b)
{
m_data[0]._mp_num = a.data()[0];
mpz_init_set(&m_data[0]._mp_den, b.data());
mpq_canonicalize(m_data);
a.data()[0]._mp_d = nullptr;
}
gmp_rational(gmp_int&& a, gmp_int&& b)
{
m_data[0]._mp_num = a.data()[0];
@@ -2531,6 +2545,174 @@ inline void eval_divide(gmp_rational& t, const gmp_rational& p, const gmp_ration
BOOST_THROW_EXCEPTION(std::overflow_error("Division by zero."));
mpq_div(t.data(), p.data(), o.data());
}
//
// operator with scalars:
//
inline void eval_add(gmp_rational& result, gmp_rational const& a, gmp_int const& b)
{
// we allow result and a to be the same object here:
if (&a != &result)
{
mpz_set(mpq_numref(result.data()), mpq_numref(a.data()));
mpz_set(mpq_denref(result.data()), mpq_denref(a.data()));
}
mpz_addmul(mpq_numref(result.data()), mpq_denref(a.data()), b.data());
// no need to normalize, there can be no common divisor as long as a is already normalized.
}
inline void eval_add(gmp_rational& result, gmp_rational const& a, unsigned long b)
{
// we allow result and a to be the same object here:
if (&a != &result)
{
mpz_set(mpq_numref(result.data()), mpq_numref(a.data()));
mpz_set(mpq_denref(result.data()), mpq_denref(a.data()));
}
mpz_addmul_ui(mpq_numref(result.data()), mpq_denref(a.data()), b);
// no need to normalize, there can be no common divisor as long as a is already normalized.
}
inline void eval_add(gmp_rational& result, gmp_rational const& a, long b)
{
// we allow result and a to be the same object here:
if (&a != &result)
{
mpz_set(mpq_numref(result.data()), mpq_numref(a.data()));
mpz_set(mpq_denref(result.data()), mpq_denref(a.data()));
}
if(b > 0)
mpz_addmul_ui(mpq_numref(result.data()), mpq_denref(a.data()), b);
else
mpz_submul_ui(mpq_numref(result.data()), mpq_denref(a.data()), boost::multiprecision::detail::unsigned_abs(b));
// no need to normalize, there can be no common divisor as long as a is already normalized.
}
template <class T>
inline void eval_add(gmp_rational& result, gmp_rational const& a, const T& b)
{
gmp_int t;
t = b;
eval_add(result, a, t);
}
template <class T>
inline void eval_add(gmp_rational& result, const T& b, gmp_rational const& a)
{
eval_add(result, a, b);
}
template <class T>
inline void eval_add(gmp_rational& result, const T& b)
{
eval_add(result, result, b);
}
inline void eval_subtract(gmp_rational& result, gmp_rational const& a, gmp_int const& b)
{
// we allow result and a to be the same object here:
if (&a != &result)
{
mpz_set(mpq_numref(result.data()), mpq_numref(a.data()));
mpz_set(mpq_denref(result.data()), mpq_denref(a.data()));
}
mpz_submul(mpq_numref(result.data()), mpq_denref(a.data()), b.data());
// no need to normalize, there can be no common divisor as long as a is already normalized.
}
inline void eval_subtract(gmp_rational& result, gmp_rational const& a, unsigned long b)
{
// we allow result and a to be the same object here:
if (&a != &result)
{
mpz_set(mpq_numref(result.data()), mpq_numref(a.data()));
mpz_set(mpq_denref(result.data()), mpq_denref(a.data()));
}
mpz_submul_ui(mpq_numref(result.data()), mpq_denref(a.data()), b);
// no need to normalize, there can be no common divisor as long as a is already normalized.
}
inline void eval_subtract(gmp_rational& result, gmp_rational const& a, long b)
{
// we allow result and a to be the same object here:
if (&a != &result)
{
mpz_set(mpq_numref(result.data()), mpq_numref(a.data()));
mpz_set(mpq_denref(result.data()), mpq_denref(a.data()));
}
if(b > 0)
mpz_submul_ui(mpq_numref(result.data()), mpq_denref(a.data()), b);
else
mpz_addmul_ui(mpq_numref(result.data()), mpq_denref(a.data()), boost::multiprecision::detail::unsigned_abs(b));
// no need to normalize, there can be no common divisor as long as a is already normalized.
}
template <class T>
inline void eval_subtract(gmp_rational& result, gmp_rational const& a, const T& b)
{
gmp_int t;
t = b;
eval_subtract(result, a, t);
}
template <class T>
inline void eval_subtract(gmp_rational& result, const T& b, gmp_rational const& a)
{
eval_subtract(result, a, b);
result.negate();
}
template <class T>
inline void eval_subtract(gmp_rational& result, const T& b)
{
eval_subtract(result, result, b);
}
inline void eval_multiply(gmp_rational& result, gmp_rational const& a, gmp_int const& b)
{
gmp_int g, t;
mpz_gcd(g.data(), mpq_denref(a.data()), b.data());
if (!mpz_fits_uint_p(g.data()) || (mpz_get_ui(g.data()) != 1))
{
eval_divide(t, b, g);
mpz_mul(mpq_numref(result.data()), t.data(), mpq_numref(a.data()));
mpz_div(mpq_denref(result.data()), mpq_denref(a.data()), g.data());
}
else
{
mpz_mul(mpq_numref(result.data()), mpq_numref(a.data()), b.data());
if (&result != &a)
mpz_set(mpq_denref(result.data()), mpq_denref(a.data()));
}
}
inline void eval_multiply(gmp_rational& result, gmp_rational const& a, unsigned long b)
{
gmp_int g;
mpz_gcd_ui(g.data(), mpq_denref(a.data()), b);
if (!mpz_fits_uint_p(g.data()) || (mpz_get_ui(g.data()) != 1))
{
b /= mpz_get_ui(g.data());
mpz_mul_ui(mpq_numref(result.data()), mpq_numref(a.data()), b);
mpz_div(mpq_denref(result.data()), mpq_denref(a.data()), g.data());
}
else
{
mpz_mul_ui(mpq_numref(result.data()), mpq_numref(a.data()), b);
if (&result != &a)
mpz_set(mpq_denref(result.data()), mpq_denref(a.data()));
}
}
inline void eval_multiply(gmp_rational& result, gmp_rational const& a, long b)
{
eval_multiply(result, a, boost::multiprecision::detail::unsigned_abs(b));
if (b < 0)
result.negate();
}
template <class T>
inline void eval_multiply(gmp_rational& result, gmp_rational const& a, const T& b)
{
gmp_int t;
t = b;
eval_multiply(result, a, t);
}
template <class T>
inline void eval_multiply(gmp_rational& result, const T& b, gmp_rational const& a)
{
eval_multiply(result, a, b);
}
template <class T>
inline void eval_multiply(gmp_rational& result, const T& b)
{
eval_multiply(result, result, b);
}
inline int eval_get_sign(const gmp_rational& val)
{
@@ -100,13 +100,15 @@ struct logged_adaptor
{
log_postfix_event(m_value, "construct from a pair of arithmetic types");
}
logged_adaptor(const Backend& i, unsigned digits10)
template <class D = Backend>
logged_adaptor(const Backend& i, unsigned digits10, typename std::enable_if<std::is_constructible<D, Backend const&, unsigned>::value>::type const* = nullptr)
: m_value(i, digits10)
{
log_postfix_event(m_value, "construct from arithmetic type and precision");
}
logged_adaptor(const logged_adaptor<Backend>& i, unsigned digits10)
: m_value(i, digits10)
template <class D = Backend>
logged_adaptor(const logged_adaptor<Backend>& i, unsigned digits10, typename std::enable_if<std::is_constructible<D, Backend const&, unsigned>::value>::type const* = nullptr)
: m_value(i.value(), digits10)
{
log_postfix_event(m_value, "construct from arithmetic type and precision");
}
+11 -6
View File
@@ -158,7 +158,7 @@ class number
(std::is_convertible<V, value_type>::value
&& std::is_convertible<U, value_type>::value
&& !std::is_same<value_type, self_type>::value
&& std::is_constructible<Backend, typename detail::canonical<Backend, decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type const&, typename detail::canonical<Backend, decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type const&>::value
&& std::is_constructible<Backend, typename detail::canonical<typename remove_cv<typename remove_reference<decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename remove_cv<typename remove_reference<decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type>::type, Backend>::type const&>::value
&& !boost::multiprecision::detail::is_variable_precision<Backend>::value)>::type* = 0)
: m_backend(canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)))
{
@@ -169,7 +169,7 @@ class number
(std::is_convertible<V, value_type>::value
&& std::is_convertible<U, value_type>::value
&& !std::is_same<value_type, self_type>::value
&& std::is_constructible<Backend, typename detail::canonical<Backend, decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type const&, typename detail::canonical<Backend, decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type const&>::value
&& std::is_constructible<Backend, typename detail::canonical<typename remove_cv<typename remove_reference<decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename remove_cv<typename remove_reference<decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type>::type, Backend>::type const&>::value
&& !boost::multiprecision::detail::is_variable_precision<Backend>::value)>::type* = 0)
: m_backend(canonical_value(detail::evaluate_if_expression(static_cast<V&&>(v1))), canonical_value(detail::evaluate_if_expression(v2)))
{
@@ -180,7 +180,7 @@ class number
(std::is_convertible<V, value_type>::value
&& std::is_convertible<U, value_type>::value
&& !std::is_same<value_type, self_type>::value
&& std::is_constructible<Backend, typename detail::canonical<Backend, decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type const&, typename detail::canonical<Backend, decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type const&>::value
&& std::is_constructible<Backend, typename detail::canonical<typename remove_cv<typename remove_reference<decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename remove_cv<typename remove_reference<decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type>::type, Backend>::type const&>::value
&& !boost::multiprecision::detail::is_variable_precision<Backend>::value)>::type* = 0)
: m_backend(canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(static_cast<U&&>(v2))))
{
@@ -191,7 +191,7 @@ class number
(std::is_convertible<V, value_type>::value
&& std::is_convertible<U, value_type>::value
&& !std::is_same<value_type, self_type>::value
&& std::is_constructible<Backend, typename detail::canonical<Backend, decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type const&, typename detail::canonical<Backend, decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type const&>::value
&& std::is_constructible<Backend, typename detail::canonical<typename remove_cv<typename remove_reference<decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename remove_cv<typename remove_reference<decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type>::type, Backend>::type const&>::value
&& !boost::multiprecision::detail::is_variable_precision<Backend>::value)>::type* = 0)
: m_backend(canonical_value(detail::evaluate_if_expression(static_cast<V&&>(v1))), canonical_value(detail::evaluate_if_expression(static_cast<U&&>(v2))))
{
@@ -202,7 +202,7 @@ class number
(std::is_convertible<V, value_type>::value
&& std::is_convertible<U, value_type>::value
&& !std::is_same<value_type, self_type>::value
&& (!std::is_constructible<Backend, typename detail::canonical<Backend, decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type const&, typename detail::canonical<Backend, decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type const&>::value
&& (!std::is_constructible<Backend, typename detail::canonical<typename remove_cv<typename remove_reference<decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename remove_cv<typename remove_reference<decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type>::type, Backend>::type const&>::value
|| boost::multiprecision::detail::is_variable_precision<Backend>::value))>::type* = 0)
{
using default_ops::assign_components;
@@ -265,7 +265,12 @@ class number
: m_backend(detail::evaluate_if_expression(v1), detail::evaluate_if_expression(v2), digits10) {}
template <class Other, expression_template_option ET>
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const number<Other, ET>& v1, const number<Other, ET>& v2, typename std::enable_if<std::is_convertible<Other, Backend>::value>::type* = 0)
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(
const number<Other, ET>& v1,
const number<Other, ET>& v2,
typename std::enable_if<
std::is_convertible<Other, Backend>::value
&& (!std::is_constructible<Backend, typename detail::canonical<typename remove_cv<typename remove_reference<decltype(detail::evaluate_if_expression(std::declval<const number<Other, ET>&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename remove_cv<typename remove_reference<decltype(detail::evaluate_if_expression(std::declval<const number<Other, ET>&>()))>::type>::type, Backend>::type const&>::value || boost::multiprecision::detail::is_variable_precision<Backend>::value) >::type* = 0)
{
using default_ops::assign_components;
detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(v1, v2);
@@ -54,6 +54,23 @@ struct rational_adaptor
return result;
}
void normalize()
{
using default_ops::eval_gcd;
using default_ops::eval_eq;
using default_ops::eval_divide;
Backend g, t;
eval_gcd(g, m_num, m_denom);
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);
}
}
// We must have a default constructor:
rational_adaptor()
: m_num(one()), m_denom(one()) {}
@@ -70,6 +87,33 @@ struct rational_adaptor
rational_adaptor(const Arithmetic& val, typename std::enable_if<std::is_constructible<Backend, Arithmetic>::value && !std::is_floating_point<Arithmetic>::value>::type const* = nullptr)
: m_num(val), m_denom(one()) {}
//
// Pass-through 2-arg construction of components:
//
template <class T, class U>
rational_adaptor(const T& a, const U& b, typename std::enable_if<std::is_constructible<Backend, T const&>::value && std::is_constructible<Backend, U const&>::value>::type const* = nullptr)
: m_num(a), m_denom(b)
{
normalize();
}
template <class T, class U>
rational_adaptor(T&& a, const U& b, typename std::enable_if<std::is_constructible<Backend, T>::value && std::is_constructible<Backend, U>::value>::type const* = nullptr)
: m_num(static_cast<T&&>(a)), m_denom(b)
{
normalize();
}
template <class T, class U>
rational_adaptor(T&& a, U&& b, typename std::enable_if<std::is_constructible<Backend, T>::value && std::is_constructible<Backend, U>::value>::type const* = nullptr)
: m_num(static_cast<T&&>(a)), m_denom(static_cast<U&&>(b))
{
normalize();
}
template <class T, class U>
rational_adaptor(const T& a, U&& b, typename std::enable_if<std::is_constructible<Backend, T>::value && std::is_constructible<Backend, U>::value>::type const* = nullptr)
: m_num(a), m_denom(static_cast<U&&>(b))
{
normalize();
}
//
// In the absense of converting constructors, operator= takes the strain.
// In addition to the usual suspects, there must be one operator= for each type
@@ -290,26 +334,20 @@ is_minus_one(const T& val)
// Required non-members:
//
template <class Backend>
void eval_add(rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b)
inline void eval_add(rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b)
{
rational_adaptor<Backend> t;
eval_add(t, a, b);
a = std::move(t);
eval_add_subtract_imp(a, a, b, true);
}
template <class Backend>
void eval_subtract(rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b)
inline void eval_subtract(rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b)
{
rational_adaptor<Backend> t;
eval_subtract(t, a, b);
a = std::move(t);
eval_add_subtract_imp(a, a, b, false);
}
template <class Backend>
void eval_multiply(rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b)
inline void eval_multiply(rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b)
{
rational_adaptor<Backend> t;
eval_multiply(t, a, b);
a = std::move(t);
eval_multiply_imp(a, a, b.num(), b.denom());
}
template <class Backend>
@@ -0,0 +1,139 @@
// Copyright 2020 John Maddock. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
#include <iostream>
#include <benchmark/benchmark.h>
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/multiprecision/gmp.hpp>
#include <gmpxx.h>
template <class Integer>
inline Integer factorial(unsigned n)
{
Integer result = 1;
for (unsigned k = 1; k <= n; ++k)
result *= k;
return result;
}
template <class Rational, class Integer = typename Rational::value_type>
inline Rational binomial(unsigned n, unsigned k)
{
return Rational(factorial<Integer>(n), factorial<Integer>(k) * factorial<Integer>(n - k));
}
inline mpz_class pow(mpz_class i, unsigned p)
{
mpz_class result;
mpz_pow_ui(result.get_mpz_t(), i.get_mpz_t(), p);
return result;
}
template <class Rational, class Integer = typename Rational::value_type>
Rational Bernoulli(unsigned m)
{
Rational result = 0;
for (unsigned k = 0; k <= m; ++k)
{
Rational inner = 0;
for (unsigned v = 0; v <= k; ++v)
{
Rational term = binomial<Rational, Integer>(k, v) * Rational(pow(Integer(v), m), k + 1);
if (v & 1)
term = -term;
inner += term;
}
result += inner;
}
return result;
}
template <class Rational, class Integer = typename Rational::value_type>
static void BM_bernoulli(benchmark::State& state)
{
int m = state.range(0);
for (auto _ : state)
{
benchmark::DoNotOptimize(Bernoulli<Rational, Integer>(m));
}
}
unsigned allocation_count = 0;
void* (*alloc_func_ptr)(size_t);
void* (*realloc_func_ptr)(void*, size_t, size_t);
void (*free_func_ptr)(void*, size_t);
void* alloc_func(size_t n)
{
++allocation_count;
return (*alloc_func_ptr)(n);
}
void free_func(void* p, size_t n)
{
(*free_func_ptr)(p, n);
}
void* realloc_func(void* p, size_t old, size_t n)
{
++allocation_count;
return (*realloc_func_ptr)(p, old, n);
}
unsigned new_count = 0;
void* operator new(std::size_t n) throw(std::bad_alloc)
{
++new_count;
return std::malloc(n);
}
void operator delete(void* p) throw()
{
std::free(p);
}
void* operator new[](std::size_t n) throw(std::bad_alloc)
{
++new_count;
return std::malloc(n);
}
void operator delete[](void* p) throw()
{
std::free(p);
}
int main()
{
using namespace boost::multiprecision;
mp_get_memory_functions(&alloc_func_ptr, &realloc_func_ptr, &free_func_ptr);
mp_set_memory_functions(&alloc_func, &realloc_func, &free_func);
std::cout << "[table Total Allocation Counts for Bernoulli Number Calculation\n"
"[[m][cpp_rational][mpq_rational][number<rational_adaptor<gmp_int>>][mpq_class]]\n";
for (unsigned m = 2; m < 200; m += 2)
{
std::cout << "[[" << m << "][";
new_count = 0;
Bernoulli<cpp_rational>(m);
std::cout << new_count << "][";
allocation_count = 0;
Bernoulli<mpq_rational>(m);
std::cout << allocation_count << "][";
allocation_count = 0;
Bernoulli<number<rational_adaptor<gmp_int>>>(m);
std::cout << allocation_count << "][";
allocation_count = 0;
Bernoulli<mpq_class, mpz_class>(m);
std::cout << allocation_count << "]]\n";
}
std::cout << "]\n";
return 0;
}
+4 -4
View File
@@ -62,9 +62,9 @@ static void BM_bernoulli(benchmark::State& state)
}
BENCHMARK_TEMPLATE(BM_bernoulli, boost::multiprecision::cpp_rational)->DenseRange(10, 100, 2);
BENCHMARK_TEMPLATE(BM_bernoulli, boost::multiprecision::mpq_rational)->DenseRange(10, 100, 2);
BENCHMARK_TEMPLATE(BM_bernoulli, boost::multiprecision::number<boost::multiprecision::rational_adaptor<boost::multiprecision::gmp_int>>)->DenseRange(10, 100, 2);
BENCHMARK_TEMPLATE(BM_bernoulli, mpq_class, mpz_class)->DenseRange(10, 100, 2);
BENCHMARK_TEMPLATE(BM_bernoulli, boost::multiprecision::cpp_rational)->DenseRange(50, 200, 4);
BENCHMARK_TEMPLATE(BM_bernoulli, boost::multiprecision::mpq_rational)->DenseRange(50, 200, 4);
BENCHMARK_TEMPLATE(BM_bernoulli, boost::multiprecision::number<boost::multiprecision::rational_adaptor<boost::multiprecision::gmp_int> >)->DenseRange(50, 200, 4);
BENCHMARK_TEMPLATE(BM_bernoulli, mpq_class, mpz_class)->DenseRange(50, 200, 4);
BENCHMARK_MAIN();