class SuperRandom
Constants
- DEFAULT_BYTES
- VERSION
Attributes
first_timeout[RW]
nevermind[RW]
randomness[R]
second_timeout[RW]
services[R]
Public Class Methods
atmospheric(n)
click to toggle source
www.random.org/ www.random.org/integers/
# 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')
click to toggle source
# 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
new()
click to toggle source
# File lib/super_random/generator.rb, line 7 def initialize @first_timeout = 3 @second_timeout = 6 @nevermind = true @randomness = 0.0 @services = 0 end
quantum(n)
click to toggle source
qrng.anu.edu.au/ qrng.anu.edu.au/contact/api-documentation/
# 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()
click to toggle source
# File lib/super_random/services.rb, line 2 def self.services [:quantum, :atmospheric, :hotbits] end
Public Instance Methods
bytes(n=DEFAULT_BYTES)
click to toggle source
# 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)
click to toggle source
# 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)
click to toggle source
# 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
Also aliased as: rand