Skip to content

Commit 7431f81

Browse files
committed
Improve bernoulli and bessel coverage.
1 parent 9e18943 commit 7431f81

9 files changed

+88
-37
lines changed

include/boost/math/special_functions/acosh.hpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,7 @@ namespace boost
3838

3939
if((x < 1) || (boost::math::isnan)(x))
4040
{
41-
return policies::raise_domain_error<T>(
42-
"boost::math::acosh<%1%>(%1%)",
43-
"acosh requires x >= 1, but got x = %1%.", x, pol);
41+
return policies::raise_domain_error<T>("boost::math::acosh<%1%>(%1%)", "acosh requires x >= 1, but got x = %1%.", x, pol);
4442
}
4543
else if ((x - 1) >= tools::root_epsilon<T>())
4644
{

include/boost/math/special_functions/asinh.hpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,7 @@ namespace boost
3838

3939
if((boost::math::isnan)(x))
4040
{
41-
return policies::raise_domain_error<T>(
42-
"boost::math::asinh<%1%>(%1%)",
43-
"asinh requires a finite argument, but got x = %1%.", x, pol);
41+
return policies::raise_domain_error<T>("boost::math::asinh<%1%>(%1%)", "asinh requires a finite argument, but got x = %1%.", x, pol);
4442
}
4543
if (x >= tools::forth_root_epsilon<T>())
4644
{

include/boost/math/special_functions/bessel.hpp

+20-28
Original file line numberDiff line numberDiff line change
@@ -99,20 +99,23 @@ T cyl_bessel_j_imp(T v, T x, const bessel_no_int_tag& t, const Policy& pol)
9999
if(x < 0)
100100
{
101101
// better have integer v:
102-
if(floor(v) == v)
102+
if (floor(v) == v)
103103
{
104+
// LCOV_EXCL_START
105+
// This branch is hit by multiprecision types only, and is
106+
// tested by our real_concept tests, but thee are excluded from coverage
107+
// due to time constraints.
104108
T r = cyl_bessel_j_imp(v, T(-x), t, pol);
105-
if(iround(v, pol) & 1)
109+
if (iround(v, pol) & 1)
106110
r = -r;
107111
return r;
112+
// LCOV_EXCL_STOP
108113
}
109114
else
110-
return policies::raise_domain_error<T>(
111-
function,
112-
"Got x = %1%, but we need x >= 0", x, pol);
115+
return policies::raise_domain_error<T>(function, "Got x = %1%, but we need x >= 0", x, pol);
113116
}
114117

115-
T result_J, y;
118+
T result_J, y; // LCOV_EXCL_LINE
116119
bessel_jy(v, x, &result_J, &y, need_j, pol);
117120
return result_J;
118121
}
@@ -143,9 +146,7 @@ inline T sph_bessel_j_imp(unsigned n, T x, const Policy& pol)
143146
{
144147
BOOST_MATH_STD_USING // ADL of std names
145148
if(x < 0)
146-
return policies::raise_domain_error<T>(
147-
"boost::math::sph_bessel_j<%1%>(%1%,%1%)",
148-
"Got x = %1%, but function requires x > 0.", x, pol);
149+
return policies::raise_domain_error<T>("boost::math::sph_bessel_j<%1%>(%1%,%1%)", "Got x = %1%, but function requires x > 0.", x, pol);
149150
//
150151
// Special case, n == 0 resolves down to the sinus cardinal of x:
151152
//
@@ -190,9 +191,7 @@ T cyl_bessel_i_imp(T v, T x, const Policy& pol)
190191
return r;
191192
}
192193
else
193-
return policies::raise_domain_error<T>(
194-
"boost::math::cyl_bessel_i<%1%>(%1%,%1%)",
195-
"Got x = %1%, but we need x >= 0", x, pol);
194+
return policies::raise_domain_error<T>("boost::math::cyl_bessel_i<%1%>(%1%,%1%)", "Got x = %1%, but we need x >= 0", x, pol);
196195
}
197196
if(x == 0)
198197
{
@@ -221,7 +220,7 @@ T cyl_bessel_i_imp(T v, T x, const Policy& pol)
221220
}
222221
if((v > 0) && (x / v < 0.25))
223222
return bessel_i_small_z_series(v, x, pol);
224-
T result_I, result_K;
223+
T result_I, result_K; // LCOV_EXCL_LINE
225224
bessel_ik(v, x, &result_I, &result_K, need_i, pol);
226225
return result_I;
227226
}
@@ -240,11 +239,9 @@ inline T cyl_bessel_k_imp(T v, T x, const bessel_no_int_tag& /* t */, const Poli
240239
if(x == 0)
241240
{
242241
return (v == 0) ? policies::raise_overflow_error<T>(function, nullptr, pol)
243-
: policies::raise_domain_error<T>(
244-
function,
245-
"Got x = %1%, but we need x > 0", x, pol);
242+
: policies::raise_domain_error<T>(function, "Got x = %1%, but we need x > 0", x, pol);
246243
}
247-
T result_I, result_K;
244+
T result_I, result_K; // LCOV_EXCL_LINE
248245
bessel_ik(v, x, &result_I, &result_K, need_k, pol);
249246
return result_K;
250247
}
@@ -278,19 +275,17 @@ inline T cyl_neumann_imp(T v, T x, const bessel_no_int_tag&, const Policy& pol)
278275
{
279276
return (v == 0) && (x == 0) ?
280277
policies::raise_overflow_error<T>(function, nullptr, pol)
281-
: policies::raise_domain_error<T>(
282-
function,
283-
"Got x = %1%, but result is complex for x <= 0", x, pol);
278+
: policies::raise_domain_error<T>(function, "Got x = %1%, but result is complex for x <= 0", x, pol);
284279
}
285-
T result_J, y;
280+
T result_J, y; // LCOV_EXCL_LINE
286281
bessel_jy(v, x, &result_J, &y, need_y, pol);
287282
//
288283
// Post evaluation check for internal overflow during evaluation,
289284
// can occur when x is small and v is large, in which case the result
290285
// is -INF:
291286
//
292287
if(!(boost::math::isfinite)(y))
293-
return -policies::raise_overflow_error<T>(function, nullptr, pol);
288+
return -policies::raise_overflow_error<T>(function, nullptr, pol); // LCOV_EXCL_LINE defensive programming? Might be dead code now...
294289
return y;
295290
}
296291

@@ -329,17 +324,15 @@ inline T sph_neumann_imp(unsigned v, T x, const Policy& pol)
329324
// evaluate the function's definition directly:
330325
//
331326
if(x < 0)
332-
return policies::raise_domain_error<T>(
333-
function,
334-
"Got x = %1%, but function requires x > 0.", x, pol);
327+
return policies::raise_domain_error<T>(function, "Got x = %1%, but function requires x > 0.", x, pol);
335328

336329
if(x < 2 * tools::min_value<T>())
337330
return -policies::raise_overflow_error<T>(function, nullptr, pol);
338331

339332
T result = cyl_neumann_imp(T(T(v)+0.5f), x, bessel_no_int_tag(), pol);
340333
T tx = sqrt(constants::pi<T>() / (2 * x));
341334

342-
if((tx > 1) && (tools::max_value<T>() / tx < result))
335+
if((tx > 1) && (tools::max_value<T>() / tx < fabs(result)))
343336
return -policies::raise_overflow_error<T>(function, nullptr, pol);
344337

345338
return result * tx;
@@ -417,8 +410,7 @@ inline T cyl_bessel_j_zero_imp(T v, int m, const Policy& pol)
417410

418411
if(number_of_iterations >= policies::get_max_root_iterations<Policy>())
419412
{
420-
return policies::raise_evaluation_error<T>(function, "Unable to locate root in a reasonable time:"
421-
" Current best guess is %1%", jvm, Policy());
413+
return policies::raise_evaluation_error<T>(function, "Unable to locate root in a reasonable time: Current best guess is %1%", jvm, Policy()); // LCOV_EXCL_LINE
422414
}
423415

424416
return jvm;

test/test_bernoulli_constants.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,11 @@ void test(const char* name)
199199
BOOST_MATH_CHECK_THROW(boost::math::bernoulli_b2n<T>(overflow_index, boost::math::policies::make_policy(boost::math::policies::overflow_error<boost::math::policies::throw_on_error>())), std::overflow_error);
200200
BOOST_MATH_CHECK_THROW(boost::math::tangent_t2n<T>(overflow_index, boost::math::policies::make_policy(boost::math::policies::overflow_error<boost::math::policies::throw_on_error>())), std::overflow_error);
201201
#endif
202+
BOOST_MATH_CHECK_THROW(boost::math::bernoulli_b2n<T>(-1), std::domain_error);
203+
BOOST_MATH_CHECK_THROW(boost::math::tangent_t2n<T>(-1), std::domain_error);
204+
std::vector<T> v;
205+
BOOST_MATH_CHECK_THROW(boost::math::bernoulli_b2n<T>(-1, 5, std::back_inserter(v)), std::domain_error);
206+
BOOST_MATH_CHECK_THROW(boost::math::tangent_t2n<T>(-1, 5, std::back_inserter(v)), std::domain_error);
202207
}
203208

204209
void test_real_concept_extra()

test/test_bessel_airy_zeros.cpp

+18-3
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,7 @@ void test_bessel_zeros(RealType)
116116
using boost::math::isnan;
117117

118118
BOOST_MATH_CHECK_THROW(cyl_bessel_j_zero(static_cast<RealType>(0), 0), std::domain_error);
119-
// BOOST_MATH_CHECK_THROW(cyl_bessel_j_zero(static_cast<RealType>(-1), 2), std::domain_error);
120-
// From 83051 negative orders are supported.
119+
BOOST_MATH_CHECK_THROW(cyl_bessel_j_zero(static_cast<RealType>(-1.5), 0), std::domain_error);
121120

122121
// Abuse with infinity and max.
123122
if (std::numeric_limits<RealType>::has_infinity)
@@ -493,7 +492,23 @@ n |
493492
BOOST_CHECK_CLOSE_FRACTION(cyl_neumann_zero(static_cast<RealType>(-3), 4), static_cast<RealType>(14.623077742393873174076722507725200649352970569915L), tolerance);
494493
BOOST_CHECK_CLOSE_FRACTION(cyl_neumann_zero(static_cast<RealType>(-3), 5), static_cast<RealType>(17.818455232945520262553239064736739443380352162752L), tolerance);
495494

496-
{ // Repeat rest using multiple zeros version.
495+
/*
496+
Table[N[BesselYZero[-5/2, n], 50], {n, 1, 5, 1}]
497+
n | y_(-2.5000000000000000000000000000000000000000000000000, n)
498+
1 | 5.7634591968945497914064666539527350764090876841674
499+
2 | 9.0950113304763551563376983279896952524009293663831
500+
3 | 12.322940970566582051969567925329726061189423834915
501+
4 | 5.7634591968945497914064666539527350764090876841674
502+
5 | 9.0950113304763551563376983279896952524009293663831
503+
*/
504+
505+
BOOST_CHECK_CLOSE_FRACTION(cyl_neumann_zero(static_cast<RealType>(-2.5), 1), static_cast<RealType>(5.7634591968945497914064666539527350764090876841674L), tolerance);
506+
BOOST_CHECK_CLOSE_FRACTION(cyl_neumann_zero(static_cast<RealType>(-2.5), 2), static_cast<RealType>(9.0950113304763551563376983279896952524009293663831L), tolerance);
507+
BOOST_CHECK_CLOSE_FRACTION(cyl_neumann_zero(static_cast<RealType>(-2.5), 3), static_cast<RealType>(12.322940970566582051969567925329726061189423834915L), tolerance);
508+
//BOOST_CHECK_CLOSE_FRACTION(cyl_neumann_zero(static_cast<RealType>(-2.5), 4), static_cast<RealType>(5.7634591968945497914064666539527350764090876841674L), tolerance);
509+
//BOOST_CHECK_CLOSE_FRACTION(cyl_neumann_zero(static_cast<RealType>(-2.5), 5), static_cast<RealType>(9.0950113304763551563376983279896952524009293663831L), tolerance);
510+
511+
{ // Repeat rest using multiple zeros version.
497512
std::vector<RealType> zeros;
498513
cyl_neumann_zero(static_cast<RealType>(0.0), 1, 3, std::back_inserter(zeros) );
499514
BOOST_CHECK_CLOSE_FRACTION(zeros[0], static_cast<RealType>(0.89357696627916752158488710205833824122514686193001L), tolerance);

test/test_bessel_i.hpp

+10
Original file line numberDiff line numberDiff line change
@@ -176,5 +176,15 @@ void test_bessel(T, const char* name)
176176

177177
if(0 != static_cast<T>(ldexp(0.5, -700)))
178178
do_test_cyl_bessel_i<T>(iv_large_data, name, "Bessel Iv: Mathworld Data (large values)");
179+
180+
//
181+
// Special cases for full coverage:
182+
//
183+
BOOST_CHECK_THROW(boost::math::cyl_bessel_i(T(-2.5), T(-2.5)), std::domain_error);
184+
T tolerance = boost::math::tools::epsilon<T>() * 100;
185+
if ((boost::math::tools::digits<T>() <= std::numeric_limits<double>::digits) && (std::numeric_limits<T>::max_exponent > 1000))
186+
{
187+
BOOST_CHECK_CLOSE_FRACTION(boost::math::cyl_bessel_i(T(0.5), T(710)), static_cast<T>(3.3447452278080108123142599104927325061327359278058601201179e306L), tolerance);
188+
}
179189
}
180190

test/test_bessel_j.hpp

+6
Original file line numberDiff line numberDiff line change
@@ -270,5 +270,11 @@ void test_bessel(T, const char* name)
270270
BOOST_MATH_CHECK_THROW(boost::math::cyl_bessel_j(T(-2.5), T(0)), std::domain_error);
271271
BOOST_MATH_CHECK_THROW(boost::math::cyl_bessel_j(T(-2.5), T(-2)), std::domain_error);
272272
BOOST_MATH_CHECK_THROW(boost::math::cyl_bessel_j(T(2.5), T(-2)), std::domain_error);
273+
274+
//
275+
// special cases for code coverage:
276+
//
277+
BOOST_CHECK_EQUAL(boost::math::sph_bessel(200, T(0.5)), T(3.070403008048099934928128420285169174541102108657574230431e-497L));
278+
BOOST_MATH_CHECK_THROW(boost::math::sph_bessel(2, T(-2.0)), std::domain_error);
273279
}
274280

test/test_bessel_k.hpp

+10
Original file line numberDiff line numberDiff line change
@@ -171,5 +171,15 @@ void test_bessel(T, const char* name)
171171
do_test_cyl_bessel_k<T>(bessel_k_int_data, name, "Bessel Kn: Random Data");
172172
#include "bessel_k_data.ipp"
173173
do_test_cyl_bessel_k<T>(bessel_k_data, name, "Bessel Kv: Random Data");
174+
175+
//
176+
// Extra test coverage:
177+
//
178+
BOOST_CHECK_THROW(boost::math::cyl_bessel_k(T(2), T(-1)), std::domain_error);
179+
if (std::numeric_limits<T>::has_infinity)
180+
{
181+
BOOST_CHECK_EQUAL(boost::math::cyl_bessel_k(T(0), T(0)), std::numeric_limits<T>::infinity());
182+
}
183+
BOOST_CHECK_THROW(boost::math::cyl_bessel_k(T(1.25), T(0)), std::domain_error);
174184
}
175185

test/test_bessel_y.hpp

+17
Original file line numberDiff line numberDiff line change
@@ -214,5 +214,22 @@ void test_bessel(T, const char* name)
214214

215215
#include "sph_neumann_data.ipp"
216216
do_test_sph_neumann_y<T>(sph_neumann_data, name, "y: Random Data");
217+
218+
//
219+
// Additional test coverage:
220+
//
221+
if (std::numeric_limits<T>::has_infinity)
222+
{
223+
BOOST_CHECK_EQUAL(boost::math::cyl_neumann(T(0), T(0)), -std::numeric_limits<T>::infinity());
224+
BOOST_CHECK_EQUAL(boost::math::sph_neumann(2, (std::numeric_limits<T>::min)() * 1.5f), -std::numeric_limits<T>::infinity());
225+
T small = 5.69289e-1645L;
226+
if (small != 0)
227+
{
228+
BOOST_CHECK_EQUAL(boost::math::sph_neumann(2, small), -std::numeric_limits<T>::infinity());
229+
}
230+
}
231+
BOOST_CHECK_THROW(boost::math::cyl_neumann(T(0), T(-1)), std::domain_error);
232+
BOOST_CHECK_THROW(boost::math::cyl_neumann(T(2), T(0)), std::domain_error);
233+
BOOST_CHECK_THROW(boost::math::sph_neumann(2, T(-2)), std::domain_error);
217234
}
218235

0 commit comments

Comments
 (0)