distribution 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/History.txt +8 -0
- data/Manifest.txt +7 -1
- data/README.txt +3 -3
- data/benchmark/factorial_method.rb +25 -0
- data/lib/distribution.rb +2 -2
- data/lib/distribution/binomial.rb +26 -0
- data/lib/distribution/f.rb +1 -1
- data/lib/distribution/hypergeometric.rb +37 -0
- data/lib/distribution/hypergeometric/gsl.rb +17 -0
- data/lib/distribution/hypergeometric/ruby.rb +69 -0
- data/lib/distribution/math_extension.rb +144 -8
- data/lib/distribution/t.rb +1 -1
- data/spec/hypergeometric_spec.rb +77 -0
- data/spec/math_extension_spec.rb +42 -0
- data/spec/shorthand_spec.rb +9 -3
- metadata +10 -4
- metadata.gz.sig +3 -1
- data/spec/shorthand_function.rb +0 -6
data.tar.gz.sig
CHANGED
Binary file
|
data/History.txt
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
=== 0.2.0 / 2011-01-27
|
2
|
+
* Shorthands for F and T are 'fdist' and 'tdist' now, to avoid confussions
|
3
|
+
* Added Hypergeometric distribution with pdf, cdf, p_value. The Ruby version uses a very slow factorial process, but also has pdf_with_stirling if you don't care about accuracy at all. This latter method needs to be improved, actually, in terms of which choose function it calls for the numerator and denominator. Once that's done, it can replace the slower pdf function. [John Woods]
|
4
|
+
* Spec for cdf and p_value of Hypergeometric
|
5
|
+
* New cdf and p_value on Hypergeometric[clbustos]
|
6
|
+
* Hypergeometric#pdf returns 0 on max(0,n+m-t)<=k<=min(m,n)
|
7
|
+
* Improved factorial calculation, using Luschny algorithms
|
8
|
+
|
1
9
|
=== 0.1.0 / 2011-01-26
|
2
10
|
|
3
11
|
* Basic set (pdf, cdf, p_value) for Normal, Chi Square, F and T distributions
|
data/Manifest.txt
CHANGED
@@ -3,8 +3,10 @@ History.txt
|
|
3
3
|
Manifest.txt
|
4
4
|
README.txt
|
5
5
|
Rakefile
|
6
|
+
benchmark/factorial_method.rb
|
6
7
|
bin/distribution
|
7
8
|
lib/distribution.rb
|
9
|
+
lib/distribution/binomial.rb
|
8
10
|
lib/distribution/bivariatenormal.rb
|
9
11
|
lib/distribution/bivariatenormal/gsl.rb
|
10
12
|
lib/distribution/bivariatenormal/ruby.rb
|
@@ -17,6 +19,9 @@ lib/distribution/f.rb
|
|
17
19
|
lib/distribution/f/gsl.rb
|
18
20
|
lib/distribution/f/ruby.rb
|
19
21
|
lib/distribution/f/statistics2.rb
|
22
|
+
lib/distribution/hypergeometric.rb
|
23
|
+
lib/distribution/hypergeometric/gsl.rb
|
24
|
+
lib/distribution/hypergeometric/ruby.rb
|
20
25
|
lib/distribution/math_extension.rb
|
21
26
|
lib/distribution/normal.rb
|
22
27
|
lib/distribution/normal/gsl.rb
|
@@ -31,8 +36,9 @@ spec/bivariatenormal_spec.rb
|
|
31
36
|
spec/chisquare_spec.rb
|
32
37
|
spec/distribution_spec.rb
|
33
38
|
spec/f_spec.rb
|
39
|
+
spec/hypergeometric_spec.rb
|
40
|
+
spec/math_extension_spec.rb
|
34
41
|
spec/normal_spec.rb
|
35
|
-
spec/shorthand_function.rb
|
36
42
|
spec/shorthand_spec.rb
|
37
43
|
spec/spec.opts
|
38
44
|
spec/spec_helper.rb
|
data/README.txt
CHANGED
@@ -0,0 +1,25 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)+"/../lib")
|
2
|
+
require 'distribution'
|
3
|
+
require 'bench_press'
|
4
|
+
|
5
|
+
extend BenchPress
|
6
|
+
|
7
|
+
name 'aprox vs exact factorization method'
|
8
|
+
author 'Claudio Bustos'
|
9
|
+
date '2011-01-27'
|
10
|
+
summary "
|
11
|
+
Factorization requires a lot of processing, so approximation method are required. But for greats value, bigdecimal are required and our
|
12
|
+
"
|
13
|
+
|
14
|
+
reps 10 #number of repetitions
|
15
|
+
|
16
|
+
x=200
|
17
|
+
|
18
|
+
measure "Math.factorial(#{x})" do
|
19
|
+
Math.factorial(x)
|
20
|
+
end
|
21
|
+
|
22
|
+
measure "Math.fast_factorial(#{x})" do
|
23
|
+
Math.fast_factorial(x)
|
24
|
+
end
|
25
|
+
|
data/lib/distribution.rb
CHANGED
@@ -48,7 +48,7 @@ require 'distribution/math_extension'
|
|
48
48
|
# Distribution::Normal.p_value(0.95)
|
49
49
|
# => 1.64485364660836
|
50
50
|
module Distribution
|
51
|
-
VERSION="0.
|
51
|
+
VERSION="0.2.0"
|
52
52
|
|
53
53
|
module Shorthand
|
54
54
|
EQUIVALENCES={:p_value=>:p, :cdf=>:cdf, :pdf=>:pdf, :rng=>:r}
|
@@ -120,7 +120,6 @@ module Distribution
|
|
120
120
|
end
|
121
121
|
# Add method to Distribution::Shorthand
|
122
122
|
sh=const_get(:SHORTHAND)
|
123
|
-
|
124
123
|
Distribution::Shorthand.add_shortcut(sh,m) do |*args|
|
125
124
|
l.send(m,*args)
|
126
125
|
end
|
@@ -142,6 +141,7 @@ module Distribution
|
|
142
141
|
autoload(:T, 'distribution/t')
|
143
142
|
autoload(:F, 'distribution/f')
|
144
143
|
autoload(:BivariateNormal, 'distribution/bivariatenormal')
|
144
|
+
autoload(:Hypergeometric, 'distribution/hypergeometric')
|
145
145
|
end
|
146
146
|
|
147
147
|
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'distribution/binomial/ruby'
|
2
|
+
require 'distribution/binomial/gsl'
|
3
|
+
module Distribution
|
4
|
+
|
5
|
+
# Calculate statisticals for T Distribution.
|
6
|
+
module T
|
7
|
+
SHORTHAND='bino'
|
8
|
+
extend Distributable
|
9
|
+
create_distribution_methods
|
10
|
+
|
11
|
+
##
|
12
|
+
# :singleton-method: pdf(x,k)
|
13
|
+
# Returns the integral of T distribution
|
14
|
+
# with +k+ degrees of freedom over [0, +x+]
|
15
|
+
|
16
|
+
##
|
17
|
+
# :singleton-method: p_value(qn, k)
|
18
|
+
# Return the P-value of the corresponding integral +qn+ with
|
19
|
+
# +k+ degrees of freedom
|
20
|
+
|
21
|
+
##
|
22
|
+
# :singleton-method: cdf(x,k)
|
23
|
+
# Returns the integral of T distribution
|
24
|
+
# with +k+ degrees of freedom over [0, +x+]
|
25
|
+
end
|
26
|
+
end
|
data/lib/distribution/f.rb
CHANGED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'distribution/hypergeometric/ruby'
|
2
|
+
require 'distribution/hypergeometric/gsl'
|
3
|
+
|
4
|
+
module Distribution
|
5
|
+
# From Wikipedia:
|
6
|
+
# In probability theory and statistics, the hypergeometric distribution is a discrete probability distribution that
|
7
|
+
# describes the number of successes in a sequence of n draws from a finite population without replacement, just as
|
8
|
+
# the binomial distribution describes the number of successes for draws with replacement.
|
9
|
+
module Hypergeometric
|
10
|
+
SHORTHAND='hypg'
|
11
|
+
extend Distributable
|
12
|
+
|
13
|
+
create_distribution_methods
|
14
|
+
|
15
|
+
##
|
16
|
+
# :singleton-method: pdf(k,m,n,total)
|
17
|
+
# This function computes the probability p(k) of obtaining k
|
18
|
+
# from a hypergeometric distribution with parameters
|
19
|
+
# m, n t.
|
20
|
+
# * m: number of elements with desired attribute on population
|
21
|
+
# * n: sample size
|
22
|
+
# * t: population size
|
23
|
+
|
24
|
+
##
|
25
|
+
# :singleton-method: cdf(k,m,n,total)
|
26
|
+
# These functions compute the cumulative distribution function P(k)
|
27
|
+
# for the hypergeometric distribution with parameters m, n and t.
|
28
|
+
# * m: number of elements with desired attribute on population
|
29
|
+
# * n: sample size
|
30
|
+
# * t: population size
|
31
|
+
|
32
|
+
|
33
|
+
##
|
34
|
+
# :singleton-method: p_value(k,m,n,total)
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Distribution
|
2
|
+
module Hypergeometric
|
3
|
+
module GSL_
|
4
|
+
class << self
|
5
|
+
def pdf(k, m, n, total) # :nodoc:
|
6
|
+
GSL::Ran::hypergeometric_pdf(k, m, total-m, n)
|
7
|
+
end
|
8
|
+
# The GSL::Cdf function for hypergeometric is broken:
|
9
|
+
#
|
10
|
+
def cdf_broken(k, m, n, total) # :nodoc:
|
11
|
+
GSL::Cdf::hypergeometric_P(k, m, total-m, n)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# Added by John O. Woods, SciRuby project.
|
2
|
+
|
3
|
+
# Extensions to Fixnum for Hypergeometric calculations in pure Ruby.
|
4
|
+
# ==Reference
|
5
|
+
# * http://bluebones.net/2007/09/combinatorics-in-ruby/
|
6
|
+
# * http://mathworld.wolfram.com/StirlingsApproximation.html
|
7
|
+
class Fixnum
|
8
|
+
# +k+-combination of a set of size +self+
|
9
|
+
def choose(k)
|
10
|
+
Math.factorial(self) / (Math.factorial(k) * Math.factorial(self - k))
|
11
|
+
end
|
12
|
+
|
13
|
+
# Fast combination calculation using Gosper's approximation of factorials.
|
14
|
+
def fast_choose(k)
|
15
|
+
Math.fast_factorial(self).quo(Math.fast_factorial(self - k) * Math.fast_factorial(k))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module Distribution
|
20
|
+
module Hypergeometric
|
21
|
+
module Ruby_
|
22
|
+
class << self
|
23
|
+
# Calculates PDF quickly. Not guaranteed to produce any accuracy, since it uses Stirling's approximation.
|
24
|
+
# This can be improved, most likely, by writing specific cases of when to use fast_choose and when to use
|
25
|
+
# choose.
|
26
|
+
def pdf_aprox(k, m, n, total)
|
27
|
+
m.fast_choose(k) * (total-m).fast_choose(n-k).quo( total.fast_choose(n))
|
28
|
+
end
|
29
|
+
|
30
|
+
# Hypergeometric probability density function
|
31
|
+
#
|
32
|
+
# Probability p(+k+, +m+, +n+, +total+) of drawing sets of size +m+ and +n+ with an intersection of size +k+
|
33
|
+
# from a total pool of size +total+, without replacement.
|
34
|
+
#
|
35
|
+
# ==References
|
36
|
+
# * http://www.gnu.org/software/gsl/manual/html_node/The-Hypergeometric-Distribution.html
|
37
|
+
# * http://en.wikipedia.org/wiki/Hypergeometric_distribution
|
38
|
+
def pdf(k, m, n, total)
|
39
|
+
min_m_n=m<n ? m : n
|
40
|
+
max_t=[0,m+n-total].max
|
41
|
+
return 0 if k>min_m_n or k<max_t
|
42
|
+
m.choose(k) * (total-m).choose(n-k) / total.choose(n).to_f
|
43
|
+
end
|
44
|
+
|
45
|
+
# p-value:
|
46
|
+
|
47
|
+
def p_value(pr, m, n, total)
|
48
|
+
ac=0
|
49
|
+
(0..total).each do |i|
|
50
|
+
ac+=pdf(i,m,n,total)
|
51
|
+
return i if ac>=pr
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Cumulative distribution function.
|
56
|
+
# The probability of obtain, from a sample of
|
57
|
+
# size +n+, +k+ or less elements
|
58
|
+
# in a population size +total+ with +m+ interesting elements.
|
59
|
+
#
|
60
|
+
# Slow, but secure
|
61
|
+
def cdf(k, m, n, total)
|
62
|
+
raise "k>m" if k>m
|
63
|
+
raise "k>n" if k>n
|
64
|
+
(0..k).collect { |ki| pdf(ki,m,n,total) }.inject { |sum,v| sum+v}
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -1,13 +1,149 @@
|
|
1
|
+
require 'prime'
|
2
|
+
require 'bigdecimal'
|
3
|
+
require 'bigdecimal/math'
|
4
|
+
|
1
5
|
# Useful additions to Math
|
2
6
|
module Distribution
|
3
7
|
module MathExtension
|
4
|
-
#
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
8
|
+
# Factorization based on Prime Swing algorithm, by Luschny (the king of factorial numbers analysis :P )
|
9
|
+
# == Reference
|
10
|
+
# * The Homepage of Factorial Algorithms. (C) Peter Luschny, 2000-2010
|
11
|
+
# == URL: http://www.luschny.de/math/factorial/csharp/FactorialPrimeSwing.cs.html
|
12
|
+
class SwingFactorial
|
13
|
+
attr_reader :result
|
14
|
+
SmallOddSwing=[ 1, 1, 1, 3, 3, 15, 5, 35, 35, 315, 63, 693, 231, 3003, 429, 6435, 6435, 109395, 12155, 230945, 46189, 969969, 88179, 2028117, 676039, 16900975, 1300075, 35102025, 5014575,145422675, 9694845, 300540195, 300540195]
|
15
|
+
def bitcount(n)
|
16
|
+
bc = n - ((n >> 1) & 0x55555555);
|
17
|
+
bc = (bc & 0x33333333) + ((bc >> 2) & 0x33333333);
|
18
|
+
bc = (bc + (bc >> 4)) & 0x0f0f0f0f;
|
19
|
+
bc += bc >> 8;
|
20
|
+
bc += bc >> 16;
|
21
|
+
bc = bc & 0x3f;
|
22
|
+
bc
|
23
|
+
end
|
24
|
+
def initialize(n)
|
25
|
+
if (n<20)
|
26
|
+
naive_factorial(n)
|
27
|
+
else
|
28
|
+
@prime_list=[]
|
29
|
+
exp2 = n - bitcount(n);
|
30
|
+
@result= recfactorial(n)<< exp2
|
31
|
+
end
|
32
|
+
end
|
33
|
+
def recfactorial(n)
|
34
|
+
return 1 if n<2
|
35
|
+
(recfactorial(n/2)**2) * swing(n)
|
36
|
+
end
|
37
|
+
def swing(n)
|
38
|
+
return SmallOddSwing[n] if (n<33)
|
39
|
+
sqrtN = Math.sqrt(n).floor
|
40
|
+
count=0
|
41
|
+
Prime.each(n/3) do |prime|
|
42
|
+
next if prime<3
|
43
|
+
if (prime<=sqrtN)
|
44
|
+
q=n
|
45
|
+
_p=1
|
46
|
+
while((q/=prime)>0) do
|
47
|
+
if ((q&1)==1)
|
48
|
+
_p*=prime
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
if _p>1
|
53
|
+
@prime_list[count]=_p
|
54
|
+
count+=1
|
55
|
+
end
|
56
|
+
|
57
|
+
else
|
58
|
+
if ((n/prime)&1==1)
|
59
|
+
@prime_list[count]=prime
|
60
|
+
count+=1
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
prod=get_primorial(n/2+1,n)
|
65
|
+
prod * @prime_list[0,count].inject(1) {|ac,v| ac*v}
|
66
|
+
end
|
67
|
+
def get_primorial(low,up)
|
68
|
+
prod=1;
|
69
|
+
Prime.each(up) do |prime|
|
70
|
+
next if prime<low
|
71
|
+
prod*=prime
|
72
|
+
end
|
73
|
+
prod
|
74
|
+
end
|
75
|
+
def naive_factorial(n)
|
76
|
+
@result=(self.class).naive_factorial(n)
|
77
|
+
end
|
78
|
+
def self.naive_factorial(n)
|
79
|
+
(2..n).inject(1) { |f,n| f * n }
|
9
80
|
end
|
10
|
-
|
81
|
+
end
|
82
|
+
# Module to calculate approximated factorial
|
83
|
+
# Based (again) on Luschny formula, with 16 digits of precision
|
84
|
+
# == Reference
|
85
|
+
# * http://www.luschny.de/math/factorial/approx/SimpleCases.html
|
86
|
+
module ApproxFactorial
|
87
|
+
def self.stieltjes_ln_factorial(z)
|
88
|
+
|
89
|
+
a0 = 1.quo(12); a1 = 1.quo(30); a2 = 53.quo(210); a3 = 195.quo(371);
|
90
|
+
a4 = 22999.quo(22737); a5 = 29944523.quo(19733142);
|
91
|
+
a6 = 109535241009.quo(48264275462);
|
92
|
+
zz = z+1;
|
93
|
+
|
94
|
+
(1.quo(2))*Math.log(2*Math::PI)+(zz-1.quo(2))*Math.log(zz) - zz +
|
95
|
+
a0.quo(zz+a1.quo(zz+a2.quo(zz+a3.quo(zz+a4.quo(zz+a5.quo(zz+a6.quo(zz)))))))
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.stieltjes_ln_factorial_big(z)
|
99
|
+
|
100
|
+
a0 = 1/12.0; a1 = 1/30.0; a2 = 53/210.0; a3 = 195/371.0;
|
101
|
+
a4 = 22999/22737.0; a5 = 29944523/19733142.0;
|
102
|
+
a6 = 109535241009/48264275462.0;
|
103
|
+
zz = z+1;
|
104
|
+
|
105
|
+
BigDecimal("0.5") * BigMath.log(BigDecimal("2")*BigMath::PI(20),20) + BigDecimal((zz - 0.5).to_s) * BigMath.log(BigDecimal(zz.to_s),20) - BigDecimal(zz.to_s) + BigDecimal( (
|
106
|
+
a0 / (zz+a1/(zz+a2/(zz+a3/(zz+a4/(zz+a5/(zz+a6/zz))))))
|
107
|
+
).to_s)
|
108
|
+
|
109
|
+
end
|
110
|
+
# Valid upto 11 digits
|
111
|
+
def self.stieltjes_factorial(x)
|
112
|
+
y = x; _p = 1;
|
113
|
+
while y < 8 do
|
114
|
+
_p = _p*y; y = y+1
|
115
|
+
end
|
116
|
+
lr= stieltjes_ln_factorial(y)
|
117
|
+
r = Math.exp(lr)
|
118
|
+
#puts "valid: #{5/2.0+(13/2.0)*Math::log(x)}"
|
119
|
+
if r.infinite?
|
120
|
+
r=BigMath.exp(BigDecimal(lr.to_s),20)
|
121
|
+
r = (r*x) / (_p*y) if x < 8
|
122
|
+
r=r.to_i
|
123
|
+
else
|
124
|
+
r = (r*x) / (_p*y) if x < 8
|
125
|
+
end
|
126
|
+
r
|
127
|
+
end
|
128
|
+
end
|
129
|
+
# Exact factorial.
|
130
|
+
# Use naive algorithm (iterative) on n<20
|
131
|
+
# and Prime Swing algorithm for higher values
|
132
|
+
def factorial(n)
|
133
|
+
SwingFactorial.new(n).result
|
134
|
+
end
|
135
|
+
# Approximate factorial, up to 16 digits
|
136
|
+
# Based of Luschy algorithm
|
137
|
+
def fast_factorial(n)
|
138
|
+
ApproxFactorial.stieltjes_factorial(n)
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
# Quick, accurate approximation of factorial for very small n. Special case, generally you want to use stirling instead.
|
143
|
+
# ==Reference
|
144
|
+
# * http://mathworld.wolfram.com/StirlingsApproximation.html
|
145
|
+
def gosper(n)
|
146
|
+
Math.sqrt( (2*n + 1/3.0) * Math::PI ) * (n/Math::E)**n
|
11
147
|
end
|
12
148
|
|
13
149
|
# Beta function.
|
@@ -61,12 +197,12 @@ end
|
|
61
197
|
|
62
198
|
module Math
|
63
199
|
include Distribution::MathExtension
|
64
|
-
module_function :factorial, :beta, :gamma
|
200
|
+
module_function :factorial, :beta, :gamma, :gosper, :loggamma, :fast_factorial
|
65
201
|
end
|
66
202
|
|
67
203
|
# Necessary on Ruby 1.9
|
68
204
|
module CMath # :nodoc:
|
69
205
|
include Distribution::MathExtension
|
70
|
-
module_function :factorial, :beta, :gamma
|
206
|
+
module_function :factorial, :beta, :gamma, :gosper, :loggamma, :fast_factorial
|
71
207
|
end
|
72
208
|
|
data/lib/distribution/t.rb
CHANGED
@@ -0,0 +1,77 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb")
|
2
|
+
include ExampleWithGSL
|
3
|
+
require 'ruby-prof'
|
4
|
+
|
5
|
+
# Need to test:
|
6
|
+
# * that Fixnum fast_choose returns same as choose
|
7
|
+
# * that pdf and exact_pdf return the same value in Ruby_
|
8
|
+
# * that cdf in Ruby_ returns the same value as cdf in GSL_
|
9
|
+
|
10
|
+
describe Distribution::Hypergeometric do
|
11
|
+
describe Distribution::Hypergeometric::Ruby_ do
|
12
|
+
before do
|
13
|
+
@engine=Distribution::Hypergeometric::Ruby_
|
14
|
+
end
|
15
|
+
it_only_with_gsl "pdf_fast should return same as pdf" do
|
16
|
+
pending("Not working yet")
|
17
|
+
if @engine.respond_to? :pdf
|
18
|
+
[0,1,2,4,8,16].each do |k|
|
19
|
+
|
20
|
+
@engine.pdf_aprox(k, 80, 100, 1000).should be_within(1e-8).of(GSL::Ran::hypergeometric_pdf(k, 80, 920, 100))
|
21
|
+
end
|
22
|
+
else
|
23
|
+
pending("No #{@engine}.pdf")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
it_only_with_gsl "should return correct pdf" do
|
29
|
+
#RubyProf.start
|
30
|
+
|
31
|
+
if @engine.respond_to? :pdf
|
32
|
+
#[2].each do |k|
|
33
|
+
[0,1,2,4,8,16].each do |k|
|
34
|
+
@engine.pdf(k, 80, 100, 10000).should be_within(1e-8).of(GSL::Ran::hypergeometric_pdf(k, 80, 9920, 100))
|
35
|
+
end
|
36
|
+
#result = RubyProf.stop
|
37
|
+
|
38
|
+
# Print a flat profile to text
|
39
|
+
#printer = RubyProf::FlatPrinter.new(result)
|
40
|
+
#printer.print(STDOUT)
|
41
|
+
|
42
|
+
else
|
43
|
+
pending("No #{@engine}.pdf")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should return correct cdf" do
|
48
|
+
total=rand(5)+30
|
49
|
+
n=rand(10)+15
|
50
|
+
m=rand(10)+5
|
51
|
+
ac=0
|
52
|
+
0.upto(m) do |i|
|
53
|
+
ac+=@engine.pdf(i,m,n,total)
|
54
|
+
@engine.cdf(i,m,n,total).should eq(ac)
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should return correct p_value" do
|
60
|
+
|
61
|
+
#0.upto(10) do |i|
|
62
|
+
# puts "#{i}:#{@engine.pdf(i,5,7,10)}"
|
63
|
+
#end
|
64
|
+
total=rand(5)+30
|
65
|
+
n=rand(10)+15
|
66
|
+
m=rand(10)+5
|
67
|
+
ac=0
|
68
|
+
0.upto(m) do |k|
|
69
|
+
ac+=@engine.pdf(k,m,n,total)
|
70
|
+
@engine.p_value(ac, m, n, total).should eq(k)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb")
|
2
|
+
describe Distribution::MathExtension do
|
3
|
+
it "fast_factorial should return 11 valid digits" do
|
4
|
+
pending("Doesn't worth the effort")
|
5
|
+
valid=11
|
6
|
+
(2..10).each {|i|
|
7
|
+
n=2**i
|
8
|
+
aprox=Math.fast_factorial(n).round.to_s[0,valid]
|
9
|
+
exact=Math.factorial(n).to_s[0,valid]
|
10
|
+
aprox.should eq exact
|
11
|
+
|
12
|
+
}
|
13
|
+
end
|
14
|
+
describe Distribution::MathExtension::SwingFactorial do
|
15
|
+
it "Math.factorial should return correct values x<20" do
|
16
|
+
ac=3628800 # 10!
|
17
|
+
11.upto(19).each do |i|
|
18
|
+
ac*=i
|
19
|
+
Math.factorial(i).should eq(ac)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it "Math.factorial should return correct values for values 21<x<33" do
|
24
|
+
ac=2432902008176640000 # 20!
|
25
|
+
21.upto(33).each do |i|
|
26
|
+
ac*=i
|
27
|
+
Math.factorial(i).should eq(ac)
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
it "Math.factorial should return correct values for values x>33" do
|
33
|
+
ac=8683317618811886495518194401280000000 # 33!
|
34
|
+
Math.factorial(33).should eq ac
|
35
|
+
34.upto(40).each do |i|
|
36
|
+
ac*=i
|
37
|
+
Math.factorial(i).should eq(ac)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/spec/shorthand_spec.rb
CHANGED
@@ -1,14 +1,20 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb")
|
2
2
|
describe Distribution::Shorthand do
|
3
3
|
include Distribution::Shorthand
|
4
|
-
it "should have
|
5
|
-
|
4
|
+
it "should have basic methods for all distributions" do
|
5
|
+
[:Normal,:ChiSquare, :F, :Hypergeometric, :T].each do |d|
|
6
|
+
klass=Distribution.const_get(d)
|
7
|
+
shortname=klass::SHORTHAND
|
8
|
+
methods=[:pdf, :cdf, :p_value].map {|m| "#{shortname}_#{m}".to_sym}
|
9
|
+
methods.each do |m|
|
10
|
+
Distribution::Shorthand.instance_methods.should include(m)
|
11
|
+
end
|
12
|
+
end
|
6
13
|
end
|
7
14
|
it "returns same values as long form" do
|
8
15
|
x=rand()
|
9
16
|
norm_cdf(x).should eql(Distribution::Normal.cdf(x))
|
10
17
|
norm_pdf(x).should eql(Distribution::Normal.pdf(x))
|
11
18
|
norm_p_value(x).should eql(Distribution::Normal.p_value(x))
|
12
|
-
|
13
19
|
end
|
14
20
|
end
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
7
|
+
- 2
|
8
8
|
- 0
|
9
|
-
version: 0.
|
9
|
+
version: 0.2.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Claudio Bustos
|
@@ -35,7 +35,7 @@ cert_chain:
|
|
35
35
|
rpP0jjs0
|
36
36
|
-----END CERTIFICATE-----
|
37
37
|
|
38
|
-
date: 2011-01-
|
38
|
+
date: 2011-01-27 00:00:00 -03:00
|
39
39
|
default_executable:
|
40
40
|
dependencies:
|
41
41
|
- !ruby/object:Gem::Dependency
|
@@ -89,8 +89,10 @@ files:
|
|
89
89
|
- Manifest.txt
|
90
90
|
- README.txt
|
91
91
|
- Rakefile
|
92
|
+
- benchmark/factorial_method.rb
|
92
93
|
- bin/distribution
|
93
94
|
- lib/distribution.rb
|
95
|
+
- lib/distribution/binomial.rb
|
94
96
|
- lib/distribution/bivariatenormal.rb
|
95
97
|
- lib/distribution/bivariatenormal/gsl.rb
|
96
98
|
- lib/distribution/bivariatenormal/ruby.rb
|
@@ -103,6 +105,9 @@ files:
|
|
103
105
|
- lib/distribution/f/gsl.rb
|
104
106
|
- lib/distribution/f/ruby.rb
|
105
107
|
- lib/distribution/f/statistics2.rb
|
108
|
+
- lib/distribution/hypergeometric.rb
|
109
|
+
- lib/distribution/hypergeometric/gsl.rb
|
110
|
+
- lib/distribution/hypergeometric/ruby.rb
|
106
111
|
- lib/distribution/math_extension.rb
|
107
112
|
- lib/distribution/normal.rb
|
108
113
|
- lib/distribution/normal/gsl.rb
|
@@ -117,8 +122,9 @@ files:
|
|
117
122
|
- spec/chisquare_spec.rb
|
118
123
|
- spec/distribution_spec.rb
|
119
124
|
- spec/f_spec.rb
|
125
|
+
- spec/hypergeometric_spec.rb
|
126
|
+
- spec/math_extension_spec.rb
|
120
127
|
- spec/normal_spec.rb
|
121
|
-
- spec/shorthand_function.rb
|
122
128
|
- spec/shorthand_spec.rb
|
123
129
|
- spec/spec.opts
|
124
130
|
- spec/spec_helper.rb
|
metadata.gz.sig
CHANGED