@@ -230,7 +230,10 @@ T ibeta_power_terms(T a,
230
230
T agh = static_cast <T>(a + Lanczos::g () - 0 .5f );
231
231
T bgh = static_cast <T>(b + Lanczos::g () - 0 .5f );
232
232
T cgh = static_cast <T>(c + Lanczos::g () - 0 .5f );
233
- result = Lanczos::lanczos_sum_expG_scaled (c) / (Lanczos::lanczos_sum_expG_scaled (a) * Lanczos::lanczos_sum_expG_scaled (b));
233
+ if ((a < tools::min_value<T>()) || (b < tools::min_value<T>()))
234
+ result = 0 ; // denominator overflows in this case
235
+ else
236
+ result = Lanczos::lanczos_sum_expG_scaled (c) / (Lanczos::lanczos_sum_expG_scaled (a) * Lanczos::lanczos_sum_expG_scaled (b));
234
237
result *= prefix;
235
238
// combine with the leftover terms from the Lanczos approximation:
236
239
result *= sqrt (bgh / boost::math::constants::e<T>());
@@ -389,14 +392,15 @@ T ibeta_power_terms(T a,
389
392
}
390
393
else
391
394
{
392
- T p1 = pow (b1, a / b);
395
+ // This protects against spurious overflow in a/b:
396
+ T p1 = (b1 < 1 ) && (b < 1 ) && (tools::max_value<T>() * b < a) ? static_cast <T>(0 ) : static_cast <T>(pow (b1, a / b));
393
397
T l3 = (p1 != 0 ) && (b2 != 0 ) ? (log (p1) + log (b2)) * b : tools::max_value<T>(); // arbitrary large value if the logs would fail!
394
398
if ((l3 < tools::log_max_value<T>())
395
399
&& (l3 > tools::log_min_value<T>()))
396
400
{
397
401
result *= pow (p1 * b2, b);
398
402
}
399
- else
403
+ else if (result != 0 ) // we can elude the calculation below if we're already going to be zero
400
404
{
401
405
l2 += l1 + log (result);
402
406
if (l2 >= tools::log_max_value<T>())
@@ -656,7 +660,10 @@ T ibeta_series(T a, T b, T x, T s0, const Lanczos&, bool normalised, T* p_deriva
656
660
T agh = static_cast <T>(a + Lanczos::g () - 0 .5f );
657
661
T bgh = static_cast <T>(b + Lanczos::g () - 0 .5f );
658
662
T cgh = static_cast <T>(c + Lanczos::g () - 0 .5f );
659
- result = Lanczos::lanczos_sum_expG_scaled (c) / (Lanczos::lanczos_sum_expG_scaled (a) * Lanczos::lanczos_sum_expG_scaled (b));
663
+ if ((a < tools::min_value<T>()) || (b < tools::min_value<T>()))
664
+ result = 0 ; // denorms cause overflow in the Lanzos series, result will be zero anyway
665
+ else
666
+ result = Lanczos::lanczos_sum_expG_scaled (c) / (Lanczos::lanczos_sum_expG_scaled (a) * Lanczos::lanczos_sum_expG_scaled (b));
660
667
661
668
if (!(boost::math::isfinite)(result))
662
669
result = 0 ;
@@ -689,10 +696,13 @@ T ibeta_series(T a, T b, T x, T s0, const Lanczos&, bool normalised, T* p_deriva
689
696
//
690
697
// Oh dear, we need logs, and this *will* cancel:
691
698
//
692
- result = log (result) + l1 + l2 + (log (agh) - 1 ) / 2 ;
693
- if (p_derivative)
694
- *p_derivative = exp (result + b * log (y));
695
- result = exp (result);
699
+ if (result != 0 ) // elude calculation when result will be zero.
700
+ {
701
+ result = log (result) + l1 + l2 + (log (agh) - 1 ) / 2 ;
702
+ if (p_derivative)
703
+ *p_derivative = exp (result + b * log (y));
704
+ result = exp (result);
705
+ }
696
706
}
697
707
}
698
708
else
0 commit comments