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