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