Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix division by zero in monomials_deflate.c. #2066

Merged

Conversation

Jake-Moss
Copy link
Contributor

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.

Here is a MWE

#include "flint/fmpz_mpoly.h"

int main(void) {
    fmpz_mpoly_ctx_t ctx;
    fmpz_mpoly_t x, res;
    fmpz *stride, *shift;

    const char *vars = "x";

    fmpz_mpoly_ctx_init(ctx, 1, ORD_LEX);
    fmpz_mpoly_init(x, ctx);
    fmpz_mpoly_init(res, ctx);

    fmpz_mpoly_gen(x, 0, ctx);

    stride = flint_malloc(ctx->minfo->nvars * sizeof(fmpz));
    shift = flint_malloc(ctx->minfo->nvars * sizeof(fmpz));
    for (int i = 0; i < ctx->minfo->nvars; i++) {
      fmpz_init(stride + i);
      fmpz_init(shift + i);
    }

    fmpz_mpoly_print_pretty(x, &vars, ctx); flint_printf("\n");

    // Division by zero here
    fmpz_mpoly_deflate(res, x, shift, stride, ctx);

    fmpz_mpoly_print_pretty(res, &vars, ctx); flint_printf("\n");

    for (int i = 0; i < ctx->minfo->nvars; i++) {
      fmpz_clear(stride + i);
      fmpz_clear(shift + i);
    }
    flint_free(stride);
    flint_free(shift);

    fmpz_mpoly_clear(x, ctx);
    fmpz_mpoly_ctx_clear(ctx);
    return 0;
}

Without this patch:

~/ λ gcc scratch.c -lflint
~/ λ ./a.out
x
Exception (fmpz_divexact). Division by zero.
aborted (core dumped)

With:

~/ λ gcc scratch.c -lflint
~/ λ ./a.out
x
1

From python-flint here: flintlib/python-flint#216 (comment)

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.
@Jake-Moss
Copy link
Contributor Author

Jake-Moss commented Sep 8, 2024

I believe I was miss-using the deflation functions that caused me to run into this, however it still does not look quite right to me in it's current form.

@albinahlback
Copy link
Collaborator

Could you add a test case for this?

@Jake-Moss
Copy link
Contributor Author

Done, I've added the test to the fmpz_mpoly suite rather than the mpoly tests as it has existing inflation/deflation tests.

@fredrik-johansson fredrik-johansson merged commit 1f98483 into flintlib:main Sep 17, 2024
13 checks passed
@fredrik-johansson
Copy link
Collaborator

Looks good, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants