1// RUN: %clang_builtins %s %librt -lm -o %t && %run %t
2// REQUIRES: x86-target-arch
3// UNSUPPORTED: powerpc64
4//===-- divxc3_test.c - Test __divxc3 -------------------------------------===//
5//
6// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
7// See https://llvm.org/LICENSE.txt for license information.
8// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
9//
10//===----------------------------------------------------------------------===//
11//
12// This file tests __divxc3 for the compiler_rt library.
13//
14//===----------------------------------------------------------------------===//
15
16#if !_ARCH_PPC
17
18#include "int_lib.h"
19#include <math.h>
20#include <complex.h>
21#include <stdio.h>
22
23// UNSUPPORTED: mips
24// REQUIRES: c99-complex
25
26// Returns: the quotient of (a + ib) / (c + id)
27
28COMPILER_RT_ABI long double _Complex
29__divxc3(long double __a, long double __b, long double __c, long double __d);
30
31enum {zero, non_zero, inf, NaN, non_zero_nan};
32
33int
34classify(long double _Complex x)
35{
36    if (x == 0)
37        return zero;
38    if (isinf(creall(x)) || isinf(cimagl(x)))
39        return inf;
40    if (isnan(creall(x)) && isnan(cimagl(x)))
41        return NaN;
42    if (isnan(creall(x)))
43    {
44        if (cimagl(x) == 0)
45            return NaN;
46        return non_zero_nan;
47    }
48    if (isnan(cimagl(x)))
49    {
50        if (creall(x) == 0)
51            return NaN;
52        return non_zero_nan;
53    }
54    return non_zero;
55}
56
57int test__divxc3(long double a, long double b, long double c, long double d)
58{
59    long double _Complex r = __divxc3(a, b, c, d);
60//     printf("test__divxc3(%Lf, %Lf, %Lf, %Lf) = %Lf + I%Lf\n",
61//             a, b, c, d, creall(r), cimagl(r));
62	long double _Complex dividend;
63	long double _Complex divisor;
64
65	__real__ dividend = a;
66	__imag__ dividend = b;
67	__real__ divisor = c;
68	__imag__ divisor = d;
69
70    switch (classify(dividend))
71    {
72    case zero:
73        switch (classify(divisor))
74        {
75        case zero:
76            if (classify(r) != NaN)
77                return 1;
78            break;
79        case non_zero:
80            if (classify(r) != zero)
81                return 1;
82            break;
83        case inf:
84            if (classify(r) != zero)
85                return 1;
86            break;
87        case NaN:
88            if (classify(r) != NaN)
89                return 1;
90            break;
91        case non_zero_nan:
92            if (classify(r) != NaN)
93                return 1;
94            break;
95        }
96        break;
97    case non_zero:
98        switch (classify(divisor))
99        {
100        case zero:
101            if (classify(r) != inf)
102                return 1;
103            break;
104        case non_zero:
105            if (classify(r) != non_zero)
106                return 1;
107            {
108            long double _Complex z = (a * c + b * d) / (c * c + d * d)
109                                   + (b * c - a * d) / (c * c + d * d) * _Complex_I;
110            if (cabs((r - z)/r) > 1.e-6)
111                return 1;
112            }
113            break;
114        case inf:
115            if (classify(r) != zero)
116                return 1;
117            break;
118        case NaN:
119            if (classify(r) != NaN)
120                return 1;
121            break;
122        case non_zero_nan:
123            if (classify(r) != NaN)
124                return 1;
125            break;
126        }
127        break;
128    case inf:
129        switch (classify(divisor))
130        {
131        case zero:
132            if (classify(r) != inf)
133                return 1;
134            break;
135        case non_zero:
136            if (classify(r) != inf)
137                return 1;
138            break;
139        case inf:
140            if (classify(r) != NaN)
141                return 1;
142            break;
143        case NaN:
144            if (classify(r) != NaN)
145                return 1;
146            break;
147        case non_zero_nan:
148            if (classify(r) != NaN)
149                return 1;
150            break;
151        }
152        break;
153    case NaN:
154        switch (classify(divisor))
155        {
156        case zero:
157            if (classify(r) != NaN)
158                return 1;
159            break;
160        case non_zero:
161            if (classify(r) != NaN)
162                return 1;
163            break;
164        case inf:
165            if (classify(r) != NaN)
166                return 1;
167            break;
168        case NaN:
169            if (classify(r) != NaN)
170                return 1;
171            break;
172        case non_zero_nan:
173            if (classify(r) != NaN)
174                return 1;
175            break;
176        }
177        break;
178    case non_zero_nan:
179        switch (classify(divisor))
180        {
181        case zero:
182            if (classify(r) != inf)
183                return 1;
184            break;
185        case non_zero:
186            if (classify(r) != NaN)
187                return 1;
188            break;
189        case inf:
190            if (classify(r) != NaN)
191                return 1;
192            break;
193        case NaN:
194            if (classify(r) != NaN)
195                return 1;
196            break;
197        case non_zero_nan:
198            if (classify(r) != NaN)
199                return 1;
200            break;
201        }
202        break;
203    }
204
205    return 0;
206}
207
208long double x[][2] =
209{
210    { 1.e-6,  1.e-6},
211    {-1.e-6,  1.e-6},
212    {-1.e-6, -1.e-6},
213    { 1.e-6, -1.e-6},
214
215    { 1.e+6,  1.e-6},
216    {-1.e+6,  1.e-6},
217    {-1.e+6, -1.e-6},
218    { 1.e+6, -1.e-6},
219
220    { 1.e-6,  1.e+6},
221    {-1.e-6,  1.e+6},
222    {-1.e-6, -1.e+6},
223    { 1.e-6, -1.e+6},
224
225    { 1.e+6,  1.e+6},
226    {-1.e+6,  1.e+6},
227    {-1.e+6, -1.e+6},
228    { 1.e+6, -1.e+6},
229
230    {NAN, NAN},
231    {-INFINITY, NAN},
232    {-2, NAN},
233    {-1, NAN},
234    {-0.5, NAN},
235    {-0., NAN},
236    {+0., NAN},
237    {0.5, NAN},
238    {1, NAN},
239    {2, NAN},
240    {INFINITY, NAN},
241
242    {NAN, -INFINITY},
243    {-INFINITY, -INFINITY},
244    {-2, -INFINITY},
245    {-1, -INFINITY},
246    {-0.5, -INFINITY},
247    {-0., -INFINITY},
248    {+0., -INFINITY},
249    {0.5, -INFINITY},
250    {1, -INFINITY},
251    {2, -INFINITY},
252    {INFINITY, -INFINITY},
253
254    {NAN, -2},
255    {-INFINITY, -2},
256    {-2, -2},
257    {-1, -2},
258    {-0.5, -2},
259    {-0., -2},
260    {+0., -2},
261    {0.5, -2},
262    {1, -2},
263    {2, -2},
264    {INFINITY, -2},
265
266    {NAN, -1},
267    {-INFINITY, -1},
268    {-2, -1},
269    {-1, -1},
270    {-0.5, -1},
271    {-0., -1},
272    {+0., -1},
273    {0.5, -1},
274    {1, -1},
275    {2, -1},
276    {INFINITY, -1},
277
278    {NAN, -0.5},
279    {-INFINITY, -0.5},
280    {-2, -0.5},
281    {-1, -0.5},
282    {-0.5, -0.5},
283    {-0., -0.5},
284    {+0., -0.5},
285    {0.5, -0.5},
286    {1, -0.5},
287    {2, -0.5},
288    {INFINITY, -0.5},
289
290    {NAN, -0.},
291    {-INFINITY, -0.},
292    {-2, -0.},
293    {-1, -0.},
294    {-0.5, -0.},
295    {-0., -0.},
296    {+0., -0.},
297    {0.5, -0.},
298    {1, -0.},
299    {2, -0.},
300    {INFINITY, -0.},
301
302    {NAN, 0.},
303    {-INFINITY, 0.},
304    {-2, 0.},
305    {-1, 0.},
306    {-0.5, 0.},
307    {-0., 0.},
308    {+0., 0.},
309    {0.5, 0.},
310    {1, 0.},
311    {2, 0.},
312    {INFINITY, 0.},
313
314    {NAN, 0.5},
315    {-INFINITY, 0.5},
316    {-2, 0.5},
317    {-1, 0.5},
318    {-0.5, 0.5},
319    {-0., 0.5},
320    {+0., 0.5},
321    {0.5, 0.5},
322    {1, 0.5},
323    {2, 0.5},
324    {INFINITY, 0.5},
325
326    {NAN, 1},
327    {-INFINITY, 1},
328    {-2, 1},
329    {-1, 1},
330    {-0.5, 1},
331    {-0., 1},
332    {+0., 1},
333    {0.5, 1},
334    {1, 1},
335    {2, 1},
336    {INFINITY, 1},
337
338    {NAN, 2},
339    {-INFINITY, 2},
340    {-2, 2},
341    {-1, 2},
342    {-0.5, 2},
343    {-0., 2},
344    {+0., 2},
345    {0.5, 2},
346    {1, 2},
347    {2, 2},
348    {INFINITY, 2},
349
350    {NAN, INFINITY},
351    {-INFINITY, INFINITY},
352    {-2, INFINITY},
353    {-1, INFINITY},
354    {-0.5, INFINITY},
355    {-0., INFINITY},
356    {+0., INFINITY},
357    {0.5, INFINITY},
358    {1, INFINITY},
359    {2, INFINITY},
360    {INFINITY, INFINITY}
361
362};
363
364#endif
365
366int main()
367{
368#if !_ARCH_PPC
369    const unsigned N = sizeof(x) / sizeof(x[0]);
370    unsigned i, j;
371    for (i = 0; i < N; ++i)
372    {
373        for (j = 0; j < N; ++j)
374        {
375            if (test__divxc3(x[i][0], x[i][1], x[j][0], x[j][1]))
376                return 1;
377        }
378    }
379
380#else
381    printf("skipped\n");
382#endif
383    return 0;
384}
385