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

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

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