Example #1
0
    def small_prime_value(self, Bmax=1000):
        r"""
        Returns a prime represented by this (primitive positive definite) binary form.

        INPUT:

        - ``Bmax`` -- a positive bound on the representing integers.

        OUTPUT:

        A prime number represented by the form.

        .. note::

            This is a very elementary implementation which just substitutes
            values until a prime is found.

        EXAMPLES::

            sage: [Q.small_prime_value() for Q in BinaryQF_reduced_representatives(-23, primitive_only=True)]
            [23, 2, 2]
            sage: [Q.small_prime_value() for Q in BinaryQF_reduced_representatives(-47, primitive_only=True)]
            [47, 2, 2, 3, 3]
        """
        from sage.sets.all import Set
        from sage.misc.all import srange
        d = self.discriminant()
        B = 10
        while True:
            llist = list(Set([self(x,y) for x in srange(-B,B) for y in srange(B)]))
            llist = [l for l in llist if l.is_prime()]
            llist.sort()
            if llist:
                return llist[0]
            if B >= Bmax:
                raise ValueError("Unable to find a prime value of %s" % self)
            B += 10
Example #2
0
 def plot_fft(self, npoints=None, channel=0, half=True, **kwds):
     v = self.vector(npoints=npoints)
     w = v.fft()
     if half:
         w = w[:len(w) // 2]
     z = [abs(x) for x in w]
     if half:
         r = math.pi
     else:
         r = 2 * math.pi
     data = zip(srange(0, r, r / len(z)), z)
     L = list_plot(data, plotjoined=True, **kwds)
     L.xmin(0)
     L.xmax(r)
     return L
Example #3
0
 def plot_fft(self, npoints=None, channel=0, half=True, **kwds):
     v = self.vector(npoints=npoints)
     w = v.fft()
     if half:
         w = w[:len(w)//2]
     z = [abs(x) for x in w]
     if half:
         r = math.pi
     else:
         r = 2*math.pi
     data = zip(srange(0, r, r/len(z)),  z)
     L = list_plot(data, plotjoined=True, **kwds)
     L.xmin(0)
     L.xmax(r)
     return L
Example #4
0
    def solve_integer(self, n):
        r"""
        Solve `Q(x,y) = n` in integers `x` and `y` where `Q` is this
        quadratic form.

        INPUT:

        - ``Q`` (BinaryQF) -- a positive definite primitive integral
          binary quadratic form

        - ``n`` (int) -- a positive integer

        OUTPUT:

        A tuple (x,y) of integers satisfying `Q(x,y) = n` or ``None``
        if no such `x` and `y` exist.

        EXAMPLES::

            sage: Qs = BinaryQF_reduced_representatives(-23,primitive_only=True)
            sage: Qs
            [x^2 + x*y + 6*y^2, 2*x^2 - x*y + 3*y^2, 2*x^2 + x*y + 3*y^2]
            sage: [Q.solve_integer(3) for Q in Qs]
            [None, (0, 1), (0, 1)]
            sage: [Q.solve_integer(5) for Q in Qs]
            [None, None, None]
            sage: [Q.solve_integer(6) for Q in Qs]
            [(0, 1), (-1, 1), (1, 1)]
        """
        a, b, c = self
        d = self.discriminant()
        if d >= 0 or a <= 0:
            raise ValueError("%s is not positive definite" % self)
        ad = -d
        an4 = 4*a*n
        a2 = 2*a
        from sage.misc.all import srange
        for y in srange(0, 1+an4//ad):
            z2 = an4 + d*y**2
            for z in z2.sqrt(extend=False, all=True):
                if a2.divides(z-b*y):
                    x = (z-b*y)//a2
                    return (x,y)
        return None
Example #5
0
def enum_projective_rational_field(X,B):
    r"""
    Enumerates projective, rational points on scheme ``X`` of height up to
    bound ``B``.

    INPUT:

    - ``X`` -  a scheme or set of abstract rational points of a scheme;
    - ``B`` -  a positive integer bound.

    OUTPUT:

    - a list containing the projective points of ``X`` of height up to ``B``,
      sorted.

    EXAMPLES::

        sage: P.<X,Y,Z> = ProjectiveSpace(2,QQ)
        sage: C = P.subscheme([X+Y-Z])
        sage: from sage.schemes.projective.projective_rational_point import enum_projective_rational_field
        sage: enum_projective_rational_field(C(QQ),6)
        [(-5 : 6 : 1), (-4 : 5 : 1), (-3 : 4 : 1), (-2 : 3 : 1),
         (-3/2 : 5/2 : 1), (-1 : 1 : 0), (-1 : 2 : 1), (-2/3 : 5/3 : 1),
         (-1/2 : 3/2 : 1), (-1/3 : 4/3 : 1), (-1/4 : 5/4 : 1),
         (-1/5 : 6/5 : 1), (0 : 1 : 1), (1/6 : 5/6 : 1), (1/5 : 4/5 : 1),
         (1/4 : 3/4 : 1), (1/3 : 2/3 : 1), (2/5 : 3/5 : 1), (1/2 : 1/2 : 1),
         (3/5 : 2/5 : 1), (2/3 : 1/3 : 1), (3/4 : 1/4 : 1), (4/5 : 1/5 : 1),
         (5/6 : 1/6 : 1), (1 : 0 : 1), (6/5 : -1/5 : 1), (5/4 : -1/4 : 1),
         (4/3 : -1/3 : 1), (3/2 : -1/2 : 1), (5/3 : -2/3 : 1), (2 : -1 : 1),
         (5/2 : -3/2 : 1), (3 : -2 : 1), (4 : -3 : 1), (5 : -4 : 1),
         (6 : -5 : 1)]
        sage: enum_projective_rational_field(C,6) == enum_projective_rational_field(C(QQ),6)
        True

    ::

        sage: P3.<W,X,Y,Z> = ProjectiveSpace(3,QQ)
        sage: enum_projective_rational_field(P3,1)
        [(-1 : -1 : -1 : 1), (-1 : -1 : 0 : 1), (-1 : -1 : 1 : 0), (-1 : -1 : 1 : 1),
        (-1 : 0 : -1 : 1), (-1 : 0 : 0 : 1), (-1 : 0 : 1 : 0), (-1 : 0 : 1 : 1),
        (-1 : 1 : -1 : 1), (-1 : 1 : 0 : 0), (-1 : 1 : 0 : 1), (-1 : 1 : 1 : 0),
        (-1 : 1 : 1 : 1), (0 : -1 : -1 : 1), (0 : -1 : 0 : 1), (0 : -1 : 1 : 0),
        (0 : -1 : 1 : 1), (0 : 0 : -1 : 1), (0 : 0 : 0 : 1), (0 : 0 : 1 : 0),
        (0 : 0 : 1 : 1), (0 : 1 : -1 : 1), (0 : 1 : 0 : 0), (0 : 1 : 0 : 1),
        (0 : 1 : 1 : 0), (0 : 1 : 1 : 1), (1 : -1 : -1 : 1), (1 : -1 : 0 : 1),
        (1 : -1 : 1 : 0), (1 : -1 : 1 : 1), (1 : 0 : -1 : 1), (1 : 0 : 0 : 0),
        (1 : 0 : 0 : 1), (1 : 0 : 1 : 0), (1 : 0 : 1 : 1), (1 : 1 : -1 : 1),
        (1 : 1 : 0 : 0), (1 : 1 : 0 : 1), (1 : 1 : 1 : 0), (1 : 1 : 1 : 1)]

    ALGORITHM:

    We just check all possible projective points in correct dimension
    of projective space to see if they lie on ``X``.

    AUTHORS:

    - John Cremona and Charlie Turner (06-2010)
    """
    from sage.schemes.projective.projective_space import is_ProjectiveSpace
    if(is_Scheme(X)):
        if (not is_ProjectiveSpace(X.ambient_space())):
            raise TypeError("Ambient space must be projective space over the rational field")
        X = X(X.base_ring())
    else:
        if (not is_ProjectiveSpace(X.codomain().ambient_space())):
            raise TypeError("Codomain must be projective space over the rational field")

    n = X.codomain().ambient_space().ngens()
    zero = (0,) * n
    pts = []
    for c in cartesian_product_iterator([srange(-B,B+1) for _ in range(n)]):
        if gcd(c) == 1 and c > zero:
            try:
                pts.append(X(c))
            except TypeError:
                pass
    pts.sort()
    return pts
Example #6
0
def bsgs(a, b, bounds, operation='*', identity=None, inverse=None, op=None):
    r"""
    Totally generic discrete baby-step giant-step function.

    Solves `na=b` (or `a^n=b`) with `lb\le n\le ub` where ``bounds==(lb,ub)``,
    raising an error if no such `n` exists.

    `a` and `b` must be elements of some group with given identity,
    inverse of ``x`` given by ``inverse(x)``, and group operation on
    ``x``, ``y`` by ``op(x,y)``.

    If operation is '*' or '+' then the other
    arguments are provided automatically; otherwise they must be
    provided by the caller.

    INPUT:

    - ``a``    - group element
    - ``b``    - group element
    - ``bounds`` - a 2-tuple of integers ``(lower,upper)`` with ``0<=lower<=upper``
    - ``operation`` - string: '*', '+', 'other'
    - ``identity`` - the identity element of the group
    - ``inverse()``  - function of 1 argument ``x`` returning inverse of ``x``
    - ``op()`` - function of 2 arguments ``x``, ``y`` returning ``x*y`` in group

    OUTPUT:

    An integer `n` such that `a^n = b` (or `na = b`).  If no
    such `n` exists, this function raises a ValueError exception.

    NOTE: This is a generalization of discrete logarithm.  One
    situation where this version is useful is to find the order of
    an element in a group where we only have bounds on the group
    order (see the elliptic curve example below).

    ALGORITHM: Baby step giant step.  Time and space are soft
    `O(\sqrt{n})` where `n` is the difference between upper and lower
    bounds.

    EXAMPLES::

        sage: b = Mod(2,37);  a = b^20
        sage: bsgs(b, a, (0,36))
        20

        sage: p=next_prime(10^20)
        sage: a=Mod(2,p); b=a^(10^25)
        sage: bsgs(a, b, (10^25-10^6,10^25+10^6)) == 10^25
        True

        sage: K = GF(3^6,'b')
        sage: a = K.gen()
        sage: b = a^210
        sage: bsgs(a, b, (0,K.order()-1))
        210

        sage: K.<z>=CyclotomicField(230)
        sage: w=z^500
        sage: bsgs(z,w,(0,229))
        40

    An additive example in an elliptic curve group::

        sage: F.<a> = GF(37^5)
        sage: E = EllipticCurve(F, [1,1])
        sage: P = E.lift_x(a); P
        (a : 28*a^4 + 15*a^3 + 14*a^2 + 7 : 1)

    This will return a multiple of the order of P::

        sage: bsgs(P,P.parent()(0),Hasse_bounds(F.order()),operation='+')
        69327408

    AUTHOR:

        - John Cremona (2008-03-15)
    """
    Z = integer_ring.ZZ

    from operator import inv, mul, neg, add

    if operation in multiplication_names:
        identity = a.parent()(1)
        inverse = inv
        op = mul
    elif operation in addition_names:
        identity = a.parent()(0)
        inverse = neg
        op = add
    else:
        if identity is None or inverse is None or op is None:
            raise ValueError("identity, inverse and operation must be given")

    lb, ub = bounds
    if lb < 0 or ub < lb:
        raise ValueError("bsgs() requires 0<=lb<=ub")

    if a.is_zero() and not b.is_zero():
        raise ValueError("No solution in bsgs()")

    ran = 1 + ub - lb  # the length of the interval

    c = op(inverse(b), multiple(a, lb, operation=operation))

    if ran < 30:  # use simple search for small ranges
        i = lb
        d = c
        #        for i,d in multiples(a,ran,c,indexed=True,operation=operation):
        for i0 in range(ran):
            i = lb + i0
            if identity == d:  # identity == b^(-1)*a^i, so return i
                return Z(i)
            d = op(a, d)
        raise ValueError("No solution in bsgs()")

    m = ran.isqrt() + 1  # we need sqrt(ran) rounded up
    table = dict()  # will hold pairs (a^(lb+i),lb+i) for i in range(m)

    d = c
    for i0 in misc.srange(m):
        i = lb + i0
        if identity == d:  # identity == b^(-1)*a^i, so return i
            return Z(i)
        table[d] = i
        d = op(d, a)

    c = op(c, inverse(d))  # this is now a**(-m)
    d = identity
    for i in misc.srange(m):
        j = table.get(d)
        if j is not None:  # then d == b*a**(-i*m) == a**j
            return Z(i * m + j)
        d = op(c, d)

    raise ValueError("Log of %s to the base %s does not exist in %s." %
                     (b, a, bounds))
Example #7
0
def enum_projective_rational_field(X, B):
    r"""
    Enumerates projective, rational points on scheme ``X`` of height up to
    bound ``B``.

    INPUT:

    - ``X`` -  a scheme or set of abstract rational points of a scheme;
    - ``B`` -  a positive integer bound.

    OUTPUT:

    - a list containing the projective points of ``X`` of height up to ``B``,
      sorted.

    EXAMPLES::

        sage: P.<X,Y,Z> = ProjectiveSpace(2,QQ)
        sage: C = P.subscheme([X+Y-Z])
        sage: from sage.schemes.projective.projective_rational_point import enum_projective_rational_field
        sage: enum_projective_rational_field(C(QQ),6)
        [(-5 : 6 : 1), (-4 : 5 : 1), (-3 : 4 : 1), (-2 : 3 : 1),
         (-3/2 : 5/2 : 1), (-1 : 1 : 0), (-1 : 2 : 1), (-2/3 : 5/3 : 1),
         (-1/2 : 3/2 : 1), (-1/3 : 4/3 : 1), (-1/4 : 5/4 : 1),
         (-1/5 : 6/5 : 1), (0 : 1 : 1), (1/6 : 5/6 : 1), (1/5 : 4/5 : 1),
         (1/4 : 3/4 : 1), (1/3 : 2/3 : 1), (2/5 : 3/5 : 1), (1/2 : 1/2 : 1),
         (3/5 : 2/5 : 1), (2/3 : 1/3 : 1), (3/4 : 1/4 : 1), (4/5 : 1/5 : 1),
         (5/6 : 1/6 : 1), (1 : 0 : 1), (6/5 : -1/5 : 1), (5/4 : -1/4 : 1),
         (4/3 : -1/3 : 1), (3/2 : -1/2 : 1), (5/3 : -2/3 : 1), (2 : -1 : 1),
         (5/2 : -3/2 : 1), (3 : -2 : 1), (4 : -3 : 1), (5 : -4 : 1),
         (6 : -5 : 1)]
        sage: enum_projective_rational_field(C,6) == enum_projective_rational_field(C(QQ),6)
        True

    ::

        sage: P3.<W,X,Y,Z> = ProjectiveSpace(3,QQ)
        sage: enum_projective_rational_field(P3,1)
        [(-1 : -1 : -1 : 1), (-1 : -1 : 0 : 1), (-1 : -1 : 1 : 0), (-1 : -1 : 1 : 1),
        (-1 : 0 : -1 : 1), (-1 : 0 : 0 : 1), (-1 : 0 : 1 : 0), (-1 : 0 : 1 : 1),
        (-1 : 1 : -1 : 1), (-1 : 1 : 0 : 0), (-1 : 1 : 0 : 1), (-1 : 1 : 1 : 0),
        (-1 : 1 : 1 : 1), (0 : -1 : -1 : 1), (0 : -1 : 0 : 1), (0 : -1 : 1 : 0),
        (0 : -1 : 1 : 1), (0 : 0 : -1 : 1), (0 : 0 : 0 : 1), (0 : 0 : 1 : 0),
        (0 : 0 : 1 : 1), (0 : 1 : -1 : 1), (0 : 1 : 0 : 0), (0 : 1 : 0 : 1),
        (0 : 1 : 1 : 0), (0 : 1 : 1 : 1), (1 : -1 : -1 : 1), (1 : -1 : 0 : 1),
        (1 : -1 : 1 : 0), (1 : -1 : 1 : 1), (1 : 0 : -1 : 1), (1 : 0 : 0 : 0),
        (1 : 0 : 0 : 1), (1 : 0 : 1 : 0), (1 : 0 : 1 : 1), (1 : 1 : -1 : 1),
        (1 : 1 : 0 : 0), (1 : 1 : 0 : 1), (1 : 1 : 1 : 0), (1 : 1 : 1 : 1)]

    ALGORITHM:

    We just check all possible projective points in correct dimension
    of projective space to see if they lie on ``X``.

    AUTHORS:

    - John Cremona and Charlie Turner (06-2010)
    """
    if is_Scheme(X):
        X = X(X.base_ring())
    n = X.codomain().ambient_space().ngens()
    zero = (0, ) * n
    pts = []
    for c in cartesian_product_iterator([srange(-B, B + 1) for _ in range(n)]):
        if gcd(c) == 1 and c > zero:
            try:
                pts.append(X(c))
            except TypeError:
                pass
    pts.sort()
    return pts
Example #8
0
def bsgs(a, b, bounds, operation='*', identity=None, inverse=None, op=None):
    r"""
    Totally generic discrete baby-step giant-step function.

    Solves `na=b` (or `a^n=b`) with `lb\le n\le ub` where ``bounds==(lb,ub)``,
    raising an error if no such `n` exists.

    `a` and `b` must be elements of some group with given identity,
    inverse of ``x`` given by ``inverse(x)``, and group operation on
    ``x``, ``y`` by ``op(x,y)``.

    If operation is '*' or '+' then the other
    arguments are provided automatically; otherwise they must be
    provided by the caller.

    INPUT:

    - ``a``    - group element
    - ``b``    - group element
    - ``bounds`` - a 2-tuple of integers ``(lower,upper)`` with ``0<=lower<=upper``
    - ``operation`` - string: '*', '+', 'other'
    - ``identity`` - the identity element of the group
    - ``inverse()``  - function of 1 argument ``x`` returning inverse of ``x``
    - ``op()`` - function of 2 arguments ``x``, ``y`` returning ``x*y`` in group

    OUTPUT:

    An integer `n` such that `a^n = b` (or `na = b`).  If no
    such `n` exists, this function raises a ValueError exception.

    NOTE: This is a generalization of discrete logarithm.  One
    situation where this version is useful is to find the order of
    an element in a group where we only have bounds on the group
    order (see the elliptic curve example below).

    ALGORITHM: Baby step giant step.  Time and space are soft
    `O(\sqrt{n})` where `n` is the difference between upper and lower
    bounds.

    EXAMPLES::

        sage: b = Mod(2,37);  a = b^20
        sage: bsgs(b, a, (0,36))
        20

        sage: p=next_prime(10^20)
        sage: a=Mod(2,p); b=a^(10^25)
        sage: bsgs(a, b, (10^25-10^6,10^25+10^6)) == 10^25
        True

        sage: K = GF(3^6,'b')
        sage: a = K.gen()
        sage: b = a^210
        sage: bsgs(a, b, (0,K.order()-1))
        210

        sage: K.<z>=CyclotomicField(230)
        sage: w=z^500
        sage: bsgs(z,w,(0,229))
        40

    An additive example in an elliptic curve group::

        sage: F.<a> = GF(37^5)
        sage: E = EllipticCurve(F, [1,1])
        sage: P = E.lift_x(a); P
        (a : 28*a^4 + 15*a^3 + 14*a^2 + 7 : 1)

    This will return a multiple of the order of P::

        sage: bsgs(P,P.parent()(0),Hasse_bounds(F.order()),operation='+')
        69327408

    AUTHOR:

        - John Cremona (2008-03-15)
    """
    Z = integer_ring.ZZ

    from operator import inv, mul, neg, add

    if operation in multiplication_names:
        identity = a.parent()(1)
        inverse  = inv
        op = mul
    elif operation in addition_names:
        identity = a.parent()(0)
        inverse  = neg
        op = add
    else:
        if identity is None or inverse is None or op is None:
            raise ValueError("identity, inverse and operation must be given")

    lb, ub = bounds
    if lb<0 or ub<lb:
        raise ValueError("bsgs() requires 0<=lb<=ub")

    if a.is_zero() and not b.is_zero():
        raise ValueError("No solution in bsgs()")

    ran = 1 + ub - lb   # the length of the interval

    c = op(inverse(b),multiple(a,lb,operation=operation))

    if ran < 30:    # use simple search for small ranges
        i = lb
        d = c
#        for i,d in multiples(a,ran,c,indexed=True,operation=operation):
        for i0 in range(ran):
            i = lb + i0
            if identity == d:        # identity == b^(-1)*a^i, so return i
                return Z(i)
            d = op(a,d)
        raise ValueError("No solution in bsgs()")

    m = ran.isqrt()+1  # we need sqrt(ran) rounded up
    table = dict()     # will hold pairs (a^(lb+i),lb+i) for i in range(m)

    d=c
    for i0 in misc.srange(m):
        i = lb + i0
        if identity==d:        # identity == b^(-1)*a^i, so return i
            return Z(i)
        table[d] = i
        d=op(d,a)

    c = op(c,inverse(d))     # this is now a**(-m)
    d=identity
    for i in misc.srange(m):
        j = table.get(d)
        if j is not None:  # then d == b*a**(-i*m) == a**j
            return Z(i*m + j)
        d=op(c,d)

    raise ValueError("Log of %s to the base %s does not exist in %s."%(b,a,bounds))