]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/gdtoa/strtodg.c
This commit was generated by cvs2svn to compensate for changes in r164146,
[FreeBSD/FreeBSD.git] / contrib / gdtoa / strtodg.c
1 /****************************************************************
2
3 The author of this software is David M. Gay.
4
5 Copyright (C) 1998-2001 by Lucent Technologies
6 All Rights Reserved
7
8 Permission to use, copy, modify, and distribute this software and
9 its documentation for any purpose and without fee is hereby
10 granted, provided that the above copyright notice appear in all
11 copies and that both that the copyright notice and this
12 permission notice and warranty disclaimer appear in supporting
13 documentation, and that the name of Lucent or any of its entities
14 not be used in advertising or publicity pertaining to
15 distribution of the software without specific, written prior
16 permission.
17
18 LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
20 IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
21 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
23 IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
24 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
25 THIS SOFTWARE.
26
27 ****************************************************************/
28
29 /* Please send bug reports to
30         David M. Gay
31         dmg@acm.org
32  */
33
34 #include "gdtoaimp.h"
35
36 #ifdef USE_LOCALE
37 #include "locale.h"
38 #endif
39
40  static CONST int
41 fivesbits[] = {  0,  3,  5,  7, 10, 12, 14, 17, 19, 21,
42                 24, 26, 28, 31, 33, 35, 38, 40, 42, 45,
43                 47, 49, 52
44 #ifdef VAX
45                 , 54, 56
46 #endif
47                 };
48
49  Bigint *
50 #ifdef KR_headers
51 increment(b) Bigint *b;
52 #else
53 increment(Bigint *b)
54 #endif
55 {
56         ULong *x, *xe;
57         Bigint *b1;
58 #ifdef Pack_16
59         ULong carry = 1, y;
60 #endif
61
62         x = b->x;
63         xe = x + b->wds;
64 #ifdef Pack_32
65         do {
66                 if (*x < (ULong)0xffffffffL) {
67                         ++*x;
68                         return b;
69                         }
70                 *x++ = 0;
71                 } while(x < xe);
72 #else
73         do {
74                 y = *x + carry;
75                 carry = y >> 16;
76                 *x++ = y & 0xffff;
77                 if (!carry)
78                         return b;
79                 } while(x < xe);
80         if (carry)
81 #endif
82         {
83                 if (b->wds >= b->maxwds) {
84                         b1 = Balloc(b->k+1);
85                         Bcopy(b1,b);
86                         Bfree(b);
87                         b = b1;
88                         }
89                 b->x[b->wds++] = 1;
90                 }
91         return b;
92         }
93
94  int
95 #ifdef KR_headers
96 decrement(b) Bigint *b;
97 #else
98 decrement(Bigint *b)
99 #endif
100 {
101         ULong *x, *xe;
102 #ifdef Pack_16
103         ULong borrow = 1, y;
104 #endif
105
106         x = b->x;
107         xe = x + b->wds;
108 #ifdef Pack_32
109         do {
110                 if (*x) {
111                         --*x;
112                         break;
113                         }
114                 *x++ = 0xffffffffL;
115                 }
116                 while(x < xe);
117 #else
118         do {
119                 y = *x - borrow;
120                 borrow = (y & 0x10000) >> 16;
121                 *x++ = y & 0xffff;
122                 } while(borrow && x < xe);
123 #endif
124         return STRTOG_Inexlo;
125         }
126
127  static int
128 #ifdef KR_headers
129 all_on(b, n) Bigint *b; int n;
130 #else
131 all_on(Bigint *b, int n)
132 #endif
133 {
134         ULong *x, *xe;
135
136         x = b->x;
137         xe = x + (n >> kshift);
138         while(x < xe)
139                 if ((*x++ & ALL_ON) != ALL_ON)
140                         return 0;
141         if (n &= kmask)
142                 return ((*x | (ALL_ON << n)) & ALL_ON) == ALL_ON;
143         return 1;
144         }
145
146  Bigint *
147 #ifdef KR_headers
148 set_ones(b, n) Bigint *b; int n;
149 #else
150 set_ones(Bigint *b, int n)
151 #endif
152 {
153         int k;
154         ULong *x, *xe;
155
156         k = (n + ((1 << kshift) - 1)) >> kshift;
157         if (b->k < k) {
158                 Bfree(b);
159                 b = Balloc(k);
160                 }
161         k = n >> kshift;
162         if (n &= kmask)
163                 k++;
164         b->wds = k;
165         x = b->x;
166         xe = x + k;
167         while(x < xe)
168                 *x++ = ALL_ON;
169         if (n)
170                 x[-1] >>= ULbits - n;
171         return b;
172         }
173
174  static int
175 rvOK
176 #ifdef KR_headers
177  (d, fpi, exp, bits, exact, rd, irv)
178  double d; FPI *fpi; Long *exp; ULong *bits; int exact, rd, *irv;
179 #else
180  (double d, FPI *fpi, Long *exp, ULong *bits, int exact, int rd, int *irv)
181 #endif
182 {
183         Bigint *b;
184         ULong carry, inex, lostbits;
185         int bdif, e, j, k, k1, nb, rv;
186
187         carry = rv = 0;
188         b = d2b(d, &e, &bdif);
189         bdif -= nb = fpi->nbits;
190         e += bdif;
191         if (bdif <= 0) {
192                 if (exact)
193                         goto trunc;
194                 goto ret;
195                 }
196         if (P == nb) {
197                 if (
198 #ifndef IMPRECISE_INEXACT
199                         exact &&
200 #endif
201                         fpi->rounding ==
202 #ifdef RND_PRODQUOT
203                                         FPI_Round_near
204 #else
205                                         Flt_Rounds
206 #endif
207                         ) goto trunc;
208                 goto ret;
209                 }
210         switch(rd) {
211           case 1:
212                 goto trunc;
213           case 2:
214                 break;
215           default: /* round near */
216                 k = bdif - 1;
217                 if (k < 0)
218                         goto trunc;
219                 if (!k) {
220                         if (!exact)
221                                 goto ret;
222                         if (b->x[0] & 2)
223                                 break;
224                         goto trunc;
225                         }
226                 if (b->x[k>>kshift] & ((ULong)1 << (k & kmask)))
227                         break;
228                 goto trunc;
229           }
230         /* "break" cases: round up 1 bit, then truncate; bdif > 0 */
231         carry = 1;
232  trunc:
233         inex = lostbits = 0;
234         if (bdif > 0) {
235                 if ( (lostbits = any_on(b, bdif)) !=0)
236                         inex = STRTOG_Inexlo;
237                 rshift(b, bdif);
238                 if (carry) {
239                         inex = STRTOG_Inexhi;
240                         b = increment(b);
241                         if ( (j = nb & kmask) !=0)
242                                 j = 32 - j;
243                         if (hi0bits(b->x[b->wds - 1]) != j) {
244                                 if (!lostbits)
245                                         lostbits = b->x[0] & 1;
246                                 rshift(b, 1);
247                                 e++;
248                                 }
249                         }
250                 }
251         else if (bdif < 0)
252                 b = lshift(b, -bdif);
253         if (e < fpi->emin) {
254                 k = fpi->emin - e;
255                 e = fpi->emin;
256                 if (k > nb || fpi->sudden_underflow) {
257                         b->wds = inex = 0;
258                         *irv = STRTOG_Underflow | STRTOG_Inexlo;
259                         }
260                 else {
261                         k1 = k - 1;
262                         if (k1 > 0 && !lostbits)
263                                 lostbits = any_on(b, k1);
264                         if (!lostbits && !exact)
265                                 goto ret;
266                         lostbits |=
267                           carry = b->x[k1>>kshift] & (1 << (k1 & kmask));
268                         rshift(b, k);
269                         *irv = STRTOG_Denormal;
270                         if (carry) {
271                                 b = increment(b);
272                                 inex = STRTOG_Inexhi | STRTOG_Underflow;
273                                 }
274                         else if (lostbits)
275                                 inex = STRTOG_Inexlo | STRTOG_Underflow;
276                         }
277                 }
278         else if (e > fpi->emax) {
279                 e = fpi->emax + 1;
280                 *irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
281 #ifndef NO_ERRNO
282                 errno = ERANGE;
283 #endif
284                 b->wds = inex = 0;
285                 }
286         *exp = e;
287         copybits(bits, nb, b);
288         *irv |= inex;
289         rv = 1;
290  ret:
291         Bfree(b);
292         return rv;
293         }
294
295  static int
296 #ifdef KR_headers
297 mantbits(d) double d;
298 #else
299 mantbits(double d)
300 #endif
301 {
302         ULong L;
303 #ifdef VAX
304         L = word1(d) << 16 | word1(d) >> 16;
305         if (L)
306 #else
307         if ( (L = word1(d)) !=0)
308 #endif
309                 return P - lo0bits(&L);
310 #ifdef VAX
311         L = word0(d) << 16 | word0(d) >> 16 | Exp_msk11;
312 #else
313         L = word0(d) | Exp_msk1;
314 #endif
315         return P - 32 - lo0bits(&L);
316         }
317
318  int
319 strtodg
320 #ifdef KR_headers
321         (s00, se, fpi, exp, bits)
322         CONST char *s00; char **se; FPI *fpi; Long *exp; ULong *bits;
323 #else
324         (CONST char *s00, char **se, FPI *fpi, Long *exp, ULong *bits)
325 #endif
326 {
327         int abe, abits, asub;
328         int bb0, bb2, bb5, bbe, bd2, bd5, bbbits, bs2;
329         int c, denorm, dsign, e, e1, e2, emin, esign, finished, i, inex, irv;
330         int j, k, nbits, nd, nd0, nf, nz, nz0, rd, rvbits, rve, rve1, sign;
331         int sudden_underflow;
332         CONST char *s, *s0, *s1;
333         double adj, adj0, rv, tol;
334         Long L;
335         ULong y, z;
336         Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0;
337
338         irv = STRTOG_Zero;
339         denorm = sign = nz0 = nz = 0;
340         dval(rv) = 0.;
341         rvb = 0;
342         nbits = fpi->nbits;
343         for(s = s00;;s++) switch(*s) {
344                 case '-':
345                         sign = 1;
346                         /* no break */
347                 case '+':
348                         if (*++s)
349                                 goto break2;
350                         /* no break */
351                 case 0:
352                         sign = 0;
353                         irv = STRTOG_NoNumber;
354                         s = s00;
355                         goto ret;
356                 case '\t':
357                 case '\n':
358                 case '\v':
359                 case '\f':
360                 case '\r':
361                 case ' ':
362                         continue;
363                 default:
364                         goto break2;
365                 }
366  break2:
367         if (*s == '0') {
368 #ifndef NO_HEX_FP
369                 switch(s[1]) {
370                   case 'x':
371                   case 'X':
372                         irv = gethex(&s, fpi, exp, &rvb, sign);
373                         if (irv == STRTOG_NoNumber) {
374                                 s = s00;
375                                 sign = 0;
376                                 }
377                         goto ret;
378                   }
379 #endif
380                 nz0 = 1;
381                 while(*++s == '0') ;
382                 if (!*s)
383                         goto ret;
384                 }
385         sudden_underflow = fpi->sudden_underflow;
386         s0 = s;
387         y = z = 0;
388         for(nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++)
389                 if (nd < 9)
390                         y = 10*y + c - '0';
391                 else if (nd < 16)
392                         z = 10*z + c - '0';
393         nd0 = nd;
394 #ifdef USE_LOCALE
395         if (c == *localeconv()->decimal_point)
396 #else
397         if (c == '.')
398 #endif
399                 {
400                 c = *++s;
401                 if (!nd) {
402                         for(; c == '0'; c = *++s)
403                                 nz++;
404                         if (c > '0' && c <= '9') {
405                                 s0 = s;
406                                 nf += nz;
407                                 nz = 0;
408                                 goto have_dig;
409                                 }
410                         goto dig_done;
411                         }
412                 for(; c >= '0' && c <= '9'; c = *++s) {
413  have_dig:
414                         nz++;
415                         if (c -= '0') {
416                                 nf += nz;
417                                 for(i = 1; i < nz; i++)
418                                         if (nd++ < 9)
419                                                 y *= 10;
420                                         else if (nd <= DBL_DIG + 1)
421                                                 z *= 10;
422                                 if (nd++ < 9)
423                                         y = 10*y + c;
424                                 else if (nd <= DBL_DIG + 1)
425                                         z = 10*z + c;
426                                 nz = 0;
427                                 }
428                         }
429                 }
430  dig_done:
431         e = 0;
432         if (c == 'e' || c == 'E') {
433                 if (!nd && !nz && !nz0) {
434                         irv = STRTOG_NoNumber;
435                         s = s00;
436                         goto ret;
437                         }
438                 s00 = s;
439                 esign = 0;
440                 switch(c = *++s) {
441                         case '-':
442                                 esign = 1;
443                         case '+':
444                                 c = *++s;
445                         }
446                 if (c >= '0' && c <= '9') {
447                         while(c == '0')
448                                 c = *++s;
449                         if (c > '0' && c <= '9') {
450                                 L = c - '0';
451                                 s1 = s;
452                                 while((c = *++s) >= '0' && c <= '9')
453                                         L = 10*L + c - '0';
454                                 if (s - s1 > 8 || L > 19999)
455                                         /* Avoid confusion from exponents
456                                          * so large that e might overflow.
457                                          */
458                                         e = 19999; /* safe for 16 bit ints */
459                                 else
460                                         e = (int)L;
461                                 if (esign)
462                                         e = -e;
463                                 }
464                         else
465                                 e = 0;
466                         }
467                 else
468                         s = s00;
469                 }
470         if (!nd) {
471                 if (!nz && !nz0) {
472 #ifdef INFNAN_CHECK
473                         /* Check for Nan and Infinity */
474                         switch(c) {
475                           case 'i':
476                           case 'I':
477                                 if (match(&s,"nf")) {
478                                         --s;
479                                         if (!match(&s,"inity"))
480                                                 ++s;
481                                         irv = STRTOG_Infinite;
482                                         goto infnanexp;
483                                         }
484                                 break;
485                           case 'n':
486                           case 'N':
487                                 if (match(&s, "an")) {
488                                         irv = STRTOG_NaN;
489                                         *exp = fpi->emax + 1;
490 #ifndef No_Hex_NaN
491                                         if (*s == '(') /*)*/
492                                                 irv = hexnan(&s, fpi, bits);
493 #endif
494                                         goto infnanexp;
495                                         }
496                           }
497 #endif /* INFNAN_CHECK */
498                         irv = STRTOG_NoNumber;
499                         s = s00;
500                         }
501                 goto ret;
502                 }
503
504         irv = STRTOG_Normal;
505         e1 = e -= nf;
506         rd = 0;
507         switch(fpi->rounding & 3) {
508           case FPI_Round_up:
509                 rd = 2 - sign;
510                 break;
511           case FPI_Round_zero:
512                 rd = 1;
513                 break;
514           case FPI_Round_down:
515                 rd = 1 + sign;
516           }
517
518         /* Now we have nd0 digits, starting at s0, followed by a
519          * decimal point, followed by nd-nd0 digits.  The number we're
520          * after is the integer represented by those digits times
521          * 10**e */
522
523         if (!nd0)
524                 nd0 = nd;
525         k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
526         dval(rv) = y;
527         if (k > 9)
528                 dval(rv) = tens[k - 9] * dval(rv) + z;
529         bd0 = 0;
530         if (nbits <= P && nd <= DBL_DIG) {
531                 if (!e) {
532                         if (rvOK(dval(rv), fpi, exp, bits, 1, rd, &irv))
533                                 goto ret;
534                         }
535                 else if (e > 0) {
536                         if (e <= Ten_pmax) {
537 #ifdef VAX
538                                 goto vax_ovfl_check;
539 #else
540                                 i = fivesbits[e] + mantbits(dval(rv)) <= P;
541                                 /* rv = */ rounded_product(dval(rv), tens[e]);
542                                 if (rvOK(dval(rv), fpi, exp, bits, i, rd, &irv))
543                                         goto ret;
544                                 e1 -= e;
545                                 goto rv_notOK;
546 #endif
547                                 }
548                         i = DBL_DIG - nd;
549                         if (e <= Ten_pmax + i) {
550                                 /* A fancier test would sometimes let us do
551                                  * this for larger i values.
552                                  */
553                                 e2 = e - i;
554                                 e1 -= i;
555                                 dval(rv) *= tens[i];
556 #ifdef VAX
557                                 /* VAX exponent range is so narrow we must
558                                  * worry about overflow here...
559                                  */
560  vax_ovfl_check:
561                                 dval(adj) = dval(rv);
562                                 word0(adj) -= P*Exp_msk1;
563                                 /* adj = */ rounded_product(dval(adj), tens[e2]);
564                                 if ((word0(adj) & Exp_mask)
565                                  > Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
566                                         goto rv_notOK;
567                                 word0(adj) += P*Exp_msk1;
568                                 dval(rv) = dval(adj);
569 #else
570                                 /* rv = */ rounded_product(dval(rv), tens[e2]);
571 #endif
572                                 if (rvOK(dval(rv), fpi, exp, bits, 0, rd, &irv))
573                                         goto ret;
574                                 e1 -= e2;
575                                 }
576                         }
577 #ifndef Inaccurate_Divide
578                 else if (e >= -Ten_pmax) {
579                         /* rv = */ rounded_quotient(dval(rv), tens[-e]);
580                         if (rvOK(dval(rv), fpi, exp, bits, 0, rd, &irv))
581                                 goto ret;
582                         e1 -= e;
583                         }
584 #endif
585                 }
586  rv_notOK:
587         e1 += nd - k;
588
589         /* Get starting approximation = rv * 10**e1 */
590
591         e2 = 0;
592         if (e1 > 0) {
593                 if ( (i = e1 & 15) !=0)
594                         dval(rv) *= tens[i];
595                 if (e1 &= ~15) {
596                         e1 >>= 4;
597                         while(e1 >= (1 << n_bigtens-1)) {
598                                 e2 += ((word0(rv) & Exp_mask)
599                                         >> Exp_shift1) - Bias;
600                                 word0(rv) &= ~Exp_mask;
601                                 word0(rv) |= Bias << Exp_shift1;
602                                 dval(rv) *= bigtens[n_bigtens-1];
603                                 e1 -= 1 << n_bigtens-1;
604                                 }
605                         e2 += ((word0(rv) & Exp_mask) >> Exp_shift1) - Bias;
606                         word0(rv) &= ~Exp_mask;
607                         word0(rv) |= Bias << Exp_shift1;
608                         for(j = 0; e1 > 0; j++, e1 >>= 1)
609                                 if (e1 & 1)
610                                         dval(rv) *= bigtens[j];
611                         }
612                 }
613         else if (e1 < 0) {
614                 e1 = -e1;
615                 if ( (i = e1 & 15) !=0)
616                         dval(rv) /= tens[i];
617                 if (e1 &= ~15) {
618                         e1 >>= 4;
619                         while(e1 >= (1 << n_bigtens-1)) {
620                                 e2 += ((word0(rv) & Exp_mask)
621                                         >> Exp_shift1) - Bias;
622                                 word0(rv) &= ~Exp_mask;
623                                 word0(rv) |= Bias << Exp_shift1;
624                                 dval(rv) *= tinytens[n_bigtens-1];
625                                 e1 -= 1 << n_bigtens-1;
626                                 }
627                         e2 += ((word0(rv) & Exp_mask) >> Exp_shift1) - Bias;
628                         word0(rv) &= ~Exp_mask;
629                         word0(rv) |= Bias << Exp_shift1;
630                         for(j = 0; e1 > 0; j++, e1 >>= 1)
631                                 if (e1 & 1)
632                                         dval(rv) *= tinytens[j];
633                         }
634                 }
635
636         rvb = d2b(dval(rv), &rve, &rvbits);     /* rv = rvb * 2^rve */
637         rve += e2;
638         if ((j = rvbits - nbits) > 0) {
639                 rshift(rvb, j);
640                 rvbits = nbits;
641                 rve += j;
642                 }
643         bb0 = 0;        /* trailing zero bits in rvb */
644         e2 = rve + rvbits - nbits;
645         if (e2 > fpi->emax) {
646                 rvb->wds = 0;
647                 irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi;
648 #ifndef NO_ERRNO
649                 errno = ERANGE;
650 #endif
651  infnanexp:
652                 *exp = fpi->emax + 1;
653                 goto ret;
654                 }
655         rve1 = rve + rvbits - nbits;
656         if (e2 < (emin = fpi->emin)) {
657                 denorm = 1;
658                 j = rve - emin;
659                 if (j > 0) {
660                         rvb = lshift(rvb, j);
661                         rvbits += j;
662                         }
663                 else if (j < 0) {
664                         rvbits += j;
665                         if (rvbits <= 0) {
666                                 if (rvbits < -1) {
667  ufl:
668                                         rvb->wds = 0;
669                                         rvb->x[0] = 0;
670                                         *exp = emin;
671                                         irv = STRTOG_Underflow | STRTOG_Inexlo;
672                                         goto ret;
673                                         }
674                                 rvb->x[0] = rvb->wds = rvbits = 1;
675                                 }
676                         else
677                                 rshift(rvb, -j);
678                         }
679                 rve = rve1 = emin;
680                 if (sudden_underflow && e2 + 1 < emin)
681                         goto ufl;
682                 }
683
684         /* Now the hard part -- adjusting rv to the correct value.*/
685
686         /* Put digits into bd: true value = bd * 10^e */
687
688         bd0 = s2b(s0, nd0, nd, y);
689
690         for(;;) {
691                 bd = Balloc(bd0->k);
692                 Bcopy(bd, bd0);
693                 bb = Balloc(rvb->k);
694                 Bcopy(bb, rvb);
695                 bbbits = rvbits - bb0;
696                 bbe = rve + bb0;
697                 bs = i2b(1);
698
699                 if (e >= 0) {
700                         bb2 = bb5 = 0;
701                         bd2 = bd5 = e;
702                         }
703                 else {
704                         bb2 = bb5 = -e;
705                         bd2 = bd5 = 0;
706                         }
707                 if (bbe >= 0)
708                         bb2 += bbe;
709                 else
710                         bd2 -= bbe;
711                 bs2 = bb2;
712                 j = nbits + 1 - bbbits;
713                 i = bbe + bbbits - nbits;
714                 if (i < emin)   /* denormal */
715                         j += i - emin;
716                 bb2 += j;
717                 bd2 += j;
718                 i = bb2 < bd2 ? bb2 : bd2;
719                 if (i > bs2)
720                         i = bs2;
721                 if (i > 0) {
722                         bb2 -= i;
723                         bd2 -= i;
724                         bs2 -= i;
725                         }
726                 if (bb5 > 0) {
727                         bs = pow5mult(bs, bb5);
728                         bb1 = mult(bs, bb);
729                         Bfree(bb);
730                         bb = bb1;
731                         }
732                 bb2 -= bb0;
733                 if (bb2 > 0)
734                         bb = lshift(bb, bb2);
735                 else if (bb2 < 0)
736                         rshift(bb, -bb2);
737                 if (bd5 > 0)
738                         bd = pow5mult(bd, bd5);
739                 if (bd2 > 0)
740                         bd = lshift(bd, bd2);
741                 if (bs2 > 0)
742                         bs = lshift(bs, bs2);
743                 asub = 1;
744                 inex = STRTOG_Inexhi;
745                 delta = diff(bb, bd);
746                 if (delta->wds <= 1 && !delta->x[0])
747                         break;
748                 dsign = delta->sign;
749                 delta->sign = finished = 0;
750                 L = 0;
751                 i = cmp(delta, bs);
752                 if (rd && i <= 0) {
753                         irv = STRTOG_Normal;
754                         if ( (finished = dsign ^ (rd&1)) !=0) {
755                                 if (dsign != 0) {
756                                         irv |= STRTOG_Inexhi;
757                                         goto adj1;
758                                         }
759                                 irv |= STRTOG_Inexlo;
760                                 if (rve1 == emin)
761                                         goto adj1;
762                                 for(i = 0, j = nbits; j >= ULbits;
763                                                 i++, j -= ULbits) {
764                                         if (rvb->x[i] & ALL_ON)
765                                                 goto adj1;
766                                         }
767                                 if (j > 1 && lo0bits(rvb->x + i) < j - 1)
768                                         goto adj1;
769                                 rve = rve1 - 1;
770                                 rvb = set_ones(rvb, rvbits = nbits);
771                                 break;
772                                 }
773                         irv |= dsign ? STRTOG_Inexlo : STRTOG_Inexhi;
774                         break;
775                         }
776                 if (i < 0) {
777                         /* Error is less than half an ulp -- check for
778                          * special case of mantissa a power of two.
779                          */
780                         irv = dsign
781                                 ? STRTOG_Normal | STRTOG_Inexlo
782                                 : STRTOG_Normal | STRTOG_Inexhi;
783                         if (dsign || bbbits > 1 || denorm || rve1 == emin)
784                                 break;
785                         delta = lshift(delta,1);
786                         if (cmp(delta, bs) > 0) {
787                                 irv = STRTOG_Normal | STRTOG_Inexlo;
788                                 goto drop_down;
789                                 }
790                         break;
791                         }
792                 if (i == 0) {
793                         /* exactly half-way between */
794                         if (dsign) {
795                                 if (denorm && all_on(rvb, rvbits)) {
796                                         /*boundary case -- increment exponent*/
797                                         rvb->wds = 1;
798                                         rvb->x[0] = 1;
799                                         rve = emin + nbits - (rvbits = 1);
800                                         irv = STRTOG_Normal | STRTOG_Inexhi;
801                                         denorm = 0;
802                                         break;
803                                         }
804                                 irv = STRTOG_Normal | STRTOG_Inexlo;
805                                 }
806                         else if (bbbits == 1) {
807                                 irv = STRTOG_Normal;
808  drop_down:
809                                 /* boundary case -- decrement exponent */
810                                 if (rve1 == emin) {
811                                         irv = STRTOG_Normal | STRTOG_Inexhi;
812                                         if (rvb->wds == 1 && rvb->x[0] == 1)
813                                                 sudden_underflow = 1;
814                                         break;
815                                         }
816                                 rve -= nbits;
817                                 rvb = set_ones(rvb, rvbits = nbits);
818                                 break;
819                                 }
820                         else
821                                 irv = STRTOG_Normal | STRTOG_Inexhi;
822                         if (bbbits < nbits && !denorm || !(rvb->x[0] & 1))
823                                 break;
824                         if (dsign) {
825                                 rvb = increment(rvb);
826                                 if ( (j = rvbits >> kshift) !=0)
827                                         j = 32 - j;
828                                 if (hi0bits(rvb->x[(rvb->wds - 1) >> kshift])
829                                                 != j)
830                                         rvbits++;
831                                 irv = STRTOG_Normal | STRTOG_Inexhi;
832                                 }
833                         else {
834                                 if (bbbits == 1)
835                                         goto undfl;
836                                 decrement(rvb);
837                                 irv = STRTOG_Normal | STRTOG_Inexlo;
838                                 }
839                         break;
840                         }
841                 if ((dval(adj) = ratio(delta, bs)) <= 2.) {
842  adj1:
843                         inex = STRTOG_Inexlo;
844                         if (dsign) {
845                                 asub = 0;
846                                 inex = STRTOG_Inexhi;
847                                 }
848                         else if (denorm && bbbits <= 1) {
849  undfl:
850                                 rvb->wds = 0;
851                                 rve = emin;
852                                 irv = STRTOG_Underflow | STRTOG_Inexlo;
853                                 break;
854                                 }
855                         adj0 = dval(adj) = 1.;
856                         }
857                 else {
858                         adj0 = dval(adj) *= 0.5;
859                         if (dsign) {
860                                 asub = 0;
861                                 inex = STRTOG_Inexlo;
862                                 }
863                         if (dval(adj) < 2147483647.) {
864                                 L = adj0;
865                                 adj0 -= L;
866                                 switch(rd) {
867                                   case 0:
868                                         if (adj0 >= .5)
869                                                 goto inc_L;
870                                         break;
871                                   case 1:
872                                         if (asub && adj0 > 0.)
873                                                 goto inc_L;
874                                         break;
875                                   case 2:
876                                         if (!asub && adj0 > 0.) {
877  inc_L:
878                                                 L++;
879                                                 inex = STRTOG_Inexact - inex;
880                                                 }
881                                   }
882                                 dval(adj) = L;
883                                 }
884                         }
885                 y = rve + rvbits;
886
887                 /* adj *= ulp(dval(rv)); */
888                 /* if (asub) rv -= adj; else rv += adj; */
889
890                 if (!denorm && rvbits < nbits) {
891                         rvb = lshift(rvb, j = nbits - rvbits);
892                         rve -= j;
893                         rvbits = nbits;
894                         }
895                 ab = d2b(dval(adj), &abe, &abits);
896                 if (abe < 0)
897                         rshift(ab, -abe);
898                 else if (abe > 0)
899                         ab = lshift(ab, abe);
900                 rvb0 = rvb;
901                 if (asub) {
902                         /* rv -= adj; */
903                         j = hi0bits(rvb->x[rvb->wds-1]);
904                         rvb = diff(rvb, ab);
905                         k = rvb0->wds - 1;
906                         if (denorm)
907                                 /* do nothing */;
908                         else if (rvb->wds <= k
909                                 || hi0bits( rvb->x[k]) >
910                                    hi0bits(rvb0->x[k])) {
911                                 /* unlikely; can only have lost 1 high bit */
912                                 if (rve1 == emin) {
913                                         --rvbits;
914                                         denorm = 1;
915                                         }
916                                 else {
917                                         rvb = lshift(rvb, 1);
918                                         --rve;
919                                         --rve1;
920                                         L = finished = 0;
921                                         }
922                                 }
923                         }
924                 else {
925                         rvb = sum(rvb, ab);
926                         k = rvb->wds - 1;
927                         if (k >= rvb0->wds
928                          || hi0bits(rvb->x[k]) < hi0bits(rvb0->x[k])) {
929                                 if (denorm) {
930                                         if (++rvbits == nbits)
931                                                 denorm = 0;
932                                         }
933                                 else {
934                                         rshift(rvb, 1);
935                                         rve++;
936                                         rve1++;
937                                         L = 0;
938                                         }
939                                 }
940                         }
941                 Bfree(ab);
942                 Bfree(rvb0);
943                 if (finished)
944                         break;
945
946                 z = rve + rvbits;
947                 if (y == z && L) {
948                         /* Can we stop now? */
949                         tol = dval(adj) * 5e-16; /* > max rel error */
950                         dval(adj) = adj0 - .5;
951                         if (dval(adj) < -tol) {
952                                 if (adj0 > tol) {
953                                         irv |= inex;
954                                         break;
955                                         }
956                                 }
957                         else if (dval(adj) > tol && adj0 < 1. - tol) {
958                                 irv |= inex;
959                                 break;
960                                 }
961                         }
962                 bb0 = denorm ? 0 : trailz(rvb);
963                 Bfree(bb);
964                 Bfree(bd);
965                 Bfree(bs);
966                 Bfree(delta);
967                 }
968         if (!denorm && rvbits < nbits) {
969                 j = nbits - rvbits;
970                 rvb = lshift(rvb, j);
971                 rve -= j;
972                 }
973         *exp = rve;
974         Bfree(bb);
975         Bfree(bd);
976         Bfree(bs);
977         Bfree(bd0);
978         Bfree(delta);
979  ret:
980         if (denorm) {
981                 if (sudden_underflow) {
982                         rvb->wds = 0;
983                         irv = STRTOG_Underflow | STRTOG_Inexlo;
984                         }
985                 else  {
986                         irv = (irv & ~STRTOG_Retmask) |
987                                 (rvb->wds > 0 ? STRTOG_Denormal : STRTOG_Zero);
988                         if (irv & STRTOG_Inexact)
989                                 irv |= STRTOG_Underflow;
990                         }
991                 }
992         if (se)
993                 *se = (char *)s;
994         if (sign)
995                 irv |= STRTOG_Neg;
996         if (rvb) {
997                 copybits(bits, nbits, rvb);
998                 Bfree(rvb);
999                 }
1000         return irv;
1001         }