Path: blob/master/sage/matrix/matrix_generic_dense.pyx
4057 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 "../ext/interrupt.pxi"20include "../ext/stdsage.pxi"21include "../ext/python_list.pxi"22include "../ext/python_number.pxi"23include "../ext/python_ref.pxi"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]225"""226A = self.__class__(self._parent, self._entries, copy = True, coerce=False)227if self._subdivisions is not None:228A.subdivide(*self.subdivisions())229return A230231def _multiply_classical(left, matrix.Matrix _right):232"""233Multiply the matrices left and right using the classical234`O(n^3)` algorithm.235236EXAMPLES: We multiply two matrices over a fairly general ring::237sage: R.<x,y> = Integers(8)['x,y']238sage: a = matrix(R,2,[x,y,x^2,y^2]); a239[ x y]240[x^2 y^2]241sage: type(a)242<type 'sage.matrix.matrix_generic_dense.Matrix_generic_dense'>243sage: a*a244[ x^2*y + x^2 y^3 + x*y]245[x^2*y^2 + x^3 y^4 + x^2*y]246sage: a.det()^2 == (a*a).det()247True248sage: a._multiply_classical(a)249[ x^2*y + x^2 y^3 + x*y]250[x^2*y^2 + x^3 y^4 + x^2*y]251252sage: A = matrix(QQ['x,y'], 2, [0,-1,2,-2])253sage: B = matrix(QQ['x,y'], 2, [-1,-1,-2,-2])254sage: A*B255[2 2]256[2 2]257258Sage fully supports degenerate matrices with 0 rows or 0 columns::259260sage: A = matrix(QQ['x,y'], 0, 4, []); A261[]262sage: B = matrix(QQ['x,y'], 4,0, []); B263[]264sage: A*B265[]266sage: B*A267[0 0 0 0]268[0 0 0 0]269[0 0 0 0]270[0 0 0 0]271"""272cdef Py_ssize_t i, j, k, m, nr, nc, snc, p273cdef object v274cdef Matrix_generic_dense A, right275right = _right276277if left._ncols != right._nrows:278raise IndexError, "Number of columns of left must equal number of rows of other."279280nr = left._nrows281nc = right._ncols282snc = left._ncols283284R = left.base_ring()285P = left.matrix_space(nr, nc)286v = PyList_New(left._nrows * right._ncols)287zero = R(0)288p = 0289cdef PyObject *l, *r290for i from 0 <= i < nr:291for j from 0 <= j < nc:292z = zero293m = i*snc294for k from 0 <= k < snc:295# The following is really:296# z = z + left._entries[m + k] * right._entries[k*right._ncols + j]297l = PyList_GET_ITEM(left._entries, m+k)298r = PyList_GET_ITEM(right._entries, k*nc + j)299z = z + PyNumber_Multiply(<object>l, <object>r)300Py_INCREF(z); PyList_SET_ITEM(v, p, z) # Basically this is "v.append(z)"301p = p + 1302303A = left.__class__.__new__(left.__class__, 0, 0 ,0)304matrix.Matrix.__init__(A, P)305A._entries = v306return A307308def _list(self):309"""310Return reference to list of entries of self. For internal use311only, since this circumvents immutability.312313EXAMPLES:314sage: A = random_matrix(Integers(25)['x'],2); A.set_immutable()315sage: A._list()[0] = 0316sage: A._list()[0]3170318"""319return self._entries320321########################################################################322# LEVEL 3 functionality (Optional)323# * cdef _sub_324# x * __deepcopy__325# * __invert__326# * _multiply_classical327# * Matrix windows -- only if you need strassen for that base328# * Other functions (list them here):329########################################################################330331def __deepcopy__(self):332"""333EXAMPLES:334sage: R.<x> = QQ[]335sage: A = matrix(R, 2, [1,2,x,x^2])336sage: B = A.__deepcopy__()337sage: A[0,0]._unsafe_mutate(1,2/3)338sage: A339[2/3*x + 1 2]340[ x x^2]341sage: B342[ 1 2]343[ x x^2]344"""345import copy346return self.__class__(self._parent, copy.deepcopy(self._entries), copy = False, coerce=False)347348349350