Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/matrix/matrix_generic_dense.pyx
4057 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 "../ext/interrupt.pxi"
21
include "../ext/stdsage.pxi"
22
include "../ext/python_list.pxi"
23
include "../ext/python_number.pxi"
24
include "../ext/python_ref.pxi"
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
"""
227
A = self.__class__(self._parent, self._entries, copy = True, coerce=False)
228
if self._subdivisions is not None:
229
A.subdivide(*self.subdivisions())
230
return A
231
232
def _multiply_classical(left, matrix.Matrix _right):
233
"""
234
Multiply the matrices left and right using the classical
235
`O(n^3)` algorithm.
236
237
EXAMPLES: We multiply two matrices over a fairly general ring::
238
sage: R.<x,y> = Integers(8)['x,y']
239
sage: a = matrix(R,2,[x,y,x^2,y^2]); a
240
[ x y]
241
[x^2 y^2]
242
sage: type(a)
243
<type 'sage.matrix.matrix_generic_dense.Matrix_generic_dense'>
244
sage: a*a
245
[ x^2*y + x^2 y^3 + x*y]
246
[x^2*y^2 + x^3 y^4 + x^2*y]
247
sage: a.det()^2 == (a*a).det()
248
True
249
sage: a._multiply_classical(a)
250
[ x^2*y + x^2 y^3 + x*y]
251
[x^2*y^2 + x^3 y^4 + x^2*y]
252
253
sage: A = matrix(QQ['x,y'], 2, [0,-1,2,-2])
254
sage: B = matrix(QQ['x,y'], 2, [-1,-1,-2,-2])
255
sage: A*B
256
[2 2]
257
[2 2]
258
259
Sage fully supports degenerate matrices with 0 rows or 0 columns::
260
261
sage: A = matrix(QQ['x,y'], 0, 4, []); A
262
[]
263
sage: B = matrix(QQ['x,y'], 4,0, []); B
264
[]
265
sage: A*B
266
[]
267
sage: B*A
268
[0 0 0 0]
269
[0 0 0 0]
270
[0 0 0 0]
271
[0 0 0 0]
272
"""
273
cdef Py_ssize_t i, j, k, m, nr, nc, snc, p
274
cdef object v
275
cdef Matrix_generic_dense A, right
276
right = _right
277
278
if left._ncols != right._nrows:
279
raise IndexError, "Number of columns of left must equal number of rows of other."
280
281
nr = left._nrows
282
nc = right._ncols
283
snc = left._ncols
284
285
R = left.base_ring()
286
P = left.matrix_space(nr, nc)
287
v = PyList_New(left._nrows * right._ncols)
288
zero = R(0)
289
p = 0
290
cdef PyObject *l, *r
291
for i from 0 <= i < nr:
292
for j from 0 <= j < nc:
293
z = zero
294
m = i*snc
295
for k from 0 <= k < snc:
296
# The following is really:
297
# z = z + left._entries[m + k] * right._entries[k*right._ncols + j]
298
l = PyList_GET_ITEM(left._entries, m+k)
299
r = PyList_GET_ITEM(right._entries, k*nc + j)
300
z = z + PyNumber_Multiply(<object>l, <object>r)
301
Py_INCREF(z); PyList_SET_ITEM(v, p, z) # Basically this is "v.append(z)"
302
p = p + 1
303
304
A = left.__class__.__new__(left.__class__, 0, 0 ,0)
305
matrix.Matrix.__init__(A, P)
306
A._entries = v
307
return A
308
309
def _list(self):
310
"""
311
Return reference to list of entries of self. For internal use
312
only, since this circumvents immutability.
313
314
EXAMPLES:
315
sage: A = random_matrix(Integers(25)['x'],2); A.set_immutable()
316
sage: A._list()[0] = 0
317
sage: A._list()[0]
318
0
319
"""
320
return self._entries
321
322
########################################################################
323
# LEVEL 3 functionality (Optional)
324
# * cdef _sub_
325
# x * __deepcopy__
326
# * __invert__
327
# * _multiply_classical
328
# * Matrix windows -- only if you need strassen for that base
329
# * Other functions (list them here):
330
########################################################################
331
332
def __deepcopy__(self):
333
"""
334
EXAMPLES:
335
sage: R.<x> = QQ[]
336
sage: A = matrix(R, 2, [1,2,x,x^2])
337
sage: B = A.__deepcopy__()
338
sage: A[0,0]._unsafe_mutate(1,2/3)
339
sage: A
340
[2/3*x + 1 2]
341
[ x x^2]
342
sage: B
343
[ 1 2]
344
[ x x^2]
345
"""
346
import copy
347
return self.__class__(self._parent, copy.deepcopy(self._entries), copy = False, coerce=False)
348
349
350