Skip to content

Commit 3503f4c

Browse files
author
Release Manager
committed
gh-39316: use memory allocator in `sage/combinat/designs/` Use MemoryAllocator in `src/sage/combinat/desings/designs_pyx.pyx` and `src/sage/combinat/designs/evenly_distributed_sets.pyx` to simplify parts of the code. ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> - [x] The title is concise and informative. - [x] The description explains in detail what this PR is about. - [ ] I have linked a relevant issue or discussion. - [ ] I have created tests covering the changes. - [ ] I have updated the documentation and checked the documentation preview. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on. For example, --> <!-- - #12345: short description why this is a dependency --> <!-- - #34567: ... --> URL: #39316 Reported by: David Coudert Reviewer(s): Kwankyu Lee
2 parents d37ff1a + 5b5e7bc commit 3503f4c

File tree

2 files changed

+26
-65
lines changed

2 files changed

+26
-65
lines changed

src/sage/combinat/designs/designs_pyx.pyx

Lines changed: 11 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ from sage.data_structures.bitset_base cimport *
1111

1212
from libc.string cimport memset
1313

14-
from cysignals.memory cimport sig_malloc, sig_calloc, sig_realloc, sig_free
14+
from cysignals.memory cimport sig_malloc, sig_realloc, sig_free
15+
from memory_allocator cimport MemoryAllocator
1516

1617
from sage.misc.unknown import Unknown
1718

@@ -305,7 +306,8 @@ def is_orthogonal_array(OA, int k, int n, int t=2, verbose=False, terminology='O
305306
cdef int i,j,l
306307

307308
# A copy of OA
308-
cdef unsigned short * OAc = <unsigned short *> sig_malloc(k*n2*sizeof(unsigned short))
309+
cdef MemoryAllocator mem = MemoryAllocator()
310+
cdef unsigned short * OAc = <unsigned short *> mem.malloc(k*n2*sizeof(unsigned short))
309311

310312
cdef unsigned short * C1
311313
cdef unsigned short * C2
@@ -321,7 +323,6 @@ def is_orthogonal_array(OA, int k, int n, int t=2, verbose=False, terminology='O
321323
if verbose:
322324
print({"OA": "{} is not in the interval [0..{}]".format(x,n-1),
323325
"MOLS": "Entry {} was expected to be in the interval [0..{}]".format(x,n-1)}[terminology])
324-
sig_free(OAc)
325326
return False
326327
OAc[j*n2+i] = x
327328

@@ -338,14 +339,12 @@ def is_orthogonal_array(OA, int k, int n, int t=2, verbose=False, terminology='O
338339
bitset_add(seen,n*C1[l]+C2[l])
339340

340341
if bitset_len(seen) != n2: # Have we seen all pairs ?
341-
sig_free(OAc)
342342
bitset_free(seen)
343343
if verbose:
344344
print({"OA": "Columns {} and {} are not orthogonal".format(i,j),
345345
"MOLS": "Squares {} and {} are not orthogonal".format(i,j)}[terminology])
346346
return False
347347

348-
sig_free(OAc)
349348
bitset_free(seen)
350349
return True
351350

@@ -469,9 +468,8 @@ def is_group_divisible_design(groups, blocks, v, G=None, K=None, lambd=1, verbos
469468
print("{} does not belong to [0,...,{}]".format(x, n-1))
470469
return False
471470

472-
cdef unsigned short * matrix = <unsigned short *> sig_calloc(n*n, sizeof(unsigned short))
473-
if matrix is NULL:
474-
raise MemoryError
471+
cdef MemoryAllocator mem = MemoryAllocator()
472+
cdef unsigned short * matrix = <unsigned short *> mem.calloc(n*n, sizeof(unsigned short))
475473

476474
# Counts the number of occurrences of each pair of points
477475
for b in blocks:
@@ -500,7 +498,6 @@ def is_group_divisible_design(groups, blocks, v, G=None, K=None, lambd=1, verbos
500498
if not len(g) in G:
501499
if verbose:
502500
print("a group has size {} while G={}".format(len(g),list(G)))
503-
sig_free(matrix)
504501
return False
505502

506503
# Checks that two points of the same group were never covered
@@ -513,7 +510,6 @@ def is_group_divisible_design(groups, blocks, v, G=None, K=None, lambd=1, verbos
513510
if matrix[ii*n+jj] != 0:
514511
if verbose:
515512
print("the pair ({},{}) belongs to a group but appears in some block".format(ii, jj))
516-
sig_free(matrix)
517513
return False
518514

519515
# We fill the entries with what is expected by the next loop
@@ -526,11 +522,8 @@ def is_group_divisible_design(groups, blocks, v, G=None, K=None, lambd=1, verbos
526522
if matrix[i*n+j] != l:
527523
if verbose:
528524
print("the pair ({},{}) has been seen {} times but lambda={}".format(i,j,matrix[i*n+j],l))
529-
sig_free(matrix)
530525
return False
531526

532-
sig_free(matrix)
533-
534527
return True if not guess_groups else (True, groups)
535528

536529

@@ -836,16 +829,11 @@ def is_quasi_difference_matrix(M, G, int k, int lmbda, int mu, int u, verbose=Fa
836829
cdef dict group_to_int = {v:i for i,v in enumerate(int_to_group)}
837830

838831
# Allocations
839-
cdef int ** x_minus_y = <int **> sig_malloc((n+1)*sizeof(int *))
840-
cdef int * x_minus_y_data = <int *> sig_malloc((n+1)*(n+1)*sizeof(int))
841-
cdef int * M_c = <int *> sig_malloc(k*M_nrows*sizeof(int))
842-
cdef int * G_seen = <int *> sig_malloc((n+1)*sizeof(int))
843-
if (x_minus_y == NULL or x_minus_y_data == NULL or M_c == NULL or G_seen == NULL):
844-
sig_free(x_minus_y)
845-
sig_free(x_minus_y_data)
846-
sig_free(G_seen)
847-
sig_free(M_c)
848-
raise MemoryError
832+
cdef MemoryAllocator mem = MemoryAllocator()
833+
cdef int ** x_minus_y = <int **> mem.malloc((n+1)*sizeof(int *))
834+
cdef int * x_minus_y_data = <int *> mem.malloc((n+1)*(n+1)*sizeof(int))
835+
cdef int * M_c = <int *> mem.malloc(k*M_nrows*sizeof(int))
836+
cdef int * G_seen = <int *> mem.malloc((n+1)*sizeof(int))
849837

850838
# The "x-y" table. If g_i, g_j \in G, then x_minus_y[i][j] is equal to
851839
# group_to_int[g_i-g_j].
@@ -883,10 +871,6 @@ def is_quasi_difference_matrix(M, G, int k, int lmbda, int mu, int u, verbose=Fa
883871
if bit:
884872
if verbose:
885873
print("Row {} contains more than one empty entry".format(i))
886-
sig_free(x_minus_y_data)
887-
sig_free(x_minus_y)
888-
sig_free(G_seen)
889-
sig_free(M_c)
890874
return False
891875
bit = True
892876

@@ -900,10 +884,6 @@ def is_quasi_difference_matrix(M, G, int k, int lmbda, int mu, int u, verbose=Fa
900884
if verbose:
901885
print("Column {} contains {} empty entries instead of the expected "
902886
"lambda.u={}.{}={}".format(j, ii, lmbda, u, lmbda*u))
903-
sig_free(x_minus_y_data)
904-
sig_free(x_minus_y)
905-
sig_free(G_seen)
906-
sig_free(M_c)
907887
return False
908888

909889
# We are now ready to test every pair of columns
@@ -917,10 +897,6 @@ def is_quasi_difference_matrix(M, G, int k, int lmbda, int mu, int u, verbose=Fa
917897
if verbose:
918898
print("Columns {} and {} generate 0 exactly {} times "
919899
"instead of the expected mu(={})".format(i,j,G_seen[0],mu))
920-
sig_free(x_minus_y_data)
921-
sig_free(x_minus_y)
922-
sig_free(G_seen)
923-
sig_free(M_c)
924900
return False
925901

926902
for ii in range(1,n): # bad number of g_ii\in G
@@ -929,16 +905,8 @@ def is_quasi_difference_matrix(M, G, int k, int lmbda, int mu, int u, verbose=Fa
929905
print("Columns {} and {} do not generate all elements of G "
930906
"exactly lambda(={}) times. The element {} appeared {} "
931907
"times as a difference.".format(i,j,lmbda,int_to_group[ii],G_seen[ii]))
932-
sig_free(x_minus_y_data)
933-
sig_free(x_minus_y)
934-
sig_free(G_seen)
935-
sig_free(M_c)
936908
return False
937909

938-
sig_free(x_minus_y_data)
939-
sig_free(x_minus_y)
940-
sig_free(G_seen)
941-
sig_free(M_c)
942910
return True
943911

944912

src/sage/combinat/designs/evenly_distributed_sets.pyx

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@ Classes and methods
1818

1919
cimport cython
2020

21-
from sage.categories.fields import Fields
2221
from libc.limits cimport UINT_MAX
2322
from libc.string cimport memset, memcpy
24-
25-
from cysignals.memory cimport check_malloc, check_calloc, sig_free
23+
from memory_allocator cimport MemoryAllocator
2624

2725
from sage.rings.integer cimport smallInteger
2826

27+
from sage.categories.fields import Fields
28+
29+
2930
cdef class EvenlyDistributedSetsBacktracker:
3031
r"""
3132
Set of evenly distributed subsets in finite fields.
@@ -168,17 +169,8 @@ cdef class EvenlyDistributedSetsBacktracker:
168169
cdef unsigned int * cosets # e array: cosets of differences of elts in B
169170
cdef unsigned int * t # e array: temporary variable for updates
170171

171-
def __dealloc__(self):
172-
if self.diff != NULL:
173-
sig_free(self.diff[0])
174-
sig_free(self.diff)
175-
if self.ratio != NULL:
176-
sig_free(self.ratio[0])
177-
sig_free(self.ratio)
178-
sig_free(self.min_orb)
179-
sig_free(self.B)
180-
sig_free(self.cosets)
181-
sig_free(self.t)
172+
# MANAGEMENT OF MEMORY
173+
cdef MemoryAllocator mem
182174

183175
def __init__(self, K, k, up_to_isomorphism=True, check=False):
184176
r"""
@@ -228,20 +220,21 @@ cdef class EvenlyDistributedSetsBacktracker:
228220
self.m = (q - 1) // e
229221
self.K = K
230222

231-
self.diff = <unsigned int **> check_calloc(q, sizeof(unsigned int *))
232-
self.diff[0] = <unsigned int *> check_malloc(q*q*sizeof(unsigned int))
223+
self.mem = MemoryAllocator()
224+
self.diff = <unsigned int **> self.mem.calloc(q, sizeof(unsigned int *))
225+
self.diff[0] = <unsigned int *> self.mem.malloc(q*q*sizeof(unsigned int))
233226
for i in range(1, self.q):
234227
self.diff[i] = self.diff[i-1] + q
235228

236-
self.ratio = <unsigned int **> check_calloc(q, sizeof(unsigned int *))
237-
self.ratio[0] = <unsigned int *> check_malloc(q*q*sizeof(unsigned int))
229+
self.ratio = <unsigned int **> self.mem.calloc(q, sizeof(unsigned int *))
230+
self.ratio[0] = <unsigned int *> self.mem.malloc(q*q*sizeof(unsigned int))
238231
for i in range(1, self.q):
239232
self.ratio[i] = self.ratio[i-1] + q
240233

241-
self.B = <unsigned int *> check_malloc(k*sizeof(unsigned int))
242-
self.min_orb = <unsigned int *> check_malloc(q*sizeof(unsigned int))
243-
self.cosets = <unsigned int *> check_malloc(e*sizeof(unsigned int))
244-
self.t = <unsigned int *> check_malloc(e*sizeof(unsigned int))
234+
self.B = <unsigned int *> self.mem.malloc(k*sizeof(unsigned int))
235+
self.min_orb = <unsigned int *> self.mem.malloc(q*sizeof(unsigned int))
236+
self.cosets = <unsigned int *> self.mem.malloc(e*sizeof(unsigned int))
237+
self.t = <unsigned int *> self.mem.malloc(e*sizeof(unsigned int))
245238

246239
x = K.multiplicative_generator()
247240
list_K = []

0 commit comments

Comments
 (0)