diff options
Diffstat (limited to 'src/math/floor.go')
-rw-r--r-- | src/math/floor.go | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/src/math/floor.go b/src/math/floor.go new file mode 100644 index 0000000..cb58564 --- /dev/null +++ b/src/math/floor.go @@ -0,0 +1,151 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package math + +// Floor returns the greatest integer value less than or equal to x. +// +// Special cases are: +// +// Floor(±0) = ±0 +// Floor(±Inf) = ±Inf +// Floor(NaN) = NaN +func Floor(x float64) float64 { + if haveArchFloor { + return archFloor(x) + } + return floor(x) +} + +func floor(x float64) float64 { + if x == 0 || IsNaN(x) || IsInf(x, 0) { + return x + } + if x < 0 { + d, fract := Modf(-x) + if fract != 0.0 { + d = d + 1 + } + return -d + } + d, _ := Modf(x) + return d +} + +// Ceil returns the least integer value greater than or equal to x. +// +// Special cases are: +// +// Ceil(±0) = ±0 +// Ceil(±Inf) = ±Inf +// Ceil(NaN) = NaN +func Ceil(x float64) float64 { + if haveArchCeil { + return archCeil(x) + } + return ceil(x) +} + +func ceil(x float64) float64 { + return -Floor(-x) +} + +// Trunc returns the integer value of x. +// +// Special cases are: +// +// Trunc(±0) = ±0 +// Trunc(±Inf) = ±Inf +// Trunc(NaN) = NaN +func Trunc(x float64) float64 { + if haveArchTrunc { + return archTrunc(x) + } + return trunc(x) +} + +func trunc(x float64) float64 { + if x == 0 || IsNaN(x) || IsInf(x, 0) { + return x + } + d, _ := Modf(x) + return d +} + +// Round returns the nearest integer, rounding half away from zero. +// +// Special cases are: +// +// Round(±0) = ±0 +// Round(±Inf) = ±Inf +// Round(NaN) = NaN +func Round(x float64) float64 { + // Round is a faster implementation of: + // + // func Round(x float64) float64 { + // t := Trunc(x) + // if Abs(x-t) >= 0.5 { + // return t + Copysign(1, x) + // } + // return t + // } + bits := Float64bits(x) + e := uint(bits>>shift) & mask + if e < bias { + // Round abs(x) < 1 including denormals. + bits &= signMask // +-0 + if e == bias-1 { + bits |= uvone // +-1 + } + } else if e < bias+shift { + // Round any abs(x) >= 1 containing a fractional component [0,1). + // + // Numbers with larger exponents are returned unchanged since they + // must be either an integer, infinity, or NaN. + const half = 1 << (shift - 1) + e -= bias + bits += half >> e + bits &^= fracMask >> e + } + return Float64frombits(bits) +} + +// RoundToEven returns the nearest integer, rounding ties to even. +// +// Special cases are: +// +// RoundToEven(±0) = ±0 +// RoundToEven(±Inf) = ±Inf +// RoundToEven(NaN) = NaN +func RoundToEven(x float64) float64 { + // RoundToEven is a faster implementation of: + // + // func RoundToEven(x float64) float64 { + // t := math.Trunc(x) + // odd := math.Remainder(t, 2) != 0 + // if d := math.Abs(x - t); d > 0.5 || (d == 0.5 && odd) { + // return t + math.Copysign(1, x) + // } + // return t + // } + bits := Float64bits(x) + e := uint(bits>>shift) & mask + if e >= bias { + // Round abs(x) >= 1. + // - Large numbers without fractional components, infinity, and NaN are unchanged. + // - Add 0.499.. or 0.5 before truncating depending on whether the truncated + // number is even or odd (respectively). + const halfMinusULP = (1 << (shift - 1)) - 1 + e -= bias + bits += (halfMinusULP + (bits>>(shift-e))&1) >> e + bits &^= fracMask >> e + } else if e == bias-1 && bits&fracMask != 0 { + // Round 0.5 < abs(x) < 1. + bits = bits&signMask | uvone // +-1 + } else { + // Round abs(x) <= 0.5 including denormals. + bits &= signMask // +-0 + } + return Float64frombits(bits) +} |