1 #include <stdlib.h>
2 #include <limits.h>
3 #include <string.h>
4 #include <stdint.h>
5 
6 #ifdef COMPILER_RT_HAS_FLOAT16
7 #define TYPE_FP16 _Float16
8 #else
9 #define TYPE_FP16 uint16_t
10 #endif
11 
12 enum EXPECTED_RESULT {
13     LESS_0, LESS_EQUAL_0, EQUAL_0, GREATER_0, GREATER_EQUAL_0, NEQUAL_0
14 };
15 
fromRep16(uint16_t x)16 static inline TYPE_FP16 fromRep16(uint16_t x)
17 {
18 #ifdef COMPILER_RT_HAS_FLOAT16
19     TYPE_FP16 ret;
20     memcpy(&ret, &x, sizeof(ret));
21     return ret;
22 #else
23     return x;
24 #endif
25 }
26 
fromRep32(uint32_t x)27 static inline float fromRep32(uint32_t x)
28 {
29     float ret;
30     memcpy(&ret, &x, 4);
31     return ret;
32 }
33 
fromRep64(uint64_t x)34 static inline double fromRep64(uint64_t x)
35 {
36     double ret;
37     memcpy(&ret, &x, 8);
38     return ret;
39 }
40 
41 #if __LDBL_MANT_DIG__ == 113
fromRep128(uint64_t hi,uint64_t lo)42 static inline long double fromRep128(uint64_t hi, uint64_t lo)
43 {
44     __uint128_t x = ((__uint128_t)hi << 64) + lo;
45     long double ret;
46     memcpy(&ret, &x, 16);
47     return ret;
48 }
49 #endif
50 
toRep16(TYPE_FP16 x)51 static inline uint16_t toRep16(TYPE_FP16 x)
52 {
53 #ifdef COMPILER_RT_HAS_FLOAT16
54     uint16_t ret;
55     memcpy(&ret, &x, sizeof(ret));
56     return ret;
57 #else
58     return x;
59 #endif
60 }
61 
toRep32(float x)62 static inline uint32_t toRep32(float x)
63 {
64     uint32_t ret;
65     memcpy(&ret, &x, 4);
66     return ret;
67 }
68 
toRep64(double x)69 static inline uint64_t toRep64(double x)
70 {
71     uint64_t ret;
72     memcpy(&ret, &x, 8);
73     return ret;
74 }
75 
76 #if __LDBL_MANT_DIG__ == 113
toRep128(long double x)77 static inline __uint128_t toRep128(long double x)
78 {
79     __uint128_t ret;
80     memcpy(&ret, &x, 16);
81     return ret;
82 }
83 #endif
84 
compareResultH(TYPE_FP16 result,uint16_t expected)85 static inline int compareResultH(TYPE_FP16 result,
86                                  uint16_t expected)
87 {
88     uint16_t rep = toRep16(result);
89 
90     if (rep == expected){
91         return 0;
92     }
93     // test other possible NaN representation(signal NaN)
94     else if (expected == 0x7e00U){
95         if ((rep & 0x7c00U) == 0x7c00U &&
96             (rep & 0x3ffU) > 0){
97             return 0;
98         }
99     }
100     return 1;
101 }
102 
compareResultF(float result,uint32_t expected)103 static inline int compareResultF(float result,
104                                  uint32_t expected)
105 {
106     uint32_t rep = toRep32(result);
107 
108     if (rep == expected){
109         return 0;
110     }
111     // test other possible NaN representation(signal NaN)
112     else if (expected == 0x7fc00000U){
113         if ((rep & 0x7f800000U) == 0x7f800000U &&
114             (rep & 0x7fffffU) > 0){
115             return 0;
116         }
117     }
118     return 1;
119 }
120 
compareResultD(double result,uint64_t expected)121 static inline int compareResultD(double result,
122                                  uint64_t expected)
123 {
124     uint64_t rep = toRep64(result);
125 
126     if (rep == expected){
127         return 0;
128     }
129     // test other possible NaN representation(signal NaN)
130     else if (expected == 0x7ff8000000000000UL){
131         if ((rep & 0x7ff0000000000000UL) == 0x7ff0000000000000UL &&
132             (rep & 0xfffffffffffffUL) > 0){
133             return 0;
134         }
135     }
136     return 1;
137 }
138 
139 #if __LDBL_MANT_DIG__ == 113
140 // return 0 if equal
141 // use two 64-bit integers intead of one 128-bit integer
142 // because 128-bit integer constant can't be assigned directly
compareResultLD(long double result,uint64_t expectedHi,uint64_t expectedLo)143 static inline int compareResultLD(long double result,
144                                   uint64_t expectedHi,
145                                   uint64_t expectedLo)
146 {
147     __uint128_t rep = toRep128(result);
148     uint64_t hi = rep >> 64;
149     uint64_t lo = rep;
150 
151     if (hi == expectedHi && lo == expectedLo){
152         return 0;
153     }
154     // test other possible NaN representation(signal NaN)
155     else if (expectedHi == 0x7fff800000000000UL && expectedLo == 0x0UL){
156         if ((hi & 0x7fff000000000000UL) == 0x7fff000000000000UL &&
157             ((hi & 0xffffffffffffUL) > 0 || lo > 0)){
158             return 0;
159         }
160     }
161     return 1;
162 }
163 #endif
164 
compareResultCMP(int result,enum EXPECTED_RESULT expected)165 static inline int compareResultCMP(int result,
166                                    enum EXPECTED_RESULT expected)
167 {
168     switch(expected){
169         case LESS_0:
170             if (result < 0)
171                 return 0;
172             break;
173         case LESS_EQUAL_0:
174             if (result <= 0)
175                 return 0;
176             break;
177         case EQUAL_0:
178             if (result == 0)
179                 return 0;
180             break;
181         case NEQUAL_0:
182             if (result != 0)
183                 return 0;
184             break;
185         case GREATER_EQUAL_0:
186             if (result >= 0)
187                 return 0;
188             break;
189         case GREATER_0:
190             if (result > 0)
191                 return 0;
192             break;
193         default:
194             return 1;
195     }
196     return 1;
197 }
198 
expectedStr(enum EXPECTED_RESULT expected)199 static inline char *expectedStr(enum EXPECTED_RESULT expected)
200 {
201     switch(expected){
202         case LESS_0:
203             return "<0";
204         case LESS_EQUAL_0:
205             return "<=0";
206         case EQUAL_0:
207             return "=0";
208         case NEQUAL_0:
209             return "!=0";
210         case GREATER_EQUAL_0:
211             return ">=0";
212         case GREATER_0:
213             return ">0";
214         default:
215             return "";
216     }
217     return "";
218 }
219 
makeQNaN16(void)220 static inline TYPE_FP16 makeQNaN16(void)
221 {
222     return fromRep16(0x7e00U);
223 }
224 
makeQNaN32(void)225 static inline float makeQNaN32(void)
226 {
227     return fromRep32(0x7fc00000U);
228 }
229 
makeQNaN64(void)230 static inline double makeQNaN64(void)
231 {
232     return fromRep64(0x7ff8000000000000UL);
233 }
234 
235 #if __LDBL_MANT_DIG__ == 113
makeQNaN128(void)236 static inline long double makeQNaN128(void)
237 {
238     return fromRep128(0x7fff800000000000UL, 0x0UL);
239 }
240 #endif
241 
makeNaN16(uint16_t rand)242 static inline TYPE_FP16 makeNaN16(uint16_t rand)
243 {
244     return fromRep16(0x7c00U | (rand & 0x7fffU));
245 }
246 
makeNaN32(uint32_t rand)247 static inline float makeNaN32(uint32_t rand)
248 {
249     return fromRep32(0x7f800000U | (rand & 0x7fffffU));
250 }
251 
makeNaN64(uint64_t rand)252 static inline double makeNaN64(uint64_t rand)
253 {
254     return fromRep64(0x7ff0000000000000UL | (rand & 0xfffffffffffffUL));
255 }
256 
257 #if __LDBL_MANT_DIG__ == 113
makeNaN128(uint64_t rand)258 static inline long double makeNaN128(uint64_t rand)
259 {
260     return fromRep128(0x7fff000000000000UL | (rand & 0xffffffffffffUL), 0x0UL);
261 }
262 #endif
263 
makeInf16(void)264 static inline TYPE_FP16 makeInf16(void)
265 {
266     return fromRep16(0x7c00U);
267 }
268 
makeInf32(void)269 static inline float makeInf32(void)
270 {
271     return fromRep32(0x7f800000U);
272 }
273 
makeNegativeInf32(void)274 static inline float makeNegativeInf32(void)
275 {
276     return fromRep32(0xff800000U);
277 }
278 
makeInf64(void)279 static inline double makeInf64(void)
280 {
281     return fromRep64(0x7ff0000000000000UL);
282 }
283 
makeNegativeInf64(void)284 static inline double makeNegativeInf64(void)
285 {
286     return fromRep64(0xfff0000000000000UL);
287 }
288 
289 #if __LDBL_MANT_DIG__ == 113
makeInf128(void)290 static inline long double makeInf128(void)
291 {
292     return fromRep128(0x7fff000000000000UL, 0x0UL);
293 }
294 
makeNegativeInf128(void)295 static inline long double makeNegativeInf128(void)
296 {
297     return fromRep128(0xffff000000000000UL, 0x0UL);
298 }
299 #endif
300