size_t mpn_sizeinbase (mp_srcptr xp, mp_size_t xsize, int base) { int lb_base, cnt; mp_size_t totbits; ASSERT (xsize >= 0); ASSERT (base >= 2); ASSERT (base < numberof (__mp_bases)); /* Special case for X == 0. */ if (xsize == 0) return 1; /* Calculate the total number of significant bits of X. */ count_leading_zeros (cnt, xp[xsize-1]); totbits = xsize * BITS_PER_MP_LIMB - cnt; if (POW2_P (base)) { /* Special case for powers of 2, giving exact result. */ lb_base = __mp_bases[base].big_base; return (totbits + lb_base - 1) / lb_base; } else return (size_t) (totbits * __mp_bases[base].chars_per_bit_exactly) + 1; }
/* Whether the absolute value of z is a power of 2. */ int mpz_pow2abs_p (mpz_srcptr z) { mp_size_t size, i; mp_srcptr ptr; size = SIZ (z); if (size == 0) return 0; /* zero is not a power of 2 */ size = ABS (size); ptr = PTR (z); for (i = 0; i < size-1; i++) if (ptr[i] != 0) return 0; /* non-zero low limb means not a power of 2 */ return POW2_P (ptr[i]); /* high limb power of 2 */ }
void table (int limb_bits, int nail_bits) { int numb_bits = limb_bits - nail_bits; int base; printf ("/* This file generated by gen-bases.c - DO NOT EDIT. */\n"); printf ("\n"); printf ("#include \"mpir.h\"\n"); printf ("#include \"gmp-impl.h\"\n"); printf ("\n"); printf ("#if GMP_NUMB_BITS != %d\n", numb_bits); printf ("Error, error, this data is for %d bits\n", numb_bits); printf ("#endif\n"); printf ("\n"); puts ("const struct bases mp_bases[257] =\n{"); puts (" /* 0 */ { 0, 0.0, 0 },"); puts (" /* 1 */ { 0, 1e37, 0 },"); for (base = 2; base <= 256; base++) { generate (limb_bits, nail_bits, base); printf (" /* %3u */ { ", base); if (POW2_P (base)) { printf ("%u, %.16f, 0x%x },\n", chars_per_limb, chars_per_bit_exactly, ulog2 (base) - 1); } else { printf ("%u, %.16f, CNST_LIMB(0x", chars_per_limb, chars_per_bit_exactly); mpz_out_str (stdout, 16, big_base); printf ("), CNST_LIMB(0x"); mpz_out_str (stdout, 16, big_base_inverted); printf (") },\n"); } } puts ("};"); }
unsigned long gmp_urandomm_ui (gmp_randstate_ptr rstate, unsigned long n) { mp_limb_t a[LIMBS_PER_ULONG]; unsigned long ret, bits, leading; int i; if (UNLIKELY (n == 0)) DIVIDE_BY_ZERO; /* start with zeros, since if bits==0 then _gmp_rand will store nothing at all (bits==0 arises when n==1), or if bits <= GMP_NUMB_BITS then it will store only a[0]. */ a[0] = 0; #if LIMBS_PER_ULONG > 1 a[1] = 0; #endif count_leading_zeros (leading, (mp_limb_t) n); bits = GMP_LIMB_BITS - leading - (POW2_P(n) != 0); for (i = 0; i < MAX_URANDOMM_ITER; i++) { _gmp_rand (a, rstate, bits); #if LIMBS_PER_ULONG == 1 ret = a[0]; #else ret = a[0] | (a[1] << GMP_NUMB_BITS); #endif if (LIKELY (ret < n)) /* usually one iteration suffices */ goto done; } /* Too many iterations, there must be something degenerate about the rstate algorithm. Return r%n. */ ret -= n; ASSERT (ret < n); done: return ret; }
int main (int argc, char *argv[]) { mp_limb_t want_bb, want_bb_inv; int base, want_chars_per_limb; want_chars_per_limb = refmpn_chars_per_limb (10); if (MP_BASES_CHARS_PER_LIMB_10 != want_chars_per_limb) { printf ("MP_BASES_CHARS_PER_LIMB_10 wrong\n"); abort (); } want_bb = refmpn_big_base (10); if (MP_BASES_BIG_BASE_10 != want_bb) { printf ("MP_BASES_BIG_BASE_10 wrong\n"); abort (); } want_bb_inv = refmpn_invert_limb (want_bb << refmpn_count_leading_zeros (want_bb)); if (MP_BASES_BIG_BASE_INVERTED_10 != want_bb_inv) { printf ("MP_BASES_BIG_BASE_INVERTED_10 wrong\n"); abort (); } if (MP_BASES_NORMALIZATION_STEPS_10 != refmpn_count_leading_zeros (MP_BASES_BIG_BASE_10)) { printf ("MP_BASES_NORMALIZATION_STEPS_10 wrong\n"); abort (); } for (base = 2; base < numberof (mp_bases); base++) { want_chars_per_limb = refmpn_chars_per_limb (base); if (mp_bases[base].chars_per_limb != want_chars_per_limb) { printf ("mp_bases[%d].chars_per_limb wrong\n", base); printf (" got %d\n", mp_bases[base].chars_per_limb); printf (" want %d\n", want_chars_per_limb); abort (); } if (POW2_P (base)) { want_bb = refmpn_count_trailing_zeros ((mp_limb_t) base); if (mp_bases[base].big_base != want_bb) { printf ("mp_bases[%d].big_base (log2 of base) wrong\n", base); abort (); } } else { want_bb = refmpn_big_base (base); if (mp_bases[base].big_base != want_bb) { printf ("mp_bases[%d].big_base wrong\n", base); abort (); } #if USE_PREINV_DIVREM_1 want_bb_inv = refmpn_invert_limb (want_bb << refmpn_count_leading_zeros (want_bb)); if (mp_bases[base].big_base_inverted != want_bb_inv) { printf ("mp_bases[%d].big_base_inverted wrong\n", base); abort (); } #endif } } exit (0); }
char * mpz_get_str (char *res_str, int base, mpz_srcptr x) { mp_ptr xp; mp_size_t x_size = SIZ (x); char *return_str; size_t str_size; size_t alloc_size = 0; const char *num_to_text; int i; TMP_DECL; if (base >= 0) { num_to_text = "0123456789abcdefghijklmnopqrstuvwxyz"; if (base <= 1) base = 10; else if (base > 36) { num_to_text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; if (base > 62) return NULL; } } else { base = -base; if (base <= 1) base = 10; else if (base > 36) return NULL; num_to_text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; } /* allocate string for the user if necessary */ if (res_str == NULL) { /* digits, null terminator, possible minus sign */ MPN_SIZEINBASE (alloc_size, PTR(x), ABS(x_size), base); alloc_size += 1 + (x_size<0); res_str = (char *) (*__gmp_allocate_func) (alloc_size); } return_str = res_str; if (x_size < 0) { *res_str++ = '-'; x_size = -x_size; } /* mpn_get_str clobbers its input on non power-of-2 bases */ TMP_MARK; xp = PTR (x); if (! POW2_P (base)) { xp = TMP_ALLOC_LIMBS (x_size | 1); /* |1 in case x_size==0 */ MPN_COPY (xp, PTR (x), x_size); } str_size = mpn_get_str ((unsigned char *) res_str, base, xp, x_size); ASSERT (alloc_size == 0 || str_size <= alloc_size - (SIZ(x) < 0)); /* Convert result to printable chars. */ for (i = 0; i < str_size; i++) res_str[i] = num_to_text[(int) res_str[i]]; res_str[str_size] = 0; TMP_FREE; /* if allocated then resize down to the actual space required */ if (alloc_size != 0) { size_t actual_size = str_size + 1 + (res_str - return_str); ASSERT (actual_size == strlen (return_str) + 1); __GMP_REALLOCATE_FUNC_MAYBE_TYPE (return_str, alloc_size, actual_size, char); } return return_str; }
void table (int limb_bits, int nail_bits) { int numb_bits = limb_bits - nail_bits; int base; mpz_t r, t, logb2, log2b; mpz_init (r); mpz_init (t); mpz_init (logb2); mpz_init (log2b); printf ("/* This file generated by gen-bases.c - DO NOT EDIT. */\n"); printf ("\n"); printf ("#include \"gmp.h\"\n"); printf ("#include \"gmp-impl.h\"\n"); printf ("\n"); printf ("#if GMP_NUMB_BITS != %d\n", numb_bits); printf ("Error, error, this data is for %d bits\n", numb_bits); printf ("#endif\n"); printf ("\n"); puts ("const struct bases mp_bases[257] =\n{"); puts (" /* 0 */ { 0, 0, 0, 0, 0 },"); puts (" /* 1 */ { 0, 0, 0, 0, 0 },"); for (base = 2; base <= 256; base++) { generate (limb_bits, nail_bits, base); mp_2logb (r, base, limb_bits + 8); mpz_tdiv_q_2exp (logb2, r, 8); mpz_set_ui (t, 1); mpz_mul_2exp (t, t, 2*limb_bits + 5); mpz_sub_ui (t, t, 1); mpz_add_ui (r, r, 1); mpz_tdiv_q (log2b, t, r); printf (" /* %3u */ { ", base); if (POW2_P (base)) { mpz_set_ui (big_base, ulog2 (base) - 1); mpz_set_ui (big_base_inverted, 0); } printf ("%u,", chars_per_limb); printf (" CNST_LIMB(0x"); mpz_out_str (stdout, 16, logb2); printf ("), CNST_LIMB(0x"); mpz_out_str (stdout, 16, log2b); printf ("), CNST_LIMB(0x"); mpz_out_str (stdout, 16, big_base); printf ("), CNST_LIMB(0x"); mpz_out_str (stdout, 16, big_base_inverted); printf (") },\n"); } puts ("};"); mpz_clear (r); mpz_clear (t); mpz_clear (logb2); mpz_clear (log2b); }
size_t mpz_out_str (FILE *stream, int base, mpz_srcptr x) { mp_ptr xp; mp_size_t x_size = SIZ (x); unsigned char *str; size_t str_size; size_t i; size_t written; const char *num_to_text; TMP_DECL; if (stream == 0) stream = stdout; if (base >= 0) { num_to_text = "0123456789abcdefghijklmnopqrstuvwxyz"; if (base <= 1) base = 10; else if (base > 36) { num_to_text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; if (base > 62) return 0; } } else { base = -base; if (base <= 1) base = 10; else if (base > 36) return 0; num_to_text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; } written = 0; if (x_size < 0) { fputc ('-', stream); x_size = -x_size; written = 1; } TMP_MARK; DIGITS_IN_BASE_PER_LIMB (str_size, x_size, base); str_size += 3; str = (unsigned char *) TMP_ALLOC (str_size); xp = PTR (x); if (! POW2_P (base)) { xp = TMP_ALLOC_LIMBS (x_size | 1); /* |1 in case x_size==0 */ MPN_COPY (xp, PTR (x), x_size); } str_size = mpn_get_str (str, base, xp, x_size); /* Convert result to printable chars. */ for (i = 0; i < str_size; i++) str[i] = num_to_text[str[i]]; str[str_size] = 0; { size_t fwret; fwret = fwrite ((char *) str, 1, str_size, stream); written += fwret; } TMP_FREE; return ferror (stream) ? 0 : written; }
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; }
int main (int argc, char *argv[]) { mp_limb_t bb, h, l, bb_inv; int i, j; for (i = 2; i < numberof (mp_bases); i++) { if (POW2_P (i)) { count_trailing_zeros (j, i); if (mp_bases[i].big_base != (mp_limb_t) j) { printf ("mp_bases[%d].big_base (trailing zeros) wrong\n", i); abort (); } } else { bb = 1; for (j = 0; j < mp_bases[i].chars_per_limb; j++) { umul_ppmm (h, bb, bb, i); if (h != 0 || (bb & GMP_NAIL_MASK) != 0) { printf ("mp_bases[%d].chars_per_limb overflow\n", i); abort (); } } umul_ppmm (h, l, bb, i); if (h == 0 && (l & GMP_NAIL_MASK) == 0) { printf ("mp_bases[%d].chars_per_limb too small\n", i); abort (); } if (mp_bases[i].big_base != bb) { printf ("mp_bases[%d].big_base wrong\n", i); abort (); } invert_limb (bb_inv, bb << refmpn_count_leading_zeros (bb)); if (mp_bases[i].big_base_inverted != bb_inv) { printf ("mp_bases[%d].big_base_inverted wrong\n", i); abort (); } } } if (MP_BASES_CHARS_PER_LIMB_10 != mp_bases[10].chars_per_limb) { printf ("MP_BASES_CHARS_PER_LIMB_10 not the same as mp_bases[10].chars_per_limb\n"); abort (); } if (MP_BASES_BIG_BASE_10 != mp_bases[10].big_base) { printf ("MP_BASES_BIG_BASE_10 not the same as mp_bases[10].big_base\n"); abort (); } if (MP_BASES_BIG_BASE_INVERTED_10 != mp_bases[10].big_base_inverted) { printf ("MP_BASES_BIG_BASE_INVERTED_10 not the same as mp_bases[10].big_base_inverted\n"); abort (); } if (MP_BASES_NORMALIZATION_STEPS_10 != refmpn_count_leading_zeros (MP_BASES_BIG_BASE_10)) { printf ("MP_BASES_NORMALIZATION_STEPS_10 wrong\n"); abort (); } exit (0); }