Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(240)

Side by Side Diff: src/pkg/math/rand/rand.go

Issue 95460049: code review 95460049: math/rand: restore Go 1.2 value stream for Float32, Float64 (Closed)
Patch Set: diff -r ddf9fa84f55b https://code.google.com/p/go/ Created 11 years ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pkg/math/rand/example_test.go ('k') | src/pkg/math/rand/regress_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2009 The Go Authors. All rights reserved. 1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 // Package rand implements pseudo-random number generators. 5 // Package rand implements pseudo-random number generators.
6 // 6 //
7 // Random numbers are generated by a Source. Top-level functions, such as 7 // Random numbers are generated by a Source. Top-level functions, such as
8 // Float64 and Int, use a default shared Source that produces a deterministic 8 // Float64 and Int, use a default shared Source that produces a deterministic
9 // sequence of values each time a program is run. Use the Seed function to 9 // sequence of values each time a program is run. Use the Seed function to
10 // initialize the default Source if different behavior is required for each run. 10 // initialize the default Source if different behavior is required for each run.
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 if n <= 0 { 94 if n <= 0 {
95 panic("invalid argument to Intn") 95 panic("invalid argument to Intn")
96 } 96 }
97 if n <= 1<<31-1 { 97 if n <= 1<<31-1 {
98 return int(r.Int31n(int32(n))) 98 return int(r.Int31n(int32(n)))
99 } 99 }
100 return int(r.Int63n(int64(n))) 100 return int(r.Int63n(int64(n)))
101 } 101 }
102 102
103 // Float64 returns, as a float64, a pseudo-random number in [0.0,1.0). 103 // Float64 returns, as a float64, a pseudo-random number in [0.0,1.0).
104 func (r *Rand) Float64() float64 { return float64(r.Int63n(1<<53)) / (1 << 53) } 104 func (r *Rand) Float64() float64 {
105 » // A clearer, simpler implementation would be:
106 » //» return float64(r.Int63n(1<<53)) / (1<<53)
107 » // However, Go 1 shipped with
108 » //» return float64(r.Int63()) / (1 << 63)
109 » // and we want to preserve that value stream.
110 » //
111 » // There is one bug in the value stream: r.Int63() may be so close
112 » // to 1<<63 that the division rounds up to 1.0, and we've guaranteed
113 » // that the result is always less than 1.0. To fix that, we treat the
114 » // range as cyclic and map 1 back to 0. This is justified by observing
115 » // that while some of the values rounded down to 0, nothing was
116 » // rounding up to 0, so 0 was underrepresented in the results.
117 » // Mapping 1 back to zero restores some balance.
118 » // (The balance is not perfect because the implementation
119 » // returns denormalized numbers for very small r.Int63(),
120 » // and those steal from what would normally be 0 results.)
121 » // The remapping only happens 1/2⁵³ of the time, so most clients
122 » // will not observe it anyway.
123 » f := float64(r.Int63()) / (1 << 63)
124 » if f == 1 {
125 » » f = 0
126 » }
127 » return f
128 }
105 129
106 // Float32 returns, as a float32, a pseudo-random number in [0.0,1.0). 130 // Float32 returns, as a float32, a pseudo-random number in [0.0,1.0).
107 func (r *Rand) Float32() float32 { return float32(r.Int31n(1<<24)) / (1 << 24) } 131 func (r *Rand) Float32() float32 {
132 » // Same rationale as in Float64: we want to preserve the Go 1 value
133 » // stream except we want to fix it not to return 1.0
134 » // There is a double rounding going on here, but the argument for
135 » // mapping 1 to 0 still applies: 0 was underrepresented before,
136 » // so mapping 1 to 0 doesn't cause too many 0s.
137 » // This only happens 1/2²⁴ of the time (plus the 1/2⁵³ of the time in Fl oat64).
138 » f := float32(r.Float64())
139 » if f == 1 {
140 » » f = 0
141 » }
142 » return f
143 }
108 144
109 // Perm returns, as a slice of n ints, a pseudo-random permutation of the intege rs [0,n). 145 // Perm returns, as a slice of n ints, a pseudo-random permutation of the intege rs [0,n).
110 func (r *Rand) Perm(n int) []int { 146 func (r *Rand) Perm(n int) []int {
111 m := make([]int, n) 147 m := make([]int, n)
112 for i := 0; i < n; i++ { 148 for i := 0; i < n; i++ {
113 j := r.Intn(i + 1) 149 j := r.Intn(i + 1)
114 m[i] = m[j] 150 m[i] = m[j]
115 m[j] = i 151 m[j] = i
116 } 152 }
117 return m 153 return m
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 n = r.src.Int63() 237 n = r.src.Int63()
202 r.lk.Unlock() 238 r.lk.Unlock()
203 return 239 return
204 } 240 }
205 241
206 func (r *lockedSource) Seed(seed int64) { 242 func (r *lockedSource) Seed(seed int64) {
207 r.lk.Lock() 243 r.lk.Lock()
208 r.src.Seed(seed) 244 r.src.Seed(seed)
209 r.lk.Unlock() 245 r.lk.Unlock()
210 } 246 }
OLDNEW
« no previous file with comments | « src/pkg/math/rand/example_test.go ('k') | src/pkg/math/rand/regress_test.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b