xref: /aosp_15_r20/external/FP16/test/alt-to-fp32-value.cc (revision 5f32b7105932ea8520a0e8811c640f936367d707)
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_ALT_TO_FP32_VALUE,normalized_powers_of_2)10 TEST(FP16_ALT_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(0x7C00);
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(0x47800000);
36 
37 	const float min_po2_value = fp16_alt_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_alt_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_alt_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_alt_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_alt_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_alt_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_alt_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_alt_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_alt_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_alt_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_alt_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_alt_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_ALT_TO_FP32_VALUE,denormalized_powers_of_2)146 TEST(FP16_ALT_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_alt_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_alt_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_alt_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_alt_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_alt_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_alt_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_alt_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_alt_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_alt_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_alt_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_ALT_TO_FP32_VALUE,zero)260 TEST(FP16_ALT_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_alt_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_alt_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_ALT_TO_FP32_VALUE,positive_normalized_values)286 TEST(FP16_ALT_TO_FP32_VALUE, positive_normalized_values) {
287 	const uint32_t exponentBias = 15;
288 	for (int32_t e = -14; e <= 16; e++) {
289 		for (uint16_t h = 0; h < 0x0400; h++) {
290 			const uint16_t fp16 = h + ((uint16_t) (e + exponentBias) << 10);
291 			const uint32_t fp32 = fp16::normalizedValues[h] + ((uint32_t) e << 23);
292 			const float value = fp16_alt_to_fp32_value(fp16);
293 			uint32_t bits;
294 			memcpy(&bits, &value, sizeof(bits));
295 			EXPECT_EQ(fp32, bits) <<
296 				std::hex << std::uppercase << std::setfill('0') <<
297 				"F16 = 0x" << std::setw(4) << fp16 << ", " <<
298 				"F32(F16) = 0x" << std::setw(8) << bits << ", " <<
299 				"F32 = 0x" << std::setw(8) << fp32;
300 		}
301 	}
302 }
303 
TEST(FP16_ALT_TO_FP32_VALUE,negative_normalized_values)304 TEST(FP16_ALT_TO_FP32_VALUE, negative_normalized_values) {
305 	const uint32_t exponentBias = 15;
306 	for (int32_t e = -14; e <= 16; e++) {
307 		for (uint16_t h = 0; h < 0x0400; h++) {
308 			const uint16_t fp16 = (h + ((uint16_t) (e + exponentBias) << 10)) ^ UINT16_C(0x8000);
309 			const uint32_t fp32 = (fp16::normalizedValues[h] + ((uint32_t) e << 23)) ^ UINT32_C(0x80000000);
310 			const float value = fp16_alt_to_fp32_value(fp16);
311 			uint32_t bits;
312 			memcpy(&bits, &value, sizeof(bits));
313 			EXPECT_EQ(fp32, bits) <<
314 				std::hex << std::uppercase << std::setfill('0') <<
315 				"F16 = 0x" << std::setw(4) << fp16 << ", " <<
316 				"F32(F16) = 0x" << std::setw(8) << bits << ", " <<
317 				"F32 = 0x" << std::setw(8) << fp32;
318 		}
319 	}
320 }
321 
TEST(FP16_ALT_TO_FP32_VALUE,positive_denormalized_values)322 TEST(FP16_ALT_TO_FP32_VALUE, positive_denormalized_values) {
323 	for (uint16_t h = 0; h < 0x0400; h++) {
324 		const float value = fp16_alt_to_fp32_value(h);
325 		uint32_t bits;
326 		memcpy(&bits, &value, sizeof(bits));
327 		EXPECT_EQ(fp16::denormalizedValues[h], bits) <<
328 			std::hex << std::uppercase << std::setfill('0') <<
329 			"F16 = 0x" << std::setw(4) << h << ", " <<
330 			"F32(F16) = 0x" << std::setw(8) << bits << ", " <<
331 			"F32 = 0x" << std::setw(8) << fp16::denormalizedValues[h];
332 	}
333 }
334 
TEST(FP16_ALT_TO_FP32_VALUE,negative_denormalized_values)335 TEST(FP16_ALT_TO_FP32_VALUE, negative_denormalized_values) {
336 	for (uint16_t h = 0; h < 0x0400; h++) {
337 		const uint16_t fp16 = h ^ UINT16_C(0x8000);
338 		const uint32_t fp32 = fp16::denormalizedValues[h] ^ UINT32_C(0x80000000);
339 		const float value = fp16_alt_to_fp32_value(fp16);
340 		uint32_t bits;
341 		memcpy(&bits, &value, sizeof(bits));
342 		EXPECT_EQ(fp32, bits) <<
343 			std::hex << std::uppercase << std::setfill('0') <<
344 			"F16 = 0x" << std::setw(4) << fp16 << ", " <<
345 			"F32(F16) = 0x" << std::setw(8) << bits << ", " <<
346 			"F32 = 0x" << std::setw(8) << fp32;
347 	}
348 }
349