Skip to content

Commit b11af6b

Browse files
committed
fix(fq_default): store variable name as str
Fixes flintlibgh-325 Previously, the variable name was stored as a char* pointing to the buffer for a bytes object that might be deallocated.
1 parent cddbf41 commit b11af6b

File tree

3 files changed

+25
-28
lines changed

3 files changed

+25
-28
lines changed

src/flint/test/test_all.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4720,9 +4720,6 @@ def test_fq_default():
47204720
assert raises(lambda: flint.fq_default_ctx(5, fq_type=-1), ValueError)
47214721
assert raises(lambda: flint.fq_default_ctx("ABC"), TypeError) # type: ignore
47224722

4723-
# var must be one character
4724-
assert raises(lambda: flint.fq_default_ctx(5, var="XXX"), ValueError)
4725-
47264723
# p must be set if modulus has no characteristic / modulus
47274724
assert raises(lambda: flint.fq_default_ctx(modulus=[0,1,0]), ValueError)
47284725

@@ -4777,7 +4774,7 @@ def test_fq_default():
47774774
assert str(gf_5) == "Context for fq_default in GF(5)"
47784775
assert str(gf_5_2) == "Context for fq_default in GF(5^2)[z]/(z^2 + 4*z + 2)"
47794776

4780-
assert repr(gf_5) == "fq_default_ctx(5, var='z' type='NMOD')"
4777+
assert repr(gf_5) == "fq_default_ctx(5, var='z', type='NMOD')"
47814778
assert repr(gf_5_2) == "fq_default_ctx(5, 2, 'z', x^2 + 4*x + 2, 'FQ_ZECH')"
47824779

47834780
# coercision

src/flint/types/fq_default.pxd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ cpdef enum fq_default_type:
2424

2525
cdef class fq_default_ctx:
2626
cdef fq_default_ctx_t val
27-
cdef readonly char *var
27+
cdef str var
2828
cdef bint _initialized
2929

3030
cdef new_ctype_fq_default(self)

src/flint/types/fq_default.pyx

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -63,19 +63,14 @@ cdef class fq_default_ctx:
6363
return fq_type
6464

6565
@staticmethod
66-
def _parse_input_var(var):
66+
def _parse_input_var(var) -> str:
6767
# If no variable is given, use x
6868
if var is None:
69-
var = b"z"
70-
71-
# Encode to bytes for cython to parse
72-
if isinstance(var, str):
73-
var = var.encode()
74-
75-
# TODO: Flint only wants one-character inputs
76-
if len(var) > 1:
77-
raise ValueError("variable for GF(p^k) generator can only be one character")
78-
69+
var = "z"
70+
elif isinstance(var, bytes):
71+
var = var.decode()
72+
if len(var) < 1:
73+
raise ValueError("variable for GF(p^k) generator must be at least one character")
7974
return var
8075

8176
def __init__(self, p=None, degree=None, var=None, modulus=None, fq_type=fq_default_type.DEFAULT,
@@ -138,7 +133,7 @@ cdef class fq_default_ctx:
138133
if d < 1:
139134
raise ValueError(f"the degree must be positive, got d = {d}")
140135

141-
fq_default_ctx_init_type(self.val, (<fmpz>prime).val, d, self.var, <fq_default_type>fq_type)
136+
fq_default_ctx_init_type(self.val, (<fmpz>prime).val, d, self.var.encode(), <fq_default_type>fq_type)
142137
self._initialized = True
143138

144139
cdef _set_from_modulus(self, modulus, var, fq_type=fq_default_type.DEFAULT,
@@ -161,7 +156,7 @@ cdef class fq_default_ctx:
161156
raise ValueError("modulus must be irreducible")
162157

163158
fq_default_ctx_init_modulus_type(self.val, (<fmpz_mod_poly>modulus).val,
164-
(<fmpz_mod_poly>modulus).ctx.mod.val, self.var, <fq_default_type>fq_type)
159+
(<fmpz_mod_poly>modulus).ctx.mod.val, self.var.encode(), <fq_default_type>fq_type)
165160
self._initialized = True
166161

167162
@property
@@ -396,28 +391,33 @@ cdef class fq_default_ctx:
396391
>>> gf3 == gf
397392
False
398393
"""
394+
cdef fq_default_ctx other_ctx
395+
399396
if self is other:
400397
return True
401398

402-
if typecheck(other, fq_default_ctx):
403-
return (self.fq_type == other.fq_type
404-
and self.var == other.var
405-
and self.prime() == other.prime()
406-
and self.modulus() == other.modulus())
407-
return False
399+
if not typecheck(other, fq_default_ctx):
400+
return NotImplemented
401+
402+
other_ctx = <fq_default_ctx>other
403+
404+
return (self.fq_type == other_ctx.fq_type
405+
and self.var == other_ctx.var
406+
and self.prime() == other_ctx.prime()
407+
and self.modulus() == other_ctx.modulus())
408408

409409
def __hash__(self):
410410
return hash((self.fq_type, self.var, self.prime(), self.modulus()))
411411

412412
def __str__(self):
413413
if self.degree() == 1:
414414
return f"Context for fq_default in GF({self.prime()})"
415-
return f"Context for fq_default in GF({self.prime()}^{self.degree()})[{self.var.decode()}]/({self.modulus().str(var=self.var.decode())})"
415+
return f"Context for fq_default in GF({self.prime()}^{self.degree()})[{self.var}]/({self.modulus().str(var=self.var)})"
416416

417417
def __repr__(self):
418418
if self.degree() == 1:
419-
return f"fq_default_ctx({self.prime()}, var='{self.var.decode()}' type='{self.fq_type._name_}')"
420-
return f"fq_default_ctx({self.prime()}, {self.degree()}, '{self.var.decode()}', {self.modulus()!r}, '{self.fq_type._name_}')"
419+
return f"fq_default_ctx({self.prime()}, var='{self.var}', type='{self.fq_type._name_}')"
420+
return f"fq_default_ctx({self.prime()}, {self.degree()}, '{self.var}', {self.modulus()!r}, '{self.fq_type._name_}')"
421421

422422
def __call__(self, val):
423423
return fq_default(val, self)
@@ -503,7 +503,7 @@ cdef class fq_default(flint_scalar):
503503
return coeffs
504504

505505
def str(self):
506-
return self.polynomial().str(var=self.ctx.var.decode())
506+
return self.polynomial().str(var=self.ctx.var)
507507

508508
def __hash__(self):
509509
return hash((self.polynomial(), hash(self.ctx)))

0 commit comments

Comments
 (0)