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/alloc.c | |
| 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/alloc.c')
| -rw-r--r-- | src/alloc.c | 78 |
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 | |||
| 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. |