Skip to content

Commit ee4d57a

Browse files
committed
Add generic Ore polynomial module
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.
1 parent 726ee2d commit ee4d57a

File tree

16 files changed

+1278
-2
lines changed

16 files changed

+1278
-2
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ set(_BUILD_DIRS
261261
acb_theta dirichlet bernoulli hypgeom
262262

263263
gr gr_generic gr_vec gr_mat
264-
gr_poly gr_mpoly gr_special
264+
gr_poly gr_mpoly gr_ore_poly gr_special
265265

266266
calcium
267267
fmpz_mpoly_q

Makefile.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ HEADER_DIRS := \
210210
acb_theta dirichlet bernoulli hypgeom \
211211
\
212212
gr gr_generic gr_vec gr_mat \
213-
gr_poly gr_mpoly gr_special \
213+
gr_poly gr_mpoly gr_ore_poly gr_special \
214214
\
215215
calcium \
216216
fmpz_mpoly_q \

doc/source/gr_domains.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,17 @@ Polynomial rings
315315
with monomial ordering *ord*.
316316
Elements have type :type:`gr_mpoly_struct`.
317317

318+
Ore polynomials
319+
-------------------------------------------------------------------------------
320+
321+
.. function:: void gr_ore_poly_ctx_init(gr_ore_poly_ctx_t ctx, gr_ctx_t base_ring, slong base_var, const ore_poly_which_operator_t operator)
322+
323+
Initializes ``ctx`` to represent an Ore polynomial ring with
324+
coefficients in ``base_ring`` and the choice of Ore operator,
325+
associated with the generator of ``base_ring`` of index ``base_var``,
326+
given by ``operator``.
327+
Elements have type :type:`gr_ore_poly_struct`.
328+
318329
Power series
319330
-------------------------------------------------------------------------------
320331

doc/source/gr_ore_poly.rst

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
.. _gr-ore-poly:
2+
3+
**gr_ore_poly.h** -- dense univariate Ore polynomials over generic rings
4+
===============================================================================
5+
6+
A :type:`gr_ore_poly_t` represents a univariate Ore polynomial `L \in R[D]`
7+
implemented as a dense array of coefficients in a generic ring *R*.
8+
The choice of Ore operator *D* (e.g. standard derivative, Euler derivative),
9+
which is associated with a generator of *R*, is stored in the context object
10+
:type:`gr_ore_poly_ctx_t`.
11+
12+
Most functions are provided in two versions: an underscore method which
13+
operates directly on pre-allocated arrays of coefficients and generally
14+
has some restrictions (often requiring the lengths to be nonzero
15+
and not supporting aliasing of the input and output arrays),
16+
and a non-underscore method which performs automatic memory
17+
management and handles degenerate cases.
18+
19+
Ore operators
20+
--------------------------------------------------------------------------------
21+
.. type:: ore_poly_which_operator_t
22+
23+
Represents one of the following supported Ore operators:
24+
25+
.. macro:: ORE_OPERATOR_STANDARD_DERIVATIVE
26+
27+
The standard derivative.
28+
29+
.. macro:: ORE_OPERATOR_EULER_DERIVATIVE
30+
31+
The Euler derivative.
32+
33+
.. function:: ore_poly_which_operator_t ore_poly_which_operator_randtest(flint_rand_t state)
34+
35+
Return a random Ore operator.
36+
37+
Type compatibility
38+
-------------------------------------------------------------------------------
39+
40+
The ``gr_ore_poly`` type has the same data layout as ``gr_poly``.
41+
Methods of ``gr_poly`` can therefore be used for linear and container
42+
operations on a ``gr_ore_poly``, given that one is careful about providing
43+
the right context object.
44+
45+
Weak normalization
46+
-------------------------------------------------------------------------------
47+
48+
A :type:`gr_ore_poly_t` is always normalised by removing leading zeros.
49+
For rings without decidable equality (e.g. rings with inexact
50+
representation), only coefficients that are provably zero will be
51+
removed, and there can thus be spurious leading zeros in the
52+
internal representation.
53+
Methods that depend on knowing the exact degree of a polynomial
54+
will act appropriately, typically by returning ``GR_UNABLE``
55+
when it is unknown whether the leading stored coefficient is nonzero.
56+
57+
Types, macros and constants
58+
-------------------------------------------------------------------------------
59+
60+
.. type:: gr_ore_poly_struct
61+
62+
.. type:: gr_ore_poly_t
63+
64+
Contains a pointer to an array of coefficients (``coeffs``), the used
65+
length (``length``), and the allocated size of the array (``alloc``).
66+
67+
A ``gr_ore_poly_t`` is defined as an array of length one of type
68+
``gr_ore_poly_struct``, permitting a ``gr_ore_poly_t`` to
69+
be passed by reference.
70+
71+
Context object methods
72+
-------------------------------------------------------------------------------
73+
74+
.. function:: void gr_ore_poly_ctx_init(gr_ore_poly_ctx_t ctx, gr_ctx_t base_ring, slong base_var, const ore_poly_which_operator_t operator)
75+
76+
Initializes ``ctx`` to represent an Ore polynomial ring with
77+
coefficients in ``base_ring`` and the choice of Ore operator,
78+
associated with the generator of ``base_ring`` of index ``base_var``,
79+
given by ``operator``.
80+
81+
.. function:: void gr_ore_poly_ctx_clear(gr_ore_poly_ctx_t ctx)
82+
83+
Clears the context object ``ctx``.
84+
85+
.. function:: void gr_ore_poly_ctx_init_rand(gr_ore_poly_ctx_t ctx, flint_rand_t state, gr_ctx_t base_ring)
86+
87+
Initializes ``ctx`` with a random Ore operator.
88+
89+
The following methods implement parts of the standard interface
90+
for ``gr`` context objects.
91+
92+
.. function:: int _gr_ore_poly_ctx_set_gen_name(gr_ctx_t ctx, const char * s)
93+
int _gr_ore_poly_ctx_set_gen_names(gr_ctx_t ctx, const char ** s)
94+
95+
Sets the name of the generator to the string in ``s``, respectively the
96+
first string in ``s``.
97+
98+
.. function:: int gr_ore_poly_ctx_write(gr_stream_t out, gr_ore_poly_ctx_t ctx)
99+
truth_t gr_ore_poly_ctx_is_ring(gr_ore_poly_ctx_t ctx)
100+
truth_t gr_ore_poly_ctx_is_zero_ring(gr_ore_poly_ctx_t ctx)
101+
truth_t gr_ore_poly_ctx_is_commutative_ring(gr_ore_poly_ctx_t ctx)
102+
truth_t gr_ore_poly_ctx_is_integral_domain(gr_ore_poly_ctx_t ctx)
103+
truth_t gr_ore_poly_ctx_is_threadsafe(gr_ore_poly_ctx_t ctx)
104+
105+
Memory management
106+
-------------------------------------------------------------------------------
107+
108+
.. function:: void gr_ore_poly_init(gr_ore_poly_t poly, gr_ore_poly_ctx_t ctx)
109+
110+
.. function:: void gr_ore_poly_init2(gr_ore_poly_t poly, slong len, gr_ore_poly_ctx_t ctx)
111+
112+
.. function:: void gr_ore_poly_clear(gr_ore_poly_t poly, gr_ore_poly_ctx_t ctx)
113+
114+
.. function:: gr_ptr gr_ore_poly_entry_ptr(gr_ore_poly_t poly, slong i, gr_ore_poly_ctx_t ctx)
115+
gr_srcptr gr_ore_poly_entry_srcptr(const gr_ore_poly_t poly, slong i, gr_ore_poly_ctx_t ctx)
116+
117+
.. function:: slong gr_ore_poly_length(const gr_ore_poly_t poly, gr_ore_poly_ctx_t ctx)
118+
119+
.. function:: void gr_ore_poly_swap(gr_ore_poly_t poly1, gr_ore_poly_t poly2, gr_ore_poly_ctx_t ctx)
120+
121+
.. function:: void gr_ore_poly_fit_length(gr_ore_poly_t poly, slong len, gr_ore_poly_ctx_t ctx)
122+
123+
.. function:: void _gr_ore_poly_set_length(gr_ore_poly_t poly, slong len, gr_ore_poly_ctx_t ctx)
124+
125+
Basic manipulation
126+
-------------------------------------------------------------------------------
127+
128+
.. function:: void _gr_ore_poly_normalise(gr_ore_poly_t poly, gr_ore_poly_ctx_t ctx)
129+
130+
.. function:: int gr_ore_poly_set(gr_ore_poly_t res, const gr_ore_poly_t src, gr_ore_poly_ctx_t ctx)
131+
132+
.. function:: int gr_ore_poly_truncate(gr_ore_poly_t res, const gr_ore_poly_t poly, slong newlen, gr_ore_poly_ctx_t ctx)
133+
134+
.. function:: int gr_ore_poly_zero(gr_ore_poly_t poly, gr_ore_poly_ctx_t ctx)
135+
int gr_ore_poly_one(gr_ore_poly_t poly, gr_ore_poly_ctx_t ctx)
136+
int gr_ore_poly_neg_one(gr_ore_poly_t poly, gr_ore_poly_ctx_t ctx)
137+
int gr_ore_poly_gen(gr_ore_poly_t poly, gr_ore_poly_ctx_t ctx)
138+
139+
.. function:: int gr_ore_poly_write(gr_stream_t out, const gr_ore_poly_t poly, const char * d, gr_ore_poly_ctx_t ctx)
140+
int _gr_ore_poly_write(gr_stream_t out, gr_srcptr poly, slong n, const char * d, gr_ore_poly_ctx_t ctx)
141+
int _gr_ore_poly_get_str(char ** res, const gr_ore_poly_t f, const char * d, gr_ore_poly_ctx_t ctx)
142+
int gr_ore_poly_get_str(char ** res, const gr_ore_poly_t f, const char * d, gr_ore_poly_ctx_t ctx)
143+
int gr_ore_poly_print(const gr_ore_poly_t poly, gr_ore_poly_ctx_t ctx)
144+
145+
.. function:: int _gr_ore_poly_set_str(gr_ptr res, const char * s, const char * d, slong len, gr_ore_poly_ctx_t ctx)
146+
int gr_ore_poly_set_str(gr_ore_poly_t res, const char * s, const char * d, gr_ore_poly_ctx_t ctx)
147+
148+
Parse Ore polynomial from an expression string, assuming that the string in *d* gives
149+
the name of the generator. The underscore method zero-pads the result if
150+
the length of the parsed polynomial is shorter than *len*, and returns
151+
``GR_UNABLE`` if the length of the parsed polynomial exceeds *len*.
152+
Intermediate terms are allowed to be longer than *len*.
153+
154+
Warning: these methods are not currently optimized for polynomials of high degree
155+
and may run with quadratic complexity.
156+
157+
.. function:: int gr_ore_poly_randtest(gr_ore_poly_t poly, flint_rand_t state, slong len, gr_ore_poly_ctx_t ctx)
158+
159+
.. function:: truth_t _gr_ore_poly_equal(gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ore_poly_ctx_t ctx)
160+
truth_t gr_ore_poly_equal(const gr_ore_poly_t poly1, const gr_ore_poly_t poly2, gr_ore_poly_ctx_t ctx)
161+
162+
.. function:: truth_t gr_ore_poly_is_zero(const gr_ore_poly_t poly, gr_ore_poly_ctx_t ctx)
163+
truth_t gr_ore_poly_is_one(const gr_ore_poly_t poly, gr_ore_poly_ctx_t ctx)
164+
truth_t gr_ore_poly_is_gen(const gr_ore_poly_t poly, gr_ore_poly_ctx_t ctx)
165+
166+
.. function:: int gr_ore_poly_set_si(gr_ore_poly_t poly, slong c, gr_ore_poly_ctx_t ctx)
167+
int gr_ore_poly_set_ui(gr_ore_poly_t poly, ulong c, gr_ore_poly_ctx_t ctx)
168+
int gr_ore_poly_set_fmpz(gr_ore_poly_t poly, const fmpz_t c, gr_ore_poly_ctx_t ctx)
169+
int gr_ore_poly_set_fmpq(gr_ore_poly_t poly, const fmpq_t c, gr_ore_poly_ctx_t ctx)
170+
int gr_ore_poly_set_other(gr_ore_poly_t poly, gr_srcptr x, gr_ctx_t x_ctx, gr_ore_poly_ctx_t ctx)
171+
172+
Arithmetic
173+
-------------------------------------------------------------------------------
174+
175+
.. function:: int gr_ore_poly_neg(gr_ore_poly_t res, const gr_ore_poly_t src, gr_ore_poly_ctx_t ctx)
176+
177+
.. function:: int _gr_ore_poly_add(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ore_poly_ctx_t ctx)
178+
int gr_ore_poly_add(gr_ore_poly_t res, const gr_ore_poly_t poly1, const gr_ore_poly_t poly2, gr_ore_poly_ctx_t ctx)
179+
180+
.. function:: int _gr_ore_poly_sub(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ore_poly_ctx_t ctx)
181+
int gr_ore_poly_sub(gr_ore_poly_t res, const gr_ore_poly_t poly1, const gr_ore_poly_t poly2, gr_ore_poly_ctx_t ctx)
182+
183+
.. function:: int gr_ore_poly_add_ui(gr_ore_poly_t res, const gr_ore_poly_t poly, ulong c, gr_ore_poly_ctx_t ctx)
184+
int gr_ore_poly_add_si(gr_ore_poly_t res, const gr_ore_poly_t poly, slong c, gr_ore_poly_ctx_t ctx)
185+
int gr_ore_poly_add_fmpz(gr_ore_poly_t res, const gr_ore_poly_t poly, const fmpz c, gr_ore_poly_ctx_t ctx)
186+
int gr_ore_poly_add_fmpq(gr_ore_poly_t res, const gr_ore_poly_t poly, const fmpq c, gr_ore_poly_ctx_t ctx)
187+
int gr_ore_poly_add_other(gr_ore_poly_t res, const gr_ore_poly_t poly, gr_srcptr x, gr_ctx_t x_ctx, gr_ore_poly_ctx_t ctx)
188+
189+
Sets *res* to *poly* plus the scalar *c* which must be
190+
an element of or coercible to the coefficient ring.
191+
192+
.. function:: int gr_ore_poly_sub_ui(gr_ore_poly_t res, const gr_ore_poly_t poly, ulong c, gr_ore_poly_ctx_t ctx)
193+
int gr_ore_poly_sub_si(gr_ore_poly_t res, const gr_ore_poly_t poly, slong c, gr_ore_poly_ctx_t ctx)
194+
int gr_ore_poly_sub_fmpz(gr_ore_poly_t res, const gr_ore_poly_t poly, const fmpz c, gr_ore_poly_ctx_t ctx)
195+
int gr_ore_poly_sub_fmpq(gr_ore_poly_t res, const gr_ore_poly_t poly, const fmpq c, gr_ore_poly_ctx_t ctx)
196+
int gr_ore_poly_sub_other(gr_ore_poly_t res, const gr_ore_poly_t poly, gr_srcptr x, gr_ctx_t x_ctx, gr_ore_poly_ctx_t ctx)
197+
198+
Sets *res* to *poly* minus *c* which must be
199+
an element of or coercible to the coefficient ring.
200+
201+
.. function:: int gr_ore_poly_mul_ui(gr_ore_poly_t res, const gr_ore_poly_t poly, ulong c, gr_ore_poly_ctx_t ctx)
202+
int gr_ore_poly_mul_si(gr_ore_poly_t res, const gr_ore_poly_t poly, slong c, gr_ore_poly_ctx_t ctx)
203+
int gr_ore_poly_mul_fmpz(gr_ore_poly_t res, const gr_ore_poly_t poly, const fmpz c, gr_ore_poly_ctx_t ctx)
204+
int gr_ore_poly_mul_fmpq(gr_ore_poly_t res, const gr_ore_poly_t poly, const fmpq c, gr_ore_poly_ctx_t ctx)
205+
int gr_ore_poly_other_mul(gr_ore_poly_t res, gr_srcptr x, gr_ctx_t x_ctx, const gr_ore_poly_t poly, gr_ore_poly_ctx_t ctx)
206+
207+
Sets *res* to *poly* multiplied by *c* (or *x* multiplied by *poly*)
208+
which must be an element of or coercible to the coefficient ring.
209+
210+
.. raw:: latex
211+
212+
\newpage
213+

doc/source/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ Generic rings
6060
gr_mat.rst
6161
gr_poly.rst
6262
gr_mpoly.rst
63+
gr_ore_poly.rst
6364

6465
.. only:: not latex
6566

doc/source/index_generic.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@
1616
gr_mat.rst
1717
gr_poly.rst
1818
gr_mpoly.rst
19+
gr_ore_poly.rst
1920

src/generic_files/io.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "gr.h"
2727
#include "gr_vec.h"
2828
#include "gr_poly.h"
29+
#include "gr_ore_poly.h"
2930
#include "gr_mat.h"
3031

3132
int _gr_mat_write(gr_stream_t out, const gr_mat_t mat, int linebreaks, gr_ctx_t ctx);
@@ -728,6 +729,14 @@ int flint_vfprintf(FILE * fs, const char * ip, va_list vlist)
728729
res += out->len;
729730
ip += STRING_LENGTH("gr_poly}");
730731
}
732+
else if (IS_FLINT_TYPE(ip, "gr_ore_poly"))
733+
{
734+
const gr_ore_poly_struct * elem = va_arg(vlist, const gr_ore_poly_struct *);
735+
gr_ctx_struct * ctx = va_arg(vlist, gr_ctx_struct *);
736+
GR_MUST_SUCCEED(gr_ore_poly_write(out, elem, "Dx", ctx));
737+
res += out->len;
738+
ip += STRING_LENGTH("gr_ore_poly}");
739+
}
731740
else if (IS_FLINT_TYPE(ip, "gr_mat"))
732741
{
733742
const gr_mat_struct * elem = va_arg(vlist, const gr_mat_struct *);

src/gr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,7 @@ typedef enum
689689
GR_CTX_FMPZ_POLY, GR_CTX_FMPQ_POLY, GR_CTX_GR_POLY,
690690
GR_CTX_FMPZ_MPOLY, GR_CTX_GR_MPOLY,
691691
GR_CTX_FMPZ_MPOLY_Q,
692+
GR_CTX_GR_ORE_POLY,
692693
GR_CTX_GR_FRACTION,
693694
GR_CTX_GR_SERIES, GR_CTX_SERIES_MOD_GR_POLY,
694695
GR_CTX_GR_MAT,

src/gr/ore_poly.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
Copyright (C) 2025 Ricardo Buring
3+
4+
This file is part of FLINT.
5+
6+
FLINT is free software: you can redistribute it and/or modify it under
7+
the terms of the GNU Lesser General Public License (LGPL) as published
8+
by the Free Software Foundation; either version 3 of the License, or
9+
(at your option) any later version. See <https://www.gnu.org/licenses/>.
10+
*/
11+
12+
#include "gr_ore_poly.h"
13+
14+
void
15+
gr_ctx_init_gr_ore_poly(gr_ctx_t ctx, gr_ctx_t base_ring, slong base_var, const ore_poly_which_operator_t operator)
16+
{
17+
gr_ore_poly_ctx_init(ctx, base_ring, base_var, operator);
18+
}

0 commit comments

Comments
 (0)