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