Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions include/boost/math/distributions/non_central_t.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,26 @@ namespace boost
return policies::raise_evaluation_error<RealType>(function, "Can't find degrees of freedom when the abscissa value is very close to zero as all degrees of freedom generate the same CDF at x=0: try again further out in the tails!!",
RealType(std::numeric_limits<RealType>::quiet_NaN()), Policy()); // LCOV_EXCL_LINE
}

// The limiting CDF values are
//
// v -> 0: Phi(-delta)
// v -> inf: Phi(x - delta)
//
// Outside the interval between these limits, a monotone CDF(v)
// has no inverse. In a non-monotone case there may instead be
// multiple inverses, so we cannot select a unique degree of freedom.
normal_distribution<RealType, Policy> normal;
RealType p0 = cdf(normal, -delta);
RealType pinf = cdf(normal, x - delta);
RealType lower = p0 < pinf ? p0 : pinf;
RealType upper = p0 < pinf ? pinf : p0;
if((p < lower) || (p > upper))
{
return policies::raise_evaluation_error<RealType>(function,
"Probability %1% lies outside the interval between the limiting CDF values; the inverse is absent or non-unique", p, Policy());
}

t_degrees_of_freedom_finder<RealType, Policy> f(delta, x, p < q ? p : q, p < q ? false : true);
tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
Expand Down
8 changes: 8 additions & 0 deletions test/test_nc_t.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,14 @@ void test_spots(RealType)
BOOST_CHECK_CLOSE_FRACTION(cdf(d, -1), static_cast<RealType>(1.61471461239552e-127), 1e-3);
}

// https://github.com/boostorg/math/issues/1410
// p=0.99 is below both limiting CDF values:
// Phi(2.5) and Phi(3.75). Previously this could return a tiny,
// meaningless degree of freedom instead of reporting that the inverse
// cannot be selected uniquely.
BOOST_MATH_CHECK_THROW(distro1::find_degrees_of_freedom(static_cast<RealType>(-2.5), static_cast<RealType>(1.25), static_cast<RealType>(0.99)), boost::math::evaluation_error);
BOOST_MATH_CHECK_THROW(distro1::find_degrees_of_freedom(boost::math::complement(static_cast<RealType>(-2.5), static_cast<RealType>(1.25), static_cast<RealType>(0.01))), boost::math::evaluation_error);

} // template <class RealType>void test_spots(RealType)

template <class T>
Expand Down
Loading