]> git.eshelyaron.com Git - emacs.git/commitdiff
(_MAXLDBL, _NMAXLDBL):
authorPaul Eggert <eggert@twinsun.com>
Thu, 23 Oct 1997 04:29:36 +0000 (04:29 +0000)
committerPaul Eggert <eggert@twinsun.com>
Thu, 23 Oct 1997 04:29:36 +0000 (04:29 +0000)
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.

src/print.c

index 6150da416553b6278a3e3f85e9a7479ef25e81d2..237bccc5a656ac4d2bbba9d41c4cff7910027f38 100644 (file)
@@ -45,6 +45,46 @@ extern Lisp_Object Qbackquote, Qcomma, Qcomma_at, Qcomma_dot, Qfunction;
 
 #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 @@ float_to_string (buf, data)
       || !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 @@ Use `g' to choose the shorter of those two formats for the number at hand.\n\
 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);