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