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