|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r83619 - in trunk: boost/multiprecision/detail/functions libs/multiprecision/test
From: john_at_[hidden]
Date: 2013-03-28 07:27:09
Author: johnmaddock
Date: 2013-03-28 07:27:08 EDT (Thu, 28 Mar 2013)
New Revision: 83619
URL: http://svn.boost.org/trac/boost/changeset/83619
Log:
Fix bug(s) that cause variable reuse in function calls to fail.
Add additional test cases.
Fixes #8326.
Text files modified:
trunk/boost/multiprecision/detail/functions/pow.hpp | 9 +++
trunk/boost/multiprecision/detail/functions/trig.hpp | 9 ++
trunk/libs/multiprecision/test/test_arithmetic.hpp | 115 +++++++++++++++++++++++++++++++++++++--
3 files changed, 126 insertions(+), 7 deletions(-)
Modified: trunk/boost/multiprecision/detail/functions/pow.hpp
==============================================================================
--- trunk/boost/multiprecision/detail/functions/pow.hpp (original)
+++ trunk/boost/multiprecision/detail/functions/pow.hpp 2013-03-28 07:27:08 EDT (Thu, 28 Mar 2013)
@@ -25,6 +25,14 @@
typedef typename boost::multiprecision::detail::canonical<U, T>::type int_type;
+ if(&result == &t)
+ {
+ T temp;
+ pow_imp(temp, t, p, mpl::false_());
+ result = temp;
+ return;
+ }
+
// This will store the result.
if(U(p % U(2)) != U(0))
{
@@ -411,6 +419,7 @@
T t;
eval_pow(t, x, a);
result = t;
+ return;
}
if(a.compare(si_type(1)) == 0)
Modified: trunk/boost/multiprecision/detail/functions/trig.hpp
==============================================================================
--- trunk/boost/multiprecision/detail/functions/trig.hpp (original)
+++ trunk/boost/multiprecision/detail/functions/trig.hpp 2013-03-28 07:27:08 EDT (Thu, 28 Mar 2013)
@@ -221,7 +221,7 @@
if(&result == &x)
{
T temp;
- eval_sin(temp, x);
+ eval_cos(temp, x);
result = temp;
return;
}
@@ -361,6 +361,13 @@
void eval_tan(T& result, const T& x)
{
BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The tan function is only valid for floating point types.");
+ if(&result == &x)
+ {
+ T temp;
+ eval_tan(temp, x);
+ result = temp;
+ return;
+ }
T t;
eval_sin(result, x);
eval_cos(t, x);
Modified: trunk/libs/multiprecision/test/test_arithmetic.hpp
==============================================================================
--- trunk/libs/multiprecision/test/test_arithmetic.hpp (original)
+++ trunk/libs/multiprecision/test/test_arithmetic.hpp 2013-03-28 07:27:08 EDT (Thu, 28 Mar 2013)
@@ -641,6 +641,107 @@
}
template <class Real, class T>
+void test_float_funcs(const T&){}
+
+template <class Real>
+void test_float_funcs(const boost::mpl::true_&)
+{
+ if(boost::multiprecision::is_interval_number<Real>::value)
+ return;
+ //
+ // Test variable reuse in function calls, see https://svn.boost.org/trac/boost/ticket/8326
+ //
+ Real a(2), b(10);
+ a = pow(a, b);
+ BOOST_CHECK_EQUAL(a, 1024);
+ a = 2;
+ b = pow(a, b);
+ BOOST_CHECK_EQUAL(b, 1024);
+ b = 10;
+ a = pow(a, 10);
+ BOOST_CHECK_EQUAL(a, 1024);
+ a = -2;
+ a = abs(a);
+ BOOST_CHECK_EQUAL(a, 2);
+ a = -2;
+ a = fabs(a);
+ BOOST_CHECK_EQUAL(a, 2);
+ a = 2.5;
+ a = floor(a);
+ BOOST_CHECK_EQUAL(a, 2);
+ a = 2.5;
+ a = ceil(a);
+ BOOST_CHECK_EQUAL(a, 3);
+ a = 2.5;
+ a = trunc(a);
+ BOOST_CHECK_EQUAL(a, 2);
+ a = 2.25;
+ a = round(a);
+ BOOST_CHECK_EQUAL(a, 2);
+ a = 2;
+ a = ldexp(a, 1);
+ BOOST_CHECK_EQUAL(a, 4);
+ int i;
+ a = frexp(a, &i);
+ BOOST_CHECK_EQUAL(a, 0.5);
+
+ Real tol = std::numeric_limits<Real>::epsilon() * 3;
+ a = 4;
+ a = sqrt(a);
+ BOOST_CHECK_CLOSE_FRACTION(a, 2, tol);
+ a = 3;
+ a = exp(a);
+ BOOST_CHECK_CLOSE_FRACTION(a, Real(exp(Real(3))), tol);
+ a = 3;
+ a = log(a);
+ BOOST_CHECK_CLOSE_FRACTION(a, Real(log(Real(3))), tol);
+ a = 3;
+ a = log10(a);
+ BOOST_CHECK_CLOSE_FRACTION(a, Real(log10(Real(3))), tol);
+
+ a = 0.5;
+ a = sin(a);
+ BOOST_CHECK_CLOSE_FRACTION(a, Real(sin(Real(0.5))), tol);
+ a = 0.5;
+ a = cos(a);
+ BOOST_CHECK_CLOSE_FRACTION(a, Real(cos(Real(0.5))), tol);
+ a = 0.5;
+ a = tan(a);
+ BOOST_CHECK_CLOSE_FRACTION(a, Real(tan(Real(0.5))), tol);
+ a = 0.5;
+ a = asin(a);
+ BOOST_CHECK_CLOSE_FRACTION(a, Real(asin(Real(0.5))), tol);
+ a = 0.5;
+ a = acos(a);
+ BOOST_CHECK_CLOSE_FRACTION(a, Real(acos(Real(0.5))), tol);
+ a = 0.5;
+ a = atan(a);
+ BOOST_CHECK_CLOSE_FRACTION(a, Real(atan(Real(0.5))), tol);
+ a = 0.5;
+ a = sinh(a);
+ BOOST_CHECK_CLOSE_FRACTION(a, Real(sinh(Real(0.5))), tol);
+ a = 0.5;
+ a = cosh(a);
+ BOOST_CHECK_CLOSE_FRACTION(a, Real(cosh(Real(0.5))), tol);
+ a = 0.5;
+ a = tanh(a);
+ BOOST_CHECK_CLOSE_FRACTION(a, Real(tanh(Real(0.5))), tol);
+ a = 4;
+ b = 2;
+ a = fmod(a, b);
+ BOOST_CHECK_CLOSE_FRACTION(a, Real(fmod(Real(4), Real(2))), tol);
+ a = 4;
+ b = fmod(a, b);
+ BOOST_CHECK_CLOSE_FRACTION(b, Real(fmod(Real(4), Real(2))), tol);
+ b = 2;
+ a = atan2(a, b);
+ BOOST_CHECK_CLOSE_FRACTION(a, Real(atan2(Real(4), Real(2))), tol);
+ a = 4;
+ b = atan2(a, b);
+ BOOST_CHECK_CLOSE_FRACTION(b, Real(atan2(Real(4), Real(2))), tol);
+}
+
+template <class Real, class T>
void test_float_ops(const T&){}
template <class Real>
@@ -662,15 +763,15 @@
BOOST_CHECK_EQUAL(ldexp(Real(2), 5) , 64);
BOOST_CHECK_EQUAL(ldexp(Real(2), -5) , Real(2) / 32);
Real v(512);
- int exp;
- Real r = frexp(v, &exp);
+ int exponent;
+ Real r = frexp(v, &exponent);
BOOST_CHECK_EQUAL(r , 0.5);
- BOOST_CHECK_EQUAL(exp , 10);
+ BOOST_CHECK_EQUAL(exponent , 10);
BOOST_CHECK_EQUAL(v , 512);
v = 1 / v;
- r = frexp(v, &exp);
+ r = frexp(v, &exponent);
BOOST_CHECK_EQUAL(r , 0.5);
- BOOST_CHECK_EQUAL(exp , -8);
+ BOOST_CHECK_EQUAL(exponent , -8);
typedef typename Real::backend_type::exponent_type e_type;
BOOST_CHECK_EQUAL(ldexp(Real(2), e_type(5)) , 64);
BOOST_CHECK_EQUAL(ldexp(Real(2), e_type(-5)) , Real(2) / 32);
@@ -685,7 +786,7 @@
BOOST_CHECK_EQUAL(r , 0.5);
BOOST_CHECK_EQUAL(exp2 , -8);
//
- // pow and exp:
+ // pow and exponent:
//
v = 3.25;
r = pow(v, 0);
@@ -719,6 +820,8 @@
BOOST_CHECK_THROW(Real(Real(20) / 0u), std::overflow_error);
}
}
+
+ test_float_funcs<Real>(boost::mpl::bool_<std::numeric_limits<Real>::is_specialized>());
}
template <class T>
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk