simple-random 1.0.2 → 1.0.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 65923da1d24e7888037400e04e8247ce5a65e223
4
- data.tar.gz: c1340f384268823745fdaefe3f0a3b8a068539d7
2
+ SHA256:
3
+ metadata.gz: 2b758006bb39a31380c6505ff4e9ecd52c67ef9b62ad952d63adeb7a2d49411c
4
+ data.tar.gz: 1ddd254e9a7cfce4b5e7d76dd19f58658501f537f4d46f2c025300d28a0aa471
5
5
  SHA512:
6
- metadata.gz: 99f369a1a00047572b031eae49326f458a2afa8944c8ccfeb03f02872ea1bedfed70939631ee84ce72aee9eabdcdf062e4911ba71f41d0f8dcaf7e8f8da7d271
7
- data.tar.gz: 9750c6caa2986f42a77333c87f9c6d436c49c9fc5282f77d61f8b9cb1eb6a6fe874bf097b72a623c0101fdb295ceb0093ff1c348a6c0dd01f69ec26f7e2fd428
6
+ metadata.gz: 89da26472354aca342ab707908b2c519389ea92d38b72157c18fcaa71f2911312e46a37f5aaa821a4562a2171ae7c220bcdc4935de8afd2a4676279ff0624ebd
7
+ data.tar.gz: fcd901b6f50d9925d820f4ced57687716363ea12be33bac361f8734c54b27a6005d8077009814fa7cafd9edc88fa919eb84d41611dd20e6daf7ba43ae1f51c29
data/.travis.yml CHANGED
@@ -1,8 +1,22 @@
1
+ # single test suite, non-parallel build.
2
+
3
+ env:
4
+ global:
5
+ - CC_TEST_REPORTER_ID=fc1330064eb82caf0f39ecd509e3e1c5b4fc5ca8b02fb9fa63d6e8a92da5ad18
1
6
  language: ruby
2
7
  rvm:
3
- - 2.2
4
- - 2.1
5
- - 1.9
6
- - jruby-19mode
7
- - rbx-2
8
- - jruby-head
8
+ - 2.6
9
+ - 2.5
10
+ - 2.4
11
+ - 2.3.6
12
+ - 2.2.0
13
+ before_install:
14
+ - gem install bundler --version 1.17.3
15
+ before_script:
16
+ - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
17
+ - chmod +x ./cc-test-reporter
18
+ - ./cc-test-reporter before-build
19
+ script:
20
+ - bundle exec rake test
21
+ after_script:
22
+ - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
data/Gemfile CHANGED
@@ -1,15 +1,11 @@
1
- source "http://rubygems.org"
2
- # Add dependencies required to use your gem here.
3
- # Example:
4
- # gem "activesupport", ">= 2.3.5"
1
+ source 'https://rubygems.org'
5
2
 
6
- # Add dependencies to develop your gem here.
7
- # Include everything needed to run rake, tests, features, etc.
8
3
  group :development do
9
- gem "minitest", ">= 0"
10
- gem "shoulda", ">= 0"
11
- gem "rdoc", "~> 3.12"
12
- gem "bundler", "~> 1.0"
13
- gem "jeweler", "~> 2.0.1"
14
- gem "simplecov", ">= 0"
4
+ gem 'awesome_print', '>= 1.6'
5
+ gem 'minitest'
6
+ gem 'shoulda'
7
+ gem 'jeweler', '~> 2.0.1'
8
+ gem 'simplecov'
9
+ gem 'nokogiri', '>= 1.8.5'
10
+ gem 'codeclimate-test-reporter', require: nil
15
11
  end
data/LICENSE CHANGED
@@ -127,4 +127,4 @@ This License represents the complete agreement concerning subject matter hereof.
127
127
 
128
128
  10. RESPONSIBILITY FOR CLAIMS.
129
129
 
130
- As between Initial Developer and the Contributors, each party is responsible for claims and damages arising, directly or indirectly, out of its utilization of rights under this License and You agree to work with Initial Developer and Contributors to distribute such responsibility on an equitable basis. Nothing herein is intended or shall be deemed to constitute any admission of liability.
130
+ As between Initial Developer and the Contributors, each party is responsible for claims and damages arising, directly or indirectly, out of its utilization of rights under this License and You agree to work with Initial Developer and Contributors to distribute such responsibility on an equitable basis. Nothing herein is intended or shall be deemed to constitute any admission of liability.
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # simple-random ![Build status](https://travis-ci.org/ealdent/simple-random.svg?branch=master)
1
+ # simple-random ![Build status](https://travis-ci.com/ealdent/simple-random.svg?branch=master)
2
2
 
3
3
  Generate random numbers sampled from the following distributions:
4
4
 
@@ -34,16 +34,16 @@ Add `gem 'simple-random', '~> 1.0.0'` to your Gemfile and run `bundle install`.
34
34
  Some of the methods available:
35
35
 
36
36
  ``` ruby
37
- > @sr = SimpleRandom.new # Initialize a SimpleRandom instance
37
+ > r = SimpleRandom.new # Initialize a SimpleRandom instance
38
38
  => #<SimpleRandom:0x007f9e3ad58010 @m_w=521288629, @m_z=362436069>
39
- > @sr.set_seed # By default the same random seed is used, so we change it
40
- > @sr.uniform(0, 5) # Produce a uniform random sample from the open interval (lower, upper).
39
+ > r.set_seed # By default the same random seed is used, so we change it
40
+ > r.uniform(0, 5) # Produce a uniform random sample from the open interval (lower, upper).
41
41
  => 0.6353204359766096
42
- > @sr.normal(1000, 200) # Sample normal distribution with given mean and standard deviation
42
+ > r.normal(1000, 200) # Sample normal distribution with given mean and standard deviation
43
43
  => 862.5447157384566
44
- > @sr.exponential(2) # Get exponential random sample with specified mean
44
+ > r.exponential(2) # Get exponential random sample with specified mean
45
45
  => 0.9386480625062965
46
- > @sr.triangular(0, 2.5, 10) # Get triangular random sample with specified lower limit, mode, upper limit
46
+ > r.triangular(0, 2.5, 10) # Get triangular random sample with specified lower limit, mode, upper limit
47
47
  => 3.1083306054169277
48
48
  ```
49
49
 
@@ -56,11 +56,12 @@ See [lib/simple-random.rb](lib/simple-random/simple_random.rb) for all available
56
56
 
57
57
  * Fork the project.
58
58
  * Make your feature addition or bug fix.
59
- * Add tests for it. This is important so I don't break it in a
60
- future version unintentionally.
61
- * Commit, do not mess with rakefile, version, or history.
59
+ * Add tests for it. This is important so I don't break it in a future version unintentionally.
60
+ * Commit, but please do not mess with the gemspec, `Rakefile`, `VERSION`, `LICENSE`, or `.travis.yml`.
62
61
  (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
63
- * Send me a pull request. Bonus points for topic branches.
62
+ * Send me a pull request.
63
+
64
+ HT: This list was modified from the default instructions that ship with [jeweler](https://github.com/technicalpickles/jeweler).
64
65
 
65
66
  ## Copyright
66
67
 
@@ -68,6 +69,14 @@ Distributed under the Code Project Open License, which is similar to MIT or BSD.
68
69
 
69
70
  ## History
70
71
 
72
+ ### 1.0.4 - 2026-02-18
73
+ * Remove vulnerable development dependency declarations for `bundler` and `rdoc`
74
+ * Use `https://rubygems.org` as the gem source in development
75
+
76
+ ### 1.0.3 - 2015-11-25
77
+ * Attempt to reduce code complexity and improve readability
78
+ * Change error handling somewhat to throw specific errors and improve messages
79
+
71
80
  ### 1.0.2 - 2015-11-24
72
81
  * Merge pull request from [cunchem](https://github.com/cunchem) to fix Laplace method
73
82
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.2
1
+ 1.0.4
@@ -5,8 +5,7 @@ class MultiThreadedSimpleRandom < SimpleRandom
5
5
  @instances = nil
6
6
 
7
7
  def instance
8
-
9
- unless @instances
8
+ unless instance_variable_defined?('@instances') && @instances
10
9
  extend MonitorMixin
11
10
 
12
11
  self.synchronize do
@@ -27,4 +26,4 @@ class MultiThreadedSimpleRandom < SimpleRandom
27
26
  end
28
27
 
29
28
  private_class_method :new
30
- end
29
+ end
@@ -1,58 +1,67 @@
1
1
  class SimpleRandom
2
- def initialize
3
- @m_w = 521288629
4
- @m_z = 362436069
5
- end
2
+ class InvalidSeedArgument < StandardError; end
6
3
 
7
- def set_seed(*args)
8
- if args.size > 1
9
- @m_w = args.first.to_i if args.first.to_i != 0
10
- @m_z = args.last.to_i if args.last.to_i != 0
11
- elsif args.first.is_a?(Numeric)
12
- @m_z = args.first.to_i if args.first.to_i != 0
13
- elsif args.first.is_a?(Time)
14
- x = (args.first.to_f * 1000000).to_i
15
- @m_w = x >> 16
16
- @m_z = x % 4294967296 # 2 ** 32
4
+ I_32_BIT = 4294967296
5
+ F_32_BIT = 4294967296.0
6
+ DEFAULT_SEEDS = [521288629, 362436069]
7
+
8
+ def initialize(*args)
9
+ if args.empty?
10
+ set_seed(*DEFAULT_SEEDS)
17
11
  else
18
- x = (Time.now.to_f * 1000000).to_i
19
- @m_w = x >> 16
20
- @m_z = x % 4294967296 # 2 ** 32
12
+ set_seed(*args)
21
13
  end
14
+ end
15
+
16
+ def set_seed(*args)
17
+ validate_seeds!(*args)
22
18
 
23
- @m_w %= 4294967296
24
- @m_z %= 4294967296
19
+ @m_w, @m_z = determine_seeds(*args)
20
+
21
+ ensure_32bit_seeds!
22
+ end
23
+
24
+ def seeds=(value)
25
+ set_seed(*[value].flatten.compact)
26
+ end
27
+
28
+ def seeds
29
+ [@m_w, @m_z]
25
30
  end
26
31
 
27
32
  # Produce a uniform random sample from the open interval (lower, upper).
28
- # The method will not return either end point.
29
33
  def uniform(lower = 0, upper = 1)
30
- raise 'Invalid range' if upper <= lower
31
- ((get_unsigned_int + 1) * (upper - lower) / 4294967296.0) + lower
34
+ fail ArgumentError, 'Upper bound must be greater than lower bound.' unless lower < upper
35
+
36
+ ((get_unsigned_int + 1) * (upper - lower) / F_32_BIT) + lower
32
37
  end
33
38
 
34
39
  # Sample normal distribution with given mean and standard deviation
35
40
  def normal(mean = 0.0, standard_deviation = 1.0)
36
- raise 'Invalid standard deviation' if standard_deviation <= 0
41
+ fail ArgumentError, 'Standard deviation must be strictly positive' unless standard_deviation > 0
42
+
37
43
  mean + standard_deviation * ((-2.0 * Math.log(uniform)) ** 0.5) * Math.sin(2.0 * Math::PI * uniform)
38
44
  end
39
45
 
40
46
  # Get exponential random sample with specified mean
41
47
  def exponential(mean = 1)
42
- raise 'Mean must be positive' if mean <= 0
48
+ fail ArgumentError, "Mean must be strictly positive" unless mean > 0
49
+
43
50
  -1.0 * mean * Math.log(uniform)
44
51
  end
45
52
 
46
53
  # Get triangular random sample with specified lower limit, mode, upper limit
47
54
  def triangular(lower, mode, upper)
48
- raise 'Upper limit must be larger than lower limit' if upper < lower
49
- raise 'Mode must lie between the upper and lower limits' if (mode < lower || mode > upper)
50
- f_c = (mode - lower) / (upper - lower)
51
- uniform_rand_num = uniform
52
- if uniform_rand_num < f_c
53
- lower + Math.sqrt(uniform_rand_num * (upper - lower) * (mode - lower))
55
+ fail ArgumentError, 'Upper bound must be greater than lower bound.' unless lower < upper
56
+ fail ArgumentError, 'Mode must lie between the upper and lower limits' if mode > upper || mode < lower
57
+
58
+ r = (upper - lower).to_f
59
+ u = uniform
60
+
61
+ if u < ((mode - lower) / r)
62
+ lower + Math.sqrt(u * r * (mode - lower))
54
63
  else
55
- upper - Math.sqrt((1 - uniform_rand_num) * (upper - lower) * (upper - mode))
64
+ upper - Math.sqrt((1.0 - u) * r * (upper - mode))
56
65
  end
57
66
  end
58
67
 
@@ -60,28 +69,26 @@ class SimpleRandom
60
69
  # by George Marsaglia and Wai Wan Tsang. ACM Transactions on Mathematical Software
61
70
  # Vol 26, No 3, September 2000, pages 363-372.
62
71
  def gamma(shape, scale)
63
- if shape >= 1.0
64
- d = shape - 1.0 / 3.0
65
- c = 1 / ((9 * d) ** 0.5)
66
- while true
67
- v = 0.0
68
- while v <= 0.0
69
- x = normal
70
- v = 1.0 + c * x
71
- end
72
- v = v ** 3
72
+ fail ArgumentError, 'Shape must be strictly positive' unless shape > 0
73
+ return scale * gamma(shape + 1.0, 1.0) * uniform ** -shape if shape < 1
74
+
75
+ d = shape - 1 / 3.0
76
+ c = (9 * d) ** -0.5
77
+
78
+ begin
79
+ z = normal
80
+
81
+ condition1 = z > (-1.0 / c)
82
+ condition2 = false
83
+
84
+ if condition1
73
85
  u = uniform
74
- if u < (1.0 - 0.0331 * (x ** 4)) || Math.log(u) < (0.5 * (x ** 2) + d * (1.0 - v + Math.log(v)))
75
- return scale * d * v
76
- end
86
+ v = (1 + c * z) ** 3
87
+ condition2 = Math.log(u) < (0.5 * (z ** 2) + d * (1.0 - v + Math.log(v)))
77
88
  end
78
- elsif shape <= 0.0
79
- raise 'Shape must be positive'
80
- else
81
- g = gamma(shape + 1.0, 1.0)
82
- w = uniform
83
- return scale * g * (w ** (1.0 / shape))
84
- end
89
+ end while !condition2
90
+
91
+ scale * d * v
85
92
  end
86
93
 
87
94
  def chi_square(degrees_of_freedom)
@@ -93,34 +100,36 @@ class SimpleRandom
93
100
  end
94
101
 
95
102
  def beta(a, b)
96
- raise "Alpha and beta parameters must be positive. Received a = #{a} and b = #{b}." unless a > 0 && b > 0
103
+ fail ArgumentError, "Parameters must be strictly positive" unless a > 0 && b > 0
97
104
  u = gamma(a, 1)
98
105
  v = gamma(b, 1)
99
106
  u / (u + v)
100
107
  end
101
108
 
102
109
  def weibull(shape, scale)
103
- raise 'Shape and scale must be positive' if shape <= 0.0 || scale <= 0.0
110
+ fail ArgumentError, 'Shape and scale must be positive' unless shape > 0 && scale > 0
104
111
 
105
112
  scale * ((-Math.log(uniform)) ** (1.0 / shape))
106
113
  end
107
114
 
108
115
  def cauchy(median, scale)
109
- raise 'Scale must be positive' if scale <= 0
116
+ fail ArgumentError, 'Scale must be positive' unless scale > 0
110
117
 
111
118
  median + scale * Math.tan(Math::PI * (uniform - 0.5))
112
119
  end
113
120
 
114
121
  def student_t(degrees_of_freedom)
115
- raise 'Degrees of freedom must be positive' if degrees_of_freedom <= 0
122
+ fail ArgumentError, 'Degrees of freedom must be strictly positive' unless degrees_of_freedom > 0
116
123
 
117
124
  normal / ((chi_square(degrees_of_freedom) / degrees_of_freedom) ** 0.5)
118
125
  end
119
126
 
120
127
  def laplace(mean, scale)
121
- u_1 = uniform
128
+ u_1 = uniform(-0.5, 0.5)
122
129
  u_2 = uniform
123
- mean + ((u_1 < 0.5 ? 1 : -1) * scale * Math.log( 1-2*(u_2-0.5).abs))
130
+
131
+ sign = u_1 / u_1.abs
132
+ mean + sign * scale * Math.log(1 - u_2)
124
133
  end
125
134
 
126
135
  def log_normal(mu, sigma)
@@ -144,65 +153,96 @@ class SimpleRandom
144
153
  ((@m_z << 16) + (@m_w & 65535)) % 4294967296
145
154
  end
146
155
 
147
- def gamma_function(x)
148
- g = [
149
- 1.0,
150
- 0.5772156649015329,
151
- -0.6558780715202538,
152
- -0.420026350340952e-1,
153
- 0.1665386113822915,
154
- -0.421977345555443e-1,
155
- -0.9621971527877e-2,
156
- 0.7218943246663e-2,
157
- -0.11651675918591e-2,
158
- -0.2152416741149e-3,
159
- 0.1280502823882e-3,
160
- -0.201348547807e-4,
161
- -0.12504934821e-5,
162
- 0.1133027232e-5,
163
- -0.2056338417e-6,
164
- 0.6116095e-8,
165
- 0.50020075e-8,
166
- -0.11812746e-8,
167
- 0.1043427e-9,
168
- 0.77823e-11,
169
- -0.36968e-11,
170
- 0.51e-12,
171
- -0.206e-13,
172
- -0.54e-14,
173
- 0.14e-14
174
- ]
175
-
176
- r = 1.0
156
+ def validate_seeds!(*args)
157
+ return true if args.compact.empty?
158
+
159
+ unless args[0].to_f > 0
160
+ fail InvalidSeedArgument, 'Seeds must be strictly positive'
161
+ end
162
+
163
+ unless args[1].nil? || args[1].to_f > 0
164
+ fail InvalidSeedArgument, 'Seeds must be strictly positive'
165
+ end
177
166
 
167
+ true
168
+ end
169
+
170
+ def generate_temporal_seed(timestamp = Time.now)
171
+ x = (timestamp.to_f * 1000000).to_i
172
+
173
+ [x >> 16, x % 4294967296]
174
+ end
175
+
176
+ def gamma_function(x)
178
177
  return 1e308 if x > 171.0
179
- if x.is_a?(Fixnum) || x == x.to_i
180
- if x > 0
181
- ga = (2...x).inject(1.0) { |prod, i| prod * i }
182
- else
183
- 1e308
184
- end
178
+
179
+ if x.to_f == x.to_i
180
+ return unless x > 0
181
+ return 1 if x.to_i == 1
182
+
183
+ (1...x).inject(&:*)
185
184
  else
186
- if x.abs > 1.0
187
- r = (1..(x.abs.to_i)).inject(1.0) { |prod, i| prod * (x.abs - i) }
188
- z = x.abs - x.abs.to_i
185
+ z = if x.abs > 1.0
186
+ x.abs - x.abs.to_i
189
187
  else
190
- z = x
188
+ x
191
189
  end
192
190
 
193
- gr = g[24]
194
- 23.downto(0).each do |i|
195
- gr = gr * z + g[i]
191
+ gr = GAMMA_VALUES.inject(GAMMA_NAUGHT) do |sum, g|
192
+ sum * z + g
196
193
  end
197
- ga = 1.0 / (gr * z)
198
- if x.abs > 1
199
- ga *= r
200
- if x < 0
201
- ga = -Math::PI / (x * ga * Math.sin(Math::PI * x))
202
- end
194
+
195
+ r = if x.abs > 1
196
+ (1..(x.abs.to_i)).inject(1.0) { |prod, i| prod * (x.abs - i) }
197
+ else
198
+ 1.0
203
199
  end
204
- end
205
200
 
206
- ga
201
+ if x < 0 && x.abs > 1
202
+ -Math::PI * gr * z / (x * r * Math.sin(Math::PI * x))
203
+ else
204
+ r / (gr * z)
205
+ end
206
+ end
207
207
  end
208
+
209
+ def ensure_32bit_seeds!
210
+ @m_w = @m_w.to_i % I_32_BIT
211
+ @m_z = @m_z.to_i % I_32_BIT
212
+ end
213
+
214
+ def determine_seeds(*args)
215
+ return generate_temporal_seed(args.first || Time.now) if args.empty? || args.first.respond_to?(:iso8601)
216
+ return [DEFAULT_SEEDS.first, args.first] if args.size < 2
217
+ args[0..1]
218
+ end
219
+
220
+ GAMMA_NAUGHT = 0.14e-14
221
+
222
+ GAMMA_VALUES = [
223
+ -5.4e-15,
224
+ -2.06e-14,
225
+ 5.1e-13,
226
+ -3.6968e-12,
227
+ 7.7823e-12,
228
+ 1.043427e-10,
229
+ -1.1812746e-09,
230
+ 5.0020075e-09,
231
+ 6.116095e-09,
232
+ -2.056338417e-07,
233
+ 1.133027232e-06,
234
+ -1.2504934821e-06,
235
+ -2.01348547807e-05,
236
+ 0.0001280502823882,
237
+ -0.0002152416741149,
238
+ -0.0011651675918591,
239
+ 0.007218943246663,
240
+ -0.009621971527877,
241
+ -0.0421977345555443,
242
+ 0.1665386113822915,
243
+ -0.0420026350340952,
244
+ -0.6558780715202538,
245
+ 0.5772156649015329,
246
+ 1.0
247
+ ]
208
248
  end
data/lib/simple-random.rb CHANGED
@@ -1,2 +1,2 @@
1
- require 'simple-random/simple_random'
2
- require 'simple-random/multi_threaded_simple_random'
1
+ require File.join(File.dirname(__FILE__), 'simple-random', 'simple_random')
2
+ require File.join(File.dirname(__FILE__), 'simple-random', 'multi_threaded_simple_random')
@@ -6,12 +6,12 @@
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "simple-random"
9
- s.version = "1.0.2"
9
+ s.version = "1.0.4"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib"]
13
13
  s.authors = ["John D. Cook", "Jason Adams"]
14
- s.date = "2015-11-24"
14
+ s.date = "2026-02-18"
15
15
  s.description = "Simple Random Number Generator including Beta, Cauchy, Chi square, Exponential, Gamma, Inverse Gamma, Laplace (double exponential), Normal, Student t, Uniform, and Weibull. Ported from John D. Cook's C# Code."
16
16
  s.email = "jasonmadams@gmail.com"
17
17
  s.extra_rdoc_files = [
@@ -22,7 +22,6 @@ Gem::Specification.new do |s|
22
22
  ".document",
23
23
  ".travis.yml",
24
24
  "Gemfile",
25
- "Gemfile.lock",
26
25
  "LICENSE",
27
26
  "README.md",
28
27
  "Rakefile",
@@ -45,23 +44,17 @@ Gem::Specification.new do |s|
45
44
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
46
45
  s.add_development_dependency(%q<minitest>, [">= 0"])
47
46
  s.add_development_dependency(%q<shoulda>, [">= 0"])
48
- s.add_development_dependency(%q<rdoc>, ["~> 3.12"])
49
- s.add_development_dependency(%q<bundler>, ["~> 1.0"])
50
47
  s.add_development_dependency(%q<jeweler>, ["~> 2.0.1"])
51
48
  s.add_development_dependency(%q<simplecov>, [">= 0"])
52
49
  else
53
50
  s.add_dependency(%q<minitest>, [">= 0"])
54
51
  s.add_dependency(%q<shoulda>, [">= 0"])
55
- s.add_dependency(%q<rdoc>, ["~> 3.12"])
56
- s.add_dependency(%q<bundler>, ["~> 1.0"])
57
52
  s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
58
53
  s.add_dependency(%q<simplecov>, [">= 0"])
59
54
  end
60
55
  else
61
56
  s.add_dependency(%q<minitest>, [">= 0"])
62
57
  s.add_dependency(%q<shoulda>, [">= 0"])
63
- s.add_dependency(%q<rdoc>, ["~> 3.12"])
64
- s.add_dependency(%q<bundler>, ["~> 1.0"])
65
58
  s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
66
59
  s.add_dependency(%q<simplecov>, [">= 0"])
67
60
  end
data/test/helper.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'simplecov'
2
+ require 'awesome_print'
2
3
 
3
4
  module SimpleCov::Configuration
4
5
  def clean_filters
@@ -33,4 +34,4 @@ require 'simple-random'
33
34
  class MiniTest::Test
34
35
  end
35
36
 
36
- MiniTest.autorun
37
+ MiniTest.autorun
@@ -12,7 +12,7 @@ end
12
12
  class Array
13
13
  def mean
14
14
  if size > 0
15
- inject(0.0) { |sum, i| sum + i } / size.to_f
15
+ inject(&:+) / size.to_f
16
16
  else
17
17
  0.0
18
18
  end
@@ -28,102 +28,72 @@ class Array
28
28
  end
29
29
  end
30
30
 
31
- class TestSimpleRandom < MiniTest::Test
32
- context "A simple random number generator" do
33
- setup do
34
- @r = SimpleRandom.new
35
- end
31
+ def Time.now
32
+ new(2015, 11, 26, 12, 1, 15, '-05:00')
33
+ end
36
34
 
37
- should "generate random numbers from a uniform distribution in the interval (0, 1)" do
38
- SAMPLE_SIZE.times do
39
- u = @r.uniform
40
- assert u < 1
41
- assert u > 0
35
+ class TestSimpleRandom < MiniTest::Test
36
+ context "Setting the seeds for a simple random number generator" do
37
+ context "on initialization" do
38
+ should "assign default seeds when none are specified" do
39
+ r = SimpleRandom.new
40
+ assert r.seeds == SimpleRandom::DEFAULT_SEEDS
42
41
  end
43
- end
44
42
 
45
- should "generate uniformly random numbers with mean approximately 0.5" do
46
- numbers = generate_numbers(@r, :uniform)
47
- epsilon = (0.5 - numbers.mean).abs
48
-
49
- assert epsilon < MAXIMUM_EPSILON
50
- end
51
-
52
- should "generate random numbers from a normal distribution with mean approximately 0" do
53
- numbers = generate_numbers(@r, :normal)
54
- epsilon = (0.0 - numbers.mean).abs
55
-
56
- assert epsilon < MAXIMUM_EPSILON
57
- end
58
-
59
- should "generate random numbers from a normal distribution with sample standard deviation approximately 1" do
60
- numbers = generate_numbers(@r, :normal)
61
- epsilon = (1.0 - numbers.standard_deviation).abs
62
-
63
- assert epsilon < MAXIMUM_EPSILON
64
- end
65
-
66
- should "generate random numbers from an exponential distribution with mean approximately 1" do
67
- numbers = generate_numbers(@r, :exponential)
68
- epsilon = (1.0 - numbers.mean).abs
69
-
70
- assert epsilon < MAXIMUM_EPSILON
71
- end
43
+ should "assign the seeds specified in the initializer" do
44
+ r = SimpleRandom.new(1, 2)
45
+ assert r.seeds == [1, 2]
46
+ end
72
47
 
73
- should "generate random numbers from triangular(0, 1, 1) in the range [0, 1]" do
74
- SAMPLE_SIZE.times do
75
- t = @r.triangular(0.0, 1.0, 1.0)
76
- assert t <= 1.0
77
- assert t >= 0.0
48
+ should "reject negative seed values" do
49
+ assert_raises SimpleRandom::InvalidSeedArgument do
50
+ SimpleRandom.new(-1, 3)
51
+ end
78
52
  end
79
53
  end
80
54
 
81
- should "generate random numbers from triangular(0, 1, 1) with mean approximately 0.66" do
82
- a = 0.0
83
- c = 1.0
84
- b = 1.0
85
- numbers = generate_numbers(@r, :triangular, a, c, b)
86
- mean = (a + b + c) / 3
87
- epsilon = (mean - numbers.mean).abs
88
-
89
- assert epsilon < MAXIMUM_EPSILON
90
- end
55
+ context 'after initialization' do
56
+ setup do
57
+ @r = SimpleRandom.new
58
+ end
91
59
 
92
- should "generate random numbers from triangular(0, 1, 1) with standard deviation approximately 0.23" do
93
- a = 0.0
94
- c = 1.0
95
- b = 1.0
96
- numbers = generate_numbers(@r, :triangular, a, c, b)
97
- std_dev = Math.sqrt((a**2 + b**2 + c**2 - a*b - a*c - b*c) / 18)
98
- epsilon = (std_dev - numbers.standard_deviation).abs
60
+ should "accept a single value and leave the first seed the same" do
61
+ @r.seeds = 1
62
+ assert @r.seeds == [521288629, 1]
63
+ end
99
64
 
100
- assert epsilon < MAXIMUM_EPSILON
101
- end
65
+ should "update the seeds when given an array of values" do
66
+ @r.seeds = [1, 2]
67
+ assert @r.seeds == [1, 2]
68
+ end
102
69
 
103
- should "generate a random number sampled from a gamma distribution" do
104
- assert @r.gamma(5, 2.3)
105
- end
70
+ should "accept a timestamp instead of an numeric value" do
71
+ @r.seeds = Time.parse('2015-01-01T00:00:00.000-0500')
72
+ assert @r.seeds == [193992865, 413250560]
73
+ end
106
74
 
107
- should "generate a random number sampled from an inverse gamma distribution" do
108
- assert @r.inverse_gamma(5, 2.3)
75
+ should "use the current timestamp when nothing is specified" do
76
+ @r.seeds = nil
77
+ assert @r.seeds == [628393424, 2245012672]
78
+ end
109
79
  end
110
80
 
111
- should "generate a random number sampled from a beta distribution" do
112
- assert @r.beta(5, 2.3)
113
- end
81
+ should "provide different results with different integer seeds" do
82
+ r1 = SimpleRandom.new
83
+ r1.set_seed(2)
84
+ r2 = SimpleRandom.new
85
+ r2.set_seed(1234512343214134)
114
86
 
115
- should "generate a random number sampled from a chi-square distribution" do
116
- assert @r.chi_square(10)
117
- end
87
+ r1_randoms = 100.times.map { r1.uniform(0, 10).floor }
88
+ r2_randoms = 100.times.map { r2.uniform(0, 10).floor }
118
89
 
119
- should "generate a random number using weibull" do
120
- assert @r.weibull(5, 2.3)
90
+ assert r1_randoms != r2_randoms
121
91
  end
122
92
  end
123
93
 
124
- context "A multi-threaded simple random number generator" do
94
+ context "A simple random number generator" do
125
95
  setup do
126
- @r = MultiThreadedSimpleRandom.instance
96
+ @r = SimpleRandom.new
127
97
  end
128
98
 
129
99
  should "generate random numbers from a uniform distribution in the interval (0, 1)" do
@@ -159,7 +129,7 @@ class TestSimpleRandom < MiniTest::Test
159
129
  numbers = generate_numbers(@r, :exponential)
160
130
  epsilon = (1.0 - numbers.mean).abs
161
131
 
162
- assert epsilon < MAXIMUM_EPSILON * 2
132
+ assert epsilon < MAXIMUM_EPSILON
163
133
  end
164
134
 
165
135
  should "generate random numbers from triangular(0, 1, 1) in the range [0, 1]" do
@@ -183,30 +153,37 @@ class TestSimpleRandom < MiniTest::Test
183
153
 
184
154
  should "generate random numbers from triangular(0, 1, 1) with standard deviation approximately 0.23" do
185
155
  a = 0.0
186
- c = 1.0
187
156
  b = 1.0
188
- numbers = generate_numbers(@r, :triangular, a, c, b)
189
- std_dev = Math.sqrt((a**2 + b**2 + c**2 - a*b - a*c - b*c) / 18)
157
+ c = 1.0
158
+ numbers = generate_numbers(@r, :triangular, a, b, c)
159
+ std_dev = Math.sqrt((a ** 2 + b ** 2 + c ** 2 - a * b - a * c - b * c) / 18)
190
160
  epsilon = (std_dev - numbers.standard_deviation).abs
191
161
 
192
162
  assert epsilon < MAXIMUM_EPSILON
193
163
  end
194
164
 
195
- should "generate random numbers from laplace(0, 1) with mean approximately 0" do
196
- mean = 0.0
197
- scale = 0.1
198
- numbers = generate_numbers(@r, :laplace, mean, scale)
165
+ should "generate random numbers from triangular(0, 0.5, 1) with mean approximately 0.5" do
166
+ a = 0.0
167
+ b = 0.5
168
+ c = 1.0
169
+
170
+ numbers = generate_numbers(@r, :triangular, a, b, c)
171
+ mean = (a + b + c) / 3
199
172
  epsilon = (mean - numbers.mean).abs
200
173
 
201
174
  assert epsilon < MAXIMUM_EPSILON
202
175
  end
203
-
176
+
204
177
  should "generate a random number sampled from a gamma distribution" do
205
178
  assert @r.gamma(5, 2.3)
179
+ assert @r.gamma(5.3, 2.7)
180
+ assert @r.gamma(2.3, 2)
206
181
  end
207
182
 
208
183
  should "generate a random number sampled from an inverse gamma distribution" do
209
184
  assert @r.inverse_gamma(5, 2.3)
185
+ assert @r.inverse_gamma(5.7, 2.8)
186
+ assert @r.inverse_gamma(3.2, 2)
210
187
  end
211
188
 
212
189
  should "generate a random number sampled from a beta distribution" do
@@ -221,6 +198,25 @@ class TestSimpleRandom < MiniTest::Test
221
198
  assert @r.weibull(5, 2.3)
222
199
  end
223
200
 
201
+ should "generate random number from a dirichlet distribution" do
202
+ assert @r.dirichlet(5.3, 2.7)
203
+ end
204
+
205
+ should "generate random numbers from laplace(0, 1) with mean approximately 0" do
206
+ mean = 0.0
207
+ scale = 0.1
208
+ numbers = generate_numbers(@r, :laplace, mean, scale)
209
+ epsilon = (mean - numbers.mean).abs
210
+
211
+ assert epsilon < MAXIMUM_EPSILON
212
+ end
213
+ end
214
+
215
+ context "A multi-threaded simple random number generator" do
216
+ setup do
217
+ @r = MultiThreadedSimpleRandom.instance
218
+ end
219
+
224
220
  should "work independently in every thread" do
225
221
  sample_count = 10
226
222
  thread_count = 10
@@ -241,17 +237,5 @@ class TestSimpleRandom < MiniTest::Test
241
237
  assert samples.size == thread_count
242
238
  assert samples.uniq.size == 1
243
239
  end
244
-
245
- should "provide different results with different integer seeds" do
246
- r1 = SimpleRandom.new
247
- r1.set_seed(2)
248
- r2 = SimpleRandom.new
249
- r2.set_seed(1234512343214134)
250
-
251
- r1_randoms = 100.times.map { r1.uniform(0, 10).floor }
252
- r2_randoms = 100.times.map { r2.uniform(0, 10).floor }
253
-
254
- assert r1_randoms != r2_randoms
255
- end
256
240
  end
257
241
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple-random
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - John D. Cook
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-11-24 00:00:00.000000000 Z
12
+ date: 2026-02-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: minitest
@@ -39,34 +39,6 @@ dependencies:
39
39
  - - ">="
40
40
  - !ruby/object:Gem::Version
41
41
  version: '0'
42
- - !ruby/object:Gem::Dependency
43
- name: rdoc
44
- requirement: !ruby/object:Gem::Requirement
45
- requirements:
46
- - - "~>"
47
- - !ruby/object:Gem::Version
48
- version: '3.12'
49
- type: :development
50
- prerelease: false
51
- version_requirements: !ruby/object:Gem::Requirement
52
- requirements:
53
- - - "~>"
54
- - !ruby/object:Gem::Version
55
- version: '3.12'
56
- - !ruby/object:Gem::Dependency
57
- name: bundler
58
- requirement: !ruby/object:Gem::Requirement
59
- requirements:
60
- - - "~>"
61
- - !ruby/object:Gem::Version
62
- version: '1.0'
63
- type: :development
64
- prerelease: false
65
- version_requirements: !ruby/object:Gem::Requirement
66
- requirements:
67
- - - "~>"
68
- - !ruby/object:Gem::Version
69
- version: '1.0'
70
42
  - !ruby/object:Gem::Dependency
71
43
  name: jeweler
72
44
  requirement: !ruby/object:Gem::Requirement
@@ -108,7 +80,6 @@ files:
108
80
  - ".document"
109
81
  - ".travis.yml"
110
82
  - Gemfile
111
- - Gemfile.lock
112
83
  - LICENSE
113
84
  - README.md
114
85
  - Rakefile
@@ -138,8 +109,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
138
109
  - !ruby/object:Gem::Version
139
110
  version: '0'
140
111
  requirements: []
141
- rubyforge_project:
142
- rubygems_version: 2.4.5.1
112
+ rubygems_version: 3.0.3.1
143
113
  signing_key:
144
114
  specification_version: 4
145
115
  summary: Simple Random Number Generator
data/Gemfile.lock DELETED
@@ -1,81 +0,0 @@
1
- GEM
2
- remote: http://rubygems.org/
3
- specs:
4
- activesupport (4.1.4)
5
- i18n (~> 0.6, >= 0.6.9)
6
- json (~> 1.7, >= 1.7.7)
7
- minitest (~> 5.1)
8
- thread_safe (~> 0.1)
9
- tzinfo (~> 1.1)
10
- addressable (2.3.6)
11
- builder (3.2.2)
12
- descendants_tracker (0.0.4)
13
- thread_safe (~> 0.3, >= 0.3.1)
14
- docile (1.1.5)
15
- faraday (0.9.0)
16
- multipart-post (>= 1.2, < 3)
17
- git (1.2.7)
18
- github_api (0.11.3)
19
- addressable (~> 2.3)
20
- descendants_tracker (~> 0.0.1)
21
- faraday (~> 0.8, < 0.10)
22
- hashie (>= 1.2)
23
- multi_json (>= 1.7.5, < 2.0)
24
- nokogiri (~> 1.6.0)
25
- oauth2
26
- hashie (3.1.0)
27
- highline (1.6.21)
28
- i18n (0.6.9)
29
- jeweler (2.0.1)
30
- builder
31
- bundler (>= 1.0)
32
- git (>= 1.2.5)
33
- github_api
34
- highline (>= 1.6.15)
35
- nokogiri (>= 1.5.10)
36
- rake
37
- rdoc
38
- json (1.8.1)
39
- jwt (1.0.0)
40
- mini_portile (0.6.0)
41
- minitest (5.4.0)
42
- multi_json (1.10.1)
43
- multi_xml (0.5.5)
44
- multipart-post (2.0.0)
45
- nokogiri (1.6.2.1)
46
- mini_portile (= 0.6.0)
47
- oauth2 (0.9.4)
48
- faraday (>= 0.8, < 0.10)
49
- jwt (~> 1.0)
50
- multi_json (~> 1.3)
51
- multi_xml (~> 0.5)
52
- rack (~> 1.2)
53
- rack (1.5.2)
54
- rake (10.3.2)
55
- rdoc (3.12.2)
56
- json (~> 1.4)
57
- shoulda (3.5.0)
58
- shoulda-context (~> 1.0, >= 1.0.1)
59
- shoulda-matchers (>= 1.4.1, < 3.0)
60
- shoulda-context (1.2.1)
61
- shoulda-matchers (2.6.1)
62
- activesupport (>= 3.0.0)
63
- simplecov (0.8.2)
64
- docile (~> 1.1.0)
65
- multi_json
66
- simplecov-html (~> 0.8.0)
67
- simplecov-html (0.8.0)
68
- thread_safe (0.3.4)
69
- tzinfo (1.2.1)
70
- thread_safe (~> 0.1)
71
-
72
- PLATFORMS
73
- ruby
74
-
75
- DEPENDENCIES
76
- bundler (~> 1.0)
77
- jeweler (~> 2.0.1)
78
- minitest
79
- rdoc (~> 3.12)
80
- shoulda
81
- simplecov