1 #include <gtest/gtest.h>
2 
3 #include <cstdint>
4 
5 #include <fp16.h>
6 #include <fp16/psimd.h>
7 
8 
TEST(FP16_ALT_TO_FP32x2_PSIMD,positive_normalized_values)9 TEST(FP16_ALT_TO_FP32x2_PSIMD, positive_normalized_values) {
10 	const uint32_t exponentBias = 15;
11 	for (int32_t e = -14; e <= 16; e++) {
12 		for (uint16_t h = 0; h < 0x0400; h += 8) {
13 			const psimd_u16 fp16 = {
14 				(uint16_t) (h + ((e + exponentBias) << 10) + 0),
15 				(uint16_t) (h + ((e + exponentBias) << 10) + 1),
16 				(uint16_t) (h + ((e + exponentBias) << 10) + 2),
17 				(uint16_t) (h + ((e + exponentBias) << 10) + 3),
18 				(uint16_t) (h + ((e + exponentBias) << 10) + 4),
19 				(uint16_t) (h + ((e + exponentBias) << 10) + 5),
20 				(uint16_t) (h + ((e + exponentBias) << 10) + 6),
21 				(uint16_t) (h + ((e + exponentBias) << 10) + 7)
22 			};
23 			const psimd_u32x2 fp32 =
24 				psimd_cast_f32x2_u32x2(fp16_alt_to_fp32x2_psimd(fp16));
25 
26 			EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[0]), fp32.lo[0]) <<
27 				std::hex << std::uppercase << std::setfill('0') <<
28 				"F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
29 				"F32(F16) = 0x" << std::setw(8) << fp32.lo[0] << ", " <<
30 				"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[0]);
31 			EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[1]), fp32.lo[1]) <<
32 				std::hex << std::uppercase << std::setfill('0') <<
33 				"F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
34 				"F32(F16) = 0x" << std::setw(8) << fp32.lo[1] << ", " <<
35 				"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[1]);
36 			EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[2]), fp32.lo[2]) <<
37 				std::hex << std::uppercase << std::setfill('0') <<
38 				"F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
39 				"F32(F16) = 0x" << std::setw(8) << fp32.lo[2] << ", " <<
40 				"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[2]);
41 			EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[3]), fp32.lo[3]) <<
42 				std::hex << std::uppercase << std::setfill('0') <<
43 				"F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
44 				"F32(F16) = 0x" << std::setw(8) << fp32.lo[3] << ", " <<
45 				"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[3]);
46 			EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[4]), fp32.hi[0]) <<
47 				std::hex << std::uppercase << std::setfill('0') <<
48 				"F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
49 				"F32(F16) = 0x" << std::setw(8) << fp32.hi[0] << ", " <<
50 				"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[4]);
51 			EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[5]), fp32.hi[1]) <<
52 				std::hex << std::uppercase << std::setfill('0') <<
53 				"F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
54 				"F32(F16) = 0x" << std::setw(8) << fp32.hi[1] << ", " <<
55 				"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[5]);
56 			EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[6]), fp32.hi[2]) <<
57 				std::hex << std::uppercase << std::setfill('0') <<
58 				"F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
59 				"F32(F16) = 0x" << std::setw(8) << fp32.hi[2] << ", " <<
60 				"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[6]);
61 			EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[7]), fp32.hi[3]) <<
62 				std::hex << std::uppercase << std::setfill('0') <<
63 				"F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
64 				"F32(F16) = 0x" << std::setw(8) << fp32.hi[3] << ", " <<
65 				"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[7]);
66 		}
67 	}
68 }
69 
TEST(FP16_ALT_TO_FP32x2_PSIMD,negative_normalized_values)70 TEST(FP16_ALT_TO_FP32x2_PSIMD, negative_normalized_values) {
71 	const uint32_t exponentBias = 15;
72 	for (int32_t e = -14; e <= 16; e++) {
73 		for (uint16_t h = 0; h < 0x0400; h += 8) {
74 			const psimd_u16 fp16 = {
75 				(uint16_t) (h + ((e + exponentBias) << 10) + 0x8000),
76 				(uint16_t) (h + ((e + exponentBias) << 10) + 0x8001),
77 				(uint16_t) (h + ((e + exponentBias) << 10) + 0x8002),
78 				(uint16_t) (h + ((e + exponentBias) << 10) + 0x8003),
79 				(uint16_t) (h + ((e + exponentBias) << 10) + 0x8004),
80 				(uint16_t) (h + ((e + exponentBias) << 10) + 0x8005),
81 				(uint16_t) (h + ((e + exponentBias) << 10) + 0x8006),
82 				(uint16_t) (h + ((e + exponentBias) << 10) + 0x8007)
83 			};
84 			const psimd_u32x2 fp32 =
85 				psimd_cast_f32x2_u32x2(fp16_alt_to_fp32x2_psimd(fp16));
86 
87 			EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[0]), fp32.lo[0]) <<
88 				std::hex << std::uppercase << std::setfill('0') <<
89 				"F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
90 				"F32(F16) = 0x" << std::setw(8) << fp32.lo[0] << ", " <<
91 				"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[0]);
92 			EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[1]), fp32.lo[1]) <<
93 				std::hex << std::uppercase << std::setfill('0') <<
94 				"F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
95 				"F32(F16) = 0x" << std::setw(8) << fp32.lo[1] << ", " <<
96 				"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[1]);
97 			EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[2]), fp32.lo[2]) <<
98 				std::hex << std::uppercase << std::setfill('0') <<
99 				"F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
100 				"F32(F16) = 0x" << std::setw(8) << fp32.lo[2] << ", " <<
101 				"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[2]);
102 			EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[3]), fp32.lo[3]) <<
103 				std::hex << std::uppercase << std::setfill('0') <<
104 				"F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
105 				"F32(F16) = 0x" << std::setw(8) << fp32.lo[3] << ", " <<
106 				"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[3]);
107 			EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[4]), fp32.hi[0]) <<
108 				std::hex << std::uppercase << std::setfill('0') <<
109 				"F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
110 				"F32(F16) = 0x" << std::setw(8) << fp32.hi[0] << ", " <<
111 				"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[4]);
112 			EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[5]), fp32.hi[1]) <<
113 				std::hex << std::uppercase << std::setfill('0') <<
114 				"F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
115 				"F32(F16) = 0x" << std::setw(8) << fp32.hi[1] << ", " <<
116 				"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[5]);
117 			EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[6]), fp32.hi[2]) <<
118 				std::hex << std::uppercase << std::setfill('0') <<
119 				"F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
120 				"F32(F16) = 0x" << std::setw(8) << fp32.hi[2] << ", " <<
121 				"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[6]);
122 			EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[7]), fp32.hi[3]) <<
123 				std::hex << std::uppercase << std::setfill('0') <<
124 				"F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
125 				"F32(F16) = 0x" << std::setw(8) << fp32.hi[3] << ", " <<
126 				"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[7]);
127 		}
128 	}
129 }
130 
TEST(FP16_ALT_TO_FP32x2_PSIMD,positive_denormalized_values)131 TEST(FP16_ALT_TO_FP32x2_PSIMD, positive_denormalized_values) {
132 	for (uint16_t h = 0; h < 0x0400; h += 8) {
133 		const psimd_u16 fp16 = {
134 			(uint16_t) (h + 0),
135 			(uint16_t) (h + 1),
136 			(uint16_t) (h + 2),
137 			(uint16_t) (h + 3),
138 			(uint16_t) (h + 4),
139 			(uint16_t) (h + 5),
140 			(uint16_t) (h + 6),
141 			(uint16_t) (h + 7)
142 		};
143 		const psimd_u32x2 fp32 =
144 			psimd_cast_f32x2_u32x2(fp16_alt_to_fp32x2_psimd(fp16));
145 
146 		EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[0]), fp32.lo[0]) <<
147 			std::hex << std::uppercase << std::setfill('0') <<
148 			"F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
149 			"F32(F16) = 0x" << std::setw(8) << fp32.lo[0] << ", " <<
150 			"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[0]);
151 		EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[1]), fp32.lo[1]) <<
152 			std::hex << std::uppercase << std::setfill('0') <<
153 			"F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
154 			"F32(F16) = 0x" << std::setw(8) << fp32.lo[1] << ", " <<
155 			"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[1]);
156 		EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[2]), fp32.lo[2]) <<
157 			std::hex << std::uppercase << std::setfill('0') <<
158 			"F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
159 			"F32(F16) = 0x" << std::setw(8) << fp32.lo[2] << ", " <<
160 			"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[2]);
161 		EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[3]), fp32.lo[3]) <<
162 			std::hex << std::uppercase << std::setfill('0') <<
163 			"F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
164 			"F32(F16) = 0x" << std::setw(8) << fp32.lo[3] << ", " <<
165 			"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[3]);
166 		EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[4]), fp32.hi[0]) <<
167 			std::hex << std::uppercase << std::setfill('0') <<
168 			"F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
169 			"F32(F16) = 0x" << std::setw(8) << fp32.hi[0] << ", " <<
170 			"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[4]);
171 		EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[5]), fp32.hi[1]) <<
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 			"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[5]);
176 		EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[6]), fp32.hi[2]) <<
177 			std::hex << std::uppercase << std::setfill('0') <<
178 			"F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
179 			"F32(F16) = 0x" << std::setw(8) << fp32.hi[2] << ", " <<
180 			"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[6]);
181 		EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[7]), fp32.hi[3]) <<
182 			std::hex << std::uppercase << std::setfill('0') <<
183 			"F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
184 			"F32(F16) = 0x" << std::setw(8) << fp32.hi[3] << ", " <<
185 			"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[7]);
186 	}
187 }
188 
TEST(FP16_ALT_TO_FP32x2_PSIMD,negative_denormalized_values)189 TEST(FP16_ALT_TO_FP32x2_PSIMD, negative_denormalized_values) {
190 	for (uint16_t h = 0; h < 0x0400; h += 8) {
191 		const psimd_u16 fp16 = {
192 			(uint16_t) (h + 0x8000),
193 			(uint16_t) (h + 0x8001),
194 			(uint16_t) (h + 0x8002),
195 			(uint16_t) (h + 0x8003),
196 			(uint16_t) (h + 0x8004),
197 			(uint16_t) (h + 0x8005),
198 			(uint16_t) (h + 0x8006),
199 			(uint16_t) (h + 0x8007)
200 		};
201 		const psimd_u32x2 fp32 =
202 			psimd_cast_f32x2_u32x2(fp16_alt_to_fp32x2_psimd(fp16));
203 
204 		EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[0]), fp32.lo[0]) <<
205 			std::hex << std::uppercase << std::setfill('0') <<
206 			"F16 = 0x" << std::setw(4) << fp16[0] << ", " <<
207 			"F32(F16) = 0x" << std::setw(8) << fp32.lo[0] << ", " <<
208 			"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[0]);
209 		EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[1]), fp32.lo[1]) <<
210 			std::hex << std::uppercase << std::setfill('0') <<
211 			"F16 = 0x" << std::setw(4) << fp16[1] << ", " <<
212 			"F32(F16) = 0x" << std::setw(8) << fp32.lo[1] << ", " <<
213 			"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[1]);
214 		EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[2]), fp32.lo[2]) <<
215 			std::hex << std::uppercase << std::setfill('0') <<
216 			"F16 = 0x" << std::setw(4) << fp16[2] << ", " <<
217 			"F32(F16) = 0x" << std::setw(8) << fp32.lo[2] << ", " <<
218 			"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[2]);
219 		EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[3]), fp32.lo[3]) <<
220 			std::hex << std::uppercase << std::setfill('0') <<
221 			"F16 = 0x" << std::setw(4) << fp16[3] << ", " <<
222 			"F32(F16) = 0x" << std::setw(8) << fp32.lo[3] << ", " <<
223 			"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[3]);
224 		EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[4]), fp32.hi[0]) <<
225 			std::hex << std::uppercase << std::setfill('0') <<
226 			"F16 = 0x" << std::setw(4) << fp16[4] << ", " <<
227 			"F32(F16) = 0x" << std::setw(8) << fp32.hi[0] << ", " <<
228 			"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[4]);
229 		EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[5]), fp32.hi[1]) <<
230 			std::hex << std::uppercase << std::setfill('0') <<
231 			"F16 = 0x" << std::setw(4) << fp16[5] << ", " <<
232 			"F32(F16) = 0x" << std::setw(8) << fp32.hi[1] << ", " <<
233 			"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[5]);
234 		EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[6]), fp32.hi[2]) <<
235 			std::hex << std::uppercase << std::setfill('0') <<
236 			"F16 = 0x" << std::setw(4) << fp16[6] << ", " <<
237 			"F32(F16) = 0x" << std::setw(8) << fp32.hi[2] << ", " <<
238 			"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[6]);
239 		EXPECT_EQ(fp16_alt_to_fp32_bits(fp16[7]), fp32.hi[3]) <<
240 			std::hex << std::uppercase << std::setfill('0') <<
241 			"F16 = 0x" << std::setw(4) << fp16[7] << ", " <<
242 			"F32(F16) = 0x" << std::setw(8) << fp32.hi[3] << ", " <<
243 			"F32 = 0x" << std::setw(8) << fp16_alt_to_fp32_bits(fp16[7]);
244 	}
245 }
246