Esempio n. 1
0
    def nu3(self):
        r"""
        Return the number of elliptic points of order 3 for this congruence
        subgroup `\Gamma_0(N)`. The number of these is given by a standard formula:
        0 if `N` is divisible by 9 or any prime congruent to -1 mod 3, and
        otherwise `2^d` where d is the number of primes other than 3 dividing `N`.

        EXAMPLE::

            sage: Gamma0(2).nu3()
            0
            sage: Gamma0(3).nu3()
            1
            sage: Gamma0(9).nu3()
            0
            sage: Gamma0(7).nu3()
            2
            sage: Gamma0(21).nu3()
            2
            sage: Gamma0(1729).nu3()
            8
        """
        n = self.level()
        if (n % 9 == 0):
            return ZZ(0)
        return prod([1 + kronecker_symbol(-3, p) for p, _ in n.factor()])
Esempio n. 2
0
    def nu3(self):
        r"""
        Return the number of elliptic points of order 3 for this congruence
        subgroup `\Gamma_0(N)`. The number of these is given by a standard formula:
        0 if `N` is divisible by 9 or any prime congruent to -1 mod 3, and
        otherwise `2^d` where d is the number of primes other than 3 dividing `N`.

        EXAMPLE::

            sage: Gamma0(2).nu3()
            0
            sage: Gamma0(3).nu3()
            1
            sage: Gamma0(9).nu3()
            0
            sage: Gamma0(7).nu3()
            2
            sage: Gamma0(21).nu3()
            2
            sage: Gamma0(1729).nu3()
            8
        """
        n = self.level()
        if (n % 9 == 0):
            return ZZ(0)
        return prod([ 1 + kronecker_symbol(-3, p) for p, _ in n.factor()])
Esempio n. 3
0
def residue_ring(N):
    fac = N.factor()
    if len(fac) != 1:
        raise NotImplementedError, "P must be a prime power"
    from sage.rings.all import kronecker_symbol

    P, e = fac[0]
    p = P.smallest_integer()
    s = kronecker_symbol(p, 5)
    if e == 1:
        return P.residue_field()
    if s == 1:
        return ResidueRing_split(N, P, p, e)
    elif s == -1:
        return ResidueRing_inert(N, P, p, e)
    else:
        if e % 2 == 0:
            # easy case
            return ResidueRing_ramified_even(N, P, p, e)
        else:
            # hardest case
            return ResidueRing_ramified_odd(N, P, p, e)
Esempio n. 4
0
def residue_ring(N):
    fac = N.factor()
    if len(fac) != 1:
        raise NotImplementedError, "P must be a prime power"
    from sage.rings.all import kronecker_symbol

    P, e = fac[0]
    p = P.smallest_integer()
    s = kronecker_symbol(p, 5)
    if e == 1:
        return P.residue_field()
    if s == 1:
        return ResidueRing_split(N, P, p, e)
    elif s == -1:
        return ResidueRing_inert(N, P, p, e)
    else:
        if e % 2 == 0:
            # easy case
            return ResidueRing_ramified_even(N, P, p, e)
        else:
            # hardest case
            return ResidueRing_ramified_odd(N, P, p, e)
Esempio n. 5
0
    def nu2(self):
        r"""
        Return the number of elliptic points of order 2 for this congruence
        subgroup `\Gamma_0(N)`. The number of these is given by a standard formula:
        0 if `N` is divisible by 4 or any prime congruent to -1 mod 4, and
        otherwise `2^d` where d is the number of odd primes dividing `N`.

        EXAMPLE::

            sage: Gamma0(2).nu2()
            1
            sage: Gamma0(4).nu2()
            0
            sage: Gamma0(21).nu2()
            0
            sage: Gamma0(1105).nu2()
            8
            sage: [Gamma0(n).nu2() for n in [1..19]]
            [1, 1, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 2, 0, 0]
        """
        n = self.level()
        if n%4 == 0:
            return ZZ(0)
        return prod([ 1 + kronecker_symbol(-4, p) for p, _ in n.factor()])
Esempio n. 6
0
    def nu2(self):
        r"""
        Return the number of elliptic points of order 2 for this congruence
        subgroup `\Gamma_0(N)`. The number of these is given by a standard formula:
        0 if `N` is divisible by 4 or any prime congruent to -1 mod 4, and
        otherwise `2^d` where d is the number of odd primes dividing `N`.

        EXAMPLE::

            sage: Gamma0(2).nu2()
            1
            sage: Gamma0(4).nu2()
            0
            sage: Gamma0(21).nu2()
            0
            sage: Gamma0(1105).nu2()
            8
            sage: [Gamma0(n).nu2() for n in [1..19]]
            [1, 1, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0, 0, 2, 0, 0]
        """
        n = self.level()
        if n % 4 == 0:
            return ZZ(0)
        return prod([1 + kronecker_symbol(-4, p) for p, _ in n.factor()])
def dimension__jacobi_scalar_f(k, m, f) :
    if moebius(f) != (-1)**k :
        return 0
    
    ## We use chapter 6 of Skoruppa's thesis
    ts = filter(lambda t: gcd(t, m // t) == 1, m.divisors())
    
    ## Eisenstein part
    eis_dimension = 0
    
    for t in ts :
        eis_dimension +=   moebius(gcd(m // t, f)) \
                        * (t // t.squarefree_part()).isqrt() \
                        * (2 if (m // t) % 4 == 0 else 1) 
    eis_dimension = eis_dimension // len(ts)
    
    if k == 2 and f == 1 :
        eis_dimension -= len( (m // m.squarefree_part()).isqrt().divisors() ) 
    
    ## Cuspidal part
    cusp_dimension = 0
    
    tmp = ZZ(0)
    for t in ts :
        tmp += moebius(gcd(m // t, f)) * t
    tmp = tmp / len(ts)
    cusp_dimension += tmp * (2 * k - 3) / ZZ(12)
    print "1: ", cusp_dimension
    
    if m % 2 == 0 :
        tmp = ZZ(0)
        for t in ts :
            tmp += moebius(gcd(m // t, f)) * kronecker_symbol(-4, t)
        tmp = tmp / len(ts)
        
        cusp_dimension += 1/ZZ(2) * kronecker_symbol(8, 2 * k - 1) * tmp
        print "2: ", 1/ZZ(2) * kronecker_symbol(8, 2 * k - 1) * tmp
        
    tmp = ZZ(0)
    for t in ts :
        tmp += moebius(gcd(m // t, f)) * kronecker_symbol(t, 3)
    tmp = tmp / len(ts)
    if m % 3 != 0 :
        cusp_dimension += 1 / ZZ(3) * kronecker_symbol(k, 3) * tmp
        print ": ", 1 / ZZ(3) * kronecker_symbol(k, 3) * tmp
    elif k % 3 == 0 :
        cusp_dimension += 2 / ZZ(3) * (-1)**k * tmp
        print "3: ", 2 / ZZ(3) * (-1)**k * tmp
    else :
        cusp_dimension += 1 / ZZ(3) * (kronecker_symbol(k, 3) + (-1)**(k - 1)) * tmp
        print "3: ", 1 / ZZ(3) * (kronecker_symbol(k, 3) + (-1)**(k - 1)) * tmp
    
    tmp = ZZ(0)
    for t in ts :
        tmp +=   moebius(gcd(m // t, f)) \
               * (t // t.squarefree_part()).isqrt() \
               * (2 if (m // t) % 4 == 0 else 1)
    tmp = tmp / len(ts)
    cusp_dimension -= 1 / ZZ(2) * tmp
    print "4: ", -1 / ZZ(2) * tmp
    
    tmp = ZZ(0)
    for t in ts :
        tmp +=   moebius(gcd(m // t, f)) \
               * sum(   (( len(BinaryQF_reduced_representatives(-d, True))
                           if d not in [3, 4] else ( 1 / ZZ(3) if d == 3 else 1 / ZZ(2) ))
                         if d % 4 == 0 or d % 4 == 3 else 0 )
                      * kronecker_symbol(-d, m // t)
                      * ( 1 if (m // t) % 2 != 0 else
                          ( 4 if (m // t) % 4 == 0 else 2 * kronecker_symbol(-d, 2) ))
                      for d in (4 * m).divisors() )
    tmp = tmp / len(ts)
    cusp_dimension -= 1 / ZZ(2) * tmp
    print "5: ", -1 / ZZ(2) * tmp
    
    if k == 2 :
        cusp_dimension += len( (m // f // (m // f).squarefree_part()).isqrt().divisors() )
    
    return eis_dimension + cusp_dimension
Esempio n. 8
0
def dimension__jacobi_scalar_f(k, m, f):
    if moebius(f) != (-1)**k:
        return 0

    ## We use chapter 6 of Skoruppa's thesis
    ts = filter(lambda t: gcd(t, m // t) == 1, m.divisors())

    ## Eisenstein part
    eis_dimension = 0

    for t in ts:
        eis_dimension +=   moebius(gcd(m // t, f)) \
                        * (t // t.squarefree_part()).isqrt() \
                        * (2 if (m // t) % 4 == 0 else 1)
    eis_dimension = eis_dimension // len(ts)

    if k == 2 and f == 1:
        eis_dimension -= len((m // m.squarefree_part()).isqrt().divisors())

    ## Cuspidal part
    cusp_dimension = 0

    tmp = ZZ(0)
    for t in ts:
        tmp += moebius(gcd(m // t, f)) * t
    tmp = tmp / len(ts)
    cusp_dimension += tmp * (2 * k - 3) / ZZ(12)
    print "1: ", cusp_dimension

    if m % 2 == 0:
        tmp = ZZ(0)
        for t in ts:
            tmp += moebius(gcd(m // t, f)) * kronecker_symbol(-4, t)
        tmp = tmp / len(ts)

        cusp_dimension += 1 / ZZ(2) * kronecker_symbol(8, 2 * k - 1) * tmp
        print "2: ", 1 / ZZ(2) * kronecker_symbol(8, 2 * k - 1) * tmp

    tmp = ZZ(0)
    for t in ts:
        tmp += moebius(gcd(m // t, f)) * kronecker_symbol(t, 3)
    tmp = tmp / len(ts)
    if m % 3 != 0:
        cusp_dimension += 1 / ZZ(3) * kronecker_symbol(k, 3) * tmp
        print ": ", 1 / ZZ(3) * kronecker_symbol(k, 3) * tmp
    elif k % 3 == 0:
        cusp_dimension += 2 / ZZ(3) * (-1)**k * tmp
        print "3: ", 2 / ZZ(3) * (-1)**k * tmp
    else:
        cusp_dimension += 1 / ZZ(3) * (kronecker_symbol(k, 3) +
                                       (-1)**(k - 1)) * tmp
        print "3: ", 1 / ZZ(3) * (kronecker_symbol(k, 3) + (-1)**(k - 1)) * tmp

    tmp = ZZ(0)
    for t in ts:
        tmp +=   moebius(gcd(m // t, f)) \
               * (t // t.squarefree_part()).isqrt() \
               * (2 if (m // t) % 4 == 0 else 1)
    tmp = tmp / len(ts)
    cusp_dimension -= 1 / ZZ(2) * tmp
    print "4: ", -1 / ZZ(2) * tmp

    tmp = ZZ(0)
    for t in ts:
        tmp +=   moebius(gcd(m // t, f)) \
               * sum(   (( len(BinaryQF_reduced_representatives(-d, True))
                           if d not in [3, 4] else ( 1 / ZZ(3) if d == 3 else 1 / ZZ(2) ))
                         if d % 4 == 0 or d % 4 == 3 else 0 )
                      * kronecker_symbol(-d, m // t)
                      * ( 1 if (m // t) % 2 != 0 else
                          ( 4 if (m // t) % 4 == 0 else 2 * kronecker_symbol(-d, 2) ))
                      for d in (4 * m).divisors() )
    tmp = tmp / len(ts)
    cusp_dimension -= 1 / ZZ(2) * tmp
    print "5: ", -1 / ZZ(2) * tmp

    if k == 2:
        cusp_dimension += len(
            (m // f // (m // f).squarefree_part()).isqrt().divisors())

    return eis_dimension + cusp_dimension