floor.mx raw
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 package math
6
7 // Floor returns the greatest integer value less than or equal to x.
8 //
9 // Special cases are:
10 //
11 // Floor(±0) = ±0
12 // Floor(±Inf) = ±Inf
13 // Floor(NaN) = NaN
14 func Floor(x float64) float64 {
15 if haveArchFloor {
16 return archFloor(x)
17 }
18 return floor(x)
19 }
20
21 func floor(x float64) float64 {
22 if x == 0 || IsNaN(x) || IsInf(x, 0) {
23 return x
24 }
25 if x < 0 {
26 d, fract := Modf(-x)
27 if fract != 0.0 {
28 d = d + 1
29 }
30 return -d
31 }
32 d, _ := Modf(x)
33 return d
34 }
35
36 // Ceil returns the least integer value greater than or equal to x.
37 //
38 // Special cases are:
39 //
40 // Ceil(±0) = ±0
41 // Ceil(±Inf) = ±Inf
42 // Ceil(NaN) = NaN
43 func Ceil(x float64) float64 {
44 if haveArchCeil {
45 return archCeil(x)
46 }
47 return ceil(x)
48 }
49
50 func ceil(x float64) float64 {
51 return -Floor(-x)
52 }
53
54 // Trunc returns the integer value of x.
55 //
56 // Special cases are:
57 //
58 // Trunc(±0) = ±0
59 // Trunc(±Inf) = ±Inf
60 // Trunc(NaN) = NaN
61 func Trunc(x float64) float64 {
62 if haveArchTrunc {
63 return archTrunc(x)
64 }
65 return trunc(x)
66 }
67
68 func trunc(x float64) float64 {
69 if x == 0 || IsNaN(x) || IsInf(x, 0) {
70 return x
71 }
72 d, _ := Modf(x)
73 return d
74 }
75
76 // Round returns the nearest integer, rounding half away from zero.
77 //
78 // Special cases are:
79 //
80 // Round(±0) = ±0
81 // Round(±Inf) = ±Inf
82 // Round(NaN) = NaN
83 func Round(x float64) float64 {
84 // Round is a faster implementation of:
85 //
86 // func Round(x float64) float64 {
87 // t := Trunc(x)
88 // if Abs(x-t) >= 0.5 {
89 // return t + Copysign(1, x)
90 // }
91 // return t
92 // }
93 bits := Float64bits(x)
94 e := uint(bits>>shift) & mask
95 if e < bias {
96 // Round abs(x) < 1 including denormals.
97 bits &= signMask // +-0
98 if e == bias-1 {
99 bits |= uvone // +-1
100 }
101 } else if e < bias+shift {
102 // Round any abs(x) >= 1 containing a fractional component [0,1).
103 //
104 // Numbers with larger exponents are returned unchanged since they
105 // must be either an integer, infinity, or NaN.
106 const half = 1 << (shift - 1)
107 e -= bias
108 bits += half >> e
109 bits &^= fracMask >> e
110 }
111 return Float64frombits(bits)
112 }
113
114 // RoundToEven returns the nearest integer, rounding ties to even.
115 //
116 // Special cases are:
117 //
118 // RoundToEven(±0) = ±0
119 // RoundToEven(±Inf) = ±Inf
120 // RoundToEven(NaN) = NaN
121 func RoundToEven(x float64) float64 {
122 // RoundToEven is a faster implementation of:
123 //
124 // func RoundToEven(x float64) float64 {
125 // t := math.Trunc(x)
126 // odd := math.Remainder(t, 2) != 0
127 // if d := math.Abs(x - t); d > 0.5 || (d == 0.5 && odd) {
128 // return t + math.Copysign(1, x)
129 // }
130 // return t
131 // }
132 bits := Float64bits(x)
133 e := uint(bits>>shift) & mask
134 if e >= bias {
135 // Round abs(x) >= 1.
136 // - Large numbers without fractional components, infinity, and NaN are unchanged.
137 // - Add 0.499.. or 0.5 before truncating depending on whether the truncated
138 // number is even or odd (respectively).
139 const halfMinusULP = (1 << (shift - 1)) - 1
140 e -= bias
141 bits += (halfMinusULP + (bits>>(shift-e))&1) >> e
142 bits &^= fracMask >> e
143 } else if e == bias-1 && bits&fracMask != 0 {
144 // Round 0.5 < abs(x) < 1.
145 bits = bits&signMask | uvone // +-1
146 } else {
147 // Round abs(x) <= 0.5 including denormals.
148 bits &= signMask // +-0
149 }
150 return Float64frombits(bits)
151 }
152