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  }