fibonacci_rng 0.4.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 24192194041fbb6a8a907907c3d80c793a25eb1a
4
- data.tar.gz: afc6ce49588ec4aaeb8de9b1ead78bbec947f3ed
3
+ metadata.gz: 92d9ec37d3384e39e3e122ed13281ba8001c8f2a
4
+ data.tar.gz: df41080f4dc1a92a75028a4f8cce4f94f5c969ed
5
5
  SHA512:
6
- metadata.gz: b8c839b0aad4e0defdc304bdb6bbdbf40a3db783711c2961345468e7e76d119bc78db0a147a763a283b42495c228e7b0017ee6b05a1d84e75d1cfa024472206a
7
- data.tar.gz: e331373058f17ef81d5b43808f48c62e29a752de076620a2bdb9b1ad3cfcd75bdf20acae5ee032250aee3c69de302ded79a406ca560adafbb148ba9a9278c1f0
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. So far, this generator has performed quite well when compared
5
- to the built-in Ruby random number generator when tested with:
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
+ ![The Cycle Operation](docs/cycle.png)
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. Apply labels
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.
@@ -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. Suitable for light duties."
13
- spec.summary = "A Fibonacci inspired pseudo random number generator."
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
- @buffer[idx] = (@buffer[idx+1] + (@buffer[idx+2] >> 1)) & CHOP
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
 
@@ -2,5 +2,5 @@
2
2
 
3
3
  #The class of Fibonacci inspired random number generators.
4
4
  class FibonacciRng
5
- VERSION = "0.4.3"
5
+ VERSION = "1.0.0"
6
6
  end
data/lib/fibonacci_rng.rb CHANGED
@@ -10,6 +10,7 @@ require_relative "fibonacci_rng/version"
10
10
  class FibonacciRng
11
11
 
12
12
  CHOP = 0x1FFFFFFF
13
+ TOP = 0x10000000
13
14
  BYTE = 0xFF
14
15
  WORD = 0xFFFF
15
16
  BASE = (CHOP+1).to_f
@@ -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('8{4y5+-N+c', rng.string(10))
156
- assert_equal('1149049996', rng.string(10, '0123456789'))
157
- assert_equal('tfes oAy', rng.string(10, 'Always look on the bright side of life.'))
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
@@ -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 = 6419946790796257801349293118951652810485853780437507149800008378866623
17
+ val = 6283409396933018229308310224792996722092866776518016470611172637516158
18
18
  assert_equal(val, fib.hash_value)
19
19
 
20
- str = 'le247zggdghf5vpcjbw2hrjf9eu8ql01wvl1fhv14bykf'
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 = 'j5jqhk7ntrze02icv38gj28efa2qrctr6mi5ejbr2p4nj'
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 = '1g5sgt443g4jcn3bfpiee1fkqoklo0i1ctkjro2vevpp0'
35
+ str = '9anamtuoyhhb7v6s7y70m31mfsl2r2rbp4vki0vb9rnag'
36
36
  assert_equal(str, fib.hash_string)
37
37
  end
38
38
 
@@ -1,9 +1,9 @@
1
1
  # coding: utf-8
2
2
 
3
- #A Chi Squared tester
3
+ #A Scatter Plot tester
4
4
  class ScatterPlot
5
5
 
6
- #Run a chi squared test on the random number generator.
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.3
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-26 00:00:00.000000000 Z
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. Suitable for light
98
- duties.
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: