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