Skip to content

Commit d92524d

Browse files
committed
fmpz_poly / fmpz now uses exact division
Previously an error would be raised instead.
1 parent c6ea352 commit d92524d

File tree

2 files changed

+50
-3
lines changed

2 files changed

+50
-3
lines changed

src/flint/test/test.py

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2319,6 +2319,33 @@ def test_division_scalar():
23192319
assert raises(lambda: "AAA" / R(5), TypeError)
23202320

23212321

2322+
def test_division_poly():
2323+
Z = flint.fmpz
2324+
Q = flint.fmpq
2325+
F17 = lambda x: flint.nmod(x, 17)
2326+
ctx = flint.fmpz_mod_ctx(163)
2327+
F163 = lambda a: flint.fmpz_mod(a, ctx)
2328+
PZ = lambda x: flint.fmpz_poly(x)
2329+
PQ = lambda x: flint.fmpq_poly(x)
2330+
PF17 = lambda x: flint.nmod_poly(x, 17)
2331+
PF163 = lambda x: flint.fmpz_mod_poly(x, flint.fmpz_mod_poly_ctx(163))
2332+
# fmpz exact scalar division
2333+
assert PZ([2, 4]) / Z(2) == PZ([1, 2])
2334+
assert PZ([2, 4]) / 2 == PZ([1, 2])
2335+
assert raises(lambda: PZ([2, 5]) / Z(2), DomainError)
2336+
assert raises(lambda: PZ([2, 5]) / 2, DomainError)
2337+
# field division by scalar
2338+
for (K, PK) in [(Q, PQ), (F17, PF17), (F163, PF163)]:
2339+
assert PK([2, 5]) / K(2) == PK([K(2)/K(2), K(5)/K(2)])
2340+
assert PK([2, 5]) / 2 == PK([K(2)/K(2), K(5)/K(2)])
2341+
# No other scalar division is allowed
2342+
for (R, PR) in [(Z, PZ), (Q, PQ), (F17, PF17), (F163, PF163)]:
2343+
assert raises(lambda: R(2) / PR([2, 5]), TypeError)
2344+
assert raises(lambda: 2 / PR([2, 5]), TypeError)
2345+
assert raises(lambda: PR([2, 5]) / 0, ZeroDivisionError)
2346+
assert raises(lambda: PR([2, 5]) / R(0), ZeroDivisionError)
2347+
2348+
23222349
def test_division_matrix():
23232350
Z = flint.fmpz
23242351
Q = flint.fmpq
@@ -2517,12 +2544,14 @@ def setbad(obj, i, val):
25172544
assert raises(lambda: P([1, 2, 1]) % P([0]), ZeroDivisionError)
25182545
assert raises(lambda: divmod(P([1, 2, 1]), P([0])), ZeroDivisionError)
25192546

2547+
# Exact/field scalar division
25202548
if is_field:
25212549
assert P([2, 2]) / 2 == P([1, 1])
25222550
assert P([1, 2]) / 2 == P([S(1)/2, 1])
2523-
assert raises(lambda: P([1, 2]) / 0, ZeroDivisionError)
25242551
else:
2525-
assert raises(lambda: P([2, 2]) / 2, TypeError)
2552+
assert P([2, 2]) / 2 == P([1, 1])
2553+
assert raises(lambda: P([1, 2]) / 2, DomainError)
2554+
assert raises(lambda: P([1, 2]) / 0, ZeroDivisionError)
25262555

25272556
assert raises(lambda: 1 / P([1, 1]), TypeError)
25282557
assert raises(lambda: P([1, 2, 1]) / P([1, 1]), TypeError)
@@ -3105,6 +3134,7 @@ def test_all_tests():
31053134
test_fmpz_mod_mat,
31063135

31073136
test_division_scalar,
3137+
test_division_poly,
31083138
test_division_matrix,
31093139

31103140
test_polys,

src/flint/types/fmpz_poly.pyx

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ from flint.types.arb cimport arb
1919
from flint.types.acb cimport any_as_acb_or_notimplemented
2020
cimport libc.stdlib
2121
from flint.flintlib.fmpz cimport fmpz_init, fmpz_clear, fmpz_set
22-
from flint.flintlib.fmpz cimport fmpz_is_one, fmpz_equal_si, fmpz_equal
22+
from flint.flintlib.fmpz cimport fmpz_is_zero, fmpz_is_one, fmpz_equal_si, fmpz_equal
2323
from flint.flintlib.acb_modular cimport *
2424
from flint.flintlib.ulong_extras cimport n_is_prime
2525
from flint.flintlib.fmpz_poly cimport *
@@ -29,6 +29,9 @@ from flint.flintlib.acb cimport *
2929
from flint.flintlib.arb_poly cimport *
3030
from flint.flintlib.arb_fmpz_poly cimport *
3131

32+
from flint.utils.flint_exceptions import DomainError
33+
34+
3235
cdef any_as_fmpz_poly(x):
3336
cdef fmpz_poly res
3437
if typecheck(x, fmpz_poly):
@@ -227,6 +230,20 @@ cdef class fmpz_poly(flint_poly):
227230
def __rmul__(self, other):
228231
return self._mul_(other)
229232

233+
def __truediv__(fmpz_poly self, other):
234+
cdef fmpz_poly res
235+
other = any_as_fmpz(other)
236+
if other is NotImplemented:
237+
return other
238+
if fmpz_is_zero((<fmpz>other).val):
239+
raise ZeroDivisionError("fmpz_poly division by 0")
240+
res = fmpz_poly.__new__(fmpz_poly)
241+
fmpz_poly_scalar_divexact_fmpz(res.val, self.val, (<fmpz>other).val)
242+
# Check division is exact - there should be a better way to do this
243+
if res * other != self:
244+
raise DomainError("fmpz_poly division is not exact")
245+
return res
246+
230247
def _floordiv_(self, other):
231248
cdef fmpz_poly res
232249
if fmpz_poly_is_zero((<fmpz_poly>other).val):

0 commit comments

Comments
 (0)