remainder.go 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. // Copyright 2010 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. package math
  5. // The original C code and the comment below are from
  6. // FreeBSD's /usr/src/lib/msun/src/e_remainder.c and came
  7. // with this notice. The go code is a simplified version of
  8. // the original C.
  9. //
  10. // ====================================================
  11. // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  12. //
  13. // Developed at SunPro, a Sun Microsystems, Inc. business.
  14. // Permission to use, copy, modify, and distribute this
  15. // software is freely granted, provided that this notice
  16. // is preserved.
  17. // ====================================================
  18. //
  19. // __ieee754_remainder(x,y)
  20. // Return :
  21. // returns x REM y = x - [x/y]*y as if in infinite
  22. // precision arithmetic, where [x/y] is the (infinite bit)
  23. // integer nearest x/y (in half way cases, choose the even one).
  24. // Method :
  25. // Based on Mod() returning x - [x/y]chopped * y exactly.
  26. // Remainder returns the IEEE 754 floating-point remainder of x/y.
  27. //
  28. // Special cases are:
  29. //
  30. // Remainder(±Inf, y) = NaN
  31. // Remainder(NaN, y) = NaN
  32. // Remainder(x, 0) = NaN
  33. // Remainder(x, ±Inf) = x
  34. // Remainder(x, NaN) = NaN
  35. func Remainder(x, y float64) float64 {
  36. if haveArchRemainder {
  37. return archRemainder(x, y)
  38. }
  39. return remainder(x, y)
  40. }
  41. func remainder(x, y float64) float64 {
  42. const (
  43. Tiny = 4.45014771701440276618e-308 // 0x0020000000000000
  44. HalfMax = MaxFloat64 / 2
  45. )
  46. // special cases
  47. switch {
  48. case IsNaN(x) || IsNaN(y) || IsInf(x, 0) || y == 0:
  49. return NaN()
  50. case IsInf(y, 0):
  51. return x
  52. }
  53. sign := false
  54. if x < 0 {
  55. x = -x
  56. sign = true
  57. }
  58. if y < 0 {
  59. y = -y
  60. }
  61. if x == y {
  62. if sign {
  63. zero := 0.0
  64. return -zero
  65. }
  66. return 0
  67. }
  68. if y <= HalfMax {
  69. x = Mod(x, y+y) // now x < 2y
  70. }
  71. if y < Tiny {
  72. if x+x > y {
  73. x -= y
  74. if x+x >= y {
  75. x -= y
  76. }
  77. }
  78. } else {
  79. yHalf := 0.5 * y
  80. if x > yHalf {
  81. x -= y
  82. if x >= yHalf {
  83. x -= y
  84. }
  85. }
  86. }
  87. if sign {
  88. x = -x
  89. }
  90. return x
  91. }