]> CyberLeo.Net >> Repos - FreeBSD/releng/9.0.git/blob - contrib/compiler-rt/lib/muldc3.c
Copy stable/9 to releng/9.0 as part of the FreeBSD 9.0-RELEASE release
[FreeBSD/releng/9.0.git] / contrib / compiler-rt / lib / muldc3.c
1 /* ===-- muldc3.c - Implement __muldc3 -------------------------------------===
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 __muldc3 for the compiler_rt library.
11  *
12  * ===----------------------------------------------------------------------===
13  */
14
15 #include "int_lib.h"
16 #include <math.h>
17 #include <complex.h>
18
19 /* Returns: the product of a + ib and c + id */
20
21 double _Complex
22 __muldc3(double __a, double __b, double __c, double __d)
23 {
24     double __ac = __a * __c;
25     double __bd = __b * __d;
26     double __ad = __a * __d;
27     double __bc = __b * __c;
28     double _Complex z;
29     __real__ z = __ac - __bd;
30     __imag__ z = __ad + __bc;
31     if (isnan(__real__ z) && isnan(__imag__ z))
32     {
33         int __recalc = 0;
34         if (isinf(__a) || isinf(__b))
35         {
36             __a = copysign(isinf(__a) ? 1 : 0, __a);
37             __b = copysign(isinf(__b) ? 1 : 0, __b);
38             if (isnan(__c))
39                 __c = copysign(0, __c);
40             if (isnan(__d))
41                 __d = copysign(0, __d);
42             __recalc = 1;
43         }
44         if (isinf(__c) || isinf(__d))
45         {
46             __c = copysign(isinf(__c) ? 1 : 0, __c);
47             __d = copysign(isinf(__d) ? 1 : 0, __d);
48             if (isnan(__a))
49                 __a = copysign(0, __a);
50             if (isnan(__b))
51                 __b = copysign(0, __b);
52             __recalc = 1;
53         }
54         if (!__recalc && (isinf(__ac) || isinf(__bd) ||
55                           isinf(__ad) || isinf(__bc)))
56         {
57             if (isnan(__a))
58                 __a = copysign(0, __a);
59             if (isnan(__b))
60                 __b = copysign(0, __b);
61             if (isnan(__c))
62                 __c = copysign(0, __c);
63             if (isnan(__d))
64                 __d = copysign(0, __d);
65             __recalc = 1;
66         }
67         if (__recalc)
68         {
69             __real__ z = INFINITY * (__a * __c - __b * __d);
70             __imag__ z = INFINITY * (__a * __d + __b * __c);
71         }
72     }
73     return z;
74 }