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

Merge pull request #433 from boostorg/issue396

Try fix min Bn arg for recur.
This commit is contained in:
jzmaddock
2020-12-24 18:35:46 +00:00
committed by GitHub
6 changed files with 230 additions and 12 deletions

View File

@@ -322,12 +322,12 @@ namespace boost{ namespace math
BOOST_DEFINE_MATH_CONSTANT(two_div_root_pi, 1.12837916709551257389615890312154517168810125, "1.12837916709551257389615890312154517168810125865799771368817144342128493688298682897348732040421472688605669581272")
#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)
BOOST_DEFINE_MATH_CONSTANT(first_feigenbaum, 4.66920160910299067185320382046620161725818557747576863274, "4.6692016091029906718532038204662016172581855774757686327456513430041343302113147371386897440239480138171");
BOOST_DEFINE_MATH_CONSTANT(plastic, 1.324717957244746025960908854478097340734404056901733364534, "1.32471795724474602596090885447809734073440405690173336453401505030282785124554759405469934798178728032991");
BOOST_DEFINE_MATH_CONSTANT(gauss, 0.834626841674073186281429732799046808993993013490347002449, "0.83462684167407318628142973279904680899399301349034700244982737010368199270952641186969116035127532412906785");
BOOST_DEFINE_MATH_CONSTANT(dottie, 0.739085133215160641655312087673873404013411758900757464965, "0.739085133215160641655312087673873404013411758900757464965680635773284654883547594599376106931766531849801246");
BOOST_DEFINE_MATH_CONSTANT(reciprocal_fibonacci, 3.35988566624317755317201130291892717968890513, "3.35988566624317755317201130291892717968890513373196848649555381532513031899668338361541621645679008729704");
BOOST_DEFINE_MATH_CONSTANT(laplace_limit, 0.662743419349181580974742097109252907056233549115022417, "0.66274341934918158097474209710925290705623354911502241752039253499097185308651127724965480259895818168");
BOOST_DEFINE_MATH_CONSTANT(first_feigenbaum, 4.66920160910299067185320382046620161725818557747576863274, "4.6692016091029906718532038204662016172581855774757686327456513430041343302113147371386897440239480138171")
BOOST_DEFINE_MATH_CONSTANT(plastic, 1.324717957244746025960908854478097340734404056901733364534, "1.32471795724474602596090885447809734073440405690173336453401505030282785124554759405469934798178728032991")
BOOST_DEFINE_MATH_CONSTANT(gauss, 0.834626841674073186281429732799046808993993013490347002449, "0.83462684167407318628142973279904680899399301349034700244982737010368199270952641186969116035127532412906785")
BOOST_DEFINE_MATH_CONSTANT(dottie, 0.739085133215160641655312087673873404013411758900757464965, "0.739085133215160641655312087673873404013411758900757464965680635773284654883547594599376106931766531849801246")
BOOST_DEFINE_MATH_CONSTANT(reciprocal_fibonacci, 3.35988566624317755317201130291892717968890513, "3.35988566624317755317201130291892717968890513373196848649555381532513031899668338361541621645679008729704")
BOOST_DEFINE_MATH_CONSTANT(laplace_limit, 0.662743419349181580974742097109252907056233549115022417, "0.66274341934918158097474209710925290705623354911502241752039253499097185308651127724965480259895818168")
#endif
} // namespace constants

View File

@@ -6,6 +6,7 @@
#ifndef BOOST_MATH_SPECIAL_CHEBYSHEV_HPP
#define BOOST_MATH_SPECIAL_CHEBYSHEV_HPP
#include <cmath>
#include <boost/math/special_functions/math_fwd.hpp>
#include <boost/math/policies/error_handling.hpp>
#include <boost/math/constants/constants.hpp>
#include <boost/math/tools/promotion.hpp>

View File

@@ -1,7 +1,7 @@
// Copyright John Maddock 2006-7, 2013-14.
// Copyright John Maddock 2006-7, 2013-20.
// Copyright Paul A. Bristow 2007, 2013-14.
// Copyright Nikhar Agrawal 2013-14
// Copyright Christopher Kormanyos 2013-14
// Copyright Christopher Kormanyos 2013-14, 2020
// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0. (See accompanying file
@@ -366,13 +366,35 @@ std::size_t highest_bernoulli_index()
template<class T>
int minimum_argument_for_bernoulli_recursion()
{
BOOST_MATH_STD_USING
const float digits10_of_type = (std::numeric_limits<T>::is_specialized
? static_cast<float>(std::numeric_limits<T>::digits10)
: static_cast<float>(boost::math::tools::digits<T>() * 0.301F));
? (float) std::numeric_limits<T>::digits10
: (float) (boost::math::tools::digits<T>() * 0.301F));
const float limit = std::ceil(std::pow(1.0f / std::ldexp(1.0f, 1-boost::math::tools::digits<T>()), 1.0f / 20.0f));
int min_arg = (int) (digits10_of_type * 1.7F);
return (int)((std::min)(digits10_of_type * 1.7F, limit));
if(digits10_of_type < 50.0F)
{
// The following code sequence has been modified
// within the context of issue 396.
// The calculation of the test-variable limit has now
// been protected against overflow/underflow dangers.
// The previous line looked like this and did, in fact,
// underflow ldexp when using certain multiprecision types.
// const float limit = std::ceil(std::pow(1.0f / std::ldexp(1.0f, 1-boost::math::tools::digits<T>()), 1.0f / 20.0f));
// The new safe version of the limit check is now here.
const float d2_minus_one = ((digits10_of_type / 0.301F) - 1.0F);
const float limit = ceil(exp((d2_minus_one * log(2.0F)) / 20.0F));
min_arg = (int) ((std::min)(digits10_of_type * 1.7F, limit));
}
return min_arg;
}
template <class T, class Policy>

View File

@@ -487,6 +487,8 @@ test-suite special_fun :
[ run test_round.cpp pch ../../test/build//boost_unit_test_framework ]
[ run test_spherical_harmonic.cpp test_instances//test_instances pch_light ../../test/build//boost_unit_test_framework ]
[ run test_sign.cpp ../../test/build//boost_unit_test_framework ]
[ run test_tgamma_for_issue396_part1.cpp ../../test/build//boost_unit_test_framework : : : <toolset>gcc-mingw:<cxxflags>-Wa,-mbig-obj <debug-symbols>off <toolset>msvc:<cxxflags>/bigobj ]
[ run test_tgamma_for_issue396_part2.cpp ../../test/build//boost_unit_test_framework : : : <toolset>gcc-mingw:<cxxflags>-Wa,-mbig-obj <debug-symbols>off <toolset>msvc:<cxxflags>/bigobj ]
[ run test_tgamma_ratio.cpp test_instances//test_instances pch_light ../../test/build//boost_unit_test_framework ]
[ run test_trig.cpp test_instances//test_instances pch_light ../../test/build//boost_unit_test_framework ]
[ run test_zeta.cpp ../../test/build//boost_unit_test_framework test_instances//test_instances pch_light ]

View File

@@ -0,0 +1,98 @@
///////////////////////////////////////////////////////////////////
// Copyright Christopher Kormanyos 2020.
// Copyright John Maddock 2020.
// 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)
//
#if 0
#define BOOST_TEST_MODULE test_tgamma_for_issue396
#include <boost/test/included/unit_test.hpp>
#else
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp> // Boost.Test
#endif
#include <boost/array.hpp>
#include <boost/math/constants/constants.hpp>
#include <boost/math/special_functions/gamma.hpp>
#include <boost/multiprecision/cpp_bin_float.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
// In issue 396, a bug regarding overflow was traced back to the tgamma function.
// This test file tests the fix in 433 and its corresponding original bug report code.
const char* issue396_control_string0 = "0.88622692545275801364908374167057259139877472806119356410690389492645564229551609068747532836927233270811341181214128533311807643286221130126254685480139353423101884932655256142496258651447541311446604768963398140008731950767573986025835009509261700929272348724745632015696088776295310820270966625045319920380686673873757671683399489468292591820439772558258086938002953369671589566640492742312409245102732742609780662578082373375752136938052805399806355360503018602224183618264830685404716174941583421211";
const char* issue396_control_string1 = "1.1332783889487855673345741655888924755602983082751597766087234145294833900560041537176305387276072906583502717008932373348895801731780765775979953796646009714415152490764416630481375706606053932396039541459764525989187023837695167161085523804417015113740063535865261183579508922972990386756543208549178543857406373798865630303794109491220205170302558277398183764099268751365861892723863412249690833216320407918186480305202146014474770321625907339955121137559264239090240758401696425720048012081453338360E6";
const char* issue396_control_string2 = "9.3209631040827166083491098091419104379064970381623611540161175194120765977611623552218076053836060223609993676387199220631835256331102029826429784793420637988460945604451237342972023988743201341318701614328454618664952897316247603329530308777063116667275003586843755354841307657702809317290363831151480295446074722690100652644579131609996151999119113967501099655433566352849645431012667388627160383486515144610582794470005796689975604764040892168183647321540427819244511610500074895473959438490375652158E156";
const char* issue396_control_string3 = "1.2723011956950554641822441803774445695066347098655278283939929838804808618389143636393314317333622154343715992535881414698586440455330620652019981627229614973177953241634213768203151670660953863412381880742653187501307209325406338924004280546485392703623101051957976224599412003938216329590158926122017907280168159527761842471509358725974702333390709735919152262756462872191402491961250987725812831155116532550035967994387094267848607390288008530653715254376729558412833771092612838971719786622446726968E2566";
template<class BigFloatType>
bool test_tgamma_for_issue396_value_checker()
{
typedef BigFloatType floating_point_type;
// Table[N[Gamma[(1/2) + (10^n)], 503], {n, 0, 3, 1}]
const boost::array<floating_point_type, 4U> control =
{{
floating_point_type(issue396_control_string0),
floating_point_type(issue396_control_string1),
floating_point_type(issue396_control_string2),
floating_point_type(issue396_control_string3)
}};
boost::uint32_t ten_pow_n = (boost::uint32_t) (1);
const floating_point_type tol = std::numeric_limits<floating_point_type>::epsilon() * (boost::uint32_t) (5000);
bool result_is_ok = true;
for(typename boost::array<floating_point_type, 4U>::size_type i = 0U; i < control.size(); ++i)
{
const floating_point_type g = boost::math::tgamma(boost::math::constants::half<floating_point_type>() + ten_pow_n);
ten_pow_n *= (boost::uint32_t) (10);
const floating_point_type closeness = fabs(1 - (g / control[i]));
result_is_ok &= (closeness < tol);
}
return result_is_ok;
}
template<const unsigned BigFloatDigits>
bool test_tgamma_for_issue396()
{
typedef boost::multiprecision::number<boost::multiprecision::cpp_bin_float<BigFloatDigits>, boost::multiprecision::et_off> cpp_bin_float_type;
typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<BigFloatDigits>, boost::multiprecision::et_off> cpp_dec_float_type;
const bool bin_is_ok = test_tgamma_for_issue396_value_checker<cpp_bin_float_type>();
const bool dec_is_ok = test_tgamma_for_issue396_value_checker<cpp_dec_float_type>();
const bool result_is_ok = (bin_is_ok && dec_is_ok);
return result_is_ok;
}
bool test_tgamma_for_issue396_cpp_dec_float_020_through_050()
{
const bool b_020 = test_tgamma_for_issue396<20U>();
const bool b_030 = test_tgamma_for_issue396<30U>();
const bool b_040 = test_tgamma_for_issue396<40U>();
const bool b_049 = test_tgamma_for_issue396<49U>();
const bool b_050 = test_tgamma_for_issue396<50U>();
const bool result_is_ok = (b_020 && b_030 && b_040 && b_049 && b_050);
return result_is_ok;
}
BOOST_AUTO_TEST_CASE(test_tgamma_for_issue396_part1_tag)
{
const bool b_020_through_050_is_ok = test_tgamma_for_issue396_cpp_dec_float_020_through_050();
BOOST_CHECK(b_020_through_050_is_ok == true);
}

View File

@@ -0,0 +1,95 @@
///////////////////////////////////////////////////////////////////
// Copyright Christopher Kormanyos 2020.
// Copyright John Maddock 2020.
// 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)
//
#if 0
#define BOOST_TEST_MODULE test_tgamma_for_issue396
#include <boost/test/included/unit_test.hpp>
#else
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp> // Boost.Test
#endif
#include <boost/array.hpp>
#include <boost/math/constants/constants.hpp>
#include <boost/math/special_functions/gamma.hpp>
#include <boost/multiprecision/cpp_bin_float.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
// In issue 396, a bug regarding overflow was traced back to the tgamma function.
// This test file tests the fix in 433 and its corresponding original bug report code.
const char* issue396_control_string0 = "0.88622692545275801364908374167057259139877472806119356410690389492645564229551609068747532836927233270811341181214128533311807643286221130126254685480139353423101884932655256142496258651447541311446604768963398140008731950767573986025835009509261700929272348724745632015696088776295310820270966625045319920380686673873757671683399489468292591820439772558258086938002953369671589566640492742312409245102732742609780662578082373375752136938052805399806355360503018602224183618264830685404716174941583421211";
const char* issue396_control_string1 = "1.1332783889487855673345741655888924755602983082751597766087234145294833900560041537176305387276072906583502717008932373348895801731780765775979953796646009714415152490764416630481375706606053932396039541459764525989187023837695167161085523804417015113740063535865261183579508922972990386756543208549178543857406373798865630303794109491220205170302558277398183764099268751365861892723863412249690833216320407918186480305202146014474770321625907339955121137559264239090240758401696425720048012081453338360E6";
const char* issue396_control_string2 = "9.3209631040827166083491098091419104379064970381623611540161175194120765977611623552218076053836060223609993676387199220631835256331102029826429784793420637988460945604451237342972023988743201341318701614328454618664952897316247603329530308777063116667275003586843755354841307657702809317290363831151480295446074722690100652644579131609996151999119113967501099655433566352849645431012667388627160383486515144610582794470005796689975604764040892168183647321540427819244511610500074895473959438490375652158E156";
const char* issue396_control_string3 = "1.2723011956950554641822441803774445695066347098655278283939929838804808618389143636393314317333622154343715992535881414698586440455330620652019981627229614973177953241634213768203151670660953863412381880742653187501307209325406338924004280546485392703623101051957976224599412003938216329590158926122017907280168159527761842471509358725974702333390709735919152262756462872191402491961250987725812831155116532550035967994387094267848607390288008530653715254376729558412833771092612838971719786622446726968E2566";
template<class BigFloatType>
bool test_tgamma_for_issue396_value_checker()
{
typedef BigFloatType floating_point_type;
// Table[N[Gamma[(1/2) + (10^n)], 503], {n, 0, 3, 1}]
const boost::array<floating_point_type, 4U> control =
{{
floating_point_type(issue396_control_string0),
floating_point_type(issue396_control_string1),
floating_point_type(issue396_control_string2),
floating_point_type(issue396_control_string3)
}};
boost::uint32_t ten_pow_n = (boost::uint32_t) (1);
const floating_point_type tol = std::numeric_limits<floating_point_type>::epsilon() * (boost::uint32_t) (5000);
bool result_is_ok = true;
for(typename boost::array<floating_point_type, 4U>::size_type i = 0U; i < control.size(); ++i)
{
const floating_point_type g = boost::math::tgamma(boost::math::constants::half<floating_point_type>() + ten_pow_n);
ten_pow_n *= (boost::uint32_t) (10);
const floating_point_type closeness = fabs(1 - (g / control[i]));
result_is_ok &= (closeness < tol);
}
return result_is_ok;
}
template<const unsigned BigFloatDigits>
bool test_tgamma_for_issue396()
{
typedef boost::multiprecision::number<boost::multiprecision::cpp_bin_float<BigFloatDigits>, boost::multiprecision::et_off> cpp_bin_float_type;
typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<BigFloatDigits>, boost::multiprecision::et_off> cpp_dec_float_type;
const bool bin_is_ok = test_tgamma_for_issue396_value_checker<cpp_bin_float_type>();
const bool dec_is_ok = test_tgamma_for_issue396_value_checker<cpp_dec_float_type>();
const bool result_is_ok = (bin_is_ok && dec_is_ok);
return result_is_ok;
}
bool test_tgamma_for_issue396_cpp_dec_float_101_through_501()
{
const bool b_101 = test_tgamma_for_issue396<101U>();
const bool b_501 = test_tgamma_for_issue396<501U>();
const bool result_is_ok = (b_101 && b_501);
return result_is_ok;
}
BOOST_AUTO_TEST_CASE(test_tgamma_for_issue396_part2_tag)
{
const bool b_101_through_501_is_ok = test_tgamma_for_issue396_cpp_dec_float_101_through_501();
BOOST_CHECK(b_101_through_501_is_ok == true);
}