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); }
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)); } }
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); }
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); }
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); } }
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); } }
// 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); }
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); }
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); }
// 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); }
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); }
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); } }
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); }
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_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); }
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); }
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; } } }
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); }
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; }
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; }
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; }
/** * 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; }
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; }
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 }
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"); }
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; }
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; }
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); } }
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); }
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; }