|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 4094 (0xffe) Types: TextFile Notes: UNIX file Names: »dtefg.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code └─⟦f4b8d8c84⟧ UNIX Filesystem └─⟦this⟧ »libc/crt/dtefg.c«
/* * Floating point output conversion routines for `printf'. * These use floating point, * but don't grind nearly as much as the old ones did! */ /* #include <math.h> */ extern double frexp(); #define L10P 17 #define LOG10B2 0.33219280948873623e+01 /* * Convert a floating point * number from binary into `f', `e' or * `g' format ASCII. The `fmt' argument is * the conversion type. The `w' argument is * the precision. The characters get put * in the buffer `bp'. * A pointer past the last character is returned. */ char * _dtefg(fmt, d, w, bp) double d; char *bp; { register char *cp1, *cp2; int dscale, minusf; char *_dtoa(); char tbuf[40]; if (w < 0) w = 6; cp1 = _dtoa(fmt, d, w, &dscale, &minusf, tbuf); if (fmt == 'g') { int nd; cp2 = cp1; while (*cp2) ++cp2; while (cp2!=cp1 && cp2[-1]=='0') --cp2; nd = cp2-cp1; if (dscale < -3 || dscale > nd+5) fmt = 'e'; else if (dscale >= nd) w = 0; /* `d' format */ } cp2 = bp; if (minusf != 0) *cp2++ = '-'; if (fmt == 'e') { *cp2++ = *cp1++; if (d != 0.0) --dscale; for (*cp2++ = '.'; w > 0; --w) *cp2++ = *cp1 ? *cp1++ : '0'; *cp2++ = 'e'; if (dscale >= 0) *cp2++ = '+'; else { *cp2++ = '-'; dscale = -dscale; } *cp2++ = (dscale/10) + '0'; *cp2++ = (dscale%10) + '0'; } else { if (dscale <= 0) *cp2++ = '0'; else do *cp2++ = *cp1 ? *cp1++ : '0'; while (--dscale); if (w != 0) { for (*cp2++ = '.'; w > 0; --w) { if (dscale++ < 0) *cp2++ = '0'; else *cp2++ = *cp1 ? *cp1++ : '0'; } } } return (cp2); } /* * Convert double to string of ascii digits * rounded after precision digits behind the decimal point. * The decimal scale is stored indirectly through `dscalep' and the sign * (non zero if negative) is saved indirectly through `minusfp'. */ char * _dtoa(fmt, d, w, dscalep, minusfp, buf) double d; int w; int *dscalep; int *minusfp; char *buf; { register char *cp; register int digit; register int i; register int dscale; int ndigit; double _pow10(); if (d >= 0.0) { *minusfp = 0; if (d == 0.0) { *dscalep = 0; cp = buf; while (w-- != 0) *cp++ = '0'; *cp = '\0'; return (buf); } } else { *minusfp = 1; d = -d; } dscale = _getexp(&d) / LOG10B2; d /= _pow10(dscale); if (d >= 1.0) ++dscale; else d *= 10.0; *dscalep = dscale; digit = (int) d; cp = buf; ndigit = w; if (fmt == 'f' || fmt == 'g' && 0 <= dscale && dscale <= 5+w) ndigit = w+dscale; else ndigit = w+1; if (ndigit < 0) ndigit = 0; if (ndigit > L10P) ndigit = L10P; for (i=0; i<ndigit; ++i) { *cp++ = digit + '0'; d = 10.0 * (d-digit); digit = (int) d; } *cp = '\0'; if (digit < 5) return (buf); while (cp != buf) { --cp; if (++*cp <= '9') return (buf); *cp = '0'; } *cp = '1'; cp[ndigit] = '\0'; ++*dscalep; return (buf); } /* * Return the binary exponent of a double. */ static _getexp(dp) double *dp; { int exp; frexp(*dp, &exp); return (exp); } /* * Compute 10**exp, as a double. */ static int i; static double _pow10(exp) register int exp; { register double d; static double _powtab[] = { 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15 }; if( exp < 0) { return( 1.0 / _pow10( -exp)); } d = 1.0; if( exp >= 256) { exp -= 256; d *= 1e256; } if( exp >= 128) { exp -= 128; d *= 1e128; } if( exp >= 64) { exp -= 64; d *= 1e64; } if( exp >= 32) { exp -= 32; d *= 1e32; } if( exp >= 16) { exp -= 16; d *= 1e16; } d *= _powtab[exp]; return( d); /* return( d * _powtab[ exp]); / this used to blow up cc */ } /* * historical interfaces */ char * ecvt(d, w, decp, signp) double d; int w, *decp, *signp; { static char buf[L10P+1]; return (_dtoa('e', d, w<=0 ? 0 : w-1, decp, signp, buf)); } char * fcvt(d, w, decp, signp) double d; int w, *decp, *signp; { static char buf[L10P+1]; return (_dtoa('f', d, w<=0 ? 0 : w, decp, signp, buf)); } char * gcvt(d, w, buf) double d; int w; char *buf; { _dtefg('g', d, w, buf); return (buf); }