Go to the documentation of this file.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
00037
00038
00039
00040
00041
00042
00043
00044
00045 #include "defs.h"
00046 #include "quad.h"
00047
00048
00049
00050
00051
00052 typedef union
00053 {
00054 struct
00055 {
00056 UINT32 hi;
00057 UINT32 lo;
00058 } word;
00059
00060 double d;
00061 } du;
00062
00063 static const du twop914 =
00064 {0x79100000, 0x00000000};
00065
00066 static const du inf =
00067 {0x7ff00000, 0x00000000};
00068
00069 extern QUAD c_q_sub(QUAD, QUAD, INT *);
00070
00071 #pragma weak c_q_sub = __c_q_sub
00072 #define c_q_sub __c_q_sub
00073
00074 double fabs(double);
00075 #pragma intrinsic (fabs)
00076
00077 QUAD
00078 c_q_sub(QUAD x, QUAD y, INT *p_err )
00079 {
00080 double xhi, xlo, yhi, ylo;
00081 INT32 ixhi, iyhi;
00082 INT32 xptxhi, xptyhi;
00083 INT64 iz, iw, iqulp;
00084 double w, ww;
00085 double u, uu;
00086 double qulp;
00087 QUAD z;
00088 double tmp1, tmp2, lo, rem;
00089
00090
00091
00092 *p_err = 0;
00093
00094 xhi = x.hi; xlo = x.lo;
00095 yhi = y.hi; ylo = y.lo;
00096
00097 iyhi = *(INT32 *)&yhi;
00098 xptyhi = (iyhi >> 20);
00099 xptyhi &= 0x7ff;
00100
00101 ixhi = *(INT32 *)&xhi;
00102 xptxhi = (ixhi >> 20);
00103 xptxhi &= 0x7ff;
00104
00105 #ifdef QUAD_DEBUG
00106 printf("c_q_sub: xhi = %08x%08x\n", *(INT32 *)&xhi, *((INT32 *)&xhi + 1));
00107 printf("c_q_sub: xlo = %08x%08x\n", *(INT32 *)&xlo, *((INT32 *)&xlo + 1));
00108 printf("c_q_sub: yhi = %08x%08x\n", *(INT32 *)&yhi, *((INT32 *)&yhi + 1));
00109 printf("c_q_sub: ylo = %08x%08x\n", *(INT32 *)&ylo, *((INT32 *)&ylo + 1));
00110 #endif
00111
00112 yhi = -yhi;
00113 ylo = -ylo;
00114
00115 if ( xptxhi < xptyhi )
00116 {
00117 tmp1 = xhi;
00118 xhi = yhi;
00119 yhi = tmp1;
00120 xptxhi = xptyhi;
00121 }
00122
00123 if ( fabs(xlo) < fabs(ylo) )
00124 {
00125 tmp2 = xlo;
00126 xlo = ylo;
00127 ylo = tmp2;
00128 }
00129
00130 if ( xptxhi < 0x7fd )
00131 {
00132 z.hi = xhi + yhi;
00133 z.lo = xhi - z.hi + yhi;
00134
00135 u = xlo + ylo;
00136 uu = xlo - u + ylo;
00137
00138 lo = z.lo + u;
00139
00140 w = z.hi + lo;
00141 ww = z.hi - w + lo;
00142
00143 rem = z.lo - lo + u;
00144
00145 ww += rem + uu;
00146 z.hi = w + ww;
00147 DBL2LL( z.hi, iz );
00148 z.lo = w - z.hi + ww;
00149
00150
00151
00152
00153
00154
00155
00156 iw = (iz >> DMANTWIDTH);
00157 iqulp = (iw & 0x7ff);
00158 iqulp -= 54;
00159 iqulp <<= DMANTWIDTH;
00160
00161 if ( iqulp > 0 )
00162 {
00163 LL2DBL( iqulp, qulp );
00164 iw <<= DMANTWIDTH;
00165
00166
00167
00168
00169
00170 if ( iw == iz )
00171 goto fix;
00172
00173 if ( fabs(z.lo) >= qulp )
00174 {
00175 qulp = 0.0;
00176 }
00177 else if ( z.lo < 0.0 )
00178 qulp = -qulp;
00179
00180 z.lo += qulp;
00181 z.lo -= qulp;
00182 }
00183
00184
00185 #ifdef QUAD_DEBUG
00186 printf("q_add: z.hi = %08x%08x\n", *(INT32 *)&z.hi, *((INT32 *)&z.hi + 1));
00187 printf("q_add: z.lo = %08x%08x\n", *(INT32 *)&z.lo, *((INT32 *)&z.lo + 1));
00188 #endif
00189
00190 return ( z );
00191 }
00192 else if ( xptxhi == 0x7ff )
00193 {
00194 z.hi = xhi + yhi;
00195 z.lo = 0.0;
00196
00197 #ifdef QUAD_DEBUG
00198 printf("q_add: z.hi = %08x%08x\n", *(INT32 *)&z.hi, *((INT32 *)&z.hi + 1));
00199 printf("q_add: z.lo = %08x%08x\n", *(INT32 *)&z.lo, *((INT32 *)&z.lo + 1));
00200 #endif
00201
00202 return ( z );
00203 }
00204 else
00205 {
00206 if ( fabs(yhi) < twop914.d )
00207 {
00208 z.hi = xhi;
00209 z.lo = xlo;
00210
00211 #ifdef QUAD_DEBUG
00212 printf("q_add: z.hi = %08x%08x\n", *(INT32 *)&z.hi, *((INT32 *)&z.hi + 1));
00213 printf("q_add: z.lo = %08x%08x\n", *(INT32 *)&z.lo, *((INT32 *)&z.lo + 1));
00214 #endif
00215
00216 return ( z );
00217 }
00218
00219
00220
00221
00222
00223 xhi *= 0.25;
00224 xlo *= 0.25;
00225 yhi *= 0.25;
00226 ylo *= 0.25;
00227
00228 z.hi = xhi + yhi;
00229 z.lo = xhi - z.hi + yhi;
00230
00231 u = xlo + ylo;
00232 uu = xlo - u + ylo;
00233
00234 lo = z.lo + u;
00235
00236 w = z.hi + lo;
00237 ww = z.hi - w + lo;
00238
00239 rem = z.lo - lo + u;
00240
00241 ww += rem + uu;
00242 z.hi = w + ww;
00243 DBL2LL( z.hi, iz );
00244 z.lo = w - z.hi + ww;
00245
00246
00247
00248
00249
00250
00251
00252 iw = (iz >> DMANTWIDTH);
00253 iqulp = (iw & 0x7ff);
00254 iqulp -= 54;
00255 iqulp <<= DMANTWIDTH;
00256
00257 if ( iqulp > 0 )
00258 {
00259 LL2DBL( iqulp, qulp );
00260 iw <<= DMANTWIDTH;
00261
00262
00263
00264
00265
00266 if ( iw == iz )
00267 goto fix2;
00268
00269 if ( fabs(z.lo) >= qulp )
00270 {
00271 qulp = 0.0;
00272 }
00273 else if ( z.lo < 0.0 )
00274 qulp = -qulp;
00275
00276 z.lo += qulp;
00277 z.lo -= qulp;
00278 }
00279
00280 z.hi *= 4.0;
00281
00282 if ( fabs(z.hi) == inf.d )
00283 {
00284 z.lo = 0.0;
00285 return ( z );
00286 }
00287
00288 z.lo *= 4.0;
00289
00290 return ( z );
00291
00292 }
00293
00294 fix:
00295 if ( ((z.hi > 0.0) && (z.lo < 0.0)) || ((z.hi < 0.0) && (z.lo > 0.0)) )
00296 qulp *= 0.5;
00297
00298 if ( fabs(z.lo) >= qulp )
00299 {
00300 qulp = 0.0;
00301 }
00302 else if ( z.lo < 0.0 )
00303 qulp = -qulp;
00304
00305 z.lo += qulp;
00306 z.lo -= qulp;
00307
00308 return ( z );
00309
00310 fix2:
00311 if ( ((z.hi > 0.0) && (z.lo < 0.0)) || ((z.hi < 0.0) && (z.lo > 0.0)) )
00312 qulp *= 0.5;
00313
00314 if ( fabs(z.lo) >= qulp )
00315 {
00316 qulp = 0.0;
00317 }
00318 else if ( z.lo < 0.0 )
00319 qulp = -qulp;
00320
00321 z.lo += qulp;
00322 z.lo -= qulp;
00323
00324 z.hi *= 4.0;
00325
00326 if ( fabs(z.hi) == inf.d )
00327 {
00328 z.lo = 0.0;
00329 return ( z );
00330 }
00331
00332 z.lo *= 4.0;
00333
00334 return ( z );
00335 }
00336