11638Srgrimes// RUN: %clang_builtins %s %librt -o %t && %run %t
21638Srgrimes//===-- multc3_test.c - Test __multc3 -------------------------------------===//
31638Srgrimes//
41638Srgrimes// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
51638Srgrimes// See https://llvm.org/LICENSE.txt for license information.
61638Srgrimes// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
71638Srgrimes//
81638Srgrimes//===----------------------------------------------------------------------===//
91638Srgrimes//
101638Srgrimes// This file tests __multc3 for the compiler_rt library.
111638Srgrimes//
121638Srgrimes//===----------------------------------------------------------------------===//
131638Srgrimes
141638Srgrimes#include <stdio.h>
151638Srgrimes
161638Srgrimes#if _ARCH_PPC || __aarch64__
171638Srgrimes
181638Srgrimes#include "int_lib.h"
191638Srgrimes#include <math.h>
201638Srgrimes#include <complex.h>
211638Srgrimes
221638Srgrimes// Returns: the product of a + ib and c + id
231638Srgrimes
241638SrgrimesCOMPILER_RT_ABI long double _Complex
251638Srgrimes__multc3(long double __a, long double __b, long double __c, long double __d);
261638Srgrimes
271638Srgrimesenum {zero, non_zero, inf, NaN, non_zero_nan};
281638Srgrimes
291638Srgrimesint
301638Srgrimesclassify(long double _Complex x)
311638Srgrimes{
321638Srgrimes    if (x == 0)
331638Srgrimes        return zero;
341638Srgrimes    if (isinf(creall(x)) || isinf(cimagl(x)))
351638Srgrimes        return inf;
361638Srgrimes    if (isnan(creall(x)) && isnan(cimagl(x)))
371638Srgrimes        return NaN;
381638Srgrimes    if (isnan(creall(x)))
391638Srgrimes    {
401638Srgrimes        if (cimagl(x) == 0)
411638Srgrimes            return NaN;
421638Srgrimes        return non_zero_nan;
431638Srgrimes    }
441638Srgrimes    if (isnan(cimagl(x)))
451638Srgrimes    {
461638Srgrimes        if (creall(x) == 0)
471638Srgrimes            return NaN;
481638Srgrimes        return non_zero_nan;
491638Srgrimes    }
501638Srgrimes    return non_zero;
511638Srgrimes}
521638Srgrimes
531638Srgrimesint test__multc3(long double a, long double b, long double c, long double d)
541638Srgrimes{
551638Srgrimes    long double _Complex r = __multc3(a, b, c, d);
561638Srgrimes//     printf("test__multc3(%Lf, %Lf, %Lf, %Lf) = %Lf + I%Lf\n",
571638Srgrimes//             a, b, c, d, creall(r), cimagl(r));
581638Srgrimes	long double _Complex dividend;
591638Srgrimes	long double _Complex divisor;
601638Srgrimes
611638Srgrimes	__real__ dividend = a;
621638Srgrimes	__imag__ dividend = b;
631638Srgrimes	__real__ divisor = c;
641638Srgrimes	__imag__ divisor = d;
651638Srgrimes
661638Srgrimes    switch (classify(dividend))
671638Srgrimes    {
681638Srgrimes    case zero:
691638Srgrimes        switch (classify(divisor))
701638Srgrimes        {
711638Srgrimes        case zero:
721638Srgrimes            if (classify(r) != zero)
731638Srgrimes                return 1;
741638Srgrimes            break;
751638Srgrimes        case non_zero:
761638Srgrimes            if (classify(r) != zero)
771638Srgrimes                return 1;
781638Srgrimes            break;
791638Srgrimes        case inf:
801638Srgrimes            if (classify(r) != NaN)
811638Srgrimes                return 1;
821638Srgrimes            break;
831638Srgrimes        case NaN:
841638Srgrimes            if (classify(r) != NaN)
851638Srgrimes                return 1;
861638Srgrimes            break;
871638Srgrimes        case non_zero_nan:
881638Srgrimes            if (classify(r) != NaN)
891638Srgrimes                return 1;
901638Srgrimes            break;
911638Srgrimes        }
921638Srgrimes        break;
931638Srgrimes    case non_zero:
94        switch (classify(divisor))
95        {
96        case zero:
97            if (classify(r) != zero)
98                return 1;
99            break;
100        case non_zero:
101            if (classify(r) != non_zero)
102                return 1;
103            if (r != a * c - b * d + _Complex_I*(a * d + b * c))
104                return 1;
105            break;
106        case inf:
107            if (classify(r) != inf)
108                return 1;
109            break;
110        case NaN:
111            if (classify(r) != NaN)
112                return 1;
113            break;
114        case non_zero_nan:
115            if (classify(r) != NaN)
116                return 1;
117            break;
118        }
119        break;
120    case inf:
121        switch (classify(divisor))
122        {
123        case zero:
124            if (classify(r) != NaN)
125                return 1;
126            break;
127        case non_zero:
128            if (classify(r) != inf)
129                return 1;
130            break;
131        case inf:
132            if (classify(r) != inf)
133                return 1;
134            break;
135        case NaN:
136            if (classify(r) != NaN)
137                return 1;
138            break;
139        case non_zero_nan:
140            if (classify(r) != inf)
141                return 1;
142            break;
143        }
144        break;
145    case NaN:
146        switch (classify(divisor))
147        {
148        case zero:
149            if (classify(r) != NaN)
150                return 1;
151            break;
152        case non_zero:
153            if (classify(r) != NaN)
154                return 1;
155            break;
156        case inf:
157            if (classify(r) != NaN)
158                return 1;
159            break;
160        case NaN:
161            if (classify(r) != NaN)
162                return 1;
163            break;
164        case non_zero_nan:
165            if (classify(r) != NaN)
166                return 1;
167            break;
168        }
169        break;
170    case non_zero_nan:
171        switch (classify(divisor))
172        {
173        case zero:
174            if (classify(r) != NaN)
175                return 1;
176            break;
177        case non_zero:
178            if (classify(r) != NaN)
179                return 1;
180            break;
181        case inf:
182            if (classify(r) != inf)
183                return 1;
184            break;
185        case NaN:
186            if (classify(r) != NaN)
187                return 1;
188            break;
189        case non_zero_nan:
190            if (classify(r) != NaN)
191                return 1;
192            break;
193        }
194        break;
195    }
196
197    return 0;
198}
199
200long double x[][2] =
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    { 1.e+6,  1.e+6},
218    {-1.e+6,  1.e+6},
219    {-1.e+6, -1.e+6},
220    { 1.e+6, -1.e+6},
221
222    {NAN, NAN},
223    {-INFINITY, NAN},
224    {-2, NAN},
225    {-1, NAN},
226    {-0.5, NAN},
227    {-0., NAN},
228    {+0., NAN},
229    {0.5, NAN},
230    {1, NAN},
231    {2, NAN},
232    {INFINITY, NAN},
233
234    {NAN, -INFINITY},
235    {-INFINITY, -INFINITY},
236    {-2, -INFINITY},
237    {-1, -INFINITY},
238    {-0.5, -INFINITY},
239    {-0., -INFINITY},
240    {+0., -INFINITY},
241    {0.5, -INFINITY},
242    {1, -INFINITY},
243    {2, -INFINITY},
244    {INFINITY, -INFINITY},
245
246    {NAN, -2},
247    {-INFINITY, -2},
248    {-2, -2},
249    {-1, -2},
250    {-0.5, -2},
251    {-0., -2},
252    {+0., -2},
253    {0.5, -2},
254    {1, -2},
255    {2, -2},
256    {INFINITY, -2},
257
258    {NAN, -1},
259    {-INFINITY, -1},
260    {-2, -1},
261    {-1, -1},
262    {-0.5, -1},
263    {-0., -1},
264    {+0., -1},
265    {0.5, -1},
266    {1, -1},
267    {2, -1},
268    {INFINITY, -1},
269
270    {NAN, -0.5},
271    {-INFINITY, -0.5},
272    {-2, -0.5},
273    {-1, -0.5},
274    {-0.5, -0.5},
275    {-0., -0.5},
276    {+0., -0.5},
277    {0.5, -0.5},
278    {1, -0.5},
279    {2, -0.5},
280    {INFINITY, -0.5},
281
282    {NAN, -0.},
283    {-INFINITY, -0.},
284    {-2, -0.},
285    {-1, -0.},
286    {-0.5, -0.},
287    {-0., -0.},
288    {+0., -0.},
289    {0.5, -0.},
290    {1, -0.},
291    {2, -0.},
292    {INFINITY, -0.},
293
294    {NAN, 0.},
295    {-INFINITY, 0.},
296    {-2, 0.},
297    {-1, 0.},
298    {-0.5, 0.},
299    {-0., 0.},
300    {+0., 0.},
301    {0.5, 0.},
302    {1, 0.},
303    {2, 0.},
304    {INFINITY, 0.},
305
306    {NAN, 0.5},
307    {-INFINITY, 0.5},
308    {-2, 0.5},
309    {-1, 0.5},
310    {-0.5, 0.5},
311    {-0., 0.5},
312    {+0., 0.5},
313    {0.5, 0.5},
314    {1, 0.5},
315    {2, 0.5},
316    {INFINITY, 0.5},
317
318    {NAN, 1},
319    {-INFINITY, 1},
320    {-2, 1},
321    {-1, 1},
322    {-0.5, 1},
323    {-0., 1},
324    {+0., 1},
325    {0.5, 1},
326    {1, 1},
327    {2, 1},
328    {INFINITY, 1},
329
330    {NAN, 2},
331    {-INFINITY, 2},
332    {-2, 2},
333    {-1, 2},
334    {-0.5, 2},
335    {-0., 2},
336    {+0., 2},
337    {0.5, 2},
338    {1, 2},
339    {2, 2},
340    {INFINITY, 2},
341
342    {NAN, INFINITY},
343    {-INFINITY, INFINITY},
344    {-2, INFINITY},
345    {-1, INFINITY},
346    {-0.5, INFINITY},
347    {-0., INFINITY},
348    {+0., INFINITY},
349    {0.5, INFINITY},
350    {1, INFINITY},
351    {2, INFINITY},
352    {INFINITY, INFINITY}
353
354};
355
356#endif
357
358int main()
359{
360#if _ARCH_PPC || __aarch64__
361    const unsigned N = sizeof(x) / sizeof(x[0]);
362    unsigned i, j;
363    for (i = 0; i < N; ++i)
364    {
365        for (j = 0; j < N; ++j)
366        {
367            if (test__multc3(x[i][0], x[i][1], x[j][0], x[j][1]))
368                return 1;
369        }
370    }
371#else
372    printf("skipped\n");
373#endif
374    return 0;
375}
376