From e5c844eff29e28f2bd32e8b185cb5d463f05a878 Mon Sep 17 00:00:00 2001 From: Alexey Frunze Date: Sat, 23 Jan 2016 19:36:41 -0800 Subject: [PATCH] Floating point improvements - Smaller C: fix a bug in __func__ introduced with float-related changes - make *printf() print floats greater than 1e25 - make *printf() print the plus sign when the format includes "+", e.g. printf("%+f\n", 1.0); - clean up and complete prototypes in - remove non-standard HUGE and LOGHUGE from - add HUGE_VAL to - express some hard-coded limits in terms of constants from - uncomment prototypes of several floating point conversion functions in for Smaller C --- include/math.h | 18 +++++++++--------- include/stdlib.h | 2 -- src/cmd/smlrc/smlrc.c | 3 ++- src/libc/gen/atof.c | 15 +++++++++++++-- src/libc/gen/ldexp.c | 10 +++++----- src/libc/stdio/doprnt.c | 13 +++++++++---- src/libm/exp.c | 5 +++-- src/libm/j0.c | 2 +- src/libm/j1.c | 2 +- src/libm/jn.c | 2 +- src/libm/log.c | 2 +- src/libm/tan.c | 4 ++-- 12 files changed, 47 insertions(+), 31 deletions(-) diff --git a/include/math.h b/include/math.h index bdd3880..a2aaec5 100644 --- a/include/math.h +++ b/include/math.h @@ -4,16 +4,16 @@ * specifies the terms and conditions for redistribution. */ -double fabs(), floor(), ceil(), fmod(), ldexp(); -double sqrt(), hypot(), atof(); -double sin(), cos(), tan(), asin(), acos(), atan(), atan2(); -double exp(), log(), log10(), pow(); -double sinh(), cosh(), tanh(); -double gamma(); -double j0(), j1(), jn(), y0(), y1(), yn(); +double fabs(double), floor(double), ceil(double); +double sqrt(double), hypot(double, double); +double sin(double), cos(double), tan(double); +double asin(double), acos(double), atan(double), atan2(double, double); +double exp(double), log(double), log10(double), pow(double, double); +double sinh(double), cosh(double), tanh(double); +double j0(double), j1(double), jn(int, double); +double y0(double), y1(double), yn(int, double); -#define HUGE 1.701411733192644270e38 -#define LOGHUGE 39 +#define HUGE_VAL 3.40282347e+38 /* TBD??? use infinity? */ int isnanf(float x); int isnan(double x); diff --git a/include/stdlib.h b/include/stdlib.h index 6b46e57..d375f3e 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -96,12 +96,10 @@ long random (void); char *setstate (char *); void srandom (unsigned); -#ifndef __SMALLER_C__ double atof (const char *); double strtod (const char *, char **); char *ecvt (double, int, int *, int *); char *fcvt (double, int, int *, int *); char *gcvt (double, int, char *); -#endif #endif /* _STDLIB_H_ */ diff --git a/src/cmd/smlrc/smlrc.c b/src/cmd/smlrc/smlrc.c index 5956605..97f3daa 100644 --- a/src/cmd/smlrc/smlrc.c +++ b/src/cmd/smlrc/smlrc.c @@ -672,7 +672,7 @@ int ParamLevel = 0; // 1+ if parsing params, 0 otherwise unsigned char SyntaxStack0[SYNTAX_STACK_MAX]; int SyntaxStack1[SYNTAX_STACK_MAX]; -int SyntaxStackCnt = 8; // number of explicitly initialized elements in SyntaxStack0[] +int SyntaxStackCnt; // all code @@ -9234,6 +9234,7 @@ int main(int argc, char** argv) tokChar }; // SyntaxStackCnt must be initialized to the number of elements in SyntaxStackInit[][] memcpy(SyntaxStack0, SyntaxStackInit, sizeof SyntaxStackInit); + SyntaxStackCnt = sizeof SyntaxStackInit / sizeof SyntaxStackInit[0]; #ifdef __SMALLER_C__ #ifdef DETERMINE_VA_LIST diff --git a/src/libc/gen/atof.c b/src/libc/gen/atof.c index da73221..5454762 100644 --- a/src/libc/gen/atof.c +++ b/src/libc/gen/atof.c @@ -4,16 +4,27 @@ * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ +#include #include #include +/* + * BIG = 2**(DBL_MANT_DIG+3) defines how many decimal digits + * to take into account from the input. It doesn't make sense + * to use more digits than log10(2**DBL_MANT_DIG)+1. + * BIG is equal 2**27 or 2**56, depending on whether double + * is single or double precision. + */ +#define BIG (8 * (double)(1L << (DBL_MANT_DIG/2)) * \ + (double)(1L << (DBL_MANT_DIG/2 + DBL_MANT_DIG%2))) + double atof(p) register char *p; { register int c; double fl, flexp, exp5; - double big = 72057594037927936.; /*2^56*/ + double big = BIG; int nd; register int eexp, exp, neg, negexp, bexp; @@ -73,7 +84,7 @@ register char *p; } - if ((nd+exp*negexp) < -LOGHUGE){ + if ((nd+exp*negexp) < DBL_MIN_10_EXP - 2) { fl = 0; exp = 0; } diff --git a/src/libc/gen/ldexp.c b/src/libc/gen/ldexp.c index 46c1807..5e0f3c6 100644 --- a/src/libc/gen/ldexp.c +++ b/src/libc/gen/ldexp.c @@ -1,3 +1,4 @@ +#include #include double @@ -5,7 +6,6 @@ ldexp(fr, exp) double fr; int exp; { - double huge = 1.701411834604692293e38; int neg; int i; @@ -20,13 +20,13 @@ ldexp(fr, exp) i = i-1; } exp = exp+i; - if (exp > 127) { + if (exp >= DBL_MAX_EXP) { if (neg) - return(-huge); + return(-HUGE_VAL); else - return(huge); + return(HUGE_VAL); } - if (exp < -127) + if (exp < DBL_MIN_EXP - 2) return(0); while (exp > 30) { fr = fr*(1L<<30); diff --git a/src/libc/stdio/doprnt.c b/src/libc/stdio/doprnt.c index eea7f09..7f54047 100644 --- a/src/libc/stdio/doprnt.c +++ b/src/libc/stdio/doprnt.c @@ -41,8 +41,10 @@ #include #include -/* Max number conversion buffer length: a long in base 2, plus NUL byte. */ -#define MAXNBUF (sizeof(long) * 8 + 1) +/* Max number conversion buffer length. */ +#define MAXNBUF \ + (1/*sign*/ + DBL_MAX_10_EXP+1/*max integral digits*/ + \ + 1/*.*/ + DBL_DIG+1/*max fractional digits*/ + 1/*NUL*/) static unsigned char *ksprintn (unsigned char *buf, unsigned long v, unsigned char base, int width, unsigned char *lp); @@ -403,7 +405,7 @@ number: if (sign && ((long) ul != 0L)) { nbuf [size + 1] = 0; } } - if (neg) + if (neg || sign) size++; if (! ladjust && width && padding == ' ' && (width -= size) > 0) @@ -411,8 +413,11 @@ number: if (sign && ((long) ul != 0L)) { PUTC (' '); } while (--width > 0); - if (neg) + if (neg) { PUTC ('-'); + } else if (sign) { + PUTC ('+'); + } if (! ladjust && width && (width -= size) > 0) do { diff --git a/src/libm/exp.c b/src/libm/exp.c index a72fc2b..e145f08 100644 --- a/src/libm/exp.c +++ b/src/libm/exp.c @@ -4,6 +4,7 @@ * * The coefficients are #1069 from Hart and Cheney. (22.35D) */ +#include #include #include @@ -16,7 +17,7 @@ static double q1 = .3277251518082914423057964422e6; static double q2 = .1749287689093076403844945335e4; static double log2e = 1.4426950408889634073599247; static double sqrt2 = 1.4142135623730950488016887; -static double maxf = 10000; +static double maxf = DBL_MAX_10_EXP * 2.5/*>ln(10)*/; double exp(arg) @@ -32,7 +33,7 @@ double arg; return(0.); if(arg > maxf) { errno = ERANGE; - return(HUGE); + return(HUGE_VAL); } arg *= log2e; ent = floor(arg); diff --git a/src/libm/j0.c b/src/libm/j0.c index 6775fd6..92ef074 100644 --- a/src/libm/j0.c +++ b/src/libm/j0.c @@ -176,7 +176,7 @@ y0(arg) errno = 0; if(arg <= 0.){ errno = EDOM; - return(-HUGE); + return(-HUGE_VAL); } if(arg > 8.){ asympt(arg); diff --git a/src/libm/j1.c b/src/libm/j1.c index 4a70987..ce513f7 100644 --- a/src/libm/j1.c +++ b/src/libm/j1.c @@ -182,7 +182,7 @@ y1(arg) x = arg; if(x <= 0.){ errno = EDOM; - return(-HUGE); + return(-HUGE_VAL); } if(x > 8.){ asympt(x); diff --git a/src/libm/jn.c b/src/libm/jn.c index d58f187..a5c4e0c 100644 --- a/src/libm/jn.c +++ b/src/libm/jn.c @@ -82,7 +82,7 @@ yn(n,x) int n; double x;{ if (x <= 0) { errno = EDOM; - return(-HUGE); + return(-HUGE_VAL); } sign = 1; if(n<0){ diff --git a/src/libm/log.c b/src/libm/log.c index ec7b17a..ac0fb81 100644 --- a/src/libm/log.c +++ b/src/libm/log.c @@ -31,7 +31,7 @@ double arg; if(arg <= 0.) { errno = EDOM; - return(-HUGE); + return(-HUGE_VAL); } x = frexp(arg,&exp); while(x<0.5) { diff --git a/src/libm/tan.c b/src/libm/tan.c index 8c76123..fb9bf3b 100644 --- a/src/libm/tan.c +++ b/src/libm/tan.c @@ -64,8 +64,8 @@ tan(arg) if(temp == 0.) { errno = ERANGE; if (sign>0) - return(HUGE); - return(-HUGE); + return(HUGE_VAL); + return(-HUGE_VAL); } temp = 1./temp; }