|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r49828 - in trunk/boost/math/special_functions: . detail
From: john_at_[hidden]
Date: 2008-11-18 14:47:51
Author: johnmaddock
Date: 2008-11-18 14:47:50 EST (Tue, 18 Nov 2008)
New Revision: 49828
URL: http://svn.boost.org/trac/boost/changeset/49828
Log:
Fixed bug in elliptic integral periodic-reduction code.
Added some more debugging/tracing aids.
Text files modified:
trunk/boost/math/special_functions/bessel.hpp | 23 +++++++++++-
trunk/boost/math/special_functions/beta.hpp | 74 ++++++++++++++++++++++++++++++++++++++++
trunk/boost/math/special_functions/detail/igamma_inverse.hpp | 31 ++++++++++++++++
trunk/boost/math/special_functions/ellint_1.hpp | 2
trunk/boost/math/special_functions/ellint_2.hpp | 2
trunk/boost/math/special_functions/ellint_3.hpp | 2
6 files changed, 129 insertions(+), 5 deletions(-)
Modified: trunk/boost/math/special_functions/bessel.hpp
==============================================================================
--- trunk/boost/math/special_functions/bessel.hpp (original)
+++ trunk/boost/math/special_functions/bessel.hpp 2008-11-18 14:47:50 EST (Tue, 18 Nov 2008)
@@ -307,6 +307,10 @@
inline T cyl_neumann_imp(T v, T x, const bessel_no_int_tag&, const Policy& pol)
{
static const char* function = "boost::math::cyl_neumann<%1%>(%1%,%1%)";
+
+ BOOST_MATH_INSTRUMENT_VARIABLE(v);
+ BOOST_MATH_INSTRUMENT_VARIABLE(x);
+
if(x <= 0)
{
return (v == 0) && (x == 0) ?
@@ -332,6 +336,10 @@
{
BOOST_MATH_STD_USING
typedef typename bessel_asymptotic_tag<T, Policy>::type tag_type;
+
+ BOOST_MATH_INSTRUMENT_VARIABLE(v);
+ BOOST_MATH_INSTRUMENT_VARIABLE(x);
+
if(floor(v) == v)
{
if((fabs(x) > asymptotic_bessel_y_limit<T>(tag_type())) && (fabs(x) > 5 * abs(v)))
@@ -339,12 +347,19 @@
T r = asymptotic_bessel_y_large_x_2(static_cast<T>(abs(v)), x);
if((v < 0) && (itrunc(v, pol) & 1))
r = -r;
+ BOOST_MATH_INSTRUMENT_VARIABLE(r);
return r;
}
else
- return bessel_yn(itrunc(v, pol), x, pol);
+ {
+ T r = bessel_yn(itrunc(v, pol), x, pol);
+ BOOST_MATH_INSTRUMENT_VARIABLE(r);
+ return r;
+ }
}
- return cyl_neumann_imp<T>(v, x, bessel_no_int_tag(), pol);
+ T r = cyl_neumann_imp<T>(v, x, bessel_no_int_tag(), pol);
+ BOOST_MATH_INSTRUMENT_VARIABLE(r);
+ return r;
}
template <class T, class Policy>
@@ -352,6 +367,10 @@
{
BOOST_MATH_STD_USING
typedef typename bessel_asymptotic_tag<T, Policy>::type tag_type;
+
+ BOOST_MATH_INSTRUMENT_VARIABLE(v);
+ BOOST_MATH_INSTRUMENT_VARIABLE(x);
+
if((fabs(x) > asymptotic_bessel_y_limit<T>(tag_type())) && (fabs(x) > 5 * abs(v)))
{
T r = asymptotic_bessel_y_large_x_2(static_cast<T>(abs(v)), x);
Modified: trunk/boost/math/special_functions/beta.hpp
==============================================================================
--- trunk/boost/math/special_functions/beta.hpp (original)
+++ trunk/boost/math/special_functions/beta.hpp 2008-11-18 14:47:50 EST (Tue, 18 Nov 2008)
@@ -242,13 +242,25 @@
// since one of the power terms will evaluate to a number close to 1.
//
if(fabs(l1) < 0.1)
+ {
result *= exp(a * boost::math::log1p(l1, pol));
+ BOOST_MATH_INSTRUMENT_VARIABLE(result);
+ }
else
+ {
result *= pow((x * cgh) / agh, a);
+ BOOST_MATH_INSTRUMENT_VARIABLE(result);
+ }
if(fabs(l2) < 0.1)
+ {
result *= exp(b * boost::math::log1p(l2, pol));
+ BOOST_MATH_INSTRUMENT_VARIABLE(result);
+ }
else
+ {
result *= pow((y * cgh) / bgh, b);
+ BOOST_MATH_INSTRUMENT_VARIABLE(result);
+ }
}
else if((std::max)(fabs(l1), fabs(l2)) < 0.5)
{
@@ -279,6 +291,7 @@
l3 = l1 + l3 + l3 * l1;
l3 = a * boost::math::log1p(l3, pol);
result *= exp(l3);
+ BOOST_MATH_INSTRUMENT_VARIABLE(result);
}
else
{
@@ -286,6 +299,7 @@
l3 = l2 + l3 + l3 * l2;
l3 = b * boost::math::log1p(l3, pol);
result *= exp(l3);
+ BOOST_MATH_INSTRUMENT_VARIABLE(result);
}
}
else if(fabs(l1) < fabs(l2))
@@ -294,6 +308,7 @@
T l = a * boost::math::log1p(l1, pol)
+ b * log((y * cgh) / bgh);
result *= exp(l);
+ BOOST_MATH_INSTRUMENT_VARIABLE(result);
}
else
{
@@ -301,6 +316,7 @@
T l = b * boost::math::log1p(l2, pol)
+ a * log((x * cgh) / agh);
result *= exp(l);
+ BOOST_MATH_INSTRUMENT_VARIABLE(result);
}
}
else
@@ -321,11 +337,13 @@
result *= pow(pow(b2, b/a) * b1, a);
else
result *= pow(pow(b1, a/b) * b2, b);
+ BOOST_MATH_INSTRUMENT_VARIABLE(result);
}
else
{
// finally the normal case:
result *= pow(b1, a) * pow(b2, b);
+ BOOST_MATH_INSTRUMENT_VARIABLE(result);
}
}
// combine with the leftover terms from the Lanczos approximation:
@@ -333,6 +351,8 @@
result *= sqrt(agh / cgh);
result *= prefix;
+ BOOST_MATH_INSTRUMENT_VARIABLE(result);
+
return result;
}
//
@@ -624,6 +644,9 @@
T ibeta_a_step(T a, T b, T x, T y, int k, const Policy& pol, bool normalised, T* p_derivative)
{
typedef typename lanczos::lanczos<T, Policy>::type lanczos_type;
+
+ BOOST_MATH_INSTRUMENT_VARIABLE(k);
+
T prefix = ibeta_power_terms(a, b, x, y, lanczos_type(), normalised, pol);
if(p_derivative)
{
@@ -662,6 +685,7 @@
// This is only called with small k, for large k
// it is grossly inefficient, do not use outside it's
// intended purpose!!!
+ BOOST_MATH_INSTRUMENT_VARIABLE(k);
if(k == 0)
return 1;
T result = 1;
@@ -845,6 +869,12 @@
typedef typename lanczos::lanczos<T, Policy>::type lanczos_type;
BOOST_MATH_STD_USING // for ADL of std math functions.
+ BOOST_MATH_INSTRUMENT_VARIABLE(a);
+ BOOST_MATH_INSTRUMENT_VARIABLE(b);
+ BOOST_MATH_INSTRUMENT_VARIABLE(x);
+ BOOST_MATH_INSTRUMENT_VARIABLE(inv);
+ BOOST_MATH_INSTRUMENT_VARIABLE(normalised);
+
bool invert = inv;
T fract;
T y = 1 - x;
@@ -894,6 +924,7 @@
std::swap(a, b);
std::swap(x, y);
invert = !invert;
+ BOOST_MATH_INSTRUMENT_VARIABLE(invert);
}
if((std::max)(a, b) <= 1)
{
@@ -901,12 +932,16 @@
if((a >= (std::min)(T(0.2), b)) || (pow(x, a) <= 0.9))
{
if(!invert)
+ {
fract = ibeta_series(a, b, x, T(0), lanczos_type(), normalised, p_derivative, y, pol);
+ BOOST_MATH_INSTRUMENT_VARIABLE(fract);
+ }
else
{
fract = -(normalised ? 1 : boost::math::beta(a, b, pol));
invert = false;
fract = -ibeta_series(a, b, x, fract, lanczos_type(), normalised, p_derivative, y, pol);
+ BOOST_MATH_INSTRUMENT_VARIABLE(fract);
}
}
else
@@ -917,12 +952,16 @@
if(y >= 0.3)
{
if(!invert)
+ {
fract = ibeta_series(a, b, x, T(0), lanczos_type(), normalised, p_derivative, y, pol);
+ BOOST_MATH_INSTRUMENT_VARIABLE(fract);
+ }
else
{
fract = -(normalised ? 1 : boost::math::beta(a, b, pol));
invert = false;
fract = -ibeta_series(a, b, x, fract, lanczos_type(), normalised, p_derivative, y, pol);
+ BOOST_MATH_INSTRUMENT_VARIABLE(fract);
}
}
else
@@ -939,12 +978,16 @@
}
fract = ibeta_a_step(a, b, x, y, 20, pol, normalised, p_derivative);
if(!invert)
+ {
fract = beta_small_b_large_a_series(a + 20, b, x, y, fract, prefix, pol, normalised);
+ BOOST_MATH_INSTRUMENT_VARIABLE(fract);
+ }
else
{
fract -= (normalised ? 1 : boost::math::beta(a, b, pol));
invert = false;
fract = -beta_small_b_large_a_series(a + 20, b, x, y, fract, prefix, pol, normalised);
+ BOOST_MATH_INSTRUMENT_VARIABLE(fract);
}
}
}
@@ -955,12 +998,16 @@
if((b <= 1) || ((x < 0.1) && (pow(b * x, a) <= 0.7)))
{
if(!invert)
+ {
fract = ibeta_series(a, b, x, T(0), lanczos_type(), normalised, p_derivative, y, pol);
+ BOOST_MATH_INSTRUMENT_VARIABLE(fract);
+ }
else
{
fract = -(normalised ? 1 : boost::math::beta(a, b, pol));
invert = false;
fract = -ibeta_series(a, b, x, fract, lanczos_type(), normalised, p_derivative, y, pol);
+ BOOST_MATH_INSTRUMENT_VARIABLE(fract);
}
}
else
@@ -972,23 +1019,31 @@
if(y >= 0.3)
{
if(!invert)
+ {
fract = ibeta_series(a, b, x, T(0), lanczos_type(), normalised, p_derivative, y, pol);
+ BOOST_MATH_INSTRUMENT_VARIABLE(fract);
+ }
else
{
fract = -(normalised ? 1 : boost::math::beta(a, b, pol));
invert = false;
fract = -ibeta_series(a, b, x, fract, lanczos_type(), normalised, p_derivative, y, pol);
+ BOOST_MATH_INSTRUMENT_VARIABLE(fract);
}
}
else if(a >= 15)
{
if(!invert)
+ {
fract = beta_small_b_large_a_series(a, b, x, y, T(0), T(1), pol, normalised);
+ BOOST_MATH_INSTRUMENT_VARIABLE(fract);
+ }
else
{
fract = -(normalised ? 1 : boost::math::beta(a, b, pol));
invert = false;
fract = -beta_small_b_large_a_series(a, b, x, y, fract, T(1), pol, normalised);
+ BOOST_MATH_INSTRUMENT_VARIABLE(fract);
}
}
else
@@ -1004,13 +1059,18 @@
prefix = 1;
}
fract = ibeta_a_step(a, b, x, y, 20, pol, normalised, p_derivative);
+ BOOST_MATH_INSTRUMENT_VARIABLE(fract);
if(!invert)
+ {
fract = beta_small_b_large_a_series(a + 20, b, x, y, fract, prefix, pol, normalised);
+ BOOST_MATH_INSTRUMENT_VARIABLE(fract);
+ }
else
{
fract -= (normalised ? 1 : boost::math::beta(a, b, pol));
invert = false;
fract = -beta_small_b_large_a_series(a + 20, b, x, y, fract, prefix, pol, normalised);
+ BOOST_MATH_INSTRUMENT_VARIABLE(fract);
}
}
}
@@ -1033,6 +1093,7 @@
std::swap(a, b);
std::swap(x, y);
invert = !invert;
+ BOOST_MATH_INSTRUMENT_VARIABLE(invert);
}
if(b < 40)
@@ -1045,16 +1106,21 @@
fract = binomial_ccdf(n, k, x, y);
if(!normalised)
fract *= boost::math::beta(a, b, pol);
+ BOOST_MATH_INSTRUMENT_VARIABLE(fract);
}
else if(b * x <= 0.7)
{
if(!invert)
+ {
fract = ibeta_series(a, b, x, T(0), lanczos_type(), normalised, p_derivative, y, pol);
+ BOOST_MATH_INSTRUMENT_VARIABLE(fract);
+ }
else
{
fract = -(normalised ? 1 : boost::math::beta(a, b, pol));
invert = false;
fract = -ibeta_series(a, b, x, fract, lanczos_type(), normalised, p_derivative, y, pol);
+ BOOST_MATH_INSTRUMENT_VARIABLE(fract);
}
}
else if(a > 15)
@@ -1076,6 +1142,7 @@
fract = ibeta_a_step(bbar, a, y, x, n, pol, normalised, static_cast<T*>(0));
fract = beta_small_b_large_a_series(a, bbar, x, y, fract, T(1), pol, normalised);
fract /= prefix;
+ BOOST_MATH_INSTRUMENT_VARIABLE(fract);
}
else if(normalised)
{
@@ -1100,12 +1167,19 @@
fract = -fract;
invert = false;
}
+ BOOST_MATH_INSTRUMENT_VARIABLE(fract);
}
else
+ {
fract = ibeta_fraction2(a, b, x, y, pol, normalised, p_derivative);
+ BOOST_MATH_INSTRUMENT_VARIABLE(fract);
+ }
}
else
+ {
fract = ibeta_fraction2(a, b, x, y, pol, normalised, p_derivative);
+ BOOST_MATH_INSTRUMENT_VARIABLE(fract);
+ }
}
if(p_derivative)
{
Modified: trunk/boost/math/special_functions/detail/igamma_inverse.hpp
==============================================================================
--- trunk/boost/math/special_functions/detail/igamma_inverse.hpp (original)
+++ trunk/boost/math/special_functions/detail/igamma_inverse.hpp 2008-11-18 14:47:50 EST (Tue, 18 Nov 2008)
@@ -109,11 +109,16 @@
T result;
if(a == 1)
+ {
result = -log(q);
+ BOOST_MATH_INSTRUMENT_VARIABLE(result);
+ }
else if(a < 1)
{
T g = boost::math::tgamma(a, pol);
T b = q * g;
+ BOOST_MATH_INSTRUMENT_VARIABLE(g);
+ BOOST_MATH_INSTRUMENT_VARIABLE(b);
if((b > 0.6) || ((b >= 0.45) && (a >= 0.3)))
{
// DiDonato & Morris Eq 21:
@@ -127,12 +132,15 @@
if((b * q > 1e-8) && (q > 1e-5))
{
u = pow(p * g * a, 1 / a);
+ BOOST_MATH_INSTRUMENT_VARIABLE(u);
}
else
{
u = exp((-q / a) - constants::euler<T>());
+ BOOST_MATH_INSTRUMENT_VARIABLE(u);
}
result = u / (1 - (u / (a + 1)));
+ BOOST_MATH_INSTRUMENT_VARIABLE(result);
}
else if((a < 0.3) && (b >= 0.35))
{
@@ -140,6 +148,7 @@
T t = exp(-constants::euler<T>() - b);
T u = t * exp(t);
result = t * exp(u);
+ BOOST_MATH_INSTRUMENT_VARIABLE(result);
}
else if((b > 0.15) || (a >= 0.3))
{
@@ -147,6 +156,7 @@
T y = -log(b);
T u = y - (1 - a) * log(y);
result = y - (1 - a) * log(u) - log(1 + (1 - a) / (1 + u));
+ BOOST_MATH_INSTRUMENT_VARIABLE(result);
}
else if (b > 0.1)
{
@@ -154,6 +164,7 @@
T y = -log(b);
T u = y - (1 - a) * log(y);
result = y - (1 - a) * log(u) - log((u * u + 2 * (3 - a) * u + (2 - a) * (3 - a)) / (u * u + (5 - a) * u + 2));
+ BOOST_MATH_INSTRUMENT_VARIABLE(result);
}
else
{
@@ -179,6 +190,7 @@
T y_3 = y_2 * y;
T y_4 = y_2 * y_2;
result = y + c1 + (c2 / y) + (c3 / y_2) + (c4 / y_3) + (c5 / y_4);
+ BOOST_MATH_INSTRUMENT_VARIABLE(result);
}
}
else
@@ -186,26 +198,34 @@
// DiDonato and Morris Eq 31:
T s = find_inverse_s(p, q);
+ BOOST_MATH_INSTRUMENT_VARIABLE(s);
+
T s_2 = s * s;
T s_3 = s_2 * s;
T s_4 = s_2 * s_2;
T s_5 = s_4 * s;
T ra = sqrt(a);
+ BOOST_MATH_INSTRUMENT_VARIABLE(ra);
+
T w = a + s * ra + (s * s -1) / 3;
w += (s_3 - 7 * s) / (36 * ra);
w -= (3 * s_4 + 7 * s_2 - 16) / (810 * a);
w += (9 * s_5 + 256 * s_3 - 433 * s) / (38880 * a * ra);
+ BOOST_MATH_INSTRUMENT_VARIABLE(w);
+
if((a >= 500) && (fabs(1 - w / a) < 1e-6))
{
result = w;
+ BOOST_MATH_INSTRUMENT_VARIABLE(result);
}
else if (p > 0.5)
{
if(w < 3 * a)
{
result = w;
+ BOOST_MATH_INSTRUMENT_VARIABLE(result);
}
else
{
@@ -236,12 +256,14 @@
T y_3 = y_2 * y;
T y_4 = y_2 * y_2;
result = y + c1 + (c2 / y) + (c3 / y_2) + (c4 / y_3) + (c5 / y_4);
+ BOOST_MATH_INSTRUMENT_VARIABLE(result);
}
else
{
// DiDonato and Morris Eq 33:
T u = -lb + (a - 1) * log(w) - log(1 + (1 - a) / (1 + w));
result = -lb + (a - 1) * log(u) - log(1 + (1 - a) / (1 + u));
+ BOOST_MATH_INSTRUMENT_VARIABLE(result);
}
}
}
@@ -253,9 +275,12 @@
z = didonato_FN(p, a, z, 2, T(0), pol);
z = didonato_FN(p, a, z, 3, T(0), pol);
+ BOOST_MATH_INSTRUMENT_VARIABLE(z);
+
if((z <= 0.01 * (a + 1)) || (z > 0.7 * (a + 1)))
{
result = z;
+ BOOST_MATH_INSTRUMENT_VARIABLE(result);
}
else
{
@@ -263,6 +288,7 @@
T zb = didonato_FN(p, a, z, 100, T(1e-4), pol);
T u = log(p) + boost::math::lgamma(a + 1, pol);
result = zb * (1 - (a * log(zb) - zb - u + log(didonato_SN(a, z, 100, T(1e-4)))) / (a - zb));
+ BOOST_MATH_INSTRUMENT_VARIABLE(result);
}
}
}
@@ -349,6 +375,9 @@
static const char* function = "boost::math::gamma_p_inv<%1%>(%1%, %1%)";
+ BOOST_MATH_INSTRUMENT_VARIABLE(a);
+ BOOST_MATH_INSTRUMENT_VARIABLE(p);
+
if(a <= 0)
policies::raise_domain_error<T>(function, "Argument a in the incomplete gamma function inverse must be >= 0 (got a=%1%).", a, pol);
if((p < 0) || (p > 1))
@@ -361,6 +390,7 @@
T lower = tools::min_value<T>();
if(guess <= lower)
guess = tools::min_value<T>();
+ BOOST_MATH_INSTRUMENT_VARIABLE(guess);
//
// Work out how many digits to converge to, normally this is
// 2/3 of the digits in T, but if the first derivative is very
@@ -379,6 +409,7 @@
lower,
tools::max_value<T>(),
digits);
+ BOOST_MATH_INSTRUMENT_VARIABLE(guess);
if(guess == lower)
guess = policies::raise_underflow_error<T>(function, "Expected result known to be non-zero, but is smaller than the smallest available number.", pol);
return guess;
Modified: trunk/boost/math/special_functions/ellint_1.hpp
==============================================================================
--- trunk/boost/math/special_functions/ellint_1.hpp (original)
+++ trunk/boost/math/special_functions/ellint_1.hpp 2008-11-18 14:47:50 EST (Tue, 18 Nov 2008)
@@ -90,7 +90,7 @@
BOOST_MATH_INSTRUMENT_CODE("pi/2 = " << constants::pi<T>() / 2);
T rphi = boost::math::tools::fmod_workaround(phi, constants::pi<T>() / 2);
BOOST_MATH_INSTRUMENT_VARIABLE(rphi);
- T m = 2 * (phi - rphi) / constants::pi<T>();
+ T m = floor((2 * phi) / constants::pi<T>());
BOOST_MATH_INSTRUMENT_VARIABLE(m);
int s = 1;
if(boost::math::tools::fmod_workaround(m, T(2)) > 0.5)
Modified: trunk/boost/math/special_functions/ellint_2.hpp
==============================================================================
--- trunk/boost/math/special_functions/ellint_2.hpp (original)
+++ trunk/boost/math/special_functions/ellint_2.hpp 2008-11-18 14:47:50 EST (Tue, 18 Nov 2008)
@@ -75,7 +75,7 @@
// so rewritten to use fmod instead:
//
T rphi = boost::math::tools::fmod_workaround(phi, constants::pi<T>() / 2);
- T m = 2 * (phi - rphi) / constants::pi<T>();
+ T m = floor((2 * phi) / constants::pi<T>());
int s = 1;
if(boost::math::tools::fmod_workaround(m, T(2)) > 0.5)
{
Modified: trunk/boost/math/special_functions/ellint_3.hpp
==============================================================================
--- trunk/boost/math/special_functions/ellint_3.hpp (original)
+++ trunk/boost/math/special_functions/ellint_3.hpp 2008-11-18 14:47:50 EST (Tue, 18 Nov 2008)
@@ -183,7 +183,7 @@
else
{
T rphi = boost::math::tools::fmod_workaround(fabs(phi), constants::pi<T>() / 2);
- T m = 2 * (fabs(phi) - rphi) / constants::pi<T>();
+ T m = floor((2 * fabs(phi)) / constants::pi<T>());
int sign = 1;
if(boost::math::tools::fmod_workaround(m, T(2)) > 0.5)
{
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk