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