remainder.go 1.8 KB

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