diff options
Diffstat (limited to 'libgo/go/math/rand/rand.go')
-rw-r--r-- | libgo/go/math/rand/rand.go | 42 |
1 files changed, 39 insertions, 3 deletions
diff --git a/libgo/go/math/rand/rand.go b/libgo/go/math/rand/rand.go index dd8d43cca1c..9fe1cbd61e1 100644 --- a/libgo/go/math/rand/rand.go +++ b/libgo/go/math/rand/rand.go @@ -23,7 +23,20 @@ type Source interface { Seed(seed int64) } +// A Source64 is a Source that can also generate +// uniformly-distributed pseudo-random uint64 values in +// the range [0, 1<<64) directly. +// If a Rand r's underlying Source s implements Source64, +// then r.Uint64 returns the result of one call to s.Uint64 +// instead of making two calls to s.Int63. +type Source64 interface { + Source + Uint64() uint64 +} + // NewSource returns a new pseudo-random Source seeded with the given value. +// Unlike the default Source used by top-level functions, this source is not +// safe for concurrent use by multiple goroutines. func NewSource(seed int64) Source { var rng rngSource rng.Seed(seed) @@ -33,6 +46,7 @@ func NewSource(seed int64) Source { // A Rand is a source of random numbers. type Rand struct { src Source + s64 Source64 // non-nil if src is source64 // readVal contains remainder of 63-bit integer used for bytes // generation during most recent Read call. @@ -46,7 +60,10 @@ type Rand struct { // New returns a new Rand that uses random values from src // to generate other random values. -func New(src Source) *Rand { return &Rand{src: src} } +func New(src Source) *Rand { + s64, _ := src.(Source64) + return &Rand{src: src, s64: s64} +} // Seed uses the provided seed value to initialize the generator to a deterministic state. // Seed should not be called concurrently with any other Rand method. @@ -66,6 +83,14 @@ func (r *Rand) Int63() int64 { return r.src.Int63() } // Uint32 returns a pseudo-random 32-bit value as a uint32. func (r *Rand) Uint32() uint32 { return uint32(r.Int63() >> 31) } +// Uint64 returns a pseudo-random 64-bit value as a uint64. +func (r *Rand) Uint64() uint64 { + if r.s64 != nil { + return r.s64.Uint64() + } + return uint64(r.Int63())>>31 | uint64(r.Int63())<<32 +} + // Int31 returns a non-negative pseudo-random 31-bit integer as an int32. func (r *Rand) Int31() int32 { return int32(r.Int63() >> 32) } @@ -207,7 +232,7 @@ func read(p []byte, int63 func() int64, readVal *int64, readPos *int8) (n int, e * Top-level convenience functions */ -var globalRand = New(&lockedSource{src: NewSource(1)}) +var globalRand = New(&lockedSource{src: NewSource(1).(Source64)}) // Seed uses the provided seed value to initialize the default Source to a // deterministic state. If Seed is not called, the generator behaves as @@ -224,6 +249,10 @@ func Int63() int64 { return globalRand.Int63() } // from the default Source. func Uint32() uint32 { return globalRand.Uint32() } +// Uint64 returns a pseudo-random 64-bit value as a uint64 +// from the default Source. +func Uint64() uint64 { return globalRand.Uint64() } + // Int31 returns a non-negative pseudo-random 31-bit integer as an int32 // from the default Source. func Int31() int32 { return globalRand.Int31() } @@ -286,7 +315,7 @@ func ExpFloat64() float64 { return globalRand.ExpFloat64() } type lockedSource struct { lk sync.Mutex - src Source + src Source64 } func (r *lockedSource) Int63() (n int64) { @@ -296,6 +325,13 @@ func (r *lockedSource) Int63() (n int64) { return } +func (r *lockedSource) Uint64() (n uint64) { + r.lk.Lock() + n = r.src.Uint64() + r.lk.Unlock() + return +} + func (r *lockedSource) Seed(seed int64) { r.lk.Lock() r.src.Seed(seed) |