From 6007dd7683752c77cdf9d7c2fbfe8d3a61ea42df Mon Sep 17 00:00:00 2001 From: Jake-Moss Date: Sun, 8 Sep 2024 12:27:19 +1000 Subject: [PATCH 1/2] Fix division by zero in `monomials_deflate.c`. The documentation for `fmpz_mpoly_deflate` (and similar) states > If any `stride[v]` is zero, the corresponding numerator `e - shift[v]` is assumed to > be zero, and the quotient is defined as zero. This allows the function to undo the > operation performed by `fmpz_mpoly_inflate()` when possible. The previous comment and if-statement did not align meaning that the denominator was not being checked leading to divisions by zero when `stride[v]` is 0. --- src/mpoly/monomials_deflate.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/mpoly/monomials_deflate.c b/src/mpoly/monomials_deflate.c index cc7b4809aa..b9c9cfab17 100644 --- a/src/mpoly/monomials_deflate.c +++ b/src/mpoly/monomials_deflate.c @@ -36,12 +36,18 @@ void mpoly_monomials_deflate(ulong * Aexps, flint_bitcnt_t Abits, for (j = 0; j < nvars; j++) { fmpz_sub(exps + j, exps + j, shift + j); - /* stride + j is allowed to be zero */ - if (!fmpz_is_zero(exps + j)) + /* stride + j is allowed to be zero, if it is then exps + j is + assumed to be zero, and the quotient is defined as zero */ + if (!fmpz_is_zero(exps + j) && !fmpz_is_zero(stride + j)) { FLINT_ASSERT(fmpz_divisible(exps + j, stride + j)); fmpz_divexact(exps + j, exps + j, stride + j); } + else + { + fmpz_zero(exps + j); + } + } FLINT_ASSERT(Abits >= mpoly_exp_bits_required_ffmpz(exps, mctx)); mpoly_set_monomial_ffmpz(Aexps + NA*i, exps, Abits, mctx); From 044117b28ed4ec2fdcf7c4a7999bbb34c49cc862 Mon Sep 17 00:00:00 2001 From: Jake-Moss Date: Tue, 17 Sep 2024 21:57:38 +1000 Subject: [PATCH 2/2] Add test for division by zero in monomial_deflate to fmpz_mpoly --- src/fmpz_mpoly/test/t-inflate_deflate.c | 60 +++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/fmpz_mpoly/test/t-inflate_deflate.c b/src/fmpz_mpoly/test/t-inflate_deflate.c index a89ec18859..da1a8c3f54 100644 --- a/src/fmpz_mpoly/test/t-inflate_deflate.c +++ b/src/fmpz_mpoly/test/t-inflate_deflate.c @@ -196,5 +196,65 @@ TEST_FUNCTION_START(fmpz_mpoly_inflate_deflate, state) fmpz_mpoly_ctx_clear(ctx); } + /* Check deflate with zero-stride does not divide by zero */ + for (i = 0; i < 40 * flint_test_multiplier(); i++) + { + fmpz_mpoly_ctx_t ctx; + fmpz_mpoly_t x, res; + fmpz *stride, *shift; + + fmpz_mpoly_ctx_init(ctx, 1, ORD_LEX); + fmpz_mpoly_init(x, ctx); + fmpz_mpoly_init(res, ctx); + + stride = flint_malloc(ctx->minfo->nvars * sizeof(fmpz)); + shift = flint_malloc(ctx->minfo->nvars * sizeof(fmpz)); + fmpz_init(stride + 0); + fmpz_init(shift + 0); + + /* Set x to just the generator */ + fmpz_mpoly_gen(x, 0, ctx); + + /* --- With zero shift --- */ + fmpz_set_ui(shift + 0, 0); + + /* Attempt to deflate x to 1 with a shift and stride 0. */ + /* That is 1 -> (1 - 0) / 0 */ + /* Division by zero should not be raised here */ + fmpz_mpoly_deflate(res, x, shift, stride, ctx); + + if (!fmpz_mpoly_equal_ui(res, 1, ctx)) + { + printf("FAIL\n"); + flint_printf("Check deflate with zero-shift and zero-stride\n"); + fflush(stdout); + flint_abort(); + } + + /* --- With non-zero shift --- */ + fmpz_set_ui(shift + 0, 1); + + /* Attempt to deflate x to 1 with a shift of 1 and stride 0. */ + /* That is 1 -> (1 - 1) / 0 */ + /* Division by zero should not be raised here */ + fmpz_mpoly_deflate(res, x, shift, stride, ctx); + + if (!fmpz_mpoly_equal_ui(res, 1, ctx)) + { + printf("FAIL\n"); + flint_printf("Check deflate with non-zero shift and zero-stride\n"); + fflush(stdout); + flint_abort(); + } + + fmpz_clear(stride + 0); + fmpz_clear(shift + 0); + flint_free(stride); + flint_free(shift); + + fmpz_mpoly_clear(x, ctx); + fmpz_mpoly_ctx_clear(ctx); + } + TEST_FUNCTION_END(state); }