Codebase list golang-github-vbauerster-mpb / 103b5f3
Move round and helper func to internal Vladimir Bauer 8 years ago
8 changed file(s) with 145 addition(s) and 138 deletion(s). Raw diff Collapse all Expand all
99 "unicode/utf8"
1010
1111 "github.com/vbauerster/mpb/decor"
12 "github.com/vbauerster/mpb/internal"
1213 )
1314
1415 const (
239240 case b.operateState <- func(s *bState) {
240241 s.current += int64(n)
241242 if s.dynamic {
242 curp := decor.CalcPercentage(s.total, s.current, 100)
243 curp := internal.Percentage(s.total, s.current, 100)
243244 if 100-curp <= s.totalAutoIncrTrigger {
244245 s.total += s.totalAutoIncrBy
245246 }
380381 // bar s.width without leftEnd and rightEnd runes
381382 barWidth := width - 2
382383
383 completedWidth := decor.CalcPercentage(s.total, s.current, int64(barWidth))
384 completedWidth := internal.Percentage(s.total, s.current, int64(barWidth))
384385
385386 if s.refill != nil {
386 till := decor.CalcPercentage(s.total, s.refill.till, int64(barWidth))
387 till := internal.Percentage(s.total, s.refill.till, int64(barWidth))
387388 // append refill rune
388389 var i int64
389390 for i = 0; i < till; i++ {
55 "time"
66
77 "github.com/VividCortex/ewma"
8 "github.com/vbauerster/mpb/internal"
89 )
910
1011 // ETA returns exponential-weighted-moving-average ETA decorator.
6061 return s.onComplete.wc.FormatMsg(s.onComplete.msg, widthAccumulator, widthDistributor)
6162 }
6263
63 v := round(s.mAverage.Value())
64 v := internal.Round(s.mAverage.Value())
6465 if math.IsInf(v, 0) || math.IsNaN(v) {
6566 v = .0
6667 }
00 package decor
11
2 import "fmt"
2 import (
3 "fmt"
4
5 "github.com/vbauerster/mpb/internal"
6 )
37
48 // Percentage returns percentage decorator.
59 //
1115 }
1216 wc.BuildFormat()
1317 return DecoratorFunc(func(s *Statistics, widthAccumulator chan<- int, widthDistributor <-chan int) string {
14 str := fmt.Sprintf("%d %%", CalcPercentage(s.Total, s.Current, 100))
18 str := fmt.Sprintf("%d %%", internal.Percentage(s.Total, s.Current, 100))
1519 return wc.FormatMsg(str, widthAccumulator, widthDistributor)
1620 })
1721 }
18
19 // CalcPercentage is a helper function, to calculate percentage.
20 func CalcPercentage(total, current, width int64) int64 {
21 if total <= 0 {
22 return 0
23 }
24 p := float64(width*current) / float64(total)
25 return int64(round(p))
26 }
+0
-74
decor/percentage_test.go less more
0 package decor
1
2 import (
3 "testing"
4 )
5
6 func TestCalcPercentage(t *testing.T) {
7 // key is barWidth
8 testSuite := map[int64]map[string]struct {
9 total, current, expected int64
10 }{
11 100: {
12 "t,c,e{-1,-1,0}": {-1, -1, 0},
13 "t,c,e{0,-1,0}": {0, -1, 0},
14 "t,c,e{0,0,0}": {0, 0, 0},
15 "t,c,e{0,1,0}": {0, 1, 0},
16 "t,c,e{100,0,0}": {100, 0, 0},
17 "t,c,e{100,10,10}": {100, 10, 10},
18 "t,c,e{100,15,15}": {100, 15, 15},
19 "t,c,e{100,50,50}": {100, 50, 50},
20 "t,c,e{100,99,99}": {100, 99, 99},
21 "t,c,e{100,100,100}": {100, 100, 100},
22 "t,c,e{100,101,101}": {100, 101, 101},
23 "t,c,e{100,102,101}": {100, 102, 102},
24 "t,c,e{120,0,0}": {120, 0, 0},
25 "t,c,e{120,10,8}": {120, 10, 8},
26 "t,c,e{120,15,13}": {120, 15, 13},
27 "t,c,e{120,50,42}": {120, 50, 42},
28 "t,c,e{120,60,50}": {120, 60, 50},
29 "t,c,e{120,99,83}": {120, 99, 83},
30 "t,c,e{120,101,84}": {120, 101, 84},
31 "t,c,e{120,118,98}": {120, 118, 98},
32 "t,c,e{120,119,99}": {120, 119, 99},
33 "t,c,e{120,120,100}": {120, 120, 100},
34 "t,c,e{120,121,101}": {120, 121, 101},
35 "t,c,e{120,122,101}": {120, 122, 102},
36 },
37 80: {
38 "t,c,e{-1,-1,0}": {-1, -1, 0},
39 "t,c,e{0,-1,0}": {0, -1, 0},
40 "t,c,e{0,0,0}": {0, 0, 0},
41 "t,c,e{0,1,0}": {0, 1, 0},
42 "t,c,e{100,0,0}": {100, 0, 0},
43 "t,c,e{100,10,8}": {100, 10, 8},
44 "t,c,e{100,15,12}": {100, 15, 12},
45 "t,c,e{100,50,40}": {100, 50, 40},
46 "t,c,e{100,99,79}": {100, 99, 79},
47 "t,c,e{100,100,80}": {100, 100, 80},
48 "t,c,e{100,101,81}": {100, 101, 81},
49 "t,c,e{100,102,82}": {100, 102, 82},
50 "t,c,e{120,0,0}": {120, 0, 0},
51 "t,c,e{120,10,7}": {120, 10, 7},
52 "t,c,e{120,15,10}": {120, 15, 10},
53 "t,c,e{120,50,33}": {120, 50, 33},
54 "t,c,e{120,60,40}": {120, 60, 40},
55 "t,c,e{120,99,66}": {120, 99, 66},
56 "t,c,e{120,101,67}": {120, 101, 67},
57 "t,c,e{120,118,79}": {120, 118, 79},
58 "t,c,e{120,119,79}": {120, 119, 79},
59 "t,c,e{120,120,80}": {120, 120, 80},
60 "t,c,e{120,121,81}": {120, 121, 81},
61 "t,c,e{120,122,81}": {120, 122, 81},
62 },
63 }
64
65 for width, cases := range testSuite {
66 for name, tc := range cases {
67 got := CalcPercentage(tc.total, tc.current, width)
68 if got != tc.expected {
69 t.Errorf("width %d; %s: Expected: %d, got: %d\n", width, name, tc.expected, got)
70 }
71 }
72 }
73 }
+0
-49
decor/round.go less more
0 package decor
1
2 import "math"
3
4 const (
5 uvone = 0x3FF0000000000000
6 mask = 0x7FF
7 shift = 64 - 11 - 1
8 bias = 1023
9 signMask = 1 << 63
10 fracMask = 1<<shift - 1
11 )
12
13 // round returns the nearest integer, rounding half away from zero.
14 //
15 // Special cases are:
16 // Round(±0) = ±0
17 // Round(±Inf) = ±Inf
18 // Round(NaN) = NaN
19 func round(x float64) float64 {
20 // Round is a faster implementation of:
21 //
22 // func Round(x float64) float64 {
23 // t := Trunc(x)
24 // if Abs(x-t) >= 0.5 {
25 // return t + Copysign(1, x)
26 // }
27 // return t
28 // }
29 bits := math.Float64bits(x)
30 e := uint(bits>>shift) & mask
31 if e < bias {
32 // Round abs(x) < 1 including denormals.
33 bits &= signMask // +-0
34 if e == bias-1 {
35 bits |= uvone // +-1
36 }
37 } else if e < bias+shift {
38 // Round any abs(x) >= 1 containing a fractional component [0,1).
39 //
40 // Numbers with larger exponents are returned unchanged since they
41 // must be either an integer, infinity, or NaN.
42 const half = 1 << (shift - 1)
43 e -= bias
44 bits += half >> e
45 bits &^= fracMask >> e
46 }
47 return math.Float64frombits(bits)
48 }
0 package internal
1
2 // Percentage is a helper function, to calculate percentage.
3 func Percentage(total, current, width int64) int64 {
4 if total <= 0 {
5 return 0
6 }
7 p := float64(width*current) / float64(total)
8 return int64(Round(p))
9 }
0 package internal
1
2 import (
3 "testing"
4 )
5
6 func TestPercentage(t *testing.T) {
7 // key is barWidth
8 testSuite := map[int64]map[string]struct {
9 total, current, expected int64
10 }{
11 100: {
12 "t,c,e{-1,-1,0}": {-1, -1, 0},
13 "t,c,e{0,-1,0}": {0, -1, 0},
14 "t,c,e{0,0,0}": {0, 0, 0},
15 "t,c,e{0,1,0}": {0, 1, 0},
16 "t,c,e{100,0,0}": {100, 0, 0},
17 "t,c,e{100,10,10}": {100, 10, 10},
18 "t,c,e{100,15,15}": {100, 15, 15},
19 "t,c,e{100,50,50}": {100, 50, 50},
20 "t,c,e{100,99,99}": {100, 99, 99},
21 "t,c,e{100,100,100}": {100, 100, 100},
22 "t,c,e{100,101,101}": {100, 101, 101},
23 "t,c,e{100,102,101}": {100, 102, 102},
24 "t,c,e{120,0,0}": {120, 0, 0},
25 "t,c,e{120,10,8}": {120, 10, 8},
26 "t,c,e{120,15,13}": {120, 15, 13},
27 "t,c,e{120,50,42}": {120, 50, 42},
28 "t,c,e{120,60,50}": {120, 60, 50},
29 "t,c,e{120,99,83}": {120, 99, 83},
30 "t,c,e{120,101,84}": {120, 101, 84},
31 "t,c,e{120,118,98}": {120, 118, 98},
32 "t,c,e{120,119,99}": {120, 119, 99},
33 "t,c,e{120,120,100}": {120, 120, 100},
34 "t,c,e{120,121,101}": {120, 121, 101},
35 "t,c,e{120,122,101}": {120, 122, 102},
36 },
37 80: {
38 "t,c,e{-1,-1,0}": {-1, -1, 0},
39 "t,c,e{0,-1,0}": {0, -1, 0},
40 "t,c,e{0,0,0}": {0, 0, 0},
41 "t,c,e{0,1,0}": {0, 1, 0},
42 "t,c,e{100,0,0}": {100, 0, 0},
43 "t,c,e{100,10,8}": {100, 10, 8},
44 "t,c,e{100,15,12}": {100, 15, 12},
45 "t,c,e{100,50,40}": {100, 50, 40},
46 "t,c,e{100,99,79}": {100, 99, 79},
47 "t,c,e{100,100,80}": {100, 100, 80},
48 "t,c,e{100,101,81}": {100, 101, 81},
49 "t,c,e{100,102,82}": {100, 102, 82},
50 "t,c,e{120,0,0}": {120, 0, 0},
51 "t,c,e{120,10,7}": {120, 10, 7},
52 "t,c,e{120,15,10}": {120, 15, 10},
53 "t,c,e{120,50,33}": {120, 50, 33},
54 "t,c,e{120,60,40}": {120, 60, 40},
55 "t,c,e{120,99,66}": {120, 99, 66},
56 "t,c,e{120,101,67}": {120, 101, 67},
57 "t,c,e{120,118,79}": {120, 118, 79},
58 "t,c,e{120,119,79}": {120, 119, 79},
59 "t,c,e{120,120,80}": {120, 120, 80},
60 "t,c,e{120,121,81}": {120, 121, 81},
61 "t,c,e{120,122,81}": {120, 122, 81},
62 },
63 }
64
65 for width, cases := range testSuite {
66 for name, tc := range cases {
67 got := Percentage(tc.total, tc.current, width)
68 if got != tc.expected {
69 t.Errorf("width %d; %s: Expected: %d, got: %d\n", width, name, tc.expected, got)
70 }
71 }
72 }
73 }
0 package internal
1
2 import "math"
3
4 const (
5 uvone = 0x3FF0000000000000
6 mask = 0x7FF
7 shift = 64 - 11 - 1
8 bias = 1023
9 signMask = 1 << 63
10 fracMask = 1<<shift - 1
11 )
12
13 // Round returns the nearest integer, rounding half away from zero.
14 //
15 // Special cases are:
16 // Round(±0) = ±0
17 // Round(±Inf) = ±Inf
18 // Round(NaN) = NaN
19 func Round(x float64) float64 {
20 // Round is a faster implementation of:
21 //
22 // func Round(x float64) float64 {
23 // t := Trunc(x)
24 // if Abs(x-t) >= 0.5 {
25 // return t + Copysign(1, x)
26 // }
27 // return t
28 // }
29 bits := math.Float64bits(x)
30 e := uint(bits>>shift) & mask
31 if e < bias {
32 // Round abs(x) < 1 including denormals.
33 bits &= signMask // +-0
34 if e == bias-1 {
35 bits |= uvone // +-1
36 }
37 } else if e < bias+shift {
38 // Round any abs(x) >= 1 containing a fractional component [0,1).
39 //
40 // Numbers with larger exponents are returned unchanged since they
41 // must be either an integer, infinity, or NaN.
42 const half = 1 << (shift - 1)
43 e -= bias
44 bits += half >> e
45 bits &^= fracMask >> e
46 }
47 return math.Float64frombits(bits)
48 }