github.com/seeker-insurance/kit@v0.0.13/pretty/text/cmd/agg/num.go (about) 1 package main 2 3 import ( 4 "math/big" 5 "strconv" 6 ) 7 8 func min(s, arg string) agg { return newBinop(s, opmin) } 9 func max(s, arg string) agg { return newBinop(s, opmax) } 10 func sum(s, arg string) agg { return newBinop(s, opsum) } 11 12 type binop struct { 13 v *big.Float 14 f func(a, b *big.Float) *big.Float 15 } 16 17 func newBinop(s string, f func(a, b *big.Float) *big.Float) *binop { 18 v, _ := parseFloat(s) 19 return &binop{v, f} 20 } 21 22 func (o *binop) String() string { 23 if o.v == nil { 24 return "NaN" 25 } 26 return o.v.Text('f', -1) 27 } 28 29 func (o *binop) merge(s string) { 30 v, ok := parseFloat(s) 31 if !ok { 32 return 33 } 34 o.v = o.f(o.v, v) 35 } 36 37 func opmin(a, b *big.Float) *big.Float { 38 if a != nil && (b == nil || a.Cmp(b) <= 0) { 39 return a 40 } 41 return b 42 } 43 44 func opmax(a, b *big.Float) *big.Float { 45 if a != nil && (b == nil || a.Cmp(b) >= 0) { 46 return a 47 } 48 return b 49 } 50 51 func opsum(a, b *big.Float) *big.Float { 52 if a == nil { 53 return b 54 } else if b == nil { 55 return a 56 } 57 return a.Add(a, b) 58 } 59 60 type meanagg struct { 61 v *big.Float 62 d float64 // actually an integer 63 } 64 65 func mean(s, arg string) agg { 66 v, ok := parseFloat(s) 67 if !ok { 68 return &meanagg{new(big.Float), 0} 69 } 70 return &meanagg{v, 1} 71 } 72 73 func (m *meanagg) String() string { 74 if m.d == 0 { 75 return "NaN" 76 } 77 v := new(big.Float).Quo(m.v, big.NewFloat(m.d)) 78 return v.Text('f', -1) 79 } 80 81 func (m *meanagg) merge(s string) { 82 v, ok := parseFloat(s) 83 if !ok { 84 return 85 } 86 m.v.Add(m.v, v) 87 m.d++ 88 } 89 90 func parseFloat(s string) (*big.Float, bool) { 91 v, _, err := big.ParseFloat(s, 0, 1000, big.ToNearestEven) 92 return v, err == nil 93 } 94 95 type counter int 96 97 func count(init, arg string) agg { return new(counter) } 98 func (c *counter) String() string { return strconv.Itoa(int(*c) + 1) } 99 func (c *counter) merge(string) { *c++ }