caio.co/de/go-tdigest

Make FromBytes accept options for constructing the digest

Id
f3c8d94f65d3096ac96eda54ffcd10c0fe1477f1
Author
Caio
Commit time
2018-11-13T08:47:14+01:00

Modified serialization.go

@@ -60,7 +60,11

// FromBytes reads a byte buffer with a serialized digest (from AsBytes)
// and deserializes it.
-func FromBytes(buf *bytes.Reader) (*TDigest, error) {
+//
+// This function creates a new tdigest instance with the provided options,
+// but ignores the compression setting since the correct value comes
+// from the buffer.
+func FromBytes(buf *bytes.Reader, options ...tdigestOption) (*TDigest, error) {
var encoding int32
err := binary.Read(buf, endianess, &encoding)
if err != nil {
@@ -71,16 +75,19
return nil, fmt.Errorf("Unsupported encoding version: %d", encoding)
}

+ t, err := newWithoutSummary(options...)
+
+ if err != nil {
+ return nil, err
+ }
+
var compression float64
err = binary.Read(buf, endianess, &compression)
if err != nil {
return nil, err
}

- t := &TDigest{
- compression: compression,
- rng: globalRNG{},
- }
+ t.compression = compression

var numCentroids int32
err = binary.Read(buf, endianess, &numCentroids)

Modified serialization_test.go

@@ -80,6 +80,28
}
}

+func TestFromBytesIgnoresCompression(t *testing.T) {
+ digest := uncheckedNew(Compression(42))
+
+ // Instructing FromBytes to use a compression different
+ // than the one in the payload should be ignored
+ payload, err := digest.AsBytes()
+
+ if err != nil {
+ t.Error(err)
+ }
+
+ other, err := FromBytes(bytes.NewReader(payload), Compression(100))
+
+ if err != nil {
+ t.Error(err)
+ }
+
+ if other.Compression() != 42 {
+ t.Errorf("Expected compression to be 42, got %f", other.Compression())
+ }
+}
+
func TestJavaSmallBytesCompat(t *testing.T) {
// Base64 string generated via (<3 clojure):
// (def t (com.tdunning.math.stats.AVLTreeDigest. 100))

Modified tdigest.go

@@ -40,6 +40,18
// set to 100 and uses the global random number generator (same
// as using math/rand top-level functions).
func New(options ...tdigestOption) (*TDigest, error) {
+ tdigest, err := newWithoutSummary(options...)
+
+ if err != nil {
+ return nil, err
+ }
+
+ tdigest.summary = newSummary(estimateCapacity(tdigest.compression))
+ return tdigest, nil
+}
+
+// Creates a tdigest instance without allocating a summary.
+func newWithoutSummary(options ...tdigestOption) (*TDigest, error) {
tdigest := &TDigest{
compression: 100,
count: 0,
@@ -53,7 +65,6
}
}

- tdigest.summary = newSummary(estimateCapacity(tdigest.compression))
return tdigest, nil
}