Skip to content

Commit 4ec5ac3

Browse files
committed
Do not use stdlib math.Round
1 parent 861468d commit 4ec5ac3

File tree

1 file changed

+53
-5
lines changed

1 file changed

+53
-5
lines changed

modules/stats/lang.go

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@ import (
1818

1919
const fileSizeLimit int64 = 16 * 1024 * 1024
2020

21-
// GetLanguageStats calculates language stats for git repository specified commit
22-
func GetLanguageStats(repoPath, commitSha string) (map[string]float32, error) {
21+
// GetLanguageStats calculates language stats for git repository at specified commit
22+
func GetLanguageStats(repoPath, commitID string) (map[string]float32, error) {
2323
r, err := git.PlainOpen(repoPath)
2424
if err != nil {
2525
return nil, err
2626
}
2727

28-
rev, err := r.ResolveRevision(plumbing.Revision(commitSha))
28+
rev, err := r.ResolveRevision(plumbing.Revision(commitID))
2929
if err != nil {
3030
return nil, err
3131
}
@@ -75,15 +75,15 @@ func GetLanguageStats(repoPath, commitSha string) (map[string]float32, error) {
7575
stats := make(map[string]float32, 0)
7676
var otherPerc float32 = 100
7777
for language, size := range sizes {
78-
perc := float32(math.Round(float64(size)/float64(total)*1000) / 10)
78+
perc := float32(round(float64(size)/float64(total)*1000) / 10)
7979
if perc <= 0.1 {
8080
continue
8181
}
8282
otherPerc -= perc
8383
stats[language] = perc
8484
}
8585
if otherPerc > 0 {
86-
stats["other"] = float32(math.Round(float64(otherPerc)*10) / 10)
86+
stats["other"] = float32(round(float64(otherPerc)*10) / 10)
8787
}
8888
return stats, nil
8989
}
@@ -108,3 +108,51 @@ func readFile(f *object.File, limit int64) ([]byte, error) {
108108
_, err = io.Copy(buf, io.LimitReader(r, limit))
109109
return buf.Bytes(), err
110110
}
111+
112+
// TODO: Taken from std lib, remove when GoLang min version updated to 1.10
113+
114+
const (
115+
uvone = 0x3FF0000000000000
116+
mask = 0x7FF
117+
shift = 64 - 11 - 1
118+
bias = 1023
119+
signMask = 1 << 63
120+
fracMask = 1<<shift - 1
121+
)
122+
123+
// round returns the nearest integer, rounding half away from zero.
124+
//
125+
// Special cases are:
126+
// round(±0) = ±0
127+
// round(±Inf) = ±Inf
128+
// round(NaN) = NaN
129+
func round(x float64) float64 {
130+
// round is a faster implementation of:
131+
//
132+
// func round(x float64) float64 {
133+
// t := Trunc(x)
134+
// if Abs(x-t) >= 0.5 {
135+
// return t + Copysign(1, x)
136+
// }
137+
// return t
138+
// }
139+
bits := math.Float64bits(x)
140+
e := uint(bits>>shift) & mask
141+
if e < bias {
142+
// Round abs(x) < 1 including denormals.
143+
bits &= signMask // +-0
144+
if e == bias-1 {
145+
bits |= uvone // +-1
146+
}
147+
} else if e < bias+shift {
148+
// Round any abs(x) >= 1 containing a fractional component [0,1).
149+
//
150+
// Numbers with larger exponents are returned unchanged since they
151+
// must be either an integer, infinity, or NaN.
152+
const half = 1 << (shift - 1)
153+
e -= bias
154+
bits += half >> e
155+
bits &^= fracMask >> e
156+
}
157+
return math.Float64frombits(bits)
158+
}

0 commit comments

Comments
 (0)