xref: /aosp_15_r20/external/FP16/test/ieee-from-fp32-value.cc (revision 5f32b7105932ea8520a0e8811c640f936367d707)
1*5f32b710SXin Li #include <gtest/gtest.h>
2*5f32b710SXin Li 
3*5f32b710SXin Li #include <cstdint>
4*5f32b710SXin Li 
5*5f32b710SXin Li #include <fp16.h>
6*5f32b710SXin Li #include "tables.h"
7*5f32b710SXin Li 
8*5f32b710SXin Li #if (defined(__i386__) || defined(__x86_64__)) && defined(__F16C__)
9*5f32b710SXin Li 	#include <x86intrin.h>
10*5f32b710SXin Li #endif
11*5f32b710SXin Li 
12*5f32b710SXin Li 
TEST(FP16_IEEE_FROM_FP32_VALUE,normalized_powers_of_2)13*5f32b710SXin Li TEST(FP16_IEEE_FROM_FP32_VALUE, normalized_powers_of_2) {
14*5f32b710SXin Li 	const uint16_t min_po2_f16   = UINT16_C(0x0400);
15*5f32b710SXin Li 	const uint16_t eighths_f16   = UINT16_C(0x3000);
16*5f32b710SXin Li 	const uint16_t quarter_f16   = UINT16_C(0x3400);
17*5f32b710SXin Li 	const uint16_t half_f16      = UINT16_C(0x3800);
18*5f32b710SXin Li 	const uint16_t one_f16       = UINT16_C(0x3C00);
19*5f32b710SXin Li 	const uint16_t two_f16       = UINT16_C(0x4000);
20*5f32b710SXin Li 	const uint16_t four_f16      = UINT16_C(0x4400);
21*5f32b710SXin Li 	const uint16_t eight_f16     = UINT16_C(0x4800);
22*5f32b710SXin Li 	const uint16_t sixteen_f16   = UINT16_C(0x4C00);
23*5f32b710SXin Li 	const uint16_t thirtytwo_f16 = UINT16_C(0x5000);
24*5f32b710SXin Li 	const uint16_t sixtyfour_f16 = UINT16_C(0x5400);
25*5f32b710SXin Li 	const uint16_t max_po2_f16   = UINT16_C(0x7800);
26*5f32b710SXin Li 
27*5f32b710SXin Li 	const uint32_t min_po2_f32   = UINT32_C(0x38800000);
28*5f32b710SXin Li 	const uint32_t eighths_f32   = UINT32_C(0x3E000000);
29*5f32b710SXin Li 	const uint32_t quarter_f32   = UINT32_C(0x3E800000);
30*5f32b710SXin Li 	const uint32_t half_f32      = UINT32_C(0x3F000000);
31*5f32b710SXin Li 	const uint32_t one_f32       = UINT32_C(0x3F800000);
32*5f32b710SXin Li 	const uint32_t two_f32       = UINT32_C(0x40000000);
33*5f32b710SXin Li 	const uint32_t four_f32      = UINT32_C(0x40800000);
34*5f32b710SXin Li 	const uint32_t eight_f32     = UINT32_C(0x41000000);
35*5f32b710SXin Li 	const uint32_t sixteen_f32   = UINT32_C(0x41800000);
36*5f32b710SXin Li 	const uint32_t thirtytwo_f32 = UINT32_C(0x42000000);
37*5f32b710SXin Li 	const uint32_t sixtyfour_f32 = UINT32_C(0x42800000);
38*5f32b710SXin Li 	const uint32_t max_po2_f32   = UINT32_C(0x47000000);
39*5f32b710SXin Li 
40*5f32b710SXin Li 	float min_po2_value;
41*5f32b710SXin Li 	memcpy(&min_po2_value, &min_po2_f32, sizeof(min_po2_value));
42*5f32b710SXin Li 	EXPECT_EQ(min_po2_f16, fp16_ieee_from_fp32_value(min_po2_value)) <<
43*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
44*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << min_po2_f32 << ", " <<
45*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(min_po2_value) << ", " <<
46*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << min_po2_f16;
47*5f32b710SXin Li 
48*5f32b710SXin Li 	float eighths_value;
49*5f32b710SXin Li 	memcpy(&eighths_value, &eighths_f32, sizeof(eighths_value));
50*5f32b710SXin Li 	EXPECT_EQ(eighths_f16, fp16_ieee_from_fp32_value(eighths_value)) <<
51*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
52*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << eighths_f32 << ", " <<
53*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(eighths_value) << ", " <<
54*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << eighths_f16;
55*5f32b710SXin Li 
56*5f32b710SXin Li 	float quarter_value;
57*5f32b710SXin Li 	memcpy(&quarter_value, &quarter_f32, sizeof(quarter_value));
58*5f32b710SXin Li 	EXPECT_EQ(quarter_f16, fp16_ieee_from_fp32_value(quarter_value)) <<
59*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
60*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << quarter_f32 << ", " <<
61*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(quarter_value) << ", " <<
62*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << quarter_f16;
63*5f32b710SXin Li 
64*5f32b710SXin Li 	float half_value;
65*5f32b710SXin Li 	memcpy(&half_value, &half_f32, sizeof(half_value));
66*5f32b710SXin Li 	EXPECT_EQ(half_f16, fp16_ieee_from_fp32_value(half_value)) <<
67*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
68*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << half_f32 << ", " <<
69*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(half_value) << ", " <<
70*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << half_f16;
71*5f32b710SXin Li 
72*5f32b710SXin Li 	float one_value;
73*5f32b710SXin Li 	memcpy(&one_value, &one_f32, sizeof(one_value));
74*5f32b710SXin Li 	EXPECT_EQ(one_f16, fp16_ieee_from_fp32_value(one_value)) <<
75*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
76*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << one_f32 << ", " <<
77*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(one_value) << ", " <<
78*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << one_f16;
79*5f32b710SXin Li 
80*5f32b710SXin Li 	float two_value;
81*5f32b710SXin Li 	memcpy(&two_value, &two_f32, sizeof(two_value));
82*5f32b710SXin Li 	EXPECT_EQ(two_f16, fp16_ieee_from_fp32_value(two_value)) <<
83*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
84*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << two_f32 << ", " <<
85*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(two_value) << ", " <<
86*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << two_f16;
87*5f32b710SXin Li 
88*5f32b710SXin Li 	float four_value;
89*5f32b710SXin Li 	memcpy(&four_value, &four_f32, sizeof(four_value));
90*5f32b710SXin Li 	EXPECT_EQ(four_f16, fp16_ieee_from_fp32_value(four_value)) <<
91*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
92*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << four_f32 << ", " <<
93*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(four_value) << ", " <<
94*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << four_f16;
95*5f32b710SXin Li 
96*5f32b710SXin Li 	float eight_value;
97*5f32b710SXin Li 	memcpy(&eight_value, &eight_f32, sizeof(eight_value));
98*5f32b710SXin Li 	EXPECT_EQ(eight_f16, fp16_ieee_from_fp32_value(eight_value)) <<
99*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
100*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << eight_f32 << ", " <<
101*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(eight_value) << ", " <<
102*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << eight_f16;
103*5f32b710SXin Li 
104*5f32b710SXin Li 	float sixteen_value;
105*5f32b710SXin Li 	memcpy(&sixteen_value, &sixteen_f32, sizeof(sixteen_value));
106*5f32b710SXin Li 	EXPECT_EQ(sixteen_f16, fp16_ieee_from_fp32_value(sixteen_value)) <<
107*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
108*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << sixteen_f32 << ", " <<
109*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(sixteen_value) << ", " <<
110*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << sixteen_f16;
111*5f32b710SXin Li 
112*5f32b710SXin Li 	float thirtytwo_value;
113*5f32b710SXin Li 	memcpy(&thirtytwo_value, &thirtytwo_f32, sizeof(thirtytwo_value));
114*5f32b710SXin Li 	EXPECT_EQ(thirtytwo_f16, fp16_ieee_from_fp32_value(thirtytwo_value)) <<
115*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
116*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << thirtytwo_f32 << ", " <<
117*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(thirtytwo_value) << ", " <<
118*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << thirtytwo_f16;
119*5f32b710SXin Li 
120*5f32b710SXin Li 	float sixtyfour_value;
121*5f32b710SXin Li 	memcpy(&sixtyfour_value, &sixtyfour_f32, sizeof(sixtyfour_value));
122*5f32b710SXin Li 	EXPECT_EQ(sixtyfour_f16, fp16_ieee_from_fp32_value(sixtyfour_value)) <<
123*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
124*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << sixtyfour_f32 << ", " <<
125*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(sixtyfour_value) << ", " <<
126*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << sixtyfour_f16;
127*5f32b710SXin Li 
128*5f32b710SXin Li 	float max_po2_value;
129*5f32b710SXin Li 	memcpy(&max_po2_value, &max_po2_f32, sizeof(max_po2_value));
130*5f32b710SXin Li 	EXPECT_EQ(max_po2_f16, fp16_ieee_from_fp32_value(max_po2_value)) <<
131*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
132*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << max_po2_f32 << ", " <<
133*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(max_po2_value) << ", " <<
134*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << max_po2_f16;
135*5f32b710SXin Li }
136*5f32b710SXin Li 
TEST(FP16_IEEE_FROM_FP32_VALUE,denormalized_powers_of_2)137*5f32b710SXin Li TEST(FP16_IEEE_FROM_FP32_VALUE, denormalized_powers_of_2) {
138*5f32b710SXin Li 	const uint16_t exp2_minus_15_f16 = UINT16_C(0x0200);
139*5f32b710SXin Li 	const uint16_t exp2_minus_16_f16 = UINT16_C(0x0100);
140*5f32b710SXin Li 	const uint16_t exp2_minus_17_f16 = UINT16_C(0x0080);
141*5f32b710SXin Li 	const uint16_t exp2_minus_18_f16 = UINT16_C(0x0040);
142*5f32b710SXin Li 	const uint16_t exp2_minus_19_f16 = UINT16_C(0x0020);
143*5f32b710SXin Li 	const uint16_t exp2_minus_20_f16 = UINT16_C(0x0010);
144*5f32b710SXin Li 	const uint16_t exp2_minus_21_f16 = UINT16_C(0x0008);
145*5f32b710SXin Li 	const uint16_t exp2_minus_22_f16 = UINT16_C(0x0004);
146*5f32b710SXin Li 	const uint16_t exp2_minus_23_f16 = UINT16_C(0x0002);
147*5f32b710SXin Li 	const uint16_t exp2_minus_24_f16 = UINT16_C(0x0001);
148*5f32b710SXin Li 	const uint16_t exp2_minus_25_f16 = UINT16_C(0x0000);
149*5f32b710SXin Li 
150*5f32b710SXin Li 	const uint32_t exp2_minus_15_f32 = UINT32_C(0x38000000);
151*5f32b710SXin Li 	const uint32_t exp2_minus_16_f32 = UINT32_C(0x37800000);
152*5f32b710SXin Li 	const uint32_t exp2_minus_17_f32 = UINT32_C(0x37000000);
153*5f32b710SXin Li 	const uint32_t exp2_minus_18_f32 = UINT32_C(0x36800000);
154*5f32b710SXin Li 	const uint32_t exp2_minus_19_f32 = UINT32_C(0x36000000);
155*5f32b710SXin Li 	const uint32_t exp2_minus_20_f32 = UINT32_C(0x35800000);
156*5f32b710SXin Li 	const uint32_t exp2_minus_21_f32 = UINT32_C(0x35000000);
157*5f32b710SXin Li 	const uint32_t exp2_minus_22_f32 = UINT32_C(0x34800000);
158*5f32b710SXin Li 	const uint32_t exp2_minus_23_f32 = UINT32_C(0x34000000);
159*5f32b710SXin Li 	const uint32_t exp2_minus_24_f32 = UINT32_C(0x33800000);
160*5f32b710SXin Li 	const uint32_t exp2_minus_25_f32 = UINT32_C(0x33000000);
161*5f32b710SXin Li 
162*5f32b710SXin Li 	float exp2_minus_15_value;
163*5f32b710SXin Li 	memcpy(&exp2_minus_15_value, &exp2_minus_15_f32, sizeof(exp2_minus_15_value));
164*5f32b710SXin Li 	EXPECT_EQ(exp2_minus_15_f16, fp16_ieee_from_fp32_value(exp2_minus_15_value)) <<
165*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
166*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << exp2_minus_15_f32 << ", " <<
167*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(exp2_minus_15_value) << ", " <<
168*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << exp2_minus_15_f16;
169*5f32b710SXin Li 
170*5f32b710SXin Li 	float exp2_minus_16_value;
171*5f32b710SXin Li 	memcpy(&exp2_minus_16_value, &exp2_minus_16_f32, sizeof(exp2_minus_16_value));
172*5f32b710SXin Li 	EXPECT_EQ(exp2_minus_16_f16, fp16_ieee_from_fp32_value(exp2_minus_16_value)) <<
173*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
174*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << exp2_minus_16_f32 << ", " <<
175*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(exp2_minus_16_value) << ", " <<
176*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << exp2_minus_16_f16;
177*5f32b710SXin Li 
178*5f32b710SXin Li 	float exp2_minus_17_value;
179*5f32b710SXin Li 	memcpy(&exp2_minus_17_value, &exp2_minus_17_f32, sizeof(exp2_minus_17_value));
180*5f32b710SXin Li 	EXPECT_EQ(exp2_minus_17_f16, fp16_ieee_from_fp32_value(exp2_minus_17_value)) <<
181*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
182*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << exp2_minus_17_f32 << ", " <<
183*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(exp2_minus_17_value) << ", " <<
184*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << exp2_minus_17_f16;
185*5f32b710SXin Li 
186*5f32b710SXin Li 	float exp2_minus_18_value;
187*5f32b710SXin Li 	memcpy(&exp2_minus_18_value, &exp2_minus_18_f32, sizeof(exp2_minus_18_value));
188*5f32b710SXin Li 	EXPECT_EQ(exp2_minus_18_f16, fp16_ieee_from_fp32_value(exp2_minus_18_value)) <<
189*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
190*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << exp2_minus_18_f32 << ", " <<
191*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(exp2_minus_18_value) << ", " <<
192*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << exp2_minus_18_f16;
193*5f32b710SXin Li 
194*5f32b710SXin Li 	float exp2_minus_19_value;
195*5f32b710SXin Li 	memcpy(&exp2_minus_19_value, &exp2_minus_19_f32, sizeof(exp2_minus_19_value));
196*5f32b710SXin Li 	EXPECT_EQ(exp2_minus_19_f16, fp16_ieee_from_fp32_value(exp2_minus_19_value)) <<
197*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
198*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << exp2_minus_19_f32 << ", " <<
199*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(exp2_minus_19_value) << ", " <<
200*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << exp2_minus_19_f16;
201*5f32b710SXin Li 
202*5f32b710SXin Li 	float exp2_minus_20_value;
203*5f32b710SXin Li 	memcpy(&exp2_minus_20_value, &exp2_minus_20_f32, sizeof(exp2_minus_20_value));
204*5f32b710SXin Li 	EXPECT_EQ(exp2_minus_20_f16, fp16_ieee_from_fp32_value(exp2_minus_20_value)) <<
205*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
206*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << exp2_minus_20_f32 << ", " <<
207*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(exp2_minus_20_value) << ", " <<
208*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << exp2_minus_20_f16;
209*5f32b710SXin Li 
210*5f32b710SXin Li 	float exp2_minus_21_value;
211*5f32b710SXin Li 	memcpy(&exp2_minus_21_value, &exp2_minus_21_f32, sizeof(exp2_minus_21_value));
212*5f32b710SXin Li 	EXPECT_EQ(exp2_minus_21_f16, fp16_ieee_from_fp32_value(exp2_minus_21_value)) <<
213*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
214*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << exp2_minus_21_f32 << ", " <<
215*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(exp2_minus_21_value) << ", " <<
216*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << exp2_minus_21_f16;
217*5f32b710SXin Li 
218*5f32b710SXin Li 	float exp2_minus_22_value;
219*5f32b710SXin Li 	memcpy(&exp2_minus_22_value, &exp2_minus_22_f32, sizeof(exp2_minus_22_value));
220*5f32b710SXin Li 	EXPECT_EQ(exp2_minus_22_f16, fp16_ieee_from_fp32_value(exp2_minus_22_value)) <<
221*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
222*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << exp2_minus_22_f32 << ", " <<
223*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(exp2_minus_22_value) << ", " <<
224*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << exp2_minus_22_f16;
225*5f32b710SXin Li 
226*5f32b710SXin Li 	float exp2_minus_23_value;
227*5f32b710SXin Li 	memcpy(&exp2_minus_23_value, &exp2_minus_23_f32, sizeof(exp2_minus_23_value));
228*5f32b710SXin Li 	EXPECT_EQ(exp2_minus_23_f16, fp16_ieee_from_fp32_value(exp2_minus_23_value)) <<
229*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
230*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << exp2_minus_23_f32 << ", " <<
231*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(exp2_minus_23_value) << ", " <<
232*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << exp2_minus_23_f16;
233*5f32b710SXin Li 
234*5f32b710SXin Li 	float exp2_minus_24_value;
235*5f32b710SXin Li 	memcpy(&exp2_minus_24_value, &exp2_minus_24_f32, sizeof(exp2_minus_24_value));
236*5f32b710SXin Li 	EXPECT_EQ(exp2_minus_24_f16, fp16_ieee_from_fp32_value(exp2_minus_24_value)) <<
237*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
238*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << exp2_minus_24_f32 << ", " <<
239*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(exp2_minus_24_value) << ", " <<
240*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << exp2_minus_24_f16;
241*5f32b710SXin Li 
242*5f32b710SXin Li 	float exp2_minus_25_value;
243*5f32b710SXin Li 	memcpy(&exp2_minus_25_value, &exp2_minus_25_f32, sizeof(exp2_minus_25_value));
244*5f32b710SXin Li 	EXPECT_EQ(exp2_minus_25_f16, fp16_ieee_from_fp32_value(exp2_minus_25_value)) <<
245*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
246*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << exp2_minus_25_f32 << ", " <<
247*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(exp2_minus_25_value) << ", " <<
248*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << exp2_minus_25_f16;
249*5f32b710SXin Li }
250*5f32b710SXin Li 
TEST(FP16_IEEE_FROM_FP32_VALUE,zero)251*5f32b710SXin Li TEST(FP16_IEEE_FROM_FP32_VALUE, zero) {
252*5f32b710SXin Li 	const uint16_t positive_zero_f16 = UINT16_C(0x0000);
253*5f32b710SXin Li 	const uint16_t negative_zero_f16 = UINT16_C(0x8000);
254*5f32b710SXin Li 
255*5f32b710SXin Li 	const uint32_t positive_zero_f32 = UINT32_C(0x00000000);
256*5f32b710SXin Li 	const uint32_t negative_zero_f32 = UINT32_C(0x80000000);
257*5f32b710SXin Li 
258*5f32b710SXin Li 	float positive_zero_value;
259*5f32b710SXin Li 	memcpy(&positive_zero_value, &positive_zero_f32, sizeof(positive_zero_value));
260*5f32b710SXin Li 	EXPECT_EQ(positive_zero_f16, fp16_ieee_from_fp32_value(positive_zero_value)) <<
261*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
262*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << positive_zero_f32 << ", " <<
263*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(positive_zero_value) << ", " <<
264*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << positive_zero_f16;
265*5f32b710SXin Li 
266*5f32b710SXin Li 	float negative_zero_value;
267*5f32b710SXin Li 	memcpy(&negative_zero_value, &negative_zero_f32, sizeof(negative_zero_value));
268*5f32b710SXin Li 	EXPECT_EQ(negative_zero_f16, fp16_ieee_from_fp32_value(negative_zero_value)) <<
269*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
270*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << negative_zero_f32 << ", " <<
271*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(negative_zero_value) << ", " <<
272*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << negative_zero_f16;
273*5f32b710SXin Li }
274*5f32b710SXin Li 
TEST(FP16_IEEE_FROM_FP32_VALUE,infinity)275*5f32b710SXin Li TEST(FP16_IEEE_FROM_FP32_VALUE, infinity) {
276*5f32b710SXin Li 	const uint16_t positive_infinity_f16 = UINT16_C(0x7C00);
277*5f32b710SXin Li 	const uint16_t negative_infinity_f16 = UINT16_C(0xFC00);
278*5f32b710SXin Li 
279*5f32b710SXin Li 	const uint32_t positive_infinity_f32 = UINT32_C(0x7F800000);
280*5f32b710SXin Li 	const uint32_t negative_infinity_f32 = UINT32_C(0xFF800000);
281*5f32b710SXin Li 
282*5f32b710SXin Li 	float positive_infinity_value;
283*5f32b710SXin Li 	memcpy(&positive_infinity_value, &positive_infinity_f32, sizeof(positive_infinity_value));
284*5f32b710SXin Li 	EXPECT_EQ(positive_infinity_f16, fp16_ieee_from_fp32_value(positive_infinity_value)) <<
285*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
286*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << positive_infinity_f32 << ", " <<
287*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(positive_infinity_value) << ", " <<
288*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << positive_infinity_f16;
289*5f32b710SXin Li 
290*5f32b710SXin Li 	float negative_infinity_value;
291*5f32b710SXin Li 	memcpy(&negative_infinity_value, &negative_infinity_f32, sizeof(negative_infinity_value));
292*5f32b710SXin Li 	EXPECT_EQ(negative_infinity_f16, fp16_ieee_from_fp32_value(negative_infinity_value)) <<
293*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
294*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << negative_infinity_f32 << ", " <<
295*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(negative_infinity_value) << ", " <<
296*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << negative_infinity_f16;
297*5f32b710SXin Li }
298*5f32b710SXin Li 
TEST(FP16_IEEE_FROM_FP32_VALUE,positive_nan)299*5f32b710SXin Li TEST(FP16_IEEE_FROM_FP32_VALUE, positive_nan) {
300*5f32b710SXin Li 	for (uint32_t nan_f32 = UINT32_C(0x7FFFFFFF); nan_f32 > UINT32_C(0x7F800000); nan_f32--) {
301*5f32b710SXin Li 		float nan_value;
302*5f32b710SXin Li 		memcpy(&nan_value, &nan_f32, sizeof(nan_value));
303*5f32b710SXin Li 		const uint16_t nan_f16 = fp16_ieee_from_fp32_value(nan_value);
304*5f32b710SXin Li 
305*5f32b710SXin Li 		/* Check sign */
306*5f32b710SXin Li 		ASSERT_EQ(nan_f16 & UINT16_C(0x8000), 0) <<
307*5f32b710SXin Li 			std::hex << std::uppercase << std::setfill('0') <<
308*5f32b710SXin Li 			"F32 = 0x" << std::setw(8) << nan_f32 << ", " <<
309*5f32b710SXin Li 			"F16(F32) = 0x" << std::setw(4) << nan_f16;
310*5f32b710SXin Li 
311*5f32b710SXin Li 		/* Check exponent */
312*5f32b710SXin Li 		ASSERT_EQ(nan_f16 & UINT16_C(0x7C00), UINT16_C(0x7C00)) <<
313*5f32b710SXin Li 			std::hex << std::uppercase << std::setfill('0') <<
314*5f32b710SXin Li 			"F32 = 0x" << std::setw(8) << nan_f32 << ", " <<
315*5f32b710SXin Li 			"F16(F32) = 0x" << std::setw(4) << nan_f16;
316*5f32b710SXin Li 
317*5f32b710SXin Li 		/* Check mantissa */
318*5f32b710SXin Li 		ASSERT_NE(nan_f16 & UINT16_C(0x03FF), 0) <<
319*5f32b710SXin Li 			std::hex << std::uppercase << std::setfill('0') <<
320*5f32b710SXin Li 			"F32 = 0x" << std::setw(8) << nan_f32 << ", " <<
321*5f32b710SXin Li 			"F16(F32) = 0x" << std::setw(4) << nan_f16;
322*5f32b710SXin Li 	}
323*5f32b710SXin Li }
324*5f32b710SXin Li 
TEST(FP16_IEEE_FROM_FP32_VALUE,negative_nan)325*5f32b710SXin Li TEST(FP16_IEEE_FROM_FP32_VALUE, negative_nan) {
326*5f32b710SXin Li 	for (uint32_t nan_f32 = UINT32_C(0xFFFFFFFF); nan_f32 > UINT32_C(0xFF800000); nan_f32--) {
327*5f32b710SXin Li 		float nan_value;
328*5f32b710SXin Li 		memcpy(&nan_value, &nan_f32, sizeof(nan_value));
329*5f32b710SXin Li 		const uint16_t nan_f16 = fp16_ieee_from_fp32_value(nan_value);
330*5f32b710SXin Li 
331*5f32b710SXin Li 		/* Check sign */
332*5f32b710SXin Li 		ASSERT_EQ(nan_f16 & UINT16_C(0x8000), UINT16_C(0x8000)) <<
333*5f32b710SXin Li 			std::hex << std::uppercase << std::setfill('0') <<
334*5f32b710SXin Li 			"F32 = 0x" << std::setw(8) << nan_f32 << ", " <<
335*5f32b710SXin Li 			"F16(F32) = 0x" << std::setw(4) << nan_f16;
336*5f32b710SXin Li 
337*5f32b710SXin Li 		/* Check exponent */
338*5f32b710SXin Li 		ASSERT_EQ(nan_f16 & UINT16_C(0x7C00), UINT16_C(0x7C00)) <<
339*5f32b710SXin Li 			std::hex << std::uppercase << std::setfill('0') <<
340*5f32b710SXin Li 			"F32 = 0x" << std::setw(8) << nan_f32 << ", " <<
341*5f32b710SXin Li 			"F16(F32) = 0x" << std::setw(4) << nan_f16;
342*5f32b710SXin Li 
343*5f32b710SXin Li 		/* Check mantissa */
344*5f32b710SXin Li 		ASSERT_NE(nan_f16 & UINT16_C(0x03FF), 0) <<
345*5f32b710SXin Li 			std::hex << std::uppercase << std::setfill('0') <<
346*5f32b710SXin Li 			"F32 = 0x" << std::setw(8) << nan_f32 << ", " <<
347*5f32b710SXin Li 			"F16(F32) = 0x" << std::setw(4) << nan_f16;
348*5f32b710SXin Li 	}
349*5f32b710SXin Li }
350*5f32b710SXin Li 
TEST(FP16_IEEE_FROM_FP32_VALUE,revertible)351*5f32b710SXin Li TEST(FP16_IEEE_FROM_FP32_VALUE, revertible) {
352*5f32b710SXin Li 	/* Positive values */
353*5f32b710SXin Li 	for (uint16_t f16 = UINT16_C(0x0000); f16 < UINT16_C(0x7C00); f16++) {
354*5f32b710SXin Li 		const float value_f32 = fp16_ieee_to_fp32_value(f16);
355*5f32b710SXin Li 		uint32_t bits_f32;
356*5f32b710SXin Li 		memcpy(&bits_f32, &value_f32, sizeof(bits_f32));
357*5f32b710SXin Li 
358*5f32b710SXin Li 		ASSERT_EQ(f16, fp16_ieee_from_fp32_value(value_f32)) <<
359*5f32b710SXin Li 			std::hex << std::uppercase << std::setfill('0') <<
360*5f32b710SXin Li 			"F16 = 0x" << std::setw(4) << f16 << ", " <<
361*5f32b710SXin Li 			"F32(F16) = 0x" << std::setw(8) << bits_f32 << ", " <<
362*5f32b710SXin Li 			"F16(F32(F16)) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(value_f32);
363*5f32b710SXin Li 	}
364*5f32b710SXin Li 
365*5f32b710SXin Li 	/* Negative values */
366*5f32b710SXin Li 	for (uint16_t f16 = UINT16_C(0x8000); f16 < UINT16_C(0xFC00); f16++) {
367*5f32b710SXin Li 		const float value_f32 = fp16_ieee_to_fp32_value(f16);
368*5f32b710SXin Li 		uint32_t bits_f32;
369*5f32b710SXin Li 		memcpy(&bits_f32, &value_f32, sizeof(bits_f32));
370*5f32b710SXin Li 
371*5f32b710SXin Li 		ASSERT_EQ(f16, fp16_ieee_from_fp32_value(value_f32)) <<
372*5f32b710SXin Li 			std::hex << std::uppercase << std::setfill('0') <<
373*5f32b710SXin Li 			"F16 = 0x" << std::setw(4) << f16 << ", " <<
374*5f32b710SXin Li 			"F32(F16) = 0x" << std::setw(8) << bits_f32 << ", " <<
375*5f32b710SXin Li 			"F16(F32(F16)) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(value_f32);
376*5f32b710SXin Li 	}
377*5f32b710SXin Li }
378*5f32b710SXin Li 
TEST(FP16_IEEE_FROM_FP32_VALUE,underflow)379*5f32b710SXin Li TEST(FP16_IEEE_FROM_FP32_VALUE, underflow) {
380*5f32b710SXin Li 	const uint32_t min_nonzero_f32 = UINT32_C(0x33000001);
381*5f32b710SXin Li 	const uint16_t zero_f16 = UINT16_C(0x0000);
382*5f32b710SXin Li 	const uint16_t min_f16 = UINT16_C(0x0001);
383*5f32b710SXin Li 	for (uint32_t bits = UINT32_C(0x00000001); bits < min_nonzero_f32; bits++) {
384*5f32b710SXin Li 		float value;
385*5f32b710SXin Li 		memcpy(&value, &bits, sizeof(value));
386*5f32b710SXin Li 		ASSERT_EQ(zero_f16, fp16_ieee_from_fp32_value(value)) <<
387*5f32b710SXin Li 			std::hex << std::uppercase << std::setfill('0') <<
388*5f32b710SXin Li 			"F32 = 0x" << std::setw(8) << bits << ", " <<
389*5f32b710SXin Li 			"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(value) << ", " <<
390*5f32b710SXin Li 			"F16 = 0x" << std::setw(4) << zero_f16;
391*5f32b710SXin Li 	}
392*5f32b710SXin Li 	float min_nonzero_value;
393*5f32b710SXin Li 	memcpy(&min_nonzero_value, &min_nonzero_f32, sizeof(min_nonzero_value));
394*5f32b710SXin Li 	ASSERT_EQ(min_f16, fp16_ieee_from_fp32_value(min_nonzero_value)) <<
395*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
396*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << min_nonzero_f32 << ", " <<
397*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(min_nonzero_value) << ", " <<
398*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << min_f16;
399*5f32b710SXin Li }
400*5f32b710SXin Li 
TEST(FP16_IEEE_FROM_FP32_VALUE,overflow)401*5f32b710SXin Li TEST(FP16_IEEE_FROM_FP32_VALUE, overflow) {
402*5f32b710SXin Li 	const uint32_t max_finite_f32 = UINT32_C(0x477FEFFF);
403*5f32b710SXin Li 	const uint16_t max_finite_f16 = UINT16_C(0x7BFF);
404*5f32b710SXin Li 	const uint32_t positive_infinity_f32 = UINT32_C(0x7F800000);
405*5f32b710SXin Li 	const uint16_t positive_infinity_f16 = UINT16_C(0x7C00);
406*5f32b710SXin Li 	for (uint32_t bits = positive_infinity_f32; bits > max_finite_f32; bits--) {
407*5f32b710SXin Li 		float value;
408*5f32b710SXin Li 		memcpy(&value, &bits, sizeof(value));
409*5f32b710SXin Li 		ASSERT_EQ(positive_infinity_f16, fp16_ieee_from_fp32_value(value)) <<
410*5f32b710SXin Li 			std::hex << std::uppercase << std::setfill('0') <<
411*5f32b710SXin Li 			"F32 = 0x" << std::setw(8) << bits << ", " <<
412*5f32b710SXin Li 			"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(value) << ", " <<
413*5f32b710SXin Li 			"F16 = 0x" << std::setw(4) << positive_infinity_f16;
414*5f32b710SXin Li 	}
415*5f32b710SXin Li 	float max_finite_value;
416*5f32b710SXin Li 	memcpy(&max_finite_value, &max_finite_f32, sizeof(max_finite_value));
417*5f32b710SXin Li 	ASSERT_EQ(max_finite_f16, fp16_ieee_from_fp32_value(max_finite_value)) <<
418*5f32b710SXin Li 		std::hex << std::uppercase << std::setfill('0') <<
419*5f32b710SXin Li 		"F32 = 0x" << std::setw(8) << max_finite_f32 << ", " <<
420*5f32b710SXin Li 		"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(max_finite_value) << ", " <<
421*5f32b710SXin Li 		"F16 = 0x" << std::setw(4) << max_finite_f16;
422*5f32b710SXin Li }
423*5f32b710SXin Li 
TEST(FP16_IEEE_FROM_FP32_VALUE,positive_denormalized_values)424*5f32b710SXin Li TEST(FP16_IEEE_FROM_FP32_VALUE, positive_denormalized_values) {
425*5f32b710SXin Li 	const uint32_t min_nonzero_f32 = UINT32_C(0x33000001);
426*5f32b710SXin Li 
427*5f32b710SXin Li 	uint32_t f32_begin = min_nonzero_f32;
428*5f32b710SXin Li 	for (uint16_t f16 = 0; f16 < UINT16_C(0x0400); f16++) {
429*5f32b710SXin Li 		const uint32_t f32_end = fp16::denormalizedRanges[f16];
430*5f32b710SXin Li 		for (uint32_t f32 = f32_begin; f32 < f32_end; f32++) {
431*5f32b710SXin Li 			float value;
432*5f32b710SXin Li 			memcpy(&value, &f32, sizeof(value));
433*5f32b710SXin Li 			ASSERT_EQ(f16, fp16_ieee_from_fp32_value(value)) <<
434*5f32b710SXin Li 				std::hex << std::uppercase << std::setfill('0') <<
435*5f32b710SXin Li 				"F32 = 0x" << std::setw(8) << f32 << ", " <<
436*5f32b710SXin Li 				"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(value) << ", " <<
437*5f32b710SXin Li 				"F16 = 0x" << std::setw(4) << f16;
438*5f32b710SXin Li 		}
439*5f32b710SXin Li 		f32_begin = f32_end;
440*5f32b710SXin Li 	}
441*5f32b710SXin Li }
442*5f32b710SXin Li 
TEST(FP16_IEEE_FROM_FP32_VALUE,negative_denormalized_values)443*5f32b710SXin Li TEST(FP16_IEEE_FROM_FP32_VALUE, negative_denormalized_values) {
444*5f32b710SXin Li 	const uint32_t min_nonzero_f32 = UINT32_C(0x33000001);
445*5f32b710SXin Li 
446*5f32b710SXin Li 	uint32_t f32_begin = min_nonzero_f32 | UINT32_C(0x80000000);
447*5f32b710SXin Li 	for (uint16_t f16 = UINT16_C(0x8000); f16 < UINT16_C(0x8400); f16++) {
448*5f32b710SXin Li 		const uint32_t f32_end = fp16::denormalizedRanges[f16 & UINT16_C(0x7FFF)] | UINT32_C(0x80000000);
449*5f32b710SXin Li 		for (uint32_t f32 = f32_begin; f32 < f32_end; f32++) {
450*5f32b710SXin Li 			float value;
451*5f32b710SXin Li 			memcpy(&value, &f32, sizeof(value));
452*5f32b710SXin Li 			ASSERT_EQ(f16, fp16_ieee_from_fp32_value(value)) <<
453*5f32b710SXin Li 				std::hex << std::uppercase << std::setfill('0') <<
454*5f32b710SXin Li 				"F32 = 0x" << std::setw(8) << f32 << ", " <<
455*5f32b710SXin Li 				"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(value) << ", " <<
456*5f32b710SXin Li 				"F16 = 0x" << std::setw(4) << f16;
457*5f32b710SXin Li 		}
458*5f32b710SXin Li 		f32_begin = f32_end;
459*5f32b710SXin Li 	}
460*5f32b710SXin Li }
461*5f32b710SXin Li 
TEST(FP16_IEEE_FROM_FP32_VALUE,positive_normalized_values)462*5f32b710SXin Li TEST(FP16_IEEE_FROM_FP32_VALUE, positive_normalized_values) {
463*5f32b710SXin Li 	/* Minimum number that rounds to 1.0h when converted to half-precision */
464*5f32b710SXin Li 	const uint32_t min_one_f32 = UINT32_C(0x3F7FF000);
465*5f32b710SXin Li 	const uint32_t e_bias = 15;
466*5f32b710SXin Li 
467*5f32b710SXin Li 	for (int32_t e = -14; e <= 15; e++) {
468*5f32b710SXin Li 		uint32_t f32_begin = min_one_f32 + (uint32_t(e) << 23);
469*5f32b710SXin Li 		for (uint16_t f16 = uint16_t(e + e_bias) << 10; f16 < uint16_t(e + e_bias + 1) << 10; f16++) {
470*5f32b710SXin Li 			const uint32_t f32_end = fp16::normalizedRanges[f16 & UINT16_C(0x3FF)] + (uint32_t(e) << 23);
471*5f32b710SXin Li 			for (uint32_t f32 = f32_begin; f32 < f32_end; f32++) {
472*5f32b710SXin Li 				float value;
473*5f32b710SXin Li 				memcpy(&value, &f32, sizeof(value));
474*5f32b710SXin Li 				ASSERT_EQ(f16, fp16_ieee_from_fp32_value(value)) <<
475*5f32b710SXin Li 					std::hex << std::uppercase << std::setfill('0') <<
476*5f32b710SXin Li 					"F32 = 0x" << std::setw(8) << f32 << ", " <<
477*5f32b710SXin Li 					"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(value) << ", " <<
478*5f32b710SXin Li 					"F16 = 0x" << std::setw(4) << f16;
479*5f32b710SXin Li 			}
480*5f32b710SXin Li 			f32_begin = f32_end;
481*5f32b710SXin Li 		}
482*5f32b710SXin Li 	}
483*5f32b710SXin Li }
484*5f32b710SXin Li 
TEST(FP16_IEEE_FROM_FP32_VALUE,negative_normalized_values)485*5f32b710SXin Li TEST(FP16_IEEE_FROM_FP32_VALUE, negative_normalized_values) {
486*5f32b710SXin Li 	/* Minimum number that rounds to 1.0h when converted to half-precision */
487*5f32b710SXin Li 	const uint32_t min_one_f32 = UINT32_C(0x3F7FF000);
488*5f32b710SXin Li 	const uint32_t e_bias = 15;
489*5f32b710SXin Li 
490*5f32b710SXin Li 	for (int32_t e = -14; e <= 15; e++) {
491*5f32b710SXin Li 		uint32_t f32_begin = (min_one_f32 | UINT32_C(0x80000000)) + (uint32_t(e) << 23);
492*5f32b710SXin Li 		for (uint16_t f16 = (UINT16_C(0x8000) | (uint16_t(e + e_bias) << 10)); f16 < (UINT16_C(0x8000) | (uint16_t(e + e_bias + 1) << 10)); f16++) {
493*5f32b710SXin Li 			const uint32_t f32_end = (fp16::normalizedRanges[f16 & UINT16_C(0x3FF)] | UINT32_C(0x80000000)) + (uint32_t(e) << 23);
494*5f32b710SXin Li 			for (uint32_t f32 = f32_begin; f32 < f32_end; f32++) {
495*5f32b710SXin Li 				float value;
496*5f32b710SXin Li 				memcpy(&value, &f32, sizeof(value));
497*5f32b710SXin Li 				ASSERT_EQ(f16, fp16_ieee_from_fp32_value(value)) <<
498*5f32b710SXin Li 					std::hex << std::uppercase << std::setfill('0') <<
499*5f32b710SXin Li 					"F32 = 0x" << std::setw(8) << f32 << ", " <<
500*5f32b710SXin Li 					"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(value) << ", " <<
501*5f32b710SXin Li 					"F16 = 0x" << std::setw(4) << f16;
502*5f32b710SXin Li 			}
503*5f32b710SXin Li 			f32_begin = f32_end;
504*5f32b710SXin Li 		}
505*5f32b710SXin Li 	}
506*5f32b710SXin Li }
507*5f32b710SXin Li 
508*5f32b710SXin Li #if (defined(__i386__) || defined(__x86_64__)) && defined(__F16C__)
TEST(FP16_IEEE_FROM_FP32_VALUE,match_hardware)509*5f32b710SXin Li 	TEST(FP16_IEEE_FROM_FP32_VALUE, match_hardware) {
510*5f32b710SXin Li 		const uint32_t min_nonzero = UINT32_C(0x00000001);
511*5f32b710SXin Li 		const uint32_t max_finite = UINT32_C(0x7F800000);
512*5f32b710SXin Li 		for (uint32_t bits = min_nonzero; bits < max_finite; bits++) {
513*5f32b710SXin Li 			float value;
514*5f32b710SXin Li 			memcpy(&value, &bits, sizeof(value));
515*5f32b710SXin Li 			const uint16_t reference = uint16_t(_mm_cvtsi128_si32(_mm_cvtps_ph(_mm_set_ss(value), _MM_FROUND_CUR_DIRECTION)));
516*5f32b710SXin Li 			ASSERT_EQ(reference, fp16_ieee_from_fp32_value(value)) <<
517*5f32b710SXin Li 				std::hex << std::uppercase << std::setfill('0') <<
518*5f32b710SXin Li 				"F32 = 0x" << std::setw(8) << bits << ", " <<
519*5f32b710SXin Li 				"F16(F32) = 0x" << std::setw(4) << fp16_ieee_from_fp32_value(value) << ", " <<
520*5f32b710SXin Li 				"F16 = 0x" << std::setw(4) << reference;
521*5f32b710SXin Li 		}
522*5f32b710SXin Li 	}
523*5f32b710SXin Li #endif
524