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

Begin adding fmpz_mod_poly #87

Merged
merged 36 commits into from
Oct 1, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
fea7def
Begin adding fmpz_mod_poly
GiacomoPope Sep 20, 2023
6b1611a
Modify methods for contexts
GiacomoPope Sep 20, 2023
6797150
Add conversion and comparison functions
GiacomoPope Sep 21, 2023
e6b28d4
Start work on factor; bug
GiacomoPope Sep 21, 2023
4e64490
Monic, Leading Coefficent and Factor
GiacomoPope Sep 21, 2023
36724e3
More progress, but badly unittested currently
GiacomoPope Sep 21, 2023
0a84867
Add additional bool to check if modulus is prime on init
GiacomoPope Sep 22, 2023
6122937
Continue adding functions and docstrings
GiacomoPope Sep 22, 2023
4827066
Address review, add random elements and further methods and docstrings
GiacomoPope Sep 22, 2023
00b87f5
Add more functions to fmpz_mod_poly, also add is_unit to fmpz_mod
GiacomoPope Sep 22, 2023
a3fec08
Add a few more functions, coverage currently at 22%
GiacomoPope Sep 26, 2023
586307a
include new types to docstring tests
GiacomoPope Sep 26, 2023
b2e2894
Ensure 100% coverage of fmpz_mod, fix docstring test bugs, fmpz_mod_p…
GiacomoPope Sep 26, 2023
b060b23
Add base class docstrings
GiacomoPope Sep 27, 2023
c30ad7a
Improve docstrings and get coverage to 100%
GiacomoPope Sep 27, 2023
a2a7c1f
Include fmpz_mod_poly into documentation:
GiacomoPope Sep 27, 2023
857ee26
Address first round of comments from the review
GiacomoPope Sep 27, 2023
9cabaa2
Add a custom, DomainError, Exception
GiacomoPope Sep 27, 2023
024a09c
Improve based off feedback and add additional functions
GiacomoPope Sep 27, 2023
9a01c5d
Begin adding Berlekamp-Massey algorithm
GiacomoPope Sep 27, 2023
87a77b7
Add minpoly, remove BM, problems with multipoint eval
GiacomoPope Sep 28, 2023
85f82a4
Fix stupid copy paste bug
GiacomoPope Sep 28, 2023
428bece
Add support for vec types
GiacomoPope Sep 29, 2023
bc85cd3
Clean up set_any function and improve memory management
GiacomoPope Sep 29, 2023
cb60fe7
Add tests
GiacomoPope Sep 29, 2023
e57a071
Merge branch 'master' into add_fmpz_mod_poly
GiacomoPope Sep 29, 2023
69b2e50
Address bug from merging in test. Rename shift and (in/de)flation fun…
GiacomoPope Sep 29, 2023
a793997
Include new type into generic test, but with some TODO
GiacomoPope Sep 29, 2023
8fd39d1
Address TODO in tests and modify how _div_ works
GiacomoPope Sep 29, 2023
3614a42
Hacky fix for memory?
GiacomoPope Sep 29, 2023
9dfd197
Simplify init function
GiacomoPope Sep 30, 2023
1945859
better handling of dealloc
GiacomoPope Sep 30, 2023
57b8346
Add new poly method to context
GiacomoPope Sep 30, 2023
6a3b447
Return to 100% coverage
GiacomoPope Sep 30, 2023
52dee64
Forgot to push test commit
GiacomoPope Sep 30, 2023
b2543b4
Fix docstring types and initalise int type
GiacomoPope Oct 1, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
("flint.types.acb_series", ["src/flint/types/acb_series.pyx"]),
("flint.types.fmpz_mpoly", ["src/flint/types/fmpz_mpoly.pyx"]),
("flint.types.fmpz_mod", ["src/flint/types/fmpz_mod.pyx"]),
("flint.types.fmpz_mod_poly", ["src/flint/types/fmpz_mod_poly.pyx"]),
("flint.types.dirichlet", ["src/flint/types/dirichlet.pyx"]),
("flint.flint_base.flint_base", ["src/flint/flint_base/flint_base.pyx"]),
("flint.flint_base.flint_context", ["src/flint/flint_base/flint_context.pyx"]),
Expand Down
1 change: 1 addition & 0 deletions src/flint/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from .types.acb_series import *
from .types.fmpz_mpoly import *
from .types.fmpz_mod import *
from .types.fmpz_mod_poly import *
from .types.dirichlet import *
from .functions.showgood import showgood

Expand Down
338 changes: 338 additions & 0 deletions src/flint/flintlib/fmpz_mod_poly.pxd

Large diffs are not rendered by default.

46 changes: 46 additions & 0 deletions src/flint/flintlib/fmpz_mod_poly_factor.pxd
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from flint.flintlib.flint cimport fmpz_struct, slong, flint_rand_t
from flint.flintlib.fmpz cimport fmpz_t
from flint.flintlib.fmpz_mod cimport fmpz_mod_ctx_t
from flint.flintlib.fmpz_factor cimport fmpz_factor_t
from flint.flintlib.fmpz_mod_poly cimport fmpz_mod_poly_struct, fmpz_mod_poly_t

# unimported types {'fmpz_mod_poly_factor_t', 'void', 'fmpz_mod_poly_t'}

cdef extern from "flint/fmpz_mod_poly_factor.h":
ctypedef struct fmpz_mod_poly_factor_struct:
fmpz_mod_poly_struct * poly
slong *exp
slong num
slong alloc
ctypedef fmpz_mod_poly_factor_struct fmpz_mod_poly_factor_t[1]

# Parsed from here
void fmpz_mod_poly_factor_init(fmpz_mod_poly_factor_t fac, const fmpz_mod_ctx_t ctx)
void fmpz_mod_poly_factor_clear(fmpz_mod_poly_factor_t fac, const fmpz_mod_ctx_t ctx)
void fmpz_mod_poly_factor_realloc(fmpz_mod_poly_factor_t fac, slong alloc, const fmpz_mod_ctx_t ctx)
void fmpz_mod_poly_factor_fit_length(fmpz_mod_poly_factor_t fac, slong len, const fmpz_mod_ctx_t ctx)
void fmpz_mod_poly_factor_set(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_factor_t fac, const fmpz_mod_ctx_t ctx)
void fmpz_mod_poly_factor_print(const fmpz_mod_poly_factor_t fac, const fmpz_mod_ctx_t ctx)
void fmpz_mod_poly_factor_insert(fmpz_mod_poly_factor_t fac, const fmpz_mod_poly_t poly, slong exp, const fmpz_mod_ctx_t ctx)
void fmpz_mod_poly_factor_concat(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_factor_t fac, const fmpz_mod_ctx_t ctx)
void fmpz_mod_poly_factor_pow(fmpz_mod_poly_factor_t fac, slong exp, const fmpz_mod_ctx_t ctx)
int fmpz_mod_poly_is_irreducible(const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx)
int fmpz_mod_poly_is_irreducible_ddf(const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx)
int fmpz_mod_poly_is_irreducible_rabin(const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx)
int fmpz_mod_poly_is_irreducible_rabin_f(fmpz_t r, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx)
int _fmpz_mod_poly_is_squarefree(const fmpz_struct * f, slong len, const fmpz_mod_ctx_t ctx)
int _fmpz_mod_poly_is_squarefree_f(fmpz_t fac, const fmpz_struct * f, slong len, const fmpz_mod_ctx_t ctx)
int fmpz_mod_poly_is_squarefree(const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx)
int fmpz_mod_poly_is_squarefree_f(fmpz_t fac, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx)
int fmpz_mod_poly_factor_equal_deg_prob(fmpz_mod_poly_t factor, flint_rand_t state, const fmpz_mod_poly_t pol, slong d, const fmpz_mod_ctx_t ctx)
void fmpz_mod_poly_factor_equal_deg(fmpz_mod_poly_factor_t factors, const fmpz_mod_poly_t pol, slong d, const fmpz_mod_ctx_t ctx)
void fmpz_mod_poly_factor_distinct_deg(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t poly, slong * const *degs, const fmpz_mod_ctx_t ctx)
void fmpz_mod_poly_factor_distinct_deg_threaded(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t poly, slong * const *degs, const fmpz_mod_ctx_t ctx)
void fmpz_mod_poly_factor_squarefree(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx)
void fmpz_mod_poly_factor(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx)
void fmpz_mod_poly_factor_cantor_zassenhaus(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx)
void fmpz_mod_poly_factor_kaltofen_shoup(fmpz_mod_poly_factor_t res, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx)
void fmpz_mod_poly_factor_berlekamp(fmpz_mod_poly_factor_t factors, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx)
void _fmpz_mod_poly_interval_poly_worker(void* arg_ptr)
void fmpz_mod_poly_roots(fmpz_mod_poly_factor_t r, const fmpz_mod_poly_t f, int with_multiplicity, const fmpz_mod_ctx_t ctx)
int fmpz_mod_poly_roots_factored(fmpz_mod_poly_factor_t r, const fmpz_mod_poly_t f, int with_multiplicity, const fmpz_factor_t n, const fmpz_mod_ctx_t ctx)
82 changes: 81 additions & 1 deletion src/flint/test/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1813,6 +1813,85 @@ def test_fmpz_mod_dlog():
x = g.discrete_log(a)
assert g**x == a

def test_fmpz_mod_poly():
from flint import fmpz_poly, fmpz_mod_poly_ctx, fmpz_mod_ctx, fmpz

# fmpz_mod_poly_ctx tests
F = fmpz_mod_ctx(11)
R1 = fmpz_mod_poly_ctx(F)
R2 = fmpz_mod_poly_ctx(11)
R3 = fmpz_mod_poly_ctx(13)

assert raises(lambda: fmpz_mod_ctx("AAA"), TypeError)
assert raises(lambda: fmpz_mod_ctx(-1), ValueError)
assert (R1 == R1) is True
assert (R1 == R2) is True
assert (R1 != R3) is True
assert (R1 != "AAA") is True
GiacomoPope marked this conversation as resolved.
Show resolved Hide resolved

assert (hash(R1) == hash(R1)) is True
assert (hash(R1) == hash(R2)) is True
assert (hash(R1) != hash(R3)) is True

assert str(R1) == "Context for fmpz_mod_poly with modulus: 11"
assert str(R1) == str(R2)
assert repr(R3) == "fmpz_mod_poly_ctx(13)"

assert R1.modulus() == 11
assert R1([0,1]) == R1.gen()

# Conversion tests
F = fmpz_mod_ctx(11)
R = fmpz_mod_poly_ctx(F)

f1 = R([int(-1),int(-2),int(-3)])
f2 = R([fmpz(-1),fmpz(-2),fmpz(-3)])
f3 = R([F(-1),F(-2),F(-3)])
f4 = R(fmpz_poly([-1, -2, -3]))

assert str(f1) == "8*x^2 + 9*x + 10"
assert str(f2) == "8*x^2 + 9*x + 10"
assert str(f3) == "8*x^2 + 9*x + 10"
assert str(f4) == "8*x^2 + 9*x + 10"

f1 = R(5)
f2 = R(fmpz(6))
f3 = R(F(7))
assert str(f1) == "5"
assert str(f2) == "6"
assert str(f3) == "7"

# Printing
f = R([5, 6, 7, 8])
assert str(f) == "8*x^3 + 7*x^2 + 6*x + 5"
# assert repr(f) == "fmpz_mod_poly([5, 6, 7, 8], fmpz_mod_poly_ctx(11))"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we need to decide what this is supposed to do. I would also include a repr(f) test for the current behaviour along with a comment indicating that maybe the behaviour should be changed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I'm not really happy with even the repr(fmpz_mod(11, ctx)) output at the moment, I think it's a bit bulky and just outputting 11 would be nicer on the eyes? I'm not sure what to do.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a bit of inconsistency:

In [20]: f(2)
Out[20]: fmpz_mod(17, 163)

In [21]: f
Out[21]: 3*x^2 + 2*x + 1

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally I think that repr should show what representation you have like:

In [28]: print(str(gmpy2.mpz(2)))
2

In [29]: print(repr(gmpy2.mpz(2)))
mpz(2)

Basically that is the purpose of repr in my mind. When you want a nicer dispaly you should use print/str. The awkward thing is that some builtin types like list will always use __repr__ recursively:

In [30]: print([gmpy2.mpz(2)])
[mpz(2)]

One way to control this is just to have repr always show the pretty form but then that defeats the point of repr in general. Another way is to have printer control for example the context settings could be used. Another way is just to take control of printing in the console (this is what SymPy and Sage do).

I think it is something that should be decided on in general for python-flint and we should have a separate issue to discuss it.

For now I would just make sure that there is a test covering repr with its current behaviour along with a comment noting that the tested output is potentially not ideal.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah at the moment for the polynomial repr is the same as str but for fmpz_mod we have a more verbose repr compared to the str method. I think I prefer what str does.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I prefer what str does.

What str does is nice for the situation where it is intended: pretty printing.

What repr should do is intended for a different situation. It is very often useful to know that you have an fmpz rather than an int or that your x^2 - 1 is in F(163)[x] rather than Z[x], and is a python-flint type rather than a Sage/SymPy type etc.


# Get and Set tests
f = R([5, 6, 7, 8])
assert f[0] == 5
assert repr(f[0]) == "fmpz_mod(5, 11)"
f[0] = 7
assert repr(f[0]) == "fmpz_mod(7, 11)"
assert str(f) == "8*x^3 + 7*x^2 + 6*x + 7"

# Comparisons
f1 = R([1,2,3])
f2 = R([12,13,14])
f3 = R([4,5,6])
f4 = R([3])

assert (f1 == f2) is True
assert (f1 != f3) is True
assert (f1 != "1") is True
assert (f4 == 3) is True

f1 = R([0])
f2 = R([1])
f3 = R([0, 1])

assert f1.is_zero() is True
assert f2.is_one() is True
assert f3.is_gen() is True


all_tests = [
Expand All @@ -1834,5 +1913,6 @@ def test_fmpz_mod_dlog():
test_nmod_mat,
test_arb,
test_fmpz_mod,
test_fmpz_mod_dlog
test_fmpz_mod_dlog,
test_fmpz_mod_poly
]
10 changes: 5 additions & 5 deletions src/flint/types/fmpz_mod.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ cdef class fmpz_mod_ctx:
mod = any_as_fmpz(mod)
if mod is NotImplemented:
raise TypeError(
"Context modulus must be able to be case to an `fmpz` type"
"Context modulus must be able to be cast to an `fmpz` type"
)

# Ensure modulus is positive
Expand All @@ -67,7 +67,7 @@ cdef class fmpz_mod_ctx:
Return the modulus from the context as an fmpz
type

>>> mod_ctx = fmpz_mod_ctx(2**127 - 1)
>>> mod_ctx = fmpz_mod_poly_ctx(2**127 - 1)
GiacomoPope marked this conversation as resolved.
Show resolved Hide resolved
>>> mod_ctx.modulus()
170141183460469231731687303715884105727

Expand Down Expand Up @@ -126,11 +126,11 @@ cdef class fmpz_mod_ctx:
# If they're not the same object in memory, they may have the
# same modulus, which is good enough
if typecheck(other, fmpz_mod_ctx):
return fmpz_equal(self.val.n, (<fmpz_mod_ctx>other).val.n)
return fmpz_equal(self.val.n, (<fmpz_mod_ctx>other).val.n) == 1
return False

def __hash__(self):
return hash(self.modulus())
return hash(repr(self))
GiacomoPope marked this conversation as resolved.
Show resolved Hide resolved

def __str__(self):
return f"Context for fmpz_mod with modulus: {self.modulus()}"
Expand Down Expand Up @@ -345,7 +345,7 @@ cdef class fmpz_mod(flint_scalar):
if not typecheck(other, fmpz_mod):
other = self.ctx.any_as_fmpz_mod(other)

if typecheck(self, fmpz_mod) and typecheck(other, fmpz_mod):
if typecheck(other, fmpz_mod):
res = fmpz_equal(self.val, (<fmpz_mod>other).val) and \
(self.ctx == (<fmpz_mod>other).ctx)
if op == 2:
Expand Down
17 changes: 17 additions & 0 deletions src/flint/types/fmpz_mod_poly.pxd
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from flint.flintlib.fmpz_mod_poly cimport *

from flint.flint_base.flint_base cimport flint_poly
from flint.types.fmpz_mod cimport fmpz_mod_ctx


cdef class fmpz_mod_poly_ctx:
cdef fmpz_mod_ctx mod
cdef any_as_fmpz_mod_poly(self, obj)
cdef set_any_as_fmpz_mod_poly(self, fmpz_mod_poly_t poly, obj)
cdef set_list_as_fmpz_mod_poly(self, fmpz_mod_poly_t poly, val)

cdef class fmpz_mod_poly(flint_poly):
cdef fmpz_mod_poly_t val
cdef fmpz_mod_poly_ctx ctx
cpdef long length(self)
cpdef long degree(self)
Loading