Path: blob/master/src/sage/matrix/matrix_modn_dense.pyx
8815 views
r"""1Dense matrices over `\ZZ/n\ZZ` for `n` small23AUTHORS:45- William Stein67- Robert Bradshaw89This is a compiled implementation of dense matrices over10`\ZZ/n\ZZ` for `n` small.1112EXAMPLES::1314sage: a = matrix(Integers(37),3,range(9),sparse=False); a15[0 1 2]16[3 4 5]17[6 7 8]18sage: a.rank()19220sage: type(a)21<type 'sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_float'>22sage: a[0,0] = 523sage: a.rank()24325sage: parent(a)26Full MatrixSpace of 3 by 3 dense matrices over Ring of integers modulo 372728::2930sage: a^231[ 3 23 31]32[20 17 29]33[25 16 0]34sage: a+a35[10 2 4]36[ 6 8 10]37[12 14 16]3839::4041sage: b = a.new_matrix(2,3,range(6)); b42[0 1 2]43[3 4 5]44sage: a*b45Traceback (most recent call last):46...47TypeError: unsupported operand parent(s) for '*': 'Full MatrixSpace of 3 by 3 dense matrices over Ring of integers modulo 37' and 'Full MatrixSpace of 2 by 3 dense matrices over Ring of integers modulo 37'48sage: b*a49[15 18 21]50[20 17 29]5152::5354sage: TestSuite(a).run()55sage: TestSuite(b).run()5657::5859sage: a.echelonize(); a60[1 0 0]61[0 1 0]62[0 0 1]63sage: b.echelonize(); b64[ 1 0 36]65[ 0 1 2]6667We create a matrix group::6869sage: M = MatrixSpace(GF(3),3,3)70sage: G = MatrixGroup([M([[0,1,0],[0,0,1],[1,0,0]]), M([[0,1,0],[1,0,0],[0,0,1]])])71sage: G72Matrix group over Finite Field of size 3 with 2 generators (73[0 1 0] [0 1 0]74[0 0 1] [1 0 0]75[1 0 0], [0 0 1]76)77sage: G.gap()78Group([ [ [ 0*Z(3), Z(3)^0, 0*Z(3) ], [ 0*Z(3), 0*Z(3), Z(3)^0 ], [ Z(3)^0, 0*Z(3), 0*Z(3) ] ],79[ [ 0*Z(3), Z(3)^0, 0*Z(3) ], [ Z(3)^0, 0*Z(3), 0*Z(3) ], [ 0*Z(3), 0*Z(3), Z(3)^0 ] ] ])8081TESTS::8283sage: M = MatrixSpace(GF(5),2,2)84sage: A = M([1,0,0,1])85sage: A - int(-1)86[2 0]87[0 2]88sage: B = M([4,0,0,1])89sage: B - int(-1)90[0 0]91[0 2]92sage: Matrix(GF(5),0,0, sparse=False).inverse()93[]94"""959697include "sage/ext/interrupt.pxi"98include "sage/ext/cdefs.pxi"99include 'sage/ext/stdsage.pxi'100include 'sage/ext/random.pxi'101from cpython.string cimport *102103cimport sage.rings.fast_arith104import sage.rings.fast_arith105cdef sage.rings.fast_arith.arith_int ArithIntObj106ArithIntObj = sage.rings.fast_arith.arith_int()107108109# TODO: DO NOT change this back until all the ints, etc., below are changed110# and get_unsafe is rewritten to return the right thing. E.g., with111# the above uncommented, on 64-bit,112# m =matrix(Integers(101^3),2,[824362, 606695, 641451, 205942])113# m.det()114# --> gives 0, which is totally wrong.115116import matrix_window_modn_dense117118from sage.modules.vector_modn_dense cimport Vector_modn_dense119120from sage.rings.arith import is_prime121from sage.structure.element cimport ModuleElement122123cimport matrix_dense124cimport matrix125cimport matrix0126cimport sage.structure.element127128from sage.matrix.matrix_modn_dense_float cimport Matrix_modn_dense_float129from sage.matrix.matrix_modn_dense_double cimport Matrix_modn_dense_double130131from sage.structure.element cimport Matrix132133from sage.rings.finite_rings.integer_mod cimport IntegerMod_int, IntegerMod_abstract134135from sage.misc.misc import verbose, get_verbose, cputime136137from sage.rings.integer cimport Integer138139from sage.structure.element cimport ModuleElement, RingElement, Element, Vector140141from matrix_integer_dense cimport Matrix_integer_dense142from sage.rings.integer_ring import ZZ143144################145from sage.rings.fast_arith cimport arith_int146cdef arith_int ai147ai = arith_int()148################149150from sage.structure.proof.proof import get_flag as get_proof_flag151152cdef long num = 1153cdef bint little_endian = (<char*>(&num))[0]154155def __matrix_from_rows_of_matrices(X):156"""157Return a matrix whose ith row is ``X[i].list()``.158159INPUT:160161- ``X`` - a nonempty list of matrices of the same size mod a162single modulus ``p``163164OUTPUT: A single matrix mod p whose ith row is ``X[i].list()``.165166167"""168# The code below is just a fast version of the following:169## from constructor import matrix170## K = X[0].base_ring()171## v = sum([y.list() for y in X],[])172## return matrix(K, len(X), X[0].nrows()*X[0].ncols(), v)173174from matrix_space import MatrixSpace175cdef Matrix_modn_dense A, T176cdef Py_ssize_t i, n, m177n = len(X)178179T = X[0]180m = T._nrows * T._ncols181A = Matrix_modn_dense.__new__(Matrix_modn_dense, MatrixSpace(X[0].base_ring(), n, m), 0, 0, 0)182A.p = T.p183A.gather = T.gather184185for i from 0 <= i < n:186T = X[i]187memcpy(A._entries + i*m, T._entries, sizeof(mod_int)*m)188return A189190cpdef is_Matrix_modn_dense(self):191"""192"""193return isinstance(self, Matrix_modn_dense) | isinstance(self, Matrix_modn_dense_float) | isinstance(self, Matrix_modn_dense_double)194195##############################################################################196# Copyright (C) 2004,2005,2006 William Stein <[email protected]>197# Distributed under the terms of the GNU General Public License (GPL)198# The full text of the GPL is available at:199# http://www.gnu.org/licenses/200##############################################################################201202cdef class Matrix_modn_dense(matrix_dense.Matrix_dense):203########################################################################204# LEVEL 1 functionality205# x * __cinit__206# x * __dealloc__207# x * __init__208# x * set_unsafe209# x * get_unsafe210# x * __richcmp__ -- always the same211########################################################################212def __cinit__(self, parent, entries, copy, coerce):213from sage.misc.superseded import deprecation214deprecation(4260, "This class is replaced by Matrix_modn_dense_float/Matrix_modn_dense_double.")215216matrix_dense.Matrix_dense.__init__(self, parent)217218cdef long p219p = self._base_ring.characteristic()220self.p = p221MAX_MODULUS = 2**23222if p >= MAX_MODULUS:223raise OverflowError, "p (=%s) must be < %s"%(p, MAX_MODULUS)224self.gather = MOD_INT_OVERFLOW/<mod_int>(p*p)225226if not isinstance(entries, list):227sig_on()228self._entries = <mod_int *> sage_calloc(self._nrows*self._ncols,sizeof(mod_int))229sig_off()230else:231sig_on()232self._entries = <mod_int *> sage_malloc(self._nrows*self._ncols * sizeof(mod_int))233sig_off()234235if self._entries == NULL:236raise MemoryError, "Error allocating matrix"237238self._matrix = <mod_int **> sage_malloc(sizeof(mod_int*)*self._nrows)239if self._matrix == NULL:240sage_free(self._entries)241self._entries = NULL242raise MemoryError, "Error allocating memory"243244cdef mod_int k245cdef Py_ssize_t i246k = 0247for i from 0 <= i < self._nrows:248self._matrix[i] = self._entries + k249k = k + self._ncols250251def __dealloc__(self):252if self._entries == NULL:253return254sage_free(self._entries)255sage_free(self._matrix)256257def __init__(self, parent, entries, copy, coerce):258"""259TESTS::260261sage: matrix(GF(7), 2, 2, [-1, int(-2), GF(7)(-3), 1/4])262[6 5]263[4 2]264"""265cdef mod_int e266cdef Py_ssize_t i, j, k267cdef mod_int *v268cdef long p269p = self._base_ring.characteristic()270271R = self.base_ring()272273# scalar?274if not isinstance(entries, list):275# sig_on()276# for i from 0 <= i < self._nrows*self._ncols:277# self._entries[i] = 0278# sig_off()279if entries is None:280# zero matrix281pass282else:283e = R(entries)284if e != 0:285for i from 0 <= i < min(self._nrows, self._ncols):286self._matrix[i][i] = e287return288289# all entries are given as a long list290if len(entries) != self._nrows * self._ncols:291raise IndexError, "The vector of entries has the wrong length."292293k = 0294cdef mod_int n295cdef long tmp296297for i from 0 <= i < self._nrows:298sig_check()299v = self._matrix[i]300for j from 0 <= j < self._ncols:301x = entries[k]302if PY_TYPE_CHECK_EXACT(x, int):303tmp = (<long>x) % p304v[j] = tmp + (tmp<0)*p305elif PY_TYPE_CHECK_EXACT(x, IntegerMod_int) and (<IntegerMod_int>x)._parent is R:306v[j] = (<IntegerMod_int>x).ivalue307elif PY_TYPE_CHECK_EXACT(x, Integer):308if coerce:309v[j] = mpz_fdiv_ui((<Integer>x).value, p)310else:311v[j] = mpz_get_ui((<Integer>x).value)312elif coerce:313v[j] = R(entries[k])314else:315v[j] = <long>(entries[k])316k = k + 1317318def __richcmp__(Matrix_modn_dense self, right, int op): # always need for mysterious reasons.319return self._richcmp(right, op)320321def __hash__(self):322"""323EXAMPLE::324325sage: B = random_matrix(GF(127),3,3)326sage: B.set_immutable()327sage: {B:0} # indirect doctest328{[ 9 75 94]329[ 4 57 112]330[ 59 85 45]: 0}331332::333334sage: M = random_matrix(GF(7), 10, 10)335sage: M.set_immutable()336sage: hash(M)337143338sage: MZ = M.change_ring(ZZ)339sage: MZ.set_immutable()340sage: hash(MZ)341143342sage: MS = M.sparse_matrix()343sage: MS.set_immutable()344sage: hash(MS)345143346347TEST::348349sage: A = matrix(GF(2),2,0)350sage: hash(A)351Traceback (most recent call last):352...353TypeError: mutable matrices are unhashable354sage: A.set_immutable()355sage: hash(A)3560357"""358if self.is_mutable():359raise TypeError("mutable matrices are unhashable")360x = self.fetch('hash')361if not x is None:362return x363364cdef long _hash = 0365cdef mod_int *_matrix366cdef long n = 0367cdef Py_ssize_t i, j368369if self._nrows == 0 or self._ncols == 0:370return 0371372sig_on()373for i from 0 <= i < self._nrows:374_matrix = self._matrix[i]375for j from 0 <= j < self._ncols:376_hash ^= (n * _matrix[j])377n+=1378sig_off()379380if _hash == -1:381return -2382383self.cache('hash', _hash)384385return _hash386387cdef set_unsafe_int(self, Py_ssize_t i, Py_ssize_t j, int value):388"""389Set the (i,j) entry of self to the int value.390"""391self._matrix[i][j] = value392393cdef set_unsafe(self, Py_ssize_t i, Py_ssize_t j, value):394"""395Set the (i,j) entry of self to the value, which is assumed396to be of type IntegerMod_int.397"""398self._matrix[i][j] = (<IntegerMod_int> value).ivalue399400cdef get_unsafe(self, Py_ssize_t i, Py_ssize_t j):401cdef IntegerMod_int n402n = IntegerMod_int.__new__(IntegerMod_int)403IntegerMod_abstract.__init__(n, self._base_ring)404n.ivalue = self._matrix[i][j]405return n406407########################################################################408# LEVEL 2 functionality409# * cdef _pickle410# * cdef _unpickle411# x * cdef _add_412# * cdef _mul_413# x * cdef _matrix_times_matrix_414# x * cdef _cmp_c_impl415# x * __neg__416# * __invert__417# x * __copy__418# * _multiply_classical419# * _list -- list of underlying elements (need not be a copy)420# * _dict -- sparse dictionary of underlying elements (need not be a copy)421########################################################################422# def _pickle(self):423# def _unpickle(self, data, int version): # use version >= 0424# cpdef ModuleElement _add_(self, ModuleElement right):425# cdef _mul_(self, Matrix right):426# cdef int _cmp_c_impl(self, Matrix right) except -2:427# def __invert__(self):428# def _multiply_classical(left, matrix.Matrix _right):429# def _list(self):430# def _dict(self):431432def _pickle(self):433"""434Utility function for pickling.435436If the prime is small enough to fit in a byte, then it is stored as437a contiguous string of bytes (to save space). Otherwise, memcpy is438used to copy the raw data in the platforms native format. Any439byte-swapping or word size difference is taken care of in440unpickling (optimizing for unpickling on the same platform things441were pickled on).442443The upcoming buffer protocol would be useful to not have to do any444copying.445446EXAMPLES::447448sage: m = matrix(Integers(128), 3, 3, [ord(c) for c in "Hi there!"]); m449[ 72 105 32]450[116 104 101]451[114 101 33]452sage: m._pickle()453((1, ..., 'Hi there!'), 10)454"""455cdef Py_ssize_t i, j456cdef unsigned char* ss457cdef unsigned char* row_ss458cdef long word_size459cdef mod_int *row_self460461if self.p <= 0xFF:462word_size = sizeof(char)463else:464word_size = sizeof(mod_int)465466s = PyString_FromStringAndSize(NULL, word_size * self._nrows * self._ncols)467ss = <unsigned char*><char *>s468469sig_on()470if word_size == sizeof(char):471for i from 0 <= i < self._nrows:472row_self = self._matrix[i]473row_ss = &ss[i*self._ncols]474for j from 0<= j < self._ncols:475row_ss[j] = row_self[j]476else:477for i from 0 <= i < self._nrows:478memcpy(&ss[i*sizeof(mod_int)*self._ncols], self._matrix[i], sizeof(mod_int) * self._ncols)479sig_off()480481return (word_size, little_endian, s), 10482483484def _unpickle(self, data, int version):485r"""486TESTS:487488Test for char-sized modulus::489490sage: A = random_matrix(GF(7), 5, 9)491sage: data, version = A._pickle()492sage: B = A.parent()(0)493sage: B._unpickle(data, version)494sage: B == A495True496497And for larger modulus::498499sage: A = random_matrix(GF(1009), 51, 5)500sage: data, version = A._pickle()501sage: B = A.parent()(0)502sage: B._unpickle(data, version)503sage: B == A504True505506Now test all the bit-packing options::507508sage: A = matrix(Integers(1000), 2, 2)509sage: A._unpickle((1, True, '\x01\x02\xFF\x00'), 10)510sage: A511[ 1 2]512[255 0]513514::515516sage: A = matrix(Integers(1000), 1, 2)517sage: A._unpickle((4, True, '\x02\x01\x00\x00\x01\x00\x00\x00'), 10)518sage: A519[258 1]520sage: A._unpickle((4, False, '\x00\x00\x02\x01\x00\x00\x01\x03'), 10)521sage: A522[513 259]523sage: A._unpickle((8, True, '\x03\x01\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00'), 10)524sage: A525[259 5]526sage: A._unpickle((8, False, '\x00\x00\x00\x00\x00\x00\x02\x08\x00\x00\x00\x00\x00\x00\x01\x04'), 10)527sage: A528[520 260]529530Now make sure it works in context::531532sage: A = random_matrix(Integers(33), 31, 31)533sage: loads(dumps(A)) == A534True535sage: A = random_matrix(Integers(3333), 31, 31)536sage: loads(dumps(A)) == A537True538"""539540if version < 10:541return matrix_dense.Matrix_dense._unpickle(self, data, version)542543cdef Py_ssize_t i, j544cdef unsigned char* ss545cdef unsigned char* row_ss546cdef long word_size547cdef mod_int *row_self548cdef bint little_endian_data549cdef unsigned char* udata550551if version == 10:552word_size, little_endian_data, s = data553ss = <unsigned char*><char *>s554555sig_on()556if word_size == sizeof(char):557for i from 0 <= i < self._nrows:558row_self = self._matrix[i]559row_ss = &ss[i*self._ncols]560for j from 0<= j < self._ncols:561row_self[j] = row_ss[j]562563elif word_size == sizeof(mod_int) and little_endian == little_endian_data:564for i from 0 <= i < self._nrows:565memcpy(self._matrix[i], &ss[i*sizeof(mod_int)*self._ncols], sizeof(mod_int) * self._ncols)566567# Note that mod_int is at least 32 bits, and never stores more than 32 bits of info568elif little_endian_data:569for i from 0 <= i < self._nrows:570row_self = self._matrix[i]571for j from 0<= j < self._ncols:572udata = &ss[(i*self._ncols+j)*word_size]573row_self[j] = ((udata[0]) +574(udata[1] << 8) +575(udata[2] << 16) +576(udata[3] << 24))577578else:579for i from 0 <= i < self._nrows:580row_self = self._matrix[i]581for j from 0<= j < self._ncols:582udata = &ss[(i*self._ncols+j)*word_size]583row_self[j] = ((udata[word_size-1]) +584(udata[word_size-2] << 8) +585(udata[word_size-3] << 16) +586(udata[word_size-4] << 24))587588sig_off()589590else:591raise RuntimeError, "unknown matrix version"592593594cdef long _hash(self) except -1:595"""596TESTS::597598sage: a = random_matrix(GF(11), 5, 5)599sage: a.set_immutable()600sage: hash(a) #random601216602sage: b = a.change_ring(ZZ)603sage: b.set_immutable()604sage: hash(b) == hash(a)605True606"""607x = self.fetch('hash')608if not x is None: return x609610if not self._is_immutable:611raise TypeError, "mutable matrices are unhashable"612613cdef Py_ssize_t i614cdef long h = 0, n = 0615616sig_on()617for i from 0 <= i < self._nrows:618for j from 0<= j < self._ncols:619h ^= n * self._matrix[i][j]620n += 1621sig_off()622623self.cache('hash', h)624return h625626627def __neg__(self):628"""629EXAMPLES::630631sage: m = matrix(GF(19), 3, 3, range(9)); m632[0 1 2]633[3 4 5]634[6 7 8]635sage: -m636[ 0 18 17]637[16 15 14]638[13 12 11]639"""640cdef Py_ssize_t i,j641cdef Matrix_modn_dense M642cdef mod_int p = self.p643644M = Matrix_modn_dense.__new__(Matrix_modn_dense, self._parent,None,None,None)645M.p = p646647sig_on()648cdef mod_int *row_self, *row_ans649for i from 0 <= i < self._nrows:650row_self = self._matrix[i]651row_ans = M._matrix[i]652for j from 0<= j < self._ncols:653if row_self[j]:654row_ans[j] = p - row_self[j]655else:656row_ans[j] = 0657sig_off()658return M659660661cpdef ModuleElement _lmul_(self, RingElement right):662"""663EXAMPLES::664665sage: a = random_matrix(Integers(60), 400, 500)666sage: 3*a + 9*a == 12*a667True668"""669return self._rmul_(right)670671cpdef ModuleElement _rmul_(self, RingElement left):672"""673EXAMPLES::674675sage: a = matrix(GF(101), 3, 3, range(9)); a676[0 1 2]677[3 4 5]678[6 7 8]679sage: a * 5680[ 0 5 10]681[15 20 25]682[30 35 40]683sage: a * 50684[ 0 50 100]685[ 49 99 48]686[ 98 47 97]687"""688cdef Py_ssize_t i,j689cdef Matrix_modn_dense M690cdef mod_int p = self.p691cdef mod_int a = left692693M = Matrix_modn_dense.__new__(Matrix_modn_dense, self._parent,None,None,None)694M.p = p695696sig_on()697cdef mod_int *row_self, *row_ans698for i from 0 <= i < self._nrows:699row_self = self._matrix[i]700row_ans = M._matrix[i]701for j from 0<= j < self._ncols:702row_ans[j] = (a*row_self[j]) % p703sig_off()704return M705706def __copy__(self):707cdef Matrix_modn_dense A708A = Matrix_modn_dense.__new__(Matrix_modn_dense, self._parent,7090, 0, 0)710memcpy(A._entries, self._entries, sizeof(mod_int)*self._nrows*self._ncols)711A.p = self.p712A.gather = self.gather713if self._subdivisions is not None:714A.subdivide(*self.subdivisions())715return A716717718cpdef ModuleElement _add_(self, ModuleElement right):719"""720Add two dense matrices over Z/nZ721722EXAMPLES::723724sage: a = MatrixSpace(GF(19),3)(range(9))725sage: a+a726[ 0 2 4]727[ 6 8 10]728[12 14 16]729sage: b = MatrixSpace(GF(19),3)(range(9))730sage: b.swap_rows(1,2)731sage: a+b732[ 0 2 4]733[ 9 11 13]734[ 9 11 13]735sage: b+a736[ 0 2 4]737[ 9 11 13]738[ 9 11 13]739"""740741cdef Py_ssize_t i,j742cdef mod_int k, p743cdef Matrix_modn_dense M744745M = Matrix_modn_dense.__new__(Matrix_modn_dense, self._parent,None,None,None)746Matrix.__init__(M, self._parent)747p = self.p748749sig_on()750cdef mod_int *row_self, *row_right, *row_ans751for i from 0 <= i < self._nrows:752row_self = self._matrix[i]753row_right = (<Matrix_modn_dense> right)._matrix[i]754row_ans = M._matrix[i]755for j from 0<= j < self._ncols:756k = row_self[j] + row_right[j]757row_ans[j] = k - (k >= p) * p758sig_off()759return M760761762cpdef ModuleElement _sub_(self, ModuleElement right):763"""764Subtract two dense matrices over Z/nZ765766EXAMPLES::767768sage: a = matrix(GF(11), 3, 3, range(9)); a769[0 1 2]770[3 4 5]771[6 7 8]772sage: a - 4773[7 1 2]774[3 0 5]775[6 7 4]776sage: a - matrix(GF(11), 3, 3, range(1, 19, 2))777[10 9 8]778[ 7 6 5]779[ 4 3 2]780"""781782cdef Py_ssize_t i,j783cdef mod_int k, p784cdef Matrix_modn_dense M785786M = Matrix_modn_dense.__new__(Matrix_modn_dense, self._parent,None,None,None)787Matrix.__init__(M, self._parent)788p = self.p789790sig_on()791cdef mod_int *row_self, *row_right, *row_ans792for i from 0 <= i < self._nrows:793row_self = self._matrix[i]794row_right = (<Matrix_modn_dense> right)._matrix[i]795row_ans = M._matrix[i]796for j from 0<= j < self._ncols:797k = p + row_self[j] - row_right[j]798row_ans[j] = k - (k >= p) * p799sig_off()800return M801802803cdef int _cmp_c_impl(self, Element right) except -2:804"""805Compare two dense matrices over Z/nZ806807EXAMPLES::808809sage: a = matrix(GF(17), 4, range(3, 83, 5)); a810[ 3 8 13 1]811[ 6 11 16 4]812[ 9 14 2 7]813[12 0 5 10]814sage: a == a815True816sage: b = a - 3; b817[ 0 8 13 1]818[ 6 8 16 4]819[ 9 14 16 7]820[12 0 5 7]821sage: b < a822True823sage: b > a824False825sage: b == a826False827sage: b + 3 == a828True829"""830831cdef Py_ssize_t i, j832cdef int cmp833834sig_on()835cdef mod_int *row_self, *row_right836for i from 0 <= i < self._nrows:837row_self = self._matrix[i]838row_right = (<Matrix_modn_dense> right)._matrix[i]839for j from 0 <= j < self._ncols:840if row_self[j] < row_right[j]:841sig_off()842return -1843elif row_self[j] > row_right[j]:844sig_off()845return 1846#cmp = memcmp(row_self, row_right, sizeof(mod_int)*self._ncols)847#if cmp:848# return cmp849sig_off()850return 0851852853cdef Matrix _matrix_times_matrix_(self, Matrix right):854if get_verbose() >= 2:855verbose('mod-p multiply of %s x %s matrix by %s x %s matrix modulo %s'%(856self._nrows, self._ncols, right._nrows, right._ncols, self.p))857if self._will_use_strassen(right):858return self._multiply_strassen(right)859else:860return self._multiply_classical(right)861862def _multiply_classical(left, right):863return left._multiply_strassen(right, left._ncols + left._nrows)864865cdef Vector _vector_times_matrix_(self, Vector v):866cdef Vector_modn_dense w, ans867cdef Py_ssize_t i, j868cdef mod_int k869cdef mod_int x870871M = self._row_ambient_module()872w = v873ans = M.zero_vector()874875for i from 0 <= i < self._ncols:876x = 0877k = 0878for j from 0 <= j < self._nrows:879x += w._entries[j] * self._matrix[j][i]880k += 1881if k >= self.gather:882x %= self.p883k = 0884ans._entries[i] = x % self.p885return ans886887888########################################################################889# LEVEL 3 functionality (Optional)890# x * cdef _sub_891# * __deepcopy__892# * __invert__893# * Matrix windows -- only if you need strassen for that base894# * Other functions (list them here):895# - all row/column operations, but optimized896# x - echelon form in place897# - Hessenberg forms of matrices898########################################################################899900901def charpoly(self, var='x', algorithm='generic'):902"""903Returns the characteristic polynomial of self.904905INPUT:906907- ``var`` - a variable name908- ``algorithm`` - 'generic' (default)909910EXAMPLES::911912sage: A = Mat(GF(7),3,3)(range(3)*3)913sage: A.charpoly()914x^3 + 4*x^2915916sage: A = Mat(Integers(6),3,3)(range(9))917sage: A.charpoly()918x^3919"""920if algorithm == 'generic':921g = matrix_dense.Matrix_dense.charpoly(self, var)922else:923raise ValueError, "no algorithm '%s'"%algorithm924self.cache('charpoly_%s_%s'%(algorithm, var), g)925return g926927def minpoly(self, var='x', algorithm='generic', proof=None):928"""929Returns the minimal polynomial of self.930931INPUT:932933- ``var`` - a variable name934- ``algorithm`` - 'generic' (default)935936- ``proof`` -- (default: True); whether to provably return937the true minimal polynomial; if False, we only guarantee938to return a divisor of the minimal polynomial. There are939also certainly cases where the computed results is940frequently not exactly equal to the minimal polynomial941(but is instead merely a divisor of it).942943WARNING: If proof=True, minpoly is insanely slow compared to944proof=False.945946EXAMPLES::947948sage: R.<x>=GF(3)[]949sage: A = matrix(GF(3),2,[0,0,1,2])950sage: A.minpoly()951x^2 + x952953Minpoly with proof=False is *dramatically* ("millions" of954times!) faster than minpoly with proof=True. This matters955since proof=True is the default, unless you first type956''proof.linear_algebra(False)''.::957958sage: A.minpoly(proof=False) in [x, x+1, x^2+x]959True960"""961962proof = get_proof_flag(proof, "linear_algebra")963964if algorithm == 'generic':965raise NotImplementedError, "minimal polynomials are not implemented for Z/nZ"966else:967raise ValueError, "no algorithm '%s'"%algorithm968self.cache('minpoly_%s_%s'%(algorithm, var), g)969return g970971def echelonize(self, algorithm="gauss", **kwds):972"""973Puts self in row echelon form.974975INPUT:976977- ``self`` - a mutable matrix978- ``algorithm``- ``'gauss'`` - uses a custom slower `O(n^3)`979Gauss elimination implemented in Sage.980- ``**kwds`` - these are all ignored981982983OUTPUT:984985- self is put in reduced row echelon form.986- the rank of self is computed and cached987- the pivot columns of self are computed and cached.988- the fact that self is now in echelon form is recorded and989cached so future calls to echelonize return immediately.990991EXAMPLES::992993sage: a = matrix(GF(97),3,4,range(12))994sage: a.echelonize(); a995[ 1 0 96 95]996[ 0 1 2 3]997[ 0 0 0 0]998sage: a.pivots()999(0, 1)1000"""1001x = self.fetch('in_echelon_form')1002if not x is None: return # already known to be in echelon form1003if not self.base_ring().is_field():1004#self._echelon_mod_n ()1005raise NotImplementedError, "Echelon form not implemented over '%s'."%self.base_ring()10061007self.check_mutability()1008self.clear_cache()10091010if algorithm == 'gauss':1011self._echelon_in_place_classical()1012else:1013raise ValueError, "algorithm '%s' not known"%algorithm10141015def _pivots(self):1016if not self.fetch('in_echelon_form'):1017raise RuntimeError, "self must be in reduced row echelon form first."1018pivots = []1019cdef Py_ssize_t i, j, nc1020nc = self._ncols1021cdef mod_int* row1022i = 01023while i < self._nrows:1024row = self._matrix[i]1025for j from i <= j < nc:1026if row[j] != 0:1027pivots.append(j)1028i += 11029break1030if j == nc:1031break1032return pivots10331034def _echelon_in_place_classical(self):1035self.check_mutability()1036self.clear_cache()10371038cdef Py_ssize_t start_row, c, r, nr, nc, i1039cdef mod_int p, a, s, t, b1040cdef mod_int **m10411042start_row = 01043p = self.p1044m = self._matrix1045nr = self._nrows1046nc = self._ncols1047pivots = []1048fifth = self._ncols / 10 + 11049do_verb = (get_verbose() >= 2)1050for c from 0 <= c < nc:1051if do_verb and (c % fifth == 0 and c>0):1052tm = verbose('on column %s of %s'%(c, self._ncols),1053level = 2,1054caller_name = 'matrix_modn_dense echelon')1055#end if1056sig_check()1057for r from start_row <= r < nr:1058a = m[r][c]1059if a:1060pivots.append(c)1061a_inverse = ai.c_inverse_mod_int(a, p)1062self._rescale_row_c(r, a_inverse, c)1063self.swap_rows_c(r, start_row)1064for i from 0 <= i < nr:1065if i != start_row:1066b = m[i][c]1067if b != 0:1068self._add_multiple_of_row_c(i, start_row, p-b, c)1069start_row = start_row + 11070break1071self.cache('pivots', tuple(pivots))1072self.cache('in_echelon_form',True)10731074cdef xgcd_eliminate (self, mod_int * row1, mod_int* row2, Py_ssize_t start_col):1075"""1076Reduces row1 and row2 by a unimodular transformation using the xgcd1077relation between their first coefficients a and b.10781079INPUT:108010811082- self: a mutable matrix10831084-````- row1, row2: the two rows to be transformed1085(within self)10861087-```` - start_col: the column of the pivots in row11088and row2. It is assumed that all entries before start_col in row11089and row2 are zero.109010911092OUTPUT:109310941095- g: the gcd of the first elements of row1 and1096row2 at column start_col10971098- put row1 = s \* row1 + t \* row2 row2 = w \*1099row1 + t \* row2 where g = sa + tb1100"""1101cdef mod_int p = self.p1102cdef mod_int * row1_p, * row2_p1103cdef mod_int tmp1104cdef int g, s, t, v, w1105cdef Py_ssize_t nc, i1106cdef mod_int a = row1[start_col]1107cdef mod_int b = row2[start_col]1108g = ArithIntObj.c_xgcd_int (a,b,<int*>&s,<int*>&t)1109v = a/g1110w = -<int>b/g1111nc = self.ncols()11121113# print("In wgcd_eliminate")1114for i from start_col <= i < nc:1115# print(self)1116tmp = ( s * <int>row1[i] + t * <int>row2[i]) % p1117# print (tmp,s, <int>row1[i],t,<int>row2[i])1118# print (row2[i],w, <int>row1[i],v,<int>row2[i])1119row2[i] = (w* <int>row1[i] + v*<int>row2[i]) % p1120# print (row2[i],w, <int>row1[i],v,<int>row2[i])1121row1[i] = tmp1122#print(self)1123# print("sortie")1124return g112511261127## This is code by William Stein and/or Clement Pernet from SD7. Unfortunately I (W.S.)1128## think it is still buggy, since it is so painful to implement with1129## unsigned ints. Code to do basically the same thing is in1130## matrix_integer_dense, by Burcin Erocal.1131## def _echelon_mod_n (self):1132## """1133## Put self in Hermite normal form modulo n1134## (echelonize the matrix over a ring $Z_n$)11351136## INPUT:1137## self: a mutable matrix over $Z_n$1138## OUTPUT:1139## Transform in place the working matrix into its Hermite1140## normal form over Z, using the modulo n algorithm of1141## [Hermite Normal form computation using modulo determinant arithmetic,1142## Domich Kannan & Trotter, 1987]1143## """1144## self.check_mutability()1145## self.clear_cache()11461147## cdef Py_ssize_t start_row, nr, nc,1148## cdef long c, r, i1149## cdef mod_int p, a, a_inverse, b, g1150## cdef mod_int **m1151## cdef Py_ssize_t start_row = 01152## p = self.p1153## m = self._matrix1154## nr = self._nrows1155## nc = self._ncols1156## pivots = []1157## cdef Py_ssize_t fifth = self._ncols / 10 + 11158## do_verb = (get_verbose() >= 2)1159## for c from 0 <= c < nc:1160## if do_verb and (c % fifth == 0 and c>0):1161## tm = verbose('on column %s of %s'%(c, self._ncols),1162## level = 2,1163## caller_name = 'matrix_modn_dense echelon mod n')11641165## sig_check()1166## for r from start_row <= r < nr:1167## a = m[r][c]1168## if a:1169## self.swap_rows_c(r, start_row)1170## for i from start_row +1 <= i < nr:1171## b = m[i][c]11721173## if b != 0:1174## self.xgcd_eliminate (self._matrix[start_row], self._matrix[i], c)1175## verbose('eliminating rows %s and %s', (start_row,i))1176## for i from 0 <= i <start_row:1177## p = -m[i][c]//m[start_row][c]1178## self._add_multiple_of_row_c(i, start_row, p, c)11791180## pivots.append(m[start_row][c])1181## start_row = start_row + 11182## break1183## self.cache('pivots',pivots)1184## self.cache('in_echelon_form',True)118511861187cdef rescale_row_c(self, Py_ssize_t row, multiple, Py_ssize_t start_col):1188self._rescale_row_c(row, multiple, start_col)11891190cdef _rescale_row_c(self, Py_ssize_t row, mod_int multiple, Py_ssize_t start_col):1191cdef mod_int r, p1192cdef mod_int* v1193cdef Py_ssize_t i1194p = self.p1195v = self._matrix[row]1196for i from start_col <= i < self._ncols:1197v[i] = (v[i]*multiple) % p11981199cdef rescale_col_c(self, Py_ssize_t col, multiple, Py_ssize_t start_row):1200self._rescale_col_c(col, multiple, start_row)12011202cdef _rescale_col_c(self, Py_ssize_t col, mod_int multiple, Py_ssize_t start_row):1203"""1204EXAMPLES::12051206sage: n=3; b = MatrixSpace(Integers(37),n,n,sparse=False)([1]*n*n)1207sage: b1208[1 1 1]1209[1 1 1]1210[1 1 1]1211sage: b.rescale_col(1,5)1212sage: b1213[1 5 1]1214[1 5 1]1215[1 5 1]12161217Rescaling need not include the entire row.12181219::12201221sage: b.rescale_col(0,2,1); b1222[1 5 1]1223[2 5 1]1224[2 5 1]12251226Bounds are checked.12271228::12291230sage: b.rescale_col(3,2)1231Traceback (most recent call last):1232...1233IndexError: matrix column index out of range12341235Rescaling by a negative number::12361237sage: b.rescale_col(2,-3); b1238[ 1 5 34]1239[ 2 5 34]1240[ 2 5 34]1241"""1242cdef mod_int r, p1243cdef mod_int* v1244cdef Py_ssize_t i1245p = self.p1246for i from start_row <= i < self._nrows:1247self._matrix[i][col] = (self._matrix[i][col]*multiple) % p12481249cdef add_multiple_of_row_c(self, Py_ssize_t row_to, Py_ssize_t row_from, multiple,1250Py_ssize_t start_col):1251self._add_multiple_of_row_c(row_to, row_from, multiple, start_col)12521253cdef _add_multiple_of_row_c(self, Py_ssize_t row_to, Py_ssize_t row_from, mod_int multiple,1254Py_ssize_t start_col):1255cdef mod_int p1256cdef mod_int *v_from, *v_to12571258p = self.p1259v_from = self._matrix[row_from]1260v_to = self._matrix[row_to]12611262cdef Py_ssize_t i, nc1263nc = self._ncols1264for i from start_col <= i < nc:1265v_to[i] = (multiple * v_from[i] + v_to[i]) % p12661267cdef add_multiple_of_column_c(self, Py_ssize_t col_to, Py_ssize_t col_from, s,1268Py_ssize_t start_row):1269self._add_multiple_of_column_c(col_to, col_from, s, start_row)12701271cdef _add_multiple_of_column_c(self, Py_ssize_t col_to, Py_ssize_t col_from, mod_int multiple,1272Py_ssize_t start_row):1273cdef mod_int p1274cdef mod_int **m12751276m = self._matrix1277p = self.p12781279cdef Py_ssize_t i, nr1280nr = self._nrows1281for i from start_row <= i < self._nrows:1282m[i][col_to] = (m[i][col_to] + multiple * m[i][col_from]) %p12831284cdef swap_rows_c(self, Py_ssize_t row1, Py_ssize_t row2):1285"""1286EXAMPLES::12871288sage: A = matrix(Integers(8), 2,[1,2,3,4])1289sage: A.swap_rows(0,1)1290sage: A1291[3 4]1292[1 2]1293"""1294cdef mod_int* temp1295temp = self._matrix[row1]1296self._matrix[row1] = self._matrix[row2]1297self._matrix[row2] = temp12981299cdef swap_columns_c(self, Py_ssize_t col1, Py_ssize_t col2):1300cdef Py_ssize_t i, nr1301cdef mod_int t1302cdef mod_int **m1303m = self._matrix1304nr = self._nrows1305for i from 0 <= i < self._nrows:1306t = m[i][col1]1307m[i][col1] = m[i][col2]1308m[i][col2] = t13091310def hessenbergize(self):1311"""1312Transforms self in place to its Hessenberg form.1313"""1314self.check_mutability()1315x = self.fetch('in_hessenberg_form')1316if not x is None and x: return # already known to be in Hessenberg form13171318if self._nrows != self._ncols:1319raise ArithmeticError, "Matrix must be square to compute Hessenberg form."13201321cdef Py_ssize_t n1322n = self._nrows13231324cdef mod_int **h1325h = self._matrix13261327cdef mod_int p, r, t, t_inv, u1328cdef Py_ssize_t i, j, m1329p = self.p13301331sig_on()1332for m from 1 <= m < n-1:1333# Search for a nonzero entry in column m-11334i = -11335for r from m+1 <= r < n:1336if h[r][m-1]:1337i = r1338break13391340if i != -1:1341# Found a nonzero entry in column m-1 that is strictly1342# below row m. Now set i to be the first nonzero position >=1343# m in column m-1.1344if h[m][m-1]:1345i = m1346t = h[i][m-1]1347t_inv = ai.c_inverse_mod_int(t,p)1348if i > m:1349self.swap_rows_c(i,m)1350self.swap_columns_c(i,m)13511352# Now the nonzero entry in position (m,m-1) is t.1353# Use t to clear the entries in column m-1 below m.1354for j from m+1 <= j < n:1355if h[j][m-1]:1356u = (h[j][m-1] * t_inv) % p1357self._add_multiple_of_row_c(j, m, p - u, 0) # h[j] -= u*h[m]1358# To maintain charpoly, do the corresponding1359# column operation, which doesn't mess up the1360# matrix, since it only changes column m, and1361# we're only worried about column m-1 right1362# now. Add u*column_j to column_m.1363self._add_multiple_of_column_c(m, j, u, 0)1364# end for1365# end if1366# end for1367sig_off()1368self.cache('in_hessenberg_form',True)13691370def _charpoly_hessenberg(self, var):1371"""1372Transforms self in place to its Hessenberg form then computes and1373returns the coefficients of the characteristic polynomial of this1374matrix.13751376INPUT:137713781379- ``var`` - name of the indeterminate of the1380charpoly.138113821383The characteristic polynomial is represented as a vector of ints,1384where the constant term of the characteristic polynomial is the 0th1385coefficient of the vector.1386"""1387if self._nrows != self._ncols:1388raise ArithmeticError, "charpoly not defined for non-square matrix."13891390cdef Py_ssize_t i, m, n,1391n = self._nrows13921393cdef mod_int p, t1394p = self.p13951396# Replace self by its Hessenberg form, and set H to this form1397# for notation below.1398cdef Matrix_modn_dense H1399H = self.__copy__()1400H.hessenbergize()140114021403# We represent the intermediate polynomials that come up in1404# the calculations as rows of an (n+1)x(n+1) matrix, since1405# we've implemented basic arithmetic with such a matrix.1406# Please see the generic implementation of charpoly in1407# matrix.py to see more clearly how the following algorithm1408# actually works. (The implementation is clearer (but slower)1409# if one uses polynomials to represent polynomials instead of1410# using the rows of a matrix.) Also see Cohen's first GTM,1411# Algorithm 2.2.9.14121413cdef Matrix_modn_dense c1414c = self.new_matrix(nrows=n+1,ncols=n+1) # the 0 matrix1415c._matrix[0][0] = 11416for m from 1 <= m <= n:1417# Set the m-th row of c to (x - H[m-1,m-1])*c[m-1] = x*c[m-1] - H[m-1,m-1]*c[m-1]1418# We do this by hand by setting the m-th row to c[m-1]1419# shifted to the right by one. We then add1420# -H[m-1,m-1]*c[m-1] to the resulting m-th row.1421for i from 1 <= i <= n:1422c._matrix[m][i] = c._matrix[m-1][i-1]1423# the p-.. below is to keep scalar normalized between 0 and p.1424c._add_multiple_of_row_c(m, m-1, p - H._matrix[m-1][m-1], 0)1425t = 11426for i from 1 <= i < m:1427t = (t*H._matrix[m-i][m-i-1]) % p1428# Set the m-th row of c to c[m] - t*H[m-i-1,m-1]*c[m-i-1]1429c._add_multiple_of_row_c(m, m-i-1, p - (t*H._matrix[m-i-1][m-1])%p, 0)14301431# The answer is now the n-th row of c.1432v = []1433for i from 0 <= i <= n:1434v.append(int(c._matrix[n][i]))1435R = self._base_ring[var] # polynomial ring over the base ring1436return R(v)14371438def rank(self):1439"""1440Return the rank of this matrix.14411442EXAMPLES::14431444sage: m = matrix(GF(7),5,range(25))1445sage: m.rank()1446214471448Rank is not implemented over the integers modulo a composite yet.::14491450sage: m = matrix(Integers(4), 2, [2,2,2,2])1451sage: m.rank()1452Traceback (most recent call last):1453...1454NotImplementedError: Echelon form not implemented over 'Ring of integers modulo 4'.1455"""1456return matrix_dense.Matrix_dense.rank(self)14571458def determinant(self):1459"""1460Return the determinant of this matrix.14611462EXAMPLES::14631464sage: m = matrix(GF(101),5,range(25))1465sage: m.det()1466014671468::14691470sage: m = matrix(Integers(4), 2, [2,2,2,2])1471sage: m.det()1472014731474TESTS::14751476sage: m = random_matrix(GF(3), 3, 4)1477sage: m.determinant()1478Traceback (most recent call last):1479...1480ValueError: self must be a square matrix1481"""1482if self._nrows != self._ncols:1483raise ValueError, "self must be a square matrix"1484if self._nrows == 0:1485return self._coerce_element(1)14861487return matrix_dense.Matrix_dense.determinant(self)14881489def randomize(self, density=1, nonzero=False):1490"""1491Randomize ``density`` proportion of the entries of this matrix,1492leaving the rest unchanged.14931494INPUT:14951496- ``density`` - Integer; proportion (roughly) to be considered for1497changes1498- ``nonzero`` - Bool (default: ``False``); whether the new entries1499are forced to be non-zero15001501OUTPUT:15021503- None, the matrix is modified in-space15041505EXAMPLES::15061507sage: A = matrix(GF(5), 5, 5, 0)1508sage: A.randomize(0.5); A1509[0 0 0 2 0]1510[0 3 0 0 2]1511[4 0 0 0 0]1512[4 0 0 0 0]1513[0 1 0 0 0]1514sage: A.randomize(); A1515[3 3 2 1 2]1516[4 3 3 2 2]1517[0 3 3 3 3]1518[3 3 2 2 4]1519[2 2 2 1 4]1520"""1521density = float(density)1522if density <= 0:1523return1524if density > 1:1525density = float(1)15261527self.check_mutability()1528self.clear_cache()15291530cdef randstate rstate = current_randstate()1531cdef int nc1532cdef long pm115331534if not nonzero:1535# Original code, before adding the ``nonzero`` option.1536if density == 1:1537for i from 0 <= i < self._nrows*self._ncols:1538self._entries[i] = rstate.c_random() % self.p1539else:1540nc = self._ncols1541num_per_row = int(density * nc)1542sig_on()1543for i from 0 <= i < self._nrows:1544for j from 0 <= j < num_per_row:1545k = rstate.c_random() % nc1546self._matrix[i][k] = rstate.c_random() % self.p1547sig_off()1548else:1549# New code, to implement the ``nonzero`` option.1550pm1 = self.p - 11551if density == 1:1552for i from 0 <= i < self._nrows*self._ncols:1553self._entries[i] = (rstate.c_random() % pm1) + 11554else:1555nc = self._ncols1556num_per_row = int(density * nc)1557sig_on()1558for i from 0 <= i < self._nrows:1559for j from 0 <= j < num_per_row:1560k = rstate.c_random() % nc1561self._matrix[i][k] = (rstate.c_random() % pm1) + 11562sig_off()15631564cdef int _strassen_default_cutoff(self, matrix0.Matrix right) except -2:1565# TODO: lots of testing1566return 10015671568cpdef matrix_window(self, Py_ssize_t row=0, Py_ssize_t col=0,1569Py_ssize_t nrows=-1, Py_ssize_t ncols=-1,1570bint check=1):1571"""1572Return the requested matrix window.15731574EXAMPLES::15751576sage: a = matrix(GF(7),3,range(9)); a1577[0 1 2]1578[3 4 5]1579[6 0 1]1580sage: type(a)1581<type 'sage.matrix.matrix_modn_dense_float.Matrix_modn_dense_float'>15821583We test the optional check flag.15841585::15861587sage: matrix(GF(7),[1]).matrix_window(0,1,1,1)1588Traceback (most recent call last):1589...1590IndexError: matrix window index out of range1591sage: matrix(GF(7),[1]).matrix_window(0,1,1,1, check=False)1592Matrix window of size 1 x 1 at (0,1):1593[1]1594"""1595if nrows == -1:1596nrows = self._nrows - row1597ncols = self._ncols - col1598if check and (row < 0 or col < 0 or row + nrows > self._nrows or \1599col + ncols > self._ncols):1600raise IndexError, "matrix window index out of range"1601return matrix_window_modn_dense.MatrixWindow_modn_dense(self, row, col, nrows, ncols)16021603def _magma_init_(self, magma):1604"""1605Returns a string representation of self in Magma form.16061607INPUT:160816091610- ``magma`` - a Magma session161116121613OUTPUT: string16141615EXAMPLES::16161617sage: a = matrix(GF(389),2,2,[1..4])1618sage: magma(a) # optional - magma1619[ 1 2]1620[ 3 4]1621sage: a._magma_init_(magma) # optional - magma1622'Matrix(GF(389),2,2,StringToIntegerSequence("1 2 3 4"))'16231624A consistency check::16251626sage: a = random_matrix(GF(13),50); b = random_matrix(GF(13),50)1627sage: magma(a*b) == magma(a)*magma(b) # optional - magma1628True1629"""1630s = self.base_ring()._magma_init_(magma)1631return 'Matrix(%s,%s,%s,StringToIntegerSequence("%s"))'%(1632s, self._nrows, self._ncols, self._export_as_string())16331634cpdef _export_as_string(self):1635"""1636Return space separated string of the entries in this matrix.16371638EXAMPLES::16391640sage: w = matrix(GF(997),2,3,[1,2,5,-3,8,2]); w1641[ 1 2 5]1642[994 8 2]1643sage: w._export_as_string()1644'1 2 5 994 8 2'1645"""1646cdef int ndigits = len(str(self.p))16471648cdef Py_ssize_t i, n1649cdef char *s, *t16501651if self._nrows == 0 or self._ncols == 0:1652data = ''1653else:1654n = self._nrows*self._ncols*(ndigits + 1) + 2 # spaces between each number plus trailing null1655s = <char*> sage_malloc(n * sizeof(char))1656t = s1657sig_on()1658for i in range(self._nrows * self._ncols):1659sprintf(t, "%d ", self._entries[i])1660t += strlen(t)1661sig_off()1662data = str(s)[:-1]1663sage_free(s)1664return data16651666def _list(self):1667"""1668Return list of elements of self. This method is called by self.list().16691670EXAMPLES::16711672sage: w = matrix(GF(19), 2, 3, [1..6])1673sage: w.list()1674[1, 2, 3, 4, 5, 6]1675sage: w._list()1676[1, 2, 3, 4, 5, 6]1677sage: w.list()[0].parent()1678Finite Field of size 1916791680TESTS::16811682sage: w = random_matrix(GF(3),100)1683sage: w.parent()(w.list()) == w1684True1685"""1686cdef Py_ssize_t i, j1687F = self.base_ring()1688entries = []1689for i from 0 <= i < self._nrows:1690for j from 0<= j < self._ncols:1691entries.append(F(self._matrix[i][j]))1692return entries16931694def lift(self):1695"""1696Return the lift of this matrix to the integers.16971698EXAMPLES::16991700sage: a = matrix(GF(7),2,3,[1..6])1701sage: a.lift()1702[1 2 3]1703[4 5 6]1704sage: a.lift().parent()1705Full MatrixSpace of 2 by 3 dense matrices over Integer Ring17061707Subdivisions are preserved when lifting::17081709sage: a.subdivide([], [1,1]); a1710[1||2 3]1711[4||5 6]1712sage: a.lift()1713[1||2 3]1714[4||5 6]1715"""1716cdef Py_ssize_t i, j17171718cdef Matrix_integer_dense L1719L = Matrix_integer_dense.__new__(Matrix_integer_dense,1720self.parent().change_ring(ZZ),17210, 0, 0)1722cdef mpz_t* L_row1723cdef mod_int* A_row1724for i from 0 <= i < self._nrows:1725L_row = L._matrix[i]1726A_row = self._matrix[i]1727for j from 0 <= j < self._ncols:1728mpz_init_set_si(L_row[j], A_row[j])1729L._initialized = 11730L.subdivide(self.subdivisions())1731return L173217331734def _matrices_from_rows(self, Py_ssize_t nrows, Py_ssize_t ncols):1735"""1736Make a list of matrix from the rows of this matrix. This is a1737fairly technical function which is used internally, e.g., by1738the cyclotomic field linear algebra code.17391740INPUT:17411742- ``nrows, ncols`` - integers17431744OUTPUT:17451746- ``list`` - a list of matrices1747"""1748if nrows * ncols != self._ncols:1749raise ValueError, "nrows * ncols must equal self's number of columns"17501751from matrix_space import MatrixSpace1752F = self.base_ring()1753MS = MatrixSpace(F, nrows, ncols)17541755cdef Matrix_modn_dense M1756cdef Py_ssize_t i1757cdef Py_ssize_t n = nrows * ncols1758ans = []1759for i from 0 <= i < self._nrows:1760# Quickly construct a new mod-p matrix1761M = Matrix_modn_dense.__new__(Matrix_modn_dense, MS, 0,0,0)1762M.p = self.p1763M.gather = self.gather1764# Set the entries1765memcpy(M._entries, self._entries+i*n, sizeof(mod_int)*n)1766ans.append(M)1767return ans17681769_matrix_from_rows_of_matrices = staticmethod(__matrix_from_rows_of_matrices)177017711772