Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
quadsim.c
Go to the documentation of this file.
00001 /*
00002 
00003   Copyright (C) 2000, 2001 Silicon Graphics, Inc.  All Rights Reserved.
00004 
00005   This program is free software; you can redistribute it and/or modify it
00006   under the terms of version 2 of the GNU General Public License as
00007   published by the Free Software Foundation.
00008 
00009   This program is distributed in the hope that it would be useful, but
00010   WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00012 
00013   Further, this software is distributed without any warranty that it is
00014   free of the rightful claim of any third person regarding infringement 
00015   or the like.  Any license provided herein, whether implied or 
00016   otherwise, applies only to this software file.  Patent licenses, if 
00017   any, provided herein do not apply to combinations of this program with 
00018   other software, or any other product whatsoever.  
00019 
00020   You should have received a copy of the GNU General Public License along
00021   with this program; if not, write the Free Software Foundation, Inc., 59
00022   Temple Place - Suite 330, Boston MA 02111-1307, USA.
00023 
00024   Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
00025   Mountain View, CA 94043, or:
00026 
00027   http://www.sgi.com
00028 
00029   For further information regarding this notice, see:
00030 
00031   http://oss.sgi.com/projects/GenInfo/NoticeExplan
00032 
00033 */
00034 
00035 
00036 /* =======================================================================
00037  * =======================================================================
00038  *
00039  *
00040  * =======================================================================
00041  * =======================================================================
00042  */
00043 
00044 
00045 
00046 #include "quad.h"
00047 #include "stdio.h"
00048 #include "stdlib.h"
00049 #include "math.h"
00050 #include <fp_class.h>
00051 #include "defs.h"
00052 #include "quadsim.h"
00053 
00054 /* For fp_class */
00055 
00056 #define DMANTWIDTH      52
00057 #define DEXPWIDTH       11
00058 #define DSIGNMASK       0x7fffffffffffffffll
00059 #define DEXPMASK        0x800fffffffffffffll
00060 #define DQNANBITMASK    0xfff7ffffffffffffll
00061 
00062 #define MANTWIDTH       23
00063 #define EXPWIDTH        8
00064 #define SIGNMASK        0x7fffffff
00065 #define EXPMASK         0x807fffff
00066 #define QNANBITMASK     0xffbfffff
00067 
00068 typedef union
00069 {
00070         struct
00071         {
00072                 UINT32 hi;
00073                 UINT32 lo;
00074         } word;
00075 
00076         double  d;
00077 } du;
00078 
00079 static const du         m_twop31 =
00080 {0xc1e00000,    0x00000000};
00081 
00082 static const du         twop31m1 =
00083 {0x41dfffff,    0xffc00000};
00084 
00085 static const du         twop32m1 =
00086 {0x41efffff,    0xffe00000};
00087 
00088 static const du         twop52 =
00089 {0x43300000,    0x00000000};
00090 
00091 static const    du      twop62 =
00092 {0x43d00000,    0x00000000};
00093 
00094 static const    du      m_twop63 =
00095 {0xc3e00000,    0x00000000};
00096 
00097 static const    du      twop63 =
00098 {0x43e00000,    0x00000000};
00099 
00100 static const    du      twop64 =
00101 {0x43f00000,    0x00000000};
00102 
00103 static const    du      twopm916 =
00104 {0x06b00000,    0x00000000};
00105 
00106 /* Note: the name 'infinity' may conflict with <math.h> */
00107 static const    du      myinfinity =
00108 {0x7ff00000,    0x00000000};
00109 
00110 extern  INT     c_q_le(QUAD x, QUAD y, INT *p_err );
00111 extern  INT     c_q_ge(QUAD x, QUAD y, INT *p_err );
00112 extern  INT32   c_ji_qint(QUAD x, INT *p_err );
00113 extern  INT32   c_fp_class_q(QUAD x);
00114 extern  UINT32  c_ji_quint(QUAD x, INT *p_err );
00115 extern  INT64   c_ki_qint(QUAD x, INT *p_err );
00116 extern  UINT64  c_ki_quint(QUAD x, INT *p_err );
00117 extern  float   c_sngl_q(QUAD x, INT *p_err );
00118 extern  double  c_dble_q(QUAD x, INT *p_err );
00119 extern  QUAD    c_q_flotj(INT32 n, INT *p_err );
00120 extern  QUAD    c_q_flotju(UINT32 n, INT *p_err );
00121 extern  QUAD    c_q_flotk(INT64 n, INT *p_err );
00122 extern  QUAD    c_q_flotku(UINT64 n, INT *p_err );
00123 extern  QUAD    c_q_ext( float x, INT *p_err );
00124 extern  QUAD    c_q_extd(double x, INT *p_err );
00125 extern  QUAD    c_q_trunc(QUAD x, INT *p_err );
00126 extern  double  trunc(double x);
00127 
00128 #if defined(_GCC_NO_PRAGMAWEAK) || defined(__CYGWIN__)
00129 
00130 #define c_q_trunc __c_q_trunc
00131 #define c_q_ge __c_q_ge
00132 #define c_ki_qint __c_ki_qint
00133 #define c_q_le __c_q_le
00134 
00135 #endif
00136 
00137 /* quad to INT32 */
00138 
00139 #pragma weak c_ji_qint = __c_ji_qint
00140 #define c_ji_qint __c_ji_qint
00141 
00142 INT32
00143 c_ji_qint(QUAD x, INT *p_err )
00144 {
00145 QUAD    xi;
00146 INT32   result;
00147 
00148         *p_err = 0;
00149 
00150         if ( x.hi != x.hi )
00151         {
00152                 *p_err = 1;
00153 
00154                 return ( (INT32)x.hi );
00155         }
00156 
00157         if ( fabs(x.hi) == myinfinity.d )
00158         {
00159                 *p_err = 1;
00160 
00161                 return ( (INT32)x.hi );
00162         }
00163 
00164         xi = c_q_trunc(x, p_err);
00165 
00166         if ( xi.hi > twop31m1.d )
00167                 *p_err = 1;
00168 
00169         if ( xi.hi < m_twop31.d )
00170                 *p_err = 1;
00171 
00172         result = (INT32)xi.hi;
00173 
00174         return ( result );
00175 }
00176 
00177 /* quad to UINT32 */
00178 
00179 #pragma weak c_ji_quint = __c_ji_quint
00180 #define c_ji_quint __c_ji_quint
00181 
00182 UINT32
00183 c_ji_quint(QUAD x, INT *p_err )
00184 {
00185 QUAD    xi;
00186 INT64   n;
00187 UINT32  result;
00188 
00189         *p_err = 0;
00190 
00191         if ( x.hi != x.hi )
00192         {
00193                 *p_err = 1;
00194 
00195                 return ( (UINT32)x.hi );
00196         }
00197 
00198         if ( fabs(x.hi) == myinfinity.d )
00199         {
00200                 *p_err = 1;
00201 
00202                 return ( (UINT32)x.hi );
00203         }
00204 
00205         xi = c_q_trunc(x, p_err);
00206 
00207         if ( xi.hi > twop32m1.d )
00208         {
00209                 *p_err = 1;
00210 
00211                 return ( (UINT32)x.hi );
00212         }
00213 
00214         if ( xi.hi < 0.0 )
00215         {
00216                 *p_err = 1;
00217 
00218                 return ( (UINT32)x.hi );
00219         }
00220 
00221         n = c_ki_qint(xi, p_err);
00222 
00223         result = n & 0xffffffff;
00224 
00225         return ( result );
00226 }
00227 
00228 /* quad to INT64 */
00229 
00230 #pragma weak c_ki_qint = __c_ki_qint
00231 #define c_ki_qint __c_ki_qint
00232 
00233 INT64
00234 c_ki_qint(QUAD x, INT *p_err )
00235 {
00236 QUAD    xi;
00237 INT64   t;
00238 
00239         *p_err = 0;
00240 
00241         if ( x.hi != x.hi )
00242         {
00243                 *p_err = 1;
00244 
00245                 return ( (INT64)x.hi );
00246         }
00247 
00248         if ( fabs(x.hi) == myinfinity.d )
00249         {
00250                 *p_err = 1;
00251 
00252                 return ( (INT64)x.hi );
00253         }
00254 
00255         xi = c_q_trunc(x, p_err);
00256 
00257         if ( (xi.hi > twop63.d) ||
00258              ((xi.hi == twop63.d) && (xi.lo >= 0.0))
00259            )
00260         {
00261                 /* we get overflow here, so just let the hardware do it */
00262 
00263                 *p_err = 1;
00264 
00265                 return ( (INT64)xi.hi );
00266         }
00267 
00268         if ( (xi.hi < m_twop63.d) ||
00269              ((xi.hi == m_twop63.d) && (xi.lo < 0.0))
00270            )
00271         {
00272                 /* we get overflow here, so just let the hardware do it */
00273 
00274                 if ( xi.hi == m_twop63.d )
00275                 {
00276                         xi.hi *= 2.0;
00277                 }
00278 
00279                 *p_err = 1;
00280 
00281                 return ( (INT64)xi.hi );
00282         }
00283 
00284         if ( fabs(xi.hi) > twop62.d )
00285         {
00286                 /* add things up very carefully to avoid overflow */
00287 
00288                 t = 0.5*xi.hi;
00289                 return ( ((INT64)xi.lo) + t + t );
00290         }
00291 
00292         /* just do it */
00293 
00294         return ( (INT64)xi.hi + (INT64)xi.lo );
00295 }
00296 
00297 /* quad to UINT64 */
00298 
00299 #pragma weak c_ki_quint = __c_ki_quint
00300 #define c_ki_quint __c_ki_quint
00301 
00302 UINT64
00303 c_ki_quint(QUAD x, INT *p_err )
00304 {
00305 QUAD    xi;
00306 double  z;
00307 UINT64  t;
00308 
00309         *p_err = 0;
00310 
00311         if ( x.hi != x.hi )
00312         {
00313                 *p_err = 1;
00314 
00315                 return ( (UINT64)x.hi );
00316         }
00317 
00318         if ( fabs(x.hi) == myinfinity.d )
00319         {
00320                 *p_err = 1;
00321 
00322                 return ( (UINT64)x.hi );
00323         }
00324 
00325         xi = c_q_trunc(x, p_err);
00326 
00327         if ( (xi.hi > twop64.d) ||
00328              ((xi.hi == twop64.d) && (xi.lo > -1.0))
00329            )
00330         {
00331                 *p_err = 1;
00332 
00333                 return ( (UINT64)x.hi );
00334         }
00335 
00336         if ( xi.hi < 0.0 )
00337         {
00338                 *p_err = 1;
00339 
00340                 return ( (UINT64)x.hi );
00341         }
00342 
00343         if ( (xi.hi > twop63.d) ||
00344              (xi.hi == twop63.d) && (xi.lo >= 0.0)
00345            )
00346         {
00347                 /* subtract 2**64       */
00348 
00349                 z = xi.hi - twop64.d;
00350 
00351                 /* normalize result */
00352 
00353                 xi.hi = z + xi.lo;
00354                 xi.lo = z - xi.hi + xi.lo;
00355         }
00356 
00357         if ( fabs(xi.hi) > twop62.d )
00358         {
00359                 /* add things up very carefully to avoid overflow */
00360 
00361                 t = 0.5*xi.hi;
00362                 return ( ((UINT64)xi.lo) + t + t );
00363         }
00364 
00365         /* just do it */
00366 
00367         return ( (UINT64)xi.hi + (UINT64)xi.lo );
00368 }
00369 
00370 /* quad to float */
00371 
00372 #pragma weak c_sngl_q = __c_sngl_q
00373 #define c_sngl_q __c_sngl_q
00374 
00375 float
00376 c_sngl_q(QUAD x, INT *p_err )
00377 {
00378         *p_err = 0;
00379 
00380         return ( (float)x.hi );
00381 }
00382 
00383 /* quad to double */
00384 
00385 #pragma weak c_dble_q = __c_dble_q
00386 #define c_dble_q __c_dble_q
00387 
00388 double
00389 c_dble_q(QUAD x, INT *p_err )
00390 {
00391         *p_err = 0;
00392 
00393         return ( x.hi );
00394 }
00395 
00396 /* INT32 to quad */
00397 
00398 #pragma weak c_q_flotj = __c_q_flotj
00399 #define c_q_flotj __c_q_flotj
00400 
00401 QUAD
00402 c_q_flotj(INT32 n, INT *p_err )
00403 {
00404 QUAD    result;
00405 
00406         *p_err = 0;
00407 
00408         result.hi = n;
00409         result.lo = 0.0;
00410         return ( result );
00411 }
00412 
00413 /* UINT32 to quad */
00414 
00415 #pragma weak c_q_flotju = __c_q_flotju
00416 #define c_q_flotju __c_q_flotju
00417 
00418 QUAD
00419 c_q_flotju(UINT32 n, INT *p_err )
00420 {
00421 QUAD    result;
00422 
00423         *p_err = 0;
00424 
00425         result.hi = n;
00426         result.lo = 0.0;
00427         return ( result );
00428 }
00429 
00430 /* INT64 to quad */
00431 
00432 #pragma weak c_q_flotk = __c_q_flotk
00433 #define c_q_flotk __c_q_flotk
00434 
00435 QUAD
00436 c_q_flotk(INT64 n, INT *p_err )
00437 {
00438 INT64 m;
00439 double  w, ww;
00440 QUAD  result;
00441 
00442         *p_err = 0;
00443 
00444         m = (n >> 11);
00445         m <<= 11;
00446 
00447         w = m;
00448 
00449         ww = n - m;
00450 
00451         /* normalize result */
00452 
00453         result.hi = w + ww;
00454         result.lo = w - result.hi + ww;
00455 
00456         return ( result );
00457 }
00458 
00459 /* UINT64 to QUAD */
00460 
00461 #pragma weak c_q_flotku = __c_q_flotku
00462 #define c_q_flotku __c_q_flotku
00463 
00464 QUAD
00465 c_q_flotku(UINT64 n, INT *p_err )
00466 {
00467 UINT64 m;
00468 double  w, ww;
00469 QUAD  result;
00470 
00471         *p_err = 0;
00472 
00473         m = (n >> 11);
00474         m <<= 11;
00475 
00476         w = m;
00477 
00478         ww = n - m;
00479 
00480         /* normalize result */
00481 
00482         result.hi = w + ww;
00483         result.lo = w - result.hi + ww;
00484 
00485         return ( result );
00486 }
00487 
00488 /* float to quad */
00489 
00490 #pragma weak c_q_ext = __c_q_ext
00491 #define c_q_ext __c_q_ext
00492 
00493 QUAD
00494 c_q_ext( float x, INT *p_err )
00495 {
00496 QUAD    result;
00497 
00498         *p_err = 0;
00499 
00500         result.hi = x;
00501         result.lo = 0.0;
00502         return ( result );
00503 }
00504 
00505 /* double to quad */
00506 
00507 #pragma weak c_q_extd = __c_q_extd
00508 #define c_q_extd __c_q_extd
00509 
00510 QUAD
00511 c_q_extd(double x, INT *p_err )
00512 {
00513 QUAD    result;
00514 
00515         *p_err = 0;
00516 
00517         result.hi = x;
00518         result.lo = 0.0;
00519         return ( result );
00520 }
00521 
00522 /* truncates a long double, i.e. computes the integral part of
00523    a long double
00524 */
00525 
00526 #pragma weak c_q_trunc = __c_q_trunc
00527 #define c_q_trunc __c_q_trunc
00528 
00529 QUAD
00530 c_q_trunc(QUAD x, INT *p_err )
00531 {
00532 double  uhi, ulo;
00533 QUAD    result;
00534 
00535         uhi = x.hi;
00536         ulo = x.lo;
00537 
00538         *p_err = 0;
00539 
00540         if ( uhi != uhi )
00541         {
00542                 result.hi = uhi;
00543                 result.lo = ulo;
00544 
00545                 return ( result );
00546         }
00547 
00548         if ( uhi >= 0.0 )
00549         {
00550                 if ( uhi < twop52.d )
00551                 {
00552                         /* binary point occurs in uhi; truncate uhi to an integer
00553                         */
00554 
00555                         result.hi = trunc(uhi);
00556 
00557                         result.lo = 0.0;
00558 
00559                         if ( result.hi < uhi )
00560                                 return ( result );
00561 
00562                         /* must adjust result by one if ulo < 0.0 */
00563 
00564                         if ( ulo < 0.0 )
00565                         {
00566                                 result.hi -= 1.0;
00567 
00568                                 return ( result );
00569                         }
00570 
00571                         return ( result );
00572                 }
00573                 else if ( fabs(ulo) < twop52.d )
00574                 {
00575                         /* binary point occurs in ulo; truncate ulo to an integer
00576                         */
00577 
00578                         result.hi = uhi;
00579 
00580                         result.lo = trunc(ulo);
00581 
00582                         if ( result.lo > ulo )
00583                         {
00584                                 result.lo -= 1.0;
00585                         }
00586 
00587                         return ( result );
00588                 }
00589 
00590                 /* arg is an integer */
00591 
00592                 result.hi = uhi;
00593                 result.lo = ulo;
00594 
00595                 return ( result );
00596         }
00597         else
00598         {
00599                 if ( fabs(uhi) < twop52.d )
00600                 {
00601                         /* binary point occurs in uhi; truncate uhi to an integer
00602                         */
00603 
00604                         result.hi = trunc(uhi);
00605 
00606                         result.lo = 0.0;
00607 
00608                         if ( result.hi > uhi )
00609                                 return ( result );
00610 
00611                         /* must adjust result by one if ulo > 0.0 */
00612 
00613                         if ( ulo > 0.0 )
00614                         {
00615                                 result.hi += 1.0;
00616 
00617                                 return ( result );
00618                         }
00619 
00620                         return ( result );
00621                 }
00622                 else if ( fabs(ulo) < twop52.d )
00623                 {
00624                         /* binary point occurs in ulo; truncate ulo to an integer
00625                         */
00626 
00627                         result.hi = uhi;
00628 
00629                         result.lo = trunc(ulo);
00630 
00631                         if ( result.lo < ulo )
00632                         {
00633                                 result.lo += 1.0;
00634                         }
00635 
00636                         return ( result );
00637                 }
00638 
00639                 /* arg is an integer */
00640 
00641                 result.hi = uhi;
00642                 result.lo = ulo;
00643 
00644                 return ( result );
00645         }
00646 }
00647 
00648 /* ====================================================================
00649  *
00650  * FunctionName: c_fp_class_q
00651  *
00652  * Description: c_fp_class_q(u) returns the floating point class 
00653  *   to which u belongs, and should work equivalently to the
00654  *   functions declared in <fp_class.h>.
00655  *
00656  * ====================================================================
00657  */
00658 
00659 
00660 #pragma weak c_fp_class_q = __c_fp_class_q
00661 #define c_fp_class_q __c_fp_class_q
00662 
00663 INT
00664 fp_class_d( double x )
00665 {
00666   UINT64 ll, exp, mantissa;
00667   INT32 sign;
00668 
00669   ll = *(UINT64*)&x;
00670   exp = (ll >> DMANTWIDTH);
00671   sign = (exp >> DEXPWIDTH);
00672   exp &= 0x7ff;
00673   mantissa = (ll & (DSIGNMASK & DEXPMASK));
00674   if ( exp == 0x7ff ) {
00675     /* result is an infinity, or a NaN */
00676     if ( mantissa == 0 )
00677       return ( (sign == 0) ? FP_POS_INF : FP_NEG_INF );
00678     else if ( mantissa & ~DQNANBITMASK )
00679       return ( FP_QNAN );
00680     else
00681       return ( FP_SNAN );
00682   }
00683 
00684   if ( exp == 0 ) {
00685     if ( mantissa == 0 )
00686       return ( (sign == 0) ? FP_POS_ZERO : FP_NEG_ZERO );
00687     else
00688       return ( (sign == 0) ? FP_POS_DENORM : FP_NEG_DENORM );
00689   }
00690   else
00691     return ( (sign == 0) ? FP_POS_NORM : FP_NEG_NORM );
00692 }
00693 
00694 INT32
00695 c_fp_class_q(QUAD x)
00696 {       
00697 QUAD    y;
00698 INT     err;
00699 INT32   class;
00700 
00701         /* Notice that the definition of denormal for quad precision is
00702          * chosen so that normal quads have a full 107 bits precision
00703          * in their mantissas.
00704          */
00705 
00706         class = fp_class_d(x.hi);
00707 
00708         if ( (class != FP_POS_NORM) && (class != FP_NEG_NORM) )
00709                 return ( class );
00710 
00711         class = fp_class_d(x.lo);
00712 
00713         if ( (class == FP_POS_DENORM) && (class == FP_NEG_DENORM) )
00714                 return ( class );
00715 
00716         y.hi = twopm916.d;
00717         y.lo = 0.0;
00718 
00719         if ( c_q_ge(x, y, &err) )
00720                 return ( FP_POS_NORM );
00721 
00722         y.hi = -y.hi;
00723 
00724         if ( c_q_le(x, y, &err) )
00725                 return ( FP_POS_NORM );
00726 
00727         if ( x.hi > 0.0 )
00728                 return ( FP_POS_DENORM );
00729 
00730         return ( FP_NEG_DENORM );
00731 }
00732 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines