1 #include <gtest/gtest.h>
2
3 #include <cstdint>
4 #include <cmath>
5
6 #include <fp16.h>
7 #include "tables.h"
8
9
TEST(FP16_IEEE_TO_FP32_VALUE,normalized_powers_of_2)10 TEST(FP16_IEEE_TO_FP32_VALUE, normalized_powers_of_2) {
11 const uint16_t min_po2_f16 = UINT16_C(0x0400);
12 const uint16_t eighths_f16 = UINT16_C(0x3000);
13 const uint16_t quarter_f16 = UINT16_C(0x3400);
14 const uint16_t half_f16 = UINT16_C(0x3800);
15 const uint16_t one_f16 = UINT16_C(0x3C00);
16 const uint16_t two_f16 = UINT16_C(0x4000);
17 const uint16_t four_f16 = UINT16_C(0x4400);
18 const uint16_t eight_f16 = UINT16_C(0x4800);
19 const uint16_t sixteen_f16 = UINT16_C(0x4C00);
20 const uint16_t thirtytwo_f16 = UINT16_C(0x5000);
21 const uint16_t sixtyfour_f16 = UINT16_C(0x5400);
22 const uint16_t max_po2_f16 = UINT16_C(0x7800);
23
24 const uint32_t min_po2_f32 = UINT32_C(0x38800000);
25 const uint32_t eighths_f32 = UINT32_C(0x3E000000);
26 const uint32_t quarter_f32 = UINT32_C(0x3E800000);
27 const uint32_t half_f32 = UINT32_C(0x3F000000);
28 const uint32_t one_f32 = UINT32_C(0x3F800000);
29 const uint32_t two_f32 = UINT32_C(0x40000000);
30 const uint32_t four_f32 = UINT32_C(0x40800000);
31 const uint32_t eight_f32 = UINT32_C(0x41000000);
32 const uint32_t sixteen_f32 = UINT32_C(0x41800000);
33 const uint32_t thirtytwo_f32 = UINT32_C(0x42000000);
34 const uint32_t sixtyfour_f32 = UINT32_C(0x42800000);
35 const uint32_t max_po2_f32 = UINT32_C(0x47000000);
36
37 const float min_po2_value = fp16_ieee_to_fp32_value(min_po2_f16);
38 uint32_t min_po2_bits;
39 memcpy(&min_po2_bits, &min_po2_value, sizeof(min_po2_bits));
40 EXPECT_EQ(min_po2_f32, min_po2_bits) <<
41 std::hex << std::uppercase << std::setfill('0') <<
42 "F16 = 0x" << std::setw(4) << min_po2_f16 << ", " <<
43 "F32(F16) = 0x" << std::setw(8) << min_po2_bits << ", " <<
44 "F32 = 0x" << std::setw(8) << min_po2_f32;
45
46 const float eighths_value = fp16_ieee_to_fp32_value(eighths_f16);
47 uint32_t eighths_bits;
48 memcpy(&eighths_bits, &eighths_value, sizeof(eighths_bits));
49 EXPECT_EQ(eighths_f32, eighths_bits) <<
50 std::hex << std::uppercase << std::setfill('0') <<
51 "F16 = 0x" << std::setw(4) << eighths_f16 << ", " <<
52 "F32(F16) = 0x" << std::setw(8) << eighths_bits << ", " <<
53 "F32 = 0x" << std::setw(8) << eighths_f32;
54
55 const float quarter_value = fp16_ieee_to_fp32_value(quarter_f16);
56 uint32_t quarter_bits;
57 memcpy(&quarter_bits, &quarter_value, sizeof(quarter_bits));
58 EXPECT_EQ(quarter_f32, quarter_bits) <<
59 std::hex << std::uppercase << std::setfill('0') <<
60 "F16 = 0x" << std::setw(4) << quarter_f16 << ", " <<
61 "F32(F16) = 0x" << std::setw(8) << quarter_bits << ", " <<
62 "F32 = 0x" << std::setw(8) << quarter_f32;
63
64 const float half_value = fp16_ieee_to_fp32_value(half_f16);
65 uint32_t half_bits;
66 memcpy(&half_bits, &half_value, sizeof(half_bits));
67 EXPECT_EQ(half_f32, half_bits) <<
68 std::hex << std::uppercase << std::setfill('0') <<
69 "F16 = 0x" << std::setw(4) << half_f16 << ", " <<
70 "F32(F16) = 0x" << std::setw(8) << half_bits << ", " <<
71 "F32 = 0x" << std::setw(8) << half_f32;
72
73 const float one_value = fp16_ieee_to_fp32_value(one_f16);
74 uint32_t one_bits;
75 memcpy(&one_bits, &one_value, sizeof(one_bits));
76 EXPECT_EQ(one_f32, one_bits) <<
77 std::hex << std::uppercase << std::setfill('0') <<
78 "F16 = 0x" << std::setw(4) << one_f16 << ", " <<
79 "F32(F16) = 0x" << std::setw(8) << one_bits << ", " <<
80 "F32 = 0x" << std::setw(8) << one_f32;
81
82 const float two_value = fp16_ieee_to_fp32_value(two_f16);
83 uint32_t two_bits;
84 memcpy(&two_bits, &two_value, sizeof(two_bits));
85 EXPECT_EQ(two_f32, two_bits) <<
86 std::hex << std::uppercase << std::setfill('0') <<
87 "F16 = 0x" << std::setw(4) << two_f16 << ", " <<
88 "F32(F16) = 0x" << std::setw(8) << two_bits << ", " <<
89 "F32 = 0x" << std::setw(8) << two_f32;
90
91 const float four_value = fp16_ieee_to_fp32_value(four_f16);
92 uint32_t four_bits;
93 memcpy(&four_bits, &four_value, sizeof(four_bits));
94 EXPECT_EQ(four_f32, four_bits) <<
95 std::hex << std::uppercase << std::setfill('0') <<
96 "F16 = 0x" << std::setw(4) << four_f16 << ", " <<
97 "F32(F16) = 0x" << std::setw(8) << four_bits << ", " <<
98 "F32 = 0x" << std::setw(8) << four_f32;
99
100 const float eight_value = fp16_ieee_to_fp32_value(eight_f16);
101 uint32_t eight_bits;
102 memcpy(&eight_bits, &eight_value, sizeof(eight_bits));
103 EXPECT_EQ(eight_f32, eight_bits) <<
104 std::hex << std::uppercase << std::setfill('0') <<
105 "F16 = 0x" << std::setw(4) << eight_f16 << ", " <<
106 "F32(F16) = 0x" << std::setw(8) << eight_bits << ", " <<
107 "F32 = 0x" << std::setw(8) << eight_f32;
108
109 const float sixteen_value = fp16_ieee_to_fp32_value(sixteen_f16);
110 uint32_t sixteen_bits;
111 memcpy(&sixteen_bits, &sixteen_value, sizeof(sixteen_bits));
112 EXPECT_EQ(sixteen_f32, sixteen_bits) <<
113 std::hex << std::uppercase << std::setfill('0') <<
114 "F16 = 0x" << std::setw(4) << sixteen_f16 << ", " <<
115 "F32(F16) = 0x" << std::setw(8) << sixteen_bits << ", " <<
116 "F32 = 0x" << std::setw(8) << sixteen_f32;
117
118 const float thirtytwo_value = fp16_ieee_to_fp32_value(thirtytwo_f16);
119 uint32_t thirtytwo_bits;
120 memcpy(&thirtytwo_bits, &thirtytwo_value, sizeof(thirtytwo_bits));
121 EXPECT_EQ(thirtytwo_f32, thirtytwo_bits) <<
122 std::hex << std::uppercase << std::setfill('0') <<
123 "F16 = 0x" << std::setw(4) << thirtytwo_f16 << ", " <<
124 "F32(F16) = 0x" << std::setw(8) << thirtytwo_bits << ", " <<
125 "F32 = 0x" << std::setw(8) << thirtytwo_f32;
126
127 const float sixtyfour_value = fp16_ieee_to_fp32_value(sixtyfour_f16);
128 uint32_t sixtyfour_bits;
129 memcpy(&sixtyfour_bits, &sixtyfour_value, sizeof(sixtyfour_bits));
130 EXPECT_EQ(sixtyfour_f32, sixtyfour_bits) <<
131 std::hex << std::uppercase << std::setfill('0') <<
132 "F16 = 0x" << std::setw(4) << sixtyfour_f16 << ", " <<
133 "F32(F16) = 0x" << std::setw(8) << sixtyfour_bits << ", " <<
134 "F32 = 0x" << std::setw(8) << sixtyfour_f32;
135
136 const float max_po2_value = fp16_ieee_to_fp32_value(max_po2_f16);
137 uint32_t max_po2_bits;
138 memcpy(&max_po2_bits, &max_po2_value, sizeof(max_po2_bits));
139 EXPECT_EQ(max_po2_f32, max_po2_bits) <<
140 std::hex << std::uppercase << std::setfill('0') <<
141 "F16 = 0x" << std::setw(4) << max_po2_f16 << ", " <<
142 "F32(F16) = 0x" << std::setw(8) << max_po2_bits << ", " <<
143 "F32 = 0x" << std::setw(8) << max_po2_f32;
144 }
145
TEST(FP16_IEEE_TO_FP32_VALUE,denormalized_powers_of_2)146 TEST(FP16_IEEE_TO_FP32_VALUE, denormalized_powers_of_2) {
147 const uint16_t exp2_minus_15_f16 = UINT16_C(0x0200);
148 const uint16_t exp2_minus_16_f16 = UINT16_C(0x0100);
149 const uint16_t exp2_minus_17_f16 = UINT16_C(0x0080);
150 const uint16_t exp2_minus_18_f16 = UINT16_C(0x0040);
151 const uint16_t exp2_minus_19_f16 = UINT16_C(0x0020);
152 const uint16_t exp2_minus_20_f16 = UINT16_C(0x0010);
153 const uint16_t exp2_minus_21_f16 = UINT16_C(0x0008);
154 const uint16_t exp2_minus_22_f16 = UINT16_C(0x0004);
155 const uint16_t exp2_minus_23_f16 = UINT16_C(0x0002);
156 const uint16_t exp2_minus_24_f16 = UINT16_C(0x0001);
157
158 const uint32_t exp2_minus_15_f32 = UINT32_C(0x38000000);
159 const uint32_t exp2_minus_16_f32 = UINT32_C(0x37800000);
160 const uint32_t exp2_minus_17_f32 = UINT32_C(0x37000000);
161 const uint32_t exp2_minus_18_f32 = UINT32_C(0x36800000);
162 const uint32_t exp2_minus_19_f32 = UINT32_C(0x36000000);
163 const uint32_t exp2_minus_20_f32 = UINT32_C(0x35800000);
164 const uint32_t exp2_minus_21_f32 = UINT32_C(0x35000000);
165 const uint32_t exp2_minus_22_f32 = UINT32_C(0x34800000);
166 const uint32_t exp2_minus_23_f32 = UINT32_C(0x34000000);
167 const uint32_t exp2_minus_24_f32 = UINT32_C(0x33800000);
168
169 const float exp2_minus_15_value = fp16_ieee_to_fp32_value(exp2_minus_15_f16);
170 uint32_t exp2_minus_15_bits;
171 memcpy(&exp2_minus_15_bits, &exp2_minus_15_value, sizeof(exp2_minus_15_bits));
172 EXPECT_EQ(exp2_minus_15_f32, exp2_minus_15_bits) <<
173 std::hex << std::uppercase << std::setfill('0') <<
174 "F16 = 0x" << std::setw(4) << exp2_minus_15_f16 << ", " <<
175 "F32(F16) = 0x" << std::setw(8) << exp2_minus_15_bits << ", " <<
176 "F32 = 0x" << std::setw(8) << exp2_minus_15_f32;
177
178 const float exp2_minus_16_value = fp16_ieee_to_fp32_value(exp2_minus_16_f16);
179 uint32_t exp2_minus_16_bits;
180 memcpy(&exp2_minus_16_bits, &exp2_minus_16_value, sizeof(exp2_minus_16_bits));
181 EXPECT_EQ(exp2_minus_16_f32, exp2_minus_16_bits) <<
182 std::hex << std::uppercase << std::setfill('0') <<
183 "F16 = 0x" << std::setw(4) << exp2_minus_16_f16 << ", " <<
184 "F32(F16) = 0x" << std::setw(8) << exp2_minus_16_bits << ", " <<
185 "F32 = 0x" << std::setw(8) << exp2_minus_16_f32;
186
187 const float exp2_minus_17_value = fp16_ieee_to_fp32_value(exp2_minus_17_f16);
188 uint32_t exp2_minus_17_bits;
189 memcpy(&exp2_minus_17_bits, &exp2_minus_17_value, sizeof(exp2_minus_17_bits));
190 EXPECT_EQ(exp2_minus_17_f32, exp2_minus_17_bits) <<
191 std::hex << std::uppercase << std::setfill('0') <<
192 "F16 = 0x" << std::setw(4) << exp2_minus_17_f16 << ", " <<
193 "F32(F16) = 0x" << std::setw(8) << exp2_minus_17_bits << ", " <<
194 "F32 = 0x" << std::setw(8) << exp2_minus_17_f32;
195
196 const float exp2_minus_18_value = fp16_ieee_to_fp32_value(exp2_minus_18_f16);
197 uint32_t exp2_minus_18_bits;
198 memcpy(&exp2_minus_18_bits, &exp2_minus_18_value, sizeof(exp2_minus_18_bits));
199 EXPECT_EQ(exp2_minus_18_f32, exp2_minus_18_bits) <<
200 std::hex << std::uppercase << std::setfill('0') <<
201 "F16 = 0x" << std::setw(4) << exp2_minus_18_f16 << ", " <<
202 "F32(F16) = 0x" << std::setw(8) << exp2_minus_18_bits << ", " <<
203 "F32 = 0x" << std::setw(8) << exp2_minus_18_f32;
204
205 const float exp2_minus_19_value = fp16_ieee_to_fp32_value(exp2_minus_19_f16);
206 uint32_t exp2_minus_19_bits;
207 memcpy(&exp2_minus_19_bits, &exp2_minus_19_value, sizeof(exp2_minus_19_bits));
208 EXPECT_EQ(exp2_minus_19_f32, exp2_minus_19_bits) <<
209 std::hex << std::uppercase << std::setfill('0') <<
210 "F16 = 0x" << std::setw(4) << exp2_minus_19_f16 << ", " <<
211 "F32(F16) = 0x" << std::setw(8) << exp2_minus_19_bits << ", " <<
212 "F32 = 0x" << std::setw(8) << exp2_minus_19_f32;
213
214 const float exp2_minus_20_value = fp16_ieee_to_fp32_value(exp2_minus_20_f16);
215 uint32_t exp2_minus_20_bits;
216 memcpy(&exp2_minus_20_bits, &exp2_minus_20_value, sizeof(exp2_minus_20_bits));
217 EXPECT_EQ(exp2_minus_20_f32, exp2_minus_20_bits) <<
218 std::hex << std::uppercase << std::setfill('0') <<
219 "F16 = 0x" << std::setw(4) << exp2_minus_20_f16 << ", " <<
220 "F32(F16) = 0x" << std::setw(8) << exp2_minus_20_bits << ", " <<
221 "F32 = 0x" << std::setw(8) << exp2_minus_20_f32;
222
223 const float exp2_minus_21_value = fp16_ieee_to_fp32_value(exp2_minus_21_f16);
224 uint32_t exp2_minus_21_bits;
225 memcpy(&exp2_minus_21_bits, &exp2_minus_21_value, sizeof(exp2_minus_21_bits));
226 EXPECT_EQ(exp2_minus_21_f32, exp2_minus_21_bits) <<
227 std::hex << std::uppercase << std::setfill('0') <<
228 "F16 = 0x" << std::setw(4) << exp2_minus_21_f16 << ", " <<
229 "F32(F16) = 0x" << std::setw(8) << exp2_minus_21_bits << ", " <<
230 "F32 = 0x" << std::setw(8) << exp2_minus_21_f32;
231
232 const float exp2_minus_22_value = fp16_ieee_to_fp32_value(exp2_minus_22_f16);
233 uint32_t exp2_minus_22_bits;
234 memcpy(&exp2_minus_22_bits, &exp2_minus_22_value, sizeof(exp2_minus_22_bits));
235 EXPECT_EQ(exp2_minus_22_f32, exp2_minus_22_bits) <<
236 std::hex << std::uppercase << std::setfill('0') <<
237 "F16 = 0x" << std::setw(4) << exp2_minus_22_f16 << ", " <<
238 "F32(F16) = 0x" << std::setw(8) << exp2_minus_22_bits << ", " <<
239 "F32 = 0x" << std::setw(8) << exp2_minus_22_f32;
240
241 const float exp2_minus_23_value = fp16_ieee_to_fp32_value(exp2_minus_23_f16);
242 uint32_t exp2_minus_23_bits;
243 memcpy(&exp2_minus_23_bits, &exp2_minus_23_value, sizeof(exp2_minus_23_bits));
244 EXPECT_EQ(exp2_minus_23_f32, exp2_minus_23_bits) <<
245 std::hex << std::uppercase << std::setfill('0') <<
246 "F16 = 0x" << std::setw(4) << exp2_minus_23_f16 << ", " <<
247 "F32(F16) = 0x" << std::setw(8) << exp2_minus_23_bits << ", " <<
248 "F32 = 0x" << std::setw(8) << exp2_minus_23_f32;
249
250 const float exp2_minus_24_value = fp16_ieee_to_fp32_value(exp2_minus_24_f16);
251 uint32_t exp2_minus_24_bits;
252 memcpy(&exp2_minus_24_bits, &exp2_minus_24_value, sizeof(exp2_minus_24_bits));
253 EXPECT_EQ(exp2_minus_24_f32, exp2_minus_24_bits) <<
254 std::hex << std::uppercase << std::setfill('0') <<
255 "F16 = 0x" << std::setw(4) << exp2_minus_24_f16 << ", " <<
256 "F32(F16) = 0x" << std::setw(8) << exp2_minus_24_bits << ", " <<
257 "F32 = 0x" << std::setw(8) << exp2_minus_24_f32;
258 }
259
TEST(FP16_IEEE_TO_FP32_VALUE,zero)260 TEST(FP16_IEEE_TO_FP32_VALUE, zero) {
261 const uint16_t positive_zero_f16 = UINT16_C(0x0000);
262 const uint16_t negative_zero_f16 = UINT16_C(0x8000);
263
264 const uint32_t positive_zero_f32 = UINT32_C(0x00000000);
265 const uint32_t negative_zero_f32 = UINT32_C(0x80000000);
266
267 const float positive_zero_value = fp16_ieee_to_fp32_value(positive_zero_f16);
268 uint32_t positive_zero_bits;
269 memcpy(&positive_zero_bits, &positive_zero_value, sizeof(positive_zero_bits));
270 EXPECT_EQ(positive_zero_f32, positive_zero_bits) <<
271 std::hex << std::uppercase << std::setfill('0') <<
272 "F16 = 0x" << std::setw(4) << positive_zero_f16 << ", " <<
273 "F32(F16) = 0x" << std::setw(8) << positive_zero_bits << ", " <<
274 "F32 = 0x" << std::setw(8) << positive_zero_f32;
275
276 const float negative_zero_value = fp16_ieee_to_fp32_value(negative_zero_f16);
277 uint32_t negative_zero_bits;
278 memcpy(&negative_zero_bits, &negative_zero_value, sizeof(negative_zero_bits));
279 EXPECT_EQ(negative_zero_f32, negative_zero_bits) <<
280 std::hex << std::uppercase << std::setfill('0') <<
281 "F16 = 0x" << std::setw(4) << negative_zero_f16 << ", " <<
282 "F32(F16) = 0x" << std::setw(8) << negative_zero_bits << ", " <<
283 "F32 = 0x" << std::setw(8) << negative_zero_f32;
284 }
285
TEST(FP16_IEEE_TO_FP32_VALUE,infinity)286 TEST(FP16_IEEE_TO_FP32_VALUE, infinity) {
287 const uint16_t positive_infinity_f16 = UINT16_C(0x7C00);
288 const uint16_t negative_infinity_f16 = UINT16_C(0xFC00);
289
290 const uint32_t positive_infinity_f32 = UINT32_C(0x7F800000);
291 const uint32_t negative_infinity_f32 = UINT32_C(0xFF800000);
292
293 const float positive_infinity_value = fp16_ieee_to_fp32_value(positive_infinity_f16);
294 uint32_t positive_infinity_bits;
295 memcpy(&positive_infinity_bits, &positive_infinity_value, sizeof(positive_infinity_bits));
296 EXPECT_EQ(positive_infinity_f32, positive_infinity_bits) <<
297 std::hex << std::uppercase << std::setfill('0') <<
298 "F16 = 0x" << std::setw(4) << positive_infinity_f16 << ", " <<
299 "F32(F16) = 0x" << std::setw(8) << positive_infinity_bits << ", " <<
300 "F32 = 0x" << std::setw(8) << positive_infinity_f32;
301
302 const float negative_infinity_value = fp16_ieee_to_fp32_value(negative_infinity_f16);
303 uint32_t negative_infinity_bits;
304 memcpy(&negative_infinity_bits, &negative_infinity_value, sizeof(negative_infinity_bits));
305 EXPECT_EQ(negative_infinity_f32, negative_infinity_bits) <<
306 std::hex << std::uppercase << std::setfill('0') <<
307 "F16 = 0x" << std::setw(4) << negative_infinity_f16 << ", " <<
308 "F32(F16) = 0x" << std::setw(8) << negative_infinity_bits << ", " <<
309 "F32 = 0x" << std::setw(8) << negative_infinity_f32;
310 }
311
TEST(FP16_IEEE_TO_FP32_VALUE,positive_nan)312 TEST(FP16_IEEE_TO_FP32_VALUE, positive_nan) {
313 using std::signbit;
314 using std::isnan;
315 for (uint16_t m = UINT16_C(1); m < UINT16_C(0x0400); m++) {
316 const uint16_t nan_f16 = UINT16_C(0x7C00) | m;
317 const float nan_f32 = fp16_ieee_to_fp32_value(nan_f16);
318 uint32_t nan_bits;
319 memcpy(&nan_bits, &nan_f32, sizeof(nan_bits));
320
321 /* Check if NaN */
322 EXPECT_TRUE(isnan(nan_f32)) <<
323 std::hex << std::uppercase << std::setfill('0') <<
324 "F16 = 0x" << std::setw(4) << nan_f16 << ", " <<
325 "F32(F16) = 0x" << std::setw(8) << nan_bits;
326
327 /* Check sign */
328 EXPECT_EQ(signbit(nan_f32), 0) <<
329 std::hex << std::uppercase << std::setfill('0') <<
330 "F16 = 0x" << std::setw(4) << nan_f16 << ", " <<
331 "F32(F16) = 0x" << std::setw(8) << nan_bits;
332 }
333 }
334
TEST(FP16_IEEE_TO_FP32_VALUE,negative_nan)335 TEST(FP16_IEEE_TO_FP32_VALUE, negative_nan) {
336 using std::signbit;
337 using std::isnan;
338 for (uint16_t m = UINT16_C(1); m < UINT16_C(0x0400); m++) {
339 const uint16_t nan_f16 = UINT16_C(0xFC00) | m;
340 const float nan_f32 = fp16_ieee_to_fp32_value(nan_f16);
341 uint32_t nan_bits;
342 memcpy(&nan_bits, &nan_f32, sizeof(nan_bits));
343
344 /* Check if NaN */
345 EXPECT_TRUE(isnan(nan_f32)) <<
346 std::hex << std::uppercase << std::setfill('0') <<
347 "F16 = 0x" << std::setw(4) << nan_f16 << ", " <<
348 "F32(F16) = 0x" << std::setw(8) << nan_bits;
349
350 /* Check sign */
351 EXPECT_EQ(signbit(nan_f32), 1) <<
352 std::hex << std::uppercase << std::setfill('0') <<
353 "F16 = 0x" << std::setw(4) << nan_f16 << ", " <<
354 "F32(F16) = 0x" << std::setw(8) << nan_bits;
355 }
356 }
357
TEST(FP16_IEEE_TO_FP32_VALUE,positive_normalized_values)358 TEST(FP16_IEEE_TO_FP32_VALUE, positive_normalized_values) {
359 const uint32_t exponentBias = 15;
360 for (int32_t e = -14; e <= 15; e++) {
361 for (uint16_t h = 0; h < 0x0400; h++) {
362 const uint16_t fp16 = h + ((uint16_t) (e + exponentBias) << 10);
363 const uint32_t fp32 = fp16::normalizedValues[h] + ((uint32_t) e << 23);
364 const float value = fp16_ieee_to_fp32_value(fp16);
365 uint32_t bits;
366 memcpy(&bits, &value, sizeof(bits));
367 EXPECT_EQ(fp32, bits) <<
368 std::hex << std::uppercase << std::setfill('0') <<
369 "F16 = 0x" << std::setw(4) << fp16 << ", " <<
370 "F32(F16) = 0x" << std::setw(8) << bits << ", " <<
371 "F32 = 0x" << std::setw(8) << fp32;
372 }
373 }
374 }
375
TEST(FP16_IEEE_TO_FP32_VALUE,negative_normalized_values)376 TEST(FP16_IEEE_TO_FP32_VALUE, negative_normalized_values) {
377 const uint32_t exponentBias = 15;
378 for (int32_t e = -14; e <= 15; e++) {
379 for (uint16_t h = 0; h < 0x0400; h++) {
380 const uint16_t fp16 = (h + ((uint16_t) (e + exponentBias) << 10)) ^ UINT16_C(0x8000);
381 const uint32_t fp32 = (fp16::normalizedValues[h] + ((uint32_t) e << 23)) ^ UINT32_C(0x80000000);
382 const float value = fp16_ieee_to_fp32_value(fp16);
383 uint32_t bits;
384 memcpy(&bits, &value, sizeof(bits));
385 EXPECT_EQ(fp32, bits) <<
386 std::hex << std::uppercase << std::setfill('0') <<
387 "F16 = 0x" << std::setw(4) << fp16 << ", " <<
388 "F32(F16) = 0x" << std::setw(8) << bits << ", " <<
389 "F32 = 0x" << std::setw(8) << fp32;
390 }
391 }
392 }
393
TEST(FP16_IEEE_TO_FP32_VALUE,positive_denormalized_values)394 TEST(FP16_IEEE_TO_FP32_VALUE, positive_denormalized_values) {
395 for (uint16_t h = 0; h < 0x0400; h++) {
396 const float value = fp16_ieee_to_fp32_value(h);
397 uint32_t bits;
398 memcpy(&bits, &value, sizeof(bits));
399 EXPECT_EQ(fp16::denormalizedValues[h], bits) <<
400 std::hex << std::uppercase << std::setfill('0') <<
401 "F16 = 0x" << std::setw(4) << h << ", " <<
402 "F32(F16) = 0x" << std::setw(8) << bits << ", " <<
403 "F32 = 0x" << std::setw(8) << fp16::denormalizedValues[h];
404 }
405 }
406
TEST(FP16_IEEE_TO_FP32_VALUE,negative_denormalized_values)407 TEST(FP16_IEEE_TO_FP32_VALUE, negative_denormalized_values) {
408 for (uint16_t h = 0; h < 0x0400; h++) {
409 const uint16_t fp16 = h ^ UINT16_C(0x8000);
410 const uint32_t fp32 = fp16::denormalizedValues[h] ^ UINT32_C(0x80000000);
411 const float value = fp16_ieee_to_fp32_value(fp16);
412 uint32_t bits;
413 memcpy(&bits, &value, sizeof(bits));
414 EXPECT_EQ(fp32, bits) <<
415 std::hex << std::uppercase << std::setfill('0') <<
416 "F16 = 0x" << std::setw(4) << fp16 << ", " <<
417 "F32(F16) = 0x" << std::setw(8) << bits << ", " <<
418 "F32 = 0x" << std::setw(8) << fp32;
419 }
420 }
421