Source file src/pkg/math/rand/rand.go
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // Package rand implements pseudo-random number generators.
6 package rand
7
8 import "sync"
9
10 // A Source represents a source of uniformly-distributed
11 // pseudo-random int64 values in the range [0, 1<<63).
12 type Source interface {
13 Int63() int64
14 Seed(seed int64)
15 }
16
17 // NewSource returns a new pseudo-random Source seeded with the given value.
18 func NewSource(seed int64) Source {
19 var rng rngSource
20 rng.Seed(seed)
21 return &rng
22 }
23
24 // A Rand is a source of random numbers.
25 type Rand struct {
26 src Source
27 }
28
29 // New returns a new Rand that uses random values from src
30 // to generate other random values.
31 func New(src Source) *Rand { return &Rand{src} }
32
33 // Seed uses the provided seed value to initialize the generator to a deterministic state.
34 func (r *Rand) Seed(seed int64) { r.src.Seed(seed) }
35
36 // Int63 returns a non-negative pseudo-random 63-bit integer as an int64.
37 func (r *Rand) Int63() int64 { return r.src.Int63() }
38
39 // Uint32 returns a pseudo-random 32-bit value as a uint32.
40 func (r *Rand) Uint32() uint32 { return uint32(r.Int63() >> 31) }
41
42 // Int31 returns a non-negative pseudo-random 31-bit integer as an int32.
43 func (r *Rand) Int31() int32 { return int32(r.Int63() >> 32) }
44
45 // Int returns a non-negative pseudo-random int.
46 func (r *Rand) Int() int {
47 u := uint(r.Int63())
48 return int(u << 1 >> 1) // clear sign bit if int == int32
49 }
50
51 // Int63n returns, as an int64, a non-negative pseudo-random number in [0,n).
52 // It panics if n <= 0.
53 func (r *Rand) Int63n(n int64) int64 {
54 if n <= 0 {
55 panic("invalid argument to Int63n")
56 }
57 max := int64((1 << 63) - 1 - (1<<63)%uint64(n))
58 v := r.Int63()
59 for v > max {
60 v = r.Int63()
61 }
62 return v % n
63 }
64
65 // Int31n returns, as an int32, a non-negative pseudo-random number in [0,n).
66 // It panics if n <= 0.
67 func (r *Rand) Int31n(n int32) int32 {
68 if n <= 0 {
69 panic("invalid argument to Int31n")
70 }
71 max := int32((1 << 31) - 1 - (1<<31)%uint32(n))
72 v := r.Int31()
73 for v > max {
74 v = r.Int31()
75 }
76 return v % n
77 }
78
79 // Intn returns, as an int, a non-negative pseudo-random number in [0,n).
80 // It panics if n <= 0.
81 func (r *Rand) Intn(n int) int {
82 if n <= 0 {
83 panic("invalid argument to Intn")
84 }
85 if n <= 1<<31-1 {
86 return int(r.Int31n(int32(n)))
87 }
88 return int(r.Int63n(int64(n)))
89 }
90
91 // Float64 returns, as a float64, a pseudo-random number in [0.0,1.0).
92 func (r *Rand) Float64() float64 { return float64(r.Int63()) / (1 << 63) }
93
94 // Float32 returns, as a float32, a pseudo-random number in [0.0,1.0).
95 func (r *Rand) Float32() float32 { return float32(r.Float64()) }
96
97 // Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n).
98 func (r *Rand) Perm(n int) []int {
99 m := make([]int, n)
100 for i := 0; i < n; i++ {
101 m[i] = i
102 }
103 for i := 0; i < n; i++ {
104 j := r.Intn(i + 1)
105 m[i], m[j] = m[j], m[i]
106 }
107 return m
108 }
109
110 /*
111 * Top-level convenience functions
112 */
113
114 var globalRand = New(&lockedSource{src: NewSource(1)})
115
116 // Seed uses the provided seed value to initialize the generator to a
117 // deterministic state. If Seed is not called, the generator behaves as
118 // if seeded by Seed(1).
119 func Seed(seed int64) { globalRand.Seed(seed) }
120
121 // Int63 returns a non-negative pseudo-random 63-bit integer as an int64.
122 func Int63() int64 { return globalRand.Int63() }
123
124 // Uint32 returns a pseudo-random 32-bit value as a uint32.
125 func Uint32() uint32 { return globalRand.Uint32() }
126
127 // Int31 returns a non-negative pseudo-random 31-bit integer as an int32.
128 func Int31() int32 { return globalRand.Int31() }
129
130 // Int returns a non-negative pseudo-random int.
131 func Int() int { return globalRand.Int() }
132
133 // Int63n returns, as an int64, a non-negative pseudo-random number in [0,n).
134 // It panics if n <= 0.
135 func Int63n(n int64) int64 { return globalRand.Int63n(n) }
136
137 // Int31n returns, as an int32, a non-negative pseudo-random number in [0,n).
138 // It panics if n <= 0.
139 func Int31n(n int32) int32 { return globalRand.Int31n(n) }
140
141 // Intn returns, as an int, a non-negative pseudo-random number in [0,n).
142 // It panics if n <= 0.
143 func Intn(n int) int { return globalRand.Intn(n) }
144
145 // Float64 returns, as a float64, a pseudo-random number in [0.0,1.0).
146 func Float64() float64 { return globalRand.Float64() }
147
148 // Float32 returns, as a float32, a pseudo-random number in [0.0,1.0).
149 func Float32() float32 { return globalRand.Float32() }
150
151 // Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n).
152 func Perm(n int) []int { return globalRand.Perm(n) }
153
154 // NormFloat64 returns a normally distributed float64 in the range
155 // [-math.MaxFloat64, +math.MaxFloat64] with
156 // standard normal distribution (mean = 0, stddev = 1).
157 // To produce a different normal distribution, callers can
158 // adjust the output using:
159 //
160 // sample = NormFloat64() * desiredStdDev + desiredMean
161 //
162 func NormFloat64() float64 { return globalRand.NormFloat64() }
163
164 // ExpFloat64 returns an exponentially distributed float64 in the range
165 // (0, +math.MaxFloat64] with an exponential distribution whose rate parameter
166 // (lambda) is 1 and whose mean is 1/lambda (1).
167 // To produce a distribution with a different rate parameter,
168 // callers can adjust the output using:
169 //
170 // sample = ExpFloat64() / desiredRateParameter
171 //
172 func ExpFloat64() float64 { return globalRand.ExpFloat64() }
173
174 type lockedSource struct {
175 lk sync.Mutex
176 src Source
177 }
178
179 func (r *lockedSource) Int63() (n int64) {
180 r.lk.Lock()
181 n = r.src.Int63()
182 r.lk.Unlock()
183 return
184 }
185
186 func (r *lockedSource) Seed(seed int64) {
187 r.lk.Lock()
188 r.src.Seed(seed)
189 r.lk.Unlock()
190 }