-
Notifications
You must be signed in to change notification settings - Fork 3
/
sum.go
84 lines (72 loc) · 1.86 KB
/
sum.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package accumulators
import (
"bytes"
"encoding/gob"
"fmt"
"github.com/go-sif/sif"
)
// Sum Sums records
type sum[T, U sif.Numeric] struct {
accessor sif.GenericColumnAccessor[U]
sum T
}
// Accumulate adds a row to this Accumulator
func (a *sum[T, U]) Accumulate(row sif.Row) error {
v, err := a.accessor.From(row)
if err != nil {
return err
}
a.sum += T(v)
return nil
}
// Merge merges another Accumulator into this one
func (a *sum[T, U]) Merge(o sif.Accumulator) error {
ca, ok := o.(*sum[T, U])
if !ok {
return fmt.Errorf("incoming accumulator is not a Sum Accumulator")
}
a.sum += ca.sum
return nil
}
// ToBytes serializes this Accumulator
func (a *sum[T, U]) ToBytes() ([]byte, error) {
buff := new(bytes.Buffer)
e := gob.NewEncoder(buff)
err := e.Encode(a.sum)
if err != nil {
return nil, err
}
return buff.Bytes(), nil
}
// FromBytes produce a new Accumulator from serialized data
func (a *sum[T, U]) FromBytes(sv []byte) (sif.Accumulator, error) {
var v T
buff := bytes.NewBuffer(sv)
d := gob.NewDecoder(buff)
err := d.Decode(&v)
if err != nil {
return nil, err
}
return &sum[T, U]{a.accessor, v}, nil
}
// Value returns the value of this Accumulator
func (a *sum[T, U]) Value() T {
return a.sum
}
type summerFactory[T, U sif.Numeric] struct {
accessor sif.GenericColumnAccessor[U]
}
func (a *summerFactory[T, U]) New() sif.Accumulator {
return &sum[T, U]{a.accessor, 0}
}
func (a *summerFactory[T, U]) Value(acc sif.Accumulator) (T, error) {
tacc, ok := acc.(sif.GenericAccumulator[T])
if !ok {
return 0, fmt.Errorf("provided accumulator was not an Adder accumulator")
}
return tacc.Value(), nil
}
// Adder returns a new summation accumulator, summing values from a particular column
func Adder[T, U sif.Numeric](accessor sif.GenericColumnAccessor[U]) sif.GenericAccumulatorFactory[T] {
return &summerFactory[T, U]{accessor}
}