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