From ce4606186ec122baf6acb2aed92a6d09d98a9efc Mon Sep 17 00:00:00 2001 From: David Einstein Date: Tue, 19 Sep 2023 12:20:47 -0400 Subject: [PATCH] Added *_push_term_*_ffmpz functions to mpoly types Updated tests and documentation as well. --- doc/source/fmpq_mpoly.rst | 4 + doc/source/fmpz_mod_mpoly.rst | 3 + doc/source/fmpz_mpoly.rst | 3 + doc/source/fq_nmod_mpoly.rst | 1 + doc/source/nmod_mpoly.rst | 1 + src/fmpq_mpoly.h | 26 +++- src/fmpq_mpoly/push_term_fmpq_fmpz.c | 48 ++++++ src/fmpq_mpoly/test/t-push_term_fmpq_fmpz.c | 32 +++- src/fmpz_mod_mpoly.h | 9 ++ src/fmpz_mod_mpoly/push_term_fmpz_fmpz.c | 29 ++++ .../test/t-push_term_fmpz_fmpz.c | 36 +++-- src/fmpz_mpoly.h | 17 ++- src/fmpz_mpoly/push_term_fmpz_fmpz.c | 27 +++- src/fmpz_mpoly/test/t-push_term_fmpz_fmpz.c | 29 +++- src/fq_nmod_mpoly.h | 3 + src/fq_nmod_mpoly/push_term_fq_nmod_fmpz.c | 11 ++ .../test/t-push_term_fq_nmod_fmpz.c | 39 +++-- src/nmod_mpoly.h | 3 + src/nmod_mpoly/push_term_ui_fmpz.c | 12 ++ src/nmod_mpoly/test/t-push_term_ui_fmpz.c | 138 ++++++++++++++++++ 20 files changed, 429 insertions(+), 42 deletions(-) create mode 100644 src/nmod_mpoly/test/t-push_term_ui_fmpz.c diff --git a/doc/source/fmpq_mpoly.rst b/doc/source/fmpq_mpoly.rst index f4c5ca2270..db629ed305 100644 --- a/doc/source/fmpq_mpoly.rst +++ b/doc/source/fmpq_mpoly.rst @@ -339,9 +339,13 @@ Container operations Set *M* to the monomial of the term of index *i* in *A*. The coefficient of *M* will be one. .. function:: void fmpq_mpoly_push_term_fmpq_fmpz(fmpq_mpoly_t A, const fmpq_t c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx) + void fmpq_mpoly_push_term_fmpq_ffmpz(fmpq_mpoly_t A, const fmpq_t c, const fmpz * exp, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_push_term_fmpz_fmpz(fmpq_mpoly_t A, const fmpz_t c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx) + void fmpq_mpoly_push_term_fmpz_ffmpz(fmpq_mpoly_t A, const fmpz_t c, const fmpz * exp, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_push_term_ui_fmpz(fmpq_mpoly_t A, ulong c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx) + void fmpq_mpoly_push_term_ui_ffmpz(fmpq_mpoly_t A, ulong c, const fmpz * exp, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_push_term_si_fmpz(fmpq_mpoly_t A, slong c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx) + void fmpq_mpoly_push_term_si_ffmpz(fmpq_mpoly_t A, slong c, const fmpz * exp, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_push_term_fmpq_ui(fmpq_mpoly_t A, const fmpq_t c, const ulong * exp, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_push_term_fmpz_ui(fmpq_mpoly_t A, const fmpz_t c, const ulong * exp, const fmpq_mpoly_ctx_t ctx) void fmpq_mpoly_push_term_ui_ui(fmpq_mpoly_t A, ulong c, const ulong * exp, const fmpq_mpoly_ctx_t ctx) diff --git a/doc/source/fmpz_mod_mpoly.rst b/doc/source/fmpz_mod_mpoly.rst index 542bcaadb0..370b60a478 100644 --- a/doc/source/fmpz_mod_mpoly.rst +++ b/doc/source/fmpz_mod_mpoly.rst @@ -310,8 +310,11 @@ Container operations Set *M* to the monomial of the term of index *i* in *A*. The coefficient of *M* will be one. .. function:: void fmpz_mod_mpoly_push_term_fmpz_fmpz(fmpz_mod_mpoly_t A, const fmpz_t c, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx) + void fmpz_mod_mpoly_push_term_fmpz_ffmpz(fmpz_mod_mpoly_t A, const fmpz_t c, const fmpz * exp, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_push_term_ui_fmpz(fmpz_mod_mpoly_t A, ulong c, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx) + void fmpz_mod_mpoly_push_term_ui_ffmpz(fmpz_mod_mpoly_t A, ulong c, const fmpz * exp, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_push_term_si_fmpz(fmpz_mod_mpoly_t A, slong c, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx) + void fmpz_mod_mpoly_push_term_si_ffmpz(fmpz_mod_mpoly_t A, slong c, const fmpz * exp, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_push_term_fmpz_ui(fmpz_mod_mpoly_t A, const fmpz_t c, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_push_term_ui_ui(fmpz_mod_mpoly_t A, ulong c, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx) void fmpz_mod_mpoly_push_term_si_ui(fmpz_mod_mpoly_t A, slong c, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx) diff --git a/doc/source/fmpz_mpoly.rst b/doc/source/fmpz_mpoly.rst index 325980f9d3..915c128595 100644 --- a/doc/source/fmpz_mpoly.rst +++ b/doc/source/fmpz_mpoly.rst @@ -358,8 +358,11 @@ Container operations Set `M` to the monomial of the term of index *i* in *A*. The coefficient of `M` will be one. .. function:: void fmpz_mpoly_push_term_fmpz_fmpz(fmpz_mpoly_t A, const fmpz_t c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx) + void fmpz_mpoly_push_term_fmpz_ffmpz(fmpz_mpoly_t A, const fmpz_t c, const fmpz * exp, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_push_term_ui_fmpz(fmpz_mpoly_t A, ulong c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx) + void fmpz_mpoly_push_term_ui_ffmpz(fmpz_mpoly_t A, ulong c, const fmpz * exp, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_push_term_si_fmpz(fmpz_mpoly_t A, slong c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx) + void fmpz_mpoly_push_term_si_ffmpz(fmpz_mpoly_t A, slong c, const fmpz * exp, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_push_term_fmpz_ui(fmpz_mpoly_t A, const fmpz_t c, const ulong * exp, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_push_term_ui_ui(fmpz_mpoly_t A, ulong c, const ulong * exp, const fmpz_mpoly_ctx_t ctx) void fmpz_mpoly_push_term_si_ui(fmpz_mpoly_t A, slong c, const ulong * exp, const fmpz_mpoly_ctx_t ctx) diff --git a/doc/source/fq_nmod_mpoly.rst b/doc/source/fq_nmod_mpoly.rst index 905a098ba9..aac5366a80 100644 --- a/doc/source/fq_nmod_mpoly.rst +++ b/doc/source/fq_nmod_mpoly.rst @@ -310,6 +310,7 @@ Container operations Set *M* to the monomial of the term of index *i* in *A*. The coefficient of *M* will be one. .. function:: void fq_nmod_mpoly_push_term_fq_nmod_fmpz(fq_nmod_mpoly_t A, const fq_nmod_t c, fmpz * const * exp, const fq_nmod_mpoly_ctx_t ctx) + void fq_nmod_mpoly_push_term_fq_nmod_ffmpz(fq_nmod_mpoly_t A, const fq_nmod_t c, const fmpz * exp, const fq_nmod_mpoly_ctx_t ctx) void fq_nmod_mpoly_push_term_fq_nmod_ui(fq_nmod_mpoly_t A, const fq_nmod_t c, const ulong * exp, const fq_nmod_mpoly_ctx_t ctx) Append a term to *A* with coefficient *c* and exponent vector *exp*. diff --git a/doc/source/nmod_mpoly.rst b/doc/source/nmod_mpoly.rst index 54d6fd5b88..3981022f1f 100644 --- a/doc/source/nmod_mpoly.rst +++ b/doc/source/nmod_mpoly.rst @@ -315,6 +315,7 @@ Container operations Set *M* to the monomial of the term of index *i* in *A*. The coefficient of *M* will be one. .. function:: void nmod_mpoly_push_term_ui_fmpz(nmod_mpoly_t A, ulong c, fmpz * const * exp, const nmod_mpoly_ctx_t ctx) + void nmod_mpoly_push_term_ui_ffmpz(nmod_mpoly_t A, ulong c, const fmpz * exp, const nmod_mpoly_ctx_t ctx) void nmod_mpoly_push_term_ui_ui(nmod_mpoly_t A, ulong c, const ulong * exp, const nmod_mpoly_ctx_t ctx) Append a term to *A* with coefficient *c* and exponent vector *exp*. diff --git a/src/fmpq_mpoly.h b/src/fmpq_mpoly.h index 46bb5dc7b5..cd32c06179 100644 --- a/src/fmpq_mpoly.h +++ b/src/fmpq_mpoly.h @@ -488,14 +488,28 @@ void fmpq_mpoly_get_term_monomial(fmpq_mpoly_t M, const fmpq_mpoly_t A, void fmpq_mpoly_push_term_fmpq_fmpz(fmpq_mpoly_t A, const fmpq_t c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx); -void fmpq_mpoly_push_term_fmpz_fmpz(fmpq_mpoly_t A, - const fmpz_t c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx); +void fmpq_mpoly_push_term_fmpq_ffmpz(fmpq_mpoly_t A, const fmpq_t c, + const fmpz *exp, const fmpq_mpoly_ctx_t ctx); -void fmpq_mpoly_push_term_ui_fmpz(fmpq_mpoly_t A, - ulong c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx); +void fmpq_mpoly_push_term_fmpz_fmpz(fmpq_mpoly_t A, const fmpz_t c, + fmpz *const *exp, + const fmpq_mpoly_ctx_t ctx); -void fmpq_mpoly_push_term_si_fmpz(fmpq_mpoly_t A, - slong c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx); +void fmpq_mpoly_push_term_fmpz_ffmpz(fmpq_mpoly_t A, const fmpz_t c, + const fmpz *exp, + const fmpq_mpoly_ctx_t ctx); + +void fmpq_mpoly_push_term_ui_fmpz(fmpq_mpoly_t A, ulong c, fmpz *const *exp, + const fmpq_mpoly_ctx_t ctx); + +void fmpq_mpoly_push_term_ui_ffmpz(fmpq_mpoly_t A, ulong c, const fmpz *exp, + const fmpq_mpoly_ctx_t ctx); + +void fmpq_mpoly_push_term_si_fmpz(fmpq_mpoly_t A, slong c, fmpz *const *exp, + const fmpq_mpoly_ctx_t ctx); + +void fmpq_mpoly_push_term_si_ffmpz(fmpq_mpoly_t A, slong c, const fmpz *exp, + const fmpq_mpoly_ctx_t ctx); void fmpq_mpoly_push_term_fmpq_ui(fmpq_mpoly_t A, const fmpq_t c, const ulong * exp, const fmpq_mpoly_ctx_t ctx); diff --git a/src/fmpq_mpoly/push_term_fmpq_fmpz.c b/src/fmpq_mpoly/push_term_fmpq_fmpz.c index 1d614020cb..7d5fe99565 100644 --- a/src/fmpq_mpoly/push_term_fmpq_fmpz.c +++ b/src/fmpq_mpoly/push_term_fmpq_fmpz.c @@ -23,6 +23,18 @@ void fmpq_mpoly_push_term_fmpq_fmpz(fmpq_mpoly_t A, fmpq_clear(C); } +void fmpq_mpoly_push_term_fmpq_ffmpz(fmpq_mpoly_t A, + const fmpq_t c, const fmpz * exp, const fmpq_mpoly_ctx_t ctx) +{ + fmpq_t C; + fmpz_init_set(fmpq_numref(C), fmpq_numref(c)); + fmpz_init_set(fmpq_denref(C), fmpq_denref(c)); + _fmpq_mpoly_push_rescale(A, C, ctx); + _fmpz_mpoly_push_exp_ffmpz(A->zpoly, exp, ctx->zctx); + fmpz_swap(A->zpoly->coeffs + A->zpoly->length - 1, fmpq_numref(C)); + fmpq_clear(C); +} + void fmpq_mpoly_push_term_fmpz_fmpz(fmpq_mpoly_t A, const fmpz_t c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx) { @@ -35,6 +47,18 @@ void fmpq_mpoly_push_term_fmpz_fmpz(fmpq_mpoly_t A, fmpq_clear(C); } +void fmpq_mpoly_push_term_fmpz_ffmpz(fmpq_mpoly_t A, const fmpz_t c, + const fmpz *exp, const fmpq_mpoly_ctx_t ctx) +{ + fmpq_t C; + fmpz_init_set(fmpq_numref(C), c); + fmpz_init_set_ui(fmpq_denref(C), UWORD(1)); + _fmpq_mpoly_push_rescale(A, C, ctx); + _fmpz_mpoly_push_exp_ffmpz(A->zpoly, exp, ctx->zctx); + fmpz_swap(A->zpoly->coeffs + A->zpoly->length - 1, fmpq_numref(C)); + fmpq_clear(C); +} + void fmpq_mpoly_push_term_ui_fmpz(fmpq_mpoly_t A, ulong c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx) { @@ -47,6 +71,18 @@ void fmpq_mpoly_push_term_ui_fmpz(fmpq_mpoly_t A, fmpq_clear(C); } +void fmpq_mpoly_push_term_ui_ffmpz(fmpq_mpoly_t A, + ulong c, const fmpz * exp, const fmpq_mpoly_ctx_t ctx) +{ + fmpq_t C; + fmpz_init_set_ui(fmpq_numref(C), c); + fmpz_init_set_ui(fmpq_denref(C), UWORD(1)); + _fmpq_mpoly_push_rescale(A, C, ctx); + _fmpz_mpoly_push_exp_ffmpz(A->zpoly, exp, ctx->zctx); + fmpz_swap(A->zpoly->coeffs + A->zpoly->length - 1, fmpq_numref(C)); + fmpq_clear(C); +} + void fmpq_mpoly_push_term_si_fmpz(fmpq_mpoly_t A, slong c, fmpz * const * exp, const fmpq_mpoly_ctx_t ctx) { @@ -58,3 +94,15 @@ void fmpq_mpoly_push_term_si_fmpz(fmpq_mpoly_t A, fmpz_swap(A->zpoly->coeffs + A->zpoly->length - 1, fmpq_numref(C)); fmpq_clear(C); } + +void fmpq_mpoly_push_term_si_ffmpz(fmpq_mpoly_t A, + slong c, const fmpz * exp, const fmpq_mpoly_ctx_t ctx) +{ + fmpq_t C; + fmpz_init_set_si(fmpq_numref(C), c); + fmpz_init_set_ui(fmpq_denref(C), UWORD(1)); + _fmpq_mpoly_push_rescale(A, C, ctx); + _fmpz_mpoly_push_exp_ffmpz(A->zpoly, exp, ctx->zctx); + fmpz_swap(A->zpoly->coeffs + A->zpoly->length - 1, fmpq_numref(C)); + fmpq_clear(C); +} diff --git a/src/fmpq_mpoly/test/t-push_term_fmpq_fmpz.c b/src/fmpq_mpoly/test/t-push_term_fmpq_fmpz.c index 7ba5caa875..b5877e3be7 100644 --- a/src/fmpq_mpoly/test/t-push_term_fmpq_fmpz.c +++ b/src/fmpq_mpoly/test/t-push_term_fmpq_fmpz.c @@ -24,29 +24,32 @@ main(void) for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpq_mpoly_ctx_t ctx; - fmpq_mpoly_t f1, f2, m; + fmpq_mpoly_t f1, f2, f3, m; flint_bitcnt_t coeff_bits, exp_bits; - fmpz ** exp, ** exp2; + fmpz **exp, **exp2, *exp3; slong len, nvars; fmpq_t c, c2; fmpq_mpoly_ctx_init_rand(ctx, state, 10); fmpq_mpoly_init(f1, ctx); fmpq_mpoly_init(f2, ctx); + fmpq_mpoly_init(f3, ctx); fmpq_mpoly_init(m, ctx); fmpq_init(c); fmpq_init(c2); nvars = fmpq_mpoly_ctx_nvars(ctx); - exp = (fmpz **) flint_malloc(nvars*sizeof(fmpz *)); - exp2 = (fmpz **) flint_malloc(nvars*sizeof(fmpz *)); + exp = (fmpz **)flint_malloc(nvars * sizeof(fmpz *)); + exp2 = (fmpz **)flint_malloc(nvars * sizeof(fmpz *)); + exp3 = (fmpz *)flint_malloc(nvars * sizeof(fmpz)); for (k = 0; k < nvars; k++) { exp[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp[k]); exp2[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp2[k]); + fmpz_init(exp3 + k); } len = n_randint(state, 20); @@ -60,9 +63,10 @@ main(void) { /* get random term */ fmpq_randtest(c, state, coeff_bits + 1); - for (k = 0; k < nvars; k++) + for (k = 0; k < nvars; k++) { fmpz_randtest_unsigned(exp[k], state, exp_bits); - + fmpz_set(exp3 + k, exp[k]); + } /* add it to f1 */ fmpq_mpoly_zero(m, ctx); fmpq_mpoly_set_coeff_fmpq_fmpz(m, c, exp, ctx); @@ -75,6 +79,7 @@ main(void) else fmpq_mpoly_push_term_fmpq_fmpz(f2, c, exp, ctx); + fmpq_mpoly_push_term_fmpq_ffmpz(f3, c, exp3, ctx); /* make sure last term matches */ fmpq_mpoly_get_term_coeff_fmpq(c2, f2, fmpq_mpoly_length(f2, ctx) - 1, ctx); fmpq_mpoly_get_term_exp_fmpz(exp2, f2, fmpq_mpoly_length(f2, ctx) - 1, ctx); @@ -101,6 +106,10 @@ main(void) fmpq_mpoly_combine_like_terms(f2, ctx); fmpq_mpoly_assert_canonical(f2, ctx); + fmpq_mpoly_sort_terms(f3, ctx); + fmpq_mpoly_combine_like_terms(f3, ctx); + fmpq_mpoly_assert_canonical(f3, ctx); + if (!fmpq_mpoly_equal(f1, f2, ctx)) { printf("FAIL\n"); @@ -109,10 +118,19 @@ main(void) flint_abort(); } + if (!fmpq_mpoly_equal(f1, f3, ctx)) + { + printf("FAIL\n"); + flint_printf("Check pushed ffmpz polynomial matches add\ni = %wd\n",i); + fflush(stdout); + flint_abort(); + } + fmpq_clear(c2); fmpq_clear(c); fmpq_mpoly_clear(f1, ctx); fmpq_mpoly_clear(f2, ctx); + fmpq_mpoly_clear(f3, ctx); fmpq_mpoly_clear(m, ctx); fmpq_mpoly_ctx_clear(ctx); @@ -122,7 +140,9 @@ main(void) flint_free(exp2[k]); fmpz_clear(exp[k]); flint_free(exp[k]); + fmpz_clear(exp3 + k); } + flint_free(exp3); flint_free(exp2); flint_free(exp); } diff --git a/src/fmpz_mod_mpoly.h b/src/fmpz_mod_mpoly.h index 112fcd0668..7dfc0701c6 100644 --- a/src/fmpz_mod_mpoly.h +++ b/src/fmpz_mod_mpoly.h @@ -478,12 +478,21 @@ void fmpz_mod_mpoly_get_term_monomial(fmpz_mod_mpoly_t M, void fmpz_mod_mpoly_push_term_fmpz_fmpz(fmpz_mod_mpoly_t A, const fmpz_t c, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx); +void fmpz_mod_mpoly_push_term_fmpz_ffmpz(fmpz_mod_mpoly_t A, + const fmpz_t c, const fmpz * exp, const fmpz_mod_mpoly_ctx_t ctx); + void fmpz_mod_mpoly_push_term_ui_fmpz(fmpz_mod_mpoly_t A, ulong c, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx); +void fmpz_mod_mpoly_push_term_ui_ffmpz(fmpz_mod_mpoly_t A, + ulong c, const fmpz * exp, const fmpz_mod_mpoly_ctx_t ctx); + void fmpz_mod_mpoly_push_term_si_fmpz(fmpz_mod_mpoly_t A, slong c, fmpz * const * exp, const fmpz_mod_mpoly_ctx_t ctx); +void fmpz_mod_mpoly_push_term_si_ffmpz(fmpz_mod_mpoly_t A, + slong c, const fmpz * exp, const fmpz_mod_mpoly_ctx_t ctx); + void fmpz_mod_mpoly_push_term_fmpz_ui(fmpz_mod_mpoly_t A, const fmpz_t c, const ulong * exp, const fmpz_mod_mpoly_ctx_t ctx); diff --git a/src/fmpz_mod_mpoly/push_term_fmpz_fmpz.c b/src/fmpz_mod_mpoly/push_term_fmpz_fmpz.c index 8c20865825..53ee09c928 100644 --- a/src/fmpz_mod_mpoly/push_term_fmpz_fmpz.c +++ b/src/fmpz_mod_mpoly/push_term_fmpz_fmpz.c @@ -78,3 +78,32 @@ void fmpz_mod_mpoly_push_term_si_fmpz( fmpz_mod_set_si(A->coeffs + A->length - 1, c, ctx->ffinfo); } +void fmpz_mod_mpoly_push_term_fmpz_ffmpz( + fmpz_mod_mpoly_t A, + const fmpz_t c, + const fmpz * exp, + const fmpz_mod_mpoly_ctx_t ctx) +{ + _fmpz_mod_mpoly_push_exp_ffmpz(A, exp, ctx); + fmpz_mod_set_fmpz(A->coeffs + A->length - 1, c, ctx->ffinfo); +} + +void fmpz_mod_mpoly_push_term_ui_ffmpz( + fmpz_mod_mpoly_t A, + ulong c, + const fmpz * exp, + const fmpz_mod_mpoly_ctx_t ctx) +{ + _fmpz_mod_mpoly_push_exp_ffmpz(A, exp, ctx); + fmpz_mod_set_ui(A->coeffs + A->length - 1, c, ctx->ffinfo); +} + +void fmpz_mod_mpoly_push_term_si_ffmpz( + fmpz_mod_mpoly_t A, + slong c, + const fmpz * exp, + const fmpz_mod_mpoly_ctx_t ctx) +{ + _fmpz_mod_mpoly_push_exp_ffmpz(A, exp, ctx); + fmpz_mod_set_si(A->coeffs + A->length - 1, c, ctx->ffinfo); +} diff --git a/src/fmpz_mod_mpoly/test/t-push_term_fmpz_fmpz.c b/src/fmpz_mod_mpoly/test/t-push_term_fmpz_fmpz.c index 3a30a712dd..f0c379c1d4 100644 --- a/src/fmpz_mod_mpoly/test/t-push_term_fmpz_fmpz.c +++ b/src/fmpz_mod_mpoly/test/t-push_term_fmpz_fmpz.c @@ -24,29 +24,32 @@ main(void) for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mod_mpoly_ctx_t ctx; - fmpz_mod_mpoly_t f1, f2, m; + fmpz_mod_mpoly_t f1, f2, f3, m; flint_bitcnt_t exp_bits; - fmpz ** exp, ** exp2; + fmpz **exp, **exp2, *exp3; slong len, nvars; fmpz_t c, c2; fmpz_mod_mpoly_ctx_init_rand_bits(ctx, state, 10, 200); fmpz_mod_mpoly_init(f1, ctx); fmpz_mod_mpoly_init(f2, ctx); + fmpz_mod_mpoly_init(f3, ctx); fmpz_mod_mpoly_init(m, ctx); fmpz_init(c); fmpz_init(c2); nvars = fmpz_mod_mpoly_ctx_nvars(ctx); - exp = (fmpz **) flint_malloc(nvars*sizeof(fmpz *)); - exp2 = (fmpz **) flint_malloc(nvars*sizeof(fmpz *)); + exp = (fmpz **)flint_malloc(nvars * sizeof(fmpz *)); + exp2 = (fmpz **)flint_malloc(nvars * sizeof(fmpz *)); + exp3 = (fmpz *)flint_malloc(nvars * sizeof(fmpz)); for (k = 0; k < nvars; k++) { exp[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp[k]); exp2[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp2[k]); + fmpz_init(exp3 + k); } len = n_randint(state, 20); @@ -59,17 +62,19 @@ main(void) { /* get random term */ fmpz_randtest(c, state, 200); - for (k = 0; k < nvars; k++) + for (k = 0; k < nvars; k++) { fmpz_randtest_unsigned(exp[k], state, exp_bits); - + fmpz_set(exp3 + k, exp[k]); + } /* add it to f1 */ fmpz_mod_mpoly_zero(m, ctx); fmpz_mod_mpoly_set_coeff_fmpz_fmpz(m, c, exp, ctx); fmpz_mod_mpoly_add(f1, f1, m, ctx); fmpz_mod_mpoly_assert_canonical(f1, ctx); - /* push it back on f2 */ + /* push it back on f2 and f3*/ fmpz_mod_mpoly_push_term_fmpz_fmpz(f2, c, exp, ctx); + fmpz_mod_mpoly_push_term_fmpz_ffmpz(f3, c, exp3, ctx); /* make sure last term matches */ fmpz_mod_mpoly_get_term_coeff_fmpz(c2, f2, fmpz_mod_mpoly_length(f2, ctx) - 1, ctx); @@ -97,6 +102,10 @@ main(void) fmpz_mod_mpoly_combine_like_terms(f2, ctx); fmpz_mod_mpoly_assert_canonical(f2, ctx); + fmpz_mod_mpoly_sort_terms(f3, ctx); + fmpz_mod_mpoly_combine_like_terms(f3, ctx); + fmpz_mod_mpoly_assert_canonical(f3, ctx); + if (!fmpz_mod_mpoly_equal(f1, f2, ctx)) { flint_printf("FAIL: Check pushed polynomial matches add\n"); @@ -105,20 +114,29 @@ main(void) flint_abort(); } + if (!fmpz_mod_mpoly_equal(f1, f3, ctx)) { + flint_printf("FAIL: Check pushed ffmpz polynomial matches add\n"); + flint_printf("i = %wd\n", i); + fflush(stdout); + flint_abort(); + } + fmpz_clear(c2); fmpz_clear(c); fmpz_mod_mpoly_clear(f1, ctx); fmpz_mod_mpoly_clear(f2, ctx); + fmpz_mod_mpoly_clear(f3, ctx); fmpz_mod_mpoly_clear(m, ctx); fmpz_mod_mpoly_ctx_clear(ctx); - for (k = 0; k < nvars; k++) - { + for (k = 0; k < nvars; k++) { fmpz_clear(exp2[k]); flint_free(exp2[k]); fmpz_clear(exp[k]); flint_free(exp[k]); + fmpz_clear(exp3 + k); } + flint_free(exp3); flint_free(exp2); flint_free(exp); } diff --git a/src/fmpz_mpoly.h b/src/fmpz_mpoly.h index 5f43cd47e3..c5d88abc19 100644 --- a/src/fmpz_mpoly.h +++ b/src/fmpz_mpoly.h @@ -499,11 +499,20 @@ void fmpz_mpoly_get_term_monomial(fmpz_mpoly_t M, const fmpz_mpoly_t A, void fmpz_mpoly_push_term_fmpz_fmpz(fmpz_mpoly_t A, const fmpz_t c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx); -void fmpz_mpoly_push_term_ui_fmpz(fmpz_mpoly_t A, - ulong c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx); +void fmpz_mpoly_push_term_fmpz_ffmpz(fmpz_mpoly_t A, const fmpz_t c, + const fmpz *exp, const fmpz_mpoly_ctx_t ctx); -void fmpz_mpoly_push_term_si_fmpz(fmpz_mpoly_t A, - slong c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx); +void fmpz_mpoly_push_term_ui_fmpz(fmpz_mpoly_t A, ulong c, fmpz *const *exp, + const fmpz_mpoly_ctx_t ctx); + +void fmpz_mpoly_push_term_ui_ffmpz(fmpz_mpoly_t A, ulong c, + const fmpz *exp, const fmpz_mpoly_ctx_t ctx); + +void fmpz_mpoly_push_term_si_fmpz(fmpz_mpoly_t A, slong c, fmpz *const *exp, + const fmpz_mpoly_ctx_t ctx); + +void fmpz_mpoly_push_term_si_ffmpz(fmpz_mpoly_t A, slong c, + const fmpz *exp, const fmpz_mpoly_ctx_t ctx); void fmpz_mpoly_push_term_fmpz_ui(fmpz_mpoly_t A, const fmpz_t c, const ulong * exp, const fmpz_mpoly_ctx_t ctx); diff --git a/src/fmpz_mpoly/push_term_fmpz_fmpz.c b/src/fmpz_mpoly/push_term_fmpz_fmpz.c index e3dc4945bb..2cfdc513ba 100644 --- a/src/fmpz_mpoly/push_term_fmpz_fmpz.c +++ b/src/fmpz_mpoly/push_term_fmpz_fmpz.c @@ -55,6 +55,13 @@ void fmpz_mpoly_push_term_fmpz_fmpz(fmpz_mpoly_t A, fmpz_set(A->coeffs + A->length - 1, c); } +void fmpz_mpoly_push_term_fmpz_ffmpz(fmpz_mpoly_t A, const fmpz_t c, + const fmpz *exp, const fmpz_mpoly_ctx_t ctx) +{ + _fmpz_mpoly_push_exp_ffmpz(A, exp, ctx); + fmpz_set(A->coeffs + A->length - 1, c); +} + void fmpz_mpoly_push_term_ui_fmpz(fmpz_mpoly_t A, ulong c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx) { @@ -62,9 +69,21 @@ void fmpz_mpoly_push_term_ui_fmpz(fmpz_mpoly_t A, fmpz_set_ui(A->coeffs + A->length - 1, c); } -void fmpz_mpoly_push_term_si_fmpz(fmpz_mpoly_t A, - slong c, fmpz * const * exp, const fmpz_mpoly_ctx_t ctx) +void fmpz_mpoly_push_term_ui_ffmpz(fmpz_mpoly_t A, ulong c, const fmpz *exp, + const fmpz_mpoly_ctx_t ctx) { + _fmpz_mpoly_push_exp_ffmpz(A, exp, ctx); + fmpz_set_ui(A->coeffs + A->length - 1, c); +} + +void fmpz_mpoly_push_term_si_fmpz(fmpz_mpoly_t A, slong c, fmpz *const *exp, + const fmpz_mpoly_ctx_t ctx) { + _fmpz_mpoly_push_exp_pfmpz(A, exp, ctx); + fmpz_set_si(A->coeffs + A->length - 1, c); +} + +void fmpz_mpoly_push_term_si_ffmpz(fmpz_mpoly_t A, slong c, + const fmpz *exp, const fmpz_mpoly_ctx_t ctx) { - _fmpz_mpoly_push_exp_pfmpz(A, exp, ctx); - fmpz_set_si(A->coeffs + A->length - 1, c); + _fmpz_mpoly_push_exp_ffmpz(A, exp, ctx); + fmpz_set_ui(A->coeffs + A->length - 1, c); } diff --git a/src/fmpz_mpoly/test/t-push_term_fmpz_fmpz.c b/src/fmpz_mpoly/test/t-push_term_fmpz_fmpz.c index 26c5c71607..13a0208078 100644 --- a/src/fmpz_mpoly/test/t-push_term_fmpz_fmpz.c +++ b/src/fmpz_mpoly/test/t-push_term_fmpz_fmpz.c @@ -24,15 +24,16 @@ main(void) for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fmpz_mpoly_ctx_t ctx; - fmpz_mpoly_t f1, f2, m; + fmpz_mpoly_t f1, f2, f3, m; flint_bitcnt_t coeff_bits, exp_bits; - fmpz ** exp, ** exp2; + fmpz **exp, **exp2, *exp3; slong len, nvars; fmpz_t c, c2; fmpz_mpoly_ctx_init_rand(ctx, state, 10); fmpz_mpoly_init(f1, ctx); fmpz_mpoly_init(f2, ctx); + fmpz_mpoly_init(f3, ctx); fmpz_mpoly_init(m, ctx); fmpz_init(c); fmpz_init(c2); @@ -41,12 +42,14 @@ main(void) exp = (fmpz **) flint_malloc(nvars*sizeof(fmpz *)); exp2 = (fmpz **) flint_malloc(nvars*sizeof(fmpz *)); + exp3 = (fmpz *) flint_malloc(nvars*sizeof(fmpz)); for (k = 0; k < nvars; k++) { exp[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp[k]); exp2[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp2[k]); + fmpz_init(exp3+k); } len = n_randint(state, 20); @@ -60,8 +63,10 @@ main(void) { /* get random term */ fmpz_randtest(c, state, coeff_bits); - for (k = 0; k < nvars; k++) + for (k = 0; k < nvars; k++){ fmpz_randtest_unsigned(exp[k], state, exp_bits); + fmpz_set(exp3 + k, exp[k]); + } /* add it to f1 */ fmpz_mpoly_zero(m, ctx); @@ -72,6 +77,9 @@ main(void) /* push it back on f2 */ fmpz_mpoly_push_term_fmpz_fmpz(f2, c, exp, ctx); + /* push it on f3 */ + fmpz_mpoly_push_term_fmpz_ffmpz(f3, c, exp3, ctx); + /* make sure last term matches */ fmpz_mpoly_get_term_coeff_fmpz(c2, f2, fmpz_mpoly_length(f2, ctx) - 1, ctx); fmpz_mpoly_get_term_exp_fmpz(exp2, f2, fmpz_mpoly_length(f2, ctx) - 1, ctx); @@ -98,6 +106,10 @@ main(void) fmpz_mpoly_combine_like_terms(f2, ctx); fmpz_mpoly_assert_canonical(f2, ctx); + fmpz_mpoly_sort_terms(f3, ctx); + fmpz_mpoly_combine_like_terms(f3, ctx); + fmpz_mpoly_assert_canonical(f3, ctx); + if (!fmpz_mpoly_equal(f1, f2, ctx)) { printf("FAIL\n"); @@ -106,20 +118,31 @@ main(void) flint_abort(); } + if (!fmpz_mpoly_equal(f1, f3, ctx)) { + printf("FAIL\n"); + flint_printf( + "Check pushed with ffmpz polynomial matches add\ni=%wd\n", i, j); + fflush(stdout); + flint_abort(); + } + fmpz_clear(c2); fmpz_clear(c); fmpz_mpoly_clear(f1, ctx); fmpz_mpoly_clear(f2, ctx); + fmpz_mpoly_clear(f3, ctx); fmpz_mpoly_clear(m, ctx); fmpz_mpoly_ctx_clear(ctx); for (k = 0; k < nvars; k++) { + fmpz_clear(exp3 + k); fmpz_clear(exp2[k]); flint_free(exp2[k]); fmpz_clear(exp[k]); flint_free(exp[k]); } + flint_free(exp3); flint_free(exp2); flint_free(exp); } diff --git a/src/fq_nmod_mpoly.h b/src/fq_nmod_mpoly.h index 5d3cb42f12..a54327cfb2 100644 --- a/src/fq_nmod_mpoly.h +++ b/src/fq_nmod_mpoly.h @@ -607,6 +607,9 @@ void fq_nmod_mpoly_get_term_monomial(fq_nmod_mpoly_t M, void fq_nmod_mpoly_push_term_fq_nmod_fmpz(fq_nmod_mpoly_t A, const fq_nmod_t c, fmpz * const * exp, const fq_nmod_mpoly_ctx_t ctx); +void fq_nmod_mpoly_push_term_fq_nmod_ffmpz(fq_nmod_mpoly_t A, + const fq_nmod_t c, const fmpz * exp, const fq_nmod_mpoly_ctx_t ctx); + void fq_nmod_mpoly_push_term_fq_nmod_ui(fq_nmod_mpoly_t A, const fq_nmod_t c, const ulong * exp, const fq_nmod_mpoly_ctx_t ctx); diff --git a/src/fq_nmod_mpoly/push_term_fq_nmod_fmpz.c b/src/fq_nmod_mpoly/push_term_fq_nmod_fmpz.c index e93592cf97..a7b119f802 100644 --- a/src/fq_nmod_mpoly/push_term_fq_nmod_fmpz.c +++ b/src/fq_nmod_mpoly/push_term_fq_nmod_fmpz.c @@ -62,3 +62,14 @@ void fq_nmod_mpoly_push_term_fq_nmod_fmpz( FLINT_ASSERT(A->length > 0); n_fq_set_fq_nmod(A->coeffs + d*(A->length - 1), c, ctx->fqctx); } + +void fq_nmod_mpoly_push_term_fq_nmod_ffmpz(fq_nmod_mpoly_t A, const fq_nmod_t c, + const fmpz *exp, + const fq_nmod_mpoly_ctx_t ctx) +{ + slong d; + _fq_nmod_mpoly_push_exp_ffmpz(A, exp, ctx); + d = fq_nmod_ctx_degree(ctx->fqctx); + FLINT_ASSERT(A->length > 0); + n_fq_set_fq_nmod(A->coeffs + d * (A->length - 1), c, ctx->fqctx); +} diff --git a/src/fq_nmod_mpoly/test/t-push_term_fq_nmod_fmpz.c b/src/fq_nmod_mpoly/test/t-push_term_fq_nmod_fmpz.c index cdc0f57392..0e82931071 100644 --- a/src/fq_nmod_mpoly/test/t-push_term_fq_nmod_fmpz.c +++ b/src/fq_nmod_mpoly/test/t-push_term_fq_nmod_fmpz.c @@ -24,29 +24,32 @@ main(void) for (i = 0; i < 1000 * flint_test_multiplier(); i++) { fq_nmod_mpoly_ctx_t ctx; - fq_nmod_mpoly_t f1, f2, m; + fq_nmod_mpoly_t f1, f2, f3, m; flint_bitcnt_t exp_bits; - fmpz ** exp, ** exp2; + fmpz **exp, **exp2, *exp3; slong len, nvars; fq_nmod_t c, c2; fq_nmod_mpoly_ctx_init_rand(ctx, state, 10, FLINT_BITS, 10); fq_nmod_mpoly_init(f1, ctx); fq_nmod_mpoly_init(f2, ctx); + fq_nmod_mpoly_init(f3, ctx); fq_nmod_mpoly_init(m, ctx); fq_nmod_init(c, ctx->fqctx); fq_nmod_init(c2, ctx->fqctx); nvars = fq_nmod_mpoly_ctx_nvars(ctx); - exp = (fmpz **) flint_malloc(nvars*sizeof(fmpz *)); - exp2 = (fmpz **) flint_malloc(nvars*sizeof(fmpz *)); + exp = (fmpz **)flint_malloc(nvars * sizeof(fmpz *)); + exp2 = (fmpz **)flint_malloc(nvars * sizeof(fmpz *)); + exp3 = (fmpz *)flint_malloc(nvars * sizeof(fmpz)); for (k = 0; k < nvars; k++) { exp[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp[k]); exp2[k] = (fmpz *) flint_malloc(sizeof(fmpz)); fmpz_init(exp2[k]); + fmpz_init(exp3 + k); } len = n_randint(state, 20); @@ -59,17 +62,19 @@ main(void) { /* get random term */ fq_nmod_randtest(c, state, ctx->fqctx); - for (k = 0; k < nvars; k++) + for (k = 0; k < nvars; k++){ fmpz_randtest_unsigned(exp[k], state, exp_bits); - + fmpz_set(exp3 + k, exp[k]); + } /* add it to f1 */ fq_nmod_mpoly_zero(m, ctx); fq_nmod_mpoly_set_coeff_fq_nmod_fmpz(m, c, exp, ctx); fq_nmod_mpoly_add(f1, f1, m, ctx); fq_nmod_mpoly_assert_canonical(f1, ctx); - /* push it back on f2 */ + /* push it back on f2 and f3*/ fq_nmod_mpoly_push_term_fq_nmod_fmpz(f2, c, exp, ctx); + fq_nmod_mpoly_push_term_fq_nmod_ffmpz(f3, c, exp3, ctx); /* make sure last term matches */ fq_nmod_mpoly_get_term_coeff_fq_nmod(c2, f2, @@ -99,10 +104,21 @@ main(void) fq_nmod_mpoly_combine_like_terms(f2, ctx); fq_nmod_mpoly_assert_canonical(f2, ctx); - if (!fq_nmod_mpoly_equal(f1, f2, ctx)) - { + fq_nmod_mpoly_sort_terms(f3, ctx); + fq_nmod_mpoly_combine_like_terms(f3, ctx); + fq_nmod_mpoly_assert_canonical(f3, ctx); + + if (!fq_nmod_mpoly_equal(f1, f2, ctx)) { + printf("FAIL\n"); + flint_printf("Check pushed polynomial matches add\ni=%wd\n", i, j); + fflush(stdout); + flint_abort(); + } + + if (!fq_nmod_mpoly_equal(f1, f3, ctx)) { printf("FAIL\n"); - flint_printf("Check pushed polynomial matches add\ni=%wd\n",i,j); + flint_printf("Check pushed ffmpz polynomial matches add\ni=%wd\n", + i, j); fflush(stdout); flint_abort(); } @@ -111,6 +127,7 @@ main(void) fq_nmod_clear(c, ctx->fqctx); fq_nmod_mpoly_clear(f1, ctx); fq_nmod_mpoly_clear(f2, ctx); + fq_nmod_mpoly_clear(f3, ctx); fq_nmod_mpoly_clear(m, ctx); fq_nmod_mpoly_ctx_clear(ctx); @@ -120,7 +137,9 @@ main(void) flint_free(exp2[k]); fmpz_clear(exp[k]); flint_free(exp[k]); + fmpz_clear(exp3 + k); } + flint_free(exp3); flint_free(exp2); flint_free(exp); } diff --git a/src/nmod_mpoly.h b/src/nmod_mpoly.h index b9839cd901..07002d3bed 100644 --- a/src/nmod_mpoly.h +++ b/src/nmod_mpoly.h @@ -664,6 +664,9 @@ void nmod_mpoly_get_term_monomial(nmod_mpoly_t M, const nmod_mpoly_t A, void nmod_mpoly_push_term_ui_fmpz(nmod_mpoly_t A, ulong c, fmpz * const * exp, const nmod_mpoly_ctx_t ctx); +void nmod_mpoly_push_term_ui_ffmpz(nmod_mpoly_t A, ulong c, + const fmpz * exp, const nmod_mpoly_ctx_t ctx); + void nmod_mpoly_push_term_ui_ui(nmod_mpoly_t A, ulong c, const ulong * exp, const nmod_mpoly_ctx_t ctx); diff --git a/src/nmod_mpoly/push_term_ui_fmpz.c b/src/nmod_mpoly/push_term_ui_fmpz.c index 7fa2d085b8..d589f1388b 100644 --- a/src/nmod_mpoly/push_term_ui_fmpz.c +++ b/src/nmod_mpoly/push_term_ui_fmpz.c @@ -59,3 +59,15 @@ void nmod_mpoly_push_term_ui_fmpz( NMOD_RED(c, c, ctx->mod); A->coeffs[A->length - 1] = c; } + +void nmod_mpoly_push_term_ui_ffmpz( + nmod_mpoly_t A, + ulong c, + const fmpz * exp, + const nmod_mpoly_ctx_t ctx) +{ + _nmod_mpoly_push_exp_ffmpz(A, exp, ctx); + if (c >= ctx->mod.n) + NMOD_RED(c, c, ctx->mod); + A->coeffs[A->length - 1] = c; +} diff --git a/src/nmod_mpoly/test/t-push_term_ui_fmpz.c b/src/nmod_mpoly/test/t-push_term_ui_fmpz.c new file mode 100644 index 0000000000..1ade5d57a6 --- /dev/null +++ b/src/nmod_mpoly/test/t-push_term_ui_fmpz.c @@ -0,0 +1,138 @@ + +/* + Copyright (C) 2019 Daniel Schultz + + This file is part of FLINT. + + FLINT is free software: you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License (LGPL) as published + by the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. See . +*/ + +#include "nmod_mpoly.h" + +int main(void) { + slong i, j, k; + FLINT_TEST_INIT(state); + + flint_printf("push_term_fq_nmod_fmpz...."); + fflush(stdout); + + /* Check pushback matches add */ + for (i = 0; i < 1000 * flint_test_multiplier(); i++) { + nmod_mpoly_ctx_t ctx; + nmod_mpoly_t f1, f2, f3, m; + flint_bitcnt_t exp_bits; + fmpz **exp, **exp2, *exp3; + slong len, nvars; + mp_limb_t c, c2; + mp_limb_t modulus; + + modulus = n_randtest_bits(state, n_randint(state, FLINT_BITS) + 1); + nmod_mpoly_ctx_init_rand(ctx, state, 10, modulus); + nmod_mpoly_init(f1, ctx); + nmod_mpoly_init(f2, ctx); + nmod_mpoly_init(f3, ctx); + nmod_mpoly_init(m, ctx); + + nvars = nmod_mpoly_ctx_nvars(ctx); + + exp = (fmpz **)flint_malloc(nvars * sizeof(fmpz *)); + exp2 = (fmpz **)flint_malloc(nvars * sizeof(fmpz *)); + exp3 = (fmpz *)flint_malloc(nvars * sizeof(fmpz)); + for (k = 0; k < nvars; k++) { + exp[k] = (fmpz *)flint_malloc(sizeof(fmpz)); + fmpz_init(exp[k]); + exp2[k] = (fmpz *)flint_malloc(sizeof(fmpz)); + fmpz_init(exp2[k]); + fmpz_init(exp3 + k); + } + + len = n_randint(state, 20); + exp_bits = n_randint(state, 200); + + nmod_mpoly_zero(f1, ctx); + nmod_mpoly_zero(f2, ctx); + + for (j = 0; j < len; j++) { + /* get random term */ + c = n_randlimb(state); + for (k = 0; k < nvars; k++) { + fmpz_randtest_unsigned(exp[k], state, exp_bits); + fmpz_set(exp3 + k, exp[k]); + } + /* add it to f1 */ + nmod_mpoly_zero(m, ctx); + nmod_mpoly_set_coeff_ui_fmpz(m, c, exp, ctx); + nmod_mpoly_add(f1, f1, m, ctx); + nmod_mpoly_assert_canonical(f1, ctx); + + /* push it back on f2 and f3*/ + nmod_mpoly_push_term_ui_fmpz(f2, c, exp, ctx); + nmod_mpoly_push_term_ui_ffmpz(f3, c, exp3, ctx); + + /* make sure last term matches */ + c2 = nmod_mpoly_get_term_coeff_ui(f2, nmod_mpoly_length(f2, ctx) - 1, ctx); + nmod_mpoly_get_term_exp_fmpz(exp2, f2, nmod_mpoly_length(f2, ctx) - 1, ctx); + if ((c % modulus) != c2) { + printf("FAIL\n"); + flint_printf("Check pushed coefficient matches\ni=%wd, j=%wd\n", i, j); + fflush(stdout); + flint_abort(); + } + for (k = 0; k < nvars; k++) { + if (!fmpz_equal(exp[k], exp2[k])) { + printf("FAIL\n"); + flint_printf("Check pushed exponent matches\ni=%wd, j=%wd\n", i, j); + fflush(stdout); + flint_abort(); + } + } + } + + nmod_mpoly_sort_terms(f2, ctx); + nmod_mpoly_combine_like_terms(f2, ctx); + nmod_mpoly_assert_canonical(f2, ctx); + + nmod_mpoly_sort_terms(f3, ctx); + nmod_mpoly_combine_like_terms(f3, ctx); + nmod_mpoly_assert_canonical(f3, ctx); + + if (!nmod_mpoly_equal(f1, f2, ctx)) { + printf("FAIL\n"); + flint_printf("Check pushed polynomial matches add\ni=%wd\n", i, j); + fflush(stdout); + flint_abort(); + } + + if (!nmod_mpoly_equal(f1, f3, ctx)) { + printf("FAIL\n"); + flint_printf("Check pushed ffmpz polynomial matches add\ni=%wd\n", i, j); + fflush(stdout); + flint_abort(); + } + + nmod_mpoly_clear(f1, ctx); + nmod_mpoly_clear(f2, ctx); + nmod_mpoly_clear(f3, ctx); + nmod_mpoly_clear(m, ctx); + nmod_mpoly_ctx_clear(ctx); + + for (k = 0; k < nvars; k++) { + fmpz_clear(exp2[k]); + flint_free(exp2[k]); + fmpz_clear(exp[k]); + flint_free(exp[k]); + fmpz_clear(exp3 + k); + } + flint_free(exp3); + flint_free(exp2); + flint_free(exp); + } + + FLINT_TEST_CLEANUP(state); + + flint_printf("PASS\n"); + return 0; +}