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