Add erf and erfc to jet.h, including tests in jet_test.cc erf is necessary for evaluating Gaussian functions. erfc was added because it is so similar to erf. Change-Id: I5e470dbe013cc938fabb87cde3b0ebf26a90fff4
diff --git a/include/ceres/jet.h b/include/ceres/jet.h index 7aafaa0..c551d51 100644 --- a/include/ceres/jet.h +++ b/include/ceres/jet.h
@@ -388,6 +388,8 @@ using std::ceil; using std::cos; using std::cosh; +using std::erf; +using std::erfc; using std::exp; using std::exp2; using std::floor; @@ -573,6 +575,21 @@ return y < x ? y : x; } +// erf is defined as an integral that cannot be expressed analyticaly +// however, the derivative is trivial to compute +// erf(x + h) = erf(x) + h * 2*exp(-x^2)/sqrt(pi) +template <typename T, int N> +inline Jet<T, N> erf(const Jet<T, N>& x) { + return Jet<T, N>(erf(x.a), x.v * M_2_SQRTPI * exp(-x.a*x.a)); +} + +// erfc(x) = 1-erf(x) +// erfc(x + h) = erfc(x) + h * (-2*exp(-x^2)/sqrt(pi)) +template <typename T, int N> +inline Jet<T, N> erfc(const Jet<T, N>& x) { + return Jet<T, N>(erfc(x.a), -x.v * M_2_SQRTPI * exp(-x.a*x.a)); +} + // Bessel functions of the first kind with integer order equal to 0, 1, n. // // Microsoft has deprecated the j[0,1,n]() POSIX Bessel functions in favour of
diff --git a/internal/ceres/jet_test.cc b/internal/ceres/jet_test.cc index a6cad62..f1e9586 100644 --- a/internal/ceres/jet_test.cc +++ b/internal/ceres/jet_test.cc
@@ -571,6 +571,28 @@ EXPECT_EQ(expected, b); } + { // Check that erf works. + J a = MakeJet(10.123, -2.7, 1e-3); + J b = erf(a); + J expected = MakeJet(erf(a.a), 0.0, 0.0); + EXPECT_EQ(expected, b); + } + NumericalTest("erf", erf<double, 2>, -1.0); + NumericalTest("erf", erf<double, 2>, 1e-5); + NumericalTest("erf", erf<double, 2>, 0.5); + NumericalTest("erf", erf<double, 2>, 100.0); + + { // Check that erfc works. + J a = MakeJet(10.123, -2.7, 1e-3); + J b = erfc(a); + J expected = MakeJet(erfc(a.a), 0.0, 0.0); + EXPECT_EQ(expected, b); + } + NumericalTest("erfc", erfc<double, 2>, -1.0); + NumericalTest("erfc", erfc<double, 2>, 1e-5); + NumericalTest("erfc", erfc<double, 2>, 0.5); + NumericalTest("erfc", erfc<double, 2>, 100.0); + { // Check that cbrt(x * x * x) == x. J z = x * x * x; J w = cbrt(z);