round.go 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. package math32
  2. // Round returns the nearest integer, rounding half away from zero.
  3. //
  4. // Special cases are:
  5. // Round(±0) = ±0
  6. // Round(±Inf) = ±Inf
  7. // Round(NaN) = NaN
  8. func Round(x float32) float32 {
  9. // Round is a faster implementation of:
  10. //
  11. // func Round(x float64) float64 {
  12. // t := Trunc(x)
  13. // if Abs(x-t) >= 0.5 {
  14. // return t + Copysign(1, x)
  15. // }
  16. // return t
  17. // }
  18. bits := Float32bits(x)
  19. e := uint(bits>>shift) & mask
  20. if e < bias {
  21. // Round abs(x) < 1 including denormals.
  22. bits &= signMask // +-0
  23. if e == bias-1 {
  24. bits |= uvone // +-1
  25. }
  26. } else if e < bias+shift {
  27. // Round any abs(x) >= 1 containing a fractional component [0,1).
  28. //
  29. // Numbers with larger exponents are returned unchanged since they
  30. // must be either an integer, infinity, or NaN.
  31. const half = 1 << (shift - 1)
  32. e -= bias
  33. bits += half >> e
  34. bits &^= fracMask >> e
  35. }
  36. return Float32frombits(bits)
  37. }
  38. // RoundToEven returns the nearest integer, rounding ties to even.
  39. //
  40. // Special cases are:
  41. // RoundToEven(±0) = ±0
  42. // RoundToEven(±Inf) = ±Inf
  43. // RoundToEven(NaN) = NaN
  44. func RoundToEven(x float32) float32 {
  45. // RoundToEven is a faster implementation of:
  46. //
  47. // func RoundToEven(x float64) float64 {
  48. // t := math.Trunc(x)
  49. // odd := math.Remainder(t, 2) != 0
  50. // if d := math.Abs(x - t); d > 0.5 || (d == 0.5 && odd) {
  51. // return t + math.Copysign(1, x)
  52. // }
  53. // return t
  54. // }
  55. bits := Float32bits(x)
  56. e := uint(bits>>shift) & mask
  57. if e >= bias {
  58. // Round abs(x) >= 1.
  59. // - Large numbers without fractional components, infinity, and NaN are unchanged.
  60. // - Add 0.499.. or 0.5 before truncating depending on whether the truncated
  61. // number is even or odd (respectively).
  62. const halfMinusULP = (1 << (shift - 1)) - 1
  63. e -= bias
  64. bits += (halfMinusULP + (bits>>(shift-e))&1) >> e
  65. bits &^= fracMask >> e
  66. } else if e == bias-1 && bits&fracMask != 0 {
  67. // Round 0.5 < abs(x) < 1.
  68. bits = bits&signMask | uvone // +-1
  69. } else {
  70. // Round abs(x) <= 0.5 including denormals.
  71. bits &= signMask // +-0
  72. }
  73. return Float32frombits(bits)
  74. }