1 #include <gtest/gtest.h>
2
3 #include <cstdint>
4
5 #include <fp16.h>
6 #include <fp16/psimd.h>
7
8
TEST(FP16_IEEE_TO_FP32x2_PSIMD,infinity)9 TEST(FP16_IEEE_TO_FP32x2_PSIMD, infinity) {
10 const uint16_t positive_infinity_f16 = UINT16_C(0x7C00);
11 const uint16_t negative_infinity_f16 = UINT16_C(0xFC00);
12
13 const uint32_t positive_infinity_f32 = UINT32_C(0x7F800000);
14 const uint32_t negative_infinity_f32 = UINT32_C(0xFF800000);
15
16 const psimd_u16 fp16 = {
17 positive_infinity_f16, negative_infinity_f16,
18 negative_infinity_f16, positive_infinity_f16,
19 positive_infinity_f16, positive_infinity_f16,
20 negative_infinity_f16, negative_infinity_f16
21 };
22 const psimd_u32x2 fp32 =
23 psimd_cast_f32x2_u32x2(fp16_ieee_to_fp32x2_psimd(fp16));
24
25 EXPECT_EQ(positive_infinity_f32, fp32.lo[0]) <<
26 std::hex << std::uppercase << std::setfill('0') <<
27 "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
28 "F32(F16) = 0x" << std::setw(8) << fp32.lo[0] << ", " <<
29 "F32 = 0x" << std::setw(8) << positive_infinity_f32;
30 EXPECT_EQ(negative_infinity_f32, fp32.lo[1]) <<
31 std::hex << std::uppercase << std::setfill('0') <<
32 "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
33 "F32(F16) = 0x" << std::setw(8) << fp32.lo[1] << ", " <<
34 "F32 = 0x" << std::setw(8) << negative_infinity_f32;
35 EXPECT_EQ(negative_infinity_f32, fp32.lo[2]) <<
36 std::hex << std::uppercase << std::setfill('0') <<
37 "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
38 "F32(F16) = 0x" << std::setw(8) << fp32.lo[2] << ", " <<
39 "F32 = 0x" << std::setw(8) << negative_infinity_f32;
40 EXPECT_EQ(positive_infinity_f32, fp32.lo[3]) <<
41 std::hex << std::uppercase << std::setfill('0') <<
42 "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
43 "F32(F16) = 0x" << std::setw(8) << fp32.lo[3] << ", " <<
44 "F32 = 0x" << std::setw(8) << positive_infinity_f32;
45 EXPECT_EQ(positive_infinity_f32, fp32.hi[0]) <<
46 std::hex << std::uppercase << std::setfill('0') <<
47 "F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
48 "F32(F16) = 0x" << std::setw(8) << fp32.hi[0] << ", " <<
49 "F32 = 0x" << std::setw(8) << positive_infinity_f32;
50 EXPECT_EQ(positive_infinity_f32, fp32.hi[1]) <<
51 std::hex << std::uppercase << std::setfill('0') <<
52 "F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
53 "F32(F16) = 0x" << std::setw(8) << fp32.hi[1] << ", " <<
54 "F32 = 0x" << std::setw(8) << positive_infinity_f32;
55 EXPECT_EQ(negative_infinity_f32, fp32.hi[2]) <<
56 std::hex << std::uppercase << std::setfill('0') <<
57 "F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
58 "F32(F16) = 0x" << std::setw(8) << fp32.hi[2] << ", " <<
59 "F32 = 0x" << std::setw(8) << negative_infinity_f32;
60 EXPECT_EQ(negative_infinity_f32, fp32.hi[3]) <<
61 std::hex << std::uppercase << std::setfill('0') <<
62 "F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
63 "F32(F16) = 0x" << std::setw(8) << fp32.hi[3] << ", " <<
64 "F32 = 0x" << std::setw(8) << negative_infinity_f32;
65 }
66
TEST(FP16_IEEE_TO_FP32x2_PSIMD,positive_nan)67 TEST(FP16_IEEE_TO_FP32x2_PSIMD, positive_nan) {
68 for (uint16_t h = 0; h < 0x0400; h += 8) {
69 const psimd_u16 fp16 = {
70 (uint16_t) (h + 0x7C00 + (h == 0)) /* Avoid infinity */,
71 (uint16_t) (h + 0x7C01),
72 (uint16_t) (h + 0x7C02),
73 (uint16_t) (h + 0x7C03),
74 (uint16_t) (h + 0x7C04),
75 (uint16_t) (h + 0x7C05),
76 (uint16_t) (h + 0x7C06),
77 (uint16_t) (h + 0x7C07),
78 };
79 const psimd_u32x2 fp32 =
80 psimd_cast_f32x2_u32x2(fp16_ieee_to_fp32x2_psimd(fp16));
81
82 /* Check sign */
83 EXPECT_EQ(fp32.lo[0] & UINT32_C(0x80000000), 0) <<
84 std::hex << std::uppercase << std::setfill('0') <<
85 "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
86 "F32(F16) = 0x" << std::setw(8) << fp32.lo[0];
87 EXPECT_EQ(fp32.lo[1] & UINT32_C(0x80000000), 0) <<
88 std::hex << std::uppercase << std::setfill('0') <<
89 "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
90 "F32(F16) = 0x" << std::setw(8) << fp32.lo[1];
91 EXPECT_EQ(fp32.lo[2] & UINT32_C(0x80000000), 0) <<
92 std::hex << std::uppercase << std::setfill('0') <<
93 "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
94 "F32(F16) = 0x" << std::setw(8) << fp32.lo[2];
95 EXPECT_EQ(fp32.lo[3] & UINT32_C(0x80000000), 0) <<
96 std::hex << std::uppercase << std::setfill('0') <<
97 "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
98 "F32(F16) = 0x" << std::setw(8) << fp32.lo[3];
99 EXPECT_EQ(fp32.hi[0] & UINT32_C(0x80000000), 0) <<
100 std::hex << std::uppercase << std::setfill('0') <<
101 "F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
102 "F32(F16) = 0x" << std::setw(8) << fp32.hi[0];
103 EXPECT_EQ(fp32.hi[1] & UINT32_C(0x80000000), 0) <<
104 std::hex << std::uppercase << std::setfill('0') <<
105 "F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
106 "F32(F16) = 0x" << std::setw(8) << fp32.hi[1];
107 EXPECT_EQ(fp32.hi[2] & UINT32_C(0x80000000), 0) <<
108 std::hex << std::uppercase << std::setfill('0') <<
109 "F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
110 "F32(F16) = 0x" << std::setw(8) << fp32.hi[2];
111 EXPECT_EQ(fp32.hi[3] & UINT32_C(0x80000000), 0) <<
112 std::hex << std::uppercase << std::setfill('0') <<
113 "F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
114 "F32(F16) = 0x" << std::setw(8) << fp32.hi[3];
115
116 /* Check exponent */
117 EXPECT_EQ(fp32.lo[0] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
118 std::hex << std::uppercase << std::setfill('0') <<
119 "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
120 "F32(F16) = 0x" << std::setw(8) << fp32.lo[0];
121 EXPECT_EQ(fp32.lo[1] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
122 std::hex << std::uppercase << std::setfill('0') <<
123 "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
124 "F32(F16) = 0x" << std::setw(8) << fp32.lo[1];
125 EXPECT_EQ(fp32.lo[2] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
126 std::hex << std::uppercase << std::setfill('0') <<
127 "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
128 "F32(F16) = 0x" << std::setw(8) << fp32.lo[2];
129 EXPECT_EQ(fp32.lo[3] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
130 std::hex << std::uppercase << std::setfill('0') <<
131 "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
132 "F32(F16) = 0x" << std::setw(8) << fp32.lo[3];
133 EXPECT_EQ(fp32.hi[0] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
134 std::hex << std::uppercase << std::setfill('0') <<
135 "F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
136 "F32(F16) = 0x" << std::setw(8) << fp32.hi[0];
137 EXPECT_EQ(fp32.hi[1] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
138 std::hex << std::uppercase << std::setfill('0') <<
139 "F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
140 "F32(F16) = 0x" << std::setw(8) << fp32.hi[1];
141 EXPECT_EQ(fp32.hi[2] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
142 std::hex << std::uppercase << std::setfill('0') <<
143 "F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
144 "F32(F16) = 0x" << std::setw(8) << fp32.hi[2];
145 EXPECT_EQ(fp32.hi[3] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
146 std::hex << std::uppercase << std::setfill('0') <<
147 "F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
148 "F32(F16) = 0x" << std::setw(8) << fp32.hi[3];
149
150 /* Check mantissa */
151 EXPECT_NE(fp32.lo[0] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
152 std::hex << std::uppercase << std::setfill('0') <<
153 "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
154 "F32(F16) = 0x" << std::setw(8) << fp32.lo[0];
155 EXPECT_NE(fp32.lo[1] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
156 std::hex << std::uppercase << std::setfill('0') <<
157 "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
158 "F32(F16) = 0x" << std::setw(8) << fp32.lo[1];
159 EXPECT_NE(fp32.lo[2] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
160 std::hex << std::uppercase << std::setfill('0') <<
161 "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
162 "F32(F16) = 0x" << std::setw(8) << fp32.lo[2];
163 EXPECT_NE(fp32.lo[3] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
164 std::hex << std::uppercase << std::setfill('0') <<
165 "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
166 "F32(F16) = 0x" << std::setw(8) << fp32.lo[3];
167 EXPECT_NE(fp32.hi[0] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
168 std::hex << std::uppercase << std::setfill('0') <<
169 "F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
170 "F32(F16) = 0x" << std::setw(8) << fp32.hi[0];
171 EXPECT_NE(fp32.hi[1] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
172 std::hex << std::uppercase << std::setfill('0') <<
173 "F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
174 "F32(F16) = 0x" << std::setw(8) << fp32.hi[1];
175 EXPECT_NE(fp32.hi[2] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
176 std::hex << std::uppercase << std::setfill('0') <<
177 "F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
178 "F32(F16) = 0x" << std::setw(8) << fp32.hi[2];
179 EXPECT_NE(fp32.hi[3] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
180 std::hex << std::uppercase << std::setfill('0') <<
181 "F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
182 "F32(F16) = 0x" << std::setw(8) << fp32.hi[3];
183 }
184 }
185
TEST(FP16_IEEE_TO_FP32x2_PSIMD,negative_nan)186 TEST(FP16_IEEE_TO_FP32x2_PSIMD, negative_nan) {
187 for (uint16_t h = 0; h < 0x0400; h += 8) {
188 const psimd_u16 fp16 = {
189 (uint16_t) (h + 0xFC00 + (h == 0)) /* Avoid infinity */,
190 (uint16_t) (h + 0xFC01),
191 (uint16_t) (h + 0xFC02),
192 (uint16_t) (h + 0xFC03),
193 (uint16_t) (h + 0xFC04),
194 (uint16_t) (h + 0xFC05),
195 (uint16_t) (h + 0xFC06),
196 (uint16_t) (h + 0xFC07),
197 };
198 const psimd_u32x2 fp32 =
199 psimd_cast_f32x2_u32x2(fp16_ieee_to_fp32x2_psimd(fp16));
200
201 /* Check sign */
202 EXPECT_EQ(fp32.lo[0] & UINT32_C(0x80000000), UINT32_C(0x80000000)) <<
203 std::hex << std::uppercase << std::setfill('0') <<
204 "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
205 "F32(F16) = 0x" << std::setw(8) << fp32.lo[0];
206 EXPECT_EQ(fp32.lo[1] & UINT32_C(0x80000000), UINT32_C(0x80000000)) <<
207 std::hex << std::uppercase << std::setfill('0') <<
208 "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
209 "F32(F16) = 0x" << std::setw(8) << fp32.lo[1];
210 EXPECT_EQ(fp32.lo[2] & UINT32_C(0x80000000), UINT32_C(0x80000000)) <<
211 std::hex << std::uppercase << std::setfill('0') <<
212 "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
213 "F32(F16) = 0x" << std::setw(8) << fp32.lo[2];
214 EXPECT_EQ(fp32.lo[3] & UINT32_C(0x80000000), UINT32_C(0x80000000)) <<
215 std::hex << std::uppercase << std::setfill('0') <<
216 "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
217 "F32(F16) = 0x" << std::setw(8) << fp32.lo[3];
218 EXPECT_EQ(fp32.hi[0] & UINT32_C(0x80000000), UINT32_C(0x80000000)) <<
219 std::hex << std::uppercase << std::setfill('0') <<
220 "F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
221 "F32(F16) = 0x" << std::setw(8) << fp32.hi[0];
222 EXPECT_EQ(fp32.hi[1] & UINT32_C(0x80000000), UINT32_C(0x80000000)) <<
223 std::hex << std::uppercase << std::setfill('0') <<
224 "F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
225 "F32(F16) = 0x" << std::setw(8) << fp32.hi[1];
226 EXPECT_EQ(fp32.hi[2] & UINT32_C(0x80000000), UINT32_C(0x80000000)) <<
227 std::hex << std::uppercase << std::setfill('0') <<
228 "F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
229 "F32(F16) = 0x" << std::setw(8) << fp32.hi[2];
230 EXPECT_EQ(fp32.hi[3] & UINT32_C(0x80000000), UINT32_C(0x80000000)) <<
231 std::hex << std::uppercase << std::setfill('0') <<
232 "F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
233 "F32(F16) = 0x" << std::setw(8) << fp32.hi[3];
234
235 /* Check exponent */
236 EXPECT_EQ(fp32.lo[0] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
237 std::hex << std::uppercase << std::setfill('0') <<
238 "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
239 "F32(F16) = 0x" << std::setw(8) << fp32.lo[0];
240 EXPECT_EQ(fp32.lo[1] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
241 std::hex << std::uppercase << std::setfill('0') <<
242 "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
243 "F32(F16) = 0x" << std::setw(8) << fp32.lo[1];
244 EXPECT_EQ(fp32.lo[2] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
245 std::hex << std::uppercase << std::setfill('0') <<
246 "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
247 "F32(F16) = 0x" << std::setw(8) << fp32.lo[2];
248 EXPECT_EQ(fp32.lo[3] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
249 std::hex << std::uppercase << std::setfill('0') <<
250 "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
251 "F32(F16) = 0x" << std::setw(8) << fp32.lo[3];
252 EXPECT_EQ(fp32.hi[0] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
253 std::hex << std::uppercase << std::setfill('0') <<
254 "F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
255 "F32(F16) = 0x" << std::setw(8) << fp32.hi[0];
256 EXPECT_EQ(fp32.hi[1] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
257 std::hex << std::uppercase << std::setfill('0') <<
258 "F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
259 "F32(F16) = 0x" << std::setw(8) << fp32.hi[1];
260 EXPECT_EQ(fp32.hi[2] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
261 std::hex << std::uppercase << std::setfill('0') <<
262 "F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
263 "F32(F16) = 0x" << std::setw(8) << fp32.hi[2];
264 EXPECT_EQ(fp32.hi[3] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
265 std::hex << std::uppercase << std::setfill('0') <<
266 "F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
267 "F32(F16) = 0x" << std::setw(8) << fp32.hi[3];
268
269 /* Check mantissa */
270 EXPECT_NE(fp32.lo[0] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
271 std::hex << std::uppercase << std::setfill('0') <<
272 "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
273 "F32(F16) = 0x" << std::setw(8) << fp32.lo[0];
274 EXPECT_NE(fp32.lo[1] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
275 std::hex << std::uppercase << std::setfill('0') <<
276 "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
277 "F32(F16) = 0x" << std::setw(8) << fp32.lo[1];
278 EXPECT_NE(fp32.lo[2] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
279 std::hex << std::uppercase << std::setfill('0') <<
280 "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
281 "F32(F16) = 0x" << std::setw(8) << fp32.lo[2];
282 EXPECT_NE(fp32.lo[3] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
283 std::hex << std::uppercase << std::setfill('0') <<
284 "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
285 "F32(F16) = 0x" << std::setw(8) << fp32.lo[3];
286 EXPECT_NE(fp32.hi[0] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
287 std::hex << std::uppercase << std::setfill('0') <<
288 "F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
289 "F32(F16) = 0x" << std::setw(8) << fp32.hi[0];
290 EXPECT_NE(fp32.hi[1] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
291 std::hex << std::uppercase << std::setfill('0') <<
292 "F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
293 "F32(F16) = 0x" << std::setw(8) << fp32.hi[1];
294 EXPECT_NE(fp32.hi[2] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
295 std::hex << std::uppercase << std::setfill('0') <<
296 "F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
297 "F32(F16) = 0x" << std::setw(8) << fp32.hi[2];
298 EXPECT_NE(fp32.hi[3] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
299 std::hex << std::uppercase << std::setfill('0') <<
300 "F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
301 "F32(F16) = 0x" << std::setw(8) << fp32.hi[3];
302 }
303 }
304
TEST(FP16_IEEE_TO_FP32x2_PSIMD,positive_normalized_values)305 TEST(FP16_IEEE_TO_FP32x2_PSIMD, positive_normalized_values) {
306 const uint32_t exponentBias = 15;
307 for (int32_t e = -14; e <= 15; e++) {
308 for (uint16_t h = 0; h < 0x0400; h += 8) {
309 const psimd_u16 fp16 = {
310 (uint16_t) (h + ((e + exponentBias) << 10) + 0),
311 (uint16_t) (h + ((e + exponentBias) << 10) + 1),
312 (uint16_t) (h + ((e + exponentBias) << 10) + 2),
313 (uint16_t) (h + ((e + exponentBias) << 10) + 3),
314 (uint16_t) (h + ((e + exponentBias) << 10) + 4),
315 (uint16_t) (h + ((e + exponentBias) << 10) + 5),
316 (uint16_t) (h + ((e + exponentBias) << 10) + 6),
317 (uint16_t) (h + ((e + exponentBias) << 10) + 7)
318 };
319 const psimd_u32x2 fp32 =
320 psimd_cast_f32x2_u32x2(fp16_ieee_to_fp32x2_psimd(fp16));
321
322 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[0]), fp32.lo[0]) <<
323 std::hex << std::uppercase << std::setfill('0') <<
324 "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
325 "F32(F16) = 0x" << std::setw(8) << fp32.lo[0] << ", " <<
326 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[0]);
327 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[1]), fp32.lo[1]) <<
328 std::hex << std::uppercase << std::setfill('0') <<
329 "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
330 "F32(F16) = 0x" << std::setw(8) << fp32.lo[1] << ", " <<
331 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[1]);
332 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[2]), fp32.lo[2]) <<
333 std::hex << std::uppercase << std::setfill('0') <<
334 "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
335 "F32(F16) = 0x" << std::setw(8) << fp32.lo[2] << ", " <<
336 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[2]);
337 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[3]), fp32.lo[3]) <<
338 std::hex << std::uppercase << std::setfill('0') <<
339 "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
340 "F32(F16) = 0x" << std::setw(8) << fp32.lo[3] << ", " <<
341 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[3]);
342 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[4]), fp32.hi[0]) <<
343 std::hex << std::uppercase << std::setfill('0') <<
344 "F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
345 "F32(F16) = 0x" << std::setw(8) << fp32.hi[0] << ", " <<
346 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[4]);
347 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[5]), fp32.hi[1]) <<
348 std::hex << std::uppercase << std::setfill('0') <<
349 "F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
350 "F32(F16) = 0x" << std::setw(8) << fp32.hi[1] << ", " <<
351 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[5]);
352 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[6]), fp32.hi[2]) <<
353 std::hex << std::uppercase << std::setfill('0') <<
354 "F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
355 "F32(F16) = 0x" << std::setw(8) << fp32.hi[2] << ", " <<
356 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[6]);
357 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[7]), fp32.hi[3]) <<
358 std::hex << std::uppercase << std::setfill('0') <<
359 "F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
360 "F32(F16) = 0x" << std::setw(8) << fp32.hi[3] << ", " <<
361 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[7]);
362 }
363 }
364 }
365
TEST(FP16_IEEE_TO_FP32x2_PSIMD,negative_normalized_values)366 TEST(FP16_IEEE_TO_FP32x2_PSIMD, negative_normalized_values) {
367 const uint32_t exponentBias = 15;
368 for (int32_t e = -14; e <= 15; e++) {
369 for (uint16_t h = 0; h < 0x0400; h += 8) {
370 const psimd_u16 fp16 = {
371 (uint16_t) (h + ((e + exponentBias) << 10) + 0x8000),
372 (uint16_t) (h + ((e + exponentBias) << 10) + 0x8001),
373 (uint16_t) (h + ((e + exponentBias) << 10) + 0x8002),
374 (uint16_t) (h + ((e + exponentBias) << 10) + 0x8003),
375 (uint16_t) (h + ((e + exponentBias) << 10) + 0x8004),
376 (uint16_t) (h + ((e + exponentBias) << 10) + 0x8005),
377 (uint16_t) (h + ((e + exponentBias) << 10) + 0x8006),
378 (uint16_t) (h + ((e + exponentBias) << 10) + 0x8007)
379 };
380 const psimd_u32x2 fp32 =
381 psimd_cast_f32x2_u32x2(fp16_ieee_to_fp32x2_psimd(fp16));
382
383 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[0]), fp32.lo[0]) <<
384 std::hex << std::uppercase << std::setfill('0') <<
385 "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
386 "F32(F16) = 0x" << std::setw(8) << fp32.lo[0] << ", " <<
387 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[0]);
388 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[1]), fp32.lo[1]) <<
389 std::hex << std::uppercase << std::setfill('0') <<
390 "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
391 "F32(F16) = 0x" << std::setw(8) << fp32.lo[1] << ", " <<
392 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[1]);
393 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[2]), fp32.lo[2]) <<
394 std::hex << std::uppercase << std::setfill('0') <<
395 "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
396 "F32(F16) = 0x" << std::setw(8) << fp32.lo[2] << ", " <<
397 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[2]);
398 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[3]), fp32.lo[3]) <<
399 std::hex << std::uppercase << std::setfill('0') <<
400 "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
401 "F32(F16) = 0x" << std::setw(8) << fp32.lo[3] << ", " <<
402 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[3]);
403 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[4]), fp32.hi[0]) <<
404 std::hex << std::uppercase << std::setfill('0') <<
405 "F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
406 "F32(F16) = 0x" << std::setw(8) << fp32.hi[0] << ", " <<
407 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[4]);
408 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[5]), fp32.hi[1]) <<
409 std::hex << std::uppercase << std::setfill('0') <<
410 "F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
411 "F32(F16) = 0x" << std::setw(8) << fp32.hi[1] << ", " <<
412 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[5]);
413 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[6]), fp32.hi[2]) <<
414 std::hex << std::uppercase << std::setfill('0') <<
415 "F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
416 "F32(F16) = 0x" << std::setw(8) << fp32.hi[2] << ", " <<
417 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[6]);
418 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[7]), fp32.hi[3]) <<
419 std::hex << std::uppercase << std::setfill('0') <<
420 "F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
421 "F32(F16) = 0x" << std::setw(8) << fp32.hi[3] << ", " <<
422 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[7]);
423 }
424 }
425 }
426
TEST(FP16_IEEE_TO_FP32x2_PSIMD,positive_denormalized_values)427 TEST(FP16_IEEE_TO_FP32x2_PSIMD, positive_denormalized_values) {
428 for (uint16_t h = 0; h < 0x0400; h += 8) {
429 const psimd_u16 fp16 = {
430 (uint16_t) (h + 0),
431 (uint16_t) (h + 1),
432 (uint16_t) (h + 2),
433 (uint16_t) (h + 3),
434 (uint16_t) (h + 4),
435 (uint16_t) (h + 5),
436 (uint16_t) (h + 6),
437 (uint16_t) (h + 7)
438 };
439 const psimd_u32x2 fp32 =
440 psimd_cast_f32x2_u32x2(fp16_ieee_to_fp32x2_psimd(fp16));
441
442 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[0]), fp32.lo[0]) <<
443 std::hex << std::uppercase << std::setfill('0') <<
444 "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
445 "F32(F16) = 0x" << std::setw(8) << fp32.lo[0] << ", " <<
446 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[0]);
447 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[1]), fp32.lo[1]) <<
448 std::hex << std::uppercase << std::setfill('0') <<
449 "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
450 "F32(F16) = 0x" << std::setw(8) << fp32.lo[1] << ", " <<
451 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[1]);
452 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[2]), fp32.lo[2]) <<
453 std::hex << std::uppercase << std::setfill('0') <<
454 "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
455 "F32(F16) = 0x" << std::setw(8) << fp32.lo[2] << ", " <<
456 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[2]);
457 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[3]), fp32.lo[3]) <<
458 std::hex << std::uppercase << std::setfill('0') <<
459 "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
460 "F32(F16) = 0x" << std::setw(8) << fp32.lo[3] << ", " <<
461 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[3]);
462 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[4]), fp32.hi[0]) <<
463 std::hex << std::uppercase << std::setfill('0') <<
464 "F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
465 "F32(F16) = 0x" << std::setw(8) << fp32.hi[0] << ", " <<
466 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[4]);
467 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[5]), fp32.hi[1]) <<
468 std::hex << std::uppercase << std::setfill('0') <<
469 "F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
470 "F32(F16) = 0x" << std::setw(8) << fp32.hi[1] << ", " <<
471 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[5]);
472 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[6]), fp32.hi[2]) <<
473 std::hex << std::uppercase << std::setfill('0') <<
474 "F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
475 "F32(F16) = 0x" << std::setw(8) << fp32.hi[2] << ", " <<
476 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[6]);
477 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[7]), fp32.hi[3]) <<
478 std::hex << std::uppercase << std::setfill('0') <<
479 "F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
480 "F32(F16) = 0x" << std::setw(8) << fp32.hi[3] << ", " <<
481 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[7]);
482 }
483 }
484
TEST(FP16_IEEE_TO_FP32x2_PSIMD,negative_denormalized_values)485 TEST(FP16_IEEE_TO_FP32x2_PSIMD, negative_denormalized_values) {
486 for (uint16_t h = 0; h < 0x0400; h += 8) {
487 const psimd_u16 fp16 = {
488 (uint16_t) (h + 0x8000),
489 (uint16_t) (h + 0x8001),
490 (uint16_t) (h + 0x8002),
491 (uint16_t) (h + 0x8003),
492 (uint16_t) (h + 0x8004),
493 (uint16_t) (h + 0x8005),
494 (uint16_t) (h + 0x8006),
495 (uint16_t) (h + 0x8007)
496 };
497 const psimd_u32x2 fp32 =
498 psimd_cast_f32x2_u32x2(fp16_ieee_to_fp32x2_psimd(fp16));
499
500 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[0]), fp32.lo[0]) <<
501 std::hex << std::uppercase << std::setfill('0') <<
502 "F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
503 "F32(F16) = 0x" << std::setw(8) << fp32.lo[0] << ", " <<
504 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[0]);
505 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[1]), fp32.lo[1]) <<
506 std::hex << std::uppercase << std::setfill('0') <<
507 "F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
508 "F32(F16) = 0x" << std::setw(8) << fp32.lo[1] << ", " <<
509 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[1]);
510 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[2]), fp32.lo[2]) <<
511 std::hex << std::uppercase << std::setfill('0') <<
512 "F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
513 "F32(F16) = 0x" << std::setw(8) << fp32.lo[2] << ", " <<
514 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[2]);
515 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[3]), fp32.lo[3]) <<
516 std::hex << std::uppercase << std::setfill('0') <<
517 "F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
518 "F32(F16) = 0x" << std::setw(8) << fp32.lo[3] << ", " <<
519 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[3]);
520 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[4]), fp32.hi[0]) <<
521 std::hex << std::uppercase << std::setfill('0') <<
522 "F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
523 "F32(F16) = 0x" << std::setw(8) << fp32.hi[0] << ", " <<
524 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[4]);
525 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[5]), fp32.hi[1]) <<
526 std::hex << std::uppercase << std::setfill('0') <<
527 "F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
528 "F32(F16) = 0x" << std::setw(8) << fp32.hi[1] << ", " <<
529 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[5]);
530 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[6]), fp32.hi[2]) <<
531 std::hex << std::uppercase << std::setfill('0') <<
532 "F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
533 "F32(F16) = 0x" << std::setw(8) << fp32.hi[2] << ", " <<
534 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[6]);
535 EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[7]), fp32.hi[3]) <<
536 std::hex << std::uppercase << std::setfill('0') <<
537 "F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
538 "F32(F16) = 0x" << std::setw(8) << fp32.hi[3] << ", " <<
539 "F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[7]);
540 }
541 }
542