Mercurial > emacs
changeset 20121:1e352b03fd8a
(_MAXLDBL, _NMAXLDBL):
Define to work around hpux 7 <math.h> problem.
(<math.h>): Include.
(<float.h>, <stdlib.h>): Include if STDC_HEADERS.
(FLT_RADIX, DBL_MANT_DIG, DBL_DIG): Default to IEEE values.
(DOUBLE_DIGITS_BOUND): New macro.
(float_to_string): By default, generate the fewest number of digits
that represent the floating point value exactly.
author | Paul Eggert <eggert@twinsun.com> |
---|---|
date | Thu, 23 Oct 1997 04:29:36 +0000 |
parents | 6aa000284161 |
children | 923e1f635ace |
files | src/print.c |
diffstat | 1 files changed, 57 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/src/print.c Wed Oct 22 04:34:23 1997 +0000 +++ b/src/print.c Thu Oct 23 04:29:36 1997 +0000 @@ -45,6 +45,46 @@ #ifdef LISP_FLOAT_TYPE Lisp_Object Vfloat_output_format, Qfloat_output_format; + +/* Work around a problem that happens because math.h on hpux 7 + defines two static variables--which, in Emacs, are not really static, + because `static' is defined as nothing. The problem is that they are + defined both here and in lread.c. + These macros prevent the name conflict. */ +#if defined (HPUX) && !defined (HPUX8) +#define _MAXLDBL print_maxldbl +#define _NMAXLDBL print_nmaxldbl +#endif + +#include <math.h> + +#if STDC_HEADERS +#include <float.h> +#include <stdlib.h> +#endif + +/* Default to values appropriate for IEEE floating point. */ +#ifndef FLT_RADIX +#define FLT_RADIX 2 +#endif +#ifndef DBL_MANT_DIG +#define DBL_MANT_DIG 53 +#endif +#ifndef DBL_DIG +#define DBL_DIG 15 +#endif + +/* Define DOUBLE_DIGITS_BOUND, an upper bound on the number of decimal digits + needed to express a float without losing information. + The general-case formula is valid for the usual case, IEEE floating point, + but many compilers can't optimize the formula to an integer constant, + so make a special case for it. */ +#if FLT_RADIX == 2 && DBL_MANT_DIG == 53 +#define DOUBLE_DIGITS_BOUND 17 /* IEEE floating point */ +#else +#define DOUBLE_DIGITS_BOUND ((int) ceil (log10 (pow (FLT_RADIX, DBL_MANT_DIG)))) +#endif + #endif /* LISP_FLOAT_TYPE */ /* Avoid actual stack overflow in print. */ @@ -865,8 +905,21 @@ || !STRINGP (Vfloat_output_format)) lose: { - sprintf (buf, "%.17g", data); - width = -1; + /* Generate the fewest number of digits that represent the + floating point value without losing information. + The following method is simple but a bit slow. + For ideas about speeding things up, please see: + + Guy L Steele Jr & Jon L White, How to print floating-point numbers + accurately. SIGPLAN notices 25, 6 (June 1990), 112-126. + + Robert G Burger & R Kent Dybvig, Printing floating point numbers + quickly and accurately, SIGPLAN notices 31, 5 (May 1996), 108-116. */ + + width = fabs (data) < DBL_MIN ? 1 : DBL_DIG; + do + sprintf (buf, "%.*g", width, data); + while (width++ < DOUBLE_DIGITS_BOUND && atof (buf) != data); } else /* oink oink */ { @@ -1514,7 +1567,8 @@ The precision in any of these cases is the number of digits following\n\ the decimal point. With `f', a precision of 0 means to omit the\n\ decimal point. 0 is not allowed with `e' or `g'.\n\n\ -A value of nil means to use `%.17g'."); +A value of nil means to use the shortest notation\n\ +that represents the number without losing information."); Vfloat_output_format = Qnil; Qfloat_output_format = intern ("float-output-format"); staticpro (&Qfloat_output_format);