diff options
| author | Paul Eggert | 2018-08-27 21:27:50 -0700 |
|---|---|---|
| committer | Paul Eggert | 2018-08-27 21:45:22 -0700 |
| commit | 9abaf5f3581ecb76f30e8a6e7ee0e9633c133d1c (patch) | |
| tree | c39260a6e26845b0a1307be98b38581468925c58 /src | |
| parent | bf1b147b55e1328efca6e40181e79dd9a369895d (diff) | |
| download | emacs-9abaf5f3581ecb76f30e8a6e7ee0e9633c133d1c.tar.gz emacs-9abaf5f3581ecb76f30e8a6e7ee0e9633c133d1c.zip | |
Modularize bignums better
* src/bignum.c, src/bignum.h: New files. Only modules that
need to know how bignums are implemented should include
bignum.h. Currently these are alloc.c, bignum.c (of course),
data.c, emacs.c, emacs-module.c, floatfns.c, fns.c, print.c.
* src/Makefile.in (base_obj): Add bignum.o.
* src/alloc.c (make_bignum_str): Move to bignum.c.
(make_number): Remove; replaced by bignum.c’s make_integer.
All callers changed.
* src/conf_post.h (ARG_NONNULL): New macro.
* src/json.c (json_to_lisp): Use it.
* src/data.c (Fnatnump):
Move NATNUMP’s implementation here from lisp.h.
* src/data.c (Fnumber_to_string):
* src/editfns.c (styled_format):
Move conversion of string to bignum to bignum_to_string, and
call it here.
* src/emacs-module.c (module_make_integer):
* src/floatfns.c (Fabs):
Simplify by using make_int.
* src/emacs.c: Include bignum.h, to expand its inline fns.
* src/floatfns.c (Ffloat): Simplify by using XFLOATINT.
(rounding_driver): Simplify by using double_to_bignum.
(rounddiv_q): Clarify use of temporaries.
* src/lisp.h: Move decls that need to know bignum internals to
bignum.h. Do not include gmp.h or mini-gmp.h; that is now
bignum.h’s job.
(GMP_NUM_BITS, struct Lisp_Bignum, XBIGNUM, mpz_set_intmax):
Move to bignum.h.
(make_int): New function.
(NATNUMP): Remove; all callers changed to use Fnatnump.
(XFLOATINT): If arg is a bignum, use bignum_to_double, so that
bignum internals are not exposed here.
* src/print.c (print_vectorlike): Use SAFE_ALLOCA to avoid the
need for a record_unwind_protect_ptr.
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile.in | 2 | ||||
| -rw-r--r-- | src/alloc.c | 78 | ||||
| -rw-r--r-- | src/bignum.c | 161 | ||||
| -rw-r--r-- | src/bignum.h | 70 | ||||
| -rw-r--r-- | src/conf_post.h | 1 | ||||
| -rw-r--r-- | src/data.c | 38 | ||||
| -rw-r--r-- | src/editfns.c | 4 | ||||
| -rw-r--r-- | src/emacs-module.c | 16 | ||||
| -rw-r--r-- | src/emacs.c | 1 | ||||
| -rw-r--r-- | src/floatfns.c | 50 | ||||
| -rw-r--r-- | src/fns.c | 1 | ||||
| -rw-r--r-- | src/json.c | 2 | ||||
| -rw-r--r-- | src/lisp.h | 72 | ||||
| -rw-r--r-- | src/print.c | 9 |
14 files changed, 299 insertions, 206 deletions
diff --git a/src/Makefile.in b/src/Makefile.in index 52ce7605f7b..7d9c2361a9b 100644 --- a/src/Makefile.in +++ b/src/Makefile.in | |||
| @@ -392,7 +392,7 @@ base_obj = dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \ | |||
| 392 | charset.o coding.o category.o ccl.o character.o chartab.o bidi.o \ | 392 | charset.o coding.o category.o ccl.o character.o chartab.o bidi.o \ |
| 393 | $(CM_OBJ) term.o terminal.o xfaces.o $(XOBJ) $(GTK_OBJ) $(DBUS_OBJ) \ | 393 | $(CM_OBJ) term.o terminal.o xfaces.o $(XOBJ) $(GTK_OBJ) $(DBUS_OBJ) \ |
| 394 | emacs.o keyboard.o macros.o keymap.o sysdep.o \ | 394 | emacs.o keyboard.o macros.o keymap.o sysdep.o \ |
| 395 | buffer.o filelock.o insdel.o marker.o \ | 395 | bignum.o buffer.o filelock.o insdel.o marker.o \ |
| 396 | minibuf.o fileio.o dired.o \ | 396 | minibuf.o fileio.o dired.o \ |
| 397 | cmds.o casetab.o casefiddle.o indent.o search.o regex-emacs.o undo.o \ | 397 | cmds.o casetab.o casefiddle.o indent.o search.o regex-emacs.o undo.o \ |
| 398 | alloc.o data.o doc.o editfns.o callint.o \ | 398 | alloc.o data.o doc.o editfns.o callint.o \ |
diff --git a/src/alloc.c b/src/alloc.c index c9788ab4c6b..350b668ec61 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -31,6 +31,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 31 | #endif | 31 | #endif |
| 32 | 32 | ||
| 33 | #include "lisp.h" | 33 | #include "lisp.h" |
| 34 | #include "bignum.h" | ||
| 34 | #include "dispextern.h" | 35 | #include "dispextern.h" |
| 35 | #include "intervals.h" | 36 | #include "intervals.h" |
| 36 | #include "ptr-bounds.h" | 37 | #include "ptr-bounds.h" |
| @@ -3728,83 +3729,6 @@ build_marker (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t bytepos) | |||
| 3728 | } | 3729 | } |
| 3729 | 3730 | ||
| 3730 | 3731 | ||
| 3731 | |||
| 3732 | Lisp_Object | ||
| 3733 | make_bignum_str (const char *num, int base) | ||
| 3734 | { | ||
| 3735 | struct Lisp_Bignum *b = ALLOCATE_PSEUDOVECTOR (struct Lisp_Bignum, value, | ||
| 3736 | PVEC_BIGNUM); | ||
| 3737 | mpz_init (b->value); | ||
| 3738 | int check = mpz_set_str (b->value, num, base); | ||
| 3739 | eassert (check == 0); | ||
| 3740 | return make_lisp_ptr (b, Lisp_Vectorlike); | ||
| 3741 | } | ||
| 3742 | |||
| 3743 | /* Given an mpz_t, make a number. This may return a bignum or a | ||
| 3744 | fixnum depending on VALUE. */ | ||
| 3745 | |||
| 3746 | Lisp_Object | ||
| 3747 | make_number (mpz_t value) | ||
| 3748 | { | ||
| 3749 | size_t bits = mpz_sizeinbase (value, 2); | ||
| 3750 | |||
| 3751 | if (bits <= FIXNUM_BITS) | ||
| 3752 | { | ||
| 3753 | EMACS_INT v = 0; | ||
| 3754 | int i = 0, shift = 0; | ||
| 3755 | |||
| 3756 | do | ||
| 3757 | { | ||
| 3758 | EMACS_INT limb = mpz_getlimbn (value, i++); | ||
| 3759 | v += limb << shift; | ||
| 3760 | shift += GMP_NUMB_BITS; | ||
| 3761 | } | ||
| 3762 | while (shift < bits); | ||
| 3763 | |||
| 3764 | if (mpz_sgn (value) < 0) | ||
| 3765 | v = -v; | ||
| 3766 | |||
| 3767 | if (!FIXNUM_OVERFLOW_P (v)) | ||
| 3768 | return make_fixnum (v); | ||
| 3769 | } | ||
| 3770 | |||
| 3771 | /* The documentation says integer-width should be nonnegative, so | ||
| 3772 | a single comparison suffices even though 'bits' is unsigned. */ | ||
| 3773 | if (integer_width < bits) | ||
| 3774 | range_error (); | ||
| 3775 | |||
| 3776 | struct Lisp_Bignum *b = ALLOCATE_PSEUDOVECTOR (struct Lisp_Bignum, value, | ||
| 3777 | PVEC_BIGNUM); | ||
| 3778 | /* We could mpz_init + mpz_swap here, to avoid a copy, but the | ||
| 3779 | resulting API seemed possibly confusing. */ | ||
| 3780 | mpz_init_set (b->value, value); | ||
| 3781 | |||
| 3782 | return make_lisp_ptr (b, Lisp_Vectorlike); | ||
| 3783 | } | ||
| 3784 | |||
| 3785 | void | ||
| 3786 | mpz_set_intmax_slow (mpz_t result, intmax_t v) | ||
| 3787 | { | ||
| 3788 | /* If V fits in long, a faster path is taken. */ | ||
| 3789 | eassert (! (LONG_MIN <= v && v <= LONG_MAX)); | ||
| 3790 | |||
| 3791 | bool complement = v < 0; | ||
| 3792 | if (complement) | ||
| 3793 | v = -1 - v; | ||
| 3794 | |||
| 3795 | enum { nails = sizeof v * CHAR_BIT - INTMAX_WIDTH }; | ||
| 3796 | # ifndef HAVE_GMP | ||
| 3797 | /* mini-gmp requires NAILS to be zero, which is true for all | ||
| 3798 | likely Emacs platforms. Sanity-check this. */ | ||
| 3799 | verify (nails == 0); | ||
| 3800 | # endif | ||
| 3801 | |||
| 3802 | mpz_import (result, 1, -1, sizeof v, 0, nails, &v); | ||
| 3803 | if (complement) | ||
| 3804 | mpz_com (result, result); | ||
| 3805 | } | ||
| 3806 | |||
| 3807 | |||
| 3808 | /* Return a newly created vector or string with specified arguments as | 3732 | /* Return a newly created vector or string with specified arguments as |
| 3809 | elements. If all the arguments are characters that can fit | 3733 | elements. If all the arguments are characters that can fit |
| 3810 | in a string of events, make a string; otherwise, make a vector. | 3734 | in a string of events, make a string; otherwise, make a vector. |
diff --git a/src/bignum.c b/src/bignum.c new file mode 100644 index 00000000000..18f94e7ed63 --- /dev/null +++ b/src/bignum.c | |||
| @@ -0,0 +1,161 @@ | |||
| 1 | /* Big numbers for Emacs. | ||
| 2 | |||
| 3 | Copyright 2018 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | This file is part of GNU Emacs. | ||
| 6 | |||
| 7 | GNU Emacs is free software: you can redistribute it and/or modify | ||
| 8 | it under the terms of the GNU General Public License as published by | ||
| 9 | the Free Software Foundation, either version 3 of the License, or (at | ||
| 10 | your option) any later version. | ||
| 11 | |||
| 12 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | GNU General Public License for more details. | ||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License | ||
| 18 | along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | ||
| 19 | |||
| 20 | #include <config.h> | ||
| 21 | |||
| 22 | #include "bignum.h" | ||
| 23 | |||
| 24 | #include "lisp.h" | ||
| 25 | |||
| 26 | /* Return the value of the Lisp bignum N, as a double. */ | ||
| 27 | double | ||
| 28 | bignum_to_double (Lisp_Object n) | ||
| 29 | { | ||
| 30 | return mpz_get_d (XBIGNUM (n)->value); | ||
| 31 | } | ||
| 32 | |||
| 33 | /* Return D, converted to a bignum. Discard any fraction. */ | ||
| 34 | Lisp_Object | ||
| 35 | double_to_bignum (double d) | ||
| 36 | { | ||
| 37 | mpz_t z; | ||
| 38 | mpz_init_set_d (z, d); | ||
| 39 | Lisp_Object result = make_integer (z); | ||
| 40 | mpz_clear (z); | ||
| 41 | return result; | ||
| 42 | } | ||
| 43 | |||
| 44 | /* Return a Lisp integer equal to OP, which has BITS bits and which | ||
| 45 | must not be in fixnum range. */ | ||
| 46 | static Lisp_Object | ||
| 47 | make_bignum_bits (mpz_t const op, size_t bits) | ||
| 48 | { | ||
| 49 | /* The documentation says integer-width should be nonnegative, so | ||
| 50 | a single comparison suffices even though 'bits' is unsigned. */ | ||
| 51 | if (integer_width < bits) | ||
| 52 | range_error (); | ||
| 53 | |||
| 54 | struct Lisp_Bignum *b = ALLOCATE_PSEUDOVECTOR (struct Lisp_Bignum, value, | ||
| 55 | PVEC_BIGNUM); | ||
| 56 | /* We could mpz_init + mpz_swap here, to avoid a copy, but the | ||
| 57 | resulting API seemed possibly confusing. */ | ||
| 58 | mpz_init_set (b->value, op); | ||
| 59 | |||
| 60 | return make_lisp_ptr (b, Lisp_Vectorlike); | ||
| 61 | } | ||
| 62 | |||
| 63 | /* Return a Lisp integer equal to OP, which must not be in fixnum range. */ | ||
| 64 | static Lisp_Object | ||
| 65 | make_bignum (mpz_t const op) | ||
| 66 | { | ||
| 67 | return make_bignum_bits (op, mpz_sizeinbase (op, 2)); | ||
| 68 | } | ||
| 69 | |||
| 70 | /* Return a Lisp integer equal to N, which must not be in fixnum range. */ | ||
| 71 | Lisp_Object | ||
| 72 | make_bigint (intmax_t n) | ||
| 73 | { | ||
| 74 | eassert (FIXNUM_OVERFLOW_P (n)); | ||
| 75 | mpz_t z; | ||
| 76 | mpz_init (z); | ||
| 77 | mpz_set_intmax (z, n); | ||
| 78 | Lisp_Object result = make_bignum (z); | ||
| 79 | mpz_clear (z); | ||
| 80 | return result; | ||
| 81 | } | ||
| 82 | |||
| 83 | /* Return a Lisp integer with value taken from OP. */ | ||
| 84 | Lisp_Object | ||
| 85 | make_integer (mpz_t const op) | ||
| 86 | { | ||
| 87 | size_t bits = mpz_sizeinbase (op, 2); | ||
| 88 | |||
| 89 | if (bits <= FIXNUM_BITS) | ||
| 90 | { | ||
| 91 | EMACS_INT v = 0; | ||
| 92 | int i = 0, shift = 0; | ||
| 93 | |||
| 94 | do | ||
| 95 | { | ||
| 96 | EMACS_INT limb = mpz_getlimbn (op, i++); | ||
| 97 | v += limb << shift; | ||
| 98 | shift += GMP_NUMB_BITS; | ||
| 99 | } | ||
| 100 | while (shift < bits); | ||
| 101 | |||
| 102 | if (mpz_sgn (op) < 0) | ||
| 103 | v = -v; | ||
| 104 | |||
| 105 | if (!FIXNUM_OVERFLOW_P (v)) | ||
| 106 | return make_fixnum (v); | ||
| 107 | } | ||
| 108 | |||
| 109 | return make_bignum_bits (op, bits); | ||
| 110 | } | ||
| 111 | |||
| 112 | void | ||
| 113 | mpz_set_intmax_slow (mpz_t result, intmax_t v) | ||
| 114 | { | ||
| 115 | bool complement = v < 0; | ||
| 116 | if (complement) | ||
| 117 | v = -1 - v; | ||
| 118 | |||
| 119 | enum { nails = sizeof v * CHAR_BIT - INTMAX_WIDTH }; | ||
| 120 | # ifndef HAVE_GMP | ||
| 121 | /* mini-gmp requires NAILS to be zero, which is true for all | ||
| 122 | likely Emacs platforms. Sanity-check this. */ | ||
| 123 | verify (nails == 0); | ||
| 124 | # endif | ||
| 125 | |||
| 126 | mpz_import (result, 1, -1, sizeof v, 0, nails, &v); | ||
| 127 | if (complement) | ||
| 128 | mpz_com (result, result); | ||
| 129 | } | ||
| 130 | |||
| 131 | /* Convert NUM to a base-BASE Lisp string. */ | ||
| 132 | |||
| 133 | Lisp_Object | ||
| 134 | bignum_to_string (Lisp_Object num, int base) | ||
| 135 | { | ||
| 136 | ptrdiff_t n = mpz_sizeinbase (XBIGNUM (num)->value, base) - 1; | ||
| 137 | USE_SAFE_ALLOCA; | ||
| 138 | char *str = SAFE_ALLOCA (n + 3); | ||
| 139 | mpz_get_str (str, base, XBIGNUM (num)->value); | ||
| 140 | while (str[n]) | ||
| 141 | n++; | ||
| 142 | Lisp_Object result = make_unibyte_string (str, n); | ||
| 143 | SAFE_FREE (); | ||
| 144 | return result; | ||
| 145 | } | ||
| 146 | |||
| 147 | /* Create a bignum by scanning NUM, with digits in BASE. | ||
| 148 | NUM must consist of an optional '-', a nonempty sequence | ||
| 149 | of base-BASE digits, and a terminating null byte, and | ||
| 150 | the represented number must not be in fixnum range. */ | ||
| 151 | |||
| 152 | Lisp_Object | ||
| 153 | make_bignum_str (char const *num, int base) | ||
| 154 | { | ||
| 155 | struct Lisp_Bignum *b = ALLOCATE_PSEUDOVECTOR (struct Lisp_Bignum, value, | ||
| 156 | PVEC_BIGNUM); | ||
| 157 | mpz_init (b->value); | ||
| 158 | int check = mpz_set_str (b->value, num, base); | ||
| 159 | eassert (check == 0); | ||
| 160 | return make_lisp_ptr (b, Lisp_Vectorlike); | ||
| 161 | } | ||
diff --git a/src/bignum.h b/src/bignum.h new file mode 100644 index 00000000000..a368333d77e --- /dev/null +++ b/src/bignum.h | |||
| @@ -0,0 +1,70 @@ | |||
| 1 | /* Big numbers for Emacs. | ||
| 2 | |||
| 3 | Copyright 2018 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | This file is part of GNU Emacs. | ||
| 6 | |||
| 7 | GNU Emacs is free software: you can redistribute it and/or modify | ||
| 8 | it under the terms of the GNU General Public License as published by | ||
| 9 | the Free Software Foundation, either version 3 of the License, or (at | ||
| 10 | your option) any later version. | ||
| 11 | |||
| 12 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | GNU General Public License for more details. | ||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License | ||
| 18 | along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | ||
| 19 | |||
| 20 | /* Include this header only if access to bignum internals is needed. */ | ||
| 21 | |||
| 22 | #ifndef BIGNUM_H | ||
| 23 | #define BIGNUM_H | ||
| 24 | |||
| 25 | #ifdef HAVE_GMP | ||
| 26 | # include <gmp.h> | ||
| 27 | #else | ||
| 28 | # include "mini-gmp.h" | ||
| 29 | #endif | ||
| 30 | |||
| 31 | #include "lisp.h" | ||
| 32 | |||
| 33 | /* Number of data bits in a limb. */ | ||
| 34 | #ifndef GMP_NUMB_BITS | ||
| 35 | enum { GMP_NUMB_BITS = TYPE_WIDTH (mp_limb_t) }; | ||
| 36 | #endif | ||
| 37 | |||
| 38 | struct Lisp_Bignum | ||
| 39 | { | ||
| 40 | union vectorlike_header header; | ||
| 41 | mpz_t value; | ||
| 42 | }; | ||
| 43 | |||
| 44 | extern Lisp_Object make_integer (mpz_t const) ARG_NONNULL ((1)); | ||
| 45 | extern void mpz_set_intmax_slow (mpz_t, intmax_t) ARG_NONNULL ((1)); | ||
| 46 | |||
| 47 | INLINE_HEADER_BEGIN | ||
| 48 | |||
| 49 | INLINE struct Lisp_Bignum * | ||
| 50 | XBIGNUM (Lisp_Object a) | ||
| 51 | { | ||
| 52 | eassert (BIGNUMP (a)); | ||
| 53 | return XUNTAG (a, Lisp_Vectorlike, struct Lisp_Bignum); | ||
| 54 | } | ||
| 55 | |||
| 56 | INLINE void ARG_NONNULL ((1)) | ||
| 57 | mpz_set_intmax (mpz_t result, intmax_t v) | ||
| 58 | { | ||
| 59 | /* mpz_set_si works in terms of long, but Emacs may use a wider | ||
| 60 | integer type, and so sometimes will have to construct the mpz_t | ||
| 61 | by hand. */ | ||
| 62 | if (LONG_MIN <= v && v <= LONG_MAX) | ||
| 63 | mpz_set_si (result, v); | ||
| 64 | else | ||
| 65 | mpz_set_intmax_slow (result, v); | ||
| 66 | } | ||
| 67 | |||
| 68 | INLINE_HEADER_END | ||
| 69 | |||
| 70 | #endif /* BIGNUM_H */ | ||
diff --git a/src/conf_post.h b/src/conf_post.h index f9838bc662a..683a96f9368 100644 --- a/src/conf_post.h +++ b/src/conf_post.h | |||
| @@ -277,6 +277,7 @@ extern int emacs_setenv_TZ (char const *); | |||
| 277 | #define ATTRIBUTE_FORMAT_PRINTF(string_index, first_to_check) \ | 277 | #define ATTRIBUTE_FORMAT_PRINTF(string_index, first_to_check) \ |
| 278 | ATTRIBUTE_FORMAT ((PRINTF_ARCHETYPE, string_index, first_to_check)) | 278 | ATTRIBUTE_FORMAT ((PRINTF_ARCHETYPE, string_index, first_to_check)) |
| 279 | 279 | ||
| 280 | #define ARG_NONNULL _GL_ARG_NONNULL | ||
| 280 | #define ATTRIBUTE_CONST _GL_ATTRIBUTE_CONST | 281 | #define ATTRIBUTE_CONST _GL_ATTRIBUTE_CONST |
| 281 | #define ATTRIBUTE_UNUSED _GL_UNUSED | 282 | #define ATTRIBUTE_UNUSED _GL_UNUSED |
| 282 | 283 | ||
diff --git a/src/data.c b/src/data.c index 170a74a6589..ece76a5bc6f 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -29,6 +29,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 29 | #include <intprops.h> | 29 | #include <intprops.h> |
| 30 | 30 | ||
| 31 | #include "lisp.h" | 31 | #include "lisp.h" |
| 32 | #include "bignum.h" | ||
| 32 | #include "puresize.h" | 33 | #include "puresize.h" |
| 33 | #include "character.h" | 34 | #include "character.h" |
| 34 | #include "buffer.h" | 35 | #include "buffer.h" |
| @@ -525,9 +526,9 @@ DEFUN ("natnump", Fnatnump, Snatnump, 1, 1, 0, | |||
| 525 | attributes: const) | 526 | attributes: const) |
| 526 | (Lisp_Object object) | 527 | (Lisp_Object object) |
| 527 | { | 528 | { |
| 528 | if (NATNUMP (object)) | 529 | return ((FIXNUMP (object) ? 0 <= XFIXNUM (object) |
| 529 | return Qt; | 530 | : BIGNUMP (object) && 0 <= mpz_sgn (XBIGNUM (object)->value)) |
| 530 | return Qnil; | 531 | ? Qt : Qnil); |
| 531 | } | 532 | } |
| 532 | 533 | ||
| 533 | DEFUN ("numberp", Fnumberp, Snumberp, 1, 1, 0, | 534 | DEFUN ("numberp", Fnumberp, Snumberp, 1, 1, 0, |
| @@ -2400,7 +2401,7 @@ emacs_mpz_size (mpz_t const op) | |||
| 2400 | the library code aborts when a number is too large. These wrappers | 2401 | the library code aborts when a number is too large. These wrappers |
| 2401 | avoid the problem for functions that can return numbers much larger | 2402 | avoid the problem for functions that can return numbers much larger |
| 2402 | than their arguments. For slowly-growing numbers, the integer | 2403 | than their arguments. For slowly-growing numbers, the integer |
| 2403 | width check in make_number should suffice. */ | 2404 | width checks in bignum.c should suffice. */ |
| 2404 | 2405 | ||
| 2405 | static void | 2406 | static void |
| 2406 | emacs_mpz_mul (mpz_t rop, mpz_t const op1, mpz_t const op2) | 2407 | emacs_mpz_mul (mpz_t rop, mpz_t const op1, mpz_t const op2) |
| @@ -2770,12 +2771,7 @@ NUMBER may be an integer or a floating point number. */) | |||
| 2770 | int len; | 2771 | int len; |
| 2771 | 2772 | ||
| 2772 | if (BIGNUMP (number)) | 2773 | if (BIGNUMP (number)) |
| 2773 | { | 2774 | return bignum_to_string (number, 10); |
| 2774 | ptrdiff_t count = SPECPDL_INDEX (); | ||
| 2775 | char *str = mpz_get_str (NULL, 10, XBIGNUM (number)->value); | ||
| 2776 | record_unwind_protect_ptr (xfree, str); | ||
| 2777 | return unbind_to (count, make_unibyte_string (str, strlen (str))); | ||
| 2778 | } | ||
| 2779 | 2775 | ||
| 2780 | CHECK_FIXNUM_OR_FLOAT (number); | 2776 | CHECK_FIXNUM_OR_FLOAT (number); |
| 2781 | 2777 | ||
| @@ -3011,7 +3007,7 @@ arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args) | |||
| 3011 | } | 3007 | } |
| 3012 | } | 3008 | } |
| 3013 | 3009 | ||
| 3014 | return unbind_to (count, make_number (accum)); | 3010 | return unbind_to (count, make_integer (accum)); |
| 3015 | } | 3011 | } |
| 3016 | 3012 | ||
| 3017 | static Lisp_Object | 3013 | static Lisp_Object |
| @@ -3141,7 +3137,7 @@ Both must be integers or markers. */) | |||
| 3141 | 3137 | ||
| 3142 | mpz_init (result); | 3138 | mpz_init (result); |
| 3143 | mpz_tdiv_r (result, *xmp, *ymp); | 3139 | mpz_tdiv_r (result, *xmp, *ymp); |
| 3144 | val = make_number (result); | 3140 | val = make_integer (result); |
| 3145 | mpz_clear (result); | 3141 | mpz_clear (result); |
| 3146 | 3142 | ||
| 3147 | if (xmp == &xm) | 3143 | if (xmp == &xm) |
| @@ -3221,7 +3217,7 @@ Both X and Y must be numbers or markers. */) | |||
| 3221 | if (cmpy < 0 ? cmpr > 0 : cmpr < 0) | 3217 | if (cmpy < 0 ? cmpr > 0 : cmpr < 0) |
| 3222 | mpz_add (result, result, *ymp); | 3218 | mpz_add (result, result, *ymp); |
| 3223 | 3219 | ||
| 3224 | val = make_number (result); | 3220 | val = make_integer (result); |
| 3225 | mpz_clear (result); | 3221 | mpz_clear (result); |
| 3226 | 3222 | ||
| 3227 | if (xmp == &xm) | 3223 | if (xmp == &xm) |
| @@ -3351,7 +3347,7 @@ In this case, the sign bit is duplicated. */) | |||
| 3351 | emacs_mpz_mul_2exp (result, XBIGNUM (value)->value, XFIXNUM (count)); | 3347 | emacs_mpz_mul_2exp (result, XBIGNUM (value)->value, XFIXNUM (count)); |
| 3352 | else | 3348 | else |
| 3353 | mpz_fdiv_q_2exp (result, XBIGNUM (value)->value, - XFIXNUM (count)); | 3349 | mpz_fdiv_q_2exp (result, XBIGNUM (value)->value, - XFIXNUM (count)); |
| 3354 | val = make_number (result); | 3350 | val = make_integer (result); |
| 3355 | mpz_clear (result); | 3351 | mpz_clear (result); |
| 3356 | } | 3352 | } |
| 3357 | else if (XFIXNUM (count) <= 0) | 3353 | else if (XFIXNUM (count) <= 0) |
| @@ -3378,7 +3374,7 @@ In this case, the sign bit is duplicated. */) | |||
| 3378 | else | 3374 | else |
| 3379 | mpz_fdiv_q_2exp (result, result, - XFIXNUM (count)); | 3375 | mpz_fdiv_q_2exp (result, result, - XFIXNUM (count)); |
| 3380 | 3376 | ||
| 3381 | val = make_number (result); | 3377 | val = make_integer (result); |
| 3382 | mpz_clear (result); | 3378 | mpz_clear (result); |
| 3383 | } | 3379 | } |
| 3384 | 3380 | ||
| @@ -3407,7 +3403,7 @@ expt_integer (Lisp_Object x, Lisp_Object y) | |||
| 3407 | ? (mpz_set_intmax (val, XFIXNUM (x)), val) | 3403 | ? (mpz_set_intmax (val, XFIXNUM (x)), val) |
| 3408 | : XBIGNUM (x)->value), | 3404 | : XBIGNUM (x)->value), |
| 3409 | exp); | 3405 | exp); |
| 3410 | Lisp_Object res = make_number (val); | 3406 | Lisp_Object res = make_integer (val); |
| 3411 | mpz_clear (val); | 3407 | mpz_clear (val); |
| 3412 | return res; | 3408 | return res; |
| 3413 | } | 3409 | } |
| @@ -3427,7 +3423,7 @@ Markers are converted to integers. */) | |||
| 3427 | mpz_t num; | 3423 | mpz_t num; |
| 3428 | mpz_init (num); | 3424 | mpz_init (num); |
| 3429 | mpz_add_ui (num, XBIGNUM (number)->value, 1); | 3425 | mpz_add_ui (num, XBIGNUM (number)->value, 1); |
| 3430 | number = make_number (num); | 3426 | number = make_integer (num); |
| 3431 | mpz_clear (num); | 3427 | mpz_clear (num); |
| 3432 | } | 3428 | } |
| 3433 | else | 3429 | else |
| @@ -3440,7 +3436,7 @@ Markers are converted to integers. */) | |||
| 3440 | mpz_t num; | 3436 | mpz_t num; |
| 3441 | mpz_init (num); | 3437 | mpz_init (num); |
| 3442 | mpz_set_intmax (num, XFIXNUM (number) + 1); | 3438 | mpz_set_intmax (num, XFIXNUM (number) + 1); |
| 3443 | number = make_number (num); | 3439 | number = make_integer (num); |
| 3444 | mpz_clear (num); | 3440 | mpz_clear (num); |
| 3445 | } | 3441 | } |
| 3446 | } | 3442 | } |
| @@ -3462,7 +3458,7 @@ Markers are converted to integers. */) | |||
| 3462 | mpz_t num; | 3458 | mpz_t num; |
| 3463 | mpz_init (num); | 3459 | mpz_init (num); |
| 3464 | mpz_sub_ui (num, XBIGNUM (number)->value, 1); | 3460 | mpz_sub_ui (num, XBIGNUM (number)->value, 1); |
| 3465 | number = make_number (num); | 3461 | number = make_integer (num); |
| 3466 | mpz_clear (num); | 3462 | mpz_clear (num); |
| 3467 | } | 3463 | } |
| 3468 | else | 3464 | else |
| @@ -3475,7 +3471,7 @@ Markers are converted to integers. */) | |||
| 3475 | mpz_t num; | 3471 | mpz_t num; |
| 3476 | mpz_init (num); | 3472 | mpz_init (num); |
| 3477 | mpz_set_intmax (num, XFIXNUM (number) - 1); | 3473 | mpz_set_intmax (num, XFIXNUM (number) - 1); |
| 3478 | number = make_number (num); | 3474 | number = make_integer (num); |
| 3479 | mpz_clear (num); | 3475 | mpz_clear (num); |
| 3480 | } | 3476 | } |
| 3481 | } | 3477 | } |
| @@ -3492,7 +3488,7 @@ DEFUN ("lognot", Flognot, Slognot, 1, 1, 0, | |||
| 3492 | mpz_t value; | 3488 | mpz_t value; |
| 3493 | mpz_init (value); | 3489 | mpz_init (value); |
| 3494 | mpz_com (value, XBIGNUM (number)->value); | 3490 | mpz_com (value, XBIGNUM (number)->value); |
| 3495 | number = make_number (value); | 3491 | number = make_integer (value); |
| 3496 | mpz_clear (value); | 3492 | mpz_clear (value); |
| 3497 | } | 3493 | } |
| 3498 | else | 3494 | else |
diff --git a/src/editfns.c b/src/editfns.c index d2281d7e81c..9ca6f373e04 100644 --- a/src/editfns.c +++ b/src/editfns.c | |||
| @@ -4491,9 +4491,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message) | |||
| 4491 | else if (conversion == 'X') | 4491 | else if (conversion == 'X') |
| 4492 | base = -16; | 4492 | base = -16; |
| 4493 | 4493 | ||
| 4494 | char *str = mpz_get_str (NULL, base, XBIGNUM (arg)->value); | 4494 | arg = bignum_to_string (arg, base); |
| 4495 | arg = make_unibyte_string (str, strlen (str)); | ||
| 4496 | xfree (str); | ||
| 4497 | conversion = 's'; | 4495 | conversion = 's'; |
| 4498 | } | 4496 | } |
| 4499 | 4497 | ||
diff --git a/src/emacs-module.c b/src/emacs-module.c index f2844c40d0f..a1bed491b62 100644 --- a/src/emacs-module.c +++ b/src/emacs-module.c | |||
| @@ -27,6 +27,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 27 | #include <stdio.h> | 27 | #include <stdio.h> |
| 28 | 28 | ||
| 29 | #include "lisp.h" | 29 | #include "lisp.h" |
| 30 | #include "bignum.h" | ||
| 30 | #include "dynlib.h" | 31 | #include "dynlib.h" |
| 31 | #include "coding.h" | 32 | #include "coding.h" |
| 32 | #include "keyboard.h" | 33 | #include "keyboard.h" |
| @@ -521,6 +522,8 @@ module_extract_integer (emacs_env *env, emacs_value n) | |||
| 521 | CHECK_INTEGER (l); | 522 | CHECK_INTEGER (l); |
| 522 | if (BIGNUMP (l)) | 523 | if (BIGNUMP (l)) |
| 523 | { | 524 | { |
| 525 | /* FIXME: This can incorrectly signal overflow on platforms | ||
| 526 | where long is narrower than intmax_t. */ | ||
| 524 | if (!mpz_fits_slong_p (XBIGNUM (l)->value)) | 527 | if (!mpz_fits_slong_p (XBIGNUM (l)->value)) |
| 525 | xsignal1 (Qoverflow_error, l); | 528 | xsignal1 (Qoverflow_error, l); |
| 526 | return mpz_get_si (XBIGNUM (l)->value); | 529 | return mpz_get_si (XBIGNUM (l)->value); |
| @@ -531,19 +534,8 @@ module_extract_integer (emacs_env *env, emacs_value n) | |||
| 531 | static emacs_value | 534 | static emacs_value |
| 532 | module_make_integer (emacs_env *env, intmax_t n) | 535 | module_make_integer (emacs_env *env, intmax_t n) |
| 533 | { | 536 | { |
| 534 | Lisp_Object obj; | ||
| 535 | MODULE_FUNCTION_BEGIN (module_nil); | 537 | MODULE_FUNCTION_BEGIN (module_nil); |
| 536 | if (FIXNUM_OVERFLOW_P (n)) | 538 | return lisp_to_value (env, make_int (n)); |
| 537 | { | ||
| 538 | mpz_t val; | ||
| 539 | mpz_init (val); | ||
| 540 | mpz_set_intmax (val, n); | ||
| 541 | obj = make_number (val); | ||
| 542 | mpz_clear (val); | ||
| 543 | } | ||
| 544 | else | ||
| 545 | obj = make_fixnum (n); | ||
| 546 | return lisp_to_value (env, obj); | ||
| 547 | } | 539 | } |
| 548 | 540 | ||
| 549 | static double | 541 | static double |
diff --git a/src/emacs.c b/src/emacs.c index 7d07ec85029..07a1aff9b06 100644 --- a/src/emacs.c +++ b/src/emacs.c | |||
| @@ -66,6 +66,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 66 | #include TERM_HEADER | 66 | #include TERM_HEADER |
| 67 | #endif /* HAVE_WINDOW_SYSTEM */ | 67 | #endif /* HAVE_WINDOW_SYSTEM */ |
| 68 | 68 | ||
| 69 | #include "bignum.h" | ||
| 69 | #include "intervals.h" | 70 | #include "intervals.h" |
| 70 | #include "character.h" | 71 | #include "character.h" |
| 71 | #include "buffer.h" | 72 | #include "buffer.h" |
diff --git a/src/floatfns.c b/src/floatfns.c index e7884864eef..8008929be61 100644 --- a/src/floatfns.c +++ b/src/floatfns.c | |||
| @@ -42,6 +42,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 42 | #include <config.h> | 42 | #include <config.h> |
| 43 | 43 | ||
| 44 | #include "lisp.h" | 44 | #include "lisp.h" |
| 45 | #include "bignum.h" | ||
| 45 | 46 | ||
| 46 | #include <math.h> | 47 | #include <math.h> |
| 47 | 48 | ||
| @@ -209,7 +210,7 @@ DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0, | |||
| 209 | 210 | ||
| 210 | /* Common Lisp spec: don't promote if both are integers, and if the | 211 | /* Common Lisp spec: don't promote if both are integers, and if the |
| 211 | result is not fractional. */ | 212 | result is not fractional. */ |
| 212 | if (INTEGERP (arg1) && NATNUMP (arg2)) | 213 | if (INTEGERP (arg1) && Fnatnump (arg2)) |
| 213 | return expt_integer (arg1, arg2); | 214 | return expt_integer (arg1, arg2); |
| 214 | 215 | ||
| 215 | return make_float (pow (XFLOATINT (arg1), XFLOATINT (arg2))); | 216 | return make_float (pow (XFLOATINT (arg1), XFLOATINT (arg2))); |
| @@ -258,19 +259,7 @@ DEFUN ("abs", Fabs, Sabs, 1, 1, 0, | |||
| 258 | if (FIXNUMP (arg)) | 259 | if (FIXNUMP (arg)) |
| 259 | { | 260 | { |
| 260 | if (XFIXNUM (arg) < 0) | 261 | if (XFIXNUM (arg) < 0) |
| 261 | { | 262 | arg = make_int (-XFIXNUM (arg)); |
| 262 | EMACS_INT absarg = -XFIXNUM (arg); | ||
| 263 | if (absarg <= MOST_POSITIVE_FIXNUM) | ||
| 264 | arg = make_fixnum (absarg); | ||
| 265 | else | ||
| 266 | { | ||
| 267 | mpz_t val; | ||
| 268 | mpz_init (val); | ||
| 269 | mpz_set_intmax (val, absarg); | ||
| 270 | arg = make_number (val); | ||
| 271 | mpz_clear (val); | ||
| 272 | } | ||
| 273 | } | ||
| 274 | } | 263 | } |
| 275 | else if (FLOATP (arg)) | 264 | else if (FLOATP (arg)) |
| 276 | { | 265 | { |
| @@ -284,7 +273,7 @@ DEFUN ("abs", Fabs, Sabs, 1, 1, 0, | |||
| 284 | mpz_t val; | 273 | mpz_t val; |
| 285 | mpz_init (val); | 274 | mpz_init (val); |
| 286 | mpz_neg (val, XBIGNUM (arg)->value); | 275 | mpz_neg (val, XBIGNUM (arg)->value); |
| 287 | arg = make_number (val); | 276 | arg = make_integer (val); |
| 288 | mpz_clear (val); | 277 | mpz_clear (val); |
| 289 | } | 278 | } |
| 290 | } | 279 | } |
| @@ -297,13 +286,8 @@ DEFUN ("float", Ffloat, Sfloat, 1, 1, 0, | |||
| 297 | (register Lisp_Object arg) | 286 | (register Lisp_Object arg) |
| 298 | { | 287 | { |
| 299 | CHECK_NUMBER (arg); | 288 | CHECK_NUMBER (arg); |
| 300 | 289 | /* If ARG is a float, give 'em the same float back. */ | |
| 301 | if (BIGNUMP (arg)) | 290 | return FLOATP (arg) ? arg : make_float (XFLOATINT (arg)); |
| 302 | return make_float (mpz_get_d (XBIGNUM (arg)->value)); | ||
| 303 | if (FIXNUMP (arg)) | ||
| 304 | return make_float ((double) XFIXNUM (arg)); | ||
| 305 | else /* give 'em the same float back */ | ||
| 306 | return arg; | ||
| 307 | } | 291 | } |
| 308 | 292 | ||
| 309 | static int | 293 | static int |
| @@ -386,7 +370,7 @@ rounding_driver (Lisp_Object arg, Lisp_Object divisor, | |||
| 386 | (FIXNUMP (divisor) | 370 | (FIXNUMP (divisor) |
| 387 | ? (mpz_set_intmax (d, XFIXNUM (divisor)), d) | 371 | ? (mpz_set_intmax (d, XFIXNUM (divisor)), d) |
| 388 | : XBIGNUM (divisor)->value)); | 372 | : XBIGNUM (divisor)->value)); |
| 389 | Lisp_Object result = make_number (q); | 373 | Lisp_Object result = make_integer (q); |
| 390 | mpz_clear (d); | 374 | mpz_clear (d); |
| 391 | mpz_clear (q); | 375 | mpz_clear (q); |
| 392 | return result; | 376 | return result; |
| @@ -410,12 +394,7 @@ rounding_driver (Lisp_Object arg, Lisp_Object divisor, | |||
| 410 | if (! FIXNUM_OVERFLOW_P (ir)) | 394 | if (! FIXNUM_OVERFLOW_P (ir)) |
| 411 | return make_fixnum (ir); | 395 | return make_fixnum (ir); |
| 412 | } | 396 | } |
| 413 | mpz_t drz; | 397 | return double_to_bignum (dr); |
| 414 | mpz_init (drz); | ||
| 415 | mpz_set_d (drz, dr); | ||
| 416 | Lisp_Object rounded = make_number (drz); | ||
| 417 | mpz_clear (drz); | ||
| 418 | return rounded; | ||
| 419 | } | 398 | } |
| 420 | 399 | ||
| 421 | static void | 400 | static void |
| @@ -433,9 +412,9 @@ rounddiv_q (mpz_t q, mpz_t const n, mpz_t const d) | |||
| 433 | r = n % d; | 412 | r = n % d; |
| 434 | neg_d = d < 0; | 413 | neg_d = d < 0; |
| 435 | neg_r = r < 0; | 414 | neg_r = r < 0; |
| 436 | r = eabs (r); | 415 | abs_r = eabs (r); |
| 437 | abs_r1 = eabs (d) - r; | 416 | abs_r1 = eabs (d) - abs_r; |
| 438 | if (abs_r1 < r + (q & 1)) | 417 | if (abs_r1 < abs_r + (q & 1)) |
| 439 | q += neg_d == neg_r ? 1 : -1; */ | 418 | q += neg_d == neg_r ? 1 : -1; */ |
| 440 | 419 | ||
| 441 | mpz_t r, abs_r1; | 420 | mpz_t r, abs_r1; |
| @@ -444,10 +423,11 @@ rounddiv_q (mpz_t q, mpz_t const n, mpz_t const d) | |||
| 444 | mpz_tdiv_qr (q, r, n, d); | 423 | mpz_tdiv_qr (q, r, n, d); |
| 445 | bool neg_d = mpz_sgn (d) < 0; | 424 | bool neg_d = mpz_sgn (d) < 0; |
| 446 | bool neg_r = mpz_sgn (r) < 0; | 425 | bool neg_r = mpz_sgn (r) < 0; |
| 447 | mpz_abs (r, r); | 426 | mpz_t *abs_r = &r; |
| 427 | mpz_abs (*abs_r, r); | ||
| 448 | mpz_abs (abs_r1, d); | 428 | mpz_abs (abs_r1, d); |
| 449 | mpz_sub (abs_r1, abs_r1, r); | 429 | mpz_sub (abs_r1, abs_r1, *abs_r); |
| 450 | if (mpz_cmp (abs_r1, r) < (mpz_odd_p (q) != 0)) | 430 | if (mpz_cmp (abs_r1, *abs_r) < (mpz_odd_p (q) != 0)) |
| 451 | (neg_d == neg_r ? mpz_add_ui : mpz_sub_ui) (q, q, 1); | 431 | (neg_d == neg_r ? mpz_add_ui : mpz_sub_ui) (q, q, 1); |
| 452 | mpz_clear (r); | 432 | mpz_clear (r); |
| 453 | mpz_clear (abs_r1); | 433 | mpz_clear (abs_r1); |
| @@ -28,6 +28,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 28 | #include <errno.h> | 28 | #include <errno.h> |
| 29 | 29 | ||
| 30 | #include "lisp.h" | 30 | #include "lisp.h" |
| 31 | #include "bignum.h" | ||
| 31 | #include "character.h" | 32 | #include "character.h" |
| 32 | #include "coding.h" | 33 | #include "coding.h" |
| 33 | #include "composite.h" | 34 | #include "composite.h" |
diff --git a/src/json.c b/src/json.c index 4e46640a0c6..d525d1b7577 100644 --- a/src/json.c +++ b/src/json.c | |||
| @@ -709,7 +709,7 @@ usage: (json-insert OBJECT &rest ARGS) */) | |||
| 709 | 709 | ||
| 710 | /* Convert a JSON object to a Lisp object. */ | 710 | /* Convert a JSON object to a Lisp object. */ |
| 711 | 711 | ||
| 712 | static _GL_ARG_NONNULL ((1)) Lisp_Object | 712 | static Lisp_Object ARG_NONNULL ((1)) |
| 713 | json_to_lisp (json_t *json, struct json_configuration *conf) | 713 | json_to_lisp (json_t *json, struct json_configuration *conf) |
| 714 | { | 714 | { |
| 715 | switch (json_typeof (json)) | 715 | switch (json_typeof (json)) |
diff --git a/src/lisp.h b/src/lisp.h index fb11a11fda3..555496bc271 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -31,12 +31,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 31 | #include <inttypes.h> | 31 | #include <inttypes.h> |
| 32 | #include <limits.h> | 32 | #include <limits.h> |
| 33 | 33 | ||
| 34 | #ifdef HAVE_GMP | ||
| 35 | # include <gmp.h> | ||
| 36 | #else | ||
| 37 | # include "mini-gmp.h" | ||
| 38 | #endif | ||
| 39 | |||
| 40 | #include <intprops.h> | 34 | #include <intprops.h> |
| 41 | #include <verify.h> | 35 | #include <verify.h> |
| 42 | 36 | ||
| @@ -589,6 +583,10 @@ enum CHECK_LISP_OBJECT_TYPE { CHECK_LISP_OBJECT_TYPE = false }; | |||
| 589 | INLINE void set_sub_char_table_contents (Lisp_Object, ptrdiff_t, | 583 | INLINE void set_sub_char_table_contents (Lisp_Object, ptrdiff_t, |
| 590 | Lisp_Object); | 584 | Lisp_Object); |
| 591 | 585 | ||
| 586 | /* Defined in bignum.c. */ | ||
| 587 | extern double bignum_to_double (Lisp_Object); | ||
| 588 | extern Lisp_Object make_bigint (intmax_t); | ||
| 589 | |||
| 592 | /* Defined in chartab.c. */ | 590 | /* Defined in chartab.c. */ |
| 593 | extern Lisp_Object char_table_ref (Lisp_Object, int); | 591 | extern Lisp_Object char_table_ref (Lisp_Object, int); |
| 594 | extern void char_table_set (Lisp_Object, int, Lisp_Object); | 592 | extern void char_table_set (Lisp_Object, int, Lisp_Object); |
| @@ -1013,14 +1011,6 @@ enum More_Lisp_Bits | |||
| 1013 | #define MOST_POSITIVE_FIXNUM (EMACS_INT_MAX >> INTTYPEBITS) | 1011 | #define MOST_POSITIVE_FIXNUM (EMACS_INT_MAX >> INTTYPEBITS) |
| 1014 | #define MOST_NEGATIVE_FIXNUM (-1 - MOST_POSITIVE_FIXNUM) | 1012 | #define MOST_NEGATIVE_FIXNUM (-1 - MOST_POSITIVE_FIXNUM) |
| 1015 | 1013 | ||
| 1016 | |||
| 1017 | /* GMP-related limits. */ | ||
| 1018 | |||
| 1019 | /* Number of data bits in a limb. */ | ||
| 1020 | #ifndef GMP_NUMB_BITS | ||
| 1021 | enum { GMP_NUMB_BITS = TYPE_WIDTH (mp_limb_t) }; | ||
| 1022 | #endif | ||
| 1023 | |||
| 1024 | #if USE_LSB_TAG | 1014 | #if USE_LSB_TAG |
| 1025 | 1015 | ||
| 1026 | INLINE Lisp_Object | 1016 | INLINE Lisp_Object |
| @@ -2460,31 +2450,25 @@ XUSER_PTR (Lisp_Object a) | |||
| 2460 | } | 2450 | } |
| 2461 | #endif | 2451 | #endif |
| 2462 | 2452 | ||
| 2463 | struct Lisp_Bignum | ||
| 2464 | { | ||
| 2465 | union vectorlike_header header; | ||
| 2466 | mpz_t value; | ||
| 2467 | }; | ||
| 2468 | |||
| 2469 | INLINE bool | 2453 | INLINE bool |
| 2470 | BIGNUMP (Lisp_Object x) | 2454 | BIGNUMP (Lisp_Object x) |
| 2471 | { | 2455 | { |
| 2472 | return PSEUDOVECTORP (x, PVEC_BIGNUM); | 2456 | return PSEUDOVECTORP (x, PVEC_BIGNUM); |
| 2473 | } | 2457 | } |
| 2474 | 2458 | ||
| 2475 | INLINE struct Lisp_Bignum * | ||
| 2476 | XBIGNUM (Lisp_Object a) | ||
| 2477 | { | ||
| 2478 | eassert (BIGNUMP (a)); | ||
| 2479 | return XUNTAG (a, Lisp_Vectorlike, struct Lisp_Bignum); | ||
| 2480 | } | ||
| 2481 | |||
| 2482 | INLINE bool | 2459 | INLINE bool |
| 2483 | INTEGERP (Lisp_Object x) | 2460 | INTEGERP (Lisp_Object x) |
| 2484 | { | 2461 | { |
| 2485 | return FIXNUMP (x) || BIGNUMP (x); | 2462 | return FIXNUMP (x) || BIGNUMP (x); |
| 2486 | } | 2463 | } |
| 2487 | 2464 | ||
| 2465 | /* Return a Lisp integer with value taken from n. */ | ||
| 2466 | INLINE Lisp_Object | ||
| 2467 | make_int (intmax_t n) | ||
| 2468 | { | ||
| 2469 | return FIXNUM_OVERFLOW_P (n) ? make_bigint (n) : make_fixnum (n); | ||
| 2470 | } | ||
| 2471 | |||
| 2488 | 2472 | ||
| 2489 | /* Forwarding pointer to an int variable. | 2473 | /* Forwarding pointer to an int variable. |
| 2490 | This is allowed only in the value cell of a symbol, | 2474 | This is allowed only in the value cell of a symbol, |
| @@ -2698,13 +2682,6 @@ FIXNATP (Lisp_Object x) | |||
| 2698 | return FIXNUMP (x) && 0 <= XFIXNUM (x); | 2682 | return FIXNUMP (x) && 0 <= XFIXNUM (x); |
| 2699 | } | 2683 | } |
| 2700 | INLINE bool | 2684 | INLINE bool |
| 2701 | NATNUMP (Lisp_Object x) | ||
| 2702 | { | ||
| 2703 | if (BIGNUMP (x)) | ||
| 2704 | return mpz_sgn (XBIGNUM (x)->value) >= 0; | ||
| 2705 | return FIXNUMP (x) && 0 <= XFIXNUM (x); | ||
| 2706 | } | ||
| 2707 | INLINE bool | ||
| 2708 | NUMBERP (Lisp_Object x) | 2685 | NUMBERP (Lisp_Object x) |
| 2709 | { | 2686 | { |
| 2710 | return INTEGERP (x) || FLOATP (x); | 2687 | return INTEGERP (x) || FLOATP (x); |
| @@ -2848,9 +2825,9 @@ CHECK_FIXNAT (Lisp_Object x) | |||
| 2848 | INLINE double | 2825 | INLINE double |
| 2849 | XFLOATINT (Lisp_Object n) | 2826 | XFLOATINT (Lisp_Object n) |
| 2850 | { | 2827 | { |
| 2851 | if (BIGNUMP (n)) | 2828 | return (FIXNUMP (n) ? XFIXNUM (n) |
| 2852 | return mpz_get_d (XBIGNUM (n)->value); | 2829 | : FLOATP (n) ? XFLOAT_DATA (n) |
| 2853 | return FLOATP (n) ? XFLOAT_DATA (n) : XFIXNUM (n); | 2830 | : bignum_to_double (n)); |
| 2854 | } | 2831 | } |
| 2855 | 2832 | ||
| 2856 | INLINE void | 2833 | INLINE void |
| @@ -3310,6 +3287,11 @@ set_sub_char_table_contents (Lisp_Object table, ptrdiff_t idx, Lisp_Object val) | |||
| 3310 | XSUB_CHAR_TABLE (table)->contents[idx] = val; | 3287 | XSUB_CHAR_TABLE (table)->contents[idx] = val; |
| 3311 | } | 3288 | } |
| 3312 | 3289 | ||
| 3290 | /* Defined in bignum.c. */ | ||
| 3291 | extern Lisp_Object bignum_to_string (Lisp_Object, int); | ||
| 3292 | extern Lisp_Object make_bignum_str (char const *, int); | ||
| 3293 | extern Lisp_Object double_to_bignum (double); | ||
| 3294 | |||
| 3313 | /* Defined in data.c. */ | 3295 | /* Defined in data.c. */ |
| 3314 | extern _Noreturn void wrong_choice (Lisp_Object, Lisp_Object); | 3296 | extern _Noreturn void wrong_choice (Lisp_Object, Lisp_Object); |
| 3315 | extern void notify_variable_watchers (Lisp_Object, Lisp_Object, | 3297 | extern void notify_variable_watchers (Lisp_Object, Lisp_Object, |
| @@ -3582,22 +3564,6 @@ extern Lisp_Object list5 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object, | |||
| 3582 | enum constype {CONSTYPE_HEAP, CONSTYPE_PURE}; | 3564 | enum constype {CONSTYPE_HEAP, CONSTYPE_PURE}; |
| 3583 | extern Lisp_Object listn (enum constype, ptrdiff_t, Lisp_Object, ...); | 3565 | extern Lisp_Object listn (enum constype, ptrdiff_t, Lisp_Object, ...); |
| 3584 | 3566 | ||
| 3585 | extern Lisp_Object make_bignum_str (const char *num, int base); | ||
| 3586 | extern Lisp_Object make_number (mpz_t value); | ||
| 3587 | extern void mpz_set_intmax_slow (mpz_t result, intmax_t v); | ||
| 3588 | |||
| 3589 | INLINE void | ||
| 3590 | mpz_set_intmax (mpz_t result, intmax_t v) | ||
| 3591 | { | ||
| 3592 | /* mpz_set_si works in terms of long, but Emacs may use a wider | ||
| 3593 | integer type, and so sometimes will have to construct the mpz_t | ||
| 3594 | by hand. */ | ||
| 3595 | if (LONG_MIN <= v && v <= LONG_MAX) | ||
| 3596 | mpz_set_si (result, v); | ||
| 3597 | else | ||
| 3598 | mpz_set_intmax_slow (result, v); | ||
| 3599 | } | ||
| 3600 | |||
| 3601 | /* Build a frequently used 2/3/4-integer lists. */ | 3567 | /* Build a frequently used 2/3/4-integer lists. */ |
| 3602 | 3568 | ||
| 3603 | INLINE Lisp_Object | 3569 | INLINE Lisp_Object |
diff --git a/src/print.c b/src/print.c index 824f8d75779..49d9e38e7d3 100644 --- a/src/print.c +++ b/src/print.c | |||
| @@ -23,6 +23,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 23 | #include "sysstdio.h" | 23 | #include "sysstdio.h" |
| 24 | 24 | ||
| 25 | #include "lisp.h" | 25 | #include "lisp.h" |
| 26 | #include "bignum.h" | ||
| 26 | #include "character.h" | 27 | #include "character.h" |
| 27 | #include "coding.h" | 28 | #include "coding.h" |
| 28 | #include "buffer.h" | 29 | #include "buffer.h" |
| @@ -1369,10 +1370,12 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag, | |||
| 1369 | { | 1370 | { |
| 1370 | case PVEC_BIGNUM: | 1371 | case PVEC_BIGNUM: |
| 1371 | { | 1372 | { |
| 1372 | struct Lisp_Bignum *b = XBIGNUM (obj); | 1373 | USE_SAFE_ALLOCA; |
| 1373 | char *str = mpz_get_str (NULL, 10, b->value); | 1374 | char *str = SAFE_ALLOCA (mpz_sizeinbase (XBIGNUM (obj)->value, 10) |
| 1374 | record_unwind_protect_ptr (xfree, str); | 1375 | + 2); |
| 1376 | mpz_get_str (str, 10, XBIGNUM (obj)->value); | ||
| 1375 | print_c_string (str, printcharfun); | 1377 | print_c_string (str, printcharfun); |
| 1378 | SAFE_FREE (); | ||
| 1376 | } | 1379 | } |
| 1377 | break; | 1380 | break; |
| 1378 | 1381 | ||