mirror of
https://github.com/boostorg/math.git
synced 2026-01-19 04:22:09 +00:00
Merge branch 'mydevelop' of https://github.com/cohomology/math into integrate_1251
This commit is contained in:
@@ -934,7 +934,7 @@ BOOST_MATH_GPU_ENABLED T full_igamma_prefix(T a, T z, const Policy& pol)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
|
||||
if (z > tools::max_value<T>())
|
||||
if (z > tools::max_value<T>() || (a > 0 && z == 0))
|
||||
return 0;
|
||||
|
||||
T alz = a * log(z);
|
||||
@@ -992,7 +992,7 @@ template <class T, class Policy, class Lanczos>
|
||||
BOOST_MATH_GPU_ENABLED T regularised_gamma_prefix(T a, T z, const Policy& pol, const Lanczos& l)
|
||||
{
|
||||
BOOST_MATH_STD_USING
|
||||
if (z >= tools::max_value<T>())
|
||||
if (z >= tools::max_value<T>() || (a > 0 && z == 0))
|
||||
return 0;
|
||||
T agh = a + static_cast<T>(Lanczos::g()) - T(0.5);
|
||||
T prefix{};
|
||||
@@ -1321,7 +1321,11 @@ BOOST_MATH_GPU_ENABLED T gamma_incomplete_imp_final(T a, T x, bool normalised, b
|
||||
|
||||
int eval_method;
|
||||
|
||||
if(is_int && (x > 0.6))
|
||||
if (x == 0)
|
||||
{
|
||||
eval_method = 2;
|
||||
}
|
||||
else if(is_int && (x > 0.6))
|
||||
{
|
||||
// calculate Q via finite sum:
|
||||
invert = !invert;
|
||||
@@ -1501,14 +1505,14 @@ BOOST_MATH_GPU_ENABLED T gamma_incomplete_imp_final(T a, T x, bool normalised, b
|
||||
#ifdef BOOST_MATH_HAS_NVRTC
|
||||
if (boost::math::is_same_v<T, float>)
|
||||
{
|
||||
init_value = (normalised ? 1 : ::tgammaf(a));
|
||||
init_value = (normalised ? T(1) : ::tgammaf(a));
|
||||
}
|
||||
else
|
||||
{
|
||||
init_value = (normalised ? 1 : ::tgamma(a));
|
||||
init_value = (normalised ? T(1) : ::tgamma(a));
|
||||
}
|
||||
#else
|
||||
init_value = (normalised ? 1 : boost::math::tgamma(a, pol));
|
||||
init_value = (normalised ? T(1) : boost::math::tgamma(a, pol));
|
||||
#endif
|
||||
|
||||
if(normalised || (result >= 1) || (tools::max_value<T>() * result > init_value))
|
||||
@@ -1640,32 +1644,26 @@ BOOST_MATH_GPU_ENABLED T gamma_incomplete_imp_final(T a, T x, bool normalised, b
|
||||
T gam;
|
||||
if (boost::math::is_same_v<T, float>)
|
||||
{
|
||||
gam = normalised ? 1 : ::tgammaf(a);
|
||||
gam = normalised ? T(1) : ::tgammaf(a);
|
||||
}
|
||||
else
|
||||
{
|
||||
gam = normalised ? 1 : ::tgamma(a);
|
||||
gam = normalised ? T(1) : ::tgamma(a);
|
||||
}
|
||||
#else
|
||||
T gam = normalised ? 1 : boost::math::tgamma(a, pol);
|
||||
T gam = normalised ? T(1) : boost::math::tgamma(a, pol);
|
||||
#endif
|
||||
result = gam - result;
|
||||
}
|
||||
if(p_derivative)
|
||||
{
|
||||
/*
|
||||
* We can never reach this:
|
||||
if((x < 1) && (tools::max_value<T>() * x < *p_derivative))
|
||||
if((x == 0) || ((x < 1) && (tools::max_value<T>() * x < *p_derivative)))
|
||||
{
|
||||
// overflow, just return an arbitrarily large value:
|
||||
*p_derivative = tools::max_value<T>() / 2;
|
||||
}
|
||||
*/
|
||||
BOOST_MATH_ASSERT((x >= 1) || (tools::max_value<T>() * x >= *p_derivative));
|
||||
//
|
||||
// Need to convert prefix term to derivative:
|
||||
//
|
||||
*p_derivative /= x;
|
||||
else
|
||||
*p_derivative /= x;
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -1687,7 +1685,7 @@ BOOST_MATH_GPU_ENABLED T gamma_incomplete_imp(T a, T x, bool normalised, bool in
|
||||
|
||||
T result = 0; // Just to avoid warning C4701: potentially uninitialized local variable 'result' used
|
||||
|
||||
if(a >= max_factorial<T>::value && !normalised)
|
||||
if(x > 0 && a >= max_factorial<T>::value && !normalised)
|
||||
{
|
||||
//
|
||||
// When we're computing the non-normalized incomplete gamma
|
||||
@@ -2143,8 +2141,8 @@ BOOST_MATH_GPU_ENABLED T gamma_p_derivative_imp(T a, T x, const Policy& pol)
|
||||
//
|
||||
if(x == 0)
|
||||
{
|
||||
return (a > 1) ? 0 :
|
||||
(a == 1) ? 1 : policies::raise_overflow_error<T>("boost::math::gamma_p_derivative<%1%>(%1%, %1%)", nullptr, pol);
|
||||
return (a > 1) ? T(0) :
|
||||
(a == 1) ? T(1) : policies::raise_overflow_error<T>("boost::math::gamma_p_derivative<%1%>(%1%, %1%)", nullptr, pol);
|
||||
}
|
||||
//
|
||||
// Normal case:
|
||||
|
||||
@@ -196,6 +196,7 @@ test-suite special_fun :
|
||||
[ run git_issue_1139.cpp ]
|
||||
[ run git_issue_1175.cpp ]
|
||||
[ run git_issue_1194.cpp ]
|
||||
[ run git_issue_1249.cpp /boost/test//boost_unit_test_framework ]
|
||||
[ run git_issue_1255.cpp ]
|
||||
[ run git_issue_1247.cpp ]
|
||||
[ run special_functions_test.cpp /boost/test//boost_unit_test_framework ]
|
||||
|
||||
145
test/git_issue_1249.cpp
Normal file
145
test/git_issue_1249.cpp
Normal file
@@ -0,0 +1,145 @@
|
||||
// (C) Copyright Kilian Kilger 2025.
|
||||
// Use, modification and distribution are subject to 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)
|
||||
|
||||
#define BOOST_TEST_MAIN
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/test/tools/floating_point_comparison.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/test/results_collector.hpp>
|
||||
#include <boost/math/special_functions/gamma.hpp>
|
||||
#include <boost/multiprecision/cpp_bin_float.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace boost::math;
|
||||
using namespace boost::math::policies;
|
||||
using namespace boost::multiprecision;
|
||||
|
||||
typedef policy<
|
||||
policies::domain_error<errno_on_error>,
|
||||
policies::pole_error<errno_on_error>,
|
||||
policies::overflow_error<errno_on_error>,
|
||||
policies::evaluation_error<errno_on_error>
|
||||
> c_policy;
|
||||
|
||||
template<typename T>
|
||||
struct test_lower
|
||||
{
|
||||
T operator()(T a, T x) const
|
||||
{
|
||||
return tgamma_lower(a, x, c_policy());
|
||||
}
|
||||
|
||||
T expected(T a) const
|
||||
{
|
||||
return T(0.0);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct test_upper
|
||||
{
|
||||
T operator()(T a, T x) const
|
||||
{
|
||||
return tgamma(a, x, c_policy());
|
||||
}
|
||||
T expected(T a) const
|
||||
{
|
||||
return tgamma(a, c_policy());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct test_gamma_p
|
||||
{
|
||||
T operator()(T a, T x) const
|
||||
{
|
||||
return gamma_p(a, x, c_policy());
|
||||
}
|
||||
T expected(T) const
|
||||
{
|
||||
return T(0.0);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct test_gamma_q
|
||||
{
|
||||
T operator()(T a, T x) const
|
||||
{
|
||||
return gamma_q(a, x, c_policy());
|
||||
}
|
||||
T expected(T) const
|
||||
{
|
||||
return T(1.0);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, template<typename> class Fun>
|
||||
void test_impl(T a)
|
||||
{
|
||||
Fun<T> fn;
|
||||
errno = 0;
|
||||
T x = T(0.0);
|
||||
T result = fn(a, x);
|
||||
int saveErrno = errno;
|
||||
|
||||
errno = 0;
|
||||
|
||||
T expected = fn.expected(a);
|
||||
|
||||
BOOST_CHECK(errno == saveErrno);
|
||||
BOOST_CHECK_EQUAL(result, expected);
|
||||
}
|
||||
|
||||
template<template<typename> class Fun, typename T>
|
||||
void test_type_dispatch(T val)
|
||||
{
|
||||
if (val <= (std::numeric_limits<float>::max)())
|
||||
test_impl<float, Fun>(static_cast<float>(val));
|
||||
if (val <= (std::numeric_limits<double>::max)())
|
||||
test_impl<double, Fun>(static_cast<double>(val));
|
||||
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
|
||||
test_impl<long double, Fun>(static_cast<long double>(val));
|
||||
#endif
|
||||
test_impl<cpp_bin_float_50, Fun>(static_cast<cpp_bin_float_50>(val));
|
||||
}
|
||||
|
||||
template<template<typename> class Fun>
|
||||
void test_impl()
|
||||
{
|
||||
test_type_dispatch<Fun, double>(1.0);
|
||||
test_type_dispatch<Fun, double>(0.1);
|
||||
test_type_dispatch<Fun, double>(0.5);
|
||||
test_type_dispatch<Fun, double>(0.6);
|
||||
test_type_dispatch<Fun, double>(1.3);
|
||||
test_type_dispatch<Fun, double>(1.5);
|
||||
test_type_dispatch<Fun, double>(2);
|
||||
test_type_dispatch<Fun, double>(100);
|
||||
test_type_dispatch<Fun, double>((std::numeric_limits<float>::max)());
|
||||
test_type_dispatch<Fun, double>((std::numeric_limits<double>::max)());
|
||||
#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
|
||||
test_type_dispatch<Fun, long double>((std::numeric_limits<long double>::max)());
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_derivative()
|
||||
{
|
||||
using namespace boost::math::detail;
|
||||
double derivative = 0;
|
||||
double result = gamma_incomplete_imp(1.0, 0.0, true, false, c_policy(), &derivative);
|
||||
BOOST_CHECK(errno == 0);
|
||||
BOOST_CHECK_EQUAL(derivative, tools::max_value<double>() / 2);
|
||||
BOOST_CHECK_EQUAL(result, 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_main )
|
||||
{
|
||||
test_impl<test_lower>();
|
||||
test_impl<test_upper>();
|
||||
test_impl<test_gamma_p>();
|
||||
test_impl<test_gamma_q>();
|
||||
test_derivative();
|
||||
}
|
||||
Reference in New Issue
Block a user