Source file src/runtime/float.go

     1  // Copyright 2017 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 runtime
     6  
     7  import "unsafe"
     8  
     9  const (
    10  	float64Mask  = 0x7FF
    11  	float64Shift = 64 - 11 - 1
    12  	float64Bias  = 1023
    13  )
    14  
    15  var inf = float64frombits(0x7FF0000000000000)
    16  
    17  // isNaN reports whether f is an IEEE 754 “not-a-number” value.
    18  func isNaN(f float64) (is bool) {
    19  	// IEEE 754 says that only NaNs satisfy f != f.
    20  	return f != f
    21  }
    22  
    23  // isFinite reports whether f is neither NaN nor an infinity.
    24  func isFinite(f float64) bool {
    25  	return !isNaN(f - f)
    26  }
    27  
    28  // isInf reports whether f is an infinity.
    29  func isInf(f float64) bool {
    30  	return !isNaN(f) && !isFinite(f)
    31  }
    32  
    33  // abs returns the absolute value of x.
    34  //
    35  // Special cases are:
    36  //
    37  //	abs(±Inf) = +Inf
    38  //	abs(NaN) = NaN
    39  func abs(x float64) float64 {
    40  	const sign = 1 << 63
    41  	return float64frombits(float64bits(x) &^ sign)
    42  }
    43  
    44  // copysign returns a value with the magnitude
    45  // of x and the sign of y.
    46  func copysign(x, y float64) float64 {
    47  	const sign = 1 << 63
    48  	return float64frombits(float64bits(x)&^sign | float64bits(y)&sign)
    49  }
    50  
    51  // float64bits returns the IEEE 754 binary representation of f.
    52  func float64bits(f float64) uint64 {
    53  	return *(*uint64)(unsafe.Pointer(&f))
    54  }
    55  
    56  // float64frombits returns the floating point number corresponding
    57  // the IEEE 754 binary representation b.
    58  func float64frombits(b uint64) float64 {
    59  	return *(*float64)(unsafe.Pointer(&b))
    60  }
    61  
    62  // floor returns the greatest integer value less than or equal to x.
    63  //
    64  // Special cases are:
    65  //
    66  //	floor(±0) = ±0
    67  //	floor(±Inf) = ±Inf
    68  //	floor(NaN) = NaN
    69  //
    70  // N.B. Portable floor copied from math. math also has optimized arch-specific
    71  // implementations.
    72  func floor(x float64) float64 {
    73  	if x == 0 || isNaN(x) || isInf(x) {
    74  		return x
    75  	}
    76  	if x < 0 {
    77  		d, fract := modf(-x)
    78  		if fract != 0.0 {
    79  			d = d + 1
    80  		}
    81  		return -d
    82  	}
    83  	d, _ := modf(x)
    84  	return d
    85  }
    86  
    87  // ceil returns the least integer value greater than or equal to x.
    88  //
    89  // Special cases are:
    90  //
    91  //	Ceil(±0) = ±0
    92  //	Ceil(±Inf) = ±Inf
    93  //	Ceil(NaN) = NaN
    94  //
    95  // N.B. Portable ceil copied from math. math also has optimized arch-specific
    96  // implementations.
    97  func ceil(x float64) float64 {
    98  	return -floor(-x)
    99  }
   100  
   101  // modf returns integer and fractional floating-point numbers
   102  // that sum to f. Both values have the same sign as f.
   103  //
   104  // Special cases are:
   105  //
   106  //	Modf(±Inf) = ±Inf, NaN
   107  //	Modf(NaN) = NaN, NaN
   108  //
   109  // N.B. Portable modf copied from math. math also has optimized arch-specific
   110  // implementations.
   111  func modf(f float64) (int float64, frac float64) {
   112  	if f < 1 {
   113  		switch {
   114  		case f < 0:
   115  			int, frac = modf(-f)
   116  			return -int, -frac
   117  		case f == 0:
   118  			return f, f // Return -0, -0 when f == -0
   119  		}
   120  		return 0, f
   121  	}
   122  
   123  	x := float64bits(f)
   124  	e := uint(x>>float64Shift)&float64Mask - float64Bias
   125  
   126  	// Keep the top 12+e bits, the integer part; clear the rest.
   127  	if e < 64-12 {
   128  		x &^= 1<<(64-12-e) - 1
   129  	}
   130  	int = float64frombits(x)
   131  	frac = f - int
   132  	return
   133  }
   134  

View as plain text