| 26 | ) |
| 27 | |
| 28 | func TestFloat16_Conversion(t *testing.T) { |
| 29 | tests := []struct { |
| 30 | name string |
| 31 | f32 float32 |
| 32 | want uint16 // bits |
| 33 | check bool // if true, check exact bits, else check float32 roundtrip within epsilon |
| 34 | }{ |
| 35 | {"Zero", 0.0, 0x0000, true}, |
| 36 | {"NegZero", float32(math.Copysign(0, -1)), 0x8000, true}, |
| 37 | {"One", 1.0, 0x3c00, true}, |
| 38 | {"MinusOne", -1.0, 0xbc00, true}, |
| 39 | {"Max", 65504.0, 0x7bff, true}, |
| 40 | {"Inf", float32(math.Inf(1)), 0x7c00, true}, |
| 41 | {"NegInf", float32(math.Inf(-1)), 0xfc00, true}, |
| 42 | // Smallest normal: 2^-14 = 0.000061035156 |
| 43 | {"SmallestNormal", float32(math.Pow(2, -14)), 0x0400, true}, |
| 44 | // Largest subnormal: 2^-14 - 2^-24 = 6.09756...e-5 |
| 45 | {"LargestSubnormal", float32(6.097555e-5), 0x03ff, true}, |
| 46 | // Smallest subnormal: 2^-24 |
| 47 | {"SmallestSubnormal", float32(math.Pow(2, -24)), 0x0001, true}, |
| 48 | } |
| 49 | |
| 50 | for _, tt := range tests { |
| 51 | t.Run(tt.name, func(t *testing.T) { |
| 52 | f16 := float16.Float16FromFloat32(tt.f32) |
| 53 | if tt.check { |
| 54 | assert.Equal(t, tt.want, f16.Bits(), "Bits match") |
| 55 | } |
| 56 | |
| 57 | // Round trip check |
| 58 | roundTrip := f16.Float32() |
| 59 | if math.IsInf(float64(tt.f32), 0) { |
| 60 | assert.True(t, math.IsInf(float64(roundTrip), 0)) |
| 61 | assert.Equal(t, math.Signbit(float64(tt.f32)), math.Signbit(float64(roundTrip))) |
| 62 | } else if math.IsNaN(float64(tt.f32)) { |
| 63 | assert.True(t, math.IsNaN(float64(roundTrip))) |
| 64 | } else { |
| 65 | // Allow small error due to precision loss |
| 66 | // Epsilon for float16 is 2^-10 ~= 0.001 relative error |
| 67 | // But we check consistency |
| 68 | if tt.check { |
| 69 | // bit exact means round trip should map back to similar float (precision loss expected) |
| 70 | // Verify that converting back to f16 gives same bits |
| 71 | f16back := float16.Float16FromFloat32(roundTrip) |
| 72 | assert.Equal(t, tt.want, f16back.Bits()) |
| 73 | } |
| 74 | } |
| 75 | }) |
| 76 | } |
| 77 | } |
| 78 | |
| 79 | func TestFloat16_NaN(t *testing.T) { |
| 80 | nan := float16.NaN |