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
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 static char *source_file = __FILE__;
00062 static char *rcs_id = "$Source: /home/bos/bk/kpro64-pending/common/util/SCCS/s.c_a_to_q.c $ $Revision: 1.6 $";
00063
00064
00065
00066
00067
00068
00069
00070 typedef union {
00071 struct {
00072 #if defined(_LITTLE_ENDIAN)
00073 unsigned int lo :32;
00074 unsigned int hi :20;
00075 unsigned int exp :11;
00076 unsigned int sign :1;
00077 #else
00078 unsigned int sign :1;
00079 unsigned int exp :11;
00080 unsigned int hi :20;
00081 unsigned int lo :32;
00082 #endif
00083 } fparts;
00084 struct {
00085 #if defined(_LITTLE_ENDIAN)
00086 unsigned int lo :32;
00087 unsigned int hi :19;
00088 unsigned int qnan_bit :1;
00089 unsigned int exp :11;
00090 unsigned int sign :1;
00091 #else
00092 unsigned int sign :1;
00093 unsigned int exp :11;
00094 unsigned int qnan_bit :1;
00095 unsigned int hi :19;
00096 unsigned int lo :32;
00097 #endif
00098 } nparts;
00099 struct {
00100 #if defined(_LITTLE_ENDIAN)
00101 unsigned int lo;
00102 unsigned int hi;
00103 #else
00104 unsigned int hi;
00105 unsigned int lo;
00106 #endif
00107 } fwords;
00108 double d;
00109 } _dval;
00110
00111
00112
00113 typedef union {
00114 struct {
00115 _dval hi;
00116 _dval lo;
00117 } qparts;
00118 struct {
00119 unsigned long long hi;
00120 unsigned long long lo;
00121 } fwords;
00122 } _ldblval;
00123
00124
00125
00126 #define SIGNBIT(X) (((_dval *)&(X))->fparts.sign)
00127 #define EXPONENT(X) (((_dval *)&(X))->fparts.exp)
00128 #define MAXCOUNT 34
00129
00130
00131 #include <math.h>
00132 #include "defs.h"
00133 #include "quad.h"
00134
00135
00136 extern void c_qtenscale( _ldblval *, INT32, INT32 *);
00137 extern QUAD c_a_to_q(char *str, INT *p_err );
00138 static QUAD c_atoq(char *buffer, INT32 ndigit, INT32 exp);
00139
00140
00141
00142 #if defined(BUILD_OS_DARWIN)
00143
00144 QUAD c_a_to_q(char *s, INT *p_err );
00145 QUAD __c_a_to_q(char *s, INT *p_err) { return c_a_to_q(s, p_err); }
00146 #else
00147 #pragma weak c_a_to_q = __c_a_to_q
00148 #define c_a_to_q __c_a_to_q
00149 #endif
00150
00151 #define MAXDIGITS 34
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167 QUAD
00168 c_a_to_q(char *s, INT *p_err )
00169 {
00170 register UINT32 c;
00171 register UINT32 negate, decimal_point;
00172 register char *d;
00173 register INT32 exp;
00174 QUAD x;
00175 register INT32 dpchar;
00176 char digits[MAXDIGITS];
00177
00178 *p_err = 0;
00179
00180 while ( (c = *s++) == ' ' )
00181 ;
00182
00183
00184 negate = 0;
00185 if (c == '+') {
00186 c = *s++;
00187 }
00188 else if (c == '-') {
00189 negate = 1;
00190 c = *s++;
00191 }
00192 d = digits;
00193 dpchar = '.' - '0';
00194 decimal_point = 0;
00195 exp = 0;
00196 while (1) {
00197 c -= '0';
00198 if (c < 10) {
00199 if (d == digits+MAXDIGITS) {
00200
00201 exp += (decimal_point ^ 1);
00202 }
00203 else {
00204 if (c == 0 && d == digits) {
00205
00206 ;
00207 }
00208 else {
00209 *d++ = c;
00210 }
00211 exp -= decimal_point;
00212 }
00213 }
00214 else if (c == dpchar && !decimal_point) {
00215 decimal_point = 1;
00216 }
00217 else {
00218 break;
00219 }
00220 c = *s++;
00221 }
00222 if (d == digits) {
00223 x.hi = 0.0;
00224 x.lo = 0.0;
00225 return x;
00226 }
00227 if (c == 'e'-'0' || c == 'E'-'0') {
00228 register UINT32 negate_exp = 0;
00229 register INT32 e = 0;
00230 c = *s++;
00231 if (c == '+' || c == ' ') {
00232 c = *s++;
00233 }
00234 else if (c == '-') {
00235 negate_exp = 1;
00236 c = *s++;
00237 }
00238 if (c -= '0', c < 10) {
00239 do {
00240 if (e <= 340)
00241 e = e * 10 + c;
00242 else break;
00243 c = *s++;
00244 }
00245 while (c -= '0', c < 10);
00246 if (negate_exp) {
00247 e = -e;
00248 }
00249 if (e < -(323+MAXDIGITS) || e > 308)
00250 exp = e;
00251 else
00252 exp += e;
00253 }
00254 }
00255
00256 if (exp < -(324+MAXDIGITS)) {
00257 x.hi = 0.0;
00258 x.lo = 0.0;
00259 }
00260 else if (exp > 308) {
00261 x.hi = HUGE_VAL;
00262 x.lo = 0.0;
00263 }
00264 else {
00265
00266
00267
00268
00269
00270 x = c_atoq (digits, d - digits, exp);
00271 }
00272 if (negate) {
00273 x.hi = -x.hi;
00274 x.lo = -x.lo;
00275 }
00276 return x;
00277 }
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 static
00293 QUAD
00294 c_atoq(buffer,ndigit,exp)
00295 char *buffer;
00296
00297
00298
00299
00300
00301 INT32 ndigit;
00302
00303
00304
00305
00306
00307 INT32 exp;
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319 {
00320 _ldblval value;
00321 #define HI (value.fwords.hi)
00322 #define LO (value.fwords.lo)
00323
00324
00325 QUAD result;
00326 UINT32 guard;
00327 UINT32 rest;
00328 UINT64 lolo;
00329 UINT32 lohi;
00330 double z;
00331
00332 INT32 exphi, explo;
00333 INT32 nzero;
00334 INT32 i;
00335 INT32 x;
00336 INT32 losign=0;
00337
00338 char *bufferend;
00339
00340 HI = 0;
00341
00342
00343
00344 if ((INT32) *buffer == 0){
00345 result.hi = result.lo = 0.0;
00346 return ( result );
00347 }
00348
00349
00350
00351 bufferend = buffer + ndigit;
00352 HI = 0;
00353 LO = *buffer++;
00354
00355
00356 for( i=1 ; buffer < bufferend && i<19; buffer++, i++ ){
00357 LO *= 10;
00358 LO += *buffer;
00359 }
00360
00361 #if QUAD_DEBUG
00362 printf("halfway thru conversion: HI=0x%016llx\n",HI);
00363 printf(" LO=0x%016llx\n",LO);
00364 printf(" i=%d\n",i);
00365 #endif
00366
00367 if( buffer < bufferend ) {
00368
00369
00370 lolo = LO & (1Ull<<60)-1;
00371 lohi = LO >> 60;
00372
00373 #if QUAD_DEBUG
00374 printf("After LO split: lohi=0x%x\n",lohi);
00375 printf(" lolo=0x%016llx\n",lolo);
00376 #endif
00377
00378 for( ; buffer < bufferend; buffer++ ){
00379 lolo = 10*lolo + *buffer;
00380 #if QUAD_DEBUG
00381 printf("After 10*: lolo=0x%016llx\n",lolo);
00382 #endif
00383 lohi = 10*lohi + (lolo>>60);
00384 HI = 10*HI + (lohi>>4);
00385 lolo &= (1Ull<<60)-1;
00386 #if QUAD_DEBUG
00387 printf("After carry discard: lolo=0x%016llx\n",lolo);
00388 #endif
00389 lohi &= (1U << 4)-1;
00390
00391 #if QUAD_DEBUG
00392 printf("After iteration: lohi=0x%x\n",lohi);
00393 printf(" lolo=0x%016llx\n",lolo);
00394 #endif
00395
00396 }
00397
00398 LO = lolo | ((UINT64) lohi)<<60;
00399
00400 #if QUAD_DEBUG
00401 printf("After reconstitution: HI=0x%016llx\n",HI);
00402 printf(" LO=0x%016llx\n",LO);
00403 #endif
00404
00405 }
00406
00407 #if QUAD_DEBUG
00408 printf("after conversion: HI=0x%016llx\n",HI);
00409 printf(" LO=0x%016llx\n",LO);
00410 #endif
00411
00412
00413
00414 exphi = 128;
00415 if (HI == 0){
00416 HI = LO;
00417 LO = 0;
00418 exphi -= 64;
00419 }
00420
00421
00422 nzero = 0;
00423 if ( HI >> (32 ) ){ nzero = 32; }
00424 if ( HI >> (16 + nzero) ){ nzero += 16; }
00425 if ( HI >> ( 8 + nzero) ){ nzero += 8; }
00426 if ( HI >> ( 4 + nzero) ){ nzero += 4; }
00427 if ( HI >> ( 2 + nzero) ){ nzero += 2; }
00428 if ( HI >> ( 1 + nzero) ){ nzero += 1; }
00429 if ( HI >> ( nzero) ){ nzero += 1; }
00430
00431
00432 HI = (HI << (64-nzero)) | (LO >> (nzero));
00433 LO <<= 64-nzero;
00434 exphi -= 64-nzero;
00435
00436
00437
00438
00439
00440 #if QUAD_DEBUG
00441 printf("after normalization: HI=0x%016llx\n",HI);
00442 printf(" LO=0x%016llx\n",LO);
00443 printf(" nzero=%d\n",nzero);
00444 printf(" exphi=%d\n",exphi);
00445 #endif
00446
00447
00448
00449 c_qtenscale(&value,exp,&x);
00450 exphi += x;
00451
00452 #if QUAD_DEBUG
00453 printf("after multiplication: HI=0x%016llx\n",HI);
00454 printf(" LO=0x%016llx\n",LO);
00455 printf(" exphi=%d\n",exphi);
00456 #endif
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467 rest = LO & (1ULL<<20)-1;
00468 LO >>= 20;
00469
00470 #if QUAD_DEBUG
00471 printf("during split: LO=0x%016llx\n",LO);
00472 #endif
00473
00474 guard = LO & 1;
00475 LO >>= 1;
00476
00477 #if QUAD_DEBUG
00478 printf("during split: LO=0x%016llx\n",LO);
00479 #endif
00480
00481 LO |= (HI & (1ULL<<11)-1) << 43;
00482 HI >>= 11;
00483
00484 #if QUAD_DEBUG
00485 printf("after split: HI=0x%016llx\n",HI);
00486 printf(" LO=0x%016llx\n",LO);
00487 printf(" guard=%d\n",guard);
00488 printf(" rest=%lx\n",rest);
00489 #endif
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499 if(guard) {
00500 if(LO&1 || rest) {
00501 LO++;
00502 HI += LO>>54;
00503 LO &= (1ULL<<54)-1;
00504 if(HI>>53) {
00505 HI >>= 1;
00506 exphi ++;
00507 }
00508 }
00509 }
00510
00511 explo = exphi-53;
00512
00513 #if QUAD_DEBUG
00514 printf("after rounding: HI=0x%016llx\n",HI);
00515 printf(" LO=0x%016llx\n",LO);
00516 printf(" exphi=%d\n",exphi);
00517 printf(" explo=%d\n",explo);
00518 #endif
00519
00520
00521
00522 if( LO & (1ULL<<53) ) {
00523 if(HI & 1 || LO & ((1ULL<<53)-1)) {
00524 HI++;
00525 if(HI & (1ULL<<53)) {
00526 HI >>= 1;
00527 exphi++;
00528 }
00529 LO = (1ULL<<54) - LO;
00530 losign = 1;
00531
00532 #if QUAD_DEBUG
00533 printf("after dekker: HI=0x%016llx\n",HI);
00534 printf(" LO=0x%016llx\n",LO);
00535 printf(" exphi=%d\n",exphi);
00536 printf(" explo=%d\n",explo);
00537 printf(" losign=%d\n",losign);
00538 #endif
00539
00540 }
00541 }
00542 if( LO ) {
00543
00544 if(LO & (1ULL<<53)) {
00545 explo++;
00546 LO >>=1;
00547
00548 #if QUAD_DEBUG
00549 printf("after right shift: LO=0x%016llx\n",LO);
00550 printf(" explo=%d\n",explo);
00551 #endif
00552
00553 }
00554 else {
00555 while( ! (LO & 0x0010000000000000ULL) ){
00556
00557 #if QUAD_DEBUG
00558 printf("before left shift: LO=0x%016llx\n",LO);
00559 printf(" explo=%d\n",explo);
00560 #endif
00561
00562 explo--;
00563 LO <<= 1;
00564 }
00565 }
00566 explo--;
00567 }
00568
00569 #if QUAD_DEBUG
00570 printf("after LO normalize: LO=0x%016llx\n",LO);
00571 printf(" explo=%d\n",explo);
00572 #endif
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588 if (exphi > 1024) {
00589 value.qparts.hi.d = value.qparts.lo.d = HUGE_VAL;
00590
00591 #if QUAD_DEBUG
00592 printf("Overflow: value.qparts.hi.d=0x%016llx\n",value.qparts.hi.d);
00593 printf(" value.qparts.lo.d=0x%016llx\n",value.qparts.lo.d);
00594 #endif
00595
00596 result.hi = value.qparts.hi.d;
00597 result.lo = value.qparts.lo.d;
00598 return ( result );
00599 }
00600 if (exphi <= -1022) {
00601
00602 value.qparts.lo.d = 0;
00603 exphi += 1022;
00604 if( exphi < -52 ) {
00605 value.qparts.hi.d = 0;
00606
00607 #if QUAD_DEBUG
00608 printf("HI underflow: HI=0x%016llx\n",HI);
00609 printf(" exphi=%d\n",exphi);
00610 #endif
00611
00612 }
00613 else {
00614 rest = HI & (1UL << exphi-1)-1;
00615 guard = (HI & (1UL << exphi)) >> exphi;
00616 HI >>= 1-exphi;
00617
00618 #if QUAD_DEBUG
00619 printf("HI denorm: HI=0x%016llx\n",HI);
00620 printf(" rest=0x%016llx\n",rest);
00621 printf(" guard=%d\n",guard);
00622 printf(" exphi=%d\n",exphi);
00623 #endif
00624
00625
00626 if( guard ) {
00627 if( HI&1 || rest ) {
00628 HI++;
00629 if( HI == (1ULL << 52) ) {
00630 HI = 0;
00631 EXPONENT(HI) = 1;
00632 }
00633
00634 #if QUAD_DEBUG
00635 printf("Round denorm: HI=0x%016llx\n",HI);
00636 #endif
00637
00638 }
00639 }
00640 }
00641 }
00642 else {
00643 HI &= ~(1ULL << 52);
00644 EXPONENT(HI) = exphi + 1022;
00645
00646 #if QUAD_DEBUG
00647 printf("Normal HI: HI=0x%016llx\n",HI);
00648 #endif
00649
00650 }
00651
00652 if( explo <= -1022 ) {
00653 explo += 1022;
00654 if( explo < -52 ) {
00655 value.qparts.lo.d = 0;
00656
00657 #if QUAD_DEBUG
00658 printf("LO underflow: LO=0x%016llx\n",LO);
00659 printf(" explo=%d\n",explo);
00660 #endif
00661
00662 }
00663 else {
00664 rest = LO & (1UL << explo-1)-1;
00665 guard = (LO & (1UL << explo)) >> explo;
00666 LO >>= 1-explo;
00667
00668 #if QUAD_DEBUG
00669 printf("LO denorm: LO=0x%016llx\n",LO);
00670 printf(" explo=%d\n",explo);
00671 printf(" guard=%d\n",guard);
00672 printf(" rest=0x%016llx\n",rest);
00673 #endif
00674
00675
00676 if( guard ) {
00677 if( LO&1 || rest ) {
00678 LO++;
00679 if( LO == (1ULL << 52) ) {
00680 LO = 0;
00681 EXPONENT(LO) = 1;
00682 }
00683
00684 #if QUAD_DEBUG
00685 printf("After LO round: LO=0x%016llx\n",LO);
00686 #endif
00687
00688 }
00689 }
00690 }
00691 }
00692 else {
00693 if(LO) {
00694 LO &= ~(1ULL << 52);
00695 EXPONENT(LO) = explo + 1022;
00696 }
00697 #if QUAD_DEBUG
00698 printf("Normal LO before making canonical: LO=0x%016llx\n",LO);
00699 #endif
00700
00701 z = value.qparts.lo.d + value.qparts.hi.d;
00702 value.qparts.lo.d -= (z - value.qparts.hi.d);
00703 value.qparts.hi.d = z;
00704 #if QUAD_DEBUG
00705 printf("After making canonical: HI=0x%016llx\n",HI);
00706 printf(" : LO=0x%016llx\n",LO);
00707 #endif
00708
00709 }
00710
00711 SIGNBIT(LO) = losign;
00712 result.hi = value.qparts.hi.d;
00713 result.lo = value.qparts.lo.d;
00714 return ( result );
00715 }
00716