blob: d04a901741815f8f4a23a7f8b2af4baced9ab5b6 [file] [log] [blame]
Edward O'Callaghan33c13472009-08-08 04:43:56 +00001/* This file is distributed under the University of Illinois Open Source
2 * License. See LICENSE.TXT for details.
3 */
Daniel Dunbarb3a69012009-06-26 16:47:03 +00004
5#include "DD.h"
Daniel Dunbar86030242011-11-16 07:33:00 +00006#include "../int_math.h"
Daniel Dunbarb3a69012009-06-26 16:47:03 +00007#include <math.h>
8
Edward O'Callaghan33c13472009-08-08 04:43:56 +00009#if !defined(INFINITY) && defined(HUGE_VAL)
10#define INFINITY HUGE_VAL
11#endif /* INFINITY */
12
Daniel Dunbar86030242011-11-16 07:33:00 +000013#define makeFinite(x) { \
14 (x).s.hi = __builtin_copysign(crt_isinf((x).s.hi) ? 1.0 : 0.0, (x).s.hi); \
15 (x).s.lo = 0.0; \
16 }
Daniel Dunbarb3a69012009-06-26 16:47:03 +000017
Daniel Dunbar86030242011-11-16 07:33:00 +000018#define zeroNaN() { \
19 if (crt_isnan((x).s.hi)) { \
20 (x).s.hi = __builtin_copysign(0.0, (x).s.hi); \
21 (x).s.lo = 0.0; \
22 } \
23 }
Daniel Dunbarb3a69012009-06-26 16:47:03 +000024
25long double __gcc_qadd(long double, long double);
26long double __gcc_qsub(long double, long double);
27long double __gcc_qmul(long double, long double);
28
29long double _Complex
30__multc3(long double a, long double b, long double c, long double d)
31{
32 long double ac = __gcc_qmul(a,c);
33 long double bd = __gcc_qmul(b,d);
34 long double ad = __gcc_qmul(a,d);
35 long double bc = __gcc_qmul(b,c);
36
37 DD real = { .ld = __gcc_qsub(ac,bd) };
38 DD imag = { .ld = __gcc_qadd(ad,bc) };
39
Daniel Dunbar86030242011-11-16 07:33:00 +000040 if (crt_isnan(real.s.hi) && crt_isnan(imag.s.hi))
Daniel Dunbarb3a69012009-06-26 16:47:03 +000041 {
42 int recalc = 0;
43
44 DD aDD = { .ld = a };
45 DD bDD = { .ld = b };
46 DD cDD = { .ld = c };
47 DD dDD = { .ld = d };
48
Daniel Dunbar86030242011-11-16 07:33:00 +000049 if (crt_isinf(aDD.s.hi) || crt_isinf(bDD.s.hi))
Daniel Dunbarb3a69012009-06-26 16:47:03 +000050 {
51 makeFinite(aDD);
52 makeFinite(bDD);
53 zeroNaN(cDD);
54 zeroNaN(dDD);
55 recalc = 1;
56 }
57
Daniel Dunbar86030242011-11-16 07:33:00 +000058 if (crt_isinf(cDD.s.hi) || crt_isinf(dDD.s.hi))
Daniel Dunbarb3a69012009-06-26 16:47:03 +000059 {
60 makeFinite(cDD);
61 makeFinite(dDD);
62 zeroNaN(aDD);
63 zeroNaN(bDD);
64 recalc = 1;
65 }
66
67 if (!recalc)
68 {
69 DD acDD = { .ld = ac };
70 DD bdDD = { .ld = bd };
71 DD adDD = { .ld = ad };
72 DD bcDD = { .ld = bc };
73
Daniel Dunbar86030242011-11-16 07:33:00 +000074 if (crt_isinf(acDD.s.hi) || crt_isinf(bdDD.s.hi) ||
75 crt_isinf(adDD.s.hi) || crt_isinf(bcDD.s.hi))
Daniel Dunbarb3a69012009-06-26 16:47:03 +000076 {
77 zeroNaN(aDD);
78 zeroNaN(bDD);
79 zeroNaN(cDD);
80 zeroNaN(dDD);
81 recalc = 1;
82 }
83 }
84
85 if (recalc)
86 {
Edward O'Callaghan8bf1e092009-08-09 18:41:02 +000087 real.s.hi = INFINITY * (aDD.s.hi*cDD.s.hi - bDD.s.hi*dDD.s.hi);
88 real.s.lo = 0.0;
89 imag.s.hi = INFINITY * (aDD.s.hi*dDD.s.hi + bDD.s.hi*cDD.s.hi);
90 imag.s.lo = 0.0;
Daniel Dunbarb3a69012009-06-26 16:47:03 +000091 }
92 }
93
94 long double _Complex z;
95 __real__ z = real.ld;
96 __imag__ z = imag.ld;
97
98 return z;
99}