@@ -13,6 +13,7 @@ from flint.flintlib.fmpz cimport(
13
13
fmpz_divexact,
14
14
fmpz_gcd,
15
15
fmpz_is_one,
16
+ fmpz_is_zero,
16
17
fmpz_randm
17
18
)
18
19
from flint.flintlib.fmpz cimport fmpz_mod as fmpz_type_mod
@@ -41,14 +42,12 @@ cdef class fmpz_mod_ctx:
41
42
cdef fmpz one = fmpz.__new__ (fmpz)
42
43
fmpz_one(one.val)
43
44
fmpz_mod_ctx_init(self .val, one.val)
44
- self .L = NULL
45
+ fmpz_mod_discrete_log_pohlig_hellman_clear( self .L)
45
46
self ._is_prime = 0
46
-
47
47
48
48
def __dealloc__ (self ):
49
49
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)
52
51
53
52
def __init__ (self , mod ):
54
53
# Ensure modulus is fmpz type
@@ -137,18 +136,15 @@ cdef class fmpz_mod_ctx:
137
136
138
137
return res
139
138
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)
152
148
153
149
cdef set_any_as_fmpz_mod(self , fmpz_t val, obj):
154
150
# Try and convert obj to fmpz
@@ -235,13 +231,11 @@ cdef class fmpz_mod(flint_scalar):
235
231
236
232
def __cinit__ (self ):
237
233
fmpz_init(self .val)
238
- self .x_g = NULL
234
+ fmpz_init( self .x_g)
239
235
240
236
def __dealloc__ (self ):
241
237
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)
245
239
246
240
def __init__ (self , val , ctx ):
247
241
if not typecheck(ctx, fmpz_mod_ctx):
@@ -354,33 +348,20 @@ cdef class fmpz_mod(flint_scalar):
354
348
if a is NotImplemented :
355
349
raise TypeError (f" Cannot solve the discrete log with {type(a)} as input" )
356
350
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
-
363
351
# Solve the discrete log for the chosen base and target
364
352
# g = y^x_g and a = y^x_a
365
353
# We want to find x such that a = g^x =>
366
354
# (y^x_a) = (y^x_g)^x => x = (x_a / x_g) mod (p-1)
367
355
368
356
# For repeated calls to discrete_log, it's more efficient to
369
357
# 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)
377
360
378
361
# Then we need to compute x_a which will be different for each call
379
362
cdef fmpz_t x_a
380
363
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)
384
365
385
366
# If g is not a primative root, then x_g and pm1 will share
386
367
# a common factor. We can use this to compute the order of
@@ -390,14 +371,14 @@ cdef class fmpz_mod(flint_scalar):
390
371
fmpz_init(g_order)
391
372
fmpz_init(x_g)
392
373
393
- fmpz_gcd(g, self .x_g[ 0 ] , self .ctx.L[ 0 ] .pm1)
374
+ fmpz_gcd(g, self .x_g, self .ctx.L.pm1)
394
375
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)
396
377
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)
398
379
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)
401
382
402
383
# Finally, compute output exponent by computing
403
384
# (x_a / x_g) mod g_order
0 commit comments