Substitute a <ieee754.h> on hosts lacking it
* .gitignore: Add lib/ieee754.h. * admin/merge-gnulib (GNULIB_MODULES): Add ieee754-h. * configure.ac: Remove ieee754.h check, as Gnulib now does that. * etc/NEWS: Mention this. * lib/gnulib.mk.in, m4/gnulib-comp.m4: Regenerate. * lib/ieee754.in.h, m4/ieee754-h.m4: New files, from Gnulib. * src/lisp.h (IEEE_FLOATING_POINT): Now a macro so that it can be used in #if. * src/lread.c, src/print.c: Include <ieee754.h> if IEEE_FLOATING_POINT, not if HAVE_IEEE754_H. * src/lread.c (string_to_number): * src/print.c (float_to_string): Process NaNs only on IEEE hosts, and assume <ieee754.h> in that case.
This commit is contained in:
parent
2f37ecaefc
commit
d216d7d248
11 changed files with 291 additions and 40 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -57,6 +57,7 @@ lib/execinfo.h
|
|||
lib/fcntl.h
|
||||
lib/getopt.h
|
||||
lib/getopt-cdefs.h
|
||||
lib/ieee754.h
|
||||
lib/inttypes.h
|
||||
lib/libgnu.a
|
||||
lib/limits.h
|
||||
|
|
|
@ -35,7 +35,7 @@ GNULIB_MODULES='
|
|||
fcntl fcntl-h fdatasync fdopendir
|
||||
filemode filevercmp flexmember fpieee fstatat fsusage fsync
|
||||
getloadavg getopt-gnu gettime gettimeofday gitlog-to-changelog
|
||||
ignore-value intprops largefile lstat
|
||||
ieee754-h ignore-value intprops largefile lstat
|
||||
manywarnings memrchr minmax mkostemp mktime nstrftime
|
||||
pipe2 pselect pthread_sigmask putenv qcopy-acl readlink readlinkat
|
||||
sig2str socklen stat-time std-gnu11 stdalign stddef stdio
|
||||
|
|
|
@ -1668,7 +1668,6 @@ fi
|
|||
|
||||
dnl checks for header files
|
||||
AC_CHECK_HEADERS_ONCE(
|
||||
ieee754.h
|
||||
linux/fs.h
|
||||
malloc.h
|
||||
sys/systeminfo.h
|
||||
|
|
6
etc/NEWS
6
etc/NEWS
|
@ -880,9 +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 <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.
|
||||
Also, 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.
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
# gettime \
|
||||
# gettimeofday \
|
||||
# gitlog-to-changelog \
|
||||
# ieee754-h \
|
||||
# ignore-value \
|
||||
# intprops \
|
||||
# largefile \
|
||||
|
@ -220,6 +221,7 @@ GL_GENERATE_ALLOCA_H = @GL_GENERATE_ALLOCA_H@
|
|||
GL_GENERATE_BYTESWAP_H = @GL_GENERATE_BYTESWAP_H@
|
||||
GL_GENERATE_ERRNO_H = @GL_GENERATE_ERRNO_H@
|
||||
GL_GENERATE_EXECINFO_H = @GL_GENERATE_EXECINFO_H@
|
||||
GL_GENERATE_IEEE754_H = @GL_GENERATE_IEEE754_H@
|
||||
GL_GENERATE_LIMITS_H = @GL_GENERATE_LIMITS_H@
|
||||
GL_GENERATE_STDALIGN_H = @GL_GENERATE_STDALIGN_H@
|
||||
GL_GENERATE_STDDEF_H = @GL_GENERATE_STDDEF_H@
|
||||
|
@ -646,6 +648,7 @@ HAVE_WINSOCK2_H = @HAVE_WINSOCK2_H@
|
|||
HAVE_XSERVER = @HAVE_XSERVER@
|
||||
HAVE__EXIT = @HAVE__EXIT@
|
||||
HYBRID_MALLOC = @HYBRID_MALLOC@
|
||||
IEEE754_H = @IEEE754_H@
|
||||
IMAGEMAGICK_CFLAGS = @IMAGEMAGICK_CFLAGS@
|
||||
IMAGEMAGICK_LIBS = @IMAGEMAGICK_LIBS@
|
||||
INCLUDE_NEXT = @INCLUDE_NEXT@
|
||||
|
@ -1787,6 +1790,32 @@ EXTRA_libgnu_a_SOURCES += group-member.c
|
|||
endif
|
||||
## end gnulib module group-member
|
||||
|
||||
## begin gnulib module ieee754-h
|
||||
ifeq (,$(OMIT_GNULIB_MODULE_ieee754-h))
|
||||
|
||||
BUILT_SOURCES += $(IEEE754_H)
|
||||
|
||||
# We need the following in order to create <ieee754.h> when the system
|
||||
# doesn't have one that works with the given compiler.
|
||||
ifneq (,$(GL_GENERATE_IEEE754_H))
|
||||
ieee754.h: ieee754.in.h $(top_builddir)/config.status
|
||||
$(AM_V_GEN)rm -f $@-t && \
|
||||
{ echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'; \
|
||||
sed -e 's/ifndef _GL_GNULIB_HEADER/if 0/g' \
|
||||
$(srcdir)/ieee754.in.h; \
|
||||
} > $@-t && \
|
||||
mv -f $@-t $@
|
||||
else
|
||||
ieee754.h: $(top_builddir)/config.status
|
||||
rm -f $@
|
||||
endif
|
||||
MOSTLYCLEANFILES += ieee754.h ieee754.h-t
|
||||
|
||||
EXTRA_DIST += ieee754.in.h
|
||||
|
||||
endif
|
||||
## end gnulib module ieee754-h
|
||||
|
||||
## begin gnulib module ignore-value
|
||||
ifeq (,$(OMIT_GNULIB_MODULE_ignore-value))
|
||||
|
||||
|
|
222
lib/ieee754.in.h
Normal file
222
lib/ieee754.in.h
Normal file
|
@ -0,0 +1,222 @@
|
|||
/* Copyright (C) 1992-2018 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 3 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _IEEE754_H
|
||||
|
||||
#define _IEEE754_H 1
|
||||
|
||||
#ifndef _GL_GNULIB_HEADER
|
||||
/* Ordinary glibc usage. */
|
||||
# include <features.h>
|
||||
# include <endian.h>
|
||||
#else
|
||||
/* Gnulib usage. */
|
||||
# ifndef __BEGIN_DECLS
|
||||
# ifdef __cplusplus
|
||||
# define __BEGIN_DECLS extern "C" {
|
||||
# define __END_DECLS }
|
||||
# else
|
||||
# define __BEGIN_DECLS
|
||||
# define __END_DECLS
|
||||
# endif
|
||||
# endif
|
||||
# ifndef __FLOAT_WORD_ORDER
|
||||
# define __LITTLE_ENDIAN 1234
|
||||
# define __BIG_ENDIAN 4321
|
||||
# ifdef WORDS_BIGENDIAN
|
||||
# define __BYTE_ORDER __BIG_ENDIAN
|
||||
# else
|
||||
# define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
# endif
|
||||
# define __FLOAT_WORD_ORDER __BYTE_ORDER
|
||||
# endif
|
||||
#endif
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
union ieee754_float
|
||||
{
|
||||
float f;
|
||||
|
||||
/* This is the IEEE 754 single-precision format. */
|
||||
struct
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned int negative:1;
|
||||
unsigned int exponent:8;
|
||||
unsigned int mantissa:23;
|
||||
#endif /* Big endian. */
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
unsigned int mantissa:23;
|
||||
unsigned int exponent:8;
|
||||
unsigned int negative:1;
|
||||
#endif /* Little endian. */
|
||||
} ieee;
|
||||
|
||||
/* This format makes it easier to see if a NaN is a signalling NaN. */
|
||||
struct
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned int negative:1;
|
||||
unsigned int exponent:8;
|
||||
unsigned int quiet_nan:1;
|
||||
unsigned int mantissa:22;
|
||||
#endif /* Big endian. */
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
unsigned int mantissa:22;
|
||||
unsigned int quiet_nan:1;
|
||||
unsigned int exponent:8;
|
||||
unsigned int negative:1;
|
||||
#endif /* Little endian. */
|
||||
} ieee_nan;
|
||||
};
|
||||
|
||||
#define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */
|
||||
|
||||
|
||||
union ieee754_double
|
||||
{
|
||||
double d;
|
||||
|
||||
/* This is the IEEE 754 double-precision format. */
|
||||
struct
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned int negative:1;
|
||||
unsigned int exponent:11;
|
||||
/* Together these comprise the mantissa. */
|
||||
unsigned int mantissa0:20;
|
||||
unsigned int mantissa1:32;
|
||||
#endif /* Big endian. */
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
|
||||
unsigned int mantissa0:20;
|
||||
unsigned int exponent:11;
|
||||
unsigned int negative:1;
|
||||
unsigned int mantissa1:32;
|
||||
# else
|
||||
/* Together these comprise the mantissa. */
|
||||
unsigned int mantissa1:32;
|
||||
unsigned int mantissa0:20;
|
||||
unsigned int exponent:11;
|
||||
unsigned int negative:1;
|
||||
# endif
|
||||
#endif /* Little endian. */
|
||||
} ieee;
|
||||
|
||||
/* This format makes it easier to see if a NaN is a signalling NaN. */
|
||||
struct
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned int negative:1;
|
||||
unsigned int exponent:11;
|
||||
unsigned int quiet_nan:1;
|
||||
/* Together these comprise the mantissa. */
|
||||
unsigned int mantissa0:19;
|
||||
unsigned int mantissa1:32;
|
||||
#else
|
||||
# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
|
||||
unsigned int mantissa0:19;
|
||||
unsigned int quiet_nan:1;
|
||||
unsigned int exponent:11;
|
||||
unsigned int negative:1;
|
||||
unsigned int mantissa1:32;
|
||||
# else
|
||||
/* Together these comprise the mantissa. */
|
||||
unsigned int mantissa1:32;
|
||||
unsigned int mantissa0:19;
|
||||
unsigned int quiet_nan:1;
|
||||
unsigned int exponent:11;
|
||||
unsigned int negative:1;
|
||||
# endif
|
||||
#endif
|
||||
} ieee_nan;
|
||||
};
|
||||
|
||||
#define IEEE754_DOUBLE_BIAS 0x3ff /* Added to exponent. */
|
||||
|
||||
|
||||
union ieee854_long_double
|
||||
{
|
||||
long double d;
|
||||
|
||||
/* This is the IEEE 854 double-extended-precision format. */
|
||||
struct
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned int negative:1;
|
||||
unsigned int exponent:15;
|
||||
unsigned int empty:16;
|
||||
unsigned int mantissa0:32;
|
||||
unsigned int mantissa1:32;
|
||||
#endif
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
|
||||
unsigned int exponent:15;
|
||||
unsigned int negative:1;
|
||||
unsigned int empty:16;
|
||||
unsigned int mantissa0:32;
|
||||
unsigned int mantissa1:32;
|
||||
# else
|
||||
unsigned int mantissa1:32;
|
||||
unsigned int mantissa0:32;
|
||||
unsigned int exponent:15;
|
||||
unsigned int negative:1;
|
||||
unsigned int empty:16;
|
||||
# endif
|
||||
#endif
|
||||
} ieee;
|
||||
|
||||
/* This is for NaNs in the IEEE 854 double-extended-precision format. */
|
||||
struct
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned int negative:1;
|
||||
unsigned int exponent:15;
|
||||
unsigned int empty:16;
|
||||
unsigned int one:1;
|
||||
unsigned int quiet_nan:1;
|
||||
unsigned int mantissa0:30;
|
||||
unsigned int mantissa1:32;
|
||||
#endif
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
# if __FLOAT_WORD_ORDER == __BIG_ENDIAN
|
||||
unsigned int exponent:15;
|
||||
unsigned int negative:1;
|
||||
unsigned int empty:16;
|
||||
unsigned int mantissa0:30;
|
||||
unsigned int quiet_nan:1;
|
||||
unsigned int one:1;
|
||||
unsigned int mantissa1:32;
|
||||
# else
|
||||
unsigned int mantissa1:32;
|
||||
unsigned int mantissa0:30;
|
||||
unsigned int quiet_nan:1;
|
||||
unsigned int one:1;
|
||||
unsigned int exponent:15;
|
||||
unsigned int negative:1;
|
||||
unsigned int empty:16;
|
||||
# endif
|
||||
#endif
|
||||
} ieee_nan;
|
||||
};
|
||||
|
||||
#define IEEE854_LONG_DOUBLE_BIAS 0x3fff
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* ieee754.h */
|
|
@ -101,6 +101,7 @@ AC_DEFUN([gl_EARLY],
|
|||
# Code from module gettimeofday:
|
||||
# Code from module gitlog-to-changelog:
|
||||
# Code from module group-member:
|
||||
# Code from module ieee754-h:
|
||||
# Code from module ignore-value:
|
||||
# Code from module include_next:
|
||||
# Code from module intprops:
|
||||
|
@ -295,6 +296,7 @@ AC_DEFUN([gl_INIT],
|
|||
gl_PREREQ_GETTIMEOFDAY
|
||||
fi
|
||||
gl_SYS_TIME_MODULE_INDICATOR([gettimeofday])
|
||||
gl_IEEE754_H
|
||||
gl_INTTYPES_INCOMPLETE
|
||||
AC_REQUIRE([gl_LARGEFILE])
|
||||
gl_LIMITS_H
|
||||
|
@ -895,6 +897,7 @@ AC_DEFUN([gl_FILE_LIST], [
|
|||
lib/gettimeofday.c
|
||||
lib/gl_openssl.h
|
||||
lib/group-member.c
|
||||
lib/ieee754.in.h
|
||||
lib/ignore-value.h
|
||||
lib/intprops.h
|
||||
lib/inttypes.in.h
|
||||
|
@ -1017,6 +1020,7 @@ AC_DEFUN([gl_FILE_LIST], [
|
|||
m4/gl-openssl.m4
|
||||
m4/gnulib-common.m4
|
||||
m4/group-member.m4
|
||||
m4/ieee754-h.m4
|
||||
m4/include_next.m4
|
||||
m4/inttypes.m4
|
||||
m4/largefile.m4
|
||||
|
|
21
m4/ieee754-h.m4
Normal file
21
m4/ieee754-h.m4
Normal file
|
@ -0,0 +1,21 @@
|
|||
# Configure ieee754-h module
|
||||
|
||||
dnl Copyright 2018 Free Software Foundation, Inc.
|
||||
dnl This file is free software; the Free Software Foundation
|
||||
dnl gives unlimited permission to copy and/or distribute it,
|
||||
dnl with or without modifications, as long as this notice is preserved.
|
||||
|
||||
AC_DEFUN([gl_IEEE754_H],
|
||||
[
|
||||
AC_REQUIRE([AC_C_BIGENDIAN])
|
||||
AC_CHECK_HEADERS_ONCE([ieee754.h])
|
||||
if test $ac_cv_header_ieee754_h = yes; then
|
||||
IEEE754_H=
|
||||
else
|
||||
IEEE754_H=ieee754.h
|
||||
AC_DEFINE([_GL_REPLACE_IEEE754_H], 1,
|
||||
[Define to 1 if <ieee754.h> is missing.])
|
||||
fi
|
||||
AC_SUBST([IEEE754_H])
|
||||
AM_CONDITIONAL([GL_GENERATE_IEEE754_H], [test -n "$IEEE754_H"])
|
||||
])
|
11
src/lisp.h
11
src/lisp.h
|
@ -2670,17 +2670,14 @@ XFLOAT_DATA (Lisp_Object f)
|
|||
|
||||
/* Most hosts nowadays use IEEE floating point, so they use IEC 60559
|
||||
representations, have infinities and NaNs, and do not trap on
|
||||
exceptions. Define IEEE_FLOATING_POINT if this host is one of the
|
||||
exceptions. Define IEEE_FLOATING_POINT to 1 if this host is one of the
|
||||
typical ones. The C11 macro __STDC_IEC_559__ is close to what is
|
||||
wanted here, but is not quite right because Emacs does not require
|
||||
all the features of C11 Annex F (and does not require C11 at all,
|
||||
for that matter). */
|
||||
enum
|
||||
{
|
||||
IEEE_FLOATING_POINT
|
||||
= (FLT_RADIX == 2 && FLT_MANT_DIG == 24
|
||||
&& FLT_MIN_EXP == -125 && FLT_MAX_EXP == 128)
|
||||
};
|
||||
|
||||
#define IEEE_FLOATING_POINT (FLT_RADIX == 2 && FLT_MANT_DIG == 24 \
|
||||
&& FLT_MIN_EXP == -125 && FLT_MAX_EXP == 128)
|
||||
|
||||
/* A character, declared with the following typedef, is a member
|
||||
of some character set associated with the current buffer. */
|
||||
|
|
|
@ -72,7 +72,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||
#define file_tell ftell
|
||||
#endif
|
||||
|
||||
#if HAVE_IEEE754_H
|
||||
#if IEEE_FLOATING_POINT
|
||||
# include <ieee754.h>
|
||||
#endif
|
||||
|
||||
|
@ -3756,21 +3756,18 @@ string_to_number (char const *string, int base, int flags)
|
|||
cp += 3;
|
||||
value = INFINITY;
|
||||
}
|
||||
#if IEEE_FLOATING_POINT
|
||||
else if (cp[-1] == '+'
|
||||
&& cp[0] == 'N' && cp[1] == 'a' && cp[2] == 'N')
|
||||
{
|
||||
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
|
||||
}
|
||||
#endif
|
||||
else
|
||||
cp = ecp;
|
||||
}
|
||||
|
|
25
src/print.c
25
src/print.c
|
@ -40,7 +40,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||
#include <ftoastr.h>
|
||||
#include <math.h>
|
||||
|
||||
#if HAVE_IEEE754_H
|
||||
#if IEEE_FLOATING_POINT
|
||||
# include <ieee754.h>
|
||||
#endif
|
||||
|
||||
|
@ -1013,34 +1013,15 @@ float_to_string (char *buf, double data)
|
|||
strcpy (buf, minus_infinity_string + positive);
|
||||
return sizeof minus_infinity_string - 1 - positive;
|
||||
}
|
||||
#if IEEE_FLOATING_POINT
|
||||
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";
|
||||
int i;
|
||||
union { double d; char c[sizeof (double)]; } u_data, u_minus_zero;
|
||||
bool negative = 0;
|
||||
u_data.d = data;
|
||||
u_minus_zero.d = - 0.0;
|
||||
for (i = 0; i < sizeof (double); i++)
|
||||
if (u_data.c[i] & u_minus_zero.c[i])
|
||||
{
|
||||
*buf = '-';
|
||||
negative = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
strcpy (buf + negative, NaN_string);
|
||||
return negative + sizeof NaN_string - 1;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
if (NILP (Vfloat_output_format)
|
||||
|| !STRINGP (Vfloat_output_format))
|
||||
|
|
Loading…
Add table
Reference in a new issue