def __add__(self, other, **kwargs): r""" Direct sum of Hermitian lattices. """ if isinstance(other, HermitianWeilRep): return HermitianWeilRep(block_diagonal_matrix( [self.complex_gram_matrix(), other.complex_gram_matrix()], subdivide=False), gen=self.__w) elif isinstance(other, RescaledHyperbolicPlane): return HermitianRescaledHyperbolicPlane(other._N()).__add__(self) return NotImplemented
def lift_for_SL(A, N=None): r""" Lift a matrix `A` from `SL_m(\ZZ / N\ZZ)` to `SL_m(\ZZ)`. This follows [Shi1971]_, Lemma 1.38, p. 21. INPUT: - ``A`` -- a square matrix with coefficients in `\ZZ / N\ZZ` (or `\ZZ`) - ``N`` -- the modulus (optional) required only if the matrix ``A`` has coefficients in `\ZZ` EXAMPLES:: sage: from sage.modular.local_comp.liftings import lift_for_SL sage: A = matrix(Zmod(11), 4, 4, [6, 0, 0, 9, 1, 6, 9, 4, 4, 4, 8, 0, 4, 0, 0, 8]) sage: A.det() 1 sage: L = lift_for_SL(A) sage: L.det() 1 sage: (L - A) == 0 True sage: B = matrix(Zmod(19), 4, 4, [1, 6, 10, 4, 4, 14, 15, 4, 13, 0, 1, 15, 15, 15, 17, 10]) sage: B.det() 1 sage: L = lift_for_SL(B) sage: L.det() 1 sage: (L - B) == 0 True TESTS:: sage: lift_for_SL(matrix(3,3,[1,2,0,3,4,0,0,0,1]),3) [10 14 3] [ 9 10 3] [ 3 3 1] sage: A = matrix(Zmod(7), 2, [1,0,0,1]) sage: L = lift_for_SL(A) sage: L.parent() Full MatrixSpace of 2 by 2 dense matrices over Integer Ring sage: A = matrix(Zmod(7), 1, [1]) sage: L = lift_for_SL(A); L [1] sage: A = matrix(ZZ, 2, [1,0,0,1]) sage: lift_for_SL(A) Traceback (most recent call last): ... ValueError: you must choose the modulus sage: for _ in range(100): ....: d = randint(0, 10) ....: p = choice([2,3,5,7,11]) ....: M = random_matrix(Zmod(p), d, algorithm='unimodular') ....: assert lift_for_SL(M).det() == 1 """ from sage.matrix.special import (identity_matrix, diagonal_matrix, block_diagonal_matrix) from sage.misc.misc_c import prod ring = A.parent().base_ring() if N is None: if ring is ZZ: raise ValueError('you must choose the modulus') else: N = ring.characteristic() m = A.nrows() if m <= 1: return identity_matrix(ZZ, m) AZZ = A.change_ring(ZZ) D, U, V = AZZ.smith_form() diag = diagonal_matrix([-1] + [1] * (m - 1)) if U.det() == -1: U = diag * U if V.det() == -1: V = V * diag a = [U.row(i) * AZZ * V.column(i) for i in range(m)] b = prod(a[1:]) Winv = identity_matrix(m) Winv[1, 0] = 1 - b Winv[0, 1] = -1 Winv[1, 1] = b Xinv = identity_matrix(m) Xinv[0, 1] = a[1] Cp = diagonal_matrix(a[1:]) Cp[0, 0] *= a[0] C = lift_for_SL(Cp, N) Cpp = block_diagonal_matrix(identity_matrix(1), C) Cpp[1, 0] = 1 - a[0] return (~U * Winv * Cpp * Xinv * ~V).change_ring(ZZ)
def _direct_sum(self, other): if not (self._base_ring == other._base_ring and self._domain_poset == other._domain_poset): raise TypeError("Sheaves are not defined on same poset or not defined over same ring") direct_sum_stalks = {x:self._stalk_dict[x] + other._stalk_dict[x] for x in self._domain_poset.list()} direct_sum_res = {tuple(r):block_diagonal_matrix(self.restriction(r[0], r[1]).matrix(), other.restriction(r[0], r[1]).matrix(), subdivide = False) for r in self._domain_poset.cover_relations()} return LocallyFreeSheafFinitePoset(direct_sum_stalks, direct_sum_res, self._base_ring, self._domain_poset)
def test_one_tensor_m_block_diag(): for m in matrices: block_diagonal_matrix([m] * one.nrows())