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