1const builtin = @import("builtin");
2const std = @import("std");
3const testing = std.testing;
4
5const impl = @import("extendf.zig");
6
7const f32_floatCast_f16 = impl.f32_floatCast_f16;
8const f64_floatCast_f16 = impl.f64_floatCast_f16;
9const f80_floatCast_f16 = impl.f80_floatCast_f16;
10const f128_floatCast_f16 = impl.f128_floatCast_f16;
11
12const f64_floatCast_f32 = impl.f64_floatCast_f32;
13const f80_floatCast_f32 = impl.f80_floatCast_f32;
14const f128_floatCast_f32 = impl.f128_floatCast_f32;
15
16const f80_floatCast_f64 = impl.f80_floatCast_f64;
17const f128_floatCast_f64 = impl.f128_floatCast_f64;
18
19const f128_floatCast_f80 = impl.f128_floatCast_f80;
20
21fn test_f80_floatCast_f64(a: f64, expected: u80) !void {
22 const x = f80_floatCast_f64(a);
23
24 const rep: u80 = @bitCast(x);
25 if (rep == expected)
26 return;
27 // test other possible NaN representation(signal NaN)
28 if (std.math.isNan(@as(f80, @bitCast(expected))) and std.math.isNan(x))
29 return;
30 return error.TestFailure;
31}
32
33fn test_f128_floatCast_f64(a: f64, expected_hi: u64, expected_lo: u64) !void {
34 const x = f128_floatCast_f64(a);
35
36 const rep: u128 = @bitCast(x);
37 const hi: u64 = @intCast(rep >> 64);
38 const lo: u64 = @truncate(rep);
39
40 if (hi == expected_hi and lo == expected_lo)
41 return;
42 // test other possible NaN representation(signal NaN)
43 if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) {
44 if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and
45 ((hi & 0xffffffffffff) > 0 or lo > 0))
46 {
47 return;
48 }
49 }
50 return error.TestFailure;
51}
52
53fn test_f32_floatCast_f16(a: u16, expected: u32) !void {
54 const x = f32_floatCast_f16(@bitCast(a));
55 const rep: u32 = @bitCast(x);
56
57 if (rep == expected) {
58 if (rep & 0x7fffffff > 0x7f800000) {
59 return; // NaN is always unequal.
60 }
61 if (x == @as(f32, @bitCast(expected))) {
62 return;
63 }
64 }
65 return error.TestFailure;
66}
67
68fn test_f128_floatCast_f32(a: f32, expected_hi: u64, expected_lo: u64) !void {
69 const x = f128_floatCast_f32(a);
70
71 const rep: u128 = @bitCast(x);
72 const hi: u64 = @intCast(rep >> 64);
73 const lo: u64 = @truncate(rep);
74
75 if (hi == expected_hi and lo == expected_lo)
76 return;
77 // test other possible NaN representation(signal NaN)
78 if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) {
79 if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and
80 ((hi & 0xffffffffffff) > 0 or lo > 0))
81 {
82 return;
83 }
84 }
85 return error.TestFailure;
86}
87
88test f80_floatCast_f64 {
89 // qNaN
90 try test_f80_floatCast_f64(makeQNaN64(), 0x7fffc000000000000000);
91
92 // NaN
93 try test_f80_floatCast_f64(makeNaN64(0x7100000000000), 0x7fffe080000000000000);
94 // This is bad?
95
96 // inf
97 try test_f80_floatCast_f64(makeInf64(), 0x7fff8000000000000000);
98
99 // zero
100 try test_f80_floatCast_f64(0.0, 0x0);
101
102 try test_f80_floatCast_f64(0x0.a3456789abcdefp+6, 0x4004a3456789abcdf000);
103
104 try test_f80_floatCast_f64(0x0.edcba987654321fp-8, 0x3ff6edcba98765432000);
105
106 try test_f80_floatCast_f64(0x0.a3456789abcdefp+46, 0x402ca3456789abcdf000);
107
108 try test_f80_floatCast_f64(0x0.edcba987654321fp-44, 0x3fd2edcba98765432000);
109
110 // subnormal
111 try test_f80_floatCast_f64(0x1.8000000000001p-1022, 0x3c01c000000000000800);
112 try test_f80_floatCast_f64(0x1.8000000000002p-1023, 0x3c00c000000000001000);
113}
114
115test f128_floatCast_f64 {
116 // qNaN
117 try test_f128_floatCast_f64(makeQNaN64(), 0x7fff800000000000, 0x0);
118
119 // NaN
120 try test_f128_floatCast_f64(makeNaN64(0x7100000000000), 0x7fff710000000000, 0x0);
121
122 // inf
123 try test_f128_floatCast_f64(makeInf64(), 0x7fff000000000000, 0x0);
124
125 // zero
126 try test_f128_floatCast_f64(0.0, 0x0, 0x0);
127
128 try test_f128_floatCast_f64(0x1.23456789abcdefp+5, 0x400423456789abcd, 0xf000000000000000);
129
130 try test_f128_floatCast_f64(0x1.edcba987654321fp-9, 0x3ff6edcba9876543, 0x2000000000000000);
131
132 try test_f128_floatCast_f64(0x1.23456789abcdefp+45, 0x402c23456789abcd, 0xf000000000000000);
133
134 try test_f128_floatCast_f64(0x1.edcba987654321fp-45, 0x3fd2edcba9876543, 0x2000000000000000);
135
136 // subnormal
137 try test_f128_floatCast_f64(0x1.8p-1022, 0x3c01800000000000, 0x0);
138 try test_f128_floatCast_f64(0x1.8p-1023, 0x3c00800000000000, 0x0);
139}
140
141test f32_floatCast_f16 {
142 try test_f32_floatCast_f16(0x7e00, 0x7fc00000); // qNaN
143 try test_f32_floatCast_f16(0x7f00, 0x7fe00000); // sNaN
144 // On x86 the NaN becomes quiet because the return is pushed on the x87
145 // stack due to ABI requirements
146 if (builtin.target.cpu.arch != .x86 and builtin.target.os.tag == .windows)
147 try test_f32_floatCast_f16(0x7c01, 0x7f802000); // sNaN
148
149 try test_f32_floatCast_f16(0, 0); // 0
150 try test_f32_floatCast_f16(0x8000, 0x80000000); // -0
151
152 try test_f32_floatCast_f16(0x7c00, 0x7f800000); // inf
153 try test_f32_floatCast_f16(0xfc00, 0xff800000); // -inf
154
155 try test_f32_floatCast_f16(0x0001, 0x33800000); // denormal (min), 2**-24
156 try test_f32_floatCast_f16(0x8001, 0xb3800000); // denormal (min), -2**-24
157
158 try test_f32_floatCast_f16(0x03ff, 0x387fc000); // denormal (max), 2**-14 - 2**-24
159 try test_f32_floatCast_f16(0x83ff, 0xb87fc000); // denormal (max), -2**-14 + 2**-24
160
161 try test_f32_floatCast_f16(0x0400, 0x38800000); // normal (min), 2**-14
162 try test_f32_floatCast_f16(0x8400, 0xb8800000); // normal (min), -2**-14
163
164 try test_f32_floatCast_f16(0x7bff, 0x477fe000); // normal (max), 65504
165 try test_f32_floatCast_f16(0xfbff, 0xc77fe000); // normal (max), -65504
166
167 try test_f32_floatCast_f16(0x3c01, 0x3f802000); // normal, 1 + 2**-10
168 try test_f32_floatCast_f16(0xbc01, 0xbf802000); // normal, -1 - 2**-10
169
170 try test_f32_floatCast_f16(0x3555, 0x3eaaa000); // normal, approx. 1/3
171 try test_f32_floatCast_f16(0xb555, 0xbeaaa000); // normal, approx. -1/3
172}
173
174test f128_floatCast_f32 {
175 // qNaN
176 try test_f128_floatCast_f32(makeQNaN32(), 0x7fff800000000000, 0x0);
177 // NaN
178 try test_f128_floatCast_f32(makeNaN32(0x410000), 0x7fff820000000000, 0x0);
179 // inf
180 try test_f128_floatCast_f32(makeInf32(), 0x7fff000000000000, 0x0);
181 // zero
182 try test_f128_floatCast_f32(0.0, 0x0, 0x0);
183 try test_f128_floatCast_f32(0x1.23456p+5, 0x4004234560000000, 0x0);
184 try test_f128_floatCast_f32(0x1.edcbap-9, 0x3ff6edcba0000000, 0x0);
185 try test_f128_floatCast_f32(0x1.23456p+45, 0x402c234560000000, 0x0);
186 try test_f128_floatCast_f32(0x1.edcbap-45, 0x3fd2edcba0000000, 0x0);
187}
188
189fn makeQNaN64() f64 {
190 return @bitCast(@as(u64, 0x7ff8000000000000));
191}
192
193fn makeInf64() f64 {
194 return @bitCast(@as(u64, 0x7ff0000000000000));
195}
196
197fn makeNaN64(rand: u64) f64 {
198 return @bitCast(0x7ff0000000000000 | (rand & 0xfffffffffffff));
199}
200
201fn makeQNaN32() f32 {
202 return @bitCast(@as(u32, 0x7fc00000));
203}
204
205fn makeNaN32(rand: u32) f32 {
206 return @bitCast(0x7f800000 | (rand & 0x7fffff));
207}
208
209fn makeInf32() f32 {
210 return @bitCast(@as(u32, 0x7f800000));
211}
212
213fn test_f128_floatCast_f16(a: u16, expected_hi: u64, expected_lo: u64) !void {
214 const x = f128_floatCast_f16(@bitCast(a));
215
216 const rep: u128 = @bitCast(x);
217 const hi: u64 = @intCast(rep >> 64);
218 const lo: u64 = @truncate(rep);
219
220 if (hi == expected_hi and lo == expected_lo)
221 return;
222
223 // test other possible NaN representation(signal NaN)
224 if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) {
225 if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and
226 ((hi & 0xffffffffffff) > 0 or lo > 0))
227 {
228 return;
229 }
230 }
231
232 return error.TestFailure;
233}
234
235test f128_floatCast_f16 {
236 // qNaN
237 try test_f128_floatCast_f16(0x7e00, 0x7fff800000000000, 0x0);
238 // NaN
239 try test_f128_floatCast_f16(0x7d00, 0x7fff400000000000, 0x0);
240 // inf
241 try test_f128_floatCast_f16(0x7c00, 0x7fff000000000000, 0x0);
242 try test_f128_floatCast_f16(0xfc00, 0xffff000000000000, 0x0);
243 // zero
244 try test_f128_floatCast_f16(0x0000, 0x0000000000000000, 0x0);
245 try test_f128_floatCast_f16(0x8000, 0x8000000000000000, 0x0);
246 // denormal
247 try test_f128_floatCast_f16(0x0010, 0x3feb000000000000, 0x0);
248 try test_f128_floatCast_f16(0x0001, 0x3fe7000000000000, 0x0);
249 try test_f128_floatCast_f16(0x8001, 0xbfe7000000000000, 0x0);
250
251 // pi
252 try test_f128_floatCast_f16(0x4248, 0x4000920000000000, 0x0);
253 try test_f128_floatCast_f16(0xc248, 0xc000920000000000, 0x0);
254
255 try test_f128_floatCast_f16(0x508c, 0x4004230000000000, 0x0);
256 try test_f128_floatCast_f16(0x1bb7, 0x3ff6edc000000000, 0x0);
257}