mirror of
https://github.com/boostorg/multiprecision.git
synced 2026-01-19 04:22:11 +00:00
Ensure remainder has correct sign when the result is zero.
Also ensure float128 specializations of eval_signbit are actually called. Change return type of signbit to bool to match std::signbit and update docs. Add test case. Fixes https://github.com/boostorg/multiprecision/issues/426.
This commit is contained in:
@@ -452,7 +452,7 @@ are either trivial or are forwarded to the Boost.Math implementations by default
|
||||
The full list of these functions is:
|
||||
|
||||
int sign (const ``['number-or-expression-template-type]``&);
|
||||
int signbit (const ``['number-or-expression-template-type]``&);
|
||||
bool signbit (const ``['number-or-expression-template-type]``&);
|
||||
``['number]`` changesign (const ``['number-or-expression-template-type]``&);
|
||||
``['number]`` copysign (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
|
||||
``['number]`` asinh (const ``['number-or-expression-template-type]``&);
|
||||
|
||||
@@ -199,7 +199,7 @@
|
||||
bool isinf (const ``['number-or-expression-template-type]``&);
|
||||
bool isnan (const ``['number-or-expression-template-type]``&);
|
||||
bool isnormal (const ``['number-or-expression-template-type]``&);
|
||||
int signbit (const ``['number-or-expression-template-type]``&);
|
||||
bool signbit (const ``['number-or-expression-template-type]``&);
|
||||
|
||||
bool isgreater (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
|
||||
bool isgreaterequal(const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
|
||||
@@ -623,7 +623,7 @@ that allows arithmetic to be performed on native integer types producing an exte
|
||||
bool isinf (const ``['number-or-expression-template-type]``&);
|
||||
bool isnan (const ``['number-or-expression-template-type]``&);
|
||||
bool isnormal (const ``['number-or-expression-template-type]``&);
|
||||
int signbit (const ``['number-or-expression-template-type]``&);
|
||||
bool signbit (const ``['number-or-expression-template-type]``&);
|
||||
|
||||
bool isgreater (const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
|
||||
bool isgreaterequal(const ``['number-or-expression-template-type]``&, const ``['number-or-expression-template-type]``&);
|
||||
|
||||
@@ -1328,6 +1328,11 @@ inline BOOST_MP_CXX14_CONSTEXPR void eval_remquo(T& result, const T& a, const T&
|
||||
eval_convert_to(pi, n);
|
||||
eval_multiply(n, b);
|
||||
eval_subtract(result, a, n);
|
||||
if (eval_is_zero(result))
|
||||
{
|
||||
if (eval_signbit(a))
|
||||
result.negate();
|
||||
}
|
||||
}
|
||||
template <class T, class A>
|
||||
inline BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value, void>::type eval_remquo(T& result, const T& x, const A& a, int* pi)
|
||||
@@ -2203,16 +2208,16 @@ inline BOOST_MP_CXX14_CONSTEXPR int sign BOOST_PREVENT_MACRO_SUBSTITUTION(const
|
||||
}
|
||||
|
||||
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
||||
inline BOOST_MP_CXX14_CONSTEXPR int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
||||
inline BOOST_MP_CXX14_CONSTEXPR bool signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
||||
{
|
||||
using default_ops::eval_signbit;
|
||||
return eval_signbit(arg.backend());
|
||||
return static_cast<bool>(eval_signbit(arg.backend()));
|
||||
}
|
||||
template <class tag, class A1, class A2, class A3, class A4>
|
||||
inline BOOST_MP_CXX14_CONSTEXPR int signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
||||
inline BOOST_MP_CXX14_CONSTEXPR bool signbit BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
|
||||
{
|
||||
using value_type = typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type;
|
||||
return signbit BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg));
|
||||
return static_cast<bool>(signbit BOOST_PREVENT_MACRO_SUBSTITUTION(value_type(arg)));
|
||||
}
|
||||
template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
|
||||
inline BOOST_MP_CXX14_CONSTEXPR multiprecision::number<Backend, ExpressionTemplates> changesign BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
|
||||
|
||||
@@ -723,6 +723,8 @@ inline boost::multiprecision::number<boost::multiprecision::backends::float128_b
|
||||
return ::copysignq(a.backend().value(), b.backend().value());
|
||||
}
|
||||
|
||||
namespace backends {
|
||||
|
||||
inline void eval_remainder(float128_backend& result, const float128_backend& a, const float128_backend& b)
|
||||
{
|
||||
result.value() = remainderq(a.value(), b.value());
|
||||
@@ -731,6 +733,8 @@ inline void eval_remainder(float128_backend& result, const float128_backend& a,
|
||||
{
|
||||
result.value() = remquoq(a.value(), b.value(), pi);
|
||||
}
|
||||
} // namespace backends
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace multiprecision
|
||||
|
||||
@@ -1134,6 +1134,7 @@ test-suite misc :
|
||||
[ run git_issue_175.cpp ]
|
||||
[ run git_issue_248.cpp ]
|
||||
[ run git_issue_265.cpp : : : [ check-target-builds ../config//has_mpfr : <source>gmp <source>mpfr : <build>no ] ]
|
||||
[ run git_issue_426.cpp : : : [ check-target-builds ../config//has_mpfr : <source>gmp <source>mpfr <define>TEST_MPFR ] [ check-target-builds ../config//has_float128 : <source>quadmath <define>TEST_FLOAT128 ] ]
|
||||
[ run git_issue_277.cpp ]
|
||||
[ run git_issue_313.cpp ]
|
||||
[ compile git_issue_98.cpp :
|
||||
|
||||
50
test/git_issue_426.cpp
Normal file
50
test/git_issue_426.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright 2019 John Maddock. Distributed under the Boost
|
||||
// Software License, Version 1.0. (See accompanying file
|
||||
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include <boost/multiprecision/cpp_bin_float.hpp>
|
||||
#ifdef TEST_MPFR
|
||||
#include <boost/multiprecision/mpfr.hpp>
|
||||
#endif
|
||||
#ifdef TEST_FLOAT128
|
||||
#include <boost/multiprecision/float128.hpp>
|
||||
#endif
|
||||
#include "test.hpp"
|
||||
|
||||
template <class T>
|
||||
void test()
|
||||
{
|
||||
T d = 360;
|
||||
for (int i = 2; i >= -2; --i)
|
||||
{
|
||||
T x = i * d;
|
||||
T y = remainder(x, d);
|
||||
if (y == 0)
|
||||
BOOST_CHECK_EQUAL(signbit(y), signbit(x));
|
||||
if (i == 0)
|
||||
{
|
||||
x = -x;
|
||||
y = remainder(x, d);
|
||||
if (y == 0)
|
||||
BOOST_CHECK_EQUAL(signbit(y), signbit(x));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test<boost::multiprecision::cpp_bin_float_50>();
|
||||
// No signed zero:
|
||||
//test<boost::multiprecision::cpp_dec_float_50>();
|
||||
//test<boost::multiprecision::mpf_float_50>();
|
||||
#ifdef TEST_MPFR
|
||||
test<boost::multiprecision::mpfr_float_50>();
|
||||
#endif
|
||||
#ifdef TEST_FLOAT128
|
||||
test<boost::multiprecision::float128>();
|
||||
#endif
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user