Home | History | Annotate | Download | only in ppc
      1 /* This file is distributed under the University of Illinois Open Source
      2  * License. See LICENSE.TXT for details.
      3  */
      4 
      5 #include "DD.h"
      6 #include <math.h>
      7 
      8 #if !defined(INFINITY) && defined(HUGE_VAL)
      9 #define INFINITY HUGE_VAL
     10 #endif /* INFINITY */
     11 
     12 #define makeFinite(x)	{ \
     13 							(x).s.hi = __builtin_copysign(isinf((x).s.hi) ? 1.0 : 0.0, (x).s.hi); \
     14 							(x).s.lo = 0.0; \
     15 						}
     16 
     17 long double __gcc_qadd(long double, long double);
     18 long double __gcc_qsub(long double, long double);
     19 long double __gcc_qmul(long double, long double);
     20 long double __gcc_qdiv(long double, long double);
     21 
     22 long double _Complex
     23 __divtc3(long double a, long double b, long double c, long double d)
     24 {
     25 	DD cDD = { .ld = c };
     26 	DD dDD = { .ld = d };
     27 
     28 	int ilogbw = 0;
     29 	const double logbw = logb(__builtin_fmax( __builtin_fabs(cDD.s.hi), __builtin_fabs(dDD.s.hi) ));
     30 
     31 	if (isfinite(logbw))
     32 	{
     33 		ilogbw = (int)logbw;
     34 
     35 		cDD.s.hi = scalbn(cDD.s.hi, -ilogbw);
     36 		cDD.s.lo = scalbn(cDD.s.lo, -ilogbw);
     37 		dDD.s.hi = scalbn(dDD.s.hi, -ilogbw);
     38 		dDD.s.lo = scalbn(dDD.s.lo, -ilogbw);
     39 	}
     40 
     41 	const long double denom = __gcc_qadd(__gcc_qmul(cDD.ld, cDD.ld), __gcc_qmul(dDD.ld, dDD.ld));
     42 	const long double realNumerator = __gcc_qadd(__gcc_qmul(a,cDD.ld), __gcc_qmul(b,dDD.ld));
     43 	const long double imagNumerator = __gcc_qsub(__gcc_qmul(b,cDD.ld), __gcc_qmul(a,dDD.ld));
     44 
     45 	DD real = { .ld = __gcc_qdiv(realNumerator, denom) };
     46 	DD imag = { .ld = __gcc_qdiv(imagNumerator, denom) };
     47 
     48 	real.s.hi = scalbn(real.s.hi, -ilogbw);
     49 	real.s.lo = scalbn(real.s.lo, -ilogbw);
     50 	imag.s.hi = scalbn(imag.s.hi, -ilogbw);
     51 	imag.s.lo = scalbn(imag.s.lo, -ilogbw);
     52 
     53 	if (isnan(real.s.hi) && isnan(imag.s.hi))
     54 	{
     55 		DD aDD = { .ld = a };
     56 		DD bDD = { .ld = b };
     57 		DD rDD = { .ld = denom };
     58 
     59 		if ((rDD.s.hi == 0.0) && (!isnan(aDD.s.hi) || !isnan(bDD.s.hi)))
     60 		{
     61 			real.s.hi = __builtin_copysign(INFINITY,cDD.s.hi) * aDD.s.hi;
     62 			real.s.lo = 0.0;
     63 			imag.s.hi = __builtin_copysign(INFINITY,cDD.s.hi) * bDD.s.hi;
     64 			imag.s.lo = 0.0;
     65 		}
     66 
     67 		else if ((isinf(aDD.s.hi) || isinf(bDD.s.hi)) && isfinite(cDD.s.hi) && isfinite(dDD.s.hi))
     68 		{
     69 			makeFinite(aDD);
     70 			makeFinite(bDD);
     71 			real.s.hi = INFINITY * (aDD.s.hi*cDD.s.hi + bDD.s.hi*dDD.s.hi);
     72 			real.s.lo = 0.0;
     73 			imag.s.hi = INFINITY * (bDD.s.hi*cDD.s.hi - aDD.s.hi*dDD.s.hi);
     74 			imag.s.lo = 0.0;
     75 		}
     76 
     77 		else if ((isinf(cDD.s.hi) || isinf(dDD.s.hi)) && isfinite(aDD.s.hi) && isfinite(bDD.s.hi))
     78 		{
     79 			makeFinite(cDD);
     80 			makeFinite(dDD);
     81 			real.s.hi = __builtin_copysign(0.0,(aDD.s.hi*cDD.s.hi + bDD.s.hi*dDD.s.hi));
     82 			real.s.lo = 0.0;
     83 			imag.s.hi = __builtin_copysign(0.0,(bDD.s.hi*cDD.s.hi - aDD.s.hi*dDD.s.hi));
     84 			imag.s.lo = 0.0;
     85 		}
     86 	}
     87 
     88 	long double _Complex z;
     89 	__real__ z = real.ld;
     90 	__imag__ z = imag.ld;
     91 
     92 	return z;
     93 }
     94