Path: blob/master/src/sage/matrix/matrix_generic_dense.pyx
8815 views
"""1Dense Matrices over a general ring2"""34def _convert_dense_entries_to_list(entries):5"""6Create list of entries that define a matrix from a list of vectors.78EXAMPLES:9sage: entries = [vector([1,2,3]), vector([4,5,6])]10sage: sage.matrix.matrix_generic_dense._convert_dense_entries_to_list(entries)11[1, 2, 3, 4, 5, 6]12"""13e = []14for v in entries:15e = e+ v.list()16copy = False17return e1819include "sage/ext/interrupt.pxi"20include "sage/ext/stdsage.pxi"21from cpython.list cimport *22from cpython.number cimport *23from cpython.ref cimport *2425cimport matrix_dense26import matrix_dense2728cimport matrix2930cdef class Matrix_generic_dense(matrix_dense.Matrix_dense):31r"""32The ``Matrix_generic_dense`` class derives from33``Matrix``, and defines functionality for dense34matrices over any base ring. Matrices are represented by a list of35elements in the base ring, and element access operations are36implemented in this class.3738EXAMPLES::3940sage: A = random_matrix(Integers(25)['x'],2); A41[ x^2 + 12*x + 2 4*x^2 + 13*x + 8]42[ 22*x^2 + 2*x + 17 19*x^2 + 22*x + 14]43sage: type(A)44<type 'sage.matrix.matrix_generic_dense.Matrix_generic_dense'>45sage: TestSuite(A).run()46"""47########################################################################48# LEVEL 1 functionality49# 0 * __cinit__ (not needed)50# x * __init__51# 0 * __dealloc__ (not needed)52# x * set_unsafe53# x * get_unsafe54# x * def _pickle55# x * def _unpickle56########################################################################57def __init__(self, parent, entries, copy, coerce):58r"""59See :class:`Matrix_generic_dense` for documentation.6061TESTS:6263We check that the problem related to Trac #9049 is not an issue any64more::6566sage: S.<t>=PolynomialRing(QQ)67sage: F.<q>=QQ.extension(t^4+1)68sage: R.<x,y>=PolynomialRing(F)69sage: M = MatrixSpace(R, 1, 2)70sage: from sage.matrix.matrix_generic_dense import Matrix_generic_dense71sage: Matrix_generic_dense(M, (x, y), True, True)72[x y]73"""74matrix.Matrix.__init__(self, parent)7576cdef Py_ssize_t i, n7778if entries is None:79entries = 08081if not isinstance(entries, (list, tuple)):82try:83x = parent.base_ring()(entries)84is_list = 085except TypeError:86try:87entries = list(entries)88is_list = 189except TypeError:90raise TypeError, "entries must be coercible to a list or the base ring"9192else:93is_list = 19495if is_list:9697if len(entries) != self._nrows * self._ncols:98raise TypeError, "entries has the wrong length"99100if not (coerce or copy):101self._entries = entries102else:103self._entries = [None]*(self._nrows*self._ncols)104n = len(entries)105if coerce:106R = parent.base_ring()107for i from 0 <= i < n:108self._entries[i] = R(entries[i])109else:110for i from 0 <= i < n:111self._entries[i] = entries[i]112113else:114115zero = parent.base_ring()(0)116self._entries = [zero]*(self._nrows*self._ncols)117118if x != zero:119if self._nrows != self._ncols:120raise TypeError, "nonzero scalar matrix must be square"121for i from 0 <= i < self._nrows:122self._entries[i*self._ncols + i] = x123124cdef set_unsafe(self, Py_ssize_t i, Py_ssize_t j, value):125Py_DECREF(<object>PyList_GET_ITEM(self._entries, i*self._ncols + j))126Py_INCREF(value)127PyList_SET_ITEM(self._entries, i*self._ncols + j, value)128129cdef get_unsafe(self, Py_ssize_t i, Py_ssize_t j):130return <object>PyList_GET_ITEM(self._entries, i*self._ncols + j)131132def _pickle(self):133"""134EXAMPLES:135sage: R.<x> = Integers(25)['x']; A = matrix(R, [1,x,x^3+1,2*x])136sage: A._pickle()137([1, x, x^3 + 1, 2*x], 0)138"""139return self._entries, 0140141def _unpickle(self, data, int version):142"""143EXAMPLES:144sage: R.<x> = Integers(25)['x']; A = matrix(R, [1,x,x^3+1,2*x]); B = A.parent()(0)145sage: v = A._pickle()146sage: B._unpickle(v[0], v[1])147sage: B148[ 1 x x^3 + 1 2*x]149"""150if version == 0:151self._entries = data152else:153raise RuntimeError, "unknown matrix version"154155def __richcmp__(matrix.Matrix self, right, int op): # always need for mysterious reasons.156"""157EXAMPLES:158sage: A = random_matrix(Integers(25)['x'],2)159sage: cmp(A,A)1600161sage: cmp(A,A+1)162-1163sage: cmp(A+1,A)1641165"""166return self._richcmp(right, op)167168def __hash__(self):169"""170EXAMPLES:171sage: A = random_matrix(Integers(25)['x'],2)172sage: hash(A)173Traceback (most recent call last):174...175TypeError: mutable matrices are unhashable176sage: A.set_immutable()177sage: hash(A)178139665060168050560 # 64-bit179-623270016 # 32-bit180"""181return self._hash()182183########################################################################184# LEVEL 2 functionality185# * cdef _add_186# * cdef _mul_187# * cdef _cmp_c_impl188# * __neg__189# * __invert__190# x * __copy__191# x * _multiply_classical192# x * _list -- copy of the list of underlying elements193# * _dict -- copy of the sparse dictionary of underlying elements194########################################################################195196def __copy__(self):197"""198Creates a copy of self, which may be changed without altering199self.200201EXAMPLES::202203sage: A = matrix(ZZ[['t']], 2,3,range(6)); A204[0 1 2]205[3 4 5]206sage: A.subdivide(1,1); A207[0|1 2]208[-+---]209[3|4 5]210sage: B = A.__copy__(); B211[0|1 2]212[-+---]213[3|4 5]214sage: B == A215True216sage: B[0,0] = 100217sage: B218[100| 1 2]219[---+-------]220[ 3| 4 5]221sage: A222[0|1 2]223[-+---]224[3|4 5]225sage: R.<x> = QQ['x']226sage: a = matrix(R,2,[x+1,2/3, x^2/2, 1+x^3]); a227[ x + 1 2/3]228[1/2*x^2 x^3 + 1]229sage: b = copy(a)230sage: b[0,0] = 5231sage: b232[ 5 2/3]233[1/2*x^2 x^3 + 1]234sage: a235[ x + 1 2/3]236[1/2*x^2 x^3 + 1]237238::239240sage: b = copy(a)241sage: f = b[0,0]; f[0] = 10242Traceback (most recent call last):243...244IndexError: polynomials are immutable245"""246A = self.__class__(self._parent, self._entries, copy = True, coerce=False)247if self._subdivisions is not None:248A.subdivide(*self.subdivisions())249return A250251def _multiply_classical(left, matrix.Matrix _right):252"""253Multiply the matrices left and right using the classical254`O(n^3)` algorithm.255256EXAMPLES: We multiply two matrices over a fairly general ring::257sage: R.<x,y> = Integers(8)['x,y']258sage: a = matrix(R,2,[x,y,x^2,y^2]); a259[ x y]260[x^2 y^2]261sage: type(a)262<type 'sage.matrix.matrix_generic_dense.Matrix_generic_dense'>263sage: a*a264[ x^2*y + x^2 y^3 + x*y]265[x^2*y^2 + x^3 y^4 + x^2*y]266sage: a.det()^2 == (a*a).det()267True268sage: a._multiply_classical(a)269[ x^2*y + x^2 y^3 + x*y]270[x^2*y^2 + x^3 y^4 + x^2*y]271272sage: A = matrix(QQ['x,y'], 2, [0,-1,2,-2])273sage: B = matrix(QQ['x,y'], 2, [-1,-1,-2,-2])274sage: A*B275[2 2]276[2 2]277278Sage fully supports degenerate matrices with 0 rows or 0 columns::279280sage: A = matrix(QQ['x,y'], 0, 4, []); A281[]282sage: B = matrix(QQ['x,y'], 4,0, []); B283[]284sage: A*B285[]286sage: B*A287[0 0 0 0]288[0 0 0 0]289[0 0 0 0]290[0 0 0 0]291"""292cdef Py_ssize_t i, j, k, m, nr, nc, snc, p293cdef object v294cdef Matrix_generic_dense A, right295right = _right296297if left._ncols != right._nrows:298raise IndexError, "Number of columns of left must equal number of rows of other."299300nr = left._nrows301nc = right._ncols302snc = left._ncols303304R = left.base_ring()305P = left.matrix_space(nr, nc)306v = PyList_New(left._nrows * right._ncols)307zero = R(0)308p = 0309cdef PyObject *l, *r310for i from 0 <= i < nr:311for j from 0 <= j < nc:312z = zero313m = i*snc314for k from 0 <= k < snc:315# The following is really:316# z = z + left._entries[m + k] * right._entries[k*right._ncols + j]317l = PyList_GET_ITEM(left._entries, m+k)318r = PyList_GET_ITEM(right._entries, k*nc + j)319z = z + PyNumber_Multiply(<object>l, <object>r)320Py_INCREF(z); PyList_SET_ITEM(v, p, z) # Basically this is "v.append(z)"321p = p + 1322323A = left.__class__.__new__(left.__class__, 0, 0 ,0)324matrix.Matrix.__init__(A, P)325A._entries = v326return A327328def _list(self):329"""330Return reference to list of entries of self. For internal use331only, since this circumvents immutability.332333EXAMPLES:334sage: A = random_matrix(Integers(25)['x'],2); A.set_immutable()335sage: A._list()[0] = 0336sage: A._list()[0]3370338"""339return self._entries340341########################################################################342# LEVEL 3 functionality (Optional)343# * cdef _sub_344# x * __deepcopy__345# * __invert__346# * _multiply_classical347# * Matrix windows -- only if you need strassen for that base348# * Other functions (list them here):349########################################################################350351def __deepcopy__(self):352"""353EXAMPLES:354sage: R.<x> = QQ[]355sage: A = matrix(R, 2, [1,2,x,x^2])356sage: B = A.__deepcopy__()357sage: A[0,0]._unsafe_mutate(1,2/3)358sage: A359[2/3*x + 1 2]360[ x x^2]361sage: B362[ 1 2]363[ x x^2]364"""365import copy366return self.__class__(self._parent, copy.deepcopy(self._entries), copy = False, coerce=False)367368369