fibonacci_rng 1.2.5 → 2.0.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.
- checksums.yaml +4 -4
- data/README.md +21 -0
- data/fibonacci_rng.gemspec +4 -5
- data/lib/fibonacci_rng.rb +1 -0
- data/lib/fibonacci_rng/generator.rb +5 -0
- data/lib/fibonacci_rng/hasher.rb +2 -0
- data/lib/fibonacci_rng/spinner.rb +2 -0
- data/lib/fibonacci_rng/validate.rb +18 -0
- data/lib/fibonacci_rng/version.rb +1 -1
- data/prng.rb +4 -1
- data/tests/fibinacci_rng_tests.rb +289 -251
- data/tools/torture_test.rb +27 -0
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dff4345e5771a9194053e94d27556d1fee55e67c
|
4
|
+
data.tar.gz: 719c15db8a33d8308a41175ea371923e55d3352f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 11c14fa2466aaffdc31e98f67c6d930c204e27dbc1c2c5f43efa7bfba111912f4ee24c993b7850ed0396697016aa1189704c0130cebadf1795bd49e8f1d6251c
|
7
|
+
data.tar.gz: dd5df2c9398baeb1fd6b25c5ee499895c5125fd910c03f2ad87dd7f47019b72fabe92939564b2db17ac361f7641eccb54088cef52cee6b0e94c0611c45793819
|
data/README.md
CHANGED
@@ -268,6 +268,27 @@ TOP = 0x10000000
|
|
268
268
|
|
269
269
|
```
|
270
270
|
|
271
|
+
## Error Detection
|
272
|
+
|
273
|
+
Like all systems, the fibonacci random number generator has a failure mode. If
|
274
|
+
it should happen that all the internal data registers have a value of zero, the
|
275
|
+
generator will be trapped in an endless state of zero output. It will cease to
|
276
|
+
operate as a pseudo random number generator.
|
277
|
+
|
278
|
+
While it is possible to show that this cannot occur in small generators, the
|
279
|
+
case for larger ones is more difficult to analyze. To this end, the code now
|
280
|
+
incorporates a test that at least one non-zero register is present. If this
|
281
|
+
test should fail an exception "InvalidFibonacciRngState" is raised so that
|
282
|
+
the application can take appropriate action.
|
283
|
+
|
284
|
+
To date, torture testing of the generator has yielded no failures, but this is
|
285
|
+
not a proof that one cannot happen.
|
286
|
+
|
287
|
+
The test scans the registers until it finds a non-zero value. This means that
|
288
|
+
it almost always only needs to look at one register, saving a great deal of
|
289
|
+
execution time.
|
290
|
+
|
291
|
+
|
271
292
|
## Contributing
|
272
293
|
|
273
294
|
Creating a good pseudo random number generator is quite an undertaking. For
|
data/fibonacci_rng.gemspec
CHANGED
@@ -9,10 +9,9 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Peter Camilleri"]
|
10
10
|
spec.email = ["peter.c.camilleri@gmail.com"]
|
11
11
|
spec.homepage = "https://github.com/PeterCamilleri/fibonacci_rng"
|
12
|
-
spec.description = "A Fibonacci inspired pseudo random number generator
|
13
|
-
"
|
14
|
-
|
15
|
-
spec.summary = "[Updated] A Fibonacci inspired pseudo random number generator."
|
12
|
+
spec.description = "A Fibonacci inspired pseudo random number generator " +
|
13
|
+
"with error detection."
|
14
|
+
spec.summary = "A Fibonacci inspired pseudo random number generator."
|
16
15
|
spec.license = "MIT"
|
17
16
|
|
18
17
|
raw_list = `git ls-files`.split($/)
|
@@ -20,7 +19,7 @@ Gem::Specification.new do |spec|
|
|
20
19
|
|
21
20
|
spec.files = raw_list
|
22
21
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
23
|
-
spec.test_files = spec.files.grep(%r{^(test
|
22
|
+
spec.test_files = spec.files.grep(%r{^(test)/})
|
24
23
|
spec.require_paths = ["lib"]
|
25
24
|
|
26
25
|
spec.required_ruby_version = '>= 1.9.3'
|
data/lib/fibonacci_rng.rb
CHANGED
@@ -4,6 +4,7 @@ require_relative "fibonacci_rng/seeder"
|
|
4
4
|
require_relative "fibonacci_rng/hasher"
|
5
5
|
require_relative "fibonacci_rng/spinner"
|
6
6
|
require_relative "fibonacci_rng/generator"
|
7
|
+
require_relative "fibonacci_rng/validate"
|
7
8
|
require_relative "fibonacci_rng/version"
|
8
9
|
|
9
10
|
#The class of Fibonacci inspired random number generators.
|
@@ -25,12 +25,14 @@ class FibonacciRng
|
|
25
25
|
do_spin
|
26
26
|
end until (value = @buffer[0]) < limit
|
27
27
|
|
28
|
+
validate
|
28
29
|
value % sides
|
29
30
|
end
|
30
31
|
|
31
32
|
#Get a pseudo random byte
|
32
33
|
def byte
|
33
34
|
do_spin
|
35
|
+
validate
|
34
36
|
@buffer[0] & BYTE
|
35
37
|
end
|
36
38
|
|
@@ -44,12 +46,14 @@ class FibonacciRng
|
|
44
46
|
#Get a pseudo random word
|
45
47
|
def word
|
46
48
|
do_spin
|
49
|
+
validate
|
47
50
|
@buffer[0] & WORD
|
48
51
|
end
|
49
52
|
|
50
53
|
#Get a pseudo random float
|
51
54
|
def float
|
52
55
|
do_spin
|
56
|
+
validate
|
53
57
|
raw_float / BASE
|
54
58
|
end
|
55
59
|
|
@@ -58,6 +62,7 @@ class FibonacciRng
|
|
58
62
|
do_spin
|
59
63
|
part_one = raw_float * BASE
|
60
64
|
do_spin
|
65
|
+
validate
|
61
66
|
(part_one + raw_float) / DOUBLE
|
62
67
|
end
|
63
68
|
|
data/lib/fibonacci_rng/hasher.rb
CHANGED
@@ -0,0 +1,18 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
# The class of RNG errors.
|
4
|
+
class InvalidFibonacciRngState < RuntimeError; end
|
5
|
+
|
6
|
+
#The class of Fibonacci inspired random number generators.
|
7
|
+
class FibonacciRng
|
8
|
+
|
9
|
+
#Validate the sanity of the generator.
|
10
|
+
def validate
|
11
|
+
@buffer.each do |element|
|
12
|
+
return true unless element.zero?
|
13
|
+
end
|
14
|
+
|
15
|
+
fail InvalidFibonacciRngState
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
data/prng.rb
CHANGED
@@ -21,7 +21,7 @@ module PrngTestSuite
|
|
21
21
|
puts "Where:"
|
22
22
|
puts " <locn> fib code location, either 'gem' or 'local'"
|
23
23
|
puts " <gen> select a generator, either 'fib' or 'int'"
|
24
|
-
puts " <test> select
|
24
|
+
puts " <test> select one of 'chisq', 'auto', 'scatter', or 'torture'"
|
25
25
|
puts " <max> the number of bins to test (2..65535)"
|
26
26
|
puts " <count> the number of samples to test (1..1000000)"
|
27
27
|
puts
|
@@ -45,6 +45,7 @@ require_relative 'tools/internal_rng'
|
|
45
45
|
require_relative 'tools/chi_squared'
|
46
46
|
require_relative 'tools/auto_corr'
|
47
47
|
require_relative 'tools/scatter_plot'
|
48
|
+
require_relative 'tools/torture_test'
|
48
49
|
|
49
50
|
module PrngTestSuite
|
50
51
|
|
@@ -63,6 +64,8 @@ module PrngTestSuite
|
|
63
64
|
tester = AutoCorrelator.new
|
64
65
|
elsif ARGV[2] == 'scatter'
|
65
66
|
tester = ScatterPlot.new
|
67
|
+
elsif ARGV[2] == 'torture'
|
68
|
+
tester = TortureTest.new
|
66
69
|
else
|
67
70
|
PrngTestSuite.usage "Error: missing or invalid test parameter."
|
68
71
|
end
|
@@ -1,251 +1,289 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
require_relative '../lib/fibonacci_rng'
|
4
|
-
gem 'minitest'
|
5
|
-
require 'minitest/autorun'
|
6
|
-
require 'minitest_visible'
|
7
|
-
|
8
|
-
#Test the monkey patches applied to the Object class.
|
9
|
-
class FibonacciRngTester < Minitest::Test
|
10
|
-
|
11
|
-
#Track mini-test progress.
|
12
|
-
include MinitestVisible
|
13
|
-
|
14
|
-
def test_how_we_build_generators
|
15
|
-
gen = FibonacciRng.new
|
16
|
-
|
17
|
-
assert_equal(
|
18
|
-
assert_equal(
|
19
|
-
|
20
|
-
gen
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
assert_equal(
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
gen
|
31
|
-
assert_equal(12, gen.depth)
|
32
|
-
assert_equal('seed', gen.seed)
|
33
|
-
assert_equal(
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
gen
|
38
|
-
assert_equal(
|
39
|
-
assert_equal('seed', gen.seed)
|
40
|
-
assert_equal(
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
assert_equal(
|
49
|
-
assert_equal(
|
50
|
-
|
51
|
-
|
52
|
-
gen = FibonacciRng.new(depth: 12
|
53
|
-
|
54
|
-
assert_equal(
|
55
|
-
assert_equal(
|
56
|
-
|
57
|
-
gen
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
end
|
99
|
-
|
100
|
-
def
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
#
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
0.
|
239
|
-
0.
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require_relative '../lib/fibonacci_rng'
|
4
|
+
gem 'minitest'
|
5
|
+
require 'minitest/autorun'
|
6
|
+
require 'minitest_visible'
|
7
|
+
|
8
|
+
#Test the monkey patches applied to the Object class.
|
9
|
+
class FibonacciRngTester < Minitest::Test
|
10
|
+
|
11
|
+
#Track mini-test progress.
|
12
|
+
include MinitestVisible
|
13
|
+
|
14
|
+
def test_how_we_build_generators
|
15
|
+
gen = FibonacciRng.new
|
16
|
+
assert(gen.validate)
|
17
|
+
assert_equal(8, gen.depth)
|
18
|
+
assert_equal(String, gen.seed.class)
|
19
|
+
assert_equal(1024, gen.init)
|
20
|
+
assert(gen.validate)
|
21
|
+
|
22
|
+
gen = FibonacciRng.new('seed')
|
23
|
+
assert(gen.validate)
|
24
|
+
assert_equal(8, gen.depth)
|
25
|
+
assert_equal('seed', gen.seed)
|
26
|
+
assert_equal(1024, gen.init)
|
27
|
+
assert(gen.validate)
|
28
|
+
|
29
|
+
gen = FibonacciRng.new('seed', 12)
|
30
|
+
assert(gen.validate)
|
31
|
+
assert_equal(12, gen.depth)
|
32
|
+
assert_equal('seed', gen.seed)
|
33
|
+
assert_equal(1152, gen.init)
|
34
|
+
assert(gen.validate)
|
35
|
+
|
36
|
+
gen = FibonacciRng.new('seed', 12, 2048)
|
37
|
+
assert(gen.validate)
|
38
|
+
assert_equal(12, gen.depth)
|
39
|
+
assert_equal('seed', gen.seed)
|
40
|
+
assert_equal(2048, gen.init)
|
41
|
+
assert(gen.validate)
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_building_with_keywords
|
45
|
+
gen = FibonacciRng.new(seed: 'seed')
|
46
|
+
assert(gen.validate)
|
47
|
+
assert_equal(8, gen.depth)
|
48
|
+
assert_equal('seed', gen.seed)
|
49
|
+
assert_equal(1024, gen.init)
|
50
|
+
assert(gen.validate)
|
51
|
+
|
52
|
+
gen = FibonacciRng.new(depth: 12)
|
53
|
+
assert(gen.validate)
|
54
|
+
assert_equal(12, gen.depth)
|
55
|
+
assert_equal(String, gen.seed.class)
|
56
|
+
assert_equal(1152, gen.init)
|
57
|
+
assert(gen.validate)
|
58
|
+
|
59
|
+
gen = FibonacciRng.new(seed: 'seed', depth: 12)
|
60
|
+
assert(gen.validate)
|
61
|
+
assert_equal(12, gen.depth)
|
62
|
+
assert_equal('seed', gen.seed)
|
63
|
+
assert_equal(1152, gen.init)
|
64
|
+
assert(gen.validate)
|
65
|
+
|
66
|
+
gen = FibonacciRng.new(depth: 12, seed: 'seed')
|
67
|
+
assert(gen.validate)
|
68
|
+
assert_equal(12, gen.depth)
|
69
|
+
assert_equal('seed', gen.seed)
|
70
|
+
assert_equal(1152, gen.init)
|
71
|
+
assert(gen.validate)
|
72
|
+
|
73
|
+
gen = FibonacciRng.new(seed: 'seed', init: 2048)
|
74
|
+
assert(gen.validate)
|
75
|
+
assert_equal('seed', gen.seed)
|
76
|
+
assert_equal(2048, gen.init)
|
77
|
+
assert(gen.validate)
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_that_it_detects_fatal_conditions
|
81
|
+
gen = FibonacciRng.new
|
82
|
+
assert(gen.validate)
|
83
|
+
|
84
|
+
gen.define_singleton_method(:kill) do
|
85
|
+
@buffer = Array.new(@buffer.length, 0)
|
86
|
+
end
|
87
|
+
|
88
|
+
gen.kill #Force a fatal error condition.
|
89
|
+
|
90
|
+
assert_raises(InvalidFibonacciRngState) {gen.validate}
|
91
|
+
assert_raises(InvalidFibonacciRngState) {gen.spin(6)}
|
92
|
+
assert_raises(InvalidFibonacciRngState) {gen.dice(6)}
|
93
|
+
assert_raises(InvalidFibonacciRngState) {gen.byte}
|
94
|
+
assert_raises(InvalidFibonacciRngState) {gen.word}
|
95
|
+
assert_raises(InvalidFibonacciRngState) {gen.float}
|
96
|
+
assert_raises(InvalidFibonacciRngState) {gen.double}
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_that_rejects_bad_parms
|
101
|
+
assert_raises { FibonacciRng.new('seed', 1) }
|
102
|
+
assert_raises { FibonacciRng.new('seed', 65536) }
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_that_it_creates_dice_rolls
|
106
|
+
prng = FibonacciRng.new
|
107
|
+
|
108
|
+
100.times do
|
109
|
+
assert((0...6) === prng.dice(6))
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_that_it_creates_bytes
|
114
|
+
prng = FibonacciRng.new
|
115
|
+
|
116
|
+
100.times do
|
117
|
+
assert((0...256) === prng.byte)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_that_it_creates_words
|
122
|
+
prng = FibonacciRng.new
|
123
|
+
|
124
|
+
100.times do
|
125
|
+
assert((0...65536) === prng.word)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_that_it_creates_floats
|
130
|
+
prng = FibonacciRng.new
|
131
|
+
|
132
|
+
100.times do
|
133
|
+
value = prng.float
|
134
|
+
assert((value >= 0.0) && (value < 1.0))
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_compatible_global_dice_rolls
|
139
|
+
100.times do
|
140
|
+
assert((0...6) === FibonacciRng.rand(6))
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_compatible_global_dice_rolls_range
|
145
|
+
100.times do
|
146
|
+
assert((0...6) === FibonacciRng.rand(0...6))
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def test_compatible_global_floats
|
151
|
+
100.times do
|
152
|
+
value = FibonacciRng.rand(0)
|
153
|
+
assert((value >= 0.0) && (value < 1.0))
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def test_random_string
|
158
|
+
prng = FibonacciRng.new
|
159
|
+
|
160
|
+
rs = prng.bytes(10)
|
161
|
+
|
162
|
+
assert(rs.is_a?(String))
|
163
|
+
assert_equal(10, rs.length)
|
164
|
+
end
|
165
|
+
|
166
|
+
def test_that_it_makes_unique_sequences
|
167
|
+
prnga = FibonacciRng.new
|
168
|
+
prngb = FibonacciRng.new
|
169
|
+
|
170
|
+
buffa = []
|
171
|
+
buffb = []
|
172
|
+
|
173
|
+
100.times do
|
174
|
+
buffa << prnga.dice(6)
|
175
|
+
buffb << prngb.dice(6)
|
176
|
+
end
|
177
|
+
|
178
|
+
assert(buffa != buffb)
|
179
|
+
end
|
180
|
+
|
181
|
+
def test_that_it_makes_repeatable_sequences
|
182
|
+
prnga = FibonacciRng.new(0)
|
183
|
+
prngb = FibonacciRng.new(0)
|
184
|
+
|
185
|
+
buffa = []
|
186
|
+
buffb = []
|
187
|
+
|
188
|
+
100.times do
|
189
|
+
buffa << prnga.dice(6)
|
190
|
+
buffb << prngb.dice(6)
|
191
|
+
end
|
192
|
+
|
193
|
+
assert(buffa == buffb)
|
194
|
+
end
|
195
|
+
|
196
|
+
def test_that_it_creates_unique_seeds
|
197
|
+
result = []
|
198
|
+
10_000.times do
|
199
|
+
result << FibonacciRng.new_seed
|
200
|
+
end
|
201
|
+
|
202
|
+
result.uniq!
|
203
|
+
assert_equal(10_000, result.length)
|
204
|
+
end
|
205
|
+
|
206
|
+
def test_building_strings
|
207
|
+
rng = FibonacciRng.new(0)
|
208
|
+
assert_equal("c}l'(q@g\\z", rng.string(10))
|
209
|
+
assert_equal('2727573312', rng.string(10, '0123456789'))
|
210
|
+
assert_equal('khto lk si', rng.string(10, 'Always look on the bright side of life.'))
|
211
|
+
|
212
|
+
rng = FibonacciRng.new("%s*08^_Tg{NnirtZ-94)q9z2l+~bB5")
|
213
|
+
assert_equal(",-+Idi6~ ~", rng.string(10))
|
214
|
+
assert_equal('5901964804', rng.string(10, '0123456789'))
|
215
|
+
end
|
216
|
+
|
217
|
+
def test_for_data_stability
|
218
|
+
#Make sure incompatibilities do not creep in.
|
219
|
+
expected = [184, 93, 0, 240, 34, 184, 4, 220, 126, 132,
|
220
|
+
13, 67, 166, 107, 165, 66, 68, 120, 102, 110,
|
221
|
+
212, 99, 80, 167, 9, 56, 47, 167, 127, 195,
|
222
|
+
169, 34, 184, 97, 136, 176, 214, 104, 218, 103,
|
223
|
+
180, 16, 83, 204, 128, 81, 63, 56, 237, 165,
|
224
|
+
0, 88, 129, 40, 152, 44, 189, 35, 205, 249,
|
225
|
+
77, 94, 142, 18, 60, 248, 49, 172, 235, 83,
|
226
|
+
84, 65, 181, 117, 16, 170, 222, 97, 130, 217]
|
227
|
+
|
228
|
+
prng = FibonacciRng.new("%s*08^_Tg{NnirtZ-94)q9z2l+~bB5")
|
229
|
+
result = Array.new(80) { prng.byte }
|
230
|
+
assert_equal(expected, result)
|
231
|
+
|
232
|
+
prng.reseed("%s*08^_Tg{NnirtZ-94)q9z2l+~bB5")
|
233
|
+
result = Array.new(80) { prng.byte }
|
234
|
+
assert_equal(expected, result)
|
235
|
+
|
236
|
+
|
237
|
+
expected = [0.466758593916893, 0.8060004059225321,
|
238
|
+
0.8063845634460449, 0.8676037490367889,
|
239
|
+
0.350975576788187, 0.2556227296590805,
|
240
|
+
0.4873242452740669, 0.07484667748212814,
|
241
|
+
0.2968141995370388, 0.5417192056775093,
|
242
|
+
0.4288134817034006, 0.26460993848741055,
|
243
|
+
0.13613684102892876, 0.27074786089360714,
|
244
|
+
0.11685592867434025, 0.814235333353281,
|
245
|
+
0.6137734726071358, 0.9152738898992538,
|
246
|
+
0.6325213424861431, 0.22782298550009727,
|
247
|
+
0.6877559795975685, 0.9354030545800924,
|
248
|
+
0.18385234475135803, 0.5579136144369841,
|
249
|
+
0.7501311469823122, 0.04208622872829437,
|
250
|
+
0.31922253780066967, 0.6471036206930876,
|
251
|
+
0.4305369835346937, 0.2239683922380209,
|
252
|
+
0.9770196247845888, 0.3727417625486851]
|
253
|
+
|
254
|
+
prng.reseed("%s*08^_Tg{NnirtZ-94)q9z2l+~bB5")
|
255
|
+
result = Array.new(32) { prng.float }
|
256
|
+
#assert_equal(expected, result)
|
257
|
+
|
258
|
+
(0...32).each do |i|
|
259
|
+
assert_in_delta(expected[i], result[i], 1.0e-16)
|
260
|
+
end
|
261
|
+
|
262
|
+
expected = [0.46675859541818576, 0.8063845650620829,
|
263
|
+
0.3509755772643215, 0.48732424541347974,
|
264
|
+
0.29681420054606944, 0.428813482196275,
|
265
|
+
0.13613684153323594, 0.11685593019097174,
|
266
|
+
0.6137734743119663, 0.6325213429104964,
|
267
|
+
0.6877559813398925, 0.18385234579055312,
|
268
|
+
0.7501311470607039, 0.31922253900599407,
|
269
|
+
0.43053698395186735, 0.9770196254788744,
|
270
|
+
0.105776653432334, 0.17992045162625886,
|
271
|
+
0.7068137351637119, 0.09374992924495854,
|
272
|
+
0.4741257221497737, 0.2717329622804037,
|
273
|
+
0.6427948478921109, 0.048162101812947195,
|
274
|
+
0.649627174383166, 0.27438020721066836,
|
275
|
+
0.9478733559036244, 0.6199505789910625,
|
276
|
+
0.8043054302444751, 0.9363898295339244,
|
277
|
+
0.6613804354420972, 0.5876014495519649]
|
278
|
+
|
279
|
+
prng.reseed("%s*08^_Tg{NnirtZ-94)q9z2l+~bB5")
|
280
|
+
result = Array.new(32) { prng.double }
|
281
|
+
#assert_equal(expected, result)
|
282
|
+
|
283
|
+
(0...32).each do |i|
|
284
|
+
assert_in_delta(expected[i], result[i], 1.0e-16)
|
285
|
+
end
|
286
|
+
|
287
|
+
end
|
288
|
+
|
289
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
#A Scatter Plot tester
|
4
|
+
class TortureTest
|
5
|
+
|
6
|
+
#Run a scatter plot test on the random number generator.
|
7
|
+
def run(gen, max, count)
|
8
|
+
max *=1000
|
9
|
+
count *=1000
|
10
|
+
|
11
|
+
puts "Starting torture test with #{max} loops of #{count} tests."
|
12
|
+
|
13
|
+
max.times do |i|
|
14
|
+
gen.spin(count)
|
15
|
+
print (i+1).to_s.rjust(8)
|
16
|
+
end
|
17
|
+
|
18
|
+
puts
|
19
|
+
puts "No errors were detected."
|
20
|
+
return
|
21
|
+
|
22
|
+
rescue InvalidFibonacciRngState
|
23
|
+
puts
|
24
|
+
puts "InvalidFibonacciRngState detected."
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fibonacci_rng
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Camilleri
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-09-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -94,8 +94,7 @@ dependencies:
|
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '4.5'
|
97
|
-
description: A Fibonacci inspired pseudo random number generator
|
98
|
-
is changed to use bit rotate instead of bit shift.
|
97
|
+
description: A Fibonacci inspired pseudo random number generator with error detection.
|
99
98
|
email:
|
100
99
|
- peter.c.camilleri@gmail.com
|
101
100
|
executables: []
|
@@ -115,6 +114,7 @@ files:
|
|
115
114
|
- lib/fibonacci_rng/hasher.rb
|
116
115
|
- lib/fibonacci_rng/seeder.rb
|
117
116
|
- lib/fibonacci_rng/spinner.rb
|
117
|
+
- lib/fibonacci_rng/validate.rb
|
118
118
|
- lib/fibonacci_rng/version.rb
|
119
119
|
- prng.rb
|
120
120
|
- rakefile.rb
|
@@ -125,6 +125,7 @@ files:
|
|
125
125
|
- tools/chi_squared.rb
|
126
126
|
- tools/internal_rng.rb
|
127
127
|
- tools/scatter_plot.rb
|
128
|
+
- tools/torture_test.rb
|
128
129
|
homepage: https://github.com/PeterCamilleri/fibonacci_rng
|
129
130
|
licenses:
|
130
131
|
- MIT
|
@@ -145,9 +146,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
145
146
|
version: '0'
|
146
147
|
requirements: []
|
147
148
|
rubyforge_project:
|
148
|
-
rubygems_version: 2.2
|
149
|
+
rubygems_version: 2.5.2
|
149
150
|
signing_key:
|
150
151
|
specification_version: 4
|
151
|
-
summary:
|
152
|
+
summary: A Fibonacci inspired pseudo random number generator.
|
152
153
|
test_files: []
|
153
|
-
has_rdoc:
|