1*5f32b710SXin Li #include <gtest/gtest.h>
2*5f32b710SXin Li
3*5f32b710SXin Li #include <cstdint>
4*5f32b710SXin Li #include <cmath>
5*5f32b710SXin Li
6*5f32b710SXin Li #include <fp16.h>
7*5f32b710SXin Li #include "tables.h"
8*5f32b710SXin Li
9*5f32b710SXin Li
TEST(FP16_IEEE_TO_FP32_VALUE,normalized_powers_of_2)10*5f32b710SXin Li TEST(FP16_IEEE_TO_FP32_VALUE, normalized_powers_of_2) {
11*5f32b710SXin Li const uint16_t min_po2_f16 = UINT16_C(0x0400);
12*5f32b710SXin Li const uint16_t eighths_f16 = UINT16_C(0x3000);
13*5f32b710SXin Li const uint16_t quarter_f16 = UINT16_C(0x3400);
14*5f32b710SXin Li const uint16_t half_f16 = UINT16_C(0x3800);
15*5f32b710SXin Li const uint16_t one_f16 = UINT16_C(0x3C00);
16*5f32b710SXin Li const uint16_t two_f16 = UINT16_C(0x4000);
17*5f32b710SXin Li const uint16_t four_f16 = UINT16_C(0x4400);
18*5f32b710SXin Li const uint16_t eight_f16 = UINT16_C(0x4800);
19*5f32b710SXin Li const uint16_t sixteen_f16 = UINT16_C(0x4C00);
20*5f32b710SXin Li const uint16_t thirtytwo_f16 = UINT16_C(0x5000);
21*5f32b710SXin Li const uint16_t sixtyfour_f16 = UINT16_C(0x5400);
22*5f32b710SXin Li const uint16_t max_po2_f16 = UINT16_C(0x7800);
23*5f32b710SXin Li
24*5f32b710SXin Li const uint32_t min_po2_f32 = UINT32_C(0x38800000);
25*5f32b710SXin Li const uint32_t eighths_f32 = UINT32_C(0x3E000000);
26*5f32b710SXin Li const uint32_t quarter_f32 = UINT32_C(0x3E800000);
27*5f32b710SXin Li const uint32_t half_f32 = UINT32_C(0x3F000000);
28*5f32b710SXin Li const uint32_t one_f32 = UINT32_C(0x3F800000);
29*5f32b710SXin Li const uint32_t two_f32 = UINT32_C(0x40000000);
30*5f32b710SXin Li const uint32_t four_f32 = UINT32_C(0x40800000);
31*5f32b710SXin Li const uint32_t eight_f32 = UINT32_C(0x41000000);
32*5f32b710SXin Li const uint32_t sixteen_f32 = UINT32_C(0x41800000);
33*5f32b710SXin Li const uint32_t thirtytwo_f32 = UINT32_C(0x42000000);
34*5f32b710SXin Li const uint32_t sixtyfour_f32 = UINT32_C(0x42800000);
35*5f32b710SXin Li const uint32_t max_po2_f32 = UINT32_C(0x47000000);
36*5f32b710SXin Li
37*5f32b710SXin Li const float min_po2_value = fp16_ieee_to_fp32_value(min_po2_f16);
38*5f32b710SXin Li uint32_t min_po2_bits;
39*5f32b710SXin Li memcpy(&min_po2_bits, &min_po2_value, sizeof(min_po2_bits));
40*5f32b710SXin Li EXPECT_EQ(min_po2_f32, min_po2_bits) <<
41*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
42*5f32b710SXin Li "F16 = 0x" << std::setw(4) << min_po2_f16 << ", " <<
43*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << min_po2_bits << ", " <<
44*5f32b710SXin Li "F32 = 0x" << std::setw(8) << min_po2_f32;
45*5f32b710SXin Li
46*5f32b710SXin Li const float eighths_value = fp16_ieee_to_fp32_value(eighths_f16);
47*5f32b710SXin Li uint32_t eighths_bits;
48*5f32b710SXin Li memcpy(&eighths_bits, &eighths_value, sizeof(eighths_bits));
49*5f32b710SXin Li EXPECT_EQ(eighths_f32, eighths_bits) <<
50*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
51*5f32b710SXin Li "F16 = 0x" << std::setw(4) << eighths_f16 << ", " <<
52*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << eighths_bits << ", " <<
53*5f32b710SXin Li "F32 = 0x" << std::setw(8) << eighths_f32;
54*5f32b710SXin Li
55*5f32b710SXin Li const float quarter_value = fp16_ieee_to_fp32_value(quarter_f16);
56*5f32b710SXin Li uint32_t quarter_bits;
57*5f32b710SXin Li memcpy(&quarter_bits, &quarter_value, sizeof(quarter_bits));
58*5f32b710SXin Li EXPECT_EQ(quarter_f32, quarter_bits) <<
59*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
60*5f32b710SXin Li "F16 = 0x" << std::setw(4) << quarter_f16 << ", " <<
61*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << quarter_bits << ", " <<
62*5f32b710SXin Li "F32 = 0x" << std::setw(8) << quarter_f32;
63*5f32b710SXin Li
64*5f32b710SXin Li const float half_value = fp16_ieee_to_fp32_value(half_f16);
65*5f32b710SXin Li uint32_t half_bits;
66*5f32b710SXin Li memcpy(&half_bits, &half_value, sizeof(half_bits));
67*5f32b710SXin Li EXPECT_EQ(half_f32, half_bits) <<
68*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
69*5f32b710SXin Li "F16 = 0x" << std::setw(4) << half_f16 << ", " <<
70*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << half_bits << ", " <<
71*5f32b710SXin Li "F32 = 0x" << std::setw(8) << half_f32;
72*5f32b710SXin Li
73*5f32b710SXin Li const float one_value = fp16_ieee_to_fp32_value(one_f16);
74*5f32b710SXin Li uint32_t one_bits;
75*5f32b710SXin Li memcpy(&one_bits, &one_value, sizeof(one_bits));
76*5f32b710SXin Li EXPECT_EQ(one_f32, one_bits) <<
77*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
78*5f32b710SXin Li "F16 = 0x" << std::setw(4) << one_f16 << ", " <<
79*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << one_bits << ", " <<
80*5f32b710SXin Li "F32 = 0x" << std::setw(8) << one_f32;
81*5f32b710SXin Li
82*5f32b710SXin Li const float two_value = fp16_ieee_to_fp32_value(two_f16);
83*5f32b710SXin Li uint32_t two_bits;
84*5f32b710SXin Li memcpy(&two_bits, &two_value, sizeof(two_bits));
85*5f32b710SXin Li EXPECT_EQ(two_f32, two_bits) <<
86*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
87*5f32b710SXin Li "F16 = 0x" << std::setw(4) << two_f16 << ", " <<
88*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << two_bits << ", " <<
89*5f32b710SXin Li "F32 = 0x" << std::setw(8) << two_f32;
90*5f32b710SXin Li
91*5f32b710SXin Li const float four_value = fp16_ieee_to_fp32_value(four_f16);
92*5f32b710SXin Li uint32_t four_bits;
93*5f32b710SXin Li memcpy(&four_bits, &four_value, sizeof(four_bits));
94*5f32b710SXin Li EXPECT_EQ(four_f32, four_bits) <<
95*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
96*5f32b710SXin Li "F16 = 0x" << std::setw(4) << four_f16 << ", " <<
97*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << four_bits << ", " <<
98*5f32b710SXin Li "F32 = 0x" << std::setw(8) << four_f32;
99*5f32b710SXin Li
100*5f32b710SXin Li const float eight_value = fp16_ieee_to_fp32_value(eight_f16);
101*5f32b710SXin Li uint32_t eight_bits;
102*5f32b710SXin Li memcpy(&eight_bits, &eight_value, sizeof(eight_bits));
103*5f32b710SXin Li EXPECT_EQ(eight_f32, eight_bits) <<
104*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
105*5f32b710SXin Li "F16 = 0x" << std::setw(4) << eight_f16 << ", " <<
106*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << eight_bits << ", " <<
107*5f32b710SXin Li "F32 = 0x" << std::setw(8) << eight_f32;
108*5f32b710SXin Li
109*5f32b710SXin Li const float sixteen_value = fp16_ieee_to_fp32_value(sixteen_f16);
110*5f32b710SXin Li uint32_t sixteen_bits;
111*5f32b710SXin Li memcpy(&sixteen_bits, &sixteen_value, sizeof(sixteen_bits));
112*5f32b710SXin Li EXPECT_EQ(sixteen_f32, sixteen_bits) <<
113*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
114*5f32b710SXin Li "F16 = 0x" << std::setw(4) << sixteen_f16 << ", " <<
115*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << sixteen_bits << ", " <<
116*5f32b710SXin Li "F32 = 0x" << std::setw(8) << sixteen_f32;
117*5f32b710SXin Li
118*5f32b710SXin Li const float thirtytwo_value = fp16_ieee_to_fp32_value(thirtytwo_f16);
119*5f32b710SXin Li uint32_t thirtytwo_bits;
120*5f32b710SXin Li memcpy(&thirtytwo_bits, &thirtytwo_value, sizeof(thirtytwo_bits));
121*5f32b710SXin Li EXPECT_EQ(thirtytwo_f32, thirtytwo_bits) <<
122*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
123*5f32b710SXin Li "F16 = 0x" << std::setw(4) << thirtytwo_f16 << ", " <<
124*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << thirtytwo_bits << ", " <<
125*5f32b710SXin Li "F32 = 0x" << std::setw(8) << thirtytwo_f32;
126*5f32b710SXin Li
127*5f32b710SXin Li const float sixtyfour_value = fp16_ieee_to_fp32_value(sixtyfour_f16);
128*5f32b710SXin Li uint32_t sixtyfour_bits;
129*5f32b710SXin Li memcpy(&sixtyfour_bits, &sixtyfour_value, sizeof(sixtyfour_bits));
130*5f32b710SXin Li EXPECT_EQ(sixtyfour_f32, sixtyfour_bits) <<
131*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
132*5f32b710SXin Li "F16 = 0x" << std::setw(4) << sixtyfour_f16 << ", " <<
133*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << sixtyfour_bits << ", " <<
134*5f32b710SXin Li "F32 = 0x" << std::setw(8) << sixtyfour_f32;
135*5f32b710SXin Li
136*5f32b710SXin Li const float max_po2_value = fp16_ieee_to_fp32_value(max_po2_f16);
137*5f32b710SXin Li uint32_t max_po2_bits;
138*5f32b710SXin Li memcpy(&max_po2_bits, &max_po2_value, sizeof(max_po2_bits));
139*5f32b710SXin Li EXPECT_EQ(max_po2_f32, max_po2_bits) <<
140*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
141*5f32b710SXin Li "F16 = 0x" << std::setw(4) << max_po2_f16 << ", " <<
142*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << max_po2_bits << ", " <<
143*5f32b710SXin Li "F32 = 0x" << std::setw(8) << max_po2_f32;
144*5f32b710SXin Li }
145*5f32b710SXin Li
TEST(FP16_IEEE_TO_FP32_VALUE,denormalized_powers_of_2)146*5f32b710SXin Li TEST(FP16_IEEE_TO_FP32_VALUE, denormalized_powers_of_2) {
147*5f32b710SXin Li const uint16_t exp2_minus_15_f16 = UINT16_C(0x0200);
148*5f32b710SXin Li const uint16_t exp2_minus_16_f16 = UINT16_C(0x0100);
149*5f32b710SXin Li const uint16_t exp2_minus_17_f16 = UINT16_C(0x0080);
150*5f32b710SXin Li const uint16_t exp2_minus_18_f16 = UINT16_C(0x0040);
151*5f32b710SXin Li const uint16_t exp2_minus_19_f16 = UINT16_C(0x0020);
152*5f32b710SXin Li const uint16_t exp2_minus_20_f16 = UINT16_C(0x0010);
153*5f32b710SXin Li const uint16_t exp2_minus_21_f16 = UINT16_C(0x0008);
154*5f32b710SXin Li const uint16_t exp2_minus_22_f16 = UINT16_C(0x0004);
155*5f32b710SXin Li const uint16_t exp2_minus_23_f16 = UINT16_C(0x0002);
156*5f32b710SXin Li const uint16_t exp2_minus_24_f16 = UINT16_C(0x0001);
157*5f32b710SXin Li
158*5f32b710SXin Li const uint32_t exp2_minus_15_f32 = UINT32_C(0x38000000);
159*5f32b710SXin Li const uint32_t exp2_minus_16_f32 = UINT32_C(0x37800000);
160*5f32b710SXin Li const uint32_t exp2_minus_17_f32 = UINT32_C(0x37000000);
161*5f32b710SXin Li const uint32_t exp2_minus_18_f32 = UINT32_C(0x36800000);
162*5f32b710SXin Li const uint32_t exp2_minus_19_f32 = UINT32_C(0x36000000);
163*5f32b710SXin Li const uint32_t exp2_minus_20_f32 = UINT32_C(0x35800000);
164*5f32b710SXin Li const uint32_t exp2_minus_21_f32 = UINT32_C(0x35000000);
165*5f32b710SXin Li const uint32_t exp2_minus_22_f32 = UINT32_C(0x34800000);
166*5f32b710SXin Li const uint32_t exp2_minus_23_f32 = UINT32_C(0x34000000);
167*5f32b710SXin Li const uint32_t exp2_minus_24_f32 = UINT32_C(0x33800000);
168*5f32b710SXin Li
169*5f32b710SXin Li const float exp2_minus_15_value = fp16_ieee_to_fp32_value(exp2_minus_15_f16);
170*5f32b710SXin Li uint32_t exp2_minus_15_bits;
171*5f32b710SXin Li memcpy(&exp2_minus_15_bits, &exp2_minus_15_value, sizeof(exp2_minus_15_bits));
172*5f32b710SXin Li EXPECT_EQ(exp2_minus_15_f32, exp2_minus_15_bits) <<
173*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
174*5f32b710SXin Li "F16 = 0x" << std::setw(4) << exp2_minus_15_f16 << ", " <<
175*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << exp2_minus_15_bits << ", " <<
176*5f32b710SXin Li "F32 = 0x" << std::setw(8) << exp2_minus_15_f32;
177*5f32b710SXin Li
178*5f32b710SXin Li const float exp2_minus_16_value = fp16_ieee_to_fp32_value(exp2_minus_16_f16);
179*5f32b710SXin Li uint32_t exp2_minus_16_bits;
180*5f32b710SXin Li memcpy(&exp2_minus_16_bits, &exp2_minus_16_value, sizeof(exp2_minus_16_bits));
181*5f32b710SXin Li EXPECT_EQ(exp2_minus_16_f32, exp2_minus_16_bits) <<
182*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
183*5f32b710SXin Li "F16 = 0x" << std::setw(4) << exp2_minus_16_f16 << ", " <<
184*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << exp2_minus_16_bits << ", " <<
185*5f32b710SXin Li "F32 = 0x" << std::setw(8) << exp2_minus_16_f32;
186*5f32b710SXin Li
187*5f32b710SXin Li const float exp2_minus_17_value = fp16_ieee_to_fp32_value(exp2_minus_17_f16);
188*5f32b710SXin Li uint32_t exp2_minus_17_bits;
189*5f32b710SXin Li memcpy(&exp2_minus_17_bits, &exp2_minus_17_value, sizeof(exp2_minus_17_bits));
190*5f32b710SXin Li EXPECT_EQ(exp2_minus_17_f32, exp2_minus_17_bits) <<
191*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
192*5f32b710SXin Li "F16 = 0x" << std::setw(4) << exp2_minus_17_f16 << ", " <<
193*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << exp2_minus_17_bits << ", " <<
194*5f32b710SXin Li "F32 = 0x" << std::setw(8) << exp2_minus_17_f32;
195*5f32b710SXin Li
196*5f32b710SXin Li const float exp2_minus_18_value = fp16_ieee_to_fp32_value(exp2_minus_18_f16);
197*5f32b710SXin Li uint32_t exp2_minus_18_bits;
198*5f32b710SXin Li memcpy(&exp2_minus_18_bits, &exp2_minus_18_value, sizeof(exp2_minus_18_bits));
199*5f32b710SXin Li EXPECT_EQ(exp2_minus_18_f32, exp2_minus_18_bits) <<
200*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
201*5f32b710SXin Li "F16 = 0x" << std::setw(4) << exp2_minus_18_f16 << ", " <<
202*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << exp2_minus_18_bits << ", " <<
203*5f32b710SXin Li "F32 = 0x" << std::setw(8) << exp2_minus_18_f32;
204*5f32b710SXin Li
205*5f32b710SXin Li const float exp2_minus_19_value = fp16_ieee_to_fp32_value(exp2_minus_19_f16);
206*5f32b710SXin Li uint32_t exp2_minus_19_bits;
207*5f32b710SXin Li memcpy(&exp2_minus_19_bits, &exp2_minus_19_value, sizeof(exp2_minus_19_bits));
208*5f32b710SXin Li EXPECT_EQ(exp2_minus_19_f32, exp2_minus_19_bits) <<
209*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
210*5f32b710SXin Li "F16 = 0x" << std::setw(4) << exp2_minus_19_f16 << ", " <<
211*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << exp2_minus_19_bits << ", " <<
212*5f32b710SXin Li "F32 = 0x" << std::setw(8) << exp2_minus_19_f32;
213*5f32b710SXin Li
214*5f32b710SXin Li const float exp2_minus_20_value = fp16_ieee_to_fp32_value(exp2_minus_20_f16);
215*5f32b710SXin Li uint32_t exp2_minus_20_bits;
216*5f32b710SXin Li memcpy(&exp2_minus_20_bits, &exp2_minus_20_value, sizeof(exp2_minus_20_bits));
217*5f32b710SXin Li EXPECT_EQ(exp2_minus_20_f32, exp2_minus_20_bits) <<
218*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
219*5f32b710SXin Li "F16 = 0x" << std::setw(4) << exp2_minus_20_f16 << ", " <<
220*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << exp2_minus_20_bits << ", " <<
221*5f32b710SXin Li "F32 = 0x" << std::setw(8) << exp2_minus_20_f32;
222*5f32b710SXin Li
223*5f32b710SXin Li const float exp2_minus_21_value = fp16_ieee_to_fp32_value(exp2_minus_21_f16);
224*5f32b710SXin Li uint32_t exp2_minus_21_bits;
225*5f32b710SXin Li memcpy(&exp2_minus_21_bits, &exp2_minus_21_value, sizeof(exp2_minus_21_bits));
226*5f32b710SXin Li EXPECT_EQ(exp2_minus_21_f32, exp2_minus_21_bits) <<
227*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
228*5f32b710SXin Li "F16 = 0x" << std::setw(4) << exp2_minus_21_f16 << ", " <<
229*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << exp2_minus_21_bits << ", " <<
230*5f32b710SXin Li "F32 = 0x" << std::setw(8) << exp2_minus_21_f32;
231*5f32b710SXin Li
232*5f32b710SXin Li const float exp2_minus_22_value = fp16_ieee_to_fp32_value(exp2_minus_22_f16);
233*5f32b710SXin Li uint32_t exp2_minus_22_bits;
234*5f32b710SXin Li memcpy(&exp2_minus_22_bits, &exp2_minus_22_value, sizeof(exp2_minus_22_bits));
235*5f32b710SXin Li EXPECT_EQ(exp2_minus_22_f32, exp2_minus_22_bits) <<
236*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
237*5f32b710SXin Li "F16 = 0x" << std::setw(4) << exp2_minus_22_f16 << ", " <<
238*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << exp2_minus_22_bits << ", " <<
239*5f32b710SXin Li "F32 = 0x" << std::setw(8) << exp2_minus_22_f32;
240*5f32b710SXin Li
241*5f32b710SXin Li const float exp2_minus_23_value = fp16_ieee_to_fp32_value(exp2_minus_23_f16);
242*5f32b710SXin Li uint32_t exp2_minus_23_bits;
243*5f32b710SXin Li memcpy(&exp2_minus_23_bits, &exp2_minus_23_value, sizeof(exp2_minus_23_bits));
244*5f32b710SXin Li EXPECT_EQ(exp2_minus_23_f32, exp2_minus_23_bits) <<
245*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
246*5f32b710SXin Li "F16 = 0x" << std::setw(4) << exp2_minus_23_f16 << ", " <<
247*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << exp2_minus_23_bits << ", " <<
248*5f32b710SXin Li "F32 = 0x" << std::setw(8) << exp2_minus_23_f32;
249*5f32b710SXin Li
250*5f32b710SXin Li const float exp2_minus_24_value = fp16_ieee_to_fp32_value(exp2_minus_24_f16);
251*5f32b710SXin Li uint32_t exp2_minus_24_bits;
252*5f32b710SXin Li memcpy(&exp2_minus_24_bits, &exp2_minus_24_value, sizeof(exp2_minus_24_bits));
253*5f32b710SXin Li EXPECT_EQ(exp2_minus_24_f32, exp2_minus_24_bits) <<
254*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
255*5f32b710SXin Li "F16 = 0x" << std::setw(4) << exp2_minus_24_f16 << ", " <<
256*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << exp2_minus_24_bits << ", " <<
257*5f32b710SXin Li "F32 = 0x" << std::setw(8) << exp2_minus_24_f32;
258*5f32b710SXin Li }
259*5f32b710SXin Li
TEST(FP16_IEEE_TO_FP32_VALUE,zero)260*5f32b710SXin Li TEST(FP16_IEEE_TO_FP32_VALUE, zero) {
261*5f32b710SXin Li const uint16_t positive_zero_f16 = UINT16_C(0x0000);
262*5f32b710SXin Li const uint16_t negative_zero_f16 = UINT16_C(0x8000);
263*5f32b710SXin Li
264*5f32b710SXin Li const uint32_t positive_zero_f32 = UINT32_C(0x00000000);
265*5f32b710SXin Li const uint32_t negative_zero_f32 = UINT32_C(0x80000000);
266*5f32b710SXin Li
267*5f32b710SXin Li const float positive_zero_value = fp16_ieee_to_fp32_value(positive_zero_f16);
268*5f32b710SXin Li uint32_t positive_zero_bits;
269*5f32b710SXin Li memcpy(&positive_zero_bits, &positive_zero_value, sizeof(positive_zero_bits));
270*5f32b710SXin Li EXPECT_EQ(positive_zero_f32, positive_zero_bits) <<
271*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
272*5f32b710SXin Li "F16 = 0x" << std::setw(4) << positive_zero_f16 << ", " <<
273*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << positive_zero_bits << ", " <<
274*5f32b710SXin Li "F32 = 0x" << std::setw(8) << positive_zero_f32;
275*5f32b710SXin Li
276*5f32b710SXin Li const float negative_zero_value = fp16_ieee_to_fp32_value(negative_zero_f16);
277*5f32b710SXin Li uint32_t negative_zero_bits;
278*5f32b710SXin Li memcpy(&negative_zero_bits, &negative_zero_value, sizeof(negative_zero_bits));
279*5f32b710SXin Li EXPECT_EQ(negative_zero_f32, negative_zero_bits) <<
280*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
281*5f32b710SXin Li "F16 = 0x" << std::setw(4) << negative_zero_f16 << ", " <<
282*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << negative_zero_bits << ", " <<
283*5f32b710SXin Li "F32 = 0x" << std::setw(8) << negative_zero_f32;
284*5f32b710SXin Li }
285*5f32b710SXin Li
TEST(FP16_IEEE_TO_FP32_VALUE,infinity)286*5f32b710SXin Li TEST(FP16_IEEE_TO_FP32_VALUE, infinity) {
287*5f32b710SXin Li const uint16_t positive_infinity_f16 = UINT16_C(0x7C00);
288*5f32b710SXin Li const uint16_t negative_infinity_f16 = UINT16_C(0xFC00);
289*5f32b710SXin Li
290*5f32b710SXin Li const uint32_t positive_infinity_f32 = UINT32_C(0x7F800000);
291*5f32b710SXin Li const uint32_t negative_infinity_f32 = UINT32_C(0xFF800000);
292*5f32b710SXin Li
293*5f32b710SXin Li const float positive_infinity_value = fp16_ieee_to_fp32_value(positive_infinity_f16);
294*5f32b710SXin Li uint32_t positive_infinity_bits;
295*5f32b710SXin Li memcpy(&positive_infinity_bits, &positive_infinity_value, sizeof(positive_infinity_bits));
296*5f32b710SXin Li EXPECT_EQ(positive_infinity_f32, positive_infinity_bits) <<
297*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
298*5f32b710SXin Li "F16 = 0x" << std::setw(4) << positive_infinity_f16 << ", " <<
299*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << positive_infinity_bits << ", " <<
300*5f32b710SXin Li "F32 = 0x" << std::setw(8) << positive_infinity_f32;
301*5f32b710SXin Li
302*5f32b710SXin Li const float negative_infinity_value = fp16_ieee_to_fp32_value(negative_infinity_f16);
303*5f32b710SXin Li uint32_t negative_infinity_bits;
304*5f32b710SXin Li memcpy(&negative_infinity_bits, &negative_infinity_value, sizeof(negative_infinity_bits));
305*5f32b710SXin Li EXPECT_EQ(negative_infinity_f32, negative_infinity_bits) <<
306*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
307*5f32b710SXin Li "F16 = 0x" << std::setw(4) << negative_infinity_f16 << ", " <<
308*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << negative_infinity_bits << ", " <<
309*5f32b710SXin Li "F32 = 0x" << std::setw(8) << negative_infinity_f32;
310*5f32b710SXin Li }
311*5f32b710SXin Li
TEST(FP16_IEEE_TO_FP32_VALUE,positive_nan)312*5f32b710SXin Li TEST(FP16_IEEE_TO_FP32_VALUE, positive_nan) {
313*5f32b710SXin Li using std::signbit;
314*5f32b710SXin Li using std::isnan;
315*5f32b710SXin Li for (uint16_t m = UINT16_C(1); m < UINT16_C(0x0400); m++) {
316*5f32b710SXin Li const uint16_t nan_f16 = UINT16_C(0x7C00) | m;
317*5f32b710SXin Li const float nan_f32 = fp16_ieee_to_fp32_value(nan_f16);
318*5f32b710SXin Li uint32_t nan_bits;
319*5f32b710SXin Li memcpy(&nan_bits, &nan_f32, sizeof(nan_bits));
320*5f32b710SXin Li
321*5f32b710SXin Li /* Check if NaN */
322*5f32b710SXin Li EXPECT_TRUE(isnan(nan_f32)) <<
323*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
324*5f32b710SXin Li "F16 = 0x" << std::setw(4) << nan_f16 << ", " <<
325*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << nan_bits;
326*5f32b710SXin Li
327*5f32b710SXin Li /* Check sign */
328*5f32b710SXin Li EXPECT_EQ(signbit(nan_f32), 0) <<
329*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
330*5f32b710SXin Li "F16 = 0x" << std::setw(4) << nan_f16 << ", " <<
331*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << nan_bits;
332*5f32b710SXin Li }
333*5f32b710SXin Li }
334*5f32b710SXin Li
TEST(FP16_IEEE_TO_FP32_VALUE,negative_nan)335*5f32b710SXin Li TEST(FP16_IEEE_TO_FP32_VALUE, negative_nan) {
336*5f32b710SXin Li using std::signbit;
337*5f32b710SXin Li using std::isnan;
338*5f32b710SXin Li for (uint16_t m = UINT16_C(1); m < UINT16_C(0x0400); m++) {
339*5f32b710SXin Li const uint16_t nan_f16 = UINT16_C(0xFC00) | m;
340*5f32b710SXin Li const float nan_f32 = fp16_ieee_to_fp32_value(nan_f16);
341*5f32b710SXin Li uint32_t nan_bits;
342*5f32b710SXin Li memcpy(&nan_bits, &nan_f32, sizeof(nan_bits));
343*5f32b710SXin Li
344*5f32b710SXin Li /* Check if NaN */
345*5f32b710SXin Li EXPECT_TRUE(isnan(nan_f32)) <<
346*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
347*5f32b710SXin Li "F16 = 0x" << std::setw(4) << nan_f16 << ", " <<
348*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << nan_bits;
349*5f32b710SXin Li
350*5f32b710SXin Li /* Check sign */
351*5f32b710SXin Li EXPECT_EQ(signbit(nan_f32), 1) <<
352*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
353*5f32b710SXin Li "F16 = 0x" << std::setw(4) << nan_f16 << ", " <<
354*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << nan_bits;
355*5f32b710SXin Li }
356*5f32b710SXin Li }
357*5f32b710SXin Li
TEST(FP16_IEEE_TO_FP32_VALUE,positive_normalized_values)358*5f32b710SXin Li TEST(FP16_IEEE_TO_FP32_VALUE, positive_normalized_values) {
359*5f32b710SXin Li const uint32_t exponentBias = 15;
360*5f32b710SXin Li for (int32_t e = -14; e <= 15; e++) {
361*5f32b710SXin Li for (uint16_t h = 0; h < 0x0400; h++) {
362*5f32b710SXin Li const uint16_t fp16 = h + ((uint16_t) (e + exponentBias) << 10);
363*5f32b710SXin Li const uint32_t fp32 = fp16::normalizedValues[h] + ((uint32_t) e << 23);
364*5f32b710SXin Li const float value = fp16_ieee_to_fp32_value(fp16);
365*5f32b710SXin Li uint32_t bits;
366*5f32b710SXin Li memcpy(&bits, &value, sizeof(bits));
367*5f32b710SXin Li EXPECT_EQ(fp32, bits) <<
368*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
369*5f32b710SXin Li "F16 = 0x" << std::setw(4) << fp16 << ", " <<
370*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << bits << ", " <<
371*5f32b710SXin Li "F32 = 0x" << std::setw(8) << fp32;
372*5f32b710SXin Li }
373*5f32b710SXin Li }
374*5f32b710SXin Li }
375*5f32b710SXin Li
TEST(FP16_IEEE_TO_FP32_VALUE,negative_normalized_values)376*5f32b710SXin Li TEST(FP16_IEEE_TO_FP32_VALUE, negative_normalized_values) {
377*5f32b710SXin Li const uint32_t exponentBias = 15;
378*5f32b710SXin Li for (int32_t e = -14; e <= 15; e++) {
379*5f32b710SXin Li for (uint16_t h = 0; h < 0x0400; h++) {
380*5f32b710SXin Li const uint16_t fp16 = (h + ((uint16_t) (e + exponentBias) << 10)) ^ UINT16_C(0x8000);
381*5f32b710SXin Li const uint32_t fp32 = (fp16::normalizedValues[h] + ((uint32_t) e << 23)) ^ UINT32_C(0x80000000);
382*5f32b710SXin Li const float value = fp16_ieee_to_fp32_value(fp16);
383*5f32b710SXin Li uint32_t bits;
384*5f32b710SXin Li memcpy(&bits, &value, sizeof(bits));
385*5f32b710SXin Li EXPECT_EQ(fp32, bits) <<
386*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
387*5f32b710SXin Li "F16 = 0x" << std::setw(4) << fp16 << ", " <<
388*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << bits << ", " <<
389*5f32b710SXin Li "F32 = 0x" << std::setw(8) << fp32;
390*5f32b710SXin Li }
391*5f32b710SXin Li }
392*5f32b710SXin Li }
393*5f32b710SXin Li
TEST(FP16_IEEE_TO_FP32_VALUE,positive_denormalized_values)394*5f32b710SXin Li TEST(FP16_IEEE_TO_FP32_VALUE, positive_denormalized_values) {
395*5f32b710SXin Li for (uint16_t h = 0; h < 0x0400; h++) {
396*5f32b710SXin Li const float value = fp16_ieee_to_fp32_value(h);
397*5f32b710SXin Li uint32_t bits;
398*5f32b710SXin Li memcpy(&bits, &value, sizeof(bits));
399*5f32b710SXin Li EXPECT_EQ(fp16::denormalizedValues[h], bits) <<
400*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
401*5f32b710SXin Li "F16 = 0x" << std::setw(4) << h << ", " <<
402*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << bits << ", " <<
403*5f32b710SXin Li "F32 = 0x" << std::setw(8) << fp16::denormalizedValues[h];
404*5f32b710SXin Li }
405*5f32b710SXin Li }
406*5f32b710SXin Li
TEST(FP16_IEEE_TO_FP32_VALUE,negative_denormalized_values)407*5f32b710SXin Li TEST(FP16_IEEE_TO_FP32_VALUE, negative_denormalized_values) {
408*5f32b710SXin Li for (uint16_t h = 0; h < 0x0400; h++) {
409*5f32b710SXin Li const uint16_t fp16 = h ^ UINT16_C(0x8000);
410*5f32b710SXin Li const uint32_t fp32 = fp16::denormalizedValues[h] ^ UINT32_C(0x80000000);
411*5f32b710SXin Li const float value = fp16_ieee_to_fp32_value(fp16);
412*5f32b710SXin Li uint32_t bits;
413*5f32b710SXin Li memcpy(&bits, &value, sizeof(bits));
414*5f32b710SXin Li EXPECT_EQ(fp32, bits) <<
415*5f32b710SXin Li std::hex << std::uppercase << std::setfill('0') <<
416*5f32b710SXin Li "F16 = 0x" << std::setw(4) << fp16 << ", " <<
417*5f32b710SXin Li "F32(F16) = 0x" << std::setw(8) << bits << ", " <<
418*5f32b710SXin Li "F32 = 0x" << std::setw(8) << fp32;
419*5f32b710SXin Li }
420*5f32b710SXin Li }
421