(2nd time) tweaks to erff() threshold values
Steve Kargl
sgk at troutmask.apl.washington.edu
Sun Aug 25 02:30:30 UTC 2013
On Sat, Aug 24, 2013 at 01:21:02PM -0700, Steve Kargl wrote:
> On Fri, Aug 23, 2013 at 09:57:44AM -0700, Steve Kargl wrote:
> > On Fri, Aug 23, 2013 at 09:12:33PM +1000, Bruce Evans wrote:
> >
> >> The whole erf implementation is probably not the best way for
> >> float precision, but is good for understanding higher precisions.
> >
> > I'm fairly certain that the implementation of erff() is not very
> > efficient. The polynomials, used in the rational approximations,
> > are the same order as those used in the double precision approximation.
> > I'll check the polys when update my P(x)/Q(x) remes algorithm for
> > erfl and erfcl.
>
> I seem to be right (although I haven't iterated on the P's and Q's).
>
Now, with pretty testing and (perhaps) better coefficients:
| usec/call | Max ULP | X Max ULP
---------+-----------+---------+---------------------------------
new erfc | 0.02757 | 0.65947 | 8.19824636e-01, 0x1.a3c00ep-1
old erfc | 0.03348 | 0.68218 | 8.43257010e-01, 0x1.afbf62p-1
---------+-----------+---------+---------------------------------
new erf | 0.02302 | 0.62437 | 1.04175471e-38, 0x1.c5bf88p-127
old erf | 0.03028 | 0.62437 | 1.04175471e-38, 0x1.c5bf88p-127
OK to commit?
--
Steve
Index: src/s_erff.c
===================================================================
--- src/s_erff.c (revision 1361)
+++ src/s_erff.c (working copy)
@@ -31,16 +31,16 @@ erx = 8.4506291151e-01, /* 0x3f58560b *
*/
efx = 1.2837916613e-01, /* 0x3e0375d4 */
efx8= 1.0270333290e+00, /* 0x3f8375d4 */
-pp0 = 1.2837916613e-01, /* 0x3e0375d4 */
-pp1 = -3.2504209876e-01, /* 0xbea66beb */
-pp2 = -2.8481749818e-02, /* 0xbce9528f */
-pp3 = -5.7702702470e-03, /* 0xbbbd1489 */
-pp4 = -2.3763017452e-05, /* 0xb7c756b1 */
-qq1 = 3.9791721106e-01, /* 0x3ecbbbce */
-qq2 = 6.5022252500e-02, /* 0x3d852a63 */
-qq3 = 5.0813062117e-03, /* 0x3ba68116 */
-qq4 = 1.3249473704e-04, /* 0x390aee49 */
-qq5 = -3.9602282413e-06, /* 0xb684e21a */
+/*
+ * Domain [0, 0.84375], range ~[-5.4446e-10,5.5197e-10]:
+ * |(erf(x) - x)/x - p(x)/q(x)| < 2**-31.
+ */
+pp0 = 1.28379166e-01F, /* 0x1.06eba8p-3 */
+pp1 = -3.36030394e-01F, /* -0x1.58185ap-2 */
+pp2 = -1.86260219e-03F, /* -0x1.e8451ep-10 */
+qq1 = 3.12324286e-01F, /* 0x1.3fd1f0p-2 */
+qq2 = 2.16070302e-02F, /* 0x1.620274p-6 */
+qq3 = -1.98859419e-03F, /* -0x1.04a626p-9 */
/*
* Coefficients for approximation to erf in [0.84375,1.25]
*/
@@ -114,8 +114,8 @@ erff(float x)
return x + efx*x;
}
z = x*x;
- r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4)));
- s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))));
+ r = pp0+z*(pp1+z*pp2);
+ s = one+z*(qq1+z*(qq2+z*qq3));
y = r/s;
return x + x*y;
}
@@ -163,8 +163,8 @@ erfcf(float x)
if(ix < 0x23800000) /* |x|<2**-56 */
return one-x;
z = x*x;
- r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4)));
- s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))));
+ r = pp0+z*(pp1+z*pp2);
+ s = one+z*(qq1+z*(qq2+z*qq3));
y = r/s;
if(hx < 0x3e800000) { /* x<1/4 */
return one-(x+x*y);
More information about the freebsd-numerics
mailing list