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
13COMPILER_RT_ABI double _Complex
14__muldc3(double __a, double __b, double __c, double __d);
15
16enum {zero, non_zero, inf, NaN, non_zero_nan};
17
18int
19classify(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
42int 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
189double 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
345int 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