ack/lang/pc/libpc/cvt.c

120 lines
2 KiB
C
Raw Normal View History

1984-07-20 11:03:31 +00:00
/* $Header$ */
1988-08-10 11:21:40 +00:00
#ifndef NOFLOAT
1984-07-20 11:20:12 +00:00
1991-03-19 10:25:36 +00:00
#if __STDC__
#include <float.h>
1991-03-20 11:30:35 +00:00
#else
#include <math.h>
#define DBL_MAX M_MAX_D
1991-03-19 10:25:36 +00:00
#endif
1988-08-10 11:21:40 +00:00
static char *cvt();
#define NDIGITS 128
1984-07-20 10:44:57 +00:00
1988-08-10 11:21:40 +00:00
char *
_ecvt(value, ndigit, decpt, sign)
double value;
int ndigit, *decpt, *sign;
{
return cvt(value, ndigit, decpt, sign, 1);
}
char *
_fcvt(value, ndigit, decpt, sign)
double value;
int ndigit, *decpt, *sign;
{
return cvt(value, ndigit, decpt, sign, 0);
}
1984-07-20 10:44:57 +00:00
1988-08-10 11:21:40 +00:00
static struct powers_of_10 {
double pval;
double rpval;
int exp;
} p10[] = {
1.0e32, 1.0e-32, 32,
1.0e16, 1.0e-16, 16,
1.0e8, 1.0e-8, 8,
1.0e4, 1.0e-4, 4,
1.0e2, 1.0e-2, 2,
1.0e1, 1.0e-1, 1,
1.0e0, 1.0e0, 0
};
1984-07-20 10:44:57 +00:00
1988-08-10 11:21:40 +00:00
static char *
cvt(value, ndigit, decpt, sign, ecvtflag)
double value;
int ndigit, *decpt, *sign;
1984-07-20 10:44:57 +00:00
{
1988-08-10 11:21:40 +00:00
static char buf[NDIGITS+1];
register char *p = buf;
register char *pe;
if (ndigit < 0) ndigit = 0;
if (ndigit > NDIGITS) ndigit = NDIGITS;
pe = &buf[ndigit];
buf[0] = '\0';
1984-07-20 10:44:57 +00:00
*sign = 0;
1988-08-10 11:21:40 +00:00
if (value < 0) {
1984-07-20 10:44:57 +00:00
*sign = 1;
1988-08-10 11:21:40 +00:00
value = -value;
1984-07-20 10:44:57 +00:00
}
1988-08-10 11:21:40 +00:00
*decpt = 0;
1991-03-19 10:25:36 +00:00
if (value >= DBL_MAX) {
value = DBL_MAX;
}
1988-08-10 11:21:40 +00:00
if (value != 0.0) {
register struct powers_of_10 *pp = &p10[0];
if (value >= 10.0) do {
while (value >= pp->pval) {
value *= pp->rpval;
*decpt += pp->exp;
}
} while ((++pp)->exp > 0);
pp = &p10[0];
if (value < 1.0) do {
while (value * pp->pval < 10.0) {
value *= pp->pval;
*decpt -= pp->exp;
}
} while ((++pp)->exp > 0);
(*decpt)++; /* because now value in [1.0, 10.0) */
1984-07-20 10:44:57 +00:00
}
1988-08-10 11:21:40 +00:00
if (! ecvtflag) {
/* for fcvt() we need ndigit digits behind the dot */
pe += *decpt;
if (pe > &buf[NDIGITS]) pe = &buf[NDIGITS];
1984-07-20 10:44:57 +00:00
}
1988-08-10 11:21:40 +00:00
while (p <= pe) {
*p++ = (int)value + '0';
value = 10.0 * (value - (int)value);
1984-07-20 10:44:57 +00:00
}
1988-08-10 11:21:40 +00:00
if (pe >= buf) {
p = pe;
*p += 5; /* round of at the end */
while (*p > '9') {
*p = '0';
if (p > buf) ++*--p;
else {
*p = '1';
++*decpt;
if (! ecvtflag) {
/* maybe add another digit at the end,
because the point was shifted right
*/
if (pe > buf) *pe = '0';
pe++;
}
1984-07-20 10:44:57 +00:00
}
}
1988-08-10 11:21:40 +00:00
*pe = '\0';
1984-07-20 10:44:57 +00:00
}
1988-08-10 11:21:40 +00:00
return buf;
1984-07-20 10:44:57 +00:00
}
1988-08-10 11:21:40 +00:00
#endif