]> Cypherpunks.ru repositories - gostls13.git/blob - src/runtime/softfloat64_test.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / src / runtime / softfloat64_test.go
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
5 package runtime_test
6
7 import (
8         "math"
9         "math/rand"
10         . "runtime"
11         "testing"
12 )
13
14 // turn uint64 op into float64 op
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,     // all 1s mantissa
40                 1.3333333333333333,     // 1.010101010101...
41                 1.1428571428571428,     // 1.001001001001...
42                 1.112536929253601e-308, // first normal
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" { // 386 is not precise!
82                 test(t, "*", mul, fop(Fmul64), all)
83                 test(t, "/", div, fop(Fdiv64), all)
84         }
85 }
86
87 // 64 -hw-> 32 -hw-> 64
88 func trunc32(f float64) float64 {
89         return float64(float32(f))
90 }
91
92 // 64 -sw->32 -hw-> 64
93 func to32sw(f float64) float64 {
94         return float64(math.Float32frombits(F64to32(math.Float64bits(f))))
95 }
96
97 // 64 -hw->32 -sw-> 64
98 func to64sw(f float64) float64 {
99         return math.Float64frombits(F32to64(math.Float32bits(float32(f))))
100 }
101
102 // float64 -hw-> int64 -hw-> float64
103 func hwint64(f float64) float64 {
104         return float64(int64(f))
105 }
106
107 // float64 -hw-> int32 -hw-> float64
108 func hwint32(f float64) float64 {
109         return float64(int32(f))
110 }
111
112 // float64 -sw-> int64 -hw-> float64
113 func toint64sw(f float64) float64 {
114         i, ok := F64toint(math.Float64bits(f))
115         if !ok {
116                 // There's no right answer for out of range.
117                 // Match the hardware to pass the test.
118                 i = int64(f)
119         }
120         return float64(i)
121 }
122
123 // float64 -hw-> int64 -sw-> float64
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         // cut errors off after a while.
134         // otherwise we spend all our time
135         // allocating memory to hold the
136         // formatted output.
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 // must be NaN
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 }