round.go (1458B)
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 // According to https://github.com/golang/go/issues/20100, the Go stdlib will
6 // include math.Round beginning with Go 1.10.
7 //
8 // The following implementation was taken from https://golang.org/cl/43652.
9
10 package math
11
12 import "math"
13
14 const (
15 mask = 0x7FF
16 shift = 64 - 11 - 1
17 bias = 1023
18 )
19
20 // Round returns the nearest integer, rounding half away from zero.
21 //
22 // Special cases are:
23 // Round(±0) = ±0
24 // Round(±Inf) = ±Inf
25 // Round(NaN) = NaN
26 func _round(x float64) float64 {
27 // Round is a faster implementation of:
28 //
29 // func Round(x float64) float64 {
30 // t := Trunc(x)
31 // if Abs(x-t) >= 0.5 {
32 // return t + Copysign(1, x)
33 // }
34 // return t
35 // }
36 const (
37 signMask = 1 << 63
38 fracMask = 1<<shift - 1
39 half = 1 << (shift - 1)
40 one = bias << shift
41 )
42
43 bits := math.Float64bits(x)
44 e := uint(bits>>shift) & mask
45 if e < bias {
46 // Round abs(x) < 1 including denormals.
47 bits &= signMask // +-0
48 if e == bias-1 {
49 bits |= one // +-1
50 }
51 } else if e < bias+shift {
52 // Round any abs(x) >= 1 containing a fractional component [0,1).
53 //
54 // Numbers with larger exponents are returned unchanged since they
55 // must be either an integer, infinity, or NaN.
56 e -= bias
57 bits += half >> e
58 bits &^= fracMask >> e
59 }
60 return math.Float64frombits(bits)
61 }