1 /* s_erff.c -- float version of s_erf.c.
2 * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
6 * ====================================================
7 * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
9 * Developed at SunPro, a Sun Microsystems, Inc. business.
10 * Permission to use, copy, modify, and distribute this
11 * software is freely granted, provided that this notice
13 * ====================================================
17 static char rcsid
[] = "$FreeBSD: src/lib/msun/src/s_erff.c,v 1.8 2008/02/22 02:30:35 das Exp $";
21 #include "math_private.h"
23 /* XXX Prevent compilers from erroneously constant folding: */
24 static const volatile float tiny
__attribute__ ((__section__(".rodata,\"a\" " SECTIONCOMMENT
))) = 1e-30;
30 erx
= 8.42697144e-01, /* 0x3f57bb00 */
32 * In the domain [0, 2**-14], only the first term in the power series
33 * expansion of erf(x) is used. The magnitude of the first neglected
34 * terms is less than 2**-42.
36 efx
= 1.28379166e-01, /* 0x3e0375d4 */
37 efx8
= 1.02703333e+00, /* 0x3f8375d4 */
39 * Domain [0, 0.84375], range ~[-5.4419e-10, 5.5179e-10]:
40 * |(erf(x) - x)/x - pp(x)/qq(x)| < 2**-31
42 pp0
= 1.28379166e-01, /* 0x3e0375d4 */
43 pp1
= -3.36030394e-01, /* 0xbeac0c2d */
44 pp2
= -1.86261395e-03, /* 0xbaf422f4 */
45 qq1
= 3.12324315e-01, /* 0x3e9fe8f9 */
46 qq2
= 2.16070414e-02, /* 0x3cb10140 */
47 qq3
= -1.98859372e-03, /* 0xbb025311 */
49 * Domain [0.84375, 1.25], range ~[-1.023e-9, 1.023e-9]:
50 * |(erf(x) - erx) - pa(x)/qa(x)| < 2**-31
52 pa0
= 3.65041046e-06, /* 0x3674f993 */
53 pa1
= 4.15109307e-01, /* 0x3ed48935 */
54 pa2
= -2.09395722e-01, /* 0xbe566bd5 */
55 pa3
= 8.67677554e-02, /* 0x3db1b34b */
56 qa1
= 4.95560974e-01, /* 0x3efdba2b */
57 qa2
= 3.71248513e-01, /* 0x3ebe1449 */
58 qa3
= 3.92478965e-02, /* 0x3d20c267 */
60 * Domain [1.25,1/0.35], range ~[-4.821e-9, 4.927e-9]:
61 * |log(x*erfc(x)) + x**2 + 0.5625 - ra(x)/sa(x)| < 2**-28
63 ra0
= -9.88156721e-03, /* 0xbc21e64c */
64 ra1
= -5.43658376e-01, /* 0xbf0b2d32 */
65 ra2
= -1.66828310e+00, /* 0xbfd58a4d */
66 ra3
= -6.91554189e-01, /* 0xbf3109b2 */
67 sa1
= 4.48581553e+00, /* 0x408f8bcd */
68 sa2
= 4.10799170e+00, /* 0x408374ab */
69 sa3
= 5.53855181e-01, /* 0x3f0dc974 */
71 * Domain [2.85715, 11], range ~[-1.484e-9, 1.505e-9]:
72 * |log(x*erfc(x)) + x**2 + 0.5625 - rb(x)/sb(x)| < 2**-30
74 rb0
= -9.86496918e-03, /* 0xbc21a0ae */
75 rb1
= -5.48049808e-01, /* 0xbf0c4cfe */
76 rb2
= -1.84115684e+00, /* 0xbfebab07 */
77 sb1
= 4.87132740e+00, /* 0x409be1ea */
78 sb2
= 3.04982710e+00, /* 0x4043305e */
79 sb3
= -7.61900663e-01; /* 0xbf430bec */
85 float R
,S
,P
,Q
,s
,y
,z
,r
;
88 if(ix
>=0x7f800000) { /* erff(nan)=nan */
89 i
= ((uint32_t)hx
>>31)<<1;
90 return (float)(1-i
)+one
/x
; /* erff(+-inf)=+-1 */
93 if(ix
< 0x3f580000) { /* |x|<0.84375 */
94 if(ix
< 0x38800000) { /* |x|<2**-14 */
95 if (ix
< 0x04000000) /* |x|<0x1p-119 */
96 return (8*x
+efx8
*x
)/8; /* avoid spurious underflow */
100 r
= pp0
+z
*(pp1
+z
*pp2
);
101 s
= one
+z
*(qq1
+z
*(qq2
+z
*qq3
));
105 if(ix
< 0x3fa00000) { /* 0.84375 <= |x| < 1.25 */
107 P
= pa0
+s
*(pa1
+s
*(pa2
+s
*pa3
));
108 Q
= one
+s
*(qa1
+s
*(qa2
+s
*qa3
));
109 if(hx
>=0) return erx
+ P
/Q
; else return -erx
- P
/Q
;
111 if (ix
>= 0x40800000) { /* inf>|x|>=4 */
112 if(hx
>=0) return one
-tiny
; else return tiny
-one
;
116 if(ix
< 0x4036db8c) { /* |x| < 2.85715 ~ 1/0.35 */
117 R
=ra0
+s
*(ra1
+s
*(ra2
+s
*ra3
));
118 S
=one
+s
*(sa1
+s
*(sa2
+s
*sa3
));
119 } else { /* |x| >= 2.85715 ~ 1/0.35 */
121 S
=one
+s
*(sb1
+s
*(sb2
+s
*sb3
));
123 SET_FLOAT_WORD(z
,hx
&0xffffe000);
124 r
= expf(-z
*z
-0.5625F
)*expf((z
-x
)*(z
+x
)+R
/S
);
125 if(hx
>=0) return one
-r
/x
; else return r
/x
-one
;
132 float R
,S
,P
,Q
,s
,y
,z
,r
;
133 GET_FLOAT_WORD(hx
,x
);
135 if(ix
>=0x7f800000) { /* erfcf(nan)=nan */
136 /* erfcf(+-inf)=0,2 */
137 return (float)(((uint32_t)hx
>>31)<<1)+one
/x
;
140 if(ix
< 0x3f580000) { /* |x|<0.84375 */
141 if(ix
< 0x33800000) /* |x|<2**-24 */
144 r
= pp0
+z
*(pp1
+z
*pp2
);
145 s
= one
+z
*(qq1
+z
*(qq2
+z
*qq3
));
147 if(hx
< 0x3e800000) { /* x<1/4 */
155 if(ix
< 0x3fa00000) { /* 0.84375 <= |x| < 1.25 */
157 P
= pa0
+s
*(pa1
+s
*(pa2
+s
*pa3
));
158 Q
= one
+s
*(qa1
+s
*(qa2
+s
*qa3
));
160 z
= one
-erx
; return z
- P
/Q
;
162 z
= erx
+P
/Q
; return one
+z
;
165 if (ix
< 0x41300000) { /* |x|<11 */
168 if(ix
< 0x4036db8c) { /* |x| < 2.85715 ~ 1/.35 */
169 R
=ra0
+s
*(ra1
+s
*(ra2
+s
*ra3
));
170 S
=one
+s
*(sa1
+s
*(sa2
+s
*sa3
));
171 } else { /* |x| >= 2.85715 ~ 1/.35 */
172 if(hx
<0&&ix
>=0x40a00000) return two
-tiny
;/* x < -5 */
174 S
=one
+s
*(sb1
+s
*(sb2
+s
*sb3
));
176 SET_FLOAT_WORD(z
,hx
&0xffffe000);
177 r
= expf(-z
*z
-0.5625F
)*expf((z
-x
)*(z
+x
)+R
/S
);
178 if(hx
>0) return r
/x
; else return two
-r
/x
;
180 if(hx
>0) return tiny
*tiny
; else return two
-tiny
;