void mpf_reldiff (mpf_t rdiff, mpf_srcptr x, mpf_srcptr y) { if (UNLIKELY (SIZ(x) == 0)) { mpf_set_ui (rdiff, (unsigned long int) (mpf_sgn (y) != 0)); } else { mp_size_t dprec; mpf_t d; TMP_DECL; TMP_MARK; dprec = PREC(rdiff) + ABSIZ(x); ASSERT (PREC(rdiff)+1 == dprec - ABSIZ(x) + 1); PREC(d) = dprec; PTR(d) = TMP_ALLOC_LIMBS (dprec + 1); mpf_sub (d, x, y); SIZ(d) = ABSIZ(d); mpf_div (rdiff, d, x); TMP_FREE; } }
void mpz_divexact (mpz_ptr quot, mpz_srcptr num, mpz_srcptr den) { mp_ptr qp; mp_size_t qn; mp_srcptr np, dp; mp_size_t nn, dn; TMP_DECL; #if WANT_ASSERT { mpz_t rem; mpz_init (rem); mpz_tdiv_r (rem, num, den); ASSERT (SIZ(rem) == 0); mpz_clear (rem); } #endif nn = ABSIZ (num); dn = ABSIZ (den); if (nn < dn) { /* This special case avoids segfaults below when the function is incorrectly called with |N| < |D|, N != 0. It also handles the well-defined case N = 0. */ SIZ(quot) = 0; return; } qn = nn - dn + 1; TMP_MARK; if (quot == num || quot == den) qp = TMP_ALLOC_LIMBS (qn); else qp = MPZ_REALLOC (quot, qn); np = PTR(num); dp = PTR(den); mpn_divexact (qp, np, nn, dp, dn); MPN_NORMALIZE (qp, qn); if (qp != PTR(quot)) MPN_COPY (MPZ_REALLOC (quot, qn), qp, qn); SIZ(quot) = (SIZ(num) ^ SIZ(den)) >= 0 ? qn : -qn; TMP_FREE; }
void check_print (mpf_srcptr src, mpf_srcptr got, mpf_srcptr want) { mp_trace_base = 16; mpf_trace ("src ", src); mpf_trace ("got ", got); mpf_trace ("want", want); printf ("got size=%d exp=%ld\n", SIZ(got), EXP(got)); mpn_trace (" limbs=", PTR(got), (mp_size_t) ABSIZ(got)); printf ("want size=%d exp=%ld\n", SIZ(want), EXP(want)); mpn_trace (" limbs=", PTR(want), (mp_size_t) ABSIZ(want)); }
int _mpq_cmp_si (mpq_srcptr q, long n, unsigned long d) { /* need canonical sign to get right result */ ASSERT (SIZ(DEN(q)) > 0); if (SIZ(NUM(q)) >= 0) { if (n >= 0) return _mpq_cmp_ui (q, n, d); /* >=0 cmp >=0 */ else return 1; /* >=0 cmp <0 */ } else { if (n >= 0) return -1; /* <0 cmp >=0 */ else { mpq_t qabs; SIZ(NUM(qabs)) = ABSIZ(NUM(q)); PTR(NUM(qabs)) = PTR(NUM(q)); SIZ(DEN(qabs)) = SIZ(DEN(q)); PTR(DEN(qabs)) = PTR(DEN(q)); return - _mpq_cmp_ui (qabs, NEG_CAST (unsigned long, n), d); /* <0 cmp <0 */ } } }
size_t mpz_sizeinbase (mpz_srcptr x, int base) { size_t result; MPN_SIZEINBASE (result, PTR(x), ABSIZ(x), base); return result; }
int mpz_divisible_2exp_p (mpz_srcptr a, unsigned long d) { unsigned long i, dlimbs, dbits; mp_ptr ap; mp_limb_t dmask; mp_size_t asize; asize = ABSIZ(a); dlimbs = d / GMP_NUMB_BITS; /* if d covers the whole of a, then only a==0 is divisible */ if (asize <= dlimbs) return asize == 0; /* whole limbs must be zero */ ap = PTR(a); for (i = 0; i < dlimbs; i++) if (ap[i] != 0) return 0; /* left over bits must be zero */ dbits = d % GMP_NUMB_BITS; dmask = (CNST_LIMB(1) << dbits) - 1; return (ap[dlimbs] & dmask) == 0; }
void mpz_realloc2 (mpz_ptr m, mp_bitcnt_t bits) { mp_size_t new_alloc; bits -= (bits != 0); /* Round down, except if 0 */ new_alloc = 1 + bits / GMP_NUMB_BITS; if (sizeof (unsigned long) > sizeof (int)) /* param vs _mp_size field */ { if (UNLIKELY (new_alloc > INT_MAX)) { fprintf (stderr, "gmp: overflow in mpz type\n"); abort (); } } PTR(m) = __GMP_REALLOCATE_FUNC_LIMBS (PTR(m), ALLOC(m), new_alloc); ALLOC(m) = new_alloc; /* Don't create an invalid number; if the current value doesn't fit after reallocation, clear it to 0. */ if (ABSIZ(m) > new_alloc) SIZ(m) = 0; }
/* Convert an mpz_t to an mpfr_exp_t, restricted to the interval [MPFR_EXP_MIN,MPFR_EXP_MAX]. */ mpfr_exp_t mpfr_ubf_zexp2exp (mpz_ptr ez) { mp_size_t n; mpfr_eexp_t e; mpfr_t d; int inex; MPFR_SAVE_EXPO_DECL (expo); n = ABSIZ (ez); /* limb size of ez */ if (n == 0) return 0; MPFR_SAVE_EXPO_MARK (expo); mpfr_init2 (d, n * GMP_NUMB_BITS); MPFR_DBGRES (inex = mpfr_set_z (d, ez, MPFR_RNDN)); MPFR_ASSERTD (inex == 0); e = mpfr_get_exp_t (d, MPFR_RNDZ); mpfr_clear (d); MPFR_SAVE_EXPO_FREE (expo); if (MPFR_UNLIKELY (e < MPFR_EXP_MIN)) return MPFR_EXP_MIN; if (MPFR_UNLIKELY (e > MPFR_EXP_MAX)) return MPFR_EXP_MAX; return e; }
void mpz_combit (mpz_ptr d, unsigned long int bit_index) { mp_size_t dsize = ABSIZ(d); mp_ptr dp = LIMBS(d); mp_size_t limb_index = bit_index / GMP_NUMB_BITS; mp_limb_t bit = ((mp_limb_t) 1 << (bit_index % GMP_NUMB_BITS)); if (limb_index >= dsize) { MPZ_REALLOC(d, limb_index + 1); dp = LIMBS(d); MPN_ZERO(dp + dsize, limb_index + 1 - dsize); dsize = limb_index + 1; } if (SIZ(d) >= 0) { dp[limb_index] ^= bit; MPN_NORMALIZE (dp, dsize); SIZ(d) = dsize; } else { mp_limb_t x = -dp[limb_index]; mp_size_t i; /* non-zero limb below us means ones-complement */ for (i = limb_index-1; i >= 0; i--) if (dp[i] != 0) { x--; /* change twos comp to ones comp */ break; } if (x & bit) { mp_limb_t c; /* Clearing the bit increases the magitude. We might need a carry. */ MPZ_REALLOC(d, dsize + 1); dp = LIMBS(d); __GMPN_ADD_1 (c, dp+limb_index, dp+limb_index, dsize - limb_index, bit); dp[dsize] = c; dsize += c; } else /* Setting the bit decreases the magnitude */ mpn_sub_1(dp+limb_index, dp+limb_index, dsize + limb_index, bit); MPN_NORMALIZE (dp, dsize); SIZ(d) = -dsize; } }
int mpz_cmpabs (mpz_srcptr u, mpz_srcptr v) { mp_size_t usize, vsize, dsize; mp_srcptr up, vp; int cmp; usize = ABSIZ (u); vsize = ABSIZ (v); dsize = usize - vsize; if (dsize != 0) return dsize; up = PTR(u); vp = PTR(v); MPN_CMP (cmp, up, vp, usize); return cmp; }
int mpz_invert (mpz_ptr inverse, mpz_srcptr x, mpz_srcptr n) { mpz_t gcd, tmp; mp_size_t xsize, nsize, size; TMP_DECL; xsize = ABSIZ (x); nsize = ABSIZ (n); /* No inverse exists if the leftside operand is 0. Likewise, no inverse exists if the mod operand is 1. */ if (xsize == 0 || (nsize == 1 && (PTR (n))[0] == 1)) return 0; size = MAX (xsize, nsize) + 1; TMP_MARK; MPZ_TMP_INIT (gcd, size); MPZ_TMP_INIT (tmp, size); mpz_gcdext (gcd, tmp, (mpz_ptr) 0, x, n); /* If no inverse existed, return with an indication of that. */ if (!MPZ_EQUAL_1_P (gcd)) { TMP_FREE; return 0; } /* Make sure we return a positive inverse. */ if (SIZ (tmp) < 0) { if (SIZ (n) < 0) mpz_sub (inverse, tmp, n); else mpz_add (inverse, tmp, n); } else mpz_set (inverse, tmp); TMP_FREE; return 1; }
void dump_abort (int i, char *s, mpz_t op1, mpz_t op2, mpz_t product, mpz_t ref_product) { mp_size_t b, e; fprintf (stderr, "ERROR: %s in test %d\n", s, i); fprintf (stderr, "op1 = "); debug_mp (op1); fprintf (stderr, "op2 = "); debug_mp (op2); fprintf (stderr, " product = "); debug_mp (product); fprintf (stderr, "ref_product = "); debug_mp (ref_product); for (b = 0; b < ABSIZ(ref_product); b++) if (PTR(ref_product)[b] != PTR(product)[b]) break; for (e = ABSIZ(ref_product) - 1; e >= 0; e--) if (PTR(ref_product)[e] != PTR(product)[e]) break; printf ("ERRORS in %ld--%ld\n", b, e); abort(); }
void hexdump (mpf_t x) { mp_size_t i; for (i = ABSIZ(x) - 1; i >= 0; i--) { gmp_printf ("%0*MX", SZ, PTR(x)[i]); if (i != 0) printf (" "); } }
/* this function is useful in debug mode to print non-normalized residues */ static void mpresn_print (mpres_t x, mpmod_t n) { mp_size_t m, xn; xn = SIZ(x); m = ABSIZ(x); MPN_NORMALIZE(PTR(x), m); SIZ(x) = xn >= 0 ? m : -m; gmp_printf ("%Zd\n", x); SIZ(x) = xn; }
void check_one (mpf_ptr got, mpq_srcptr q) { mpf_t n, d; mpf_set_q (got, q); PTR(n) = PTR(&q->_mp_num); SIZ(n) = SIZ(&q->_mp_num); EXP(n) = ABSIZ(&q->_mp_num); PTR(d) = PTR(&q->_mp_den); SIZ(d) = SIZ(&q->_mp_den); EXP(d) = ABSIZ(&q->_mp_den); if (! refmpf_validate_division ("mpf_set_q", got, n, d)) { mp_trace_base = -16; mpq_trace (" q", q); abort (); } }
unsigned long refmpz_scan (mpz_srcptr z, unsigned long i, int sought) { unsigned long z_bits = (unsigned long) ABSIZ(z) * GMP_NUMB_BITS; do { if (mpz_tstbit (z, i) == sought) return i; i++; } while (i <= z_bits); return ULONG_MAX; }
void check_one (mpf_srcptr src, mpf_srcptr trunc, mpf_srcptr ceil, mpf_srcptr floor) { mpf_t got; mpf_init2 (got, mpf_get_prec (trunc)); ASSERT_ALWAYS (PREC(got) == PREC(trunc)); ASSERT_ALWAYS (PREC(got) == PREC(ceil)); ASSERT_ALWAYS (PREC(got) == PREC(floor)); #define CHECK_SEP(name, fun, want) \ mpf_set_ui (got, 54321L); /* initial junk */ \ fun (got, src); \ MPF_CHECK_FORMAT (got); \ if (mpf_cmp (got, want) != 0) \ { \ printf ("%s wrong\n", name); \ check_print (src, got, want); \ abort (); \ } CHECK_SEP ("mpf_trunc", mpf_trunc, trunc); CHECK_SEP ("mpf_ceil", mpf_ceil, ceil); CHECK_SEP ("mpf_floor", mpf_floor, floor); #define CHECK_INPLACE(name, fun, want) \ mpf_set (got, src); \ fun (got, got); \ MPF_CHECK_FORMAT (got); \ if (mpf_cmp (got, want) != 0) \ { \ printf ("%s wrong\n", name); \ check_print (src, got, want); \ abort (); \ } CHECK_INPLACE ("mpf_trunc", mpf_trunc, trunc); /* Can't do these unconditionally in case truncation by mpf_set strips some low non-zero limbs which would have rounded the result. */ if (ABSIZ(src) <= PREC(trunc)+1) { CHECK_INPLACE ("mpf_ceil", mpf_ceil, ceil); CHECK_INPLACE ("mpf_floor", mpf_floor, floor); } mpf_clear (got); }
/* this function is useful in debug mode to print residues */ static void mpres_print (mpres_t x, char* name, mpmod_t n) { mp_size_t m, xn; mpres_t t; mpres_init(t, n); mpz_set_ui(t, 1); mpres_mul (t, x, t, n); xn = SIZ(t); m = ABSIZ(t); MPN_NORMALIZE(PTR(t), m); SIZ(t) = xn >= 0 ? m : -m; gmp_printf ("%s=%Zd\n", name, t); SIZ(t) = xn; mpres_clear (t, n); }
void mpz_tdiv_r_2exp (mpz_ptr res, mpz_srcptr in, mp_bitcnt_t cnt) { mp_size_t in_size = ABSIZ (in); mp_size_t res_size; mp_size_t limb_cnt = cnt / GMP_NUMB_BITS; mp_srcptr in_ptr = PTR (in); if (in_size > limb_cnt) { /* The input operand is (probably) greater than 2**CNT. */ mp_limb_t x; x = in_ptr[limb_cnt] & (((mp_limb_t) 1 << cnt % GMP_NUMB_BITS) - 1); if (x != 0) { res_size = limb_cnt + 1; MPZ_REALLOC (res, res_size); PTR (res)[limb_cnt] = x; } else { res_size = limb_cnt; MPN_NORMALIZE (in_ptr, res_size); MPZ_REALLOC (res, res_size); limb_cnt = res_size; } } else { /* The input operand is smaller than 2**CNT. We perform a no-op, apart from that we might need to copy IN to RES. */ res_size = in_size; MPZ_REALLOC (res, res_size); limb_cnt = res_size; } if (res != in) MPN_COPY (PTR (res), PTR (in), limb_cnt); SIZ (res) = SIZ (in) >= 0 ? res_size : -res_size; }
void * _mpz_realloc (mpz_ptr m, mp_size_t new_alloc) { mp_ptr mp; /* Never allocate zero space. */ new_alloc = MAX (new_alloc, 1); mp = __GMP_REALLOCATE_FUNC_LIMBS (PTR(m), ALLOC(m), new_alloc); PTR(m) = mp; ALLOC(m) = new_alloc; /* Don't create an invalid number; if the current value doesn't fit after reallocation, clear it to 0. */ if (ABSIZ(m) > new_alloc) SIZ(m) = 0; return (void *) mp; }
void mpq_abs (mpq_ptr dst, mpq_srcptr src) { mp_size_t num_abs_size = ABSIZ(NUM(src)); if (dst != src) { mp_size_t den_size = SIZ(DEN(src)); mp_ptr dp; dp = MPZ_NEWALLOC (NUM(dst), num_abs_size); MPN_COPY (dp, PTR(NUM(src)), num_abs_size); dp = MPZ_NEWALLOC (DEN(dst), den_size); SIZ(DEN(dst)) = den_size; MPN_COPY (dp, PTR(DEN(src)), den_size); } SIZ(NUM(dst)) = num_abs_size; }
void gmp_randinit_lc (gmp_randstate_t rstate, mpz_srcptr a, unsigned long int c, mpz_srcptr m) { /* FIXME: Not finished. We don't handle this in _gmp_rand() yet. */ abort (); mpz_init_set_ui (rstate->_mp_seed, 1); _mpz_realloc (rstate->_mp_seed, ABSIZ (m)); /* Allocate algorithm specific data. */ rstate->_mp_algdata._mp_lc = (__gmp_randata_lc *) (*__gmp_allocate_func) (sizeof (__gmp_randata_lc)); mpz_init_set (rstate->_mp_algdata._mp_lc->_mp_a, a); rstate->_mp_algdata._mp_lc->_mp_c = c; mpz_init_set (rstate->_mp_algdata._mp_lc->_mp_m, m); rstate->_mp_alg = GMP_RAND_ALG_LC; }
void * _mpz_realloc (mpz_ptr m, mp_size_t new_alloc) { mp_ptr mp; /* Never allocate zero space. */ new_alloc = MAX (new_alloc, 1); if (sizeof (mp_size_t) == sizeof (int)) { if (UNLIKELY (new_alloc > ULONG_MAX / GMP_NUMB_BITS)) { fprintf (stderr, "gmp: overflow in mpz type\n"); abort (); } } else { if (UNLIKELY (new_alloc > INT_MAX)) { fprintf (stderr, "gmp: overflow in mpz type\n"); abort (); } } mp = __GMP_REALLOCATE_FUNC_LIMBS (PTR(m), ALLOC(m), new_alloc); PTR(m) = mp; ALLOC(m) = (int) new_alloc; // (int) added by PM /* Don't create an invalid number; if the current value doesn't fit after reallocation, clear it to 0. */ if (ABSIZ(m) > new_alloc) SIZ(m) = 0; return (void *) mp; }
int mpz_ui_kronecker (unsigned long a, mpz_srcptr b) { mp_srcptr b_ptr; mp_limb_t b_low; int b_abs_size; mp_limb_t b_rem; int twos; int result_bit1; /* (a/-1)=1 when a>=0, so the sign of b is ignored */ b_abs_size = ABSIZ (b); if (b_abs_size == 0) return JACOBI_U0 (a); /* (a/0) */ if (a > GMP_NUMB_MAX) { mp_limb_t alimbs[2]; mpz_t az; ALLOC(az) = numberof (alimbs); PTR(az) = alimbs; mpz_set_ui (az, a); return mpz_kronecker (az, b); } b_ptr = PTR(b); b_low = b_ptr[0]; result_bit1 = 0; if (! (b_low & 1)) { /* (0/b)=0 for b!=+/-1; and (even/even)=0 */ if (! (a & 1)) return 0; /* a odd, b even Establish shifted b_low with valid bit1 for the RECIP below. Zero limbs stripped are accounted for, but zero bits on b_low are not because they remain in {b_ptr,b_abs_size} for JACOBI_MOD_OR_MODEXACT_1_ODD. */ JACOBI_STRIP_LOW_ZEROS (result_bit1, a, b_ptr, b_abs_size, b_low); if (! (b_low & 1)) { if (UNLIKELY (b_low == GMP_NUMB_HIGHBIT)) { /* need b_ptr[1] to get bit1 in b_low */ if (b_abs_size == 1) { /* (a/0x80...00) == (a/2)^(NUMB-1) */ if ((GMP_NUMB_BITS % 2) == 0) { /* JACOBI_STRIP_LOW_ZEROS does nothing to result_bit1 when GMP_NUMB_BITS is even, so it's still 0. */ ASSERT (result_bit1 == 0); result_bit1 = JACOBI_TWO_U_BIT1 (a); } return JACOBI_BIT1_TO_PN (result_bit1); } /* b_abs_size > 1 */ b_low = b_ptr[1] << 1; } else { count_trailing_zeros (twos, b_low); b_low >>= twos; } } } else { if (a == 0) /* (0/b)=1 for b=+/-1, 0 otherwise */
int mpz_congruent_2exp_p (mpz_srcptr a, mpz_srcptr c, mp_bitcnt_t d) { mp_size_t i, dlimbs; unsigned dbits; mp_ptr ap, cp; mp_limb_t dmask, alimb, climb, sum; mp_size_t asize_signed, csize_signed, asize, csize; if (ABSIZ(a) < ABSIZ(c)) MPZ_SRCPTR_SWAP (a, c); dlimbs = d / GMP_NUMB_BITS; dbits = d % GMP_NUMB_BITS; dmask = (CNST_LIMB(1) << dbits) - 1; ap = PTR(a); cp = PTR(c); asize_signed = SIZ(a); asize = ABS(asize_signed); csize_signed = SIZ(c); csize = ABS(csize_signed); if (csize_signed == 0) goto a_zeros; if ((asize_signed ^ csize_signed) >= 0) { /* same signs, direct comparison */ /* a==c for limbs in common */ if (mpn_cmp (ap, cp, MIN (csize, dlimbs)) != 0) return 0; /* if that's all of dlimbs, then a==c for remaining bits */ if (csize > dlimbs) return ((ap[dlimbs]-cp[dlimbs]) & dmask) == 0; a_zeros: /* a remains, need all zero bits */ /* if d covers all of a and c, then must be exactly equal */ if (asize <= dlimbs) return asize == csize; /* whole limbs zero */ for (i = csize; i < dlimbs; i++) if (ap[i] != 0) return 0; /* partial limb zero */ return (ap[dlimbs] & dmask) == 0; } else { /* different signs, negated comparison */ /* common low zero limbs, stopping at first non-zeros, which must match twos complement */ i = 0; for (;;) { ASSERT (i < csize); /* always have a non-zero limb on c */ alimb = ap[i]; climb = cp[i]; sum = (alimb + climb) & GMP_NUMB_MASK; if (i >= dlimbs) return (sum & dmask) == 0; i++; /* require both zero, or first non-zeros as twos-complements */ if (sum != 0) return 0; if (alimb != 0) break; } /* further limbs matching as ones-complement */ for (;;) { if (i >= csize) break; alimb = ap[i]; climb = cp[i]; sum = (alimb + climb + 1) & GMP_NUMB_MASK; if (i >= dlimbs) return (sum & dmask) == 0; if (sum != 0) return 0; i++; } /* no more c, so require all 1 bits in a */ if (asize < dlimbs) return 0; /* not enough a */ /* whole limbs */ for ( ; i < dlimbs; i++) if (ap[i] != GMP_NUMB_MAX) return 0; /* if only whole limbs, no further fetches from a */ if (dbits == 0) return 1; /* need enough a */ if (asize == dlimbs) return 0; return ((ap[dlimbs]+1) & dmask) == 0; } }
void check_z (void) { static const struct { const char *fmt; const char *z; const char *want; } data[] = { { "%Zd", "0", "0" }, { "%Zd", "1", "1" }, { "%Zd", "123", "123" }, { "%Zd", "-1", "-1" }, { "%Zd", "-123", "-123" }, { "%+Zd", "0", "+0" }, { "%+Zd", "123", "+123" }, { "%+Zd", "-123", "-123" }, { "%Zx", "123", "7b" }, { "%ZX", "123", "7B" }, { "%Zx", "-123", "-7b" }, { "%ZX", "-123", "-7B" }, { "%Zo", "123", "173" }, { "%Zo", "-123", "-173" }, { "%#Zx", "0", "0" }, { "%#ZX", "0", "0" }, { "%#Zx", "123", "0x7b" }, { "%#ZX", "123", "0X7B" }, { "%#Zx", "-123", "-0x7b" }, { "%#ZX", "-123", "-0X7B" }, { "%#Zo", "0", "0" }, { "%#Zo", "123", "0173" }, { "%#Zo", "-123", "-0173" }, { "%10Zd", "0", " 0" }, { "%10Zd", "123", " 123" }, { "%10Zd", "-123", " -123" }, { "%-10Zd", "0", "0 " }, { "%-10Zd", "123", "123 " }, { "%-10Zd", "-123", "-123 " }, { "%+10Zd", "123", " +123" }, { "%+-10Zd", "123", "+123 " }, { "%+10Zd", "-123", " -123" }, { "%+-10Zd", "-123", "-123 " }, { "%08Zd", "0", "00000000" }, { "%08Zd", "123", "00000123" }, { "%08Zd", "-123", "-0000123" }, { "%+08Zd", "0", "+0000000" }, { "%+08Zd", "123", "+0000123" }, { "%+08Zd", "-123", "-0000123" }, { "%#08Zx", "0", "00000000" }, { "%#08Zx", "123", "0x00007b" }, { "%#08Zx", "-123", "-0x0007b" }, { "%+#08Zx", "0", "+0000000" }, { "%+#08Zx", "123", "+0x0007b" }, { "%+#08Zx", "-123", "-0x0007b" }, { "%.0Zd", "0", "" }, { "%.1Zd", "0", "0" }, { "%.2Zd", "0", "00" }, { "%.3Zd", "0", "000" }, }; int i, j; mpz_t z; char *nfmt; mp_size_t nsize, zeros; mpz_init (z); for (i = 0; i < numberof (data); i++) { mpz_set_str_or_abort (z, data[i].z, 0); /* don't try negatives or forced sign in hex or octal */ if (mpz_fits_slong_p (z) && ! (hex_or_octal_p (data[i].fmt) && (strchr (data[i].fmt, '+') != NULL || mpz_sgn(z) < 0))) { check_plain (data[i].want, data[i].fmt, mpz_get_si (z)); } check_one (data[i].want, data[i].fmt, z); /* Same again, with %N and possibly some high zero limbs */ nfmt = __gmp_allocate_strdup (data[i].fmt); for (j = 0; nfmt[j] != '\0'; j++) if (nfmt[j] == 'Z') nfmt[j] = 'N'; for (zeros = 0; zeros <= 3; zeros++) { nsize = ABSIZ(z)+zeros; MPZ_REALLOC (z, nsize); nsize = (SIZ(z) >= 0 ? nsize : -nsize); refmpn_zero (PTR(z)+ABSIZ(z), zeros); check_one (data[i].want, nfmt, PTR(z), nsize); } __gmp_free_func (nfmt, strlen(nfmt)+1); } mpz_clear (z); }
void mpz_powm_sec (mpz_ptr r, mpz_srcptr b, mpz_srcptr e, mpz_srcptr m) { mp_size_t n; mp_ptr rp, tp; mp_srcptr bp, ep, mp; mp_size_t rn, bn, es, en; TMP_DECL; n = ABSIZ(m); mp = PTR(m); if (UNLIKELY ((n == 0) || (mp[0] % 2 == 0))) DIVIDE_BY_ZERO; es = SIZ(e); if (UNLIKELY (es <= 0)) { if (es == 0) { /* b^0 mod m, b is anything and m is non-zero. Result is 1 mod m, i.e., 1 or 0 depending on if m = 1. */ SIZ(r) = n != 1 || mp[0] != 1; PTR(r)[0] = 1; return; } DIVIDE_BY_ZERO; } en = es; bn = ABSIZ(b); if (UNLIKELY (bn == 0)) { SIZ(r) = 0; return; } TMP_MARK; tp = TMP_ALLOC_LIMBS (n + mpn_sec_powm_itch (bn, en * GMP_NUMB_BITS, n)); rp = tp; tp += n; bp = PTR(b); ep = PTR(e); mpn_sec_powm (rp, bp, bn, ep, en * GMP_NUMB_BITS, mp, n, tp); rn = n; MPN_NORMALIZE (rp, rn); if ((ep[0] & 1) && SIZ(b) < 0 && rn != 0) { mpn_sub (rp, PTR(m), n, rp, rn); rn = n; MPN_NORMALIZE (rp, rn); } MPZ_REALLOC (r, rn); SIZ(r) = rn; MPN_COPY (PTR(r), rp, rn); TMP_FREE; }
void mpz_urandomm (mpz_ptr rop, gmp_randstate_t rstate, mpz_srcptr n) { mp_ptr rp, np, nlast; mp_size_t nbits, size; int count; int pow2; int cmp; TMP_DECL; size = ABSIZ (n); if (size == 0) DIVIDE_BY_ZERO; nlast = &PTR (n)[size - 1]; /* Detect whether n is a power of 2. */ pow2 = POW2_P (*nlast); if (pow2 != 0) for (np = PTR (n); np < nlast; np++) if (*np != 0) { pow2 = 0; /* Mark n as `not a power of two'. */ break; } count_leading_zeros (count, *nlast); nbits = size * GMP_NUMB_BITS - (count - GMP_NAIL_BITS) - pow2; if (nbits == 0) /* nbits == 0 means that n was == 1. */ { SIZ (rop) = 0; return; } TMP_MARK; np = PTR (n); if (rop == n) { mp_ptr tp; tp = TMP_ALLOC_LIMBS (size); MPN_COPY (tp, np, size); np = tp; } /* Here the allocated size can be one too much if n is a power of (2^GMP_NUMB_BITS) but it's convenient for using mpn_cmp below. */ rp = MPZ_REALLOC (rop, size); /* Clear last limb to prevent the case in which size is one too much. */ rp[size - 1] = 0; count = MAX_URANDOMM_ITER; /* Set iteration count limit. */ do { _gmp_rand (rp, rstate, nbits); MPN_CMP (cmp, rp, np, size); } while (cmp >= 0 && --count != 0); if (count == 0) /* Too many iterations; return result mod n == result - n */ mpn_sub_n (rp, rp, np, size); MPN_NORMALIZE (rp, size); SIZ (rop) = size; TMP_FREE; }
void mpz_powm_ui (mpz_ptr r, mpz_srcptr b, unsigned long int el, mpz_srcptr m) { mp_ptr xp, tp, qp, mp, bp; mp_size_t xn, tn, mn, bn; int m_zero_cnt; int c; mp_limb_t e; TMP_DECL; mp = PTR(m); mn = ABSIZ(m); if (mn == 0) DIVIDE_BY_ZERO; if (el == 0) { /* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0 depending on if MOD equals 1. */ SIZ(r) = (mn == 1 && mp[0] == 1) ? 0 : 1; PTR(r)[0] = 1; return; } TMP_MARK; /* Normalize m (i.e. make its most significant bit set) as required by division functions below. */ count_leading_zeros (m_zero_cnt, mp[mn - 1]); m_zero_cnt -= GMP_NAIL_BITS; if (m_zero_cnt != 0) { mp_ptr new_mp = TMP_ALLOC_LIMBS (mn); mpn_lshift (new_mp, mp, mn, m_zero_cnt); mp = new_mp; } bn = ABSIZ(b); bp = PTR(b); if (bn > mn) { /* Reduce possibly huge base. Use a function call to reduce, since we don't want the quotient allocation to live until function return. */ mp_ptr new_bp = TMP_ALLOC_LIMBS (mn); reduce (new_bp, bp, bn, mp, mn); bp = new_bp; bn = mn; /* Canonicalize the base, since we are potentially going to multiply with it quite a few times. */ MPN_NORMALIZE (bp, bn); } if (bn == 0) { SIZ(r) = 0; TMP_FREE; return; } tp = TMP_ALLOC_LIMBS (2 * mn + 1); xp = TMP_ALLOC_LIMBS (mn); qp = TMP_ALLOC_LIMBS (mn + 1); MPN_COPY (xp, bp, bn); xn = bn; e = el; count_leading_zeros (c, e); e = (e << c) << 1; /* shift the exp bits to the left, lose msb */ c = BITS_PER_MP_LIMB - 1 - c; /* Main loop. */ /* If m is already normalized (high bit of high limb set), and b is the same size, but a bigger value, and e==1, then there's no modular reductions done and we can end up with a result out of range at the end. */ if (c == 0) { if (xn == mn && mpn_cmp (xp, mp, mn) >= 0) mpn_sub_n (xp, xp, mp, mn); goto finishup; } while (c != 0) { mpn_sqr_n (tp, xp, xn); tn = 2 * xn; tn -= tp[tn - 1] == 0; if (tn < mn) { MPN_COPY (xp, tp, tn); xn = tn; } else { mpn_tdiv_qr (qp, xp, 0L, tp, tn, mp, mn); xn = mn; } if ((mp_limb_signed_t) e < 0) { mpn_mul (tp, xp, xn, bp, bn); tn = xn + bn; tn -= tp[tn - 1] == 0; if (tn < mn) { MPN_COPY (xp, tp, tn); xn = tn; } else { mpn_tdiv_qr (qp, xp, 0L, tp, tn, mp, mn); xn = mn; } } e <<= 1; c--; } finishup: /* We shifted m left m_zero_cnt steps. Adjust the result by reducing it with the original MOD. */ if (m_zero_cnt != 0) { mp_limb_t cy; cy = mpn_lshift (tp, xp, xn, m_zero_cnt); tp[xn] = cy; xn += cy != 0; if (xn < mn) { MPN_COPY (xp, tp, xn); } else { mpn_tdiv_qr (qp, xp, 0L, tp, xn, mp, mn); xn = mn; } mpn_rshift (xp, xp, xn, m_zero_cnt); } MPN_NORMALIZE (xp, xn); if ((el & 1) != 0 && SIZ(b) < 0 && xn != 0) { mp = PTR(m); /* want original, unnormalized m */ mpn_sub (xp, mp, mn, xp, xn); xn = mn; MPN_NORMALIZE (xp, xn); } MPZ_REALLOC (r, xn); SIZ (r) = xn; MPN_COPY (PTR(r), xp, xn); TMP_FREE; }
void mpz_gcdext (mpz_ptr g, mpz_ptr s, mpz_ptr t, mpz_srcptr a, mpz_srcptr b) { mp_size_t asize, bsize; mp_ptr tmp_ap, tmp_bp; mp_size_t gsize, ssize, tmp_ssize; mp_ptr gp, tmp_gp, tmp_sp; TMP_DECL; /* mpn_gcdext requires that Usize >= Vsize. Therefore, we often have to swap U and V. The computed cofactor will be the "smallest" one, which is faster to produce. The wanted one will be computed here; this is needed anyway when both are requested. */ asize = ABSIZ (a); bsize = ABSIZ (b); if (asize < bsize) { MPZ_SRCPTR_SWAP (a, b); MP_SIZE_T_SWAP (asize, bsize); MPZ_PTR_SWAP (s, t); } if (bsize == 0) { /* g = |a|, s = sgn(a), t = 0. */ ssize = SIZ (a) >= 0 ? (asize != 0) : -1; gp = MPZ_REALLOC (g, asize); MPN_COPY (gp, PTR (a), asize); SIZ (g) = asize; if (t != NULL) SIZ (t) = 0; if (s != NULL) { SIZ (s) = ssize; PTR (s)[0] = 1; } return; } TMP_MARK; TMP_ALLOC_LIMBS_2 (tmp_ap, asize, tmp_bp, bsize); MPN_COPY (tmp_ap, PTR (a), asize); MPN_COPY (tmp_bp, PTR (b), bsize); TMP_ALLOC_LIMBS_2 (tmp_gp, bsize, tmp_sp, bsize + 1); gsize = mpn_gcdext (tmp_gp, tmp_sp, &tmp_ssize, tmp_ap, asize, tmp_bp, bsize); ssize = ABS (tmp_ssize); tmp_ssize = SIZ (a) >= 0 ? tmp_ssize : -tmp_ssize; if (t != NULL) { mpz_t x; __mpz_struct gtmp, stmp; PTR (>mp) = tmp_gp; SIZ (>mp) = gsize; PTR (&stmp) = tmp_sp; SIZ (&stmp) = tmp_ssize; MPZ_TMP_INIT (x, ssize + asize + 1); mpz_mul (x, &stmp, a); mpz_sub (x, >mp, x); mpz_divexact (t, x, b); } if (s != NULL) { mp_ptr sp; sp = MPZ_REALLOC (s, ssize); MPN_COPY (sp, tmp_sp, ssize); SIZ (s) = tmp_ssize; } gp = MPZ_REALLOC (g, gsize); MPN_COPY (gp, tmp_gp, gsize); SIZ (g) = gsize; TMP_FREE; }