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
21COMPILER_RT_ABI float _Complex
22__mulsc3(float __a, float __b, float __c, float __d);
23
24enum {zero, non_zero, inf, NaN, non_zero_nan};
25
26int
27classify(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
50int 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
201float 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
357int 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