Path: blob/master/sage/matrix/matrix_integer_dense.pyx
4045 views
"""1Dense matrices over the integer ring23AUTHORS:45- William Stein67- Robert Bradshaw89EXAMPLES::1011sage: a = matrix(ZZ, 3,3, range(9)); a12[0 1 2]13[3 4 5]14[6 7 8]15sage: a.det()16017sage: a[0,0] = 10; a.det()18-3019sage: a.charpoly()20x^3 - 22*x^2 + 102*x + 3021sage: b = -3*a22sage: a == b23False24sage: b < a25True2627TESTS::2829sage: a = matrix(ZZ,2,range(4), sparse=False)30sage: TestSuite(a).run()31sage: Matrix(ZZ,0,0).inverse()32[]33"""3435########## *** IMPORTANT ***36# If you're working on this code, we *always* assume that37# self._matrix[i] = self._entries[i*self._ncols]38# !!!!!!!! Do not break this!39# This is assumed in the _rational_kernel_iml4041######################################################################42# Copyright (C) 2006,2007 William Stein43#44# Distributed under the terms of the GNU General Public License (GPL)45#46# The full text of the GPL is available at:47# http://www.gnu.org/licenses/48######################################################################4950from sage.modules.vector_integer_dense cimport Vector_integer_dense5152from sage.misc.misc import verbose, get_verbose, cputime5354from sage.rings.arith import previous_prime55from sage.structure.element import is_Element56from sage.structure.proof.proof import get_flag as get_proof_flag5758from sage.matrix.matrix_rational_dense cimport Matrix_rational_dense5960#########################################################61# PARI C library62from sage.libs.pari.gen cimport gen, PariInstance63from sage.libs.pari.gen import pari6465cdef extern from 'pari/pari.h':66GEN zeromat(long m, long n)67GEN mathnf0(GEN x,long flag)68GEN det0(GEN a,long flag)69GEN gcoeff(GEN,long,long)70GEN gtomat(GEN x)71GEN gel(GEN,long)72long glength(GEN x)73GEN ginv(GEN x)74long rank(GEN x)7576cdef extern from "convert.h":77cdef void t_INT_to_ZZ( mpz_t value, long *g )7879#########################################################8081include "../ext/interrupt.pxi"82include "../ext/stdsage.pxi"83include "../ext/gmp.pxi"84include "../ext/random.pxi"8586ctypedef unsigned int uint8788from sage.ext.multi_modular import MultiModularBasis89from sage.ext.multi_modular cimport MultiModularBasis9091from sage.rings.integer cimport Integer92from sage.rings.rational_field import QQ93from sage.rings.real_double import RDF94from sage.rings.integer_ring import ZZ, IntegerRing_class95from sage.rings.integer_ring cimport IntegerRing_class96from sage.rings.finite_rings.integer_mod_ring import IntegerModRing97from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing98from sage.structure.element cimport ModuleElement, RingElement, Element, Vector99from sage.structure.element import is_Vector100from sage.structure.sequence import Sequence101102from matrix_modn_dense_float cimport Matrix_modn_dense_template103from matrix_modn_dense_float cimport Matrix_modn_dense_float104from matrix_modn_dense_double cimport Matrix_modn_dense_double105106from matrix_mod2_dense import Matrix_mod2_dense107from matrix_mod2_dense cimport Matrix_mod2_dense108109from matrix_modn_dense cimport is_Matrix_modn_dense110111112from matrix2 import decomp_seq113114import sage.modules.free_module115import sage.modules.free_module_element116117from matrix cimport Matrix118119cimport sage.structure.element120121import sage.matrix.matrix_space as matrix_space122123################124# Used for modular HNF125from sage.rings.fast_arith cimport arith_int126cdef arith_int ai127ai = arith_int()128################129130######### linbox interface ##########131from sage.libs.linbox.linbox cimport Linbox_integer_dense, Linbox_modn_dense132cdef Linbox_integer_dense linbox133linbox = Linbox_integer_dense()134USE_LINBOX_POLY = True135136137########## iml -- integer matrix library ###########138139cdef extern from "iml.h":140141enum SOLU_POS:142LeftSolu = 101143RightSolu = 102144145long nullspaceMP(long n, long m,146mpz_t *A, mpz_t * *mp_N_pass)147148void nonsingSolvLlhsMM (SOLU_POS solupos, long n, \149long m, mpz_t *mp_A, mpz_t *mp_B, mpz_t *mp_N, \150mpz_t mp_D)151152153154cdef class Matrix_integer_dense(matrix_dense.Matrix_dense): # dense or sparse155r"""156Matrix over the integers.157158On a 32-bit machine, they can have at most `2^{32}-1` rows or159columns. On a 64-bit machine, matrices can have at most160`2^{64}-1` rows or columns.161162EXAMPLES::163164sage: a = MatrixSpace(ZZ,3)(2); a165[2 0 0]166[0 2 0]167[0 0 2]168sage: a = matrix(ZZ,1,3, [1,2,-3]); a169[ 1 2 -3]170sage: a = MatrixSpace(ZZ,2,4)(2); a171Traceback (most recent call last):172...173TypeError: nonzero scalar matrix must be square174"""175########################################################################176# LEVEL 1 functionality177# x * __cinit__178# x * __dealloc__179# x * __init__180# x * set_unsafe181# x * get_unsafe182# x * def _pickle183# x * def _unpickle184########################################################################185186def __cinit__(self, parent, entries, coerce, copy):187"""188Create and allocate memory for the matrix. Does not actually189initialize any of the memory.190191INPUT:192193194- ``parent, entries, coerce, copy`` - as for195__init__.196197198EXAMPLES::199200sage: from sage.matrix.matrix_integer_dense import Matrix_integer_dense201sage: a = Matrix_integer_dense.__new__(Matrix_integer_dense, Mat(ZZ,3), 0,0,0)202sage: type(a)203<type 'sage.matrix.matrix_integer_dense.Matrix_integer_dense'>204205.. warning::206207This is for internal use only, or if you really know what208you're doing.209"""210matrix_dense.Matrix_dense.__init__(self, parent)211self._nrows = parent.nrows()212self._ncols = parent.ncols()213self._pivots = None214215# Allocate an array where all the entries of the matrix are stored.216sig_on()217self._entries = <mpz_t *>sage_malloc(sizeof(mpz_t) * (self._nrows * self._ncols))218sig_off()219if self._entries == NULL:220raise MemoryError("out of memory allocating a matrix")221222# Allocate an array of pointers to the rows, which is useful for223# certain algorithms.224##################################225# *IMPORTANT*: FOR MATRICES OVER ZZ, WE ALWAYS ASSUME THAT226# THIS ARRAY IS *not* PERMUTED. This should be OK, since all227# algorithms are multi-modular.228##################################229self._matrix = <mpz_t **> sage_malloc(sizeof(mpz_t*)*self._nrows)230if self._matrix == NULL:231sage_free(self._entries)232self._entries = NULL233raise MemoryError("out of memory allocating a matrix")234235# Set each of the pointers in the array self._matrix to point236# at the memory for the corresponding row.237cdef Py_ssize_t i, k238k = 0239for i from 0 <= i < self._nrows:240self._matrix[i] = self._entries + k241k = k + self._ncols242243cdef _init_linbox(self):244sig_on()245linbox.set(self._matrix, self._nrows, self._ncols)246sig_off()247248def __copy__(self):249r"""250Returns a new copy of this matrix.251252EXAMPLES::253254sage: a = matrix(ZZ,1,3, [1,2,-3]); a255[ 1 2 -3]256sage: b = a.__copy__(); b257[ 1 2 -3]258sage: b is a259False260sage: b == a261True262"""263cdef Matrix_integer_dense A264A = Matrix_integer_dense.__new__(Matrix_integer_dense, self._parent,2650, 0, 0)266cdef Py_ssize_t i267sig_on()268for i from 0 <= i < self._nrows * self._ncols:269mpz_init_set(A._entries[i], self._entries[i])270sig_off()271A._initialized = True272if self._subdivisions is not None:273A.subdivide(*self.subdivisions())274return A275276def __hash__(self):277r"""278Returns hash of self.279280self must be immutable.281282EXAMPLES::283284sage: a = Matrix(ZZ,2,[1,2,3,4])285sage: hash(a)286Traceback (most recent call last):287...288TypeError: mutable matrices are unhashable289290::291292sage: a.set_immutable()293sage: hash(a)2948295"""296return self._hash()297298def __dealloc__(self):299"""300Frees all the memory allocated for this matrix. EXAMPLE::301302sage: a = Matrix(ZZ,2,[1,2,3,4])303sage: del a304"""305cdef Py_ssize_t i306if self._initialized:307for i from 0 <= i < (self._nrows * self._ncols):308mpz_clear(self._entries[i])309sage_free(self._entries)310sage_free(self._matrix)311312def __init__(self, parent, entries, copy, coerce):313r"""314Initialize a dense matrix over the integers.315316INPUT:317318319- ``parent`` - a matrix space320321- ``entries`` - list - create the matrix with those322entries along the rows.323324- ``other`` - a scalar; entries is coerced to an325integer and the diagonal entries of this matrix are set to that326integer.327328- ``coerce`` - whether need to coerce entries to the329integers (program may crash if you get this wrong)330331- ``copy`` - ignored (since integers are immutable)332333334EXAMPLES:335336The __init__ function is called implicitly in each of the337examples below to actually fill in the values of the matrix.338339We create a `2 \times 2` and a `1\times 4` matrix::340341sage: matrix(ZZ,2,2,range(4))342[0 1]343[2 3]344sage: Matrix(ZZ,1,4,range(4))345[0 1 2 3]346347If the number of columns isn't given, it is determined from the348number of elements in the list.349350::351352sage: matrix(ZZ,2,range(4))353[0 1]354[2 3]355sage: matrix(ZZ,2,range(6))356[0 1 2]357[3 4 5]358359Another way to make a matrix is to create the space of matrices and360coerce lists into it.361362::363364sage: A = Mat(ZZ,2); A365Full MatrixSpace of 2 by 2 dense matrices over Integer Ring366sage: A(range(4))367[0 1]368[2 3]369370Actually it is only necessary that the input can be coerced to a371list, so the following also works::372373sage: v = reversed(range(4)); type(v)374<type 'listreverseiterator'>375sage: A(v)376[3 2]377[1 0]378379Matrices can have many rows or columns (in fact, on a 64-bit380machine they could have up to `2^64-1` rows or columns)::381382sage: v = matrix(ZZ,1,10^5, range(10^5))383sage: v.parent()384Full MatrixSpace of 1 by 100000 dense matrices over Integer Ring385"""386cdef Py_ssize_t i, j387cdef bint is_list388cdef Integer x389390if entries is None:391x = ZZ(0)392is_list = 0393elif isinstance(entries, (int,long)) or is_Element(entries):394try:395x = ZZ(entries)396except TypeError:397self._initialized = False398raise TypeError("unable to coerce entry to an integer")399is_list = 0400else:401entries = list(entries)402is_list = 1403404if is_list:405406# Create the matrix whose entries are in the given entry list.407if len(entries) != self._nrows * self._ncols:408sage_free(self._entries)409sage_free(self._matrix)410self._entries = NULL411raise TypeError("entries has the wrong length")412if coerce:413for i from 0 <= i < self._nrows * self._ncols:414x = ZZ(entries[i])415# todo -- see integer.pyx and the TODO there; perhaps this could be416# sped up by creating a mpz_init_set_sage function.417mpz_init_set(self._entries[i], x.value)418self._initialized = True419else:420for i from 0 <= i < self._nrows * self._ncols:421mpz_init_set(self._entries[i], (<Integer> entries[i]).value)422self._initialized = True423else:424425# If x is zero, make the zero matrix and be done.426if mpz_sgn(x.value) == 0:427self._zero_out_matrix()428return429430# the matrix must be square:431if self._nrows != self._ncols:432sage_free(self._entries)433sage_free(self._matrix)434self._entries = NULL435raise TypeError("nonzero scalar matrix must be square")436437# Now we set all the diagonal entries to x and all other entries to 0.438self._zero_out_matrix()439j = 0440for i from 0 <= i < self._nrows:441mpz_set(self._entries[j], x.value)442j = j + self._nrows + 1443self._initialized = True444445cdef set_unsafe(self, Py_ssize_t i, Py_ssize_t j, value):446"""447Set position i,j of this matrix to x.448449(VERY UNSAFE - value *must* be of type Integer).450451INPUT:452453454- ``i`` - row455456- ``j`` - column457458- ``value`` - The value to set self[i,j] to. value459MUST be of type Integer460461462EXAMPLES::463464sage: a = matrix(ZZ,2,3, range(6)); a465[0 1 2]466[3 4 5]467sage: a[0,0] = 10468sage: a469[10 1 2]470[ 3 4 5]471"""472mpz_set(self._matrix[i][j], (<Integer>value).value)473474cdef get_unsafe(self, Py_ssize_t i, Py_ssize_t j):475"""476Returns (j, i) entry of self as a new Integer.477478.. warning::479480This is very unsafe; it assumes i and j are in the right481range.482483EXAMPLES::484485sage: a = MatrixSpace(ZZ,3)(range(9)); a486[0 1 2]487[3 4 5]488[6 7 8]489sage: a[1,2]4905491sage: a[4,7]492Traceback (most recent call last):493...494IndexError: matrix index out of range495sage: a[-1,0]4966497"""498cdef Integer z499z = PY_NEW(Integer)500mpz_set(z.value, self._matrix[i][j])501return z502503def _pickle(self):504"""505EXAMPLES::506507sage: a = matrix(ZZ,2,3,[1,193,15,-2,3,0])508sage: a._pickle()509('1 61 f -2 3 0', 0)510511sage: S = ModularSymbols(250,4,sign=1).cuspidal_submodule().new_subspace().decomposition() # long time512sage: S == loads(dumps(S)) # long time513True514"""515return self._pickle_version0(), 0516517cdef _pickle_version0(self):518"""519EXAMPLES::520521sage: matrix(ZZ,1,3,[1,193,15])._pickle() # indirect doctest522('1 61 f', 0)523524"""525return self._export_as_string(32)526527cpdef _export_as_string(self, int base=10):528"""529Return space separated string of the entries in this matrix, in the530given base. This is optimized for speed.531532INPUT: base -an integer = 36; (default: 10)533534EXAMPLES::535536sage: m = matrix(ZZ,2,3,[1,2,-3,1,-2,-45])537sage: m._export_as_string(10)538'1 2 -3 1 -2 -45'539sage: m._export_as_string(16)540'1 2 -3 1 -2 -2d'541"""542# TODO: *maybe* redo this to use mpz_import and mpz_export543# from sec 5.14 of the GMP manual. ??544cdef int i, j, len_so_far, m, n545cdef char *a546cdef char *s, *t, *tmp547548if self._nrows == 0 or self._ncols == 0:549data = ''550else:551n = self._nrows*self._ncols*10552s = <char*> sage_malloc(n * sizeof(char))553t = s554len_so_far = 0555556sig_on()557for i from 0 <= i < self._nrows * self._ncols:558m = mpz_sizeinbase (self._entries[i], base)559if len_so_far + m + 2 >= n:560# copy to new string with double the size561n = 2*n + m + 1562tmp = <char*> sage_malloc(n * sizeof(char))563strcpy(tmp, s)564sage_free(s)565s = tmp566t = s + len_so_far567#endif568mpz_get_str(t, base, self._entries[i])569m = strlen(t)570len_so_far = len_so_far + m + 1571t = t + m572t[0] = <char>32573t[1] = <char>0574t = t + 1575sig_off()576data = str(s)[:-1]577sage_free(s)578return data579580def _unpickle(self, data, int version):581if version == 0:582self._unpickle_version0(data)583else:584raise RuntimeError("unknown matrix version (=%s)"%version)585586cdef _unpickle_version0(self, data):587cdef Py_ssize_t i, n588data = data.split()589n = self._nrows * self._ncols590if len(data) != n:591raise RuntimeError("invalid pickle data.")592for i from 0 <= i < n:593s = data[i]594if mpz_init_set_str(self._entries[i], s, 32):595raise RuntimeError("invalid pickle data")596self._initialized = True597598599def __richcmp__(Matrix self, right, int op): # always need for mysterious reasons.600return self._richcmp(right, op)601602########################################################################603# LEVEL 1 helpers:604# These function support the implementation of the level 1 functionality.605########################################################################606cdef _zero_out_matrix(self):607"""608Set this matrix to be the zero matrix. This is only for internal609use. (Note: this matrix must NOT already have initialised610entries.)611"""612# TODO: This is about 6-10 slower than MAGMA doing what seems to be the same thing.613# Moreover, NTL can also do this quickly. Why? I think both have specialized614# small integer classes. (dmharvey: yes, NTL does not allocate any memory when615# initializing a ZZ to zero.)616sig_on()617cdef Py_ssize_t i618for i from 0 <= i < self._nrows * self._ncols:619mpz_init(self._entries[i])620sig_off()621self._initialized = True622623cdef _new_unitialized_matrix(self, Py_ssize_t nrows, Py_ssize_t ncols):624"""625Return a new matrix over the integers with the given number of rows626and columns. All memory is allocated for this matrix, but its627entries have not yet been filled in.628"""629P = self._parent.matrix_space(nrows, ncols)630return Matrix_integer_dense.__new__(Matrix_integer_dense, P, None, None, None)631632633########################################################################634# LEVEL 2 functionality635# x * cdef _add_636# x * cdef _sub_637# x * cdef _mul_638# x * cdef _cmp_c_impl639# * __neg__640# * __invert__641# * __copy__642# x * _multiply_classical643# * _list -- list of underlying elements (need not be a copy)644# * _dict -- sparse dictionary of underlying elements (need not be a copy)645########################################################################646647# cdef _mul_(self, Matrix right):648# def __neg__(self):649# def __invert__(self):650# def __copy__(self):651# def _multiply_classical(left, matrix.Matrix _right):652# def _list(self):653# def _dict(self):654655def __nonzero__(self):656r"""657Tests whether self is the zero matrix.658659EXAMPLES::660661sage: a = MatrixSpace(ZZ, 2, 3)(range(6)); a662[0 1 2]663[3 4 5]664sage: a.__nonzero__()665True666sage: (a - a).__nonzero__()667False668669::670671sage: a = MatrixSpace(ZZ, 0, 3)()672sage: a.__nonzero__()673False674sage: a = MatrixSpace(ZZ, 3, 0)()675sage: a.__nonzero__()676False677sage: a = MatrixSpace(ZZ, 0, 0)()678sage: a.__nonzero__()679False680"""681cdef mpz_t *a, *b682cdef Py_ssize_t i, j683cdef int k684for i from 0 <= i < self._nrows * self._ncols:685if mpz_sgn(self._entries[i]):686return True687return False688689def _multiply_linbox(self, Matrix right):690"""691Multiply matrices over ZZ using linbox.692693.. warning::694695This is very slow right now, i.e., linbox is very slow.696697EXAMPLES::698699sage: A = matrix(ZZ,2,3,range(6))700sage: A*A.transpose()701[ 5 14]702[14 50]703sage: A._multiply_linbox(A.transpose())704[ 5 14]705[14 50]706"""707cdef int e708cdef Matrix_integer_dense ans, B709B = right710ans = self.new_matrix(nrows = self.nrows(), ncols = right.ncols())711self._init_linbox()712sig_on()713linbox.matrix_matrix_multiply(ans._matrix, B._matrix, B._nrows, B._ncols)714sig_off()715return ans716717def _multiply_classical(self, Matrix right):718"""719EXAMPLE::720721sage: n = 3722sage: a = MatrixSpace(ZZ,n,n)(range(n^2))723sage: b = MatrixSpace(ZZ,n,n)(range(1, n^2 + 1))724sage: a._multiply_classical(b)725[ 18 21 24]726[ 54 66 78]727[ 90 111 132]728"""729if self._ncols != right._nrows:730raise IndexError("Number of columns of self must equal number of rows of right.")731732cdef Py_ssize_t i, j, k, l, nr, nc, snc733cdef mpz_t *v734cdef object parent735736nr = self._nrows737nc = right._ncols738snc = self._ncols739740if self._nrows == right._nrows:741# self acts on the space of right742parent = right.parent()743if self._ncols == right._ncols:744# right acts on the space of self745parent = self.parent()746else:747parent = self.matrix_space(nr, nc)748749cdef Matrix_integer_dense M, _right750_right = right751752M = Matrix_integer_dense.__new__(Matrix_integer_dense, parent, None, None, None)753Matrix.__init__(M, parent)754755# M has memory allocated but entries are not initialized756cdef mpz_t *entries757entries = M._entries758759cdef mpz_t s, z760mpz_init(s)761mpz_init(z)762763sig_on()764l = 0765for i from 0 <= i < nr:766for j from 0 <= j < nc:767mpz_set_si(s,0) # set s = 0768v = self._matrix[i]769for k from 0 <= k < snc:770mpz_mul(z, v[k], _right._matrix[k][j])771mpz_add(s, s, z)772mpz_init_set(entries[l], s)773l += 1774sig_off()775mpz_clear(s)776mpz_clear(z)777M._initialized = True778return M779780cdef sage.structure.element.Matrix _matrix_times_matrix_(self, sage.structure.element.Matrix right):781782#############783# see the tune_multiplication function below.784n = max(self._nrows, self._ncols, right._nrows, right._ncols)785if n <= 20:786return self._multiply_classical(right)787a = self.height(); b = right.height()788if float(max(a,b)) / float(n) >= 0.70:789return self._multiply_classical(right)790else:791return self._multiply_multi_modular(right)792793cpdef ModuleElement _lmul_(self, RingElement right):794"""795EXAMPLES::796797sage: a = matrix(QQ,2,range(6))798sage: (3/4) * a799[ 0 3/4 3/2]800[ 9/4 3 15/4]801"""802cdef Py_ssize_t i803cdef Integer _x804_x = Integer(right)805cdef Matrix_integer_dense M806M = Matrix_integer_dense.__new__(Matrix_integer_dense, self._parent, None, None, None)807for i from 0 <= i < self._nrows * self._ncols:808mpz_init(M._entries[i])809mpz_mul(M._entries[i], self._entries[i], _x.value)810M._initialized = True811return M812813cpdef ModuleElement _add_(self, ModuleElement right):814"""815Add two dense matrices over ZZ.816817EXAMPLES::818819sage: a = MatrixSpace(ZZ,3)(range(9))820sage: a+a821[ 0 2 4]822[ 6 8 10]823[12 14 16]824sage: b = MatrixSpace(ZZ,3)(range(9))825sage: b.swap_rows(1,2)826sage: a+b827[ 0 2 4]828[ 9 11 13]829[ 9 11 13]830"""831cdef Py_ssize_t i, j832833cdef Matrix_integer_dense M834M = Matrix_integer_dense.__new__(Matrix_integer_dense, self._parent, None, None, None)835836sig_on()837cdef mpz_t *row_self, *row_right, *row_ans838for i from 0 <= i < self._nrows:839row_self = self._matrix[i]840row_right = (<Matrix_integer_dense> right)._matrix[i]841row_ans = M._matrix[i]842for j from 0 <= j < self._ncols:843mpz_init(row_ans[j])844mpz_add(row_ans[j], row_self[j], row_right[j])845sig_off()846M._initialized = True847return M848849cpdef ModuleElement _sub_(self, ModuleElement right):850"""851Subtract two dense matrices over ZZ.852853EXAMPLES::854855sage: M = Mat(ZZ,3)856sage: a = M(range(9)); b = M(reversed(range(9)))857sage: a - b858[-8 -6 -4]859[-2 0 2]860[ 4 6 8]861"""862cdef Py_ssize_t i, j863864cdef Matrix_integer_dense M865M = Matrix_integer_dense.__new__(Matrix_integer_dense, self._parent, None, None, None)866867sig_on()868cdef mpz_t *row_self, *row_right, *row_ans869for i from 0 <= i < self._nrows:870row_self = self._matrix[i]871row_right = (<Matrix_integer_dense> right)._matrix[i]872row_ans = M._matrix[i]873for j from 0 <= j < self._ncols:874mpz_init(row_ans[j])875mpz_sub(row_ans[j], row_self[j], row_right[j])876sig_off()877M._initialized = True878return M879880881cdef int _cmp_c_impl(self, Element right) except -2:882r"""883Compares self with right, examining entries in lexicographic (row884major) ordering.885886EXAMPLES::887888sage: Matrix(ZZ, [[0, 10], [20, 30]]).__cmp__(Matrix(ZZ, [[0, 10], [20, 30]]))8890890sage: Matrix(ZZ, [[0, 10], [20, 30]]).__cmp__(Matrix(ZZ, [[0, 15], [20, 30]]))891-1892sage: Matrix(ZZ, [[5, 10], [20, 30]]).__cmp__(Matrix(ZZ, [[0, 15], [20, 30]]))8931894sage: Matrix(ZZ, [[5, 10], [20, 30]]).__cmp__(Matrix(ZZ, [[0, 10], [25, 30]]))8951896"""897cdef mpz_t *a, *b898cdef Py_ssize_t i, j899cdef int k900901for i from 0 <= i < self._nrows:902a = self._matrix[i]903b = (<Matrix_integer_dense>right)._matrix[i]904for j from 0 <= j < self._ncols:905k = mpz_cmp(a[j], b[j])906if k:907if k < 0:908return -1909else:910return 1911return 0912913914cdef Vector _vector_times_matrix_(self, Vector v):915"""916Returns the vector times matrix product.917918INPUT:919920921- ``v`` - a free module element.922923924OUTPUT: The vector times matrix product v\*A.925926EXAMPLES::927928sage: B = matrix(ZZ,2, [1,2,3,4])929sage: V = ZZ^2930sage: w = V([-1,5])931sage: w*B932(14, 18)933"""934cdef Vector_integer_dense w, ans935cdef Py_ssize_t i, j936cdef mpz_t x937938M = self._row_ambient_module()939w = <Vector_integer_dense> v940ans = M.zero_vector()941942mpz_init(x)943for i from 0 <= i < self._ncols:944mpz_set_si(x, 0)945for j from 0 <= j < self._nrows:946mpz_addmul(x, w._entries[j], self._matrix[j][i])947mpz_set(ans._entries[i], x)948mpz_clear(x)949return ans950951952########################################################################953# LEVEL 3 functionality (Optional)954# * __deepcopy__955# * __invert__956# * Matrix windows -- only if you need strassen for that base957# * Other functions (list them here):958# * Specialized echelon form959########################################################################960961def _clear_denom(self):962"""963INPUT:964965- ``self`` - a matrix966967OUTPUT: self, 1968969EXAMPLES::970971sage: a = matrix(ZZ,2,[1,2,3,4])972sage: a._clear_denom()973(974[1 2]975[3 4], 1976)977"""978return self, ZZ(1)979980def charpoly(self, var='x', algorithm='linbox'):981"""982INPUT:983984985- ``var`` - a variable name986987- ``algorithm`` - 'linbox' (default) 'generic'988989990.. note::991992Linbox charpoly disabled on 64-bit machines, since it hangs993in many cases.994995EXAMPLES::996997sage: A = matrix(ZZ,6, range(36))998sage: f = A.charpoly(); f999x^6 - 105*x^5 - 630*x^41000sage: f(A) == 01001True1002sage: n=20; A = Mat(ZZ,n)(range(n^2))1003sage: A.charpoly()1004x^20 - 3990*x^19 - 266000*x^181005sage: A.minpoly()1006x^3 - 3990*x^2 - 266000*x10071008TESTS:10091010The cached polynomial should be independent of the ``var``1011argument (:trac:`12292`). We check (indirectly) that the1012second call uses the cached value by noting that its result is1013not cached::10141015sage: M = MatrixSpace(ZZ, 2)1016sage: A = M(range(0, 2^2))1017sage: type(A)1018<type 'sage.matrix.matrix_integer_dense.Matrix_integer_dense'>1019sage: A.charpoly('x')1020x^2 - 3*x - 21021sage: A.charpoly('y')1022y^2 - 3*y - 21023sage: A._cache['charpoly_linbox']1024x^2 - 3*x - 210251026"""1027cache_key = 'charpoly_%s' % algorithm1028g = self.fetch(cache_key)1029if g is not None:1030return g.change_variable_name(var)10311032if algorithm == 'linbox' and not USE_LINBOX_POLY:1033algorithm = 'generic'10341035if algorithm == 'linbox':1036g = self._charpoly_linbox(var)1037elif algorithm == 'generic':1038g = matrix_dense.Matrix_dense.charpoly(self, var)1039else:1040raise ValueError("no algorithm '%s'"%algorithm)10411042self.cache(cache_key, g)1043return g10441045def minpoly(self, var='x', algorithm='linbox'):1046"""1047INPUT:104810491050- ``var`` - a variable name10511052- ``algorithm`` - 'linbox' (default) 'generic'105310541055.. note::10561057Linbox charpoly disabled on 64-bit machines, since it hangs1058in many cases.10591060EXAMPLES::10611062sage: A = matrix(ZZ,6, range(36))1063sage: A.minpoly()1064x^3 - 105*x^2 - 630*x1065sage: n=6; A = Mat(ZZ,n)([k^2 for k in range(n^2)])1066sage: A.minpoly()1067x^4 - 2695*x^3 - 257964*x^2 + 1693440*x1068"""1069key = 'minpoly_%s_%s'%(algorithm, var)1070x = self.fetch(key)1071if x: return x10721073if algorithm == 'linbox' and not USE_LINBOX_POLY:1074algorithm = 'generic'10751076if algorithm == 'linbox':1077g = self._minpoly_linbox(var)1078elif algorithm == 'generic':1079g = matrix_dense.Matrix_dense.minpoly(self, var)1080else:1081raise ValueError("no algorithm '%s'"%algorithm)10821083self.cache(key, g)1084return g10851086def _minpoly_linbox(self, var='x'):1087return self._poly_linbox(var=var, typ='minpoly')10881089def _charpoly_linbox(self, var='x'):1090if self.is_zero(): # program around a bug in linbox on 32-bit linux1091x = self.base_ring()[var].gen()1092return x ** self._nrows1093return self._poly_linbox(var=var, typ='charpoly')10941095def _poly_linbox(self, var='x', typ='minpoly'):1096"""1097INPUT:109810991100- ``var`` - 'x'11011102- ``typ`` - 'minpoly' or 'charpoly'1103"""1104time = verbose('computing %s of %s x %s matrix using linbox'%(typ, self._nrows, self._ncols))1105if self._nrows != self._ncols:1106raise ArithmeticError("self must be a square matrix")1107if self._nrows <= 1:1108return matrix_dense.Matrix_dense.charpoly(self, var)1109self._init_linbox()1110if typ == 'minpoly':1111sig_on()1112v = linbox.minpoly()1113sig_off()1114else:1115sig_on()1116v = linbox.charpoly()1117sig_off()1118R = self._base_ring[var]1119verbose('finished computing %s'%typ, time)1120return R(v)112111221123def height(self):1124"""1125Return the height of this matrix, i.e., the max absolute value of1126the entries of the matrix.11271128OUTPUT: A nonnegative integer.11291130EXAMPLE::11311132sage: a = Mat(ZZ,3)(range(9))1133sage: a.height()113481135sage: a = Mat(ZZ,2,3)([-17,3,-389,15,-1,0]); a1136[ -17 3 -389]1137[ 15 -1 0]1138sage: a.height()11393891140"""1141cdef mpz_t h1142cdef Integer x11431144self.mpz_height(h)1145x = Integer()1146x.set_from_mpz(h)1147mpz_clear(h)11481149return x11501151cdef int mpz_height(self, mpz_t height) except -1:1152"""1153Used to compute the height of this matrix.11541155INPUT:115611571158- ``height`` - a GMP mpz_t (that has not been1159initialized!)116011611162OUTPUT: sets the value of height to the height of this matrix,1163i.e., the max absolute value of the entries of the matrix.1164"""1165cdef mpz_t x, h1166cdef Py_ssize_t i11671168mpz_init_set_si(h, 0)1169mpz_init(x)11701171sig_on()11721173for i from 0 <= i < self._nrows * self._ncols:1174mpz_abs(x, self._entries[i])1175if mpz_cmp(h, x) < 0:1176mpz_set(h, x)11771178sig_off()11791180mpz_init_set(height, h)1181mpz_clear(h)1182mpz_clear(x)11831184return 0 # no error occurred.11851186def _multiply_multi_modular(left, Matrix_integer_dense right):1187"""1188Multiply this matrix by ``left`` using a multi modular algorithm.11891190EXAMPLES::11911192sage: M = Matrix(ZZ, 2, 3, range(5,11))1193sage: N = Matrix(ZZ, 3, 2, range(15,21))1194sage: M._multiply_multi_modular(N)1195[310 328]1196[463 490]1197sage: M._multiply_multi_modular(-N)1198[-310 -328]1199[-463 -490]1200"""1201cdef Integer h1202cdef mod_int *moduli1203cdef int i, n, k12041205h = left.height() * right.height() * left.ncols()1206verbose('multiplying matrices of height %s and %s'%(left.height(),right.height()))1207mm = MultiModularBasis(h)1208res = left._reduce(mm)1209res_right = right._reduce(mm)1210k = len(mm)1211for i in range(k): # yes, I could do this with zip, but to conserve memory...1212t = cputime()1213res[i] *= res_right[i]1214verbose('multiplied matrices modulo a prime (%s/%s)'%(i+1,k), t)1215result = left.new_matrix(left.nrows(), right.ncols())1216_lift_crt(result, res, mm) # changes result1217return result12181219cdef void reduce_entry_unsafe(self, Py_ssize_t i, Py_ssize_t j, Integer modulus):1220# Used for p-adic matrices.1221if mpz_cmp(self._matrix[i][j], modulus.value) >= 0 or mpz_cmp_ui(self._matrix[i][j], 0) < 0:1222mpz_mod(self._matrix[i][j], self._matrix[i][j], modulus.value)12231224def _mod_int(self, modulus):1225"""1226Reduce the integer matrix modulo a positive integer.12271228EXAMPLES::1229sage: matrix(QQ,2,[1,0,0,1]).change_ring(GF(2)) - 11230[0 0]1231[0 0]12321233"""1234cdef mod_int c = modulus1235if int(c) != modulus:1236raise OverflowError1237else:1238return self._mod_int_c(modulus)12391240cdef _mod_two(self):1241cdef Matrix_mod2_dense res1242res = Matrix_mod2_dense.__new__(Matrix_mod2_dense, matrix_space.MatrixSpace(IntegerModRing(2), self._nrows, self._ncols, sparse=False), None, None, None)1243res.__init__(matrix_space.MatrixSpace(IntegerModRing(2), self._nrows, self._ncols, sparse=False), self.list(), None, None)1244return res12451246cdef _mod_int_c(self, mod_int p):1247from matrix_modn_dense_float import MAX_MODULUS as MAX_MODULUS_FLOAT1248from matrix_modn_dense_double import MAX_MODULUS as MAX_MODULUS_DOUBLE12491250cdef Py_ssize_t i, j1251cdef mpz_t* self_row12521253cdef float* res_row_f1254cdef Matrix_modn_dense_float res_f12551256cdef double* res_row_d1257cdef Matrix_modn_dense_double res_d12581259if p == 2:1260return self._mod_two()1261elif p < MAX_MODULUS_FLOAT:1262res_f = Matrix_modn_dense_float.__new__(Matrix_modn_dense_float,1263matrix_space.MatrixSpace(IntegerModRing(p), self._nrows, self._ncols, sparse=False), None, None, None)1264for i from 0 <= i < self._nrows:1265self_row = self._matrix[i]1266res_row_f = res_f._matrix[i]1267for j from 0 <= j < self._ncols:1268res_row_f[j] = <float>mpz_fdiv_ui(self_row[j], p)1269return res_f12701271elif p < MAX_MODULUS_DOUBLE:1272res_d = Matrix_modn_dense_double.__new__(Matrix_modn_dense_double,1273matrix_space.MatrixSpace(IntegerModRing(p), self._nrows, self._ncols, sparse=False), None, None, None)1274for i from 0 <= i < self._nrows:1275self_row = self._matrix[i]1276res_row_d = res_d._matrix[i]1277for j from 0 <= j < self._ncols:1278res_row_d[j] = <double>mpz_fdiv_ui(self_row[j], p)1279return res_d1280else:1281raise ValueError("p to big.")12821283def _reduce(self, moduli):1284from matrix_modn_dense_float import MAX_MODULUS as MAX_MODULUS_FLOAT1285from matrix_modn_dense_double import MAX_MODULUS as MAX_MODULUS_DOUBLE12861287if isinstance(moduli, (int, long, Integer)):1288return self._mod_int(moduli)1289elif isinstance(moduli, list):1290moduli = MultiModularBasis(moduli)12911292cdef MultiModularBasis mm1293mm = moduli12941295res = []1296for p in mm:1297if p < MAX_MODULUS_FLOAT:1298res.append( Matrix_modn_dense_float.__new__(Matrix_modn_dense_float,1299matrix_space.MatrixSpace(IntegerModRing(p), self._nrows, self._ncols, sparse=False),1300None, None, None) )1301elif p < MAX_MODULUS_DOUBLE:1302res.append( Matrix_modn_dense_double.__new__(Matrix_modn_dense_double,1303matrix_space.MatrixSpace(IntegerModRing(p), self._nrows, self._ncols, sparse=False),1304None, None, None) )1305else:1306raise ValueError("p=%d too big."%p)13071308cdef size_t i, k, n1309cdef Py_ssize_t nr, nc13101311n = len(mm)1312nr = self._nrows1313nc = self._ncols13141315cdef mod_int **row_list1316row_list = <mod_int**>sage_malloc(sizeof(mod_int*) * n)1317if row_list == NULL:1318raise MemoryError("out of memory allocating multi-modular coefficient list")1319for k in range(n):1320row_list[k] = <mod_int*>sage_malloc(sizeof(mod_int)*nc)1321if row_list[k] == NULL:1322for i in range(k):1323sage_free(row_list[i])1324sage_free(row_list)1325raise MemoryError("out of memory allocating multi-modular coefficient list")13261327sig_on()1328for i from 0 <= i < nr:1329for k from 0 <= k < n:1330mm.mpz_reduce_vec(self._matrix[i], row_list, nc)1331if isinstance(res[k], Matrix_modn_dense_float):1332for j in range(nc):1333(<Matrix_modn_dense_float>res[k])._matrix[i][j] = (<float>row_list[k][j])%(<Matrix_modn_dense_float>res[k]).p1334else:1335for j in range(nc):1336(<Matrix_modn_dense_double>res[k])._matrix[i][j] = (<double>row_list[k][j])%(<Matrix_modn_dense_double>res[k]).p1337sig_off()13381339for k in range(n):1340sage_free(row_list[k])1341sage_free(row_list)1342return res13431344def _linbox_modn_det(self, mod_int n):1345"""1346INPUT:134713481349- ``n`` - a prime (at most 67108879)135013511352EXAMPLES::13531354sage: a = matrix(ZZ, 3, [1,2,5,-7,8,10,192,5,18])1355sage: a.det()1356-36691357sage: a._linbox_modn_det(5077)135814081359sage: a._linbox_modn_det(3)136001361sage: a._linbox_modn_det(2)136211363sage: a.det()%5077136414081365sage: a.det()%2136611367sage: a.det()%3136801369"""1370d = self._linbox_modn(n).det()1371return IntegerModRing(n)(d)13721373def _linbox_modn(self, mod_int n):1374"""1375Return modn linbox object associated to this integer matrix.13761377EXAMPLES::13781379sage: a = matrix(ZZ, 3, [1,2,5,-7,8,10,192,5,18])1380sage: b = a._linbox_modn(19); b1381<sage.libs.linbox.linbox.Linbox_modn_dense object at ...>1382sage: b.charpoly()1383[2L, 10L, 11L, 1L]1384"""1385if n > 67108879: # doesn't work for bigger primes -- experimental observation1386raise NotImplementedError("modulus to big")1387cdef mod_int** matrix = <mod_int**>sage_malloc(sizeof(mod_int*) * self._nrows)1388if matrix == NULL:1389raise MemoryError("out of memory allocating multi-modular coefficient list")13901391cdef Py_ssize_t i, j1392for i from 0 <= i < self._nrows:1393matrix[i] = <mod_int *>sage_malloc(sizeof(mod_int) * self._ncols)1394if matrix[i] == NULL:1395raise MemoryError("out of memory allocating multi-modular coefficient list")1396for j from 0 <= j < self._ncols:1397matrix[i][j] = mpz_fdiv_ui(self._matrix[i][j], n)13981399cdef Linbox_modn_dense L = Linbox_modn_dense()1400L.set(n, matrix, self._nrows, self._ncols)1401return L14021403def _echelon_in_place_classical(self):1404cdef Matrix_integer_dense E1405E = self.echelon_form()14061407cdef int i1408for i from 0 <= i < self._ncols * self._nrows:1409mpz_set(self._entries[i], E._entries[i])14101411self.clear_cache()14121413def _echelon_strassen(self):1414raise NotImplementedError14151416def _magma_init_(self, magma):1417"""1418EXAMPLES::14191420sage: m = matrix(ZZ,2,3,[1,2,-3,1,-2,-45])1421sage: m._magma_init_(magma)1422'Matrix(IntegerRing(),2,3,StringToIntegerSequence("1 2 -3 1 -2 -45"))'1423sage: magma(m) # optional - magma1424[ 1 2 -3]1425[ 1 -2 -45]1426"""1427w = self._export_as_string(base=10)1428return 'Matrix(IntegerRing(),%s,%s,StringToIntegerSequence("%s"))'%(1429self.nrows(), self.ncols(), w)14301431def symplectic_form(self):1432r"""1433Find a symplectic basis for self if self is an anti-symmetric,1434alternating matrix.14351436Returns a pair (F, C) such that the rows of C form a symplectic1437basis for self and F = C \* self \* C.transpose().14381439Raises a ValueError if self is not anti-symmetric, or self is not1440alternating.14411442Anti-symmetric means that `M = -M^t`. Alternating means1443that the diagonal of `M` is identically zero.14441445A symplectic basis is a basis of the form1446`e_1, \ldots, e_j, f_1, \ldots f_j, z_1, \dots, z_k`1447such that14481449- `z_i M v^t` = 0 for all vectors `v`14501451- `e_i M {e_j}^t = 0` for all `i, j`14521453- `f_i M {f_j}^t = 0` for all `i, j`14541455- `e_i M {f_i}^t = 1` for all `i`14561457- `e_i M {f_j}^t = 0` for all `i` not equal1458`j`.14591460The ordering for the factors `d_{i} | d_{i+1}` and for1461the placement of zeroes was chosen to agree with the output of1462``smith_form``.14631464See the example for a pictorial description of such a basis.14651466EXAMPLES::14671468sage: E = matrix(ZZ, 5, 5, [0, 14, 0, -8, -2, -14, 0, -3, -11, 4, 0, 3, 0, 0, 0, 8, 11, 0, 0, 8, 2, -4, 0, -8, 0]); E1469[ 0 14 0 -8 -2]1470[-14 0 -3 -11 4]1471[ 0 3 0 0 0]1472[ 8 11 0 0 8]1473[ 2 -4 0 -8 0]1474sage: F, C = E.symplectic_form()1475sage: F1476[ 0 0 1 0 0]1477[ 0 0 0 2 0]1478[-1 0 0 0 0]1479[ 0 -2 0 0 0]1480[ 0 0 0 0 0]1481sage: F == C * E * C.transpose()1482True1483sage: E.smith_form()[0]1484[1 0 0 0 0]1485[0 1 0 0 0]1486[0 0 2 0 0]1487[0 0 0 2 0]1488[0 0 0 0 0]1489"""1490import sage.matrix.symplectic_basis1491return sage.matrix.symplectic_basis.symplectic_basis_over_ZZ(self)14921493hermite_form = echelon_form14941495def echelon_form(self, algorithm="default", proof=None, include_zero_rows=True,1496transformation=False, D=None):1497r"""1498Return the echelon form of this matrix over the integers, also known1499as the hermit normal form (HNF).15001501INPUT:15021503- ``algorithm`` -- String. The algorithm to use. Valid options are:15041505- ``'default'`` -- Let Sage pick an algorithm (default). Up1506to 10 rows or columns: pari with flag 0; Up to 75 rows or1507columns: pari with flag 1; Larger: use padic algorithm.15081509- ``'padic'`` - an asymptotically fast p-adic modular1510algorithm, If your matrix has large coefficients and is1511small, you may also want to try this.15121513- ``'pari'`` - use PARI with flag 115141515- ``'pari0'`` - use PARI with flag 015161517- ``'pari4'`` - use PARI with flag 4 (use heuristic LLL)15181519- ``'ntl'`` - use NTL (only works for square matrices of1520full rank!)15211522- ``proof`` - (default: True); if proof=False certain1523determinants are computed using a randomized hybrid p-adic1524multimodular strategy until it stabilizes twice (instead of up to1525the Hadamard bound). It is *incredibly* unlikely that one would1526ever get an incorrect result with proof=False.15271528- ``include_zero_rows`` - (default: True) if False,1529don't include zero rows15301531- ``transformation`` - if given, also compute1532transformation matrix; only valid for padic algorithm15331534- ``D`` - (default: None) if given and the algorithm1535is 'ntl', then D must be a multiple of the determinant and this1536function will use that fact.15371538OUTPUT:15391540The Hermite normal form (=echelon form over `\ZZ`) of self.15411542EXAMPLES::15431544sage: A = MatrixSpace(ZZ,2)([1,2,3,4])1545sage: A.echelon_form()1546[1 0]1547[0 2]1548sage: A = MatrixSpace(ZZ,5)(range(25))1549sage: A.echelon_form()1550[ 5 0 -5 -10 -15]1551[ 0 1 2 3 4]1552[ 0 0 0 0 0]1553[ 0 0 0 0 0]1554[ 0 0 0 0 0]15551556Getting a transformation matrix in the nonsquare case::15571558sage: A = matrix(ZZ,5,3,[1..15])1559sage: H, U = A.hermite_form(transformation=True, include_zero_rows=False)1560sage: H1561[1 2 3]1562[0 3 6]1563sage: U1564[ 0 0 0 4 -3]1565[ 0 0 0 13 -10]1566sage: U*A == H1567True15681569TESTS: Make sure the zero matrices are handled correctly::15701571sage: m = matrix(ZZ,3,3,[0]*9)1572sage: m.echelon_form()1573[0 0 0]1574[0 0 0]1575[0 0 0]1576sage: m = matrix(ZZ,3,1,[0]*3)1577sage: m.echelon_form()1578[0]1579[0]1580[0]1581sage: m = matrix(ZZ,1,3,[0]*3)1582sage: m.echelon_form()1583[0 0 0]15841585The ultimate border case!15861587::15881589sage: m = matrix(ZZ,0,0,[])1590sage: m.echelon_form()1591[]15921593.. note::15941595If 'ntl' is chosen for a non square matrix this function1596raises a ValueError.15971598Special cases: 0 or 1 rows::15991600sage: a = matrix(ZZ, 1,2,[0,-1])1601sage: a.hermite_form()1602[0 1]1603sage: a.pivots()1604(1,)1605sage: a = matrix(ZZ, 1,2,[0,0])1606sage: a.hermite_form()1607[0 0]1608sage: a.pivots()1609()1610sage: a = matrix(ZZ,1,3); a1611[0 0 0]1612sage: a.echelon_form(include_zero_rows=False)1613[]1614sage: a.echelon_form(include_zero_rows=True)1615[0 0 0]16161617Illustrate using various algorithms.::16181619sage: matrix(ZZ,3,[1..9]).hermite_form(algorithm='pari')1620[1 2 3]1621[0 3 6]1622[0 0 0]1623sage: matrix(ZZ,3,[1..9]).hermite_form(algorithm='pari0')1624[1 2 3]1625[0 3 6]1626[0 0 0]1627sage: matrix(ZZ,3,[1..9]).hermite_form(algorithm='pari4')1628[1 2 3]1629[0 3 6]1630[0 0 0]1631sage: matrix(ZZ,3,[1..9]).hermite_form(algorithm='padic')1632[1 2 3]1633[0 3 6]1634[0 0 0]1635sage: matrix(ZZ,3,[1..9]).hermite_form(algorithm='default')1636[1 2 3]1637[0 3 6]1638[0 0 0]16391640The 'ntl' algorithm doesn't work on matrices that do not have full rank.::16411642sage: matrix(ZZ,3,[1..9]).hermite_form(algorithm='ntl')1643Traceback (most recent call last):1644...1645ValueError: ntl only computes HNF for square matrices of full rank.1646sage: matrix(ZZ,3,[0] +[2..9]).hermite_form(algorithm='ntl')1647[1 0 0]1648[0 1 0]1649[0 0 3]16501651TESTS:16521653This example illustrated trac 2398::16541655sage: a = matrix([(0, 0, 3), (0, -2, 2), (0, 1, 2), (0, -2, 5)])1656sage: a.hermite_form()1657[0 1 2]1658[0 0 3]1659[0 0 0]1660[0 0 0]16611662Check that #12280 is fixed::16631664sage: m = matrix([(-2, 1, 9, 2, -8, 1, -3, -1, -4, -1),1665... (5, -2, 0, 1, 0, 4, -1, 1, -2, 0),1666... (-11, 3, 1, 0, -3, -2, -1, -11, 2, -2),1667... (-1, 1, -1, -2, 1, -1, -1, -1, -1, 7),1668... (-2, -1, -1, 1, 1, -2, 1, 0, 2, -4)]).stack(1669... 200 * identity_matrix(ZZ, 10))1670sage: matrix(ZZ,m).hermite_form(algorithm='pari', include_zero_rows=False)1671[ 1 0 2 0 13 5 1 166 72 69]1672[ 0 1 1 0 20 4 15 195 65 190]1673[ 0 0 4 0 24 5 23 22 51 123]1674[ 0 0 0 1 23 7 20 105 60 151]1675[ 0 0 0 0 40 4 0 80 36 68]1676[ 0 0 0 0 0 10 0 100 190 170]1677[ 0 0 0 0 0 0 25 0 100 150]1678[ 0 0 0 0 0 0 0 200 0 0]1679[ 0 0 0 0 0 0 0 0 200 0]1680[ 0 0 0 0 0 0 0 0 0 200]1681sage: matrix(ZZ,m).hermite_form(algorithm='padic', include_zero_rows=False)1682[ 1 0 2 0 13 5 1 166 72 69]1683[ 0 1 1 0 20 4 15 195 65 190]1684[ 0 0 4 0 24 5 23 22 51 123]1685[ 0 0 0 1 23 7 20 105 60 151]1686[ 0 0 0 0 40 4 0 80 36 68]1687[ 0 0 0 0 0 10 0 100 190 170]1688[ 0 0 0 0 0 0 25 0 100 150]1689[ 0 0 0 0 0 0 0 200 0 0]1690[ 0 0 0 0 0 0 0 0 200 0]1691[ 0 0 0 0 0 0 0 0 0 200]1692"""1693if self._nrows == 0 or self._ncols == 0:1694self.cache('pivots', ())1695self.cache('rank', 0)1696if transformation:1697return self, self1698return self16991700key = 'hnf-%s-%s'%(include_zero_rows,transformation)1701ans = self.fetch(key)1702if ans is not None: return ans17031704cdef Py_ssize_t nr, nc, n, i, j1705nr = self._nrows1706nc = self._ncols1707n = nr if nr >= nc else nc1708if algorithm is 'default':1709if transformation: algorithm = 'padic'1710else:1711if n <= 10: algorithm = 'pari0'1712elif n <= 75: algorithm = 'pari'1713else: algorithm = 'padic'17141715cdef bint pari_big = 01716if algorithm.startswith('pari'):1717if self.height().ndigits() > 10000 or n >= 50:1718pari_big = 117191720cdef Matrix_integer_dense H_m17211722proof = get_proof_flag(proof, "linear_algebra")1723pivots = None1724rank = None17251726if algorithm == "padic":1727import matrix_integer_dense_hnf1728if transformation:1729H_m, U, pivots = matrix_integer_dense_hnf.hnf_with_transformation(self, proof=proof)1730if not include_zero_rows:1731r = H_m.rank()1732H_m = H_m[:r]1733U = U[:r]1734else:1735H_m, pivots = matrix_integer_dense_hnf.hnf(self,1736include_zero_rows=include_zero_rows, proof=proof)1737self.cache('pivots', tuple(pivots))1738self.cache('rank', len(pivots))173917401741elif algorithm == 'pari0':1742if transformation:1743raise ValueError("transformation matrix only available with p-adic algorithm")1744if pari_big:1745H_m = self._hnf_pari_big(0, include_zero_rows=include_zero_rows)1746else:1747H_m = self._hnf_pari(0, include_zero_rows=include_zero_rows)17481749elif algorithm == 'pari':1750if transformation:1751raise ValueError("transformation matrix only available with p-adic algorithm")1752if pari_big:1753H_m = self._hnf_pari_big(1, include_zero_rows=include_zero_rows)1754else:1755H_m = self._hnf_pari(1, include_zero_rows=include_zero_rows)17561757elif algorithm == 'pari4':1758if transformation:1759raise ValueError("transformation matrix only available with p-adic algorithm")1760if pari_big:1761H_m = self._hnf_pari_big(4, include_zero_rows=include_zero_rows)1762else:1763H_m = self._hnf_pari(4, include_zero_rows=include_zero_rows)17641765elif algorithm == 'ntl':1766if transformation:1767raise ValueError("transformation matrix only available with p-adic algorithm")17681769if nr != nc:1770raise ValueError("ntl only computes HNF for square matrices of full rank.")17711772import sage.libs.ntl.ntl_mat_ZZ1773v = sage.libs.ntl.ntl_mat_ZZ.ntl_mat_ZZ(self._nrows,self._ncols)1774for i from 0 <= i < self._nrows:1775for j from 0 <= j < self._ncols:1776v[i,j] = self.get_unsafe(nr-i-1,nc-j-1)17771778try:1779w = v.HNF(D=D)1780except RuntimeError: # HNF may fail if a nxm matrix has rank < m1781raise ValueError("ntl only computes HNF for square matrices of full rank.")17821783rank = w.nrows()17841785if include_zero_rows:1786H_m = self.new_matrix()1787else:1788H_m = self.new_matrix(nrows=w.nrows())17891790nr = w.nrows()1791nc = w.ncols()17921793for i from 0 <= i < w.nrows():1794for j from 0 <= j < w.ncols():1795H_m[i,j] = w[nr-i-1,nc-j-1]17961797else:1798raise TypeError("algorithm '%s' not understood"%(algorithm))17991800H_m.set_immutable()1801if pivots is None:1802from matrix_integer_dense_hnf import pivots_of_hnf_matrix1803pivots = tuple(pivots_of_hnf_matrix(H_m))1804rank = len(pivots)1805else:1806pivots = tuple(pivots)18071808H_m.cache('pivots', pivots)1809self.cache('pivots', pivots)18101811H_m.cache('rank', rank)1812self.cache('rank',rank)18131814H_m.cache('in_echelon_form', True)181518161817if transformation:1818U.set_immutable()1819ans = H_m, U1820else:1821ans = H_m1822self.cache(key, ans)1823return ans18241825def saturation(self, p=0, proof=None, max_dets=5):1826r"""1827Return a saturation matrix of self, which is a matrix whose rows1828span the saturation of the row span of self. This is not unique.18291830The saturation of a `\ZZ` module `M`1831embedded in `\ZZ^n` is the a module `S` that1832contains `M` with finite index such that1833`\ZZ^n/S` is torsion free. This function takes the1834row span `M` of self, and finds another matrix of full rank1835with row span the saturation of `M`.18361837INPUT:183818391840- ``p`` - (default: 0); if nonzero given, saturate1841only at the prime `p`, i.e., return a matrix whose row span1842is a `\ZZ`-module `S` that contains self and1843such that the index of `S` in its saturation is coprime to1844`p`. If `p` is None, return full saturation of1845self.18461847- ``proof`` - (default: use proof.linear_algebra());1848if False, the determinant calculations are done with proof=False.18491850- ``max_dets`` - (default: 5); technical parameter -1851max number of determinant to compute when bounding prime divisor of1852self in its saturation.185318541855OUTPUT:185618571858- ``matrix`` - a matrix over ZZ185918601861.. note::18621863The result is *not* cached.18641865ALGORITHM: 1. Replace input by a matrix of full rank got from a1866subset of the rows. 2. Divide out any common factors from rows. 3.1867Check max_dets random dets of submatrices to see if their GCD1868(with p) is 1 - if so matrix is saturated and we're done. 4.1869Finally, use that if A is a matrix of full rank, then1870`hnf(transpose(A))^{-1}*A` is a saturation of A.18711872EXAMPLES::18731874sage: A = matrix(ZZ, 3, 5, [-51, -1509, -71, -109, -593, -19, -341, 4, 86, 98, 0, -246, -11, 65, 217])1875sage: A.echelon_form()1876[ 1 5 2262 20364 56576]1877[ 0 6 35653 320873 891313]1878[ 0 0 42993 386937 1074825]1879sage: S = A.saturation(); S1880[ -51 -1509 -71 -109 -593]1881[ -19 -341 4 86 98]1882[ 35 994 43 51 347]18831884Notice that the saturation spans a different module than A.18851886::18871888sage: S.echelon_form()1889[ 1 2 0 8 32]1890[ 0 3 0 -2 -6]1891[ 0 0 1 9 25]1892sage: V = A.row_space(); W = S.row_space()1893sage: V.is_submodule(W)1894True1895sage: V.index_in(W)1896859861897sage: V.index_in_saturation()18988598618991900We illustrate each option::19011902sage: S = A.saturation(p=2)1903sage: S = A.saturation(proof=False)1904sage: S = A.saturation(max_dets=2)1905"""1906proof = get_proof_flag(proof, "linear_algebra")1907import matrix_integer_dense_saturation1908return matrix_integer_dense_saturation.saturation(self, p=p, proof=proof, max_dets=max_dets)19091910def index_in_saturation(self, proof=None):1911"""1912Return the index of self in its saturation.19131914INPUT:191519161917- ``proof`` - (default: use proof.linear_algebra());1918if False, the determinant calculations are done with proof=False.191919201921OUTPUT:192219231924- ``positive integer`` - the index of the row span of1925this matrix in its saturation192619271928ALGORITHM: Use Hermite normal form twice to find an invertible1929matrix whose inverse transforms a matrix with the same row span as1930self to its saturation, then compute the determinant of that1931matrix.19321933EXAMPLES::19341935sage: A = matrix(ZZ, 2,3, [1..6]); A1936[1 2 3]1937[4 5 6]1938sage: A.index_in_saturation()193931940sage: A.saturation()1941[1 2 3]1942[1 1 1]1943"""1944proof = get_proof_flag(proof, "linear_algebra")1945import matrix_integer_dense_saturation1946return matrix_integer_dense_saturation.index_in_saturation(self, proof=proof)19471948def pivots(self):1949"""1950Return the pivot column positions of this matrix.19511952OUTPUT: a tuple of Python integers: the position of the1953first nonzero entry in each row of the echelon form.19541955EXAMPLES::19561957sage: n = 3; A = matrix(ZZ,n,range(n^2)); A1958[0 1 2]1959[3 4 5]1960[6 7 8]1961sage: A.pivots()1962(0, 1)1963sage: A.echelon_form()1964[ 3 0 -3]1965[ 0 1 2]1966[ 0 0 0]1967"""1968p = self.fetch('pivots')1969if not p is None: return tuple(p)19701971cdef Matrix_integer_dense E1972E = self.echelon_form()19731974# Now we determine the pivots from the matrix E as quickly as we can.1975# For each row, we find the first nonzero position in that row -- it is the pivot.1976cdef Py_ssize_t i, j, k1977cdef mpz_t *row1978p = []1979k = 01980for i from 0 <= i < E._nrows:1981row = E._matrix[i] # pointer to ith row1982for j from k <= j < E._ncols:1983if mpz_cmp_si(row[j], 0) != 0: # nonzero position1984p.append(j)1985k = j+1 # so start at next position next time1986break1987p = tuple(p)1988self.cache('pivots', p)1989return p19901991#### Elementary divisors19921993def elementary_divisors(self, algorithm='pari'):1994"""1995Return the elementary divisors of self, in order.199619971998.. warning::19992000This is MUCH faster than the smith_form function.20012002The elementary divisors are the invariants of the finite abelian2003group that is the cokernel of *left* multiplication of this matrix.2004They are ordered in reverse by divisibility.20052006INPUT:200720082009- ``self`` - matrix20102011- ``algorithm`` - (default: 'pari')20122013- ``'pari'``: works robustly, but is slower.20142015- ``'linbox'`` - use linbox (currently off, broken)201620172018OUTPUT: list of integers201920202021.. note::20222023These are the invariants of the cokernel of *left* multiplication::20242025sage: M = Matrix([[3,0,1],[0,1,0]])2026sage: M2027[3 0 1]2028[0 1 0]2029sage: M.elementary_divisors()2030[1, 1]2031sage: M.transpose().elementary_divisors()2032[1, 1, 0]20332034EXAMPLES::20352036sage: matrix(3, range(9)).elementary_divisors()2037[1, 3, 0]2038sage: matrix(3, range(9)).elementary_divisors(algorithm='pari')2039[1, 3, 0]2040sage: C = MatrixSpace(ZZ,4)([3,4,5,6,7,3,8,10,14,5,6,7,2,2,10,9])2041sage: C.elementary_divisors()2042[1, 1, 1, 687]20432044::20452046sage: M = matrix(ZZ, 3, [1,5,7, 3,6,9, 0,1,2])2047sage: M.elementary_divisors()2048[1, 1, 6]20492050This returns a copy, which is safe to change::20512052sage: edivs = M.elementary_divisors()2053sage: edivs.pop()205462055sage: M.elementary_divisors()2056[1, 1, 6]20572058.. seealso::20592060:meth:`smith_form`2061"""2062d = self.fetch('elementary_divisors')2063if not d is None:2064return d[:]2065if self._nrows == 0 or self._ncols == 0:2066d = []2067else:2068if algorithm == 'linbox':2069raise ValueError("linbox too broken -- currently Linbox SNF is disabled.")2070# This fails in linbox: a = matrix(ZZ,2,[1, 1, -1, 0, 0, 0, 0, 1])2071try:2072d = self._elementary_divisors_linbox()2073except RuntimeError:2074import sys2075sys.stderr.write("DONT PANIC -- switching to using PARI (which will work fine)\n")2076algorithm = 'pari'2077if algorithm == 'pari':2078d = self._pari_().matsnf(0).python()2079i = d.count(0)2080d.sort()2081if i > 0:2082d = d[i:] + [d[0]]*i2083elif not (algorithm in ['pari', 'linbox']):2084raise ValueError("algorithm (='%s') unknown"%algorithm)2085self.cache('elementary_divisors', d)2086return d[:]20872088def _elementary_divisors_linbox(self):2089self._init_linbox()2090sig_on()2091d = linbox.smithform()2092sig_off()2093return d20942095def smith_form(self):2096r"""2097Returns matrices S, U, and V such that S = U\*self\*V, and S is in2098Smith normal form. Thus S is diagonal with diagonal entries the2099ordered elementary divisors of S.21002101.. warning::21022103The elementary_divisors function, which returns the2104diagonal entries of S, is VASTLY faster than this function.21052106The elementary divisors are the invariants of the finite abelian2107group that is the cokernel of this matrix. They are ordered in2108reverse by divisibility.21092110EXAMPLES::21112112sage: A = MatrixSpace(IntegerRing(), 3)(range(9))2113sage: D, U, V = A.smith_form()2114sage: D2115[1 0 0]2116[0 3 0]2117[0 0 0]2118sage: U2119[ 0 1 0]2120[ 0 -1 1]2121[-1 2 -1]2122sage: V2123[-1 4 1]2124[ 1 -3 -2]2125[ 0 0 1]2126sage: U*A*V2127[1 0 0]2128[0 3 0]2129[0 0 0]21302131It also makes sense for nonsquare matrices::21322133sage: A = Matrix(ZZ,3,2,range(6))2134sage: D, U, V = A.smith_form()2135sage: D2136[1 0]2137[0 2]2138[0 0]2139sage: U2140[ 0 1 0]2141[ 0 -1 1]2142[-1 2 -1]2143sage: V2144[-1 3]2145[ 1 -2]2146sage: U * A * V2147[1 0]2148[0 2]2149[0 0]21502151Empty matrices are handled sensibly (see trac #3068)::21522153sage: m = MatrixSpace(ZZ, 2,0)(0); d,u,v = m.smith_form(); u*m*v == d2154True2155sage: m = MatrixSpace(ZZ, 0,2)(0); d,u,v = m.smith_form(); u*m*v == d2156True2157sage: m = MatrixSpace(ZZ, 0,0)(0); d,u,v = m.smith_form(); u*m*v == d2158True21592160.. seealso::21612162:meth:`elementary_divisors`2163"""2164v = self._pari_().matsnf(1).python()2165if self._ncols == 0: v[0] = self.matrix_space(ncols = self._nrows)(1)2166if self._nrows == 0: v[1] = self.matrix_space(nrows = self._ncols)(1)2167# need to reverse order of rows of U, columns of V, and both of D.2168D = self.matrix_space()([v[2][i,j] for i in xrange(self._nrows-1,-1,-1) for j in xrange(self._ncols-1,-1,-1)])21692170if self._ncols == 0:2171# silly special cases for matrices with 0 columns (PARI has a unique empty matrix)2172U = self.matrix_space(ncols = self._nrows)(1)2173else:2174U = self.matrix_space(ncols = self._nrows)([v[0][i,j] for i in xrange(self._nrows-1,-1,-1) for j in xrange(self._nrows)])21752176if self._nrows == 0:2177# silly special cases for matrices with 0 rows (PARI has a unique empty matrix)2178V = self.matrix_space(nrows = self._ncols)(1)2179else:2180V = self.matrix_space(nrows = self._ncols)([v[1][i,j] for i in xrange(self._ncols) for j in xrange(self._ncols-1,-1,-1)])21812182return D, U, V21832184def frobenius(self, flag=0, var='x'):2185"""2186Return the Frobenius form (rational canonical form) of this2187matrix.21882189INPUT:21902191- ``flag`` -- 0 (default), 1 or 2 as follows:21922193- ``0`` -- (default) return the Frobenius form of this2194matrix.21952196- ``1`` -- return only the elementary divisor2197polynomials, as polynomials in var.21982199- ``2`` -- return a two-components vector [F,B] where F2200is the Frobenius form and B is the basis change so that2201`M=B^{-1}FB`.22022203- ``var`` -- a string (default: 'x')22042205ALGORITHM: uses PARI's matfrobenius()22062207EXAMPLES::22082209sage: A = MatrixSpace(ZZ, 3)(range(9))2210sage: A.frobenius(0)2211[ 0 0 0]2212[ 1 0 18]2213[ 0 1 12]2214sage: A.frobenius(1)2215[x^3 - 12*x^2 - 18*x]2216sage: A.frobenius(1, var='y')2217[y^3 - 12*y^2 - 18*y]2218sage: F, B = A.frobenius(2)2219sage: A == B^(-1)*F*B2220True2221sage: a=matrix([])2222sage: a.frobenius(2)2223([], [])2224sage: a.frobenius(0)2225[]2226sage: a.frobenius(1)2227[]2228sage: B = random_matrix(ZZ,2,3)2229sage: B.frobenius()2230Traceback (most recent call last):2231...2232ArithmeticError: frobenius matrix of non-square matrix not defined.22332234AUTHORS:22352236- Martin Albrect (2006-04-02)22372238TODO: - move this to work for more general matrices than just over2239Z. This will require fixing how PARI polynomials are coerced to2240Sage polynomials.2241"""2242if not self.is_square():2243raise ArithmeticError("frobenius matrix of non-square matrix not defined.")22442245v = self._pari_().matfrobenius(flag)2246if flag==0:2247return self.matrix_space()(v.python())2248elif flag==1:2249r = PolynomialRing(self.base_ring(), names=var)2250retr = []2251for f in v:2252retr.append(eval(str(f).replace("^","**"), {'x':r.gen()}, r.gens_dict()))2253return retr2254elif flag==2:2255F = matrix_space.MatrixSpace(QQ, self.nrows())(v[0].python())2256B = matrix_space.MatrixSpace(QQ, self.nrows())(v[1].python())2257return F, B22582259def _right_kernel_matrix(self, **kwds):2260r"""2261Returns a pair that includes a matrix of basis vectors2262for the right kernel of ``self``.22632264INPUT:22652266- ``algorithm`` - determines which algorithm to use, options are:22672268- 'pari' - use the ``matkerint()`` function from the PARI library2269- 'padic' - use the p-adic algorithm from the IML library2270- 'default' - use a heuristic to decide which of the two above2271routines is fastest. This is the default value.22722273- ``proof`` - this is passed to the p-adic IML algorithm.2274If not specified, the global flag for linear algebra will be used.22752276OUTPUT:22772278Returns a pair. First item is the string is either2279'computed-pari-int' or 'computed-iml-int', which identifies2280the nature of the basis vectors.22812282Second item is a matrix whose rows are a basis for the right kernel,2283over the integers, as computed by either the IML or PARI libraries.22842285EXAMPLES::22862287sage: A = matrix(ZZ, [[4, 7, 9, 7, 5, 0],2288... [1, 0, 5, 8, 9, 1],2289... [0, 1, 0, 1, 9, 7],2290... [4, 7, 6, 5, 1, 4]])22912292sage: result = A._right_kernel_matrix(algorithm='pari')2293sage: result[0]2294'computed-pari-int'2295sage: X = result[1]; X2296[-26 31 -30 21 2 -10]2297[-47 -13 48 -14 -11 18]2298sage: A*X.transpose() == zero_matrix(ZZ, 4, 2)2299True23002301sage: result = A._right_kernel_matrix(algorithm='padic')2302sage: result[0]2303'computed-iml-int'2304sage: X = result[1]; X2305[-469 214 -30 119 -37 0]2306[ 370 -165 18 -91 30 -2]2307sage: A*X.transpose() == zero_matrix(ZZ, 4, 2)2308True23092310sage: result = A._right_kernel_matrix(algorithm='default')2311sage: result[0]2312'computed-pari-int'2313sage: result[1]2314[-26 31 -30 21 2 -10]2315[-47 -13 48 -14 -11 18]23162317sage: result = A._right_kernel_matrix()2318sage: result[0]2319'computed-pari-int'2320sage: result[1]2321[-26 31 -30 21 2 -10]2322[-47 -13 48 -14 -11 18]23232324With the 'default' given as the algorithm, several heuristics are2325used to determine if PARI or IML ('padic') is used. The code has2326exact details, but roughly speaking, relevant factors are: the2327absolute size of the matrix, or the relative dimensions, or the2328magnitude of the entries. ::23292330sage: A = random_matrix(ZZ, 18, 11)2331sage: A._right_kernel_matrix(algorithm='default')[0]2332'computed-pari-int'2333sage: A = random_matrix(ZZ, 18, 11, x = 10^200)2334sage: A._right_kernel_matrix(algorithm='default')[0]2335'computed-iml-int'2336sage: A = random_matrix(ZZ, 60, 60)2337sage: A._right_kernel_matrix(algorithm='default')[0]2338'computed-iml-int'2339sage: A = random_matrix(ZZ, 60, 55)2340sage: A._right_kernel_matrix(algorithm='default')[0]2341'computed-pari-int'23422343TESTS:23442345We test three trivial cases. PARI is used for small matrices,2346but we let the heuristic decide that. ::23472348sage: A = matrix(ZZ, 0, 2)2349sage: A._right_kernel_matrix()[1]2350[1 0]2351[0 1]2352sage: A = matrix(ZZ, 2, 0)2353sage: A._right_kernel_matrix()[1].parent()2354Full MatrixSpace of 0 by 0 dense matrices over Integer Ring2355sage: A = zero_matrix(ZZ, 4, 3)2356sage: A._right_kernel_matrix()[1]2357[1 0 0]2358[0 1 0]2359[0 0 1]2360"""2361tm = verbose("computing right kernel matrix over the integers for %sx%s matrix" % (self.nrows(), self.ncols()),level=1)23622363algorithm = kwds.pop('algorithm', None)2364if algorithm == None:2365algorithm = 'default'23662367if algorithm == 'default':2368# The heuristic here could be auto-tuned, stored for2369# different architecture, etc. What I've done below here2370# I just got by playing around with examples. This is2371# *dramatically* better than doing absolutely nothing2372# (i.e., always choosing 'padic'), but is of course2373# far from optimal. -- William Stein2374if max(self._nrows, self._ncols) <= 10:2375# pari much better for very small matrices, as long as entries aren't huge.2376algorithm = 'pari'2377if max(self._nrows, self._ncols) <= 50:2378# when entries are huge, padic relatively good.2379h = self.height().ndigits()2380if h < 100:2381algorithm = 'pari'2382else:2383algorithm = 'padic'2384elif self._nrows <= self._ncols + 3:2385# the padic algorithm is much better for bigger2386# matrices if there are nearly more columns than rows2387# (that is its forte)2388algorithm = 'padic'2389else:2390algorithm = 'pari'23912392if algorithm == 'pari':2393K = self._pari_().matkerint().mattranspose().python()2394format = 'computed-pari-int'2395if algorithm == 'padic':2396proof = kwds.pop('proof', None)2397proof = get_proof_flag(proof, "linear_algebra")2398K = self._rational_kernel_iml().transpose().saturation(proof=proof)2399format = 'computed-iml-int'2400tm = verbose("done computing right kernel matrix over the integers for %sx%s matrix" % (self.nrows(), self.ncols()),level=1, t=tm)2401return (format, K)24022403def _adjoint(self):2404"""2405Return the adjoint of this matrix.24062407Assumes self is a square matrix (checked in adjoint).24082409EXAMPLES::24102411sage: m = matrix(ZZ,3,[1..9])2412sage: m.adjoint()2413[ -3 6 -3]2414[ 6 -12 6]2415[ -3 6 -3]2416"""2417return self.parent()(self._pari_().matadjoint().python())24182419def _ntl_(self):2420r"""2421ntl.mat_ZZ representation of self.24222423EXAMPLE::24242425sage: a = MatrixSpace(ZZ,200).random_element(x=-2, y=2) # -2 to 22426sage: A = a._ntl_()24272428.. note::24292430NTL only knows dense matrices, so if you provide a sparse2431matrix NTL will allocate memory for every zero entry.2432"""2433import sage.libs.ntl.ntl_mat_ZZ2434return sage.libs.ntl.ntl_mat_ZZ.ntl_mat_ZZ(self._nrows,self._ncols, self.list())243524362437####################################################################################2438# LLL2439####################################################################################2440def LLL_gram(self):2441"""2442LLL reduction of the lattice whose gram matrix is self.24432444INPUT:244524462447- ``M`` - gram matrix of a definite quadratic form244824492450OUTPUT:245124522453- ``U`` - unimodular transformation matrix such that2454U.transpose() \* M \* U is LLL-reduced.24552456ALGORITHM: Use PARI24572458EXAMPLES::24592460sage: M = Matrix(ZZ, 2, 2, [5,3,3,2]) ; M2461[5 3]2462[3 2]2463sage: U = M.LLL_gram(); U2464[-1 1]2465[ 1 -2]2466sage: U.transpose() * M * U2467[1 0]2468[0 1]24692470Semidefinite and indefinite forms no longer raise a ValueError::24712472sage: Matrix(ZZ,2,2,[2,6,6,3]).LLL_gram()2473[-3 -1]2474[ 1 0]2475sage: Matrix(ZZ,2,2,[1,0,0,-1]).LLL_gram()2476[ 0 -1]2477[ 1 0]24782479"""2480if self._nrows != self._ncols:2481raise ArithmeticError("self must be a square matrix")24822483n = self.nrows()2484# maybe should be /unimodular/ matrices ?2485P = self._pari_()2486try:2487U = P.lllgramint()2488except (RuntimeError, ArithmeticError), msg:2489raise ValueError("not a definite matrix")2490MS = matrix_space.MatrixSpace(ZZ,n)2491U = MS(U.python())2492# Fix last column so that det = +12493if U.det() == -1:2494for i in range(n):2495U[i,n-1] = - U[i,n-1]2496return U24972498def BKZ(self, delta=None, fp="rr", block_size=10, prune=0, use_givens=False):2499"""2500Block Korkin-Zolotarev reduction.25012502INPUT:250325042505- ``fp`` - 'fp' - double precision: NTL's FP or2506fpLLL's double25072508- ``'qd'`` - quad doubles: NTL's QP25092510- ``'qd1'`` - quad doubles: uses quad_float precision2511to compute Gram-Schmidt, but uses double precision in the search2512phase of the block reduction algorithm. This seems adequate for2513most purposes, and is faster than 'qd', which uses quad_float2514precision uniformly throughout.25152516- ``'xd'`` - extended exponent: NTL's XD25172518- ``'rr'`` - arbitrary precision (default)25192520- ``block_size`` - specifies the size of the blocks2521in the reduction. High values yield shorter vectors, but the2522running time increases exponentially with2523``block_size``. ``block_size`` should be2524between 2 and the number of rows of ``self`` (default:252510)25262527- ``prune`` - The optional parameter2528``prune`` can be set to any positive number to invoke2529the Volume Heuristic from [Schnorr and Horner, Eurocrypt '95]. This2530can significantly reduce the running time, and hence allow much2531bigger block size, but the quality of the reduction is of course2532not as good in general. Higher values of ``prune`` mean2533better quality, and slower running time. When ``prune``2534== 0, pruning is disabled. Recommended usage: for2535``block_size`` = 30, set 10 = ``prune`` =253615.25372538- ``use_givens`` - use Given's orthogonalization.2539This is a bit slower, but generally much more stable, and is really2540the preferred orthogonalization strategy. For a nice description of2541this, see Chapter 5 of [G. Golub and C. van Loan, Matrix2542Computations, 3rd edition, Johns Hopkins Univ. Press, 1996].254325442545EXAMPLE::25462547sage: A = Matrix(ZZ,3,3,range(1,10))2548sage: A.BKZ()2549[ 0 0 0]2550[ 2 1 0]2551[-1 1 3]2552sage: A = Matrix(ZZ,3,3,range(1,10))2553sage: A.BKZ(use_givens=True)2554[ 0 0 0]2555[ 2 1 0]2556[-1 1 3]25572558::25592560sage: A = Matrix(ZZ,3,3,range(1,10))2561sage: A.BKZ(fp="fp")2562[ 0 0 0]2563[ 2 1 0]2564[-1 1 3]2565"""2566if delta is None:2567delta = 0.992568elif delta <= 0.25:2569raise TypeError("delta must be > 0.25")2570elif delta > 1:2571raise TypeError("delta must be <= 1")2572delta = float(delta)25732574if fp is None:2575fp = "rr"25762577if fp == "fp":2578algorithm = "BKZ_FP"2579elif fp == "qd":2580algorithm = "BKZ_QP"2581elif fp == "qd1":2582algorithm = "BKZ_QP1"2583elif fp == "xd":2584algorithm = "BKZ_XD"2585elif fp == "rr":2586algorithm = "BKZ_RR"2587else:2588raise TypeError("fp parameter not understood.")25892590block_size = int(block_size)25912592if prune < 0:2593raise TypeError("prune must be >= 0")2594prune = int(prune)25952596if get_verbose() >= 2:2597verbose = True2598else:2599verbose = False26002601A = self._ntl_()26022603if algorithm == "BKZ_FP":2604if not use_givens:2605r = A.BKZ_FP(U=None, delta=delta, BlockSize=block_size, prune=prune, verbose=verbose)2606else:2607r = A.G_BKZ_FP(U=None, delta=delta, BlockSize=block_size, prune=prune, verbose=verbose)26082609elif algorithm == "BKZ_QP":2610if not use_givens:2611r = A.BKZ_QP(U=None, delta=delta, BlockSize=block_size, prune=prune, verbose=verbose)2612else:2613r = A.G_BKZ_QP(U=None, delta=delta, BlockSize=block_size, prune=prune, verbose=verbose)26142615elif algorithm == "BKZ_QP1":2616if not use_givens:2617r = A.BKZ_QP1(U=None, delta=delta, BlockSize=block_size, prune=prune, verbose=verbose)2618else:2619r = A.G_BKZ_QP1(U=None, delta=delta, BlockSize=block_size, prune=prune, verbose=verbose)26202621elif algorithm == "BKZ_XD":2622if not use_givens:2623r = A.BKZ_XD(U=None, delta=delta, BlockSize=block_size, prune=prune, verbose=verbose)2624else:2625r = A.G_BKZ_XD(U=None, delta=delta, BlockSize=block_size, prune=prune, verbose=verbose)26262627elif algorithm == "BKZ_RR":2628if not use_givens:2629r = A.BKZ_RR(U=None, delta=delta, BlockSize=block_size, prune=prune, verbose=verbose)2630else:2631r = A.G_BKZ_RR(U=None, delta=delta, BlockSize=block_size, prune=prune, verbose=verbose)26322633self.cache("rank",ZZ(r))2634R = <Matrix_integer_dense>self.new_matrix(entries=map(ZZ,A.list()))2635return R26362637def LLL(self, delta=None, eta=None, algorithm="fpLLL:wrapper", fp=None, prec=0, early_red = False, use_givens = False):2638r"""2639Returns LLL reduced or approximated LLL reduced lattice R for this2640matrix interpreted as a lattice.26412642A lattice `(b_1, b_2, ..., b_d)` is2643`(\delta, \eta)` -LLL-reduced if the two following2644conditions hold:26452646- For any `i>j`, we have `|mu_{i, j}| <= \eta`,2647- For any `i<d`, we have2648`\delta |b_i^*|^2 <= |b_{i + 1}^* + mu_{i + 1, i} b_i^* |^2`,26492650where `mu_{i,j} = <b_i, b_j^*>/<b_j^*,b_j^*>` and2651`b_i^*` is the `i`-th vector of the Gram-Schmidt2652orthogonalisation of `(b_1, b_2, ..., b_d)`.26532654The default reduction parameters are `\delta=3/4` and2655`eta=0.501`. The parameters `\delta` and2656`\eta` must satisfy: `0.25 < \delta <= 1.0` and2657`0.5 <= \eta < sqrt(\delta)`. Polynomial time2658complexity is only guaranteed for `\delta < 1`.26592660The lattice is returned as a matrix. Also the rank (and the2661determinant) of self are cached if those are computed during the2662reduction. Note that in general this only happens when self.rank()2663== self.ncols() and the exact algorithm is used.26642665INPUT:266626672668- ``delta`` - parameter as described above (default:26693/4)26702671- ``eta`` - parameter as described above (default:26720.501), ignored by NTL26732674- ``algorithm`` - string (default: "fpLLL:wrapper")2675one of the algorithms mentioned below26762677- ``fp``26782679- None - NTL's exact reduction or fpLLL's2680wrapper26812682- ``'fp'`` - double precision: NTL's FP or fpLLL's2683double26842685- ``'qd'`` - quad doubles: NTL's QP26862687- ``'xd'`` - extended exponent: NTL's XD or fpLLL's2688dpe26892690- ``'rr'`` - arbitrary precision: NTL'RR or fpLLL's2691MPFR26922693- ``prec`` - precision, ignored by NTL (default: auto2694choose)26952696- ``early_red`` - perform early reduction, ignored by2697NTL (default: False)26982699- ``use_givens`` - use Givens orthogonalization2700(default: False) only applicable to approximate reductions and NTL.2701This is more stable but slower.27022703Also, if the verbose level is = 2, some more verbose output is2704printed during the calculation if NTL is used.27052706AVAILABLE ALGORITHMS:27072708- ``NTL:LLL`` - NTL's LLL + fp27092710- ``fpLLL:heuristic`` - fpLLL's heuristic + fp27112712- ``fpLLL:fast`` - fpLLL's fast27132714- ``fpLLL:wrapper`` - fpLLL's automatic choice2715(default)271627172718OUTPUT: a matrix over the integers27192720EXAMPLE::27212722sage: A = Matrix(ZZ,3,3,range(1,10))2723sage: A.LLL()2724[ 0 0 0]2725[ 2 1 0]2726[-1 1 3]27272728We compute the extended GCD of a list of integers using LLL, this2729example is from the Magma handbook::27302731sage: Q = [ 67015143, 248934363018, 109210, 25590011055, 74631449, \273210230248, 709487, 68965012139, 972065, 864972271 ]2733sage: n = len(Q)2734sage: S = 1002735sage: X = Matrix(ZZ, n, n + 1)2736sage: for i in xrange(n):2737... X[i,i + 1] = 12738sage: for i in xrange(n):2739... X[i,0] = S*Q[i]2740sage: L = X.LLL()2741sage: M = L.row(n-1).list()[1:]2742sage: M2743[-3, -1, 13, -1, -4, 2, 3, 4, 5, -1]2744sage: add([Q[i]*M[i] for i in range(n)])2745-127462747TESTS::27482749sage: matrix(ZZ, 0, 0).LLL()2750[]2751sage: matrix(ZZ, 3, 0).LLL()2752[]2753sage: matrix(ZZ, 0, 3).LLL()2754[]27552756sage: M = matrix(ZZ, [[1,2,3],[31,41,51],[101,201,301]])2757sage: A = M.LLL()2758sage: A2759[ 0 0 0]2760[-1 0 1]2761[ 1 1 1]2762sage: B = M.LLL(algorithm='NTL:LLL')2763sage: C = M.LLL(algorithm='NTL:LLL', fp=None)2764sage: D = M.LLL(algorithm='NTL:LLL', fp='fp')2765sage: F = M.LLL(algorithm='NTL:LLL', fp='xd')2766sage: G = M.LLL(algorithm='NTL:LLL', fp='rr')2767sage: A == B == C == D == F == G2768True2769sage: H = M.LLL(algorithm='NTL:LLL', fp='qd')2770Traceback (most recent call last):2771...2772TypeError: algorithm NTL:LLL_QD not supported27732774ALGORITHM: Uses the NTL library by Victor Shoup or fpLLL library by2775Damien Stehle depending on the chosen algorithm.27762777REFERENCES:27782779- ``ntl.mat_ZZ`` or ``sage.libs.fplll.fplll`` for details on2780the used algorithms.2781"""2782if self.ncols()==0 or self.nrows()==0:2783verbose("Trivial matrix, nothing to do")2784return self27852786tm = verbose("LLL of %sx%s matrix (algorithm %s)"%(self.nrows(), self.ncols(), algorithm))2787import sage.libs.ntl.all2788ntl_ZZ = sage.libs.ntl.all.ZZ27892790from sage.libs.fplll.fplll import FP_LLL27912792if get_verbose() >= 2: verb = True2793else: verb = False27942795# auto choice27962797# FP choice2798if algorithm == 'NTL:LLL':2799if fp == None:2800algorithm = 'NTL:LLL_FP'2801elif fp == 'fp':2802algorithm = 'NTL:LLL_FP'2803elif fp == 'qd':2804algorithm = 'NTL:LLL_QD'2805elif fp == 'xd':2806algorithm = 'NTL:LLL_XD'2807elif fp == 'rr':2808algorithm = 'NTL:LLL_RR'2809elif algorithm == 'fpLLL:heuristic':2810if fp == None:2811raise TypeError("if 'fpLLL:heuristic' is chosen, a floating point number implementation must be chosen")2812elif fp == 'fp':2813fp = 'double'2814elif fp == 'qd':2815raise TypeError("fpLLL does not support quad doubles.")2816elif fp == 'xd':2817fp = 'dpe'2818elif fp == 'rr':2819fp = 'mpfr'28202821if algorithm == "NTL:LLL":2822if delta is None:2823delta = ZZ(3)/ZZ(4)2824elif delta <= ZZ(1)/ZZ(4):2825raise TypeError("delta must be > 1/4")2826elif delta > 1:2827raise TypeError("delta must be <= 1")2828delta = QQ(delta)2829a = delta.numer()2830b = delta.denom()28312832else:2833if delta is None:2834delta = 0.992835elif delta <= 0.25:2836raise TypeError("delta must be > 0.25")2837elif delta > 1:2838raise TypeError("delta must be <= 1")2839delta = float(delta)28402841if eta is None:2842eta = 0.5012843elif eta < 0.5:2844raise TypeError("eta must be >= 0.5")28452846if prec < 0:2847raise TypeError("precision prec must be >= 0")2848int(prec)28492850if algorithm.startswith('NTL:'):2851A = sage.libs.ntl.all.mat_ZZ(self.nrows(),self.ncols(),map(ntl_ZZ,self.list()))28522853if algorithm == "NTL:LLL":2854r, det2 = A.LLL(a,b, verbose=verb)2855det2 = ZZ(det2)2856try:2857det = ZZ(det2.sqrt_approx())2858self.cache("det", det)2859except TypeError:2860pass2861elif algorithm == "NTL:LLL_FP":2862if use_givens:2863r = A.G_LLL_FP(delta, verbose=verb)2864else:2865r = A.LLL_FP(delta, verbose=verb)2866elif algorithm == "NTL:LLL_QP":2867if use_givens:2868r = A.G_LLL_QP(delta, verbose=verb)2869else:2870r = A.LLL_QP(delta, verbose=verb)2871elif algorithm == "NTL:LLL_XD":2872if use_givens:2873r = A.G_LLL_XD(delta, verbose=verb)2874else:2875r = A.LLL_XD(delta, verbose=verb)2876elif algorithm == "NTL:LLL_RR":2877if use_givens:2878r = A.G_LLL_RR(delta, verbose=verb)2879else:2880r = A.LLL_XD(delta, verbose=verb)2881else:2882raise TypeError("algorithm %s not supported"%algorithm)28832884r = ZZ(r)28852886R = <Matrix_integer_dense>self.new_matrix(entries=map(ZZ,A.list()))2887self.cache("rank",r)28882889elif algorithm.startswith('fpLLL:'):28902891A = sage.libs.fplll.fplll.FP_LLL(self)2892if algorithm == 'fpLLL:wrapper':2893A.wrapper(prec, eta, delta)2894elif algorithm == 'fpLLL:heuristic':2895if early_red:2896A.heuristic_early_red(prec,eta,delta,fp)2897else:2898A.heuristic(prec,eta,delta,fp)2899elif algorithm == 'fpLLL:fast':2900if early_red:2901A.fast_early_red(prec,eta,delta)2902else:2903A.fast(prec,eta,delta)2904elif algorithm == 'fpLLL:proved':2905A.proved(prec,eta,delta)2906else:2907raise TypeError("algorithm %s not supported"%algorithm)2908R = A._sage_()2909else:2910raise TypeError("algorithm %s not supported"%algorithm)29112912verbose("LLL finished", tm)2913return R29142915def is_LLL_reduced(self, delta=None, eta=None):2916r"""2917Return ``True`` if this lattice is2918`(\delta, \eta)`-LLL reduced. See ``self.LLL``2919for a definition of LLL reduction.29202921INPUT:292229232924- ``delta`` - parameter as described above (default:29253/4)29262927- ``eta`` - parameter as described above (default:29280.501)292929302931EXAMPLE::29322933sage: A = random_matrix(ZZ, 10, 10)2934sage: L = A.LLL()2935sage: A.is_LLL_reduced()2936False2937sage: L.is_LLL_reduced()2938True2939"""2940if eta is None:2941eta = 0.5012942if delta is None:2943delta = ZZ(3)/ZZ(4)29442945if delta <= ZZ(1)/ZZ(4):2946raise TypeError("delta must be > 1/4")2947elif delta > 1:2948raise TypeError("delta must be <= 1")29492950if eta < 0.5:2951raise TypeError("eta must be >= 0.5")29522953# this is pretty slow2954import sage.modules.misc2955G, mu = sage.modules.misc.gram_schmidt(self.rows())2956#For any $i>j$, we have $|mu_{i, j}| <= \eta$2957for e in mu.list():2958if e.abs() > eta:2959return False29602961#For any $i<d$, we have $\delta |b_i^*|^2 <= |b_{i+1}^* + mu_{i+1, i} b_i^* |^2$2962norms = [G[i].norm()**2 for i in range(len(G))]2963for i in xrange(1,self.nrows()):2964if norms[i] < (delta - mu[i,i-1]**2) * norms[i-1]:2965return False2966return True29672968def prod_of_row_sums(self, cols):2969"""2970Return the product of the sums of the entries in the submatrix of2971self with given columns.29722973INPUT:297429752976- ``cols`` - a list (or set) of integers representing2977columns of self.297829792980OUTPUT: an integer29812982EXAMPLES::29832984sage: a = matrix(ZZ,2,3,[1..6]); a2985[1 2 3]2986[4 5 6]2987sage: a.prod_of_row_sums([0,2])2988402989sage: (1+3)*(4+6)2990402991sage: a.prod_of_row_sums(set([0,2]))2992402993"""2994cdef Py_ssize_t c, row2995cdef mpz_t s, pr2996mpz_init(s)2997mpz_init(pr)29982999mpz_set_si(pr, 1)3000for row from 0 <= row < self._nrows:3001mpz_set_si(s, 0)3002for c in cols:3003if c<0 or c >= self._ncols:3004raise IndexError("matrix column index out of range")3005mpz_add(s, s, self._matrix[row][c])3006mpz_mul(pr, pr, s)3007cdef Integer z3008z = PY_NEW(Integer)3009mpz_set(z.value, pr)3010mpz_clear(s)3011mpz_clear(pr)3012return z30133014def _linbox_sparse(self):3015cdef Py_ssize_t i, j3016v = ['%s %s M'%(self._nrows, self._ncols)]3017for i from 0 <= i < self._nrows:3018for j from 0 <= j < self._ncols:3019if mpz_cmp_si(self._matrix[i][j], 0):3020v.append('%s %s %s'%(i+1,j+1,self.get_unsafe(i,j)))3021v.append('0 0 0\n')3022return '\n'.join(v)30233024def _linbox_dense(self):3025cdef Py_ssize_t i, j3026v = ['%s %s x'%(self._nrows, self._ncols)]3027for i from 0 <= i < self._nrows:3028for j from 0 <= j < self._ncols:3029v.append(str(self.get_unsafe(i,j)))3030return ' '.join(v)30313032def rational_reconstruction(self, N):3033"""3034Use rational reconstruction to lift self to a matrix over the3035rational numbers (if possible), where we view self as a matrix3036modulo N.30373038INPUT:303930403041- ``N`` - an integer304230433044OUTPUT:304530463047- ``matrix`` - over QQ or raise a ValueError304830493050EXAMPLES: We create a random 4x4 matrix over ZZ.30513052::30533054sage: A = matrix(ZZ, 4, [4, -4, 7, 1, -1, 1, -1, -12, -1, -1, 1, -1, -3, 1, 5, -1])30553056There isn't a unique rational reconstruction of it::30573058sage: A.rational_reconstruction(11)3059Traceback (most recent call last):3060...3061ValueError: Rational reconstruction of 4 (mod 11) does not exist.30623063We throw in a denominator and reduce the matrix modulo 389 - it3064does rationally reconstruct.30653066::30673068sage: B = (A/3 % 389).change_ring(ZZ)3069sage: B.rational_reconstruction(389) == A/33070True30713072TEST:30733074Check that ticket #9345 is fixed::30753076sage: A = random_matrix(ZZ, 3, 3)3077sage: A.rational_reconstruction(0)3078Traceback (most recent call last):3079...3080ZeroDivisionError: The modulus cannot be zero3081"""3082import misc3083return misc.matrix_integer_dense_rational_reconstruction(self, N)30843085def randomize(self, density=1, x=None, y=None, distribution=None, \3086nonzero=False):3087"""3088Randomize ``density`` proportion of the entries of this matrix,3089leaving the rest unchanged.30903091The parameters are the same as the ones for the integer ring's3092``random_element`` function.30933094If ``x`` and ``y`` are given, randomized entries of this matrix have3095to be between ``x`` and ``y`` and have density 1.30963097INPUT:30983099- ``self`` - a mutable matrix over ZZ31003101- ``density`` - a float between 0 and 131023103- ``x, y`` - if not ``None``, these are passed to the3104``ZZ.random_element`` function as the upper and lower endpoints in3105the uniform distribution31063107- ``distribution`` - would also be passed into ``ZZ.random_element``3108if given31093110- ``nonzero`` - bool (default: ``False``); whether the new entries3111are guaranteed to be zero31123113OUTPUT:31143115- None, the matrix is modified in-place31163117EXAMPLES::31183119sage: A = matrix(ZZ, 2,3, [1..6]); A3120[1 2 3]3121[4 5 6]3122sage: A.randomize()3123sage: A3124[-8 2 0]3125[ 0 1 -1]3126sage: A.randomize(x=-30,y=30)3127sage: A3128[ 5 -19 24]3129[ 24 23 -9]3130"""3131density = float(density)3132if density <= 0:3133return3134if density > 1:3135density = float(1)31363137self.check_mutability()3138self.clear_cache()31393140cdef randstate rstate = current_randstate()31413142cdef Py_ssize_t i, j, k, nc, num_per_row3143global state, ZZ31443145cdef IntegerRing_class the_integer_ring = ZZ31463147if not nonzero:3148# Original code, before adding the ``nonzero`` option.3149sig_on()3150if density == 1:3151for i from 0 <= i < self._nrows*self._ncols:3152the_integer_ring._randomize_mpz(self._entries[i], x, y, \3153distribution)3154else:3155nc = self._ncols3156num_per_row = int(density * nc)3157for i from 0 <= i < self._nrows:3158for j from 0 <= j < num_per_row:3159k = rstate.c_random()%nc3160the_integer_ring._randomize_mpz(self._matrix[i][k], \3161x, y, distribution)3162sig_off()3163else:3164# New code, to implement the ``nonzero`` option. Note that this3165# code is almost the same as above, the only difference being that3166# each entry is set until it's non-zero.3167sig_on()3168if density == 1:3169for i from 0 <= i < self._nrows*self._ncols:3170while mpz_sgn(self._entries[i]) == 0:3171the_integer_ring._randomize_mpz(self._entries[i], \3172x, y, distribution)3173else:3174nc = self._ncols3175num_per_row = int(density * nc)3176for i from 0 <= i < self._nrows:3177for j from 0 <= j < num_per_row:3178k = rstate.c_random() % nc3179while mpz_sgn(self._matrix[i][k]) == 0:3180the_integer_ring._randomize_mpz(self._matrix[i][k],\3181x, y, distribution)3182sig_off()31833184#### Rank31853186def rank(self):3187"""3188Return the rank of this matrix.31893190OUTPUT:319131923193- ``nonnegative integer`` - the rank319431953196.. note::31973198The rank is cached.31993200ALGORITHM: First check if the matrix has maxim possible rank by3201working modulo one random prime. If not call LinBox's rank3202function.32033204EXAMPLES::32053206sage: a = matrix(ZZ,2,3,[1..6]); a3207[1 2 3]3208[4 5 6]3209sage: a.rank()321023211sage: a = matrix(ZZ,3,3,[1..9]); a3212[1 2 3]3213[4 5 6]3214[7 8 9]3215sage: a.rank()3216232173218Here's a bigger example - the rank is of course still 2::32193220sage: a = matrix(ZZ,100,[1..100^2]); a.rank()322123222"""3223r = self.fetch('rank')3224if not r is None: return r32253226if self._nrows <= 6 and self._ncols <= 6 and self.height().ndigits() <= 10000:3227r = self._rank_pari()3228# Can very quickly detect full rank by working modulo p.3229r = self._rank_modp()3230if r == self._nrows or r == self._ncols:3231self.cache('rank', r)3232return r3233# Detecting full rank didn't work -- use LinBox's general algorithm.3234r = self._rank_linbox()3235self.cache('rank', r)3236return r32373238def _rank_linbox(self):3239"""3240Compute the rank of this matrix using Linbox.3241"""3242self._init_linbox()3243cdef unsigned long r3244sig_on()3245r = linbox.rank()3246sig_off()3247return Integer(r)32483249def _rank_modp(self, p=46337):3250A = self._mod_int_c(p)3251return A.rank()32523253#### Determinant32543255def determinant(self, algorithm='default', proof=None, stabilize=2):3256r"""3257Return the determinant of this matrix.32583259INPUT:32603261- ``algorithm``32623263- ``'default'`` -- use 'pari' when number of rows less than 50;3264otherwise, use 'padic'32653266- ``'padic'`` - uses a p-adic / multimodular3267algorithm that relies on code in IML and linbox32683269- ``'linbox'`` - calls linbox det (you *must* set3270proof=False to use this!)32713272- ``'ntl'`` - calls NTL's det function32733274- ``'pari'`` - uses PARI32753276- ``proof`` - bool or None; if None use3277proof.linear_algebra(); only relevant for the padic algorithm.32783279.. note::32803281It would be *VERY VERY* hard for det to fail even with3282proof=False.32833284- ``stabilize`` - if proof is False, require det to be3285the same for this many CRT primes in a row. Ignored if proof is3286True.328732883289ALGORITHM: The p-adic algorithm works by first finding a random3290vector v, then solving A\*x = v and taking the denominator3291`d`. This gives a divisor of the determinant. Then we3292compute `\det(A)/d` using a multimodular algorithm and the3293Hadamard bound, skipping primes that divide `d`.32943295TIMINGS: This is perhaps the fastest implementation of determinants3296in the world. E.g., for a 500x500 random matrix with 32-bit entries3297on a core2 duo 2.6Ghz running OS X, Sage takes 4.12 seconds,3298whereas Magma takes 62.87 seconds (both with proof False). With3299proof=True on the same problem Sage takes 5.73 seconds. For another3300example, a 200x200 random matrix with 1-digit entries takes 4.183301seconds in pari, 0.18 in Sage with proof True, 0.11 in Sage with3302proof False, and 0.21 seconds in Magma with proof True and 0.18 in3303Magma with proof False.33043305EXAMPLES::33063307sage: A = matrix(ZZ,8,8,[3..66])3308sage: A.determinant()3309033103311::33123313sage: A = random_matrix(ZZ,20,20)3314sage: D1 = A.determinant()3315sage: A._clear_cache()3316sage: D2 = A.determinant(algorithm='ntl')3317sage: D1 == D23318True33193320Next we try the Linbox det. Note that we must have proof=False.33213322::33233324sage: A = matrix(ZZ,5,[1,2,3,4,5,4,6,3,2,1,7,9,7,5,2,1,4,6,7,8,3,2,4,6,7])3325sage: A.determinant(algorithm='linbox')3326Traceback (most recent call last):3327...3328RuntimeError: you must pass the proof=False option to the determinant command to use LinBox's det algorithm3329sage: A.determinant(algorithm='linbox',proof=False)3330-213331sage: A._clear_cache()3332sage: A.determinant()3333-2133343335A bigger example::33363337sage: A = random_matrix(ZZ,30)3338sage: d = A.determinant()3339sage: A._clear_cache()3340sage: A.determinant(algorithm='linbox',proof=False) == d3341True3342"""3343d = self.fetch('det')3344if not d is None:3345return d3346if not self.is_square():3347raise ValueError("self must be a square matrix")3348n = self.nrows()33493350if n <= 3:3351# use generic special cased code.3352return matrix_dense.Matrix_dense.determinant(self)3353elif n == 4:3354return self._det_4x4_unsafe()33553356if algorithm == 'default':3357if n <= 50 and self.height().ndigits() <= 100:3358algorithm = 'pari'3359else:3360algorithm = 'padic'33613362proof = get_proof_flag(proof, "linear_algebra")33633364if algorithm == 'padic':3365import matrix_integer_dense_hnf3366return matrix_integer_dense_hnf.det_padic(self, proof=proof, stabilize=stabilize)3367elif algorithm == 'linbox':3368if proof:3369raise RuntimeError("you must pass the proof=False option to the determinant command to use LinBox's det algorithm")3370d = self._det_linbox()3371elif algorithm == 'pari':3372d = self._det_pari()3373elif algorithm == 'ntl':3374d = self._det_ntl()3375else:3376raise TypeError("algorithm '%s' not known"%(algorithm))33773378self.cache('det', d)3379return d33803381def _det_linbox(self):3382"""3383Compute the determinant of this matrix using Linbox.3384"""3385self._init_linbox()3386sig_on()3387d = linbox.det()3388sig_off()3389return Integer(d)33903391cdef _det_4x4_unsafe(self):3392"""3393Compute the determinant of this matrix using a special3394formulation for 4x4 matrices.33953396TESTS::33973398sage: A = matrix(ZZ,4,[1,2,3,4,4,3,2,1,0,5,0,1,9,1,2,3])3399sage: A.determinant() # indirect doctest34002703401"""3402cdef Integer d = ZZ(0)3403sig_on()3404four_dim_det(d.value,self._entries)3405sig_off()3406return d34073408def _det_ntl(self):3409"""3410Compute the determinant of this matrix using NTL.3411"""3412sig_on()3413d = self._ntl_().determinant()3414sig_off()3415return Integer(d)34163417#### Rational kernel, via IML3418def _rational_kernel_iml(self):3419"""3420IML: Return the rational kernel of this matrix (acting from the3421left), considered as a matrix over QQ. I.e., returns a matrix K3422such that self\*K = 0, and the number of columns of K equals the3423nullity of self.34243425AUTHORS:34263427- William Stein3428"""3429if self._nrows == 0 or self._ncols == 0:3430return self.matrix_space(self._ncols, 0).zero_matrix()34313432cdef long dim3433cdef mpz_t *mp_N3434time = verbose('computing null space of %s x %s matrix using IML'%(self._nrows, self._ncols))3435sig_on()3436dim = nullspaceMP (self._nrows, self._ncols, self._entries, &mp_N)3437sig_off()3438P = self.matrix_space(self._ncols, dim)34393440# Now read the answer as a matrix.3441cdef Matrix_integer_dense M3442M = Matrix_integer_dense.__new__(Matrix_integer_dense, P, None, None, None)3443for i from 0 <= i < dim*self._ncols:3444mpz_init_set(M._entries[i], mp_N[i])3445mpz_clear(mp_N[i])3446sage_free(mp_N)34473448verbose("finished computing null space", time)3449M._initialized = True3450return M34513452def _invert_iml(self, use_nullspace=False, check_invertible=True):3453"""3454Invert this matrix using IML. The output matrix is an integer3455matrix and a denominator.34563457INPUT:345834593460- ``self`` - an invertible matrix34613462- ``use_nullspace`` - (default: False): whether to3463use nullspace algorithm, which is slower, but doesn't require3464checking that the matrix is invertible as a precondition.34653466- ``check_invertible`` - (default: True) whether to3467check that the matrix is invertible.346834693470OUTPUT: A, d such that A\*self = d347134723473- ``A`` - a matrix over ZZ34743475- ``d`` - an integer347634773478ALGORITHM: Uses IML's p-adic nullspace function.34793480EXAMPLES::34813482sage: a = matrix(ZZ,3,[1,2,5, 3,7,8, 2,2,1])3483sage: b, d = a._invert_iml(); b,d3484(3485[ 9 -8 19]3486[-13 9 -7]3487[ 8 -2 -1], 233488)3489sage: a*b3490[23 0 0]3491[ 0 23 0]3492[ 0 0 23]34933494AUTHORS:34953496- William Stein3497"""3498if self._nrows != self._ncols:3499raise TypeError("self must be a square matrix.")35003501P = self.parent()3502time = verbose('computing inverse of %s x %s matrix using IML'%(self._nrows, self._ncols))3503if use_nullspace:3504A = self.augment(P.identity_matrix())3505K = A._rational_kernel_iml()3506d = -K[self._nrows,0]3507if K.ncols() != self._ncols or d == 0:3508raise ZeroDivisionError("input matrix must be nonsingular")3509B = K[:self._nrows]3510verbose("finished computing inverse using IML", time)3511return B, d3512else:3513if check_invertible and self.rank() != self._nrows:3514raise ZeroDivisionError("input matrix must be nonsingular")3515return self._solve_iml(P.identity_matrix(), right=True)35163517def _solve_right_nonsingular_square(self, B, check_rank=True):3518r"""3519If self is a matrix `A` of full rank, then this function3520returns a vector or matrix `X` such that `A X = B`.3521If `B` is a vector then `X` is a vector and if3522`B` is a matrix, then `X` is a matrix. The base3523ring of `X` is the integers unless a denominator is needed3524in which case the base ring is the rational numbers.35253526.. note::35273528In Sage one can also write ``A B`` for3529``A.solve_right(B)``, i.e., Sage implements the "the3530MATLAB/Octave backslash operator".35313532.. note::35333534This is currently only implemented when A is square.35353536INPUT:353735383539- ``B`` - a matrix or vector35403541- ``check_rank`` - bool (default: True); if True3542verify that in fact the rank is full.354335443545OUTPUT: a matrix or vector over `\QQ`35463547EXAMPLES::35483549sage: a = matrix(ZZ, 2, [0, -1, 1, 0])3550sage: v = vector(ZZ, [2, 3])3551sage: a \ v3552(3, -2)35533554Note that the output vector or matrix is always over3555`\QQ`.35563557::35583559sage: parent(a\v)3560Vector space of dimension 2 over Rational Field35613562We solve a bigger system where the answer is over the rationals.35633564::35653566sage: a = matrix(ZZ, 3, 3, [1,2,3,4, 5, 6, 8, -2, 3])3567sage: v = vector(ZZ, [1,2,3])3568sage: w = a \ v; w3569(2/15, -4/15, 7/15)3570sage: parent(w)3571Vector space of dimension 3 over Rational Field3572sage: a * w3573(1, 2, 3)35743575We solve a system where the right hand matrix has multiple3576columns.35773578::35793580sage: a = matrix(ZZ, 3, 3, [1,2,3,4, 5, 6, 8, -2, 3])3581sage: b = matrix(ZZ, 3, 2, [1,5, 2, -3, 3, 0])3582sage: w = a \ b; w3583[ 2/15 -19/5]3584[-4/15 -27/5]3585[ 7/15 98/15]3586sage: a * w3587[ 1 5]3588[ 2 -3]3589[ 3 0]35903591TESTS: We create a random 100x100 matrix and solve the3592corresponding system, then verify that the result is correct.3593(Note that this test is very risky without having a seeded3594random number generator!)35953596::35973598sage: n = 1003599sage: a = random_matrix(ZZ,n)3600sage: v = vector(ZZ,n,range(n))3601sage: x = a \ v3602sage: a * x == v3603True3604"""3605t = verbose('starting IML solve_right...')3606# It would probably be much better to rewrite linbox so it3607# throws an error instead of ** going into an infinite loop **3608# in the non-full rank case. In any case, we do this for now,3609# since rank is very fast and infinite loops are evil.3610if check_rank and self.rank() < self.nrows():3611raise ValueError("self must be of full rank.")36123613if not self.is_square():3614raise NotImplementedError("the input matrix must be square.")36153616if is_Vector(B):3617if self.nrows() != B.degree():3618raise ValueError("number of rows of self must equal degree of B.")3619elif self.nrows() != B.nrows():3620raise ValueError("number of rows of self must equal number of rows of B.")36213622if self.nrows() == 0:3623return B36243625matrix = True3626C = B3627if not isinstance(B, Matrix_integer_dense):3628if is_Vector(B):3629matrix = False3630C = self.matrix_space(self.nrows(), 1)(B.list())3631else:3632raise NotImplementedError36333634if C.ncols() >= 2*self.ncols():3635# likely much better to just invert then multiply3636X = self**(-1)*C3637verbose('finished solve_right (via inverse)', t)3638return X36393640X, d = self._solve_iml(C, right=True)3641if d != 1:3642X = (1/d) * X3643if not matrix:3644# Convert back to a vector3645X = (X.base_ring() ** X.nrows())(X.list())3646verbose('finished solve_right via IML', t)3647return X36483649def _solve_iml(self, Matrix_integer_dense B, right=True):3650"""3651Let A equal self be a square matrix. Given B return an integer3652matrix C and an integer d such that self C\*A == d\*B if right is3653False or A\*C == d\*B if right is True.36543655OUTPUT:365636573658- ``C`` - integer matrix36593660- ``d`` - integer denominator366136623663EXAMPLES::36643665sage: A = matrix(ZZ,4,4,[0, 1, -2, -1, -1, 1, 0, 2, 2, 2, 2, -1, 0, 2, 2, 1])3666sage: B = matrix(ZZ,3,4, [-1, 1, 1, 0, 2, 0, -2, -1, 0, -2, -2, -2])3667sage: C,d = A._solve_iml(B,right=False); C3668[ 6 -18 -15 27]3669[ 0 24 24 -36]3670[ 4 -12 -6 -2]36713672::36733674sage: d36751236763677::36783679sage: C*A == d*B3680True36813682::36833684sage: A = matrix(ZZ,4,4,[0, 1, -2, -1, -1, 1, 0, 2, 2, 2, 2, -1, 0, 2, 2, 1])3685sage: B = matrix(ZZ,4,3, [-1, 1, 1, 0, 2, 0, -2, -1, 0, -2, -2, -2])3686sage: C,d = A._solve_iml(B)3687sage: C3688[ 12 40 28]3689[-12 -4 -4]3690[ -6 -25 -16]3691[ 12 34 16]36923693::36943695sage: d36961236973698::36993700sage: A*C == d*B3701True37023703ALGORITHM: Uses IML.37043705AUTHORS:37063707- Martin Albrecht3708"""3709cdef int i3710cdef mpz_t *mp_N, mp_D3711cdef Matrix_integer_dense M3712cdef Integer D37133714if self._nrows != self._ncols:3715# This is *required* by the IML function we call below.3716raise ArithmeticError("self must be a square matrix")37173718if self.nrows() == 1:3719return B, self[0,0]372037213722if right:3723if self._ncols != B._nrows:3724raise ArithmeticError("B's number of rows must match self's number of columns")37253726n = self._ncols3727m = B._ncols3728P = self.matrix_space(n, m)3729if self._nrows == 0 or self._ncols == 0:3730return P.zero_matrix(), Integer(1)37313732if m == 0 or n == 0:3733return self.new_matrix(nrows = n, ncols = m), Integer(1)37343735mpz_init(mp_D)3736mp_N = <mpz_t *> sage_malloc( n * m * sizeof(mpz_t) )3737for i from 0 <= i < n * m:3738mpz_init( mp_N[i] )37393740nonsingSolvLlhsMM(RightSolu, n, m, self._entries, B._entries, mp_N, mp_D)37413742else: # left3743if self._nrows != B._ncols:3744raise ArithmeticError("B's number of columns must match self's number of rows")37453746n = self._ncols3747m = B._nrows37483749P = self.matrix_space(m, n)3750if self._nrows == 0 or self._ncols == 0:3751return P.zero_matrix(), Integer(1)37523753if m == 0 or n == 0:3754return self.new_matrix(nrows = m, ncols = n), Integer(1)37553756mpz_init(mp_D)3757mp_N = <mpz_t *> sage_malloc( n * m * sizeof(mpz_t) )3758for i from 0 <= i < n * m:3759mpz_init( mp_N[i] )37603761nonsingSolvLlhsMM(LeftSolu, n, m, self._entries, B._entries, mp_N, mp_D)376237633764M = Matrix_integer_dense.__new__(Matrix_integer_dense, P, None, None, None)3765for i from 0 <= i < n*m:3766mpz_init_set(M._entries[i], mp_N[i])3767mpz_clear(mp_N[i])3768sage_free(mp_N)3769M._initialized = True37703771D = PY_NEW(Integer)3772mpz_set(D.value, mp_D)3773mpz_clear(mp_D)37743775return M,D37763777def _rational_echelon_via_solve(self):3778r"""3779Computes information that gives the reduced row echelon form (over3780QQ!) of a matrix with integer entries.37813782INPUT:378337843785- ``self`` - a matrix over the integers.378637873788OUTPUT:378937903791- ``pivots`` - ordered list of integers that give the3792pivot column positions37933794- ``nonpivots`` - ordered list of the nonpivot column3795positions37963797- ``X`` - matrix with integer entries37983799- ``d`` - integer380038013802If you put standard basis vectors in order at the pivot columns,3803and put the matrix (1/d)\*X everywhere else, then you get the3804reduced row echelon form of self, without zero rows at the bottom.38053806.. note::38073808IML is the actual underlying `p`-adic solver that we3809use.38103811AUTHORS:38123813- William Stein38143815ALGORITHM: I came up with this algorithm from scratch. As far as I3816know it is new. It's pretty simple, but it is ... (fast?!).38173818Let A be the input matrix.381938203821#. Compute r = rank(A).38223823#. Compute the pivot columns of the transpose `A^t` of3824`A`. One way to do this is to choose a random prime3825`p` and compute the row echelon form of `A^t`3826modulo `p` (if the number of pivot columns is not equal to3827`r`, pick another prime).38283829#. Let `B` be the submatrix of `A` consisting of3830the rows corresponding to the pivot columns found in the previous3831step. Note that, aside from zero rows at the bottom, `B`3832and `A` have the same reduced row echelon form.38333834#. Compute the pivot columns of `B`, again possibly by3835choosing a random prime `p` as in [2] and computing the3836Echelon form modulo `p`. If the number of pivot columns is3837not `r`, repeat with a different prime. Note - in this step3838it is possible that we mistakenly choose a bad prime `p`3839such that there are the right number of pivot columns modulo3840`p`, but they are at the wrong positions - e.g., imagine3841the augmented matrix `[pI|I]` - modulo `p` we would3842miss all the pivot columns. This is OK, since in the next step we3843would detect this, as the matrix we would obtain would not be in3844echelon form.38453846#. Let `C` be the submatrix of `B` of pivot3847columns. Let `D` be the complementary submatrix of3848`B` of all all non-pivot columns. Use a `p`-adic3849solver to find the matrix `X` and integer `d` such3850that `C (1/d) X=D`. I.e., solve a bunch of linear systems3851of the form `Cx = v`, where the columns of `X` are3852the solutions.38533854#. Verify that we had chosen the correct pivot columns. Inspect the3855matrix `X` obtained in step 5. If when used to construct3856the echelon form of `B`, `X` indeed gives a matrix3857in reduced row echelon form, then we are done - output the pivot3858columns, `X`, and `d`. To tell if `X` is3859correct, do the following: For each column of `X`3860(corresponding to non-pivot column `i` of `B`),3861read up the column of `X` until finding the first nonzero3862position `j`; then verify that `j` is strictly less3863than the number of pivot columns of `B` that are strictly3864less than `i`. Otherwise, we got the pivots of `B`3865wrong - try again starting at step 4, but with a different random3866prime.3867"""3868if self._nrows == 0:3869pivots = []3870nonpivots = range(self._ncols)3871X = self.__copy__()3872d = Integer(1)3873return pivots, nonpivots, X, d3874elif self._ncols == 0:3875pivots = []3876nonpivots = []3877X = self.__copy__()3878d = Integer(1)3879return pivots, nonpivots, X, d38803881from matrix_modn_dense import MAX_MODULUS3882A = self3883# Step 1: Compute the rank38843885t = verbose('computing rank', level=2, caller_name='p-adic echelon')3886r = A.rank()3887verbose('done computing rank', level=2, t=t, caller_name='p-adic echelon')38883889cdef randstate rstate = current_randstate()38903891if r == self._nrows:3892# The input matrix already has full rank.3893B = A3894else:3895# Steps 2 and 3: Extract out a submatrix of full rank.3896i = 03897while True:3898p = previous_prime(rstate.c_random() % (MAX_MODULUS-15000) + 10000)3899P = A._mod_int(p).transpose().pivots()3900if len(P) == r:3901B = A.matrix_from_rows(P)3902break3903else:3904i += 13905if i == 50:3906raise RuntimeError("Bug in _rational_echelon_via_solve in finding linearly independent rows.")39073908_i = 03909while True:3910_i += 13911if _i == 50:3912raise RuntimeError("Bug in _rational_echelon_via_solve -- pivot columns keep being wrong.")39133914# Step 4: Now we instead worry about computing the reduced row echelon form of B.3915i = 03916while True:3917p = previous_prime(rstate.c_random() % (MAX_MODULUS-15000) + 10000)3918pivots = B._mod_int(p).pivots()3919if len(pivots) == r:3920break3921else:3922i += 13923if i == 50:3924raise RuntimeError("Bug in _rational_echelon_via_solve in finding pivot columns.")39253926# Step 5: Apply p-adic solver3927C = B.matrix_from_columns(pivots)3928pivots_ = set(pivots)3929non_pivots = [i for i in range(B.ncols()) if not i in pivots_]3930D = B.matrix_from_columns(non_pivots)3931t = verbose('calling IML solver', level=2, caller_name='p-adic echelon')3932X, d = C._solve_iml(D, right=True)3933t = verbose('finished IML solver', level=2, caller_name='p-adic echelon', t=t)39343935# Step 6: Verify that we had chosen the correct pivot columns.3936pivots_are_right = True3937for z in range(X.ncols()):3938if not pivots_are_right:3939break3940i = non_pivots[z]3941np = len([k for k in pivots if k < i])3942for j in reversed(range(X.nrows())):3943if X[j,z] != 0:3944if j < np:3945break # we're good -- go on to next column of X3946else:3947pivots_are_right = False3948break3949if pivots_are_right:3950break39513952#end while395339543955# Finally, return the answer.3956return pivots, non_pivots, X, d39573958def decomposition(self, **kwds):3959"""3960Returns the decomposition of the free module on which this matrix A3961acts from the right (i.e., the action is x goes to x A), along with3962whether this matrix acts irreducibly on each factor. The factors3963are guaranteed to be sorted in the same way as the corresponding3964factors of the characteristic polynomial, and are saturated as ZZ3965modules.39663967INPUT:396839693970- ``self`` - a matrix over the integers39713972- ``**kwds`` - these are passed onto to the3973decomposition over QQ command.397439753976EXAMPLES::39773978sage: t = ModularSymbols(11,sign=1).hecke_matrix(2)3979sage: w = t.change_ring(ZZ)3980sage: w.list()3981[3, -1, 0, -2]3982"""3983F = self.charpoly().factor()3984if len(F) == 1:3985V = self.base_ring()**self.nrows()3986return decomp_seq([(V, F[0][1]==1)])39873988A = self.change_ring(QQ)3989X = A.decomposition(**kwds)3990V = ZZ**self.nrows()3991if isinstance(X, tuple):3992D, E = X3993D = [(W.intersection(V), t) for W, t in D]3994E = [(W.intersection(V), t) for W, t in E]3995return decomp_seq(D), decomp_seq(E)3996else:3997return decomp_seq([(W.intersection(V), t) for W, t in X])39983999def _add_row_and_maintain_echelon_form(self, row, pivots):4000"""4001Assuming self is a full rank n x m matrix in reduced row Echelon4002form over ZZ and row is a vector of degree m, this function creates4003a new matrix that is the echelon form of self with row appended to4004the bottom.40054006.. warning::40074008It is assumed that self is in echelon form.40094010INPUT:401140124013- ``row`` - a vector of degree m over ZZ40144015- ``pivots`` - a list of integers that are the pivot4016columns of self.401740184019OUTPUT:402040214022- ``matrix`` - a matrix of in reduced row echelon form4023over ZZ40244025- ``pivots`` - list of integers402640274028ALGORITHM: For each pivot column of self, we use the extended4029Euclidean algorithm to clear the column. The result is a new matrix4030B whose row span is the same as self.stack(row), and whose last row4031is 0 if and only if row is in the QQ-span of the rows of self. If4032row is not in the QQ-span of the rows of self, then row is nonzero4033and suitable to be inserted into the top n rows of A to form a new4034matrix that is in reduced row echelon form. We then clear that4035corresponding new pivot column.40364037EXAMPLES::40384039sage: a = matrix(ZZ, 3, [1, 0, 110, 0, 3, 112, 0, 0, 221]); a4040[ 1 0 110]4041[ 0 3 112]4042[ 0 0 221]4043sage: a._add_row_and_maintain_echelon_form(vector(ZZ,[1,2,3]),[0,1,2])4044(4045[1 0 0]4046[0 1 0]4047[0 0 1], [0, 1, 2]4048)4049sage: a._add_row_and_maintain_echelon_form(vector(ZZ,[0,0,0]),[0,1,2])4050(4051[ 1 0 110]4052[ 0 3 112]4053[ 0 0 221], [0, 1, 2]4054)4055sage: a = matrix(ZZ, 2, [1, 0, 110, 0, 3, 112])4056sage: a._add_row_and_maintain_echelon_form(vector(ZZ,[1,2,3]),[0,1])4057(4058[ 1 0 110]4059[ 0 1 219]4060[ 0 0 545], [0, 1, 2]4061)4062"""4063from sage.all import get_memory_usage4064cdef Py_ssize_t i, j, piv, n = self._nrows, m = self._ncols40654066import constructor40674068# 0. Base case4069if self.nrows() == 0:4070pos = row.nonzero_positions()4071if len(pos) > 0:4072pivots = [pos[0]]4073if row[pivots[0]] < 0:4074row *= -14075else:4076pivots = []4077return constructor.matrix([row]), pivots407840794080if row == 0:4081return self, pivots4082# 1. Create a new matrix that has row as the last row.4083row_mat = constructor.matrix(row)4084A = self.stack(row_mat)4085# 2. Working from the left, clear each column to put4086# the resulting matrix back in echelon form.4087for i, p in enumerate(pivots):4088# p is the i-th pivot4089b = A[n,p]4090if not b:4091continue40924093# (a). Take xgcd of pivot positions in last row and in ith4094# row.40954096# TODO (optimize) -- change to use direct call to gmp and4097# no bounds checking!4098a = A[i,p]4099if not a:4100raise ZeroDivisionError("claimed pivot is not a pivot")4101if b % a == 0:4102# (b) Subtract a multiple of row i from row n.4103c = b // a4104if c:4105for j in range(m):4106A[n,j] -= c * A[i,j]4107else:4108# (b). More elaborate.4109# Replace the ith row by s*A[i] + t*A[n], which will4110# have g in the i,p position, and replace the last row by4111# (b//g)*A[i] - (a//g)*A[n], which will have 0 in the i,p4112# position.4113g, s, t = a.xgcd(b)4114if not g:4115raise ZeroDivisionError("claimed pivot is not a pivot (got a 0 gcd)")41164117row_i = A.row(i)4118row_n = A.row(n)41194120ag = a//g; bg = b//g41214122new_top = s*row_i + t*row_n4123new_bot = bg*row_i - ag*row_n412441254126# OK -- now we have to make sure the top part of the matrix4127# but with row i replaced by4128# r = s*row_i[j] + t*row_n[j]4129# is put in rref. We do this by recursively calling this4130# function with the top part of A (all but last row) and the4131# row r.41324133zz = range(A.nrows()-1)4134del zz[i]4135top_mat = A.matrix_from_rows(zz)4136new_pivots = list(pivots)4137del new_pivots[i]41384139top_mat, pivots = top_mat._add_row_and_maintain_echelon_form(new_top, new_pivots)4140w = top_mat._add_row_and_maintain_echelon_form(new_bot, pivots)4141return w4142# 3. If it turns out that the last row is nonzero,4143# insert last row in A sliding other rows down.4144v = A.row(n)4145new_pivots = list(pivots)4146if v != 0:4147i = v.nonzero_positions()[0]4148assert not (i in pivots), 'WARNING: bug in add_row -- i (=%s) should not be a pivot'%i41494150# If pivot entry is negative negate this row.4151if v[i] < 0:4152v = -v41534154# Determine where the last row should be inserted.4155new_pivots.append(i)4156new_pivots.sort()4157import bisect4158j = bisect.bisect(pivots, i)4159# The new row should go *before* row j, so it becomes row j4160A = A.insert_row(j, v)4161try:4162_clear_columns(A, new_pivots, A.nrows())4163except RuntimeError:4164raise ZeroDivisionError("mistake in claimed pivots")4165if A.row(A.nrows() - 1) == 0:4166A = A.matrix_from_rows(range(A.nrows()-1))4167return A, new_pivots41684169#####################################################################################4170# Hermite form modulo D4171# This code below is by E. Burcin. Thanks!4172#####################################################################################4173cdef _new_uninitialized_matrix(self, Py_ssize_t nrows, Py_ssize_t ncols):4174"""4175Return a new matrix over the integers with the given number of rows4176and columns. All memory is allocated for this matrix, but its4177entries have not yet been filled in.4178"""4179P = self._parent.matrix_space(nrows, ncols)4180return Matrix_integer_dense.__new__(Matrix_integer_dense, P, None, None, None)41814182def _hnf_mod(self, D):4183"""4184INPUT:418541864187- ``D`` - a small integer that is assumed to be a4188multiple of 2\*det(self)418941904191OUTPUT:419241934194- ``matrix`` - the Hermite normal form of self.4195"""4196t = verbose('hermite mod %s'%D, caller_name='matrix_integer_dense')4197cdef Matrix_integer_dense res = self._new_uninitialized_matrix(self._nrows, self._ncols)4198self._hnf_modn(res, D)4199verbose('finished hnf mod', t, caller_name='matrix_integer_dense')4200return res42014202cdef int _hnf_modn(Matrix_integer_dense self, Matrix_integer_dense res,4203mod_int det) except -1:4204"""4205Puts self into HNT form modulo det. Changes self in place.4206"""4207cdef long long *res_l4208cdef Py_ssize_t i,j,k4209res_l = self._hnf_modn_impl(det, self._nrows, self._ncols)4210k = 04211for i from 0 <= i < self._nrows:4212for j from 0 <= j < self._ncols:4213mpz_init_set_si(res._matrix[i][j], res_l[k])4214k += 14215res._initialized = True4216sage_free(res_l)421742184219cdef long long* _hnf_modn_impl(Matrix_integer_dense self, mod_int det,4220Py_ssize_t nrows, Py_ssize_t ncols) except NULL:4221cdef long long *res, *T_ent, **res_rows, **T_rows, *B4222cdef Py_ssize_t i, j, k4223cdef long long R, mod, T_i_i, T_j_i, c1, c2, q, t4224cdef int u, v, d4225cdef mpz_t m42264227# allocate memory for result matrix4228res = <long long*> sage_malloc(sizeof(long long)*ncols*nrows)4229if res == NULL:4230raise MemoryError("out of memory allocating a matrix")4231res_rows = <long long**> sage_malloc(sizeof(long long*)*nrows)4232if res_rows == NULL:4233sage_free(res)4234raise MemoryError("out of memory allocating a matrix")42354236# allocate memory for temporary matrix4237T_ent = <long long*> sage_malloc(sizeof(long long)*ncols*nrows)4238if T_ent == NULL:4239sage_free(res)4240sage_free(res_rows)4241raise MemoryError("out of memory allocating a matrix")4242T_rows = <long long**> sage_malloc(sizeof(long long*)*nrows)4243if T_rows == NULL:4244sage_free(res)4245sage_free(res_rows)4246sage_free(T_ent)4247raise MemoryError("out of memory allocating a matrix")42484249# allocate memory for temporary row vector4250B = <long long*>sage_malloc(sizeof(long long)*nrows)4251if B == NULL:4252sage_free(res)4253sage_free(res_rows)4254sage_free(T_ent)4255sage_free(T_rows)4256raise MemoryError("out of memory allocating a matrix")42574258# initialize the row pointers4259k = 04260for i from 0 <= i < nrows:4261res_rows[i] = res + k4262T_rows[i] = T_ent + k4263k += nrows426442654266mpz_init(m)4267# copy entries from self to temporary matrix4268k = 04269for i from 0 <= i < nrows:4270for j from 0 <= j < ncols:4271mpz_mod_ui(m, self._matrix[i][j], det)4272T_ent[k] = mpz_get_si(m)4273k += 14274mpz_clear(m)427542764277# initialize variables4278i = 04279j = 04280R = det42814282while 1:4283if j == nrows-1:4284T_i_i = T_rows[i][i]4285d = ai.c_xgcd_int(T_i_i, R, &u, &v)4286for k from 0 <= k < i:4287res_rows[i][k] = 04288for k from i <= k < ncols:4289t = (u*T_rows[i][k])%R4290if t < 0:4291t += R4292res_rows[i][k] = t4293if res_rows[i][i] == 0:4294res_rows[i][i] = R4295d = res_rows[i][i]4296for j from 0 <= j < i:4297q = res_rows[j][i]/d4298for k from i <= k < ncols:4299u = (res_rows[j][k] - q*res_rows[i][k])%R4300if u < 0:4301u += R4302res_rows[j][k] = u43034304R = R/d4305i += 14306j = i4307if i == nrows :4308break # return res4309if T_rows[i][i] == 0:4310T_rows[i][i] = R4311continue431243134314j += 14315if T_rows[j][i] == 0:4316continue43174318T_i_i = T_rows[i][i]4319T_j_i = T_rows[j][i]4320d = ai.c_xgcd_int(T_i_i , T_j_i, &u, &v)4321if d != T_i_i:4322for k from i <= k < ncols:4323B[k] = (u*T_rows[i][k] + v*T_rows[j][k])4324c1 = T_i_i/d4325c2 = -T_j_i/d4326for k from i <= k < ncols:4327T_rows[j][k] = (c1*T_rows[j][k] + c2*T_rows[i][k])%R4328if d != T_i_i:4329for k from i <= k < ncols:4330T_rows[i][k] = B[k]%R43314332sage_free(B)4333sage_free(res_rows)4334sage_free(T_ent)4335sage_free(T_rows)4336return res433743384339#####################################################################################4340# operations with matrices4341#####################################################################################4342def stack(self, bottom, subdivide=False):4343r"""4344Return the matrix self on top of bottom: [ self ] [ bottom ]43454346EXAMPLES::43474348sage: M = Matrix(ZZ, 2, 3, range(6))4349sage: N = Matrix(ZZ, 1, 3, [10,11,12])4350sage: M.stack(N)4351[ 0 1 2]4352[ 3 4 5]4353[10 11 12]43544355A vector may be stacked below a matrix. ::43564357sage: A = matrix(ZZ, 2, 4, range(8))4358sage: v = vector(ZZ, 4, range(4))4359sage: A.stack(v)4360[0 1 2 3]4361[4 5 6 7]4362[0 1 2 3]43634364The ``subdivide`` option will add a natural subdivision between4365``self`` and ``bottom``. For more details about how subdivisions4366are managed when stacking, see4367:meth:`sage.matrix.matrix1.Matrix.stack`. ::43684369sage: A = matrix(ZZ, 3, 4, range(12))4370sage: B = matrix(ZZ, 2, 4, range(8))4371sage: A.stack(B, subdivide=True)4372[ 0 1 2 3]4373[ 4 5 6 7]4374[ 8 9 10 11]4375[-----------]4376[ 0 1 2 3]4377[ 4 5 6 7]43784379TESTS:43804381Stacking a dense matrix atop a sparse one should work::43824383sage: M = Matrix(ZZ, 2, 3, range(6))4384sage: M.is_sparse()4385False4386sage: N = diagonal_matrix([10,11,12], sparse=True)4387sage: N.is_sparse()4388True4389sage: P = M.stack(N); P4390[ 0 1 2]4391[ 3 4 5]4392[10 0 0]4393[ 0 11 0]4394[ 0 0 12]4395sage: P.is_sparse()4396False4397"""4398if hasattr(bottom, '_vector_'):4399bottom = bottom.row()4400if self._ncols != bottom.ncols():4401raise TypeError("number of columns must be the same")4402if not (self._base_ring is bottom.base_ring()):4403bottom = bottom.change_ring(self._base_ring)4404cdef Matrix_integer_dense other = bottom.dense_matrix()4405cdef Matrix_integer_dense M4406M = self.new_matrix(nrows = self._nrows + other._nrows, ncols = self.ncols())4407cdef Py_ssize_t i, k4408k = self._nrows * self._ncols4409for i from 0 <= i < k:4410mpz_set(M._entries[i], self._entries[i])4411for i from 0 <= i < other._nrows * other._ncols:4412mpz_set(M._entries[k + i], other._entries[i])4413if subdivide:4414M._subdivide_on_stack(self, other)4415return M44164417def augment(self, right, subdivide=False):4418r"""4419Returns a new matrix formed by appending the matrix4420(or vector) ``right`` on the right side of ``self``.44214422INPUT:44234424- ``right`` - a matrix, vector or free module element, whose4425dimensions are compatible with ``self``.44264427- ``subdivide`` - default: ``False`` - request the resulting4428matrix to have a new subdivision, separating ``self`` from ``right``.44294430OUTPUT:44314432A new matrix formed by appending ``right`` onto the right side of ``self``.4433If ``right`` is a vector (or free module element) then in this context4434it is appropriate to consider it as a column vector. (The code first4435converts a vector to a 1-column matrix.)44364437EXAMPLES::44384439sage: A = matrix(ZZ, 4, 5, range(20))4440sage: B = matrix(ZZ, 4, 3, range(12))4441sage: A.augment(B)4442[ 0 1 2 3 4 0 1 2]4443[ 5 6 7 8 9 3 4 5]4444[10 11 12 13 14 6 7 8]4445[15 16 17 18 19 9 10 11]44464447A vector may be augmented to a matrix. ::44484449sage: A = matrix(ZZ, 3, 5, range(15))4450sage: v = vector(ZZ, 3, range(3))4451sage: A.augment(v)4452[ 0 1 2 3 4 0]4453[ 5 6 7 8 9 1]4454[10 11 12 13 14 2]44554456The ``subdivide`` option will add a natural subdivision between4457``self`` and ``right``. For more details about how subdivisions4458are managed when augmenting, see4459:meth:`sage.matrix.matrix1.Matrix.augment`. ::44604461sage: A = matrix(ZZ, 3, 5, range(15))4462sage: B = matrix(ZZ, 3, 3, range(9))4463sage: A.augment(B, subdivide=True)4464[ 0 1 2 3 4| 0 1 2]4465[ 5 6 7 8 9| 3 4 5]4466[10 11 12 13 14| 6 7 8]44674468Errors are raised if the sizes are incompatible. ::44694470sage: A = matrix(ZZ, [[1, 2],[3, 4]])4471sage: B = matrix(ZZ, [[10, 20], [30, 40], [50, 60]])4472sage: A.augment(B)4473Traceback (most recent call last):4474...4475TypeError: number of rows must be the same, not 2 != 34476"""4477if hasattr(right, '_vector_'):4478right = right.column()4479if self._nrows != right.nrows():4480raise TypeError('number of rows must be the same, not {0} != {1}'.format(self._nrows, right.nrows()))4481if not (self._base_ring is right.base_ring()):4482right = right.change_ring(self._base_ring)44834484cdef Matrix_integer_dense other = right.dense_matrix()4485m = self._nrows4486ns, na = self._ncols, other._ncols4487n = ns + na44884489cdef Matrix_integer_dense Z4490Z = self.new_matrix(nrows = m, ncols = n)4491cdef Py_ssize_t i, j, p, qs, qa4492p, qs, qa = 0, 0, 04493for i from 0 <= i < m:4494for j from 0 <= j < ns:4495mpz_set(Z._entries[p], self._entries[qs])4496p = p + 14497qs = qs + 14498for j from 0 <= j < na:4499mpz_set(Z._entries[p], other._entries[qa])4500p = p + 14501qa = qa + 14502if subdivide:4503Z._subdivide_on_augment(self, other)4504return Z45054506def insert_row(self, Py_ssize_t index, row):4507"""4508Create a new matrix from self with.45094510INPUT:45114512- ``index`` - integer45134514- ``row`` - a vector45154516EXAMPLES::45174518sage: X = matrix(ZZ,3,range(9)); X4519[0 1 2]4520[3 4 5]4521[6 7 8]4522sage: X.insert_row(1, [1,5,-10])4523[ 0 1 2]4524[ 1 5 -10]4525[ 3 4 5]4526[ 6 7 8]4527sage: X.insert_row(0, [1,5,-10])4528[ 1 5 -10]4529[ 0 1 2]4530[ 3 4 5]4531[ 6 7 8]4532sage: X.insert_row(3, [1,5,-10])4533[ 0 1 2]4534[ 3 4 5]4535[ 6 7 8]4536[ 1 5 -10]4537"""4538cdef Matrix_integer_dense res = self._new_uninitialized_matrix(self._nrows + 1, self._ncols)4539cdef Py_ssize_t j, k4540cdef Integer z4541if index < 0:4542raise ValueError("index must be nonnegative")4543if index > self._nrows:4544raise ValueError("index must be less than number of rows")4545for j from 0 <= j < self._ncols * index:4546mpz_init_set(res._entries[j], self._entries[j])45474548k = 04549for j from self._ncols * index <= j < self._ncols * (index+1):4550z = row[k]4551mpz_init_set(res._entries[j], z.value)4552k += 145534554for j from self._ncols * (index+1) <= j < (self._nrows + 1)*self._ncols:4555mpz_init_set(res._entries[j], self._entries[j - self._ncols])45564557res._initialized = True4558return res45594560def _delete_zero_columns(self):4561"""4562Return matrix obtained from self by deleting all zero columns along4563with the positions of those columns.45644565OUTPUT: matrix list of integers45664567EXAMPLES::45684569sage: a = matrix(ZZ, 2,3, [1,0,3,-1,0,5]); a4570[ 1 0 3]4571[-1 0 5]4572sage: a._delete_zero_columns()4573(4574[ 1 3]4575[-1 5], [1]4576)4577"""4578C = self.columns()4579zero_cols = [i for i,v in enumerate(self.columns()) if v.is_zero()]4580s = set(zero_cols)4581nonzero_cols = [i for i in range(self.ncols()) if not (i in s)]4582return self.matrix_from_columns(nonzero_cols), zero_cols45834584def _insert_zero_columns(self, cols):4585"""4586Return matrix obtained by self by inserting zero columns so that4587the columns with positions specified in cols are all 0.45884589INPUT:45904591- ``cols`` - list of nonnegative integers45924593OUTPUT: matrix45944595EXAMPLES::45964597sage: a = matrix(ZZ, 2,3, [1,0,3,-1,0,5]); a4598[ 1 0 3]4599[-1 0 5]4600sage: b, cols = a._delete_zero_columns()4601sage: b4602[ 1 3]4603[-1 5]4604sage: cols4605[1]4606sage: b._insert_zero_columns(cols)4607[ 1 0 3]4608[-1 0 5]4609"""4610if len(cols) == 0:4611return self4612cdef Py_ssize_t i, c, r, nc = max(self._ncols + len(cols), max(cols)+1)4613cdef Matrix_integer_dense A = self.new_matrix(self._nrows, nc)4614# Now fill in the entries of A that come from self.4615cols_set = set(cols)4616cols_ins = [j for j in range(nc) if j not in cols_set]4617for r from 0 <= r < self._nrows:4618i = 04619for c in cols_ins:4620# The following does this quickly: A[r,c] = self[r,i]4621mpz_set(A._matrix[r][c], self._matrix[r][i])4622i += 14623return A46244625def _factor_out_common_factors_from_each_row(self):4626"""4627Very very quickly modifies self so that the gcd of the entries in4628each row is 1 by dividing each row by the common gcd.46294630EXAMPLES::46314632sage: a = matrix(ZZ, 3, [-9, 3, -3, -36, 18, -5, -40, -5, -5, -20, -45, 15, 30, -15, 180])4633sage: a4634[ -9 3 -3 -36 18]4635[ -5 -40 -5 -5 -20]4636[-45 15 30 -15 180]4637sage: a._factor_out_common_factors_from_each_row()4638sage: a4639[ -3 1 -1 -12 6]4640[ -1 -8 -1 -1 -4]4641[ -3 1 2 -1 12]4642"""4643self.check_mutability()46444645cdef mpz_t g4646mpz_init(g)4647cdef Py_ssize_t i, j4648cdef mpz_t* row46494650for i from 0 <= i < self._nrows:4651mpz_set_ui(g, 0)4652row = self._matrix[i]4653for j from 0 <= j < self._ncols:4654mpz_gcd(g, g, row[j])4655if mpz_cmp_ui(g, 1) == 0:4656break4657if mpz_cmp_ui(g, 1) != 0:4658# divide through row4659for j from 0 <= j < self._ncols:4660mpz_divexact(row[j], row[j], g)4661mpz_clear(g)46624663def gcd(self):4664"""4665Return the gcd of all entries of self; very fast.46664667EXAMPLES::46684669sage: a = matrix(ZZ,2, [6,15,-6,150])4670sage: a.gcd()467134672"""4673cdef Integer g = Integer(0)4674cdef Py_ssize_t i, j4675cdef mpz_t* row46764677for i from 0 <= i < self._nrows:4678row = self._matrix[i]4679for j from 0 <= j < self._ncols:4680mpz_gcd(g.value, g.value, row[j])4681if mpz_cmp_ui(g.value, 1) == 0:4682return g4683return g46844685def _change_ring(self, ring):4686"""4687Return the matrix obtained by coercing the entries of this matrix4688into the given ring.46894690EXAMPLES::46914692sage: a = matrix(ZZ,2,[1,-7,3,5])4693sage: a._change_ring(RDF)4694[ 1.0 -7.0]4695[ 3.0 5.0]4696"""4697if ring == RDF:4698import change_ring4699return change_ring.integer_to_real_double_dense(self)4700else:4701raise NotImplementedError47024703def _singular_(self, singular=None):4704r"""4705Return Singular representation of this integer matrix.47064707INPUT:470847094710- ``singular`` - Singular interface instance (default:4711None)471247134714EXAMPLE::47154716sage: A = random_matrix(ZZ,3,3)4717sage: As = singular(A); As4718-8 2 047190 1 -147202 1 -954721sage: As.type()4722'intmat'4723"""4724if singular is None:4725from sage.interfaces.singular import singular as singular_default4726singular = singular_default47274728name = singular._next_var_name()4729values = str(self.list())[1:-1]4730singular.eval("intmat %s[%d][%d] = %s"%(name, self.nrows(), self.ncols(), values))47314732from sage.interfaces.singular import SingularElement4733return SingularElement(singular, 'foobar', name, True)47344735def transpose(self):4736"""4737Returns the transpose of self, without changing self.47384739EXAMPLES:47404741We create a matrix, compute its transpose, and note that the4742original matrix is not changed.47434744::47454746sage: A = matrix(ZZ,2,3,xrange(6))4747sage: type(A)4748<type 'sage.matrix.matrix_integer_dense.Matrix_integer_dense'>4749sage: B = A.transpose()4750sage: print B4751[0 3]4752[1 4]4753[2 5]4754sage: print A4755[0 1 2]4756[3 4 5]47574758``.T`` is a convenient shortcut for the transpose::47594760sage: A.T4761[0 3]4762[1 4]4763[2 5]47644765::47664767sage: A.subdivide(None, 1); A4768[0|1 2]4769[3|4 5]4770sage: A.transpose()4771[0 3]4772[---]4773[1 4]4774[2 5]4775"""4776cdef Matrix_integer_dense A4777A = Matrix_integer_dense.__new__(Matrix_integer_dense,4778self._parent.matrix_space(self._ncols,self._nrows),47790,False,False)4780cdef Py_ssize_t i,j4781sig_on()4782for i from 0 <= i < self._nrows:4783for j from 0 <= j < self._ncols:4784mpz_init_set(A._matrix[j][i], self._matrix[i][j])4785sig_off()4786A._initialized = True4787if self._subdivisions is not None:4788row_divs, col_divs = self.subdivisions()4789A.subdivide(col_divs, row_divs)4790return A47914792def antitranspose(self):4793"""4794Returns the antitranspose of self, without changing self.47954796EXAMPLES::47974798sage: A = matrix(2,3,range(6))4799sage: type(A)4800<type 'sage.matrix.matrix_integer_dense.Matrix_integer_dense'>4801sage: A.antitranspose()4802[5 2]4803[4 1]4804[3 0]4805sage: A4806[0 1 2]4807[3 4 5]48084809sage: A.subdivide(1,2); A4810[0 1|2]4811[---+-]4812[3 4|5]4813sage: A.antitranspose()4814[5|2]4815[-+-]4816[4|1]4817[3|0]4818"""4819nr , nc = (self._nrows, self._ncols)48204821cdef Matrix_integer_dense A4822A = Matrix_integer_dense.__new__(Matrix_integer_dense,4823self._parent.matrix_space(nc,nr),48240,False,False)48254826cdef Py_ssize_t i,j4827cdef Py_ssize_t ri,rj # reversed i and j4828sig_on()4829ri = nr4830for i from 0 <= i < nr:4831rj = nc4832ri = ri-14833for j from 0 <= j < nc:4834rj = rj-14835mpz_init_set(A._matrix[rj][ri], self._matrix[i][j])4836sig_off()4837A._initialized = True48384839if self._subdivisions is not None:4840row_divs, col_divs = self.subdivisions()4841A.subdivide([nc - t for t in reversed(col_divs)],4842[nr - t for t in reversed(row_divs)])4843return A48444845def _pari_(self):4846"""4847Return PARI C-library version of this matrix.48484849EXAMPLES::48504851sage: a = matrix(ZZ,2,2,[1,2,3,4])4852sage: a._pari_()4853[1, 2; 3, 4]4854sage: pari(a)4855[1, 2; 3, 4]4856sage: type(pari(a))4857<type 'sage.libs.pari.gen.gen'>4858"""4859cdef PariInstance P = sage.libs.pari.gen.pari4860return P.integer_matrix(self._matrix, self._nrows, self._ncols, 0)48614862def _det_pari(self, int flag=0):4863"""4864Determinant of this matrix using Gauss-Bareiss. If (optional)4865flag is set to 1, use classical Gaussian elimination.48664867For efficiency purposes, this det is computed entirely on the4868PARI stack then the PARI stack is cleared. This function is4869most useful for very small matrices.48704871EXAMPLES::48724873sage: matrix(ZZ,3,[1..9])._det_pari()487404875sage: matrix(ZZ,3,[1..9])._det_pari(1)487604877"""4878cdef PariInstance P = sage.libs.pari.gen.pari4879sig_on()4880cdef GEN d = det0(pari_GEN(self), flag)4881# now convert d to a Sage integer e4882cdef Integer e = Integer()4883t_INT_to_ZZ(e.value, d)4884P.clear_stack()4885return e48864887def _rank_pari(self):4888"""4889Rank of this matrix, computed using PARI. The computation is4890done entirely on the PARI stack, then the PARI stack is4891cleared. This function is most useful for very small4892matrices.48934894EXAMPLES::4895sage: matrix(ZZ,3,[1..9])._rank_pari()489624897"""4898cdef PariInstance P = sage.libs.pari.gen.pari4899sig_on()4900cdef long r = rank(pari_GEN(self))4901P.clear_stack()4902return r49034904def _hnf_pari(self, int flag=0, bint include_zero_rows=True):4905"""4906Hermite form of this matrix, computed using PARI. The4907computation is done entirely on the PARI stack, then the PARI4908stack is cleared. This function is only useful for small4909matrices, and can crash on large matrices (e.g., if the PARI4910stack overflows).49114912INPUT:49134914- ``flag`` -- 0 (default), 1, 3 or 4 (see docstring for4915gp.mathnf).49164917- ``include_zero_rows`` -- boolean. if False, do not include4918any of the zero rows at the bottom of the matrix in the4919output.49204921.. NOTE::49224923In no cases is the transformation matrix returned by this4924function.49254926EXAMPLES::49274928sage: matrix(ZZ,3,[1..9])._hnf_pari()4929[1 2 3]4930[0 3 6]4931[0 0 0]4932sage: matrix(ZZ,3,[1..9])._hnf_pari(1)4933[1 2 3]4934[0 3 6]4935[0 0 0]4936sage: matrix(ZZ,3,[1..9])._hnf_pari(3)4937[1 2 3]4938[0 3 6]4939[0 0 0]4940sage: matrix(ZZ,3,[1..9])._hnf_pari(4)4941[1 2 3]4942[0 3 6]4943[0 0 0]49444945Check that ``include_zero_rows=False`` works correctly::49464947sage: matrix(ZZ,3,[1..9])._hnf_pari(0, include_zero_rows=False)4948[1 2 3]4949[0 3 6]4950sage: matrix(ZZ,3,[1..9])._hnf_pari(1, include_zero_rows=False)4951[1 2 3]4952[0 3 6]4953sage: matrix(ZZ,3,[1..9])._hnf_pari(3, include_zero_rows=False)4954[1 2 3]4955[0 3 6]4956sage: matrix(ZZ,3,[1..9])._hnf_pari(4, include_zero_rows=False)4957Traceback (most recent call last):4958...4959NotImplementedError: Pari flag=4 is currently broken.49604961The following tests for the Pari bug in trac #12280. Expected4962output is ``Mat(1), [1, 0; 0, 1]]``. Once this gets fixed we4963can remove the ``NotImplementedError`` below. This is trac4964#12346 ::49654966sage: pari('mathnf(Mat([0,1]), 4)')4967[Mat([0, 1]), [1, 0; 0, 1]]4968"""4969if not include_zero_rows and flag==4:4970raise NotImplementedError('Pari flag=4 is currently broken.')4971cdef PariInstance P = sage.libs.pari.gen.pari4972cdef GEN A4973sig_on()4974A = P._new_GEN_from_mpz_t_matrix_rotate90(self._matrix, self._nrows, self._ncols)4975cdef GEN H = mathnf0(A, flag)4976B = self.extract_hnf_from_pari_matrix(H, flag, include_zero_rows)4977P.clear_stack() # This calls sig_off()4978return B497949804981def _hnf_pari_big(self, int flag=0, bint include_zero_rows=True):4982"""4983Hermite form of this matrix, computed using PARI.49844985INPUT:49864987- ``flag`` -- 0 (default), 1, 3 or 4 (see docstring for4988gp.mathnf).49894990- ``include_zero_rows`` -- boolean. if False, do not include4991any of the zero rows at the bottom of the matrix in the4992output.49934994.. NOTE::49954996In no cases is the transformation matrix returned by this4997function.49984999EXAMPLES::50005001sage: a = matrix(ZZ,3,3,[1..9])5002sage: a._hnf_pari_big(flag=0, include_zero_rows=True)5003[1 2 3]5004[0 3 6]5005[0 0 0]5006sage: a._hnf_pari_big(flag=1, include_zero_rows=True)5007[1 2 3]5008[0 3 6]5009[0 0 0]5010sage: a._hnf_pari_big(flag=3, include_zero_rows=True)5011[1 2 3]5012[0 3 6]5013[0 0 0]5014sage: a._hnf_pari_big(flag=4, include_zero_rows=True)5015[1 2 3]5016[0 3 6]5017[0 0 0]50185019Check that ``include_zero_rows=False`` works correctly::50205021sage: matrix(ZZ,3,[1..9])._hnf_pari_big(0, include_zero_rows=False)5022[1 2 3]5023[0 3 6]5024sage: matrix(ZZ,3,[1..9])._hnf_pari_big(1, include_zero_rows=False)5025[1 2 3]5026[0 3 6]5027sage: matrix(ZZ,3,[1..9])._hnf_pari_big(3, include_zero_rows=False)5028[1 2 3]5029[0 3 6]5030sage: matrix(ZZ,3,[1..9])._hnf_pari_big(4, include_zero_rows=False)5031Traceback (most recent call last):5032...5033NotImplementedError: Pari flag=4 is currently broken.50345035The following tests for the Pari bug in trac #12280. Expected output5036is ``Mat(1), [1, 0; 0, 1]]``. If this gets fixed we can remove5037the ``NotImplementedError`` below. This is trac #12346 ::50385039sage: pari('mathnf(Mat([0,1]), 4)')5040[Mat([0, 1]), [1, 0; 0, 1]]5041"""5042if (not include_zero_rows and flag==4):5043raise NotImplementedError('Pari flag=4 is currently broken.')5044cdef PariInstance P = sage.libs.pari.gen.pari5045cdef gen H = P.integer_matrix(self._matrix, self._nrows, self._ncols, 1)5046H = H.mathnf(flag)5047return self.extract_hnf_from_pari_matrix(H.g, flag, include_zero_rows)50485049cdef extract_hnf_from_pari_matrix(self, GEN H, int flag, bint include_zero_rows):5050# Throw away the transformation matrix (yes, we should later5051# code this to keep track of it).5052if flag > 0:5053H = gel(H,1)50545055# Figure out how many columns we got back.5056cdef Py_ssize_t H_nc = glength(H) # number of columns5057# Now get the resulting Hermite form matrix back to Sage, suitably re-arranged.5058cdef Matrix_integer_dense B5059if include_zero_rows:5060B = self.new_matrix()5061else:5062B = self.new_matrix(nrows=H_nc)5063for i in range(self._ncols):5064for j in range(H_nc):5065t_INT_to_ZZ(B._matrix[j][self._ncols-i-1], gcoeff(H, i+1, H_nc-j))5066return B50675068cdef inline GEN pari_GEN(Matrix_integer_dense B):5069r"""5070Create the PARI GEN object on the stack defined by the integer5071matrix B. This is used internally by the function for conversion5072of matrices to PARI.50735074For internal use only; this directly uses the PARI stack.5075One should call ``sig_on()`` before and ``sig_off()`` after.5076"""5077cdef PariInstance P = sage.libs.pari.gen.pari5078cdef GEN A5079A = P._new_GEN_from_mpz_t_matrix(B._matrix, B._nrows, B._ncols)5080return A508150825083#####################################################################################50845085cdef _clear_columns(Matrix_integer_dense A, pivots, Py_ssize_t n):5086# Clear all columns5087cdef Py_ssize_t i, k, p, l, m = A._ncols5088cdef mpz_t** matrix = A._matrix5089cdef mpz_t c, t5090sig_on()5091mpz_init(c)5092mpz_init(t)5093for i from 0 <= i < len(pivots):5094p = pivots[i]5095for k from 0 <= k < n:5096if k != i:5097if mpz_cmp_si(matrix[k][p],0):5098mpz_fdiv_q(c, matrix[k][p], matrix[i][p])5099# subtract off c*v from row k; resulting A[k,i] entry will be < b, hence in Echelon form.5100for l from 0 <= l < m:5101mpz_mul(t, c, matrix[i][l])5102mpz_sub(matrix[k][l], matrix[k][l], t)5103mpz_clear(c)5104mpz_clear(t)5105sig_off()51065107###############################################################510851095110511151125113def _lift_crt(Matrix_integer_dense M, residues, moduli=None):5114"""5115TESTS::51165117sage: from sage.matrix.matrix_integer_dense import _lift_crt5118sage: T1 = Matrix(Zmod(5), 4, 4, [1, 4, 4, 0, 2, 0, 1, 4, 2, 0, 4, 1, 1, 4, 0, 3])5119sage: T2 = Matrix(Zmod(7), 4, 4, [1, 4, 6, 0, 2, 0, 1, 2, 4, 0, 6, 6, 1, 6, 0, 5])5120sage: T3 = Matrix(Zmod(11), 4, 4, [1, 4, 10, 0, 2, 0, 1, 9, 8, 0, 10, 6, 1, 10, 0, 9])5121sage: _lift_crt(Matrix(ZZ, 4, 4), [T1, T2, T3])5122[ 1 4 -1 0]5123[ 2 0 1 9]5124[-3 0 -1 6]5125[ 1 -1 0 -2]51265127sage: from sage.ext.multi_modular import MultiModularBasis5128sage: mm = MultiModularBasis([5,7,11])5129sage: _lift_crt(Matrix(ZZ, 4, 4), [T1, T2, T3], mm)5130[ 1 4 -1 0]5131[ 2 0 1 9]5132[-3 0 -1 6]5133[ 1 -1 0 -2]5134"""51355136cdef size_t n, i, j, k5137cdef Py_ssize_t nr, nc51385139n = len(residues)5140if n == 0: # special case: obviously residues[0] wouldn't make sense here.5141return M5142nr = residues[0].nrows()5143nc = residues[0].ncols()51445145if moduli is None:5146moduli = MultiModularBasis([m.base_ring().order() for m in residues])5147else:5148if len(residues) != len(moduli):5149raise IndexError("Number of residues (%s) does not match number of moduli (%s)"%(len(residues), len(moduli)))51505151cdef MultiModularBasis mm5152mm = moduli51535154for b in residues:5155if not is_Matrix_modn_dense(b):5156raise TypeError("Can only perform CRT on list of matrices mod n.")51575158cdef mod_int **row_list5159row_list = <mod_int**>sage_malloc(sizeof(mod_int*) * n)5160if row_list == NULL:5161raise MemoryError("out of memory allocating multi-modular coefficient list")51625163sig_on()5164for k in range(n):5165row_list[k] = <mod_int *>sage_malloc(sizeof(mod_int) * nc)5166if row_list[k] == NULL:5167raise MemoryError("out of memory allocating multi-modular coefficient list")51685169for i in range(nr):5170for k in range(n):5171(<Matrix_modn_dense_template>residues[k])._copy_row_to_mod_int_array(row_list[k],i)5172mm.mpz_crt_vec(M._matrix[i], row_list, nc)51735174for k in range(n):5175sage_free(row_list[k])5176sage_free(row_list)51775178sig_off()5179return M51805181#######################################################51825183# Conclusions:5184# On OS X Intel, at least:5185# - if log_2(height) >= 0.70 * nrows, use classical51865187def tune_multiplication(k, nmin=10, nmax=200, bitmin=2,bitmax=64):5188"""5189Compare various multiplication algorithms.51905191INPUT:51925193- ``k`` - integer; affects numbers of trials51945195- ``nmin`` - integer; smallest matrix to use51965197- ``nmax`` - integer; largest matrix to use51985199- ``bitmin`` - integer; smallest bitsize52005201- ``bitmax`` - integer; largest bitsize52025203OUTPUT:52045205- ``prints what doing then who wins`` - multimodular5206or classical52075208EXAMPLES::52095210sage: from sage.matrix.matrix_integer_dense import tune_multiplication5211sage: tune_multiplication(2, nmin=10, nmax=60, bitmin=2,bitmax=8)521210 2 0.25213...5214"""5215from constructor import random_matrix5216from sage.rings.integer_ring import ZZ5217for n in range(nmin,nmax,10):5218for i in range(bitmin, bitmax, 4):5219A = random_matrix(ZZ, n, n, x = 2**i)5220B = random_matrix(ZZ, n, n, x = 2**i)5221t0 = cputime()5222for j in range(k//n + 1):5223C = A._multiply_classical(B)5224t0 = cputime(t0)5225t1 = cputime()5226for j in range(k//n+1):5227C = A._multiply_multi_modular(B)5228t1 = cputime(t1)5229print n, i, float(i)/float(n)5230if t0 < t1:5231print 'classical'5232else:5233print 'multimod'523452355236##############################################################5237# Some people really really really want to make sure their5238# 4x4 determinant is really really really fast.5239##############################################################52405241cdef void four_dim_det(mpz_t r,mpz_t *x):5242"""5243Internal function used in computing determinants of 4x4 matrices.52445245TESTS::52465247sage: A = matrix(ZZ,4,[1,0,3,0,4,3,2,1,0,5,0,0,9,1,2,3])5248sage: A.determinant() # indirect doctest5249255250"""5251cdef mpz_t a,b5252mpz_init(a)5253mpz_init(b)52545255mpz_mul(a,x[3], x[6] ); mpz_submul(a,x[2], x[7] )5256mpz_mul(b,x[9], x[12]); mpz_submul(b,x[8], x[13])5257mpz_mul(r,a,b)5258mpz_mul(a,x[1], x[7] ); mpz_submul(a,x[3], x[5] )5259mpz_mul(b,x[10],x[12]); mpz_submul(b,x[8], x[14])5260mpz_addmul(r,a,b)5261mpz_mul(a,x[2], x[5] ); mpz_submul(a,x[1], x[6] )5262mpz_mul(b,x[11],x[12]); mpz_submul(b,x[8], x[15])5263mpz_addmul(r,a,b)5264mpz_mul(a,x[3], x[4] ); mpz_submul(a,x[0], x[7] )5265mpz_mul(b,x[10],x[13]); mpz_submul(b,x[9], x[14])5266mpz_addmul(r,a,b)5267mpz_mul(a,x[0], x[6] ); mpz_submul(a,x[2], x[4] )5268mpz_mul(b,x[11],x[13]); mpz_submul(b,x[9], x[15])5269mpz_addmul(r,a,b)5270mpz_mul(a,x[1], x[4] ); mpz_submul(a,x[0], x[5] )5271mpz_mul(b,x[11],x[14]); mpz_submul(b,x[10],x[15])5272mpz_addmul(r,a,b)52735274mpz_clear(a)5275mpz_clear(b)52765277#The above was generated by the following Sage code:5278#def idx(x):5279# return [i for i in range(16) if x[i]]5280#5281#def Det4Maker():5282# Q = PolynomialRing(QQ,['x%s'%ZZ(i).str(16) for i in range(16)])5283# M = Matrix(Q,4,4,Q.gens())5284# D = M.det()5285# Dm = [(m.exponents()[0],D[m]) for m in D.monomials()]5286# Dm.sort(reverse=True)5287# MM = [[Dm[i],Dm[i+1]] for i in range(0,len(Dm),2)]5288#5289# S = []5290# for j,((t,s),(r,o)) in enumerate(MM):5291# a,b,c,d = [ZZ(i).str(16) for i in range(16) if t[i]]5292# e,f,g,h = [ZZ(i).str(16) for i in range(16) if r[i]]5293# S.append((c+d+g+h,j))5294# S.sort(lambda x,y: cmp(x[0],y[0]))5295# MM = [MM[s[1]] for s in S]5296# MMM = [[MM[i],MM[i+1]] for i in range(0,len(MM),2)]5297#5298# N = 05299# Cstrux = ""5300# Pstrux = ""5301# for ((t1,s1),(t2,s2)),((t3,s3),(t4,s4)) in MMM:5302# a,b,c,d = idx(t1)5303# e,f = idx(t2)[2:]5304# h,i = idx(t3)[:2]5305#5306# if s1 == 1:5307# a,b,h,i = h,i,a,b5308#5309# Pstrux+= 'a = x[%s]*x[%s]; '%(a,b)5310# Cstrux+= 'mpz_mul(a,x[%s],x[%s]); '%(a,b)5311#5312# Pstrux+= 'a-=x[%s]*x[%s]; '%(h,i)5313# Cstrux+= 'mpz_submul(a,x[%s],x[%s])\n'%(h,i)5314#5315# if s4*s1 == 1:5316# c,d,e,f = e,f,c,d5317#5318# Pstrux+= 'b = x[%s]*x[%s]; '%(c,d)5319# Cstrux+= 'mpz_mul(b,x[%s],x[%s]); '%(c,d)5320#5321# Pstrux+= 'b-=x[%s]*x[%s]; '%(e,f)5322# Cstrux+= 'mpz_submul(b,x[%s],x[%s])\n'%(e,f)5323#5324#5325# if N:5326# Pstrux+= 'r+= a*b\n'5327# Cstrux+= 'mpz_addmul(r,a,b)\n'5328# else:5329# Pstrux+= 'r = a*b\n'5330# Cstrux+= 'mpz_mul(r,a,b)\n'5331# N = 15332# return Cstrux,Pstrux5333#5334#print Det4Maker()[0]53355336#Note, one can prove correctness of the above by setting5337# sage: Q = PolynomialRing(QQ,['x%s'%ZZ(i).str(16) for i in range(16)])5338# sage: M = Matrix(Q,4,4,Q.gens())5339# sage: D = M.det()5340# sage: x = Q.gens()5341#and then evaluating the contents of Det4Maker()[1]...5342# sage: a = x[3]*x[6]; a-=x[2]*x[7]; b = x[9]*x[12]; b-=x[8]*x[13]; r = a*b5343# sage: a = x[1]*x[7]; a-=x[3]*x[5]; b = x[10]*x[12]; b-=x[8]*x[14]; r+= a*b5344# sage: a = x[2]*x[5]; a-=x[1]*x[6]; b = x[11]*x[12]; b-=x[8]*x[15]; r+= a*b5345# sage: a = x[3]*x[4]; a-=x[0]*x[7]; b = x[10]*x[13]; b-=x[9]*x[14]; r+= a*b5346# sage: a = x[0]*x[6]; a-=x[2]*x[4]; b = x[11]*x[13]; b-=x[9]*x[15]; r+= a*b5347# sage: a = x[1]*x[4]; a-=x[0]*x[5]; b = x[11]*x[14]; b-=x[10]*x[15]; r+= a*b5348#and comparing results:5349# sage: r-D5350# 05351#bingo!5352535353545355