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
19COMPILER_RT_ABI Qcomplex __divtc3(tf_float __a, tf_float __b, tf_float __c,
20 tf_float __d);
21
22enum {zero, non_zero, inf, NaN, non_zero_nan};
23
24static 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
46static int test__divtc3(tf_float a, tf_float b, tf_float c, tf_float d) {
47 Qcomplex r = __divtc3(a: a, b: b, c: c, d: 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(x: dividend)) {
57 case zero:
58 switch (classify(x: divisor)) {
59 case zero:
60 if (classify(x: r) != NaN)
61 return 1;
62 break;
63 case non_zero:
64 if (classify(x: r) != zero)
65 return 1;
66 break;
67 case inf:
68 if (classify(x: r) != zero)
69 return 1;
70 break;
71 case NaN:
72 if (classify(x: r) != NaN)
73 return 1;
74 break;
75 case non_zero_nan:
76 if (classify(x: r) != NaN)
77 return 1;
78 break;
79 }
80 break;
81 case non_zero:
82 switch (classify(x: divisor)) {
83 case zero:
84 if (classify(x: r) != inf)
85 return 1;
86 break;
87 case non_zero:
88 if (classify(x: 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(x: r) != zero)
108 return 1;
109 break;
110 case NaN:
111 if (classify(x: r) != NaN)
112 return 1;
113 break;
114 case non_zero_nan:
115 if (classify(x: r) != NaN)
116 return 1;
117 break;
118 }
119 break;
120 case inf:
121 switch (classify(x: divisor)) {
122 case zero:
123 if (classify(x: r) != inf)
124 return 1;
125 break;
126 case non_zero:
127 if (classify(x: r) != inf)
128 return 1;
129 break;
130 case inf:
131 if (classify(x: r) != NaN)
132 return 1;
133 break;
134 case NaN:
135 if (classify(x: r) != NaN)
136 return 1;
137 break;
138 case non_zero_nan:
139 if (classify(x: r) != NaN)
140 return 1;
141 break;
142 }
143 break;
144 case NaN:
145 switch (classify(x: divisor)) {
146 case zero:
147 if (classify(x: r) != NaN)
148 return 1;
149 break;
150 case non_zero:
151 if (classify(x: r) != NaN)
152 return 1;
153 break;
154 case inf:
155 if (classify(x: r) != NaN)
156 return 1;
157 break;
158 case NaN:
159 if (classify(x: r) != NaN)
160 return 1;
161 break;
162 case non_zero_nan:
163 if (classify(x: r) != NaN)
164 return 1;
165 break;
166 }
167 break;
168 case non_zero_nan:
169 switch (classify(x: divisor)) {
170 case zero:
171 if (classify(x: r) != inf)
172 return 1;
173 break;
174 case non_zero:
175 if (classify(x: r) != NaN)
176 return 1;
177 break;
178 case inf:
179 if (classify(x: r) != NaN)
180 return 1;
181 break;
182 case NaN:
183 if (classify(x: r) != NaN)
184 return 1;
185 break;
186 case non_zero_nan:
187 if (classify(x: r) != NaN)
188 return 1;
189 break;
190 }
191 break;
192 }
193
194 return 0;
195}
196
197tf_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
351int 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(a: x[i][0], b: x[i][1], c: x[j][0], d: x[j][1])) {
357 fprintf(stderr, format: "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, format: "No errors found.\n");
365 return 0;
366}
367
368#else
369
370int main() {
371 printf("skipped\n");
372 return 0;
373}
374
375#endif // CRT_HAS_TF_MODE
376

source code of compiler-rt/test/builtins/Unit/divtc3_test.c