示例#1
0
def num_cusps_of_width(N, d) -> Integer:
    r"""
    Return the number of cusps on `X_0(N)` of width ``d``.

    INPUT:

    -  ``N`` -- (integer): the level

    -  ``d`` -- (integer): an integer dividing N, the cusp width

    EXAMPLES::

        sage: from sage.modular.etaproducts import num_cusps_of_width
        sage: [num_cusps_of_width(18,d) for d in divisors(18)]
        [1, 1, 2, 2, 1, 1]
        sage: num_cusps_of_width(4,8)
        Traceback (most recent call last):
        ...
        ValueError: N and d must be positive integers with d|N
    """
    N = ZZ(N)
    d = ZZ(d)
    if N <= 0 or d <= 0 or N % d:
        raise ValueError("N and d must be positive integers with d|N")

    return euler_phi(d.gcd(N // d))
class Small_primes_of_degree_one_iter():
    r"""
    Iterator that finds primes of a number field of absolute degree
    one and bounded small prime norm.

    INPUT:

    - ``field`` -- a ``NumberField``.

    - ``num_integer_primes`` (default: 10000) -- an integer.  We try to find
      primes of absolute norm no greater than the
      ``num_integer_primes``-th prime number. For example, if
      ``num_integer_primes`` is 2, the largest norm found will be 3, since
      the second prime is 3.

    - ``max_iterations`` (default: 100) -- an integer. We test
      ``max_iterations`` integers to find small primes before raising
      ``StopIteration``.

    AUTHOR:

    - Nick Alexander
    """
    def __init__(self, field, num_integer_primes=10000, max_iterations=100):
        r"""
        Construct a new iterator of small degree one primes.

        EXAMPLES::

            sage: x = QQ['x'].gen()
            sage: K.<a> = NumberField(x^2 - 3)
            sage: K.primes_of_degree_one_list(3) # random
            [Fractional ideal (2*a + 1), Fractional ideal (-a + 4), Fractional ideal (3*a + 2)]
        """
        self._field = field
        self._poly = self._field.absolute_field('b').defining_polynomial()
        self._poly = ZZ['x'](self._poly.denominator() * self._poly()) # make integer polynomial
        self._lc = self._poly.leading_coefficient()

        # this uses that [ O_K : Z[a] ]^2 = | disc(f(x)) / disc(O_K) |
        from sage.libs.pari.all import pari
        self._prod_of_small_primes = ZZ(pari('TEMPn = %s; TEMPps = primes(TEMPn); prod(X = 1, TEMPn, TEMPps[X])' % num_integer_primes))
        self._prod_of_small_primes //= self._prod_of_small_primes.gcd(self._poly.discriminant() * self._lc)

        self._integer_iter = iter(ZZ)
        self._queue = []
        self._max_iterations = max_iterations

    def __iter__(self):
        r"""
        Return self as an iterator.

        EXAMPLES::

            sage: x = QQ['x'].gen()
            sage: K.<a> = NumberField(x^2 - 3)
            sage: it = K.primes_of_degree_one_iter()
            sage: iter(it) == it # indirect doctest
            True
        """
        return self

    def _lengthen_queue(self):
        r"""
        Try to find more primes of absolute degree one of small prime
        norm.

        Checks \code{self._max_iterations} integers before failing.

        WARNING:

            Internal function.  Not for external use!

        EXAMPLES::

            sage: x = QQ['x'].gen()
            sage: K.<a> = NumberField(x^2 - 3)
            sage: Ps = K.primes_of_degree_one_list(20, max_iterations=3) # indirect doctest
            sage: len(Ps) == 20
            True
        """
        count = 0
        while count < self._max_iterations:
            n = next(self._integer_iter)
            g = self._prod_of_small_primes.gcd(self._poly(n))
            self._prod_of_small_primes //= g
            self._queue = self._queue + [ (p, n) for p in g.prime_divisors() ]
            count += 1
        self._queue.sort() # sorts in ascending order

    def __next__(self):
        r"""
        Return a prime of absolute degree one of small prime norm.

        Raises ``StopIteration`` if such a prime cannot be easily found.

        EXAMPLES::

            sage: x = QQ['x'].gen()
            sage: K.<a> = NumberField(x^2 - 3)
            sage: it = K.primes_of_degree_one_iter()
            sage: [ next(it) for i in range(3) ] # random
            [Fractional ideal (2*a + 1), Fractional ideal (-a + 4), Fractional ideal (3*a + 2)]

        TESTS:

        We test that :trac:`6396` is fixed. Note that the doctest is
        flagged as random since the string representation of ideals is
        somewhat unpredictable::

            sage: N.<a,b> = NumberField([x^2 + 1, x^2 - 5])
            sage: ids = N.primes_of_degree_one_list(10); ids  # random
            [Fractional ideal ((-1/2*b + 1/2)*a + 2),
             Fractional ideal (-b*a + 1/2*b + 1/2),
             Fractional ideal ((1/2*b + 3/2)*a - b),
             Fractional ideal ((-1/2*b - 3/2)*a + b - 1),
             Fractional ideal (-b*a - b + 1),
             Fractional ideal (3*a + 1/2*b - 1/2),
             Fractional ideal ((-3/2*b + 1/2)*a + 1/2*b - 1/2),
             Fractional ideal ((-1/2*b - 5/2)*a - b + 1),
             Fractional ideal (2*a - 3/2*b - 1/2),
             Fractional ideal (3*a + 1/2*b + 5/2)]
             sage: [x.absolute_norm() for x in ids]
             [29, 41, 61, 89, 101, 109, 149, 181, 229, 241]
             sage: ids[9] == N.ideal(3*a + 1/2*b + 5/2)
             True
        
        We test that :trac:`23468` is fixed::

            sage: R.<z> = QQ[]
            sage: K.<y> = QQ.extension(25*z^2 + 26*z + 5)
            sage: for p in K.primes_of_degree_one_list(10):
            ....:     assert p.is_prime()
        """
        if not self._queue:
            self._lengthen_queue()
        if not self._queue:
            raise StopIteration

        p, n = self._queue.pop(0)
        x = self._field.absolute_generator()
        return self._field.ideal([p, (x - n) * self._lc])

    next = __next__
示例#3
0
def find_m(n, k, bound = None, b = 1):
    '''
    INPUT :

    - ``n`` -- an integer, the degree,

    - ``k`` -- a finite field, the base field,

    - ``bound`` -- (default : None) a positive integer used as the max for m.

    OUTPUT :

    - A tuple containing an integer and a set of class modulo m.

    EXAMPLES :

    sage: find_m(281, GF(1747))

    (3373, {4, 14, 18, 43, 57, 3325, 3337, 3348, 3354, 3357, 3364})

    sage: find_m(23, GF(11))

    (47, {0, 1, 2, 3, 44, 45, 46})

    ALGORITHM :
    
    First and foremost we are looking for an integer m for which n | phi(m). A 
    good way to obtain such integers is to look for prime power of  the form 

    m = an + 1, 

    because then phi(m) = d.(an) which is divisible by n. We also want phi(m) 
    to be coprime with n, then choosing m to be a prime (which is possible 
    thanks to Dirichlet's theorem on the arithmetic progressions) we ensure 
    that it is actually the case.

    It still works fine, theoratically, if an + 1 is a prime power and d isn't 
    divisble by n. Though, we almost always get to pick a m that is prime.
    
    Once we have that integer, we try to compute good candidates for the 
    traces and see how many works. If less than a certain number works (this 
    number is equal to 1 at the moment), we discard it and test the next prime 
    power. When one is found, we return it with its trace class candidates.
    '''
    if bound is None:
        bound_a = 100 # Arbitrary value.  
    else:
        # if m = a*n + 1 < b, then a < (b- 1)/n.
        bound_a = (bound - 1) / n 

    for a in range(bound_a):
        m = a*n + b
        try:
            euphin = ZZ(euler_phi(m)/n)
        except TypeError:
            continue
        # m composite not implemented yet
        if not m.is_prime():
            continue 
        #elif euphin == 1:
        #    temp = find_m(n, k, b = b+1)
        #    if temp  == None:
        #        continue
        #    else:
        #       return temp
        elif euphin.gcd(n) != 1:
            continue
        else:
            S_t = find_trace(n, m, k)
            # Some time in the future we'd like to have a 
            # better bound than just 1.
            if len(S_t) < 1:   
                continue       
            else:
                return m, S_t, 0