mirror of
https://github.com/boostorg/multiprecision.git
synced 2026-07-21 13:23:49 +00:00
Update for better interoperability of rationals and integers.
Fix generic_interconvert.hpp for unsigned types. Update performance testing code to include testing with ::value_type. Start testing unsigned and checked integer types with rational_adaptor. Update arithmetic tests to test mixed arithmetic with ::value_type.
This commit is contained in:
@@ -237,6 +237,15 @@ void generic_interconvert(To& to, const From& from, const std::integral_constant
|
||||
assign_components(to, n.backend(), d.backend());
|
||||
}
|
||||
|
||||
template <class LargeInteger>
|
||||
inline typename std::enable_if<is_signed_number<LargeInteger>::value>::type make_positive(LargeInteger& val)
|
||||
{
|
||||
if (val.sign() < 0)
|
||||
val = -val;
|
||||
}
|
||||
template <class LargeInteger>
|
||||
inline typename std::enable_if<!is_signed_number<LargeInteger>::value>::type make_positive(LargeInteger&){}
|
||||
|
||||
template <class R, class LargeInteger>
|
||||
R safe_convert_to_float(const LargeInteger& i)
|
||||
{
|
||||
@@ -246,8 +255,7 @@ R safe_convert_to_float(const LargeInteger& i)
|
||||
BOOST_IF_CONSTEXPR(std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::max_exponent)
|
||||
{
|
||||
LargeInteger val(i);
|
||||
if (val.sign() < 0)
|
||||
val = -val;
|
||||
make_positive(val);
|
||||
unsigned mb = msb(val);
|
||||
if (mb >= std::numeric_limits<R>::max_exponent)
|
||||
{
|
||||
|
||||
@@ -453,8 +453,7 @@ inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value&&
|
||||
// Arithmetic operations, starting with addition:
|
||||
//
|
||||
template <class Backend, class Arithmetic>
|
||||
typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && std::is_integral<Arithmetic>::value>::type
|
||||
eval_add_subtract_imp(rational_adaptor<Backend>& result, Arithmetic arg, bool isaddition)
|
||||
void eval_add_subtract_imp(rational_adaptor<Backend>& result, const Arithmetic& arg, bool isaddition)
|
||||
{
|
||||
using default_ops::eval_multiply;
|
||||
using default_ops::eval_divide;
|
||||
@@ -485,15 +484,15 @@ typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && std::
|
||||
}
|
||||
|
||||
template <class Backend, class Arithmetic>
|
||||
inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && std::is_integral<Arithmetic>::value>::type
|
||||
eval_add(rational_adaptor<Backend>& result, Arithmetic arg)
|
||||
inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && std::is_integral<Arithmetic>::value || std::is_same<Arithmetic, Backend>::value>::type
|
||||
eval_add(rational_adaptor<Backend>& result, const Arithmetic& arg)
|
||||
{
|
||||
eval_add_subtract_imp(result, arg, true);
|
||||
}
|
||||
|
||||
template <class Backend, class Arithmetic>
|
||||
inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && std::is_integral<Arithmetic>::value>::type
|
||||
eval_subtract(rational_adaptor<Backend>& result, Arithmetic arg)
|
||||
inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && std::is_integral<Arithmetic>::value || std::is_same<Arithmetic, Backend>::value>::type
|
||||
eval_subtract(rational_adaptor<Backend>& result, const Arithmetic& arg)
|
||||
{
|
||||
eval_add_subtract_imp(result, arg, false);
|
||||
}
|
||||
@@ -599,8 +598,7 @@ inline void eval_subtract(rational_adaptor<Backend>& result, const rational_adap
|
||||
}
|
||||
|
||||
template <class Backend, class Arithmetic>
|
||||
typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && std::is_integral<Arithmetic>::value>::type
|
||||
eval_add_subtract_imp(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, Arithmetic b, bool isaddition)
|
||||
void eval_add_subtract_imp(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, const Arithmetic& b, bool isaddition)
|
||||
{
|
||||
using default_ops::eval_add;
|
||||
using default_ops::eval_subtract;
|
||||
@@ -632,14 +630,14 @@ eval_add_subtract_imp(rational_adaptor<Backend>& result, const rational_adaptor<
|
||||
//
|
||||
}
|
||||
template <class Backend, class Arithmetic>
|
||||
inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && std::is_integral<Arithmetic>::value>::type
|
||||
eval_add(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, Arithmetic b)
|
||||
inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && std::is_integral<Arithmetic>::value || std::is_same<Arithmetic, Backend>::value>::type
|
||||
eval_add(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, const Arithmetic& b)
|
||||
{
|
||||
eval_add_subtract_imp(result, a, b, true);
|
||||
}
|
||||
template <class Backend, class Arithmetic>
|
||||
inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && std::is_integral<Arithmetic>::value>::type
|
||||
eval_subtract(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, Arithmetic b)
|
||||
inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && std::is_integral<Arithmetic>::value || std::is_same<Arithmetic, Backend>::value>::type
|
||||
eval_subtract(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, const Arithmetic& b)
|
||||
{
|
||||
eval_add_subtract_imp(result, a, b, false);
|
||||
}
|
||||
@@ -719,8 +717,7 @@ void eval_multiply(rational_adaptor<Backend>& result, const rational_adaptor<Bac
|
||||
}
|
||||
|
||||
template <class Backend, class Arithmetic>
|
||||
typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value&& std::is_integral<Arithmetic>::value>::type
|
||||
eval_multiply_imp(Backend& result_num, Backend& result_denom, Arithmetic arg)
|
||||
void eval_multiply_imp(Backend& result_num, Backend& result_denom, Arithmetic arg)
|
||||
{
|
||||
if (arg == 0)
|
||||
{
|
||||
@@ -754,10 +751,55 @@ typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value&& std::i
|
||||
result_denom = std::move(t);
|
||||
}
|
||||
}
|
||||
template <class Backend>
|
||||
void eval_multiply_imp(Backend& result_num, Backend& result_denom, Backend arg)
|
||||
{
|
||||
using default_ops::eval_multiply;
|
||||
using default_ops::eval_divide;
|
||||
using default_ops::eval_gcd;
|
||||
using default_ops::eval_convert_to;
|
||||
using default_ops::eval_is_zero;
|
||||
using default_ops::eval_eq;
|
||||
using default_ops::eval_get_sign;
|
||||
|
||||
if (eval_is_zero(arg))
|
||||
{
|
||||
result_num = rational_adaptor<Backend>::zero();
|
||||
result_denom = rational_adaptor<Backend>::one();
|
||||
return;
|
||||
}
|
||||
else if (eval_eq(arg, rational_adaptor<Backend>::one()))
|
||||
return;
|
||||
|
||||
Backend gcd, t;
|
||||
eval_gcd(gcd, result_denom, arg);
|
||||
if (!eval_eq(gcd, rational_adaptor<Backend>::one()))
|
||||
{
|
||||
eval_divide(t, arg, gcd);
|
||||
arg = t;
|
||||
}
|
||||
else
|
||||
t = arg;
|
||||
if (eval_get_sign(arg) < 0)
|
||||
t.negate();
|
||||
|
||||
if (!eval_eq(t, rational_adaptor<Backend>::one()))
|
||||
{
|
||||
eval_multiply(t, result_num, arg);
|
||||
result_num = std::move(t);
|
||||
}
|
||||
else if (eval_get_sign(arg) < 0)
|
||||
result_num.negate();
|
||||
if (!eval_eq(gcd, rational_adaptor<Backend>::one()))
|
||||
{
|
||||
eval_divide(t, result_denom, gcd);
|
||||
result_denom = std::move(t);
|
||||
}
|
||||
}
|
||||
|
||||
template <class Backend, class Arithmetic>
|
||||
inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value&& std::is_integral<Arithmetic>::value>::type
|
||||
eval_multiply(rational_adaptor<Backend>& result, Arithmetic arg)
|
||||
inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value&& std::is_integral<Arithmetic>::value || std::is_same<Arithmetic, Backend>::value>::type
|
||||
eval_multiply(rational_adaptor<Backend>& result, const Arithmetic& arg)
|
||||
{
|
||||
eval_multiply_imp(result.num(), result.denom(), arg);
|
||||
}
|
||||
@@ -803,10 +845,17 @@ typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value&& std::i
|
||||
else
|
||||
result.denom() = a_denom;
|
||||
}
|
||||
template <class Backend>
|
||||
inline void eval_multiply_imp(rational_adaptor<Backend>& result, const Backend& a_num, const Backend& a_denom, const Backend& b)
|
||||
{
|
||||
result.num() = a_num;
|
||||
result.denom() = a_denom;
|
||||
eval_multiply_imp(result.num(), result.denom(), b);
|
||||
}
|
||||
|
||||
template <class Backend, class Arithmetic>
|
||||
inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value&& std::is_integral<Arithmetic>::value>::type
|
||||
eval_multiply(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, Arithmetic b)
|
||||
inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value&& std::is_integral<Arithmetic>::value || std::is_same<Arithmetic, Backend>::value>::type
|
||||
eval_multiply(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, const Arithmetic& b)
|
||||
{
|
||||
if (&result == &a)
|
||||
return eval_multiply(result, b);
|
||||
@@ -815,8 +864,8 @@ inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value&&
|
||||
}
|
||||
|
||||
template <class Backend, class Arithmetic>
|
||||
inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value&& std::is_integral<Arithmetic>::value>::type
|
||||
eval_multiply(rational_adaptor<Backend>& result, unsigned long long b, const rational_adaptor<Backend>& a)
|
||||
inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value&& std::is_integral<Arithmetic>::value || std::is_same<Arithmetic, Backend>::value>::type
|
||||
eval_multiply(rational_adaptor<Backend>& result, const Arithmetic& b, const rational_adaptor<Backend>& a)
|
||||
{
|
||||
return eval_multiply(result, a, b);
|
||||
}
|
||||
@@ -850,8 +899,8 @@ inline void eval_divide(rational_adaptor<Backend>& result, const rational_adapto
|
||||
}
|
||||
|
||||
template <class Backend, class Arithmetic>
|
||||
inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value&& std::is_integral<Arithmetic>::value>::type
|
||||
eval_divide(rational_adaptor<Backend>& result, Arithmetic b, const rational_adaptor<Backend>& a)
|
||||
inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value&& std::is_integral<Arithmetic>::value || std::is_same<Arithmetic, Backend>::value>::type
|
||||
eval_divide(rational_adaptor<Backend>& result, const Arithmetic& b, const rational_adaptor<Backend>& a)
|
||||
{
|
||||
using default_ops::eval_get_sign;
|
||||
|
||||
@@ -920,6 +969,63 @@ eval_divide(rational_adaptor<Backend>& result, Arithmetic arg)
|
||||
result.num() = std::move(t);
|
||||
}
|
||||
}
|
||||
template <class Backend>
|
||||
void eval_divide(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, Backend arg)
|
||||
{
|
||||
using default_ops::eval_multiply;
|
||||
using default_ops::eval_gcd;
|
||||
using default_ops::eval_convert_to;
|
||||
using default_ops::eval_divide;
|
||||
using default_ops::eval_is_zero;
|
||||
using default_ops::eval_eq;
|
||||
using default_ops::eval_get_sign;
|
||||
|
||||
if (eval_is_zero(arg))
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(std::overflow_error("Integer division by zero"));
|
||||
return;
|
||||
}
|
||||
else if (eval_eq(a, rational_adaptor<Backend>::one()) || (eval_get_sign(a) == 0))
|
||||
{
|
||||
if (&result != &a)
|
||||
result = a;
|
||||
return;
|
||||
}
|
||||
|
||||
Backend gcd, u_arg, t;
|
||||
eval_gcd(gcd, a.num(), arg);
|
||||
bool has_unit_gcd = eval_eq(gcd, rational_adaptor<Backend>::one());
|
||||
if (!has_unit_gcd)
|
||||
{
|
||||
eval_divide(u_arg, arg, gcd);
|
||||
arg = u_arg;
|
||||
}
|
||||
else
|
||||
u_arg = arg;
|
||||
if (eval_get_sign(u_arg) < 0)
|
||||
u_arg.negate();
|
||||
|
||||
eval_multiply(t, a.denom(), u_arg);
|
||||
result.denom() = std::move(t);
|
||||
|
||||
if (!has_unit_gcd)
|
||||
{
|
||||
eval_divide(t, a.num(), gcd);
|
||||
result.num() = std::move(t);
|
||||
}
|
||||
else if (&result != &a)
|
||||
result.num() = a.num();
|
||||
|
||||
if (eval_get_sign(arg) < 0)
|
||||
{
|
||||
result.num().negate();
|
||||
}
|
||||
}
|
||||
template <class Backend>
|
||||
void eval_divide(rational_adaptor<Backend>& result, Backend arg)
|
||||
{
|
||||
eval_divide(result, result, arg);
|
||||
}
|
||||
|
||||
template <class Backend, class Arithmetic>
|
||||
typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value&& std::is_integral<Arithmetic>::value>::type
|
||||
@@ -974,84 +1080,32 @@ typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value&& std::i
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Multiply and add/subtract as one:
|
||||
//
|
||||
#if 0
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b);
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, unsigned long long b);
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, unsigned long b);
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, unsigned b);
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, unsigned short b);
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, unsigned char b);
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, long long b);
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, long b);
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, int b);
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, short b);
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, signed char b);
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, char b);
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, long double b);
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, double b);
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, float b);
|
||||
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, unsigned long long b, const rational_adaptor<Backend>& a);
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, unsigned long b, const rational_adaptor<Backend>& a);
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, unsigned b, const rational_adaptor<Backend>& a);
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, unsigned short b, const rational_adaptor<Backend>& a);
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, unsigned char b, const rational_adaptor<Backend>& a);
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, long long b, const rational_adaptor<Backend>& a);
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, long b, const rational_adaptor<Backend>& a);
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, int b, const rational_adaptor<Backend>& a);
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, short b, const rational_adaptor<Backend>& a);
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, signed char b, const rational_adaptor<Backend>& a);
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, char b, const rational_adaptor<Backend>& a);
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, long double b, const rational_adaptor<Backend>& a);
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, double b, const rational_adaptor<Backend>& a);
|
||||
template <class Backend> void eval_multiply_add(rational_adaptor<Backend>& result, float b, const rational_adaptor<Backend>& a);
|
||||
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b);
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, unsigned long long b);
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, unsigned long b);
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, unsigned b);
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, unsigned short b);
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, unsigned char b);
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, long long b);
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, long b);
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, int b);
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, short b);
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, signed char b);
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, char b);
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, long double b);
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, double b);
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, float b);
|
||||
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, unsigned long long b, const rational_adaptor<Backend>& a);
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, unsigned long b, const rational_adaptor<Backend>& a);
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, unsigned b, const rational_adaptor<Backend>& a);
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, unsigned short b, const rational_adaptor<Backend>& a);
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, unsigned char b, const rational_adaptor<Backend>& a);
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, long long b, const rational_adaptor<Backend>& a);
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, long b, const rational_adaptor<Backend>& a);
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, int b, const rational_adaptor<Backend>& a);
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, short b, const rational_adaptor<Backend>& a);
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, signed char b, const rational_adaptor<Backend>& a);
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, char b, const rational_adaptor<Backend>& a);
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, long double b, const rational_adaptor<Backend>& a);
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, double b, const rational_adaptor<Backend>& a);
|
||||
template <class Backend> void eval_multiply_subtract(rational_adaptor<Backend>& result, float b, const rational_adaptor<Backend>& a);
|
||||
#endif
|
||||
//
|
||||
// Increment and decrement:
|
||||
//
|
||||
//template <class Backend> void eval_increment(rational_adaptor<Backend>& arg);
|
||||
//template <class Backend> void eval_decrement(rational_adaptor<Backend>& arg);
|
||||
//
|
||||
// abs/fabs:
|
||||
//
|
||||
// template <class Backend> void eval_abs(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& arg);
|
||||
// template <class Backend> void eval_fabs(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& arg);
|
||||
//
|
||||
template <class Backend>
|
||||
inline void eval_increment(rational_adaptor<Backend>& arg)
|
||||
{
|
||||
using default_ops::eval_add;
|
||||
eval_add(arg.num(), arg.denom());
|
||||
}
|
||||
template <class Backend>
|
||||
inline void eval_decrement(rational_adaptor<Backend>& arg)
|
||||
{
|
||||
using default_ops::eval_subtract;
|
||||
eval_subtract(arg.num(), arg.denom());
|
||||
}
|
||||
|
||||
//
|
||||
// abs:
|
||||
//
|
||||
template <class Backend>
|
||||
inline void eval_abs(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& arg)
|
||||
{
|
||||
using default_ops::eval_abs;
|
||||
eval_abs(result.num(), arg.num());
|
||||
result.denom() = arg.denom();
|
||||
}
|
||||
|
||||
} // namespace backends
|
||||
|
||||
@@ -1093,6 +1147,11 @@ inline number<IntBackend, ET> denominator(const number<rational_adaptor<IntBacke
|
||||
return val.backend().denom();
|
||||
}
|
||||
|
||||
template <class Backend>
|
||||
struct is_unsigned_number<rational_adaptor<Backend> > : public is_unsigned_number<Backend>
|
||||
{};
|
||||
|
||||
|
||||
}} // namespace boost::multiprecision
|
||||
|
||||
namespace std {
|
||||
|
||||
@@ -1,8 +1,30 @@
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Copyright 2011-9 John Maddock. Distributed under the Boost
|
||||
// Copyright 2011-21 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
|
||||
|
||||
//
|
||||
// This is the main entry point for our operator performance test suite.
|
||||
// In order to build this program, you must compile and link this file against
|
||||
// all the libs/multiprecision/performance/performance_test_files/*.cpp files.
|
||||
//
|
||||
// The default behaviour is to "test everything", which is probably not what you want.
|
||||
// In order to restict testing to a specific selection of backends, you will need to
|
||||
// define one or more of the following macros when building:
|
||||
//
|
||||
// TEST_MPF
|
||||
// TEST_MPZ
|
||||
// TEST_CPP_DEC_FLOAT
|
||||
// TEST_MPFR
|
||||
// TEST_MPQ
|
||||
// TEST_TOMMATH
|
||||
// TEST_TOMMATH_BOOST_RATIONAL
|
||||
// TEST_MPZ_BOOST_RATIONAL
|
||||
// TEST_CPP_INT
|
||||
// TEST_CPP_INT_RATIONAL
|
||||
// TEST_CPP_BIN_FLOAT
|
||||
//
|
||||
|
||||
#include "performance_test.hpp"
|
||||
|
||||
#ifdef TEST_MPZ
|
||||
|
||||
@@ -387,96 +387,96 @@ struct tester
|
||||
template <class U>
|
||||
double test_multiply_hetero()
|
||||
{
|
||||
static const U val = get_hetero_test_value<U>();
|
||||
const std::vector<U>& vals = get_hetero_test_vector<U>();
|
||||
stopwatch<boost::chrono::high_resolution_clock> w;
|
||||
for (unsigned i = 0; i < 1000; ++i)
|
||||
{
|
||||
for (unsigned j = 0; j < b.size(); ++j)
|
||||
a[j] = b[j] * val;
|
||||
a[j] = b[j] * vals[j];
|
||||
}
|
||||
return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
|
||||
}
|
||||
template <class U>
|
||||
double test_inplace_multiply_hetero()
|
||||
{
|
||||
static const U val = get_hetero_test_value<U>();
|
||||
const std::vector<U>& vals = get_hetero_test_vector<U>();
|
||||
stopwatch<boost::chrono::high_resolution_clock> w;
|
||||
for (unsigned i = 0; i < 1000; ++i)
|
||||
{
|
||||
for (unsigned j = 0; j < b.size(); ++j)
|
||||
a[j] = b[j], a[j] *= val;
|
||||
a[j] = b[j], a[j] *= vals[j];
|
||||
}
|
||||
return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
|
||||
}
|
||||
template <class U>
|
||||
double test_add_hetero()
|
||||
{
|
||||
static const U val = get_hetero_test_value<U>();
|
||||
const std::vector<U>& vals = get_hetero_test_vector<U>();
|
||||
stopwatch<boost::chrono::high_resolution_clock> w;
|
||||
for (unsigned i = 0; i < 1000; ++i)
|
||||
{
|
||||
for (unsigned j = 0; j < b.size(); ++j)
|
||||
a[j] = b[j] + val;
|
||||
a[j] = b[j] + vals[j];
|
||||
}
|
||||
return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
|
||||
}
|
||||
template <class U>
|
||||
double test_inplace_add_hetero()
|
||||
{
|
||||
static const U val = get_hetero_test_value<U>();
|
||||
const std::vector<U>& vals = get_hetero_test_vector<U>();
|
||||
stopwatch<boost::chrono::high_resolution_clock> w;
|
||||
for (unsigned i = 0; i < 1000; ++i)
|
||||
{
|
||||
for (unsigned j = 0; j < b.size(); ++j)
|
||||
a[j] = b[j], a[j] += val;
|
||||
a[j] = b[j], a[j] += vals[j];
|
||||
}
|
||||
return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
|
||||
}
|
||||
template <class U>
|
||||
double test_subtract_hetero()
|
||||
{
|
||||
static const U val = get_hetero_test_value<U>();
|
||||
const std::vector<U>& vals = get_hetero_test_vector<U>();
|
||||
stopwatch<boost::chrono::high_resolution_clock> w;
|
||||
for (unsigned i = 0; i < 1000; ++i)
|
||||
{
|
||||
for (unsigned j = 0; j < b.size(); ++j)
|
||||
a[j] = b[j] - val;
|
||||
a[j] = b[j] - vals[j];
|
||||
}
|
||||
return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
|
||||
}
|
||||
template <class U>
|
||||
double test_inplace_subtract_hetero()
|
||||
{
|
||||
static const U val = get_hetero_test_value<U>();
|
||||
const std::vector<U>& vals = get_hetero_test_vector<U>();
|
||||
stopwatch<boost::chrono::high_resolution_clock> w;
|
||||
for (unsigned i = 0; i < 1000; ++i)
|
||||
{
|
||||
for (unsigned j = 0; j < b.size(); ++j)
|
||||
a[j] = b[j], a[j] -= val;
|
||||
a[j] = b[j], a[j] -= vals[j];
|
||||
}
|
||||
return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
|
||||
}
|
||||
template <class U>
|
||||
double test_divide_hetero()
|
||||
{
|
||||
static const U val = get_hetero_test_value<U>();
|
||||
const std::vector<U>& vals = get_hetero_test_vector<U>();
|
||||
stopwatch<boost::chrono::high_resolution_clock> w;
|
||||
for (unsigned i = 0; i < 1000; ++i)
|
||||
{
|
||||
for (unsigned j = 0; j < b.size(); ++j)
|
||||
a[j] = b[j] / val;
|
||||
a[j] = b[j] / vals[j];
|
||||
}
|
||||
return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
|
||||
}
|
||||
template <class U>
|
||||
double test_inplace_divide_hetero()
|
||||
{
|
||||
static const U val = get_hetero_test_value<U>();
|
||||
const std::vector<U>& vals = get_hetero_test_vector<U>();
|
||||
stopwatch<boost::chrono::high_resolution_clock> w;
|
||||
for (unsigned i = 0; i < 1000; ++i)
|
||||
{
|
||||
for (unsigned j = 0; j < b.size(); ++j)
|
||||
a[j] = b[j], a[j] /= val;
|
||||
a[j] = b[j], a[j] /= vals[j];
|
||||
}
|
||||
return boost::chrono::duration_cast<boost::chrono::duration<double> >(w.elapsed()).count();
|
||||
}
|
||||
@@ -484,12 +484,13 @@ struct tester
|
||||
private:
|
||||
T generate_random()
|
||||
{
|
||||
return generate_random(std::integral_constant<int, Type>());
|
||||
return generate_random<T>(std::integral_constant<int, Type>());
|
||||
}
|
||||
T generate_random(const std::integral_constant<int, boost::multiprecision::number_kind_floating_point>&)
|
||||
template <class U>
|
||||
U generate_random(const std::integral_constant<int, boost::multiprecision::number_kind_floating_point>&)
|
||||
{
|
||||
T val = gen();
|
||||
T prev_val = -1;
|
||||
U val = gen();
|
||||
U prev_val = -1;
|
||||
while (val != prev_val)
|
||||
{
|
||||
val *= (gen.max)();
|
||||
@@ -499,24 +500,25 @@ struct tester
|
||||
int e;
|
||||
val = frexp(val, &e);
|
||||
|
||||
typedef typename T::backend_type::exponent_type e_type;
|
||||
typedef typename U::backend_type::exponent_type e_type;
|
||||
static boost::random::uniform_int_distribution<e_type> ui(-30, 30);
|
||||
return ldexp(val, static_cast<int>(ui(gen)));
|
||||
}
|
||||
T generate_random(const std::integral_constant<int, boost::multiprecision::number_kind_integer>&)
|
||||
template <class U>
|
||||
U generate_random(const std::integral_constant<int, boost::multiprecision::number_kind_integer>&)
|
||||
{
|
||||
typedef boost::random::mt19937::result_type random_type;
|
||||
|
||||
T max_val;
|
||||
U max_val;
|
||||
unsigned digits;
|
||||
if (std::numeric_limits<T>::is_bounded)
|
||||
if (std::numeric_limits<U>::is_bounded)
|
||||
{
|
||||
max_val = (std::numeric_limits<T>::max)();
|
||||
digits = std::numeric_limits<T>::digits;
|
||||
max_val = (std::numeric_limits<U>::max)();
|
||||
digits = std::numeric_limits<U>::digits;
|
||||
}
|
||||
else
|
||||
{
|
||||
max_val = T(1) << bits_wanted;
|
||||
max_val = U(1) << bits_wanted;
|
||||
digits = bits_wanted;
|
||||
}
|
||||
|
||||
@@ -526,7 +528,7 @@ struct tester
|
||||
|
||||
unsigned terms_needed = digits / bits_per_r_val + 1;
|
||||
|
||||
T val = 0;
|
||||
U val = 0;
|
||||
for (unsigned i = 0; i < terms_needed; ++i)
|
||||
{
|
||||
val *= (gen.max)();
|
||||
@@ -535,10 +537,11 @@ struct tester
|
||||
val %= max_val;
|
||||
return val;
|
||||
}
|
||||
T generate_random(const std::integral_constant<int, boost::multiprecision::number_kind_rational>&)
|
||||
template <class U>
|
||||
U generate_random(const std::integral_constant<int, boost::multiprecision::number_kind_rational>&)
|
||||
{
|
||||
typedef boost::random::mt19937::result_type random_type;
|
||||
typedef typename boost::multiprecision::component_type<T>::type IntType;
|
||||
typedef typename boost::multiprecision::component_type<U>::type IntType;
|
||||
|
||||
IntType max_val;
|
||||
unsigned digits;
|
||||
@@ -575,8 +578,20 @@ struct tester
|
||||
denom = 1;
|
||||
val %= max_val;
|
||||
denom %= max_val;
|
||||
return T(val, denom);
|
||||
return U(val, denom);
|
||||
}
|
||||
|
||||
template <class U>
|
||||
const std::vector<U>& get_hetero_test_vector()
|
||||
{
|
||||
static std::vector<U> result;
|
||||
while (result.size() < a.size())
|
||||
{
|
||||
result.push_back(generate_random<U>(std::integral_constant<int, boost::multiprecision::number_category<U>::value>()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<T> a, b, c, small;
|
||||
static boost::random::mt19937 gen;
|
||||
};
|
||||
@@ -638,6 +653,23 @@ void test_int_ops(tester<Number, N>&, const char*, unsigned, const U&)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Number, int N, class U>
|
||||
void test_related_ops(tester<Number, N>& t, const char* type, unsigned precision, const U&, const char* cat)
|
||||
{
|
||||
report_result(cat, type, "+(value_type)", precision, t.template test_add_hetero<U>());
|
||||
report_result(cat, type, "-(value_type)", precision, t.template test_subtract_hetero<U>());
|
||||
report_result(cat, type, "*(value_type)", precision, t.template test_multiply_hetero<U>());
|
||||
report_result(cat, type, "/(value_type)", precision, t.template test_divide_hetero<U>());
|
||||
report_result(cat, type, "+=(value_type)", precision, t.template test_inplace_add_hetero<U>());
|
||||
report_result(cat, type, "-=(value_type)", precision, t.template test_inplace_subtract_hetero<U>());
|
||||
report_result(cat, type, "*=(value_type)", precision, t.template test_inplace_multiply_hetero<U>());
|
||||
report_result(cat, type, "/=(value_type)", precision, t.template test_inplace_divide_hetero<U>());
|
||||
}
|
||||
template <class Number, int N>
|
||||
void test_related_ops(tester<Number, N>& t, const char* type, unsigned precision, const Number&, const char* cat)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Number>
|
||||
void test(const char* type, unsigned precision)
|
||||
{
|
||||
@@ -671,6 +703,7 @@ void test(const char* type, unsigned precision)
|
||||
report_result(cat, type, "construct(unsigned)", precision, t.test_construct_unsigned());
|
||||
report_result(cat, type, "construct(unsigned long long)", precision, t.test_construct_unsigned_ll());
|
||||
test_int_ops(t, type, precision, typename boost::multiprecision::number_category<Number>::type());
|
||||
test_related_ops(t, type, precision, typename Number::value_type(), cat);
|
||||
// Hetero ops:
|
||||
report_result(cat, type, "+(unsigned long long)", precision, t.template test_add_hetero<unsigned long long>());
|
||||
report_result(cat, type, "-(unsigned long long)", precision, t.template test_subtract_hetero<unsigned long long>());
|
||||
|
||||
@@ -162,6 +162,9 @@ test-suite arithmetic_tests :
|
||||
[ run test_arithmetic_cpp_int_18.cpp no_eh_support : : : <toolset>msvc:<cxxflags>-bigobj ]
|
||||
[ run test_arithmetic_cpp_int_19.cpp no_eh_support : : : <toolset>msvc:<cxxflags>-bigobj ]
|
||||
[ run test_arithmetic_cpp_int_20.cpp no_eh_support : : : <toolset>msvc:<cxxflags>-bigobj ]
|
||||
[ run test_arithmetic_cpp_int_21.cpp no_eh_support : : : <toolset>msvc:<cxxflags>-bigobj ]
|
||||
[ run test_arithmetic_cpp_int_22.cpp no_eh_support : : : <toolset>msvc:<cxxflags>-bigobj ]
|
||||
[ run test_arithmetic_cpp_int_23.cpp no_eh_support : : : <toolset>msvc:<cxxflags>-bigobj ]
|
||||
[ run test_arithmetic_cpp_int_br.cpp no_eh_support : : : <toolset>msvc:<cxxflags>-bigobj ]
|
||||
|
||||
[ run test_arithmetic_ab_1.cpp no_eh_support ]
|
||||
|
||||
@@ -311,6 +311,18 @@ void test_rational(const std::integral_constant<bool, true>&)
|
||||
ss >> b;
|
||||
BOOST_CHECK_EQUAL(a, b);
|
||||
}
|
||||
template <class Real>
|
||||
void test_rational_signed(const std::integral_constant<bool, true>&)
|
||||
{
|
||||
Real three = -3;
|
||||
BOOST_CHECK_EQUAL(static_cast<std::int16_t>(three), -3);
|
||||
BOOST_CHECK_EQUAL(static_cast<std::int32_t>(three), -3);
|
||||
BOOST_CHECK_EQUAL(static_cast<std::int64_t>(three), -3);
|
||||
}
|
||||
template <class Real>
|
||||
void test_rational_signed(const std::integral_constant<bool, false>&)
|
||||
{
|
||||
}
|
||||
|
||||
template <class Real>
|
||||
void test_rational(const std::integral_constant<bool, false>&)
|
||||
@@ -343,10 +355,7 @@ void test_rational(const std::integral_constant<bool, false>&)
|
||||
BOOST_CHECK_EQUAL(static_cast<std::uint16_t>(three), 3);
|
||||
BOOST_CHECK_EQUAL(static_cast<std::uint32_t>(three), 3);
|
||||
BOOST_CHECK_EQUAL(static_cast<std::uint64_t>(three), 3);
|
||||
three = -three;
|
||||
BOOST_CHECK_EQUAL(static_cast<std::int16_t>(three), -3);
|
||||
BOOST_CHECK_EQUAL(static_cast<std::int32_t>(three), -3);
|
||||
BOOST_CHECK_EQUAL(static_cast<std::int64_t>(three), -3);
|
||||
test_rational_signed<Real>(std::integral_constant<bool, std::numeric_limits<Real>::is_signed>());
|
||||
}
|
||||
|
||||
template <class Real>
|
||||
|
||||
@@ -11,6 +11,13 @@ template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer
|
||||
struct is_twos_complement_integer<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, boost::multiprecision::checked, Allocator>, ExpressionTemplates> > : public std::integral_constant<bool, false>
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct related_type<boost::multiprecision::number<boost::multiprecision::rational_adaptor<boost::multiprecision::int128_t::backend_type> > >
|
||||
{
|
||||
typedef boost::multiprecision::int128_t type;
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
test<boost::multiprecision::number<boost::multiprecision::rational_adaptor<boost::multiprecision::int128_t::backend_type> > >();
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Copyright 2012 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 <boost/multiprecision/cpp_int.hpp>
|
||||
|
||||
#include "test_arithmetic.hpp"
|
||||
|
||||
template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, class Allocator, boost::multiprecision::expression_template_option ExpressionTemplates>
|
||||
struct is_twos_complement_integer<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, boost::multiprecision::checked, Allocator>, ExpressionTemplates> > : public std::integral_constant<bool, false>
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct related_type<boost::multiprecision::number<boost::multiprecision::rational_adaptor<boost::multiprecision::uint128_t::backend_type> > >
|
||||
{
|
||||
typedef boost::multiprecision::uint128_t type;
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
test<boost::multiprecision::number<boost::multiprecision::rational_adaptor<boost::multiprecision::uint128_t::backend_type> > >();
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Copyright 2012 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 <boost/multiprecision/cpp_int.hpp>
|
||||
|
||||
#include "test_arithmetic.hpp"
|
||||
|
||||
template <>
|
||||
struct related_type<boost::multiprecision::number<boost::multiprecision::rational_adaptor<boost::multiprecision::checked_uint128_t::backend_type> > >
|
||||
{
|
||||
typedef boost::multiprecision::checked_uint128_t type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_twos_complement_integer<boost::multiprecision::number<boost::multiprecision::rational_adaptor<boost::multiprecision::checked_uint128_t::backend_type> > > : public std::false_type
|
||||
{};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
test<boost::multiprecision::number<boost::multiprecision::rational_adaptor<boost::multiprecision::checked_uint128_t::backend_type> > >();
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
///////////////////////////////////////////////////////////////
|
||||
// Copyright 2012 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 <boost/multiprecision/cpp_int.hpp>
|
||||
|
||||
#include "test_arithmetic.hpp"
|
||||
|
||||
template <>
|
||||
struct related_type<boost::multiprecision::number<boost::multiprecision::rational_adaptor<boost::multiprecision::checked_int128_t::backend_type> > >
|
||||
{
|
||||
typedef boost::multiprecision::checked_int128_t type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_twos_complement_integer<boost::multiprecision::number<boost::multiprecision::rational_adaptor<boost::multiprecision::checked_int128_t::backend_type> > > : public std::false_type
|
||||
{};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
test<boost::multiprecision::number<boost::multiprecision::rational_adaptor<boost::multiprecision::checked_int128_t::backend_type> > >();
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -16,6 +16,11 @@ struct related_type<boost::multiprecision::cpp_int>
|
||||
{
|
||||
typedef boost::multiprecision::int256_t type;
|
||||
};
|
||||
template <>
|
||||
struct related_type<boost::multiprecision::cpp_rational>
|
||||
{
|
||||
typedef boost::multiprecision::cpp_int type;
|
||||
};
|
||||
template <unsigned MinBits, unsigned MaxBits, boost::multiprecision::cpp_integer_type SignType, boost::multiprecision::cpp_int_check_type Checked, class Allocator, boost::multiprecision::expression_template_option ET>
|
||||
struct related_type<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<MinBits, MaxBits, SignType, Checked, Allocator>, ET> >
|
||||
{
|
||||
|
||||
@@ -12,6 +12,13 @@
|
||||
|
||||
#include "test_arithmetic.hpp"
|
||||
|
||||
template <>
|
||||
struct related_type<boost::multiprecision::number<boost::multiprecision::rational_adaptor<boost::multiprecision::gmp_int> > >
|
||||
{
|
||||
typedef boost::multiprecision::mpz_int type;
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
test<boost::multiprecision::number<boost::multiprecision::rational_adaptor<boost::multiprecision::gmp_int> > >();
|
||||
|
||||
@@ -15,6 +15,13 @@ template <>
|
||||
struct is_twos_complement_integer<boost::multiprecision::tom_int> : public std::integral_constant<bool, false>
|
||||
{};
|
||||
|
||||
template <>
|
||||
struct related_type<boost::multiprecision::number<boost::multiprecision::rational_adaptor<boost::multiprecision::tommath_int> > >
|
||||
{
|
||||
typedef boost::multiprecision::number<boost::multiprecision::tommath_int> type;
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
test<boost::multiprecision::number<boost::multiprecision::rational_adaptor<boost::multiprecision::tommath_int> > >();
|
||||
|
||||
@@ -922,6 +922,242 @@ struct tester
|
||||
BOOST_CHECK_EQUAL(z1, -1);
|
||||
}
|
||||
|
||||
void t6()
|
||||
{
|
||||
//
|
||||
// Mixed with signed integer:
|
||||
//
|
||||
boost::multiprecision::mpq_rational x(a, b), y(c, d), z;
|
||||
boost::multiprecision::cpp_rational x1(a1, b1), y1(c1, d1), z1;
|
||||
|
||||
boost::multiprecision::mpz_int bi = generate_random<boost::multiprecision::mpz_int>(1000);
|
||||
boost::multiprecision::cpp_int bi1(bi.str());
|
||||
|
||||
BOOST_CHECK_EQUAL(x.str(), x1.str());
|
||||
BOOST_CHECK_EQUAL(y.str(), y1.str());
|
||||
BOOST_CHECK_EQUAL(bi.str(), bi1.str());
|
||||
|
||||
// Both positive:
|
||||
z = x + bi;
|
||||
z1 = x1 + bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = x - bi;
|
||||
z1 = x1 - bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = x * bi;
|
||||
z1 = x1 * bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = x / bi;
|
||||
z1 = x1 / bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = bi + x;
|
||||
z1 = bi1 + x1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = bi - x;
|
||||
z1 = bi1 - x1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = bi * x;
|
||||
z1 = bi1 * x1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = bi / x;
|
||||
z1 = bi1 / x1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
|
||||
// x negative:
|
||||
x = -x;
|
||||
x1 = -x1;
|
||||
z = x + bi;
|
||||
z1 = x1 + bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = x - bi;
|
||||
z1 = x1 - bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = x * bi;
|
||||
z1 = x1 * bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = x / bi;
|
||||
z1 = x1 / bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = bi + x;
|
||||
z1 = bi1 + x1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = bi - x;
|
||||
z1 = bi1 - x1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = bi * x;
|
||||
z1 = bi1 * x1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = bi / x;
|
||||
z1 = bi1 / x1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
|
||||
// x and bi both negative:
|
||||
z = x + bi;
|
||||
z1 = x1 + bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = x - bi;
|
||||
z1 = x1 - bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = x * bi;
|
||||
z1 = x1 * bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = x / bi;
|
||||
z1 = x1 / bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = bi + x;
|
||||
z1 = bi1 + x1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = bi - x;
|
||||
z1 = bi1 - x1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = bi * x;
|
||||
z1 = bi1 * x1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = bi / x;
|
||||
z1 = bi1 / x1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
|
||||
// bi negative:
|
||||
x = -x;
|
||||
x1 = -x1;
|
||||
z = x + bi;
|
||||
z1 = x1 + bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = x - bi;
|
||||
z1 = x1 - bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = x * bi;
|
||||
z1 = x1 * bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = x / bi;
|
||||
z1 = x1 / bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = bi + x;
|
||||
z1 = bi1 + x1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = bi - x;
|
||||
z1 = bi1 - x1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = bi * x;
|
||||
z1 = bi1 * x1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = bi / x;
|
||||
z1 = bi1 / x1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
|
||||
bi = -bi;
|
||||
bi1 = -bi1;
|
||||
// Inplace:
|
||||
z = x;
|
||||
z1 = x1;
|
||||
z += bi;
|
||||
z1 += bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = x;
|
||||
z1 = x1;
|
||||
z -= bi;
|
||||
z1 -= bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = x;
|
||||
z1 = x1;
|
||||
z *= bi;
|
||||
z1 *= bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = x;
|
||||
z1 = x1;
|
||||
z /= bi;
|
||||
z1 /= bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
|
||||
// bi negative:
|
||||
bi = -bi;
|
||||
bi1 = -bi1;
|
||||
z = x;
|
||||
z1 = x1;
|
||||
z += bi;
|
||||
z1 += bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = x;
|
||||
z1 = x1;
|
||||
z -= bi;
|
||||
z1 -= bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = x;
|
||||
z1 = x1;
|
||||
z *= bi;
|
||||
z1 *= bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = x;
|
||||
z1 = x1;
|
||||
z /= bi;
|
||||
z1 /= bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
|
||||
// Both negative:
|
||||
x = -x;
|
||||
x1 = -x1;
|
||||
z = x;
|
||||
z1 = x1;
|
||||
z += bi;
|
||||
z1 += bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = x;
|
||||
z1 = x1;
|
||||
z -= bi;
|
||||
z1 -= bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = x;
|
||||
z1 = x1;
|
||||
z *= bi;
|
||||
z1 *= bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = x;
|
||||
z1 = x1;
|
||||
z /= bi;
|
||||
z1 /= bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
|
||||
// x negative:
|
||||
bi = -bi;
|
||||
bi1 = -bi1;
|
||||
z = x;
|
||||
z1 = x1;
|
||||
z += bi;
|
||||
z1 += bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = x;
|
||||
z1 = x1;
|
||||
z -= bi;
|
||||
z1 -= bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = x;
|
||||
z1 = x1;
|
||||
z *= bi;
|
||||
z1 *= bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
z = x;
|
||||
z1 = x1;
|
||||
z /= bi;
|
||||
z1 /= bi1;
|
||||
BOOST_CHECK_EQUAL(z.str(), z1.str());
|
||||
|
||||
BOOST_CHECK_EQUAL((x == bi), (x1 == bi1));
|
||||
BOOST_CHECK_EQUAL((x != bi), (x1 != bi1));
|
||||
BOOST_CHECK_EQUAL((x <= bi), (x1 <= bi1));
|
||||
BOOST_CHECK_EQUAL((x >= bi), (x1 >= bi1));
|
||||
BOOST_CHECK_EQUAL((x < bi), (x1 < bi1));
|
||||
BOOST_CHECK_EQUAL((x > bi), (x1 > bi1));
|
||||
|
||||
z = bi;
|
||||
z1 = bi1;
|
||||
BOOST_CHECK_EQUAL((x == bi), (x1 == bi1));
|
||||
BOOST_CHECK_EQUAL((x != bi), (x1 != bi1));
|
||||
BOOST_CHECK_EQUAL((x <= bi), (x1 <= bi1));
|
||||
BOOST_CHECK_EQUAL((x >= bi), (x1 >= bi1));
|
||||
BOOST_CHECK_EQUAL((x < bi), (x1 < bi1));
|
||||
BOOST_CHECK_EQUAL((x > bi), (x1 > bi1));
|
||||
}
|
||||
|
||||
void test()
|
||||
{
|
||||
using namespace boost::multiprecision;
|
||||
@@ -951,6 +1187,7 @@ struct tester
|
||||
t3();
|
||||
t4();
|
||||
t5();
|
||||
t6();
|
||||
|
||||
if (last_error_count != (unsigned)boost::detail::test_errors())
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user