source: sasmodels/sasmodels/models/lib/sas_erf.c @ b3796fa

core_shell_microgelscostrafo411magnetic_modelrelease_v0.94release_v0.95ticket-1257-vesicle-productticket_1156ticket_1265_superballticket_822_more_unit_tests
Last change on this file since b3796fa was b3796fa, checked in by Paul Kienzle <pkienzle@…>, 8 years ago

Allow use of cephes erf() even if erf() is available in the math library

  • Property mode set to 100644
File size: 6.7 KB
Line 
1
2/*
3 * Cephes Math Library Release 2.2:  June, 1992
4 * Copyright 1984, 1987, 1988, 1992 by Stephen L. Moshier
5 * Direct inquiries to 30 Frost Street, Cambridge, MA 02140
6 */
7/*
8 *
9 *      Error function
10 *
11 *
12 *
13 * SYNOPSIS:
14 *
15 * double x, y, erf();
16 *
17 * y = erf( x );
18 *
19 *
20 *
21 * DESCRIPTION:
22 *
23 * The integral is
24 *
25 *                           x
26 *                            -
27 *                 2         | |          2
28 *   erf(x)  =  --------     |    exp( - t  ) dt.
29 *              sqrt(pi)   | |
30 *                          -
31 *                           0
32 *
33 * For 0 <= |x| < 1, erf(x) = x * P4(x**2)/Q5(x**2); otherwise
34 * erf(x) = 1 - erfc(x).
35 *
36 *
37 *
38 * ACCURACY:
39 *
40 *                      Relative error:
41 * arithmetic   domain     # trials      peak         rms
42 *    IEEE      0,1         30000       3.7e-16     1.0e-16
43 *
44 */
45/*
46 *
47 *      Complementary error function
48 *
49 *
50 *
51 * SYNOPSIS:
52 *
53 * double x, y, erfc();
54 *
55 * y = erfc( x );
56 *
57 *
58 *
59 * DESCRIPTION:
60 *
61 *
62 *  1 - erf(x) =
63 *
64 *                           inf.
65 *                             -
66 *                  2         | |          2
67 *   erfc(x)  =  --------     |    exp( - t  ) dt
68 *               sqrt(pi)   | |
69 *                           -
70 *                            x
71 *
72 *
73 * For small x, erfc(x) = 1 - erf(x); otherwise rational
74 * approximations are computed.
75 *
76 *
77 *
78 * ACCURACY:
79 *
80 *                      Relative error:
81 * arithmetic   domain     # trials      peak         rms
82 *    IEEE      0,26.6417   30000       5.7e-14     1.5e-14
83 */
84
85#ifdef NEED_ERF
86
87#if FLOAT_SIZE>4  // DOUBLE_PRECISION
88
89double cephes_erf(double x);
90double cephes_erfc(double a);
91
92constant double PD[] = {
93    2.46196981473530512524E-10,
94    5.64189564831068821977E-1,
95    7.46321056442269912687E0,
96    4.86371970985681366614E1,
97    1.96520832956077098242E2,
98    5.26445194995477358631E2,
99    9.34528527171957607540E2,
100    1.02755188689515710272E3,
101    5.57535335369399327526E2
102};
103
104constant double QD[] = {
105    /* 1.00000000000000000000E0, */
106    1.32281951154744992508E1,
107    8.67072140885989742329E1,
108    3.54937778887819891062E2,
109    9.75708501743205489753E2,
110    1.82390916687909736289E3,
111    2.24633760818710981792E3,
112    1.65666309194161350182E3,
113    5.57535340817727675546E2
114};
115
116constant double RD[] = {
117    5.64189583547755073984E-1,
118    1.27536670759978104416E0,
119    5.01905042251180477414E0,
120    6.16021097993053585195E0,
121    7.40974269950448939160E0,
122    2.97886665372100240670E0
123};
124
125constant double SD[] = {
126    /* 1.00000000000000000000E0, */
127    2.26052863220117276590E0,
128    9.39603524938001434673E0,
129    1.20489539808096656605E1,
130    1.70814450747565897222E1,
131    9.60896809063285878198E0,
132    3.36907645100081516050E0
133};
134
135constant double TD[] = {
136    9.60497373987051638749E0,
137    9.00260197203842689217E1,
138    2.23200534594684319226E3,
139    7.00332514112805075473E3,
140    5.55923013010394962768E4
141};
142
143constant double UD[] = {
144    /* 1.00000000000000000000E0, */
145    3.35617141647503099647E1,
146    5.21357949780152679795E2,
147    4.59432382970980127987E3,
148    2.26290000613890934246E4,
149    4.92673942608635921086E4
150};
151
152double cephes_erfc(double a)
153{
154    double MAXLOG = 88.72283905206835;
155    double p, q, x, y, z;
156
157
158    x = fabs(a);
159
160    if (x < 1.0) {
161        // The line below causes problems on the GPU, so inline
162        // the erf function instead and z < 1.0.
163        //return (1.0 - cephes_erf(a));
164        z = x * x;
165        y = x * polevl(z, TD, 4) / p1evl(z, UD, 5);
166
167        return y;
168    }
169
170    z = -a * a;
171
172    if (z < -MAXLOG) {
173        if (a < 0)
174            return (2.0);
175        else
176            return (0.0);
177    }
178
179    z = exp(z);
180
181
182    if (x < 8.0) {
183        p = polevl(x, PD, 8);
184        q = p1evl(x, QD, 8);
185    }
186    else {
187        p = polevl(x, RD, 5);
188        q = p1evl(x, SD, 6);
189    }
190    y = (z * p) / q;
191
192    if (a < 0)
193        y = 2.0 - y;
194
195    if (y == 0.0) {
196        if (a < 0)
197            return (2.0);
198        else
199            return (0.0);
200    }
201    return y;
202}
203
204
205double cephes_erf(double x)
206{
207    double y, z;
208
209    if (fabs(x) > 1.0)
210        return (1.0 - cephes_erfc(x));
211
212    z = x * x;
213    y = x * polevl(z, TD, 4) / p1evl(z, UD, 5);
214
215    return y;
216}
217
218#else // SINGLE PRECISION
219
220float cephes_erff(float x);
221float cephes_erfcf(float a);
222
223/* erfc(x) = exp(-x^2) P(1/x), 1 < x < 2 */
224constant float PF[] = {
225    2.326819970068386E-002,
226    -1.387039388740657E-001,
227    3.687424674597105E-001,
228    -5.824733027278666E-001,
229    6.210004621745983E-001,
230    -4.944515323274145E-001,
231    3.404879937665872E-001,
232    -2.741127028184656E-001,
233    5.638259427386472E-001
234};
235
236/* erfc(x) = exp(-x^2) 1/x P(1/x^2), 2 < x < 14 */
237constant float RF[] = {
238    -1.047766399936249E+001,
239    1.297719955372516E+001,
240    -7.495518717768503E+000,
241    2.921019019210786E+000,
242    -1.015265279202700E+000,
243    4.218463358204948E-001,
244    -2.820767439740514E-001,
245    5.641895067754075E-001
246};
247
248/* erf(x) = x P(x^2), 0 < x < 1 */
249 constant float TF[] = {
250    7.853861353153693E-005,
251    -8.010193625184903E-004,
252    5.188327685732524E-003,
253    -2.685381193529856E-002,
254    1.128358514861418E-001,
255    -3.761262582423300E-001,
256    1.128379165726710E+000
257};
258
259
260float cephes_erfcf(float a)
261{
262    float MAXLOG = 88.72283905206835;
263    float p, q, x, y, z;
264
265
266    /*if (a < 0.0)
267        x = -a;
268    else
269        x = a;*/
270    // TODO: tinycc does not support fabsf
271    x = fabs(a);
272
273
274    if (x < 1.0) {
275        //The line below is a troublemaker for GPU, so sas_erf function
276        //is explicit here for the case < 1.0
277        //return (1.0 - sas_erf(a));
278        z = x * x;
279        y = x * polevl( z, TF, 6 );
280
281        return y;
282    }
283
284    z = -a * a;
285
286    if (z < -MAXLOG) {
287        if (a < 0)
288            return (2.0);
289        else
290            return (0.0);
291    }
292    z = expf(z);
293
294
295    q=1.0/x;
296    y=q*q;
297    if( x < 2.0 ) {
298        p = polevl( y, PF, 8 );
299    } else {
300        p = polevl( y, RF, 7 );
301    }
302    y = z * q * p;
303
304    if (a < 0)
305        y = 2.0 - y;
306
307    if (y == 0.0) {
308        if (a < 0)
309            return (2.0);
310        else
311            return (0.0);
312    }
313    return y;
314}
315
316
317float cephes_erff(float x)
318{
319    float y, z;
320
321    // TODO: tinycc does not support fabsf
322    if (fabs(x) > 1.0)
323        return (1.0 - cephes_erfcf(x));
324
325    z = x * x;
326    y = x * polevl( z, TF, 6 );
327
328    return y;
329}
330
331#endif // SINGLE_PRECISION
332
333#if FLOAT_SIZE>4
334//static double sas_erf(double x) { return erf(x); }
335//static double sas_erfc(double x) { return erfc(x); }
336#define sas_erf cephes_erf
337#define sas_erfc cephes_erfc
338#else
339#define sas_erf cephes_erff
340#define sas_erfc cephes_erfcf
341#endif
342
343#else // !NEED_ERF
344
345#if FLOAT_SIZE>4
346//static double sas_erf(double x) { return erf(x); }
347//static double sas_erfc(double x) { return erfc(x); }
348#define sas_erf erf
349#define sas_erfc erfc
350#else
351#define sas_erf erff
352#define sas_erfc erfcf
353#endif
354#endif // !NEED_ERF
Note: See TracBrowser for help on using the repository browser.