Skip to content

Commit faaf17e

Browse files
committed
feat: Add comprehensive tests to increase coverage
1 parent 33ab34d commit faaf17e

3 files changed

Lines changed: 677 additions & 139 deletions

File tree

convert_extra_test.go

Lines changed: 327 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,327 @@
1+
package float16
2+
3+
import (
4+
"math"
5+
"testing"
6+
)
7+
8+
func TestIntConversions(t *testing.T) {
9+
testCases := []struct {
10+
name string
11+
i32 int32
12+
i64 int64
13+
f Float16
14+
expected interface{}
15+
op interface{}
16+
}{
17+
// FromInt32
18+
{"FromInt32(0)", 0, 0, 0, FromFloat32(0), FromInt32},
19+
{"FromInt32(1)", 1, 0, 0, FromFloat32(1), FromInt32},
20+
{"FromInt32(-1)", -1, 0, 0, FromFloat32(-1), FromInt32},
21+
22+
// FromInt64
23+
{"FromInt64(0)", 0, 0, 0, FromFloat32(0), FromInt64},
24+
{"FromInt64(1)", 0, 1, 0, FromFloat32(1), FromInt64},
25+
{"FromInt64(-1)", 0, -1, 0, FromFloat32(-1), FromInt64},
26+
27+
// ToInt
28+
{"ToInt(0)", 0, 0, FromFloat32(0), 0, "ToInt"},
29+
{"ToInt(1.5)", 0, 0, FromFloat32(1.5), 1, "ToInt"},
30+
{"ToInt(-1.5)", 0, 0, FromFloat32(-1.5), -1, "ToInt"},
31+
32+
// ToInt32
33+
{"ToInt32(0)", 0, 0, FromFloat32(0), int32(0), "ToInt32"},
34+
{"ToInt32(1.5)", 0, 0, FromFloat32(1.5), int32(1), "ToInt32"},
35+
{"ToInt32(-1.5)", 0, 0, FromFloat32(-1.5), int32(-1), "ToInt32"},
36+
37+
// ToInt64
38+
{"ToInt64(0)", 0, 0, FromFloat32(0), int64(0), "ToInt64"},
39+
{"ToInt64(1.5)", 0, 0, FromFloat32(1.5), int64(1), "ToInt64"},
40+
{"ToInt64(-1.5)", 0, 0, FromFloat32(-1.5), int64(-1), "ToInt64"},
41+
}
42+
43+
for _, tc := range testCases {
44+
t.Run(tc.name, func(t *testing.T) {
45+
switch op := tc.op.(type) {
46+
case func(int32) Float16:
47+
res := op(tc.i32)
48+
if res.Bits() != tc.expected.(Float16).Bits() {
49+
t.Errorf("Expected %v, got %v", tc.expected, res)
50+
}
51+
case func(int64) Float16:
52+
res := op(tc.i64)
53+
if res.Bits() != tc.expected.(Float16).Bits() {
54+
t.Errorf("Expected %v, got %v", tc.expected, res)
55+
}
56+
case string:
57+
switch op {
58+
case "ToInt":
59+
res := tc.f.ToInt()
60+
if res != tc.expected.(int) {
61+
t.Errorf("Expected %v, got %v", tc.expected, res)
62+
}
63+
case "ToInt32":
64+
res := tc.f.ToInt32()
65+
if res != tc.expected.(int32) {
66+
t.Errorf("Expected %v, got %v", tc.expected, res)
67+
}
68+
case "ToInt64":
69+
res := tc.f.ToInt64()
70+
if res != tc.expected.(int64) {
71+
t.Errorf("Expected %v, got %v", tc.expected, res)
72+
}
73+
}
74+
}
75+
})
76+
}
77+
}
78+
79+
func TestParse(t *testing.T) {
80+
_, err := Parse("1.0")
81+
if err == nil {
82+
t.Errorf("Expected error, got nil")
83+
}
84+
}
85+
86+
func TestFloat32Conversions(t *testing.T) {
87+
testCases := []struct {
88+
name string
89+
f32 float32
90+
f16 Float16
91+
expected interface{}
92+
op string
93+
}{
94+
// ToFloat16
95+
{"ToFloat16(0)", 0, 0, FromFloat32(0), "ToFloat16"},
96+
{"ToFloat16(1)", 1, 0, FromFloat32(1), "ToFloat16"},
97+
{"ToFloat16(-1)", -1, 0, FromFloat32(-1), "ToFloat16"},
98+
{"ToFloat16(65504)", 65504, 0, FromFloat32(65504), "ToFloat16"},
99+
100+
// FromFloat32
101+
{"FromFloat32(0)", 0, FromFloat32(0), float32(0), "FromFloat32"},
102+
{"FromFloat32(1)", 0, FromFloat32(1), float32(1), "FromFloat32"},
103+
{"FromFloat32(-1)", 0, FromFloat32(-1), float32(-1), "FromFloat32"},
104+
}
105+
106+
for _, tc := range testCases {
107+
t.Run(tc.name, func(t *testing.T) {
108+
switch tc.op {
109+
case "ToFloat16":
110+
res := ToFloat16(tc.f32)
111+
if res.Bits() != tc.expected.(Float16).Bits() {
112+
t.Errorf("Expected %v, got %v", tc.expected, res)
113+
}
114+
case "FromFloat32":
115+
res := tc.f16.ToFloat32()
116+
if res != tc.expected.(float32) {
117+
t.Errorf("Expected %v, got %v", tc.expected, res)
118+
}
119+
}
120+
})
121+
}
122+
}
123+
124+
func TestFloat64Conversions(t *testing.T) {
125+
testCases := []struct {
126+
name string
127+
f64 float64
128+
f16 Float16
129+
expected interface{}
130+
op string
131+
}{
132+
// FromFloat64
133+
{"FromFloat64(0)", 0, 0, FromFloat64(0), "FromFloat64"},
134+
{"FromFloat64(1)", 1, 0, FromFloat64(1), "FromFloat64"},
135+
{"FromFloat64(-1)", -1, 0, FromFloat64(-1), "FromFloat64"},
136+
{"FromFloat64(65504)", 65504, 0, FromFloat64(65504), "FromFloat64"},
137+
138+
// ToFloat64
139+
{"ToFloat64(0)", 0, FromFloat64(0), float64(0), "ToFloat64"},
140+
{"ToFloat64(1)", 0, FromFloat64(1), float64(1), "ToFloat64"},
141+
{"ToFloat64(-1)", 0, FromFloat64(-1), float64(-1), "ToFloat64"},
142+
}
143+
144+
for _, tc := range testCases {
145+
t.Run(tc.name, func(t *testing.T) {
146+
switch tc.op {
147+
case "FromFloat64":
148+
res := FromFloat64(tc.f64)
149+
if res.Bits() != tc.expected.(Float16).Bits() {
150+
t.Errorf("Expected %v, got %v", tc.expected, res)
151+
}
152+
case "ToFloat64":
153+
res := tc.f16.ToFloat64()
154+
if res != tc.expected.(float64) {
155+
t.Errorf("Expected %v, got %v", tc.expected, res)
156+
}
157+
}
158+
})
159+
}
160+
}
161+
162+
func TestFromFloat64WithModeExtra(t *testing.T) {
163+
testCases := []struct {
164+
name string
165+
f64 float64
166+
convMode ConversionMode
167+
roundMode RoundingMode
168+
expected Float16
169+
err bool
170+
}{
171+
{"Normal", 1.0, ModeIEEE, RoundNearestEven, FromFloat64(1.0), false},
172+
{"Strict Inf", math.Inf(1), ModeStrict, RoundNearestEven, 0, true},
173+
{"Strict NaN", math.NaN(), ModeStrict, RoundNearestEven, 0, true},
174+
}
175+
176+
for _, tc := range testCases {
177+
t.Run(tc.name, func(t *testing.T) {
178+
res, err := FromFloat64WithMode(tc.f64, tc.convMode, tc.roundMode)
179+
if (err != nil) != tc.err {
180+
t.Errorf("Expected error %v, got %v", tc.err, err)
181+
}
182+
if res.Bits() != tc.expected.Bits() {
183+
t.Errorf("Expected %v, got %v", tc.expected, res)
184+
}
185+
})
186+
}
187+
}
188+
189+
func TestToFloat16WithMode(t *testing.T) {
190+
testCases := []struct {
191+
name string
192+
f32 float32
193+
convMode ConversionMode
194+
roundMode RoundingMode
195+
expected Float16
196+
err bool
197+
}{
198+
{"Normal", 1.0, ModeIEEE, RoundNearestEven, FromFloat32(1.0), false},
199+
{"Strict Inf", float32(math.Inf(1)), ModeStrict, RoundNearestEven, 0, true},
200+
{"Strict NaN", float32(math.NaN()), ModeStrict, RoundNearestEven, 0, true},
201+
}
202+
203+
for _, tc := range testCases {
204+
t.Run(tc.name, func(t *testing.T) {
205+
res, err := ToFloat16WithMode(tc.f32, tc.convMode, tc.roundMode)
206+
if (err != nil) != tc.err {
207+
t.Errorf("Expected error %v, got %v", tc.err, err)
208+
}
209+
if res.Bits() != tc.expected.Bits() {
210+
t.Errorf("Expected %v, got %v", tc.expected, res)
211+
}
212+
})
213+
}
214+
}
215+
216+
func TestShouldRound(t *testing.T) {
217+
testCases := []struct {
218+
name string
219+
mantissa uint32
220+
shift int
221+
mode RoundingMode
222+
expected bool
223+
}{
224+
{"NearestEven_NoRound", 0x1234, 4, RoundNearestEven, false},
225+
{"NearestEven_Round", 0x1238, 4, RoundNearestEven, true},
226+
}
227+
228+
for _, tc := range testCases {
229+
t.Run(tc.name, func(t *testing.T) {
230+
res := shouldRound(tc.mantissa, tc.shift, tc.mode)
231+
if res != tc.expected {
232+
t.Errorf("Expected %v, got %v", tc.expected, res)
233+
}
234+
})
235+
}
236+
}
237+
238+
func TestSliceConversions(t *testing.T) {
239+
// Test ToSlice16
240+
f32s := []float32{0, 1, -1, 65504}
241+
f16s := ToSlice16(f32s)
242+
if len(f16s) != len(f32s) {
243+
t.Errorf("ToSlice16: expected length %d, got %d", len(f32s), len(f16s))
244+
}
245+
expectedF16s := []Float16{FromFloat32(0), FromFloat32(1), FromFloat32(-1), FromFloat32(65504)}
246+
for i := range f16s {
247+
if f16s[i].Bits() != expectedF16s[i].Bits() {
248+
t.Errorf("ToSlice16: at index %d, expected %v, got %v", i, expectedF16s[i], f16s[i])
249+
}
250+
}
251+
252+
// Test ToSlice32
253+
f32sBack := ToSlice32(f16s)
254+
if len(f32sBack) != len(f16s) {
255+
t.Errorf("ToSlice32: expected length %d, got %d", len(f16s), len(f32sBack))
256+
}
257+
for i := range f32sBack {
258+
if f32sBack[i] != f32s[i] {
259+
t.Errorf("ToSlice32: at index %d, expected %v, got %v", i, f32s[i], f32sBack[i])
260+
}
261+
}
262+
263+
// Test ToSlice64 and FromSlice64
264+
f64s := []float64{0, 1, -1, 65504}
265+
f16sFrom64 := FromSlice64(f64s)
266+
if len(f16sFrom64) != len(f64s) {
267+
t.Errorf("FromSlice64: expected length %d, got %d", len(f64s), len(f16sFrom64))
268+
}
269+
expectedF16sFrom64 := []Float16{FromFloat64(0), FromFloat64(1), FromFloat64(-1), FromFloat64(65504)}
270+
for i := range f16sFrom64 {
271+
if f16sFrom64[i].Bits() != expectedF16sFrom64[i].Bits() {
272+
t.Errorf("FromSlice64: at index %d, expected %v, got %v", i, expectedF16sFrom64[i], f16sFrom64[i])
273+
}
274+
}
275+
276+
f64sBack := ToSlice64(f16sFrom64)
277+
if len(f64sBack) != len(f16sFrom64) {
278+
t.Errorf("ToSlice64: expected length %d, got %d", len(f16sFrom64), len(f64sBack))
279+
}
280+
for i := range f64sBack {
281+
if f64sBack[i] != f64s[i] {
282+
t.Errorf("ToSlice64: at index %d, expected %v, got %v", i, f64s[i], f64sBack[i])
283+
}
284+
}
285+
286+
// Test empty slices
287+
if ToSlice16(nil) != nil {
288+
t.Error("ToSlice16(nil) should be nil")
289+
}
290+
if ToSlice32(nil) != nil {
291+
t.Error("ToSlice32(nil) should be nil")
292+
}
293+
if ToSlice64(nil) != nil {
294+
t.Error("ToSlice64(nil) should be nil")
295+
}
296+
if FromSlice64(nil) != nil {
297+
t.Error("FromSlice64(nil) should be nil")
298+
}
299+
}
300+
301+
func TestToSlice16WithModeExtra(t *testing.T) {
302+
f32s := []float32{1.0, float32(math.Inf(1)), float32(math.NaN())}
303+
_, errs := ToSlice16WithMode(f32s, ModeStrict, RoundNearestEven)
304+
if len(errs) != 2 {
305+
t.Errorf("Expected 2 errors, got %d", len(errs))
306+
}
307+
308+
f16s, errs := ToSlice16WithMode(f32s, ModeIEEE, RoundNearestEven)
309+
if len(errs) != 0 {
310+
t.Errorf("Expected 0 errors, got %d", len(errs))
311+
}
312+
expectedF16s := []Float16{FromFloat32(1.0), PositiveInfinity, QuietNaN}
313+
for i := range f16s {
314+
if expectedF16s[i].IsNaN() {
315+
if !f16s[i].IsNaN() {
316+
t.Errorf("ToSlice16WithMode: at index %d, expected NaN, got %v", i, f16s[i])
317+
}
318+
} else if f16s[i].Bits() != expectedF16s[i].Bits() {
319+
t.Errorf("ToSlice16WithMode: at index %d, expected %v, got %v", i, expectedF16s[i], f16s[i])
320+
}
321+
}
322+
323+
f16s, errs = ToSlice16WithMode(nil, ModeIEEE, RoundNearestEven)
324+
if f16s != nil || errs != nil {
325+
t.Error("ToSlice16WithMode(nil) should be (nil, nil)")
326+
}
327+
}

0 commit comments

Comments
 (0)