Skip to content

Commit

Permalink
Merge pull request flintlib#2149 from fredrik-johansson/mpoly
Browse files Browse the repository at this point in the history
gr_mpoly: slightly better equality testing code; better test code
  • Loading branch information
fredrik-johansson authored Jan 12, 2025
2 parents 7824d0d + a541dad commit 54bfda0
Show file tree
Hide file tree
Showing 9 changed files with 268 additions and 44 deletions.
23 changes: 2 additions & 21 deletions src/gr_mpoly.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,15 +172,7 @@ int gr_mpoly_zero(gr_mpoly_t A, gr_mpoly_ctx_t ctx)
return GR_SUCCESS;
}

GR_MPOLY_INLINE
truth_t gr_mpoly_is_zero(const gr_mpoly_t A, gr_mpoly_ctx_t ctx)
{
if (A->length == 0)
return T_TRUE;

/* todo: skip when we have canonical representation */
return _gr_vec_is_zero(A->coeffs, A->length, GR_MPOLY_CCTX(ctx));
}
truth_t gr_mpoly_is_zero(const gr_mpoly_t A, gr_mpoly_ctx_t ctx);

WARN_UNUSED_RESULT int gr_mpoly_gen(gr_mpoly_t A, slong var, gr_mpoly_ctx_t ctx);
truth_t gr_mpoly_is_gen(const gr_mpoly_t A, slong var, gr_mpoly_ctx_t ctx);
Expand Down Expand Up @@ -231,18 +223,7 @@ int gr_mpoly_one(gr_mpoly_t A, gr_mpoly_ctx_t ctx)
return gr_mpoly_set_ui(A, 1, ctx);
}

/* todo: efficient version */
GR_MPOLY_INLINE
truth_t gr_mpoly_is_one(const gr_mpoly_t A, gr_mpoly_ctx_t ctx)
{
gr_mpoly_t t;
truth_t res = T_UNKNOWN;
gr_mpoly_init(t, ctx);
if (gr_mpoly_one(t, ctx) == GR_SUCCESS)
res = gr_mpoly_equal(A, t, ctx);
gr_mpoly_clear(t, ctx);
return res;
}
truth_t gr_mpoly_is_one(const gr_mpoly_t A, gr_mpoly_ctx_t ctx);

/* Coefficient/exponent access */

Expand Down
4 changes: 4 additions & 0 deletions src/gr_mpoly/ctx.c
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,10 @@ gr_method_tab_input _gr_mpoly_methods_input[] =
{GR_METHOD_ADD, (gr_funcptr) gr_mpoly_add},
{GR_METHOD_SUB, (gr_funcptr) gr_mpoly_sub},
{GR_METHOD_MUL, (gr_funcptr) gr_mpoly_mul},
{GR_METHOD_MUL_UI, (gr_funcptr) gr_mpoly_mul_ui},
{GR_METHOD_MUL_SI, (gr_funcptr) gr_mpoly_mul_si},
{GR_METHOD_MUL_FMPZ, (gr_funcptr) gr_mpoly_mul_fmpz},
{GR_METHOD_MUL_FMPQ, (gr_funcptr) gr_mpoly_mul_fmpq},
{0, (gr_funcptr) NULL},
};

Expand Down
55 changes: 38 additions & 17 deletions src/gr_mpoly/equal.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,60 @@
(at your option) any later version. See <https://www.gnu.org/licenses/>.
*/

#include "mpoly.h"
#include "gr_mpoly.h"

/* todo: proper algorithm */
truth_t gr_mpoly_equal(
const gr_mpoly_t A,
const gr_mpoly_t B,
gr_mpoly_ctx_t ctx)
{
truth_t eq;
gr_mpoly_t t;
mpoly_ctx_struct * mctx = GR_MPOLY_MCTX(ctx);
gr_ctx_struct * cctx = GR_MPOLY_CCTX(ctx);
int canonical;

if (A == B)
return T_TRUE;

/* todo: if canonical representation */
/*
if (A->length != B->length)
return T_FALSE;
canonical = 1;

... _gr_vec_equal(A->coeffs, B->coeffs, A->length) ...
if (gr_ctx_is_canonical(cctx) != T_TRUE)
{
slong i, sz = cctx->sizeof_elem;

return (0 == mpoly_monomials_cmp(A->exps, A->bits, B->exps, B->bits,
A->length, ctx->minfo)) ? T_TRUE : T_FALSE;
*/
for (i = 0; canonical && i < A->length; i++)
if (gr_is_zero(GR_ENTRY(A->coeffs, i, sz), cctx) != T_FALSE)
canonical = 0;

gr_mpoly_init(t, ctx);
for (i = 0; canonical && i < B->length; i++)
if (gr_is_zero(GR_ENTRY(B->coeffs, i, sz), cctx) != T_FALSE)
canonical = 0;
}

if (gr_mpoly_sub(t, A, B, ctx) == GR_SUCCESS)
eq = gr_mpoly_is_zero(t, ctx);
if (canonical)
{
if (A->length != B->length)
return T_FALSE;

if (0 != mpoly_monomials_cmp(A->exps, A->bits, B->exps, B->bits, A->length, mctx))
return T_FALSE;

return _gr_vec_equal(A->coeffs, B->coeffs, A->length, cctx);
}
else
eq = T_UNKNOWN;
{
/* todo: a better fallback algorithm */
truth_t eq;
gr_mpoly_t t;
gr_mpoly_init(t, ctx);

if (gr_mpoly_sub(t, A, B, ctx) == GR_SUCCESS)
eq = gr_mpoly_is_zero(t, ctx);
else
eq = T_UNKNOWN;

gr_mpoly_clear(t, ctx);
gr_mpoly_clear(t, ctx);

return eq;
return eq;
}
}
45 changes: 45 additions & 0 deletions src/gr_mpoly/is_one.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
Copyright (C) 2020 Daniel Schultz
Copyright (C) 2025 Fredrik Johansson
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 3 of the License, or
(at your option) any later version. See <https://www.gnu.org/licenses/>.
*/

#include "mpoly.h"
#include "gr_mpoly.h"

truth_t gr_mpoly_is_one(const gr_mpoly_t A, gr_mpoly_ctx_t ctx)
{
if (A->length == 0)
return gr_ctx_is_zero_ring(ctx);

if (gr_ctx_is_canonical(GR_MPOLY_CCTX(ctx)) == T_TRUE)
{
slong N;

if (A->length != 1)
return T_FALSE;

N = mpoly_words_per_exp(A->bits, GR_MPOLY_MCTX(ctx));

if (!mpoly_monomial_is_zero(A->exps + N*0, N))
return T_FALSE;

return gr_is_one(A->coeffs, GR_MPOLY_CCTX(ctx));
}
else
{
gr_mpoly_t t;
truth_t res = T_UNKNOWN;
gr_mpoly_init(t, ctx);
if (gr_mpoly_one(t, ctx) == GR_SUCCESS)
res = gr_mpoly_equal(A, t, ctx);
gr_mpoly_clear(t, ctx);
return res;
}
}
25 changes: 25 additions & 0 deletions src/gr_mpoly/is_zero.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
Copyright (C) 2020 Daniel Schultz
Copyright (C) 2025 Fredrik Johansson
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 3 of the License, or
(at your option) any later version. See <https://www.gnu.org/licenses/>.
*/

#include "mpoly.h"
#include "gr_mpoly.h"

truth_t gr_mpoly_is_zero(const gr_mpoly_t A, gr_mpoly_ctx_t ctx)
{
if (A->length == 0)
return T_TRUE;

if (gr_ctx_is_canonical(GR_MPOLY_CCTX(ctx)) == T_TRUE)
return T_FALSE;
else
return _gr_vec_is_zero(A->coeffs, A->length, GR_MPOLY_CCTX(ctx));
}
4 changes: 3 additions & 1 deletion src/gr_mpoly/test/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "t-get_set_coeff.c"
#include "t-mul_johnson.c"
#include "t-mul_monomial.c"
#include "t-ring.c"

/* Array of test functions ***************************************************/

Expand All @@ -25,7 +26,8 @@ test_struct tests[] =
TEST_FUNCTION(gr_mpoly_gen),
TEST_FUNCTION(gr_mpoly_get_set_coeff),
TEST_FUNCTION(gr_mpoly_mul_johnson),
TEST_FUNCTION(gr_mpoly_mul_monomial)
TEST_FUNCTION(gr_mpoly_mul_monomial),
TEST_FUNCTION(gr_mpoly_ring)
};

/* main function *************************************************************/
Expand Down
85 changes: 80 additions & 5 deletions src/gr_mpoly/test/t-get_set_coeff.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
Copyright (C) 2020 Daniel Schultz
Copyright (C) 2022 Fredrik Johansson
Copyright (C) 2022, 2025 Fredrik Johansson
This file is part of FLINT.
Expand All @@ -11,6 +11,8 @@
*/

#include "test_helpers.h"
#include "fmpz.h"
#include "fmpq.h"
#include "fmpz_vec.h"
#include "gr_mpoly.h"

Expand All @@ -28,6 +30,7 @@ TEST_FUNCTION_START(gr_mpoly_get_set_coeff, state)
flint_bitcnt_t exp_bits;
int status;
slong nvars;
int which;

gr_ctx_init_random(cctx, state);
gr_mpoly_ctx_init_rand(ctx, state, cctx, 20);
Expand All @@ -48,11 +51,47 @@ TEST_FUNCTION_START(gr_mpoly_get_set_coeff, state)

status = GR_SUCCESS;

GR_MUST_SUCCEED(gr_randtest(c, state, cctx));
for (k = 0; k < nvars; k++)
exp[k] = n_randtest(state);

status |= gr_mpoly_set_coeff_scalar_ui(f, c, exp, ctx);
which = n_randint(state, 5);

if (which == 0)
{
GR_MUST_SUCCEED(gr_randtest(c, state, cctx));
status |= gr_mpoly_set_coeff_scalar_ui(f, c, exp, ctx);
}
else if (which == 1)
{
ulong uc = n_randtest(state);
status |= gr_set_ui(c, uc, cctx);
status |= gr_mpoly_set_coeff_ui_ui(f, uc, exp, ctx);
}
else if (which == 2)
{
slong sc = n_randtest(state);
status |= gr_set_si(c, sc, cctx);
status |= gr_mpoly_set_coeff_si_ui(f, sc, exp, ctx);
}
else if (which == 3)
{
fmpz_t zc;
fmpz_init(zc);
fmpz_randtest(zc, state, 100);
status |= gr_set_fmpz(c, zc, cctx);
status |= gr_mpoly_set_coeff_fmpz_ui(f, zc, exp, ctx);
fmpz_clear(zc);
}
else if (which == 4)
{
fmpq_t qc;
fmpq_init(qc);
fmpq_randtest(qc, state, 100);
status |= gr_set_fmpq(c, qc, cctx);
status |= gr_mpoly_set_coeff_fmpq_ui(f, qc, exp, ctx);
fmpq_clear(qc);
}

gr_mpoly_assert_canonical(f, ctx);
status |= gr_mpoly_get_coeff_scalar_ui(d, f, exp, ctx);

Expand All @@ -79,10 +118,46 @@ TEST_FUNCTION_START(gr_mpoly_get_set_coeff, state)

status = GR_SUCCESS;

GR_MUST_SUCCEED(gr_randtest(c, state, cctx));
_fmpz_vec_randtest(exp, state, nvars, exp_bits);

status |= gr_mpoly_set_coeff_scalar_fmpz(f, c, exp, ctx);
which = n_randint(state, 5);

if (which == 0)
{
GR_MUST_SUCCEED(gr_randtest(c, state, cctx));
status |= gr_mpoly_set_coeff_scalar_fmpz(f, c, exp, ctx);
}
else if (which == 1)
{
ulong uc = n_randtest(state);
status |= gr_set_ui(c, uc, cctx);
status |= gr_mpoly_set_coeff_ui_fmpz(f, uc, exp, ctx);
}
else if (which == 2)
{
slong sc = n_randtest(state);
status |= gr_set_si(c, sc, cctx);
status |= gr_mpoly_set_coeff_si_fmpz(f, sc, exp, ctx);
}
else if (which == 3)
{
fmpz_t zc;
fmpz_init(zc);
fmpz_randtest(zc, state, 100);
status |= gr_set_fmpz(c, zc, cctx);
status |= gr_mpoly_set_coeff_fmpz_fmpz(f, zc, exp, ctx);
fmpz_clear(zc);
}
else if (which == 4)
{
fmpq_t qc;
fmpq_init(qc);
fmpq_randtest(qc, state, 100);
status |= gr_set_fmpq(c, qc, cctx);
status |= gr_mpoly_set_coeff_fmpq_fmpz(f, qc, exp, ctx);
fmpq_clear(qc);
}

gr_mpoly_assert_canonical(f, ctx);
status |= gr_mpoly_get_coeff_scalar_fmpz(d, f, exp, ctx);

Expand Down
Loading

0 comments on commit 54bfda0

Please sign in to comment.