diff options
| author | Paul Eggert | 2018-08-01 18:53:31 -0700 |
|---|---|---|
| committer | Paul Eggert | 2018-08-01 19:01:51 -0700 |
| commit | d216d7d248199aa6c99cd642116717c5b301ae6d (patch) | |
| tree | 687b9efadbb87fa1095fb0a2e0569e625856e15a /src | |
| parent | 2f37ecaefcc61b0bf389f1c1eb3ac1b15105f056 (diff) | |
| download | emacs-d216d7d248199aa6c99cd642116717c5b301ae6d.tar.gz emacs-d216d7d248199aa6c99cd642116717c5b301ae6d.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lisp.h | 11 | ||||
| -rw-r--r-- | src/lread.c | 9 | ||||
| -rw-r--r-- | src/print.c | 25 |
3 files changed, 10 insertions, 35 deletions
diff --git a/src/lisp.h b/src/lisp.h index 96de60e4670..bdece817bd6 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -2670,17 +2670,14 @@ XFLOAT_DATA (Lisp_Object f) | |||
| 2670 | 2670 | ||
| 2671 | /* Most hosts nowadays use IEEE floating point, so they use IEC 60559 | 2671 | /* Most hosts nowadays use IEEE floating point, so they use IEC 60559 |
| 2672 | representations, have infinities and NaNs, and do not trap on | 2672 | representations, have infinities and NaNs, and do not trap on |
| 2673 | exceptions. Define IEEE_FLOATING_POINT if this host is one of the | 2673 | exceptions. Define IEEE_FLOATING_POINT to 1 if this host is one of the |
| 2674 | typical ones. The C11 macro __STDC_IEC_559__ is close to what is | 2674 | typical ones. The C11 macro __STDC_IEC_559__ is close to what is |
| 2675 | wanted here, but is not quite right because Emacs does not require | 2675 | wanted here, but is not quite right because Emacs does not require |
| 2676 | all the features of C11 Annex F (and does not require C11 at all, | 2676 | all the features of C11 Annex F (and does not require C11 at all, |
| 2677 | for that matter). */ | 2677 | for that matter). */ |
| 2678 | enum | 2678 | |
| 2679 | { | 2679 | #define IEEE_FLOATING_POINT (FLT_RADIX == 2 && FLT_MANT_DIG == 24 \ |
| 2680 | IEEE_FLOATING_POINT | 2680 | && FLT_MIN_EXP == -125 && FLT_MAX_EXP == 128) |
| 2681 | = (FLT_RADIX == 2 && FLT_MANT_DIG == 24 | ||
| 2682 | && FLT_MIN_EXP == -125 && FLT_MAX_EXP == 128) | ||
| 2683 | }; | ||
| 2684 | 2681 | ||
| 2685 | /* A character, declared with the following typedef, is a member | 2682 | /* A character, declared with the following typedef, is a member |
| 2686 | of some character set associated with the current buffer. */ | 2683 | of some character set associated with the current buffer. */ |
diff --git a/src/lread.c b/src/lread.c index 290b0f6bbe9..9a025d8664d 100644 --- a/src/lread.c +++ b/src/lread.c | |||
| @@ -72,7 +72,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 72 | #define file_tell ftell | 72 | #define file_tell ftell |
| 73 | #endif | 73 | #endif |
| 74 | 74 | ||
| 75 | #if HAVE_IEEE754_H | 75 | #if IEEE_FLOATING_POINT |
| 76 | # include <ieee754.h> | 76 | # include <ieee754.h> |
| 77 | #endif | 77 | #endif |
| 78 | 78 | ||
| @@ -3756,21 +3756,18 @@ string_to_number (char const *string, int base, int flags) | |||
| 3756 | cp += 3; | 3756 | cp += 3; |
| 3757 | value = INFINITY; | 3757 | value = INFINITY; |
| 3758 | } | 3758 | } |
| 3759 | #if IEEE_FLOATING_POINT | ||
| 3759 | else if (cp[-1] == '+' | 3760 | else if (cp[-1] == '+' |
| 3760 | && cp[0] == 'N' && cp[1] == 'a' && cp[2] == 'N') | 3761 | && cp[0] == 'N' && cp[1] == 'a' && cp[2] == 'N') |
| 3761 | { | 3762 | { |
| 3762 | state |= E_EXP; | 3763 | state |= E_EXP; |
| 3763 | cp += 3; | 3764 | cp += 3; |
| 3764 | #if HAVE_IEEE754_H | ||
| 3765 | union ieee754_double u | 3765 | union ieee754_double u |
| 3766 | = { .ieee_nan = { .exponent = -1, .quiet_nan = 1, | 3766 | = { .ieee_nan = { .exponent = -1, .quiet_nan = 1, |
| 3767 | .mantissa0 = n >> 31 >> 1, .mantissa1 = n }}; | 3767 | .mantissa0 = n >> 31 >> 1, .mantissa1 = n }}; |
| 3768 | value = u.d; | 3768 | value = u.d; |
| 3769 | #else | ||
| 3770 | /* NAN is a "positive" NaN on all known Emacs hosts. */ | ||
| 3771 | value = NAN; | ||
| 3772 | #endif | ||
| 3773 | } | 3769 | } |
| 3770 | #endif | ||
| 3774 | else | 3771 | else |
| 3775 | cp = ecp; | 3772 | cp = ecp; |
| 3776 | } | 3773 | } |
diff --git a/src/print.c b/src/print.c index add21609cc5..34c7fa12b6e 100644 --- a/src/print.c +++ b/src/print.c | |||
| @@ -40,7 +40,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 40 | #include <ftoastr.h> | 40 | #include <ftoastr.h> |
| 41 | #include <math.h> | 41 | #include <math.h> |
| 42 | 42 | ||
| 43 | #if HAVE_IEEE754_H | 43 | #if IEEE_FLOATING_POINT |
| 44 | # include <ieee754.h> | 44 | # include <ieee754.h> |
| 45 | #endif | 45 | #endif |
| 46 | 46 | ||
| @@ -1013,34 +1013,15 @@ float_to_string (char *buf, double data) | |||
| 1013 | strcpy (buf, minus_infinity_string + positive); | 1013 | strcpy (buf, minus_infinity_string + positive); |
| 1014 | return sizeof minus_infinity_string - 1 - positive; | 1014 | return sizeof minus_infinity_string - 1 - positive; |
| 1015 | } | 1015 | } |
| 1016 | #if IEEE_FLOATING_POINT | ||
| 1016 | if (isnan (data)) | 1017 | if (isnan (data)) |
| 1017 | { | 1018 | { |
| 1018 | #if HAVE_IEEE754_H | ||
| 1019 | union ieee754_double u = { .d = data }; | 1019 | union ieee754_double u = { .d = data }; |
| 1020 | uprintmax_t hi = u.ieee_nan.mantissa0; | 1020 | uprintmax_t hi = u.ieee_nan.mantissa0; |
| 1021 | return sprintf (buf, &"-%"pMu".0e+NaN"[!u.ieee_nan.negative], | 1021 | return sprintf (buf, &"-%"pMu".0e+NaN"[!u.ieee_nan.negative], |
| 1022 | (hi << 31 << 1) + u.ieee_nan.mantissa1); | 1022 | (hi << 31 << 1) + u.ieee_nan.mantissa1); |
| 1023 | #else | ||
| 1024 | /* Prepend "-" if the NaN's sign bit is negative. | ||
| 1025 | The sign bit of a double is the bit that is 1 in -0.0. */ | ||
| 1026 | static char const NaN_string[] = "0.0e+NaN"; | ||
| 1027 | int i; | ||
| 1028 | union { double d; char c[sizeof (double)]; } u_data, u_minus_zero; | ||
| 1029 | bool negative = 0; | ||
| 1030 | u_data.d = data; | ||
| 1031 | u_minus_zero.d = - 0.0; | ||
| 1032 | for (i = 0; i < sizeof (double); i++) | ||
| 1033 | if (u_data.c[i] & u_minus_zero.c[i]) | ||
| 1034 | { | ||
| 1035 | *buf = '-'; | ||
| 1036 | negative = 1; | ||
| 1037 | break; | ||
| 1038 | } | ||
| 1039 | |||
| 1040 | strcpy (buf + negative, NaN_string); | ||
| 1041 | return negative + sizeof NaN_string - 1; | ||
| 1042 | #endif | ||
| 1043 | } | 1023 | } |
| 1024 | #endif | ||
| 1044 | 1025 | ||
| 1045 | if (NILP (Vfloat_output_format) | 1026 | if (NILP (Vfloat_output_format) |
| 1046 | || !STRINGP (Vfloat_output_format)) | 1027 | || !STRINGP (Vfloat_output_format)) |