1/* ===-- multc3.c - Implement __multc3 -------------------------------------===
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 implements __multc3 for the compiler_rt library.
11 *
12 * ===----------------------------------------------------------------------===
13 */
14
15#include "int_lib.h"
16#include "int_math.h"
17
18/* Returns: the product of a + ib and c + id */
19
20COMPILER_RT_ABI long double _Complex
21__multc3(long double a, long double b, long double c, long double d)
22{
23    long double ac = a * c;
24    long double bd = b * d;
25    long double ad = a * d;
26    long double bc = b * c;
27    long double _Complex z;
28    __real__ z = ac - bd;
29    __imag__ z = ad + bc;
30    if (crt_isnan(__real__ z) && crt_isnan(__imag__ z)) {
31        int recalc = 0;
32        if (crt_isinf(a) || crt_isinf(b)) {
33            a = crt_copysignl(crt_isinf(a) ? 1 : 0, a);
34            b = crt_copysignl(crt_isinf(b) ? 1 : 0, b);
35            if (crt_isnan(c))
36                c = crt_copysignl(0, c);
37            if (crt_isnan(d))
38                d = crt_copysignl(0, d);
39            recalc = 1;
40        }
41        if (crt_isinf(c) || crt_isinf(d)) {
42            c = crt_copysignl(crt_isinf(c) ? 1 : 0, c);
43            d = crt_copysignl(crt_isinf(d) ? 1 : 0, d);
44            if (crt_isnan(a))
45                a = crt_copysignl(0, a);
46            if (crt_isnan(b))
47                b = crt_copysignl(0, b);
48            recalc = 1;
49        }
50        if (!recalc && (crt_isinf(ac) || crt_isinf(bd) ||
51                          crt_isinf(ad) || crt_isinf(bc))) {
52            if (crt_isnan(a))
53                a = crt_copysignl(0, a);
54            if (crt_isnan(b))
55                b = crt_copysignl(0, b);
56            if (crt_isnan(c))
57                c = crt_copysignl(0, c);
58            if (crt_isnan(d))
59                d = crt_copysignl(0, d);
60            recalc = 1;
61        }
62        if (recalc) {
63            __real__ z = CRT_INFINITY * (a * c - b * d);
64            __imag__ z = CRT_INFINITY * (a * d + b * c);
65        }
66    }
67    return z;
68}
69