rubystats 0.1.2 → 0.2.0

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