Skip to content

Commit 93570df

Browse files
committed
fix(fmpz_mod): avoid using malloc/free
1 parent e6c0078 commit 93570df

File tree

2 files changed

+27
-44
lines changed

2 files changed

+27
-44
lines changed

src/flint/types/fmpz_mod.pxd

+5-3
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@ from flint.flintlib.fmpz_mod cimport (
88
cdef class fmpz_mod_ctx:
99
cdef fmpz_mod_ctx_t val
1010
cdef bint _is_prime
11-
cdef fmpz_mod_discrete_log_pohlig_hellman_t *L
11+
cdef bint _init_L
12+
cdef fmpz_mod_discrete_log_pohlig_hellman_t L
13+
1214
cdef set_any_as_fmpz_mod(self, fmpz_t val, obj)
1315
cdef any_as_fmpz_mod(self, obj)
14-
cdef _precompute_dlog_prime(self)
16+
cdef discrete_log_pohlig_hellman_run(self, fmpz_t x, fmpz_t y)
1517

1618
cdef class fmpz_mod(flint_scalar):
1719
cdef fmpz_mod_ctx ctx
1820
cdef fmpz_t val
19-
cdef fmpz_t *x_g
21+
cdef fmpz_t x_g

src/flint/types/fmpz_mod.pyx

+22-41
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ from flint.flintlib.fmpz cimport(
1313
fmpz_divexact,
1414
fmpz_gcd,
1515
fmpz_is_one,
16+
fmpz_is_zero,
1617
fmpz_randm
1718
)
1819
from flint.flintlib.fmpz cimport fmpz_mod as fmpz_type_mod
@@ -41,14 +42,12 @@ cdef class fmpz_mod_ctx:
4142
cdef fmpz one = fmpz.__new__(fmpz)
4243
fmpz_one(one.val)
4344
fmpz_mod_ctx_init(self.val, one.val)
44-
self.L = NULL
45+
fmpz_mod_discrete_log_pohlig_hellman_clear(self.L)
4546
self._is_prime = 0
46-
4747

4848
def __dealloc__(self):
4949
fmpz_mod_ctx_clear(self.val)
50-
if self.L:
51-
fmpz_mod_discrete_log_pohlig_hellman_clear(self.L[0])
50+
fmpz_mod_discrete_log_pohlig_hellman_clear(self.L)
5251

5352
def __init__(self, mod):
5453
# Ensure modulus is fmpz type
@@ -137,18 +136,15 @@ cdef class fmpz_mod_ctx:
137136

138137
return res
139138

140-
cdef _precompute_dlog_prime(self):
141-
"""
142-
Initalise the dlog data, all discrete logs are solved with an
143-
internally chosen base `y`
144-
"""
145-
self.L = <fmpz_mod_discrete_log_pohlig_hellman_t *>libc.stdlib.malloc(
146-
cython.sizeof(fmpz_mod_discrete_log_pohlig_hellman_struct)
147-
)
148-
fmpz_mod_discrete_log_pohlig_hellman_init(self.L[0])
149-
fmpz_mod_discrete_log_pohlig_hellman_precompute_prime(
150-
self.L[0], self.val.n
151-
)
139+
cdef discrete_log_pohlig_hellman_run(self, fmpz_t x, fmpz_t y):
140+
# First, Ensure that L has performed precomputations This generates a
141+
# base which is a primative root, and used as the base in
142+
# fmpz_mod_discrete_log_pohlig_hellman_run
143+
if not self._init_L:
144+
fmpz_mod_discrete_log_pohlig_hellman_precompute_prime(self.L, self.val.n)
145+
self._init_L = True
146+
147+
fmpz_mod_discrete_log_pohlig_hellman_run(x, self.L, y)
152148

153149
cdef set_any_as_fmpz_mod(self, fmpz_t val, obj):
154150
# Try and convert obj to fmpz
@@ -235,13 +231,11 @@ cdef class fmpz_mod(flint_scalar):
235231

236232
def __cinit__(self):
237233
fmpz_init(self.val)
238-
self.x_g = NULL
234+
fmpz_init(self.x_g)
239235

240236
def __dealloc__(self):
241237
fmpz_clear(self.val)
242-
if self.x_g:
243-
fmpz_clear(self.x_g[0])
244-
libc.stdlib.free(self.x_g)
238+
fmpz_clear(self.x_g)
245239

246240
def __init__(self, val, ctx):
247241
if not typecheck(ctx, fmpz_mod_ctx):
@@ -354,33 +348,20 @@ cdef class fmpz_mod(flint_scalar):
354348
if a is NotImplemented:
355349
raise TypeError(f"Cannot solve the discrete log with {type(a)} as input")
356350

357-
# First, Ensure that self.ctx.L has performed precomputations
358-
# This generates a `y` which is a primative root, and used as
359-
# the base in `fmpz_mod_discrete_log_pohlig_hellman_run`
360-
if not self.ctx.L:
361-
self.ctx._precompute_dlog_prime()
362-
363351
# Solve the discrete log for the chosen base and target
364352
# g = y^x_g and a = y^x_a
365353
# We want to find x such that a = g^x =>
366354
# (y^x_a) = (y^x_g)^x => x = (x_a / x_g) mod (p-1)
367355

368356
# For repeated calls to discrete_log, it's more efficient to
369357
# store x_g rather than keep computing it
370-
if not self.x_g:
371-
self.x_g = <fmpz_t *>libc.stdlib.malloc(
372-
cython.sizeof(fmpz_t)
373-
)
374-
fmpz_mod_discrete_log_pohlig_hellman_run(
375-
self.x_g[0], self.ctx.L[0], self.val
376-
)
358+
if fmpz_is_zero(self.x_g):
359+
self.ctx.discrete_log_pohlig_hellman_run(self.x_g, self.val)
377360

378361
# Then we need to compute x_a which will be different for each call
379362
cdef fmpz_t x_a
380363
fmpz_init(x_a)
381-
fmpz_mod_discrete_log_pohlig_hellman_run(
382-
x_a, self.ctx.L[0], (<fmpz_mod>a).val
383-
)
364+
self.ctx.discrete_log_pohlig_hellman_run(x_a, (<fmpz_mod>a).val)
384365

385366
# If g is not a primative root, then x_g and pm1 will share
386367
# a common factor. We can use this to compute the order of
@@ -390,14 +371,14 @@ cdef class fmpz_mod(flint_scalar):
390371
fmpz_init(g_order)
391372
fmpz_init(x_g)
392373

393-
fmpz_gcd(g, self.x_g[0], self.ctx.L[0].pm1)
374+
fmpz_gcd(g, self.x_g, self.ctx.L.pm1)
394375
if not fmpz_is_one(g):
395-
fmpz_divexact(x_g, self.x_g[0], g)
376+
fmpz_divexact(x_g, self.x_g, g)
396377
fmpz_divexact(x_a, x_a, g)
397-
fmpz_divexact(g_order, self.ctx.L[0].pm1, g)
378+
fmpz_divexact(g_order, self.ctx.L.pm1, g)
398379
else:
399-
fmpz_set(g_order, self.ctx.L[0].pm1)
400-
fmpz_set(x_g, self.x_g[0])
380+
fmpz_set(g_order, self.ctx.L.pm1)
381+
fmpz_set(x_g, self.x_g)
401382

402383
# Finally, compute output exponent by computing
403384
# (x_a / x_g) mod g_order

0 commit comments

Comments
 (0)