/* Assumes poly1 and poly2 are not length 0 and len1 >= len2. */ void _fmpz_poly_mulmid_classical(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) { if ((len1 == 1) && (len2 == 1)) /* Special case if the length of both inputs is 1 */ { fmpz_mul(res, poly1, poly2); } else /* Ordinary case */ { slong i; /* Set res[i] = poly1[i]*poly2[0] */ _fmpz_vec_scalar_mul_fmpz(res, poly1 + len2 - 1, len1 - len2 + 1, poly2); /* out[i+j] += in1[i]*in2[j] */ for (i = 0; i < len2 - 1; i++) _fmpz_vec_scalar_addmul_fmpz(res, poly2 + len2 - i - 1, FLINT_MIN(i + 1, len1 - len2 + 1), poly1 + i); for (; i < len1 - 1; i++) _fmpz_vec_scalar_addmul_fmpz(res + i - len2 + 2, poly2 + 1, FLINT_MIN(len2 - 1, len1 - i - 1), poly1 + i); } }
/* Assumes poly1 and poly2 are not length 0. */ void _fmpz_poly_mul_classical(fmpz * res, const fmpz * poly1, slong len1, const fmpz * poly2, slong len2) { if (len1 == 1 && len2 == 1) /* Special case if the length of both inputs is 1 */ { fmpz_mul(res, poly1, poly2); } else /* Ordinary case */ { slong i; /* Set res[i] = poly1[i]*poly2[0] */ _fmpz_vec_scalar_mul_fmpz(res, poly1, len1, poly2); /* Set res[i+len1-1] = in1[len1-1]*in2[i] */ _fmpz_vec_scalar_mul_fmpz(res + len1, poly2 + 1, len2 - 1, poly1 + len1 - 1); /* out[i+j] += in1[i]*in2[j] */ for (i = 0; i < len1 - 1; i++) _fmpz_vec_scalar_addmul_fmpz(res + i + 1, poly2 + 1, len2 - 1, poly1 + i); } }
/* Assumes poly1 and poly2 are not length 0 and 0 < n <= len1 + len2 - 1. */ void _fmpz_poly_mullow_classical(fmpz * res, const fmpz * poly1, long len1, const fmpz * poly2, long len2, long n) { if ((len1 == 1 && len2 == 1) || n == 1) /* Special case if the length of output is 1 */ { fmpz_mul(res, poly1, poly2); } else /* Ordinary case */ { long i; /* Set res[i] = poly1[i]*poly2[0] */ _fmpz_vec_scalar_mul_fmpz(res, poly1, FLINT_MIN(len1, n), poly2); /* Set res[i+len1-1] = in1[len1-1]*in2[i] */ if (n > len1) _fmpz_vec_scalar_mul_fmpz(res + len1, poly2 + 1, n - len1, poly1 + len1 - 1); /* out[i+j] += in1[i]*in2[j] */ for (i = 0; i < FLINT_MIN(len1, n) - 1; i++) _fmpz_vec_scalar_addmul_fmpz(res + i + 1, poly2 + 1, FLINT_MIN(len2, n - i) - 1, poly1 + i); } }
int dgsl_mp_call_inlattice(fmpz *rop, const dgsl_mp_t *self, gmp_randstate_t state) { assert(rop); assert(self); const long m = fmpz_mat_nrows(self->B); const long n = fmpz_mat_ncols(self->B); mpz_t tmp_g; mpz_init(tmp_g); fmpz_t tmp_f; fmpz_init(tmp_f); _fmpz_vec_zero(rop, n); for(long i=0; i<m; i++) { self->D[i]->call(tmp_g, self->D[i], state); fmpz_set_mpz(tmp_f, tmp_g); _fmpz_vec_scalar_addmul_fmpz(rop, self->B->rows[i], n, tmp_f); } _fmpz_vec_add(rop, rop, self->c_z, n); mpz_clear(tmp_g); fmpz_clear(tmp_f); return 0; }
/* Assumes len > 0. */ void _fmpz_poly_sqr_classical(fmpz *rop, const fmpz *op, long len) { if (len == 1) /* Special case */ { fmpz_mul(rop, op, op); } else /* Ordinary case */ { long i; _fmpz_vec_scalar_mul_fmpz(rop, op, len, op); _fmpz_vec_scalar_mul_fmpz(rop + len, op + 1, len - 1, op + len - 1); for (i = 1; i < len - 1; i++) _fmpz_vec_scalar_addmul_fmpz(rop + i + 1, op + 1, i - 1, op + i); for (i = 1; i < 2 * len - 2; i++) fmpz_mul_ui(rop + i, rop + i, 2); for (i = 1; i < len - 1; i++) fmpz_addmul(rop + 2 * i, op + i, op + i); } }
/* Assumes poly1 and poly2 are not length 0. */ void _fmpz_poly_mulhigh_classical(fmpz * res, const fmpz * poly1, long len1, const fmpz * poly2, long len2, long start) { _fmpz_vec_zero(res, start); if (len1 == 1 && len2 == 1) /* Special case if the length of both inputs is 1 */ { if (start == 0) fmpz_mul(res, poly1, poly2); } else /* Ordinary case */ { long i, m, n; /* Set res[i] = poly1[i]*poly2[0] */ if (start < len1) _fmpz_vec_scalar_mul_fmpz(res + start, poly1 + start, len1 - start, poly2); /* Set res[i+len1-1] = in1[len1-1]*in2[i] */ m = FLINT_MAX(len1 - 1, start); _fmpz_vec_scalar_mul_fmpz(res + m, poly2 + m - len1 + 1, len2 - 1 + len1 - m, poly1 + len1 - 1); /* out[i+j] += in1[i]*in2[j] */ m = FLINT_MAX(start, len2 - 1); for (i = m - len2 + 1; i < len1 - 1; i++) { n = FLINT_MAX(i + 1, start); _fmpz_vec_scalar_addmul_fmpz(res + n, poly2 + n - i, len2 + i - n, poly1 + i); } } }
int dgsl_mp_call_coset(fmpz *rop, const dgsl_mp_t *self, gmp_randstate_t state) { assert(rop); assert(self); const long n = fmpz_mat_ncols(self->B); _fmpz_vec_zero(rop, n); mpfr_t *c = _mpfr_vec_init(n, mpfr_get_prec(self->sigma)); _mpfr_vec_set(c, self->c, n, MPFR_RNDN); mpfr_t c_prime; mpfr_init2(c_prime, mpfr_get_prec(self->sigma)); mpfr_t tmp; mpfr_init2(tmp, mpfr_get_prec(self->sigma)); mpfr_t sigma_prime; mpfr_init2(sigma_prime, mpfr_get_prec(self->sigma)); mpz_t z; mpz_init(z); mpfr_t z_mpfr; mpfr_init2(z_mpfr, mpfr_get_prec(self->sigma)); fmpz_t z_fmpz; fmpz_init(z_fmpz); size_t tau = 3; if (ceil(sqrt(log2((double)n))) > tau) tau = ceil(sqrt(log2((double)n))); mpfr_t *b = _mpfr_vec_init(n, mpfr_get_prec(self->sigma)); const long m = fmpz_mat_nrows(self->B); for(long j=0; j<m; j++) { long i = m-j-1; _mpfr_vec_dot_product(c_prime, c, self->G->rows[i], n, MPFR_RNDN); _mpfr_vec_dot_product(tmp, self->G->rows[i], self->G->rows[i], n, MPFR_RNDN); mpfr_div(c_prime, c_prime, tmp, MPFR_RNDN); mpfr_sqrt(tmp, tmp, MPFR_RNDN); mpfr_div(sigma_prime, self->sigma, tmp, MPFR_RNDN); assert(mpfr_cmp_d(sigma_prime, 0.0) > 0); dgs_disc_gauss_mp_t *D = dgs_disc_gauss_mp_init(sigma_prime, c_prime, tau, DGS_DISC_GAUSS_UNIFORM_ONLINE); D->call(z, D, state); dgs_disc_gauss_mp_clear(D); mpfr_set_z(z_mpfr, z, MPFR_RNDN); mpfr_neg(z_mpfr, z_mpfr, MPFR_RNDN); _mpfr_vec_set_fmpz_vec(b, self->B->rows[i], n, MPFR_RNDN); _mpfr_vec_scalar_addmul_mpfr(c, b, n, z_mpfr, MPFR_RNDN); fmpz_set_mpz(z_fmpz, z); _fmpz_vec_scalar_addmul_fmpz(rop, self->B->rows[i], n, z_fmpz); } fmpz_clear(z_fmpz); mpfr_clear(z_mpfr); mpfr_clear(sigma_prime); mpfr_clear(tmp); mpfr_clear(c_prime); _mpfr_vec_clear(c, n); _mpfr_vec_clear(b, n); return 0; }
void _padic_poly_sub(fmpz *rop, slong *val, slong N, const fmpz *op1, slong val1, slong len1, slong N1, const fmpz *op2, slong val2, slong len2, slong N2, const padic_ctx_t ctx) { const slong len = FLINT_MAX(len1, len2); *val = FLINT_MIN(val1, val2); if (val1 == val2) { _fmpz_poly_sub(rop, op1, len1, op2, len2); _padic_poly_canonicalise(rop, val, len, ctx->p); } else { fmpz_t x; fmpz_init(x); if (val1 < val2) /* F := p^g (G - p^{h-g} H) */ { fmpz_pow_ui(x, ctx->p, val2 - val1); if (rop == op1) { _fmpz_vec_zero(rop + len1, len2 - len1); _fmpz_vec_scalar_submul_fmpz(rop, op2, len2, x); } else { _fmpz_vec_scalar_mul_fmpz(rop, op2, len2, x); _fmpz_vec_neg(rop, rop, len2); _fmpz_poly_add(rop, op1, len1, rop, len2); } } else /* F := p^h (p^(g-h) G - H) */ { fmpz_pow_ui(x, ctx->p, val1 - val2); if (rop == op2) { _fmpz_vec_neg(rop, op2, len2); _fmpz_vec_zero(rop + len2, len1 - len2); _fmpz_vec_scalar_addmul_fmpz(rop, op1, len1, x); } else { _fmpz_vec_scalar_mul_fmpz(rop, op1, len1, x); _fmpz_poly_sub(rop, rop, len1, op2, len2); } } fmpz_clear(x); } /* Reduce */ if (N - *val > 0) { fmpz_t pow; int alloc; alloc = _padic_ctx_pow_ui(pow, N - *val, ctx); if (N >= N1 && N >= N2) { slong i; for (i = 0; i < len; i++) if (fmpz_sgn(rop + i) < 0) fmpz_add(rop + i, rop + i, pow); } else { _fmpz_vec_scalar_mod_fmpz(rop, rop, len, pow); } if (alloc) fmpz_clear(pow); } else { _fmpz_vec_zero(rop, len); *val = 0; } }
void _fmpq_poly_interpolate_fmpz_vec(fmpz * poly, fmpz_t den, const fmpz * xs, const fmpz * ys, long n) { fmpz *P, *Q, *w; fmpz_t t; long i, j; /* Constant */ if (n == 1) { fmpz_set(poly, ys); fmpz_one(den); return; } /* Linear */ if (n == 2) { fmpz_sub(den, xs, xs + 1); fmpz_sub(poly + 1, ys, ys + 1); fmpz_mul(poly, xs, ys + 1); fmpz_submul(poly, xs + 1, ys); return; } fmpz_init(t); P = _fmpz_vec_init(n + 1); Q = _fmpz_vec_init(n); w = _fmpz_vec_init(n); /* P = (x-x[0])*(x-x[1])*...*(x-x[n-1]) */ _fmpz_poly_product_roots_fmpz_vec(P, xs, n); /* Weights */ for (i = 0; i < n; i++) { fmpz_one(w + i); for (j = 0; j < n; j++) { if (i != j) { fmpz_sub(t, xs + i, xs + j); fmpz_mul(w + i, w + i, t); } } } _fmpz_vec_zero(poly, n); _fmpz_vec_lcm(den, w, n); for (i = 0; i < n; i++) { /* Q = P / (x - x[i]) */ _fmpz_poly_div_root(Q, P, n + 1, xs + i); /* result += Q * weight(i) */ fmpz_divexact(t, den, w + i); fmpz_mul(t, t, ys + i); _fmpz_vec_scalar_addmul_fmpz(poly, Q, n, t); } _fmpz_vec_clear(P, n + 1); _fmpz_vec_clear(Q, n); _fmpz_vec_clear(w, n); fmpz_clear(t); }
int _fmpz_poly_sqrt_classical(fmpz * res, const fmpz * poly, long len) { long i, m; int result; /* the degree must be even */ if (len % 2 == 0) return 0; /* valuation must be even, and then can be reduced to 0 */ while (fmpz_is_zero(poly)) { if (!fmpz_is_zero(poly + 1)) return 0; fmpz_zero(res); poly += 2; len -= 2; res++; } /* check whether a square root exists modulo 2 */ for (i = 1; i < len; i += 2) if (!fmpz_is_even(poly + i)) return 0; /* check endpoints */ if (!fmpz_is_square(poly) || (len > 1 && !fmpz_is_square(poly + len - 1))) return 0; /* square root of leading coefficient */ m = (len + 1) / 2; fmpz_sqrt(res + m - 1, poly + len - 1); result = 1; /* do long divison style 'square root with remainder' from top to bottom */ if (len > 1) { fmpz_t t, u; fmpz * r; fmpz_init(t); fmpz_init(u); r = _fmpz_vec_init(len); _fmpz_vec_set(r, poly, len); fmpz_mul_ui(u, res + m - 1, 2); for (i = 1; i < m; i++) { fmpz_fdiv_qr(res + m - i - 1, t, r + len - i - 1, u); if (!fmpz_is_zero(t)) { result = 0; break; } fmpz_mul_si(t, res + m - i - 1, -2); _fmpz_vec_scalar_addmul_fmpz(r + len - 2*i, res + m - i, i - 1, t); fmpz_submul(r + len - 2*i - 1, res + m - i - 1, res + m - i - 1); } for (i = m; i < len && result; i++) if (!fmpz_is_zero(r + len - 1 - i)) result = 0; _fmpz_vec_clear(r, len); fmpz_clear(t); fmpz_clear(u); } return result; }