Breaking: add Clone method to RNG interface
- Id
- a11b2e8dc6420325b0b7432146592531e0ffd166
- Author
- Caio
- Commit time
- 2025-11-29T14:45:00+01:00
Modified options.go
// This allows changing which random number source is used when using
// the TDigest structure (rngs are used when deciding which candidate
// centroid to merge with and when compressing or merging with
-// another digest for it increases accuracy). This functionality is
-// particularly useful for testing or when you want to disconnect
-// your sample collection from the (default) shared random source
-// to minimize lock contention.
+// another digest for it increases accuracy).
+//
+// By default the digest is initialized with a local RNG seeded with 1.
func RandomNumberGenerator(rng RNG) tdigestOption { // nolint
return func(t *TDigest) error {
t.rng = rng
}
// LocalRandomNumberGenerator makes the TDigest use the default
-// `math/random` functions but with an unshared source that is
+// `math/rand` functions but with an unshared source that is
// seeded with the given `seed` parameter.
func LocalRandomNumberGenerator(seed int64) tdigestOption { // nolint
return RandomNumberGenerator(newLocalRNG(seed))
Modified rng.go
type RNG interface {
Float32() float32
Intn(int) int
-}
-
-type globalRNG struct{}
-
-func (r globalRNG) Float32() float32 {
- return rand.Float32()
-}
-
-func (r globalRNG) Intn(i int) int {
- return rand.Intn(i)
+ Clone() RNG
}
type localRNG struct {
func (r *localRNG) Intn(i int) int {
return r.localRand.Intn(i)
+}
+
+func (r *localRNG) Clone() RNG {
+ return newLocalRNG(r.localRand.Int63())
}
Modified tdigest.go
}
// Clone returns a deep copy of a TDigest.
+//
+// Notice that the provided RNG (via options.LocalRandomNumberGenerator)
+// does NOT clone its state - a brand new source is created. Users
+// must implement their own RNG if they want something different.
func (t *TDigest) Clone() *TDigest {
return &TDigest{
summary: t.summary.Clone(),
compression: t.compression,
count: t.count,
- rng: t.rng,
+ rng: t.rng.Clone(),
}
}
t.summary.Reset()
t.count = 0
}
-
func interpolate(x, x0, x1 float64) float64 {
return (x - x0) / (x1 - x0)
Modified tdigest_test.go
},
compression: 5,
count: 1250,
- rng: globalRNG{},
+ rng: newLocalRNG(1),
}
if cdf := td.CDF(7.144560976650238e+06); cdf > 1 {