void _nmod_poly_divrem_basecase_1(mp_ptr Q, mp_ptr R, mp_ptr W, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod) { const mp_limb_t invL = n_invmod(B[lenB - 1], mod.n); slong iR; mp_ptr ptrQ = Q - lenB + 1; mp_ptr R1 = W; flint_mpn_copyi(R1, A, lenA); for (iR = lenA - 1; iR >= lenB - 1; iR--) { if (R1[iR] == 0) { ptrQ[iR] = WORD(0); } else { ptrQ[iR] = n_mulmod2_preinv(R1[iR], invL, mod.n, mod.ninv); if (lenB > 1) { const mp_limb_t c = n_negmod(ptrQ[iR], mod.n); mpn_addmul_1(R1 + iR - lenB + 1, B, lenB - 1, c); } } } if (lenB > 1) _nmod_vec_reduce(R, R1, lenB - 1, mod); }
void sample(void * arg, ulong count) { mp_limb_t n; nmod_t mod; info_t * info = (info_t *) arg; mp_bitcnt_t bits = info->bits; mp_ptr vec = _nmod_vec_init(1000); mp_ptr vec2 = _nmod_vec_init(1000); mp_size_t j; long i; flint_rand_t state; flint_randinit(state); for (j = 0; j < 1000; j++) vec[j] = n_randlimb(state); prof_start(); for (i = 0; i < count; i++) { n = n_randbits(state, bits); if (n == 0UL) n++; nmod_init(&mod, n); _nmod_vec_reduce(vec2, vec, 1000, mod); } prof_stop(); flint_randclear(state); _nmod_vec_clear(vec); _nmod_vec_clear(vec2); }
void _nmod_poly_rem_basecase_1(mp_ptr R, mp_ptr W, mp_srcptr A, long lenA, mp_srcptr B, long lenB, nmod_t mod) { if (lenB > 1) { const mp_limb_t invL = n_invmod(B[lenB - 1], mod.n); long iR; mp_ptr R1 = W; mpn_copyi(R1, A, lenA); for (iR = lenA - 1; iR >= lenB - 1; iR--) { if (R1[iR] != 0) { const mp_limb_t q = n_mulmod2_preinv(R1[iR], invL, mod.n, mod.ninv); const mp_limb_t c = n_negmod(q, mod.n); mpn_addmul_1(R1 + iR - lenB + 1, B, lenB - 1, c); } } _nmod_vec_reduce(R, R1, lenB - 1, mod); } }
void nmod_mat_set(nmod_mat_t B, const nmod_mat_t A) { if (A->mod.n <= B->mod.n) _nmod_vec_set(B->entries, A->entries, A->r*A->c); else _nmod_vec_reduce(B->entries, A->entries, A->r*A->c, B->mod); }
/* Assumes poly1 and poly2 are not length 0 and 0 < trunc <= len1 + len2 - 1 */ void _nmod_poly_mullow_classical(mp_ptr res, mp_srcptr poly1, slong len1, mp_srcptr poly2, slong len2, slong trunc, nmod_t mod) { if (len1 == 1 || trunc == 1) /* Special case if the length of output is 1 */ { res[0] = n_mulmod2_preinv(poly1[0], poly2[0], mod.n, mod.ninv); } else /* Ordinary case */ { slong i; slong bits = FLINT_BITS - (slong) mod.norm; slong log_len = FLINT_BIT_COUNT(len2); if (2 * bits + log_len <= FLINT_BITS) { /* Set res[i] = poly1[i]*poly2[0] */ mpn_mul_1(res, poly1, FLINT_MIN(len1, trunc), poly2[0]); if (len2 != 1) { /* Set res[i+len1-1] = in1[len1-1]*in2[i] */ if (trunc > len1) mpn_mul_1(res + len1, poly2 + 1, trunc - len1, poly1[len1 - 1]); /* out[i+j] += in1[i]*in2[j] */ for (i = 0; i < FLINT_MIN(len1, trunc) - 1; i++) mpn_addmul_1(res + i + 1, poly2 + 1, FLINT_MIN(len2, trunc - i) - 1, poly1[i]); } _nmod_vec_reduce(res, res, trunc, mod); } else { /* Set res[i] = poly1[i]*poly2[0] */ _nmod_vec_scalar_mul_nmod(res, poly1, FLINT_MIN(len1, trunc), poly2[0], mod); if (len2 == 1) return; /* Set res[i+len1-1] = in1[len1-1]*in2[i] */ if (trunc > len1) _nmod_vec_scalar_mul_nmod(res + len1, poly2 + 1, trunc - len1, poly1[len1 - 1], mod); /* out[i+j] += in1[i]*in2[j] */ for (i = 0; i < FLINT_MIN(len1, trunc) - 1; i++) _nmod_vec_scalar_addmul_nmod(res + i + 1, poly2 + 1, FLINT_MIN(len2, trunc - i) - 1, poly1[i], mod); } } }
int main(void) { int i, result; flint_rand_t state; flint_randinit(state); printf("reduce...."); fflush(stdout); for (i = 0; i < 10000; i++) { long j, len = n_randint(state, 100) + 1; mp_ptr vec = _nmod_vec_init(len); mp_ptr vec2 = _nmod_vec_init(len); mp_limb_t n = n_randtest_not_zero(state); nmod_t mod; nmod_init(&mod, n); for (j = 0; j < len; j++) { vec[j] = n_randtest(state); vec2[j] = vec[j]; } _nmod_vec_reduce(vec, vec, len, mod); for (j = 0; j < len; j++) vec2[j] = n_mod2_preinv(vec2[j], mod.n, mod.ninv); result = _nmod_vec_equal(vec, vec2, len); if (!_nmod_vec_equal(vec, vec2, len)) { printf("FAIL:\n"); printf("len = %ld, n = %ld\n", len, n); abort(); } _nmod_vec_clear(vec); _nmod_vec_clear(vec2); } flint_randclear(state); printf("PASS\n"); return 0; }
void _nmod_vec_scalar_mul_nmod(mp_ptr res, mp_srcptr vec, slong len, mp_limb_t c, nmod_t mod) { if (mod.norm >= FLINT_BITS/2) /* products will fit in a limb */ { mpn_mul_1(res, vec, len, c); _nmod_vec_reduce(res, res, len, mod); } else /* products may take two limbs */ { slong i; for (i = 0; i < len; i++) { mp_limb_t hi, lo; umul_ppmm(hi, lo, vec[i], c); NMOD_RED2(res[i], hi, lo, mod); /* hi already reduced mod n */ } } }
void _nmod_poly_divrem_q1(mp_ptr Q, mp_ptr R, mp_srcptr A, long lenA, mp_srcptr B, long lenB, nmod_t mod) { const mp_limb_t invL = (B[lenB-1] == 1) ? 1 : n_invmod(B[lenB-1], mod.n); if (lenB == 1) { _nmod_vec_scalar_mul_nmod(Q, A, lenA, invL, mod); } else { mp_limb_t t; Q[1] = n_mulmod2_preinv(A[lenA-1], invL, mod.n, mod.ninv); t = n_mulmod2_preinv(Q[1], B[lenB-2], mod.n, mod.ninv); t = n_submod(A[lenA-2], t, mod.n); Q[0] = n_mulmod2_preinv(t, invL, mod.n, mod.ninv); if (FLINT_BITS + 2 <= 2 * mod.norm) { mpn_mul_1(R, B, lenB - 1, Q[0]); if (lenB > 2) mpn_addmul_1(R + 1, B, lenB - 2, Q[1]); _nmod_vec_reduce(R, R, lenB - 1, mod); } else { _nmod_vec_scalar_mul_nmod(R, B, lenB - 1, Q[0], mod); if (lenB > 2) _nmod_vec_scalar_addmul_nmod(R + 1, B, lenB - 2, Q[1], mod); } _nmod_vec_sub(R, A, R, lenB - 1, mod); } }