diff options
Diffstat (limited to 'nuttx/lib/stdio')
-rw-r--r-- | nuttx/lib/stdio/lib_dtoa.c | 194 | ||||
-rw-r--r-- | nuttx/lib/stdio/lib_libdtoa.c | 368 | ||||
-rw-r--r-- | nuttx/lib/stdio/lib_libvsprintf.c | 4 |
3 files changed, 301 insertions, 265 deletions
diff --git a/nuttx/lib/stdio/lib_dtoa.c b/nuttx/lib/stdio/lib_dtoa.c index 894af4f42..b8c7db980 100644 --- a/nuttx/lib/stdio/lib_dtoa.c +++ b/nuttx/lib/stdio/lib_dtoa.c @@ -970,7 +970,9 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) word0(d) &= ~Sign_bit; /* clear sign bit */ } else - *sign = 0; + { + *sign = 0; + } #if defined(IEEE_Arith) # ifdef IEEE_Arith @@ -1040,17 +1042,22 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) i -= (Bias + (P - 1) - 1) + 1; denorm = 1; } + ds = (d2 - 1.5) * 0.289529654602168 + 0.1760912590558 + i * 0.301029995663981; k = (int)ds; if (ds < 0. && ds != k) - k--; /* want k = floor(ds) */ + { + k--; /* want k = floor(ds) */ + } k_check = 1; + if (k >= 0 && k <= Ten_pmax) { if (d < tens[k]) k--; k_check = 0; } + j = bbits - i - 1; if (j >= 0) { @@ -1062,6 +1069,7 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) b2 = -j; s2 = 0; } + if (k >= 0) { b5 = 0; @@ -1074,14 +1082,19 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) b5 = -k; s5 = 0; } + if (mode < 0 || mode > 9) - mode = 0; + { + mode = 0; + } + try_quick = 1; if (mode > 5) { mode -= 4; try_quick = 0; } + leftright = 1; switch (mode) { @@ -1091,14 +1104,19 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) i = 18; ndigits = 0; break; + case 2: leftright = 0; /* no break */ case 4: if (ndigits <= 0) - ndigits = 1; + { + ndigits = 1; + } + ilim = ilim1 = i = ndigits; break; + case 3: leftright = 0; /* no break */ @@ -1107,18 +1125,24 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) ilim = i; ilim1 = i - 1; if (i <= 0) - i = 1; + { + i = 1; + } } + j = sizeof(unsigned long); - for (result_k = 0; (signed)(sizeof(Bigint) - sizeof(unsigned long) + j) <= i; + for (result_k = 0; + (signed)(sizeof(Bigint) - sizeof(unsigned long) + j) <= i; j <<= 1) - result_k++; + { + result_k++; + } + result = Balloc(result_k); s = s0 = (char *)result; if (ilim >= 0 && ilim <= Quick_max && try_quick) { - /* Try to get by with floating-point arithmetic. */ i = 0; @@ -1126,10 +1150,12 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) k0 = k; ilim0 = ilim; ieps = 2; /* conservative */ + if (k > 0) { ds = tens[k & 0xf]; j = k >> 4; + if (j & Bletch) { /* prevent overflows */ @@ -1137,33 +1163,44 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) d /= bigtens[n_bigtens - 1]; ieps++; } + for (; j; j >>= 1, i++) - if (j & 1) - { - ieps++; - ds *= bigtens[i]; - } + { + if (j & 1) + { + ieps++; + ds *= bigtens[i]; + } + } + d /= ds; } else if ((j_1 = -k)) { d *= tens[j_1 & 0xf]; for (j = j_1 >> 4; j; j >>= 1, i++) - if (j & 1) - { - ieps++; - d *= bigtens[i]; - } + { + if (j & 1) + { + ieps++; + d *= bigtens[i]; + } + } } + if (k_check && d < 1. && ilim > 0) { if (ilim1 <= 0) - goto fast_failed; + { + goto fast_failed; + } + ilim = ilim1; k--; d *= 10.; ieps++; } + eps = ieps * d + 7.; word0(eps) -= (P - 1) * Exp_msk1; if (ilim == 0) @@ -1176,10 +1213,12 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) goto no_digits; goto fast_failed; } + #ifndef No_leftright if (leftright) { /* Use Steele & White method of only generating digits needed. */ + eps = 0.5 / tens[ilim - 1] - eps; for (i = 0;;) { @@ -1200,6 +1239,7 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) { #endif /* Generate ilim digits, then fix them up. */ + eps *= tens[ilim - 1]; for (i = 1;; i++, d *= 10.) { @@ -1234,6 +1274,7 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) if (be >= 0 && k <= Int_max) { /* Yes. */ + ds = tens[k]; if (ndigits < 0 && ilim <= 0) { @@ -1242,6 +1283,7 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) goto no_digits; goto one_digit; } + for (i = 1;; i++) { L = (int)(d / ds); @@ -1273,8 +1315,11 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) break; } if (!(d *= 10.)) - break; + { + break; + } } + goto ret1; } @@ -1304,10 +1349,12 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) i = 0; } } + b2 += i; s2 += i; mhi = i2b(1); } + if (m2 > 0 && s2 > 0) { i = m2 < s2 ? m2 : s2; @@ -1315,6 +1362,7 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) m2 -= i; s2 -= i; } + if (b5 > 0) { if (leftright) @@ -1330,11 +1378,16 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) b = pow5mult(b, j); } else - b = pow5mult(b, b5); + { + b = pow5mult(b, b5); + } } + S = i2b(1); if (s5 > 0) - S = pow5mult(S, s5); + { + S = pow5mult(S, s5); + } /* Check for special case that d is a normalized power of 2. */ @@ -1348,24 +1401,31 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) spec_case = 1; } else - spec_case = 0; + { + spec_case = 0; + } } - /* - * Arrange for convenient computation of quotients: shift left if + /* Arrange for convenient computation of quotients: shift left if * necessary so divisor has 4 leading 0 bits. * * Perhaps we should just compute leading 28 bits of S once and for all * and pass them and a shift to quorem, so it can do shifts and ors * to compute the numerator for q. */ + #ifdef Pack_32 if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds - 1]) : 1) + s2) & 0x1f)) - i = 32 - i; + { + i = 32 - i; + } #else if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds - 1]) : 1) + s2) & 0xf)) - i = 16 - i; + { + i = 16 - i; + } #endif + if (i > 4) { i -= 4; @@ -1380,10 +1440,17 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) m2 += i; s2 += i; } + if (b2 > 0) - b = lshift(b, b2); + { + b = lshift(b, b2); + } + if (s2 > 0) - S = lshift(S, s2); + { + S = lshift(S, s2); + } + if (k_check) { if (cmp(b, S) < 0) @@ -1391,10 +1458,14 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) k--; b = multadd(b, 10, 0); /* we botched the k estimate */ if (leftright) - mhi = multadd(mhi, 10, 0); + { + mhi = multadd(mhi, 10, 0); + } + ilim = ilim1; } } + if (ilim <= 0 && mode > 2) { if (ilim < 0 || cmp(b, S = multadd(S, 5, 0)) <= 0) @@ -1409,10 +1480,13 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) k++; goto ret; } + if (leftright) { if (m2 > 0) - mhi = lshift(mhi, m2); + { + mhi = lshift(mhi, m2); + } /* Compute mlo -- check for special case that d is a normalized power of * 2. */ @@ -1437,9 +1511,15 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) if (j_1 == 0 && !mode && !(word1(d) & 1)) { if (dig == '9') - goto round_9_up; + { + goto round_9_up; + } + if (j > 0) - dig++; + { + dig++; + } + *s++ = dig; goto ret; } @@ -1455,11 +1535,15 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) b = lshift(b, 1); j_1 = cmp(b, S); if ((j_1 > 0 || (j_1 == 0 && (dig & 1))) && dig++ == '9') - goto round_9_up; + { + goto round_9_up; + } } + *s++ = dig; goto ret; } + if (j_1 > 0) { if (dig == '9') @@ -1468,15 +1552,22 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) *s++ = '9'; goto roundoff; } + *s++ = dig + 1; goto ret; } + *s++ = dig; if (i == ilim) - break; + { + break; + } + b = multadd(b, 10, 0); if (mlo == mhi) - mlo = mhi = multadd(mhi, 10, 0); + { + mlo = mhi = multadd(mhi, 10, 0); + } else { mlo = multadd(mlo, 10, 0); @@ -1485,13 +1576,18 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) } } else - for (i = 1;; i++) - { - *s++ = dig = quorem(b, S) + '0'; - if (i >= ilim) - break; - b = multadd(b, 10, 0); - } + { + for (i = 1;; i++) + { + *s++ = dig = quorem(b, S) + '0'; + if (i >= ilim) + { + break; + } + + b = multadd(b, 10, 0); + } + } /* Round off last digit */ @@ -1514,12 +1610,16 @@ char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve) while (*--s == '0'); s++; } + ret: Bfree(S); if (mhi) { if (mlo && mlo != mhi) - Bfree(mlo); + { + Bfree(mlo); + } + Bfree(mhi); } ret1: @@ -1529,9 +1629,13 @@ ret1: *s++ = '0'; k = 0; } + *s = 0; *decpt = k + 1; if (rve) - *rve = s; + { + *rve = s; + } + return s0; } diff --git a/nuttx/lib/stdio/lib_libdtoa.c b/nuttx/lib/stdio/lib_libdtoa.c index 3bfe70aea..1e022a8eb 100644 --- a/nuttx/lib/stdio/lib_libdtoa.c +++ b/nuttx/lib/stdio/lib_libdtoa.c @@ -48,7 +48,15 @@ * Pre-processor Definitions ****************************************************************************/ -#define MAXEXP 308 +#define MAX_PREC 16 + +#ifndef MIN +# define MIN(a,b) (a < b ? a : b) +#endif + +#ifndef MAX +# define MAX(a,b) (a > b ? a : b) +#endif /**************************************************************************** * Private Type Declarations @@ -58,10 +66,6 @@ * Private Function Prototypes ****************************************************************************/ -static char* cvt(double value, int ndigits, int flags, char *sign, - int *decpt, int ch, int *length); -static int exponent(char *p0, int exp, int fmtch); - /**************************************************************************** * Global Constant Data ****************************************************************************/ @@ -79,284 +83,212 @@ static int exponent(char *p0, int exp, int fmtch); ****************************************************************************/ /**************************************************************************** + * Name: zeroes + * + * Description: + * Print the specified number of zeres + * + ****************************************************************************/ + +static void zeroes(FAR struct lib_outstream_s *obj, int nzeroes) +{ + int i; + + for (i = nzeroes; i > 0; i--) + { + obj->put(obj, '0'); + } +} + +/**************************************************************************** * Private Functions ****************************************************************************/ /**************************************************************************** - * Name: cvt + * Name: lib_dtoa + * + * Description: + * This is part of lib_vsprintf(). It handles the floating point formats. + * This version supports only the %f (with precision). If no precision + * was provided in the format, this will use precision == 0 which is + * probably not what you want. + * + * Input Parameters: + * obj - The output stream object + * fmt - The format character. Not used 'f' is always assumed + * prec - The number of digits to the right of the decimal point. If no + * precision is provided in the format, this will be zero. And, + * unfortunately in this case, it will be treated literally as + * a precision of zero. + * flags - Only ALTFORM and SHOWPLUS flags are supported. ALTFORM only + * applies if prec == 0 which is not supported anyway. + * value - The floating point value to convert. + * ****************************************************************************/ -static char* cvt(double value, int ndigits, int flags, char *sign, - int *decpt, int ch, int *length) +static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec, + uint8_t flags, double value) { - int mode, dsgn; - char *digits, *bp, *rve; + FAR char *digits; /* String returned by __dtoa */ + FAR char *digalloc; /* Copy of digits to be freed after usage */ + FAR char *rve; /* Points to the end of the return value */ + int expt; /* Integer value of exponent */ + int numlen; /* Actual number of digits returned by cvt */ + int nchars; /* Number of characters to print */ + int dsgn; /* Unused sign indicator */ + int i; - if (ch == 'f') + /* Non-zero... positive or negative */ + + if (value < 0) { - mode = 3; /* ndigits after the decimal point */ + value = -value; + SET_NEGATE(flags); } - else - { - /* To obtain ndigits after the decimal point for the 'e' and 'E' - * formats, round to ndigits + 1 significant figures. - */ - if (ch == 'e' || ch == 'E') - { - ndigits++; - } - mode = 2; /* ndigits significant digits */ - } + /* Perform the conversion */ - if (value < 0) + digits = __dtoa(value, 3, prec, &expt, &dsgn, &rve); + digalloc = digits; + numlen = rve - digits; + + if (IS_NEGATE(flags)) { - value = -value; - *sign = '-'; + obj->put(obj, '-'); } - else + else if (IS_SHOWPLUS(flags)) { - *sign = '\000'; + obj->put(obj, '+'); } - digits = __dtoa(value, mode, ndigits, decpt, &dsgn, &rve); - if ((ch != 'g' && ch != 'G') || IS_ALTFORM(flags)) + /* Special case exact zero or the case where the number is smaller than + * the print precision. + */ + + if (value == 0 || expt < -prec) { - /* Print trailing zeros */ + /* kludge for __dtoa irregularity */ - bp = digits + ndigits; - if (ch == 'f') - { - if (*digits == '0' && value) - { - *decpt = -ndigits + 1; - } - bp += *decpt; - } + obj->put(obj, '0'); - if (value == 0) + /* A decimal point is printed only in the alternate form or if a + * particular precision is requested. + */ + + if (prec > 0 || IS_ALTFORM(flags)) { - /* kludge for __dtoa irregularity */ + obj->put(obj, '.'); - rve = bp; - } + /* Always print at least one digit to the right of the decimal point. */ - while (rve < bp) - { - *rve++ = '0'; + prec = MAX(1, prec); } } - *length = rve - digits; - return digits; -} - -/**************************************************************************** - * Name: exponent - ****************************************************************************/ - -static int exponent(FAR char *p0, int exp, int fmtch) -{ - FAR char *p; - FAR char *t; - char expbuf[MAXEXP]; + /* A non-zero value will be printed */ - p = p0; - *p++ = fmtch; - if (exp < 0) - { - exp = -exp; - *p++ = '-'; - } else { - *p++ = '+'; - } - t = expbuf + MAXEXP; - if (exp > 9) - { - do + /* Handle the case where the value is less than 1.0 (in magnitude) and + * will need a leading zero. + */ + + if (expt <= 0) { - *--t = (exp % 10) + '0'; - } - while ((exp /= 10) > 9); - *--t = exp + '0'; - for (; t < expbuf + MAXEXP; *p++ = *t++); - } - else - { - *p++ = '0'; - *p++ = exp + '0'; - } - return (p - p0); -} + /* Print a single zero to the left of the decimal point */ -/**************************************************************************** - * Name: lib_dtoa - * - * Description: - * This is part of lib_vsprintf(). It handles the floating point formats. - * - ****************************************************************************/ + obj->put(obj, '0'); -static void lib_dtoa(FAR struct lib_outstream_s *obj, int ch, int prec, - uint8_t flags, double _double) -{ - FAR char *cp; /* Handy char pointer (short term usage) */ - FAR char *cp_free = NULL; /* BIONIC: copy of cp to be freed after usage */ - char expstr[7]; /* Buffer for exponent string */ - char sign; /* Temporary negative sign for floats */ - int expt; /* Integer value of exponent */ - int expsize = 0; /* Character count for expstr */ - int ndig; /* Actual number of digits returned by cvt */ - int size; /* Size of converted field or string */ - int i; + /* Print the decimal point */ - cp = cvt(_double, prec, flags, &sign, &expt, ch, &ndig); - cp_free = cp; + obj->put(obj, '.'); - if (ch == 'g' || ch == 'G') - { - /* 'g' or 'G' fmt */ + /* Print any leading zeros to the right of the decimal point */ - if (expt <= -4 || expt > prec) - { - ch = (ch == 'g') ? 'e' : 'E'; - } - else - { - ch = 'g'; + if (expt < 0) + { + nchars = MIN(-expt, prec); + zeroes(obj, nchars); + prec -= nchars; + } } - } - if (ch <= 'e') - { - /* 'e' or 'E' fmt */ + /* Handle the general case where the value is greater than 1.0 (in + * magnitude). + */ - --expt; - expsize = exponent(expstr, expt, ch); - size = expsize + ndig; - if (ndig > 1 || IS_ALTFORM(flags)) + else { - ++size; - } - } - else if (ch == 'f') - { - /* f fmt */ + /* Print the integer part to the left of the decimal point */ - if (expt > 0) - { - size = expt; - if (prec || IS_ALTFORM(flags)) + for (i = expt; i > 0; i--) { - size += prec + 1; + obj->put(obj, *digits); + digits++; } - } - else /* "0.X" */ - { - size = prec + 2; - } - } - else if (expt >= ndig) - { - /* fixed g fmt */ - size = expt; - if (IS_ALTFORM(flags)) - { - ++size; - } - } - else - { - size = ndig + (expt > 0 ? 1 : 2 - expt); - } + /* Get the length of the fractional part */ - if (sign) - { - obj->put(obj, '-'); - } + numlen -= expt; - if (_double == 0) - { - /* kludge for __dtoa irregularity */ - - obj->put(obj, '0'); - if (expt < ndig || IS_ALTFORM(flags)) - { - obj->put(obj, '.'); + /* If there is no fractional part, then a decimal point is printed + * only in the alternate form or if a particular precision is + * requested. + */ - i = ndig - 1; - while (i > 0) + if (numlen > 0 || prec > 0 || IS_ALTFORM(flags)) { - obj->put(obj, '0'); - i--; + /* Print the decimal point */ + + obj->put(obj, '.'); + + /* Always print at least one digit to the right of the decimal + * point. + */ + + prec = MAX(1, prec); } } - } - else if (expt <= 0) - { - obj->put(obj, '0'); - obj->put(obj, '.'); - i = ndig; - while (i > 0) + /* If a precision was specified, then limit the number digits to the + * right of the decimal point. + */ + + if (prec > 0) { - obj->put(obj, *cp); - i--; - cp++; + nchars = MIN(numlen, prec); } - } - else if (expt >= ndig) - { - i = ndig; - while (i > 0) + else { - obj->put(obj, *cp); - i--; - cp++; + nchars = numlen; } - i = expt - ndig; - while (i > 0) - { - obj->put(obj, '0'); - i--; - } + /* Print the fractional part to the right of the decimal point */ - if (IS_ALTFORM(flags)) + for (i = nchars; i > 0; i--) { - obj->put(obj, '.'); + obj->put(obj, *digits); + digits++; } - } - else - { - /* print the integer */ - i = expt; - while (i > 0) - { - obj->put(obj, *cp); - i--; - cp++; - } + /* Decremnt to get the number of trailing zeroes to print */ + + prec -= nchars; + } - /* print the decimal place */ + /* Finally, print any trailing zeroes */ - obj->put(obj, '.'); + zeroes(obj, prec); - /* print the decimal */ + /* Is this memory supposed to be freed or not? */ - i = ndig - expt; - while (i > 0) - { - obj->put(obj, *cp); - i--; - cp++; - } +#if 0 + if (digalloc) + { + free(digalloc); } +#endif } /**************************************************************************** diff --git a/nuttx/lib/stdio/lib_libvsprintf.c b/nuttx/lib/stdio/lib_libvsprintf.c index 1fb0376a9..2bf095880 100644 --- a/nuttx/lib/stdio/lib_libvsprintf.c +++ b/nuttx/lib/stdio/lib_libvsprintf.c @@ -1587,7 +1587,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const char *src, va_list a /* Perform left field justification actions */ - prejustify(obj, fmt, flags, width, dblsize); + prejustify(obj, fmt, 0, width, dblsize); /* Output the number */ @@ -1595,7 +1595,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const char *src, va_list a /* Perform right field justification actions */ - postjustify(obj, fmt, flags, width, dblsize); + postjustify(obj, fmt, 0, width, dblsize); #else /* Output the number with a fixed precision */ |