• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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