Skip to content

Commit 1d0b792

Browse files
Merge pull request #85 from GiacomoPope/add_fmpz_mod
Clean up and include discrete logarithm functions into fmpz_mod
2 parents 7394b1d + bb25d9d commit 1d0b792

File tree

4 files changed

+337
-98
lines changed

4 files changed

+337
-98
lines changed

src/flint/flintlib/fmpz_mod.pxd

+39-8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
from flint.flintlib.flint cimport ulong, slong
2-
from flint.flintlib.fmpz cimport fmpz_t, fmpz_preinvn_struct
2+
from flint.flintlib.fmpz cimport fmpz_t, fmpz_struct, fmpz_preinvn_struct
33
from flint.flintlib.nmod cimport nmod_t
44

5-
# unimported types {'fmpz_mod_discrete_log_pohlig_hellman_t'}
6-
75
cdef extern from "flint/fmpz_mod.h":
6+
#
7+
# fmpz_mod structs, a la Pohlig - Hellman
8+
#
89
ctypedef struct fmpz_mod_ctx_struct:
910
fmpz_t n
1011
nmod_t mod
@@ -13,6 +14,36 @@ cdef extern from "flint/fmpz_mod.h":
1314
fmpz_preinvn_struct * ninv_huge
1415
ctypedef fmpz_mod_ctx_struct fmpz_mod_ctx_t[1]
1516

17+
#
18+
# discrete logs structs, a la Pohlig - Hellman
19+
#
20+
21+
ctypedef struct fmpz_mod_discrete_log_pohlig_hellman_table_entry_struct:
22+
fmpz_t gammapow
23+
ulong cm
24+
25+
ctypedef struct fmpz_mod_discrete_log_pohlig_hellman_entry_struct:
26+
slong exp
27+
ulong prime
28+
fmpz_t gamma
29+
fmpz_t gammainv
30+
fmpz_t startingbeta
31+
fmpz_t co
32+
fmpz_t startinge
33+
fmpz_t idem
34+
ulong cbound
35+
ulong dbound
36+
fmpz_mod_discrete_log_pohlig_hellman_table_entry_struct * table # length cbound */
37+
38+
ctypedef struct fmpz_mod_discrete_log_pohlig_hellman_struct:
39+
fmpz_mod_ctx_t fpctx
40+
fmpz_t pm1 # p - 1 */
41+
fmpz_t alpha # p.r. of p */
42+
fmpz_t alphainv
43+
slong num_factors # factors of p - 1
44+
fmpz_mod_discrete_log_pohlig_hellman_entry_struct * entries
45+
ctypedef fmpz_mod_discrete_log_pohlig_hellman_struct fmpz_mod_discrete_log_pohlig_hellman_t[1]
46+
1647
# Parsed from here
1748
void fmpz_mod_ctx_init(fmpz_mod_ctx_t ctx, const fmpz_t n)
1849
void fmpz_mod_ctx_clear(fmpz_mod_ctx_t ctx)
@@ -37,9 +68,9 @@ cdef extern from "flint/fmpz_mod.h":
3768
int fmpz_mod_divides(fmpz_t a, const fmpz_t b, const fmpz_t c, const fmpz_mod_ctx_t ctx)
3869
void fmpz_mod_pow_ui(fmpz_t a, const fmpz_t b, ulong e, const fmpz_mod_ctx_t ctx)
3970
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)
71+
void fmpz_mod_discrete_log_pohlig_hellman_init(fmpz_mod_discrete_log_pohlig_hellman_t L)
72+
void fmpz_mod_discrete_log_pohlig_hellman_clear(fmpz_mod_discrete_log_pohlig_hellman_t L)
73+
double fmpz_mod_discrete_log_pohlig_hellman_precompute_prime(fmpz_mod_discrete_log_pohlig_hellman_t L, const fmpz_t p)
74+
const fmpz_struct * fmpz_mod_discrete_log_pohlig_hellman_primitive_root(const fmpz_mod_discrete_log_pohlig_hellman_t L)
75+
void fmpz_mod_discrete_log_pohlig_hellman_run(fmpz_t x, const fmpz_mod_discrete_log_pohlig_hellman_t L, const fmpz_t y)
4576
int fmpz_next_smooth_prime(fmpz_t a, const fmpz_t b)

src/flint/test/test.py

+45
Original file line numberDiff line numberDiff line change
@@ -1770,6 +1770,50 @@ def test_fmpz_mod():
17701770
assert fmpz(test_y) / F_test(test_x) == (test_y * pow(test_x, -1, test_mod)) % test_mod
17711771
assert test_y / F_test(test_x) == (test_y * pow(test_x, -1, test_mod)) % test_mod
17721772

1773+
def test_fmpz_mod_dlog():
1774+
from flint import fmpz, fmpz_mod_ctx
1775+
1776+
# Input modulus must be prime
1777+
F = fmpz_mod_ctx(4)
1778+
g, a = F(1), F(2)
1779+
assert raises(lambda: g.discrete_log(a, check=True), ValueError)
1780+
1781+
# Moduli must match
1782+
F1, F2 = fmpz_mod_ctx(2), fmpz_mod_ctx(3)
1783+
g = F1(2)
1784+
a = F2(4)
1785+
assert raises(lambda: g.discrete_log(a, check=True), ValueError)
1786+
1787+
# Need to use either fmpz_mod or something which can be case to
1788+
# fmpz
1789+
assert raises(lambda: g.discrete_log("A", check=True), TypeError)
1790+
1791+
F = fmpz_mod_ctx(163)
1792+
g = F(2)
1793+
a = g**123
1794+
1795+
assert 123 == g.discrete_log(a)
1796+
1797+
a_int = pow(2, 123, 163)
1798+
a_fmpz = fmpz(a_int)
1799+
assert 123 == g.discrete_log(a_int)
1800+
assert 123 == g.discrete_log(a_fmpz)
1801+
1802+
# Randomised testing with smooth large modulus
1803+
e2, e3 = 92, 79
1804+
p = 2**e2 * 3**e3 + 1
1805+
F = fmpz_mod_ctx(p)
1806+
1807+
import random
1808+
for _ in range(10):
1809+
g = F(random.randint(0,p))
1810+
for _ in range(10):
1811+
i = random.randint(0,p)
1812+
a = g**i
1813+
x = g.discrete_log(a)
1814+
assert g**x == a
1815+
1816+
17731817

17741818
all_tests = [
17751819
test_pyflint,
@@ -1790,4 +1834,5 @@ def test_fmpz_mod():
17901834
test_nmod_mat,
17911835
test_arb,
17921836
test_fmpz_mod,
1837+
test_fmpz_mod_dlog
17931838
]

src/flint/types/fmpz_mod.pxd

+9-5
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
from flint.flint_base.flint_base cimport flint_scalar
22
from flint.flintlib.fmpz cimport fmpz_t
3-
from flint.flintlib.fmpz_mod cimport fmpz_mod_ctx_t
3+
from flint.flintlib.fmpz_mod cimport (
4+
fmpz_mod_ctx_t,
5+
fmpz_mod_discrete_log_pohlig_hellman_t
6+
)
47

58

69
cdef class fmpz_mod_ctx:
710
cdef fmpz_mod_ctx_t val
8-
11+
cdef fmpz_mod_discrete_log_pohlig_hellman_t *L
12+
cdef any_as_fmpz_mod(self, obj)
13+
cdef _precompute_dlog_prime(self)
14+
915
cdef class fmpz_mod(flint_scalar):
1016
cdef fmpz_mod_ctx ctx
1117
cdef fmpz_t val
12-
13-
cdef any_as_fmpz_mod(self, obj)
14-
18+
cdef fmpz_t *x_g

0 commit comments

Comments
 (0)