YoushouldhavereceivedcopiesoftheGNUGeneralPublicLicenseandthe GNULesserGeneralPublicLicensealongwiththeGNUMPLibrary.Ifnot,
see https://www.gnu.org/licenses/. */
/* NOTE: All functions in this file which are not declared in mini-gmp.hareinternal,andarenotintendedtobecompatible
with GMP or with future versions of mini-gmp. */
/* Much of the material copied from GMP files, including: gmp-impl.h, longlong.h,mpn/generic/add_n.c,mpn/generic/addmul_1.c, mpn/generic/lshift.c,mpn/generic/mul_1.c, mpn/generic/mul_basecase.c,mpn/generic/rshift.c, mpn/generic/sbpi1_div_qr.c,mpn/generic/sub_n.c,
mpn/generic/submul_1.c. */
assert (sizeof (unsigned) * 2 >= sizeof (mp_limb_t)); /* For notation, let b denote the half-limb base, so that B = b^2.
Split u1 = b uh + ul. */
ul = u1 & GMP_LLIMB_MASK;
uh = u1 >> (GMP_LIMB_BITS / 2);
/* Approximation of the high half of quotient. Differs from the 2/1 inverseofthehalflimbuh,sincewehavealreadysubtracted
u0. */
qh = (u1 ^ GMP_LIMB_MAX) / uh;
/* Adjust to get a half-limb 3/2 inverse, i.e., we want
p = (mp_limb_t) qh * ul; /* Adjustment steps taken from udiv_qrnnd_c */ if (r < p)
{
qh--;
r += u1; if (r >= u1) /* i.e. we didn't get carry when adding to r */ if (r < p)
{
qh--;
r += u1;
}
}
r -= p;
p = (r >> (GMP_LIMB_BITS / 2)) * qh + r; /* Unlike full-limb 3/2, we can add 1 without overflow. For this to
work, it is essential that ql is a full mp_limb_t. */
ql = (p >> (GMP_LIMB_BITS / 2)) + 1;
/* By the 3/2 trick, we don't need the high half limb. */
r = (r << (GMP_LIMB_BITS / 2)) + GMP_LLIMB_MASK - ql * u1;
if (r >= (GMP_LIMB_MAX & (p << (GMP_LIMB_BITS / 2))))
{
ql--;
r += u1;
}
m = ((mp_limb_t) qh << (GMP_LIMB_BITS / 2)) + ql; if (r >= u1)
{
m++;
r -= u1;
}
}
/* Now m is the 2/1 inverse of u1. If u0 > 0, adjust it to become a
3/2 inverse. */ if (u0 > 0)
{
mp_limb_t th, tl;
r = ~r;
r += u0; if (r < u0)
{
m--; if (r >= u1)
{
m--;
r -= u1;
}
r -= u1;
}
gmp_umul_ppmm (th, tl, u0, m);
r += th; if (r < th)
{
m--;
m -= ((r > u1) | ((r == u1) & (tl > u0)));
}
}
assert ((d1 & GMP_LIMB_HIGHBIT) != 0); /* Iteration variable is the index of the q limb. * *Wedivide<n1,np[dn-1+i],np[dn-2+i],np[dn-3+i],...,np[i]> *by<d1,d0,dp[dn-3],...,dp[0]>
*/
i = nn - dn; do
{
mp_limb_t n0 = np[dn-1+i];
if (n1 == d1 && n0 == d0)
{
q = GMP_LIMB_MAX;
mpn_submul_1 (np+i, dp, dn, q);
n1 = np[dn-1+i]; /* update n1, last loop's value will now be invalid */
} else
{
gmp_udiv_qr_3by2 (q, n1, n0, n1, n0, np[dn-2+i], d1, d0, dinv);
struct mpn_base_info
{ /* bb is the largest power of the base which fits in one limb, and
exp is the corresponding exponent. */ unsigned exp;
mp_limb_t bb;
};
staticvoid
mpn_get_base_info (struct mpn_base_info *info, mp_limb_t b)
{
mp_limb_t m;
mp_limb_t p; unsigned exp;
m = GMP_LIMB_MAX / b; for (exp = 1, p = b; p <= m; exp++)
p *= b;
/* We generate digits from the least significant end, and reverse at
the end. */ static size_t
mpn_limb_get_str (unsignedchar *sp, mp_limb_t w, conststruct gmp_div_inverse *binv)
{
mp_size_t i; for (i = 0; w > 0; i++)
{
mp_limb_t h, l, r;
h = w >> (GMP_LIMB_BITS - binv->shift);
l = w << binv->shift;
for (limb = 0, rn = 0, shift = 0; sn-- > 0; )
{
limb |= (mp_limb_t) sp[sn] << shift;
shift += bits; if (shift >= GMP_LIMB_BITS)
{
shift -= GMP_LIMB_BITS;
rp[rn++] = limb; /* Next line is correct also if shift == 0,
bits == 8, and mp_limb_t == unsigned char. */
limb = (unsignedint) sp[sn] >> (bits - shift);
}
} if (limb != 0)
rp[rn++] = limb; else
rn = mpn_normalized_size (rp, rn); return rn;
}
/* Result is usually normalized, except for all-zero input, in which
case a single zero limb is written at *RP, and 1 is returned. */ static mp_size_t
mpn_set_str_other (mp_ptr rp, constunsignedchar *sp, size_t sn,
mp_limb_t b, conststruct mpn_base_info *info)
{
mp_size_t rn;
mp_limb_t w; unsigned k;
size_t j;
assert (sn > 0);
k = 1 + (sn - 1) % info->exp;
j = 0;
w = sp[j++]; while (--k != 0)
w = w * b + sp[j++];
rp[0] = w;
for (rn = 1; j < sn;)
{
mp_limb_t cy;
w = sp[j++]; for (k = 1; k < info->exp; k++)
w = w * b + sp[j++];
/* The utility of this function is a bit limited, since many functions
assigns the result variable using mpz_swap. */ void
mpz_init2 (mpz_t r, mp_bitcnt_t bits)
{
mp_size_t rn;
staticvoid
mpz_div_q_2exp (mpz_t q, const mpz_t u, mp_bitcnt_t bit_index, enum mpz_div_round_mode mode)
{
mp_size_t un, qn;
mp_size_t limb_cnt;
mp_ptr qp; int adjust;
un = u->_mp_size; if (un == 0)
{
q->_mp_size = 0; return;
}
limb_cnt = bit_index / GMP_LIMB_BITS;
qn = GMP_ABS (un) - limb_cnt;
bit_index %= GMP_LIMB_BITS;
if (mode == ((un > 0) ? GMP_DIV_CEIL : GMP_DIV_FLOOR)) /* un != 0 here. */ /* Note: Below, the final indexing at limb_cnt is valid because at
that point we have qn > 0. */
adjust = (qn <= 0
|| !mpn_zero_p (u->_mp_d, limb_cnt)
|| (u->_mp_d[limb_cnt]
& (((mp_limb_t) 1 << bit_index) - 1))); else
adjust = 0;
if (rn > un)
{ /* Quotient (with truncation) is zero, and remainder is
non-zero */ if (mode == ((us > 0) ? GMP_DIV_CEIL : GMP_DIV_FLOOR)) /* us != 0 here. */
{ /* Have to negate and sign extend. */
mp_size_t i;
gmp_assert_nocarry (! mpn_neg (rp, u->_mp_d, un)); for (i = un; i < rn - 1; i++)
rp[i] = GMP_LIMB_MAX;
rp[rn-1] = mask;
us = -us;
} else
{ /* Just copy */ if (r != u)
mpn_copyi (rp, u->_mp_d, un);
if (mode == ((us > 0) ? GMP_DIV_CEIL : GMP_DIV_FLOOR)) /* us != 0 here. */
{ /* If r != 0, compute 2^{bit_count} - r. */
mpn_neg (rp, rp, rn);
rp[rn-1] &= mask;
/* us is not used for anything else, so we can modify it
here to indicate flipped sign. */
us = -us;
}
}
rn = mpn_normalized_size (rp, rn);
r->_mp_size = us < 0 ? -rn : rn;
}
void
mpz_cdiv_q_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt)
{
mpz_div_q_2exp (r, u, cnt, GMP_DIV_CEIL);
}
void
mpz_fdiv_q_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt)
{
mpz_div_q_2exp (r, u, cnt, GMP_DIV_FLOOR);
}
void
mpz_tdiv_q_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt)
{
mpz_div_q_2exp (r, u, cnt, GMP_DIV_TRUNC);
}
void
mpz_cdiv_r_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt)
{
mpz_div_r_2exp (r, u, cnt, GMP_DIV_CEIL);
}
void
mpz_fdiv_r_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt)
{
mpz_div_r_2exp (r, u, cnt, GMP_DIV_FLOOR);
}
void
mpz_tdiv_r_2exp (mpz_t r, const mpz_t u, mp_bitcnt_t cnt)
{
mpz_div_r_2exp (r, u, cnt, GMP_DIV_TRUNC);
}
void
mpz_divexact (mpz_t q, const mpz_t n, const mpz_t d)
{
gmp_assert_nocarry (mpz_div_qr (q, NULL, n, d, GMP_DIV_TRUNC));
}
int
mpz_divisible_p (const mpz_t n, const mpz_t d)
{ return mpz_div_qr (NULL, NULL, n, d, GMP_DIV_TRUNC) == 0;
}
int
mpz_congruent_p (const mpz_t a, const mpz_t b, const mpz_t m)
{
mpz_t t; int res;
/* a == b (mod 0) iff a == b */ if (mpz_sgn (m) == 0) return (mpz_cmp (a, b) == 0);
mpz_init (t);
mpz_sub (t, a, b);
res = mpz_divisible_p (t, m);
mpz_clear (t);
return res;
}
staticunsignedlong
mpz_div_qr_ui (mpz_t q, mpz_t r, const mpz_t n, unsignedlong d, enum mpz_div_round_mode mode)
{ unsignedlong ret;
mpz_t rr, dd;
mpz_init (rr);
mpz_init_set_ui (dd, d);
mpz_div_qr (q, rr, n, dd, mode);
mpz_clear (dd);
ret = mpz_get_ui (rr);
if (r)
mpz_swap (r, rr);
mpz_clear (rr);
return ret;
}
unsignedlong
mpz_cdiv_qr_ui (mpz_t q, mpz_t r, const mpz_t n, unsignedlong d)
{ return mpz_div_qr_ui (q, r, n, d, GMP_DIV_CEIL);
}
unsignedlong
mpz_fdiv_qr_ui (mpz_t q, mpz_t r, const mpz_t n, unsignedlong d)
{ return mpz_div_qr_ui (q, r, n, d, GMP_DIV_FLOOR);
}
unsignedlong
mpz_tdiv_qr_ui (mpz_t q, mpz_t r, const mpz_t n, unsignedlong d)
{ return mpz_div_qr_ui (q, r, n, d, GMP_DIV_TRUNC);
}
unsignedlong
mpz_cdiv_q_ui (mpz_t q, const mpz_t n, unsignedlong d)
{ return mpz_div_qr_ui (q, NULL, n, d, GMP_DIV_CEIL);
}
unsignedlong
mpz_fdiv_q_ui (mpz_t q, const mpz_t n, unsignedlong d)
{ return mpz_div_qr_ui (q, NULL, n, d, GMP_DIV_FLOOR);
}
unsignedlong
mpz_tdiv_q_ui (mpz_t q, const mpz_t n, unsignedlong d)
{ return mpz_div_qr_ui (q, NULL, n, d, GMP_DIV_TRUNC);
}
unsignedlong
mpz_cdiv_r_ui (mpz_t r, const mpz_t n, unsignedlong d)
{ return mpz_div_qr_ui (NULL, r, n, d, GMP_DIV_CEIL);
} unsignedlong
mpz_fdiv_r_ui (mpz_t r, const mpz_t n, unsignedlong d)
{ return mpz_div_qr_ui (NULL, r, n, d, GMP_DIV_FLOOR);
} unsignedlong
mpz_tdiv_r_ui (mpz_t r, const mpz_t n, unsignedlong d)
{ return mpz_div_qr_ui (NULL, r, n, d, GMP_DIV_TRUNC);
}
unsignedlong
mpz_cdiv_ui (const mpz_t n, unsignedlong d)
{ return mpz_div_qr_ui (NULL, NULL, n, d, GMP_DIV_CEIL);
}
unsignedlong
mpz_fdiv_ui (const mpz_t n, unsignedlong d)
{ return mpz_div_qr_ui (NULL, NULL, n, d, GMP_DIV_FLOOR);
}
unsignedlong
mpz_tdiv_ui (const mpz_t n, unsignedlong d)
{ return mpz_div_qr_ui (NULL, NULL, n, d, GMP_DIV_TRUNC);
}
unsignedlong
mpz_mod_ui (mpz_t r, const mpz_t n, unsignedlong d)
{ return mpz_div_qr_ui (NULL, r, n, d, GMP_DIV_FLOOR);
}
void
mpz_divexact_ui (mpz_t q, const mpz_t n, unsignedlong d)
{
gmp_assert_nocarry (mpz_div_qr_ui (q, NULL, n, d, GMP_DIV_TRUNC));
}
int
mpz_divisible_ui_p (const mpz_t n, unsignedlong d)
{ return mpz_div_qr_ui (NULL, NULL, n, d, GMP_DIV_TRUNC) == 0;
}
assert (r->_mp_size > 0); /* Count trailing zeros, equivalent to mpn_scan1, because we know that there is a 1 */
shift = mpn_scan1 (r->_mp_d, 0);
mpz_tdiv_q_2exp (r, r, shift);
if (u->_mp_size == 0)
{ /* g = 0 u + sgn(v) v */ signedlong sign = mpz_sgn (v);
mpz_abs (g, v); if (s)
s->_mp_size = 0; if (t)
mpz_set_si (t, sign); return;
}
if (v->_mp_size == 0)
{ /* g = sgn(u) u + 0 v */ signedlong sign = mpz_sgn (u);
mpz_abs (g, u); if (s)
mpz_set_si (s, sign); if (t)
t->_mp_size = 0; return;
}
/* We have reduced the absolute value. Now take care of the sign.Notethatwegetzerorepresentednon-canonicallyas
m. */ if (b->_mp_size < 0)
{
mp_ptr bp = MPZ_REALLOC (base, mn);
gmp_assert_nocarry (mpn_sub (bp, mp, mn, bp, bn));
bn = mn;
}
base->_mp_size = mpn_normalized_size (base->_mp_d, bn);
}
mpz_init_set_ui (tr, 1);
while (--en >= 0)
{
mp_limb_t w = e->_mp_d[en];
mp_limb_t bit;
bit = GMP_LIMB_HIGHBIT; do
{
mpz_mul (tr, tr, tr); if (w & bit)
mpz_mul (tr, tr, base); if (tr->_mp_size > mn)
{
mpn_div_qr_preinv (NULL, tr->_mp_d, tr->_mp_size, mp, mn, &minv);
tr->_mp_size = mpn_normalized_size (tr->_mp_d, mn);
}
bit >>= 1;
} while (bit > 0);
}
/* Final reduction */ if (tr->_mp_size >= mn)
{
minv.shift = shift;
mpn_div_qr_preinv (NULL, tr->_mp_d, tr->_mp_size, mp, mn, &minv);
tr->_mp_size = mpn_normalized_size (tr->_mp_d, mn);
} if (tp)
gmp_free_limbs (tp, mn);
/* Computes Kronecker (a/b) with odd b, a!=0 and GCD(a,b) = 1 */ /* Adapted from JACOBI_BASE_METHOD==4 in mpn/generic/jacbase.c */ staticint
gmp_jacobi_coprime (mp_limb_t a, mp_limb_t b)
{ int c, bit = 0;
assert (b & 1);
assert (a != 0); /* assert (mpn_gcd_11 (a, b) == 1); */
/* Below, we represent a and b shifted right so that the least
significant one bit is implicit. */
b >>= 1;
gmp_ctz(c, a);
a >>= 1;
for (;;)
{
a >>= c; /* (2/b) = -1 if b = 3 or 5 mod 8 */
bit ^= c & (b ^ (b >> 1)); if (a < b)
{ if (a == 0) return bit & 1 ? -1 : 1;
bit ^= a & b;
a = b - a;
b -= a;
} else
{
a -= b;
assert (a != 0);
}
/* Computes V_k, Q^k (mod n) for the Lucas' sequence */ /* with P=1, Q=Q; k = (n>>b0)|1. */ /* Requires an odd n > 4; b0 > 0; -2*Q must not overflow a long */ /* Returns (U_k == 0) and sets V=V_k and Qk=Q^k. */ staticint
gmp_lucas_mod (mpz_t V, mpz_t Qk, long Q,
mp_bitcnt_t b0, const mpz_t n)
{
mp_bitcnt_t bs;
mpz_t U; int res;
/* A step k->k+1 is performed if the bit in $n$ is 1 */ /* mpz_tstbit(n,bs) or the bit is 0 in $n$ but */ /* should be 1 in $n+1$ (bs == b0) */ if (b0 == bs || mpz_tstbit (n, bs))
{ /* Q^{k+1} <- Q^k * Q */
mpz_mul_si (Qk, Qk, Q); /* U_{k+1} <- (U_k + V_k) / 2 */
mpz_swap (U, V); /* Keep in V the old value of U_k */
mpz_add (U, U, V); /* We have to compute U/2, so we need an even value, */ /* equivalent (mod n) */ if (mpz_odd_p (U))
mpz_add (U, U, n);
mpz_tdiv_q_2exp (U, U, 1); /* V_{k+1} <-(D*U_k + V_k) / 2 =
U_{k+1} + (D-1)/2*U_k = U_{k+1} - 2Q*U_k */
mpz_mul_si (V, V, -2*Q);
mpz_add (V, U, V);
mpz_tdiv_r (V, V, n);
}
mpz_tdiv_r (U, U, n);
}
res = U->_mp_size == 0;
mpz_clear (U); return res;
}
/* Performs strong Lucas' test on x, with parameters suggested */ /* for the BPSW test. Qk is only passed to recycle a variable. */ /* Requires GCD (x,6) = 1.*/ staticint
gmp_stronglucas (const mpz_t x, mpz_t Qk)
{
mp_bitcnt_t b0;
mpz_t V, n;
mp_limb_t maxD, D; /* The absolute value is stored. */ long Q;
mp_limb_t tl;
/* Test on the absolute value. */
mpz_roinit_normal_n (n, x->_mp_d, GMP_ABS (x->_mp_size));
assert (mpz_odd_p (n)); /* assert (mpz_gcd_ui (NULL, n, 6) == 1); */ if (mpz_root (Qk, n, 2)) return0; /* A square is composite. */
/* Check Ds up to square root (in case, n is prime)
or avoid overflows */
maxD = (Qk->_mp_size == 1) ? Qk->_mp_d [0] - 1 : GMP_LIMB_MAX;
D = 3; /* Search a D such that (D/n) = -1 in the sequence 5,-7,9,-11,.. */ /* For those Ds we have (D/n) = (n/|D|) */ do
{ if (D >= maxD) return1 + (D != GMP_LIMB_MAX); /* (1 + ! ~ D) */
D += 2;
tl = mpz_tdiv_ui (n, D); if (tl == 0) return0;
} while (gmp_jacobi_coprime (tl, D) == 1);
while (--k > 0)
{
mpz_powm_ui (y, y, 2, n); if (mpz_cmp (y, nm1) == 0) return1;
} return0;
}
/* This product is 0xc0cfd797, and fits in 32 bits. */ #define GMP_PRIME_PRODUCT \
(3UL*5UL*7UL*11UL*13UL*17UL*19UL*23UL*29UL)
/* Bit (p+1)/2 is set, for each odd prime <= 61 */ #define GMP_PRIME_MASK 0xc96996dcUL
int
mpz_probab_prime_p (const mpz_t n, int reps)
{
mpz_t nm1;
mpz_t q;
mpz_t y;
mp_bitcnt_t k; int is_prime; int j;
/* Note that we use the absolute value of n only, for compatibility
with the real GMP. */ if (mpz_even_p (n)) return (mpz_cmpabs_ui (n, 2) == 0) ? 2 : 0;
/* Above test excludes n == 0 */
assert (n->_mp_size != 0);
if (mpz_gcd_ui (NULL, n, GMP_PRIME_PRODUCT) != 1) return0;
/* All prime factors are >= 31. */ if (mpz_cmpabs_ui (n, 31*31) < 0) return2;
mpz_init (nm1);
mpz_init (q);
/* Find q and k, where q is odd and n = 1 + 2**k * q. */
mpz_abs (nm1, n);
nm1->_mp_d[0] -= 1; /* Count trailing zeros, equivalent to mpn_scan1, because we know that there is a 1 */
k = mpn_scan1 (nm1->_mp_d, 0);
mpz_tdiv_q_2exp (q, nm1, k);
/* BPSW test */
mpz_init_set_ui (y, 2);
is_prime = gmp_millerrabin (n, nm1, y, q, k) && gmp_stronglucas (n, y);
reps -= 24; /* skip the first 24 repetitions */
/* Use Miller-Rabin, with a deterministic sequence of bases, a[j] = j^2+j+41usingEuler'spolynomial.Wepotentiallystopearly, ifa[j]>=n-1.Sincen>=31*31,thiscanhappenonlyifreps>
30 (a[30] == 971 > 31*31 == 961). */
for (j = 0; is_prime & (j < reps); j++)
{
mpz_set_ui (y, (unsignedlong) j*j+j+41); if (mpz_cmp (y, nm1) >= 0)
{ /* Don't try any further bases. This "early" break does not affect
the result for any reasonable reps value (<=5000 was tested) */
assert (j >= 30); break;
}
is_prime = gmp_millerrabin (n, nm1, y, q, k);
}
mpz_clear (nm1);
mpz_clear (q);
mpz_clear (y);
return is_prime;
}
/* Logical operations and bit manipulation. */
/* Numbers are treated as if represented in two's complement (and infinitelysignextended).Foranegativevalueswegetthetwo's complementfrom-x=~x+1,where~isbitwisecomplement. Negationtransforms
shift = bit_index % GMP_LIMB_BITS;
w = d->_mp_d[limb_index];
bit = (w >> shift) & 1;
if (ds < 0)
{ /* d < 0. Check if any of the bits below is set: If so, our bit
must be complemented. */ if (shift > 0 && (mp_limb_t) (w << (GMP_LIMB_BITS - shift)) > 0) return bit ^ 1; while (--limb_index >= 0) if (d->_mp_d[limb_index] > 0) return bit ^ 1;
} return bit;
}
if (limb_index >= dn)
{
mp_size_t i; /* The bit should be set outside of the end of the number.
We have to increase the size of the number. */
dp = MPZ_REALLOC (d, limb_index + 1);
dp[limb_index] = bit; for (i = dn; i < limb_index; i++)
dp[i] = 0;
dn = limb_index + 1;
} else
{
mp_limb_t cy;
/* Do 16 bits at a time, to avoid limb-sized constants. */ int LOCAL_SHIFT_BITS = 16; for (c = 0; x > 0;)
{ unsigned w = x - ((x >> 1) & 0x5555);
w = ((w >> 2) & 0x3333) + (w & 0x3333);
w = (w >> 4) + w;
w = ((w >> 8) & 0x000f) + (w & 0x000f);
c += w; if (GMP_LIMB_BITS > LOCAL_SHIFT_BITS)
x >>= LOCAL_SHIFT_BITS; else
x = 0;
} return c;
}
for (; i < un; i++)
{
ul = (up[i] ^ comp) + uc;
uc = ul < uc;
c += gmp_popcount_limb (ul ^ comp);
}
return c;
}
mp_bitcnt_t
mpz_scan1 (const mpz_t u, mp_bitcnt_t starting_bit)
{
mp_ptr up;
mp_size_t us, un, i;
mp_limb_t limb, ux;
us = u->_mp_size;
un = GMP_ABS (us);
i = starting_bit / GMP_LIMB_BITS;
/* Past the end there's no 1 bits for u>=0, or an immediate 1 bit
for u<0. Notice this test picks up any u==0 too. */ if (i >= un) return (us >= 0 ? ~(mp_bitcnt_t) 0 : starting_bit);
/* Mask to 0 all bits before starting_bit, thus ignoring them. */
limb &= GMP_LIMB_MAX << (starting_bit % GMP_LIMB_BITS);
}
return mpn_common_scan (limb, i, up, un, ux);
}
mp_bitcnt_t
mpz_scan0 (const mpz_t u, mp_bitcnt_t starting_bit)
{
mp_ptr up;
mp_size_t us, un, i;
mp_limb_t limb, ux;
us = u->_mp_size;
ux = - (mp_limb_t) (us >= 0);
un = GMP_ABS (us);
i = starting_bit / GMP_LIMB_BITS;
/* When past end, there's an immediate 0 bit for u>=0, or no 0 bits for
u<0. Notice this test picks up all cases of u==0 too. */ if (i >= un) return (ux ? starting_bit : ~(mp_bitcnt_t) 0);
digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; if (base > 1)
{ if (base <= 36)
digits = "0123456789abcdefghijklmnopqrstuvwxyz"; elseif (base > 62) return NULL;
} elseif (base >= -1)
base = 10; else
{
base = -base; if (base > 36) return NULL;
}
sn = 1 + mpz_sizeinbase (u, base); if (!sp)
{
osn = 1 + sn;
sp = (char *) gmp_alloc (osn);
} else
osn = 0;
un = GMP_ABS (u->_mp_size);
if (un == 0)
{
sp[0] = '0';
sn = 1; goto ret;
}
i = 0;
if (u->_mp_size < 0)
sp[i++] = '-';
bits = mpn_base_power_of_two_p (base);
if (bits) /* Not modified in this case. */
sn = i + mpn_get_str_bits ((unsignedchar *) sp + i, bits, u->_mp_d, un); else
{ struct mpn_base_info info;
mp_ptr tp;
str = mpz_get_str (NULL, base, x);
if (!str)
return 0;
len = strlen (str);
n = fwrite (str, 1, len, stream);
gmp_free (str, len + 1);
return n;
}
static int
gmp_detect_endian (void)
{
static const int i = 2;
const unsigned char *p = (const unsigned char *) &i;
return 1 - *p;
}
/* Import and export. Does not support nails. */
void
mpz_import (mpz_t r, size_t count, int order, size_t size, int endian,
size_t nails, const void *src)
{
const unsigned char *p;
ptrdiff_t word_step;
mp_ptr rp;
mp_size_t rn;
/* The current (partial) limb. */
mp_limb_t limb;
/* The number of bytes already copied to this limb (starting from
the low end). */
size_t bytes;
/* The index where the limb should be stored, when completed. */
mp_size_t i;
if (nails != 0)
gmp_die ("mpz_import: Nails not supported.");
/* Process bytes from the least significant end, so point p at the
least significant word. */
if (order == 1)
{
p += size * (count - 1);
word_step = - word_step;
}
/* And at least significant byte of that word. */
if (endian == 1)
p += (size - 1);
un = u->_mp_size;
count = 0;
if (un != 0)
{
size_t k;
unsigned char *p;
ptrdiff_t word_step;
/* The current (partial) limb. */
mp_limb_t limb;
/* The number of bytes left to do in this limb. */
size_t bytes;
/* The index where the limb was read. */
mp_size_t i;
un = GMP_ABS (un);
/* Count bytes in top limb. */
limb = u->_mp_d[un-1];
assert (limb != 0);
k = (GMP_LIMB_BITS <= CHAR_BIT);
if (!k)
{
do {
int LOCAL_CHAR_BIT = CHAR_BIT;
k++; limb >>= LOCAL_CHAR_BIT;
} while (limb != 0);
}
/* else limb = 0; */
/* Process bytes from the least significant end, so point p at the
least significant word. */
if (order == 1)
{
p += size * (count - 1);
word_step = - word_step;
}
/* And at least significant byte of that word. */
if (endian == 1)
p += (size - 1);
for (bytes = 0, i = 0, k = 0; k < count; k++, p += word_step)
{
size_t j;
for (j = 0; j < size; ++j, p -= (ptrdiff_t) endian)
{
if (sizeof (mp_limb_t) == 1)
{
if (i < un)
*p = u->_mp_d[i++];
else
*p = 0;
}
else
{
int LOCAL_CHAR_BIT = CHAR_BIT;
if (bytes == 0)
{
if (i < un)
limb = u->_mp_d[i++];
bytes = sizeof (mp_limb_t);
}
*p = limb;
limb >>= LOCAL_CHAR_BIT;
bytes--;
}
}
}
assert (i == un);
assert (k == count);
}
if (countp)
*countp = count;
return r;
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.118 Sekunden
(vorverarbeitet am 2026-06-10)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.