static uint8_t *ccder_encode_nanoseconds(CFAbsoluteTime at, const uint8_t *der, uint8_t *der_end) { int dotoff; int sign; char *end; char *str = __dtoa(at, 0, 0, &dotoff, &sign, &end); char *begin = str + (dotoff < 0 ? 0 : dotoff); // Compute 1.0000000 - fraction in ascii space if (at < 0.0 && begin < end) { char *p = end - 1; // Borrow for last digit *p = ('9' + 1) - (*p - '0'); while (p-- > begin) { // Every other digit is a 9 since we borrowed from the last one *p = '9' - (*p - '0'); } } ptrdiff_t len = end - str; if (len > dotoff) { if (dotoff < 0) { assert(-1.0 < at && at < 1.0); der_end = ccder_encode_body(len, (const uint8_t *)str, der, der_end); der_end = ccder_encode_body_nocopy(-dotoff, der, der_end); if (der_end) memset(der_end, at < 0.0 ? '9' : '0', -dotoff); } else { der_end = ccder_encode_body(len - dotoff, (const uint8_t *)(str + dotoff), der, der_end); } der_end = ccder_encode_byte('.', der, der_end); } __freedtoa(str); return der_end; }
static size_t ccder_sizeof_nanoseconds(CFAbsoluteTime at) { int dotoff; int sign; char *end; char *str = __dtoa(at, 0, 0, &dotoff, &sign, &end); ptrdiff_t len = end - str; __freedtoa(str); return len < dotoff ? 0 : len - dotoff; //return len < dotoff ? 0 : len - dotoff > 9 ? 9 : len - dotoff; }
int main(int argc, char **argv) { double cst = M_PI; if (argc > 1) cst = strtod(argv[1], 0); printf("%g\n", cst); printf("%.0g\n", cst); printf("%.1g\n", cst); printf("%.2g\n", cst); #if 0 #ifdef __mt_freestanding__ int expt, signflag; char *dtoaend; char *s; s = __dtoa(cst, 0, 6 /*prec*/, &expt, &signflag, &dtoaend); fprintf(stderr, "dtoa 0: '%s', exp %d, sign %d len %d\n", s, expt, signflag, dtoaend - s); s = __dtoa(cst, 1, 6 /*prec*/, &expt, &signflag, &dtoaend); fprintf(stderr, "dtoa 1: '%s', exp %d, sign %d len %d\n", s, expt, signflag, dtoaend - s); s = __dtoa(cst, 2, 6 /*prec*/, &expt, &signflag, &dtoaend); fprintf(stderr, "dtoa 2: '%s', exp %d, sign %d len %d\n", s, expt, signflag, dtoaend - s); s = __dtoa(cst, 3, 6 /*prec*/, &expt, &signflag, &dtoaend); fprintf(stderr, "dtoa 3: '%s', exp %d, sign %d len %d\n", s, expt, signflag, dtoaend - s); s = __dtoa(cst, 4, 6 /*prec*/, &expt, &signflag, &dtoaend); fprintf(stderr, "dtoa 4: '%s', exp %d, sign %d len %d\n", s, expt, signflag, dtoaend - s); s = __dtoa(cst, 5, 6 /*prec*/, &expt, &signflag, &dtoaend); fprintf(stderr, "dtoa 5: '%s', exp %d, sign %d len %d\n", s, expt, signflag, dtoaend - s); s = __dtoa(cst, 6, 6 /*prec*/, &expt, &signflag, &dtoaend); fprintf(stderr, "dtoa 6: '%s', exp %d, sign %d len %d\n", s, expt, signflag, dtoaend - s); s = __dtoa(cst, 7, 6 /*prec*/, &expt, &signflag, &dtoaend); fprintf(stderr, "dtoa 7: '%s', exp %d, sign %d len %d\n", s, expt, signflag, dtoaend - s); s = __dtoa(cst, 8, 6 /*prec*/, &expt, &signflag, &dtoaend); fprintf(stderr, "dtoa 8: '%s', exp %d, sign %d len %d\n", s, expt, signflag, dtoaend - s); s = __dtoa(cst, 9, 6 /*prec*/, &expt, &signflag, &dtoaend); fprintf(stderr, "dtoa 9: '%s', exp %d, sign %d len %d\n", s, expt, signflag, dtoaend - s); #endif #endif return 0; }
char * fcvt_mp (double arg, int ndigits, int *decpt, int *sign, char *buffer) { *decpt = __dtoa (buffer, ndigits, arg, 1, _ROUNDUP_RM) + 1; if (*decpt + ndigits <= 0 && buffer[1] >= '5' && buffer[1] <= '9') { /* need to round up the digit beyond 'ndigits' */ buffer[1] = '1'; buffer[2] = '0'; buffer[3] = '\0'; (*decpt)++; } *sign = buffer[0] == '-'; return buffer+1; }
char * ecvt_mp (double arg, int ndigits, int *decpt, int *sign, char *buffer) { /* extern FILE *debugfile; */ if (ndigits > 17) { register char *p, *e; *decpt = __dtoa (buffer, 17, arg, 0, _ROUNDUP_RM) + 1; for (p = buffer+18, e = buffer + 1 + (ndigits > NDIG ? NDIG : ndigits); p != e; ) *p++ = '0'; *p++ = '\0'; } else if (ndigits <= 0) { *decpt = __dtoa (buffer, 1, arg, 0, _ROUNDUP_RM) + 1; buffer[1] = '\0'; } else { *decpt = __dtoa (buffer, ndigits, arg, 0, _ROUNDUP_RM) + 1; } *sign = buffer[0] == '-'; return buffer+1; }
static char * __cvt(double value, int ndigit, int *decpt, int *sign, int fmode, int pad) { static char *s; char *p, *rve, c; size_t siz; if (ndigit == 0) { *sign = value < 0.0; *decpt = 0; return (""); } if (s) { free(s); s = NULL; } if (ndigit < 0) siz = -ndigit + 1; else siz = ndigit + 1; /* __dtoa() doesn't allocate space for 0 so we do it by hand */ if (value == 0.0) { *decpt = 1 - fmode; /* 1 for 'e', 0 for 'f' */ *sign = 0; if ((rve = s = (char *)malloc(siz)) == NULL) return(NULL); *rve++ = '0'; *rve = '\0'; } else { p = __dtoa(value, fmode + 2, ndigit, decpt, sign, &rve); if (*decpt == 9999) { /* Infinity or Nan, convert to inf or nan like printf */ *decpt = 0; c = *p; __freedtoa(p); return(c == 'I' ? "inf" : "nan"); } /* Make a local copy and adjust rve to be in terms of s */ if (pad && fmode) siz += *decpt; if ((s = (char *)malloc(siz)) == NULL) { __freedtoa(p); return(NULL); } (void) strlcpy(s, p, siz); rve = s + (rve - p); __freedtoa(p); } /* Add trailing zeros */ if (pad) { siz -= rve - s; while (--siz) *rve++ = '0'; *rve = '\0'; } return(s); }
static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec, uint8_t flags, double value) { 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; /* Special handling for NaN and Infinity */ if (isnan(value)) { lib_dtoa_string(obj, "NaN"); return; } if (isinf(value)) { if (value < 0.0) { obj->put(obj, '-'); } lib_dtoa_string(obj, "Infinity"); return; } /* Non-zero... positive or negative */ if (value < 0) { value = -value; SET_NEGATE(flags); } /* Perform the conversion */ digits = __dtoa(value, 3, prec, &expt, &dsgn, &rve); digalloc = digits; numlen = rve - digits; if (IS_NEGATE(flags)) { obj->put(obj, '-'); } else if (IS_SHOWPLUS(flags)) { obj->put(obj, '+'); } /* Special case exact zero or the case where the number is smaller than * the print precision. */ if (value == 0 || expt < -prec) { /* kludge for __dtoa irregularity */ obj->put(obj, '0'); /* A decimal point is printed only in the alternate form or if a * particular precision is requested. */ if (prec > 0 || IS_ALTFORM(flags)) { obj->put(obj, '.'); /* Always print at least one digit to the right of the decimal point. */ prec = MAX(1, prec); } } /* A non-zero value will be printed */ else { /* Handle the case where the value is less than 1.0 (in magnitude) and * will need a leading zero. */ if (expt <= 0) { /* Print a single zero to the left of the decimal point */ obj->put(obj, '0'); /* Print the decimal point */ obj->put(obj, '.'); /* Print any leading zeros to the right of the decimal point */ if (expt < 0) { nchars = MIN(-expt, prec); zeroes(obj, nchars); prec -= nchars; } } /* Handle the general case where the value is greater than 1.0 (in * magnitude). */ else { /* Print the integer part to the left of the decimal point */ for (i = expt; i > 0; i--) { if (*digits != '\0') { obj->put(obj, *digits); digits++; } else { obj->put(obj, '0'); } } /* Get the length of the fractional part */ numlen -= expt; /* If there is no fractional part, then a decimal point is printed * only in the alternate form or if a particular precision is * requested. */ if (numlen > 0 || prec > 0 || IS_ALTFORM(flags)) { /* Print the decimal point */ obj->put(obj, '.'); /* Always print at least one digit to the right of the decimal * point. */ prec = MAX(1, prec); } } /* If a precision was specified, then limit the number digits to the * right of the decimal point. */ if (prec > 0) { nchars = MIN(numlen, prec); } else { nchars = numlen; } /* Print the fractional part to the right of the decimal point */ for (i = nchars; i > 0; i--) { obj->put(obj, *digits); digits++; } /* Decremnt to get the number of trailing zeroes to print */ prec -= nchars; } /* Finally, print any trailing zeroes */ zeroes(obj, prec); /* Is this memory supposed to be freed or not? */ #if 0 if (digalloc) { lib_free(digalloc); } #endif }
/* * ldtoa() is a wrapper for gdtoa() that makes it smell like dtoa(), * except that the floating point argument is passed by reference. * When dtoa() is passed a NaN or infinity, it sets expt to 9999. * However, a long double could have a valid exponent of 9999, so we * use INT_MAX in ldtoa() instead. */ char * __ldtoa(long double *ld, int mode, int ndigits, int *decpt, int *sign, char **rve) { #if defined(__arm__) /* On arm, double == long double, so short circuit this */ char * ret = __dtoa((double)*ld, mode, ndigits, decpt, sign, rve); if (*decpt == 9999) *decpt = INT_MAX; return ret; #else FPI fpi = { LDBL_MANT_DIG, /* nbits */ LDBL_MIN_EXP - LDBL_MANT_DIG, /* emin */ LDBL_MAX_EXP - LDBL_MANT_DIG, /* emax */ FLT_ROUNDS, /* rounding */ #ifdef Sudden_Underflow /* unused, but correct anyway */ 1 #else 0 #endif }; int be, kind; char *ret; union IEEEl2bits u; uint32_t bits[(LDBL_MANT_DIG + 31) / 32]; void *vbits = bits; int type; u.e = *ld; type = fpclassify(u.e); /* * gdtoa doesn't know anything about the sign of the number, so * if the number is negative, we need to swap rounding modes of * 2 (upwards) and 3 (downwards). */ *sign = u.bits.sign; fpi.rounding ^= (fpi.rounding >> 1) & u.bits.sign; be = u.bits.exp - (LDBL_MAX_EXP - 1) - (LDBL_MANT_DIG - 1); LDBL_TO_ARRAY32(u, bits); switch (type) { case FP_NORMAL: case FP_SUPERNORMAL: kind = STRTOG_Normal; #ifdef LDBL_IMPLICIT_NBIT bits[LDBL_MANT_DIG / 32] |= 1 << ((LDBL_MANT_DIG - 1) % 32); #endif /* LDBL_IMPLICIT_NBIT */ break; case FP_ZERO: kind = STRTOG_Zero; break; case FP_SUBNORMAL: kind = STRTOG_Denormal; be++; break; case FP_INFINITE: kind = STRTOG_Infinite; break; case FP_NAN: kind = STRTOG_NaN; break; default: LIBC_ABORT("fpclassify returned %d", type); } ret = gdtoa(&fpi, be, vbits, &kind, mode, ndigits, decpt, rve); if (*decpt == -32768) *decpt = INT_MAX; return ret; #endif }
char * gcvt(double value, int ndigit, char *buf) { char *digits, *dst, *src; int i, decpt, sign; struct lconv *lconv; lconv = localeconv(); if (ndigit == 0) { buf[0] = '\0'; return (buf); } digits = __dtoa(value, 2, ndigit, &decpt, &sign, NULL); if (decpt == 9999) { /* * Infinity or NaN, convert to inf or nan with sign. * We assume the buffer is at least ndigit long. */ snprintf(buf, ndigit + 1, "%s%s", sign ? "-" : "", *digits == 'I' ? "inf" : "nan"); __freedtoa(digits); return (buf); } dst = buf; if (sign) *dst++ = '-'; if (decpt < 0 || decpt > ndigit) { /* exponential format (e.g. 1.2345e+13) */ if (--decpt < 0) { sign = 1; decpt = -decpt; } else sign = 0; src = digits; *dst++ = *src++; *dst++ = *lconv->decimal_point; while (*src != '\0') *dst++ = *src++; *dst++ = 'e'; if (sign) *dst++ = '-'; else *dst++ = '+'; if (decpt < 10) { *dst++ = '0'; *dst++ = '0' + decpt; *dst = '\0'; } else { /* XXX - optimize */ for (sign = decpt, i = 0; (sign /= 10) != 0; i++) continue; dst[i + 1] = '\0'; while (decpt != 0) { dst[i--] = '0' + decpt % 10; decpt /= 10; } } } else { /* standard format */ for (i = 0, src = digits; i < decpt; i++) { if (*src != '\0') *dst++ = *src++; else *dst++ = '0'; } if (*src != '\0') { if (src == digits) *dst++ = '0'; /* zero before decimal point */ *dst++ = *lconv->decimal_point; for (i = decpt; digits[i] != '\0'; i++) { *dst++ = digits[i]; } } *dst = '\0'; } __freedtoa(digits); return (buf); }
static char* cvt(double value, int ndigits, int flags, char *sign, int *decpt, int ch, int *length) { int mode, dsgn; char *digits, *bp, *rve; if (ch == 'f') { mode = 3; /* ndigits after the decimal point */ } 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 */ } if (value < 0) { value = -value; *sign = '-'; } else { *sign = '\000'; } digits = __dtoa(value, mode, ndigits, decpt, &dsgn, &rve); if ((ch != 'g' && ch != 'G') || IS_ALTFORM(flags)) { /* Print trailing zeros */ bp = digits + ndigits; if (ch == 'f') { if (*digits == '0' && value) { *decpt = -ndigits + 1; } bp += *decpt; } if (value == 0) { /* kludge for __dtoa irregularity */ rve = bp; } while (rve < bp) { *rve++ = '0'; } } *length = rve - digits; return digits; }
prec = DEFPREC; if (dtoaresult) __freedtoa(dtoaresult); if (flags & LONGDBL) { fparg.ldbl = GETARG(long double); dtoaresult = cp = __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec, &expt, &signflag, &dtoaend); if (dtoaresult == NULL) { /*errno = ENOMEM*/; goto error; } } else { fparg.dbl = GETARG(double); dtoaresult = cp = __dtoa(fparg.dbl, expchar ? 2 : 3, prec, &expt, &signflag, &dtoaend); if (dtoaresult == NULL) { /*errno = ENOMEM*/; goto error; } if (expt == 9999) expt = INT_MAX; } fp_common: if (signflag) sign = '-'; if (expt == INT_MAX) { /* inf or nan */ if (*cp == 'N') { cp = (ch >= 'a') ? "nan" : "NAN"; sign = '\0'; } else