1// RUN: %clang_builtins %s %librt -lm -o %t && %run %t
2// REQUIRES: librt_has_mulsc3
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 float _Complex
14__mulsc3(float __a, float __b, float __c, float __d);
15
16enum {zero, non_zero, inf, NaN, non_zero_nan};
17
18int
19classify(float _Complex x)
20{
21 if (x == 0)
22 return zero;
23 if (isinf(crealf(x)) || isinf(cimagf(x)))
24 return inf;
25 if (isnan(crealf(x)) && isnan(cimagf(x)))
26 return NaN;
27 if (isnan(crealf(x)))
28 {
29 if (cimagf(x) == 0)
30 return NaN;
31 return non_zero_nan;
32 }
33 if (isnan(cimagf(x)))
34 {
35 if (crealf(x) == 0)
36 return NaN;
37 return non_zero_nan;
38 }
39 return non_zero;
40}
41
42int test__mulsc3(float a, float b, float c, float d)
43{
44 float _Complex r = __mulsc3(a, b, c, d);
45// printf("test__mulsc3(%f, %f, %f, %f) = %f + I%f\n",
46// a, b, c, d, crealf(r), cimagf(r));
47 float _Complex dividend;
48 float _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 {
93 float _Complex z = a * c - b * d + _Complex_I*(a * d + b * c);
94 // relaxed tolerance to arbitrary (1.e-6) amount.
95 if (cabsf((r-z)/r) > 1.e-6)
96 return 1;
97 }
98 break;
99 case inf:
100 if (classify(r) != inf)
101 return 1;
102 break;
103 case NaN:
104 if (classify(r) != NaN)
105 return 1;
106 break;
107 case non_zero_nan:
108 if (classify(r) != NaN)
109 return 1;
110 break;
111 }
112 break;
113 case inf:
114 switch (classify(divisor))
115 {
116 case zero:
117 if (classify(r) != NaN)
118 return 1;
119 break;
120 case non_zero:
121 if (classify(r) != inf)
122 return 1;
123 break;
124 case inf:
125 if (classify(r) != inf)
126 return 1;
127 break;
128 case NaN:
129 if (classify(r) != NaN)
130 return 1;
131 break;
132 case non_zero_nan:
133 if (classify(r) != inf)
134 return 1;
135 break;
136 }
137 break;
138 case NaN:
139 switch (classify(divisor))
140 {
141 case zero:
142 if (classify(r) != NaN)
143 return 1;
144 break;
145 case non_zero:
146 if (classify(r) != NaN)
147 return 1;
148 break;
149 case inf:
150 if (classify(r) != NaN)
151 return 1;
152 break;
153 case NaN:
154 if (classify(r) != NaN)
155 return 1;
156 break;
157 case non_zero_nan:
158 if (classify(r) != NaN)
159 return 1;
160 break;
161 }
162 break;
163 case non_zero_nan:
164 switch (classify(divisor))
165 {
166 case zero:
167 if (classify(r) != NaN)
168 return 1;
169 break;
170 case non_zero:
171 if (classify(r) != NaN)
172 return 1;
173 break;
174 case inf:
175 if (classify(r) != inf)
176 return 1;
177 break;
178 case NaN:
179 if (classify(r) != NaN)
180 return 1;
181 break;
182 case non_zero_nan:
183 if (classify(r) != NaN)
184 return 1;
185 break;
186 }
187 break;
188 }
189
190 return 0;
191}
192
193float x[][2] =
194{
195 { 1.e-6, 1.e-6},
196 {-1.e-6, 1.e-6},
197 {-1.e-6, -1.e-6},
198 { 1.e-6, -1.e-6},
199
200 { 1.e+6, 1.e-6},
201 {-1.e+6, 1.e-6},
202 {-1.e+6, -1.e-6},
203 { 1.e+6, -1.e-6},
204
205 { 1.e-6, 1.e+6},
206 {-1.e-6, 1.e+6},
207 {-1.e-6, -1.e+6},
208 { 1.e-6, -1.e+6},
209
210 { 1.e+6, 1.e+6},
211 {-1.e+6, 1.e+6},
212 {-1.e+6, -1.e+6},
213 { 1.e+6, -1.e+6},
214
215 {NAN, NAN},
216 {-INFINITY, NAN},
217 {-2, NAN},
218 {-1, NAN},
219 {-0.5, NAN},
220 {-0., NAN},
221 {+0., NAN},
222 {0.5, NAN},
223 {1, NAN},
224 {2, NAN},
225 {INFINITY, NAN},
226
227 {NAN, -INFINITY},
228 {-INFINITY, -INFINITY},
229 {-2, -INFINITY},
230 {-1, -INFINITY},
231 {-0.5, -INFINITY},
232 {-0., -INFINITY},
233 {+0., -INFINITY},
234 {0.5, -INFINITY},
235 {1, -INFINITY},
236 {2, -INFINITY},
237 {INFINITY, -INFINITY},
238
239 {NAN, -2},
240 {-INFINITY, -2},
241 {-2, -2},
242 {-1, -2},
243 {-0.5, -2},
244 {-0., -2},
245 {+0., -2},
246 {0.5, -2},
247 {1, -2},
248 {2, -2},
249 {INFINITY, -2},
250
251 {NAN, -1},
252 {-INFINITY, -1},
253 {-2, -1},
254 {-1, -1},
255 {-0.5, -1},
256 {-0., -1},
257 {+0., -1},
258 {0.5, -1},
259 {1, -1},
260 {2, -1},
261 {INFINITY, -1},
262
263 {NAN, -0.5},
264 {-INFINITY, -0.5},
265 {-2, -0.5},
266 {-1, -0.5},
267 {-0.5, -0.5},
268 {-0., -0.5},
269 {+0., -0.5},
270 {0.5, -0.5},
271 {1, -0.5},
272 {2, -0.5},
273 {INFINITY, -0.5},
274
275 {NAN, -0.},
276 {-INFINITY, -0.},
277 {-2, -0.},
278 {-1, -0.},
279 {-0.5, -0.},
280 {-0., -0.},
281 {+0., -0.},
282 {0.5, -0.},
283 {1, -0.},
284 {2, -0.},
285 {INFINITY, -0.},
286
287 {NAN, 0.},
288 {-INFINITY, 0.},
289 {-2, 0.},
290 {-1, 0.},
291 {-0.5, 0.},
292 {-0., 0.},
293 {+0., 0.},
294 {0.5, 0.},
295 {1, 0.},
296 {2, 0.},
297 {INFINITY, 0.},
298
299 {NAN, 0.5},
300 {-INFINITY, 0.5},
301 {-2, 0.5},
302 {-1, 0.5},
303 {-0.5, 0.5},
304 {-0., 0.5},
305 {+0., 0.5},
306 {0.5, 0.5},
307 {1, 0.5},
308 {2, 0.5},
309 {INFINITY, 0.5},
310
311 {NAN, 1},
312 {-INFINITY, 1},
313 {-2, 1},
314 {-1, 1},
315 {-0.5, 1},
316 {-0., 1},
317 {+0., 1},
318 {0.5, 1},
319 {1, 1},
320 {2, 1},
321 {INFINITY, 1},
322
323 {NAN, 2},
324 {-INFINITY, 2},
325 {-2, 2},
326 {-1, 2},
327 {-0.5, 2},
328 {-0., 2},
329 {+0., 2},
330 {0.5, 2},
331 {1, 2},
332 {2, 2},
333 {INFINITY, 2},
334
335 {NAN, INFINITY},
336 {-INFINITY, INFINITY},
337 {-2, INFINITY},
338 {-1, INFINITY},
339 {-0.5, INFINITY},
340 {-0., INFINITY},
341 {+0., INFINITY},
342 {0.5, INFINITY},
343 {1, INFINITY},
344 {2, INFINITY},
345 {INFINITY, INFINITY}
346
347};
348
349int main()
350{
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__mulsc3(x[i][0], x[i][1], x[j][0], x[j][1]))
358 return 1;
359 }
360 }
361
362 return 0;
363}
364