Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/matrix/matrix_generic_dense.pyx
8815 views
1
"""
2
Dense Matrices over a general ring
3
"""
4
5
def _convert_dense_entries_to_list(entries):
6
"""
7
Create list of entries that define a matrix from a list of vectors.
8
9
EXAMPLES:
10
sage: entries = [vector([1,2,3]), vector([4,5,6])]
11
sage: sage.matrix.matrix_generic_dense._convert_dense_entries_to_list(entries)
12
[1, 2, 3, 4, 5, 6]
13
"""
14
e = []
15
for v in entries:
16
e = e+ v.list()
17
copy = False
18
return e
19
20
include "sage/ext/interrupt.pxi"
21
include "sage/ext/stdsage.pxi"
22
from cpython.list cimport *
23
from cpython.number cimport *
24
from cpython.ref cimport *
25
26
cimport matrix_dense
27
import matrix_dense
28
29
cimport matrix
30
31
cdef class Matrix_generic_dense(matrix_dense.Matrix_dense):
32
r"""
33
The ``Matrix_generic_dense`` class derives from
34
``Matrix``, and defines functionality for dense
35
matrices over any base ring. Matrices are represented by a list of
36
elements in the base ring, and element access operations are
37
implemented in this class.
38
39
EXAMPLES::
40
41
sage: A = random_matrix(Integers(25)['x'],2); A
42
[ x^2 + 12*x + 2 4*x^2 + 13*x + 8]
43
[ 22*x^2 + 2*x + 17 19*x^2 + 22*x + 14]
44
sage: type(A)
45
<type 'sage.matrix.matrix_generic_dense.Matrix_generic_dense'>
46
sage: TestSuite(A).run()
47
"""
48
########################################################################
49
# LEVEL 1 functionality
50
# 0 * __cinit__ (not needed)
51
# x * __init__
52
# 0 * __dealloc__ (not needed)
53
# x * set_unsafe
54
# x * get_unsafe
55
# x * def _pickle
56
# x * def _unpickle
57
########################################################################
58
def __init__(self, parent, entries, copy, coerce):
59
r"""
60
See :class:`Matrix_generic_dense` for documentation.
61
62
TESTS:
63
64
We check that the problem related to Trac #9049 is not an issue any
65
more::
66
67
sage: S.<t>=PolynomialRing(QQ)
68
sage: F.<q>=QQ.extension(t^4+1)
69
sage: R.<x,y>=PolynomialRing(F)
70
sage: M = MatrixSpace(R, 1, 2)
71
sage: from sage.matrix.matrix_generic_dense import Matrix_generic_dense
72
sage: Matrix_generic_dense(M, (x, y), True, True)
73
[x y]
74
"""
75
matrix.Matrix.__init__(self, parent)
76
77
cdef Py_ssize_t i, n
78
79
if entries is None:
80
entries = 0
81
82
if not isinstance(entries, (list, tuple)):
83
try:
84
x = parent.base_ring()(entries)
85
is_list = 0
86
except TypeError:
87
try:
88
entries = list(entries)
89
is_list = 1
90
except TypeError:
91
raise TypeError, "entries must be coercible to a list or the base ring"
92
93
else:
94
is_list = 1
95
96
if is_list:
97
98
if len(entries) != self._nrows * self._ncols:
99
raise TypeError, "entries has the wrong length"
100
101
if not (coerce or copy):
102
self._entries = entries
103
else:
104
self._entries = [None]*(self._nrows*self._ncols)
105
n = len(entries)
106
if coerce:
107
R = parent.base_ring()
108
for i from 0 <= i < n:
109
self._entries[i] = R(entries[i])
110
else:
111
for i from 0 <= i < n:
112
self._entries[i] = entries[i]
113
114
else:
115
116
zero = parent.base_ring()(0)
117
self._entries = [zero]*(self._nrows*self._ncols)
118
119
if x != zero:
120
if self._nrows != self._ncols:
121
raise TypeError, "nonzero scalar matrix must be square"
122
for i from 0 <= i < self._nrows:
123
self._entries[i*self._ncols + i] = x
124
125
cdef set_unsafe(self, Py_ssize_t i, Py_ssize_t j, value):
126
Py_DECREF(<object>PyList_GET_ITEM(self._entries, i*self._ncols + j))
127
Py_INCREF(value)
128
PyList_SET_ITEM(self._entries, i*self._ncols + j, value)
129
130
cdef get_unsafe(self, Py_ssize_t i, Py_ssize_t j):
131
return <object>PyList_GET_ITEM(self._entries, i*self._ncols + j)
132
133
def _pickle(self):
134
"""
135
EXAMPLES:
136
sage: R.<x> = Integers(25)['x']; A = matrix(R, [1,x,x^3+1,2*x])
137
sage: A._pickle()
138
([1, x, x^3 + 1, 2*x], 0)
139
"""
140
return self._entries, 0
141
142
def _unpickle(self, data, int version):
143
"""
144
EXAMPLES:
145
sage: R.<x> = Integers(25)['x']; A = matrix(R, [1,x,x^3+1,2*x]); B = A.parent()(0)
146
sage: v = A._pickle()
147
sage: B._unpickle(v[0], v[1])
148
sage: B
149
[ 1 x x^3 + 1 2*x]
150
"""
151
if version == 0:
152
self._entries = data
153
else:
154
raise RuntimeError, "unknown matrix version"
155
156
def __richcmp__(matrix.Matrix self, right, int op): # always need for mysterious reasons.
157
"""
158
EXAMPLES:
159
sage: A = random_matrix(Integers(25)['x'],2)
160
sage: cmp(A,A)
161
0
162
sage: cmp(A,A+1)
163
-1
164
sage: cmp(A+1,A)
165
1
166
"""
167
return self._richcmp(right, op)
168
169
def __hash__(self):
170
"""
171
EXAMPLES:
172
sage: A = random_matrix(Integers(25)['x'],2)
173
sage: hash(A)
174
Traceback (most recent call last):
175
...
176
TypeError: mutable matrices are unhashable
177
sage: A.set_immutable()
178
sage: hash(A)
179
139665060168050560 # 64-bit
180
-623270016 # 32-bit
181
"""
182
return self._hash()
183
184
########################################################################
185
# LEVEL 2 functionality
186
# * cdef _add_
187
# * cdef _mul_
188
# * cdef _cmp_c_impl
189
# * __neg__
190
# * __invert__
191
# x * __copy__
192
# x * _multiply_classical
193
# x * _list -- copy of the list of underlying elements
194
# * _dict -- copy of the sparse dictionary of underlying elements
195
########################################################################
196
197
def __copy__(self):
198
"""
199
Creates a copy of self, which may be changed without altering
200
self.
201
202
EXAMPLES::
203
204
sage: A = matrix(ZZ[['t']], 2,3,range(6)); A
205
[0 1 2]
206
[3 4 5]
207
sage: A.subdivide(1,1); A
208
[0|1 2]
209
[-+---]
210
[3|4 5]
211
sage: B = A.__copy__(); B
212
[0|1 2]
213
[-+---]
214
[3|4 5]
215
sage: B == A
216
True
217
sage: B[0,0] = 100
218
sage: B
219
[100| 1 2]
220
[---+-------]
221
[ 3| 4 5]
222
sage: A
223
[0|1 2]
224
[-+---]
225
[3|4 5]
226
sage: R.<x> = QQ['x']
227
sage: a = matrix(R,2,[x+1,2/3, x^2/2, 1+x^3]); a
228
[ x + 1 2/3]
229
[1/2*x^2 x^3 + 1]
230
sage: b = copy(a)
231
sage: b[0,0] = 5
232
sage: b
233
[ 5 2/3]
234
[1/2*x^2 x^3 + 1]
235
sage: a
236
[ x + 1 2/3]
237
[1/2*x^2 x^3 + 1]
238
239
::
240
241
sage: b = copy(a)
242
sage: f = b[0,0]; f[0] = 10
243
Traceback (most recent call last):
244
...
245
IndexError: polynomials are immutable
246
"""
247
A = self.__class__(self._parent, self._entries, copy = True, coerce=False)
248
if self._subdivisions is not None:
249
A.subdivide(*self.subdivisions())
250
return A
251
252
def _multiply_classical(left, matrix.Matrix _right):
253
"""
254
Multiply the matrices left and right using the classical
255
`O(n^3)` algorithm.
256
257
EXAMPLES: We multiply two matrices over a fairly general ring::
258
sage: R.<x,y> = Integers(8)['x,y']
259
sage: a = matrix(R,2,[x,y,x^2,y^2]); a
260
[ x y]
261
[x^2 y^2]
262
sage: type(a)
263
<type 'sage.matrix.matrix_generic_dense.Matrix_generic_dense'>
264
sage: a*a
265
[ x^2*y + x^2 y^3 + x*y]
266
[x^2*y^2 + x^3 y^4 + x^2*y]
267
sage: a.det()^2 == (a*a).det()
268
True
269
sage: a._multiply_classical(a)
270
[ x^2*y + x^2 y^3 + x*y]
271
[x^2*y^2 + x^3 y^4 + x^2*y]
272
273
sage: A = matrix(QQ['x,y'], 2, [0,-1,2,-2])
274
sage: B = matrix(QQ['x,y'], 2, [-1,-1,-2,-2])
275
sage: A*B
276
[2 2]
277
[2 2]
278
279
Sage fully supports degenerate matrices with 0 rows or 0 columns::
280
281
sage: A = matrix(QQ['x,y'], 0, 4, []); A
282
[]
283
sage: B = matrix(QQ['x,y'], 4,0, []); B
284
[]
285
sage: A*B
286
[]
287
sage: B*A
288
[0 0 0 0]
289
[0 0 0 0]
290
[0 0 0 0]
291
[0 0 0 0]
292
"""
293
cdef Py_ssize_t i, j, k, m, nr, nc, snc, p
294
cdef object v
295
cdef Matrix_generic_dense A, right
296
right = _right
297
298
if left._ncols != right._nrows:
299
raise IndexError, "Number of columns of left must equal number of rows of other."
300
301
nr = left._nrows
302
nc = right._ncols
303
snc = left._ncols
304
305
R = left.base_ring()
306
P = left.matrix_space(nr, nc)
307
v = PyList_New(left._nrows * right._ncols)
308
zero = R(0)
309
p = 0
310
cdef PyObject *l, *r
311
for i from 0 <= i < nr:
312
for j from 0 <= j < nc:
313
z = zero
314
m = i*snc
315
for k from 0 <= k < snc:
316
# The following is really:
317
# z = z + left._entries[m + k] * right._entries[k*right._ncols + j]
318
l = PyList_GET_ITEM(left._entries, m+k)
319
r = PyList_GET_ITEM(right._entries, k*nc + j)
320
z = z + PyNumber_Multiply(<object>l, <object>r)
321
Py_INCREF(z); PyList_SET_ITEM(v, p, z) # Basically this is "v.append(z)"
322
p = p + 1
323
324
A = left.__class__.__new__(left.__class__, 0, 0 ,0)
325
matrix.Matrix.__init__(A, P)
326
A._entries = v
327
return A
328
329
def _list(self):
330
"""
331
Return reference to list of entries of self. For internal use
332
only, since this circumvents immutability.
333
334
EXAMPLES:
335
sage: A = random_matrix(Integers(25)['x'],2); A.set_immutable()
336
sage: A._list()[0] = 0
337
sage: A._list()[0]
338
0
339
"""
340
return self._entries
341
342
########################################################################
343
# LEVEL 3 functionality (Optional)
344
# * cdef _sub_
345
# x * __deepcopy__
346
# * __invert__
347
# * _multiply_classical
348
# * Matrix windows -- only if you need strassen for that base
349
# * Other functions (list them here):
350
########################################################################
351
352
def __deepcopy__(self):
353
"""
354
EXAMPLES:
355
sage: R.<x> = QQ[]
356
sage: A = matrix(R, 2, [1,2,x,x^2])
357
sage: B = A.__deepcopy__()
358
sage: A[0,0]._unsafe_mutate(1,2/3)
359
sage: A
360
[2/3*x + 1 2]
361
[ x x^2]
362
sage: B
363
[ 1 2]
364
[ x x^2]
365
"""
366
import copy
367
return self.__class__(self._parent, copy.deepcopy(self._entries), copy = False, coerce=False)
368
369