| package main |
| |
| import ( |
| "math/big" |
| "strconv" |
| ) |
| |
| func min(s, arg string) agg { return newBinop(s, opmin) } |
| func max(s, arg string) agg { return newBinop(s, opmax) } |
| func sum(s, arg string) agg { return newBinop(s, opsum) } |
| |
| type binop struct { |
| v *big.Float |
| f func(a, b *big.Float) *big.Float |
| } |
| |
| func newBinop(s string, f func(a, b *big.Float) *big.Float) *binop { |
| v, _ := parseFloat(s) |
| return &binop{v, f} |
| } |
| |
| func (o *binop) String() string { |
| if o.v == nil { |
| return "NaN" |
| } |
| return o.v.Text('f', -1) |
| } |
| |
| func (o *binop) merge(s string) { |
| v, ok := parseFloat(s) |
| if !ok { |
| return |
| } |
| o.v = o.f(o.v, v) |
| } |
| |
| func opmin(a, b *big.Float) *big.Float { |
| if a != nil && (b == nil || a.Cmp(b) <= 0) { |
| return a |
| } |
| return b |
| } |
| |
| func opmax(a, b *big.Float) *big.Float { |
| if a != nil && (b == nil || a.Cmp(b) >= 0) { |
| return a |
| } |
| return b |
| } |
| |
| func opsum(a, b *big.Float) *big.Float { |
| if a == nil { |
| return b |
| } else if b == nil { |
| return a |
| } |
| return a.Add(a, b) |
| } |
| |
| type meanagg struct { |
| v *big.Float |
| d float64 // actually an integer |
| } |
| |
| func mean(s, arg string) agg { |
| v, ok := parseFloat(s) |
| if !ok { |
| return &meanagg{new(big.Float), 0} |
| } |
| return &meanagg{v, 1} |
| } |
| |
| func (m *meanagg) String() string { |
| if m.d == 0 { |
| return "NaN" |
| } |
| v := new(big.Float).Quo(m.v, big.NewFloat(m.d)) |
| return v.Text('f', -1) |
| } |
| |
| func (m *meanagg) merge(s string) { |
| v, ok := parseFloat(s) |
| if !ok { |
| return |
| } |
| m.v.Add(m.v, v) |
| m.d++ |
| } |
| |
| func parseFloat(s string) (*big.Float, bool) { |
| v, _, err := big.ParseFloat(s, 0, 1000, big.ToNearestEven) |
| return v, err == nil |
| } |
| |
| type counter int |
| |
| func count(init, arg string) agg { return new(counter) } |
| func (c *counter) String() string { return strconv.Itoa(int(*c) + 1) } |
| func (c *counter) merge(string) { *c++ } |