Skip to content

Commit 7dc31d3

Browse files
Merge pull request #1759 from flintlib/divexact
nmod_poly_divexact
2 parents d1f45e5 + 94a348f commit 7dc31d3

30 files changed

+327
-54
lines changed

doc/source/nmod_poly.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,6 +1032,12 @@ Division
10321032

10331033
Computes the remainder `R` on polynomial division of `A` by `B`.
10341034

1035+
.. function:: void _nmod_poly_divexact(mp_ptr Q, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, nmod_t mod)
1036+
void nmod_poly_divexact(nmod_poly_t Q, const nmod_poly_t A, const nmod_poly_t B)
1037+
1038+
Computes the quotient `Q` of `A` and `B` assuming that the division
1039+
is exact.
1040+
10351041
.. function:: void _nmod_poly_inv_series_basecase(mp_ptr Qinv, mp_srcptr Q, slong Qlen, slong n, nmod_t mod)
10361042

10371043
Given ``Q`` of length ``Qlen`` whose leading coefficient is invertible

src/gr/nmod.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,6 +1002,19 @@ _gr_nmod_poly_divrem(mp_ptr Q, mp_ptr R, mp_srcptr A, slong lenA,
10021002
}
10031003
}
10041004

1005+
int
1006+
_gr_nmod_poly_divexact(mp_ptr Q, mp_srcptr A, slong lenA, mp_srcptr B, slong lenB, gr_ctx_t ctx)
1007+
{
1008+
slong lenQ = lenA - lenB + 1;
1009+
1010+
if (lenB <= 40 || lenQ <= 20)
1011+
return _gr_poly_divexact_basecase(Q, A, lenA, B, lenB, ctx);
1012+
else if (lenB <= 60 || lenQ <= 60)
1013+
return _gr_poly_divexact_basecase_bidirectional(Q, A, lenA, B, lenB, ctx);
1014+
else
1015+
return _gr_poly_divexact_bidirectional(Q, A, lenA, B, lenB, ctx);
1016+
}
1017+
10051018
/* basecase -> Newton cutoffs */
10061019
/* todo: better unbalanced tuning */
10071020

@@ -1434,6 +1447,7 @@ gr_method_tab_input __gr_nmod_methods_input[] =
14341447
{GR_METHOD_VEC_RECIPROCALS, (gr_funcptr) _gr_nmod_vec_reciprocals},
14351448
{GR_METHOD_POLY_MULLOW, (gr_funcptr) _gr_nmod_poly_mullow},
14361449
{GR_METHOD_POLY_DIVREM, (gr_funcptr) _gr_nmod_poly_divrem},
1450+
{GR_METHOD_POLY_DIVEXACT, (gr_funcptr) _gr_nmod_poly_divexact},
14371451
{GR_METHOD_POLY_INV_SERIES, (gr_funcptr) _gr_nmod_poly_inv_series},
14381452
{GR_METHOD_POLY_INV_SERIES_BASECASE, (gr_funcptr) _gr_nmod_poly_inv_series_basecase},
14391453
{GR_METHOD_POLY_DIV_SERIES, (gr_funcptr) _gr_nmod_poly_div_series},

src/gr_mat/minpoly_field.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ gr_mat_minpoly_field(gr_poly_t p, const gr_mat_t X, gr_ctx_t ctx)
165165
}
166166
_gr_poly_set_length(b, r1 + 1, ctx);
167167

168+
/* todo: poly_divexact */
169+
/* todo: compute as (p * b) / g or (p / g) * b or p * (g / b) ? */
168170
status |= gr_poly_gcd(g, p, b, ctx);
169171
status |= gr_poly_mul(p, p, b, ctx);
170172
status |= gr_poly_divrem(p, r, p, g, ctx);

src/gr_poly/divexact_basecase.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ _gr_poly_divexact_basecase(gr_ptr Q,
4848
slong sz = ctx->sizeof_elem;
4949
gr_ptr invB;
5050

51+
/* note: if we wanted to be clever, we could pick a pair of coefficients such
52+
that the division is easy */
53+
if (Alen == Blen)
54+
return gr_divexact(Q, GR_ENTRY(A, Alen - 1, sz), GR_ENTRY(B, Blen - 1, sz), ctx);
55+
5156
GR_TMP_INIT(invB, ctx);
5257

5358
/* todo: we sometimes want to keep dividing, e.g. over RR with small coefficient */

src/n_poly.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,22 @@ void _n_poly_mod_div(n_poly_t Q, const n_poly_t A, const n_poly_t B, nmod_t mod)
410410
Q->length = lenA - lenB + 1;
411411
}
412412

413+
FLINT_FORCE_INLINE
414+
void _n_poly_mod_divexact(n_poly_t Q, const n_poly_t A, const n_poly_t B, nmod_t mod)
415+
{
416+
const slong lenA = A->length, lenB = B->length;
417+
FLINT_ASSERT(lenB > 0);
418+
FLINT_ASSERT(Q != A && Q != B);
419+
if (lenA < lenB)
420+
{
421+
n_poly_zero(Q);
422+
return;
423+
}
424+
n_poly_fit_length(Q, lenA - lenB + 1);
425+
_nmod_poly_divexact(Q->coeffs, A->coeffs, lenA, B->coeffs, lenB, mod);
426+
Q->length = lenA - lenB + 1;
427+
}
428+
413429
FLINT_FORCE_INLINE
414430
void _n_poly_mod_rem(n_poly_t R, const n_poly_t A, const n_poly_t B, nmod_t mod)
415431
{
@@ -472,6 +488,9 @@ void n_poly_mod_rem(n_poly_t R, const n_poly_t A, const n_poly_t B,
472488
void n_poly_mod_divrem(n_poly_t Q, n_poly_t R, const n_poly_t A,
473489
const n_poly_t B, nmod_t mod);
474490

491+
void n_poly_mod_divexact(n_poly_t Q, const n_poly_t A, const n_poly_t B,
492+
nmod_t mod);
493+
475494
void n_poly_mod_mulmod(n_poly_t res, const n_poly_t poly1,
476495
const n_poly_t poly2, const n_poly_t f, nmod_t mod);
477496

src/n_poly/n_bpoly_mod.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ void n_bpoly_mod_divexact_last(n_bpoly_t A, const n_poly_t b, nmod_t ctx)
8181
if (A->coeffs[i].length < 1)
8282
continue;
8383

84-
n_poly_mod_div(t, A->coeffs + i, b, ctx);
84+
n_poly_mod_divexact(t, A->coeffs + i, b, ctx);
8585
n_poly_swap(A->coeffs + i, t);
8686
}
8787
}

src/n_poly/n_bpoly_mod_gcd.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,8 @@ int n_bpoly_mod_gcd_brown_smprime(
225225

226226
n_poly_mod_gcd(cG, cA, cB, ctx);
227227

228-
n_poly_mod_div(cAbar, cA, cG, ctx);
229-
n_poly_mod_div(cBbar, cB, cG, ctx);
228+
n_poly_mod_divexact(cAbar, cA, cG, ctx);
229+
n_poly_mod_divexact(cBbar, cB, cG, ctx);
230230

231231
n_poly_mod_gcd(gamma, A->coeffs + A->length - 1, B->coeffs + B->length - 1, ctx);
232232

@@ -311,11 +311,11 @@ int n_bpoly_mod_gcd_brown_smprime(
311311
else
312312
{
313313
n_poly_mod_gcd(Gevalp, Aevalp, Bevalp, ctx);
314-
n_poly_mod_div(Abarevalp, Aevalp, Gevalp, ctx);
315-
n_poly_mod_div(Bbarevalp, Bevalp, Gevalp, ctx);
314+
n_poly_mod_divexact(Abarevalp, Aevalp, Gevalp, ctx);
315+
n_poly_mod_divexact(Bbarevalp, Bevalp, Gevalp, ctx);
316316
n_poly_mod_gcd(Gevalm, Aevalm, Bevalm, ctx);
317-
n_poly_mod_div(Abarevalm, Aevalm, Gevalm, ctx);
318-
n_poly_mod_div(Bbarevalm, Bevalm, Gevalm, ctx);
317+
n_poly_mod_divexact(Abarevalm, Aevalm, Gevalm, ctx);
318+
n_poly_mod_divexact(Bbarevalm, Bevalm, Gevalm, ctx);
319319
gstab = astab = bstab = 0;
320320
}
321321

src/n_poly/n_poly_mod.c

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,57 @@ void n_poly_mod_div(n_poly_t Q, const n_poly_t A, const n_poly_t B, nmod_t ctx)
339339
Q->length = A_len - B_len + 1;
340340
}
341341

342+
void n_poly_mod_divexact(n_poly_t Q, const n_poly_t A, const n_poly_t B, nmod_t ctx)
343+
{
344+
n_poly_t tQ;
345+
mp_ptr q;
346+
slong A_len, B_len;
347+
348+
B_len = B->length;
349+
350+
if (B_len == 0)
351+
{
352+
if (ctx.n == 1)
353+
{
354+
n_poly_set(Q, A);
355+
return;
356+
}
357+
else
358+
{
359+
flint_throw(FLINT_ERROR, "Exception (n_poly_mod_divexact). Division by zero.\n");
360+
}
361+
}
362+
363+
A_len = A->length;
364+
365+
if (A_len < B_len)
366+
{
367+
n_poly_zero(Q);
368+
return;
369+
}
370+
371+
if (Q == A || Q == B)
372+
{
373+
n_poly_init2(tQ, A_len - B_len + 1);
374+
q = tQ->coeffs;
375+
}
376+
else
377+
{
378+
n_poly_fit_length(Q, A_len - B_len + 1);
379+
q = Q->coeffs;
380+
}
381+
382+
_nmod_poly_divexact(q, A->coeffs, A_len, B->coeffs, B_len, ctx);
383+
384+
if (Q == A || Q == B)
385+
{
386+
n_poly_swap(tQ, Q);
387+
n_poly_clear(tQ);
388+
}
389+
390+
Q->length = A_len - B_len + 1;
391+
}
392+
342393
void n_poly_mod_rem(n_poly_t R, const n_poly_t A, const n_poly_t B, nmod_t ctx)
343394
{
344395
const slong lenA = A->length, lenB = B->length;

src/n_poly/n_polyu1n_gcd.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -298,8 +298,8 @@ int n_polyu1n_mod_gcd_brown_smprime(
298298
_n_poly_vec_mod_remove_content(cB, B->coeffs, B->length, ctx);
299299

300300
n_poly_mod_gcd(cG, cA, cB, ctx);
301-
n_poly_mod_div(cAbar, cA, cG, ctx);
302-
n_poly_mod_div(cBbar, cB, cG, ctx);
301+
n_poly_mod_divexact(cAbar, cA, cG, ctx);
302+
n_poly_mod_divexact(cBbar, cB, cG, ctx);
303303

304304
n_poly_mod_gcd(gamma, A->coeffs + 0, B->coeffs + 0, ctx);
305305

@@ -377,11 +377,11 @@ int n_polyu1n_mod_gcd_brown_smprime(
377377
else
378378
{
379379
n_poly_mod_gcd(Gevalp, Aevalp, Bevalp, ctx);
380-
n_poly_mod_div(Abarevalp, Aevalp, Gevalp, ctx);
381-
n_poly_mod_div(Bbarevalp, Bevalp, Gevalp, ctx);
380+
n_poly_mod_divexact(Abarevalp, Aevalp, Gevalp, ctx);
381+
n_poly_mod_divexact(Bbarevalp, Bevalp, Gevalp, ctx);
382382
n_poly_mod_gcd(Gevalm, Aevalm, Bevalm, ctx);
383-
n_poly_mod_div(Abarevalm, Aevalm, Gevalm, ctx);
384-
n_poly_mod_div(Bbarevalm, Bevalm, Gevalm, ctx);
383+
n_poly_mod_divexact(Abarevalm, Aevalm, Gevalm, ctx);
384+
n_poly_mod_divexact(Bbarevalm, Bevalm, Gevalm, ctx);
385385
gstab = astab = bstab = 0;
386386
}
387387

src/nmod_mat/minpoly.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,9 @@ void nmod_mat_minpoly_with_gens(nmod_poly_t p, const nmod_mat_t X, ulong * P)
164164
_nmod_poly_set_length(b, r1 + 1);
165165

166166
nmod_poly_gcd(g, p, b);
167+
/* todo: compute as (p * b) / g or (p / g) * b or p * (g / b) ? */
167168
nmod_poly_mul(p, p, b);
168-
nmod_poly_div(p, p, g);
169+
nmod_poly_divexact(p, p, g);
169170

170171
if (first_poly && r2 < n)
171172
{

0 commit comments

Comments
 (0)