Skip to content

Commit 51fd626

Browse files
author
Release Manager
committed
gh-39367: Shorten pickle for matrix_mod2_dense Previously it recursively pickles an array of Python `int` . Now it pickles a `bytes` object, which should be faster and result in (generally speaking, for very short input it may lead to slightly longer output) smaller input. ### 📝 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. - [x] 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: #39367 Reported by: user202729 Reviewer(s): David Coudert, user202729
2 parents 9e8b113 + 660b757 commit 51fd626

File tree

1 file changed

+52
-12
lines changed

1 file changed

+52
-12
lines changed

src/sage/matrix/matrix_mod2_dense.pyx

+52-12
Original file line numberDiff line numberDiff line change
@@ -1799,6 +1799,12 @@ cdef class Matrix_mod2_dense(matrix_dense.Matrix_dense): # dense or sparse
17991799
sage: A.set_immutable()
18001800
sage: loads(dumps(A)).is_immutable()
18011801
True
1802+
1803+
Check that :issue:`39367` is achieved::
1804+
1805+
sage: l = len(dumps(random_matrix(GF(2), 2000, 2000))); l # random # previously ~ 785000
1806+
610207
1807+
sage: assert l < 650000
18021808
"""
18031809
cdef int i,j, r,c, size
18041810

@@ -1817,11 +1823,17 @@ cdef class Matrix_mod2_dense(matrix_dense.Matrix_dense): # dense or sparse
18171823
if mzd_read_bit(self._entries, i, j):
18181824
gdImageSetPixel(im, j, i, black )
18191825

1820-
cdef signed char *buf = <signed char*>gdImagePngPtr(im, &size)
1826+
cdef char *buf
1827+
try:
1828+
buf = <char*>gdImagePngPtr(im, &size)
1829+
finally:
1830+
gdImageDestroy(im)
18211831

1822-
data = [buf[i] for i in range(size)]
1823-
gdFree(buf)
1824-
gdImageDestroy(im)
1832+
cdef bytes data
1833+
try:
1834+
data = buf[:size]
1835+
finally: # recommended by https://cython.readthedocs.io/en/latest/src/tutorial/strings.html
1836+
gdFree(buf)
18251837
return unpickle_matrix_mod2_dense_v2, (r,c, data, size, self._is_immutable)
18261838

18271839
cpdef _export_as_string(self):
@@ -2195,6 +2207,28 @@ def unpickle_matrix_mod2_dense_v2(r, c, data, size, immutable=False):
21952207
sage: loads(s)
21962208
[1 0]
21972209
[0 1]
2210+
2211+
Check that old pickles before :issue:`39367` still work::
2212+
2213+
sage: loads(bytes.fromhex( # hexstring produced with dumps(matrix.zero(GF(2),10,10)).hex()
2214+
....: '789c6b604a2e4e4c4fd5cb4d2c29caac8052f1b9f92946f129a979c5a95ca5'
2215+
....: '790599c9d939a9f11852f165465c850c1ade5cde5cb1858c1a5e9dfffffff7'
2216+
....: '0ef0f6f376f7e6050a4a01310318f27a7b7a7b78bb780741f95c709ad19b19'
2217+
....: 'c2f6da0ed4ecf5076442acd73f100551c20634d0c73bc4db15aaec3f481982'
2218+
....: '580a226e8288f920e22e4223a77701d0ce48ef62308fcfeb084c0aca64f49a'
2219+
....: '0aa2b4bdf9bca5a15af880ce74f17604dac6e135132499ecf50344d57b3580'
2220+
....: '75789b7b330195b103fd21e85deeb51064e362908c2f441d03147a025debe7'
2221+
....: 'ede2b50e24e8e49de0d50464a47ae775961432051532eb0100093b9ba3'))
2222+
[0 0 0 0 0 0 0 0 0 0]
2223+
[0 0 0 0 0 0 0 0 0 0]
2224+
[0 0 0 0 0 0 0 0 0 0]
2225+
[0 0 0 0 0 0 0 0 0 0]
2226+
[0 0 0 0 0 0 0 0 0 0]
2227+
[0 0 0 0 0 0 0 0 0 0]
2228+
[0 0 0 0 0 0 0 0 0 0]
2229+
[0 0 0 0 0 0 0 0 0 0]
2230+
[0 0 0 0 0 0 0 0 0 0]
2231+
[0 0 0 0 0 0 0 0 0 0]
21982232
"""
21992233
from sage.matrix.constructor import Matrix
22002234
from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF
@@ -2206,15 +2240,21 @@ def unpickle_matrix_mod2_dense_v2(r, c, data, size, immutable=False):
22062240
if r == 0 or c == 0:
22072241
return A
22082242

2209-
cdef signed char *buf = <signed char*>check_malloc(size)
2210-
for i from 0 <= i < size:
2211-
buf[i] = data[i]
2212-
2213-
sig_on()
2214-
cdef gdImagePtr im = gdImageCreateFromPngPtr(size, buf)
2215-
sig_off()
2243+
cdef signed char *buf
2244+
cdef gdImagePtr im
2245+
if isinstance(data, bytes):
2246+
sig_on()
2247+
im = gdImageCreateFromPngPtr(size, <char *><bytes>data)
2248+
sig_off()
2249+
else:
2250+
buf = <signed char*>check_malloc(size)
2251+
for i from 0 <= i < size:
2252+
buf[i] = data[i]
22162253

2217-
sig_free(buf)
2254+
sig_on()
2255+
im = gdImageCreateFromPngPtr(size, buf)
2256+
sig_off()
2257+
sig_free(buf)
22182258

22192259
if gdImageSX(im) != c or gdImageSY(im) != r:
22202260
raise TypeError("Pickled data dimension doesn't match.")

0 commit comments

Comments
 (0)