summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authoruqs <uqs@FreeBSD.org>2010-11-13 10:54:10 +0000
committeruqs <uqs@FreeBSD.org>2010-11-13 10:54:10 +0000
commit34589aa4cb98789f70c21cb1b1cd54d6ec9bc1b5 (patch)
treed537c1ef0b301f7d65f779b81cab45e4de9b30a1 /lib
parente0a2d4f15ed9e93fcb62544ed65f7a98e2339c3b (diff)
downloadFreeBSD-src-34589aa4cb98789f70c21cb1b1cd54d6ec9bc1b5.zip
FreeBSD-src-34589aa4cb98789f70c21cb1b1cd54d6ec9bc1b5.tar.gz
Fix bug in jn(3) and jnf(3) that led to -inf results
Explanation by Steve: jn[f](n,x) for certain ranges of x uses downward recursion to compute the value of the function. The recursion sequence that is generated is proportional to the actual desired value, so a normalization step is taken. This normalization is j0[f](x) divided by the zeroth sequence member. As Bruce notes, near the zeros of j0[f](x) the computed value can have giga-ULP inaccuracy. I found for the 1st zero of j0f(x) only the leading decimal digit is correct. The solution to the issue is fairly straight forward. The zeros of j0(x) and j1(x) never coincide, so as j0(x) approaches a zero, the normalization constant switches to j1[f](x) divided by the 2nd sequence member. The expectation is that j1[f](x) is a more accurately computed value. PR: bin/144306 Submitted by: Steven G. Kargl <kargl@troutmask.apl.washington.edu> Reviewed by: bde MFC after: 7 days
Diffstat (limited to 'lib')
-rw-r--r--lib/msun/src/e_jn.c7
-rw-r--r--lib/msun/src/e_jnf.c7
2 files changed, 12 insertions, 2 deletions
diff --git a/lib/msun/src/e_jn.c b/lib/msun/src/e_jn.c
index e277e30..8b0bc62 100644
--- a/lib/msun/src/e_jn.c
+++ b/lib/msun/src/e_jn.c
@@ -200,7 +200,12 @@ __ieee754_jn(int n, double x)
}
}
}
- b = (t*__ieee754_j0(x)/b);
+ z = __ieee754_j0(x);
+ w = __ieee754_j1(x);
+ if (fabs(z) >= fabs(w))
+ b = (t*z/b);
+ else
+ b = (t*w/a);
}
}
if(sgn==1) return -b; else return b;
diff --git a/lib/msun/src/e_jnf.c b/lib/msun/src/e_jnf.c
index 3bbf7b7..f564aec 100644
--- a/lib/msun/src/e_jnf.c
+++ b/lib/msun/src/e_jnf.c
@@ -152,7 +152,12 @@ __ieee754_jnf(int n, float x)
}
}
}
- b = (t*__ieee754_j0f(x)/b);
+ z = __ieee754_j0f(x);
+ w = __ieee754_j1f(x);
+ if (fabsf(z) >= fabsf(w))
+ b = (t*z/b);
+ else
+ b = (t*w/a);
}
}
if(sgn==1) return -b; else return b;
OpenPOWER on IntegriCloud