aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
authorPaul Eggert2018-08-27 21:27:50 -0700
committerPaul Eggert2018-08-27 21:45:22 -0700
commit9abaf5f3581ecb76f30e8a6e7ee0e9633c133d1c (patch)
treec39260a6e26845b0a1307be98b38581468925c58 /src/alloc.c
parentbf1b147b55e1328efca6e40181e79dd9a369895d (diff)
downloademacs-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/alloc.c')
-rw-r--r--src/alloc.c78
1 files changed, 1 insertions, 77 deletions
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
3732Lisp_Object
3733make_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
3746Lisp_Object
3747make_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
3785void
3786mpz_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.