softfloat64_test.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  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 runtime_test
  5. import (
  6. "math"
  7. "math/rand"
  8. . "runtime"
  9. "testing"
  10. )
  11. // turn uint64 op into float64 op
  12. func fop(f func(x, y uint64) uint64) func(x, y float64) float64 {
  13. return func(x, y float64) float64 {
  14. bx := math.Float64bits(x)
  15. by := math.Float64bits(y)
  16. return math.Float64frombits(f(bx, by))
  17. }
  18. }
  19. func add(x, y float64) float64 { return x + y }
  20. func sub(x, y float64) float64 { return x - y }
  21. func mul(x, y float64) float64 { return x * y }
  22. func div(x, y float64) float64 { return x / y }
  23. func TestFloat64(t *testing.T) {
  24. base := []float64{
  25. 0,
  26. math.Copysign(0, -1),
  27. -1,
  28. 1,
  29. math.NaN(),
  30. math.Inf(+1),
  31. math.Inf(-1),
  32. 0.1,
  33. 1.5,
  34. 1.9999999999999998, // all 1s mantissa
  35. 1.3333333333333333, // 1.010101010101...
  36. 1.1428571428571428, // 1.001001001001...
  37. 1.112536929253601e-308, // first normal
  38. 2,
  39. 4,
  40. 8,
  41. 16,
  42. 32,
  43. 64,
  44. 128,
  45. 256,
  46. 3,
  47. 12,
  48. 1234,
  49. 123456,
  50. -0.1,
  51. -1.5,
  52. -1.9999999999999998,
  53. -1.3333333333333333,
  54. -1.1428571428571428,
  55. -2,
  56. -3,
  57. 1e-200,
  58. 1e-300,
  59. 1e-310,
  60. 5e-324,
  61. 1e-105,
  62. 1e-305,
  63. 1e+200,
  64. 1e+306,
  65. 1e+307,
  66. 1e+308,
  67. }
  68. all := make([]float64, 200)
  69. copy(all, base)
  70. for i := len(base); i < len(all); i++ {
  71. all[i] = rand.NormFloat64()
  72. }
  73. test(t, "+", add, fop(Fadd64), all)
  74. test(t, "-", sub, fop(Fsub64), all)
  75. if GOARCH != "386" { // 386 is not precise!
  76. test(t, "*", mul, fop(Fmul64), all)
  77. test(t, "/", div, fop(Fdiv64), all)
  78. }
  79. }
  80. // 64 -hw-> 32 -hw-> 64
  81. func trunc32(f float64) float64 {
  82. return float64(float32(f))
  83. }
  84. // 64 -sw->32 -hw-> 64
  85. func to32sw(f float64) float64 {
  86. return float64(math.Float32frombits(F64to32(math.Float64bits(f))))
  87. }
  88. // 64 -hw->32 -sw-> 64
  89. func to64sw(f float64) float64 {
  90. return math.Float64frombits(F32to64(math.Float32bits(float32(f))))
  91. }
  92. // float64 -hw-> int64 -hw-> float64
  93. func hwint64(f float64) float64 {
  94. return float64(int64(f))
  95. }
  96. // float64 -hw-> int32 -hw-> float64
  97. func hwint32(f float64) float64 {
  98. return float64(int32(f))
  99. }
  100. // float64 -sw-> int64 -hw-> float64
  101. func toint64sw(f float64) float64 {
  102. i, ok := F64toint(math.Float64bits(f))
  103. if !ok {
  104. // There's no right answer for out of range.
  105. // Match the hardware to pass the test.
  106. i = int64(f)
  107. }
  108. return float64(i)
  109. }
  110. // float64 -hw-> int64 -sw-> float64
  111. func fromint64sw(f float64) float64 {
  112. return math.Float64frombits(Fintto64(int64(f)))
  113. }
  114. var nerr int
  115. func err(t *testing.T, format string, args ...interface{}) {
  116. t.Errorf(format, args...)
  117. // cut errors off after a while.
  118. // otherwise we spend all our time
  119. // allocating memory to hold the
  120. // formatted output.
  121. if nerr++; nerr >= 10 {
  122. t.Fatal("too many errors")
  123. }
  124. }
  125. func test(t *testing.T, op string, hw, sw func(float64, float64) float64, all []float64) {
  126. for _, f := range all {
  127. for _, g := range all {
  128. h := hw(f, g)
  129. s := sw(f, g)
  130. if !same(h, s) {
  131. err(t, "%g %s %g = sw %g, hw %g\n", f, op, g, s, h)
  132. }
  133. testu(t, "to32", trunc32, to32sw, h)
  134. testu(t, "to64", trunc32, to64sw, h)
  135. testu(t, "toint64", hwint64, toint64sw, h)
  136. testu(t, "fromint64", hwint64, fromint64sw, h)
  137. testcmp(t, f, h)
  138. testcmp(t, h, f)
  139. testcmp(t, g, h)
  140. testcmp(t, h, g)
  141. }
  142. }
  143. }
  144. func testu(t *testing.T, op string, hw, sw func(float64) float64, v float64) {
  145. h := hw(v)
  146. s := sw(v)
  147. if !same(h, s) {
  148. err(t, "%s %g = sw %g, hw %g\n", op, v, s, h)
  149. }
  150. }
  151. func hwcmp(f, g float64) (cmp int, isnan bool) {
  152. switch {
  153. case f < g:
  154. return -1, false
  155. case f > g:
  156. return +1, false
  157. case f == g:
  158. return 0, false
  159. }
  160. return 0, true // must be NaN
  161. }
  162. func testcmp(t *testing.T, f, g float64) {
  163. hcmp, hisnan := hwcmp(f, g)
  164. scmp, sisnan := Fcmp64(math.Float64bits(f), math.Float64bits(g))
  165. if hcmp != scmp || hisnan != sisnan {
  166. err(t, "cmp(%g, %g) = sw %v, %v, hw %v, %v\n", f, g, scmp, sisnan, hcmp, hisnan)
  167. }
  168. }
  169. func same(f, g float64) bool {
  170. if math.IsNaN(f) && math.IsNaN(g) {
  171. return true
  172. }
  173. if math.Copysign(1, f) != math.Copysign(1, g) {
  174. return false
  175. }
  176. return f == g
  177. }