ext_comp.c

Go to the documentation of this file.
00001 /*
00002   (c) copyright 1989 by the Vrije Universiteit, Amsterdam, The Netherlands.
00003   See the copyright notice in the ACK home directory, in the file "Copyright".
00004 */
00005 
00006 /* $Id: ext_comp.c,v 1.1.1.1 2005/04/21 14:56:05 beng Exp $ */
00007 
00008 /* extended precision arithmetic for the strtod() and cvt() routines */
00009 
00010 /* This may require some more work when long doubles get bigger than 8
00011    bytes. In this case, these routines may become obsolete. ???
00012 */
00013 
00014 #include        "ext_fmt.h"
00015 #include        <float.h>
00016 #include        <errno.h>
00017 #include        <ctype.h>
00018 
00019 static int b64_add(struct mantissa *e1, struct mantissa *e2);
00020 static b64_sft(struct mantissa *e1, int n);
00021 
00022 static
00023 mul_ext(struct EXTEND *e1, struct EXTEND *e2, struct EXTEND *e3)
00024 {
00025         /*      Multiply the extended numbers e1 and e2, and put the
00026                 result in e3.
00027         */
00028         register int    i,j;            /* loop control */
00029         unsigned short  mp[4];
00030         unsigned short  mc[4];
00031         unsigned short  result[8];      /* result */
00032 
00033         register unsigned short *pres;
00034 
00035         /* first save the sign (XOR)                    */
00036         e3->sign = e1->sign ^ e2->sign;
00037 
00038         /* compute new exponent */
00039         e3->exp = e1->exp + e2->exp + 1;
00040 
00041         /* check for overflow/underflow ??? */
00042 
00043         /* 128 bit multiply of mantissas        */
00044 
00045         /* assign unknown long formats          */
00046         /* to known unsigned word formats       */
00047         mp[0] = e1->m1 >> 16;
00048         mp[1] = (unsigned short) e1->m1;
00049         mp[2] = e1->m2 >> 16;
00050         mp[3] = (unsigned short) e1->m2;
00051         mc[0] = e2->m1 >> 16;
00052         mc[1] = (unsigned short) e2->m1;
00053         mc[2] = e2->m2 >> 16;
00054         mc[3] = (unsigned short) e2->m2;
00055         for (i = 8; i--;) {
00056                 result[i] = 0;
00057         }
00058         /*
00059          *      fill registers with their components
00060          */
00061         for(i=4, pres = &result[4];i--;pres--) if (mp[i]) {
00062                 unsigned short k = 0;
00063                 unsigned long mpi = mp[i];
00064                 for(j=4;j--;) {
00065                         unsigned long tmp = (unsigned long)pres[j] + k;
00066                         if (mc[j]) tmp += mpi * mc[j];
00067                         pres[j] = tmp;
00068                         k = tmp >> 16;
00069                 }
00070                 pres[-1] = k;
00071         }
00072 
00073         if (! (result[0] & 0x8000)) {
00074                 e3->exp--;
00075                 for (i = 0; i <= 3; i++) {
00076                         result[i] <<= 1;
00077                         if (result[i+1]&0x8000) result[i] |= 1;
00078                 }
00079                 result[4] <<= 1;
00080         }       
00081         /*
00082          *      combine the registers to a total
00083          */
00084         e3->m1 = ((unsigned long)(result[0]) << 16) + result[1];
00085         e3->m2 = ((unsigned long)(result[2]) << 16) + result[3];
00086         if (result[4] & 0x8000) {
00087                 if (++e3->m2 == 0) {
00088                         if (++e3->m1 == 0) {
00089                                 e3->m1 = 0x80000000;
00090                                 e3->exp++;
00091                         }
00092                 }
00093         }
00094 }
00095 
00096 static
00097 add_ext(struct EXTEND *e1, struct EXTEND *e2, struct EXTEND *e3)
00098 {
00099         /*      Add two extended numbers e1 and e2, and put the result
00100                 in e3
00101         */
00102         struct EXTEND ce2;
00103         int diff;
00104 
00105         if ((e2->m1 | e2->m2) == 0L) {
00106                 *e3 = *e1;
00107                 return;
00108         }
00109         if ((e1->m1 | e1->m2) == 0L) {
00110                 *e3 = *e2;
00111                 return;
00112         }
00113         ce2 = *e2;
00114         *e3 = *e1;
00115         e1 = &ce2;
00116 
00117         /* adjust mantissas to equal power */
00118         diff = e3->exp - e1->exp;
00119         if (diff < 0) {
00120                 diff = -diff;
00121                 e3->exp += diff;
00122                 b64_sft(&(e3->mantissa), diff);
00123         }
00124         else if (diff > 0) {
00125                 e1->exp += diff;
00126                 b64_sft(&(e1->mantissa), diff);
00127         }
00128         if (e1->sign != e3->sign) {
00129                 /* e3 + e1 = e3 - (-e1) */
00130                 if (e1->m1 > e3->m1 ||
00131                     (e1->m1 == e3->m1 && e1->m2 > e3->m2)) {
00132                         /*      abs(e1) > abs(e3) */
00133                         if (e3->m2 > e1->m2) {
00134                                 e1->m1 -= 1;    /* carry in */
00135                         }
00136                         e1->m1 -= e3->m1;
00137                         e1->m2 -= e3->m2;
00138                         *e3 = *e1;
00139                 }
00140                 else {
00141                         if (e1->m2 > e3->m2)
00142                                 e3->m1 -= 1;    /* carry in */
00143                         e3->m1 -= e1->m1;
00144                         e3->m2 -= e1->m2;
00145                 }
00146         }
00147         else {
00148                 if (b64_add(&e3->mantissa,&e1->mantissa)) {/* addition carry */
00149                         b64_sft(&e3->mantissa,1);/* shift mantissa one bit RIGHT */
00150                         e3->m1 |= 0x80000000L;  /* set max bit  */
00151                         e3->exp++;              /* increase the exponent */
00152                 }
00153         }
00154         if ((e3->m2 | e3->m1) != 0L) {
00155                 /* normalize */
00156                 if (e3->m1 == 0L) {
00157                         e3->m1 = e3->m2; e3->m2 = 0L; e3->exp -= 32;
00158                 }
00159                 if (!(e3->m1 & 0x80000000)) {
00160                         unsigned long l = 0x40000000;
00161                         int cnt = -1;
00162 
00163                         while (! (l & e3->m1)) {
00164                                 l >>= 1; cnt--;
00165                         }
00166                         e3->exp += cnt;
00167                         b64_sft(&(e3->mantissa), cnt);
00168                 }
00169         }
00170 }
00171 
00172 static int
00173 cmp_ext(struct EXTEND *e1, struct EXTEND *e2)
00174 {
00175         struct EXTEND tmp; 
00176          
00177         e2->sign = ! e2->sign; 
00178         add_ext(e1, e2, &tmp);  
00179         e2->sign = ! e2->sign;
00180         if (tmp.m1 == 0 && tmp.m2 == 0) return 0; 
00181         if (tmp.sign) return -1;
00182         return 1;
00183 }
00184 
00185 static
00186 b64_sft(struct mantissa *e1, int n)
00187 {
00188         if (n > 0) {
00189                 if (n > 63) {
00190                         e1->l_32 = 0;
00191                         e1->h_32 = 0;
00192                         return;
00193                 }
00194                 if (n >= 32) {
00195                         e1->l_32 = e1->h_32;
00196                         e1->h_32 = 0;
00197                         n -= 32;
00198                 }
00199                 if (n > 0) {
00200                         e1->l_32 >>= n;
00201                         if (e1->h_32 != 0) {
00202                                 e1->l_32 |= (e1->h_32 << (32 - n));
00203                                 e1->h_32 >>= n;
00204                         }
00205                 }
00206                 return;
00207         }
00208         n = -n;
00209         if (n > 0) {
00210                 if (n > 63) {
00211                         e1->l_32 = 0;
00212                         e1->h_32 = 0;
00213                         return;
00214                 }
00215                 if (n >= 32) {
00216                         e1->h_32 = e1->l_32;
00217                         e1->l_32 = 0;
00218                         n -= 32;
00219                 }
00220                 if (n > 0) {
00221                         e1->h_32 <<= n;
00222                         if (e1->l_32 != 0) {
00223                                 e1->h_32 |= (e1->l_32 >> (32 - n));
00224                                 e1->l_32 <<= n;
00225                         }
00226                 }
00227         }
00228 }
00229 
00230 static int
00231 b64_add(struct mantissa *e1, struct mantissa *e2)
00232                 /*
00233                  * pointers to 64 bit 'registers'
00234                  */
00235 {
00236         register int    overflow;
00237         int             carry;
00238 
00239                         /* add higher pair of 32 bits */
00240         overflow = ((unsigned long) 0xFFFFFFFF - e1->h_32 < e2->h_32);
00241         e1->h_32 += e2->h_32;
00242 
00243                         /* add lower pair of 32 bits */
00244         carry = ((unsigned long) 0xFFFFFFFF - e1->l_32 < e2->l_32);
00245         e1->l_32 += e2->l_32;
00246         if ((carry) && (++e1->h_32 == 0))
00247                 return(1);              /* had a 64 bit overflow */
00248         else
00249                 return(overflow);       /* return status from higher add */
00250 }
00251 
00252 /* The following tables can be computed with the following bc(1)
00253    program:
00254 
00255 obase=16
00256 scale=0
00257 define t(x){
00258         auto a, b, c
00259         a=2;b=1;c=2^32;n=1
00260         while(a<x) {
00261                 b=a;n+=n;a*=a
00262         }
00263         n/=2
00264         a=b
00265         while(b<x) {
00266                 a=b;b*=c;n+=32
00267         }
00268         n-=32
00269         b=a
00270         while(a<x) {
00271                 b=a;a+=a;n+=1
00272         }
00273         n-=1
00274         x*=16^16
00275         b=x%a
00276         x/=a
00277         if(a<=(2*b)) x+=1
00278         obase=10
00279         n
00280         obase=16
00281         return(x)
00282 }
00283 for (i=1;i<28;i++) {
00284         t(10^i)
00285 }
00286 0
00287 for (i=1;i<20;i++) {
00288         t(10^(28*i))
00289 }
00290 0
00291 define r(x){
00292         auto a, b, c
00293         a=2;b=1;c=2^32;n=1
00294         while(a<x) {
00295                 b=a;n+=n;a*=a
00296         }
00297         n/=2
00298         a=b
00299         while(b<x) {
00300                 a=b;b*=c;n+=32
00301         }
00302         n-=32
00303         b=a
00304         while(a<x) {
00305                 b=a;a+=a;n+=1
00306         }
00307         a=b
00308         a*=16^16
00309         b=a%x
00310         a/=x
00311         if(x<=(2*b)) a+=1
00312         obase=10
00313         -n
00314         obase=16
00315         return(a)
00316 }
00317 for (i=1;i<28;i++) {
00318         r(10^i)
00319 }
00320 0
00321 for (i=1;i<20;i++) {
00322         r(10^(28*i))
00323 }
00324 0
00325 
00326 */
00327 static struct EXTEND ten_powers[] = {   /* representation of 10 ** i */
00328         { 0,    0,      0x80000000,     0 },
00329         { 0,    3,      0xA0000000,     0 },
00330         { 0,    6,      0xC8000000,     0 },
00331         { 0,    9,      0xFA000000,     0 },
00332         { 0,    13,     0x9C400000,     0 },
00333         { 0,    16,     0xC3500000,     0 },
00334         { 0,    19,     0xF4240000,     0 },
00335         { 0,    23,     0x98968000,     0 },
00336         { 0,    26,     0xBEBC2000,     0 },
00337         { 0,    29,     0xEE6B2800,     0 },
00338         { 0,    33,     0x9502F900,     0 },
00339         { 0,    36,     0xBA43B740,     0 },
00340         { 0,    39,     0xE8D4A510,     0 },
00341         { 0,    43,     0x9184E72A,     0 },
00342         { 0,    46,     0xB5E620F4,     0x80000000 },
00343         { 0,    49,     0xE35FA931,     0xA0000000 },
00344         { 0,    53,     0x8E1BC9BF,     0x04000000 },
00345         { 0,    56,     0xB1A2BC2E,     0xC5000000 },
00346         { 0,    59,     0xDE0B6B3A,     0x76400000 },
00347         { 0,    63,     0x8AC72304,     0x89E80000 },
00348         { 0,    66,     0xAD78EBC5,     0xAC620000 },
00349         { 0,    69,     0xD8D726B7,     0x177A8000 },
00350         { 0,    73,     0x87867832,     0x6EAC9000 },
00351         { 0,    76,     0xA968163F,     0x0A57B400 },
00352         { 0,    79,     0xD3C21BCE,     0xCCEDA100 },
00353         { 0,    83,     0x84595161,     0x401484A0 },
00354         { 0,    86,     0xA56FA5B9,     0x9019A5C8 },
00355         { 0,    89,     0xCECB8F27,     0xF4200F3A }
00356 };
00357 static struct EXTEND big_ten_powers[] = {  /* representation of 10 ** (28*i) */
00358         { 0,    0,      0x80000000,     0 },
00359         { 0,    93,     0x813F3978,     0xF8940984 },
00360         { 0,    186,    0x82818F12,     0x81ED44A0 },
00361         { 0,    279,    0x83C7088E,     0x1AAB65DB },
00362         { 0,    372,    0x850FADC0,     0x9923329E },
00363         { 0,    465,    0x865B8692,     0x5B9BC5C2 },
00364         { 0,    558,    0x87AA9AFF,     0x79042287 },
00365         { 0,    651,    0x88FCF317,     0xF22241E2 },
00366         { 0,    744,    0x8A5296FF,     0xE33CC930 },
00367         { 0,    837,    0x8BAB8EEF,     0xB6409C1A },
00368         { 0,    930,    0x8D07E334,     0x55637EB3 },
00369         { 0,    1023,   0x8E679C2F,     0x5E44FF8F },
00370         { 0,    1116,   0x8FCAC257,     0x558EE4E6 },
00371         { 0,    1209,   0x91315E37,     0xDB165AA9 },
00372         { 0,    1302,   0x929B7871,     0xDE7F22B9 },
00373         { 0,    1395,   0x940919BB,     0xD4620B6D },
00374         { 0,    1488,   0x957A4AE1,     0xEBF7F3D4 },
00375         { 0,    1581,   0x96EF14C6,     0x454AA840 },
00376         { 0,    1674,   0x98678061,     0x27ECE4F5 },
00377         { 0,    1767,   0x99E396C1,     0x3A3ACFF2 }
00378 };
00379 
00380 static struct EXTEND r_ten_powers[] = { /* representation of 10 ** -i */
00381         { 0,    0,      0x80000000,     0 },
00382         { 0,    -4,     0xCCCCCCCC,     0xCCCCCCCD },
00383         { 0,    -7,     0xA3D70A3D,     0x70A3D70A },
00384         { 0,    -10,    0x83126E97,     0x8D4FDF3B },
00385         { 0,    -14,    0xD1B71758,     0xE219652C },
00386         { 0,    -17,    0xA7C5AC47,     0x1B478423 },
00387         { 0,    -20,    0x8637BD05,     0xAF6C69B6 },
00388         { 0,    -24,    0xD6BF94D5,     0xE57A42BC },
00389         { 0,    -27,    0xABCC7711,     0x8461CEFD },
00390         { 0,    -30,    0x89705F41,     0x36B4A597 },
00391         { 0,    -34,    0xDBE6FECE,     0xBDEDD5BF },
00392         { 0,    -37,    0xAFEBFF0B,     0xCB24AAFF },
00393         { 0,    -40,    0x8CBCCC09,     0x6F5088CC },
00394         { 0,    -44,    0xE12E1342,     0x4BB40E13 },
00395         { 0,    -47,    0xB424DC35,     0x095CD80F },
00396         { 0,    -50,    0x901D7CF7,     0x3AB0ACD9 },
00397         { 0,    -54,    0xE69594BE,     0xC44DE15B },
00398         { 0,    -57,    0xB877AA32,     0x36A4B449 },
00399         { 0,    -60,    0x9392EE8E,     0x921D5D07 },
00400         { 0,    -64,    0xEC1E4A7D,     0xB69561A5 },
00401         { 0,    -67,    0xBCE50864,     0x92111AEB },
00402         { 0,    -70,    0x971DA050,     0x74DA7BEF },
00403         { 0,    -74,    0xF1C90080,     0xBAF72CB1 },
00404         { 0,    -77,    0xC16D9A00,     0x95928A27 },
00405         { 0,    -80,    0x9ABE14CD,     0x44753B53 },
00406         { 0,    -84,    0xF79687AE,     0xD3EEC551 },
00407         { 0,    -87,    0xC6120625,     0x76589DDB },
00408         { 0,    -90,    0x9E74D1B7,     0x91E07E48 }
00409 };
00410 
00411 static struct EXTEND r_big_ten_powers[] = { /* representation of 10 ** -(28*i) */
00412         { 0,    0,      0x80000000,     0 },
00413         { 0,    -94,    0xFD87B5F2,     0x8300CA0E },
00414         { 0,    -187,   0xFB158592,     0xBE068D2F },
00415         { 0,    -280,   0xF8A95FCF,     0x88747D94 },
00416         { 0,    -373,   0xF64335BC,     0xF065D37D },
00417         { 0,    -466,   0xF3E2F893,     0xDEC3F126 },
00418         { 0,    -559,   0xF18899B1,     0xBC3F8CA2 },
00419         { 0,    -652,   0xEF340A98,     0x172AACE5 },
00420         { 0,    -745,   0xECE53CEC,     0x4A314EBE },
00421         { 0,    -838,   0xEA9C2277,     0x23EE8BCB },
00422         { 0,    -931,   0xE858AD24,     0x8F5C22CA },
00423         { 0,    -1024,  0xE61ACF03,     0x3D1A45DF },
00424         { 0,    -1117,  0xE3E27A44,     0x4D8D98B8 },
00425         { 0,    -1210,  0xE1AFA13A,     0xFBD14D6E },
00426         { 0,    -1303,  0xDF82365C,     0x497B5454 },
00427         { 0,    -1396,  0xDD5A2C3E,     0xAB3097CC },
00428         { 0,    -1489,  0xDB377599,     0xB6074245 },
00429         { 0,    -1582,  0xD91A0545,     0xCDB51186 },
00430         { 0,    -1675,  0xD701CE3B,     0xD387BF48 },
00431         { 0,    -1768,  0xD4EEC394,     0xD6258BF8 }
00432 };
00433 
00434 #define TP      (int)(sizeof(ten_powers)/sizeof(ten_powers[0]))
00435 #define BTP     (int)(sizeof(big_ten_powers)/sizeof(big_ten_powers[0]))
00436 #define MAX_EXP (TP * BTP - 1)
00437 
00438 static
00439 add_exponent(struct EXTEND *e, int exp)
00440 {
00441         int neg = exp < 0;
00442         int divsz, modsz;
00443         struct EXTEND x;
00444 
00445         if (neg) exp = -exp;
00446         divsz = exp / TP;
00447         modsz = exp % TP;
00448         if (neg) {
00449                 mul_ext(e, &r_ten_powers[modsz], &x);
00450                 mul_ext(&x, &r_big_ten_powers[divsz], e);
00451         }
00452         else {
00453                 mul_ext(e, &ten_powers[modsz], &x);
00454                 mul_ext(&x, &big_ten_powers[divsz], e);
00455         }
00456 }
00457 
00458 _str_ext_cvt(const char *s, char **ss, struct EXTEND *e)
00459 {
00460         /*      Like strtod, but for extended precision */
00461         register int    c;
00462         int             dotseen = 0;
00463         int             digitseen = 0;
00464         int             exp = 0;
00465 
00466         if (ss) *ss = (char *)s;
00467         while (isspace(*s)) s++;
00468 
00469         e->sign = 0;
00470         e->exp = 0;
00471         e->m1 = e->m2 = 0;
00472 
00473         c = *s;
00474         switch(c) {
00475         case '-':
00476                 e->sign = 1;
00477         case '+':
00478                 s++;
00479         }
00480         while (c = *s++, isdigit(c) || (c == '.' && ! dotseen++)) {
00481                 if (c == '.') continue;
00482                 digitseen = 1;
00483                 if (e->m1 <= (unsigned long)(0xFFFFFFFF)/10) {
00484                         struct mantissa a1;
00485 
00486                         a1 = e->mantissa;
00487                         b64_sft(&(e->mantissa), -3);
00488                         b64_sft(&a1, -1);
00489                         b64_add(&(e->mantissa), &a1);
00490                         a1.h_32 = 0;
00491                         a1.l_32 = c - '0';
00492                         b64_add(&(e->mantissa), &a1);
00493                 }
00494                 else exp++;
00495                 if (dotseen) exp--;
00496         }
00497         if (! digitseen) return;
00498 
00499         if (ss) *ss = (char *)s - 1;
00500 
00501         if (c == 'E' || c == 'e') {
00502                 int     exp1 = 0;
00503                 int     sign = 1;
00504                 int     exp_overflow = 0;
00505 
00506                 switch(*s) {
00507                 case '-':
00508                         sign = -1;
00509                 case '+':
00510                         s++;
00511                 }
00512                 if (c = *s, isdigit(c)) {
00513                         do {
00514                                 int tmp;
00515 
00516                                 exp1 = 10 * exp1 + (c - '0');
00517                                 if ((tmp = sign * exp1 + exp) > MAX_EXP ||
00518                                      tmp < -MAX_EXP) {
00519                                         exp_overflow = 1;
00520                                 }
00521                         } while (c = *++s, isdigit(c));
00522                         if (ss) *ss = (char *)s;
00523                 }
00524                 exp += sign * exp1;
00525                 if (exp_overflow) {
00526                         exp = sign * MAX_EXP;
00527                         if (e->m1 != 0 || e->m2 != 0) errno = ERANGE;
00528                 }
00529         }
00530         if (e->m1 == 0 && e->m2 == 0) return;
00531         e->exp = 63;
00532         while (! (e->m1 & 0x80000000)) {
00533                 b64_sft(&(e->mantissa),-1);
00534                 e->exp--;
00535         }
00536         add_exponent(e, exp);
00537 }
00538 
00539 #include        <math.h>
00540 
00541 static
00542 ten_mult(struct EXTEND *e)
00543 {
00544         struct EXTEND e1 = *e;
00545 
00546         e1.exp++;
00547         e->exp += 3;
00548         add_ext(e, &e1, e);
00549 }
00550 
00551 #define NDIGITS 128
00552 #define NSIGNIFICANT 19
00553 
00554 char *
00555 _ext_str_cvt(struct EXTEND *e, int ndigit, int *decpt, int *sign, int ecvtflag)
00556 {
00557         /*      Like cvt(), but for extended precision */
00558 
00559         static char buf[NDIGITS+1];
00560         struct EXTEND m;
00561         register char *p = buf;
00562         register char *pe;
00563         int findex = 0;
00564 
00565         if (ndigit < 0) ndigit = 0;
00566         if (ndigit > NDIGITS) ndigit = NDIGITS;
00567         pe = &buf[ndigit];
00568         buf[0] = '\0';
00569 
00570         *sign = 0;
00571         if (e->sign) {
00572                 *sign = 1;
00573                 e->sign = 0;
00574         }
00575 
00576         *decpt = 0;
00577         if (e->m1 != 0) {
00578                 register struct EXTEND *pp = &big_ten_powers[1];
00579 
00580                 while(cmp_ext(e,pp) >= 0) {
00581                         pp++;
00582                         findex = pp - big_ten_powers;
00583                         if (findex >= BTP) break;
00584                 }
00585                 pp--;
00586                 findex = pp - big_ten_powers;
00587                 mul_ext(e,&r_big_ten_powers[findex],e);
00588                 *decpt += findex * TP;
00589                 pp = &ten_powers[1];
00590                 while(pp < &ten_powers[TP] && cmp_ext(e, pp) >= 0) pp++;
00591                 pp--;
00592                 findex = pp - ten_powers;
00593                 *decpt += findex;
00594 
00595                 if (cmp_ext(e, &ten_powers[0]) < 0) {
00596                         pp = &r_big_ten_powers[1];
00597                         while(cmp_ext(e,pp) < 0) pp++;
00598                         pp--;
00599                         findex = pp - r_big_ten_powers;
00600                         mul_ext(e, &big_ten_powers[findex], e);
00601                         *decpt -= findex * TP;
00602                         /* here, value >= 10 ** -28 */
00603                         ten_mult(e);
00604                         (*decpt)--;
00605                         pp = &r_ten_powers[0];
00606                         while(cmp_ext(e, pp) < 0) pp++;
00607                         findex = pp - r_ten_powers;
00608                         mul_ext(e, &ten_powers[findex], e);
00609                         *decpt -= findex;
00610                         findex = 0;
00611                 }
00612                 (*decpt)++;     /* because now value in [1.0, 10.0) */
00613         }
00614         if (! ecvtflag) {
00615                 /* for fcvt() we need ndigit digits behind the dot */
00616                 pe += *decpt;
00617                 if (pe > &buf[NDIGITS]) pe = &buf[NDIGITS];
00618         }
00619         m.exp = -62;
00620         m.sign = 0;
00621         m.m1 = 0xA0000000;
00622         m.m2 = 0;
00623         while (p <= pe) {
00624                 struct EXTEND oneminm;
00625 
00626                 if (p - pe > NSIGNIFICANT) {
00627                         findex = 0;
00628                         e->m1 = 0;
00629                 }
00630                 if (findex) {
00631                         struct EXTEND tc, oldtc;
00632                         int count = 0;
00633 
00634                         oldtc.exp = 0;
00635                         oldtc.sign = 0;
00636                         oldtc.m1 = 0;
00637                         oldtc.m2 = 0;
00638                         tc = ten_powers[findex];
00639                         while (cmp_ext(e, &tc) >= 0) {
00640                                 oldtc = tc;
00641                                 add_ext(&tc, &ten_powers[findex], &tc);
00642                                 count++;
00643                         }
00644                         *p++ = count + '0';
00645                         oldtc.sign = 1;
00646                         add_ext(e, &oldtc, e);
00647                         findex--;
00648                         continue;
00649                 }
00650                 if (e->m1) {
00651                         m.sign = 1;
00652                         add_ext(&ten_powers[0], &m, &oneminm);
00653                         m.sign = 0;
00654                         if (e->exp >= 0) {
00655                                 struct EXTEND x;
00656 
00657                                 x.m2 = 0; x.exp = e->exp;
00658                                 x.sign = 1;
00659                                 x.m1 = e->m1>>(31-e->exp);
00660                                 *p++ = (x.m1) + '0';
00661                                 x.m1 = x.m1 << (31-e->exp);
00662                                 add_ext(e, &x, e);
00663                         }
00664                         else *p++ = '0';
00665                         /* Check that remainder is still significant */
00666                         if (cmp_ext(&m, e) > 0 || cmp_ext(e, &oneminm) > 0) {
00667                                 if (e->m1 && e->exp >= -1) *(p-1) += 1;
00668                                 e->m1 = 0;
00669                                 continue;
00670                         }
00671                         ten_mult(&m);
00672                         ten_mult(e);
00673                 }
00674                 else *p++ = '0';
00675         }
00676         if (pe >= buf) {
00677                 p = pe;
00678                 *p += 5;        /* round of at the end */
00679                 while (*p > '9') {
00680                         *p = '0';
00681                         if (p > buf) ++*--p;
00682                         else {
00683                                 *p = '1';
00684                                 ++*decpt;
00685                                 if (! ecvtflag) {
00686                                         /* maybe add another digit at the end,
00687                                            because the point was shifted right
00688                                         */
00689                                         if (pe > buf) *pe = '0';
00690                                         pe++;
00691                                 }
00692                         }
00693                 }
00694                 *pe = '\0';
00695         }
00696         return buf;
00697 }
00698 
00699 _dbl_ext_cvt(double value, struct EXTEND *e)
00700 {
00701         /*      Convert double to extended
00702         */
00703         int exponent;
00704 
00705         value = frexp(value, &exponent);
00706         e->sign = value < 0.0;
00707         if (e->sign) value = -value;
00708         e->exp = exponent - 1;
00709         value *= 4294967296.0;
00710         e->m1 = value;
00711         value -= e->m1;
00712         value *= 4294967296.0;
00713         e->m2 = value;
00714 }
00715 
00716 static struct EXTEND max_d;
00717 
00718 double
00719 _ext_dbl_cvt(struct EXTEND *e)
00720 {
00721         /*      Convert extended to double
00722         */
00723         double f;
00724         int sign = e->sign;
00725 
00726         e->sign = 0;
00727         if (e->m1 == 0 && e->m2 == 0) {
00728                 return 0.0;
00729         }
00730         if (max_d.exp == 0) {
00731                 _dbl_ext_cvt(DBL_MAX, &max_d);
00732         }
00733         if (cmp_ext(&max_d, e) < 0) {
00734                 f = HUGE_VAL;
00735                 errno = ERANGE;
00736         }
00737         else    f = ldexp((double)e->m1*4294967296.0 + (double)e->m2, e->exp-63);
00738         if (sign) f = -f;
00739         if (f == 0.0 && (e->m1 != 0 || e->m2 != 0)) {
00740                 errno = ERANGE;
00741         }
00742         return f;
00743 }

Generated on Fri Apr 14 22:57:25 2006 for minix by  doxygen 1.4.6