distribution 0.7.3 → 0.8.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.
Files changed (100) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +4 -6
  3. data/.yardopts +5 -0
  4. data/History.txt +3 -0
  5. data/README.md +87 -44
  6. data/benchmark/binomial_coefficient.rb +19 -23
  7. data/benchmark/binomial_coefficient/experiment.rb +33 -36
  8. data/benchmark/factorial_hash.rb +7 -8
  9. data/benchmark/factorial_method.rb +4 -6
  10. data/benchmark/odd.rb +6 -7
  11. data/benchmark/power.rb +11 -11
  12. data/bin/distribution +26 -26
  13. data/distribution.gemspec +3 -4
  14. data/lib/distribution.rb +55 -96
  15. data/lib/distribution/beta/gsl.rb +10 -5
  16. data/lib/distribution/beta/ruby.rb +3 -1
  17. data/lib/distribution/binomial/ruby.rb +5 -2
  18. data/lib/distribution/bivariatenormal.rb +4 -5
  19. data/lib/distribution/bivariatenormal/gsl.rb +2 -2
  20. data/lib/distribution/bivariatenormal/java.rb +1 -1
  21. data/lib/distribution/bivariatenormal/ruby.rb +245 -254
  22. data/lib/distribution/chisquare.rb +8 -10
  23. data/lib/distribution/chisquare/gsl.rb +24 -19
  24. data/lib/distribution/chisquare/java.rb +1 -1
  25. data/lib/distribution/chisquare/ruby.rb +25 -25
  26. data/lib/distribution/chisquare/statistics2.rb +16 -13
  27. data/lib/distribution/distributable.rb +40 -0
  28. data/lib/distribution/exponential.rb +4 -5
  29. data/lib/distribution/exponential/gsl.rb +13 -9
  30. data/lib/distribution/exponential/ruby.rb +14 -9
  31. data/lib/distribution/f.rb +1 -1
  32. data/lib/distribution/f/gsl.rb +26 -22
  33. data/lib/distribution/f/java.rb +1 -1
  34. data/lib/distribution/f/ruby.rb +16 -19
  35. data/lib/distribution/f/statistics2.rb +22 -19
  36. data/lib/distribution/gamma.rb +5 -7
  37. data/lib/distribution/gamma/gsl.rb +13 -9
  38. data/lib/distribution/gamma/java.rb +1 -1
  39. data/lib/distribution/gamma/ruby.rb +5 -11
  40. data/lib/distribution/hypergeometric.rb +5 -8
  41. data/lib/distribution/hypergeometric/gsl.rb +4 -5
  42. data/lib/distribution/hypergeometric/java.rb +1 -1
  43. data/lib/distribution/hypergeometric/ruby.rb +34 -35
  44. data/lib/distribution/logistic.rb +5 -8
  45. data/lib/distribution/logistic/ruby.rb +13 -8
  46. data/lib/distribution/lognormal.rb +5 -7
  47. data/lib/distribution/lognormal/gsl.rb +8 -6
  48. data/lib/distribution/lognormal/ruby.rb +5 -9
  49. data/lib/distribution/math_extension.rb +6 -15
  50. data/lib/distribution/math_extension/chebyshev_series.rb +281 -272
  51. data/lib/distribution/math_extension/erfc.rb +26 -29
  52. data/lib/distribution/math_extension/exponential_integral.rb +17 -17
  53. data/lib/distribution/math_extension/gammastar.rb +19 -20
  54. data/lib/distribution/math_extension/gsl_utilities.rb +12 -12
  55. data/lib/distribution/math_extension/incomplete_beta.rb +52 -61
  56. data/lib/distribution/math_extension/incomplete_gamma.rb +166 -168
  57. data/lib/distribution/math_extension/log_utilities.rb +20 -22
  58. data/lib/distribution/normal.rb +11 -13
  59. data/lib/distribution/normal/gsl.rb +13 -10
  60. data/lib/distribution/normal/java.rb +14 -13
  61. data/lib/distribution/normal/ruby.rb +68 -58
  62. data/lib/distribution/normal/statistics2.rb +5 -2
  63. data/lib/distribution/normalmultivariate.rb +64 -64
  64. data/lib/distribution/poisson.rb +11 -13
  65. data/lib/distribution/poisson/gsl.rb +7 -7
  66. data/lib/distribution/poisson/java.rb +19 -24
  67. data/lib/distribution/poisson/ruby.rb +38 -9
  68. data/lib/distribution/shorthand.rb +17 -0
  69. data/lib/distribution/t.rb +13 -15
  70. data/lib/distribution/t/gsl.rb +27 -24
  71. data/lib/distribution/t/java.rb +1 -1
  72. data/lib/distribution/t/ruby.rb +99 -100
  73. data/lib/distribution/t/statistics2.rb +19 -19
  74. data/lib/distribution/uniform.rb +26 -0
  75. data/lib/distribution/uniform/gsl.rb +36 -0
  76. data/lib/distribution/uniform/ruby.rb +91 -0
  77. data/lib/distribution/version.rb +1 -1
  78. data/lib/distribution/weibull.rb +6 -7
  79. data/lib/distribution/weibull/gsl.rb +16 -16
  80. data/lib/distribution/weibull/ruby.rb +30 -23
  81. data/spec/beta_spec.rb +45 -47
  82. data/spec/binomial_spec.rb +77 -85
  83. data/spec/bivariatenormal_spec.rb +28 -35
  84. data/spec/chisquare_spec.rb +48 -52
  85. data/spec/distribution_spec.rb +10 -10
  86. data/spec/exponential_spec.rb +44 -49
  87. data/spec/f_spec.rb +4 -4
  88. data/spec/gamma_spec.rb +50 -53
  89. data/spec/hypergeometric_spec.rb +63 -69
  90. data/spec/logistic_spec.rb +32 -37
  91. data/spec/lognormal_spec.rb +25 -31
  92. data/spec/math_extension_spec.rb +192 -210
  93. data/spec/normal_spec.rb +80 -73
  94. data/spec/poisson_spec.rb +63 -41
  95. data/spec/shorthand_spec.rb +19 -22
  96. data/spec/spec_helper.rb +8 -9
  97. data/spec/t_spec.rb +63 -77
  98. data/spec/uniform_spec.rb +154 -0
  99. data/spec/weibull_spec.rb +13 -14
  100. metadata +17 -8
@@ -3,26 +3,26 @@ module Distribution
3
3
  module T
4
4
  module Statistics2_
5
5
  class << self
6
- # Return the P-value of the corresponding integral with
7
- # k degrees of freedom
8
- def p_value(pr,k)
9
- Statistics2.ptdist(k, pr)
10
- end
11
-
12
-
13
- # There are some problem on i686 with t on statistics2
14
- if true or !RbConfig::CONFIG['arch']=~/i686/
15
- # T cumulative distribution function (cdf).
16
- #
17
- # Returns the integral of t-distribution
18
- # with n degrees of freedom over (-Infty, x].
19
- #
20
- def cdf(x,k)
21
- Statistics2.tdist(k,x)
6
+ # There are some problem on i686 with t on statistics2
7
+ if true || !RbConfig::CONFIG['arch'] =~ /i686/
8
+ # T cumulative distribution function (cdf).
9
+ #
10
+ # Returns the integral of t-distribution
11
+ # with n degrees of freedom over (-Infty, x].
12
+ #
13
+ def cdf(x, k)
14
+ Statistics2.tdist(k, x)
15
+ end
16
+
17
+ # Return the P-value of the corresponding integral with
18
+ # k degrees of freedom
19
+ def quantile(pr, k)
20
+ Statistics2.ptdist(k, pr)
21
+ end
22
+
23
+ alias_method :p_value, :quantile
22
24
  end
23
25
  end
24
-
25
- end
26
26
  end
27
27
  end
28
- end
28
+ end
@@ -0,0 +1,26 @@
1
+ require 'distribution/uniform/ruby'
2
+ require 'distribution/uniform/gsl'
3
+ #require 'distribution/uniform/java'
4
+
5
+
6
+ module Distribution
7
+ # Expresses the uniformly spread probability over a finite interval
8
+ module Uniform
9
+ SHORTHAND='unif'
10
+ extend Distributable
11
+ create_distribution_methods
12
+
13
+ ##
14
+ # :singleton-method: pdf(x, lower, upper)
15
+ # Returns the uniform PDF
16
+
17
+ ##
18
+ # :singleton-method: cdf(x, lower, upper)
19
+ # Returns the uniform CDF
20
+
21
+ ##
22
+ # :singleton-method: quantile(qn, lower, upper)
23
+ # Returns the uniform inverse CDF or P-value
24
+
25
+ end
26
+ end
@@ -0,0 +1,36 @@
1
+ module Distribution
2
+ module Uniform
3
+ module GSL_
4
+ class << self
5
+ # Returns a lambda to call for uniformly distributed random numbers
6
+ # returns a double precision float in [0, 1]
7
+ def rng(lower = 0, upper = 1, seed = nil)
8
+ seed = Random.new_seed.modulo 100000007 if seed.nil?
9
+ rng = GSL::Rng.alloc(GSL::Rng::MT19937, seed)
10
+
11
+ -> { lower + (upper - lower) * rng.uniform }
12
+ end
13
+
14
+ # :nodoc:
15
+ def pdf(x, lower = 0, upper = 1)
16
+ # rb-gsl/blob/master/ext/gsl_native/randist.c#L1732
17
+ GSL::Ran.flat_pdf(x, lower, upper)
18
+ end
19
+
20
+ # :nodoc:
21
+ def cdf(x, lower = 0, upper = 1)
22
+ # rb-gsl/blob/master/ext/gsl_native/cdf.c#L644
23
+ GSL::Cdf.flat_P(x, lower, upper)
24
+ end
25
+
26
+ # :nodoc:
27
+ def quantile(qn, lower, upper)
28
+ # rb-gsl/blob/master/ext/gsl_native/cdf.c#L646
29
+ GSL::Cdf.flat_Pinv(qn, lower, upper)
30
+ end
31
+
32
+ alias_method :p_value, :quantile
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,91 @@
1
+ module Distribution
2
+ module Uniform
3
+ module Ruby_
4
+ # Module contain pure ruby implementation of the
5
+ # uniform distribution (rng, pdf, cdf and quantile functions)
6
+ class << self
7
+ # Returns a lambda that emits a uniformly distributed
8
+ # sequence of random numbers between the defined limits
9
+ #
10
+ # == Arguments
11
+ # * +lower+ - Lower limit of the distribution
12
+ # * +upper+ - Upper limit of the distribution
13
+ # * +seed+ - Seed to set the initial state, randomized if ommited
14
+ #
15
+ def rng(lower = 0, upper = 1, seed = nil)
16
+ seed = Random.new_seed if seed.nil?
17
+ prng = Random.new(seed)
18
+ -> { prng.rand * (upper - lower) + lower }
19
+ end
20
+
21
+ # Uniform probability density function on [a, b]
22
+ #
23
+ # == Arguments
24
+ # If you are referring the wiki page for this continuous distribution
25
+ # the arguments can be translated as follows
26
+ # * +x+ - same as continuous random variable
27
+ # * +lower+ - lower limit or a, must be a real number
28
+ # * +upper+ - upper limit or b, must be a real number
29
+ #
30
+ # == Reference
31
+ # * https://en.wikipedia.org/wiki/Uniform_distribution_(continuous)
32
+ #
33
+ # The implementation has been adopted from GSL-1.9 gsl/randist/flat.c
34
+ #
35
+ def pdf(x, lower = 0, upper = 1)
36
+ upper, lower = lower, upper if lower > upper
37
+ return 1 / (upper - lower) if (lower..upper).member? x
38
+ 0
39
+ end
40
+
41
+ # The uniform cumulative density function (CDF)
42
+ # == Arguments
43
+ # If you are referring the wiki page for this continuous distribution
44
+ # the arguments can be translated as follows
45
+ # * +x+ - same as continuous random variable
46
+ # * +lower+ - lower limit or a, must be a real number
47
+ # * +upper+ - upper limit or b, must be a real number
48
+ #
49
+ # == Reference
50
+ # * https://en.wikipedia.org/wiki/Uniform_distribution_(continuous)
51
+ #
52
+ # The implementation has been adpoted from GSL-1.9 gsl/cdf/flat.c
53
+ #
54
+ def cdf(x, lower = 0, upper = 1)
55
+ if x < lower
56
+ 0
57
+ elsif x > upper
58
+ 1
59
+ else
60
+ (x - lower) / (upper - lower)
61
+ end
62
+ end
63
+
64
+ # The uniform inverse CDF density function / P-value function
65
+ # == Arguments
66
+ # If you are referring the wiki page for this continuous distribution
67
+ # the arguments can be translated as follows
68
+ # * +qn+ - same as integral value
69
+ # * +lower+ - lower limit or a, must be a real number
70
+ # * +upper+ - upper limit or b, must be a real number
71
+ #
72
+ # == Returns
73
+ # * nil if the integral value is not in [0, 1]
74
+ # * inverse cdf otherwise
75
+ # == Reference
76
+ # * https://en.wikipedia.org/wiki/Uniform_distribution_(continuous)
77
+ #
78
+ # The implementation has been adpoted from GSL-1.9 gsl/cdf/flatinv.c
79
+ #
80
+ def quantile(qn, lower = 0, upper = 1)
81
+ fail RangeError, 'cdf value(qn) must be from [0, 1]. '\
82
+ "Cannot find quantile for qn=#{qn}" if qn > 1 || qn < 0
83
+
84
+ qn * upper + (1 - qn) * lower
85
+ end
86
+
87
+ alias p_value quantile
88
+ end
89
+ end
90
+ end
91
+ end
@@ -1,3 +1,3 @@
1
1
  module Distribution
2
- VERSION = '0.7.3'
2
+ VERSION = '0.8.0'
3
3
  end
@@ -2,10 +2,9 @@ require 'distribution/weibull/ruby'
2
2
  require 'distribution/weibull/gsl'
3
3
 
4
4
  module Distribution
5
-
6
- module Weibull
7
- SHORTHAND = 'weibull'
8
- extend Distributable
9
- create_distribution_methods
10
- end
11
- end
5
+ module Weibull
6
+ SHORTHAND = 'weibull'
7
+ extend Distributable
8
+ create_distribution_methods
9
+ end
10
+ end
@@ -1,21 +1,21 @@
1
1
  module Distribution
2
- module Weibull
3
- module GSL_
4
- class << self
5
-
6
- def pdf(x, k, lam)
7
- GSL::Ran.weibull_pdf(x, lam, k)
8
- end
9
-
2
+ module Weibull
3
+ module GSL_
4
+ class << self
5
+ def pdf(x, k, lam)
6
+ GSL::Ran.weibull_pdf(x, lam, k)
7
+ end
10
8
 
11
- def cdf(x, k, lam)
12
- GSL::Cdf.weibull_P(x, lam, k)
13
- end
9
+ def cdf(x, k, lam)
10
+ GSL::Cdf.weibull_P(x, lam, k)
11
+ end
14
12
 
15
- def p_value(y, k, lam)
16
- GSL::Cdf.weibull_Pinv(y, lam, k)
17
- end
18
- end
19
- end
13
+ def quantile(y, k, lam)
14
+ GSL::Cdf.weibull_Pinv(y, lam, k)
20
15
  end
16
+
17
+ alias_method :p_value, :quantile
18
+ end
19
+ end
20
+ end
21
21
  end
@@ -1,27 +1,34 @@
1
1
  module Distribution
2
- module Weibull
3
- module Ruby_
4
- class << self
5
- def pdf(x, k, lam)
6
- return 0.0 if x < 0.0
7
- return ((k.to_f/lam.to_f)*(x.to_f/lam.to_f)**(k-1.0))*Math.exp(-(x.to_f/lam.to_f)**k)
8
- end
2
+ module Weibull
3
+ module Ruby_
4
+ class << self
5
+ def pdf(x, k, lam)
6
+ if x < 0.0
7
+ 0.0
8
+ else
9
+ a = (k.to_f / lam.to_f)
10
+ b = (x.to_f / lam.to_f)
11
+ c = (k - 1.0)
12
+ d = Math.exp(-(x.to_f / lam.to_f)**k)
13
+ (a * b**c) * d
14
+ end
15
+ end
9
16
 
10
- #Returns the integral of the Weibull distribution from [-Inf to x]
17
+ # Returns the integral of the Weibull distribution from [-Inf to x]
18
+ def cdf(x, k, lam)
19
+ return 0.0 if x < 0.0
20
+ 1.0 - Math.exp(-(x.to_f / lam.to_f)**k)
21
+ end
11
22
 
12
- def cdf(x, k, lam)
13
- return 0.0 if x < 0.0
14
- return 1.0-Math.exp(-(x.to_f/lam.to_f)**k)
15
- end
23
+ # Returns the P-value of weibull
24
+ def quantile(y, k, lam)
25
+ return 1.0 if y > 1.0
26
+ return 0.0 if y < 0.0
27
+ -lam * (Math.log(1.0 - y))**(1.0 / k)
28
+ end
16
29
 
17
- # Returns the P-value of weibull
18
-
19
- def p_value(y, k, lam)
20
- return 1.0 if y > 1.0
21
- return 0.0 if y < 0.0
22
- return -lam*(Math.log(1.0-y))**(1.0/k)
23
- end
24
- end
25
- end
26
- end
27
- end
30
+ alias_method :p_value, :quantile
31
+ end
32
+ end
33
+ end
34
+ end
@@ -1,82 +1,80 @@
1
- require File.expand_path(File.dirname(__FILE__)+"/spec_helper.rb")
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper.rb')
2
2
  include ExampleWithGSL
3
3
  describe Distribution::Beta do
4
-
5
- shared_examples_for "Beta engine" do
6
- it_only_with_gsl "should return correct pdf" do
4
+ shared_examples_for 'Beta engine' do
5
+ it_only_with_gsl 'should return correct pdf' do
7
6
  if @engine.respond_to? :pdf
8
7
  1.upto(101) do |x|
9
- a=rand * x
10
- b=1 + rand * 5
11
- g=GSL::Ran.beta_pdf(x,a,b)
12
- @engine.pdf(x,a,b).should be_within(1e-09).of(g)
8
+ a = rand * x
9
+ b = 1 + rand * 5
10
+ g = GSL::Ran.beta_pdf(x, a, b)
11
+ expect(@engine.pdf(x, a, b)).to be_within(1e-09).of(g)
13
12
  end
14
13
  else
15
14
  skip("No #{@engine}.pdf")
16
15
  end
17
16
  end
18
17
 
19
- it_only_with_gsl "should return correct cdf" do
20
- if @engine.respond_to? :cdf
21
- # From GSL-1.9.
22
- tol = 1048576.0*Float::EPSILON
23
- @engine.cdf(0.0, 1.2, 1.3).should eq(0.0)
24
- @engine.cdf(1e-100, 1.2, 1.3).should be_within(tol).of(1.34434944656489596e-120)
25
- @engine.cdf(0.001, 1.2, 1.3).should be_within(tol).of(3.37630042504535813e-4)
26
- @engine.cdf(0.01, 1.2, 1.3).should be_within(tol).of(5.34317264038929473e-3)
27
- @engine.cdf(0.1, 1.2, 1.3).should be_within(tol).of(8.33997828306748346e-2)
28
- @engine.cdf(0.325, 1.2, 1.3).should be_within(tol).of(3.28698654180583916e-1)
29
- @engine.cdf(0.5, 1.2, 1.3).should be_within(tol).of(5.29781429451299081e-1)
30
- @engine.cdf(0.9, 1.2, 1.3).should be_within(tol).of(9.38529397224430659e-1)
31
- @engine.cdf(0.99, 1.2, 1.3).should be_within(tol).of(9.96886438341254380e-1)
32
- @engine.cdf(0.999, 1.2, 1.3).should be_within(tol).of(9.99843792833067634e-1)
33
- @engine.cdf(1.0, 1.2, 1.3).should be_within(tol).of(1.0)
34
- else
35
- skip("No #{@engine}.cdf")
18
+ it_only_with_gsl 'should return correct cdf' do
19
+ if @engine.respond_to? :cdf
20
+ # From GSL-1.9.
21
+ tol = 1_048_576.0 * Float::EPSILON
22
+ expect(@engine.cdf(0.0, 1.2, 1.3)).to eq(0.0)
23
+ expect(@engine.cdf(1e-100, 1.2, 1.3)).to be_within(tol).of(1.34434944656489596e-120)
24
+ expect(@engine.cdf(0.001, 1.2, 1.3)).to be_within(tol).of(3.37630042504535813e-4)
25
+ expect(@engine.cdf(0.01, 1.2, 1.3)).to be_within(tol).of(5.34317264038929473e-3)
26
+ expect(@engine.cdf(0.1, 1.2, 1.3)).to be_within(tol).of(8.33997828306748346e-2)
27
+ expect(@engine.cdf(0.325, 1.2, 1.3)).to be_within(tol).of(3.28698654180583916e-1)
28
+ expect(@engine.cdf(0.5, 1.2, 1.3)).to be_within(tol).of(5.29781429451299081e-1)
29
+ expect(@engine.cdf(0.9, 1.2, 1.3)).to be_within(tol).of(9.38529397224430659e-1)
30
+ expect(@engine.cdf(0.99, 1.2, 1.3)).to be_within(tol).of(9.96886438341254380e-1)
31
+ expect(@engine.cdf(0.999, 1.2, 1.3)).to be_within(tol).of(9.99843792833067634e-1)
32
+ expect(@engine.cdf(1.0, 1.2, 1.3)).to be_within(tol).of(1.0)
33
+ else
34
+ skip("No #{@engine}.cdf")
35
+ end
36
36
  end
37
- end
38
- it "should return correct p_value" do
39
- if @engine.respond_to? :p_value
40
- 2.upto(99) do |x|
41
- a=rand() * x
42
- b=1 + rand() * 5
43
- pr=@engine.cdf(x/100.0,a,b)
44
- @engine.p_value(pr,a, b).should be_within(1e-09).of(x/100.0)
45
- end
46
- else
47
- skip("No #{@engine}.p_value")
37
+ it 'should return correct p_value' do
38
+ if @engine.respond_to? :p_value
39
+ 2.upto(99) do |x|
40
+ a = rand * x
41
+ b = 1 + rand * 5
42
+ pr = @engine.cdf(x / 100.0, a, b)
43
+ expect(@engine.p_value(pr, a, b)).to be_within(1e-09).of(x / 100.0)
44
+ end
45
+ else
46
+ skip("No #{@engine}.p_value")
47
+ end
48
48
  end
49
49
  end
50
- end
51
50
 
52
- describe "singleton" do
51
+ describe 'singleton' do
53
52
  before do
54
- @engine=Distribution::Beta
53
+ @engine = Distribution::Beta
55
54
  end
56
- it_should_behave_like "Beta engine"
55
+ it_should_behave_like 'Beta engine'
57
56
  end
58
57
 
59
58
  describe Distribution::Beta::Ruby_ do
60
59
  before do
61
- @engine=Distribution::Beta::Ruby_
60
+ @engine = Distribution::Beta::Ruby_
62
61
  end
63
- it_should_behave_like "Beta engine"
62
+ it_should_behave_like 'Beta engine'
64
63
  end
65
64
  if Distribution.has_gsl?
66
65
  describe Distribution::Beta::GSL_ do
67
66
  before do
68
- @engine=Distribution::Beta::GSL_
67
+ @engine = Distribution::Beta::GSL_
69
68
  end
70
- it_should_behave_like "Beta engine"
69
+ it_should_behave_like 'Beta engine'
71
70
  end
72
71
  end
73
72
  if Distribution.has_java?
74
73
  describe Distribution::Beta::Java_ do
75
74
  before do
76
- @engine=Distribution::Beta::Java_
75
+ @engine = Distribution::Beta::Java_
77
76
  end
78
- it_should_behave_like "Beta engine"
77
+ it_should_behave_like 'Beta engine'
79
78
  end
80
79
  end
81
-
82
80
  end