Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
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 * 26-jul-93 - Original Version 00042 * 00043 * Description: Convert a quad precision binary number to decimal. 00044 * 00045 * ==================================================================== 00046 * ==================================================================== 00047 */ 00048 00049 00050 #if QUAD_DEBUG 00051 #include <stdio.h> 00052 #endif 00053 00054 /* Macros to pull apart parts of single and double precision 00055 * floating point numbers in IEEE format 00056 */ 00057 00058 /* double precision */ 00059 00060 typedef union { 00061 struct { 00062 unsigned sign :1; 00063 unsigned exp :11; 00064 unsigned hi :20; 00065 unsigned lo :32; 00066 } fparts; 00067 struct { 00068 unsigned sign :1; 00069 unsigned exp :11; 00070 unsigned qnan_bit :1; 00071 unsigned hi :19; 00072 unsigned lo :32; 00073 } nparts; 00074 struct { 00075 unsigned hi; 00076 unsigned lo; 00077 } fwords; 00078 double d; 00079 } _dval; 00080 00081 /* quad precision */ 00082 00083 typedef union { 00084 struct { 00085 _dval hi; 00086 _dval lo; 00087 } qparts; 00088 struct { 00089 unsigned long long hi; 00090 unsigned long long lo; 00091 } fwords; 00092 } _ldblval; 00093 00094 /* parts of a double precision floating point number */ 00095 00096 #define SIGNBIT(X) (((_dval *)&(X))->fparts.sign) 00097 #define EXPONENT(X) (((_dval *)&(X))->fparts.exp) 00098 00099 #include "defs.h" 00100 #include "quad.h" 00101 00102 00103 #define min(x,y) ((x)<(y)? (x): (y)) 00104 #define max(x,y) ((x)>(y)? (x): (y)) 00105 00106 extern void c_qtenscale( _ldblval *, INT32, INT32 *); 00107 static INT32 c_qtoa(char *buffer, INT32 ndigit, QUAD x, INT32 fflag); 00108 extern INT c_q_to_a(char *str, QUAD x, INT *p_err ); 00109 00110 #pragma weak c_q_to_a = __c_q_to_a 00111 #define c_q_to_a __c_q_to_a 00112 00113 00114 /* ==================================================================== 00115 * 00116 * FunctionName: c_q_to_a 00117 * 00118 * Description: Convert a quad precision binary number to decimal. 00119 * 00120 * ==================================================================== 00121 */ 00122 00123 00124 INT 00125 c_q_to_a(char *str, QUAD x, INT *p_err ) 00126 { 00127 char buffer[42]; 00128 char *pbuff; 00129 INT32 ndigit; 00130 INT32 fflag; 00131 INT32 m, n; 00132 00133 *p_err = 0; 00134 00135 ndigit = 34; 00136 fflag = 0; 00137 00138 n = c_qtoa(buffer, ndigit, x, fflag); 00139 00140 if ( strncmp(buffer, "inf", 3) == 0 ) 00141 { 00142 strncpy( str, buffer, 3 ); 00143 00144 *(str + 3) = '\0'; 00145 00146 return ( *p_err ); 00147 } 00148 00149 if ( strncmp(buffer, "nan", 3) == 0 ) 00150 { 00151 strncpy( str, buffer, 3 ); 00152 00153 *(str + 3) = '\0'; 00154 00155 return ( *p_err ); 00156 } 00157 00158 if ( strncmp(buffer+1, "inf", 3) == 0 ) 00159 { 00160 strncpy( str, buffer, 4 ); 00161 00162 *(str + 4) = '\0'; 00163 00164 return ( *p_err ); 00165 } 00166 00167 if ( strncmp(buffer+1, "nan", 3) == 0 ) 00168 { 00169 strncpy( str, buffer+1, 3 ); 00170 00171 *(str + 3) = '\0'; 00172 00173 return ( *p_err ); 00174 } 00175 00176 if ( (n <= -1000) || (n >= 1000) ) 00177 { 00178 *p_err = 1; 00179 00180 *str = '\0'; 00181 00182 return ( *p_err ); 00183 } 00184 00185 pbuff = buffer; 00186 00187 if ( (buffer[0] == ' ') || (buffer[0] == '-') ) 00188 *str++ = *pbuff++; 00189 00190 *str++ = *pbuff++; /* copy first digit to output string */ 00191 00192 *str++ = '.'; 00193 00194 if ( ndigit > 1 ) 00195 { 00196 strncpy(str, pbuff, ndigit-1); 00197 00198 str += ndigit - 1; /* skip over digits copied */ 00199 } 00200 00201 *str++ = 'E'; 00202 00203 if ( n < 0 ) 00204 { 00205 n = -n; 00206 *str++ = '-'; 00207 } 00208 00209 m = n/100; 00210 00211 if ( m!= 0 ) 00212 *str++ = m + '0'; 00213 00214 n = n%100; 00215 00216 m = n/10; 00217 00218 *str++ = m + '0'; 00219 00220 m = n%10; 00221 00222 *str++ = m + '0'; 00223 00224 *str++ = '\0'; 00225 00226 return ( *p_err ); 00227 } 00228 00229 00230 /* ==================================================================== 00231 * 00232 * FunctionName: c_qtoa 00233 * 00234 * Description: Convert a quad precision binary number to decimal. 00235 * 00236 * Except for minor changes, this routine is the same as _qtoa() 00237 * in libc. Included here, so we can do cross compilations on 00238 * machines not supporting quad precision. 00239 * 00240 * ==================================================================== 00241 */ 00242 00243 static 00244 INT32 /* returns decimal exponent */ 00245 c_qtoa(buffer,ndigit,x,fflag) 00246 char *buffer; /* Destination for ascii string */ 00247 INT32 ndigit; /* number of digits to convert. 00248 * 1 <= ndigits <= 34 00249 * Log2(1e34) = 112.9 bits, so the 00250 * 107 significant bits can be con- 00251 * verted to decimal with room left 00252 * over. 00253 */ 00254 QUAD x; /* number to convert to ascii */ 00255 INT32 fflag; /* 0 for e format, 1 for f format */ 00256 { 00257 _ldblval value; /* the value manipulated */ 00258 #define HI (value.fwords.hi) /* top 64b of 128b fraction */ 00259 #define LO (value.fwords.lo) /* bottom 64b of 128b fraction */ 00260 00261 INT32 signhi, signlo; /* sign of HI = sign of number */ 00262 INT32 exphi, explo; /* exponents of HI and LO */ 00263 INT32 dexp; /* decimal exponent */ 00264 INT32 bexp; /* binary exponent */ 00265 UINT32 lohi; /* top 4 bits of lo */ 00266 UINT64 lolo; /* bottom 60 bits of lo */ 00267 INT32 nd; /* number of digits output */ 00268 INT32 guard; /* guard digit */ 00269 00270 #if QUAD_DEBUG 00271 char *buffer0=buffer; /* initial value of buffer */ 00272 #endif 00273 00274 00275 value.qparts.hi.d = x.hi; 00276 value.qparts.lo.d = x.lo; 00277 00278 #if QUAD_DEBUG 00279 printf("initially: HI=0x%016llx\n",HI); 00280 printf("LO=0x%016llx\n",LO); 00281 #endif 00282 00283 signhi = SIGNBIT(HI); 00284 HI = (HI<<1)>>1; /* discard sign bit */ 00285 *buffer++ = signhi? '-': ' '; 00286 00287 #if QUAD_DEBUG 00288 printf("after de-signing hi: HI=0x%016llx\n",HI); 00289 printf("signhi=%d\n",signhi); 00290 *buffer = '\0'; 00291 printf(" buffer=%s\n",buffer0); 00292 #endif 00293 00294 if( HI == 0 ) { /* true zero */ 00295 char *b; /* fencepost for buffer */ 00296 00297 b = buffer + ndigit; 00298 while(buffer < b) 00299 *buffer++ = '0'; 00300 00301 #if QUAD_DEBUG 00302 printf("HI was zero: HI=0x%016llx\n",HI); 00303 printf("signhi=%d\n",signhi); 00304 *buffer = '\0'; 00305 printf(" buffer=%s\n",buffer0); 00306 #endif 00307 00308 return(0); 00309 } 00310 00311 exphi = EXPONENT(HI); 00312 EXPONENT(HI) = 0; 00313 00314 #if QUAD_DEBUG 00315 printf("HI non-zero: HI=0x%016llx\n",HI); 00316 printf("exphi=%d\n",exphi); 00317 #endif 00318 00319 if(exphi == 2047) { /* infinity or NaN */ 00320 char *s; /* infinity or nan string */ 00321 char *infinity = "inf"; 00322 char *nan = "nan"; 00323 00324 s = HI==0? infinity: nan; 00325 00326 do 00327 *buffer++ = *s; 00328 while(*s++); 00329 00330 #if QUAD_DEBUG 00331 printf("NaN or Infinity: buffer=%s\n",buffer0); 00332 #endif 00333 00334 return(0); 00335 } 00336 00337 /* processing a number. create 128b fraction */ 00338 /* hi is non-zero, or the following while loop wouldn't terminate */ 00339 if(exphi == 0) { /* HI denorm */ 00340 exphi++; 00341 while( !(HI & (1ULL<<52))) { /* normalize - need not be fast */ 00342 HI <<=1; 00343 exphi--; 00344 00345 #if QUAD_DEBUG 00346 printf("HI denorm: HI=0x%016llx\n",HI); 00347 printf("exphi=%d\n",exphi); 00348 #endif 00349 00350 } 00351 } 00352 else { /* HI is normal number */ 00353 HI |= 1ULL<<52; /* expose hidden bit */ 00354 00355 #if QUAD_DEBUG 00356 printf("HI normal: HI=0x%016llx\n",HI); 00357 printf("exphi=%d\n",exphi); 00358 #endif 00359 00360 } 00361 00362 HI <<=11; /* left align */ 00363 00364 #if QUAD_DEBUG 00365 printf("HI aligned: HI=0x%016llx\n",HI); 00366 #endif 00367 00368 /* handle LO */ 00369 00370 signlo = SIGNBIT(LO) ^ signhi; /* HI,LO signs differ? */ 00371 SIGNBIT(LO) = 0; /* discard sign */ 00372 00373 #if QUAD_DEBUG 00374 printf("handle LO: LO=0x%016llx\n",LO); 00375 printf(" signlo=%d\n",signlo); 00376 #endif 00377 00378 if(LO) { /* lo is non-zero */ 00379 00380 explo = EXPONENT(LO); 00381 EXPONENT(LO) = 0; 00382 00383 #if QUAD_DEBUG 00384 printf("non-zero LO: LO=0x%016llx\n",LO); 00385 printf(" explo=%d\n",explo); 00386 #endif 00387 00388 LO <<=1; /* shift LO to expose 107th bit */ 00389 00390 #if QUAD_DEBUG 00391 printf("left-shifted LO: LO=0x%016llx\n",LO); 00392 #endif 00393 00394 if(explo == 0) { /* denorm */ 00395 INT32 shift_n; /* shift count */ 00396 00397 LO <<= 1; /* shift up one more bit */ 00398 #if QUAD_DEBUG 00399 printf("shifted up LO: LO=0x%016llx\n",LO); 00400 #endif 00401 shift_n = 53 - (exphi-explo); 00402 /* normalize to HI */ 00403 if(shift_n > 0) { 00404 LO <<= shift_n; 00405 } 00406 else if(shift_n < 0) { 00407 LO >>= -shift_n; 00408 } 00409 } 00410 else { /* LO normal number */ 00411 LO |= 1ULL<<53; /* expose hidden bit */ 00412 00413 #if QUAD_DEBUG 00414 printf("expose hidden bit: LO=0x%016llx\n",LO); 00415 #endif 00416 00417 LO >>= (exphi-explo) - 53; /* normalize to HI */ 00418 } 00419 00420 #if QUAD_DEBUG 00421 printf("normalize LO to HI: LO=0x%016llx\n",LO); 00422 #endif 00423 00424 if( signlo ) { /* LO is negative */ 00425 HI-= 1<<11; /* unround HI */ 00426 LO = (1ULL<<54) - LO; /* complement LO */ 00427 00428 #if QUAD_DEBUG 00429 printf("LO negative: HI=0x%016llx\n",HI); 00430 printf(" LO=0x%016llx\n",LO); 00431 #endif 00432 00433 } 00434 00435 HI |= LO>>43; /* combine HI and LO into 107b fract. */ 00436 LO <<=21; 00437 #if QUAD_DEBUG 00438 printf("LO&HI combined: HI=0x%016llx\n",HI); 00439 printf(" LO=0x%016llx\n",LO); 00440 #endif 00441 00442 } 00443 00444 /* At this point we have a 128b binary fraction HILO, the low 21 00445 * bits of which are zero, and a biased binary exponent exphi. 00446 * 00447 * Generate the decimal exponent by multiplying the binary 00448 * exponent by log10(2). 00449 */ 00450 00451 /* exphi is at most 9 bits plus sign. Shifts avoid overflow 00452 * and recover integer part. 00453 */ 00454 00455 dexp = ( ((INT32) (exphi-1023)) * (0x4D104D42L >> 21) ); 00456 /* truncate to -infinity */ 00457 dexp >>= 11; 00458 dexp++; 00459 00460 #if QUAD_DEBUG 00461 printf("before scaling: dexp=%d\n",dexp); 00462 #endif 00463 00464 /* Scale fraction by decimal exponent. */ 00465 00466 if(dexp) /* value *= 10 ** -dexp */ 00467 c_qtenscale(&value, -dexp, &bexp); 00468 else 00469 bexp=0; 00470 00471 #if QUAD_DEBUG 00472 printf("after scaling: HI=0x%016llx\n",HI); 00473 printf(" LO=0x%016llx\n",LO); 00474 printf(" bexp=%d\n",bexp); 00475 #endif 00476 00477 exphi += bexp; 00478 00479 #if QUAD_DEBUG 00480 printf("adjusted exphi: exphi=%d\n",exphi); 00481 #endif 00482 00483 /* unbias exphi */ 00484 00485 exphi -= 1022; 00486 00487 /* Remove binary exponent by denormalizing */ 00488 /* Shift an extra 4 bits to allow for later digit generation */ 00489 00490 LO = (LO >> 4-exphi) | (HI << (60+exphi)); 00491 HI >>= 4-exphi; 00492 00493 #if QUAD_DEBUG 00494 printf("denormalized: HI=0x%016llx\n",HI); 00495 printf(" LO=0x%016llx\n",LO); 00496 #endif 00497 00498 /* Split LO inpreparation to producing digits */ 00499 00500 lohi = LO >> 60; 00501 lolo = LO & ((1ULL<<60)-1); 00502 00503 #if QUAD_DEBUG 00504 printf("split LO: lohi=0x%02x\n",lohi); 00505 printf(" lolo=0x%016llx\n",lolo); 00506 #endif 00507 00508 /* find first non-zero digit */ 00509 while( !(HI >> 60) ) { 00510 lolo *= 10; 00511 lohi = lohi * 10 + (lolo>>60); 00512 lolo &= (1ULL<<60)-1; 00513 HI = HI * 10 + (lohi>>4); 00514 lohi &= 0xF; 00515 dexp--; 00516 00517 #if QUAD_DEBUG 00518 printf("finding first digit: HI=0x%016llx\n",HI); 00519 printf(" lohi=0x%02x\n",lohi); 00520 printf(" lolo=0x%016llx\n",lolo); 00521 printf(" dexp=%d\n",dexp); 00522 #endif 00523 00524 } 00525 /* produce digits */ 00526 00527 if(fflag) { /* f format */ 00528 nd = min(34, ndigit + dexp + 1); /* need 1 integer digit */ 00529 } 00530 else { 00531 nd = ndigit; /* e format */ 00532 } 00533 00534 #if QUAD_DEBUG 00535 printf("number of digits: nd=%d\n",nd); 00536 printf(" ndigit=%d\n",ndigit); 00537 printf(" dexp=%d\n",dexp); 00538 #endif 00539 00540 /* produce digits - always at least one */ 00541 do { 00542 *buffer++ = '0' + (HI>>60); 00543 HI &= (1ULL<<60) - 1; 00544 lolo *= 10; 00545 lohi = lohi * 10 + (lolo>>60); 00546 lolo &= (1ULL<<60)-1; 00547 HI = HI * 10 + (lohi>>4); 00548 lohi &= 0xF; 00549 00550 #if QUAD_DEBUG 00551 printf("another digit: HI=0x%016llx\n",HI); 00552 printf(" lohi=0x%02x\n",lohi); 00553 printf(" lolo=0x%016llx\n",lolo); 00554 *buffer = '\0'; 00555 printf(" buffer=%s\n",buffer0); 00556 #endif 00557 00558 } 00559 while(--nd > 0); 00560 00561 /* decimal round */ 00562 00563 /* *buffer guard rest Action 00564 * 00565 * dc 0-4 dc none 00566 * dc 6-9 dc round 00567 * odd 5 dc round 00568 * even 5 0 none 00569 * even 5 !=0 round 00570 */ 00571 00572 guard = HI>>60; 00573 if(guard >= 5) { 00574 if(guard > 5 || 00575 (*buffer-1)&1 || /* buffer odd */ 00576 HI & ((1ULL<<60) - 1) || 00577 lohi || lolo) { /* rest non-zero */ 00578 char *b=buffer; /* buffer pointer */ 00579 00580 /* must round */ 00581 00582 #if QUAD_DEBUG 00583 printf("must round\n"); 00584 #endif 00585 for(b=buffer-1; ; b--) { 00586 if(*b < '0' || '9' < *b) { /* attempt to carry into sign */ 00587 *(b+1) = '1'; 00588 dexp++; 00589 if(fflag && nd != min(34, ndigit + dexp + 1)) { 00590 *buffer++ = '0'; /* need one more digit */ 00591 #if QUAD_DEBUG 00592 printf("added a zero: fflag=%d\n",fflag); 00593 printf(" ndigit=%d\n",ndigit); 00594 printf(" nd=%d\n",nd); 00595 #endif 00596 } 00597 00598 #if QUAD_DEBUG 00599 printf("carry into sign: dexp=%d\n",dexp); 00600 printf(" buffer=%s\n",buffer0); 00601 #endif 00602 00603 break; 00604 } 00605 (*b)++; 00606 00607 #if QUAD_DEBUG 00608 *buffer = '\0'; 00609 printf("round: buffer=%s\n",buffer0); 00610 #endif 00611 00612 if(*b > '9') { /* carry */ 00613 *b = '0'; 00614 00615 #if QUAD_DEBUG 00616 printf("carry: buffer=%s\n",buffer0); 00617 #endif 00618 00619 } 00620 else 00621 break; /* no carry */ 00622 } 00623 00624 } 00625 } 00626 00627 #if REALLYNEEDED 00628 if(fflag && ndigit+dexp < 0) { /* no significant digits */ 00629 00630 dexp--; /* This is a lie. However, that's the 00631 * way dtoa behaves (sometimes!), so 00632 * make qtoa work the same way. 00633 */ 00634 } 00635 #endif 00636 00637 *buffer = '\0'; 00638 00639 #if QUAD_DEBUG 00640 printf("done: buffer=%s\n",buffer0); 00641 printf(" dexp=%d\n", dexp); 00642 #endif 00643 00644 return dexp; 00645 } 00646