File: num.go

package info (click to toggle)
golang-text 0.2.0-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 128 kB
  • sloc: makefile: 5
file content (99 lines) | stat: -rw-r--r-- 1,747 bytes parent folder | download | duplicates (3)
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
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++ }