Crash in `nmod_poly`
For fmpz_mod_poly we get an error when we cannot compute an inverse when performing operations
>>> from flint import fmpz_mod_poly_ctx, fmpz_mod_poly
>>> R = fmpz_mod_poly_ctx(10)
>>> f = R([1,2,3])
>>> f
3*x^2 + 2*x + 1
>>> f % f
0
>>> g = R([3,1,2])
>>> g
2*x^2 + x + 3
>>> g % g
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "src/flint/types/fmpz_mod_poly.pyx", line 659, in flint.types.fmpz_mod_poly.fmpz_mod_poly.__mod__
File "src/flint/types/fmpz_mod_poly.pyx", line 652, in flint.types.fmpz_mod_poly.fmpz_mod_poly._mod_
ValueError: Cannot compute remainder of 2*x^2 + x + 3 modulo 2*x^2 + x + 3
But for nmod_poly we get a crash:
Python 3.11.4 (main, Jul 25 2023, 17:07:07) [Clang 14.0.3 (clang-1403.0.22.14.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from flint import *
>>> f = nmod_poly([2,1,3], 10)
>>> f
3*x^2 + x + 2
>>> f % f
0
>>> f = nmod_poly([3, 1, 2], 10)
>>> f % f
Flint exception (Impossible inverse):
Cannot invert modulo 2*5
zsh: abort python3
I think what is needed is to have contexts for nmod so that there is somewhere to store whether or not the modulus is prime. Then operations that are not well defined for composite moduli could be rejected.
Yeah I agree. I think this would also help users simply because then different polynomial objects would be used in the same way.
I can see potentially two different kinds of contexts. The low-level version is sort of what fmpz_mod_poly_ctx is except that it would be good to make it so that all objects have such a context and can quickly compare them in methods like __add__ or can quickly check for prime modulus.
A higher level version could be a user interface like:
R = Zmod(10)
n = R(5)
p = R.poly([1, 2, 1])
M = R.matrix([[1, 2], [3, 4]])
s = R.series(...)
Here the user does not need to create an fmpz_mod_poly_ctx explicitly. Perhaps Zmod should choose automatically between nmod and fmpz_mod.
I'm not sure if it would be better to have polynomial rings with distinct symbol names like
R.poly_ring('y')
R['y']
R['x']
Something like this would likely be needed for mpoly.
Yeah, this would be really nice but reminds me more of the "level above" when you were talking about the goals and different ideas.
Here Zmod is more like a python (rather than cython?) interface which allows you to select and construct everything you want smartly from what python flint gives.
Whether we do:
K = Zmod(10)
f = K.poly([1,2,3])
or
K = Zmod(10)
R = PolynomialRing(K, 'x') # more like sage
Is another question I suppose.
Yeah, this would be really nice but reminds me more of the "level above"
Yeah, I'm getting sidetracked.
We can just add an nmod_ctx type. I just mentioned the other things because I think that more broadly it would be better to have consistent handling of contexts for each of the types.