rubystats 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +7 -0
- data/Manifest.txt +22 -0
- data/README.txt +109 -0
- data/Rakefile +19 -0
- data/examples/beta.rb +10 -12
- data/examples/binomial.rb +12 -10
- data/examples/failrate_vs_goal.rb +28 -0
- data/examples/fisher.rb +2 -6
- data/examples/norm.rb +10 -4
- data/lib/rubystats.rb +9 -0
- data/lib/rubystats/beta_distribution.rb +88 -0
- data/lib/rubystats/binomial_distribution.rb +195 -0
- data/lib/rubystats/fishers_exact_test.rb +171 -0
- data/lib/rubystats/modules.rb +742 -0
- data/lib/rubystats/normal_distribution.rb +114 -0
- data/lib/rubystats/probability_distribution.rb +131 -0
- data/{tests → test}/tc_beta.rb +4 -4
- data/{tests → test}/tc_binomial.rb +4 -4
- data/{tests → test}/tc_fisher.rb +2 -2
- data/test/tc_norm.rb +14 -0
- data/test/tc_require_all.rb +18 -0
- data/{tests → test}/ts_stats.rb +0 -0
- metadata +72 -51
- data/README +0 -9
- data/lib/beta_distribution.rb +0 -87
- data/lib/binomial_distribution.rb +0 -194
- data/lib/fishers_exact_test.rb +0 -171
- data/lib/modules/extra_math.rb +0 -7
- data/lib/modules/numerical_constants.rb +0 -17
- data/lib/modules/special_math.rb +0 -721
- data/lib/normal_distribution.rb +0 -114
- data/lib/probability_distribution.rb +0 -132
- data/tests/tc_norm.rb +0 -13
@@ -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
|