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 static char *source_file = __FILE__;
00050
00051
00052
00053
00054
00055
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
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
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
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
00118
00119
00120
00121
00122
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
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
00162 exp += (decimal_point ^ 1);
00163 }
00164 else {
00165 if (c == 0 && d == digits) {
00166
00167 ;
00168 }
00169 else {
00170 *d++ = c;
00171 }
00172 exp -= decimal_point;
00173 }
00174 }
00175 else if (c == dpchar && !decimal_point) {
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
00227
00228
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
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253 static
00254 QUAD
00255 c_atoq(buffer,ndigit,exp)
00256 char *buffer;
00257
00258
00259
00260
00261
00262 INT32 ndigit;
00263
00264
00265
00266
00267
00268 INT32 exp;
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280 {
00281 _ldblval value;
00282 #define HI (value.fwords.hi)
00283 #define LO (value.fwords.lo)
00284
00285
00286 QUAD result;
00287 UINT32 guard;
00288 UINT32 rest;
00289 UINT64 lolo;
00290 UINT32 lohi;
00291 double z;
00292
00293 INT32 exphi, explo;
00294 INT32 nzero;
00295 INT32 i;
00296 INT32 x;
00297 INT32 losign=0;
00298
00299 char *bufferend;
00300
00301 HI = 0;
00302
00303
00304
00305 if ((INT32) *buffer == 0){
00306 result.hi = result.lo = 0.0;
00307 return ( result );
00308 }
00309
00310
00311
00312 bufferend = buffer + ndigit;
00313 HI = 0;
00314 LO = *buffer++;
00315
00316
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
00330
00331 lolo = LO & (1Ull<<60)-1;
00332 lohi = LO >> 60;
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;
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;
00347 #if QUAD_DEBUG
00348 printf("After carry discard: lolo=0x%016llx\n",lolo);
00349 #endif
00350 lohi &= (1U << 4)-1;
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
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
00374
00375 exphi = 128;
00376 if (HI == 0){
00377 HI = LO;
00378 LO = 0;
00379 exphi -= 64;
00380 }
00381
00382
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
00393 HI = (HI << (64-nzero)) | (LO >> (nzero));
00394 LO <<= 64-nzero;
00395 exphi -= 64-nzero;
00396
00397
00398
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
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
00419
00420
00421
00422
00423
00424
00425
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
00453
00454
00455
00456
00457
00458
00459
00460 if(guard) {
00461 if(LO&1 || rest) {
00462 LO++;
00463 HI += LO>>54;
00464 LO &= (1ULL<<54)-1;
00465 if(HI>>53) {
00466 HI >>= 1;
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
00482
00483 if( LO & (1ULL<<53) ) {
00484 if(HI & 1 || LO & ((1ULL<<53)-1)) {
00485 HI++;
00486 if(HI & (1ULL<<53)) {
00487 HI >>= 1;
00488 exphi++;
00489 }
00490 LO = (1ULL<<54) - 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
00505 if(LO & (1ULL<<53)) {
00506 explo++;
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--;
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
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549 if (exphi > 1024) {
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) {
00562
00563 value.qparts.lo.d = 0;
00564 exphi += 1022;
00565 if( exphi < -52 ) {
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 {
00575 rest = HI & (1UL << exphi-1)-1;
00576 guard = (HI & (1UL << exphi)) >> exphi;
00577 HI >>= 1-exphi;
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
00587 if( guard ) {
00588 if( HI&1 || rest ) {
00589 HI++;
00590 if( HI == (1ULL << 52) ) {
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 {
00604 HI &= ~(1ULL << 52);
00605 EXPONENT(HI) = exphi + 1022;
00606
00607 #if QUAD_DEBUG
00608 printf("Normal HI: HI=0x%016llx\n",HI);
00609 #endif
00610
00611 }
00612
00613 if( explo <= -1022 ) {
00614 explo += 1022;
00615 if( explo < -52 ) {
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 {
00625 rest = LO & (1UL << explo-1)-1;
00626 guard = (LO & (1UL << explo)) >> explo;
00627 LO >>= 1-explo;
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
00637 if( guard ) {
00638 if( LO&1 || rest ) {
00639 LO++;
00640 if( LO == (1ULL << 52) ) {
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 {
00654 if(LO) {
00655 LO &= ~(1ULL << 52);
00656 EXPONENT(LO) = explo + 1022;
00657 }
00658 #if QUAD_DEBUG
00659 printf("Normal LO before making canonical: LO=0x%016llx\n",LO);
00660 #endif
00661
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