Signed biased distribution generator
This commit is contained in:
16
gen/rand.go
16
gen/rand.go
@@ -6,5 +6,19 @@ import "math/rand"
|
||||
func RandBiasedUint64() uint64 {
|
||||
// The shift-right by up to 64 (shifting it to 0) makes up for randomness
|
||||
// lost by setting the high bit.
|
||||
return (rand.Uint64() | 0x8000000000000000) >> rand.Int31n(65)
|
||||
return (rand.Uint64() | 0x8000000000000000) >> rand.Intn(65)
|
||||
}
|
||||
|
||||
// Generate a random int64 with an even distribution of the tuple
|
||||
// {sign, bits.Len64(math.Abs())}
|
||||
func RandBiasedInt64() int64 {
|
||||
shift := rand.Intn(127)
|
||||
// [0,62]: positive
|
||||
// [63,63]: zero
|
||||
// [64,126]: negative
|
||||
if shift < 64 {
|
||||
return int64((rand.Uint64() | 0x8000000000000000) >> (shift + 1))
|
||||
} else {
|
||||
return int64((rand.Uint64() | 0x8000000000000000) >> (shift - 63)) * -1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,3 +31,39 @@ func TestRandBiasedUint64(t *testing.T) {
|
||||
t.Fatalf("Variance greater than allowed: %d > %d (max=%d min=%d)", max - min, max / 10, max, min)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRandBiasedInt64(t *testing.T) {
|
||||
// [0,62]: positive
|
||||
// [63,63]: zero
|
||||
// [64,126]: negative
|
||||
buckets := [127]uint64{}
|
||||
|
||||
for i := 0; i < 1000000; i++ {
|
||||
val := gen.RandBiasedInt64()
|
||||
switch {
|
||||
case val == 0:
|
||||
buckets[63]++
|
||||
case val < 0:
|
||||
buckets[63 + bits.Len64(uint64(val * -1))]++
|
||||
case val > 0:
|
||||
buckets[63 - bits.Len64(uint64(val))]++
|
||||
}
|
||||
}
|
||||
|
||||
var max uint64 = 0
|
||||
var min uint64 = math.MaxUint64
|
||||
|
||||
for _, count := range buckets {
|
||||
if count > max {
|
||||
max = count
|
||||
}
|
||||
|
||||
if count < min {
|
||||
min = count
|
||||
}
|
||||
}
|
||||
|
||||
if max - min > max / 10 {
|
||||
t.Fatalf("Variance greater than allowed: %d > %d (max=%d min=%d)", max - min, max / 10, max, min)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user