• 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_FP32_PSIMD,infinity)9 TEST(FP16_IEEE_TO_FP32_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 	};
20 	const psimd_u32 fp32 = (psimd_u32) fp16_ieee_to_fp32_psimd(fp16);
21 
22 	EXPECT_EQ(positive_infinity_f32, fp32[0]) <<
23 		std::hex << std::uppercase << std::setfill('0') <<
24 		"F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
25 		"F32(F16) = 0x" << std::setw(8) << fp32[0] << ", " <<
26 		"F32 = 0x" << std::setw(8) << positive_infinity_f32;
27 	EXPECT_EQ(negative_infinity_f32, fp32[1]) <<
28 		std::hex << std::uppercase << std::setfill('0') <<
29 		"F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
30 		"F32(F16) = 0x" << std::setw(8) << fp32[1] << ", " <<
31 		"F32 = 0x" << std::setw(8) << negative_infinity_f32;
32 	EXPECT_EQ(negative_infinity_f32, fp32[2]) <<
33 		std::hex << std::uppercase << std::setfill('0') <<
34 		"F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
35 		"F32(F16) = 0x" << std::setw(8) << fp32[2] << ", " <<
36 		"F32 = 0x" << std::setw(8) << negative_infinity_f32;
37 	EXPECT_EQ(positive_infinity_f32, fp32[3]) <<
38 		std::hex << std::uppercase << std::setfill('0') <<
39 		"F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
40 		"F32(F16) = 0x" << std::setw(8) << fp32[3] << ", " <<
41 		"F32 = 0x" << std::setw(8) << positive_infinity_f32;
42 }
43 
TEST(FP16_IEEE_TO_FP32_PSIMD,positive_nan)44 TEST(FP16_IEEE_TO_FP32_PSIMD, positive_nan) {
45 	for (uint16_t h = 0; h < 0x0400; h += 4) {
46 		const psimd_u16 fp16 = {
47 			(uint16_t) (h + 0x7C00 + (h == 0)) /* Avoid infinity */,
48 			(uint16_t) (h + 0x7C01),
49 			(uint16_t) (h + 0x7C02),
50 			(uint16_t) (h + 0x7C03),
51 		};
52 		const psimd_u32 fp32 = (psimd_u32) fp16_ieee_to_fp32_psimd(fp16);
53 
54 		/* Check sign */
55 		EXPECT_EQ(fp32[0] & UINT32_C(0x80000000), 0) <<
56 			std::hex << std::uppercase << std::setfill('0') <<
57 			"F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
58 			"F32(F16) = 0x" << std::setw(8) << fp32[0];
59 		EXPECT_EQ(fp32[1] & UINT32_C(0x80000000), 0) <<
60 			std::hex << std::uppercase << std::setfill('0') <<
61 			"F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
62 			"F32(F16) = 0x" << std::setw(8) << fp32[1];
63 		EXPECT_EQ(fp32[2] & UINT32_C(0x80000000), 0) <<
64 			std::hex << std::uppercase << std::setfill('0') <<
65 			"F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
66 			"F32(F16) = 0x" << std::setw(8) << fp32[2];
67 		EXPECT_EQ(fp32[3] & UINT32_C(0x80000000), 0) <<
68 			std::hex << std::uppercase << std::setfill('0') <<
69 			"F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
70 			"F32(F16) = 0x" << std::setw(8) << fp32[3];
71 
72 		/* Check exponent */
73 		EXPECT_EQ(fp32[0] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
74 			std::hex << std::uppercase << std::setfill('0') <<
75 			"F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
76 			"F32(F16) = 0x" << std::setw(8) << fp32[0];
77 		EXPECT_EQ(fp32[1] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
78 			std::hex << std::uppercase << std::setfill('0') <<
79 			"F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
80 			"F32(F16) = 0x" << std::setw(8) << fp32[1];
81 		EXPECT_EQ(fp32[2] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
82 			std::hex << std::uppercase << std::setfill('0') <<
83 			"F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
84 			"F32(F16) = 0x" << std::setw(8) << fp32[2];
85 		EXPECT_EQ(fp32[3] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
86 			std::hex << std::uppercase << std::setfill('0') <<
87 			"F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
88 			"F32(F16) = 0x" << std::setw(8) << fp32[3];
89 
90 		/* Check mantissa */
91 		EXPECT_NE(fp32[0] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
92 			std::hex << std::uppercase << std::setfill('0') <<
93 			"F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
94 			"F32(F16) = 0x" << std::setw(8) << fp32[0];
95 		EXPECT_NE(fp32[1] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
96 			std::hex << std::uppercase << std::setfill('0') <<
97 			"F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
98 			"F32(F16) = 0x" << std::setw(8) << fp32[1];
99 		EXPECT_NE(fp32[2] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
100 			std::hex << std::uppercase << std::setfill('0') <<
101 			"F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
102 			"F32(F16) = 0x" << std::setw(8) << fp32[2];
103 		EXPECT_NE(fp32[3] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
104 			std::hex << std::uppercase << std::setfill('0') <<
105 			"F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
106 			"F32(F16) = 0x" << std::setw(8) << fp32[3];
107 	}
108 }
109 
TEST(FP16_IEEE_TO_FP32_PSIMD,negative_nan)110 TEST(FP16_IEEE_TO_FP32_PSIMD, negative_nan) {
111 	for (uint16_t h = 0; h < 0x0400; h += 4) {
112 		const psimd_u16 fp16 = {
113 			(uint16_t) (h + 0xFC00 + (h == 0)) /* Avoid infinity */,
114 			(uint16_t) (h + 0xFC01),
115 			(uint16_t) (h + 0xFC02),
116 			(uint16_t) (h + 0xFC03),
117 		};
118 		const psimd_u32 fp32 = (psimd_u32) fp16_ieee_to_fp32_psimd(fp16);
119 
120 		/* Check sign */
121 		EXPECT_EQ(fp32[0] & UINT32_C(0x80000000), UINT32_C(0x80000000)) <<
122 			std::hex << std::uppercase << std::setfill('0') <<
123 			"F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
124 			"F32(F16) = 0x" << std::setw(8) << fp32[0];
125 		EXPECT_EQ(fp32[1] & UINT32_C(0x80000000), UINT32_C(0x80000000)) <<
126 			std::hex << std::uppercase << std::setfill('0') <<
127 			"F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
128 			"F32(F16) = 0x" << std::setw(8) << fp32[1];
129 		EXPECT_EQ(fp32[2] & UINT32_C(0x80000000), UINT32_C(0x80000000)) <<
130 			std::hex << std::uppercase << std::setfill('0') <<
131 			"F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
132 			"F32(F16) = 0x" << std::setw(8) << fp32[2];
133 		EXPECT_EQ(fp32[3] & UINT32_C(0x80000000), UINT32_C(0x80000000)) <<
134 			std::hex << std::uppercase << std::setfill('0') <<
135 			"F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
136 			"F32(F16) = 0x" << std::setw(8) << fp32[3];
137 
138 		/* Check exponent */
139 		EXPECT_EQ(fp32[0] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
140 			std::hex << std::uppercase << std::setfill('0') <<
141 			"F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
142 			"F32(F16) = 0x" << std::setw(8) << fp32[0];
143 		EXPECT_EQ(fp32[1] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
144 			std::hex << std::uppercase << std::setfill('0') <<
145 			"F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
146 			"F32(F16) = 0x" << std::setw(8) << fp32[1];
147 		EXPECT_EQ(fp32[2] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
148 			std::hex << std::uppercase << std::setfill('0') <<
149 			"F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
150 			"F32(F16) = 0x" << std::setw(8) << fp32[2];
151 		EXPECT_EQ(fp32[3] & UINT32_C(0x7F800000), UINT32_C(0x7F800000)) <<
152 			std::hex << std::uppercase << std::setfill('0') <<
153 			"F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
154 			"F32(F16) = 0x" << std::setw(8) << fp32[3];
155 
156 		/* Check mantissa */
157 		EXPECT_NE(fp32[0] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
158 			std::hex << std::uppercase << std::setfill('0') <<
159 			"F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
160 			"F32(F16) = 0x" << std::setw(8) << fp32[0];
161 		EXPECT_NE(fp32[1] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
162 			std::hex << std::uppercase << std::setfill('0') <<
163 			"F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
164 			"F32(F16) = 0x" << std::setw(8) << fp32[1];
165 		EXPECT_NE(fp32[2] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
166 			std::hex << std::uppercase << std::setfill('0') <<
167 			"F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
168 			"F32(F16) = 0x" << std::setw(8) << fp32[2];
169 		EXPECT_NE(fp32[3] & UINT32_C(0x007FFFFF), UINT32_C(0)) <<
170 			std::hex << std::uppercase << std::setfill('0') <<
171 			"F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
172 			"F32(F16) = 0x" << std::setw(8) << fp32[3];
173 	}
174 }
175 
TEST(FP16_IEEE_TO_FP32_PSIMD,positive_normalized_values)176 TEST(FP16_IEEE_TO_FP32_PSIMD, positive_normalized_values) {
177 	const uint32_t exponentBias = 15;
178 	for (int32_t e = -14; e <= 15; e++) {
179 		for (uint16_t h = 0; h < 0x0400; h += 4) {
180 			const psimd_u16 fp16 = {
181 				(uint16_t) (h + ((e + exponentBias) << 10) + 0),
182 				(uint16_t) (h + ((e + exponentBias) << 10) + 1),
183 				(uint16_t) (h + ((e + exponentBias) << 10) + 2),
184 				(uint16_t) (h + ((e + exponentBias) << 10) + 3),
185 			};
186 			const psimd_u32 fp32 = (psimd_u32) fp16_ieee_to_fp32_psimd(fp16);
187 
188 			EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[0]), fp32[0]) <<
189 				std::hex << std::uppercase << std::setfill('0') <<
190 				"F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
191 				"F32(F16) = 0x" << std::setw(8) << fp32[0] << ", " <<
192 				"F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[0]);
193 			EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[1]), fp32[1]) <<
194 				std::hex << std::uppercase << std::setfill('0') <<
195 				"F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
196 				"F32(F16) = 0x" << std::setw(8) << fp32[1] << ", " <<
197 				"F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[1]);
198 			EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[2]), fp32[2]) <<
199 				std::hex << std::uppercase << std::setfill('0') <<
200 				"F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
201 				"F32(F16) = 0x" << std::setw(8) << fp32[2] << ", " <<
202 				"F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[2]);
203 			EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[3]), fp32[3]) <<
204 				std::hex << std::uppercase << std::setfill('0') <<
205 				"F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
206 				"F32(F16) = 0x" << std::setw(8) << fp32[3] << ", " <<
207 				"F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[3]);
208 		}
209 	}
210 }
211 
TEST(FP16_IEEE_TO_FP32_PSIMD,negative_normalized_values)212 TEST(FP16_IEEE_TO_FP32_PSIMD, negative_normalized_values) {
213 	const uint32_t exponentBias = 15;
214 	for (int32_t e = -14; e <= 15; e++) {
215 		for (uint16_t h = 0; h < 0x0400; h += 4) {
216 			const psimd_u16 fp16 = {
217 				(uint16_t) (h + ((e + exponentBias) << 10) + 0x8000),
218 				(uint16_t) (h + ((e + exponentBias) << 10) + 0x8001),
219 				(uint16_t) (h + ((e + exponentBias) << 10) + 0x8002),
220 				(uint16_t) (h + ((e + exponentBias) << 10) + 0x8003),
221 			};
222 			const psimd_u32 fp32 = (psimd_u32) fp16_ieee_to_fp32_psimd(fp16);
223 
224 			EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[0]), fp32[0]) <<
225 				std::hex << std::uppercase << std::setfill('0') <<
226 				"F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
227 				"F32(F16) = 0x" << std::setw(8) << fp32[0] << ", " <<
228 				"F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[0]);
229 			EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[1]), fp32[1]) <<
230 				std::hex << std::uppercase << std::setfill('0') <<
231 				"F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
232 				"F32(F16) = 0x" << std::setw(8) << fp32[1] << ", " <<
233 				"F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[1]);
234 			EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[2]), fp32[2]) <<
235 				std::hex << std::uppercase << std::setfill('0') <<
236 				"F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
237 				"F32(F16) = 0x" << std::setw(8) << fp32[2] << ", " <<
238 				"F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[2]);
239 			EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[3]), fp32[3]) <<
240 				std::hex << std::uppercase << std::setfill('0') <<
241 				"F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
242 				"F32(F16) = 0x" << std::setw(8) << fp32[3] << ", " <<
243 				"F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[3]);
244 		}
245 	}
246 }
247 
TEST(FP16_IEEE_TO_FP32_PSIMD,positive_denormalized_values)248 TEST(FP16_IEEE_TO_FP32_PSIMD, positive_denormalized_values) {
249 	for (uint16_t h = 0; h < 0x0400; h += 4) {
250 		const psimd_u16 fp16 = {
251 			(uint16_t) (h + 0),
252 			(uint16_t) (h + 1),
253 			(uint16_t) (h + 2),
254 			(uint16_t) (h + 3),
255 		};
256 		const psimd_u32 fp32 = (psimd_u32) fp16_ieee_to_fp32_psimd(fp16);
257 
258 		EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[0]), fp32[0]) <<
259 			std::hex << std::uppercase << std::setfill('0') <<
260 			"F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
261 			"F32(F16) = 0x" << std::setw(8) << fp32[0] << ", " <<
262 			"F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[0]);
263 		EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[1]), fp32[1]) <<
264 			std::hex << std::uppercase << std::setfill('0') <<
265 			"F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
266 			"F32(F16) = 0x" << std::setw(8) << fp32[1] << ", " <<
267 			"F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[1]);
268 		EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[2]), fp32[2]) <<
269 			std::hex << std::uppercase << std::setfill('0') <<
270 			"F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
271 			"F32(F16) = 0x" << std::setw(8) << fp32[2] << ", " <<
272 			"F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[2]);
273 		EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[3]), fp32[3]) <<
274 			std::hex << std::uppercase << std::setfill('0') <<
275 			"F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
276 			"F32(F16) = 0x" << std::setw(8) << fp32[3] << ", " <<
277 			"F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[3]);
278 	}
279 }
280 
TEST(FP16_IEEE_TO_FP32_PSIMD,negative_denormalized_values)281 TEST(FP16_IEEE_TO_FP32_PSIMD, negative_denormalized_values) {
282 	for (uint16_t h = 0; h < 0x0400; h += 4) {
283 		const psimd_u16 fp16 = {
284 			(uint16_t) (h + 0x8000),
285 			(uint16_t) (h + 0x8001),
286 			(uint16_t) (h + 0x8002),
287 			(uint16_t) (h + 0x8003),
288 		};
289 		const psimd_u32 fp32 = (psimd_u32) fp16_ieee_to_fp32_psimd(fp16);
290 
291 		EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[0]), fp32[0]) <<
292 			std::hex << std::uppercase << std::setfill('0') <<
293 			"F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
294 			"F32(F16) = 0x" << std::setw(8) << fp32[0] << ", " <<
295 			"F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[0]);
296 		EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[1]), fp32[1]) <<
297 			std::hex << std::uppercase << std::setfill('0') <<
298 			"F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
299 			"F32(F16) = 0x" << std::setw(8) << fp32[1] << ", " <<
300 			"F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[1]);
301 		EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[2]), fp32[2]) <<
302 			std::hex << std::uppercase << std::setfill('0') <<
303 			"F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
304 			"F32(F16) = 0x" << std::setw(8) << fp32[2] << ", " <<
305 			"F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[2]);
306 		EXPECT_EQ(fp16_ieee_to_fp32_bits(fp16[3]), fp32[3]) <<
307 			std::hex << std::uppercase << std::setfill('0') <<
308 			"F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
309 			"F32(F16) = 0x" << std::setw(8) << fp32[3] << ", " <<
310 			"F32 = 0x" << std::setw(8) << fp16_ieee_to_fp32_bits(fp16[3]);
311 	}
312 }
313