xref: /llvm-project/compiler-rt/test/builtins/Unit/divtc3_test.c (revision 0901f918daa6c5da19b3d2cf38d7de63c265a086)
1 // RUN: %clang_builtins %s %librt -lm -o %t && %run %t
2 // REQUIRES: librt_has_divtc3
3 // REQUIRES: c99-complex
4 
5 //
6 // This test should be XFAILed on 32-bit sparc (sparc-target-arch, Issue
7 // #41838), but that is currently hidden, which caused an XPASS (Issue #72398).
8 //
9 #include <stdio.h>
10 
11 #include "int_lib.h"
12 #include "int_math.h"
13 #include <complex.h>
14 #include <math.h>
15 
16 // Returns: the quotient of (a + ib) / (c + id)
17 #if defined(CRT_HAS_TF_MODE)
18 
19 COMPILER_RT_ABI Qcomplex __divtc3(tf_float __a, tf_float __b, tf_float __c,
20                                   tf_float __d);
21 
22 enum {zero, non_zero, inf, NaN, non_zero_nan};
23 
classify(Qcomplex x)24 static int classify(Qcomplex x) {
25   tf_float real = COMPLEXTF_REAL(x);
26   tf_float imag = COMPLEXTF_IMAGINARY(x);
27   if (real == 0.0 && imag == 0.0)
28     return zero;
29   if (crt_isinf(real) || crt_isinf(imag))
30     return inf;
31   if (crt_isnan(real) && crt_isnan(imag))
32     return NaN;
33   if (crt_isnan(real)) {
34     if (imag == 0.0)
35       return NaN;
36     return non_zero_nan;
37   }
38   if (crt_isnan(imag)) {
39     if (real == 0.0)
40       return NaN;
41     return non_zero_nan;
42   }
43   return non_zero;
44 }
45 
test__divtc3(tf_float a,tf_float b,tf_float c,tf_float d)46 static int test__divtc3(tf_float a, tf_float b, tf_float c, tf_float d) {
47   Qcomplex r = __divtc3(a, b, c, d);
48   Qcomplex dividend;
49   Qcomplex divisor;
50 
51   COMPLEXTF_REAL(dividend) = a;
52   COMPLEXTF_IMAGINARY(dividend) = b;
53   COMPLEXTF_REAL(divisor) = c;
54   COMPLEXTF_IMAGINARY(divisor) = d;
55 
56   switch (classify(dividend)) {
57   case zero:
58     switch (classify(divisor)) {
59     case zero:
60       if (classify(r) != NaN)
61         return 1;
62       break;
63     case non_zero:
64       if (classify(r) != zero)
65         return 1;
66       break;
67     case inf:
68       if (classify(r) != zero)
69         return 1;
70       break;
71     case NaN:
72       if (classify(r) != NaN)
73         return 1;
74       break;
75     case non_zero_nan:
76       if (classify(r) != NaN)
77         return 1;
78       break;
79     }
80     break;
81   case non_zero:
82     switch (classify(divisor)) {
83     case zero:
84       if (classify(r) != inf)
85         return 1;
86       break;
87     case non_zero:
88       if (classify(r) != non_zero)
89         return 1;
90       {
91         tf_float zReal = (a * c + b * d) / (c * c + d * d);
92         tf_float zImag = (b * c - a * d) / (c * c + d * d);
93         Qcomplex diff =
94             __divtc3(COMPLEXTF_REAL(r) - zReal, COMPLEXTF_IMAGINARY(r) - zImag,
95                      COMPLEXTF_REAL(r), COMPLEXTF_IMAGINARY(r));
96         // cabsl(z) == hypotl(creall(z), cimagl(z))
97 #ifdef CRT_LDBL_128BIT
98         if (hypotl(COMPLEXTF_REAL(diff), COMPLEXTF_IMAGINARY(diff)) > 1.e-6)
99 #else
100         // Avoid dependency on __trunctfxf2 for ld80 platforms and use double instead.
101         if (hypot(COMPLEXTF_REAL(diff), COMPLEXTF_IMAGINARY(diff)) > 1.e-6)
102 #endif
103           return 1;
104       }
105       break;
106     case inf:
107       if (classify(r) != zero)
108         return 1;
109       break;
110     case NaN:
111       if (classify(r) != NaN)
112         return 1;
113       break;
114     case non_zero_nan:
115       if (classify(r) != NaN)
116         return 1;
117       break;
118     }
119     break;
120   case inf:
121     switch (classify(divisor)) {
122     case zero:
123       if (classify(r) != inf)
124         return 1;
125       break;
126     case non_zero:
127       if (classify(r) != inf)
128         return 1;
129       break;
130     case inf:
131       if (classify(r) != NaN)
132         return 1;
133       break;
134     case NaN:
135       if (classify(r) != NaN)
136         return 1;
137       break;
138     case non_zero_nan:
139       if (classify(r) != NaN)
140         return 1;
141       break;
142     }
143     break;
144   case NaN:
145     switch (classify(divisor)) {
146     case zero:
147       if (classify(r) != NaN)
148         return 1;
149       break;
150     case non_zero:
151       if (classify(r) != NaN)
152         return 1;
153       break;
154     case inf:
155       if (classify(r) != NaN)
156         return 1;
157       break;
158     case NaN:
159       if (classify(r) != NaN)
160         return 1;
161       break;
162     case non_zero_nan:
163       if (classify(r) != NaN)
164         return 1;
165       break;
166     }
167     break;
168   case non_zero_nan:
169     switch (classify(divisor)) {
170     case zero:
171       if (classify(r) != inf)
172         return 1;
173       break;
174     case non_zero:
175       if (classify(r) != NaN)
176         return 1;
177       break;
178     case inf:
179       if (classify(r) != NaN)
180         return 1;
181       break;
182     case NaN:
183       if (classify(r) != NaN)
184         return 1;
185       break;
186     case non_zero_nan:
187       if (classify(r) != NaN)
188         return 1;
189       break;
190     }
191     break;
192   }
193 
194   return 0;
195 }
196 
197 tf_float x[][2] = {{1.e-6, 1.e-6},
198                    {-1.e-6, 1.e-6},
199                    {-1.e-6, -1.e-6},
200                    {1.e-6, -1.e-6},
201 
202                    {1.e+6, 1.e-6},
203                    {-1.e+6, 1.e-6},
204                    {-1.e+6, -1.e-6},
205                    {1.e+6, -1.e-6},
206 
207                    {1.e-6, 1.e+6},
208                    {-1.e-6, 1.e+6},
209                    {-1.e-6, -1.e+6},
210                    {1.e-6, -1.e+6},
211 
212                    {1.e+6, 1.e+6},
213                    {-1.e+6, 1.e+6},
214                    {-1.e+6, -1.e+6},
215                    {1.e+6, -1.e+6},
216 
217                    {NAN, NAN},
218                    {-INFINITY, NAN},
219                    {-2, NAN},
220                    {-1, NAN},
221                    {-0.5, NAN},
222                    {-0., NAN},
223                    {+0., NAN},
224                    {0.5, NAN},
225                    {1, NAN},
226                    {2, NAN},
227                    {INFINITY, NAN},
228 
229                    {NAN, -INFINITY},
230                    {-INFINITY, -INFINITY},
231                    {-2, -INFINITY},
232                    {-1, -INFINITY},
233                    {-0.5, -INFINITY},
234                    {-0., -INFINITY},
235                    {+0., -INFINITY},
236                    {0.5, -INFINITY},
237                    {1, -INFINITY},
238                    {2, -INFINITY},
239                    {INFINITY, -INFINITY},
240 
241                    {NAN, -2},
242                    {-INFINITY, -2},
243                    {-2, -2},
244                    {-1, -2},
245                    {-0.5, -2},
246                    {-0., -2},
247                    {+0., -2},
248                    {0.5, -2},
249                    {1, -2},
250                    {2, -2},
251                    {INFINITY, -2},
252 
253                    {NAN, -1},
254                    {-INFINITY, -1},
255                    {-2, -1},
256                    {-1, -1},
257                    {-0.5, -1},
258                    {-0., -1},
259                    {+0., -1},
260                    {0.5, -1},
261                    {1, -1},
262                    {2, -1},
263                    {INFINITY, -1},
264 
265                    {NAN, -0.5},
266                    {-INFINITY, -0.5},
267                    {-2, -0.5},
268                    {-1, -0.5},
269                    {-0.5, -0.5},
270                    {-0., -0.5},
271                    {+0., -0.5},
272                    {0.5, -0.5},
273                    {1, -0.5},
274                    {2, -0.5},
275                    {INFINITY, -0.5},
276 
277                    {NAN, -0.},
278                    {-INFINITY, -0.},
279                    {-2, -0.},
280                    {-1, -0.},
281                    {-0.5, -0.},
282                    {-0., -0.},
283                    {+0., -0.},
284                    {0.5, -0.},
285                    {1, -0.},
286                    {2, -0.},
287                    {INFINITY, -0.},
288 
289                    {NAN, 0.},
290                    {-INFINITY, 0.},
291                    {-2, 0.},
292                    {-1, 0.},
293                    {-0.5, 0.},
294                    {-0., 0.},
295                    {+0., 0.},
296                    {0.5, 0.},
297                    {1, 0.},
298                    {2, 0.},
299                    {INFINITY, 0.},
300 
301                    {NAN, 0.5},
302                    {-INFINITY, 0.5},
303                    {-2, 0.5},
304                    {-1, 0.5},
305                    {-0.5, 0.5},
306                    {-0., 0.5},
307                    {+0., 0.5},
308                    {0.5, 0.5},
309                    {1, 0.5},
310                    {2, 0.5},
311                    {INFINITY, 0.5},
312 
313                    {NAN, 1},
314                    {-INFINITY, 1},
315                    {-2, 1},
316                    {-1, 1},
317                    {-0.5, 1},
318                    {-0., 1},
319                    {+0., 1},
320                    {0.5, 1},
321                    {1, 1},
322                    {2, 1},
323                    {INFINITY, 1},
324 
325                    {NAN, 2},
326                    {-INFINITY, 2},
327                    {-2, 2},
328                    {-1, 2},
329                    {-0.5, 2},
330                    {-0., 2},
331                    {+0., 2},
332                    {0.5, 2},
333                    {1, 2},
334                    {2, 2},
335                    {INFINITY, 2},
336 
337                    {NAN, INFINITY},
338                    {-INFINITY, INFINITY},
339                    {-2, INFINITY},
340                    {-1, INFINITY},
341                    {-0.5, INFINITY},
342                    {-0., INFINITY},
343                    {+0., INFINITY},
344                    {0.5, INFINITY},
345                    {1, INFINITY},
346                    {2, INFINITY},
347                    {INFINITY, INFINITY}
348 
349 };
350 
main()351 int main() {
352   const unsigned N = sizeof(x) / sizeof(x[0]);
353   unsigned i, j;
354   for (i = 0; i < N; ++i) {
355     for (j = 0; j < N; ++j) {
356       if (test__divtc3(x[i][0], x[i][1], x[j][0], x[j][1])) {
357         fprintf(stderr, "Failed for %g, %g, %g, %g\n", (double)x[i][0],
358                 (double)x[i][1], (double)x[j][0], (double)x[j][1]);
359         return 1;
360       }
361     }
362   }
363 
364   fprintf(stderr, "No errors found.\n");
365   return 0;
366 }
367 
368 #else
369 
main()370 int main() {
371   printf("skipped\n");
372   return 0;
373 }
374 
375 #endif // CRT_HAS_TF_MODE
376