# Random number generation based on code from GST-3.2.5 (2.01)
# @see qmjAJh
class PiRandom
def initialize
self.seed(Time.now.to_f)
end
def seed(value)
@state = (value / 100000.0 + value) % 1.0
self.rand
self.rand
end
def rand(*args)
case args.size
when 0
@state = ((@state + Math::PI) ** 4) % 1.0
when 1
rand_with(args.first)
else
raise ArgumentError.new("wrong number of arguments "\
"(given #{args.size}, expected 0..1)")
end
end
private def rand_with(arg)
case arg
when Float
# [0, arg) exclusive.
self.rand * [arg, 0].max
when Integer
# [0, arg] inclusive.
rand_with(arg + 1.0).to_i
when Range
raise ArgumentError.new("invalid argument: #{arg}")\
if arg.min.nil?
rand_with(arg.max - arg.min) + arg.min
else
raise TypeError.new("no support for #{arg.class}")
end
end
end
# Test.
def chi_square(n, r, prng)
f = Array.new(r, 0)
n.times do
f[prng.rand(0...r)] += 1
end
t = f.sum {|x| x * x}
r * t / n - n
end
prng = PiRandom.new
n = 5
n.times do
p chi_square(1000, 100, prng)
end
n.times do
# [0.0, 1.0)
p prng.rand
end
# Max.
n.times do
# [0, 5]
p prng.rand(5)
end
n.times do
# [0.0, 5.0)
p prng.rand(5.0)
end
# Range.
n.times do
# [1, 5]
p prng.rand(1..5)
end
n.times do
# [1.0, 5.0)
p prng.rand(1.0..5.0)
end
IyBSYW5kb20gbnVtYmVyIGdlbmVyYXRpb24gYmFzZWQgb24gY29kZSBmcm9tIEdTVC0zLjIuNSAoMi4wMSkKIyBAc2VlIHFtakFKaAoKY2xhc3MgUGlSYW5kb20KICBkZWYgaW5pdGlhbGl6ZQogICAgc2VsZi5zZWVkKFRpbWUubm93LnRvX2YpCiAgZW5kCgogIGRlZiBzZWVkKHZhbHVlKQogICAgQHN0YXRlID0gKHZhbHVlIC8gMTAwMDAwLjAgKyB2YWx1ZSkgJSAxLjAKICAgIHNlbGYucmFuZAogICAgc2VsZi5yYW5kCiAgZW5kCgogIGRlZiByYW5kKCphcmdzKQogICAgY2FzZSBhcmdzLnNpemUKICAgIHdoZW4gMAogICAgICBAc3RhdGUgPSAoKEBzdGF0ZSArIE1hdGg6OlBJKSAqKiA0KSAlIDEuMAogICAgd2hlbiAxCiAgICAgIHJhbmRfd2l0aChhcmdzLmZpcnN0KQogICAgZWxzZQogICAgICByYWlzZSBBcmd1bWVudEVycm9yLm5ldygid3JvbmcgbnVtYmVyIG9mIGFyZ3VtZW50cyAiXAogICAgICAgICAgICAiKGdpdmVuICN7YXJncy5zaXplfSwgZXhwZWN0ZWQgMC4uMSkiKQogICAgZW5kCiAgZW5kCgogIHByaXZhdGUgZGVmIHJhbmRfd2l0aChhcmcpCiAgICBjYXNlIGFyZwogICAgd2hlbiBGbG9hdAogICAgICAjIFswLCBhcmcpIGV4Y2x1c2l2ZS4KICAgICAgc2VsZi5yYW5kICogW2FyZywgMF0ubWF4CiAgICB3aGVuIEludGVnZXIKICAgICAgIyBbMCwgYXJnXSBpbmNsdXNpdmUuCiAgICAgIHJhbmRfd2l0aChhcmcgKyAxLjApLnRvX2kKICAgIHdoZW4gUmFuZ2UKICAgICAgcmFpc2UgQXJndW1lbnRFcnJvci5uZXcoImludmFsaWQgYXJndW1lbnQ6ICN7YXJnfSIpXAogICAgICAgICAgICBpZiBhcmcubWluLm5pbD8KICAgICAgcmFuZF93aXRoKGFyZy5tYXggLSBhcmcubWluKSArIGFyZy5taW4KICAgIGVsc2UKICAgICAgcmFpc2UgVHlwZUVycm9yLm5ldygibm8gc3VwcG9ydCBmb3IgI3thcmcuY2xhc3N9IikKICAgIGVuZAogIGVuZAplbmQKCiMgVGVzdC4KCmRlZiBjaGlfc3F1YXJlKG4sIHIsIHBybmcpCiAgZiA9IEFycmF5Lm5ldyhyLCAwKQogIG4udGltZXMgZG8KICAgIGZbcHJuZy5yYW5kKDAuLi5yKV0gKz0gMQogIGVuZAogIHQgPSBmLnN1bSB7fHh8IHggKiB4fQogIHIgKiB0IC8gbiAtIG4KZW5kCgpwcm5nID0gUGlSYW5kb20ubmV3Cm4gPSA1CgpuLnRpbWVzIGRvCiAgcCBjaGlfc3F1YXJlKDEwMDAsIDEwMCwgcHJuZykKZW5kCgpuLnRpbWVzIGRvCiAgIyBbMC4wLCAxLjApCiAgcCBwcm5nLnJhbmQKZW5kCgojIE1heC4KCm4udGltZXMgZG8KICAjIFswLCA1XQogIHAgcHJuZy5yYW5kKDUpCmVuZAoKbi50aW1lcyBkbwogICMgWzAuMCwgNS4wKQogIHAgcHJuZy5yYW5kKDUuMCkKZW5kCgojIFJhbmdlLgoKbi50aW1lcyBkbwogICMgWzEsIDVdCiAgcCBwcm5nLnJhbmQoMS4uNSkKZW5kCgpuLnRpbWVzIGRvCiAgIyBbMS4wLCA1LjApCiAgcCBwcm5nLnJhbmQoMS4wLi41LjApCmVuZA==