Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
c_a_to_q.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  * Revision history:
00041  *  28-jun-93 - Original Version
00042  *
00043  * Description: Convert a decimal number to a quad precision binary.
00044  *
00045  * ====================================================================
00046  * ====================================================================
00047  */
00048 
00049 static char *source_file = __FILE__;
00050 
00051 /* Macros to pull apart parts of single and  double precision
00052  * floating point numbers in IEEE format
00053  */
00054 
00055 /* double precision */
00056 
00057 typedef  union {
00058         struct {
00059                 unsigned  sign  :1;
00060                 unsigned  exp   :11;
00061                 unsigned  hi    :20;
00062                 unsigned  lo    :32;
00063         } fparts;
00064         struct {
00065                 unsigned  sign  :1;
00066                 unsigned  exp   :11;
00067                 unsigned  qnan_bit      :1;
00068                 unsigned  hi    :19;
00069                 unsigned  lo    :32;
00070         } nparts;
00071         struct {
00072                 unsigned hi;
00073                 unsigned lo;
00074         } fwords;
00075         double  d;
00076 } _dval;
00077 
00078 /* quad precision */
00079 
00080 typedef  union {
00081         struct {
00082                 _dval   hi;
00083                 _dval   lo;
00084         } qparts;
00085         struct {
00086                 unsigned long long hi;
00087                 unsigned long long lo;
00088         } fwords;
00089 } _ldblval;
00090 
00091 /* parts of a double precision floating point number */
00092 
00093 #define SIGNBIT(X)      (((_dval *)&(X))->fparts.sign)
00094 #define EXPONENT(X)     (((_dval *)&(X))->fparts.exp)
00095 #define MAXCOUNT        34
00096 
00097 
00098 #include <math.h>
00099 #include "defs.h"
00100 #include "quad.h"
00101 
00102 
00103 extern  void    c_qtenscale( _ldblval *, INT32, INT32 *);
00104 extern  QUAD    c_a_to_q(char *str, INT *p_err );
00105 static  QUAD    c_atoq(char *buffer, INT32 ndigit, INT32 exp);
00106 
00107 /* ascii to quad */
00108 
00109 #pragma weak c_a_to_q = __c_a_to_q
00110 #define c_a_to_q __c_a_to_q
00111 
00112 #define MAXDIGITS 34
00113 
00114 
00115 /* ====================================================================
00116  *
00117  * FunctionName: c_a_to_q
00118  *
00119  * Description: Convert a decimal number to quad precision
00120  * Except for minor changes, this routine is the same as atold()
00121  * in libc.  Included here, so we can do cross compilations on
00122  * machines not supporting quad precision.
00123  *
00124  *
00125  * ====================================================================
00126  */
00127 
00128 QUAD
00129 c_a_to_q(char *s, INT *p_err )
00130 {
00131     register UINT32 c;
00132     register UINT32 negate, decimal_point;
00133     register char *d;
00134     register INT32 exp;
00135     QUAD        x;
00136     register INT32 dpchar;
00137     char digits[MAXDIGITS];
00138 
00139     *p_err = 0;
00140 
00141     while ( (c = *s++) == ' ' )
00142                 ;
00143 
00144     /* process sign */
00145     negate = 0;
00146     if (c == '+') {
00147         c = *s++;
00148     }
00149     else if (c == '-') {
00150         negate = 1;
00151         c = *s++;
00152     }
00153     d = digits;
00154     dpchar = '.' - '0';
00155     decimal_point = 0;
00156     exp = 0;
00157     while (1) {
00158         c -= '0';
00159         if (c < 10) {
00160             if (d == digits+MAXDIGITS) {
00161                 /* ignore more than 34 digits, but adjust exponent */
00162                 exp += (decimal_point ^ 1);
00163             }
00164             else {
00165                 if (c == 0 && d == digits) {
00166                     /* ignore leading zeros */
00167                         ;
00168                 }
00169                 else {
00170                     *d++ = c;
00171                 }
00172                 exp -= decimal_point;
00173             }
00174         }
00175         else if (c == dpchar && !decimal_point) {    /* INTERNATIONAL */
00176             decimal_point = 1;
00177         }
00178         else {
00179             break;
00180         }
00181         c = *s++;
00182     }
00183     if (d == digits) {
00184         x.hi = 0.0;
00185         x.lo = 0.0;
00186         return x;
00187     }
00188     if (c == 'e'-'0' || c == 'E'-'0') {
00189         register UINT32 negate_exp = 0;
00190         register INT32 e = 0;
00191         c = *s++;
00192         if (c == '+' || c == ' ') {
00193             c = *s++;
00194         }
00195         else if (c == '-') {
00196             negate_exp = 1;
00197             c = *s++;
00198         }
00199         if (c -= '0', c < 10) {
00200             do {
00201                 if (e <= 340) 
00202                     e = e * 10 + c;
00203                 else break;
00204                 c = *s++;
00205             }
00206             while (c -= '0', c < 10);
00207             if (negate_exp) {
00208                 e = -e;
00209             }
00210             if (e < -(323+MAXDIGITS) || e > 308) 
00211                 exp = e;
00212             else 
00213                 exp += e;
00214         }
00215     }
00216 
00217     if (exp < -(324+MAXDIGITS)) {
00218         x.hi = 0.0;
00219         x.lo = 0.0;
00220     }
00221     else if (exp > 308) {
00222         x.hi = HUGE_VAL;
00223         x.lo = 0.0;
00224     }
00225     else {
00226         /* let c_atoq diagnose under- and over-flows */
00227         /* if the input was == 0.0, we have already returned,
00228            so retval of +-Inf signals OVERFLOW, 0.0 UNDERFLOW
00229         */
00230 
00231         x = c_atoq (digits, d - digits, exp);
00232     }
00233     if (negate) {
00234         x.hi = -x.hi;
00235         x.lo = -x.lo;
00236     }
00237     return x;
00238 }
00239 
00240 /* ====================================================================
00241  *
00242  * FunctionName: c_atoq
00243  *
00244  * Description: Convert a decimal number to a quad precision binary.
00245  *
00246  * Except for minor changes, this routine is the same as _atoq()
00247  * in libc.  Included here, so we can do cross compilations on
00248  * machines not supporting quad precision.
00249  *
00250  * ====================================================================
00251  */
00252 
00253 static
00254 QUAD
00255 c_atoq(buffer,ndigit,exp)
00256      char *buffer;              /* Values from 0 to 9, NOT ascii. 
00257                                  * Leading zeros have been discarded, 
00258                                  * except for the case of zero in which
00259                                  * case there is a single 0 digit. 
00260                                  */
00261 
00262      INT32  ndigit;             /* 1 <= ndigit <= 37.
00263                                  * Log2(1e37) = 122.9 bits, so the 
00264                                  * number can be converted to a 128 bit
00265                                  * integer with room left over.
00266                                  */
00267 
00268      INT32 exp;                 /* The minimum quad numbers are
00269                                  *
00270                                  * 4.9406564584124654e-324 (denorm) and 
00271                                  * 2.2250738585072014e-308 (norm).
00272                                  *
00273                                  * The maximum value is 
00274                                  *
00275                                  * 1.7976931348623157e+308, 
00276                                  *
00277                                  * therefore 
00278                                  * -324-ndigit = -361 <= exp <= 308.
00279                                  */
00280 {
00281   _ldblval value;               /* the result */
00282 #define HI (value.fwords.hi)    /* top 64b of 124b integer */
00283 #define LO (value.fwords.lo)    /* bottom 60b of 124b integer */
00284                                 /* later converted to 128b fraction */
00285 
00286   QUAD  result;
00287   UINT32 guard;                 /* First guard bit */
00288   UINT32 rest;                  /* Remaining 21 guard bits */
00289   UINT64 lolo;                  /* lower 60b of LO */
00290   UINT32 lohi;                  /* upper  4b of LO */
00291   double z;                     /* canonical HI */
00292 
00293   INT32 exphi, explo;           /* binary exponent */
00294   INT32 nzero;                  /* number of non-zeros */
00295   INT32 i;                      /* loop index */
00296   INT32 x;                      /* temporary */
00297   INT32 losign=0;               /* sign of LO */
00298 
00299   char *bufferend;              /* pointer to char after last digit */
00300   
00301   HI = 0;
00302 
00303   /* Check for zero and treat it as a special case */
00304 
00305   if ((INT32) *buffer == 0){
00306     result.hi = result.lo = 0.0;
00307     return ( result );
00308   }
00309 
00310   /* Convert the decimal digits to a binary integer. */
00311 
00312   bufferend = buffer + ndigit;
00313   HI = 0;                       
00314   LO = *buffer++;
00315 
00316   /* the first batch of digits fits in LO */
00317   for( i=1 ; buffer < bufferend && i<19; buffer++, i++ ){
00318     LO *= 10;
00319     LO += *buffer;
00320   }
00321 
00322 #if QUAD_DEBUG
00323   printf("halfway thru conversion: HI=0x%016llx\n",HI);
00324   printf("                         LO=0x%016llx\n",LO);
00325   printf("                         i=%d\n",i);
00326 #endif
00327 
00328   if( buffer < bufferend ) {
00329     /* The second batch of digits affects both HI and LO */
00330 
00331     lolo = LO & (1Ull<<60)-1;   /* Split LO into 60b  */
00332     lohi = LO >> 60;            /*            and 4b pieces */
00333 
00334 #if QUAD_DEBUG
00335   printf("After LO split: lohi=0x%x\n",lohi);
00336   printf("                lolo=0x%016llx\n",lolo);
00337 #endif
00338 
00339     for( ; buffer < bufferend; buffer++ ){
00340       lolo = 10*lolo + *buffer; /* Multiply by 10 and add digit */
00341 #if QUAD_DEBUG
00342   printf("After 10*: lolo=0x%016llx\n",lolo);
00343 #endif
00344       lohi = 10*lohi + (lolo>>60);
00345       HI   = 10*HI   + (lohi>>4);
00346       lolo &= (1Ull<<60)-1;     /* discard carries already propagated */
00347 #if QUAD_DEBUG
00348   printf("After carry discard: lolo=0x%016llx\n",lolo);
00349 #endif
00350       lohi &= (1U  << 4)-1;     /* Are these two statements needed??? */
00351 
00352 #if QUAD_DEBUG
00353   printf("After iteration: lohi=0x%x\n",lohi);
00354   printf("                 lolo=0x%016llx\n",lolo);
00355 #endif
00356 
00357     }
00358     /* Reconstitute LO from its pieces. */
00359     LO = lolo | ((UINT64) lohi)<<60;
00360 
00361 #if QUAD_DEBUG
00362   printf("After reconstitution: HI=0x%016llx\n",HI);
00363   printf("                      LO=0x%016llx\n",LO);
00364 #endif
00365 
00366   }
00367 
00368 #if QUAD_DEBUG
00369   printf("after conversion: HI=0x%016llx\n",HI);
00370   printf("                  LO=0x%016llx\n",LO);
00371 #endif
00372 
00373   /* Normalize HI-LO */
00374 
00375   exphi = 128;                  /* convert from 128b int to fraction */
00376   if (HI == 0){                 /* 64 bit shift */
00377     HI = LO;
00378     LO = 0;
00379     exphi -= 64;
00380   }
00381 
00382   /* Count number of non-zeroes in HI */
00383   nzero = 0;
00384   if ( HI >> (32        ) ){ nzero  = 32; }
00385   if ( HI >> (16 + nzero) ){ nzero += 16; }
00386   if ( HI >> ( 8 + nzero) ){ nzero +=  8; }
00387   if ( HI >> ( 4 + nzero) ){ nzero +=  4; }
00388   if ( HI >> ( 2 + nzero) ){ nzero +=  2; }
00389   if ( HI >> ( 1 + nzero) ){ nzero +=  1; }
00390   if ( HI >> (     nzero) ){ nzero +=  1; }
00391 
00392   /* Normalize */
00393   HI = (HI << (64-nzero)) | (LO >> (nzero));
00394   LO <<= 64-nzero;
00395   exphi -= 64-nzero;
00396 
00397   /* At this point we have a 128b fraction and a binary exponent 
00398    * but have yet to incorporate the decimal exponent.
00399    */
00400 
00401 #if QUAD_DEBUG
00402   printf("after normalization: HI=0x%016llx\n",HI);
00403   printf("                     LO=0x%016llx\n",LO);
00404   printf("                     nzero=%d\n",nzero);
00405   printf("                     exphi=%d\n",exphi);
00406 #endif
00407 
00408   /* multiply by 10^exp */
00409 
00410   c_qtenscale(&value,exp,&x);
00411   exphi += x;
00412 
00413 #if QUAD_DEBUG
00414   printf("after multiplication: HI=0x%016llx\n",HI);
00415   printf("                      LO=0x%016llx\n",LO);
00416   printf("                     exphi=%d\n",exphi);
00417 #endif
00418   /* Round to 107 bits */
00419   /* Take the 128 bits of HI and LO and divide them as follows
00420    *
00421    * before     HI      LO      guard   rest
00422    *            64b     64b
00423    * after      53b     54b     1b      20b
00424    *                   =11 of HI
00425    *                   +43 of LO
00426    */
00427 
00428   rest = LO & (1ULL<<20)-1;
00429   LO >>= 20;
00430 
00431 #if QUAD_DEBUG
00432   printf("during split: LO=0x%016llx\n",LO);
00433 #endif
00434 
00435   guard = LO & 1;
00436   LO >>= 1;
00437 
00438 #if QUAD_DEBUG
00439   printf("during split: LO=0x%016llx\n",LO);
00440 #endif
00441 
00442   LO |= (HI & (1ULL<<11)-1) << 43;
00443   HI >>= 11;
00444 
00445 #if QUAD_DEBUG
00446   printf("after split: HI=0x%016llx\n",HI);
00447   printf("             LO=0x%016llx\n",LO);
00448   printf("             guard=%d\n",guard);
00449   printf("             rest=%lx\n",rest);
00450 #endif
00451 
00452   /*    LO&1    guard   rest    Action
00453    *    
00454    *    dc      0       dc      none
00455    *    1       1       dc      round
00456    *    0       1       0       none
00457    *    0       1       !=0     round
00458    */
00459 
00460   if(guard) {
00461     if(LO&1 || rest) {
00462       LO++;                     /* round */
00463       HI += LO>>54;
00464       LO &= (1ULL<<54)-1;
00465       if(HI>>53) {              /* carry all the way across */
00466         HI >>= 1;               /* renormalize */
00467         exphi ++;
00468       }
00469     }
00470   }
00471 
00472   explo = exphi-53;
00473   
00474 #if QUAD_DEBUG
00475   printf("after rounding: HI=0x%016llx\n",HI);
00476   printf("                LO=0x%016llx\n",LO);
00477   printf("                exphi=%d\n",exphi);
00478   printf("                explo=%d\n",explo);
00479 #endif
00480 
00481   /* Apply Dekker's algorithm */
00482   /* Determine whether HI <- (double) HI+LO would change HI */
00483   if( LO & (1ULL<<53) ) {       /* high bit of LO on */
00484     if(HI & 1  ||  LO & ((1ULL<<53)-1)) { 
00485       HI++;                     /* round */
00486       if(HI & (1ULL<<53)) {     /* ripple carry */
00487         HI >>= 1;
00488         exphi++;
00489       }
00490       LO = (1ULL<<54) - LO;     /* complement LO */
00491       losign = 1;
00492 
00493 #if QUAD_DEBUG
00494   printf("after dekker: HI=0x%016llx\n",HI);
00495   printf("              LO=0x%016llx\n",LO);
00496   printf("              exphi=%d\n",exphi);
00497   printf("              explo=%d\n",explo);
00498   printf("              losign=%d\n",losign);
00499 #endif
00500       
00501     }
00502   }
00503   if( LO ) {
00504     /* normalize LO */
00505     if(LO & (1ULL<<53)) {       /* LO = 0x0020000000000000 */
00506       explo++;                  /* in all other cases this bit's zero */
00507       LO >>=1;
00508 
00509 #if QUAD_DEBUG
00510   printf("after right shift: LO=0x%016llx\n",LO);
00511   printf("                   explo=%d\n",explo);
00512 #endif
00513       
00514     }
00515     else {
00516       while( ! (LO & 0x0010000000000000ULL) ){
00517 
00518 #if QUAD_DEBUG
00519   printf("before left shift: LO=0x%016llx\n",LO);
00520   printf("                  explo=%d\n",explo);
00521 #endif
00522       
00523         explo--;
00524         LO <<= 1;
00525       }
00526     }
00527     explo--;                    /* we now have only 53 bits */
00528   }
00529   
00530 #if QUAD_DEBUG
00531   printf("after LO normalize: LO=0x%016llx\n",LO);
00532   printf("                    explo=%d\n",explo);
00533 #endif
00534 
00535   /*
00536    * Check for overflow and denorm......
00537    * IEEE Double Precision Format
00538    * (From Table 7-8 of Kane and Heinrich)
00539    * 
00540    * Fraction bits               52
00541    * Emax                     +1023
00542    * Emin                     -1022
00543    * Exponent bias            +1023
00544    * Exponent bits               11
00545    * Integer bit             hidden
00546    * Total width in bits         64
00547    */
00548   
00549   if (exphi > 1024) {           /* overflow */
00550     value.qparts.hi.d = value.qparts.lo.d =  HUGE_VAL;
00551 
00552 #if QUAD_DEBUG
00553   printf("Overflow: value.qparts.hi.d=0x%016llx\n",value.qparts.hi.d);
00554   printf("          value.qparts.lo.d=0x%016llx\n",value.qparts.lo.d);
00555 #endif
00556 
00557     result.hi = value.qparts.hi.d;
00558     result.lo = value.qparts.lo.d;
00559     return ( result );
00560   }
00561   if (exphi <= -1022) {         /* HI denorm or underflow */
00562 
00563     value.qparts.lo.d = 0;      /* therefore LO is zero */
00564     exphi += 1022;
00565     if( exphi < -52 ) {         /* underflow */
00566       value.qparts.hi.d = 0;
00567 
00568 #if QUAD_DEBUG
00569   printf("HI underflow: HI=0x%016llx\n",HI);
00570   printf("              exphi=%d\n",exphi);
00571 #endif
00572 
00573     }
00574     else {                      /* denorm */
00575       rest = HI & (1UL << exphi-1)-1;
00576       guard = (HI & (1UL << exphi)) >> exphi;
00577       HI >>= 1-exphi;           /* exponent is zero */
00578 
00579 #if QUAD_DEBUG
00580   printf("HI denorm: HI=0x%016llx\n",HI);
00581   printf("           rest=0x%016llx\n",rest);
00582   printf("           guard=%d\n",guard);
00583   printf("           exphi=%d\n",exphi);
00584 #endif
00585 
00586       /* Round */
00587       if( guard ) {
00588         if( HI&1 || rest ) {
00589           HI++;
00590           if( HI == (1ULL << 52) ) { /* carry created a normal number */
00591             HI = 0;
00592             EXPONENT(HI) = 1;
00593           }
00594 
00595 #if QUAD_DEBUG
00596   printf("Round denorm: HI=0x%016llx\n",HI);
00597 #endif
00598 
00599         }
00600       }
00601     }
00602   }
00603   else {                        /* HI is normal */
00604     HI &= ~(1ULL << 52);        /* hide hidden bit */
00605     EXPONENT(HI) = exphi + 1022; /* add bias */
00606 
00607 #if QUAD_DEBUG
00608   printf("Normal HI: HI=0x%016llx\n",HI);
00609 #endif
00610 
00611   }
00612 
00613   if( explo <= -1022 ) {        /* LO denorm or underflow */
00614     explo += 1022;
00615     if( explo < -52 ) {         /* underflow */
00616       value.qparts.lo.d = 0;
00617 
00618 #if QUAD_DEBUG
00619   printf("LO underflow: LO=0x%016llx\n",LO);
00620   printf("              explo=%d\n",explo);
00621 #endif
00622 
00623     }
00624     else {                      /* denorm */
00625       rest = LO & (1UL << explo-1)-1;
00626       guard = (LO & (1UL << explo)) >> explo;
00627       LO >>= 1-explo;           /* exponent is zero */
00628 
00629 #if QUAD_DEBUG
00630   printf("LO denorm: LO=0x%016llx\n",LO);
00631   printf("           explo=%d\n",explo);
00632   printf("           guard=%d\n",guard);
00633   printf("           rest=0x%016llx\n",rest);
00634 #endif
00635 
00636       /* Round */
00637       if( guard ) {
00638         if( LO&1 || rest ) {
00639           LO++;
00640           if( LO == (1ULL << 52) ) { /* carry created normal number */
00641             LO = 0;
00642             EXPONENT(LO) = 1;   
00643   }
00644 
00645 #if QUAD_DEBUG
00646   printf("After LO round: LO=0x%016llx\n",LO);
00647 #endif
00648 
00649         }
00650       }
00651     }
00652   }
00653   else {                        /* LO is normal */
00654     if(LO) {
00655       LO &= ~(1ULL << 52);      /* hide hidden bit */
00656       EXPONENT(LO) = explo + 1022; /* add bias */
00657     }
00658 #if QUAD_DEBUG
00659   printf("Normal LO before making canonical: LO=0x%016llx\n",LO);
00660 #endif
00661     /* Make representation canonical */
00662     z = value.qparts.lo.d + value.qparts.hi.d;
00663     value.qparts.lo.d -= (z - value.qparts.hi.d);
00664     value.qparts.hi.d = z;
00665 #if QUAD_DEBUG
00666   printf("After making canonical: HI=0x%016llx\n",HI);
00667   printf("                      : LO=0x%016llx\n",LO);
00668 #endif
00669 
00670   }
00671     
00672   SIGNBIT(LO) = losign;
00673   result.hi = value.qparts.hi.d;
00674   result.lo = value.qparts.lo.d;
00675   return ( result );
00676 }
00677 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines