示例#1
0
文件: fmpz.c 项目: hperl/flint
void fmpz_invert(fmpz_t res, fmpz_t x, fmpz_t m)
{
   if (m[0] == 0)
   {
       printf("Error: division by zero!\n");
       abort();
   }

   fmpz_t s0, U, V, temp;
   unsigned long size = fmpz_size(m);
   // U may use fmpz_size(m) + 1 limbs after the sum, and gmp requires +1
   U = fmpz_init(size + 2);
   V = fmpz_init(size + 2);
   s0 = fmpz_init(size + 2);
   temp = fmpz_init(size + 2);

   // U := (x%m) + abs(m)
   // V := abs(m)
   fmpz_abs(V, m);
   fmpz_mod(U, x, V);
   fmpz_add(U, U, V);

   // Compute s0 such that 1 = s0 * x  %  m
   mpn_gcdext(temp+1, s0+1, (long *) s0, U+1, fmpz_size(U), V+1, fmpz_size(V));
   fmpz_mod(res, s0, m);

   fmpz_clear(temp);
   fmpz_clear(s0);
   fmpz_clear(V);
   fmpz_clear(U);
}
示例#2
0
文件: fmpz.c 项目: hperl/flint
void fmpz_multi_mod_ui(unsigned long * out, fmpz_t in, fmpz_comb_t comb, fmpz_t ** temp)
{
   ulong i, j, k;
   ulong n = comb->n;
   long log_comb;
	ulong size;
	mp_limb_t * ptr;
	ulong num;
	unsigned long num_primes = comb->num_primes;

   if (num_primes == 1) // we are reducing modulo a single prime which is assumed to be big enough
   {
	  if ((long)in[0] > 0L) out[0] = in[1];
	  else if ((long)in[0] < 0L) out[0] = comb->primes[0] - in[1];
	  else out[0] = 0L;
	  return;
   }

   log_comb = n - 1;
   

   // find level in comb with entries bigger than the input integer
	log_comb = 0;
	if ((long) in[0] < 0L)
	  while ((fmpz_bits(in) >= fmpz_bits(comb->comb[log_comb][0]) - 1) && (log_comb < comb->n - 1)) log_comb++;
   else
		while (fmpz_cmpabs(in, comb->comb[log_comb][0]) >= 0) log_comb++;
   num = (1L<<(n - log_comb - 1));

	// set each entry of this level of temp to the input integer
	for (i = 0; i < num; i++)
   {
      fmpz_set(temp[log_comb][i], in);
   }
   log_comb--;
   num *= 2;
   
   // fill in other entries of temp by taking entries of temp at higher level mod pairs from comb
	while (log_comb > FLINT_LOG_MULTI_MOD_CUTOFF) // keep going until we reach the basecase
   {
      for (i = 0, j = 0; i < num; i += 2, j++)
      {
         fmpz_mod(temp[log_comb][i], temp[log_comb + 1][j], comb->comb[log_comb][i]);
         fmpz_mod(temp[log_comb][i+1], temp[log_comb + 1][j], comb->comb[log_comb][i+1]);
      }
      num *= 2;
      log_comb--;
   }
   
   // do basecase
	num /= 2;
   log_comb++;
   ulong stride = (1L << (log_comb + 1));
   for (i = 0, j = 0; j < num_primes; i++, j += stride)
   {
	   fmpz_multi_mod_ui_basecase(out + j, temp[log_comb][i], comb->primes + j, FLINT_MIN(stride, num_primes - j));
   }
}
示例#3
0
static void dsum_p(
    fmpz_t rop, 
    const fmpz *dinv, const fmpz *mu, long M, const long *C, long lenC, 
    const fmpz_t a, long ui, long vi, long n, long d, long p, long N)
{
    long m, r, idx;
    fmpz_t apm1, apow, f, g, P, PN;

    fmpz_init(apm1);
    fmpz_init(apow);
    fmpz_init(f);
    fmpz_init(g);
    fmpz_init_set_ui(P, p);
    fmpz_init(PN);

    fmpz_pow_ui(PN, P, N);

    fmpz_zero(rop);

    r = 0;
    m = (p * (ui + 1) - (vi + 1)) / d;

    if (m <= M)  /* Step {r = 0} */
    {
        idx = _bsearch(C, 0, lenC, m % p);

        fmpz_powm_ui(apm1, a, p - 1, PN);
        fmpz_one(apow);
        fmpz_one(f);
        fmpz_mod(rop, mu + idx + lenC * (m / p), PN);
    }

    for (r = 1, m += p; m <= M; r++, m += p)
    {
        idx = _bsearch(C, 0, lenC, m % p);

        fmpz_mul(apow, apow, apm1);
        fmpz_mod(apow, apow, PN);
        fmpz_mul_ui(f, f, ui + 1 + (r - 1) * d);
        fmpz_mod(f, f, PN);
        fmpz_mul(g, f, dinv + r);
        fmpz_mul(g, g, apow);
        fmpz_mul(g, g, mu + idx + lenC * (m / p));
        fmpz_mod(g, g, PN);
        fmpz_add(rop, rop, g);
    }

    fmpz_mod(rop, rop, PN);

    fmpz_clear(apm1);
    fmpz_clear(apow);
    fmpz_clear(f);
    fmpz_clear(g);
    fmpz_clear(P);
    fmpz_clear(PN);
}
示例#4
0
void
_nf_elem_mod_fmpz(nf_elem_t res, const nf_elem_t a, const fmpz_t mod, const nf_t nf)
{
    if (nf_elem_is_zero(a, nf))
    {
        nf_elem_zero(res, nf);
        return;
    }
    if (nf->flag & NF_LINEAR)
    {
        fmpz_mod(LNF_ELEM_NUMREF(res), LNF_ELEM_NUMREF(a), mod);
        fmpz_one(LNF_ELEM_DENREF(res));
    }
    else if (nf->flag & NF_QUADRATIC)
    { 
        _fmpz_vec_scalar_mod_fmpz(QNF_ELEM_NUMREF(res), QNF_ELEM_NUMREF(a), 3, mod);
        fmpz_one(QNF_ELEM_DENREF(res));
    }
    else
    {
        fmpq_poly_fit_length(NF_ELEM(res), fmpq_poly_length(NF_ELEM(a)));
        _fmpq_poly_set_length(NF_ELEM(res), fmpq_poly_length(NF_ELEM(a)));
        _fmpz_vec_scalar_mod_fmpz(NF_ELEM(res)->coeffs, NF_ELEM(a)->coeffs, fmpq_poly_length(NF_ELEM(a)), mod);
        fmpz_one(NF_ELEM_DENREF(res));
    }
    nf_elem_canonicalise(res, nf);
}
示例#5
0
static void precompute_dinv_p(fmpz *list, long M, long d, long p, long N)
{
    fmpz_one(list + 0);

    if (M >= p)
    {
        fmpz_t P, PN;
        long r;

        fmpz_init_set_ui(P, p);
        fmpz_init(PN);
        fmpz_pow_ui(PN, P, N);

        fmpz_set_ui(list + 1, d);
        _padic_inv(list + 1, list + 1, P, N);

        for (r = 2; r <= M / p; r++)
        {
            fmpz_mul(list + r, list + (r - 1), list + 1);
            fmpz_mod(list + r, list + r, PN);
        }

        fmpz_clear(P);
        fmpz_clear(PN);
    }
}
示例#6
0
void _fmpz_mod_poly_evaluate_fmpz(fmpz_t res, const fmpz *poly, slong len, 
                                  const fmpz_t a, const fmpz_t p)
{
    if (len == 0)
    {
        fmpz_zero(res);
    }
    else if (len == 1 || fmpz_is_zero(a))
    {
        fmpz_set(res, poly);
    }
    else
    {
        slong i = len - 1;
        fmpz_t t;

        fmpz_init(t);
        fmpz_set(res, poly + i);
        for (i = len - 2; i >= 0; i--)
        {
            fmpz_mul(t, res, a);
            fmpz_mod(t, t, p);
            fmpz_add(res, poly + i, t);
        }
        fmpz_clear(t);

        if (fmpz_cmpabs(res, p) >= 0)
            fmpz_sub(res, res, p);
    }
}
示例#7
0
文件: fmpz.c 项目: hperl/flint
// Compute a*b mod m
void fmpz_mulmod(fmpz_t res, fmpz_t a, fmpz_t b, fmpz_t m)
{
    fmpz_t ab = fmpz_init(fmpz_size(a) + fmpz_size(b));
    fmpz_mul(ab, a, b);
    fmpz_mod(res, ab, m);

    fmpz_clear(ab);
}
示例#8
0
static void entry(fmpz_t rop_u, long *rop_v, 
    const long *u, const long *v, const fmpz *a, const fmpz *dinv, 
    const fmpz **mu, long M, const long **C, const long *lenC, 
    long n, long d, long p, long N, long N2)
{
    const long ku = diagfrob_k(u, n, d);
    const long kv = diagfrob_k(v, n, d);

    fmpz_t f, g, P;

    fmpz_init(f);
    fmpz_init(g);
    fmpz_init_set_ui(P, p);

    /*
        Compute $g := (u'-1)! \alpha_{u+1,v+1}$ to precision $N2$.
     */

    fmpz_fac_ui(f, ku - 1);
    alpha(g, u, v, a, dinv, mu, M, C, lenC, n, d, p, N2);
    fmpz_mul(g, f, g);

    /*
        Compute $f := (-1)^{u'+v'} (v'-1)!$ exactly.
     */

    fmpz_fac_ui(f, kv - 1);
    if ((ku + kv) % 2 != 0)
    {
        fmpz_neg(f, f);
    }

    /*
        Set rop to the product of $f$ and $g^{-1} mod $p^N$.
     */

    *rop_v = fmpz_remove(f, f, P) + n - fmpz_remove(g, g, P);

    if (*rop_v >= N)
    {
        fmpz_zero(rop_u);
        *rop_v = 0;
    }
    else
    {
        _padic_inv(g, g, P, N - *rop_v);

        fmpz_mul(rop_u, f, g);
        fmpz_pow_ui(f, P, N - *rop_v);
        fmpz_mod(rop_u, rop_u, f);
    }

    fmpz_clear(f);
    fmpz_clear(g);
    fmpz_clear(P);
}
示例#9
0
void 
_padic_log_balanced(fmpz_t z, const fmpz_t y, long v, const fmpz_t p, long N)
{
    fmpz_t pv, pN, r, t, u;
    long val;
    padic_inv_t S;

    fmpz_init(pv);
    fmpz_init(pN);
    fmpz_init(r);
    fmpz_init(t);
    fmpz_init(u);
    _padic_inv_precompute(S, p, N);

    fmpz_set(t, y);
    fmpz_set(pv, p);
    fmpz_pow_ui(pN, p, N);
    fmpz_zero(z);
    val = 1;

    /*
        TODO:  Abort earlier if larger than $p^N$, possible
        with variable precision?
     */
    while (!fmpz_is_zero(t))
    {
        fmpz_mul(pv, pv, pv);
        fmpz_fdiv_qr(t, r, t, pv);

        if (!fmpz_is_zero(t))
        {
            fmpz_mul(t, t, pv);
            fmpz_add_ui(u, r, 1);
            _padic_inv_precomp(u, u, S);
            fmpz_mul(t, t, u);
            fmpz_mod(t, t, pN);
        }

        if (!fmpz_is_zero(r))
        {
            fmpz_neg(r, r);
            _padic_log_bsplit(r, r, val, p, N);
            fmpz_sub(z, z, r);
        }
        val *= 2;
    }

    fmpz_clear(pv);
    fmpz_clear(pN);
    fmpz_clear(r);
    fmpz_clear(t);
    fmpz_clear(u);
    _padic_inv_clear(S);
}
示例#10
0
文件: fmpz.c 项目: hperl/flint
// Compute a/b mod m
void fmpz_divmod(fmpz_t res, fmpz_t a, fmpz_t b, fmpz_t m)
{
    fmpz_t b_inv = fmpz_init(fmpz_size(m));
    fmpz_invert(b_inv, b, m);

    fmpz_t ab = fmpz_init(fmpz_size(a) + fmpz_size(b_inv));
    fmpz_mul(ab, a, b_inv);
    fmpz_mod(res, ab, m);

    fmpz_clear(ab);
    fmpz_clear(b_inv);
}
示例#11
0
static void alpha(fmpz_t rop, const long *u, const long *v, 
    const fmpz *a, const fmpz *dinv, const fmpz **mu, long M, const long **C, const long *lenC, 
    long n, long d, long p, long N)
{
    const long ku = diagfrob_k(u, n, d);

    long i;
    fmpz_t f, g, P, PN;

    fmpz_init(f);
    fmpz_init(g);
    fmpz_init_set_ui(P, p);
    fmpz_init(PN);
    fmpz_pow_ui(PN, P, N);

    fmpz_pow_ui(rop, P, ku);
    fmpz_mod(rop, rop, PN);

    for (i = 0; i <= n; i++)
    {
        long e = (p * (u[i] + 1) - (v[i] + 1)) / d;

        fmpz_powm_ui(f, a + i, e, PN);
        dsum(g, dinv, mu[i], M, C[i], lenC[i], a + i, u[i], v[i], n, d, p, N);
        fmpz_mul(rop, rop, f);
        fmpz_mul(rop, rop, g);
        fmpz_mod(rop, rop, PN);
    }

    if (ku % 2 != 0 && !fmpz_is_zero(rop))
    {
        fmpz_sub(rop, PN, rop);
    }

    fmpz_clear(f);
    fmpz_clear(g);
    fmpz_clear(P);
    fmpz_clear(PN);
}
示例#12
0
void
elem_set_si(elem_ptr elem, long v, const ring_t ring)
{
    switch (ring->type)
    {
        case TYPE_FMPZ:
            fmpz_set_si(elem, v);
            break;

        case TYPE_LIMB:
            *((mp_ptr) elem) = v;
            break;

        case TYPE_POLY:
            elem_poly_set_si(elem, v, ring);
            break;

        case TYPE_MOD:
            {
                switch (RING_PARENT(ring)->type)
                {
                    case TYPE_FMPZ:
                        fmpz_set_si(elem, v);
                        fmpz_mod(elem, elem, RING_MODULUS(ring));
                        break;

                    case TYPE_LIMB:
                        *((mp_ptr) elem) = nmod_set_si(v, ring->nmod);
                        break;

                    default:
                        NOT_IMPLEMENTED("set_si (mod)", ring);
                }
            }
            break;

        case TYPE_FRAC:
            elem_set_si(NUMER(elem, ring), v, RING_NUMER(ring));
            elem_one(DENOM(elem, ring), RING_DENOM(ring));
            break;

        case TYPE_COMPLEX:
            elem_set_si(REALPART(elem, ring), v, ring->parent);
            elem_zero(IMAGPART(elem, ring), ring->parent);
            break;

        default:
            NOT_IMPLEMENTED("set_si", ring);
    }
}
示例#13
0
文件: trace.c 项目: clear731/lattice
void _qadic_trace(fmpz_t rop, const fmpz *op, slong len, 
                  const fmpz *a, const slong *j, slong lena, const fmpz_t pN)
{
    const slong d = j[lena - 1];

    slong i, l;
    fmpz *t;

    t = _fmpz_vec_init(d);

    fmpz_set_ui(t + 0, d);
    for (i = 1; i < d; i++)
    {
        for (l = lena - 2; l >= 0 && j[l] >= d - (i - 1); l--)
        {
            fmpz_addmul(t + i, t + (j[l] + i - d), a + l);
        }

        if (l >= 0 && j[l] == d - i)
        {
            fmpz_addmul_ui(t + i, a + l, i);
        }

        fmpz_neg(t + i, t + i);
        fmpz_mod(t + i, t + i, pN);
    }

    fmpz_zero(rop);
    for (i = 0; i < d; i++)
    {
        fmpz_addmul(rop, op + i, t + i);
    }
    fmpz_mod(rop, rop, pN);

    _fmpz_vec_clear(t, d);
}
示例#14
0
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);
}
示例#15
0
文件: radix.c 项目: goens/flint2
void _fmpz_mod_poly_radix_init(fmpz **Rpow, fmpz **Rinv, 
                    const fmpz *R, long lenR, long k, 
                    const fmpz_t invL, const fmpz_t p)
{
    const long degR = lenR - 1;
    long i;
    fmpz_t invLP;
    fmpz *W;

    fmpz_init_set(invLP, invL);
    W = flint_malloc((1L << (k - 1)) * degR * sizeof(fmpz));

    _fmpz_vec_set(Rpow[0], R, lenR);
    for (i = 1; i < k; i++)
    {
        _fmpz_mod_poly_sqr(Rpow[i], Rpow[i - 1], degR * (1L << (i - 1)) + 1, p);
    }

    for (i = 0; i < k; i++)
    {
        const long lenQ = (1L << i) * degR;
        long j;

        /* W := rev{Rpow[i], lenQ} */
        for (j = 0; j < lenQ; j++)
        {
            W[j] = Rpow[i][lenQ - j];
        }

        _fmpz_mod_poly_inv_series_newton(Rinv[i], W, lenQ, invLP, p);

        /* invLP := inv{lead{R^{2^i}}} */
        if (i != k - 1)
        {
            fmpz_mul(invLP, invLP, invLP);
            fmpz_mod(invLP, invLP, p);
        }
    }

    fmpz_clear(invLP);
    flint_free(W);
}
示例#16
0
void _fmpz_vec_scalar_smod_fmpz(fmpz *res, const fmpz *vec, slong len, const fmpz_t p)
{
    slong i;
    fmpz_t pdiv2;

    fmpz_init(pdiv2);
    fmpz_fdiv_q_2exp(pdiv2, p, 1);

    for (i = 0; i < len; i++)
    {
        fmpz_mod(res + i, vec + i, p);

        if (fmpz_cmp(res + i, pdiv2) > 0)
        {
            fmpz_sub(res + i, res + i, p);
        }
    }

    fmpz_clear(pdiv2);
}
示例#17
0
文件: reduce.c 项目: goens/flint2
void _padic_reduce(padic_t rop, const padic_ctx_t ctx)
{
    if (!fmpz_is_zero(padic_unit(rop)))
    {
        if (padic_val(rop) < ctx->N)
        {
            int alloc;
            fmpz_t pow;

            alloc = _padic_ctx_pow_ui(pow, ctx->N - padic_val(rop), ctx);
            fmpz_mod(padic_unit(rop), padic_unit(rop), pow);
            if (alloc)
                fmpz_clear(pow);
        }
        else
        {
            fmpz_zero(padic_unit(rop));
            padic_val(rop) = 0;
        }
    }
}
示例#18
0
void _fmpz_mod_poly_div_basecase(fmpz *Q, fmpz *R, 
    const fmpz *A, long lenA, const fmpz *B, long lenB, 
    const fmpz_t invB, const fmpz_t p)
{
    const long alloc = (R == NULL) ? lenA : 0;
    long lenR = lenB - 1, iQ;

    if (alloc)
        R = _fmpz_vec_init(alloc);
    if (R != A)
        _fmpz_vec_set(R + lenR, A + lenR, lenA - lenR);

    for (iQ = lenA - lenB; iQ >= 0; iQ--)
    {
        if (fmpz_is_zero(R + lenA - 1))
        {
            fmpz_zero(Q + iQ);
        }
        else
        {
            fmpz_mul(Q + iQ, R + lenA - 1, invB);
            fmpz_mod(Q + iQ, Q + iQ, p);

            _fmpz_vec_scalar_submul_fmpz(R + lenA - lenR - 1, B, lenR, Q + iQ);
            _fmpz_vec_scalar_mod_fmpz(R + lenA - lenR - 1, R + lenA - lenR - 1, lenR, p);
        }

        if (lenR - 1 >= iQ)
        {
            B++;
            lenR--;
        }

        lenA--;
    }

    if (alloc)
        _fmpz_vec_clear(R, alloc);
}
示例#19
0
int main()
{
    long i, j;
    int sign;

    fmpz_t input;
    fmpz_t result;
    fmpz_t r1;
    fmpz_t m1;
    fmpz_t mprod;
    ulong r2, m2;

    flint_rand_t state;

    printf("CRT_ui....");
    fflush(stdout);

    fmpz_init(input);
    fmpz_init(result);
    fmpz_init(r1);
    fmpz_init(m1);
    fmpz_init(mprod);
    flint_randinit(state);

    for (i = 0; i < 10000; i++)
    {
        long nprimes;

        m2 = n_randtest_prime(state, 0);
        nprimes = 1 + n_randint(state, 4);

        fmpz_set_ui(m1, 1UL);
        for (j = 0; j < nprimes; )
        {
            ulong t = n_randtest_prime(state, 0);
            if (t != m2)
            {
                fmpz_mul_ui(m1, m1, t);
                j++;
            }
        }

        fmpz_mul_ui(mprod, m1, m2);

        sign = n_randint(state, 2);

        if (sign)
            fmpz_randtest_mod_signed(input, state, mprod);
        else
            fmpz_randtest_mod(input, state, mprod);

        fmpz_mod(r1, input, m1);
        r2 = fmpz_fdiv_ui(input, m2);

        if (sign)
            fmpz_CRT_ui(result, r1, m1, r2, m2);
        else
            fmpz_CRT_ui_unsigned(result, r1, m1, r2, m2);

        if (!fmpz_equal(result, input))
        {
            printf("FAIL:\n");
            printf("m1: "); fmpz_print(m1); printf("\n");
            printf("m2: %lu\n", m2);
            printf("m1*m2: "); fmpz_print(mprod); printf("\n");
            printf("input: "); fmpz_print(input); printf("\n");
            printf("r1: "); fmpz_print(r1); printf("\n");
            printf("r2: %lu\n", r2);
            printf("result: "); fmpz_print(result); printf("\n");
            printf("%ld Equalness: %d\n", i, fmpz_equal(result, input));
            printf("\n");
            abort();
        }
    }

    fmpz_clear(input);
    fmpz_clear(result);
    fmpz_clear(r1);
    fmpz_clear(m1);
    fmpz_clear(mprod);
    flint_randclear(state);

    _fmpz_cleanup();

    printf("PASS\n");
    return 0;
}
示例#20
0
文件: get_str.c 项目: goens/flint2
char * _padic_get_str(char * str, const padic_t op, const padic_ctx_t ctx)
{
    const fmpz * u = padic_unit(op);
    const long v   = padic_val(op);

    if (fmpz_is_zero(u))
    {
        if (!str)
        {
            str = flint_malloc(2);
        }
        str[0] = '0';
        str[1] = '\0';
        return str;
    }

    if (ctx->mode == PADIC_TERSE)
    {
        if (v == 0)
        {
            str = fmpz_get_str(str, 10, u);
        }
        else if (v > 0)
        {
            fmpz_t t;

            fmpz_init(t);
            fmpz_pow_ui(t, ctx->p, v);
            fmpz_mul(t, t, u);
            str = fmpz_get_str(str, 10, t);
            fmpz_clear(t);
        }
        else  /* v < 0 */
        {
            fmpz_t t;

            fmpz_init(t);
            fmpz_pow_ui(t, ctx->p, -v);
            str = _fmpq_get_str(str, 10, u, t);
            fmpz_clear(t);
        }
    }
    else if (ctx->mode == PADIC_SERIES)
    {
        char *s;
        fmpz_t x;
        fmpz_t d;
        long j, N;

        if (fmpz_sgn(u) < 0)
        {
            printf("ERROR (_padic_get_str).  u < 0 in SERIES mode.\n");
            abort();
        }

        N = fmpz_clog(u, ctx->p) + v;

        if (!str)
        {
            long b = (N - v) * (2 * fmpz_sizeinbase(ctx->p, 10) 
                     + z_sizeinbase(FLINT_MAX(FLINT_ABS(v), FLINT_ABS(N)), 10) 
                     + 5) + 1;

            str = flint_malloc(b);
            if (!str)
            {
                printf("ERROR (_padic_get_str).  Memory allocation failed.\n");
                abort();
            }
        }

        s = str;

        fmpz_init(d);
        fmpz_init(x);

        fmpz_set(x, u);

        /* Unroll first step */
        j = 0;
        {
            fmpz_mod(d, x, ctx->p);       /* d = u mod p^{j+1} */
            fmpz_sub(x, x, d);            /* x = x - d */
            fmpz_divexact(x, x, ctx->p);  /* x = x / p */

            if (!fmpz_is_zero(d))
            {
                if (j + v != 0)
                {
                    fmpz_get_str(s, 10, d);
                    while (*++s != '\0') ;
                    *s++ = '*';
                    fmpz_get_str(s, 10, ctx->p);
                    while (*++s != '\0') ;
                    *s++ = '^';
                    sprintf(s, "%ld", j + v);
                    while (*++s != '\0') ;
                }
                else
                {
                    fmpz_get_str(s, 10, d);
                    while (*++s != '\0') ;
                }
            }

            j++;
        }

        for ( ; !fmpz_is_zero(x); j++)
        {
            fmpz_mod(d, x, ctx->p);       /* d = u mod p^{j+1} */
            fmpz_sub(x, x, d);            /* x = x - d */
            fmpz_divexact(x, x, ctx->p);  /* x = x / p */

            if (!fmpz_is_zero(d))
            {
                if (j + v != 0)
                {
                    *s++ = ' ';
                    *s++ = '+';
                    *s++ = ' ';
                    fmpz_get_str(s, 10, d);
                    while (*++s != '\0') ;
                    *s++ = '*';
                    fmpz_get_str(s, 10, ctx->p);
                    while (*++s != '\0') ;
                    *s++ = '^';
                    sprintf(s, "%ld", j + v);
                    while (*++s != '\0') ;
                }
                else
                {
                    *s++ = ' ';
                    *s++ = '+';
                    *s++ = ' ';
                    fmpz_get_str(s, 10, d);
                    while (*++s != '\0') ;
                }
            }
        }
        
        fmpz_clear(x);
        fmpz_clear(d);
    }
    else  /* ctx->mode == PADIC_VAL_UNIT */
    {
        if (!str)
        {
            long b = fmpz_sizeinbase(u, 10) + fmpz_sizeinbase(ctx->p, 10) 
                   + z_sizeinbase(v, 10) + 4;

            str = flint_malloc(b);
            if (!str)
            {
                printf("ERROR (_padic_get_str).  Memory allocation failed.\n");
                abort();
            }
        }

        if (v == 0)
        {
            str = fmpz_get_str(str, 10, u);
        }
        else if (v == 1)
        {
            char *s = str;

            fmpz_get_str(s, 10, u);
            while (*++s != '\0') ;
            *s++ = '*';
            fmpz_get_str(s, 10, ctx->p);
        }
        else
        {
            char *s = str;

            fmpz_get_str(s, 10, u);
            while (*++s != '\0') ;
            *s++ = '*';
            fmpz_get_str(s, 10, ctx->p);
            while (*++s != '\0') ;
            *s++ = '^';
            sprintf(s, "%ld", v);
        }
    }

    return str;
}
示例#21
0
int test_jigsaw(const size_t lambda, const size_t kappa, int symmetric, aes_randstate_t randstate) {

    printf("λ: %4zu, κ: %2zu, symmetric: %d …", lambda, kappa, symmetric);

    gghlite_sk_t self;
    gghlite_flag_t flags = GGHLITE_FLAGS_QUIET;
    if (symmetric)
        gghlite_init(self, lambda, kappa, kappa, 0x0, flags | GGHLITE_FLAGS_GOOD_G_INV, randstate);
    else
        gghlite_jigsaw_init(self, lambda, kappa, flags, randstate);

    fmpz_t p; fmpz_init(p);
    fmpz_poly_oz_ideal_norm(p, self->g, self->params->n, 0);


    fmpz_t a[kappa];
    fmpz_t acc;  fmpz_init(acc);
    fmpz_set_ui(acc, 1);

    for(size_t k=0; k<kappa; k++) {
        fmpz_init(a[k]);
        fmpz_randm_aes(a[k], randstate, p);
        fmpz_mul(acc, acc, a[k]);
        fmpz_mod(acc, acc, p);
    }

    gghlite_clr_t e[kappa];
    gghlite_enc_t u[kappa];

    for(size_t k=0; k<kappa; k++) {
        gghlite_clr_init(e[k]);
        gghlite_enc_init(u[k], self->params);
    }

    gghlite_enc_t left;
    gghlite_enc_init(left, self->params);
    gghlite_enc_set_ui0(left, 1, self->params);

    for(size_t k=0; k<kappa; k++) {
        fmpz_poly_set_coeff_fmpz(e[k], 0, a[k]);
        const int i = (gghlite_sk_is_symmetric(self)) ? 0 : k;
		int group[GAMMA];
		memset(group, 0, GAMMA * sizeof(int));
		group[i] = 1;
        gghlite_enc_set_gghlite_clr(u[k], self, e[k], 1, group, 1);
        gghlite_enc_mul(left, self->params, left, u[k]);
    }

    gghlite_enc_t rght;
    gghlite_enc_init(rght, self->params);
    gghlite_enc_set_ui0(rght, 1, self->params);

    fmpz_poly_t tmp; fmpz_poly_init(tmp);
    fmpz_poly_set_coeff_fmpz(tmp, 0, acc);
    gghlite_enc_set_gghlite_clr0(rght, self, tmp);

    for(size_t k=0; k<kappa; k++) {
        const int i = (gghlite_sk_is_symmetric(self)) ? 0 : k;
        gghlite_enc_mul(rght, self->params, rght, self->z_inv[i]);
    }

    gghlite_enc_sub(rght, self->params, rght, left);
    int status = 1 - gghlite_enc_is_zero(self->params, rght);

    for(size_t i=0; i<kappa; i++) {
        fmpz_clear(a[i]);
        gghlite_clr_clear(e[i]);
        gghlite_enc_clear(u[i]);
    }

    gghlite_enc_clear(left);
    gghlite_enc_clear(rght);
    gghlite_clr_clear(tmp);
    fmpz_clear(p);
    gghlite_sk_clear(self, 1);

    if (status == 0)
        printf(" PASS\n");
    else
        printf(" FAIL\n");

    return status;
}
示例#22
0
/**
 * Testing the flexibility of large index sets with a smaller kappa
 */
int test_jigsaw_indices(const size_t lambda, const size_t kappa, const size_t gamma, aes_randstate_t randstate) {

	printf("lambda: %d, kappa: %d, gamma: %d", (int) lambda, (int) kappa, (int) gamma);

    gghlite_sk_t self;
    gghlite_flag_t flags = GGHLITE_FLAGS_QUIET;

    gghlite_jigsaw_init_gamma(self, lambda, kappa, gamma, flags, randstate);

    fmpz_t p; fmpz_init(p);
    fmpz_poly_oz_ideal_norm(p, self->g, self->params->n, 0);

	/* partitioning of the universe set */
	int partition[GAMMA];
	for (int i = 0; i < gamma; i++) {
		partition[i] = rand() % kappa;
	}

    fmpz_t a[kappa];
    fmpz_t acc;  fmpz_init(acc);
    fmpz_set_ui(acc, 1);

    for(size_t k=0; k<kappa; k++) {
        fmpz_init(a[k]);
        fmpz_randm_aes(a[k], randstate, p);
        fmpz_mul(acc, acc, a[k]);
        fmpz_mod(acc, acc, p);
    }

    gghlite_clr_t e[kappa];
    gghlite_enc_t u[kappa];

    for(size_t k=0; k<kappa; k++) {
        gghlite_clr_init(e[k]);
        gghlite_enc_init(u[k], self->params);
    }

    gghlite_enc_t left;
    gghlite_enc_init(left, self->params);
    gghlite_enc_set_ui0(left, 1, self->params);

    for(size_t k=0; k<kappa; k++) {
        fmpz_poly_set_coeff_fmpz(e[k], 0, a[k]);
        const int i = (gghlite_sk_is_symmetric(self)) ? 0 : k;
		int group[GAMMA];
		memset(group, 0, GAMMA * sizeof(int));
		for (int j = 0; j < gamma; j++) {
			if (partition[j] == k) {
				group[j] = 1;
			}
		}
        gghlite_enc_set_gghlite_clr(u[k], self, e[k], 1, group, 1);
        gghlite_enc_mul(left, self->params, left, u[k]);
    }

    gghlite_enc_t rght;
    gghlite_enc_init(rght, self->params);
    gghlite_enc_set_ui0(rght, 1, self->params);

    fmpz_poly_t tmp; fmpz_poly_init(tmp);
    fmpz_poly_set_coeff_fmpz(tmp, 0, acc);
    gghlite_enc_set_gghlite_clr0(rght, self, tmp);

    for(size_t k=0; k<gamma; k++) {
        gghlite_enc_mul(rght, self->params, rght, self->z_inv[k]);
    }
 
    gghlite_enc_sub(rght, self->params, rght, left);
    int status = 1 - gghlite_enc_is_zero(self->params, rght);

    for(size_t i=0; i<kappa; i++) {
        fmpz_clear(a[i]);
        gghlite_clr_clear(e[i]);
        gghlite_enc_clear(u[i]);
    }

    gghlite_enc_clear(left);
    gghlite_enc_clear(rght);
    gghlite_clr_clear(tmp);
    fmpz_clear(p);
    gghlite_sk_clear(self, 1);

    if (status == 0)
        printf(" PASS\n");
    else
        printf(" FAIL\n");

    return status;
}
示例#23
0
int main(int argc, char *argv[]) {
  cmdline_params_t cmdline_params;

  const char *name =  "Jigsaw Puzzles";
  parse_cmdline(cmdline_params, argc, argv, name, NULL);

  print_header(name, cmdline_params);

  aes_randstate_t randstate;
  aes_randinit_seed(randstate, cmdline_params->shaseed, NULL);

  uint64_t t = ggh_walltime(0);
  uint64_t t_total = ggh_walltime(0);

  uint64_t t_gen = 0;

  gghlite_sk_t self;


  gghlite_jigsaw_init(self,
                      cmdline_params->lambda,
                      cmdline_params->kappa,
                      cmdline_params->flags,
                      randstate);

  printf("\n");
  gghlite_params_print(self->params);
  printf("\n---\n\n");

  t_gen = ggh_walltime(t);
  printf("1. GGH InstGen wall time:                 %8.2f s\n", ggh_seconds(t_gen));

  t = ggh_walltime(0);

  fmpz_t p; fmpz_init(p);
  fmpz_poly_oz_ideal_norm(p, self->g, self->params->n, 0);

  fmpz_t a[5];
  for(long k=0; k<5; k++)
    fmpz_init(a[k]);

  fmpz_t acc;  fmpz_init(acc);
  fmpz_set_ui(acc, 1);

  // reducing these elements to something small mod g is expensive, for benchmarketing purposes we
  // hence avoid this costly step most of the time by doing it only twice and by then computing the
  // remaining elements from those two elements using cheap operations. The reported times still
  // refer to the expensive step for fairness.
  fmpz_randm_aes(a[0], randstate, p);
  fmpz_mul(acc, acc, a[0]);
  fmpz_mod(acc, acc, p);

  fmpz_randm_aes(a[1], randstate, p);
  fmpz_mul(acc, acc, a[1]);
  fmpz_mod(acc, acc, p);

  fmpz_set(a[3], a[0]);
  fmpz_set(a[4], a[1]);

  for(long k=2; k<cmdline_params->kappa; k++) {
    fmpz_mul(a[2], a[0], a[1]);
    fmpz_add_ui(a[2], a[2], k);
    fmpz_mod(a[2], a[2], p);
    fmpz_mul(acc, acc, a[2]);
    fmpz_mod(acc, acc, p);
    fmpz_set(a[1], a[0]);
    fmpz_set(a[0], a[2]);
  }

  printf("2. Sampling from U(Z_p) wall time:        %8.2f s\n", ggh_seconds(ggh_walltime(t)));

  gghlite_clr_t e[3];
  gghlite_clr_init(e[0]);
  gghlite_clr_init(e[1]);
  gghlite_clr_init(e[2]);

  gghlite_enc_t u_k;
  gghlite_enc_init(u_k, self->params);

  gghlite_enc_t left;
  gghlite_enc_init(left, self->params);
  gghlite_enc_set_ui0(left, 1, self->params);

  fmpz_poly_set_coeff_fmpz(e[0], 0, a[3]);

  int GAMMA = 20;
  uint64_t t_enc = ggh_walltime(0);
	int group0[GAMMA];
	memset(group0, 0, GAMMA * sizeof(int));
	group0[0] = 1;
  gghlite_enc_set_gghlite_clr(u_k, self, e[0], 1, group0, 1, randstate);
  t_enc = ggh_walltime(t_enc);

  printf("3. Encoding wall time:                    %8.2f s (per elem)\n", ggh_seconds(t_enc));
  fflush(0);

  uint64_t t_mul = 0;
  t = ggh_walltime(0);
  gghlite_enc_mul(left, self->params, left, u_k);
  t_mul += ggh_walltime(t);

  fmpz_poly_set_coeff_fmpz(e[1], 0, a[4]);
	int group1[GAMMA];
	memset(group1, 0, GAMMA * sizeof(int));
	group1[1] = 1;
  gghlite_enc_set_gghlite_clr(u_k, self, e[1], 1, group1, 1, randstate);
  t = ggh_walltime(0);
  gghlite_enc_mul(left, self->params, left, u_k);
  t_mul += ggh_walltime(t);

  const mp_bitcnt_t prec = (self->params->n/4 < 8192) ? 8192 : self->params->n/4;
  const oz_flag_t flags = (self->params->flags & GGHLITE_FLAGS_VERBOSE) ? OZ_VERBOSE : 0;
  _fmpz_poly_oz_rem_small_iter(e[0], e[0], self->g, self->params->n, self->g_inv, prec, flags);
  _fmpz_poly_oz_rem_small_iter(e[1], e[1], self->g, self->params->n, self->g_inv, prec, flags);

  for(long k=2; k<cmdline_params->kappa; k++) {
    fmpz_poly_oz_mul(e[2], e[0], e[1], self->params->n);
    assert(fmpz_poly_degree(e[2])>=0);
    fmpz_add_ui(e[2]->coeffs, e[2]->coeffs, k);
    _fmpz_poly_oz_rem_small_iter(e[2], e[2], self->g, self->params->n, self->g_inv, prec, flags);
		int groupk[GAMMA];
		memset(groupk, 0, GAMMA * sizeof(int));
		groupk[k] = 1;
		gghlite_enc_set_gghlite_clr(u_k, self, e[2], 1, groupk, 1, randstate);
    t = ggh_walltime(0);
    gghlite_enc_mul(left, self->params, left, u_k);
    t_mul += ggh_walltime(t);
    fmpz_poly_set(e[1], e[0]);
    fmpz_poly_set(e[0], e[2]);
  }

  printf("4. Multiplication wall time:              %8.4f s\n", ggh_seconds(t_mul));
  fflush(0);

  t = ggh_walltime(0);
  gghlite_enc_t rght;
  gghlite_enc_init(rght, self->params);
  gghlite_enc_set_ui0(rght, 1, self->params);

  fmpz_poly_t tmp; fmpz_poly_init(tmp);
  fmpz_poly_set_coeff_fmpz(tmp, 0, acc);
  gghlite_enc_set_gghlite_clr0(rght, self, tmp, randstate);

  for(long k=0; k<cmdline_params->kappa; k++) {
    gghlite_enc_mul(rght, self->params, rght, self->z_inv[k]);
  }

  printf("5. RHS generation wall time:              %8.2f s\n", ggh_seconds(ggh_walltime(t)));
  t = ggh_walltime(0);

  gghlite_enc_sub(rght, self->params, rght, left);
  int status = 1 - gghlite_enc_is_zero(self->params, rght);

  gghlite_clr_t clr; gghlite_clr_init(clr);
  gghlite_enc_extract(clr, self->params, rght);
  double size = fmpz_poly_2norm_log2(clr);
  gghlite_clr_clear(clr);

  printf("6. Checking correctness wall time:        %8.2f s\n", ggh_seconds(ggh_walltime(t)));
  printf("   Correct:                               %8s (%8.2f)\n\n", (status == 0) ? "TRUE" : "FALSE", size);

  for(long i=0; i<5; i++) {
    fmpz_clear(a[i]);
  }

  gghlite_clr_clear(e[0]);
  gghlite_clr_clear(e[1]);
  gghlite_clr_clear(e[2]);
  gghlite_enc_clear(u_k);

  fmpz_clear(acc);
  gghlite_enc_clear(left);
  gghlite_enc_clear(rght);
  gghlite_clr_clear(tmp);
  fmpz_clear(p);
  gghlite_sk_clear(self, 1);

  t_total = ggh_walltime(t_total);
  printf("λ: %3ld, κ: %2ld, n: %6ld, seed: 0x%08lx, success: %d, gen: %10.2fs, enc: %8.2fs, mul: %8.4fs, time: %10.2fs\n",
         cmdline_params->lambda, cmdline_params->kappa, self->params->n, cmdline_params->seed,
         status==0,
         ggh_seconds(t_gen), ggh_seconds(t_enc), ggh_seconds(t_mul), ggh_seconds(t_total));

  aes_randclear(randstate);
  mpfr_free_cache();
  flint_cleanup();
  return status;
}
示例#24
0
文件: fmpz.c 项目: hperl/flint
void fmpz_multi_CRT_ui(fmpz_t output, unsigned long * residues, fmpz_comb_t comb, fmpz_t ** comb_temp)
{
   ulong i, j, k;

   ulong n = comb->n;
   ulong num;
   ulong log_res;
	mp_limb_t * ptr;
	ulong size;
   ulong num_primes = comb->num_primes;

   if (num_primes == 1) // the output is less than a single prime, so just output the result
   {
	   unsigned long p = comb->primes[0];
	   if ((p - residues[0]) < residues[0]) fmpz_set_si(output, (long) (residues[0] - p));
	   else fmpz_set_ui(output, residues[0]);
	   return;
	}

	// first layer of reconstruction
	num = (1L<<n);
   mp_limb_t temps[3];
   mp_limb_t temp2s[3];
   for (i = 0, j = 0; i + 2 <= num_primes; i += 2, j++)
   {
      fmpz_set_ui(temps, residues[i]);
      fmpz_set_ui(temp2s, fmpz_mod_ui(temps, comb->primes[i+1]));
      fmpz_sub_ui_inplace(temp2s, residues[i + 1]);
      temp2s[0] = -temp2s[0];
      fmpz_mul(temps, temp2s, comb->res[0][j]);
      fmpz_set_ui(temp2s, fmpz_mod_ui(temps, comb->primes[i+1]));
      fmpz_mul_ui(temps, temp2s, comb->primes[i]); 
      fmpz_add_ui(comb_temp[0][j], temps, residues[i]);
   }
   if (i < num_primes) fmpz_set_ui(comb_temp[0][j], residues[i]);
   
   // compute other layers of reconstruction
	fmpz_t temp = (fmpz_t) flint_heap_alloc(2*num + 1); 
   fmpz_t temp2 = (fmpz_t) flint_heap_alloc(2*num + 1); 
   num /= 2;
   log_res = 1;
   while (log_res < n)
   {
      for (i = 0, j = 0; i < num; i += 2, j++)
      {
         if (fmpz_is_one(comb->comb[log_res-1][i+1]))
		   {
		      if (!fmpz_is_one(comb->comb[log_res-1][i])) fmpz_set(comb_temp[log_res][j], comb_temp[log_res-1][i]);
		   } else
		   {
			   fmpz_mod(temp2, comb_temp[log_res-1][i], comb->comb[log_res-1][i+1]);
            fmpz_sub(temp, temp2, comb_temp[log_res-1][i+1]);
            temp[0] = -temp[0];
            fmpz_mul(temp2, temp, comb->res[log_res][j]);
            fmpz_mod(temp, temp2, comb->comb[log_res-1][i+1]);
            fmpz_mul(temp2, temp, comb->comb[log_res-1][i]);
            fmpz_add(comb_temp[log_res][j], temp2, comb_temp[log_res-1][i]);
		   }
      }     
      log_res++;
      num /= 2; 
   }

   // write out the output
	__fmpz_multi_CRT_sign(comb_temp[log_res - 1][0], comb_temp[log_res - 1][0], comb);
	fmpz_set(output, comb_temp[log_res - 1][0]);

   flint_heap_free(temp2); //temp2
   flint_heap_free(temp); //temp 
}
示例#25
0
int
main(void)
{
    long l, len = 20;
    long runs[] = {
        100000000, 1000000, 1000000, 1000000, 100000, 
        100000, 10000, 10000, 10000, 1000, 
        100, 100, 10, 1, 1, 
        1, 1, 1, 1, 1
    };
    long N[] = {
        1, 2, 4, 8, 16, 
        32, 64, 128, 256, 512, 
        1024, WORD(1) << 11, WORD(1) << 12, WORD(1) << 13, WORD(1) << 14, 
        WORD(1) << 15, WORD(1) << 16, WORD(1) << 17, WORD(1) << 18, WORD(1) << 19
    };
    long T[20] = {0};

    flint_printf("Benchmark for p-adic exponential (rectangular).\n");
    fflush(stdout);

for (l = 0; l < FLINT_MIN(17, len); l++)
{
    FLINT_TEST_INIT(state);
    long n = N[l], r;
    clock_t c0, c1;
    long double cputime;

    fmpz_t p;
    padic_ctx_t ctx;
    padic_t d, z;

    

    fmpz_init_set_ui(p, 17);

    padic_ctx_init(ctx, p, n, n, PADIC_VAL_UNIT);

    padic_init(d);
    padic_init(z);

    if (n > 1)
    {
        fmpz_t f = {WORD(3)}, pow;

        fmpz_init(pow);
        fmpz_pow_ui(pow, p, n - 1);
        fmpz_pow_ui(padic_unit(d), f, 3 * n);
        fmpz_mod(padic_unit(d), padic_unit(d), pow);
        padic_val(d) = 1;
        
        fmpz_clear(pow);
    }

    c0 = clock();
    for (r = runs[l]; (r); r--)
    {
        padic_exp_rectangular(z, d, ctx);
        padic_zero(z);
    }
    c1 = clock();

    cputime = (long double) (c1 - c0) / (long double) CLOCKS_PER_SEC;

    T[l] = (slong) (cputime * (1000000000 / runs[l]));

    flint_printf("%2ld, %4XYXYXYXY, %9ld, %wd\n", 
        l, cputime, runs[l], T[l]);

    padic_clear(d);
    padic_clear(z);

    fmpz_clear(p);
    padic_ctx_clear(ctx);
    flint_randclear(state);
}

    flint_printf("Output as a list:\n");
    for (l = 0; l < len; l++)
        flint_printf("%wd, ", T[l]);
    flint_printf("\n");
}
示例#26
0
long _fmpz_poly_hensel_start_lift(fmpz_poly_factor_t lifted_fac, long *link, 
    fmpz_poly_t *v, fmpz_poly_t *w, const fmpz_poly_t f, 
    const nmod_poly_factor_t local_fac, long N)
{
    const long r = local_fac->num;

    long i, preve;
    fmpz_t p, P;
    fmpz_poly_t monic_f;

    fmpz_init(p);
    fmpz_init(P);
    fmpz_poly_init(monic_f);

    fmpz_set_ui(p, (local_fac->p + 0)->mod.n);
    fmpz_pow_ui(P, p, N);

    if (fmpz_is_one(fmpz_poly_lead(f)))
    {
        fmpz_poly_set(monic_f, f);
    }
    else if (fmpz_cmp_si(fmpz_poly_lead(f), -1) == 0)
    {
        fmpz_poly_neg(monic_f, f);
    }
    else
    {
        fmpz_t t;

        fmpz_init(t);
        fmpz_mod(t, fmpz_poly_lead(f), P);

        if (fmpz_invmod(t, t, P) == 0)
        {
            printf("Exception in fmpz_poly_start_hensel_lift.\n");
            abort();
        }

        fmpz_poly_scalar_mul_fmpz(monic_f, f, t);
        fmpz_poly_scalar_mod_fmpz(monic_f, monic_f, P);
        fmpz_clear(t);
    }

    fmpz_poly_hensel_build_tree(link, v, w, local_fac);

    {
        long *e, n = FLINT_CLOG2(N) + 1;

        e = flint_malloc(n * sizeof(long));
        for (e[i = 0] = N; e[i] > 1; i++)
            e[i + 1] = (e[i] + 1) / 2;

        for (i--; i > 0; i--)
        {
            fmpz_poly_hensel_lift_tree(link, v, w, monic_f, r, 
                p, e[i+1], e[i], 1);
        }
        if (N > 1)
        {
            fmpz_poly_hensel_lift_tree(link, v, w, monic_f, r, 
                p, e[i+1], e[i], 0);
        }

        preve = e[i+1];

        flint_free(e);
    }

    /*
        Now everything is lifted to p^N, we just need to 
        insert the factors into their correct places in lifted_fac.
     */
    fmpz_poly_factor_fit_length(lifted_fac, r);

    for (i = 0; i < 2*r - 2; i++)
    { 
        if (link[i] < 0)
        {
            fmpz_poly_scalar_smod_fmpz(lifted_fac->p + (- link[i] - 1), v[i], P);
            lifted_fac->exp[- link[i] - 1] = 1L; 
        }
    }
    lifted_fac->num = r;

    fmpz_clear(p);
    fmpz_clear(P);
    fmpz_poly_clear(monic_f);

    return preve;
}
示例#27
0
int main(void)
{
   int i, j, result;
   ulong count = UWORD(0);
   gmp_randstate_t st;
   FLINT_TEST_INIT(state);
   gmp_randinit_default(st);
   

   flint_printf("factor_pp1....");
   fflush(stdout);

   for (i = 0; i < 50 * flint_test_multiplier(); i++) /* Test random numbers */
   {
      mp_bitcnt_t bits;
      mpz_t m, n;
      fmpz_t n1, n2, r;

      mpz_init(n);
      mpz_init(m);
      fmpz_init(n1);
      fmpz_init(n2);
      fmpz_init(r);

      do {
         mpz_urandomb(n, st, n_randint(state, 128) + 2); 
      } while (flint_mpz_cmp_ui(n, 2) < 0);
      do {
         mpz_urandomb(m, st, n_randint(state, 50) + 2); 
      } while (!mpz_probab_prime_p(m, 20));
      mpz_mul(n, n, m);

      fmpz_set_mpz(n1, n);
      bits = FLINT_MIN(fmpz_bits(n1), FLINT_BITS);

      for (j = 0; j < 20; j++)
      {
         fmpz_factor_pp1(n2, n1, 10000, 10000, n_randbits(state, bits - 2) + 3);
         if (fmpz_cmp_ui(n2, 1) > 0) break;
      }
      
      if (fmpz_cmp_ui(n2, 1) > 0)
      {
         count++;
         fmpz_mod(r, n1, n2);
         result = (fmpz_is_zero(r));
         if (!result)
         {
            flint_printf("FAIL:\n");
            flint_printf("n1 = ");
            fmpz_print(n1);
            flint_printf(", n2 = ");
            fmpz_print(n2);
            flint_printf("\n"); 
            fmpz_print(r); flint_printf("\n");
            abort();
         }
      }

      fmpz_clear(n1);
      fmpz_clear(n2);
      fmpz_clear(r);
      mpz_clear(m);
      mpz_clear(n);
   }
   
   if (count < 49 * flint_test_multiplier())
   {
      flint_printf("FAIL:\n");
      flint_printf("Only %wu numbers factored\n", count); 
      abort();
   }

   
   gmp_randclear(st);
   FLINT_TEST_CLEANUP(state);
   flint_printf("PASS\n");
   return 0;
}
示例#28
0
void _padic_teichmuller(fmpz_t rop, const fmpz_t op, const fmpz_t p, slong N)
{
    if (fmpz_equal_ui(p, 2))
    {
        fmpz_one(rop);
    }
    else if (N == 1)
    {
        fmpz_mod(rop, op, p);
    }
    else
    {
        slong *a, i, n;
        fmpz *pow, *u;
        fmpz_t s, t;
        fmpz_t inv;
        fmpz_t pm1;

        a = _padic_lifts_exps(&n, N);

        pow = _fmpz_vec_init(2 * n);
        u   = pow + n;

        _padic_lifts_pows(pow, a, n, p);

        fmpz_init(s);
        fmpz_init(t);
        fmpz_init(inv);
        fmpz_init(pm1);

        fmpz_sub_ui(pm1, p, 1);

        /* Compute reduced units for (p-1) */
        {
            fmpz_mod(u + 0, pm1, pow + 0);
        }
        for (i = 1; i < n; i++)
        {
            fmpz_mod(u + i, u + (i - 1), pow + i);
        }

        /* Run Newton iteration */
        i = n - 1;
        {
            fmpz_mod(rop, op, pow + i);

            fmpz_set(inv, pm1);
        }
        for (i--; i >= 0; i--)
        {
            /* Lift rop */
            fmpz_powm(s, rop, p, pow + i);
            fmpz_sub(s, s, rop);
            fmpz_mul(t, s, inv);
            fmpz_sub(rop, rop, t);
            fmpz_mod(rop, rop, pow + i);

            /* Lift inv */
            if (i > 0)
            {
                fmpz_mul(s, inv, inv);
                fmpz_mul(t, u + i, s);
                fmpz_mul_2exp(inv, inv, 1);
                fmpz_sub(inv, inv, t);
                fmpz_mod(inv, inv, pow + i);
            }
        }

        fmpz_clear(s);
        fmpz_clear(t);
        fmpz_clear(inv);
        fmpz_clear(pm1);
        _fmpz_vec_clear(pow, 2 * n);
        flint_free(a);
    }
}
示例#29
0
void frob(const mpoly_t P, const ctx_t ctxFracQt,
          const qadic_t t1, const qadic_ctx_t Qq,
          prec_t *prec, const prec_t *prec_in,
          int verbose)
{
    const padic_ctx_struct *Qp = &Qq->pctx;
    const fmpz *p = Qp->p;
    const long a  = qadic_ctx_degree(Qq);
    const long n  = P->n - 1;
    const long d  = mpoly_degree(P, -1, ctxFracQt);
    const long b  = gmc_basis_size(n, d);

    long i, j, k;

    /* Diagonal fibre */
    padic_mat_t F0;

    /* Gauss--Manin Connection */
    mat_t M;
    mon_t *bR, *bC;
    fmpz_poly_t r;

    /* Local solution */
    fmpz_poly_mat_t C, Cinv;
    long vC, vCinv;

    /* Frobenius */
    fmpz_poly_mat_t F;
    long vF;

    fmpz_poly_mat_t F1;
    long vF1;

    fmpz_poly_t cp;

    clock_t c0, c1;
    double c;

    if (verbose)
    {
        printf("Input:\n");
        printf("  P  = "), mpoly_print(P, ctxFracQt), printf("\n");
        printf("  p  = "), fmpz_print(p), printf("\n");
        printf("  t1 = "), qadic_print_pretty(t1, Qq), printf("\n");
        printf("\n");
        fflush(stdout);
    }

    /* Step 1 {M, r} *********************************************************/

    c0 = clock();

    mat_init(M, b, b, ctxFracQt);
    fmpz_poly_init(r);

    gmc_compute(M, &bR, &bC, P, ctxFracQt);

    {
        fmpz_poly_t t;

        fmpz_poly_init(t);
        fmpz_poly_set_ui(r, 1);
        for (i = 0; i < M->m; i++)
            for (j = 0; j < M->n; j++)
            {
                fmpz_poly_lcm(t, r, fmpz_poly_q_denref(
                                  (fmpz_poly_q_struct *) mat_entry(M, i, j, ctxFracQt)));
                fmpz_poly_swap(r, t);
            }
        fmpz_poly_clear(t);
    }

    c1 = clock();
    c  = (double) (c1 - c0) / CLOCKS_PER_SEC;

    if (verbose)
    {
        printf("Gauss-Manin connection:\n");
        printf("  r(t) = "), fmpz_poly_print_pretty(r, "t"), printf("\n");
        printf("  Time = %f\n", c);
        printf("\n");
        fflush(stdout);
    }

    {
        qadic_t t;

        qadic_init2(t, 1);
        fmpz_poly_evaluate_qadic(t, r, t1, Qq);

        if (qadic_is_zero(t))
        {
            printf("Exception (deformation_frob).\n");
            printf("The resultant r evaluates to zero (mod p) at t1.\n");
            abort();
        }
        qadic_clear(t);
    }

    /* Precisions ************************************************************/

    if (prec_in != NULL)
    {
        *prec = *prec_in;
    }
    else
    {
        deformation_precisions(prec, p, a, n, d, fmpz_poly_degree(r));
    }

    if (verbose)
    {
        printf("Precisions:\n");
        printf("  N0   = %ld\n", prec->N0);
        printf("  N1   = %ld\n", prec->N1);
        printf("  N2   = %ld\n", prec->N2);
        printf("  N3   = %ld\n", prec->N3);
        printf("  N3i  = %ld\n", prec->N3i);
        printf("  N3w  = %ld\n", prec->N3w);
        printf("  N3iw = %ld\n", prec->N3iw);
        printf("  N4   = %ld\n", prec->N4);
        printf("  m    = %ld\n", prec->m);
        printf("  K    = %ld\n", prec->K);
        printf("  r    = %ld\n", prec->r);
        printf("  s    = %ld\n", prec->s);
        printf("\n");
        fflush(stdout);
    }

    /* Initialisation ********************************************************/

    padic_mat_init2(F0, b, b, prec->N4);

    fmpz_poly_mat_init(C, b, b);
    fmpz_poly_mat_init(Cinv, b, b);

    fmpz_poly_mat_init(F, b, b);
    vF = 0;

    fmpz_poly_mat_init(F1, b, b);
    vF1 = 0;

    fmpz_poly_init(cp);

    /* Step 2 {F0} ***********************************************************/

    {
        padic_ctx_t pctx_F0;
        fmpz *t;

        padic_ctx_init(pctx_F0, p, FLINT_MIN(prec->N4 - 10, 0), prec->N4, PADIC_VAL_UNIT);
        t = _fmpz_vec_init(n + 1);

        c0 = clock();

        mpoly_diagonal_fibre(t, P, ctxFracQt);

        diagfrob(F0, t, n, d, prec->N4, pctx_F0, 0);
        padic_mat_transpose(F0, F0);

        c1 = clock();
        c  = (double) (c1 - c0) / CLOCKS_PER_SEC;

        if (verbose)
        {
            printf("Diagonal fibre:\n");
            printf("  P(0) = {"), _fmpz_vec_print(t, n + 1), printf("}\n");
            printf("  Time = %f\n", c);
            printf("\n");
            fflush(stdout);
        }

        _fmpz_vec_clear(t, n + 1);
        padic_ctx_clear(pctx_F0);
    }

    /* Step 3 {C, Cinv} ******************************************************/
    /*
        Compute C as a matrix over Z_p[[t]].  A is the same but as a series
        of matrices over Z_p.  Mt is the matrix -M^t, and Cinv is C^{-1}^t,
        the local solution of the differential equation replacing M by Mt.
     */

    c0 = clock();
    {
        const long K = prec->K;
        padic_mat_struct *A;

        gmde_solve(&A, K, p, prec->N3, prec->N3w, M, ctxFracQt);
        gmde_convert_soln(C, &vC, A, K, p);

        for(i = 0; i < K; i++)
            padic_mat_clear(A + i);
        free(A);
    }
    c1 = clock();
    c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
    if (verbose)
    {
        printf("Local solution:\n");
        printf("  Time for C      = %f\n", c);
        fflush(stdout);
    }

    c0 = clock();
    {
        const long K = (prec->K + (*p) - 1) / (*p);
        mat_t Mt;
        padic_mat_struct *Ainv;

        mat_init(Mt, b, b, ctxFracQt);
        mat_transpose(Mt, M, ctxFracQt);
        mat_neg(Mt, Mt, ctxFracQt);
        gmde_solve(&Ainv, K, p, prec->N3i, prec->N3iw, Mt, ctxFracQt);
        gmde_convert_soln(Cinv, &vCinv, Ainv, K, p);

        fmpz_poly_mat_transpose(Cinv, Cinv);
        fmpz_poly_mat_compose_pow(Cinv, Cinv, *p);

        for(i = 0; i < K; i++)
            padic_mat_clear(Ainv + i);
        free(Ainv);
        mat_clear(Mt, ctxFracQt);
    }
    c1 = clock();
    c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
    if (verbose)
    {
        printf("  Time for C^{-1} = %f\n", c);
        printf("\n");
        fflush(stdout);
    }

    /* Step 4 {F(t) := C(t) F(0) C(t^p)^{-1}} ********************************/
    /*
        Computes the product C(t) F(0) C(t^p)^{-1} modulo (p^{N_2}, t^K).
        This is done by first computing the unit part of the product
        exactly over the integers modulo t^K.
     */

    c0 = clock();
    {
        fmpz_t pN;
        fmpz_poly_mat_t T;

        fmpz_init(pN);
        fmpz_poly_mat_init(T, b, b);

        for (i = 0; i < b; i++)
        {
            /* Find the unique k s.t. F0(i,k) is non-zero */
            for (k = 0; k < b; k++)
                if (!fmpz_is_zero(padic_mat_entry(F0, i, k)))
                    break;
            if (k == b)
            {
                printf("Exception (frob). F0 is singular.\n\n");
                abort();
            }

            for (j = 0; j < b; j++)
            {
                fmpz_poly_scalar_mul_fmpz(fmpz_poly_mat_entry(T, i, j),
                                          fmpz_poly_mat_entry(Cinv, k, j),
                                          padic_mat_entry(F0, i, k));
            }
        }

        fmpz_poly_mat_mul(F, C, T);
        fmpz_poly_mat_truncate(F, prec->K);
        vF = vC + padic_mat_val(F0) + vCinv;

        /* Canonicalise (F, vF) */
        {
            long v = fmpz_poly_mat_ord_p(F, p);

            if (v == LONG_MAX)
            {
                printf("ERROR (deformation_frob).  F(t) == 0.\n");
                abort();
            }
            else if (v > 0)
            {
                fmpz_pow_ui(pN, p, v);
                fmpz_poly_mat_scalar_divexact_fmpz(F, F, pN);
                vF = vF + v;
            }
        }

        /* Reduce (F, vF) modulo p^{N2} */
        fmpz_pow_ui(pN, p, prec->N2 - vF);
        fmpz_poly_mat_scalar_mod_fmpz(F, F, pN);

        fmpz_clear(pN);
        fmpz_poly_mat_clear(T);
    }
    c1 = clock();
    c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
    if (verbose)
    {
        printf("Matrix for F(t):\n");
        printf("  Time = %f\n", c);
        printf("\n");
        fflush(stdout);
    }

    /* Step 5 {G = r(t)^m F(t)} **********************************************/

    c0 = clock();
    {
        fmpz_t pN;
        fmpz_poly_t t;

        fmpz_init(pN);
        fmpz_poly_init(t);

        fmpz_pow_ui(pN, p, prec->N2 - vF);

        /* Compute r(t)^m mod p^{N2-vF} */
        if (prec->denR == NULL)
        {
            fmpz_mod_poly_t _t;

            fmpz_mod_poly_init(_t, pN);
            fmpz_mod_poly_set_fmpz_poly(_t, r);
            fmpz_mod_poly_pow(_t, _t, prec->m);
            fmpz_mod_poly_get_fmpz_poly(t, _t);
            fmpz_mod_poly_clear(_t);
        }
        else
        {
            /* TODO: We don't really need a copy */
            fmpz_poly_set(t, prec->denR);
        }

        fmpz_poly_mat_scalar_mul_fmpz_poly(F, F, t);
        fmpz_poly_mat_scalar_mod_fmpz(F, F, pN);

        /* TODO: This should not be necessary? */
        fmpz_poly_mat_truncate(F, prec->K);

        fmpz_clear(pN);
        fmpz_poly_clear(t);
    }
    c1 = clock();
    c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
    if (verbose)
    {
        printf("Analytic continuation:\n");
        printf("  Time = %f\n", c);
        printf("\n");
        fflush(stdout);
    }

    /* Steps 6 and 7 *********************************************************/

    if (a == 1)
    {
        /* Step 6 {F(1) = r(t_1)^{-m} G(t_1)} ********************************/

        c0 = clock();
        {
            const long N = prec->N2 - vF;

            fmpz_t f, g, t, pN;

            fmpz_init(f);
            fmpz_init(g);
            fmpz_init(t);
            fmpz_init(pN);

            fmpz_pow_ui(pN, p, N);

            /* f := \hat{t_1}, g := r(\hat{t_1})^{-m} */
            _padic_teichmuller(f, t1->coeffs + 0, p, N);
            if (prec->denR == NULL)
            {
                _fmpz_mod_poly_evaluate_fmpz(g, r->coeffs, r->length, f, pN);
                fmpz_powm_ui(t, g, prec->m, pN);
            }
            else
            {
                _fmpz_mod_poly_evaluate_fmpz(t, prec->denR->coeffs, prec->denR->length, f, pN);
            }
            _padic_inv(g, t, p, N);

            /* F1 := g G(\hat{t_1}) */
            for (i = 0; i < b; i++)
                for (j = 0; j < b; j++)
                {
                    const fmpz_poly_struct *poly = fmpz_poly_mat_entry(F, i, j);
                    const long len               = poly->length;

                    if (len == 0)
                    {
                        fmpz_poly_zero(fmpz_poly_mat_entry(F1, i, j));
                    }
                    else
                    {
                        fmpz_poly_fit_length(fmpz_poly_mat_entry(F1, i, j), 1);

                        _fmpz_mod_poly_evaluate_fmpz(t, poly->coeffs, len, f, pN);
                        fmpz_mul(fmpz_poly_mat_entry(F1, i, j)->coeffs + 0, g, t);
                        fmpz_mod(fmpz_poly_mat_entry(F1, i, j)->coeffs + 0,
                                 fmpz_poly_mat_entry(F1, i, j)->coeffs + 0, pN);

                        _fmpz_poly_set_length(fmpz_poly_mat_entry(F1, i, j), 1);
                        _fmpz_poly_normalise(fmpz_poly_mat_entry(F1, i, j));
                    }
                }

            vF1 = vF;
            fmpz_poly_mat_canonicalise(F1, &vF1, p);

            fmpz_clear(f);
            fmpz_clear(g);
            fmpz_clear(t);
            fmpz_clear(pN);
        }
        c1 = clock();
        c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
        if (verbose)
        {
            printf("Evaluation:\n");
            printf("  Time = %f\n", c);
            printf("\n");
            fflush(stdout);
        }
    }
    else
    {
        /* Step 6 {F(1) = r(t_1)^{-m} G(t_1)} ********************************/

        c0 = clock();
        {
            const long N = prec->N2 - vF;
            fmpz_t pN;
            fmpz *f, *g, *t;

            fmpz_init(pN);

            f = _fmpz_vec_init(a);
            g = _fmpz_vec_init(2 * a - 1);
            t = _fmpz_vec_init(2 * a - 1);

            fmpz_pow_ui(pN, p, N);

            /* f := \hat{t_1}, g := r(\hat{t_1})^{-m} */
            _qadic_teichmuller(f, t1->coeffs, t1->length, Qq->a, Qq->j, Qq->len, p, N);
            if (prec->denR == NULL)
            {
                fmpz_t e;
                fmpz_init_set_ui(e, prec->m);
                _fmpz_mod_poly_compose_smod(g, r->coeffs, r->length, f, a,
                                            Qq->a, Qq->j, Qq->len, pN);
                _qadic_pow(t, g, a, e, Qq->a, Qq->j, Qq->len, pN);
                fmpz_clear(e);
            }
            else
            {
                _fmpz_mod_poly_reduce(prec->denR->coeffs, prec->denR->length, Qq->a, Qq->j, Qq->len, pN);
                _fmpz_poly_normalise(prec->denR);

                _fmpz_mod_poly_compose_smod(t, prec->denR->coeffs, prec->denR->length, f, a,
                                            Qq->a, Qq->j, Qq->len, pN);
            }
            _qadic_inv(g, t, a, Qq->a, Qq->j, Qq->len, p, N);

            /* F1 := g G(\hat{t_1}) */
            for (i = 0; i < b; i++)
                for (j = 0; j < b; j++)
                {
                    const fmpz_poly_struct *poly = fmpz_poly_mat_entry(F, i, j);
                    const long len               = poly->length;

                    fmpz_poly_struct *poly2 = fmpz_poly_mat_entry(F1, i, j);

                    if (len == 0)
                    {
                        fmpz_poly_zero(poly2);
                    }
                    else
                    {
                        _fmpz_mod_poly_compose_smod(t, poly->coeffs, len, f, a,
                                                    Qq->a, Qq->j, Qq->len, pN);

                        fmpz_poly_fit_length(poly2, 2 * a - 1);
                        _fmpz_poly_mul(poly2->coeffs, g, a, t, a);
                        _fmpz_mod_poly_reduce(poly2->coeffs, 2 * a - 1, Qq->a, Qq->j, Qq->len, pN);
                        _fmpz_poly_set_length(poly2, a);
                        _fmpz_poly_normalise(poly2);
                    }
                }

            /* Now the matrix for p^{-1} F_p at t=t_1 is (F1, vF1). */
            vF1 = vF;
            fmpz_poly_mat_canonicalise(F1, &vF1, p);

            fmpz_clear(pN);
            _fmpz_vec_clear(f, a);
            _fmpz_vec_clear(g, 2 * a - 1);
            _fmpz_vec_clear(t, 2 * a - 1);
        }
        c1 = clock();
        c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
        if (verbose)
        {
            printf("Evaluation:\n");
            printf("  Time = %f\n", c);
            printf("\n");
            fflush(stdout);
        }

        /* Step 7 {Norm} *****************************************************/
        /*
            Computes the matrix for $q^{-1} F_q$ at $t = t_1$ as the
            product $F \sigma(F) \dotsm \sigma^{a-1}(F)$ up appropriate
            transpositions because our convention of columns vs rows is
            the opposite of that used by Gerkmann.

            Note that, in any case, transpositions do not affect
            the characteristic polynomial.
         */

        c0 = clock();
        {
            const long N = prec->N1 - a * vF1;

            fmpz_t pN;
            fmpz_poly_mat_t T;

            fmpz_init(pN);
            fmpz_poly_mat_init(T, b, b);

            fmpz_pow_ui(pN, p, N);

            fmpz_poly_mat_frobenius(T, F1, 1, p, N, Qq);
            _qadic_mat_mul(F1, F1, T, pN, Qq);

            for (i = 2; i < a; i++)
            {
                fmpz_poly_mat_frobenius(T, T, 1, p, N, Qq);
                _qadic_mat_mul(F1, F1, T, pN, Qq);
            }

            vF1 = a * vF1;
            fmpz_poly_mat_canonicalise(F1, &vF1, p);

            fmpz_clear(pN);
            fmpz_poly_mat_clear(T);
        }
        c1 = clock();
        c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
        if (verbose)
        {
            printf("Norm:\n");
            printf("  Time = %f\n", c);
            printf("\n");
            fflush(stdout);
        }
    }

    /* Step 8 {Reverse characteristic polynomial} ****************************/

    c0 = clock();

    deformation_revcharpoly(cp, F1, vF1, n, d, prec->N0, prec->r, prec->s, Qq);

    c1 = clock();
    c  = (double) (c1 - c0) / CLOCKS_PER_SEC;
    if (verbose)
    {
        printf("Reverse characteristic polynomial:\n");
        printf("  p(T) = "), fmpz_poly_print_pretty(cp, "T"), printf("\n");
        printf("  Time = %f\n", c);
        printf("\n");
        fflush(stdout);
    }

    /* Clean up **************************************************************/

    padic_mat_clear(F0);

    mat_clear(M, ctxFracQt);
    free(bR);
    free(bC);
    fmpz_poly_clear(r);

    fmpz_poly_mat_clear(C);
    fmpz_poly_mat_clear(Cinv);

    fmpz_poly_mat_clear(F);
    fmpz_poly_mat_clear(F1);
    fmpz_poly_clear(cp);
}
示例#30
0
int main(void)
{
    int i, result;
    FLINT_TEST_INIT(state);

    flint_printf("sqrtmod....");
    fflush(stdout);

    

    for (i = 0; i < 100 * flint_test_multiplier(); i++) /* Test random integers */
    {
        int ans;
        fmpz_t a, b, c, p;
        mp_limb_t prime;

        prime = n_randint(state, UWORD(1) << (FLINT_BITS - 1));
        prime = n_nextprime(prime, 1);

        fmpz_init(a);
        fmpz_init(b);
        fmpz_init(c);
        fmpz_init(p);

        fmpz_set_ui(p, prime);
        fmpz_randm(a, state, p);

        ans = fmpz_sqrtmod(b, a, p);

        fmpz_mul(c, b, b);
        fmpz_mod(c, c, p);

        result = (ans == 0 || fmpz_equal(a, c));
        if (!result)
        {
            flint_printf("FAIL (random):\n");
            flint_printf("p = "), fmpz_print(p), flint_printf("\n");
            flint_printf("a = "), fmpz_print(a), flint_printf("\n");
            flint_printf("b = "), fmpz_print(b), flint_printf("\n");
            flint_printf("c = "), fmpz_print(c), flint_printf("\n");
            abort();
        }

        fmpz_clear(a);
        fmpz_clear(b);
        fmpz_clear(c);
        fmpz_clear(p);
    }

    for (i = 0; i < 100 * flint_test_multiplier(); i++) /* Test random squares */
    {
        int ans;
        fmpz_t a, b, c, d, p;
        mp_limb_t prime;

        prime = n_randint(state, UWORD(1) << (FLINT_BITS - 1));
        prime = n_nextprime(prime, 1);

        fmpz_init(a);
        fmpz_init(b);
        fmpz_init(c);
        fmpz_init(d);
        fmpz_init(p);

        fmpz_set_ui(p, prime);
        do 
            fmpz_randm(b, state, p);
        while (fmpz_is_zero(b));

        fmpz_mul(a, b, b);
        fmpz_mod(a, a, p);

        /* check a special case */
        if (i == 0)
        {
            fmpz_set_str(p, "15951355998396157", 10);
            fmpz_set_str(a, "7009303413761286", 10);
        }

        ans = fmpz_sqrtmod(c, a, p);

        fmpz_mul(d, c, c);
        fmpz_mod(d, d, p);

        result = (ans && fmpz_equal(a, d));
        if (!result)
        {
            flint_printf("FAIL (squares):\n");
            flint_printf("p            = "), fmpz_print(p), flint_printf("\n");
            flint_printf("a (= b^2)    = "), fmpz_print(a), flint_printf("\n");
            flint_printf("b            = "), fmpz_print(b), flint_printf("\n");
            flint_printf("c (= sqrt(a) = "), fmpz_print(c), flint_printf("\n");
            flint_printf("d (= c^2)    = "), fmpz_print(d), flint_printf("\n");
            flint_printf("ans          = %d\n", ans);
            abort();
        }

        fmpz_clear(a);
        fmpz_clear(b);
        fmpz_clear(c);
        fmpz_clear(d);
        fmpz_clear(p);
    }

    FLINT_TEST_CLEANUP(state);
    
    flint_printf("PASS\n");
    return 0;
}