Skip to content

Commit 7394b1d

Browse files
Merge pull request #83 from GiacomoPope/add_fmpz_mod
Add fmpz mod
2 parents 11bb708 + 5dead0c commit 7394b1d

File tree

13 files changed

+635
-9
lines changed

13 files changed

+635
-9
lines changed

doc/source/fmpz_mod.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
**fmpz_mod** -- integers mod n
2+
===============================================================================
3+
4+
.. autoclass :: flint.fmpz_mod_ctx
5+
:members:
6+
:inherited-members:
7+
:undoc-members:
8+
9+
.. autoclass :: flint.fmpz_mod
10+
:members:
11+
:inherited-members:
12+
:undoc-members:
13+

doc/source/general.rst

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,6 @@ determined from the available data.
161161
The following convenience functions are provided for numerical evaluation
162162
with adaptive working precision.
163163

164-
.. autofunction :: flint.good
165-
166164
.. autofunction :: flint.showgood
167165
168166
Power series

doc/source/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ Scalar types
4343

4444
fmpz.rst
4545
fmpq.rst
46+
fmpz_mod.rst
4647
nmod.rst
4748
arb.rst
4849
acb.rst

doc/source/nmod.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
**nmod** -- integers mod n
1+
**nmod** -- integers mod wordsize n
22
===============================================================================
33

44
.. autoclass :: flint.nmod

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
("flint.types.acb_mat", ["src/flint/types/acb_mat.pyx"]),
9595
("flint.types.acb_series", ["src/flint/types/acb_series.pyx"]),
9696
("flint.types.fmpz_mpoly", ["src/flint/types/fmpz_mpoly.pyx"]),
97+
("flint.types.fmpz_mod", ["src/flint/types/fmpz_mod.pyx"]),
9798
("flint.types.dirichlet", ["src/flint/types/dirichlet.pyx"]),
9899
("flint.flint_base.flint_base", ["src/flint/flint_base/flint_base.pyx"]),
99100
("flint.flint_base.flint_context", ["src/flint/flint_base/flint_context.pyx"]),

src/flint/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
from .types.acb_mat import *
2222
from .types.acb_series import *
2323
from .types.fmpz_mpoly import *
24+
from .types.fmpz_mod import *
25+
from .types.dirichlet import *
2426
from .functions.showgood import showgood
2527

2628
__version__ = '0.4.4'

src/flint/flintlib/fmpz.pxd

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
from flint.flintlib.flint cimport fmpz_struct, ulong, mp_limb_t
1+
from flint.flintlib.flint cimport fmpz_struct, ulong, mp_limb_t, mp_ptr
22
from flint.flintlib.flint cimport mp_size_t, mp_bitcnt_t, slong, flint_rand_t, flint_bitcnt_t
3-
# from flint.flintlib.nmod cimport nmod_t
4-
# from flint.flintlib.fmpz_factor cimport fmpz_factor_t
53

64
cdef extern from "flint/fmpz.h":
75
ctypedef fmpz_struct fmpz_t[1]
86

7+
ctypedef struct fmpz_preinvn_struct:
8+
mp_ptr dinv
9+
slong n
10+
flint_bitcnt_t norm
11+
ctypedef fmpz_preinvn_struct fmpz_preinvn_t[1]
912

1013
# from here on is parsed
1114
# fmpz_struct PTR_TO_COEFF(__mpz_struct * ptr)

src/flint/flintlib/fmpz_mod.pxd

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
from flint.flintlib.flint cimport ulong, slong
2+
from flint.flintlib.fmpz cimport fmpz_t, fmpz_preinvn_struct
3+
from flint.flintlib.nmod cimport nmod_t
4+
5+
# unimported types {'fmpz_mod_discrete_log_pohlig_hellman_t'}
6+
7+
cdef extern from "flint/fmpz_mod.h":
8+
ctypedef struct fmpz_mod_ctx_struct:
9+
fmpz_t n
10+
nmod_t mod
11+
ulong n_limbs[3]
12+
ulong ninv_limbs[3]
13+
fmpz_preinvn_struct * ninv_huge
14+
ctypedef fmpz_mod_ctx_struct fmpz_mod_ctx_t[1]
15+
16+
# Parsed from here
17+
void fmpz_mod_ctx_init(fmpz_mod_ctx_t ctx, const fmpz_t n)
18+
void fmpz_mod_ctx_clear(fmpz_mod_ctx_t ctx)
19+
void fmpz_mod_ctx_set_modulus(fmpz_mod_ctx_t ctx, const fmpz_t n)
20+
void fmpz_mod_set_fmpz(fmpz_t a, const fmpz_t b, const fmpz_mod_ctx_t ctx)
21+
int fmpz_mod_is_canonical(const fmpz_t a, const fmpz_mod_ctx_t ctx)
22+
int fmpz_mod_is_one(const fmpz_t a, const fmpz_mod_ctx_t ctx)
23+
void fmpz_mod_add(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx)
24+
void fmpz_mod_add_fmpz(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx)
25+
void fmpz_mod_add_ui(fmpz_t a, const fmpz_t b, ulong c, const fmpz_mod_ctx_t ctx)
26+
void fmpz_mod_add_si(fmpz_t a, const fmpz_t b, slong c, const fmpz_mod_ctx_t ctx)
27+
void fmpz_mod_sub(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx)
28+
void fmpz_mod_sub_fmpz(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx)
29+
void fmpz_mod_sub_ui(fmpz_t a, const fmpz_t b, ulong c, const fmpz_mod_ctx_t ctx)
30+
void fmpz_mod_sub_si(fmpz_t a, const fmpz_t b, slong c, const fmpz_mod_ctx_t ctx)
31+
void fmpz_mod_fmpz_sub(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx)
32+
void fmpz_mod_ui_sub(fmpz_t a, ulong b, const fmpz_t c, const fmpz_mod_ctx_t ctx)
33+
void fmpz_mod_si_sub(fmpz_t a, slong b, const fmpz_t c, const fmpz_mod_ctx_t ctx)
34+
void fmpz_mod_neg(fmpz_t a, const fmpz_t b, const fmpz_mod_ctx_t ctx)
35+
void fmpz_mod_mul(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx)
36+
void fmpz_mod_inv(fmpz_t a, const fmpz_t b, const fmpz_mod_ctx_t ctx)
37+
int fmpz_mod_divides(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx)
38+
void fmpz_mod_pow_ui(fmpz_t a, const fmpz_t b, ulong e, const fmpz_mod_ctx_t ctx)
39+
int fmpz_mod_pow_fmpz(fmpz_t a, const fmpz_t b, const fmpz_t e, const fmpz_mod_ctx_t ctx)
40+
# void fmpz_mod_discrete_log_pohlig_hellman_init(fmpz_mod_discrete_log_pohlig_hellman_t L)
41+
# void fmpz_mod_discrete_log_pohlig_hellman_clear(fmpz_mod_discrete_log_pohlig_hellman_t L)
42+
# double fmpz_mod_discrete_log_pohlig_hellman_precompute_prime(fmpz_mod_discrete_log_pohlig_hellman_t L, const fmpz_t p)
43+
# const fmpz_struct * fmpz_mod_discrete_log_pohlig_hellman_primitive_root(const fmpz_mod_discrete_log_pohlig_hellman_t L)
44+
# void fmpz_mod_discrete_log_pohlig_hellman_run(fmpz_t x, const fmpz_mod_discrete_log_pohlig_hellman_t L, const fmpz_t y)
45+
int fmpz_next_smooth_prime(fmpz_t a, const fmpz_t b)

src/flint/test/test.py

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,6 +1584,192 @@ def test_pickling():
15841584
obj2 = pickle.loads(s)
15851585
assert obj == obj2
15861586

1587+
def test_fmpz_mod():
1588+
from flint import fmpz_mod_ctx, fmpz, fmpz_mod
1589+
1590+
p_sml = 163
1591+
p_med = 2**127 - 1
1592+
p_big = 2**255 - 19
1593+
1594+
F_sml = fmpz_mod_ctx(p_sml)
1595+
F_med = fmpz_mod_ctx(p_med)
1596+
F_big = fmpz_mod_ctx(p_big)
1597+
1598+
# Context tests
1599+
assert raises(lambda: fmpz_mod_ctx("AAA"), TypeError)
1600+
assert raises(lambda: fmpz_mod_ctx(-1), ValueError)
1601+
assert F_sml.modulus() == p_sml
1602+
assert F_med.modulus() == p_med
1603+
assert F_big.modulus() == p_big
1604+
1605+
F_big_copy = fmpz_mod_ctx(p_big)
1606+
assert F_big_copy == F_big
1607+
assert F_big != F_sml
1608+
assert hash(F_big_copy) == hash(F_big)
1609+
assert hash(F_big) != hash(F_sml)
1610+
assert F_big_copy != F_sml
1611+
assert F_big_copy != "A"
1612+
1613+
assert repr(F_sml) == "fmpz_mod_ctx(163)"
1614+
assert str(F_sml) == "Context for fmpz_mod with modulus: 163"
1615+
1616+
# Type tests
1617+
assert raises(lambda: fmpz_mod(1, "AAA"), TypeError)
1618+
1619+
# Test for small, medium and large char.
1620+
for F_test in [F_sml, F_med, F_big]:
1621+
test_mod = int(F_test.modulus())
1622+
test_x = (-123) % test_mod # canonical value
1623+
test_y = ((-456) % test_mod)**2 # non-canoncial value
1624+
1625+
F_test_copy = fmpz_mod_ctx(test_mod)
1626+
F_other = fmpz_mod_ctx(11)
1627+
1628+
assert raises(lambda: F_test(test_x) > 0, TypeError)
1629+
assert raises(lambda: F_test(test_x) >= 0, TypeError)
1630+
assert raises(lambda: F_test(test_x) < 0, TypeError)
1631+
assert raises(lambda: F_test(test_x) <= 0, TypeError)
1632+
1633+
assert (test_x == F_test(test_x)) is True, f"{test_x}, {F_test(test_x)}"
1634+
assert (124 != F_test(test_x)) is True
1635+
assert (F_test(test_x) == test_x) is True
1636+
assert (F_test(test_x) == test_x + test_mod) is True
1637+
assert (F_test(test_x) == 1) is False
1638+
assert (F_test(test_x) != 1) is True
1639+
assert (F_test(test_x) == F_test(test_x)) is True
1640+
assert (F_test(test_x) == F_test(test_x + test_mod)) is True
1641+
assert (F_test(test_x) == F_test(1)) is False
1642+
assert (F_test(test_x) != F_test(1)) is True
1643+
1644+
assert (hash(F_test(test_x)) == hash(test_x)) is True
1645+
assert (hash(F_test(F_test(test_x))) == hash(test_x)) is True
1646+
assert (hash(F_test(test_x)) == hash(1)) is False
1647+
assert (hash(F_test(test_x)) != hash(1)) is True
1648+
assert (hash(F_test(test_x)) == hash(F_test(test_x))) is True
1649+
assert (hash(F_test(test_x)) == hash(F_test(test_x + test_mod))) is True
1650+
assert (hash(F_test(test_x)) == hash(F_test(1))) is False
1651+
assert (hash(F_test(test_x)) != hash(F_test(1))) is True
1652+
1653+
# Is one, zero
1654+
assert (F_test(0) == 0) is True
1655+
assert F_test(0).is_zero() is True
1656+
assert not F_test(0)
1657+
assert not F_test(test_mod)
1658+
assert F_test(1).is_one() is True
1659+
assert F_test(test_mod + 1).is_one() is True
1660+
assert F_test(1).is_one() is True
1661+
assert F_test(2).is_one() is False
1662+
1663+
# int, str, repr
1664+
assert str(F_test(11)) == "11"
1665+
assert str(F_test(-1)) == str(test_mod - 1)
1666+
assert repr(F_test(11)) == f"fmpz_mod(11, {test_mod})"
1667+
assert repr(F_test(-1)) == f"fmpz_mod({test_mod - 1}, {test_mod})"
1668+
1669+
assert +F_test(5) == F_test(5)
1670+
1671+
# Arithmetic tests
1672+
1673+
# Negation
1674+
assert -F_test(test_x) == F_test(-test_x) == (-test_x % test_mod)
1675+
assert -F_test(1) == F_test(-1) == F_test(test_mod - 1)
1676+
1677+
# Addition
1678+
assert F_test(test_x) + F_test(test_y) == F_test(test_x + test_y)
1679+
assert F_test(test_x) + F_test_copy(test_y) == F_test(test_x + test_y)
1680+
assert F_test(test_x) + F_test(test_y) == F_test_copy(test_x + test_y)
1681+
assert raises(lambda: F_test(test_x) + "AAA", TypeError)
1682+
1683+
assert F_test(test_x) + F_test(test_y) == F_test(test_y) + F_test(test_x)
1684+
assert F_test(test_x) + test_y == F_test(test_x + test_y)
1685+
assert test_y + F_test(test_x) == F_test(test_x + test_y)
1686+
assert F_test(test_x) + fmpz(test_y) == F_test(test_y) + F_test(test_x)
1687+
assert raises(lambda: F_test(test_x) + F_other(test_y), ValueError)
1688+
1689+
# Subtraction
1690+
1691+
assert F_test(test_x) - F_test(test_y) == F_test(test_x - test_y)
1692+
assert F_test(test_x) - test_y == F_test(test_x - test_y)
1693+
assert F_test(test_x) - test_y == F_test(test_x) - F_test(test_y)
1694+
assert F_test(test_y) - test_x == F_test(test_y) - F_test(test_x)
1695+
assert test_x - F_test(test_y) == F_test(test_x) - F_test(test_y)
1696+
assert test_y - F_test(test_x) == F_test(test_y) - F_test(test_x)
1697+
assert F_test(test_x) - fmpz(test_y) == F_test(test_x) - F_test(test_y)
1698+
assert raises(lambda: F_test(test_x) - F_other(test_y), ValueError)
1699+
assert raises(lambda: F_test(test_x) - "AAA", TypeError)
1700+
1701+
# Multiplication
1702+
1703+
assert F_test(test_x) * F_test(test_y) == (test_x * test_y) % test_mod
1704+
assert F_test(test_x) * test_y == (test_x * test_y) % test_mod
1705+
assert test_y * F_test(test_x) == (test_x * test_y) % test_mod
1706+
1707+
assert F_test(1) * F_test(test_x) == F_test(1 * test_x)
1708+
assert F_test(2) * F_test(test_x) == F_test(2 * test_x)
1709+
assert F_test(3) * F_test(test_x) == F_test(3 * test_x)
1710+
assert 1 * F_test(test_x) == F_test(1 * test_x)
1711+
assert 2 * F_test(test_x) == F_test(2 * test_x)
1712+
assert 3 * F_test(test_x) == F_test(3 * test_x)
1713+
assert F_test(test_x) * 1 == F_test(1 * test_x)
1714+
assert F_test(test_x) * 2 == F_test(2 * test_x)
1715+
assert F_test(test_x) * 3 == F_test(3 * test_x)
1716+
assert fmpz(1) * F_test(test_x) == F_test(1 * test_x)
1717+
assert fmpz(2) * F_test(test_x) == F_test(2 * test_x)
1718+
assert fmpz(3) * F_test(test_x) == F_test(3 * test_x)
1719+
assert raises(lambda: F_test(test_x) * "AAA", TypeError)
1720+
assert raises(lambda: F_test(test_x) * F_other(test_x), ValueError)
1721+
1722+
# Exponentiation
1723+
1724+
assert F_test(0)**0 == pow(0, 0, test_mod)
1725+
assert F_test(0)**1 == pow(0, 1, test_mod)
1726+
assert F_test(0)**2 == pow(0, 2, test_mod)
1727+
assert raises(lambda: F_test(0)**(-1), ZeroDivisionError)
1728+
assert raises(lambda: F_test(0)**("AA"), NotImplementedError)
1729+
1730+
assert F_test(test_x)**fmpz(0) == pow(test_x, 0, test_mod)
1731+
assert F_test(test_x)**fmpz(1) == pow(test_x, 1, test_mod)
1732+
assert F_test(test_x)**fmpz(2) == pow(test_x, 2, test_mod)
1733+
assert F_test(test_x)**fmpz(3) == pow(test_x, 3, test_mod)
1734+
1735+
assert F_test(test_x)**0 == pow(test_x, 0, test_mod)
1736+
assert F_test(test_x)**1 == pow(test_x, 1, test_mod)
1737+
assert F_test(test_x)**2 == pow(test_x, 2, test_mod)
1738+
assert F_test(test_x)**3 == pow(test_x, 3, test_mod)
1739+
assert F_test(test_x)**100 == pow(test_x, 100, test_mod)
1740+
1741+
assert F_test(test_x)**(-1) == pow(test_x, -1, test_mod)
1742+
assert F_test(test_x)**(-2) == pow(test_x, -2, test_mod)
1743+
assert F_test(test_x)**(-3) == pow(test_x, -3, test_mod)
1744+
assert F_test(test_x)**(-4) == pow(test_x, -4, test_mod)
1745+
1746+
# Inversion
1747+
1748+
assert raises(lambda: ~F_test(0), ZeroDivisionError)
1749+
assert ~F_test(test_x) == pow(test_x, -1, test_mod)
1750+
assert ~F_test(1) == pow(1, -1, test_mod)
1751+
assert ~F_test(2) == pow(2, -1, test_mod), f"Broken!! {~F_test(2)}, {pow(2, -1, test_mod)}"
1752+
1753+
assert F_test(1).inverse(check=False) == pow(1, -1, test_mod)
1754+
assert F_test(2).inverse(check=False) == pow(2, -1, test_mod)
1755+
assert F_test(test_x).inverse(check=False) == pow(test_x, -1, test_mod)
1756+
1757+
# Division
1758+
assert raises(lambda: F_test(1) / F_test(0), ZeroDivisionError)
1759+
assert F_test(test_x) / F_test(test_y) == (test_x * pow(test_y, -1, test_mod)) % test_mod
1760+
assert F_test(test_x) / fmpz(test_y) == (test_x * pow(test_y, -1, test_mod)) % test_mod
1761+
assert F_test(test_x) / test_y == (test_x * pow(test_y, -1, test_mod)) % test_mod
1762+
assert raises(lambda: F_test(test_x) / "AAA", TypeError)
1763+
assert raises(lambda: "AAA" / F_test(test_x), TypeError)
1764+
assert raises(lambda: F_other(test_x) / F_test(test_x), ValueError)
1765+
assert raises(lambda: F_test(test_x) // F_test(test_x), TypeError)
1766+
assert 1 / F_test(2) == pow(2, -1, test_mod)
1767+
assert 1 / F_test(test_x) == pow(test_x, -1, test_mod)
1768+
assert 1 / F_test(test_y) == pow(test_y, -1, test_mod)
1769+
1770+
assert fmpz(test_y) / F_test(test_x) == (test_y * pow(test_x, -1, test_mod)) % test_mod
1771+
assert test_y / F_test(test_x) == (test_y * pow(test_x, -1, test_mod)) % test_mod
1772+
15871773

15881774
all_tests = [
15891775
test_pyflint,
@@ -1603,4 +1789,5 @@ def test_pickling():
16031789
test_nmod_poly,
16041790
test_nmod_mat,
16051791
test_arb,
1792+
test_fmpz_mod,
16061793
]

src/flint/types/fmpz.pxd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ from flint.flintlib.fmpz cimport fmpz_t, fmpz_set_str, fmpz_set_si
1010
from cpython.version cimport PY_MAJOR_VERSION
1111

1212
cdef int fmpz_set_any_ref(fmpz_t x, obj)
13+
cdef fmpz_get_intlong(fmpz_t x)
1314

1415
cdef inline int fmpz_set_pylong(fmpz_t x, obj):
1516
cdef int overflow

src/flint/types/fmpz_mod.pxd

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from flint.flint_base.flint_base cimport flint_scalar
2+
from flint.flintlib.fmpz cimport fmpz_t
3+
from flint.flintlib.fmpz_mod cimport fmpz_mod_ctx_t
4+
5+
6+
cdef class fmpz_mod_ctx:
7+
cdef fmpz_mod_ctx_t val
8+
9+
cdef class fmpz_mod(flint_scalar):
10+
cdef fmpz_mod_ctx ctx
11+
cdef fmpz_t val
12+
13+
cdef any_as_fmpz_mod(self, obj)
14+

0 commit comments

Comments
 (0)