-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrng.go
81 lines (72 loc) · 1.67 KB
/
rng.go
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package crazy
import (
"encoding/binary"
"math/big"
)
// RNG adapts a Source to produce integers.
type RNG struct {
Source
}
// Uint64 generates a random uint64.
func (r RNG) Uint64() uint64 {
p := [8]byte{}
r.Read(p[:])
return binary.LittleEndian.Uint64(p[:])
}
// Uint32 generates a random uint32.
func (r RNG) Uint32() uint32 {
p := [4]byte{}
r.Read(p[:])
return binary.LittleEndian.Uint32(p[:])
}
// Uint16 generates a random uint16.
func (r RNG) Uint16() uint16 {
p := [2]byte{}
r.Read(p[:])
return binary.LittleEndian.Uint16(p[:])
}
// Uintn generates a random uint in the interval [0, max). It panics if
// max == 0.
func (r RNG) Uintn(max uint) uint {
bad := ^uint(0) - ^uint(0)%max
x := uint(r.Uint64())
for x > bad {
x = uint(r.Uint64())
}
return x % max
}
// Intn generates a random int in the interval [0, max). It panics if max <= 0.
func (r RNG) Intn(max int) int {
if max < 0 {
panic("maximum below zero")
}
return int(r.Uintn(uint(max)))
}
// Big generates a random number with maximum bit length nbits.
func (r RNG) Big(nbits int) *big.Int {
p := make([]byte, (uint(nbits)+7)>>3)
r.Read(p)
p[0] &= byte(0xff >> (8 - uint(nbits)&7))
return new(big.Int).SetBytes(p)
}
// Bign generates a random number in the range [0, max). It panics if max <= 0.
func (r RNG) Bign(max *big.Int) *big.Int {
if max.Sign() <= 0 {
panic("maximum zero or below")
}
n := make([]big.Word, len(max.Bits()))
for i := range n[1:] {
n[i+1] = ^big.Word(0)
}
nbits := max.BitLen() + 1
m := new(big.Int)
m.Sub(m.SetBit(m, nbits, 1), big.NewInt(1))
k := new(big.Int)
k.Rem(m, max)
k.Sub(m, k)
x := r.Big(nbits)
for x.Cmp(k) > 0 {
x = r.Big(nbits)
}
return x.Rem(x, max)
}