betainc() function documentation and edge cases
Summary
-
The
betainc()
function provided inunsupported/Eigen/src/SpecialFunctions.h
is documented online and in code as the incomplete beta function, but appears to be the regularized (or alternatively normalized) incomplete beta function. -
Given this, there are some additional edge cases of its arguments that it can (ought?) to handle. Currently it returns
nan
for these.
Environment
Eigen 3.4.0, otherwise not specific to a certain environment.
Minimal Example
Comparing the Eigen implementation of this function to the Boost implementation:
#include <boost/math/special_functions.hpp>
#include <unsupported/Eigen/SpecialFunctions>
#include <iostream>
int main() {
/* Eigen betainc() matches Boost ibeta(), i.e. it is the *regularized* or
* *normalized* incomplete beta function, not just the incomplete beta
* function as documented (which is Boost beta()) */
std::cout << "Eigen betainc(): " << Eigen::numext::betainc(4.0, 5.0, 0.6) << std::endl;
std::cout << "Boost ibeta(): " << boost::math::ibeta(4.0, 5.0, 0.6) << std::endl;
std::cout << "Boost beta(): " << boost::math::beta(4.0, 5.0, 0.6) << std::endl;
std::cout << std::endl;
/* given that it is the regularized function, it could be defined for the
* edge cases where the first argument is zero... */
std::cout << "Eigen betainc(): " << Eigen::numext::betainc(0.0, 5.0, 0.6) << std::endl;
std::cout << "Boost ibeta(): " << boost::math::ibeta(0.0, 5.0, 0.6) << std::endl;
std::cout << "Boost beta(): " << "undefined" /*boost::math::beta(0.0, 5.0, 0.6)*/ << std::endl;
std::cout << std::endl;
/* ...or the second argument is zero */
std::cout << "Eigen betainc(): " << Eigen::numext::betainc(4.0, 0.0, 0.6) << std::endl;
std::cout << "Boost ibeta(): " << boost::math::ibeta(4.0, 0.0, 0.6) << std::endl;
std::cout << "Boost beta(): " << "undefined" /*boost::math::beta(4.0, 0.0, 0.6)*/ << std::endl;
return 0;
}
output:
Eigen betainc(): 0.82633
Boost ibeta(): 0.82633
Boost beta(): 0.00295118
Eigen betainc(): nan
Boost ibeta(): 1
Boost beta(): undefined
Eigen betainc(): nan
Boost ibeta(): 0
Boost beta(): undefined
i.e. Eigen's betainc()
matches Boost's ibeta()
, which is the regularized incomplete beta function, not just the incomplete beta function as documented in Eigen. Furthermore, there are some edge cases that are not handled in Eigen's implementation.
Steps to reproduce
The above code example demonstrates.
What is the current bug behavior?
Passing zero as the first or second argument to betainc()
produces nan
.
What is the expected correct behavior?
It could (should?) produce 1 and 0, respectively.
Anything else that might help
I'm reporting early before having the chance to develop a patch, but this should be straightforward: update the documentation, catch the edge cases with a conditional.