-
Notifications
You must be signed in to change notification settings - Fork 14
/
numbers.go
141 lines (128 loc) · 3.87 KB
/
numbers.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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package myqlib
import (
"fmt"
"sort"
"strings"
"unicode/utf8"
)
type UnitsDef map[float64]string
var (
NumberUnits UnitsDef = UnitsDef{
1: ``,
1000: `k`,
1000000: `m`,
1000000000: `g`,
}
MemoryUnits UnitsDef = UnitsDef{
1: `b`,
1024: `K`,
1048576: `M`,
1073741824: `G`,
1099511627776: `T`,
}
SecondUnits UnitsDef = UnitsDef{
1000: `ks`,
1: `s`,
0.001: `ms`,
0.000001: `µs`,
0.000000001: `ns`,
}
MicroSecondUnits UnitsDef = UnitsDef{
1000000000: `ks`,
1000000: `s`,
1000: `ms`,
1: `µs`,
}
NanoSecondUnits UnitsDef = UnitsDef{
1000000000: `s`,
1000000: `ms`,
1000: `µs`,
1: `ns`,
}
PercentUnits UnitsDef = UnitsDef{
1: `%`,
}
)
// Fit the given value of units into width + at most precision decimals
func collapse_number(value float64, width int64, precision int64, units UnitsDef) string {
// Load the factors from the given unit and sort them
var factors []float64
for k := range units {
factors = append(factors, k)
}
sort.Float64s(factors)
// Starting from the smallest to the biggest factors
for _, factor := range factors {
unit := units[factor]
raw := value / factor
str := fmt.Sprintf(fmt.Sprint(`%.`, precision, `f%s`), raw, unit)
left := width - int64(utf8.RuneCountInString(str))
// fmt.Printf( "%f, %d, %d, %s, %f, %s, %d\n", value, width, precision, unit, raw, str, left )
if raw >= 0 && (width+precision)-int64(utf8.RuneCountInString(str)) >= 0 {
// Our number is > 0 and fits into width + precision
if left < 0 {
if precision > 0 {
// No space left, try to chop the precision
return collapse_number(value, width, precision-1, units)
} else {
// Nothing to chop, any bigger factors will be too wide, so return here.
return str
}
} else if left > 1 && factor != 1 {
// If we have space for some extra precision, use it
return fmt.Sprintf(fmt.Sprint(`%.`, left-1, `f%s`), raw, unit)
} else {
if factor != 1 && raw < 1 && left > 0 && fmt.Sprintf(`%.1f`, raw ) != `1.0` {
// Raw is < 1, therefore str is rounded up. Let's print a decimal instead
return fmt.Sprintf(fmt.Sprint(`%0.`, precision+left, `f%s`), raw, unit)[1:]
} else if factor != 1 && str == fmt.Sprintf("0%s", unit) {
if left > 0 {
// There's still some space left to print something intelligent
return fmt.Sprintf(fmt.Sprint(`%.`, precision+1, `f%s`), raw, unit)[1:]
}
// if we are returning 0m, 0k, etc, then we can't fit this number into the size given
return strings.Repeat(`#`, int(width))
} else {
// Just return what we've got
return str
}
}
}
}
// We're past the highest factor and nothing fits
str := fmt.Sprintf(fmt.Sprint(`%.`, precision, `f`), value)
if int64(len(str)) > width && precision > 0 {
// We can try chopping precision here for a fit
return collapse_number(value, width, precision-1, units)
} else {
// Just print it (too wide)
// return str
return strings.Repeat(`#`, int(width))
}
}
// Calculate diff between two numbers, if negative, just return bigger
func calculate_diff(bigger, smaller float64) float64 {
if bigger < smaller {
// special case -- if c is < p, the number rolled over or was reset, so best effort answer here.
return bigger
} else {
return bigger - smaller
}
}
// Calculate the rate of change between two values, given the time difference between them
func calculate_rate(bigger, smaller, seconds float64) float64 {
diff := calculate_diff(bigger, smaller)
if seconds <= 0 { // negative seconds is weird
return diff
} else {
return diff / seconds
}
}
// Return the sum of all variables in the given sample
func calculate_sum(sample MyqSample, variable_names []string) (sum float64) {
for _, v := range variable_names {
v, _ := sample.getFloat(v)
sum += v
}
return sum
}