Path: blob/master/src/sage/matrix/matrix_integer_dense.pyx
8815 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 gen63from sage.libs.pari.pari_instance cimport PariInstance6465import sage.libs.pari.pari_instance66cdef PariInstance pari = sage.libs.pari.pari_instance.pari6768include "sage/libs/pari/decl.pxi"69include "sage/libs/pari/pari_err.pxi"7071cdef extern from "convert.h":72cdef void t_INT_to_ZZ( mpz_t value, long *g )7374#########################################################7576include "sage/ext/interrupt.pxi"77include "sage/ext/stdsage.pxi"78include "sage/ext/gmp.pxi"79include "sage/ext/random.pxi"8081cdef extern from "math.h":82double log(double x)838485from sage.ext.multi_modular import MultiModularBasis86from sage.ext.multi_modular cimport MultiModularBasis8788from sage.rings.integer cimport Integer89from sage.rings.rational_field import QQ90from sage.rings.real_double import RDF91from sage.rings.integer_ring import ZZ, IntegerRing_class92from sage.rings.integer_ring cimport IntegerRing_class93from sage.rings.finite_rings.integer_mod_ring import IntegerModRing94from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing95from sage.structure.element cimport ModuleElement, RingElement, Element, Vector96from sage.structure.element import is_Vector97from sage.structure.sequence import Sequence9899from matrix_modn_dense_float cimport Matrix_modn_dense_template100from matrix_modn_dense_float cimport Matrix_modn_dense_float101from matrix_modn_dense_double cimport Matrix_modn_dense_double102103from matrix_mod2_dense import Matrix_mod2_dense104from matrix_mod2_dense cimport Matrix_mod2_dense105106from matrix_modn_dense cimport is_Matrix_modn_dense107108109from matrix2 import decomp_seq110111import sage.modules.free_module112import sage.modules.free_module_element113114from matrix cimport Matrix115116cimport sage.structure.element117118import sage.matrix.matrix_space as matrix_space119120################121# Used for modular HNF122from sage.rings.fast_arith cimport arith_int123cdef arith_int ai124ai = arith_int()125################126127######### linbox interface ##########128from sage.libs.linbox.linbox cimport Linbox_integer_dense129cdef Linbox_integer_dense linbox130linbox = Linbox_integer_dense()131USE_LINBOX_POLY = True132133134########## iml -- integer matrix library ###########135136cdef extern from "iml.h":137138enum SOLU_POS:139LeftSolu = 101140RightSolu = 102141142long nullspaceMP(long n, long m,143mpz_t *A, mpz_t * *mp_N_pass)144145void nonsingSolvLlhsMM (SOLU_POS solupos, long n, \146long m, mpz_t *mp_A, mpz_t *mp_B, mpz_t *mp_N, \147mpz_t mp_D)148149150151cdef class Matrix_integer_dense(matrix_dense.Matrix_dense): # dense or sparse152r"""153Matrix over the integers.154155On a 32-bit machine, they can have at most `2^{32}-1` rows or156columns. On a 64-bit machine, matrices can have at most157`2^{64}-1` rows or columns.158159EXAMPLES::160161sage: a = MatrixSpace(ZZ,3)(2); a162[2 0 0]163[0 2 0]164[0 0 2]165sage: a = matrix(ZZ,1,3, [1,2,-3]); a166[ 1 2 -3]167sage: a = MatrixSpace(ZZ,2,4)(2); a168Traceback (most recent call last):169...170TypeError: nonzero scalar matrix must be square171"""172########################################################################173# LEVEL 1 functionality174# x * __cinit__175# x * __dealloc__176# x * __init__177# x * set_unsafe178# x * get_unsafe179# x * def _pickle180# x * def _unpickle181########################################################################182183def __cinit__(self, parent, entries, coerce, copy):184"""185Create and allocate memory for the matrix. Does not actually186initialize any of the memory.187188INPUT:189190191- ``parent, entries, coerce, copy`` - as for192__init__.193194195EXAMPLES::196197sage: from sage.matrix.matrix_integer_dense import Matrix_integer_dense198sage: a = Matrix_integer_dense.__new__(Matrix_integer_dense, Mat(ZZ,3), 0,0,0)199sage: type(a)200<type 'sage.matrix.matrix_integer_dense.Matrix_integer_dense'>201202.. warning::203204This is for internal use only, or if you really know what205you're doing.206"""207self._parent = parent208self._base_ring = ZZ209self._nrows = parent.nrows()210self._ncols = parent.ncols()211self._pivots = None212213# Allocate an array where all the entries of the matrix are stored.214sig_on()215self._entries = <mpz_t *>sage_malloc(sizeof(mpz_t) * (self._nrows * self._ncols))216sig_off()217if self._entries == NULL:218raise MemoryError("out of memory allocating a matrix")219220# Allocate an array of pointers to the rows, which is useful for221# certain algorithms.222##################################223# *IMPORTANT*: FOR MATRICES OVER ZZ, WE ALWAYS ASSUME THAT224# THIS ARRAY IS *not* PERMUTED. This should be OK, since all225# algorithms are multi-modular.226##################################227self._matrix = <mpz_t **> sage_malloc(sizeof(mpz_t*)*self._nrows)228if self._matrix == NULL:229sage_free(self._entries)230self._entries = NULL231raise MemoryError("out of memory allocating a matrix")232233# Set each of the pointers in the array self._matrix to point234# at the memory for the corresponding row.235cdef Py_ssize_t i, k236k = 0237for i from 0 <= i < self._nrows:238self._matrix[i] = self._entries + k239k = k + self._ncols240241cdef _init_linbox(self):242sig_on()243linbox.set(self._matrix, self._nrows, self._ncols)244sig_off()245246def __copy__(self):247r"""248Returns a new copy of this matrix.249250EXAMPLES::251252sage: a = matrix(ZZ,1,3, [1,2,-3]); a253[ 1 2 -3]254sage: b = a.__copy__(); b255[ 1 2 -3]256sage: b is a257False258sage: b == a259True260"""261cdef Matrix_integer_dense A262A = Matrix_integer_dense.__new__(Matrix_integer_dense, self._parent,2630, 0, 0)264cdef Py_ssize_t i265sig_on()266for i from 0 <= i < self._nrows * self._ncols:267mpz_init_set(A._entries[i], self._entries[i])268sig_off()269A._initialized = True270if self._subdivisions is not None:271A.subdivide(*self.subdivisions())272return A273274def __hash__(self):275r"""276Returns hash of self.277278self must be immutable.279280EXAMPLES::281282sage: a = Matrix(ZZ,2,[1,2,3,4])283sage: hash(a)284Traceback (most recent call last):285...286TypeError: mutable matrices are unhashable287288::289290sage: a.set_immutable()291sage: hash(a)2928293"""294return self._hash()295296def __dealloc__(self):297"""298Frees all the memory allocated for this matrix. EXAMPLE::299300sage: a = Matrix(ZZ,2,[1,2,3,4])301sage: del a302"""303cdef Py_ssize_t i304if self._initialized:305for i from 0 <= i < (self._nrows * self._ncols):306mpz_clear(self._entries[i])307sage_free(self._entries)308sage_free(self._matrix)309310def __init__(self, parent, entries, copy, coerce):311r"""312Initialize a dense matrix over the integers.313314INPUT:315316317- ``parent`` - a matrix space318319- ``entries`` - list - create the matrix with those320entries along the rows.321322- ``other`` - a scalar; entries is coerced to an323integer and the diagonal entries of this matrix are set to that324integer.325326- ``coerce`` - whether need to coerce entries to the327integers (program may crash if you get this wrong)328329- ``copy`` - ignored (since integers are immutable)330331332EXAMPLES:333334The __init__ function is called implicitly in each of the335examples below to actually fill in the values of the matrix.336337We create a `2 \times 2` and a `1\times 4` matrix::338339sage: matrix(ZZ,2,2,range(4))340[0 1]341[2 3]342sage: Matrix(ZZ,1,4,range(4))343[0 1 2 3]344345If the number of columns isn't given, it is determined from the346number of elements in the list.347348::349350sage: matrix(ZZ,2,range(4))351[0 1]352[2 3]353sage: matrix(ZZ,2,range(6))354[0 1 2]355[3 4 5]356357Another way to make a matrix is to create the space of matrices and358coerce lists into it.359360::361362sage: A = Mat(ZZ,2); A363Full MatrixSpace of 2 by 2 dense matrices over Integer Ring364sage: A(range(4))365[0 1]366[2 3]367368Actually it is only necessary that the input can be coerced to a369list, so the following also works::370371sage: v = reversed(range(4)); type(v)372<type 'listreverseiterator'>373sage: A(v)374[3 2]375[1 0]376377Matrices can have many rows or columns (in fact, on a 64-bit378machine they could have up to `2^64-1` rows or columns)::379380sage: v = matrix(ZZ,1,10^5, range(10^5))381sage: v.parent()382Full MatrixSpace of 1 by 100000 dense matrices over Integer Ring383"""384cdef Py_ssize_t i, j385cdef bint is_list386cdef Integer x387388if entries is None:389x = ZZ(0)390is_list = 0391elif isinstance(entries, (int,long)) or is_Element(entries):392try:393x = ZZ(entries)394except TypeError:395self._initialized = False396raise TypeError("unable to coerce entry to an integer")397is_list = 0398else:399entries = list(entries)400is_list = 1401402if is_list:403404# Create the matrix whose entries are in the given entry list.405if len(entries) != self._nrows * self._ncols:406sage_free(self._entries)407sage_free(self._matrix)408self._entries = NULL409raise TypeError("entries has the wrong length")410if coerce:411for i from 0 <= i < self._nrows * self._ncols:412x = ZZ(entries[i])413# todo -- see integer.pyx and the TODO there; perhaps this could be414# sped up by creating a mpz_init_set_sage function.415mpz_init_set(self._entries[i], x.value)416self._initialized = True417else:418for i from 0 <= i < self._nrows * self._ncols:419mpz_init_set(self._entries[i], (<Integer> entries[i]).value)420self._initialized = True421else:422423# If x is zero, make the zero matrix and be done.424if mpz_sgn(x.value) == 0:425self._zero_out_matrix()426return427428# the matrix must be square:429if self._nrows != self._ncols:430sage_free(self._entries)431sage_free(self._matrix)432self._entries = NULL433raise TypeError("nonzero scalar matrix must be square")434435# Now we set all the diagonal entries to x and all other entries to 0.436self._zero_out_matrix()437j = 0438for i from 0 <= i < self._nrows:439mpz_set(self._entries[j], x.value)440j = j + self._nrows + 1441self._initialized = True442443cdef set_unsafe(self, Py_ssize_t i, Py_ssize_t j, value):444"""445Set position i,j of this matrix to x.446447(VERY UNSAFE - value *must* be of type Integer).448449INPUT:450451452- ``i`` - row453454- ``j`` - column455456- ``value`` - The value to set self[i,j] to. value457MUST be of type Integer458459460EXAMPLES::461462sage: a = matrix(ZZ,2,3, range(6)); a463[0 1 2]464[3 4 5]465sage: a[0,0] = 10466sage: a467[10 1 2]468[ 3 4 5]469"""470mpz_set(self._matrix[i][j], (<Integer>value).value)471472cdef get_unsafe(self, Py_ssize_t i, Py_ssize_t j):473"""474Returns (j, i) entry of self as a new Integer.475476.. warning::477478This is very unsafe; it assumes i and j are in the right479range.480481EXAMPLES::482483sage: a = MatrixSpace(ZZ,3)(range(9)); a484[0 1 2]485[3 4 5]486[6 7 8]487sage: a[1,2]4885489sage: a[4,7]490Traceback (most recent call last):491...492IndexError: matrix index out of range493sage: a[-1,0]4946495"""496cdef Integer z497z = PY_NEW(Integer)498mpz_set(z.value, self._matrix[i][j])499return z500501def _pickle(self):502"""503EXAMPLES::504505sage: a = matrix(ZZ,2,3,[1,193,15,-2,3,0])506sage: a._pickle()507('1 61 f -2 3 0', 0)508509sage: S = ModularSymbols(250,4,sign=1).cuspidal_submodule().new_subspace().decomposition() # long time510sage: S == loads(dumps(S)) # long time511True512"""513return self._pickle_version0(), 0514515cdef _pickle_version0(self):516"""517EXAMPLES::518519sage: matrix(ZZ,1,3,[1,193,15])._pickle() # indirect doctest520('1 61 f', 0)521522"""523return self._export_as_string(32)524525cpdef _export_as_string(self, int base=10):526"""527Return space separated string of the entries in this matrix, in the528given base. This is optimized for speed.529530INPUT: base -an integer = 36; (default: 10)531532EXAMPLES::533534sage: m = matrix(ZZ,2,3,[1,2,-3,1,-2,-45])535sage: m._export_as_string(10)536'1 2 -3 1 -2 -45'537sage: m._export_as_string(16)538'1 2 -3 1 -2 -2d'539"""540# TODO: *maybe* redo this to use mpz_import and mpz_export541# from sec 5.14 of the GMP manual. ??542cdef int i, j, len_so_far, m, n543cdef char *a544cdef char *s, *t, *tmp545546if self._nrows == 0 or self._ncols == 0:547data = ''548else:549n = self._nrows*self._ncols*10550s = <char*> sage_malloc(n * sizeof(char))551t = s552len_so_far = 0553554sig_on()555for i from 0 <= i < self._nrows * self._ncols:556m = mpz_sizeinbase (self._entries[i], base)557if len_so_far + m + 2 >= n:558# copy to new string with double the size559n = 2*n + m + 1560tmp = <char*> sage_malloc(n * sizeof(char))561strcpy(tmp, s)562sage_free(s)563s = tmp564t = s + len_so_far565#endif566mpz_get_str(t, base, self._entries[i])567m = strlen(t)568len_so_far = len_so_far + m + 1569t = t + m570t[0] = <char>32571t[1] = <char>0572t = t + 1573sig_off()574data = str(s)[:-1]575sage_free(s)576return data577578def _unpickle(self, data, int version):579if version == 0:580self._unpickle_version0(data)581else:582raise RuntimeError("unknown matrix version (=%s)"%version)583584cdef _unpickle_version0(self, data):585cdef Py_ssize_t i, n586data = data.split()587n = self._nrows * self._ncols588if len(data) != n:589raise RuntimeError("invalid pickle data.")590for i from 0 <= i < n:591s = data[i]592if mpz_init_set_str(self._entries[i], s, 32):593raise RuntimeError("invalid pickle data")594self._initialized = True595596597def __richcmp__(Matrix self, right, int op): # always need for mysterious reasons.598return self._richcmp(right, op)599600########################################################################601# LEVEL 1 helpers:602# These function support the implementation of the level 1 functionality.603########################################################################604cdef _zero_out_matrix(self):605"""606Set this matrix to be the zero matrix. This is only for internal607use. (Note: this matrix must NOT already have initialised608entries.)609"""610# TODO: This is about 6-10 slower than MAGMA doing what seems to be the same thing.611# Moreover, NTL can also do this quickly. Why? I think both have specialized612# small integer classes. (dmharvey: yes, NTL does not allocate any memory when613# initializing a ZZ to zero.)614sig_on()615cdef Py_ssize_t i616for i from 0 <= i < self._nrows * self._ncols:617mpz_init(self._entries[i])618sig_off()619self._initialized = True620621cdef _new_unitialized_matrix(self, Py_ssize_t nrows, Py_ssize_t ncols):622"""623Return a new matrix over the integers with the given number of rows624and columns. All memory is allocated for this matrix, but its625entries have not yet been filled in.626"""627P = self._parent.matrix_space(nrows, ncols)628return Matrix_integer_dense.__new__(Matrix_integer_dense, P, None, None, None)629630631########################################################################632# LEVEL 2 functionality633# x * cdef _add_634# x * cdef _sub_635# x * cdef _mul_636# x * cdef _cmp_c_impl637# * __neg__638# * __invert__639# * __copy__640# x * _multiply_classical641# * _list -- list of underlying elements (need not be a copy)642# * _dict -- sparse dictionary of underlying elements (need not be a copy)643########################################################################644645# cdef _mul_(self, Matrix right):646# def __neg__(self):647# def __invert__(self):648# def __copy__(self):649# def _multiply_classical(left, matrix.Matrix _right):650# def _list(self):651# def _dict(self):652653def __nonzero__(self):654r"""655Tests whether self is the zero matrix.656657EXAMPLES::658659sage: a = MatrixSpace(ZZ, 2, 3)(range(6)); a660[0 1 2]661[3 4 5]662sage: a.__nonzero__()663True664sage: (a - a).__nonzero__()665False666667::668669sage: a = MatrixSpace(ZZ, 0, 3)()670sage: a.__nonzero__()671False672sage: a = MatrixSpace(ZZ, 3, 0)()673sage: a.__nonzero__()674False675sage: a = MatrixSpace(ZZ, 0, 0)()676sage: a.__nonzero__()677False678"""679cdef mpz_t *a, *b680cdef Py_ssize_t i, j681cdef int k682for i from 0 <= i < self._nrows * self._ncols:683if mpz_sgn(self._entries[i]):684return True685return False686687def _multiply_linbox(self, Matrix right):688"""689Multiply matrices over ZZ using linbox.690691.. warning::692693This is very slow right now, i.e., linbox is very slow.694695EXAMPLES::696697sage: A = matrix(ZZ,2,3,range(6))698sage: A*A.transpose()699[ 5 14]700[14 50]701sage: A._multiply_linbox(A.transpose())702[ 5 14]703[14 50]704"""705cdef int e706cdef Matrix_integer_dense ans, B707B = right708ans = self.new_matrix(nrows = self.nrows(), ncols = right.ncols())709self._init_linbox()710sig_on()711linbox.matrix_matrix_multiply(ans._matrix, B._matrix, B._nrows, B._ncols)712sig_off()713return ans714715def _multiply_classical(self, Matrix right):716"""717EXAMPLE::718719sage: n = 3720sage: a = MatrixSpace(ZZ,n,n)(range(n^2))721sage: b = MatrixSpace(ZZ,n,n)(range(1, n^2 + 1))722sage: a._multiply_classical(b)723[ 18 21 24]724[ 54 66 78]725[ 90 111 132]726"""727if self._ncols != right._nrows:728raise IndexError("Number of columns of self must equal number of rows of right.")729730cdef Py_ssize_t i, j, k, l, nr, nc, snc731cdef mpz_t *v732cdef object parent733734nr = self._nrows735nc = right._ncols736snc = self._ncols737738if self._nrows == right._nrows:739# self acts on the space of right740parent = right.parent()741if self._ncols == right._ncols:742# right acts on the space of self743parent = self.parent()744else:745parent = self.matrix_space(nr, nc)746747cdef Matrix_integer_dense M, _right748_right = right749750M = Matrix_integer_dense.__new__(Matrix_integer_dense, parent, None, None, None)751Matrix.__init__(M, parent)752753# M has memory allocated but entries are not initialized754cdef mpz_t *entries755entries = M._entries756757cdef mpz_t s, z758mpz_init(s)759mpz_init(z)760761sig_on()762l = 0763for i from 0 <= i < nr:764for j from 0 <= j < nc:765mpz_set_si(s,0) # set s = 0766v = self._matrix[i]767for k from 0 <= k < snc:768mpz_mul(z, v[k], _right._matrix[k][j])769mpz_add(s, s, z)770mpz_init_set(entries[l], s)771l += 1772sig_off()773mpz_clear(s)774mpz_clear(z)775M._initialized = True776return M777778cdef sage.structure.element.Matrix _matrix_times_matrix_(self, sage.structure.element.Matrix right):779780#############781# see the tune_multiplication function below.782n = max(self._nrows, self._ncols, right._nrows, right._ncols)783if n <= 20:784return self._multiply_classical(right)785a = self.height(); b = right.height()786if float(max(a,b)) / float(n) >= 0.70:787return self._multiply_classical(right)788else:789return self._multiply_multi_modular(right)790791cpdef ModuleElement _lmul_(self, RingElement right):792"""793EXAMPLES::794795sage: a = matrix(QQ,2,range(6))796sage: (3/4) * a797[ 0 3/4 3/2]798[ 9/4 3 15/4]799"""800cdef Py_ssize_t i801cdef Integer _x802_x = Integer(right)803cdef Matrix_integer_dense M804M = Matrix_integer_dense.__new__(Matrix_integer_dense, self._parent, None, None, None)805for i from 0 <= i < self._nrows * self._ncols:806mpz_init(M._entries[i])807mpz_mul(M._entries[i], self._entries[i], _x.value)808M._initialized = True809return M810811cpdef ModuleElement _add_(self, ModuleElement right):812"""813Add two dense matrices over ZZ.814815EXAMPLES::816817sage: a = MatrixSpace(ZZ,3)(range(9))818sage: a+a819[ 0 2 4]820[ 6 8 10]821[12 14 16]822sage: b = MatrixSpace(ZZ,3)(range(9))823sage: b.swap_rows(1,2)824sage: a+b825[ 0 2 4]826[ 9 11 13]827[ 9 11 13]828"""829cdef Py_ssize_t i, j830831cdef Matrix_integer_dense M832M = Matrix_integer_dense.__new__(Matrix_integer_dense, self._parent, None, None, None)833834sig_on()835cdef mpz_t *row_self, *row_right, *row_ans836for i from 0 <= i < self._nrows:837row_self = self._matrix[i]838row_right = (<Matrix_integer_dense> right)._matrix[i]839row_ans = M._matrix[i]840for j from 0 <= j < self._ncols:841mpz_init(row_ans[j])842mpz_add(row_ans[j], row_self[j], row_right[j])843sig_off()844M._initialized = True845return M846847cpdef ModuleElement _sub_(self, ModuleElement right):848"""849Subtract two dense matrices over ZZ.850851EXAMPLES::852853sage: M = Mat(ZZ,3)854sage: a = M(range(9)); b = M(reversed(range(9)))855sage: a - b856[-8 -6 -4]857[-2 0 2]858[ 4 6 8]859"""860cdef Py_ssize_t i, j861862cdef Matrix_integer_dense M863M = Matrix_integer_dense.__new__(Matrix_integer_dense, self._parent, None, None, None)864865sig_on()866cdef mpz_t *row_self, *row_right, *row_ans867for i from 0 <= i < self._nrows:868row_self = self._matrix[i]869row_right = (<Matrix_integer_dense> right)._matrix[i]870row_ans = M._matrix[i]871for j from 0 <= j < self._ncols:872mpz_init(row_ans[j])873mpz_sub(row_ans[j], row_self[j], row_right[j])874sig_off()875M._initialized = True876return M877878879cdef int _cmp_c_impl(self, Element right) except -2:880r"""881Compares self with right, examining entries in lexicographic (row882major) ordering.883884EXAMPLES::885886sage: Matrix(ZZ, [[0, 10], [20, 30]]).__cmp__(Matrix(ZZ, [[0, 10], [20, 30]]))8870888sage: Matrix(ZZ, [[0, 10], [20, 30]]).__cmp__(Matrix(ZZ, [[0, 15], [20, 30]]))889-1890sage: Matrix(ZZ, [[5, 10], [20, 30]]).__cmp__(Matrix(ZZ, [[0, 15], [20, 30]]))8911892sage: Matrix(ZZ, [[5, 10], [20, 30]]).__cmp__(Matrix(ZZ, [[0, 10], [25, 30]]))8931894"""895cdef mpz_t *a, *b896cdef Py_ssize_t i, j897cdef int k898899for i from 0 <= i < self._nrows:900a = self._matrix[i]901b = (<Matrix_integer_dense>right)._matrix[i]902for j from 0 <= j < self._ncols:903k = mpz_cmp(a[j], b[j])904if k:905if k < 0:906return -1907else:908return 1909return 0910911912cdef Vector _vector_times_matrix_(self, Vector v):913"""914Returns the vector times matrix product.915916INPUT:917918919- ``v`` - a free module element.920921922OUTPUT: The vector times matrix product v\*A.923924EXAMPLES::925926sage: B = matrix(ZZ,2, [1,2,3,4])927sage: V = ZZ^2928sage: w = V([-1,5])929sage: w*B930(14, 18)931"""932cdef Vector_integer_dense w, ans933cdef Py_ssize_t i, j934cdef mpz_t x935936M = self._row_ambient_module()937w = <Vector_integer_dense> v938ans = M.zero_vector()939940mpz_init(x)941for i from 0 <= i < self._ncols:942mpz_set_si(x, 0)943for j from 0 <= j < self._nrows:944mpz_addmul(x, w._entries[j], self._matrix[j][i])945mpz_set(ans._entries[i], x)946mpz_clear(x)947return ans948949950########################################################################951# LEVEL 3 functionality (Optional)952# * __deepcopy__953# * __invert__954# * Matrix windows -- only if you need strassen for that base955# * Other functions (list them here):956# * Specialized echelon form957########################################################################958959def _clear_denom(self):960"""961INPUT:962963- ``self`` - a matrix964965OUTPUT: self, 1966967EXAMPLES::968969sage: a = matrix(ZZ,2,[1,2,3,4])970sage: a._clear_denom()971(972[1 2]973[3 4], 1974)975"""976return self, ZZ(1)977978def charpoly(self, var='x', algorithm='linbox'):979"""980INPUT:981982983- ``var`` - a variable name984985- ``algorithm`` - 'linbox' (default) 'generic'986987988.. note::989990Linbox charpoly disabled on 64-bit machines, since it hangs991in many cases.992993EXAMPLES::994995sage: A = matrix(ZZ,6, range(36))996sage: f = A.charpoly(); f997x^6 - 105*x^5 - 630*x^4998sage: f(A) == 0999True1000sage: n=20; A = Mat(ZZ,n)(range(n^2))1001sage: A.charpoly()1002x^20 - 3990*x^19 - 266000*x^181003sage: A.minpoly()1004x^3 - 3990*x^2 - 266000*x10051006TESTS:10071008The cached polynomial should be independent of the ``var``1009argument (:trac:`12292`). We check (indirectly) that the1010second call uses the cached value by noting that its result is1011not cached::10121013sage: M = MatrixSpace(ZZ, 2)1014sage: A = M(range(0, 2^2))1015sage: type(A)1016<type 'sage.matrix.matrix_integer_dense.Matrix_integer_dense'>1017sage: A.charpoly('x')1018x^2 - 3*x - 21019sage: A.charpoly('y')1020y^2 - 3*y - 21021sage: A._cache['charpoly_linbox']1022x^2 - 3*x - 210231024"""1025cache_key = 'charpoly_%s' % algorithm1026g = self.fetch(cache_key)1027if g is not None:1028return g.change_variable_name(var)10291030if algorithm == 'linbox' and not USE_LINBOX_POLY:1031algorithm = 'generic'10321033if algorithm == 'linbox':1034g = self._charpoly_linbox(var)1035elif algorithm == 'generic':1036g = matrix_dense.Matrix_dense.charpoly(self, var)1037else:1038raise ValueError("no algorithm '%s'"%algorithm)10391040self.cache(cache_key, g)1041return g10421043def minpoly(self, var='x', algorithm='linbox'):1044"""1045INPUT:104610471048- ``var`` - a variable name10491050- ``algorithm`` - 'linbox' (default) 'generic'105110521053.. note::10541055Linbox charpoly disabled on 64-bit machines, since it hangs1056in many cases.10571058EXAMPLES::10591060sage: A = matrix(ZZ,6, range(36))1061sage: A.minpoly()1062x^3 - 105*x^2 - 630*x1063sage: n=6; A = Mat(ZZ,n)([k^2 for k in range(n^2)])1064sage: A.minpoly()1065x^4 - 2695*x^3 - 257964*x^2 + 1693440*x1066"""1067key = 'minpoly_%s_%s'%(algorithm, var)1068x = self.fetch(key)1069if x: return x10701071if algorithm == 'linbox' and not USE_LINBOX_POLY:1072algorithm = 'generic'10731074if algorithm == 'linbox':1075g = self._minpoly_linbox(var)1076elif algorithm == 'generic':1077g = matrix_dense.Matrix_dense.minpoly(self, var)1078else:1079raise ValueError("no algorithm '%s'"%algorithm)10801081self.cache(key, g)1082return g10831084def _minpoly_linbox(self, var='x'):1085return self._poly_linbox(var=var, typ='minpoly')10861087def _charpoly_linbox(self, var='x'):1088if self.is_zero(): # program around a bug in linbox on 32-bit linux1089x = self.base_ring()[var].gen()1090return x ** self._nrows1091return self._poly_linbox(var=var, typ='charpoly')10921093def _poly_linbox(self, var='x', typ='minpoly'):1094"""1095INPUT:109610971098- ``var`` - 'x'10991100- ``typ`` - 'minpoly' or 'charpoly'1101"""1102time = verbose('computing %s of %s x %s matrix using linbox'%(typ, self._nrows, self._ncols))1103if self._nrows != self._ncols:1104raise ArithmeticError("self must be a square matrix")1105if self._nrows <= 1:1106return matrix_dense.Matrix_dense.charpoly(self, var)1107self._init_linbox()1108if typ == 'minpoly':1109sig_on()1110v = linbox.minpoly()1111sig_off()1112else:1113sig_on()1114v = linbox.charpoly()1115sig_off()1116R = self._base_ring[var]1117verbose('finished computing %s'%typ, time)1118return R(v)111911201121def height(self):1122"""1123Return the height of this matrix, i.e., the max absolute value of1124the entries of the matrix.11251126OUTPUT: A nonnegative integer.11271128EXAMPLE::11291130sage: a = Mat(ZZ,3)(range(9))1131sage: a.height()113281133sage: a = Mat(ZZ,2,3)([-17,3,-389,15,-1,0]); a1134[ -17 3 -389]1135[ 15 -1 0]1136sage: a.height()11373891138"""1139cdef mpz_t h1140cdef Integer x11411142self.mpz_height(h)1143x = Integer()1144x.set_from_mpz(h)1145mpz_clear(h)11461147return x11481149cdef int mpz_height(self, mpz_t height) except -1:1150"""1151Used to compute the height of this matrix.11521153INPUT:115411551156- ``height`` - a GMP mpz_t (that has not been1157initialized!)115811591160OUTPUT: sets the value of height to the height of this matrix,1161i.e., the max absolute value of the entries of the matrix.1162"""1163cdef mpz_t x, h1164cdef Py_ssize_t i11651166sig_on()1167mpz_init_set_si(h, 0)1168mpz_init(x)11691170for i from 0 <= i < self._nrows * self._ncols:1171mpz_abs(x, self._entries[i])1172if mpz_cmp(h, x) < 0:1173mpz_set(h, x)11741175mpz_init_set(height, h)1176mpz_clear(h)1177mpz_clear(x)1178sig_off()11791180return 0 # no error occurred.11811182cpdef double _log_avg_sq1(self) except -1.0:1183"""1184Return the logarithm of the average of `x^2 + 1`, where `x`1185ranges over the matrix entries.11861187This is used to determine which determinant algorithm to use.11881189TESTS::11901191sage: M = random_matrix(ZZ,100)1192sage: L1 = M._log_avg_sq1()1193sage: L2 = log(RR(sum([i*i+1 for i in M.list()])/10000))1194sage: abs(L1 - L2) < 1e-131195True1196sage: matrix(ZZ,10)._log_avg_sq1()11970.01198"""1199cdef Py_ssize_t i1200cdef Py_ssize_t N = self._nrows * self._ncols12011202# wsq * 4^wsq_e = sum of entries squared plus number of entries1203cdef double wsq = N1204cdef long wsq_e = 012051206cdef double d1207cdef long e12081209sig_on()1210for i in range(N):1211d = mpz_get_d_2exp(&e, self._entries[i])1212if (e > wsq_e):1213wsq = ldexp(wsq, 2*(wsq_e - e))1214wsq_e = e1215elif (e < wsq_e):1216d = ldexp(d, e - wsq_e)1217wsq += d*d1218sig_off()12191220# Compute log(wsq * 4^wsq_e / N) =1221# log(wsq * 4^wsq_e / N) = log(wsq/N) + wsq_e * log(4)1222return log(wsq/N) + wsq_e * log(4.0)12231224def _multiply_multi_modular(left, Matrix_integer_dense right):1225"""1226Multiply this matrix by ``left`` using a multi modular algorithm.12271228EXAMPLES::12291230sage: M = Matrix(ZZ, 2, 3, range(5,11))1231sage: N = Matrix(ZZ, 3, 2, range(15,21))1232sage: M._multiply_multi_modular(N)1233[310 328]1234[463 490]1235sage: M._multiply_multi_modular(-N)1236[-310 -328]1237[-463 -490]1238"""1239cdef Integer h1240cdef mod_int *moduli1241cdef int i, n, k12421243h = left.height() * right.height() * left.ncols()1244verbose('multiplying matrices of height %s and %s'%(left.height(),right.height()))1245mm = MultiModularBasis(h)1246res = left._reduce(mm)1247res_right = right._reduce(mm)1248k = len(mm)1249for i in range(k): # yes, I could do this with zip, but to conserve memory...1250t = cputime()1251res[i] *= res_right[i]1252verbose('multiplied matrices modulo a prime (%s/%s)'%(i+1,k), t)1253result = left.new_matrix(left.nrows(), right.ncols())1254_lift_crt(result, res, mm) # changes result1255return result12561257cdef void reduce_entry_unsafe(self, Py_ssize_t i, Py_ssize_t j, Integer modulus):1258# Used for p-adic matrices.1259if mpz_cmp(self._matrix[i][j], modulus.value) >= 0 or mpz_cmp_ui(self._matrix[i][j], 0) < 0:1260mpz_mod(self._matrix[i][j], self._matrix[i][j], modulus.value)12611262def _mod_int(self, modulus):1263"""1264Reduce the integer matrix modulo a positive integer.12651266EXAMPLES::1267sage: matrix(QQ,2,[1,0,0,1]).change_ring(GF(2)) - 11268[0 0]1269[0 0]12701271"""1272cdef mod_int c = modulus1273if int(c) != modulus:1274raise OverflowError1275else:1276return self._mod_int_c(modulus)12771278cdef _mod_two(self):1279cdef Matrix_mod2_dense res1280res = Matrix_mod2_dense.__new__(Matrix_mod2_dense, matrix_space.MatrixSpace(IntegerModRing(2), self._nrows, self._ncols, sparse=False), None, None, None)1281res.__init__(matrix_space.MatrixSpace(IntegerModRing(2), self._nrows, self._ncols, sparse=False), self.list(), None, None)1282return res12831284cdef _mod_int_c(self, mod_int p):1285from matrix_modn_dense_float import MAX_MODULUS as MAX_MODULUS_FLOAT1286from matrix_modn_dense_double import MAX_MODULUS as MAX_MODULUS_DOUBLE12871288cdef Py_ssize_t i, j1289cdef mpz_t* self_row12901291cdef float* res_row_f1292cdef Matrix_modn_dense_float res_f12931294cdef double* res_row_d1295cdef Matrix_modn_dense_double res_d12961297if p == 2:1298return self._mod_two()1299elif p < MAX_MODULUS_FLOAT:1300res_f = Matrix_modn_dense_float.__new__(Matrix_modn_dense_float,1301matrix_space.MatrixSpace(IntegerModRing(p), self._nrows, self._ncols, sparse=False), None, None, None)1302for i from 0 <= i < self._nrows:1303self_row = self._matrix[i]1304res_row_f = res_f._matrix[i]1305for j from 0 <= j < self._ncols:1306res_row_f[j] = <float>mpz_fdiv_ui(self_row[j], p)1307return res_f13081309elif p < MAX_MODULUS_DOUBLE:1310res_d = Matrix_modn_dense_double.__new__(Matrix_modn_dense_double,1311matrix_space.MatrixSpace(IntegerModRing(p), self._nrows, self._ncols, sparse=False), None, None, None)1312for i from 0 <= i < self._nrows:1313self_row = self._matrix[i]1314res_row_d = res_d._matrix[i]1315for j from 0 <= j < self._ncols:1316res_row_d[j] = <double>mpz_fdiv_ui(self_row[j], p)1317return res_d1318else:1319raise ValueError("p to big.")13201321def _reduce(self, moduli):1322from matrix_modn_dense_float import MAX_MODULUS as MAX_MODULUS_FLOAT1323from matrix_modn_dense_double import MAX_MODULUS as MAX_MODULUS_DOUBLE13241325if isinstance(moduli, (int, long, Integer)):1326return self._mod_int(moduli)1327elif isinstance(moduli, list):1328moduli = MultiModularBasis(moduli)13291330cdef MultiModularBasis mm1331mm = moduli13321333res = []1334for p in mm:1335if p < MAX_MODULUS_FLOAT:1336res.append( Matrix_modn_dense_float.__new__(Matrix_modn_dense_float,1337matrix_space.MatrixSpace(IntegerModRing(p), self._nrows, self._ncols, sparse=False),1338None, None, None) )1339elif p < MAX_MODULUS_DOUBLE:1340res.append( Matrix_modn_dense_double.__new__(Matrix_modn_dense_double,1341matrix_space.MatrixSpace(IntegerModRing(p), self._nrows, self._ncols, sparse=False),1342None, None, None) )1343else:1344raise ValueError("p=%d too big."%p)13451346cdef size_t i, k, n1347cdef Py_ssize_t nr, nc13481349n = len(mm)1350nr = self._nrows1351nc = self._ncols13521353cdef mod_int **row_list1354row_list = <mod_int**>sage_malloc(sizeof(mod_int*) * n)1355if row_list == NULL:1356raise MemoryError("out of memory allocating multi-modular coefficient list")1357for k in range(n):1358row_list[k] = <mod_int*>sage_malloc(sizeof(mod_int)*nc)1359if row_list[k] == NULL:1360for i in range(k):1361sage_free(row_list[i])1362sage_free(row_list)1363raise MemoryError("out of memory allocating multi-modular coefficient list")13641365sig_on()1366for i from 0 <= i < nr:1367for k from 0 <= k < n:1368mm.mpz_reduce_vec(self._matrix[i], row_list, nc)1369if isinstance(res[k], Matrix_modn_dense_float):1370for j in range(nc):1371(<Matrix_modn_dense_float>res[k])._matrix[i][j] = (<float>row_list[k][j])%(<Matrix_modn_dense_float>res[k]).p1372else:1373for j in range(nc):1374(<Matrix_modn_dense_double>res[k])._matrix[i][j] = (<double>row_list[k][j])%(<Matrix_modn_dense_double>res[k]).p1375sig_off()13761377for k in range(n):1378sage_free(row_list[k])1379sage_free(row_list)1380return res13811382def _echelon_in_place_classical(self):1383cdef Matrix_integer_dense E1384E = self.echelon_form()13851386cdef int i1387for i from 0 <= i < self._ncols * self._nrows:1388mpz_set(self._entries[i], E._entries[i])13891390self.clear_cache()13911392def _echelon_strassen(self):1393raise NotImplementedError13941395def _magma_init_(self, magma):1396"""1397EXAMPLES::13981399sage: m = matrix(ZZ,2,3,[1,2,-3,1,-2,-45])1400sage: m._magma_init_(magma)1401'Matrix(IntegerRing(),2,3,StringToIntegerSequence("1 2 -3 1 -2 -45"))'1402sage: magma(m) # optional - magma1403[ 1 2 -3]1404[ 1 -2 -45]1405"""1406w = self._export_as_string(base=10)1407return 'Matrix(IntegerRing(),%s,%s,StringToIntegerSequence("%s"))'%(1408self.nrows(), self.ncols(), w)14091410def symplectic_form(self):1411r"""1412Find a symplectic basis for self if self is an anti-symmetric,1413alternating matrix.14141415Returns a pair (F, C) such that the rows of C form a symplectic1416basis for self and F = C \* self \* C.transpose().14171418Raises a ValueError if self is not anti-symmetric, or self is not1419alternating.14201421Anti-symmetric means that `M = -M^t`. Alternating means1422that the diagonal of `M` is identically zero.14231424A symplectic basis is a basis of the form1425`e_1, \ldots, e_j, f_1, \ldots f_j, z_1, \dots, z_k`1426such that14271428- `z_i M v^t` = 0 for all vectors `v`14291430- `e_i M {e_j}^t = 0` for all `i, j`14311432- `f_i M {f_j}^t = 0` for all `i, j`14331434- `e_i M {f_i}^t = 1` for all `i`14351436- `e_i M {f_j}^t = 0` for all `i` not equal1437`j`.14381439The ordering for the factors `d_{i} | d_{i+1}` and for1440the placement of zeroes was chosen to agree with the output of1441``smith_form``.14421443See the example for a pictorial description of such a basis.14441445EXAMPLES::14461447sage: 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]); E1448[ 0 14 0 -8 -2]1449[-14 0 -3 -11 4]1450[ 0 3 0 0 0]1451[ 8 11 0 0 8]1452[ 2 -4 0 -8 0]1453sage: F, C = E.symplectic_form()1454sage: F1455[ 0 0 1 0 0]1456[ 0 0 0 2 0]1457[-1 0 0 0 0]1458[ 0 -2 0 0 0]1459[ 0 0 0 0 0]1460sage: F == C * E * C.transpose()1461True1462sage: E.smith_form()[0]1463[1 0 0 0 0]1464[0 1 0 0 0]1465[0 0 2 0 0]1466[0 0 0 2 0]1467[0 0 0 0 0]1468"""1469import sage.matrix.symplectic_basis1470return sage.matrix.symplectic_basis.symplectic_basis_over_ZZ(self)14711472hermite_form = echelon_form14731474def echelon_form(self, algorithm="default", proof=None, include_zero_rows=True,1475transformation=False, D=None):1476r"""1477Return the echelon form of this matrix over the integers, also known1478as the hermit normal form (HNF).14791480INPUT:14811482- ``algorithm`` -- String. The algorithm to use. Valid options are:14831484- ``'default'`` -- Let Sage pick an algorithm (default). Up1485to 10 rows or columns: pari with flag 0; Up to 75 rows or1486columns: pari with flag 1; Larger: use padic algorithm.14871488- ``'padic'`` - an asymptotically fast p-adic modular1489algorithm, If your matrix has large coefficients and is1490small, you may also want to try this.14911492- ``'pari'`` - use PARI with flag 114931494- ``'pari0'`` - use PARI with flag 014951496- ``'pari4'`` - use PARI with flag 4 (use heuristic LLL)14971498- ``'ntl'`` - use NTL (only works for square matrices of1499full rank!)15001501- ``proof`` - (default: True); if proof=False certain1502determinants are computed using a randomized hybrid p-adic1503multimodular strategy until it stabilizes twice (instead of up to1504the Hadamard bound). It is *incredibly* unlikely that one would1505ever get an incorrect result with proof=False.15061507- ``include_zero_rows`` - (default: True) if False,1508don't include zero rows15091510- ``transformation`` - if given, also compute1511transformation matrix; only valid for padic algorithm15121513- ``D`` - (default: None) if given and the algorithm1514is 'ntl', then D must be a multiple of the determinant and this1515function will use that fact.15161517OUTPUT:15181519The Hermite normal form (=echelon form over `\ZZ`) of self.15201521EXAMPLES::15221523sage: A = MatrixSpace(ZZ,2)([1,2,3,4])1524sage: A.echelon_form()1525[1 0]1526[0 2]1527sage: A = MatrixSpace(ZZ,5)(range(25))1528sage: A.echelon_form()1529[ 5 0 -5 -10 -15]1530[ 0 1 2 3 4]1531[ 0 0 0 0 0]1532[ 0 0 0 0 0]1533[ 0 0 0 0 0]15341535Getting a transformation matrix in the nonsquare case::15361537sage: A = matrix(ZZ,5,3,[1..15])1538sage: H, U = A.hermite_form(transformation=True, include_zero_rows=False)1539sage: H1540[1 2 3]1541[0 3 6]1542sage: U1543[ 0 0 0 4 -3]1544[ 0 0 0 13 -10]1545sage: U*A == H1546True15471548TESTS: Make sure the zero matrices are handled correctly::15491550sage: m = matrix(ZZ,3,3,[0]*9)1551sage: m.echelon_form()1552[0 0 0]1553[0 0 0]1554[0 0 0]1555sage: m = matrix(ZZ,3,1,[0]*3)1556sage: m.echelon_form()1557[0]1558[0]1559[0]1560sage: m = matrix(ZZ,1,3,[0]*3)1561sage: m.echelon_form()1562[0 0 0]15631564The ultimate border case!15651566::15671568sage: m = matrix(ZZ,0,0,[])1569sage: m.echelon_form()1570[]15711572.. note::15731574If 'ntl' is chosen for a non square matrix this function1575raises a ValueError.15761577Special cases: 0 or 1 rows::15781579sage: a = matrix(ZZ, 1,2,[0,-1])1580sage: a.hermite_form()1581[0 1]1582sage: a.pivots()1583(1,)1584sage: a = matrix(ZZ, 1,2,[0,0])1585sage: a.hermite_form()1586[0 0]1587sage: a.pivots()1588()1589sage: a = matrix(ZZ,1,3); a1590[0 0 0]1591sage: a.echelon_form(include_zero_rows=False)1592[]1593sage: a.echelon_form(include_zero_rows=True)1594[0 0 0]15951596Illustrate using various algorithms.::15971598sage: matrix(ZZ,3,[1..9]).hermite_form(algorithm='pari')1599[1 2 3]1600[0 3 6]1601[0 0 0]1602sage: matrix(ZZ,3,[1..9]).hermite_form(algorithm='pari0')1603[1 2 3]1604[0 3 6]1605[0 0 0]1606sage: matrix(ZZ,3,[1..9]).hermite_form(algorithm='pari4')1607[1 2 3]1608[0 3 6]1609[0 0 0]1610sage: matrix(ZZ,3,[1..9]).hermite_form(algorithm='padic')1611[1 2 3]1612[0 3 6]1613[0 0 0]1614sage: matrix(ZZ,3,[1..9]).hermite_form(algorithm='default')1615[1 2 3]1616[0 3 6]1617[0 0 0]16181619The 'ntl' algorithm doesn't work on matrices that do not have full rank.::16201621sage: matrix(ZZ,3,[1..9]).hermite_form(algorithm='ntl')1622Traceback (most recent call last):1623...1624ValueError: ntl only computes HNF for square matrices of full rank.1625sage: matrix(ZZ,3,[0] +[2..9]).hermite_form(algorithm='ntl')1626[1 0 0]1627[0 1 0]1628[0 0 3]16291630TESTS:16311632This example illustrated trac 2398::16331634sage: a = matrix([(0, 0, 3), (0, -2, 2), (0, 1, 2), (0, -2, 5)])1635sage: a.hermite_form()1636[0 1 2]1637[0 0 3]1638[0 0 0]1639[0 0 0]16401641Check that #12280 is fixed::16421643sage: m = matrix([(-2, 1, 9, 2, -8, 1, -3, -1, -4, -1),1644... (5, -2, 0, 1, 0, 4, -1, 1, -2, 0),1645... (-11, 3, 1, 0, -3, -2, -1, -11, 2, -2),1646... (-1, 1, -1, -2, 1, -1, -1, -1, -1, 7),1647... (-2, -1, -1, 1, 1, -2, 1, 0, 2, -4)]).stack(1648... 200 * identity_matrix(ZZ, 10))1649sage: matrix(ZZ,m).hermite_form(algorithm='pari', include_zero_rows=False)1650[ 1 0 2 0 13 5 1 166 72 69]1651[ 0 1 1 0 20 4 15 195 65 190]1652[ 0 0 4 0 24 5 23 22 51 123]1653[ 0 0 0 1 23 7 20 105 60 151]1654[ 0 0 0 0 40 4 0 80 36 68]1655[ 0 0 0 0 0 10 0 100 190 170]1656[ 0 0 0 0 0 0 25 0 100 150]1657[ 0 0 0 0 0 0 0 200 0 0]1658[ 0 0 0 0 0 0 0 0 200 0]1659[ 0 0 0 0 0 0 0 0 0 200]1660sage: matrix(ZZ,m).hermite_form(algorithm='padic', include_zero_rows=False)1661[ 1 0 2 0 13 5 1 166 72 69]1662[ 0 1 1 0 20 4 15 195 65 190]1663[ 0 0 4 0 24 5 23 22 51 123]1664[ 0 0 0 1 23 7 20 105 60 151]1665[ 0 0 0 0 40 4 0 80 36 68]1666[ 0 0 0 0 0 10 0 100 190 170]1667[ 0 0 0 0 0 0 25 0 100 150]1668[ 0 0 0 0 0 0 0 200 0 0]1669[ 0 0 0 0 0 0 0 0 200 0]1670[ 0 0 0 0 0 0 0 0 0 200]1671"""1672if self._nrows == 0 or self._ncols == 0:1673self.cache('pivots', ())1674self.cache('rank', 0)1675if transformation:1676return self, self1677return self16781679key = 'hnf-%s-%s'%(include_zero_rows,transformation)1680ans = self.fetch(key)1681if ans is not None: return ans16821683cdef Py_ssize_t nr, nc, n, i, j1684nr = self._nrows1685nc = self._ncols1686n = nr if nr >= nc else nc1687if algorithm is 'default':1688if transformation: algorithm = 'padic'1689else:1690if n <= 10: algorithm = 'pari0'1691elif n <= 75: algorithm = 'pari'1692else: algorithm = 'padic'16931694cdef bint pari_big = 01695if algorithm.startswith('pari'):1696if self.height().ndigits() > 10000 or n >= 50:1697pari_big = 116981699cdef Matrix_integer_dense H_m17001701proof = get_proof_flag(proof, "linear_algebra")1702pivots = None1703rank = None17041705if algorithm == "padic":1706import matrix_integer_dense_hnf1707if transformation:1708H_m, U, pivots = matrix_integer_dense_hnf.hnf_with_transformation(self, proof=proof)1709if not include_zero_rows:1710r = H_m.rank()1711H_m = H_m[:r]1712U = U[:r]1713else:1714H_m, pivots = matrix_integer_dense_hnf.hnf(self,1715include_zero_rows=include_zero_rows, proof=proof)1716self.cache('pivots', tuple(pivots))1717self.cache('rank', len(pivots))171817191720elif algorithm == 'pari0':1721if transformation:1722raise ValueError("transformation matrix only available with p-adic algorithm")1723if pari_big:1724H_m = self._hnf_pari_big(0, include_zero_rows=include_zero_rows)1725else:1726H_m = self._hnf_pari(0, include_zero_rows=include_zero_rows)17271728elif algorithm == 'pari':1729if transformation:1730raise ValueError("transformation matrix only available with p-adic algorithm")1731if pari_big:1732H_m = self._hnf_pari_big(1, include_zero_rows=include_zero_rows)1733else:1734H_m = self._hnf_pari(1, include_zero_rows=include_zero_rows)17351736elif algorithm == 'pari4':1737if transformation:1738raise ValueError("transformation matrix only available with p-adic algorithm")1739if pari_big:1740H_m = self._hnf_pari_big(4, include_zero_rows=include_zero_rows)1741else:1742H_m = self._hnf_pari(4, include_zero_rows=include_zero_rows)17431744elif algorithm == 'ntl':1745if transformation:1746raise ValueError("transformation matrix only available with p-adic algorithm")17471748if nr != nc:1749raise ValueError("ntl only computes HNF for square matrices of full rank.")17501751import sage.libs.ntl.ntl_mat_ZZ1752v = sage.libs.ntl.ntl_mat_ZZ.ntl_mat_ZZ(self._nrows,self._ncols)1753for i from 0 <= i < self._nrows:1754for j from 0 <= j < self._ncols:1755v[i,j] = self.get_unsafe(nr-i-1,nc-j-1)17561757try:1758w = v.HNF(D=D)1759except RuntimeError: # HNF may fail if a nxm matrix has rank < m1760raise ValueError("ntl only computes HNF for square matrices of full rank.")17611762rank = w.nrows()17631764if include_zero_rows:1765H_m = self.new_matrix()1766else:1767H_m = self.new_matrix(nrows=w.nrows())17681769nr = w.nrows()1770nc = w.ncols()17711772for i from 0 <= i < w.nrows():1773for j from 0 <= j < w.ncols():1774H_m[i,j] = w[nr-i-1,nc-j-1]17751776else:1777raise TypeError("algorithm '%s' not understood"%(algorithm))17781779H_m.set_immutable()1780if pivots is None:1781from matrix_integer_dense_hnf import pivots_of_hnf_matrix1782pivots = tuple(pivots_of_hnf_matrix(H_m))1783rank = len(pivots)1784else:1785pivots = tuple(pivots)17861787H_m.cache('pivots', pivots)1788self.cache('pivots', pivots)17891790H_m.cache('rank', rank)1791self.cache('rank',rank)17921793H_m.cache('in_echelon_form', True)179417951796if transformation:1797U.set_immutable()1798ans = H_m, U1799else:1800ans = H_m1801self.cache(key, ans)1802return ans18031804def saturation(self, p=0, proof=None, max_dets=5):1805r"""1806Return a saturation matrix of self, which is a matrix whose rows1807span the saturation of the row span of self. This is not unique.18081809The saturation of a `\ZZ` module `M`1810embedded in `\ZZ^n` is the a module `S` that1811contains `M` with finite index such that1812`\ZZ^n/S` is torsion free. This function takes the1813row span `M` of self, and finds another matrix of full rank1814with row span the saturation of `M`.18151816INPUT:181718181819- ``p`` - (default: 0); if nonzero given, saturate1820only at the prime `p`, i.e., return a matrix whose row span1821is a `\ZZ`-module `S` that contains self and1822such that the index of `S` in its saturation is coprime to1823`p`. If `p` is None, return full saturation of1824self.18251826- ``proof`` - (default: use proof.linear_algebra());1827if False, the determinant calculations are done with proof=False.18281829- ``max_dets`` - (default: 5); technical parameter -1830max number of determinant to compute when bounding prime divisor of1831self in its saturation.183218331834OUTPUT:183518361837- ``matrix`` - a matrix over ZZ183818391840.. note::18411842The result is *not* cached.18431844ALGORITHM: 1. Replace input by a matrix of full rank got from a1845subset of the rows. 2. Divide out any common factors from rows. 3.1846Check max_dets random dets of submatrices to see if their GCD1847(with p) is 1 - if so matrix is saturated and we're done. 4.1848Finally, use that if A is a matrix of full rank, then1849`hnf(transpose(A))^{-1}*A` is a saturation of A.18501851EXAMPLES::18521853sage: A = matrix(ZZ, 3, 5, [-51, -1509, -71, -109, -593, -19, -341, 4, 86, 98, 0, -246, -11, 65, 217])1854sage: A.echelon_form()1855[ 1 5 2262 20364 56576]1856[ 0 6 35653 320873 891313]1857[ 0 0 42993 386937 1074825]1858sage: S = A.saturation(); S1859[ -51 -1509 -71 -109 -593]1860[ -19 -341 4 86 98]1861[ 35 994 43 51 347]18621863Notice that the saturation spans a different module than A.18641865::18661867sage: S.echelon_form()1868[ 1 2 0 8 32]1869[ 0 3 0 -2 -6]1870[ 0 0 1 9 25]1871sage: V = A.row_space(); W = S.row_space()1872sage: V.is_submodule(W)1873True1874sage: V.index_in(W)1875859861876sage: V.index_in_saturation()18778598618781879We illustrate each option::18801881sage: S = A.saturation(p=2)1882sage: S = A.saturation(proof=False)1883sage: S = A.saturation(max_dets=2)1884"""1885proof = get_proof_flag(proof, "linear_algebra")1886import matrix_integer_dense_saturation1887return matrix_integer_dense_saturation.saturation(self, p=p, proof=proof, max_dets=max_dets)18881889def index_in_saturation(self, proof=None):1890"""1891Return the index of self in its saturation.18921893INPUT:189418951896- ``proof`` - (default: use proof.linear_algebra());1897if False, the determinant calculations are done with proof=False.189818991900OUTPUT:190119021903- ``positive integer`` - the index of the row span of1904this matrix in its saturation190519061907ALGORITHM: Use Hermite normal form twice to find an invertible1908matrix whose inverse transforms a matrix with the same row span as1909self to its saturation, then compute the determinant of that1910matrix.19111912EXAMPLES::19131914sage: A = matrix(ZZ, 2,3, [1..6]); A1915[1 2 3]1916[4 5 6]1917sage: A.index_in_saturation()191831919sage: A.saturation()1920[1 2 3]1921[1 1 1]1922"""1923proof = get_proof_flag(proof, "linear_algebra")1924import matrix_integer_dense_saturation1925return matrix_integer_dense_saturation.index_in_saturation(self, proof=proof)19261927def pivots(self):1928"""1929Return the pivot column positions of this matrix.19301931OUTPUT: a tuple of Python integers: the position of the1932first nonzero entry in each row of the echelon form.19331934EXAMPLES::19351936sage: n = 3; A = matrix(ZZ,n,range(n^2)); A1937[0 1 2]1938[3 4 5]1939[6 7 8]1940sage: A.pivots()1941(0, 1)1942sage: A.echelon_form()1943[ 3 0 -3]1944[ 0 1 2]1945[ 0 0 0]1946"""1947p = self.fetch('pivots')1948if not p is None: return tuple(p)19491950cdef Matrix_integer_dense E1951E = self.echelon_form()19521953# Now we determine the pivots from the matrix E as quickly as we can.1954# For each row, we find the first nonzero position in that row -- it is the pivot.1955cdef Py_ssize_t i, j, k1956cdef mpz_t *row1957p = []1958k = 01959for i from 0 <= i < E._nrows:1960row = E._matrix[i] # pointer to ith row1961for j from k <= j < E._ncols:1962if mpz_cmp_si(row[j], 0) != 0: # nonzero position1963p.append(j)1964k = j+1 # so start at next position next time1965break1966p = tuple(p)1967self.cache('pivots', p)1968return p19691970#### Elementary divisors19711972def elementary_divisors(self, algorithm='pari'):1973"""1974Return the elementary divisors of self, in order.197519761977.. warning::19781979This is MUCH faster than the smith_form function.19801981The elementary divisors are the invariants of the finite abelian1982group that is the cokernel of *left* multiplication of this matrix.1983They are ordered in reverse by divisibility.19841985INPUT:198619871988- ``self`` - matrix19891990- ``algorithm`` - (default: 'pari')19911992- ``'pari'``: works robustly, but is slower.19931994- ``'linbox'`` - use linbox (currently off, broken)199519961997OUTPUT: list of integers199819992000.. note::20012002These are the invariants of the cokernel of *left* multiplication::20032004sage: M = Matrix([[3,0,1],[0,1,0]])2005sage: M2006[3 0 1]2007[0 1 0]2008sage: M.elementary_divisors()2009[1, 1]2010sage: M.transpose().elementary_divisors()2011[1, 1, 0]20122013EXAMPLES::20142015sage: matrix(3, range(9)).elementary_divisors()2016[1, 3, 0]2017sage: matrix(3, range(9)).elementary_divisors(algorithm='pari')2018[1, 3, 0]2019sage: C = MatrixSpace(ZZ,4)([3,4,5,6,7,3,8,10,14,5,6,7,2,2,10,9])2020sage: C.elementary_divisors()2021[1, 1, 1, 687]20222023::20242025sage: M = matrix(ZZ, 3, [1,5,7, 3,6,9, 0,1,2])2026sage: M.elementary_divisors()2027[1, 1, 6]20282029This returns a copy, which is safe to change::20302031sage: edivs = M.elementary_divisors()2032sage: edivs.pop()203362034sage: M.elementary_divisors()2035[1, 1, 6]20362037.. seealso::20382039:meth:`smith_form`2040"""2041d = self.fetch('elementary_divisors')2042if not d is None:2043return d[:]2044if self._nrows == 0 or self._ncols == 0:2045d = []2046else:2047if algorithm == 'linbox':2048raise ValueError("linbox too broken -- currently Linbox SNF is disabled.")2049# This fails in linbox: a = matrix(ZZ,2,[1, 1, -1, 0, 0, 0, 0, 1])2050try:2051d = self._elementary_divisors_linbox()2052except RuntimeError:2053import sys2054sys.stderr.write("DONT PANIC -- switching to using PARI (which will work fine)\n")2055algorithm = 'pari'2056if algorithm == 'pari':2057d = self._pari_().matsnf(0).python()2058i = d.count(0)2059d.sort()2060if i > 0:2061d = d[i:] + [d[0]]*i2062elif not (algorithm in ['pari', 'linbox']):2063raise ValueError("algorithm (='%s') unknown"%algorithm)2064self.cache('elementary_divisors', d)2065return d[:]20662067def _elementary_divisors_linbox(self):2068self._init_linbox()2069sig_on()2070d = linbox.smithform()2071sig_off()2072return d20732074def smith_form(self):2075r"""2076Returns matrices S, U, and V such that S = U\*self\*V, and S is in2077Smith normal form. Thus S is diagonal with diagonal entries the2078ordered elementary divisors of S.20792080.. warning::20812082The elementary_divisors function, which returns the2083diagonal entries of S, is VASTLY faster than this function.20842085The elementary divisors are the invariants of the finite abelian2086group that is the cokernel of this matrix. They are ordered in2087reverse by divisibility.20882089EXAMPLES::20902091sage: A = MatrixSpace(IntegerRing(), 3)(range(9))2092sage: D, U, V = A.smith_form()2093sage: D2094[1 0 0]2095[0 3 0]2096[0 0 0]2097sage: U2098[ 0 1 0]2099[ 0 -1 1]2100[-1 2 -1]2101sage: V2102[-1 4 1]2103[ 1 -3 -2]2104[ 0 0 1]2105sage: U*A*V2106[1 0 0]2107[0 3 0]2108[0 0 0]21092110It also makes sense for nonsquare matrices::21112112sage: A = Matrix(ZZ,3,2,range(6))2113sage: D, U, V = A.smith_form()2114sage: D2115[1 0]2116[0 2]2117[0 0]2118sage: U2119[ 0 1 0]2120[ 0 -1 1]2121[-1 2 -1]2122sage: V2123[-1 3]2124[ 1 -2]2125sage: U * A * V2126[1 0]2127[0 2]2128[0 0]21292130Empty matrices are handled sensibly (see trac #3068)::21312132sage: m = MatrixSpace(ZZ, 2,0)(0); d,u,v = m.smith_form(); u*m*v == d2133True2134sage: m = MatrixSpace(ZZ, 0,2)(0); d,u,v = m.smith_form(); u*m*v == d2135True2136sage: m = MatrixSpace(ZZ, 0,0)(0); d,u,v = m.smith_form(); u*m*v == d2137True21382139.. seealso::21402141:meth:`elementary_divisors`2142"""2143v = self._pari_().matsnf(1).python()2144if self._ncols == 0: v[0] = self.matrix_space(ncols = self._nrows)(1)2145if self._nrows == 0: v[1] = self.matrix_space(nrows = self._ncols)(1)2146# need to reverse order of rows of U, columns of V, and both of D.2147D = 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)])21482149if self._ncols == 0:2150# silly special cases for matrices with 0 columns (PARI has a unique empty matrix)2151U = self.matrix_space(ncols = self._nrows)(1)2152else:2153U = 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)])21542155if self._nrows == 0:2156# silly special cases for matrices with 0 rows (PARI has a unique empty matrix)2157V = self.matrix_space(nrows = self._ncols)(1)2158else:2159V = 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)])21602161return D, U, V21622163def frobenius(self, flag=0, var='x'):2164"""2165Return the Frobenius form (rational canonical form) of this2166matrix.21672168INPUT:21692170- ``flag`` -- 0 (default), 1 or 2 as follows:21712172- ``0`` -- (default) return the Frobenius form of this2173matrix.21742175- ``1`` -- return only the elementary divisor2176polynomials, as polynomials in var.21772178- ``2`` -- return a two-components vector [F,B] where F2179is the Frobenius form and B is the basis change so that2180`M=B^{-1}FB`.21812182- ``var`` -- a string (default: 'x')21832184ALGORITHM: uses PARI's matfrobenius()21852186EXAMPLES::21872188sage: A = MatrixSpace(ZZ, 3)(range(9))2189sage: A.frobenius(0)2190[ 0 0 0]2191[ 1 0 18]2192[ 0 1 12]2193sage: A.frobenius(1)2194[x^3 - 12*x^2 - 18*x]2195sage: A.frobenius(1, var='y')2196[y^3 - 12*y^2 - 18*y]2197sage: F, B = A.frobenius(2)2198sage: A == B^(-1)*F*B2199True2200sage: a=matrix([])2201sage: a.frobenius(2)2202([], [])2203sage: a.frobenius(0)2204[]2205sage: a.frobenius(1)2206[]2207sage: B = random_matrix(ZZ,2,3)2208sage: B.frobenius()2209Traceback (most recent call last):2210...2211ArithmeticError: frobenius matrix of non-square matrix not defined.22122213AUTHORS:22142215- Martin Albrect (2006-04-02)22162217TODO: - move this to work for more general matrices than just over2218Z. This will require fixing how PARI polynomials are coerced to2219Sage polynomials.2220"""2221if not self.is_square():2222raise ArithmeticError("frobenius matrix of non-square matrix not defined.")22232224v = self._pari_().matfrobenius(flag)2225if flag==0:2226return self.matrix_space()(v.python())2227elif flag==1:2228r = PolynomialRing(self.base_ring(), names=var)2229retr = []2230for f in v:2231retr.append(eval(str(f).replace("^","**"), {'x':r.gen()}, r.gens_dict()))2232return retr2233elif flag==2:2234F = matrix_space.MatrixSpace(QQ, self.nrows())(v[0].python())2235B = matrix_space.MatrixSpace(QQ, self.nrows())(v[1].python())2236return F, B22372238def _right_kernel_matrix(self, **kwds):2239r"""2240Returns a pair that includes a matrix of basis vectors2241for the right kernel of ``self``.22422243INPUT:22442245- ``algorithm`` - determines which algorithm to use, options are:22462247- 'pari' - use the ``matkerint()`` function from the PARI library2248- 'padic' - use the p-adic algorithm from the IML library2249- 'default' - use a heuristic to decide which of the two above2250routines is fastest. This is the default value.22512252- ``proof`` - this is passed to the p-adic IML algorithm.2253If not specified, the global flag for linear algebra will be used.22542255OUTPUT:22562257Returns a pair. First item is the string is either2258'computed-pari-int' or 'computed-iml-int', which identifies2259the nature of the basis vectors.22602261Second item is a matrix whose rows are a basis for the right kernel,2262over the integers, as computed by either the IML or PARI libraries.22632264EXAMPLES::22652266sage: A = matrix(ZZ, [[4, 7, 9, 7, 5, 0],2267... [1, 0, 5, 8, 9, 1],2268... [0, 1, 0, 1, 9, 7],2269... [4, 7, 6, 5, 1, 4]])22702271sage: result = A._right_kernel_matrix(algorithm='pari')2272sage: result[0]2273'computed-pari-int'2274sage: X = result[1]; X2275[-26 31 -30 21 2 -10]2276[-47 -13 48 -14 -11 18]2277sage: A*X.transpose() == zero_matrix(ZZ, 4, 2)2278True22792280sage: result = A._right_kernel_matrix(algorithm='padic')2281sage: result[0]2282'computed-iml-int'2283sage: X = result[1]; X2284[-469 214 -30 119 -37 0]2285[ 370 -165 18 -91 30 -2]2286sage: A*X.transpose() == zero_matrix(ZZ, 4, 2)2287True22882289sage: result = A._right_kernel_matrix(algorithm='default')2290sage: result[0]2291'computed-pari-int'2292sage: result[1]2293[-26 31 -30 21 2 -10]2294[-47 -13 48 -14 -11 18]22952296sage: result = A._right_kernel_matrix()2297sage: result[0]2298'computed-pari-int'2299sage: result[1]2300[-26 31 -30 21 2 -10]2301[-47 -13 48 -14 -11 18]23022303With the 'default' given as the algorithm, several heuristics are2304used to determine if PARI or IML ('padic') is used. The code has2305exact details, but roughly speaking, relevant factors are: the2306absolute size of the matrix, or the relative dimensions, or the2307magnitude of the entries. ::23082309sage: A = random_matrix(ZZ, 18, 11)2310sage: A._right_kernel_matrix(algorithm='default')[0]2311'computed-pari-int'2312sage: A = random_matrix(ZZ, 18, 11, x = 10^200)2313sage: A._right_kernel_matrix(algorithm='default')[0]2314'computed-iml-int'2315sage: A = random_matrix(ZZ, 60, 60)2316sage: A._right_kernel_matrix(algorithm='default')[0]2317'computed-iml-int'2318sage: A = random_matrix(ZZ, 60, 55)2319sage: A._right_kernel_matrix(algorithm='default')[0]2320'computed-pari-int'23212322TESTS:23232324We test three trivial cases. PARI is used for small matrices,2325but we let the heuristic decide that. ::23262327sage: A = matrix(ZZ, 0, 2)2328sage: A._right_kernel_matrix()[1]2329[1 0]2330[0 1]2331sage: A = matrix(ZZ, 2, 0)2332sage: A._right_kernel_matrix()[1].parent()2333Full MatrixSpace of 0 by 0 dense matrices over Integer Ring2334sage: A = zero_matrix(ZZ, 4, 3)2335sage: A._right_kernel_matrix()[1]2336[1 0 0]2337[0 1 0]2338[0 0 1]2339"""2340tm = verbose("computing right kernel matrix over the integers for %sx%s matrix" % (self.nrows(), self.ncols()),level=1)23412342algorithm = kwds.pop('algorithm', None)2343if algorithm == None:2344algorithm = 'default'23452346if algorithm == 'default':2347# The heuristic here could be auto-tuned, stored for2348# different architecture, etc. What I've done below here2349# I just got by playing around with examples. This is2350# *dramatically* better than doing absolutely nothing2351# (i.e., always choosing 'padic'), but is of course2352# far from optimal. -- William Stein2353if max(self._nrows, self._ncols) <= 10:2354# pari much better for very small matrices, as long as entries aren't huge.2355algorithm = 'pari'2356if max(self._nrows, self._ncols) <= 50:2357# when entries are huge, padic relatively good.2358h = self.height().ndigits()2359if h < 100:2360algorithm = 'pari'2361else:2362algorithm = 'padic'2363elif self._nrows <= self._ncols + 3:2364# the padic algorithm is much better for bigger2365# matrices if there are nearly more columns than rows2366# (that is its forte)2367algorithm = 'padic'2368else:2369algorithm = 'pari'23702371if algorithm == 'pari':2372K = self._pari_().matkerint().mattranspose().python()2373format = 'computed-pari-int'2374if algorithm == 'padic':2375proof = kwds.pop('proof', None)2376proof = get_proof_flag(proof, "linear_algebra")2377K = self._rational_kernel_iml().transpose().saturation(proof=proof)2378format = 'computed-iml-int'2379tm = verbose("done computing right kernel matrix over the integers for %sx%s matrix" % (self.nrows(), self.ncols()),level=1, t=tm)2380return (format, K)23812382def _adjoint(self):2383"""2384Return the adjoint of this matrix.23852386Assumes self is a square matrix (checked in adjoint).23872388EXAMPLES::23892390sage: m = matrix(ZZ,3,[1..9])2391sage: m.adjoint()2392[ -3 6 -3]2393[ 6 -12 6]2394[ -3 6 -3]2395"""2396return self.parent()(self._pari_().matadjoint().python())23972398def _ntl_(self):2399r"""2400ntl.mat_ZZ representation of self.24012402EXAMPLE::24032404sage: a = MatrixSpace(ZZ,200).random_element(x=-2, y=2) # -2 to 22405sage: A = a._ntl_()24062407.. note::24082409NTL only knows dense matrices, so if you provide a sparse2410matrix NTL will allocate memory for every zero entry.2411"""2412import sage.libs.ntl.ntl_mat_ZZ2413return sage.libs.ntl.ntl_mat_ZZ.ntl_mat_ZZ(self._nrows,self._ncols, self.list())241424152416####################################################################################2417# LLL2418####################################################################################2419def LLL_gram(self):2420"""2421LLL reduction of the lattice whose gram matrix is self.24222423INPUT:242424252426- ``M`` - gram matrix of a definite quadratic form242724282429OUTPUT:243024312432- ``U`` - unimodular transformation matrix such that2433U.transpose() \* M \* U is LLL-reduced.24342435ALGORITHM: Use PARI24362437EXAMPLES::24382439sage: M = Matrix(ZZ, 2, 2, [5,3,3,2]) ; M2440[5 3]2441[3 2]2442sage: U = M.LLL_gram(); U2443[-1 1]2444[ 1 -2]2445sage: U.transpose() * M * U2446[1 0]2447[0 1]24482449Semidefinite and indefinite forms no longer raise a ValueError::24502451sage: Matrix(ZZ,2,2,[2,6,6,3]).LLL_gram()2452[-3 -1]2453[ 1 0]2454sage: Matrix(ZZ,2,2,[1,0,0,-1]).LLL_gram()2455[ 0 -1]2456[ 1 0]24572458"""2459if self._nrows != self._ncols:2460raise ArithmeticError("self must be a square matrix")24612462n = self.nrows()2463# maybe should be /unimodular/ matrices ?2464P = self._pari_()2465try:2466U = P.lllgramint()2467except (RuntimeError, ArithmeticError), msg:2468raise ValueError("not a definite matrix")2469MS = matrix_space.MatrixSpace(ZZ,n)2470U = MS(U.python())2471# Fix last column so that det = +12472if U.det() == -1:2473for i in range(n):2474U[i,n-1] = - U[i,n-1]2475return U24762477def BKZ(self, delta=None, fp="rr", block_size=10, prune=0, use_givens=False):2478"""2479Block Korkin-Zolotarev reduction.24802481INPUT:248224832484- ``fp`` - 'fp' - double precision: NTL's FP or2485fpLLL's double24862487- ``'qd'`` - quad doubles: NTL's QP24882489- ``'qd1'`` - quad doubles: uses quad_float precision2490to compute Gram-Schmidt, but uses double precision in the search2491phase of the block reduction algorithm. This seems adequate for2492most purposes, and is faster than 'qd', which uses quad_float2493precision uniformly throughout.24942495- ``'xd'`` - extended exponent: NTL's XD24962497- ``'rr'`` - arbitrary precision (default)24982499- ``block_size`` - specifies the size of the blocks2500in the reduction. High values yield shorter vectors, but the2501running time increases exponentially with2502``block_size``. ``block_size`` should be2503between 2 and the number of rows of ``self`` (default:250410)25052506- ``prune`` - The optional parameter2507``prune`` can be set to any positive number to invoke2508the Volume Heuristic from [Schnorr and Horner, Eurocrypt '95]. This2509can significantly reduce the running time, and hence allow much2510bigger block size, but the quality of the reduction is of course2511not as good in general. Higher values of ``prune`` mean2512better quality, and slower running time. When ``prune``2513== 0, pruning is disabled. Recommended usage: for2514``block_size`` = 30, set 10 = ``prune`` =251515.25162517- ``use_givens`` - use Given's orthogonalization.2518This is a bit slower, but generally much more stable, and is really2519the preferred orthogonalization strategy. For a nice description of2520this, see Chapter 5 of [G. Golub and C. van Loan, Matrix2521Computations, 3rd edition, Johns Hopkins Univ. Press, 1996].252225232524EXAMPLE::25252526sage: A = Matrix(ZZ,3,3,range(1,10))2527sage: A.BKZ()2528[ 0 0 0]2529[ 2 1 0]2530[-1 1 3]2531sage: A = Matrix(ZZ,3,3,range(1,10))2532sage: A.BKZ(use_givens=True)2533[ 0 0 0]2534[ 2 1 0]2535[-1 1 3]25362537::25382539sage: A = Matrix(ZZ,3,3,range(1,10))2540sage: A.BKZ(fp="fp")2541[ 0 0 0]2542[ 2 1 0]2543[-1 1 3]2544"""2545if delta is None:2546delta = 0.992547elif delta <= 0.25:2548raise TypeError("delta must be > 0.25")2549elif delta > 1:2550raise TypeError("delta must be <= 1")2551delta = float(delta)25522553if fp is None:2554fp = "rr"25552556if fp == "fp":2557algorithm = "BKZ_FP"2558elif fp == "qd":2559algorithm = "BKZ_QP"2560elif fp == "qd1":2561algorithm = "BKZ_QP1"2562elif fp == "xd":2563algorithm = "BKZ_XD"2564elif fp == "rr":2565algorithm = "BKZ_RR"2566else:2567raise TypeError("fp parameter not understood.")25682569block_size = int(block_size)25702571if prune < 0:2572raise TypeError("prune must be >= 0")2573prune = int(prune)25742575if get_verbose() >= 2:2576verbose = True2577else:2578verbose = False25792580A = self._ntl_()25812582if algorithm == "BKZ_FP":2583if not use_givens:2584r = A.BKZ_FP(U=None, delta=delta, BlockSize=block_size, prune=prune, verbose=verbose)2585else:2586r = A.G_BKZ_FP(U=None, delta=delta, BlockSize=block_size, prune=prune, verbose=verbose)25872588elif algorithm == "BKZ_QP":2589if not use_givens:2590r = A.BKZ_QP(U=None, delta=delta, BlockSize=block_size, prune=prune, verbose=verbose)2591else:2592r = A.G_BKZ_QP(U=None, delta=delta, BlockSize=block_size, prune=prune, verbose=verbose)25932594elif algorithm == "BKZ_QP1":2595if not use_givens:2596r = A.BKZ_QP1(U=None, delta=delta, BlockSize=block_size, prune=prune, verbose=verbose)2597else:2598r = A.G_BKZ_QP1(U=None, delta=delta, BlockSize=block_size, prune=prune, verbose=verbose)25992600elif algorithm == "BKZ_XD":2601if not use_givens:2602r = A.BKZ_XD(U=None, delta=delta, BlockSize=block_size, prune=prune, verbose=verbose)2603else:2604r = A.G_BKZ_XD(U=None, delta=delta, BlockSize=block_size, prune=prune, verbose=verbose)26052606elif algorithm == "BKZ_RR":2607if not use_givens:2608r = A.BKZ_RR(U=None, delta=delta, BlockSize=block_size, prune=prune, verbose=verbose)2609else:2610r = A.G_BKZ_RR(U=None, delta=delta, BlockSize=block_size, prune=prune, verbose=verbose)26112612self.cache("rank",ZZ(r))2613R = <Matrix_integer_dense>self.new_matrix(entries=map(ZZ,A.list()))2614return R26152616def LLL(self, delta=None, eta=None, algorithm="fpLLL:wrapper", fp=None, prec=0, early_red = False, use_givens = False):2617r"""2618Returns LLL reduced or approximated LLL reduced lattice R for this2619matrix interpreted as a lattice.26202621A lattice `(b_1, b_2, ..., b_d)` is2622`(\delta, \eta)` -LLL-reduced if the two following2623conditions hold:26242625- For any `i>j`, we have `|mu_{i, j}| <= \eta`,2626- For any `i<d`, we have2627`\delta |b_i^*|^2 <= |b_{i + 1}^* + mu_{i + 1, i} b_i^* |^2`,26282629where `mu_{i,j} = <b_i, b_j^*>/<b_j^*,b_j^*>` and2630`b_i^*` is the `i`-th vector of the Gram-Schmidt2631orthogonalisation of `(b_1, b_2, ..., b_d)`.26322633The default reduction parameters are `\delta=3/4` and2634`eta=0.501`. The parameters `\delta` and2635`\eta` must satisfy: `0.25 < \delta <= 1.0` and2636`0.5 <= \eta < sqrt(\delta)`. Polynomial time2637complexity is only guaranteed for `\delta < 1`.26382639The lattice is returned as a matrix. Also the rank (and the2640determinant) of self are cached if those are computed during the2641reduction. Note that in general this only happens when self.rank()2642== self.ncols() and the exact algorithm is used.26432644INPUT:264526462647- ``delta`` - parameter as described above (default:26483/4)26492650- ``eta`` - parameter as described above (default:26510.501), ignored by NTL26522653- ``algorithm`` - string (default: "fpLLL:wrapper")2654one of the algorithms mentioned below26552656- ``fp``26572658- None - NTL's exact reduction or fpLLL's2659wrapper26602661- ``'fp'`` - double precision: NTL's FP or fpLLL's2662double26632664- ``'qd'`` - quad doubles: NTL's QP26652666- ``'xd'`` - extended exponent: NTL's XD or fpLLL's2667dpe26682669- ``'rr'`` - arbitrary precision: NTL'RR or fpLLL's2670MPFR26712672- ``prec`` - precision, ignored by NTL (default: auto2673choose)26742675- ``early_red`` - perform early reduction, ignored by2676NTL (default: False)26772678- ``use_givens`` - use Givens orthogonalization2679(default: False) only applicable to approximate reductions and NTL.2680This is more stable but slower.26812682Also, if the verbose level is = 2, some more verbose output is2683printed during the calculation if NTL is used.26842685AVAILABLE ALGORITHMS:26862687- ``NTL:LLL`` - NTL's LLL + fp26882689- ``fpLLL:heuristic`` - fpLLL's heuristic + fp26902691- ``fpLLL:fast`` - fpLLL's fast26922693- ``fpLLL:wrapper`` - fpLLL's automatic choice2694(default)269526962697OUTPUT: a matrix over the integers26982699EXAMPLE::27002701sage: A = Matrix(ZZ,3,3,range(1,10))2702sage: A.LLL()2703[ 0 0 0]2704[ 2 1 0]2705[-1 1 3]27062707We compute the extended GCD of a list of integers using LLL, this2708example is from the Magma handbook::27092710sage: Q = [ 67015143, 248934363018, 109210, 25590011055, 74631449, \271110230248, 709487, 68965012139, 972065, 864972271 ]2712sage: n = len(Q)2713sage: S = 1002714sage: X = Matrix(ZZ, n, n + 1)2715sage: for i in xrange(n):2716... X[i,i + 1] = 12717sage: for i in xrange(n):2718... X[i,0] = S*Q[i]2719sage: L = X.LLL()2720sage: M = L.row(n-1).list()[1:]2721sage: M2722[-3, -1, 13, -1, -4, 2, 3, 4, 5, -1]2723sage: add([Q[i]*M[i] for i in range(n)])2724-127252726TESTS::27272728sage: matrix(ZZ, 0, 0).LLL()2729[]2730sage: matrix(ZZ, 3, 0).LLL()2731[]2732sage: matrix(ZZ, 0, 3).LLL()2733[]27342735sage: M = matrix(ZZ, [[1,2,3],[31,41,51],[101,201,301]])2736sage: A = M.LLL()2737sage: A2738[ 0 0 0]2739[-1 0 1]2740[ 1 1 1]2741sage: B = M.LLL(algorithm='NTL:LLL')2742sage: C = M.LLL(algorithm='NTL:LLL', fp=None)2743sage: D = M.LLL(algorithm='NTL:LLL', fp='fp')2744sage: F = M.LLL(algorithm='NTL:LLL', fp='xd')2745sage: G = M.LLL(algorithm='NTL:LLL', fp='rr')2746sage: A == B == C == D == F == G2747True2748sage: H = M.LLL(algorithm='NTL:LLL', fp='qd')2749Traceback (most recent call last):2750...2751TypeError: algorithm NTL:LLL_QD not supported27522753ALGORITHM: Uses the NTL library by Victor Shoup or fpLLL library by2754Damien Stehle depending on the chosen algorithm.27552756REFERENCES:27572758- ``ntl.mat_ZZ`` or ``sage.libs.fplll.fplll`` for details on2759the used algorithms.2760"""2761if self.ncols()==0 or self.nrows()==0:2762verbose("Trivial matrix, nothing to do")2763return self27642765tm = verbose("LLL of %sx%s matrix (algorithm %s)"%(self.nrows(), self.ncols(), algorithm))2766import sage.libs.ntl.all2767ntl_ZZ = sage.libs.ntl.all.ZZ27682769from sage.libs.fplll.fplll import FP_LLL27702771if get_verbose() >= 2: verb = True2772else: verb = False27732774# auto choice27752776# FP choice2777if algorithm == 'NTL:LLL':2778if fp == None:2779algorithm = 'NTL:LLL_FP'2780elif fp == 'fp':2781algorithm = 'NTL:LLL_FP'2782elif fp == 'qd':2783algorithm = 'NTL:LLL_QD'2784elif fp == 'xd':2785algorithm = 'NTL:LLL_XD'2786elif fp == 'rr':2787algorithm = 'NTL:LLL_RR'2788elif algorithm == 'fpLLL:heuristic':2789if fp == None:2790raise TypeError("if 'fpLLL:heuristic' is chosen, a floating point number implementation must be chosen")2791elif fp == 'fp':2792fp = 'double'2793elif fp == 'qd':2794raise TypeError("fpLLL does not support quad doubles.")2795elif fp == 'xd':2796fp = 'dpe'2797elif fp == 'rr':2798fp = 'mpfr'27992800if algorithm == "NTL:LLL":2801if delta is None:2802delta = ZZ(3)/ZZ(4)2803elif delta <= ZZ(1)/ZZ(4):2804raise TypeError("delta must be > 1/4")2805elif delta > 1:2806raise TypeError("delta must be <= 1")2807delta = QQ(delta)2808a = delta.numer()2809b = delta.denom()28102811else:2812if delta is None:2813delta = 0.992814elif delta <= 0.25:2815raise TypeError("delta must be > 0.25")2816elif delta > 1:2817raise TypeError("delta must be <= 1")2818delta = float(delta)28192820if eta is None:2821eta = 0.5012822elif eta < 0.5:2823raise TypeError("eta must be >= 0.5")28242825if prec < 0:2826raise TypeError("precision prec must be >= 0")2827int(prec)28282829if algorithm.startswith('NTL:'):2830A = sage.libs.ntl.all.mat_ZZ(self.nrows(),self.ncols(),map(ntl_ZZ,self.list()))28312832if algorithm == "NTL:LLL":2833r, det2 = A.LLL(a,b, verbose=verb)2834det2 = ZZ(det2)2835try:2836det = ZZ(det2.sqrt_approx())2837self.cache("det", det)2838except TypeError:2839pass2840elif algorithm == "NTL:LLL_FP":2841if use_givens:2842r = A.G_LLL_FP(delta, verbose=verb)2843else:2844r = A.LLL_FP(delta, verbose=verb)2845elif algorithm == "NTL:LLL_QP":2846if use_givens:2847r = A.G_LLL_QP(delta, verbose=verb)2848else:2849r = A.LLL_QP(delta, verbose=verb)2850elif algorithm == "NTL:LLL_XD":2851if use_givens:2852r = A.G_LLL_XD(delta, verbose=verb)2853else:2854r = A.LLL_XD(delta, verbose=verb)2855elif algorithm == "NTL:LLL_RR":2856if use_givens:2857r = A.G_LLL_RR(delta, verbose=verb)2858else:2859r = A.LLL_XD(delta, verbose=verb)2860else:2861raise TypeError("algorithm %s not supported"%algorithm)28622863r = ZZ(r)28642865R = <Matrix_integer_dense>self.new_matrix(entries=map(ZZ,A.list()))2866self.cache("rank",r)28672868elif algorithm.startswith('fpLLL:'):28692870A = sage.libs.fplll.fplll.FP_LLL(self)2871if algorithm == 'fpLLL:wrapper':2872A.wrapper(prec, eta, delta)2873elif algorithm == 'fpLLL:heuristic':2874if early_red:2875A.heuristic_early_red(prec,eta,delta,fp)2876else:2877A.heuristic(prec,eta,delta,fp)2878elif algorithm == 'fpLLL:fast':2879if early_red:2880A.fast_early_red(prec,eta,delta)2881else:2882A.fast(prec,eta,delta)2883elif algorithm == 'fpLLL:proved':2884A.proved(prec,eta,delta)2885else:2886raise TypeError("algorithm %s not supported"%algorithm)2887R = A._sage_()2888else:2889raise TypeError("algorithm %s not supported"%algorithm)28902891verbose("LLL finished", tm)2892return R28932894def is_LLL_reduced(self, delta=None, eta=None):2895r"""2896Return ``True`` if this lattice is2897`(\delta, \eta)`-LLL reduced. See ``self.LLL``2898for a definition of LLL reduction.28992900INPUT:290129022903- ``delta`` - parameter as described above (default:29043/4)29052906- ``eta`` - parameter as described above (default:29070.501)290829092910EXAMPLE::29112912sage: A = random_matrix(ZZ, 10, 10)2913sage: L = A.LLL()2914sage: A.is_LLL_reduced()2915False2916sage: L.is_LLL_reduced()2917True2918"""2919if eta is None:2920eta = 0.5012921if delta is None:2922delta = ZZ(3)/ZZ(4)29232924if delta <= ZZ(1)/ZZ(4):2925raise TypeError("delta must be > 1/4")2926elif delta > 1:2927raise TypeError("delta must be <= 1")29282929if eta < 0.5:2930raise TypeError("eta must be >= 0.5")29312932# this is pretty slow2933import sage.modules.misc2934G, mu = sage.modules.misc.gram_schmidt(self.rows())2935#For any $i>j$, we have $|mu_{i, j}| <= \eta$2936for e in mu.list():2937if e.abs() > eta:2938return False29392940#For any $i<d$, we have $\delta |b_i^*|^2 <= |b_{i+1}^* + mu_{i+1, i} b_i^* |^2$2941norms = [G[i].norm()**2 for i in range(len(G))]2942for i in xrange(1,self.nrows()):2943if norms[i] < (delta - mu[i,i-1]**2) * norms[i-1]:2944return False2945return True29462947def prod_of_row_sums(self, cols):2948"""2949Return the product of the sums of the entries in the submatrix of2950self with given columns.29512952INPUT:295329542955- ``cols`` - a list (or set) of integers representing2956columns of self.295729582959OUTPUT: an integer29602961EXAMPLES::29622963sage: a = matrix(ZZ,2,3,[1..6]); a2964[1 2 3]2965[4 5 6]2966sage: a.prod_of_row_sums([0,2])2967402968sage: (1+3)*(4+6)2969402970sage: a.prod_of_row_sums(set([0,2]))2971402972"""2973cdef Py_ssize_t c, row2974cdef mpz_t s, pr2975mpz_init(s)2976mpz_init(pr)29772978mpz_set_si(pr, 1)2979for row from 0 <= row < self._nrows:2980mpz_set_si(s, 0)2981for c in cols:2982if c<0 or c >= self._ncols:2983raise IndexError("matrix column index out of range")2984mpz_add(s, s, self._matrix[row][c])2985mpz_mul(pr, pr, s)2986cdef Integer z2987z = PY_NEW(Integer)2988mpz_set(z.value, pr)2989mpz_clear(s)2990mpz_clear(pr)2991return z29922993def _linbox_sparse(self):2994cdef Py_ssize_t i, j2995v = ['%s %s M'%(self._nrows, self._ncols)]2996for i from 0 <= i < self._nrows:2997for j from 0 <= j < self._ncols:2998if mpz_cmp_si(self._matrix[i][j], 0):2999v.append('%s %s %s'%(i+1,j+1,self.get_unsafe(i,j)))3000v.append('0 0 0\n')3001return '\n'.join(v)30023003def _linbox_dense(self):3004cdef Py_ssize_t i, j3005v = ['%s %s x'%(self._nrows, self._ncols)]3006for i from 0 <= i < self._nrows:3007for j from 0 <= j < self._ncols:3008v.append(str(self.get_unsafe(i,j)))3009return ' '.join(v)30103011def rational_reconstruction(self, N):3012"""3013Use rational reconstruction to lift self to a matrix over the3014rational numbers (if possible), where we view self as a matrix3015modulo N.30163017INPUT:301830193020- ``N`` - an integer302130223023OUTPUT:302430253026- ``matrix`` - over QQ or raise a ValueError302730283029EXAMPLES: We create a random 4x4 matrix over ZZ.30303031::30323033sage: A = matrix(ZZ, 4, [4, -4, 7, 1, -1, 1, -1, -12, -1, -1, 1, -1, -3, 1, 5, -1])30343035There isn't a unique rational reconstruction of it::30363037sage: A.rational_reconstruction(11)3038Traceback (most recent call last):3039...3040ValueError: Rational reconstruction of 4 (mod 11) does not exist.30413042We throw in a denominator and reduce the matrix modulo 389 - it3043does rationally reconstruct.30443045::30463047sage: B = (A/3 % 389).change_ring(ZZ)3048sage: B.rational_reconstruction(389) == A/33049True30503051TEST:30523053Check that ticket #9345 is fixed::30543055sage: A = random_matrix(ZZ, 3, 3)3056sage: A.rational_reconstruction(0)3057Traceback (most recent call last):3058...3059ZeroDivisionError: The modulus cannot be zero3060"""3061import misc3062return misc.matrix_integer_dense_rational_reconstruction(self, N)30633064def randomize(self, density=1, x=None, y=None, distribution=None, \3065nonzero=False):3066"""3067Randomize ``density`` proportion of the entries of this matrix,3068leaving the rest unchanged.30693070The parameters are the same as the ones for the integer ring's3071``random_element`` function.30723073If ``x`` and ``y`` are given, randomized entries of this matrix have3074to be between ``x`` and ``y`` and have density 1.30753076INPUT:30773078- ``self`` - a mutable matrix over ZZ30793080- ``density`` - a float between 0 and 130813082- ``x, y`` - if not ``None``, these are passed to the3083``ZZ.random_element`` function as the upper and lower endpoints in3084the uniform distribution30853086- ``distribution`` - would also be passed into ``ZZ.random_element``3087if given30883089- ``nonzero`` - bool (default: ``False``); whether the new entries3090are guaranteed to be zero30913092OUTPUT:30933094- None, the matrix is modified in-place30953096EXAMPLES::30973098sage: A = matrix(ZZ, 2,3, [1..6]); A3099[1 2 3]3100[4 5 6]3101sage: A.randomize()3102sage: A3103[-8 2 0]3104[ 0 1 -1]3105sage: A.randomize(x=-30,y=30)3106sage: A3107[ 5 -19 24]3108[ 24 23 -9]3109"""3110density = float(density)3111if density <= 0:3112return3113if density > 1:3114density = float(1)31153116self.check_mutability()3117self.clear_cache()31183119cdef randstate rstate = current_randstate()31203121cdef Py_ssize_t i, j, k, nc, num_per_row3122global state, ZZ31233124cdef IntegerRing_class the_integer_ring = ZZ31253126if not nonzero:3127# Original code, before adding the ``nonzero`` option.3128sig_on()3129if density == 1:3130for i from 0 <= i < self._nrows*self._ncols:3131the_integer_ring._randomize_mpz(self._entries[i], x, y, \3132distribution)3133else:3134nc = self._ncols3135num_per_row = int(density * nc)3136for i from 0 <= i < self._nrows:3137for j from 0 <= j < num_per_row:3138k = rstate.c_random()%nc3139the_integer_ring._randomize_mpz(self._matrix[i][k], \3140x, y, distribution)3141sig_off()3142else:3143# New code, to implement the ``nonzero`` option. Note that this3144# code is almost the same as above, the only difference being that3145# each entry is set until it's non-zero.3146sig_on()3147if density == 1:3148for i from 0 <= i < self._nrows*self._ncols:3149while mpz_sgn(self._entries[i]) == 0:3150the_integer_ring._randomize_mpz(self._entries[i], \3151x, y, distribution)3152else:3153nc = self._ncols3154num_per_row = int(density * nc)3155for i from 0 <= i < self._nrows:3156for j from 0 <= j < num_per_row:3157k = rstate.c_random() % nc3158while mpz_sgn(self._matrix[i][k]) == 0:3159the_integer_ring._randomize_mpz(self._matrix[i][k],\3160x, y, distribution)3161sig_off()31623163#### Rank31643165def rank(self):3166"""3167Return the rank of this matrix.31683169OUTPUT:317031713172- ``nonnegative integer`` - the rank317331743175.. note::31763177The rank is cached.31783179ALGORITHM: First check if the matrix has maxim possible rank by3180working modulo one random prime. If not call LinBox's rank3181function.31823183EXAMPLES::31843185sage: a = matrix(ZZ,2,3,[1..6]); a3186[1 2 3]3187[4 5 6]3188sage: a.rank()318923190sage: a = matrix(ZZ,3,3,[1..9]); a3191[1 2 3]3192[4 5 6]3193[7 8 9]3194sage: a.rank()3195231963197Here's a bigger example - the rank is of course still 2::31983199sage: a = matrix(ZZ,100,[1..100^2]); a.rank()320023201"""3202r = self.fetch('rank')3203if not r is None: return r32043205if self._nrows <= 6 and self._ncols <= 6 and self.height().ndigits() <= 10000:3206r = self._rank_pari()3207# Can very quickly detect full rank by working modulo p.3208r = self._rank_modp()3209if r == self._nrows or r == self._ncols:3210self.cache('rank', r)3211return r3212# Detecting full rank didn't work -- use LinBox's general algorithm.3213r = self._rank_linbox()3214self.cache('rank', r)3215return r32163217def _rank_linbox(self):3218"""3219Compute the rank of this matrix using Linbox.3220"""3221self._init_linbox()3222cdef unsigned long r3223sig_on()3224r = linbox.rank()3225sig_off()3226return Integer(r)32273228def _rank_modp(self, p=46337):3229A = self._mod_int_c(p)3230return A.rank()32313232#### Determinant32333234def determinant(self, algorithm='default', proof=None, stabilize=2):3235r"""3236Return the determinant of this matrix.32373238INPUT:32393240- ``algorithm``32413242- ``'default'`` -- automatically determine which algorithm3243to use depending on the matrix.32443245- ``'padic'`` - uses a p-adic / multimodular3246algorithm that relies on code in IML and linbox32473248- ``'linbox'`` - calls linbox det (you *must* set3249proof=False to use this!)32503251- ``'ntl'`` - calls NTL's det function32523253- ``'pari'`` - uses PARI32543255- ``proof`` - bool or None; if None use3256proof.linear_algebra(); only relevant for the padic algorithm.32573258.. note::32593260It would be *VERY VERY* hard for det to fail even with3261proof=False.32623263- ``stabilize`` - if proof is False, require det to be3264the same for this many CRT primes in a row. Ignored if proof is3265True.326632673268ALGORITHM: The p-adic algorithm works by first finding a random3269vector v, then solving A\*x = v and taking the denominator3270`d`. This gives a divisor of the determinant. Then we3271compute `\det(A)/d` using a multimodular algorithm and the3272Hadamard bound, skipping primes that divide `d`.32733274TIMINGS: This is perhaps the fastest implementation of determinants3275in the world. E.g., for a 500x500 random matrix with 32-bit entries3276on a core2 duo 2.6Ghz running OS X, Sage takes 4.12 seconds,3277whereas Magma takes 62.87 seconds (both with proof False). With3278proof=True on the same problem Sage takes 5.73 seconds. For another3279example, a 200x200 random matrix with 1-digit entries takes 4.183280seconds in pari, 0.18 in Sage with proof True, 0.11 in Sage with3281proof False, and 0.21 seconds in Magma with proof True and 0.18 in3282Magma with proof False.32833284EXAMPLES::32853286sage: A = matrix(ZZ,8,8,[3..66])3287sage: A.determinant()3288032893290::32913292sage: A = random_matrix(ZZ,20,20)3293sage: D1 = A.determinant()3294sage: A._clear_cache()3295sage: D2 = A.determinant(algorithm='ntl')3296sage: D1 == D23297True32983299We have a special-case algorithm for 4 x 4 determinants::33003301sage: A = matrix(ZZ,4,[1,2,3,4,4,3,2,1,0,5,0,1,9,1,2,3])3302sage: A.determinant()330327033043305Next we try the Linbox det. Note that we must have proof=False.33063307::33083309sage: 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])3310sage: A.determinant(algorithm='linbox')3311Traceback (most recent call last):3312...3313RuntimeError: you must pass the proof=False option to the determinant command to use LinBox's det algorithm3314sage: A.determinant(algorithm='linbox',proof=False)3315-213316sage: A._clear_cache()3317sage: A.determinant()3318-2133193320A bigger example::33213322sage: A = random_matrix(ZZ,30)3323sage: d = A.determinant()3324sage: A._clear_cache()3325sage: A.determinant(algorithm='linbox',proof=False) == d3326True33273328TESTS:33293330This shows that we can compute determinants for all sizes up to333180. The check that the determinant of a squared matrix is a3332square is a sanity check that the result is probably correct::33333334sage: for s in [1..80]: # long time (6s on sage.math, 2013)3335... M = random_matrix(ZZ, s)3336... d = (M*M).determinant()3337... assert d.is_square()3338"""3339d = self.fetch('det')3340if d is not None:3341return d3342if not self.is_square():3343raise ValueError("self must be a square matrix")33443345cdef Py_ssize_t n = self.nrows()33463347cdef Integer det4x43348if n <= 4:3349if n <= 3:3350# Use generic special cased code.3351return matrix_dense.Matrix_dense.determinant(self)3352else:3353det4x4 = ZZ(0)3354four_dim_det(det4x4.value, self._entries)3355return det4x433563357proof = get_proof_flag(proof, "linear_algebra")33583359cdef double difficulty3360if algorithm == 'default':3361# These heuristics are by Jeroen Demeyer (#14007). There3362# is no mathematics behind this, it was experimentally3363# observed to work well. I tried various estimates for3364# the "difficulty" of a matrix, and this one worked best.3365# I tested matrices with entries uniformly distributed in3366# [0,n] as well as random_matrix(ZZ,s).3367#3368# linbox works sometimes better for large matrices with3369# mostly small entries, but it is never much faster than3370# padic (and it only works with proof=False), so we never3371# default to using linbox.3372difficulty = (self._log_avg_sq1() + 2.0) * (n * n)3373if difficulty <= 800:3374algorithm = 'pari'3375elif n <= 48 or (proof and n <= 72) or (proof and n <= 400 and difficulty <= 600000):3376algorithm = 'ntl'3377else:3378algorithm = 'padic'33793380if algorithm == 'padic':3381import matrix_integer_dense_hnf3382d = matrix_integer_dense_hnf.det_padic(self, proof=proof, stabilize=stabilize)3383elif algorithm == 'linbox':3384if proof:3385raise RuntimeError("you must pass the proof=False option to the determinant command to use LinBox's det algorithm")3386d = self._det_linbox()3387elif algorithm == 'pari':3388d = self._det_pari()3389elif algorithm == 'ntl':3390d = self._det_ntl()3391else:3392raise TypeError("algorithm '%s' not known"%(algorithm))33933394self.cache('det', d)3395return d33963397def _det_linbox(self):3398"""3399Compute the determinant of this matrix using Linbox.3400"""3401self._init_linbox()3402sig_on()3403d = linbox.det()3404sig_off()3405return Integer(d)34063407def _det_ntl(self):3408"""3409Compute the determinant of this matrix using NTL.3410"""3411sig_on()3412d = self._ntl_().determinant()3413sig_off()3414return Integer(d)34153416#### Rational kernel, via IML3417def _rational_kernel_iml(self):3418"""3419IML: Return the rational kernel of this matrix (acting from the3420left), considered as a matrix over QQ. I.e., returns a matrix K3421such that self\*K = 0, and the number of columns of K equals the3422nullity of self.34233424AUTHORS:34253426- William Stein3427"""3428if self._nrows == 0 or self._ncols == 0:3429return self.matrix_space(self._ncols, 0).zero_matrix()34303431cdef long dim3432cdef mpz_t *mp_N3433time = verbose('computing null space of %s x %s matrix using IML'%(self._nrows, self._ncols))3434sig_on()3435dim = nullspaceMP (self._nrows, self._ncols, self._entries, &mp_N)3436sig_off()3437P = self.matrix_space(self._ncols, dim)34383439# Now read the answer as a matrix.3440cdef Matrix_integer_dense M3441M = Matrix_integer_dense.__new__(Matrix_integer_dense, P, None, None, None)3442for i from 0 <= i < dim*self._ncols:3443mpz_init_set(M._entries[i], mp_N[i])3444mpz_clear(mp_N[i])3445sage_free(mp_N)34463447verbose("finished computing null space", time)3448M._initialized = True3449return M34503451def _invert_iml(self, use_nullspace=False, check_invertible=True):3452"""3453Invert this matrix using IML. The output matrix is an integer3454matrix and a denominator.34553456INPUT:345734583459- ``self`` - an invertible matrix34603461- ``use_nullspace`` - (default: False): whether to3462use nullspace algorithm, which is slower, but doesn't require3463checking that the matrix is invertible as a precondition.34643465- ``check_invertible`` - (default: True) whether to3466check that the matrix is invertible.346734683469OUTPUT: A, d such that A\*self = d347034713472- ``A`` - a matrix over ZZ34733474- ``d`` - an integer347534763477ALGORITHM: Uses IML's p-adic nullspace function.34783479EXAMPLES::34803481sage: a = matrix(ZZ,3,[1,2,5, 3,7,8, 2,2,1])3482sage: b, d = a._invert_iml(); b,d3483(3484[ 9 -8 19]3485[-13 9 -7]3486[ 8 -2 -1], 233487)3488sage: a*b3489[23 0 0]3490[ 0 23 0]3491[ 0 0 23]34923493AUTHORS:34943495- William Stein3496"""3497if self._nrows != self._ncols:3498raise TypeError("self must be a square matrix.")34993500P = self.parent()3501time = verbose('computing inverse of %s x %s matrix using IML'%(self._nrows, self._ncols))3502if use_nullspace:3503A = self.augment(P.identity_matrix())3504K = A._rational_kernel_iml()3505d = -K[self._nrows,0]3506if K.ncols() != self._ncols or d == 0:3507raise ZeroDivisionError("input matrix must be nonsingular")3508B = K[:self._nrows]3509verbose("finished computing inverse using IML", time)3510return B, d3511else:3512if check_invertible and self.rank() != self._nrows:3513raise ZeroDivisionError("input matrix must be nonsingular")3514return self._solve_iml(P.identity_matrix(), right=True)35153516def _solve_right_nonsingular_square(self, B, check_rank=True):3517r"""3518If self is a matrix `A` of full rank, then this function3519returns a vector or matrix `X` such that `A X = B`.3520If `B` is a vector then `X` is a vector and if3521`B` is a matrix, then `X` is a matrix. The base3522ring of `X` is the integers unless a denominator is needed3523in which case the base ring is the rational numbers.35243525.. note::35263527In Sage one can also write ``A B`` for3528``A.solve_right(B)``, i.e., Sage implements the "the3529MATLAB/Octave backslash operator".35303531.. note::35323533This is currently only implemented when A is square.35343535INPUT:353635373538- ``B`` - a matrix or vector35393540- ``check_rank`` - bool (default: True); if True3541verify that in fact the rank is full.354235433544OUTPUT: a matrix or vector over `\QQ`35453546EXAMPLES::35473548sage: a = matrix(ZZ, 2, [0, -1, 1, 0])3549sage: v = vector(ZZ, [2, 3])3550sage: a \ v3551(3, -2)35523553Note that the output vector or matrix is always over3554`\QQ`.35553556::35573558sage: parent(a\v)3559Vector space of dimension 2 over Rational Field35603561We solve a bigger system where the answer is over the rationals.35623563::35643565sage: a = matrix(ZZ, 3, 3, [1,2,3,4, 5, 6, 8, -2, 3])3566sage: v = vector(ZZ, [1,2,3])3567sage: w = a \ v; w3568(2/15, -4/15, 7/15)3569sage: parent(w)3570Vector space of dimension 3 over Rational Field3571sage: a * w3572(1, 2, 3)35733574We solve a system where the right hand matrix has multiple3575columns.35763577::35783579sage: a = matrix(ZZ, 3, 3, [1,2,3,4, 5, 6, 8, -2, 3])3580sage: b = matrix(ZZ, 3, 2, [1,5, 2, -3, 3, 0])3581sage: w = a \ b; w3582[ 2/15 -19/5]3583[-4/15 -27/5]3584[ 7/15 98/15]3585sage: a * w3586[ 1 5]3587[ 2 -3]3588[ 3 0]35893590TESTS: We create a random 100x100 matrix and solve the3591corresponding system, then verify that the result is correct.3592(Note that this test is very risky without having a seeded3593random number generator!)35943595::35963597sage: n = 1003598sage: a = random_matrix(ZZ,n)3599sage: v = vector(ZZ,n,range(n))3600sage: x = a \ v3601sage: a * x == v3602True3603"""3604t = verbose('starting IML solve_right...')3605# It would probably be much better to rewrite linbox so it3606# throws an error instead of ** going into an infinite loop **3607# in the non-full rank case. In any case, we do this for now,3608# since rank is very fast and infinite loops are evil.3609if check_rank and self.rank() < self.nrows():3610raise ValueError("self must be of full rank.")36113612if not self.is_square():3613raise NotImplementedError("the input matrix must be square.")36143615if is_Vector(B):3616if self.nrows() != B.degree():3617raise ValueError("number of rows of self must equal degree of B.")3618elif self.nrows() != B.nrows():3619raise ValueError("number of rows of self must equal number of rows of B.")36203621if self.nrows() == 0:3622return B36233624matrix = True3625C = B3626if not isinstance(B, Matrix_integer_dense):3627if is_Vector(B):3628matrix = False3629C = self.matrix_space(self.nrows(), 1)(B.list())3630else:3631raise NotImplementedError36323633if C.ncols() >= 2*self.ncols():3634# likely much better to just invert then multiply3635X = self**(-1)*C3636verbose('finished solve_right (via inverse)', t)3637return X36383639X, d = self._solve_iml(C, right=True)3640if d != 1:3641X = (1/d) * X3642if not matrix:3643# Convert back to a vector3644X = (X.base_ring() ** X.nrows())(X.list())3645verbose('finished solve_right via IML', t)3646return X36473648def _solve_iml(self, Matrix_integer_dense B, right=True):3649"""3650Let A equal self be a square matrix. Given B return an integer3651matrix C and an integer d such that self C\*A == d\*B if right is3652False or A\*C == d\*B if right is True.36533654OUTPUT:365536563657- ``C`` - integer matrix36583659- ``d`` - integer denominator366036613662EXAMPLES::36633664sage: A = matrix(ZZ,4,4,[0, 1, -2, -1, -1, 1, 0, 2, 2, 2, 2, -1, 0, 2, 2, 1])3665sage: B = matrix(ZZ,3,4, [-1, 1, 1, 0, 2, 0, -2, -1, 0, -2, -2, -2])3666sage: C,d = A._solve_iml(B,right=False); C3667[ 6 -18 -15 27]3668[ 0 24 24 -36]3669[ 4 -12 -6 -2]36703671::36723673sage: d36741236753676::36773678sage: C*A == d*B3679True36803681::36823683sage: A = matrix(ZZ,4,4,[0, 1, -2, -1, -1, 1, 0, 2, 2, 2, 2, -1, 0, 2, 2, 1])3684sage: B = matrix(ZZ,4,3, [-1, 1, 1, 0, 2, 0, -2, -1, 0, -2, -2, -2])3685sage: C,d = A._solve_iml(B)3686sage: C3687[ 12 40 28]3688[-12 -4 -4]3689[ -6 -25 -16]3690[ 12 34 16]36913692::36933694sage: d36951236963697::36983699sage: A*C == d*B3700True37013702Test wrong dimensions::37033704sage: A = random_matrix(ZZ, 4, 4)3705sage: B = random_matrix(ZZ, 2, 3)3706sage: B._solve_iml(A)3707Traceback (most recent call last):3708...3709ValueError: self must be a square matrix3710sage: A._solve_iml(B, right=False)3711Traceback (most recent call last):3712...3713ArithmeticError: B's number of columns must match self's number of rows3714sage: A._solve_iml(B, right=True)3715Traceback (most recent call last):3716...3717ArithmeticError: B's number of rows must match self's number of columns37183719Check that this can be interrupted properly (:trac:`15453`)::37203721sage: A = random_matrix(ZZ, 2000, 2000)3722sage: B = random_matrix(ZZ, 2000, 2000)3723sage: t0 = walltime()3724sage: alarm(2); A._solve_iml(B) # long time3725Traceback (most recent call last):3726...3727AlarmInterrupt3728sage: t = walltime(t0)3729sage: t < 10 or t3730True37313732ALGORITHM: Uses IML.37333734AUTHORS:37353736- Martin Albrecht3737"""3738cdef int i3739cdef mpz_t *mp_N, mp_D3740cdef Matrix_integer_dense M3741cdef Integer D37423743if self._nrows != self._ncols:3744# This is *required* by the IML function we call below.3745raise ValueError("self must be a square matrix")37463747if self.nrows() == 1:3748return B, self[0,0]37493750cdef SOLU_POS solu_pos37513752if right:3753if self._ncols != B._nrows:3754raise ArithmeticError("B's number of rows must match self's number of columns")37553756n = self._ncols3757m = B._ncols37583759P = self.matrix_space(n, m)3760if self._nrows == 0 or self._ncols == 0:3761return P.zero_matrix(), Integer(1)37623763if m == 0 or n == 0:3764return self.new_matrix(nrows = n, ncols = m), Integer(1)37653766solu_pos = RightSolu37673768else: # left3769if self._nrows != B._ncols:3770raise ArithmeticError("B's number of columns must match self's number of rows")37713772n = self._ncols3773m = B._nrows37743775P = self.matrix_space(m, n)3776if self._nrows == 0 or self._ncols == 0:3777return P.zero_matrix(), Integer(1)37783779if m == 0 or n == 0:3780return self.new_matrix(nrows = m, ncols = n), Integer(1)37813782solu_pos = LeftSolu37833784sig_check()37853786mp_N = <mpz_t *> sage_malloc( n * m * sizeof(mpz_t) )3787for i from 0 <= i < n * m:3788mpz_init(mp_N[i])3789mpz_init(mp_D)37903791try:3792sig_on()3793nonsingSolvLlhsMM(solu_pos, n, m, self._entries, B._entries, mp_N, mp_D)3794sig_off()37953796M = Matrix_integer_dense.__new__(Matrix_integer_dense, P, None, None, None)3797for i from 0 <= i < n*m:3798mpz_init_set(M._entries[i], mp_N[i])3799M._initialized = True38003801D = PY_NEW(Integer)3802mpz_set(D.value, mp_D)38033804return M, D3805finally:3806mpz_clear(mp_D)3807for i from 0 <= i < n*m:3808mpz_clear(mp_N[i])3809sage_free(mp_N)38103811def _rational_echelon_via_solve(self):3812r"""3813Computes information that gives the reduced row echelon form (over3814QQ!) of a matrix with integer entries.38153816INPUT:381738183819- ``self`` - a matrix over the integers.382038213822OUTPUT:382338243825- ``pivots`` - ordered list of integers that give the3826pivot column positions38273828- ``nonpivots`` - ordered list of the nonpivot column3829positions38303831- ``X`` - matrix with integer entries38323833- ``d`` - integer383438353836If you put standard basis vectors in order at the pivot columns,3837and put the matrix (1/d)\*X everywhere else, then you get the3838reduced row echelon form of self, without zero rows at the bottom.38393840.. note::38413842IML is the actual underlying `p`-adic solver that we3843use.38443845AUTHORS:38463847- William Stein38483849ALGORITHM: I came up with this algorithm from scratch. As far as I3850know it is new. It's pretty simple, but it is ... (fast?!).38513852Let A be the input matrix.385338543855#. Compute r = rank(A).38563857#. Compute the pivot columns of the transpose `A^t` of3858`A`. One way to do this is to choose a random prime3859`p` and compute the row echelon form of `A^t`3860modulo `p` (if the number of pivot columns is not equal to3861`r`, pick another prime).38623863#. Let `B` be the submatrix of `A` consisting of3864the rows corresponding to the pivot columns found in the previous3865step. Note that, aside from zero rows at the bottom, `B`3866and `A` have the same reduced row echelon form.38673868#. Compute the pivot columns of `B`, again possibly by3869choosing a random prime `p` as in [2] and computing the3870Echelon form modulo `p`. If the number of pivot columns is3871not `r`, repeat with a different prime. Note - in this step3872it is possible that we mistakenly choose a bad prime `p`3873such that there are the right number of pivot columns modulo3874`p`, but they are at the wrong positions - e.g., imagine3875the augmented matrix `[pI|I]` - modulo `p` we would3876miss all the pivot columns. This is OK, since in the next step we3877would detect this, as the matrix we would obtain would not be in3878echelon form.38793880#. Let `C` be the submatrix of `B` of pivot3881columns. Let `D` be the complementary submatrix of3882`B` of all all non-pivot columns. Use a `p`-adic3883solver to find the matrix `X` and integer `d` such3884that `C (1/d) X=D`. I.e., solve a bunch of linear systems3885of the form `Cx = v`, where the columns of `X` are3886the solutions.38873888#. Verify that we had chosen the correct pivot columns. Inspect the3889matrix `X` obtained in step 5. If when used to construct3890the echelon form of `B`, `X` indeed gives a matrix3891in reduced row echelon form, then we are done - output the pivot3892columns, `X`, and `d`. To tell if `X` is3893correct, do the following: For each column of `X`3894(corresponding to non-pivot column `i` of `B`),3895read up the column of `X` until finding the first nonzero3896position `j`; then verify that `j` is strictly less3897than the number of pivot columns of `B` that are strictly3898less than `i`. Otherwise, we got the pivots of `B`3899wrong - try again starting at step 4, but with a different random3900prime.3901"""3902if self._nrows == 0:3903pivots = []3904nonpivots = range(self._ncols)3905X = self.__copy__()3906d = Integer(1)3907return pivots, nonpivots, X, d3908elif self._ncols == 0:3909pivots = []3910nonpivots = []3911X = self.__copy__()3912d = Integer(1)3913return pivots, nonpivots, X, d39143915from matrix_modn_dense_double import MAX_MODULUS3916A = self3917# Step 1: Compute the rank39183919t = verbose('computing rank', level=2, caller_name='p-adic echelon')3920r = A.rank()3921verbose('done computing rank', level=2, t=t, caller_name='p-adic echelon')39223923cdef randstate rstate = current_randstate()39243925if r == self._nrows:3926# The input matrix already has full rank.3927B = A3928else:3929# Steps 2 and 3: Extract out a submatrix of full rank.3930i = 03931while True:3932p = previous_prime(rstate.c_random() % (MAX_MODULUS-15000) + 10000)3933P = A._mod_int(p).transpose().pivots()3934if len(P) == r:3935B = A.matrix_from_rows(P)3936break3937else:3938i += 13939if i == 50:3940raise RuntimeError("Bug in _rational_echelon_via_solve in finding linearly independent rows.")39413942_i = 03943while True:3944_i += 13945if _i == 50:3946raise RuntimeError("Bug in _rational_echelon_via_solve -- pivot columns keep being wrong.")39473948# Step 4: Now we instead worry about computing the reduced row echelon form of B.3949i = 03950while True:3951p = previous_prime(rstate.c_random() % (MAX_MODULUS-15000) + 10000)3952pivots = B._mod_int(p).pivots()3953if len(pivots) == r:3954break3955else:3956i += 13957if i == 50:3958raise RuntimeError("Bug in _rational_echelon_via_solve in finding pivot columns.")39593960# Step 5: Apply p-adic solver3961C = B.matrix_from_columns(pivots)3962pivots_ = set(pivots)3963non_pivots = [i for i in range(B.ncols()) if not i in pivots_]3964D = B.matrix_from_columns(non_pivots)3965t = verbose('calling IML solver', level=2, caller_name='p-adic echelon')3966X, d = C._solve_iml(D, right=True)3967t = verbose('finished IML solver', level=2, caller_name='p-adic echelon', t=t)39683969# Step 6: Verify that we had chosen the correct pivot columns.3970pivots_are_right = True3971for z in range(X.ncols()):3972if not pivots_are_right:3973break3974i = non_pivots[z]3975np = len([k for k in pivots if k < i])3976for j in reversed(range(X.nrows())):3977if X[j,z] != 0:3978if j < np:3979break # we're good -- go on to next column of X3980else:3981pivots_are_right = False3982break3983if pivots_are_right:3984break39853986#end while398739883989# Finally, return the answer.3990return pivots, non_pivots, X, d39913992def decomposition(self, **kwds):3993"""3994Returns the decomposition of the free module on which this matrix A3995acts from the right (i.e., the action is x goes to x A), along with3996whether this matrix acts irreducibly on each factor. The factors3997are guaranteed to be sorted in the same way as the corresponding3998factors of the characteristic polynomial, and are saturated as ZZ3999modules.40004001INPUT:400240034004- ``self`` - a matrix over the integers40054006- ``**kwds`` - these are passed onto to the4007decomposition over QQ command.400840094010EXAMPLES::40114012sage: t = ModularSymbols(11,sign=1).hecke_matrix(2)4013sage: w = t.change_ring(ZZ)4014sage: w.list()4015[3, -1, 0, -2]4016"""4017F = self.charpoly().factor()4018if len(F) == 1:4019V = self.base_ring()**self.nrows()4020return decomp_seq([(V, F[0][1]==1)])40214022A = self.change_ring(QQ)4023X = A.decomposition(**kwds)4024V = ZZ**self.nrows()4025if isinstance(X, tuple):4026D, E = X4027D = [(W.intersection(V), t) for W, t in D]4028E = [(W.intersection(V), t) for W, t in E]4029return decomp_seq(D), decomp_seq(E)4030else:4031return decomp_seq([(W.intersection(V), t) for W, t in X])40324033def _add_row_and_maintain_echelon_form(self, row, pivots):4034"""4035Assuming self is a full rank n x m matrix in reduced row Echelon4036form over ZZ and row is a vector of degree m, this function creates4037a new matrix that is the echelon form of self with row appended to4038the bottom.40394040.. warning::40414042It is assumed that self is in echelon form.40434044INPUT:404540464047- ``row`` - a vector of degree m over ZZ40484049- ``pivots`` - a list of integers that are the pivot4050columns of self.405140524053OUTPUT:405440554056- ``matrix`` - a matrix of in reduced row echelon form4057over ZZ40584059- ``pivots`` - list of integers406040614062ALGORITHM: For each pivot column of self, we use the extended4063Euclidean algorithm to clear the column. The result is a new matrix4064B whose row span is the same as self.stack(row), and whose last row4065is 0 if and only if row is in the QQ-span of the rows of self. If4066row is not in the QQ-span of the rows of self, then row is nonzero4067and suitable to be inserted into the top n rows of A to form a new4068matrix that is in reduced row echelon form. We then clear that4069corresponding new pivot column.40704071EXAMPLES::40724073sage: a = matrix(ZZ, 3, [1, 0, 110, 0, 3, 112, 0, 0, 221]); a4074[ 1 0 110]4075[ 0 3 112]4076[ 0 0 221]4077sage: a._add_row_and_maintain_echelon_form(vector(ZZ,[1,2,3]),[0,1,2])4078(4079[1 0 0]4080[0 1 0]4081[0 0 1], [0, 1, 2]4082)4083sage: a._add_row_and_maintain_echelon_form(vector(ZZ,[0,0,0]),[0,1,2])4084(4085[ 1 0 110]4086[ 0 3 112]4087[ 0 0 221], [0, 1, 2]4088)4089sage: a = matrix(ZZ, 2, [1, 0, 110, 0, 3, 112])4090sage: a._add_row_and_maintain_echelon_form(vector(ZZ,[1,2,3]),[0,1])4091(4092[ 1 0 110]4093[ 0 1 219]4094[ 0 0 545], [0, 1, 2]4095)4096"""4097from sage.all import get_memory_usage4098cdef Py_ssize_t i, j, piv, n = self._nrows, m = self._ncols40994100import constructor41014102# 0. Base case4103if self.nrows() == 0:4104pos = row.nonzero_positions()4105if len(pos) > 0:4106pivots = [pos[0]]4107if row[pivots[0]] < 0:4108row *= -14109else:4110pivots = []4111return constructor.matrix([row]), pivots411241134114if row == 0:4115return self, pivots4116# 1. Create a new matrix that has row as the last row.4117row_mat = constructor.matrix(row)4118A = self.stack(row_mat)4119# 2. Working from the left, clear each column to put4120# the resulting matrix back in echelon form.4121for i, p in enumerate(pivots):4122# p is the i-th pivot4123b = A[n,p]4124if not b:4125continue41264127# (a). Take xgcd of pivot positions in last row and in ith4128# row.41294130# TODO (optimize) -- change to use direct call to gmp and4131# no bounds checking!4132a = A[i,p]4133if not a:4134raise ZeroDivisionError("claimed pivot is not a pivot")4135if b % a == 0:4136# (b) Subtract a multiple of row i from row n.4137c = b // a4138if c:4139for j in range(m):4140A[n,j] -= c * A[i,j]4141else:4142# (b). More elaborate.4143# Replace the ith row by s*A[i] + t*A[n], which will4144# have g in the i,p position, and replace the last row by4145# (b//g)*A[i] - (a//g)*A[n], which will have 0 in the i,p4146# position.4147g, s, t = a.xgcd(b)4148if not g:4149raise ZeroDivisionError("claimed pivot is not a pivot (got a 0 gcd)")41504151row_i = A.row(i)4152row_n = A.row(n)41534154ag = a//g; bg = b//g41554156new_top = s*row_i + t*row_n4157new_bot = bg*row_i - ag*row_n415841594160# OK -- now we have to make sure the top part of the matrix4161# but with row i replaced by4162# r = s*row_i[j] + t*row_n[j]4163# is put in rref. We do this by recursively calling this4164# function with the top part of A (all but last row) and the4165# row r.41664167zz = range(A.nrows()-1)4168del zz[i]4169top_mat = A.matrix_from_rows(zz)4170new_pivots = list(pivots)4171del new_pivots[i]41724173top_mat, pivots = top_mat._add_row_and_maintain_echelon_form(new_top, new_pivots)4174w = top_mat._add_row_and_maintain_echelon_form(new_bot, pivots)4175return w4176# 3. If it turns out that the last row is nonzero,4177# insert last row in A sliding other rows down.4178v = A.row(n)4179new_pivots = list(pivots)4180if v != 0:4181i = v.nonzero_positions()[0]4182assert not (i in pivots), 'WARNING: bug in add_row -- i (=%s) should not be a pivot'%i41834184# If pivot entry is negative negate this row.4185if v[i] < 0:4186v = -v41874188# Determine where the last row should be inserted.4189new_pivots.append(i)4190new_pivots.sort()4191import bisect4192j = bisect.bisect(pivots, i)4193# The new row should go *before* row j, so it becomes row j4194A = A.insert_row(j, v)4195try:4196_clear_columns(A, new_pivots, A.nrows())4197except RuntimeError:4198raise ZeroDivisionError("mistake in claimed pivots")4199if A.row(A.nrows() - 1) == 0:4200A = A.matrix_from_rows(range(A.nrows()-1))4201return A, new_pivots42024203#####################################################################################4204# Hermite form modulo D4205# This code below is by E. Burcin. Thanks!4206#####################################################################################4207cdef _new_uninitialized_matrix(self, Py_ssize_t nrows, Py_ssize_t ncols):4208"""4209Return a new matrix over the integers with the given number of rows4210and columns. All memory is allocated for this matrix, but its4211entries have not yet been filled in.4212"""4213P = self._parent.matrix_space(nrows, ncols)4214return Matrix_integer_dense.__new__(Matrix_integer_dense, P, None, None, None)42154216def _hnf_mod(self, D):4217"""4218INPUT:421942204221- ``D`` - a small integer that is assumed to be a4222multiple of 2\*det(self)422342244225OUTPUT:422642274228- ``matrix`` - the Hermite normal form of self.4229"""4230t = verbose('hermite mod %s'%D, caller_name='matrix_integer_dense')4231cdef Matrix_integer_dense res = self._new_uninitialized_matrix(self._nrows, self._ncols)4232self._hnf_modn(res, D)4233verbose('finished hnf mod', t, caller_name='matrix_integer_dense')4234return res42354236cdef int _hnf_modn(Matrix_integer_dense self, Matrix_integer_dense res,4237mod_int det) except -1:4238"""4239Puts self into HNT form modulo det. Changes self in place.4240"""4241cdef long long *res_l4242cdef Py_ssize_t i,j,k4243res_l = self._hnf_modn_impl(det, self._nrows, self._ncols)4244k = 04245for i from 0 <= i < self._nrows:4246for j from 0 <= j < self._ncols:4247mpz_init_set_si(res._matrix[i][j], res_l[k])4248k += 14249res._initialized = True4250sage_free(res_l)425142524253cdef long long* _hnf_modn_impl(Matrix_integer_dense self, mod_int det,4254Py_ssize_t nrows, Py_ssize_t ncols) except NULL:4255cdef long long *res, *T_ent, **res_rows, **T_rows, *B4256cdef Py_ssize_t i, j, k4257cdef long long R, mod, T_i_i, T_j_i, c1, c2, q, t4258cdef int u, v, d4259cdef mpz_t m42604261# allocate memory for result matrix4262res = <long long*> sage_malloc(sizeof(long long)*ncols*nrows)4263if res == NULL:4264raise MemoryError("out of memory allocating a matrix")4265res_rows = <long long**> sage_malloc(sizeof(long long*)*nrows)4266if res_rows == NULL:4267sage_free(res)4268raise MemoryError("out of memory allocating a matrix")42694270# allocate memory for temporary matrix4271T_ent = <long long*> sage_malloc(sizeof(long long)*ncols*nrows)4272if T_ent == NULL:4273sage_free(res)4274sage_free(res_rows)4275raise MemoryError("out of memory allocating a matrix")4276T_rows = <long long**> sage_malloc(sizeof(long long*)*nrows)4277if T_rows == NULL:4278sage_free(res)4279sage_free(res_rows)4280sage_free(T_ent)4281raise MemoryError("out of memory allocating a matrix")42824283# allocate memory for temporary row vector4284B = <long long*>sage_malloc(sizeof(long long)*nrows)4285if B == NULL:4286sage_free(res)4287sage_free(res_rows)4288sage_free(T_ent)4289sage_free(T_rows)4290raise MemoryError("out of memory allocating a matrix")42914292# initialize the row pointers4293k = 04294for i from 0 <= i < nrows:4295res_rows[i] = res + k4296T_rows[i] = T_ent + k4297k += nrows429842994300mpz_init(m)4301# copy entries from self to temporary matrix4302k = 04303for i from 0 <= i < nrows:4304for j from 0 <= j < ncols:4305mpz_mod_ui(m, self._matrix[i][j], det)4306T_ent[k] = mpz_get_si(m)4307k += 14308mpz_clear(m)430943104311# initialize variables4312i = 04313j = 04314R = det43154316while 1:4317if j == nrows-1:4318T_i_i = T_rows[i][i]4319d = ai.c_xgcd_int(T_i_i, R, &u, &v)4320for k from 0 <= k < i:4321res_rows[i][k] = 04322for k from i <= k < ncols:4323t = (u*T_rows[i][k])%R4324if t < 0:4325t += R4326res_rows[i][k] = t4327if res_rows[i][i] == 0:4328res_rows[i][i] = R4329d = res_rows[i][i]4330for j from 0 <= j < i:4331q = res_rows[j][i]/d4332for k from i <= k < ncols:4333u = (res_rows[j][k] - q*res_rows[i][k])%R4334if u < 0:4335u += R4336res_rows[j][k] = u43374338R = R/d4339i += 14340j = i4341if i == nrows :4342break # return res4343if T_rows[i][i] == 0:4344T_rows[i][i] = R4345continue434643474348j += 14349if T_rows[j][i] == 0:4350continue43514352T_i_i = T_rows[i][i]4353T_j_i = T_rows[j][i]4354d = ai.c_xgcd_int(T_i_i , T_j_i, &u, &v)4355if d != T_i_i:4356for k from i <= k < ncols:4357B[k] = (u*T_rows[i][k] + v*T_rows[j][k])4358c1 = T_i_i/d4359c2 = -T_j_i/d4360for k from i <= k < ncols:4361T_rows[j][k] = (c1*T_rows[j][k] + c2*T_rows[i][k])%R4362if d != T_i_i:4363for k from i <= k < ncols:4364T_rows[i][k] = B[k]%R43654366sage_free(B)4367sage_free(res_rows)4368sage_free(T_ent)4369sage_free(T_rows)4370return res437143724373#####################################################################################4374# operations with matrices4375#####################################################################################4376def stack(self, bottom, subdivide=False):4377r"""4378Return the matrix self on top of bottom: [ self ] [ bottom ]43794380EXAMPLES::43814382sage: M = Matrix(ZZ, 2, 3, range(6))4383sage: N = Matrix(ZZ, 1, 3, [10,11,12])4384sage: M.stack(N)4385[ 0 1 2]4386[ 3 4 5]4387[10 11 12]43884389A vector may be stacked below a matrix. ::43904391sage: A = matrix(ZZ, 2, 4, range(8))4392sage: v = vector(ZZ, 4, range(4))4393sage: A.stack(v)4394[0 1 2 3]4395[4 5 6 7]4396[0 1 2 3]43974398The ``subdivide`` option will add a natural subdivision between4399``self`` and ``bottom``. For more details about how subdivisions4400are managed when stacking, see4401:meth:`sage.matrix.matrix1.Matrix.stack`. ::44024403sage: A = matrix(ZZ, 3, 4, range(12))4404sage: B = matrix(ZZ, 2, 4, range(8))4405sage: A.stack(B, subdivide=True)4406[ 0 1 2 3]4407[ 4 5 6 7]4408[ 8 9 10 11]4409[-----------]4410[ 0 1 2 3]4411[ 4 5 6 7]44124413TESTS:44144415Stacking a dense matrix atop a sparse one should work::44164417sage: M = Matrix(ZZ, 2, 3, range(6))4418sage: M.is_sparse()4419False4420sage: N = diagonal_matrix([10,11,12], sparse=True)4421sage: N.is_sparse()4422True4423sage: P = M.stack(N); P4424[ 0 1 2]4425[ 3 4 5]4426[10 0 0]4427[ 0 11 0]4428[ 0 0 12]4429sage: P.is_sparse()4430False4431"""4432if hasattr(bottom, '_vector_'):4433bottom = bottom.row()4434if self._ncols != bottom.ncols():4435raise TypeError("number of columns must be the same")4436if not (self._base_ring is bottom.base_ring()):4437bottom = bottom.change_ring(self._base_ring)4438cdef Matrix_integer_dense other = bottom.dense_matrix()4439cdef Matrix_integer_dense M4440M = self.new_matrix(nrows = self._nrows + other._nrows, ncols = self.ncols())4441cdef Py_ssize_t i, k4442k = self._nrows * self._ncols4443for i from 0 <= i < k:4444mpz_set(M._entries[i], self._entries[i])4445for i from 0 <= i < other._nrows * other._ncols:4446mpz_set(M._entries[k + i], other._entries[i])4447if subdivide:4448M._subdivide_on_stack(self, other)4449return M44504451def augment(self, right, subdivide=False):4452r"""4453Returns a new matrix formed by appending the matrix4454(or vector) ``right`` on the right side of ``self``.44554456INPUT:44574458- ``right`` - a matrix, vector or free module element, whose4459dimensions are compatible with ``self``.44604461- ``subdivide`` - default: ``False`` - request the resulting4462matrix to have a new subdivision, separating ``self`` from ``right``.44634464OUTPUT:44654466A new matrix formed by appending ``right`` onto the right side of ``self``.4467If ``right`` is a vector (or free module element) then in this context4468it is appropriate to consider it as a column vector. (The code first4469converts a vector to a 1-column matrix.)44704471EXAMPLES::44724473sage: A = matrix(ZZ, 4, 5, range(20))4474sage: B = matrix(ZZ, 4, 3, range(12))4475sage: A.augment(B)4476[ 0 1 2 3 4 0 1 2]4477[ 5 6 7 8 9 3 4 5]4478[10 11 12 13 14 6 7 8]4479[15 16 17 18 19 9 10 11]44804481A vector may be augmented to a matrix. ::44824483sage: A = matrix(ZZ, 3, 5, range(15))4484sage: v = vector(ZZ, 3, range(3))4485sage: A.augment(v)4486[ 0 1 2 3 4 0]4487[ 5 6 7 8 9 1]4488[10 11 12 13 14 2]44894490The ``subdivide`` option will add a natural subdivision between4491``self`` and ``right``. For more details about how subdivisions4492are managed when augmenting, see4493:meth:`sage.matrix.matrix1.Matrix.augment`. ::44944495sage: A = matrix(ZZ, 3, 5, range(15))4496sage: B = matrix(ZZ, 3, 3, range(9))4497sage: A.augment(B, subdivide=True)4498[ 0 1 2 3 4| 0 1 2]4499[ 5 6 7 8 9| 3 4 5]4500[10 11 12 13 14| 6 7 8]45014502Errors are raised if the sizes are incompatible. ::45034504sage: A = matrix(ZZ, [[1, 2],[3, 4]])4505sage: B = matrix(ZZ, [[10, 20], [30, 40], [50, 60]])4506sage: A.augment(B)4507Traceback (most recent call last):4508...4509TypeError: number of rows must be the same, not 2 != 34510"""4511if hasattr(right, '_vector_'):4512right = right.column()4513if self._nrows != right.nrows():4514raise TypeError('number of rows must be the same, not {0} != {1}'.format(self._nrows, right.nrows()))4515if not (self._base_ring is right.base_ring()):4516right = right.change_ring(self._base_ring)45174518cdef Matrix_integer_dense other = right.dense_matrix()4519m = self._nrows4520ns, na = self._ncols, other._ncols4521n = ns + na45224523cdef Matrix_integer_dense Z4524Z = self.new_matrix(nrows = m, ncols = n)4525cdef Py_ssize_t i, j, p, qs, qa4526p, qs, qa = 0, 0, 04527for i from 0 <= i < m:4528for j from 0 <= j < ns:4529mpz_set(Z._entries[p], self._entries[qs])4530p = p + 14531qs = qs + 14532for j from 0 <= j < na:4533mpz_set(Z._entries[p], other._entries[qa])4534p = p + 14535qa = qa + 14536if subdivide:4537Z._subdivide_on_augment(self, other)4538return Z45394540def insert_row(self, Py_ssize_t index, row):4541"""4542Create a new matrix from self with.45434544INPUT:45454546- ``index`` - integer45474548- ``row`` - a vector45494550EXAMPLES::45514552sage: X = matrix(ZZ,3,range(9)); X4553[0 1 2]4554[3 4 5]4555[6 7 8]4556sage: X.insert_row(1, [1,5,-10])4557[ 0 1 2]4558[ 1 5 -10]4559[ 3 4 5]4560[ 6 7 8]4561sage: X.insert_row(0, [1,5,-10])4562[ 1 5 -10]4563[ 0 1 2]4564[ 3 4 5]4565[ 6 7 8]4566sage: X.insert_row(3, [1,5,-10])4567[ 0 1 2]4568[ 3 4 5]4569[ 6 7 8]4570[ 1 5 -10]4571"""4572cdef Matrix_integer_dense res = self._new_uninitialized_matrix(self._nrows + 1, self._ncols)4573cdef Py_ssize_t j, k4574cdef Integer z4575if index < 0:4576raise ValueError("index must be nonnegative")4577if index > self._nrows:4578raise ValueError("index must be less than number of rows")4579for j from 0 <= j < self._ncols * index:4580mpz_init_set(res._entries[j], self._entries[j])45814582k = 04583for j from self._ncols * index <= j < self._ncols * (index+1):4584z = row[k]4585mpz_init_set(res._entries[j], z.value)4586k += 145874588for j from self._ncols * (index+1) <= j < (self._nrows + 1)*self._ncols:4589mpz_init_set(res._entries[j], self._entries[j - self._ncols])45904591res._initialized = True4592return res45934594def _delete_zero_columns(self):4595"""4596Return matrix obtained from self by deleting all zero columns along4597with the positions of those columns.45984599OUTPUT: matrix list of integers46004601EXAMPLES::46024603sage: a = matrix(ZZ, 2,3, [1,0,3,-1,0,5]); a4604[ 1 0 3]4605[-1 0 5]4606sage: a._delete_zero_columns()4607(4608[ 1 3]4609[-1 5], [1]4610)4611"""4612C = self.columns()4613zero_cols = [i for i,v in enumerate(self.columns()) if v.is_zero()]4614s = set(zero_cols)4615nonzero_cols = [i for i in range(self.ncols()) if not (i in s)]4616return self.matrix_from_columns(nonzero_cols), zero_cols46174618def _insert_zero_columns(self, cols):4619"""4620Return matrix obtained by self by inserting zero columns so that4621the columns with positions specified in cols are all 0.46224623INPUT:46244625- ``cols`` - list of nonnegative integers46264627OUTPUT: matrix46284629EXAMPLES::46304631sage: a = matrix(ZZ, 2,3, [1,0,3,-1,0,5]); a4632[ 1 0 3]4633[-1 0 5]4634sage: b, cols = a._delete_zero_columns()4635sage: b4636[ 1 3]4637[-1 5]4638sage: cols4639[1]4640sage: b._insert_zero_columns(cols)4641[ 1 0 3]4642[-1 0 5]4643"""4644if len(cols) == 0:4645return self4646cdef Py_ssize_t i, c, r, nc = max(self._ncols + len(cols), max(cols)+1)4647cdef Matrix_integer_dense A = self.new_matrix(self._nrows, nc)4648# Now fill in the entries of A that come from self.4649cols_set = set(cols)4650cols_ins = [j for j in range(nc) if j not in cols_set]4651for r from 0 <= r < self._nrows:4652i = 04653for c in cols_ins:4654# The following does this quickly: A[r,c] = self[r,i]4655mpz_set(A._matrix[r][c], self._matrix[r][i])4656i += 14657return A46584659def _factor_out_common_factors_from_each_row(self):4660"""4661Very very quickly modifies self so that the gcd of the entries in4662each row is 1 by dividing each row by the common gcd.46634664EXAMPLES::46654666sage: a = matrix(ZZ, 3, [-9, 3, -3, -36, 18, -5, -40, -5, -5, -20, -45, 15, 30, -15, 180])4667sage: a4668[ -9 3 -3 -36 18]4669[ -5 -40 -5 -5 -20]4670[-45 15 30 -15 180]4671sage: a._factor_out_common_factors_from_each_row()4672sage: a4673[ -3 1 -1 -12 6]4674[ -1 -8 -1 -1 -4]4675[ -3 1 2 -1 12]4676"""4677self.check_mutability()46784679cdef mpz_t g4680mpz_init(g)4681cdef Py_ssize_t i, j4682cdef mpz_t* row46834684for i from 0 <= i < self._nrows:4685mpz_set_ui(g, 0)4686row = self._matrix[i]4687for j from 0 <= j < self._ncols:4688mpz_gcd(g, g, row[j])4689if mpz_cmp_ui(g, 1) == 0:4690break4691if mpz_cmp_ui(g, 1) != 0:4692# divide through row4693for j from 0 <= j < self._ncols:4694mpz_divexact(row[j], row[j], g)4695mpz_clear(g)46964697def gcd(self):4698"""4699Return the gcd of all entries of self; very fast.47004701EXAMPLES::47024703sage: a = matrix(ZZ,2, [6,15,-6,150])4704sage: a.gcd()470534706"""4707cdef Integer g = Integer(0)4708cdef Py_ssize_t i, j4709cdef mpz_t* row47104711for i from 0 <= i < self._nrows:4712row = self._matrix[i]4713for j from 0 <= j < self._ncols:4714mpz_gcd(g.value, g.value, row[j])4715if mpz_cmp_ui(g.value, 1) == 0:4716return g4717return g47184719def _change_ring(self, ring):4720"""4721Return the matrix obtained by coercing the entries of this matrix4722into the given ring.47234724EXAMPLES::47254726sage: a = matrix(ZZ,2,[1,-7,3,5])4727sage: a._change_ring(RDF)4728[ 1.0 -7.0]4729[ 3.0 5.0]4730"""4731if ring == RDF:4732import change_ring4733return change_ring.integer_to_real_double_dense(self)4734else:4735raise NotImplementedError47364737def _singular_(self, singular=None):4738r"""4739Return Singular representation of this integer matrix.47404741INPUT:474247434744- ``singular`` - Singular interface instance (default:4745None)474647474748EXAMPLE::47494750sage: A = random_matrix(ZZ,3,3)4751sage: As = singular(A); As4752-8 2 047530 1 -147542 1 -954755sage: As.type()4756'intmat'4757"""4758if singular is None:4759from sage.interfaces.singular import singular as singular_default4760singular = singular_default47614762name = singular._next_var_name()4763values = str(self.list())[1:-1]4764singular.eval("intmat %s[%d][%d] = %s"%(name, self.nrows(), self.ncols(), values))47654766from sage.interfaces.singular import SingularElement4767return SingularElement(singular, 'foobar', name, True)47684769def transpose(self):4770"""4771Returns the transpose of self, without changing self.47724773EXAMPLES:47744775We create a matrix, compute its transpose, and note that the4776original matrix is not changed.47774778::47794780sage: A = matrix(ZZ,2,3,xrange(6))4781sage: type(A)4782<type 'sage.matrix.matrix_integer_dense.Matrix_integer_dense'>4783sage: B = A.transpose()4784sage: print B4785[0 3]4786[1 4]4787[2 5]4788sage: print A4789[0 1 2]4790[3 4 5]47914792``.T`` is a convenient shortcut for the transpose::47934794sage: A.T4795[0 3]4796[1 4]4797[2 5]47984799::48004801sage: A.subdivide(None, 1); A4802[0|1 2]4803[3|4 5]4804sage: A.transpose()4805[0 3]4806[---]4807[1 4]4808[2 5]4809"""4810cdef Matrix_integer_dense A4811A = Matrix_integer_dense.__new__(Matrix_integer_dense,4812self._parent.matrix_space(self._ncols,self._nrows),48130,False,False)4814cdef Py_ssize_t i,j4815sig_on()4816for i from 0 <= i < self._nrows:4817for j from 0 <= j < self._ncols:4818mpz_init_set(A._matrix[j][i], self._matrix[i][j])4819sig_off()4820A._initialized = True4821if self._subdivisions is not None:4822row_divs, col_divs = self.subdivisions()4823A.subdivide(col_divs, row_divs)4824return A48254826def antitranspose(self):4827"""4828Returns the antitranspose of self, without changing self.48294830EXAMPLES::48314832sage: A = matrix(2,3,range(6))4833sage: type(A)4834<type 'sage.matrix.matrix_integer_dense.Matrix_integer_dense'>4835sage: A.antitranspose()4836[5 2]4837[4 1]4838[3 0]4839sage: A4840[0 1 2]4841[3 4 5]48424843sage: A.subdivide(1,2); A4844[0 1|2]4845[---+-]4846[3 4|5]4847sage: A.antitranspose()4848[5|2]4849[-+-]4850[4|1]4851[3|0]4852"""4853nr , nc = (self._nrows, self._ncols)48544855cdef Matrix_integer_dense A4856A = Matrix_integer_dense.__new__(Matrix_integer_dense,4857self._parent.matrix_space(nc,nr),48580,False,False)48594860cdef Py_ssize_t i,j4861cdef Py_ssize_t ri,rj # reversed i and j4862sig_on()4863ri = nr4864for i from 0 <= i < nr:4865rj = nc4866ri = ri-14867for j from 0 <= j < nc:4868rj = rj-14869mpz_init_set(A._matrix[rj][ri], self._matrix[i][j])4870sig_off()4871A._initialized = True48724873if self._subdivisions is not None:4874row_divs, col_divs = self.subdivisions()4875A.subdivide([nc - t for t in reversed(col_divs)],4876[nr - t for t in reversed(row_divs)])4877return A48784879def _pari_(self):4880"""4881Return PARI C-library version of this matrix.48824883EXAMPLES::48844885sage: a = matrix(ZZ,2,2,[1,2,3,4])4886sage: a._pari_()4887[1, 2; 3, 4]4888sage: pari(a)4889[1, 2; 3, 4]4890sage: type(pari(a))4891<type 'sage.libs.pari.gen.gen'>4892"""4893return pari.integer_matrix(self._matrix, self._nrows, self._ncols, 0)48944895def _det_pari(self, int flag=0):4896"""4897Determinant of this matrix using Gauss-Bareiss. If (optional)4898flag is set to 1, use classical Gaussian elimination.48994900For efficiency purposes, this det is computed entirely on the4901PARI stack then the PARI stack is cleared. This function is4902most useful for very small matrices.49034904EXAMPLES::49054906sage: matrix(ZZ,3,[1..9])._det_pari()490704908sage: matrix(ZZ,3,[1..9])._det_pari(1)490904910"""4911pari_catch_sig_on()4912cdef GEN d = det0(pari_GEN(self), flag)4913# now convert d to a Sage integer e4914cdef Integer e = Integer()4915t_INT_to_ZZ(e.value, d)4916pari.clear_stack()4917return e49184919def _rank_pari(self):4920"""4921Rank of this matrix, computed using PARI. The computation is4922done entirely on the PARI stack, then the PARI stack is4923cleared. This function is most useful for very small4924matrices.49254926EXAMPLES::4927sage: matrix(ZZ,3,[1..9])._rank_pari()492824929"""4930pari_catch_sig_on()4931cdef long r = rank(pari_GEN(self))4932pari.clear_stack()4933return r49344935def _hnf_pari(self, int flag=0, bint include_zero_rows=True):4936"""4937Hermite form of this matrix, computed using PARI. The4938computation is done entirely on the PARI stack, then the PARI4939stack is cleared. This function is only useful for small4940matrices, and can crash on large matrices (e.g., if the PARI4941stack overflows).49424943INPUT:49444945- ``flag`` -- 0 (default), 1, 3 or 4 (see docstring for4946gp.mathnf).49474948- ``include_zero_rows`` -- boolean. if False, do not include4949any of the zero rows at the bottom of the matrix in the4950output.49514952.. NOTE::49534954In no cases is the transformation matrix returned by this4955function.49564957EXAMPLES::49584959sage: matrix(ZZ,3,[1..9])._hnf_pari()4960[1 2 3]4961[0 3 6]4962[0 0 0]4963sage: matrix(ZZ,3,[1..9])._hnf_pari(1)4964[1 2 3]4965[0 3 6]4966[0 0 0]4967sage: matrix(ZZ,3,[1..9])._hnf_pari(3)4968[1 2 3]4969[0 3 6]4970[0 0 0]4971sage: matrix(ZZ,3,[1..9])._hnf_pari(4)4972[1 2 3]4973[0 3 6]4974[0 0 0]49754976Check that ``include_zero_rows=False`` works correctly::49774978sage: matrix(ZZ,3,[1..9])._hnf_pari(0, include_zero_rows=False)4979[1 2 3]4980[0 3 6]4981sage: matrix(ZZ,3,[1..9])._hnf_pari(1, include_zero_rows=False)4982[1 2 3]4983[0 3 6]4984sage: matrix(ZZ,3,[1..9])._hnf_pari(3, include_zero_rows=False)4985[1 2 3]4986[0 3 6]4987sage: matrix(ZZ,3,[1..9])._hnf_pari(4, include_zero_rows=False)4988[1 2 3]4989[0 3 6]49904991Check that :trac:`12346` is fixed::49924993sage: pari('mathnf(Mat([0,1]), 4)')4994[Mat(1), [1, 0; 0, 1]]4995"""4996cdef GEN A4997pari_catch_sig_on()4998A = pari._new_GEN_from_mpz_t_matrix_rotate90(self._matrix, self._nrows, self._ncols)4999cdef GEN H = mathnf0(A, flag)5000B = self.extract_hnf_from_pari_matrix(H, flag, include_zero_rows)5001pari.clear_stack() # This calls pari_catch_sig_off()5002return B500350045005def _hnf_pari_big(self, int flag=0, bint include_zero_rows=True):5006"""5007Hermite form of this matrix, computed using PARI.50085009INPUT:50105011- ``flag`` -- 0 (default), 1, 3 or 4 (see docstring for5012gp.mathnf).50135014- ``include_zero_rows`` -- boolean. if False, do not include5015any of the zero rows at the bottom of the matrix in the5016output.50175018.. NOTE::50195020In no cases is the transformation matrix returned by this5021function.50225023EXAMPLES::50245025sage: a = matrix(ZZ,3,3,[1..9])5026sage: a._hnf_pari_big(flag=0, include_zero_rows=True)5027[1 2 3]5028[0 3 6]5029[0 0 0]5030sage: a._hnf_pari_big(flag=1, include_zero_rows=True)5031[1 2 3]5032[0 3 6]5033[0 0 0]5034sage: a._hnf_pari_big(flag=3, include_zero_rows=True)5035[1 2 3]5036[0 3 6]5037[0 0 0]5038sage: a._hnf_pari_big(flag=4, include_zero_rows=True)5039[1 2 3]5040[0 3 6]5041[0 0 0]50425043Check that ``include_zero_rows=False`` works correctly::50445045sage: matrix(ZZ,3,[1..9])._hnf_pari_big(0, include_zero_rows=False)5046[1 2 3]5047[0 3 6]5048sage: matrix(ZZ,3,[1..9])._hnf_pari_big(1, include_zero_rows=False)5049[1 2 3]5050[0 3 6]5051sage: matrix(ZZ,3,[1..9])._hnf_pari_big(3, include_zero_rows=False)5052[1 2 3]5053[0 3 6]5054sage: matrix(ZZ,3,[1..9])._hnf_pari_big(4, include_zero_rows=False)5055[1 2 3]5056[0 3 6]5057"""5058cdef gen H = pari.integer_matrix(self._matrix, self._nrows, self._ncols, 1)5059H = H.mathnf(flag)5060pari_catch_sig_on()5061B = self.extract_hnf_from_pari_matrix(H.g, flag, include_zero_rows)5062pari.clear_stack() # This calls pari_catch_sig_off()5063return B50645065cdef extract_hnf_from_pari_matrix(self, GEN H, int flag, bint include_zero_rows):5066# Throw away the transformation matrix (yes, we should later5067# code this to keep track of it).5068if flag > 0:5069H = gel(H,1)50705071# Figure out how many columns we got back.5072cdef Py_ssize_t H_nc = glength(H) # number of columns5073# Now get the resulting Hermite form matrix back to Sage, suitably re-arranged.5074cdef Matrix_integer_dense B5075if include_zero_rows:5076B = self.new_matrix()5077else:5078B = self.new_matrix(nrows=H_nc)5079for i in range(self._ncols):5080for j in range(H_nc):5081t_INT_to_ZZ(B._matrix[j][self._ncols-i-1], gcoeff(H, i+1, H_nc-j))5082return B50835084cdef inline GEN pari_GEN(Matrix_integer_dense B):5085r"""5086Create the PARI GEN object on the stack defined by the integer5087matrix B. This is used internally by the function for conversion5088of matrices to PARI.50895090For internal use only; this directly uses the PARI stack.5091One should call ``sig_on()`` before and ``sig_off()`` after.5092"""5093cdef GEN A = pari._new_GEN_from_mpz_t_matrix(B._matrix, B._nrows, B._ncols)5094return A509550965097#####################################################################################50985099cdef _clear_columns(Matrix_integer_dense A, pivots, Py_ssize_t n):5100# Clear all columns5101cdef Py_ssize_t i, k, p, l, m = A._ncols5102cdef mpz_t** matrix = A._matrix5103cdef mpz_t c, t5104sig_on()5105mpz_init(c)5106mpz_init(t)5107for i from 0 <= i < len(pivots):5108p = pivots[i]5109for k from 0 <= k < n:5110if k != i:5111if mpz_cmp_si(matrix[k][p],0):5112mpz_fdiv_q(c, matrix[k][p], matrix[i][p])5113# subtract off c*v from row k; resulting A[k,i] entry will be < b, hence in Echelon form.5114for l from 0 <= l < m:5115mpz_mul(t, c, matrix[i][l])5116mpz_sub(matrix[k][l], matrix[k][l], t)5117mpz_clear(c)5118mpz_clear(t)5119sig_off()51205121###############################################################512251235124512551265127cpdef _lift_crt(Matrix_integer_dense M, residues, moduli=None):5128"""5129INPUT:51305131- ``M`` -- A ``Matrix_integer_dense``. Will be modified to hold5132the output.51335134- ``residues`` -- a list of ``Matrix_modn_dense_template``. The5135matrix to reconstruct modulo primes.51365137OUTPUT:51385139The matrix whose reductions modulo primes are the input5140``residues``.51415142TESTS::51435144sage: from sage.matrix.matrix_integer_dense import _lift_crt5145sage: T1 = Matrix(Zmod(5), 4, 4, [1, 4, 4, 0, 2, 0, 1, 4, 2, 0, 4, 1, 1, 4, 0, 3])5146sage: T2 = Matrix(Zmod(7), 4, 4, [1, 4, 6, 0, 2, 0, 1, 2, 4, 0, 6, 6, 1, 6, 0, 5])5147sage: T3 = Matrix(Zmod(11), 4, 4, [1, 4, 10, 0, 2, 0, 1, 9, 8, 0, 10, 6, 1, 10, 0, 9])5148sage: _lift_crt(Matrix(ZZ, 4, 4), [T1, T2, T3])5149[ 1 4 -1 0]5150[ 2 0 1 9]5151[-3 0 -1 6]5152[ 1 -1 0 -2]51535154sage: from sage.ext.multi_modular import MultiModularBasis5155sage: mm = MultiModularBasis([5,7,11])5156sage: _lift_crt(Matrix(ZZ, 4, 4), [T1, T2, T3], mm)5157[ 1 4 -1 0]5158[ 2 0 1 9]5159[-3 0 -1 6]5160[ 1 -1 0 -2]51615162The modulus must be smaller than the maximum for the multi-modular5163reconstruction (using ``mod_int``) and also smaller than the limit5164for ``Matrix_modn_dense_double`` to be able to represent the5165``residues`` ::51665167sage: from sage.ext.multi_modular import MAX_MODULUS as MAX_multi_modular5168sage: from sage.matrix.matrix_modn_dense_double import MAX_MODULUS as MAX_modn_dense_double5169sage: MAX_MODULUS = min(MAX_multi_modular, MAX_modn_dense_double)5170sage: p0 = previous_prime(MAX_MODULUS)5171sage: p1 = previous_prime(p0)5172sage: mmod = [matrix(GF(p0), [[-1, 0, 1, 0, 0, 1, 1, 0, 0, 0, p0-1, p0-2]]),5173....: matrix(GF(p1), [[-1, 0, 1, 0, 0, 1, 1, 0, 0, 0, p1-1, p1-2]])]5174sage: _lift_crt(Matrix(ZZ, 1, 12), mmod)5175[-1 0 1 0 0 1 1 0 0 0 -1 -2]5176"""51775178cdef size_t n, i, j, k5179cdef Py_ssize_t nr, nc51805181n = len(residues)5182if n == 0: # special case: obviously residues[0] wouldn't make sense here.5183return M5184nr = residues[0].nrows()5185nc = residues[0].ncols()51865187if moduli is None:5188moduli = MultiModularBasis([m.base_ring().order() for m in residues])5189else:5190if len(residues) != len(moduli):5191raise IndexError("Number of residues (%s) does not match number of moduli (%s)"%(len(residues), len(moduli)))51925193cdef MultiModularBasis mm5194mm = moduli51955196for b in residues:5197if not is_Matrix_modn_dense(b):5198raise TypeError("Can only perform CRT on list of matrices mod n.")51995200cdef mod_int **row_list5201row_list = <mod_int**>sage_malloc(sizeof(mod_int*) * n)5202if row_list == NULL:5203raise MemoryError("out of memory allocating multi-modular coefficient list")52045205sig_on()5206for k in range(n):5207row_list[k] = <mod_int *>sage_malloc(sizeof(mod_int) * nc)5208if row_list[k] == NULL:5209raise MemoryError("out of memory allocating multi-modular coefficient list")52105211for i in range(nr):5212for k in range(n):5213(<Matrix_modn_dense_template>residues[k])._copy_row_to_mod_int_array(row_list[k],i)5214mm.mpz_crt_vec(M._matrix[i], row_list, nc)52155216for k in range(n):5217sage_free(row_list[k])5218sage_free(row_list)52195220sig_off()5221return M52225223#######################################################52245225# Conclusions:5226# On OS X Intel, at least:5227# - if log_2(height) >= 0.70 * nrows, use classical52285229def tune_multiplication(k, nmin=10, nmax=200, bitmin=2,bitmax=64):5230"""5231Compare various multiplication algorithms.52325233INPUT:52345235- ``k`` - integer; affects numbers of trials52365237- ``nmin`` - integer; smallest matrix to use52385239- ``nmax`` - integer; largest matrix to use52405241- ``bitmin`` - integer; smallest bitsize52425243- ``bitmax`` - integer; largest bitsize52445245OUTPUT:52465247- ``prints what doing then who wins`` - multimodular5248or classical52495250EXAMPLES::52515252sage: from sage.matrix.matrix_integer_dense import tune_multiplication5253sage: tune_multiplication(2, nmin=10, nmax=60, bitmin=2,bitmax=8)525410 2 0.25255...5256"""5257from constructor import random_matrix5258from sage.rings.integer_ring import ZZ5259for n in range(nmin,nmax,10):5260for i in range(bitmin, bitmax, 4):5261A = random_matrix(ZZ, n, n, x = 2**i)5262B = random_matrix(ZZ, n, n, x = 2**i)5263t0 = cputime()5264for j in range(k//n + 1):5265C = A._multiply_classical(B)5266t0 = cputime(t0)5267t1 = cputime()5268for j in range(k//n+1):5269C = A._multiply_multi_modular(B)5270t1 = cputime(t1)5271print n, i, float(i)/float(n)5272if t0 < t1:5273print 'classical'5274else:5275print 'multimod'527652775278##############################################################5279# Some people really really really want to make sure their5280# 4x4 determinant is really really really fast.5281##############################################################52825283cdef int four_dim_det(mpz_t r,mpz_t *x) except -1:5284"""5285Internal function used in computing determinants of 4x4 matrices.52865287TESTS::52885289sage: A = matrix(ZZ,4,[1,0,3,0,4,3,2,1,0,5,0,0,9,1,2,3])5290sage: A.determinant() # indirect doctest5291255292"""5293cdef mpz_t a,b52945295sig_on()5296mpz_init(a)5297mpz_init(b)52985299mpz_mul(a,x[3], x[6] ); mpz_submul(a,x[2], x[7] )5300mpz_mul(b,x[9], x[12]); mpz_submul(b,x[8], x[13])5301mpz_mul(r,a,b)5302mpz_mul(a,x[1], x[7] ); mpz_submul(a,x[3], x[5] )5303mpz_mul(b,x[10],x[12]); mpz_submul(b,x[8], x[14])5304mpz_addmul(r,a,b)5305mpz_mul(a,x[2], x[5] ); mpz_submul(a,x[1], x[6] )5306mpz_mul(b,x[11],x[12]); mpz_submul(b,x[8], x[15])5307mpz_addmul(r,a,b)5308mpz_mul(a,x[3], x[4] ); mpz_submul(a,x[0], x[7] )5309mpz_mul(b,x[10],x[13]); mpz_submul(b,x[9], x[14])5310mpz_addmul(r,a,b)5311mpz_mul(a,x[0], x[6] ); mpz_submul(a,x[2], x[4] )5312mpz_mul(b,x[11],x[13]); mpz_submul(b,x[9], x[15])5313mpz_addmul(r,a,b)5314mpz_mul(a,x[1], x[4] ); mpz_submul(a,x[0], x[5] )5315mpz_mul(b,x[11],x[14]); mpz_submul(b,x[10],x[15])5316mpz_addmul(r,a,b)53175318mpz_clear(a)5319mpz_clear(b)5320sig_off()5321return 053225323#The above was generated by the following Sage code:5324#def idx(x):5325# return [i for i in range(16) if x[i]]5326#5327#def Det4Maker():5328# Q = PolynomialRing(QQ,['x%s'%ZZ(i).str(16) for i in range(16)])5329# M = Matrix(Q,4,4,Q.gens())5330# D = M.det()5331# Dm = [(m.exponents()[0],D[m]) for m in D.monomials()]5332# Dm.sort(reverse=True)5333# MM = [[Dm[i],Dm[i+1]] for i in range(0,len(Dm),2)]5334#5335# S = []5336# for j,((t,s),(r,o)) in enumerate(MM):5337# a,b,c,d = [ZZ(i).str(16) for i in range(16) if t[i]]5338# e,f,g,h = [ZZ(i).str(16) for i in range(16) if r[i]]5339# S.append((c+d+g+h,j))5340# S.sort(lambda x,y: cmp(x[0],y[0]))5341# MM = [MM[s[1]] for s in S]5342# MMM = [[MM[i],MM[i+1]] for i in range(0,len(MM),2)]5343#5344# N = 05345# Cstrux = ""5346# Pstrux = ""5347# for ((t1,s1),(t2,s2)),((t3,s3),(t4,s4)) in MMM:5348# a,b,c,d = idx(t1)5349# e,f = idx(t2)[2:]5350# h,i = idx(t3)[:2]5351#5352# if s1 == 1:5353# a,b,h,i = h,i,a,b5354#5355# Pstrux+= 'a = x[%s]*x[%s]; '%(a,b)5356# Cstrux+= 'mpz_mul(a,x[%s],x[%s]); '%(a,b)5357#5358# Pstrux+= 'a-=x[%s]*x[%s]; '%(h,i)5359# Cstrux+= 'mpz_submul(a,x[%s],x[%s])\n'%(h,i)5360#5361# if s4*s1 == 1:5362# c,d,e,f = e,f,c,d5363#5364# Pstrux+= 'b = x[%s]*x[%s]; '%(c,d)5365# Cstrux+= 'mpz_mul(b,x[%s],x[%s]); '%(c,d)5366#5367# Pstrux+= 'b-=x[%s]*x[%s]; '%(e,f)5368# Cstrux+= 'mpz_submul(b,x[%s],x[%s])\n'%(e,f)5369#5370#5371# if N:5372# Pstrux+= 'r+= a*b\n'5373# Cstrux+= 'mpz_addmul(r,a,b)\n'5374# else:5375# Pstrux+= 'r = a*b\n'5376# Cstrux+= 'mpz_mul(r,a,b)\n'5377# N = 15378# return Cstrux,Pstrux5379#5380#print Det4Maker()[0]53815382#Note, one can prove correctness of the above by setting5383# sage: Q = PolynomialRing(QQ,['x%s'%ZZ(i).str(16) for i in range(16)])5384# sage: M = Matrix(Q,4,4,Q.gens())5385# sage: D = M.det()5386# sage: x = Q.gens()5387#and then evaluating the contents of Det4Maker()[1]...5388# sage: a = x[3]*x[6]; a-=x[2]*x[7]; b = x[9]*x[12]; b-=x[8]*x[13]; r = a*b5389# sage: a = x[1]*x[7]; a-=x[3]*x[5]; b = x[10]*x[12]; b-=x[8]*x[14]; r+= a*b5390# sage: a = x[2]*x[5]; a-=x[1]*x[6]; b = x[11]*x[12]; b-=x[8]*x[15]; r+= a*b5391# sage: a = x[3]*x[4]; a-=x[0]*x[7]; b = x[10]*x[13]; b-=x[9]*x[14]; r+= a*b5392# sage: a = x[0]*x[6]; a-=x[2]*x[4]; b = x[11]*x[13]; b-=x[9]*x[15]; r+= a*b5393# sage: a = x[1]*x[4]; a-=x[0]*x[5]; b = x[11]*x[14]; b-=x[10]*x[15]; r+= a*b5394#and comparing results:5395# sage: r-D5396# 05397#bingo!5398539954005401