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

source code of compiler-rt/test/builtins/Unit/mulxc3_test.c