/
pure.rb
59 lines (47 loc) · 1.27 KB
/
pure.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
59
# A pure Ruby micro-implementation. Use crypt-xorshift if you want a complete implementation.
module Crypt
class Xorshift64Star
UINT32_C = 2**32
UINT64_C = 2**64
UINT64_Cm = UINT64_C - 1
UINT64_Cf = UINT64_C.to_f
def initialize( seed = new_seed )
srand( seed )
@old_seed = @seed
end
def new_seed
n = Time.now
@@counter ||= 0
@@counter += 1
[n.usec % 65536, n.to_i % 65536, $$ ^ 65536, @@counter % 65536 ].collect {|x| x.to_s(16)}.join.to_i(16)
end
def srand( seed = new_seed )
@old_seed = @seed
@seed = seed % UINT64_C
end
def rand( n = 0)
@seed ^= @seed >> 12
@seed ^= @seed << 25
@seed ^= @seed >> 27
if n < 1
( ( @seed * 2685821657736338717 ) % UINT64_C ) / UINT64_Cf
else
( ( @seed * 2685821657736338717 ) % UINT64_C ) % Integer( n )
end
end
def seed
@old_seed
end
def ==(v)
self.class == v.class && @old_seed == v.seed
end
def bytes(size)
buffer = ""
( size / 8 ).times { buffer << [rand(UINT64_Cm)].pack("L").unpack("aaaaaaaa").join }
if size % 8 != 0
buffer << [rand(UINT64_Cm)].pack("L").unpack("aaaaaaaa")[0..(size % 8 - 1)].join
end
buffer
end
end
end