1#include <stdlib.h>
2#include <limits.h>
3#include <string.h>
4#include <stdint.h>
5
6#include "int_types.h"
7
8#ifdef COMPILER_RT_HAS_FLOAT16
9#define TYPE_FP16 _Float16
10#else
11#define TYPE_FP16 uint16_t
12#endif
13
14enum EXPECTED_RESULT {
15 LESS_0, LESS_EQUAL_0, EQUAL_0, GREATER_0, GREATER_EQUAL_0, NEQUAL_0
16};
17
18static inline TYPE_FP16 fromRep16(uint16_t x)
19{
20#ifdef COMPILER_RT_HAS_FLOAT16
21 TYPE_FP16 ret;
22 memcpy(&ret, &x, sizeof(ret));
23 return ret;
24#else
25 return x;
26#endif
27}
28
29static inline float fromRep32(uint32_t x)
30{
31 float ret;
32 memcpy(dest: &ret, src: &x, n: 4);
33 return ret;
34}
35
36static inline double fromRep64(uint64_t x)
37{
38 double ret;
39 memcpy(dest: &ret, src: &x, n: 8);
40 return ret;
41}
42
43#if defined(CRT_HAS_TF_MODE)
44static inline tf_float fromRep128(uint64_t hi, uint64_t lo) {
45 __uint128_t x = ((__uint128_t)hi << 64) + lo;
46 tf_float ret;
47 memcpy(dest: &ret, src: &x, n: 16);
48 return ret;
49}
50#endif
51
52static inline uint16_t toRep16(TYPE_FP16 x)
53{
54#ifdef COMPILER_RT_HAS_FLOAT16
55 uint16_t ret;
56 memcpy(&ret, &x, sizeof(ret));
57 return ret;
58#else
59 return x;
60#endif
61}
62
63static inline uint32_t toRep32(float x)
64{
65 uint32_t ret;
66 memcpy(dest: &ret, src: &x, n: 4);
67 return ret;
68}
69
70static inline uint64_t toRep64(double x)
71{
72 uint64_t ret;
73 memcpy(dest: &ret, src: &x, n: 8);
74 return ret;
75}
76
77#if defined(CRT_HAS_TF_MODE)
78static inline __uint128_t toRep128(tf_float x) {
79 __uint128_t ret;
80 memcpy(dest: &ret, src: &x, n: 16);
81 return ret;
82}
83#endif
84
85static inline int compareResultH(TYPE_FP16 result,
86 uint16_t expected)
87{
88 uint16_t rep = toRep16(x: 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
103static inline int compareResultF(float result,
104 uint32_t expected)
105{
106 uint32_t rep = toRep32(x: 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
121static inline int compareResultD(double result,
122 uint64_t expected)
123{
124 uint64_t rep = toRep64(x: 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 defined(CRT_HAS_TF_MODE)
140// return 0 if equal
141// use two 64-bit integers instead of one 128-bit integer
142// because 128-bit integer constant can't be assigned directly
143static inline int compareResultF128(tf_float result, uint64_t expectedHi,
144 uint64_t expectedLo) {
145 __uint128_t rep = toRep128(x: result);
146 uint64_t hi = rep >> 64;
147 uint64_t lo = rep;
148
149 if (hi == expectedHi && lo == expectedLo) {
150 return 0;
151 }
152 // test other possible NaN representation(signal NaN)
153 else if (expectedHi == 0x7fff800000000000UL && expectedLo == 0x0UL) {
154 if ((hi & 0x7fff000000000000UL) == 0x7fff000000000000UL &&
155 ((hi & 0xffffffffffffUL) > 0 || lo > 0)) {
156 return 0;
157 }
158 }
159 return 1;
160}
161#endif
162
163static inline int compareResultCMP(int result,
164 enum EXPECTED_RESULT expected)
165{
166 switch(expected){
167 case LESS_0:
168 if (result < 0)
169 return 0;
170 break;
171 case LESS_EQUAL_0:
172 if (result <= 0)
173 return 0;
174 break;
175 case EQUAL_0:
176 if (result == 0)
177 return 0;
178 break;
179 case NEQUAL_0:
180 if (result != 0)
181 return 0;
182 break;
183 case GREATER_EQUAL_0:
184 if (result >= 0)
185 return 0;
186 break;
187 case GREATER_0:
188 if (result > 0)
189 return 0;
190 break;
191 default:
192 return 1;
193 }
194 return 1;
195}
196
197static inline char *expectedStr(enum EXPECTED_RESULT expected)
198{
199 switch(expected){
200 case LESS_0:
201 return "<0";
202 case LESS_EQUAL_0:
203 return "<=0";
204 case EQUAL_0:
205 return "=0";
206 case NEQUAL_0:
207 return "!=0";
208 case GREATER_EQUAL_0:
209 return ">=0";
210 case GREATER_0:
211 return ">0";
212 default:
213 return "";
214 }
215 return "";
216}
217
218static inline TYPE_FP16 makeQNaN16(void)
219{
220 return fromRep16(x: 0x7e00U);
221}
222
223static inline float makeQNaN32(void)
224{
225 return fromRep32(x: 0x7fc00000U);
226}
227
228static inline double makeQNaN64(void)
229{
230 return fromRep64(x: 0x7ff8000000000000UL);
231}
232
233#if __LDBL_MANT_DIG__ == 64 && defined(__x86_64__)
234static inline long double F80FromRep128(uint64_t hi, uint64_t lo) {
235 __uint128_t x = ((__uint128_t)hi << 64) + lo;
236 long double ret;
237 memcpy(dest: &ret, src: &x, n: 16);
238 return ret;
239}
240
241static inline __uint128_t F80ToRep128(long double x) {
242 __uint128_t ret;
243 memcpy(dest: &ret, src: &x, n: 16);
244 return ret;
245}
246
247static inline int compareResultF80(long double result, uint64_t expectedHi,
248 uint64_t expectedLo) {
249 __uint128_t rep = F80ToRep128(x: result);
250 // F80 occupies the lower 80 bits of __uint128_t.
251 uint64_t hi = (rep >> 64) & ((1UL << (80 - 64)) - 1);
252 uint64_t lo = rep;
253 return !(hi == expectedHi && lo == expectedLo);
254}
255
256static inline long double makeQNaN80(void) {
257 return F80FromRep128(hi: 0x7fffUL, lo: 0xc000000000000000UL);
258}
259
260static inline long double makeNaN80(uint64_t rand) {
261 return F80FromRep128(hi: 0x7fffUL,
262 lo: 0x8000000000000000 | (rand & 0x3fffffffffffffff));
263}
264
265static inline long double makeInf80(void) {
266 return F80FromRep128(hi: 0x7fffUL, lo: 0x8000000000000000UL);
267}
268#endif
269
270#if defined(CRT_HAS_TF_MODE)
271static inline tf_float makeQNaN128(void) {
272 return fromRep128(hi: 0x7fff800000000000UL, lo: 0x0UL);
273}
274#endif
275
276static inline TYPE_FP16 makeNaN16(uint16_t rand)
277{
278 return fromRep16(x: 0x7c00U | (rand & 0x7fffU));
279}
280
281static inline float makeNaN32(uint32_t rand)
282{
283 return fromRep32(x: 0x7f800000U | (rand & 0x7fffffU));
284}
285
286static inline double makeNaN64(uint64_t rand)
287{
288 return fromRep64(x: 0x7ff0000000000000UL | (rand & 0xfffffffffffffUL));
289}
290
291#if defined(CRT_HAS_TF_MODE)
292static inline tf_float makeNaN128(uint64_t rand) {
293 return fromRep128(hi: 0x7fff000000000000UL | (rand & 0xffffffffffffUL), lo: 0x0UL);
294}
295#endif
296
297static inline TYPE_FP16 makeInf16(void)
298{
299 return fromRep16(x: 0x7c00U);
300}
301
302static inline float makeInf32(void)
303{
304 return fromRep32(x: 0x7f800000U);
305}
306
307static inline float makeNegativeInf32(void)
308{
309 return fromRep32(x: 0xff800000U);
310}
311
312static inline double makeInf64(void)
313{
314 return fromRep64(x: 0x7ff0000000000000UL);
315}
316
317static inline double makeNegativeInf64(void)
318{
319 return fromRep64(x: 0xfff0000000000000UL);
320}
321
322#if defined(CRT_HAS_TF_MODE)
323static inline tf_float makeInf128(void) {
324 return fromRep128(hi: 0x7fff000000000000UL, lo: 0x0UL);
325}
326
327static inline tf_float makeNegativeInf128(void) {
328 return fromRep128(hi: 0xffff000000000000UL, lo: 0x0UL);
329}
330#endif
331

source code of compiler-rt/test/builtins/Unit/fp_test.h