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 #if QUAD_DEBUG
00051 #include <stdio.h>
00052 #endif
00053
00054
00055
00056
00057
00058
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
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
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
00117
00118
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++;
00191
00192 *str++ = '.';
00193
00194 if ( ndigit > 1 )
00195 {
00196 strncpy(str, pbuff, ndigit-1);
00197
00198 str += ndigit - 1;
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
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243 static
00244 INT32
00245 c_qtoa(buffer,ndigit,x,fflag)
00246 char *buffer;
00247 INT32 ndigit;
00248
00249
00250
00251
00252
00253
00254 QUAD x;
00255 INT32 fflag;
00256 {
00257 _ldblval value;
00258 #define HI (value.fwords.hi)
00259 #define LO (value.fwords.lo)
00260
00261 INT32 signhi, signlo;
00262 INT32 exphi, explo;
00263 INT32 dexp;
00264 INT32 bexp;
00265 UINT32 lohi;
00266 UINT64 lolo;
00267 INT32 nd;
00268 INT32 guard;
00269
00270 #if QUAD_DEBUG
00271 char *buffer0=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;
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 ) {
00295 char *b;
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) {
00320 char *s;
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
00338
00339 if(exphi == 0) {
00340 exphi++;
00341 while( !(HI & (1ULL<<52))) {
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 {
00353 HI |= 1ULL<<52;
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;
00363
00364 #if QUAD_DEBUG
00365 printf("HI aligned: HI=0x%016llx\n",HI);
00366 #endif
00367
00368
00369
00370 signlo = SIGNBIT(LO) ^ signhi;
00371 SIGNBIT(LO) = 0;
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) {
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;
00389
00390 #if QUAD_DEBUG
00391 printf("left-shifted LO: LO=0x%016llx\n",LO);
00392 #endif
00393
00394 if(explo == 0) {
00395 INT32 shift_n;
00396
00397 LO <<= 1;
00398 #if QUAD_DEBUG
00399 printf("shifted up LO: LO=0x%016llx\n",LO);
00400 #endif
00401 shift_n = 53 - (exphi-explo);
00402
00403 if(shift_n > 0) {
00404 LO <<= shift_n;
00405 }
00406 else if(shift_n < 0) {
00407 LO >>= -shift_n;
00408 }
00409 }
00410 else {
00411 LO |= 1ULL<<53;
00412
00413 #if QUAD_DEBUG
00414 printf("expose hidden bit: LO=0x%016llx\n",LO);
00415 #endif
00416
00417 LO >>= (exphi-explo) - 53;
00418 }
00419
00420 #if QUAD_DEBUG
00421 printf("normalize LO to HI: LO=0x%016llx\n",LO);
00422 #endif
00423
00424 if( signlo ) {
00425 HI-= 1<<11;
00426 LO = (1ULL<<54) - 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;
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
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455 dexp = ( ((INT32) (exphi-1023)) * (0x4D104D42L >> 21) );
00456
00457 dexp >>= 11;
00458 dexp++;
00459
00460 #if QUAD_DEBUG
00461 printf("before scaling: dexp=%d\n",dexp);
00462 #endif
00463
00464
00465
00466 if(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
00484
00485 exphi -= 1022;
00486
00487
00488
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
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
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
00526
00527 if(fflag) {
00528 nd = min(34, ndigit + dexp + 1);
00529 }
00530 else {
00531 nd = ndigit;
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
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
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572 guard = HI>>60;
00573 if(guard >= 5) {
00574 if(guard > 5 ||
00575 (*buffer-1)&1 ||
00576 HI & ((1ULL<<60) - 1) ||
00577 lohi || lolo) {
00578 char *b=buffer;
00579
00580
00581
00582 #if QUAD_DEBUG
00583 printf("must round\n");
00584 #endif
00585 for(b=buffer-1; ; b--) {
00586 if(*b < '0' || '9' < *b) {
00587 *(b+1) = '1';
00588 dexp++;
00589 if(fflag && nd != min(34, ndigit + dexp + 1)) {
00590 *buffer++ = '0';
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') {
00613 *b = '0';
00614
00615 #if QUAD_DEBUG
00616 printf("carry: buffer=%s\n",buffer0);
00617 #endif
00618
00619 }
00620 else
00621 break;
00622 }
00623
00624 }
00625 }
00626
00627 #if REALLYNEEDED
00628 if(fflag && ndigit+dexp < 0) {
00629
00630 dexp--;
00631
00632
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