fibonacci_rng 0.4.3 → 1.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 +78 -6
- data/fibonacci_rng.gemspec +4 -2
- data/lib/fibonacci_rng/spinner.rb +2 -1
- data/lib/fibonacci_rng/version.rb +1 -1
- data/lib/fibonacci_rng.rb +1 -0
- data/tests/fibinacci_rng_tests.rb +3 -3
- data/tests/hasher_tests.rb +4 -4
- data/tools/scatter_plot.rb +2 -2
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 92d9ec37d3384e39e3e122ed13281ba8001c8f2a
|
4
|
+
data.tar.gz: df41080f4dc1a92a75028a4f8cce4f94f5c969ed
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7885893e8155ca7b2c59ffd7688dd319a9935288b1796113d7185d263e4caad9c718aabbee84e1c7ca7e6c24bf8a79bbfd68634709c21467b02cb9ba22bb77de
|
7
|
+
data.tar.gz: 3e5cb32a061f12aa8a6218984318509788aea414a69ea4d2149733fd783bcd834bd0a86b7c7e522756cf08bda9fffea7177310c6cb870763c33ad9e437156331
|
data/README.md
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
# FibonacciRng
|
2
2
|
|
3
3
|
This gem implements a random number generator inspired by the famous Fibonacci
|
4
|
-
number sequence.
|
5
|
-
|
4
|
+
number sequence. To be specific, it is a normalized, cyclic Fibonacci pseudo
|
5
|
+
random number generator. So far, this generator has performed quite well when
|
6
|
+
compared to the built-in Ruby random number generator when tested with:
|
6
7
|
|
7
8
|
* A chi-squared test
|
8
9
|
* An auto-correlation test
|
@@ -170,9 +171,83 @@ generator = FibonacciRng.new
|
|
170
171
|
random_bytes = Array.new(len) { generator.byte }
|
171
172
|
```
|
172
173
|
|
174
|
+
## Theory of Operation
|
175
|
+
|
176
|
+
The random number generator used in this gem is based on a modified, cyclic
|
177
|
+
Fibonacci generator. This ring buffer design modifies the simple sequence so
|
178
|
+
that it feeds back onto itself, which in turn gives the appearance of chaos.
|
179
|
+
There is one further required modification however. Since the Fibonacci sequence
|
180
|
+
uses additions, a mechanism for preventing zeros from "swamping" the data, is
|
181
|
+
needed. This is accomplished by rotating one of the arguments to the right by
|
182
|
+
one bit. The basic outline of the generational cycle operation, with depth of
|
183
|
+
N is shown below:
|
184
|
+

|
185
|
+
<br>Notes:
|
186
|
+
* The last two elements are copies of the first two elements before
|
187
|
+
the array was transformed.
|
188
|
+
* Not shown above for brevity, the result of each addition is masked with the
|
189
|
+
value 0x1FFFFFFF before being stored. This masks off any data beyond the low
|
190
|
+
29 bits.
|
191
|
+
|
192
|
+
#### 29 bit Integers?
|
193
|
+
|
194
|
+
The random number generator masks the data in the ring buffer to 29 bit,
|
195
|
+
unsigned values. To understand this, it is first necessary to under why
|
196
|
+
masking is needed at all, and secondly, why this was done at 29 bits.
|
197
|
+
|
198
|
+
Masking at some level is required because it is needed to simulate the numeric
|
199
|
+
overflow of more primitive systems of arithmetic. In most systems, when the
|
200
|
+
limit of an integer is reached, overflow occurs with no error indication. Ruby
|
201
|
+
does not permit this to occur. To avoid overflow, Ruby transparently converts
|
202
|
+
from a simple integer (FIXNUM class) to a multiple-precision number
|
203
|
+
(BIGNUM class). The random number generator *requires* the computations to
|
204
|
+
overflow, so masking the results forces the computation to act as if they had.
|
205
|
+
|
206
|
+
So why 29 bits? Why not 32? or 64? The issue here is performance. Arithmetic
|
207
|
+
with BIGNUM values is much slower than with FIXNUM values. Further, the
|
208
|
+
conversion between FIXNUM and BIGNUM is also slow. The 29 bit size was
|
209
|
+
chosen to ensure that all computations remain with FIXNUM values without
|
210
|
+
ever reaching the threshold for the switch to BIGNUM values. In 32 bit Ruby
|
211
|
+
systems, 29 bits is the largest value that meets this requirement.
|
212
|
+
|
213
|
+
#### Code
|
214
|
+
|
215
|
+
Enough with all these words and pictures. The best way to gain insight into
|
216
|
+
ruby code is to study ruby code! What follows is the critical snippet of code
|
217
|
+
that makes this random number generator spin:
|
218
|
+
|
219
|
+
```ruby
|
220
|
+
private
|
221
|
+
|
222
|
+
#Cycle through the PRNG once.
|
223
|
+
def do_spin
|
224
|
+
@buffer[-2] = @buffer[0]
|
225
|
+
@buffer[-1] = @buffer[1]
|
226
|
+
|
227
|
+
(0...@depth).each do |idx|
|
228
|
+
tmp = @buffer[idx+2]
|
229
|
+
@buffer[idx] = (@buffer[idx+1] + ((tmp >> 1)|(tmp.odd? ? TOP : 0))) & CHOP
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
```
|
234
|
+
The above is found in the spinner.rb file. For completeness of understanding,
|
235
|
+
the following constants are defined in the fibonacci_rng.rb file:
|
236
|
+
|
237
|
+
```ruby
|
238
|
+
CHOP = 0x1FFFFFFF
|
239
|
+
TOP = 0x10000000
|
240
|
+
|
241
|
+
```
|
173
242
|
|
174
243
|
## Contributing
|
175
244
|
|
245
|
+
Creating a good pseudo random number generator is quite an undertaking. For
|
246
|
+
this reason, any input is most welcomed. There are two basic plans by which
|
247
|
+
this can be accomplished.
|
248
|
+
|
249
|
+
#### Plan A
|
250
|
+
|
176
251
|
1. Fork it
|
177
252
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
178
253
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
@@ -182,7 +257,4 @@ random_bytes = Array.new(len) { generator.byte }
|
|
182
257
|
#### Plan B
|
183
258
|
|
184
259
|
Go to the GitHub repository and raise an issue calling attention to some
|
185
|
-
aspect that could use some TLC or a suggestion or an idea.
|
186
|
-
to the issue that match the point you are trying to make. Then follow
|
187
|
-
your issue and keep up-to-date as it is worked on. All input are greatly
|
188
|
-
appreciated.
|
260
|
+
aspect that could use some TLC or a suggestion or an idea.
|
data/fibonacci_rng.gemspec
CHANGED
@@ -9,8 +9,10 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["Peter Camilleri"]
|
10
10
|
spec.email = ["peter.c.camilleri@gmail.com"]
|
11
11
|
spec.homepage = "http://teuthida-technologies.com/"
|
12
|
-
spec.description = "A Fibonacci inspired pseudo random number generator.
|
13
|
-
|
12
|
+
spec.description = "A Fibonacci inspired pseudo random number generator. " +
|
13
|
+
"[Updated] The algorithm is changed to use bit rotate " +
|
14
|
+
"instead of bit shift."
|
15
|
+
spec.summary = "[Updated] A Fibonacci inspired pseudo random number generator."
|
14
16
|
spec.license = "MIT"
|
15
17
|
|
16
18
|
raw_list = `git ls-files`.split($/)
|
@@ -18,7 +18,8 @@ class FibonacciRng
|
|
18
18
|
@buffer[-1] = @buffer[1]
|
19
19
|
|
20
20
|
(0...@depth).each do |idx|
|
21
|
-
|
21
|
+
tmp = @buffer[idx+2]
|
22
|
+
@buffer[idx] = (@buffer[idx+1] + ((tmp >> 1)|(tmp.odd? ? TOP : 0))) & CHOP
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
data/lib/fibonacci_rng.rb
CHANGED
@@ -152,9 +152,9 @@ class FibonacciRngTester < Minitest::Test
|
|
152
152
|
def test_building_strings
|
153
153
|
rng = FibonacciRng.new(0)
|
154
154
|
|
155
|
-
assert_equal(
|
156
|
-
assert_equal('
|
157
|
-
assert_equal('
|
155
|
+
assert_equal("c}l'(q@g\\z", rng.string(10))
|
156
|
+
assert_equal('2727573312', rng.string(10, '0123456789'))
|
157
|
+
assert_equal('khto lk si', rng.string(10, 'Always look on the bright side of life.'))
|
158
158
|
end
|
159
159
|
|
160
160
|
end
|
data/tests/hasher_tests.rb
CHANGED
@@ -14,10 +14,10 @@ class FibonacciHasherTester < Minitest::Test
|
|
14
14
|
def test_that_it_can_be_read
|
15
15
|
fib = FibonacciRng.new('salt')
|
16
16
|
|
17
|
-
val =
|
17
|
+
val = 6283409396933018229308310224792996722092866776518016470611172637516158
|
18
18
|
assert_equal(val, fib.hash_value)
|
19
19
|
|
20
|
-
str = '
|
20
|
+
str = 'kxoj5k4rx6mqx1bmskx2133lrr21h8l2fs0zd1ver0ozi'
|
21
21
|
assert_equal(str, fib.hash_string)
|
22
22
|
end
|
23
23
|
|
@@ -26,13 +26,13 @@ class FibonacciHasherTester < Minitest::Test
|
|
26
26
|
|
27
27
|
fib << "The quick brown fox jumps over the lazy dog."
|
28
28
|
|
29
|
-
str = '
|
29
|
+
str = 'hoeh45h3fqlrgnynud0rg3v8q62cadr9gmxx9lomzo3hi'
|
30
30
|
assert_equal(str, fib.hash_string)
|
31
31
|
|
32
32
|
fib << nil
|
33
33
|
|
34
34
|
refute_equal(str, fib.hash_string)
|
35
|
-
str = '
|
35
|
+
str = '9anamtuoyhhb7v6s7y70m31mfsl2r2rbp4vki0vb9rnag'
|
36
36
|
assert_equal(str, fib.hash_string)
|
37
37
|
end
|
38
38
|
|
data/tools/scatter_plot.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
|
3
|
-
#A
|
3
|
+
#A Scatter Plot tester
|
4
4
|
class ScatterPlot
|
5
5
|
|
6
|
-
#Run a
|
6
|
+
#Run a scatter plot test on the random number generator.
|
7
7
|
def run(gen, max, count)
|
8
8
|
puts "Starting test"
|
9
9
|
bins = Array.new(max * 2, 0)
|
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: 0.
|
4
|
+
version: 1.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: 2016-03
|
11
|
+
date: 2016-04-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest_visible
|
@@ -94,8 +94,8 @@ dependencies:
|
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: 4.0.1
|
97
|
-
description: A Fibonacci inspired pseudo random number generator.
|
98
|
-
|
97
|
+
description: A Fibonacci inspired pseudo random number generator. [Updated] The algorithm
|
98
|
+
is changed to use bit rotate instead of bit shift.
|
99
99
|
email:
|
100
100
|
- peter.c.camilleri@gmail.com
|
101
101
|
executables: []
|
@@ -146,6 +146,6 @@ rubyforge_project:
|
|
146
146
|
rubygems_version: 2.2.2
|
147
147
|
signing_key:
|
148
148
|
specification_version: 4
|
149
|
-
summary: A Fibonacci inspired pseudo random number generator.
|
149
|
+
summary: "[Updated] A Fibonacci inspired pseudo random number generator."
|
150
150
|
test_files: []
|
151
151
|
has_rdoc:
|