Example #1
0
File: hmf.py Project: bubonic/psage
    def dual_eigenspace(self, B=None):
        """
        Return 1-dimensional subspace of the dual of the ambient space
        with the same system of eigenvalues as self.  This is useful when
        computing a large number of `a_P`.

        If we can't find such a subspace using Hecke operators of norm
        less than B, then we raise a RuntimeError.  This should only happen
        if you set B way too small, or self is actually not new.
        
        INPUT:
            - B -- Integer or None; if None, defaults to a heuristic bound.
        """
        N = self.conductor()
        H = self._S.ambient()
        V = H.vector_space()
        if B is None:
            # TODO: This is a heuristic guess at a "Sturm bound"; it's the same
            # formula as the one over QQ for Gamma_0(N).  I have no idea if this
            # is correct or not yet. It is probably much too large. -- William Stein
            from sage.modular.all import Gamma0
            B = Gamma0(N.norm()).index()//6 + 1
        for P in primes_of_bounded_norm(B+1):
            P = P.sage_ideal()
            if V.dimension() == 1:
                return V
            if not P.divides(N):
                T = H.hecke_matrix(P).transpose()
                V = (T - self.ap(P)).kernel_on(V)
        raise RuntimeError, "unable to isolate 1-dimensional space"
Example #2
0
    def dual_eigenspace(self, B=None):
        """
        Return 1-dimensional subspace of the dual of the ambient space
        with the same system of eigenvalues as self.  This is useful when
        computing a large number of `a_P`.

        If we can't find such a subspace using Hecke operators of norm
        less than B, then we raise a RuntimeError.  This should only happen
        if you set B way too small, or self is actually not new.
        
        INPUT:
            - B -- Integer or None; if None, defaults to a heuristic bound.
        """
        N = self.conductor()
        H = self._S.ambient()
        V = H.vector_space()
        if B is None:
            # TODO: This is a heuristic guess at a "Sturm bound"; it's the same
            # formula as the one over QQ for Gamma_0(N).  I have no idea if this
            # is correct or not yet. It is probably much too large. -- William Stein
            from sage.modular.all import Gamma0
            B = Gamma0(N.norm()).index() // 6 + 1
        for P in primes_of_bounded_norm(B + 1):
            P = P.sage_ideal()
            if V.dimension() == 1:
                return V
            if not P.divides(N):
                T = H.hecke_matrix(P).transpose()
                V = (T - self.ap(P)).kernel_on(V)
        raise RuntimeError("unable to isolate 1-dimensional space")
Example #3
0
    def aplist(self, B, dual_bound=None, algorithm='dual'):
        """
        Return list of traces of Frobenius for all primes P of norm
        less than bound.  Use the function
        psage.number_fields.sqrt5.primes_of_bounded_norm(B)
        to get the corresponding primes.

        INPUT:
            - `B` -- a nonnegative integer
            - ``dual_bound`` -- default None; passed to dual_eigenvector function
            - ``algorithm`` -- 'dual' (default) or 'direct'

        OUTPUT:
             - a list of Sage integers

        EXAMPLES::

        We compute the aplists up to B=50::

            sage: from psage.modform.hilbert.sqrt5.hmf import HilbertModularForms, F
            sage: H = HilbertModularForms(F.primes_above(71)[1]).elliptic_curve_factors()[0]
            sage: v = H.aplist(50); v
            [-1, 0, -2, 0, 0, 2, -4, 6, -6, 8, 2, 6, 12, -4]

        This agrees with what we get using an elliptic curve of this
        conductor::
        
            sage: a = F.0; E = EllipticCurve(F, [a,a+1,a,a,0])
            sage: from psage.ellcurve.lseries.aplist_sqrt5 import aplist
            sage: w = aplist(E, 50)
            sage: v == w
            True

        We compare the output from the two algorithms up to norm 75::

            sage: H.aplist(75, algorithm='direct') == H.aplist(75, algorithm='dual')
            True
        """
        primes = [P.sage_ideal() for P in primes_of_bounded_norm(B)]
        if algorithm == 'direct':
            return [self.ap(P) for P in primes]
        elif algorithm == 'dual':
            v = self.dual_eigenvector(dual_bound)
            i = v.nonzero_positions()[0]
            c = v[i]
            I = self._S.ambient()._icosians_mod_p1
            N = self.conductor()
            aplist = []
            for P in primes:
                if P.divides(N):
                    ap = self.ap(P)
                else:
                    ap = (I.hecke_operator_on_basis_element(
                        P, i).dot_product(v)) / c
                aplist.append(ap)
            return aplist
        else:
            raise ValueError("unknown algorithm '{0}'".format(algorithm))
Example #4
0
File: hmf.py Project: bubonic/psage
    def aplist(self, B, dual_bound=None, algorithm='dual'):
        """
        Return list of traces of Frobenius for all primes P of norm
        less than bound.  Use the function
        psage.number_fields.sqrt5.primes_of_bounded_norm(B)
        to get the corresponding primes.

        INPUT:
            - `B` -- a nonnegative integer
            - ``dual_bound`` -- default None; passed to dual_eigenvector function
            - ``algorithm`` -- 'dual' (default) or 'direct'

        OUTPUT:
             - a list of Sage integers

        EXAMPLES::

        We compute the aplists up to B=50::

            sage: from psage.modform.hilbert.sqrt5.hmf import HilbertModularForms, F
            sage: H = HilbertModularForms(F.primes_above(71)[1]).elliptic_curve_factors()[0]
            sage: v = H.aplist(50); v
            [-1, 0, -2, 0, 0, 2, -4, 6, -6, 8, 2, 6, 12, -4]

        This agrees with what we get using an elliptic curve of this
        conductor::
        
            sage: a = F.0; E = EllipticCurve(F, [a,a+1,a,a,0])
            sage: from psage.ellcurve.lseries.aplist_sqrt5 import aplist
            sage: w = aplist(E, 50)
            sage: v == w
            True

        We compare the output from the two algorithms up to norm 75::

            sage: H.aplist(75, algorithm='direct') == H.aplist(75, algorithm='dual')
            True
        """
        primes = [P.sage_ideal() for P in primes_of_bounded_norm(B)]
        if algorithm == 'direct':
            return [self.ap(P) for P in primes]
        elif algorithm == 'dual':
            v = self.dual_eigenvector(dual_bound)
            i = v.nonzero_positions()[0]
            c = v[i]
            I = self._S.ambient()._icosians_mod_p1
            N = self.conductor()
            aplist = []
            for P in primes:
                if P.divides(N):
                    ap = self.ap(P)
                else:
                    ap = (I.hecke_operator_on_basis_element(P,i).dot_product(v))/c
                aplist.append(ap)
            return aplist
        else:
            raise ValueError, "unknown algorithm '%s'"%algorithm