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