def __cmp__(self, right): """ Compare self to right. EXAMPLES:: sage: x = Gamma0(18)([19,1,18,1]) sage: x.__cmp__(3) is not 0 True sage: x.__cmp__(x) 0 sage: x = Gamma0(5)([1,1,0,1]) sage: x == 0 False This once caused a segfault (see trac #5443):: sage: r,s,t,u,v = map(SL2Z, [[1, 1, 0, 1], [-1, 0, 0, -1], [1, -1, 0, 1], [1, -1, 2, -1], [-1, 1, -2, 1]]) sage: v == s*u True sage: s*u == v True """ from sage.misc.functional import parent if parent(self) != parent(right): return cmp(type(self), type(right)) else: return cmp(self.__x, right.__x)
def _negaconvolution_fft(L1, L2, n): """ Returns negacyclic convolution of lists L1 and L2, using FFT algorithm. L1 and L2 must both be length `2^n`, where `n \geq 3`. Assumes all entries of L1 and L2 belong to the same ring. EXAMPLES:: sage: from sage.rings.polynomial.convolution import _negaconvolution_naive sage: from sage.rings.polynomial.convolution import _negaconvolution_fft sage: _negaconvolution_naive(range(8), range(5, 13)) [-224, -234, -224, -192, -136, -54, 56, 196] sage: _negaconvolution_fft(range(8), range(5, 13), 3) [-224, -234, -224, -192, -136, -54, 56, 196] :: sage: for n in range(3, 10): ... L1 = [ZZ.random_element(100) for _ in range(1 << n)] ... L2 = [ZZ.random_element(100) for _ in range(1 << n)] ... assert _negaconvolution_naive(L1, L2) == _negaconvolution_fft(L1, L2, n) """ assert n >= 3 R = parent(L1[0]) # split into 2^m pieces of 2^(k-1) coefficients each, with k as small # as possible, subject to m <= k (so that the ring of Fourier coefficients # has enough roots of unity) m = (n + 1) >> 1 k = n + 1 - m M = 1 << m K = 1 << k # split inputs into polynomials L1 = _split(L1, m, k) L2 = _split(L2, m, k) # fft each input _fft(L1, K, 0, m, K >> 1) _fft(L2, K, 0, m, K >> 1) # pointwise multiply L3 = [_negaconvolution(L1[i], L2[i], k) for i in range(M)] # inverse fft _ifft(L3, K, 0, m, K >> 1) # combine back into a single list L3 = _nega_combine(L3, m, k) # normalise return [R(x / M) for x in L3]
def __contains__(self, x): r""" Check in the element x is in the mathematical parent self. EXAMPLES:: sage: D5 = FiniteCoxeterGroups().example() sage: D5.an_element() in D5 True sage: 1 in D5 False (also tested by :meth:`test_an_element` :meth:`test_some_elements`) """ from sage.misc.functional import parent return parent(x) is self
def _coerce_impl(self, x): """ Coerce x into self, if possible. EXAMPLES:: sage: J = J0(37) ; J.Hom(J)._coerce_impl(matrix(ZZ,4,[5..20])) Abelian variety endomorphism of Abelian variety J0(37) of dimension 2 sage: K = J0(11) * J0(11) ; J.Hom(K)._coerce_impl(matrix(ZZ,4,[5..20])) Abelian variety morphism: From: Abelian variety J0(37) of dimension 2 To: Abelian variety J0(11) x J0(11) of dimension 2 """ if self.matrix_space().has_coerce_map_from(parent(x)): return self(x) else: return HomsetWithBase._coerce_impl(self, x)
def _split(L, m, k): """ Assumes L is a list of length `2^{m+k-1}`. Splits it into `2^m` lists of length `2^{k-1}`, returned as a list of lists. Each list is zero padded up to length `2^k`. EXAMPLES:: sage: from sage.rings.polynomial.convolution import _split sage: _split([1, 2, 3, 4, 5, 6, 7, 8], 2, 2) [[1, 2, 0, 0], [3, 4, 0, 0], [5, 6, 0, 0], [7, 8, 0, 0]] sage: _split([1, 2, 3, 4, 5, 6, 7, 8], 1, 3) [[1, 2, 3, 4, 0, 0, 0, 0], [5, 6, 7, 8, 0, 0, 0, 0]] sage: _split([1, 2, 3, 4, 5, 6, 7, 8], 3, 1) [[1, 0], [2, 0], [3, 0], [4, 0], [5, 0], [6, 0], [7, 0], [8, 0]] """ K = 1 << (k-1) zero = parent(L[0])(0) zeroes = [zero] * K return [[L[i+j] for j in range(K)] + zeroes for i in range(0, K << m, K)]
def _split(L, m, k): """ Assumes L is a list of length `2^{m+k-1}`. Splits it into `2^m` lists of length `2^{k-1}`, returned as a list of lists. Each list is zero padded up to length `2^k`. EXAMPLES:: sage: from sage.rings.polynomial.convolution import _split sage: _split([1, 2, 3, 4, 5, 6, 7, 8], 2, 2) [[1, 2, 0, 0], [3, 4, 0, 0], [5, 6, 0, 0], [7, 8, 0, 0]] sage: _split([1, 2, 3, 4, 5, 6, 7, 8], 1, 3) [[1, 2, 3, 4, 0, 0, 0, 0], [5, 6, 7, 8, 0, 0, 0, 0]] sage: _split([1, 2, 3, 4, 5, 6, 7, 8], 3, 1) [[1, 0], [2, 0], [3, 0], [4, 0], [5, 0], [6, 0], [7, 0], [8, 0]] """ K = 1 << (k - 1) zero = parent(L[0])(0) zeroes = [zero] * K return [[L[i + j] for j in range(K)] + zeroes for i in range(0, K << m, K)]
def _convolution_fft(L1, L2): """ Returns convolution of non-empty lists L1 and L2, using FFT algorithm. L1 and L2 may have arbitrary lengths `\geq 4`. Assumes all entries of L1 and L2 belong to the same ring. EXAMPLES:: sage: from sage.rings.polynomial.convolution import _convolution_naive sage: from sage.rings.polynomial.convolution import _convolution_fft sage: _convolution_naive([1, 2, 3], [4, 5, 6]) [4, 13, 28, 27, 18] sage: _convolution_fft([1, 2, 3], [4, 5, 6]) [4, 13, 28, 27, 18] :: sage: for len1 in range(4, 30): ... for len2 in range(4, 30): ... L1 = [ZZ.random_element(100) for _ in range(len1)] ... L2 = [ZZ.random_element(100) for _ in range(len2)] ... assert _convolution_naive(L1, L2) == _convolution_fft(L1, L2) """ R = parent(L1[0]) # choose n so that output convolution length is 2^n len1 = len(L1) len2 = len(L2) outlen = len1 + len2 - 1 n = int(ceil(log(outlen) / log(2.0))) # split into 2^m pieces of 2^(k-1) coefficients each, with k as small # as possible, subject to m <= k + 1 (so that the ring of Fourier # coefficients has enough roots of unity) m = (n >> 1) + 1 k = n + 1 - m N = 1 << n M = 1 << m K = 1 << k # zero pad inputs up to length N zero = R(0) L1 = L1 + [zero] * (N - len(L1)) L2 = L2 + [zero] * (N - len(L2)) # split inputs into polynomials L1 = _split(L1, m, k) L2 = _split(L2, m, k) # fft each input _fft(L1, K, 0, m, K) _fft(L2, K, 0, m, K) # pointwise multiply L3 = [_negaconvolution(L1[i], L2[i], k) for i in range(M)] # inverse fft _ifft(L3, K, 0, m, K) # combine back into a single list L3 = _combine(L3, m, k) # normalise, and truncate to correct length return [R(L3[i] / M) for i in range(outlen)]
def __call__(self, M): r""" Create a homomorphism in this space from M. M can be any of the following: - a Morphism of abelian varieties - a matrix of the appropriate size (i.e. 2\*self.domain().dimension() x 2\*self.codomain().dimension()) whose entries are coercible into self.base_ring() - anything that can be coerced into self.matrix_space() EXAMPLES:: sage: H = Hom(J0(11), J0(22)) sage: phi = H(matrix(ZZ,2,4,[5..12])) ; phi Abelian variety morphism: From: Abelian variety J0(11) of dimension 1 To: Abelian variety J0(22) of dimension 2 sage: phi.matrix() [ 5 6 7 8] [ 9 10 11 12] sage: phi.matrix().parent() Full MatrixSpace of 2 by 4 dense matrices over Integer Ring :: sage: H = J0(22).Hom(J0(11)*J0(11)) sage: m1 = J0(22).degeneracy_map(11,1).matrix() ; m1 [ 0 1] [-1 1] [-1 0] [ 0 -1] sage: m2 = J0(22).degeneracy_map(11,2).matrix() ; m2 [ 1 -2] [ 0 -2] [ 1 -1] [ 0 -1] sage: m = m1.transpose().stack(m2.transpose()).transpose() ; m [ 0 1 1 -2] [-1 1 0 -2] [-1 0 1 -1] [ 0 -1 0 -1] sage: phi = H(m) ; phi Abelian variety morphism: From: Abelian variety J0(22) of dimension 2 To: Abelian variety J0(11) x J0(11) of dimension 2 sage: phi.matrix() [ 0 1 1 -2] [-1 1 0 -2] [-1 0 1 -1] [ 0 -1 0 -1] """ if isinstance(M, morphism.Morphism): if M.parent() is self: return M elif M.domain() == self.domain() and M.codomain() == self.codomain(): M = M.matrix() else: raise ValueError, "cannot convert %s into %s" % (M, self) elif is_Matrix(M): if M.base_ring() != ZZ: M = M.change_ring(ZZ) if M.nrows() != 2*self.domain().dimension() or M.ncols() != 2*self.codomain().dimension(): raise TypeError, "matrix has wrong dimension" elif self.matrix_space().has_coerce_map_from(parent(M)): M = self.matrix_space()(M) else: raise TypeError, "can only coerce in matrices or morphisms" return morphism.Morphism(self, M)
def __call__(self, M): r""" Create a homomorphism in this space from M. M can be any of the following: - a Morphism of abelian varieties - a matrix of the appropriate size (i.e. 2\*self.domain().dimension() x 2\*self.codomain().dimension()) whose entries are coercible into self.base_ring() - anything that can be coerced into self.matrix_space() EXAMPLES:: sage: H = Hom(J0(11), J0(22)) sage: phi = H(matrix(ZZ,2,4,[5..12])) ; phi Abelian variety morphism: From: Abelian variety J0(11) of dimension 1 To: Abelian variety J0(22) of dimension 2 sage: phi.matrix() [ 5 6 7 8] [ 9 10 11 12] sage: phi.matrix().parent() Full MatrixSpace of 2 by 4 dense matrices over Integer Ring :: sage: H = J0(22).Hom(J0(11)*J0(11)) sage: m1 = J0(22).degeneracy_map(11,1).matrix() ; m1 [ 0 1] [-1 1] [-1 0] [ 0 -1] sage: m2 = J0(22).degeneracy_map(11,2).matrix() ; m2 [ 1 -2] [ 0 -2] [ 1 -1] [ 0 -1] sage: m = m1.transpose().stack(m2.transpose()).transpose() ; m [ 0 1 1 -2] [-1 1 0 -2] [-1 0 1 -1] [ 0 -1 0 -1] sage: phi = H(m) ; phi Abelian variety morphism: From: Abelian variety J0(22) of dimension 2 To: Abelian variety J0(11) x J0(11) of dimension 2 sage: phi.matrix() [ 0 1 1 -2] [-1 1 0 -2] [-1 0 1 -1] [ 0 -1 0 -1] """ if isinstance(M, morphism.Morphism): if M.parent() is self: return M elif M.domain() == self.domain() and M.codomain() == self.codomain( ): M = M.matrix() else: raise ValueError, "cannot convert %s into %s" % (M, self) elif is_Matrix(M): if M.base_ring() != ZZ: M = M.change_ring(ZZ) if M.nrows() != 2 * self.domain().dimension() or M.ncols( ) != 2 * self.codomain().dimension(): raise TypeError, "matrix has wrong dimension" elif self.matrix_space().has_coerce_map_from(parent(M)): M = self.matrix_space()(M) else: raise TypeError, "can only coerce in matrices or morphisms" return morphism.Morphism(self, M)