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:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user