Read and print NaN significand if <ieee754.h>

* 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.
This commit is contained in:
Paul Eggert 2018-08-01 00:49:39 -07:00
parent e28a37438d
commit 6e37d2fd05
5 changed files with 27 additions and 1 deletions

View file

@ -1668,6 +1668,7 @@ fi
dnl checks for header files dnl checks for header files
AC_CHECK_HEADERS_ONCE( AC_CHECK_HEADERS_ONCE(
ieee754.h
linux/fs.h linux/fs.h
malloc.h malloc.h
sys/systeminfo.h sys/systeminfo.h

View file

@ -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 NaNs carry a sign and a significand, and non-numeric functions treat
two NaNs as equal when their two NaNs as equal when their
signs and significands agree. Significands of NaNs are 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 When NaNs and signed zeros are involved, non-numeric functions like
@code{eql}, @code{equal}, @code{sxhash-eql}, @code{sxhash-equal} and @code{eql}, @code{equal}, @code{sxhash-eql}, @code{sxhash-equal} and

View file

@ -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 NaNs. Now, all these functions treat NaN signs and significands as
significant. For example, (eql 0.0e+NaN -0.0e+NaN) now returns nil significant. For example, (eql 0.0e+NaN -0.0e+NaN) now returns nil
because the two NaNs have different signs; formerly it returned t. because the two NaNs have different signs; formerly it returned t.
Also, on platforms that have <ieee754.h> 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. ** The function 'make-string' accepts an additional optional argument.

View file

@ -72,6 +72,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#define file_tell ftell #define file_tell ftell
#endif #endif
#if HAVE_IEEE754_H
# include <ieee754.h>
#endif
/* The objects or placeholders read with the #n=object form. /* The objects or placeholders read with the #n=object form.
A hash table maps a number to either a placeholder (while the 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; state |= E_EXP;
cp += 3; 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. */ /* NAN is a "positive" NaN on all known Emacs hosts. */
value = NAN; value = NAN;
#endif
} }
else else
cp = ecp; cp = ecp;

View file

@ -40,6 +40,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <ftoastr.h> #include <ftoastr.h>
#include <math.h> #include <math.h>
#if HAVE_IEEE754_H
# include <ieee754.h>
#endif
#ifdef WINDOWSNT #ifdef WINDOWSNT
# include <sys/socket.h> /* for F_DUPFD_CLOEXEC */ # include <sys/socket.h> /* for F_DUPFD_CLOEXEC */
#endif #endif
@ -1011,6 +1015,12 @@ float_to_string (char *buf, double data)
} }
if (isnan (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. /* Prepend "-" if the NaN's sign bit is negative.
The sign bit of a double is the bit that is 1 in -0.0. */ The sign bit of a double is the bit that is 1 in -0.0. */
static char const NaN_string[] = "0.0e+NaN"; static char const NaN_string[] = "0.0e+NaN";
@ -1029,6 +1039,7 @@ float_to_string (char *buf, double data)
strcpy (buf + negative, NaN_string); strcpy (buf + negative, NaN_string);
return negative + sizeof NaN_string - 1; return negative + sizeof NaN_string - 1;
#endif
} }
if (NILP (Vfloat_output_format) if (NILP (Vfloat_output_format)