rubystats 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ module ExtraMath
2
+
3
+ def binomial (n, k)
4
+ return Math.exp(log_gamma(n + 1.0) - log_gamma(k + 1.0) - log_gamma(n - k + 1.0))
5
+ end
6
+
7
+ end
@@ -0,0 +1,17 @@
1
+ module NumericalConstants
2
+ Max_float = 3.40282346638528860e292
3
+ Eps = 2.22e-16
4
+ Max_value = 1.2e290
5
+ Log_gamma_x_max_value = 2.55e292
6
+ Gamma_x_max_value = 171.624
7
+ Sqrt2pi = 2.5066282746310005024157652848110452530069867406099
8
+ Sqrt2 = 1.4142135623730950488016887242096980785696718753769
9
+ Xminin = 2.23e-303
10
+ Max_iterations = 1000
11
+ Precision = 8.88e-016
12
+ Two_pi = 6.2831853071795864769252867665590057683943387987502
13
+ Gamma = 0.57721566490153286060651209008240243104215933593992
14
+ Golden_ratio = 1.6180339887498948482045868343656381177203091798058
15
+ end
16
+
17
+
@@ -0,0 +1,721 @@
1
+ require 'modules/numerical_constants'
2
+
3
+ # Ruby port of SpecialMath.php from PHPMath, which is
4
+ # a port of JSci methods found in SpecialMath.java.
5
+ #
6
+ #
7
+ # Ruby port by Bryan Donovan Bryan.Donovan@sun.com
8
+ #
9
+ # Author:: Jaco van Kooten
10
+ # Author:: Paul Meagher
11
+ # Author:: Bryan Donovan
12
+
13
+ module SpecialMath
14
+
15
+ include NumericalConstants
16
+
17
+ @logGammaCache_res = 0.0
18
+ @logGammaCache_x = 0.0
19
+ @logBetaCache_res = 0.0
20
+ @logBetaCache_p = 0.0
21
+ @logBetaCache_q = 0.0
22
+
23
+
24
+ def log_beta(p,q)
25
+ if p != @logBetaCache_p || q != @logBetaCache_q
26
+ logBetaCache_p = p
27
+ logBetaCache_q = q
28
+ if p <= 0.0 || q <= 0.0 || (p + q) > Log_gamma_x_max_value
29
+ logBetaCache_res = 0.0
30
+ else
31
+ logBetaCache_res = log_gamma(p) + log_gamma(q) - log_gamma(p + q)
32
+ end
33
+ return logBetaCache_res
34
+ end
35
+ end
36
+
37
+ # Gamma function.
38
+ # Based on public domain NETLIB (Fortran) code by W. J. Cody and L. Stoltz<BR>
39
+ # Applied Mathematics Division<BR>
40
+ # Argonne National Laboratory<BR>
41
+ # Argonne, IL 60439<BR>
42
+ # <P>
43
+ # References:
44
+ # <OL>
45
+ # <LI>"An Overview of Software Development for Special Functions", W. J. Cody, Lecture Notes in Mathematics, 506, Numerical Analysis Dundee, 1975, G. A. Watson (ed.), Springer Verlag, Berlin, 1976.
46
+ # <LI>Computer Approximations, Hart, Et. Al., Wiley and sons, New York, 1968.
47
+ # </OL></P><P>
48
+ # From the original documentation:
49
+ # </P><P>
50
+ # This routine calculates the GAMMA function for a real argument X.
51
+ # Computation is based on an algorithm outlined in reference 1.
52
+ # The program uses rational functions that approximate the GAMMA
53
+ # function to at least 20 significant decimal digits. Coefficients
54
+ # for the approximation over the interval (1,2) are unpublished.
55
+ # Those for the approximation for X .GE. 12 are from reference 2.
56
+ # The accuracy achieved depends on the arithmetic system, the
57
+ # compiler, the intrinsic functions, and proper selection of the
58
+ # machine-dependent constants.
59
+ # </P><P>
60
+ # Error returns:<BR>
61
+ # The program returns the value XINF for singularities or when overflow would occur.
62
+ # The computation is believed to be free of underflow and overflow.
63
+ # </P>
64
+ # Author:: Jaco van Kooten
65
+
66
+ def gamma(x)
67
+ # gamma related constants
68
+ g_p = [ -1.71618513886549492533811, 24.7656508055759199108314,
69
+ -379.804256470945635097577, 629.331155312818442661052,
70
+ 866.966202790413211295064, -31451.2729688483675254357,
71
+ -36144.4134186911729807069, 66456.1438202405440627855 ]
72
+ g_q = [-30.8402300119738975254353, 315.350626979604161529144,
73
+ -1015.15636749021914166146, -3107.77167157231109440444,
74
+ 22538.1184209801510330112, 4755.84627752788110767815,
75
+ -134659.959864969306392456, -115132.259675553483497211 ]
76
+ g_c = [-0.001910444077728, 8.4171387781295e-4, -5.952379913043012e-4,
77
+ 7.93650793500350248e-4, -0.002777777777777681622553,
78
+ 0.08333333333333333331554247, 0.0057083835261 ]
79
+ fact=1.0
80
+ i=0
81
+ n=0
82
+ y=x
83
+ parity=false
84
+ if y <= 0.0
85
+ # ----------------------------------------------------------------------
86
+ # Argument is negative
87
+ # ----------------------------------------------------------------------
88
+ y = -(x)
89
+ y1 = y.to_i
90
+ res = y - y1
91
+ if res != 0.0
92
+ if y1 != (((y1*0.5).to_i) * 2.0)
93
+ parity = true
94
+ fact = -M_pi/sin(M_pi * res)
95
+ y += 1
96
+ end
97
+ else
98
+ return Max_value
99
+ end
100
+ end
101
+
102
+ # ----------------------------------------------------------------------
103
+ # Argument is positive
104
+ # ----------------------------------------------------------------------
105
+ if y < Eps
106
+ # ----------------------------------------------------------------------
107
+ # Argument .LT. EPS
108
+ # ----------------------------------------------------------------------
109
+ if y >= Xminin
110
+ res = 1.0 / y
111
+ else
112
+ return Max_value
113
+ end
114
+ elsif y < 12.0
115
+ y1 = y
116
+ #end
117
+ if y < 1.0
118
+ # ----------------------------------------------------------------------
119
+ # 0.0 .LT. argument .LT. 1.0
120
+ # ----------------------------------------------------------------------
121
+ z = y
122
+ y += 1
123
+ else
124
+ # ----------------------------------------------------------------------
125
+ # 1.0 .LT. argument .LT. 12.0, reduce argument if necessary
126
+ # ----------------------------------------------------------------------
127
+ n = y.to_i - 1
128
+ y -= n.to_f
129
+ z = y - 1.0
130
+ end
131
+ # ----------------------------------------------------------------------
132
+ # Evaluate approximation for 1.0 .LT. argument .LT. 2.0
133
+ # ----------------------------------------------------------------------
134
+ xnum = 0.0
135
+ xden = 1.0
136
+ for i in (0...8)
137
+ xnum = (xnum + g_p[i]) * z
138
+ xden = xden * z + g_q[i]
139
+ end
140
+ res = xnum / xden + 1.0
141
+ if y1 < y
142
+ # ----------------------------------------------------------------------
143
+ # Adjust result for case 0.0 .LT. argument .LT. 1.0
144
+ # ----------------------------------------------------------------------
145
+ res /= y1
146
+ elsif y1 > y
147
+ # ----------------------------------------------------------------------
148
+ # Adjust result for case 2.0 .LT. argument .LT. 12.0
149
+ # ----------------------------------------------------------------------
150
+ for i in (0...n)
151
+ res *= y
152
+ y += 1
153
+ end
154
+ end
155
+ else
156
+ # ----------------------------------------------------------------------
157
+ # Evaluate for argument .GE. 12.0
158
+ # ----------------------------------------------------------------------
159
+ if y <= Gamma_x_max_value
160
+ ysq = y * y
161
+ sum = g_c[6]
162
+ for i in(0...6)
163
+ sum = sum / ysq + g_c[i]
164
+ sum = sum / y - y + log(sqrt2pi)
165
+ sum += (y - 0.5) * log(y)
166
+ res = Math.exp(sum)
167
+ end
168
+ else
169
+ return Max_value
170
+ end
171
+ # ----------------------------------------------------------------------
172
+ # Final adjustments and return
173
+ # ----------------------------------------------------------------------
174
+ if parity
175
+ res = -res
176
+ if fact != 1.0
177
+ res = fact / res
178
+ return res
179
+ end
180
+ end
181
+ end
182
+ end
183
+
184
+ def log_gamma(x)
185
+ logGammaCache_res = @logGammaCache_res
186
+ logGammaCache_x = @logGammaCache_x
187
+
188
+ lg_d1 = -0.5772156649015328605195174
189
+ lg_d2 = 0.4227843350984671393993777
190
+ lg_d4 = 1.791759469228055000094023
191
+
192
+ lg_p1 = [ 4.945235359296727046734888,
193
+ 201.8112620856775083915565, 2290.838373831346393026739,
194
+ 11319.67205903380828685045, 28557.24635671635335736389,
195
+ 38484.96228443793359990269, 26377.48787624195437963534,
196
+ 7225.813979700288197698961 ]
197
+
198
+ lg_p2 = [ 4.974607845568932035012064,
199
+ 542.4138599891070494101986, 15506.93864978364947665077,
200
+ 184793.2904445632425417223, 1088204.76946882876749847,
201
+ 3338152.967987029735917223, 5106661.678927352456275255,
202
+ 3074109.054850539556250927 ]
203
+
204
+ lg_p4 = [ 14745.02166059939948905062,
205
+ 2426813.369486704502836312, 121475557.4045093227939592,
206
+ 2663432449.630976949898078, 29403789566.34553899906876,
207
+ 170266573776.5398868392998, 492612579337.743088758812,
208
+ 560625185622.3951465078242 ]
209
+
210
+ lg_q1 = [ 67.48212550303777196073036,
211
+ 1113.332393857199323513008, 7738.757056935398733233834,
212
+ 27639.87074403340708898585, 54993.10206226157329794414,
213
+ 61611.22180066002127833352, 36351.27591501940507276287,
214
+ 8785.536302431013170870835 ]
215
+
216
+ lg_q2 = [ 183.0328399370592604055942,
217
+ 7765.049321445005871323047, 133190.3827966074194402448,
218
+ 1136705.821321969608938755, 5267964.117437946917577538,
219
+ 13467014.54311101692290052, 17827365.30353274213975932,
220
+ 9533095.591844353613395747 ]
221
+
222
+ lg_q4 = [ 2690.530175870899333379843,
223
+ 639388.5654300092398984238, 41355999.30241388052042842,
224
+ 1120872109.61614794137657, 14886137286.78813811542398,
225
+ 101680358627.2438228077304, 341747634550.7377132798597,
226
+ 446315818741.9713286462081 ]
227
+
228
+ lg_c = [ -0.001910444077728,8.4171387781295e-4,
229
+ -5.952379913043012e-4, 7.93650793500350248e-4,
230
+ -0.002777777777777681622553, 0.08333333333333333331554247,
231
+ 0.0057083835261 ]
232
+
233
+ # Rough estimate of the fourth root of logGamma_xBig
234
+ lg_frtbig = 2.25e76
235
+ pnt68 = 0.6796875
236
+
237
+ if x == logGammaCache_x
238
+ return logGammaCache_res
239
+ end
240
+
241
+ y = x
242
+ if y > 0.0 && y <= Log_gamma_x_max_value
243
+ if y <= Eps
244
+ res = -Math.log(y)
245
+ elsif y <= 1.5
246
+ # EPS .LT. X .LE. 1.5
247
+ if y < pnt68
248
+ corr = -Math.log(y)
249
+ # xm1 is x-m-one, not x-m-L
250
+ xm1 = y
251
+ else
252
+ corr = 0.0
253
+ xm1 = y - 1.0
254
+ end
255
+ if y <= 0.5 || y >= pnt68
256
+ xden = 1.0
257
+ xnum = 0.0
258
+ for i in (0...8)
259
+ xnum = xnum * xm1 + lg_p1[i]
260
+ xden = xden * xm1 + lg_q1[i]
261
+ end
262
+ res = corr * xm1 * (lg_d1 + xm1 * (xnum / xden))
263
+ else
264
+ xm2 = y - 1.0
265
+ xden = 1.0
266
+ xnum = 0.0
267
+ for i in (0 ... 8)
268
+ xnum = xnum * xm2 + lg_p2[i]
269
+ xden = xden * xm2 + lg_q2[i]
270
+ end
271
+ res = corr + xm2 * (lg_d2 + xm2 * (xnum / xden))
272
+ end
273
+ elsif y <= 4.0
274
+ # 1.5 .LT. X .LE. 4.0
275
+ xm2 = y - 2.0
276
+ xden = 1.0
277
+ xnum = 0.0
278
+ for i in (0 ... 8)
279
+ xnum = xnum * xm2 + lg_p2[i]
280
+ xden = xden * xm2 + lg_q2[i]
281
+ end
282
+ res = xm2 * (lg_d2 + xm2 * (xnum / xden))
283
+ elsif y <= 12.0
284
+ # 4.0 .LT. X .LE. 12.0
285
+ xm4 = y - 4.0
286
+ xden = -1.0
287
+ xnum = 0.0
288
+ for i in (0 ... 8)
289
+ xnum = xnum * xm4 + lg_p4[i]
290
+ xden = xden * xm4 + lg_q4[i]
291
+ end
292
+ res = lg_d4 + xm4 * (xnum / xden)
293
+ else
294
+ # Evaluate for argument .GE. 12.0
295
+ res = 0.0
296
+ if y <= lg_frtbig
297
+ res = lg_c[6]
298
+ ysq = y * y
299
+ for i in (0...6)
300
+ res = res / ysq + lg_c[i]
301
+ end
302
+ end
303
+ res = res/y
304
+ corr = Math.log(y)
305
+ res = res + Math.log(Sqrt2pi) - 0.5 * corr
306
+ res = res + y * (corr - 1.0)
307
+ end
308
+ else
309
+ #return for bad arguments
310
+ res = Max_value
311
+ end
312
+ # final adjustments and return
313
+ logGammaCache_x = x
314
+ logGammaCache_res = res
315
+ return res
316
+ end
317
+
318
+
319
+ # Incomplete gamma function.
320
+ # The computation is based on approximations presented in
321
+ # Numerical Recipes, Chapter 6.2 (W.H. Press et al, 1992).
322
+ # @param a require a>=0
323
+ # @param x require x>=0
324
+ # @return 0 if x<0, a<=0 or a>2.55E305 to avoid errors and over/underflow
325
+ # @author Jaco van Kooten
326
+
327
+ def incomplete_gamma(a, x)
328
+ if x <= 0.0 || a <= 0.0 || a > Log_gamma_x_max_value
329
+ return 0.0
330
+ elsif x < (a + 1.0)
331
+ return gamma_series_expansion(a, x)
332
+ else
333
+ return 1.0-gamma_fraction(a, x)
334
+ end
335
+ end
336
+
337
+ # Author:: Jaco van Kooten
338
+ def gamma_series_expansion(a, x)
339
+ ap = a
340
+ del = 1.0 / a
341
+ sum = del
342
+ for n in (1...Max_iterations)
343
+ ap += 1
344
+ del *= x / ap
345
+ sum += del
346
+ if del < sum * Precision
347
+ return sum * Math.exp(-x + a * Math.log(x) - log_gamma(a))
348
+ end
349
+ end
350
+ return "Maximum iterations exceeded: please file a bug report."
351
+ end
352
+
353
+ # Author:: Jaco van Kooten
354
+ def gamma_fraction(a, x)
355
+ b = x + 1.0 - a
356
+ c = 1.0 / Xminin
357
+ d = 1.0 / b
358
+ h = d
359
+ del= 0.0
360
+ an = 0.0
361
+ for i in (1...Max_iterations)
362
+ if (del-1.0).abs > Precision
363
+ an = -i * (i - a)
364
+ b += 2.0
365
+ d = an * d + b
366
+ c = b + an / c
367
+ if c.abs < Xminin
368
+ c = Xminin
369
+ if d.abs < Xminin
370
+ c = Xminin
371
+ d = 1.0 / d
372
+ del = d * c
373
+ h *= del
374
+ end
375
+ end
376
+ end
377
+ return Math.exp(-x + a * Math.log(x) - log_gamma(a)) * h
378
+ end
379
+ end
380
+
381
+ # Beta function.
382
+ #
383
+ # Author:: Jaco van Kooten
384
+
385
+ def beta(p, q)
386
+ if p <= 0.0 || q <= 0.0 || (p + q) > Log_gamma_x_max_value
387
+ return 0.0
388
+ else
389
+ return Math.exp(log_beta(p, q))
390
+ end
391
+ end
392
+
393
+ # Incomplete Beta function.
394
+ #
395
+ # Author:: Jaco van Kooten
396
+ # Author:: Paul Meagher
397
+ #
398
+ # The computation is based on formulas from Numerical Recipes,
399
+ # Chapter 6.4 (W.H. Press et al, 1992).
400
+
401
+ def incomplete_beta(x, p, q)
402
+ if x <= 0.0
403
+ return 0.0
404
+ elsif x >= 1.0
405
+ return 1.0
406
+ elsif p <= 0.0 || q <= 0.0 || (p + q) > Log_gamma_x_max_value
407
+ return 0.0
408
+ else
409
+ beta_gam = Math.exp( -log_beta(p, q) + p * Math.log(x) + q * Math.log(1.0 - x) )
410
+ if x < (p + 1.0) / (p + q + 2.0)
411
+ return beta_gam * beta_fraction(x, p, q) / p
412
+ else
413
+ beta_frac = beta_fraction(1.0 - x, p, q)
414
+ return 1.0 - (beta_gam * beta_fraction(1.0 - x, q, p) / q)
415
+ end
416
+ end
417
+ end
418
+
419
+
420
+ # Evaluates of continued fraction part of incomplete beta function.
421
+ # Based on an idea from Numerical Recipes (W.H. Press et al, 1992).
422
+ # Author:: Jaco van Kooten
423
+
424
+ def beta_fraction(x, p, q)
425
+ c = 1.0
426
+ sum_pq = p + q
427
+ p_plus = p + 1.0
428
+ p_minus = p - 1.0
429
+ h = 1.0 - sum_pq * x / p_plus
430
+ if h.abs < Xminin
431
+ h = Xminin
432
+ end
433
+ h = 1.0 / h
434
+ frac = h
435
+ m = 1
436
+ delta = 0.0
437
+
438
+ while (m <= Max_iterations) && ((delta - 1.0).abs > Precision)
439
+ m2 = 2 * m
440
+ # even index for d
441
+ d = m * (q - m) * x / ( (p_minus + m2) * (p + m2))
442
+ h = 1.0 + d * h
443
+ if h.abs < Xminin
444
+ h = Xminin
445
+ end
446
+ h = 1.0 / h
447
+ c = 1.0 + d / c
448
+ if c.abs < Xminin
449
+ c = Xminin
450
+ end
451
+ frac *= h * c
452
+ # odd index for d
453
+ d = -(p + m) * (sum_pq + m) * x / ((p + m2) * (p_plus + m2))
454
+ h = 1.0 + d * h
455
+ if h.abs < Xminin
456
+ h = Xminin
457
+ end
458
+ h = 1.0 / h
459
+ c = 1.0 + d / c
460
+ if c.abs < Xminin
461
+ c = Xminin
462
+ end
463
+ delta = h * c
464
+ frac *= delta
465
+ m += 1
466
+ end
467
+ return frac
468
+ end
469
+
470
+
471
+
472
+ # Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
473
+ #
474
+ # Developed at SunSoft, a Sun Microsystems, Inc. business.
475
+ # Permission to use, copy, modify, and distribute this
476
+ # software is freely granted, provided that this notice
477
+ # is preserved.
478
+ #
479
+ # x
480
+ # 2 |\
481
+ # erf(x) = --------- | exp(-t*t)dt
482
+ # sqrt(pi) \|
483
+ # 0
484
+ #
485
+ # erfc(x) = 1-erf(x)
486
+ # Note that
487
+ # erf(-x) = -erf(x)
488
+ # erfc(-x) = 2 - erfc(x)
489
+ #
490
+ # Method:
491
+ # 1. For |x| in [0, 0.84375]
492
+ # erf(x) = x + x*R(x^2)
493
+ # erfc(x) = 1 - erf(x) if x in [-.84375,0.25]
494
+ # = 0.5 + ((0.5-x)-x*R) if x in [0.25,0.84375]
495
+ # where R = P/Q where P is an odd poly of degree 8 and
496
+ # Q is an odd poly of degree 10.
497
+ # -57.90
498
+ # | R - (erf(x)-x)/x | <= 2
499
+ #
500
+ #
501
+ # Remark. The formula is derived by noting
502
+ # erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....)
503
+ # and that
504
+ # 2/sqrt(pi) = 1.128379167095512573896158903121545171688
505
+ # is close to one. The interval is chosen because the fix
506
+ # point of erf(x) is near 0.6174 (i.e., erf(x)=x when x is
507
+ # near 0.6174), and by some experiment, 0.84375 is chosen to
508
+ # guarantee the error is less than one ulp for erf.
509
+ #
510
+ # 2. For |x| in [0.84375,1.25], let s = |x| - 1, and
511
+ # c = 0.84506291151 rounded to single (24 bits)
512
+ # erf(x) = sign(x) * (c + P1(s)/Q1(s))
513
+ # erfc(x) = (1-c) - P1(s)/Q1(s) if x > 0
514
+ # 1+(c+P1(s)/Q1(s)) if x < 0
515
+ # |P1/Q1 - (erf(|x|)-c)| <= 2**-59.06
516
+ # Remark: here we use the taylor series expansion at x=1.
517
+ # erf(1+s) = erf(1) + s*Poly(s)
518
+ # = 0.845.. + P1(s)/Q1(s)
519
+ # That is, we use rational approximation to approximate
520
+ # erf(1+s) - (c = (single)0.84506291151)
521
+ # Note that |P1/Q1|< 0.078 for x in [0.84375,1.25]
522
+ # where
523
+ # P1(s) = degree 6 poly in s
524
+ # Q1(s) = degree 6 poly in s
525
+ #
526
+ # 3. For x in [1.25,1/0.35(~2.857143)],
527
+ # erfc(x) = (1/x)*exp(-x*x-0.5625+R1/S1)
528
+ # erf(x) = 1 - erfc(x)
529
+ # where
530
+ # R1(z) = degree 7 poly in z, (z=1/x^2)
531
+ # S1(z) = degree 8 poly in z
532
+ #
533
+ # 4. For x in [1/0.35,28]
534
+ # erfc(x) = (1/x)*exp(-x*x-0.5625+R2/S2) if x > 0
535
+ # = 2.0 - (1/x)*exp(-x*x-0.5625+R2/S2) if -6<x<0
536
+ # = 2.0 - tiny (if x <= -6)
537
+ # erf(x) = sign(x)*(1.0 - erfc(x)) if x < 6, else
538
+ # erf(x) = sign(x)*(1.0 - tiny)
539
+ # where
540
+ # R2(z) = degree 6 poly in z, (z=1/x^2)
541
+ # S2(z) = degree 7 poly in z
542
+ #
543
+ # Note1:
544
+ # To compute exp(-x*x-0.5625+R/S), let s be a single
545
+ # precision number and s := x then
546
+ # -x*x = -s*s + (s-x)*(s+x)
547
+ # exp(-x*x-0.5626+R/S) =
548
+ # exp(-s*s-0.5625)*exp((s-x)*(s+x)+R/S)
549
+ # Note2:
550
+ # Here 4 and 5 make use of the asymptotic series
551
+ # exp(-x*x)
552
+ # erfc(x) ~ ---------- * ( 1 + Poly(1/x^2) )
553
+ # x*sqrt(pi)
554
+ # We use rational approximation to approximate
555
+ # g(s)=f(1/x^2) = log(erfc(x)*x) - x*x + 0.5625
556
+ # Here is the error bound for R1/S1 and R2/S2
557
+ # |R1/S1 - f(x)| < 2**(-62.57)
558
+ # |R2/S2 - f(x)| < 2**(-61.52)
559
+ #
560
+ # 5. For inf > x >= 28
561
+ # erf(x) = sign(x) *(1 - tiny) (raise inexact)
562
+ # erfc(x) = tiny*tiny (raise underflow) if x > 0
563
+ # = 2 - tiny if x<0
564
+ #
565
+ # 7. Special case:
566
+ # erf(0) = 0, erf(inf) = 1, erf(-inf) = -1,
567
+ # erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2,
568
+ # erfc/erf(NaN) is NaN
569
+ #
570
+ # $efx8 = 1.02703333676410069053e00
571
+ #
572
+ # Coefficients for approximation to erf on [0,0.84375]
573
+ #
574
+
575
+ # Error function.
576
+ # Based on C-code for the error function developed at Sun Microsystems.
577
+ # Author:: Jaco van Kooten
578
+
579
+ def error(x)
580
+ e_efx = 1.28379167095512586316e-01
581
+
582
+ ePp = [ 1.28379167095512558561e-01,
583
+ -3.25042107247001499370e-01,
584
+ -2.84817495755985104766e-02,
585
+ -5.77027029648944159157e-03,
586
+ -2.37630166566501626084e-05 ]
587
+
588
+ eQq = [ 3.97917223959155352819e-01,
589
+ 6.50222499887672944485e-02,
590
+ 5.08130628187576562776e-03,
591
+ 1.32494738004321644526e-04,
592
+ -3.96022827877536812320e-06 ]
593
+
594
+ # Coefficients for approximation to erf in [0.84375,1.25]
595
+ ePa = [-2.36211856075265944077e-03,
596
+ 4.14856118683748331666e-01,
597
+ -3.72207876035701323847e-01,
598
+ 3.18346619901161753674e-01,
599
+ -1.10894694282396677476e-01,
600
+ 3.54783043256182359371e-02,
601
+ -2.16637559486879084300e-03 ]
602
+
603
+ eQa = [ 1.06420880400844228286e-01,
604
+ 5.40397917702171048937e-01,
605
+ 7.18286544141962662868e-02,
606
+ 1.26171219808761642112e-01,
607
+ 1.36370839120290507362e-02,
608
+ 1.19844998467991074170e-02 ]
609
+
610
+ e_erx = 8.45062911510467529297e-01
611
+
612
+ abs_x = (if x >= 0.0 then x else -x end)
613
+ # 0 < |x| < 0.84375
614
+ if abs_x < 0.84375
615
+ #|x| < 2**-28
616
+ if abs_x < 3.7252902984619141e-9
617
+ retval = abs_x + abs_x * e_efx
618
+ else
619
+ s = x * x
620
+ p = ePp[0] + s * (ePp[1] + s * (ePp[2] + s * (ePp[3] + s * ePp[4])))
621
+
622
+ q = 1.0 + s * (eQq[0] + s * (eQq[1] + s *
623
+ ( eQq[2] + s * (eQq[3] + s * eQq[4]))))
624
+ retval = abs_x + abs_x * (p / q)
625
+ end
626
+ elsif abs_x < 1.25
627
+ s = abs_x - 1.0
628
+ p = ePa[0] + s * (ePa[1] + s *
629
+ (ePa[2] + s * (ePa[3] + s *
630
+ (ePa[4] + s * (ePa[5] + s * ePa[6])))))
631
+
632
+ q = 1.0 + s * (eQa[0] + s *
633
+ (eQa[1] + s * (eQa[2] + s *
634
+ (eQa[3] + s * (eQa[4] + s * eQa[5])))))
635
+ retval = e_erx + p / q
636
+
637
+ elsif abs_x >= 6.0
638
+ retval = 1.0
639
+ else
640
+ retval = 1.0 - complementary_error(abs_x)
641
+ end
642
+ return (if x >= 0.0 then retval else -retval end)
643
+ end
644
+
645
+ # Complementary error function.
646
+ # Based on C-code for the error function developed at Sun Microsystems.
647
+ # author Jaco van Kooten
648
+
649
+ def complementary_error(x)
650
+ # Coefficients for approximation of erfc in [1.25,1/.35]
651
+
652
+ eRa = [-9.86494403484714822705e-03,
653
+ -6.93858572707181764372e-01,
654
+ -1.05586262253232909814e01,
655
+ -6.23753324503260060396e01,
656
+ -1.62396669462573470355e02,
657
+ -1.84605092906711035994e02,
658
+ -8.12874355063065934246e01,
659
+ -9.81432934416914548592e00 ]
660
+
661
+ eSa = [ 1.96512716674392571292e01,
662
+ 1.37657754143519042600e02,
663
+ 4.34565877475229228821e02,
664
+ 6.45387271733267880336e02,
665
+ 4.29008140027567833386e02,
666
+ 1.08635005541779435134e02,
667
+ 6.57024977031928170135e00,
668
+ -6.04244152148580987438e-02 ]
669
+
670
+ # Coefficients for approximation to erfc in [1/.35,28]
671
+
672
+ eRb = [-9.86494292470009928597e-03,
673
+ -7.99283237680523006574e-01,
674
+ -1.77579549177547519889e01,
675
+ -1.60636384855821916062e02,
676
+ -6.37566443368389627722e02,
677
+ -1.02509513161107724954e03,
678
+ -4.83519191608651397019e02 ]
679
+
680
+ eSb = [ 3.03380607434824582924e01,
681
+ 3.25792512996573918826e02,
682
+ 1.53672958608443695994e03,
683
+ 3.19985821950859553908e03,
684
+ 2.55305040643316442583e03,
685
+ 4.74528541206955367215e02,
686
+ -2.24409524465858183362e01 ]
687
+
688
+ abs_x = (if x >= 0.0 then x else -x end)
689
+ if abs_x < 1.25
690
+ retval = 1.0 - error(abs_x)
691
+ elsif abs_x > 28.0
692
+ retval = 0.0
693
+
694
+ # 1.25 < |x| < 28
695
+ else
696
+ s = 1.0/(abs_x * abs_x)
697
+ if abs_x < 2.8571428
698
+ r = eRa[0] + s * (eRa[1] + s *
699
+ (eRa[2] + s * (eRa[3] + s * (eRa[4] + s *
700
+ (eRa[5] + s *(eRa[6] + s * eRa[7])
701
+ )))))
702
+
703
+ s = 1.0 + s * (eSa[0] + s * (eSa[1] + s *
704
+ (eSa[2] + s * (eSa[3] + s * (eSa[4] + s *
705
+ (eSa[5] + s * (eSa[6] + s * eSa[7])))))))
706
+
707
+ else
708
+ r = eRb[0] + s * (eRb[1] + s *
709
+ (eRb[2] + s * (eRb[3] + s * (eRb[4] + s *
710
+ (eRb[5] + s * eRb[6])))))
711
+
712
+ s = 1.0 + s * (eSb[0] + s *
713
+ (eSb[1] + s * (eSb[2] + s * (eSb[3] + s *
714
+ (eSb[4] + s * (eSb[5] + s * eSb[6]))))))
715
+ end
716
+ retval = Math.exp(-x * x - 0.5625 + r/s) / abs_x
717
+ end
718
+ return ( if x >= 0.0 then retval else 2.0 - retval end )
719
+ end
720
+ end
721
+