Source file src/math/floor.go

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

View as plain text