[Scipy-svn] r5466 - in trunk/scipy/special: . tests
scipy-svn at scipy.org
scipy-svn at scipy.org
Thu Jan 15 19:04:54 EST 2009
Author: ptvirtan
Date: 2009-01-15 18:04:38 -0600 (Thu, 15 Jan 2009)
New Revision: 5466
Modified:
trunk/scipy/special/specfun_wrappers.c
trunk/scipy/special/tests/test_basic.py
Log:
Ensure that STVHV is never called with x<0
Use symmetries for integer v, and return NaN for non-integer v (when
the result would be complex). This works around bad accuracy in
Cephes and Specfun.
Modified: trunk/scipy/special/specfun_wrappers.c
===================================================================
--- trunk/scipy/special/specfun_wrappers.c 2009-01-16 00:04:07 UTC (rev 5465)
+++ trunk/scipy/special/specfun_wrappers.c 2009-01-16 00:04:38 UTC (rev 5466)
@@ -212,27 +212,40 @@
double struve_wrap(double v, double x) {
double out;
+ double rem;
int flag=0;
+ if (x < 0) {
+ rem = fmod(v, 2.0);
+ if (rem == 0) {
+ x = -x;
+ flag = 1;
+ } else if (rem == 1 || rem == -1) {
+ x = -x;
+ flag = 0;
+ } else {
+ /* non-integer v and x < 0 => complex-valued */
+ return NAN;
+ }
+ }
+
if ((v<-8.0) || (v>12.5)) {
- return cephes_struve(v, x); /* from cephes */
+ out = cephes_struve(v, x); /* from cephes */
}
- if (v==0.0) {
- if (x < 0) {x = -x; flag=1;}
+ else if (v==0.0) {
F_FUNC(stvh0,STVH0)(&x,&out);
CONVINF(out);
- if (flag) out = -out;
- return out;
}
- if (v==1.0) {
- if (x < 0) x=-x;
+ else if (v==1.0) {
F_FUNC(stvh1,STVH1)(&x,&out);
CONVINF(out);
- return out;
}
- F_FUNC(stvhv,STVHV)(&v,&x,&out);
- CONVINF(out);
- return out;
+ else {
+ F_FUNC(stvhv,STVHV)(&v,&x,&out);
+ CONVINF(out);
+ }
+ if (flag) out = -out;
+ return out;
}
double modstruve_wrap(double v, double x) {
Modified: trunk/scipy/special/tests/test_basic.py
===================================================================
--- trunk/scipy/special/tests/test_basic.py 2009-01-16 00:04:07 UTC (rev 5465)
+++ trunk/scipy/special/tests/test_basic.py 2009-01-16 00:04:38 UTC (rev 5466)
@@ -2014,7 +2014,7 @@
def test_vs_series(self):
"""Check Struve function versus its power series"""
- for v in [-10, -7.99, -3.4, -1, 0, 1, 3.4, 12.49, 16]:
+ for v in [-20, -10, -7.99, -3.4, -1, 0, 1, 3.4, 12.49, 16]:
for z in [1, 10, 19, 21, 30]:
value, err = self._series(v, z)
assert allclose(struve(v, z), value, atol=err), (v, z)
@@ -2023,7 +2023,15 @@
assert_almost_equal(struve(-7.99, 21), 0.0467547614113, decimal=8)
assert_almost_equal(struve(-8.01, 21), 0.0398716951023, decimal=9)
assert_almost_equal(struve(-3.0, 200), 0.0142134427432, decimal=13)
+ assert_almost_equal(struve(-8.0, -41), 0.0192469727846, decimal=9)
+ assert_equal(struve(-12, -41), -struve(-12, 41))
+ assert_equal(struve(+12, -41), -struve(+12, 41))
+ assert_equal(struve(-11, -41), +struve(-11, 41))
+ assert_equal(struve(+11, -41), +struve(+11, 41))
+ assert isnan(struve(-7.1, -1))
+ assert isnan(struve(-10.1, -1))
+
def test_regression_679(self):
"""Regression test for #679"""
assert_almost_equal(struve(-1.0, 20 - 1e-8), struve(-1.0, 20 + 1e-8))
More information about the Scipy-svn
mailing list