Conversation
|
On Saturday, 12 April 2025 Ricardo Buring wrote:
> +typedef enum {
+ ORE_OPERATOR_DERIVATIVE,
+ ORE_OPERATOR_EULER_DERIVATIVE,
+ /* TODO: Shift operator, etc. */
+}
+ore_operator_t;
I named this enum (and the value prefix) improperly. What should the
name be?
Maybe gr_ore_poly_which_operator, for consistency with
gr_which_structure?
…--
Marc
|
|
Some/most of the arithmetic/setter methods ( I'm not sure what I did wrong since I did put them in the method table. Edit: Never mind, I put some |
4cfe741 to
c5d790c
Compare
|
So, working with Ore polynomials over say R[x], one might indeed want to do mixed operations with operands from either R or R[x]. The term "scalar" being ambiguous, instead of adding many extra methods, perhaps just define |
|
I don't see the need for |
|
Most of the one-line trivial methods could go in a single file. |
Yes, this is the right way to do it. The way |
|
I reorganized the code to collect the wrapper functions in one file, and applied all the other suggestions above. I removed all the methods with Let me know if this needs any further changes. |
|
Looks good. The only thing missing is documentation. |
e5ac464 to
6323582
Compare
|
Something that doesn't seem to be well specified in the documentation is the generator name (set_gen_name / string conversion methods). If I'm in |
|
In fact, shouldn't the generator x (given as an element of the base ring) be a parameter to the Ore polynomial ring constructor? In general, the base ring could be something multivariate. |
|
I updated the context and constructor to include an index of a generator of the base ring, and (hopefully) clarified the documentation. I think the restriction to generators of the base ring (rather than elements of the base ring) is reasonable, and e.g. in the univariate case it saves the user from having to define a variable that will probably never be used (e.g. multiplication by the variable will be replaced by a shift). Let me know if this is alright. |
5b16adc to
ee4d57a
Compare
|
On Tuesday, 29 April 2025 Ricardo Buring wrote:
@rburing requested your review on: flintlib/flint#2299 Add generic Ore
polynomial module.
Sure, I can take a look, but maybe not before next week. Thanks for your
work on this!
|
|
Another question: How should the |
|
Thanks for the extensive feedback @mezzarobba, I think it looks better now. What do you think about using the name @fredrik-johansson Should I keep |
|
I think the |
Sounds good too. I think I would call d/dx |
f4704c9 to
d2f0653
Compare
|
I added support for general (σ,δ) and implemented a number of standard (σ,δ) pairs, see https://github.com/mezzarobba/flint/tree/gr_ore_poly. Any feedback welcome. (Ricardo, feel free to merge my branch into this PR if you like.) |
|
I should add that most predefined operator types are currently limited to base rings of type |
This contains only the basic structure so far, such as memory management, additive arithmetic, and multiplication from the left by an element of the base ring.
Mark some functions as static, add ngens to pass ring test, fix mismatch of sigma_delta_compose function name in header.
|
I merged the implementation of Ore polynomial multiplication by @vioneers into this branch, and rebased it to resolve merge conflicts and a few technical issues (due to other developments in the codebase in the meantime). |
|
I don't really understand why the tests ( |
|
For the Line 206 in baf1c95 can read past the end of the buffer, e.g. when there is a How should we deal with this (pre-existing) issue? |
|
Good catch. I guess |
| found_algebra = 1; | ||
| else | ||
| { | ||
| if (algebra != ORE_ALGEBRA_FROBENIUS && ctx->which_ring == GR_CTX_GR_POLY) |
There was a problem hiding this comment.
why don't you like the Frobenius case? and what is this doing with the base ring??
| while(!found_algebra) | ||
| { | ||
| // Random context | ||
| gr_ore_poly_ctx_init_randtest2(ctx, ore_ctx, state); |
There was a problem hiding this comment.
Only the ctx and ore_ctx from the last iteration are cleared.
| gr_ore_poly_ctx_t ore_ctx; | ||
| slong reps; | ||
| ore_algebra_t algebra; | ||
| int found_algebra = 0; |
There was a problem hiding this comment.
I don't see the need for this flag.
|
The powering tests from the generic test suite are slow in the Mahler case (reached with diff --git a/src/gr_ore_poly/mul.c b/src/gr_ore_poly/mul.c
index 377ed6d78..d2d9e1999 100644
--- a/src/gr_ore_poly/mul.c
+++ b/src/gr_ore_poly/mul.c
@@ -146,6 +146,9 @@ int gr_ore_poly_mul(gr_ore_poly_t res, const gr_ore_poly_t poly1, const gr_ore_p
if (len1 == 0 || len2 == 0)
return gr_ore_poly_zero(res, ctx);
+ if (len1 + len2 - 1 > ctx->size_limit)
+ return GR_UNABLE;
+
if (GR_ORE_POLY_CTX(ctx)->sigma_delta == NULL)
return GR_UNABLE;
diff --git a/src/gr_ore_poly/test/t-ring.c b/src/gr_ore_poly/test/t-ring.c
index 82768e04f..e0e4f860b 100644
--- a/src/gr_ore_poly/test/t-ring.c
+++ b/src/gr_ore_poly/test/t-ring.c
@@ -28,6 +28,9 @@ TEST_FUNCTION_START(gr_ore_poly_ring, state)
slong reps;
gr_ore_poly_ctx_init_randtest2(ctx, ore_ctx, state);
+ if (GR_ORE_POLY_CTX(ore_ctx)->which_algebra == ORE_ALGEBRA_MAHLER
+ || GR_ORE_POLY_CTX(ore_ctx)->which_algebra == ORE_ALGEBRA_Q_SHIFT)
+ ore_ctx->size_limit = 2;
if (gr_ctx_is_finite(ctx) == T_TRUE ||
gr_ctx_has_real_prec(ctx) == T_TRUE) |
| #include "gr_vec.h" | ||
|
|
||
| // same as GR_MUST_SUCCEED but details of the failing printed | ||
| #define MUST_OK(expr) do { \ |
There was a problem hiding this comment.
I thought this was temporary debugging stuff that would be removed in the final code?
Note that requiring all products to succeed is not correct since it may happen, for instance, that multiplications in the base ring return GR_ENABLE.
But, btw: is this test file needed at all in the end? Or is it subsumed by t-ring?
| reps = 3; | ||
| } | ||
|
|
||
| /* Hack: for string conversion tests, make sure we don't have |
There was a problem hiding this comment.
What string conversion tests? (Eager copy-paste useless here, or am I missing something?)
| @@ -0,0 +1,170 @@ | |||
| /* | |||
| Copyright (C) 2026 Maria Neagoie, supervised by Marc Mezzarobba and Ricardo Buring | |||
There was a problem hiding this comment.
I don't think the “supervised by…” part is necessary :-)
| slong el_size = gr_ctx_sizeof_elem(GR_ORE_POLY_ELEM_CTX(ctx)); | ||
| int status = GR_SUCCESS; | ||
|
|
||
| if (GR_ORE_POLY_CTX(ctx)->sigma_delta == NULL) |
There was a problem hiding this comment.
when/why would that be null?
| TMP_INIT; | ||
| TMP_START; | ||
|
|
||
| gr_ptr temps = TMP_ALLOC(el_size); |
| } | ||
| else | ||
| { | ||
| // Output initialized at 0 |
There was a problem hiding this comment.
why do you need to zero all coefficients in the non-aliased case?
| Sets *res* to *poly* multiplied by *c* (or *x* multiplied by *poly*) | ||
| which must be an element of or coercible to the coefficient ring. | ||
|
|
||
| .. function:: int _gr_ore_poly_lmul_gen(gr_ptr res, gr_srcptr poly, slong len, gr_ore_poly_ctx_t ctx) |
There was a problem hiding this comment.
If you list the underscore variants, it would be good to document the assumptions they make.
| // Initialize Q = b, then Q = D^i * b. | ||
| gr_ore_poly_t Q; | ||
| gr_ore_poly_init2(Q, len2, ctx); | ||
| for (slong i = 0; i < len2; i++) |
There was a problem hiding this comment.
doesn't gr_set work on Ore polynomials?
| { | ||
| gr_srcptr qj = GR_ENTRY(Q->coeffs, j, el_size); | ||
|
|
||
| // Compute a_i * q_j |
There was a problem hiding this comment.
It's probably better to do it with gr_add/gr_mul for now. Many rings don't implement an optimized gr_addmul and the generic version will do a temporary allocation each time.
|
|
||
| void gr_ore_poly_ctx_init(gr_ore_poly_ctx_t ctx, gr_ctx_t base_ring, slong base_var, const ore_algebra_t which_algebra); | ||
| int gr_ore_poly_ctx_init_q_shift(gr_ore_poly_ctx_t ctx, gr_ctx_t base_ring, slong base_var, gr_srcptr q); | ||
| int gr_ore_poly_ctx_init_mahler(gr_ore_poly_ctx_t ctx, gr_ctx_t base_ring, slong base_var, long mahler_base); |
There was a problem hiding this comment.
The long type should be avoided; change to slong?
This contains only the basic structure so far, such as memory management, additive arithmetic, and multiplication from the left by an element of the base ring.
Feedback welcome!
We would like to use this data type as input to differential equation solvers, so we don't need the multiplicative structure initially, though it would be nice to have it in the future.
Multiplicative operations (to be defined later) depend on the Ore context object, so I figured that all operations should take the Ore context as input, to make the interface uniform. So now the interface looks like
gr_mpoly, and the basic operations implemented so far callgr_polymethods.Since the base ring will typically be polynomial, shouldgr_ore_poly_scalar_mulandGR_ORE_POLY_ELEM_CTXbe named differently? Maybe usingbase/BASE?I also tried to make the module "optional" in the sense thatgr_mpolyis, let me know if I missed something in this regard.cc @mezzarobba