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
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
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
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
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
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))
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
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))