From 6e37d2fd05bea373c472af1c6e80238ace5e1c94 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Wed, 1 Aug 2018 00:49:39 -0700 Subject: [PATCH] Read and print NaN significand if * configure.ac: Check for ieee754.h. * doc/lispref/numbers.texi (Float Basics): Document that NaN string representation digits are machine-dependent. * etc/NEWS: Mention the change. * src/lread.c, src/print.c [HAVE_IEEE754_H]: Include ieee754.h. * src/lread.c (string_to_number) [HAVE_IEEE754_H]: * src/print.c (float_to_string) [HAVE_IEEE754_H]: Read and print NaN significand. --- configure.ac | 1 + doc/lispref/numbers.texi | 2 +- etc/NEWS | 3 +++ src/lread.c | 11 +++++++++++ src/print.c | 11 +++++++++++ 5 files changed, 27 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index b6918671e40..dbdcce7c8d8 100644 --- a/configure.ac +++ b/configure.ac @@ -1668,6 +1668,7 @@ fi dnl checks for header files AC_CHECK_HEADERS_ONCE( + ieee754.h linux/fs.h malloc.h sys/systeminfo.h diff --git a/doc/lispref/numbers.texi b/doc/lispref/numbers.texi index 14d5059ffb3..a3317c9a260 100644 --- a/doc/lispref/numbers.texi +++ b/doc/lispref/numbers.texi @@ -241,7 +241,7 @@ A NaN is never numerically equal to any value, not even to itself. NaNs carry a sign and a significand, and non-numeric functions treat two NaNs as equal when their signs and significands agree. Significands of NaNs are -machine-dependent and are not directly visible to Emacs Lisp. +machine-dependent, as are the digits in their string representation. When NaNs and signed zeros are involved, non-numeric functions like @code{eql}, @code{equal}, @code{sxhash-eql}, @code{sxhash-equal} and diff --git a/etc/NEWS b/etc/NEWS index f1ea8356790..9e7a765dc61 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -880,6 +880,9 @@ Formerly, some of these functions ignored signs and significands of NaNs. Now, all these functions treat NaN signs and significands as significant. For example, (eql 0.0e+NaN -0.0e+NaN) now returns nil because the two NaNs have different signs; formerly it returned t. +Also, on platforms that have Emacs now reads and prints +NaN significands; e.g., if X is a NaN, (format "%s" X) now returns +"0.0e+NaN", "1.0e+NaN", etc., depending on X's significand. +++ ** The function 'make-string' accepts an additional optional argument. diff --git a/src/lread.c b/src/lread.c index 50fc6ef8f3a..290b0f6bbe9 100644 --- a/src/lread.c +++ b/src/lread.c @@ -72,6 +72,10 @@ along with GNU Emacs. If not, see . */ #define file_tell ftell #endif +#if HAVE_IEEE754_H +# include +#endif + /* The objects or placeholders read with the #n=object form. A hash table maps a number to either a placeholder (while the @@ -3757,8 +3761,15 @@ string_to_number (char const *string, int base, int flags) { state |= E_EXP; cp += 3; +#if HAVE_IEEE754_H + union ieee754_double u + = { .ieee_nan = { .exponent = -1, .quiet_nan = 1, + .mantissa0 = n >> 31 >> 1, .mantissa1 = n }}; + value = u.d; +#else /* NAN is a "positive" NaN on all known Emacs hosts. */ value = NAN; +#endif } else cp = ecp; diff --git a/src/print.c b/src/print.c index da6ec1aaedf..add21609cc5 100644 --- a/src/print.c +++ b/src/print.c @@ -40,6 +40,10 @@ along with GNU Emacs. If not, see . */ #include #include +#if HAVE_IEEE754_H +# include +#endif + #ifdef WINDOWSNT # include /* for F_DUPFD_CLOEXEC */ #endif @@ -1011,6 +1015,12 @@ float_to_string (char *buf, double data) } if (isnan (data)) { +#if HAVE_IEEE754_H + union ieee754_double u = { .d = data }; + uprintmax_t hi = u.ieee_nan.mantissa0; + return sprintf (buf, &"-%"pMu".0e+NaN"[!u.ieee_nan.negative], + (hi << 31 << 1) + u.ieee_nan.mantissa1); +#else /* Prepend "-" if the NaN's sign bit is negative. The sign bit of a double is the bit that is 1 in -0.0. */ static char const NaN_string[] = "0.0e+NaN"; @@ -1029,6 +1039,7 @@ float_to_string (char *buf, double data) strcpy (buf + negative, NaN_string); return negative + sizeof NaN_string - 1; +#endif } if (NILP (Vfloat_output_format) -- 2.39.2