g_ddfmt.c revision 225736
11573Srgrimes/**************************************************************** 21573Srgrimes 31573SrgrimesThe author of this software is David M. Gay. 41573Srgrimes 51573SrgrimesCopyright (C) 1998 by Lucent Technologies 61573SrgrimesAll Rights Reserved 71573Srgrimes 81573SrgrimesPermission to use, copy, modify, and distribute this software and 91573Srgrimesits documentation for any purpose and without fee is hereby 101573Srgrimesgranted, provided that the above copyright notice appear in all 111573Srgrimescopies and that both that the copyright notice and this 121573Srgrimespermission notice and warranty disclaimer appear in supporting 131573Srgrimesdocumentation, and that the name of Lucent or any of its entities 141573Srgrimesnot be used in advertising or publicity pertaining to 151573Srgrimesdistribution of the software without specific, written prior 161573Srgrimespermission. 171573Srgrimes 181573SrgrimesLUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 191573SrgrimesINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 201573SrgrimesIN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY 211573SrgrimesSPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 221573SrgrimesWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 231573SrgrimesIN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 241573SrgrimesARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 251573SrgrimesTHIS SOFTWARE. 261573Srgrimes 271573Srgrimes****************************************************************/ 281573Srgrimes 291573Srgrimes/* Please send bug reports to David M. Gay (dmg@acm.org). */ 301573Srgrimes 311573Srgrimes#include "gdtoaimp.h" 3282995Sache#include <string.h> 3382995Sache 341573Srgrimes char * 351573Srgrimes#ifdef KR_headers 361573Srgrimesg_ddfmt(buf, dd0, ndig, bufsize) char *buf; double *dd0; int ndig; size_t bufsize; 371573Srgrimes#else 381573Srgrimesg_ddfmt(char *buf, double *dd0, int ndig, size_t bufsize) 391573Srgrimes#endif 401573Srgrimes{ 411573Srgrimes FPI fpi; 421573Srgrimes char *b, *s, *se; 431573Srgrimes ULong *L, bits0[4], *bits, *zx; 441573Srgrimes int bx, by, decpt, ex, ey, i, j, mode; 451573Srgrimes Bigint *x, *y, *z; 461573Srgrimes U *dd, ddx[2]; 471573Srgrimes#ifdef Honor_FLT_ROUNDS /*{{*/ 481573Srgrimes int Rounding; 4982975Sache#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */ 501573Srgrimes Rounding = Flt_Rounds; 511573Srgrimes#else /*}{*/ 521573Srgrimes Rounding = 1; 531573Srgrimes switch(fegetround()) { 541573Srgrimes case FE_TOWARDZERO: Rounding = 0; break; 551573Srgrimes case FE_UPWARD: Rounding = 2; break; 5687016Sache case FE_DOWNWARD: Rounding = 3; 571573Srgrimes } 5887016Sache#endif /*}}*/ 5987016Sache#else /*}{*/ 6087016Sache#define Rounding FPI_Round_near 6187016Sache#endif /*}}*/ 6287016Sache 631573Srgrimes if (bufsize < 10 || bufsize < ndig + 8) 641573Srgrimes return 0; 651573Srgrimes 661573Srgrimes dd = (U*)dd0; 671573Srgrimes L = dd->L; 681573Srgrimes if ((L[_0] & 0x7ff00000L) == 0x7ff00000L) { 6982975Sache /* Infinity or NaN */ 701573Srgrimes if (L[_0] & 0xfffff || L[_1]) { 711573Srgrimes nanret: 721573Srgrimes return strcp(buf, "NaN"); 731573Srgrimes } 741573Srgrimes if ((L[2+_0] & 0x7ff00000) == 0x7ff00000) { 751573Srgrimes if (L[2+_0] & 0xfffff || L[2+_1]) 7682975Sache goto nanret; 7782975Sache if ((L[_0] ^ L[2+_0]) & 0x80000000L) 7882975Sache goto nanret; /* Infinity - Infinity */ 7982975Sache } 8082975Sache infret: 811573Srgrimes b = buf; 821573Srgrimes if (L[_0] & 0x80000000L) 831573Srgrimes *b++ = '-'; 841573Srgrimes return strcp(b, "Infinity"); 851573Srgrimes } 861573Srgrimes if ((L[2+_0] & 0x7ff00000) == 0x7ff00000) { 871573Srgrimes L += 2; 881573Srgrimes if (L[_0] & 0xfffff || L[_1]) 8982982Sache goto nanret; 9087016Sache goto infret; 9182975Sache } 921573Srgrimes if (dval(&dd[0]) + dval(&dd[1]) == 0.) { 931573Srgrimes b = buf; 941573Srgrimes#ifndef IGNORE_ZERO_SIGN 951573Srgrimes if (L[_0] & L[2+_0] & 0x80000000L) 961573Srgrimes *b++ = '-'; 971573Srgrimes#endif 981573Srgrimes *b++ = '0'; 991573Srgrimes *b = 0; 1001573Srgrimes return b; 1011573Srgrimes } 1021573Srgrimes if ((L[_0] & 0x7ff00000L) < (L[2+_0] & 0x7ff00000L)) { 1031573Srgrimes dval(&ddx[1]) = dval(&dd[0]); 1041573Srgrimes dval(&ddx[0]) = dval(&dd[1]); 1051573Srgrimes dd = ddx; 1061573Srgrimes L = dd->L; 10782975Sache } 1081573Srgrimes z = d2b(dval(&dd[0]), &ex, &bx); 1091573Srgrimes if (dval(&dd[1]) == 0.) 11087016Sache goto no_y; 11182975Sache x = z; 11282975Sache y = d2b(dval(&dd[1]), &ey, &by); 11382975Sache if ( (i = ex - ey) !=0) { 11482982Sache if (i > 0) { 11587016Sache x = lshift(x, i); 11687016Sache ex = ey; 11787016Sache } 1181573Srgrimes else 1191573Srgrimes y = lshift(y, -i); 1201573Srgrimes } 1211573Srgrimes if ((L[_0] ^ L[2+_0]) & 0x80000000L) { 1221573Srgrimes z = diff(x, y); 12317141Sjkh if (L[_0] & 0x80000000L) 1241573Srgrimes z->sign = 1 - z->sign; 1251573Srgrimes } 1261573Srgrimes else { 1271573Srgrimes z = sum(x, y); 1281573Srgrimes if (L[_0] & 0x80000000L) 1291573Srgrimes z->sign = 1; 1301573Srgrimes } 1311573Srgrimes Bfree(x); 1321573Srgrimes Bfree(y); 1331573Srgrimes no_y: 13482975Sache bits = zx = z->x; 13582975Sache for(i = 0; !*zx; zx++) 13682975Sache i += 32; 1371573Srgrimes i += lo0bits(zx); 1381573Srgrimes if (i) { 13982975Sache rshift(z, i); 1401573Srgrimes ex += i; 1411573Srgrimes } 1421573Srgrimes fpi.nbits = z->wds * 32 - hi0bits(z->x[j = z->wds-1]); 143 if (fpi.nbits < 106) { 144 fpi.nbits = 106; 145 if (j < 3) { 146 for(i = 0; i <= j; i++) 147 bits0[i] = bits[i]; 148 while(i < 4) 149 bits0[i++] = 0; 150 bits = bits0; 151 } 152 } 153 mode = 2; 154 if (ndig <= 0) { 155 if (bufsize < (int)(fpi.nbits * .301029995664) + 10) { 156 Bfree(z); 157 return 0; 158 } 159 mode = 0; 160 } 161 fpi.emin = 1-1023-53+1; 162 fpi.emax = 2046-1023-106+1; 163 fpi.rounding = Rounding; 164 fpi.sudden_underflow = 0; 165 i = STRTOG_Normal; 166 s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se); 167 b = g__fmt(buf, s, se, decpt, z->sign, bufsize); 168 Bfree(z); 169 return b; 170 } 171