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