00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <inttypes.h>
00037 #include "quad.h"
00038
00039
00040
00041
00042 #ifdef FUSED_MADD
00043 static double __sub(double, double, double);
00044 #endif
00045
00046 typedef union
00047 {
00048 struct
00049 {
00050 unsigned int hi;
00051 unsigned int lo;
00052 } word;
00053
00054 double d;
00055 } du;
00056
00057 double fabs(double);
00058 #pragma intrinsic (fabs)
00059
00060 #ifndef FUSED_MADD
00061
00062 static const du const1 = {0x41a00000, 0x02000000};
00063 #endif
00064
00065 static const du twop590 = {0x64d00000, 0x00000000};
00066 static const du twopm590 = {0x1b100000, 0x00000000};
00067 static const du inf = {0x7ff00000, 0x00000000};
00068
00069 #define NO 0
00070 #define YES 1
00071
00072 long double __qprod(double x, double y)
00073 {
00074 ldquad z;
00075 int32_t ix, xptx, iy, xpty;
00076 double w, ww;
00077 double xfactor, yfactor;
00078 int32_t scaleup, scaledown;
00079
00080 #ifndef FUSED_MADD
00081 double p;
00082 double hx, hy, tx, ty;
00083 #endif
00084
00085 #include "msg.h"
00086
00087
00088
00089
00090
00091
00092 ix = *(int32_t *)&x;
00093 xptx = (ix >> 20);
00094 xptx &= 0x7ff;
00095 iy = *(int32_t *)&y;
00096 xpty = (iy >> 20);
00097 xpty &= 0x7ff;
00098 if ((0x21a < xptx) && (xptx < 0x5fd) && (0x21a < xpty) && (xpty < 0x5fd)) {
00099
00100 #ifdef FUSED_MADD
00101 z.q.hi = x*y;
00102 z.q.lo = __sub(x, y, z.q.hi);
00103 #else
00104 p = x*const1.d;
00105 hx = p + (x - p);
00106 tx = x - hx;
00107 p = y*const1.d;
00108 hy = p + (y - p);
00109 ty = y - hy;
00110 z.q.hi = x*y;
00111 z.q.lo = (((hx*hy - z.q.hi) + hx*ty) + hy*tx) + tx*ty;
00112 #endif
00113 return (z.ld);
00114 }
00115
00116 if ((xptx < 0x7ff) && (xpty < 0x7ff)) {
00117 if ((x == 0.0) || (y == 0.0)) {
00118 z.q.lo = 0.0;
00119 z.q.hi = x*y;
00120 return (z.ld);
00121 }
00122 xfactor = 1.0;
00123 yfactor = 1.0;
00124 scaleup = scaledown = NO;
00125 if (xptx <= 0x21a) {
00126 x *= twop590.d;
00127 xfactor = twopm590.d;
00128 scaleup = YES;
00129 }
00130 if (xpty <= 0x21a) {
00131 y *= twop590.d;
00132 yfactor = twopm590.d;
00133 scaleup = YES;
00134 }
00135 if (xptx >= 0x5fd) {
00136 x *= twopm590.d;
00137 xfactor = twop590.d;
00138 scaledown = YES;
00139 }
00140 if (xpty >= 0x5fd) {
00141 y *= twopm590.d;
00142 yfactor = twop590.d;
00143 scaledown = YES;
00144 }
00145 if ((scaleup == YES) && (scaledown == YES)) {
00146 xfactor = yfactor = 1.0;
00147 }
00148 #ifdef FUSED_MADD
00149 w = x*y;
00150 ww = __sub(x, y, w);
00151 #else
00152 p = x*const1.d;
00153 hx = p + (x - p);
00154 tx = x - hx;
00155 p = y*const1.d;
00156 hy = p + (y - p);
00157 ty = y - hy;
00158 w = x*y;
00159 ww = (((hx*hy - w) + hx*ty) + hy*tx) + tx*ty;
00160 #endif
00161 w *= xfactor;
00162 w *= yfactor;
00163 if ((w == 0.0) || (fabs(w) == inf.d)) {
00164 z.q.hi = w;
00165 z.q.lo = 0.0;
00166 return (z.ld);
00167 }
00168 ww *= xfactor;
00169 ww *= yfactor;
00170
00171
00172
00173 z.q.hi = w + ww;
00174 z.q.lo = w - z.q.hi + ww;
00175 return (z.ld);
00176 }
00177 z.q.lo = 0.0;
00178 z.q.hi = x*y;
00179 return (z.ld);
00180 }
00181
00182 #ifdef FUSED_MADD
00183 static double __sub(double x, double y, double z)
00184 {
00185 return (x*y-z);
00186 }
00187 #endif