diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2018-10-03 09:10:01 -0700 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2018-10-06 23:31:04 -0700 |
commit | 84f39d3389209e566dde9acbdd78f5572f0c6751 (patch) | |
tree | ad9788f26ffd9e9ceb7a520ed863833a5b60db8b /src/bignum.c | |
parent | 0faad0a0025cb4c6cbdba44e5b259690fae27b1a (diff) | |
download | emacs-84f39d3389209e566dde9acbdd78f5572f0c6751.tar.gz |
Export converting mpz to [u]intmax
This refactoring will help improve timestamp handling later
(Bug#32902).
* src/bignum.c (mpz_set_uintmax): Move to bignum.h,
and make inline.
(mpz_set_uintmax_slow): Now extern.
(mpz_to_intmax, mpz_to_uintmax): New functions, with
implementation taken from the old bignum_to_intmax
and bignum_to_uintmax.
(bignum_to_intmax, bignum_to_uintmax): Use them.
Diffstat (limited to 'src/bignum.c')
-rw-r--r-- | src/bignum.c | 91 |
1 files changed, 50 insertions, 41 deletions
diff --git a/src/bignum.c b/src/bignum.c index 1e78d981b7d..5d8ab670f24 100644 --- a/src/bignum.c +++ b/src/bignum.c @@ -101,18 +101,6 @@ make_bignum (void) return make_bignum_bits (mpz_sizeinbase (mpz[0], 2)); } -static void mpz_set_uintmax_slow (mpz_t, uintmax_t); - -/* Set RESULT to V. */ -static void -mpz_set_uintmax (mpz_t result, uintmax_t v) -{ - if (v <= ULONG_MAX) - mpz_set_ui (result, v); - else - mpz_set_uintmax_slow (result, v); -} - /* Return a Lisp integer equal to N, which must not be in fixnum range. */ Lisp_Object make_bigint (intmax_t n) @@ -183,7 +171,7 @@ mpz_set_intmax_slow (mpz_t result, intmax_t v) mpz_limbs_finish (result, negative ? -n : n); } -static void +void mpz_set_uintmax_slow (mpz_t result, uintmax_t v) { int maxlimbs = (UINTMAX_WIDTH + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS; @@ -200,13 +188,13 @@ mpz_set_uintmax_slow (mpz_t result, uintmax_t v) mpz_limbs_finish (result, n); } -/* Return the value of the bignum X if it fits, 0 otherwise. - A bignum cannot be zero, so 0 indicates failure reliably. */ -intmax_t -bignum_to_intmax (Lisp_Object x) +/* If Z fits into *PI, store its value there and return true. + Return false otherwise. */ +bool +mpz_to_intmax (mpz_t const z, intmax_t *pi) { - ptrdiff_t bits = mpz_sizeinbase (XBIGNUM (x)->value, 2); - bool negative = mpz_sgn (XBIGNUM (x)->value) < 0; + ptrdiff_t bits = mpz_sizeinbase (z, 2); + bool negative = mpz_sgn (z) < 0; if (bits < INTMAX_WIDTH) { @@ -215,39 +203,60 @@ bignum_to_intmax (Lisp_Object x) do { - intmax_t limb = mpz_getlimbn (XBIGNUM (x)->value, i++); + intmax_t limb = mpz_getlimbn (z, i++); v += limb << shift; shift += GMP_NUMB_BITS; } while (shift < bits); - return negative ? -v : v; + *pi = negative ? -v : v; + return true; + } + if (bits == INTMAX_WIDTH && INTMAX_MIN < -INTMAX_MAX && negative + && mpz_scan1 (z, 0) == INTMAX_WIDTH - 1) + { + *pi = INTMAX_MIN; + return true; } - return ((bits == INTMAX_WIDTH && INTMAX_MIN < -INTMAX_MAX && negative - && mpz_scan1 (XBIGNUM (x)->value, 0) == INTMAX_WIDTH - 1) - ? INTMAX_MIN : 0); + return false; } -uintmax_t -bignum_to_uintmax (Lisp_Object x) +bool +mpz_to_uintmax (mpz_t const z, uintmax_t *pi) { + if (mpz_sgn (z) < 0) + return false; + ptrdiff_t bits = mpz_sizeinbase (z, 2); + if (UINTMAX_WIDTH < bits) + return false; + uintmax_t v = 0; - if (0 <= mpz_sgn (XBIGNUM (x)->value)) + int i = 0, shift = 0; + + do { - ptrdiff_t bits = mpz_sizeinbase (XBIGNUM (x)->value, 2); - if (bits <= UINTMAX_WIDTH) - { - int i = 0, shift = 0; - - do - { - uintmax_t limb = mpz_getlimbn (XBIGNUM (x)->value, i++); - v += limb << shift; - shift += GMP_NUMB_BITS; - } - while (shift < bits); - } + uintmax_t limb = mpz_getlimbn (z, i++); + v += limb << shift; + shift += GMP_NUMB_BITS; } - return v; + while (shift < bits); + + *pi = v; + return true; +} + +/* Return the value of the bignum X if it fits, 0 otherwise. + A bignum cannot be zero, so 0 indicates failure reliably. */ +intmax_t +bignum_to_intmax (Lisp_Object x) +{ + intmax_t i; + return mpz_to_intmax (XBIGNUM (x)->value, &i) ? i : 0; +} +uintmax_t +bignum_to_uintmax (Lisp_Object x) +{ + uintmax_t i; + return mpz_to_uintmax (XBIGNUM (x)->value, &i) ? i : 0; } /* Yield an upper bound on the buffer size needed to contain a C |