Source file
src/runtime/softfloat64_test.go
1
2
3
4
5 package runtime_test
6
7 import (
8 "math"
9 "math/rand"
10 . "runtime"
11 "testing"
12 )
13
14
15 func fop(f func(x, y uint64) uint64) func(x, y float64) float64 {
16 return func(x, y float64) float64 {
17 bx := math.Float64bits(x)
18 by := math.Float64bits(y)
19 return math.Float64frombits(f(bx, by))
20 }
21 }
22
23 func add(x, y float64) float64 { return x + y }
24 func sub(x, y float64) float64 { return x - y }
25 func mul(x, y float64) float64 { return x * y }
26 func div(x, y float64) float64 { return x / y }
27
28 func TestFloat64(t *testing.T) {
29 base := []float64{
30 0,
31 math.Copysign(0, -1),
32 -1,
33 1,
34 math.NaN(),
35 math.Inf(+1),
36 math.Inf(-1),
37 0.1,
38 1.5,
39 1.9999999999999998,
40 1.3333333333333333,
41 1.1428571428571428,
42 1.112536929253601e-308,
43 -2.662107816930723e-301,
44 2.662107858822336e-301,
45 2,
46 4,
47 8,
48 16,
49 32,
50 64,
51 128,
52 256,
53 3,
54 12,
55 1234,
56 123456,
57 -0.1,
58 -1.5,
59 -1.9999999999999998,
60 -1.3333333333333333,
61 -1.1428571428571428,
62 -2,
63 -3,
64 1e-200,
65 1e-300,
66 1e-310,
67 5e-324,
68 1e-105,
69 1e-305,
70 1e+200,
71 1e+306,
72 1e+307,
73 1e+308,
74 }
75 all := make([]float64, 200)
76 copy(all, base)
77 for i := len(base); i < len(all); i++ {
78 all[i] = rand.NormFloat64()
79 }
80
81 test(t, "+", add, fop(Fadd64), all)
82 test(t, "-", sub, fop(Fsub64), all)
83 if GOARCH != "386" {
84 test(t, "*", mul, fop(Fmul64), all)
85 test(t, "/", div, fop(Fdiv64), all)
86 }
87 }
88
89
90 func trunc32(f float64) float64 {
91 return float64(float32(f))
92 }
93
94
95 func to32sw(f float64) float64 {
96 return float64(math.Float32frombits(F64to32(math.Float64bits(f))))
97 }
98
99
100 func to64sw(f float64) float64 {
101 return math.Float64frombits(F32to64(math.Float32bits(float32(f))))
102 }
103
104
105 func hwint64(f float64) float64 {
106 return float64(int64(f))
107 }
108
109
110 func hwint32(f float64) float64 {
111 return float64(int32(f))
112 }
113
114
115 func toint64sw(f float64) float64 {
116 i, ok := F64toint(math.Float64bits(f))
117 if !ok {
118
119
120 i = int64(f)
121 }
122 return float64(i)
123 }
124
125
126 func fromint64sw(f float64) float64 {
127 return math.Float64frombits(Fintto64(int64(f)))
128 }
129
130 var nerr int
131
132 func err(t *testing.T, format string, args ...any) {
133 t.Errorf(format, args...)
134
135
136
137
138
139 if nerr++; nerr >= 10 {
140 t.Fatal("too many errors")
141 }
142 }
143
144 func test(t *testing.T, op string, hw, sw func(float64, float64) float64, all []float64) {
145 for _, f := range all {
146 for _, g := range all {
147 h := hw(f, g)
148 s := sw(f, g)
149 if !same(h, s) {
150 err(t, "%g %s %g = sw %g, hw %g\n", f, op, g, s, h)
151 }
152 testu(t, "to32", trunc32, to32sw, h)
153 testu(t, "to64", trunc32, to64sw, h)
154 testu(t, "toint64", hwint64, toint64sw, h)
155 testu(t, "fromint64", hwint64, fromint64sw, h)
156 testcmp(t, f, h)
157 testcmp(t, h, f)
158 testcmp(t, g, h)
159 testcmp(t, h, g)
160 }
161 }
162 }
163
164 func testu(t *testing.T, op string, hw, sw func(float64) float64, v float64) {
165 h := hw(v)
166 s := sw(v)
167 if !same(h, s) {
168 err(t, "%s %g = sw %g, hw %g\n", op, v, s, h)
169 }
170 }
171
172 func hwcmp(f, g float64) (cmp int, isnan bool) {
173 switch {
174 case f < g:
175 return -1, false
176 case f > g:
177 return +1, false
178 case f == g:
179 return 0, false
180 }
181 return 0, true
182 }
183
184 func testcmp(t *testing.T, f, g float64) {
185 hcmp, hisnan := hwcmp(f, g)
186 scmp, sisnan := Fcmp64(math.Float64bits(f), math.Float64bits(g))
187 if int32(hcmp) != scmp || hisnan != sisnan {
188 err(t, "cmp(%g, %g) = sw %v, %v, hw %v, %v\n", f, g, scmp, sisnan, hcmp, hisnan)
189 }
190 }
191
192 func same(f, g float64) bool {
193 if math.IsNaN(f) && math.IsNaN(g) {
194 return true
195 }
196 if math.Copysign(1, f) != math.Copysign(1, g) {
197 return false
198 }
199 return f == g
200 }
201
View as plain text