#include <gmp.h>
#include "ulong_extras.h"
#include "mpn_extras.h"
#include "fmpz.h"
void
fmpz_randbits_unsigned(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits)
{
if (bits <= SMALL_FMPZ_BITCOUNT_MAX)
{
_fmpz_demote(f);
*f = n_randbits(state, bits);
}
else
{
mpz_ptr mf = _fmpz_promote(f);
mp_size_t n = BITS_TO_LIMBS(bits);
mp_ptr zd = FLINT_MPZ_REALLOC(mf, n);
flint_mpn_urandomb(zd, state, bits);
MPN_NORM(zd, n);
mf->_mp_size = n;
mpz_setbit(mf, bits - 1);
_fmpz_demote_val(f);
}
}
void
fmpz_randbits(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits)
{
fmpz_randbits_unsigned(f, state, bits);
if (n_randint(state, 2))
fmpz_neg(f, f);
}
void
fmpz_randm(fmpz_t f, flint_rand_t state, const fmpz_t m)
{
flint_bitcnt_t bits = fmpz_bits(m);
int sgn = fmpz_sgn(m);
if (bits <= SMALL_FMPZ_BITCOUNT_MAX)
{
_fmpz_demote(f);
*f = (sgn >= 0) ? n_randint(state, *m) : - n_randint(state, -(*m));
}
else if (f == m)
{
fmpz_t t;
fmpz_init(t);
fmpz_randm(t, state, m);
fmpz_swap(f, t);
fmpz_clear(t);
}
else
{
mpz_ptr mf = _fmpz_promote(f);
mp_size_t n = BITS_TO_LIMBS(bits);
mp_ptr zd = FLINT_MPZ_REALLOC(mf, n);
flint_mpn_urandomm(zd, state, COEFF_TO_PTR(*m)->_mp_d, n);
MPN_NORM(zd, n);
mf->_mp_size = n;
if (sgn < 0)
mpz_neg(mf, mf);
_fmpz_demote_val(f);
}
}
void fmpz_randprime(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits, int proved)
{
if (bits <= FLINT_BITS)
{
fmpz_set_ui(f, n_randprime(state, bits, proved));
}
else
{
do
{
fmpz_randbits_unsigned(f, state, bits);
fmpz_nextprime(f, f, proved);
} while (fmpz_bits(f) != bits);
}
}
void
fmpz_randtest(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits)
{
ulong m;
fmpz_randtest_unsigned(f, state, bits);
m = n_randlimb(state);
if (m & UWORD(1))
fmpz_neg(f, f);
}
void
fmpz_randtest_unsigned(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits)
{
ulong m;
m = n_randlimb(state);
bits = n_randint(state, bits + 1);
if (bits <= SMALL_FMPZ_BITCOUNT_MAX)
{
_fmpz_demote(f);
if (m & UWORD(3))
*f = n_randtest_bits(state, bits);
else
{
m >>= 2;
if (bits == 0)
*f = 0;
else if (bits < SMALL_FMPZ_BITCOUNT_MAX)
*f = m & UWORD(1);
else
*f = COEFF_MAX;
}
}
else
{
mpz_ptr mf = _fmpz_promote(f);
mp_size_t n = BITS_TO_LIMBS(bits);
mp_ptr zd = FLINT_MPZ_REALLOC(mf, n);
flint_mpn_rrandomb(zd, state, bits);
MPN_NORM(zd, n);
mf->_mp_size = n;
_fmpz_demote_val(f);
}
}
void
fmpz_randtest_not_zero(fmpz_t f, flint_rand_t state, flint_bitcnt_t bits)
{
if (bits == 0)
{
flint_throw(FLINT_ERROR, "Exception (fmpz_randtest_not_zero). bits == 0.\n");
}
fmpz_randtest(f, state, bits);
if (fmpz_is_zero(f))
fmpz_one(f);
}
void
fmpz_randtest_mod(fmpz_t f, flint_rand_t state, const fmpz_t m)
{
fmpz_t t;
fmpz_init(t);
fmpz_randtest_unsigned(t, state, fmpz_bits(m) + 2);
fmpz_mod(t, t, m);
if (n_randlimb(state) & UWORD(1))
{
fmpz_sub(t, m, t);
fmpz_sub_ui(t, t, UWORD(1));
}
fmpz_set(f, t);
fmpz_clear(t);
}
void
fmpz_randtest_mod_signed(fmpz_t f, flint_rand_t state, const fmpz_t m)
{
if ((n_randlimb(state) % 32 == 1) && (fmpz_fdiv_ui(m, 2) == 0))
{
fmpz_fdiv_q_ui(f, m, UWORD(2));
}
else
{
fmpz_t t;
fmpz_init(t);
fmpz_tdiv_q_ui(t, m, UWORD(2));
fmpz_randtest_mod(t, state, t);
if (n_randlimb(state) & UWORD(1))
{
fmpz_neg(t, t);
}
fmpz_set(f, t);
fmpz_clear(t);
}
}