multc3.c revision 276789
1169689Skan/* This file is distributed under the University of Illinois Open Source 2169689Skan * License. See LICENSE.TXT for details. 3169689Skan */ 4169689Skan 5169689Skan#include "DD.h" 6169689Skan#include "../int_math.h" 7169689Skan 8169689Skan#define makeFinite(x) { \ 9169689Skan (x).s.hi = crt_copysign(crt_isinf((x).s.hi) ? 1.0 : 0.0, (x).s.hi); \ 10169689Skan (x).s.lo = 0.0; \ 11169689Skan } 12169689Skan 13169689Skan#define zeroNaN(x) { \ 14169689Skan if (crt_isnan((x).s.hi)) { \ 15169689Skan (x).s.hi = crt_copysign(0.0, (x).s.hi); \ 16169689Skan (x).s.lo = 0.0; \ 17169689Skan } \ 18169689Skan } 19169689Skan 20169689Skanlong double __gcc_qadd(long double, long double); 21169689Skanlong double __gcc_qsub(long double, long double); 22169689Skanlong double __gcc_qmul(long double, long double); 23169689Skan 24169689Skanlong double _Complex 25169689Skan__multc3(long double a, long double b, long double c, long double d) 26169689Skan{ 27169689Skan long double ac = __gcc_qmul(a,c); 28169689Skan long double bd = __gcc_qmul(b,d); 29169689Skan long double ad = __gcc_qmul(a,d); 30169689Skan long double bc = __gcc_qmul(b,c); 31169689Skan 32169689Skan DD real = { .ld = __gcc_qsub(ac,bd) }; 33169689Skan DD imag = { .ld = __gcc_qadd(ad,bc) }; 34169689Skan 35169689Skan if (crt_isnan(real.s.hi) && crt_isnan(imag.s.hi)) 36169689Skan { 37169689Skan int recalc = 0; 38169689Skan 39169689Skan DD aDD = { .ld = a }; 40169689Skan DD bDD = { .ld = b }; 41169689Skan DD cDD = { .ld = c }; 42169689Skan DD dDD = { .ld = d }; 43169689Skan 44169689Skan if (crt_isinf(aDD.s.hi) || crt_isinf(bDD.s.hi)) 45169689Skan { 46169689Skan makeFinite(aDD); 47169689Skan makeFinite(bDD); 48169689Skan zeroNaN(cDD); 49169689Skan zeroNaN(dDD); 50169689Skan recalc = 1; 51169689Skan } 52169689Skan 53169689Skan if (crt_isinf(cDD.s.hi) || crt_isinf(dDD.s.hi)) 54169689Skan { 55169689Skan makeFinite(cDD); 56169689Skan makeFinite(dDD); 57169689Skan zeroNaN(aDD); 58169689Skan zeroNaN(bDD); 59169689Skan recalc = 1; 60169689Skan } 61169689Skan 62169689Skan if (!recalc) 63169689Skan { 64169689Skan DD acDD = { .ld = ac }; 65169689Skan DD bdDD = { .ld = bd }; 66169689Skan DD adDD = { .ld = ad }; 67169689Skan DD bcDD = { .ld = bc }; 68169689Skan 69169689Skan if (crt_isinf(acDD.s.hi) || crt_isinf(bdDD.s.hi) || 70169689Skan crt_isinf(adDD.s.hi) || crt_isinf(bcDD.s.hi)) 71169689Skan { 72169689Skan zeroNaN(aDD); 73169689Skan zeroNaN(bDD); 74169689Skan zeroNaN(cDD); 75169689Skan zeroNaN(dDD); 76169689Skan recalc = 1; 77169689Skan } 78169689Skan } 79169689Skan 80169689Skan if (recalc) 81169689Skan { 82169689Skan real.s.hi = CRT_INFINITY * (aDD.s.hi*cDD.s.hi - bDD.s.hi*dDD.s.hi); 83169689Skan real.s.lo = 0.0; 84169689Skan imag.s.hi = CRT_INFINITY * (aDD.s.hi*dDD.s.hi + bDD.s.hi*cDD.s.hi); 85169689Skan imag.s.lo = 0.0; 86169689Skan } 87169689Skan } 88169689Skan 89169689Skan long double _Complex z; 90246314Sandrew __real__ z = real.ld; 91169689Skan __imag__ z = imag.ld; 92169689Skan 93169689Skan return z; 94169689Skan} 95169689Skan