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

sinc_pi: simplify and correct taylor series usage, improve tests.

See https://svn.boost.org/trac10/ticket/13606.
This commit is contained in:
jzmaddock
2018-06-19 18:26:43 +01:00
parent 47b022cb3a
commit 838dd94193
2 changed files with 38 additions and 26 deletions

View File

@@ -43,37 +43,14 @@ namespace boost
{
BOOST_MATH_STD_USING
T const taylor_0_bound = 2.449 * tools::epsilon<T>();
T const taylor_2_bound = 3.30 * tools::root_epsilon<T>();
T const taylor_n_bound = 4.14 * tools::forth_root_epsilon<T>();
if (abs(x) >= taylor_n_bound)
if (abs(x) >= 3.3 * tools::forth_root_epsilon<T>())
{
return(sin(x)/x);
}
else
{
// approximation by taylor series in x at 0 up to order 0
T result = static_cast<T>(1);
if (abs(x) >= taylor_0_bound)
{
T x2 = x*x;
if (abs(x) >= taylor_2_bound)
{
// approximation by taylor series in x at 0 up to order 4
result = 1.0 + x2 * (-1.0 + x2 / 20.0) / 6.0;
}
else
{
// approximation by taylor series in x at 0 up to order 2
result -= x2 / static_cast<T>(6);
}
}
return(result);
// |x| < (eps*120)^(1/4)
return 1 - x * x / 6;
}
}

View File

@@ -5,6 +5,8 @@
#include <pch_light.hpp>
#include "test_sinc.hpp"
#include <boost/multiprecision/cpp_bin_float.hpp>
#include <boost/math/special_functions/next.hpp>
//
// DESCRIPTION:
@@ -50,6 +52,36 @@ void expected_results()
<< BOOST_STDLIB << ", " << BOOST_PLATFORM << std::endl;
}
template <class T>
void test_close_to_transition()
{
T transition = 3.3f * boost::math::tools::forth_root_epsilon<T>();
T val = transition;
for (unsigned i = 0; i < 100; ++i)
{
boost::multiprecision::cpp_bin_float_50 extended = val;
extended = sin(extended) / extended;
T expected = extended.template convert_to<T>();
T result = boost::math::sinc_pi(val);
BOOST_CHECK_LE(boost::math::epsilon_difference(result, expected), 3);
result = boost::math::sinc_pi(-val);
BOOST_CHECK_LE(boost::math::epsilon_difference(result, expected), 3);
val = boost::math::float_prior(val);
}
for (unsigned i = 0; i < 100; ++i)
{
boost::multiprecision::cpp_bin_float_50 extended = val;
extended = sin(extended) / extended;
T expected = extended.template convert_to<T>();
T result = boost::math::sinc_pi(val);
BOOST_CHECK_LE(boost::math::epsilon_difference(result, expected), 3);
result = boost::math::sinc_pi(-val);
BOOST_CHECK_LE(boost::math::epsilon_difference(result, expected), 3);
val = boost::math::float_next(val);
}
}
BOOST_AUTO_TEST_CASE( test_main )
{
@@ -58,9 +90,12 @@ BOOST_AUTO_TEST_CASE( test_main )
expected_results();
test_sinc(0.1F, "float");
test_close_to_transition<float>();
test_sinc(0.1, "double");
test_close_to_transition<double>();
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
test_sinc(0.1L, "long double");
test_close_to_transition<long double>();
#ifndef BOOST_MATH_NO_REAL_CONCEPT_TESTS
test_sinc(boost::math::concepts::real_concept(0.1), "real_concept");
#endif