from sage.matrix.all import MatrixSpace
from sage.rings.all import ZZ
from sage.matrix.matrix_integer_sparse cimport Matrix_integer_sparse
from sage.matrix.matrix_integer_dense cimport Matrix_integer_dense
from sage.rings.integer cimport Integer
cdef class Matrix:
"""
A Cremona Matrix.
EXAMPLES::
sage: M = CremonaModularSymbols(225)
sage: t = M.hecke_matrix(2)
sage: type(t)
<type 'sage.libs.cremona.mat.Matrix'>
sage: t
61 x 61 Cremona matrix over Rational Field
"""
def __init__(self):
"""
Called when the matrix is being created.
EXAMPLES::
sage: t = CremonaModularSymbols(11).hecke_matrix(2); t
3 x 3 Cremona matrix over Rational Field
sage: type(t)
<type 'sage.libs.cremona.mat.Matrix'>
"""
self.M = NULL
def __repr__(self):
"""
String representation of this matrix. Use print self.str() to
print out the matrix entries on the screen.
EXAMPLES::
sage: M = CremonaModularSymbols(23)
sage: t = M.hecke_matrix(2); t
5 x 5 Cremona matrix over Rational Field
sage: print t.str()
[ 3 0 0 0 0]
[-1 -1 0 0 -1]
[ 1 1 0 1 1]
[-1 1 1 -1 0]
[ 0 -1 0 0 0]
"""
return "%s x %s Cremona matrix over Rational Field"%(self.nrows(), self.ncols())
def str(self):
"""
Return full string representation of this matrix, never in compact form.
EXAMPLES::
sage: M = CremonaModularSymbols(22, sign=1)
sage: t = M.hecke_matrix(13)
sage: t.str()
'[14 0 0 0 0]\n[-4 12 0 8 4]\n[ 0 -6 4 -6 0]\n[ 4 2 0 6 -4]\n[ 0 0 0 0 14]'
"""
return self.sage_matrix_over_ZZ(sparse=False).str()
cdef set(self, mat* M):
if self.M:
raise RuntimeError, "self.M is already set."
self.M = M
def __dealloc__(self):
if self.M:
delete_mat(self.M)
def __getitem__(self, ij):
"""
Return the (i,j) entry of this matrix.
Here, ij is a 2-tuple (i,j) and the row and column indices start
at 1 and not 0.
EXAMPLES::
sage: M = CremonaModularSymbols(19, sign=1)
sage: t = M.hecke_matrix(13); t
2 x 2 Cremona matrix over Rational Field
sage: t.sage_matrix_over_ZZ()
[ 28 0]
[-12 -8]
sage: [[t.__getitem__((i,j)) for j in [1,2]] for i in [1,2]]
[[28, 0], [-12, -8]]
sage: t.__getitem__((0,0))
Traceback (most recent call last):
...
IndexError: matrix indices out of range
"""
cdef long i, j
if self.M:
i, j = ij
if 0<i and i<=nrows(self.M[0]) and 0<j and j<=ncols(self.M[0]):
return self.M.sub(i,j)
raise IndexError, "matrix indices out of range"
raise IndexError, "cannot index into an undefined matrix"
def nrows(self):
"""
Return the number of rows of this matrix.
EXAMPLES::
sage: M = CremonaModularSymbols(19, sign=1)
sage: t = M.hecke_matrix(13); t
2 x 2 Cremona matrix over Rational Field
sage: t.nrows()
2
"""
return nrows(self.M[0])
def ncols(self):
"""
Return the number of columns of this matrix.
EXAMPLES::
sage: M = CremonaModularSymbols(1234, sign=1)
sage: t = M.hecke_matrix(3); t.ncols()
156
sage: M.dimension()
156
"""
return ncols(self.M[0])
def add_scalar(self, scalar s):
"""
Return new matrix obtained by adding s to each diagonal entry of self.
EXAMPLES::
sage: M = CremonaModularSymbols(23, cuspidal=True, sign=1)
sage: t = M.hecke_matrix(2); print t.str()
[ 0 1]
[ 1 -1]
sage: w = t.add_scalar(3); print w.str()
[3 1]
[1 2]
"""
return new_Matrix(addscalar(self.M[0], s))
def charpoly(self, var='x'):
"""
Return the characteristic polynomial of this matrix, viewed as
as a matrix over the integers.
ALGORITHM:
Note that currently, this function converts this matrix into a
dense matrix over the integers, then calls the charpoly
algorithm on that, which I think is LinBox's.
EXAMPLES::
sage: M = CremonaModularSymbols(33, cuspidal=True, sign=1)
sage: t = M.hecke_matrix(2)
sage: t.charpoly()
x^3 + 3*x^2 - 4
sage: t.charpoly().factor()
(x - 1) * (x + 2)^2
"""
return self.sage_matrix_over_ZZ(sparse=False).charpoly(var)
def sage_matrix_over_ZZ(self, sparse=True):
"""
Return corresponding Sage matrix over the integers.
INPUT:
- ``sparse`` -- (default: True) whether the return matrix has
a sparse representation
EXAMPLES::
sage: M = CremonaModularSymbols(23, cuspidal=True, sign=1)
sage: t = M.hecke_matrix(2)
sage: s = t.sage_matrix_over_ZZ(); s
[ 0 1]
[ 1 -1]
sage: type(s)
<type 'sage.matrix.matrix_integer_sparse.Matrix_integer_sparse'>
sage: s = t.sage_matrix_over_ZZ(sparse=False); s
[ 0 1]
[ 1 -1]
sage: type(s)
<type 'sage.matrix.matrix_integer_dense.Matrix_integer_dense'>
"""
cdef long n = self.nrows()
cdef long i, j, k
cdef scalar* v = <scalar*> self.M.get_entries()
cdef Matrix_integer_dense Td
cdef Matrix_integer_sparse Ts
if sparse:
Ts = MatrixSpace(ZZ, n, sparse=sparse).zero_matrix().__copy__()
k = 0
for i from 0 <= i < n:
for j from 0 <= j < n:
if v[k]:
Ts.set_unsafe(i, j, Integer(v[k]))
k += 1
return Ts
else:
Td = MatrixSpace(ZZ, n, sparse=sparse).zero_matrix().__copy__()
k = 0
for i from 0 <= i < n:
for j from 0 <= j < n:
if v[k]:
Td.set_unsafe(i, j, Integer(v[k]))
k += 1
return Td
cdef class MatrixFactory:
cdef new_matrix(self, mat M):
return new_Matrix(M)
cdef Matrix new_Matrix(mat M):
cdef Matrix A = Matrix()
A.set(new_mat(M))
return A