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)
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;
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)
{
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
extern void init_bignum (void);
extern Lisp_Object make_integer_mpz (void);
+extern bool mpz_to_intmax (mpz_t const, intmax_t *) ARG_NONNULL ((1, 2));
+extern bool mpz_to_uintmax (mpz_t const, uintmax_t *) ARG_NONNULL ((1, 2));
extern void mpz_set_intmax_slow (mpz_t, intmax_t) ARG_NONNULL ((1));
+extern void mpz_set_uintmax_slow (mpz_t, uintmax_t) ARG_NONNULL ((1));
extern double mpz_get_d_rounded (mpz_t const);
INLINE_HEADER_BEGIN
else
mpz_set_intmax_slow (result, v);
}
+INLINE void ARG_NONNULL ((1))
+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 pointer to an mpz_t that is equal to the Lisp integer I.
If I is a bignum this returns a pointer to I's representation;