2
0
mirror of https://github.com/boostorg/math.git synced 2026-01-19 04:22:09 +00:00

Improve performance of sin_pi and cos_pi:

Use a static_cast to int when available for parity checking as it's much faster than itrunc.
Don't check for overflows in the result, since we know the result is in [-1,1].
This commit is contained in:
jzmaddock
2019-05-03 19:11:03 +01:00
parent 24b410d0b0
commit c759981a2a
3 changed files with 64 additions and 7 deletions

View File

@@ -33,7 +33,7 @@ T cos_pi_imp(T x, const Policy& pol)
x = -x;
}
T rem = floor(x);
if(itrunc(rem, pol) & 1)
if(iconvert(rem, pol) & 1)
invert = !invert;
rem = x - rem;
if(rem > 0.5f)
@@ -66,7 +66,10 @@ inline typename tools::promote_args<T>::type cos_pi(T x, const Policy&)
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
policies::assert_undefined<>,
// We want to igore overflows since the result is in [-1,1] and the
// check slows the code down considerably.
policies::overflow_error<policies::ignore_error> >::type forwarding_policy;
return policies::checked_narrowing_cast<result_type, forwarding_policy>(boost::math::detail::cos_pi_imp<value_type>(x, forwarding_policy()), "cos_pi");
}

View File

@@ -20,11 +20,11 @@
namespace boost{ namespace math{ namespace detail{
template <class T, class Policy>
T sin_pi_imp(T x, const Policy& pol)
inline T sin_pi_imp(T x, const Policy& pol)
{
BOOST_MATH_STD_USING // ADL of std names
if(x < 0)
return -sin_pi(-x);
return -sin_pi_imp(T(-x), pol);
// sin of pi*x:
bool invert;
if(x < 0.5)
@@ -38,7 +38,7 @@ T sin_pi_imp(T x, const Policy& pol)
invert = false;
T rem = floor(x);
if(itrunc(rem, pol) & 1)
if(iconvert(rem, pol) & 1)
invert = !invert;
rem = x - rem;
if(rem > 0.5f)
@@ -62,8 +62,11 @@ inline typename tools::promote_args<T>::type sin_pi(T x, const Policy&)
policies::promote_float<false>,
policies::promote_double<false>,
policies::discrete_quantile<>,
policies::assert_undefined<> >::type forwarding_policy;
return policies::checked_narrowing_cast<result_type, forwarding_policy>(boost::math::detail::sin_pi_imp<value_type>(x, forwarding_policy()), "cos_pi");
policies::assert_undefined<>,
// We want to igore overflows since the result is in [-1,1] and the
// check slows the code down considerably.
policies::overflow_error<policies::ignore_error> >::type forwarding_policy;
return policies::checked_narrowing_cast<result_type, forwarding_policy>(boost::math::detail::sin_pi_imp<value_type>(x, forwarding_policy()), "sin_pi");
}
template <class T>

View File

@@ -14,6 +14,8 @@
#include <boost/math/tools/config.hpp>
#include <boost/math/policies/error_handling.hpp>
#include <boost/math/special_functions/fpclassify.hpp>
#include <boost/type_traits/is_constructible.hpp>
#include <boost/core/enable_if.hpp>
namespace boost{ namespace math{ namespace detail{
@@ -106,6 +108,55 @@ inline boost::long_long_type lltrunc(const T& v)
#endif
template <class T, class Policy>
inline typename boost::enable_if_c<boost::is_constructible<int, T>::value, int>::type
iconvert(const T& v, const Policy&)
{
return static_cast<int>(v);
}
template <class T, class Policy>
inline typename boost::disable_if_c<boost::is_constructible<int, T>::value, int>::type
iconvert(const T& v, const Policy& pol)
{
using boost::math::itrunc;
return itrunc(v, pol);
}
template <class T, class Policy>
inline typename boost::enable_if_c<boost::is_constructible<long, T>::value, long>::type
lconvert(const T& v, const Policy&)
{
return static_cast<long>(v);
}
template <class T, class Policy>
inline typename boost::disable_if_c<boost::is_constructible<long, T>::value, long>::type
lconvert(const T& v, const Policy& pol)
{
using boost::math::ltrunc;
return ltrunc(v, pol);
}
#ifdef BOOST_HAS_LONG_LONG
template <class T, class Policy>
inline typename boost::enable_if_c<boost::is_constructible<boost::long_long_type, T>::value, boost::long_long_type>::type
llconvertert(const T& v, const Policy&)
{
return static_cast<boost::long_long_type>(v);
}
template <class T, class Policy>
inline typename boost::disable_if_c<boost::is_constructible<boost::long_long_type, T>::value, boost::long_long_type>::type
llconvertert(const T& v, const Policy& pol)
{
using boost::math::lltrunc;
return lltrunc(v, pol);
}
#endif
}} // namespaces
#endif // BOOST_MATH_TRUNC_HPP