1214152Sed/* ===-- muldc3.c - Implement __muldc3 -------------------------------------===
2214152Sed *
3214152Sed *                     The LLVM Compiler Infrastructure
4214152Sed *
5222656Sed * This file is dual licensed under the MIT and the University of Illinois Open
6222656Sed * Source Licenses. See LICENSE.TXT for details.
7214152Sed *
8214152Sed * ===----------------------------------------------------------------------===
9214152Sed *
10214152Sed * This file implements __muldc3 for the compiler_rt library.
11214152Sed *
12214152Sed * ===----------------------------------------------------------------------===
13214152Sed */
14214152Sed
15214152Sed#include "int_lib.h"
16236011Smarius#include "int_math.h"
17214152Sed
18214152Sed/* Returns: the product of a + ib and c + id */
19214152Sed
20214152Seddouble _Complex
21214152Sed__muldc3(double __a, double __b, double __c, double __d)
22214152Sed{
23214152Sed    double __ac = __a * __c;
24214152Sed    double __bd = __b * __d;
25214152Sed    double __ad = __a * __d;
26214152Sed    double __bc = __b * __c;
27214152Sed    double _Complex z;
28214152Sed    __real__ z = __ac - __bd;
29214152Sed    __imag__ z = __ad + __bc;
30236011Smarius    if (crt_isnan(__real__ z) && crt_isnan(__imag__ z))
31214152Sed    {
32214152Sed        int __recalc = 0;
33236011Smarius        if (crt_isinf(__a) || crt_isinf(__b))
34214152Sed        {
35236011Smarius            __a = crt_copysign(crt_isinf(__a) ? 1 : 0, __a);
36236011Smarius            __b = crt_copysign(crt_isinf(__b) ? 1 : 0, __b);
37236011Smarius            if (crt_isnan(__c))
38236011Smarius                __c = crt_copysign(0, __c);
39236011Smarius            if (crt_isnan(__d))
40236011Smarius                __d = crt_copysign(0, __d);
41214152Sed            __recalc = 1;
42214152Sed        }
43236011Smarius        if (crt_isinf(__c) || crt_isinf(__d))
44214152Sed        {
45236011Smarius            __c = crt_copysign(crt_isinf(__c) ? 1 : 0, __c);
46236011Smarius            __d = crt_copysign(crt_isinf(__d) ? 1 : 0, __d);
47236011Smarius            if (crt_isnan(__a))
48236011Smarius                __a = crt_copysign(0, __a);
49236011Smarius            if (crt_isnan(__b))
50236011Smarius                __b = crt_copysign(0, __b);
51214152Sed            __recalc = 1;
52214152Sed        }
53236011Smarius        if (!__recalc && (crt_isinf(__ac) || crt_isinf(__bd) ||
54236011Smarius                          crt_isinf(__ad) || crt_isinf(__bc)))
55214152Sed        {
56236011Smarius            if (crt_isnan(__a))
57236011Smarius                __a = crt_copysign(0, __a);
58236011Smarius            if (crt_isnan(__b))
59236011Smarius                __b = crt_copysign(0, __b);
60236011Smarius            if (crt_isnan(__c))
61236011Smarius                __c = crt_copysign(0, __c);
62236011Smarius            if (crt_isnan(__d))
63236011Smarius                __d = crt_copysign(0, __d);
64214152Sed            __recalc = 1;
65214152Sed        }
66214152Sed        if (__recalc)
67214152Sed        {
68236011Smarius            __real__ z = CRT_INFINITY * (__a * __c - __b * __d);
69236011Smarius            __imag__ z = CRT_INFINITY * (__a * __d + __b * __c);
70214152Sed        }
71214152Sed    }
72214152Sed    return z;
73214152Sed}
74