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
00046
00047
00048
00049
00050 #include "defs.h"
00051 #include "quad.h"
00052
00053
00054
00055
00056
00057 typedef union
00058 {
00059 struct
00060 {
00061 UINT32 hi;
00062 UINT32 lo;
00063 } word;
00064
00065 double d;
00066 } du;
00067
00068
00069
00070
00071 static const du const1 =
00072 {0x41a00000, 0x02000000};
00073
00074 static const du twop590 =
00075 {0x64d00000, 0x00000000};
00076
00077 static const du twopm590 =
00078 {0x1b100000, 0x00000000};
00079
00080 static const du inf =
00081 {0x7ff00000, 0x00000000};
00082
00083 #define NO 0
00084 #define YES 1
00085
00086 extern QUAD c_q_mul(QUAD, QUAD, INT *);
00087
00088 #if defined(BUILD_OS_DARWIN)
00089
00090 QUAD c_q_mul(QUAD x, QUAD y, INT *p_err );
00091 QUAD __c_q_mul(QUAD x, QUAD y, INT *p_err ) { return c_q_mul(x, y, p_err); }
00092 #else
00093 #pragma weak c_q_mul = __c_q_mul
00094 #define c_q_mul __c_q_mul
00095 #endif
00096
00097 double fabs(double);
00098 #pragma intrinsic (fabs)
00099
00100 QUAD
00101 c_q_mul(QUAD x, QUAD y, INT *p_err )
00102 {
00103 INT32 ixhi, iyhi;
00104 INT32 xptxhi, xptyhi;
00105 INT32 xpthi, xptlo;
00106 INT32 scaleup, scaledown;
00107 INT64 iz, iw, iqulp;
00108 double xhi, xlo, yhi, ylo;
00109 double xfactor, yfactor;
00110 double hx, tx, hy, ty;
00111 double p, q;
00112 double w, ww;
00113 double qulp;
00114 QUAD z, u;
00115 double rem;
00116 double a, v, vv;
00117
00118
00119
00120
00121
00122
00123
00124 *p_err = 0;
00125
00126 xhi = x.hi; xlo = x.lo;
00127 yhi = y.hi; ylo = y.lo;
00128
00129 #ifdef QUAD_DEBUG
00130 printf("c_q_mul: xhi = %08x%08x\n", *(INT32 *)&xhi, *((INT32 *)&xhi + 1));
00131 printf("c_q_mul: xlo = %08x%08x\n", *(INT32 *)&xlo, *((INT32 *)&xlo + 1));
00132 printf("c_q_mul: yhi = %08x%08x\n", *(INT32 *)&yhi, *((INT32 *)&yhi + 1));
00133 printf("c_q_mul: ylo = %08x%08x\n", *(INT32 *)&ylo, *((INT32 *)&ylo + 1));
00134 #endif
00135
00136
00137 iyhi = *(INT32 *)&yhi;
00138 xptyhi = (iyhi >> 20);
00139 xptyhi &= 0x7ff;
00140
00141 ixhi = *(INT32 *)&xhi;
00142 xptxhi = (ixhi >> 20);
00143 xptxhi &= 0x7ff;
00144
00145 xpthi = xptxhi;
00146 xptlo = xptyhi;
00147
00148 if ( xptxhi < xptyhi )
00149 {
00150 xptlo = xptxhi;
00151 xpthi = xptyhi;
00152 }
00153
00154 if ( (0x21a < xptlo) && (xpthi < 0x5fd) )
00155 {
00156
00157
00158
00159
00160
00161
00162 p = xhi*const1.d;
00163
00164 hx = (xhi - p) + p;
00165 tx = xhi - hx;
00166
00167 q = yhi*const1.d;
00168
00169 hy = (yhi - q) + q;
00170 ty = yhi - hy;
00171
00172 u.hi = xhi*yhi;
00173 u.lo = (((hx*hy - u.hi) + hx*ty) + hy*tx) + tx*ty;
00174
00175
00176
00177 a = xhi*ylo;
00178
00179 ww = u.lo + a;
00180 rem = u.lo - ww + a;
00181
00182 v = u.hi + ww;
00183 vv = u.hi - v + ww;
00184
00185 a = xlo*yhi + rem;
00186 u.lo = vv + a;
00187
00188 rem = vv - u.lo + a;
00189
00190 w = v + u.lo;
00191 ww = v - w + u.lo;
00192
00193 a = xlo*ylo + rem;
00194
00195 vv = ww + a;
00196
00197 z.hi = w + vv;
00198 DBL2LL(z.hi, iz);
00199 z.lo = w - z.hi + vv;
00200
00201
00202
00203
00204
00205
00206
00207 iw = (iz >> DMANTWIDTH);
00208 iqulp = (iw & 0x7ff);
00209 iqulp -= 54;
00210 iqulp <<= DMANTWIDTH;
00211
00212 if ( iqulp > 0 )
00213 {
00214 LL2DBL( iqulp, qulp );
00215 iw <<= DMANTWIDTH;
00216
00217
00218
00219
00220
00221 if ( iw == iz )
00222 goto fix;
00223
00224 if ( fabs(z.lo) >= qulp )
00225 {
00226 qulp = 0.0;
00227 }
00228 else if ( z.lo < 0.0 )
00229 qulp = -qulp;
00230
00231 z.lo += qulp;
00232 z.lo -= qulp;
00233 }
00234
00235 #ifdef QUAD_DEBUG
00236 printf("c_q_mul: z.hi = %08x%08x\n", *(INT32 *)&z.hi, *((INT32 *)&z.hi + 1));
00237 printf("c_q_mul: z.lo = %08x%08x\n", *(INT32 *)&z.lo, *((INT32 *)&z.lo + 1));
00238 #endif
00239
00240 return ( z );
00241 }
00242 else if ( (xptxhi == 0x7ff) || (xhi == 0.0) || (yhi == 0.0) )
00243 {
00244 z.hi = xhi*yhi;
00245 z.lo = 0.0;
00246
00247 #ifdef QUAD_DEBUG
00248 printf("c_q_mul: z.hi = %08x%08x\n", *(INT32 *)&z.hi, *((INT32 *)&z.hi + 1));
00249 printf("c_q_mul: z.lo = %08x%08x\n", *(INT32 *)&z.lo, *((INT32 *)&z.lo + 1));
00250 #endif
00251
00252 return ( z );
00253 }
00254 else
00255 {
00256 xfactor = 1.0;
00257 yfactor = 1.0;
00258 scaleup = scaledown = NO;
00259
00260 if ( xptxhi <= 0x21a )
00261 {
00262 xhi *= twop590.d;
00263 xlo *= twop590.d;
00264 xfactor = twopm590.d;
00265 scaleup = YES;
00266 }
00267
00268 if ( xptyhi <= 0x21a )
00269 {
00270 yhi *= twop590.d;
00271 ylo *= twop590.d;
00272 yfactor = twopm590.d;
00273 scaleup = YES;
00274 }
00275
00276 if ( xptxhi >= 0x5fd )
00277 {
00278 xhi *= twopm590.d;
00279 xlo *= twopm590.d;
00280 xfactor = twop590.d;
00281 scaledown = YES;
00282 }
00283
00284 if ( xptyhi >= 0x5fd )
00285 {
00286 yhi *= twopm590.d;
00287 ylo *= twopm590.d;
00288 yfactor = twop590.d;
00289 scaledown = YES;
00290 }
00291
00292 if ( (scaleup == YES) && (scaledown == YES) )
00293 {
00294 xfactor = yfactor = 1.0;
00295 }
00296
00297
00298
00299
00300
00301
00302 p = xhi*const1.d;
00303
00304 hx = (xhi - p) + p;
00305 tx = xhi - hx;
00306
00307 q = yhi*const1.d;
00308
00309 hy = (yhi - q) + q;
00310 ty = yhi - hy;
00311
00312 u.hi = xhi*yhi;
00313 u.lo = (((hx*hy - u.hi) + hx*ty) + hy*tx) + tx*ty;
00314
00315
00316
00317 a = xhi*ylo;
00318
00319 ww = u.lo + a;
00320 rem = u.lo - ww + a;
00321
00322 v = u.hi + ww;
00323 vv = u.hi - v + ww;
00324
00325 a = xlo*yhi + rem;
00326 u.lo = vv + a;
00327
00328 rem = vv - u.lo + a;
00329
00330 w = v + u.lo;
00331 ww = v - w + u.lo;
00332
00333 a = xlo*ylo + rem;
00334
00335 vv = ww + a;
00336
00337 z.hi = w + vv;
00338 z.lo = w - z.hi + vv;
00339
00340
00341
00342 w = z.hi*xfactor;
00343 w *= yfactor;
00344
00345 if ( (w == 0.0) || (fabs(w) == inf.d) )
00346 {
00347 z.hi = w;
00348 z.lo = 0.0;
00349
00350 #ifdef QUAD_DEBUG
00351 printf("c_q_mul: z.hi = %08x%08x\n", *(INT32 *)&z.hi, *((INT32 *)&z.hi + 1));
00352 printf("c_q_mul: z.lo = %08x%08x\n", *(INT32 *)&z.lo, *((INT32 *)&z.lo + 1));
00353 #endif
00354
00355 return ( z );
00356 }
00357
00358 ww = z.lo*xfactor;
00359 ww *= yfactor;
00360
00361 z.hi = w + ww;
00362 DBL2LL(z.hi, iz);
00363 z.lo = w - z.hi + ww;
00364
00365 #ifdef QUAD_DEBUG
00366 printf("c_q_mul: z.hi = %08x%08x\n", *(INT32 *)&z.hi, *((INT32 *)&z.hi + 1));
00367 printf("c_q_mul: z.lo = %08x%08x\n", *(INT32 *)&z.lo, *((INT32 *)&z.lo + 1));
00368 #endif
00369
00370
00371
00372
00373
00374
00375
00376 iw = (iz >> DMANTWIDTH);
00377 iqulp = (iw & 0x7ff);
00378 iqulp -= 54;
00379 iqulp <<= DMANTWIDTH;
00380
00381 if ( iqulp > 0 )
00382 {
00383 LL2DBL( iqulp, qulp );
00384 iw <<= DMANTWIDTH;
00385
00386
00387
00388
00389
00390 if ( iw == iz )
00391 goto fix2;
00392
00393 back:
00394 if ( fabs(z.lo) >= qulp )
00395 {
00396 qulp = 0.0;
00397 }
00398 else if ( z.lo < 0.0 )
00399 qulp = -qulp;
00400
00401 z.lo += qulp;
00402 z.lo -= qulp;
00403 }
00404
00405 return ( z );
00406 }
00407
00408 fix:
00409 if ( ((z.hi > 0.0) && (z.lo < 0.0)) || ((z.hi < 0.0) && (z.lo > 0.0)) )
00410 qulp *= 0.5;
00411
00412 if ( fabs(z.lo) >= qulp )
00413 {
00414 qulp = 0.0;
00415 }
00416 else if ( z.lo < 0.0 )
00417 qulp = -qulp;
00418
00419 z.lo += qulp;
00420 z.lo -= qulp;
00421
00422 return ( z );
00423
00424 fix2:
00425 if ( ((z.hi > 0.0) && (z.lo < 0.0)) || ((z.hi < 0.0) && (z.lo > 0.0)) )
00426 qulp *= 0.5;
00427
00428 goto back;
00429 }
00430