Class: SuperRandom
- Inherits:
-
Object
- Object
- SuperRandom
- Defined in:
- lib/super_random.rb,
lib/super_random/services.rb,
lib/super_random/generator.rb
Constant Summary collapse
- VERSION =
'2.0.210126'- DEFAULT_BYTES =
32
Instance Attribute Summary collapse
-
#first_timeout ⇒ Object
Returns the value of attribute first_timeout.
-
#nevermind ⇒ Object
Returns the value of attribute nevermind.
-
#randomness ⇒ Object
readonly
Returns the value of attribute randomness.
-
#second_timeout ⇒ Object
Returns the value of attribute second_timeout.
-
#services ⇒ Object
readonly
Returns the value of attribute services.
Class Method Summary collapse
- .atmospheric(n) ⇒ Object
- .hotbits(n, k = 'Pseudorandom') ⇒ Object
- .quantum(n) ⇒ Object
- .services ⇒ Object
Instance Method Summary collapse
- #bytes(n = DEFAULT_BYTES) ⇒ Object
- #hexadecimal(n = DEFAULT_BYTES) ⇒ Object
-
#initialize ⇒ SuperRandom
constructor
A new instance of SuperRandom.
- #random_number(scale = 1.0, minbytes = 6, maxbytes = [minbytes,DEFAULT_BYTES].max) ⇒ Object (also: #rand)
Constructor Details
#initialize ⇒ SuperRandom
Returns a new instance of SuperRandom.
7 8 9 10 11 12 13 |
# File 'lib/super_random/generator.rb', line 7 def initialize @first_timeout = 3 @second_timeout = 6 @nevermind = true @randomness = 0.0 @services = 0 end |
Instance Attribute Details
#first_timeout ⇒ Object
Returns the value of attribute first_timeout.
4 5 6 |
# File 'lib/super_random/generator.rb', line 4 def first_timeout @first_timeout end |
#nevermind ⇒ Object
Returns the value of attribute nevermind.
4 5 6 |
# File 'lib/super_random/generator.rb', line 4 def nevermind @nevermind end |
#randomness ⇒ Object (readonly)
Returns the value of attribute randomness.
5 6 7 |
# File 'lib/super_random/generator.rb', line 5 def randomness @randomness end |
#second_timeout ⇒ Object
Returns the value of attribute second_timeout.
4 5 6 |
# File 'lib/super_random/generator.rb', line 4 def second_timeout @second_timeout end |
#services ⇒ Object (readonly)
Returns the value of attribute services.
5 6 7 |
# File 'lib/super_random/generator.rb', line 5 def services @services end |
Class Method Details
.atmospheric(n) ⇒ Object
22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/super_random/services.rb', line 22 def self.atmospheric(n) s = Net::HTTP.get(URI( "https://www.random.org/integers/?num=#{n}&min=0&max=255&col=1&base=10&format=plain&rnd=new")) a = s.strip.split(/\s+/).map{|j|j.to_i} raise unless a.length==n raise unless a.all?{|i| i.between?(0,255)} return a rescue StandardError warn "atmospheric (www.random.org) failed." return nil end |
.hotbits(n, k = 'Pseudorandom') ⇒ Object
35 36 37 38 39 40 41 42 43 44 |
# File 'lib/super_random/services.rb', line 35 def self.hotbits(n, k='Pseudorandom') s = Net::HTTP.get(URI( "https://www.fourmilab.ch/cgi-bin/Hotbits.api?nbytes=#{n}&fmt=bin&apikey=#{k}")) a = s.bytes raise unless a.length==n return a rescue StandardError warn "hotbits (www.fourmilab.ch) failed." return nil end |
.quantum(n) ⇒ Object
8 9 10 11 12 13 14 15 16 17 18 |
# File 'lib/super_random/services.rb', line 8 def self.quantum(n) s = Net::HTTP.get(URI( "https://qrng.anu.edu.au/API/jsonI.php?length=#{n}&type=uint8")) a = JSON.parse(s)['data'] raise unless a.is_a?(Array) and a.length==n raise unless a.all?{|i| i.is_a?(Integer) and i.between?(0,255)} return a rescue StandardError warn "quantum (qrng.anu.edu.au) failed." return nil end |
.services ⇒ Object
2 3 4 |
# File 'lib/super_random/services.rb', line 2 def self.services [:quantum, :atmospheric, :hotbits] end |
Instance Method Details
#bytes(n = DEFAULT_BYTES) ⇒ Object
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/super_random/generator.rb', line 15 def bytes(n=DEFAULT_BYTES) @randomness = 0.0 @services = 0 m = SuperRandom.services a = Array.new m.length t = Array.new m.length m.each_with_index do |k,i| t[i] = Thread.new{ a[i] = SuperRandom.send(k, n) } end begin Timeout.timeout(@first_timeout) do # Initially, would like to get them all. t.each{_1.join} end rescue Timeout::Error begin Timeout.timeout(@second_timeout) do # But at this point, # would like to get at least one. while a.all?{_1.nil?} and t.any?{_1.alive?} Thread.pass end end rescue Timeout::Error # If we don't care that we got nothing, go on. raise $! unless @nevermind end end r = Array.new n n.times{|i| r[i] = SecureRandom.random_number(256)} a.each do |b| next if b.nil? l = b.length @randomness += l.to_f/n.to_f @services += 1 n.times{|i|r[i]=(r[i]+b[i%l])%256} end return r end |
#hexadecimal(n = DEFAULT_BYTES) ⇒ Object
60 61 62 |
# File 'lib/super_random/generator.rb', line 60 def hexadecimal(n=DEFAULT_BYTES) bytes(n).map{|i|i.to_s(16).rjust(2,'0')}.join end |
#random_number(scale = 1.0, minbytes = 6, maxbytes = [minbytes,DEFAULT_BYTES].max) ⇒ Object Also known as: rand
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 |
# File 'lib/super_random/generator.rb', line 64 def random_number(scale=1.0, minbytes=6, maxbytes=[minbytes,DEFAULT_BYTES].max) case scale when Float div = minbytes.times.inject(''){|s,i| s+'FF'}.to_i(16) den = hexadecimal(minbytes).to_i(16) return scale * den.to_f / div.to_f when Integer n = n0 = Math.log(scale, 256).ceil e = e0 = 256**n r = r0 = e0 % scale while r > 0 n0 += 1 e0 *= 256 r0 = e0 % scale if r0 <= r # break if repeating pattern with big enough integer break if r0 == r and n0 > minbytes r,n,e = r0,n0,e0 end break if n0 >= maxbytes end max = (e/scale)*scale loop do number = hexadecimal(n).to_i(16) return number % scale if number < max # On a relatively small chance that we're above max... if @nevermind warn "using SecureRandom.random_number(#{scale})" return SecureRandom.random_number(scale) end end end raise "rand(scale Integer|Float)" end |