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
5package 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
14func Floor(x float64) float64 {
15	if haveArchFloor {
16		return archFloor(x)
17	}
18	return floor(x)
19}
20
21func 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
43func Ceil(x float64) float64 {
44	if haveArchCeil {
45		return archCeil(x)
46	}
47	return ceil(x)
48}
49
50func 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
61func Trunc(x float64) float64 {
62	if haveArchTrunc {
63		return archTrunc(x)
64	}
65	return trunc(x)
66}
67
68func 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
83func 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
121func 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