|
|
1.1 root 1: /*
2: * Floating point output conversion routines for 'printf'.
3: * Conditionalized #if NDP to do 8087 conversion.
4: */
5:
6: #include <math.h>
7:
8: extern char *_dtoa();
9: extern char *_dtof();
10: extern double frexp();
11: extern double modf();
12: extern double _pow10();
13:
14: #if NDP
15: #include <stdio.h>
16:
17: extern char *strcpy();
18:
19: /*
20: * This table is indexed by the return value of the "_fxam" routine.
21: * The number is converted if the entry is NULL,
22: * otherwise the entry gives the string to print.
23: */
24: static readonly char *fxamsg[] = {
25: "{+ Unnormal}",
26: "{+ NAN}",
27: "{- Unnormal}",
28: "{- NAN}",
29: NULL, /* + Normal */
30: "{+ Infinity}",
31: NULL, /* - Normal */
32: "{- Infinity}",
33: NULL, /* +0 */
34: NULL, /* Empty */
35: NULL, /* -0 */
36: NULL, /* Empty */
37: "{+ Denormal}",
38: NULL, /* Empty */
39: "{- Denormal}",
40: NULL /* Empty */
41: };
42: #endif
43:
44: /*
45: * Convert a floating point number 'd' from binary
46: * into 'e', 'f' or 'g' format ASCII in the buffer 'buf'.
47: * The 'fmt' argument is the conversion type.
48: * The 'prec' argument is the precision.
49: * Return a pointer past the last character.
50: */
51: char *
52: _dtefg(fmt, dp, prec, buf)
53: int fmt;
54: double *dp;
55: int prec;
56: register char *buf;
57: {
58: register char *cp;
59: int decexp, sign;
60: char tbuf[64];
61: double d;
62:
63: d = *dp;
64: #if NDP
65: /* Print given string if 8087 format is special. */
66: if ((cp=fxamsg[_fxam(d)]) != NULL) {
67: strcpy(buf, cp);
68: return(buf + strlen(buf));
69: }
70: #endif
71:
72: if (prec < 0)
73: prec = 6; /* Default precision */
74: if (d < 0.0) {
75: d = -d; /* Force d nonnegative */
76: *buf++ = '-'; /* Leading '-' */
77: }
78: cp = _dtoa(fmt, d, prec, &decexp, &sign, tbuf);
79: if (fmt == 'e'
80: || (fmt == 'g' && (decexp > 4 || decexp < -prec))) { /* 'e' format */
81: buf = _dtof(buf, cp, prec, 0, fmt=='g'); /* mantissa */
82: if (decexp >= 0)
83: sprintf(buf, "e+%02u", decexp); /* exponent */
84: else
85: sprintf(buf, "e-%02u", -decexp);
86: return(buf + strlen(buf));
87: }
88: return(_dtof(buf, cp, prec, decexp, fmt=='g')); /* 'f' format */
89: }
90:
91: /*
92: * Copy ASCII number from 'cp' to 'buf' in %f format
93: * with precision 'prec' and decimal exponent 'decexp'.
94: * The 'isgfmt' flag determines whether trailing zeros are suppressed.
95: * Return a pointer past the last character.
96: */
97: static
98: char *
99: _dtof(buf, cp, prec, decexp, isgfmt)
100: register char *buf;
101: register char *cp;
102: register int prec;
103: register int decexp;
104: int isgfmt;
105: {
106: if (decexp < 0)
107: *buf++ = '0'; /* Units digit '0' */
108: else do
109: *buf++ = *cp ? *cp++ : '0'; /* or integral part */
110: while (decexp--);
111: if (prec == 0 || (isgfmt && *cp == '\0'))
112: return(buf);
113: *buf++ = '.'; /* '.' */
114: while (prec-- > 0) {
115: if (isgfmt && *cp == '\0')
116: break; /* suppress trailing zeros */
117: if (++decexp < 0)
118: *buf++ = '0'; /* put leading zero */
119: else
120: *buf++ = *cp ? *cp++ : '0';
121: }
122: return (buf);
123: }
124:
125: /*
126: * Convert nonnegative double 'd' to string of ASCII digits with no leading zeros
127: * (unless "0") and no trailing zeros, with precision 'prec' in format 'fmt'.
128: * Return a pointer to the converted string, usually (not always) in 'buf'.
129: * Store the decimal exponent indirectly through 'decexpp'.
130: * The first digit of the return value is implicitly followed by '.'
131: * and the return value is implicitly multiplied by 10 to the decimal exponent.
132: */
133: char *
134: _dtoa(fmt, d, prec, decexpp, signp, buf)
135: int fmt;
136: double d;
137: int prec;
138: int *decexpp;
139: int *signp;
140: char *buf;
141: {
142: register char *cp;
143: register int digit;
144: register int decexp;
145: int ndigits;
146: int binexp;
147: double dexp;
148:
149: /*
150: * Force d >= 0.0. The "signp" arg is extraneous in the _dtefg() call,
151: * but is retained for the calls from ecvt() and fcvt(). Bah.
152: */
153: if (d < 0.0) {
154: *signp = 1;
155: d = -d;
156: }
157: else
158: *signp = 0;
159:
160: /* Handle 0.0 as a special case. */
161: if (d == 0.0) {
162: *decexpp = 0;
163: return("0");
164: }
165:
166: /* Reduce d to range [1., 10) and set decexp accordingly. */
167: /* Approximate the decimal exponent from the binary exponent. */
168: /* Obscure but it makes floating output much more efficient. */
169: frexp(d, &binexp); /* Find binary exponent */
170: modf((--binexp)/LOG10B2, &dexp); /* Scale, take integer part */
171: decexp = dexp; /* Convert to integer */
172: d *= _pow10(-decexp); /* Reduce d by power of 10 */
173: if (d >= 10.) { /* May be off by 1 place */
174: ++decexp;
175: d *= 0.10;
176: }
177: *decexpp = decexp; /* Store the decimal exponent */
178:
179: /* Compute the desired number of result digits. */
180: if (fmt == 'e' || (fmt == 'g' && (decexp > 4 || decexp < -prec)))
181: ndigits = prec + 1; /* For 'e' format */
182: else
183: ndigits = prec + decexp + 1; /* For 'f' format */
184: if (ndigits <= 0) { /* No significant digits */
185: if (ndigits == 0 && d > 5.0) { /* Round up to one digit */
186: ++*decexpp;
187: return("1");
188: }
189: *decexpp = 0;
190: return("0");
191: }
192: else if (ndigits > L10P)
193: ndigits = L10P; /* Maximum precision */
194:
195: /* Compute the result digits. */
196: for (cp = buf; cp < &buf[ndigits] && d != 0.0; ) {
197: digit = (int) d;
198: *cp++ = digit + '0'; /* Store next digit */
199: d = 10.0 * (d-digit); /* and reduce d accordingly */
200: }
201: *cp = '\0'; /* NUL-terminate result */
202:
203: /* Round up the result if appropriate. */
204: if (d <= 5.0) { /* Do not round up */
205: while (--cp != buf && *cp == '0')
206: *cp = '\0'; /* Strip a trailing '0' */
207: return (buf);
208: }
209: while (cp-- != buf) { /* Round up */
210: if (++*cp <= '9') /* Bump last digit */
211: return (buf);
212: *cp = '\0'; /* Strip a trailing '0' */
213: }
214: ++*decexpp; /* Bump exponent */
215: return("1"); /* and return "1" */
216: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.