def BinaryQF_reduced_representatives(D, primitive_only=False, proper=True): r""" Return representatives for the classes of binary quadratic forms of discriminant `D`. INPUT: - ``D`` -- (integer) a discriminant - ``primitive_only`` -- (boolean; default: ``True``): if ``True``, only return primitive forms. - ``proper`` -- (boolean; default: ``True``) OUTPUT: (list) A lexicographically-ordered list of inequivalent reduced representatives for the (im)proper equivalence classes of binary quadratic forms of discriminant `D`. If ``primitive_only`` is ``True`` then imprimitive forms (which only exist when `D` is not fundamental) are omitted; otherwise they are included. EXAMPLES:: sage: BinaryQF_reduced_representatives(-4) [x^2 + y^2] sage: BinaryQF_reduced_representatives(-163) [x^2 + x*y + 41*y^2] sage: BinaryQF_reduced_representatives(-12) [x^2 + 3*y^2, 2*x^2 + 2*x*y + 2*y^2] sage: BinaryQF_reduced_representatives(-16) [x^2 + 4*y^2, 2*x^2 + 2*y^2] sage: BinaryQF_reduced_representatives(-63) [x^2 + x*y + 16*y^2, 2*x^2 - x*y + 8*y^2, 2*x^2 + x*y + 8*y^2, 3*x^2 + 3*x*y + 6*y^2, 4*x^2 + x*y + 4*y^2] The number of inequivalent reduced binary forms with a fixed negative fundamental discriminant D is the class number of the quadratic field `\QQ(\sqrt{D})`:: sage: len(BinaryQF_reduced_representatives(-13*4)) 2 sage: QuadraticField(-13*4, 'a').class_number() 2 sage: p=next_prime(2^20); p 1048583 sage: len(BinaryQF_reduced_representatives(-p)) 689 sage: QuadraticField(-p, 'a').class_number() 689 sage: BinaryQF_reduced_representatives(-23*9) [x^2 + x*y + 52*y^2, 2*x^2 - x*y + 26*y^2, 2*x^2 + x*y + 26*y^2, 3*x^2 + 3*x*y + 18*y^2, 4*x^2 - x*y + 13*y^2, 4*x^2 + x*y + 13*y^2, 6*x^2 - 3*x*y + 9*y^2, 6*x^2 + 3*x*y + 9*y^2, 8*x^2 + 7*x*y + 8*y^2] sage: BinaryQF_reduced_representatives(-23*9, primitive_only=True) [x^2 + x*y + 52*y^2, 2*x^2 - x*y + 26*y^2, 2*x^2 + x*y + 26*y^2, 4*x^2 - x*y + 13*y^2, 4*x^2 + x*y + 13*y^2, 8*x^2 + 7*x*y + 8*y^2] TESTS:: sage: BinaryQF_reduced_representatives(73) [-4*x^2 + 3*x*y + 4*y^2, 4*x^2 + 3*x*y - 4*y^2] sage: BinaryQF_reduced_representatives(76, primitive_only=True) [-3*x^2 + 4*x*y + 5*y^2, 3*x^2 + 4*x*y - 5*y^2] Check that the primitive_only keyword does something:: sage: BinaryQF_reduced_representatives(4*5, primitive_only=True) [-x^2 + 4*x*y + y^2, x^2 + 4*x*y - y^2] sage: BinaryQF_reduced_representatives(4*5, primitive_only=False) [-2*x^2 + 2*x*y + 2*y^2, -x^2 + 4*x*y + y^2, x^2 + 4*x*y - y^2, 2*x^2 + 2*x*y - 2*y^2] """ D = ZZ(D) # For a fundamental discriminant all forms are primitive so we need not check: if primitive_only: primitive_only = not is_fundamental_discriminant(D) form_list = [] from sage.arith.srange import xsrange D4 = D % 4 if D4 == 2 or D4 == 3: raise ValueError("%s is not a discriminant" % D) if D > 0: # Indefinite if D.is_square(): b = D.sqrt() c = ZZ(0) # -b/2 < a <= b/2 for a in xsrange((-b/2).floor() + 1, (b/2).floor() + 1): Q = BinaryQF(a, b, c) form_list.append(Q) # We follow the description of Buchmann/Vollmer 6.7.1. They # enumerate all reduced forms. We only want representatives. else: sqrt_d = D.sqrt(prec=53) for b in xsrange(1, sqrt_d.floor() + 1): if (D - b) % 2: continue A = (D - b**2) / 4 Low_a = ((sqrt_d - b) / 2).ceil() High_a = (A.sqrt(prec=53)).floor() for a in xsrange(Low_a, High_a + 1): if a == 0: continue c = -A/a if c in ZZ: if (not primitive_only) or gcd([a, b, c])==1: Q = BinaryQF(a, b, c) Q1 = BinaryQF(-a, b, -c) form_list.append(Q) form_list.append(Q1) if a.abs() != c.abs(): Q = BinaryQF(c, b, a) Q1 = BinaryQF(-c, b, -a) form_list.append(Q) form_list.append(Q1) else: # Definite # Only iterate over positive a and over b of the same # parity as D such that 4a^2 + D <= b^2 <= a^2 for a in xsrange(1,1+((-D)//3).isqrt()): a4 = 4*a s = D + a*a4 w = 1+(s-1).isqrt() if s > 0 else 0 if w%2 != D%2: w += 1 for b in xsrange(w,a+1,2): t = b*b-D if t % a4 == 0: c = t // a4 if (not primitive_only) or gcd([a,b,c])==1: if b>0 and a>b and c>a: form_list.append(BinaryQF([a,-b,c])) form_list.append(BinaryQF([a,b,c])) if not proper or D > 0: # TODO: # instead of filtering, enumerate only improper classes to start with # filter for equivalence classes form_list_new = [] for q in form_list: if not any(q.is_equivalent(q1, proper=proper) for q1 in form_list_new): form_list_new.append(q) form_list = form_list_new form_list.sort() return form_list
def _eval_(self, n, x): """ The :meth:`_eval_()` method decides which evaluation suits best for the given input, and returns a proper value. EXAMPLES:: sage: var('n,x') (n, x) sage: chebyshev_T(5,x) 16*x^5 - 20*x^3 + 5*x sage: chebyshev_T(64, x) 2*(2*(2*(2*(2*(2*x^2 - 1)^2 - 1)^2 - 1)^2 - 1)^2 - 1)^2 - 1 sage: chebyshev_T(n,-1) (-1)^n sage: chebyshev_T(-7,x) 64*x^7 - 112*x^5 + 56*x^3 - 7*x sage: chebyshev_T(3/2,x) chebyshev_T(3/2, x) sage: R.<t> = QQ[] sage: chebyshev_T(2,t) 2*t^2 - 1 sage: chebyshev_U(2,t) 4*t^2 - 1 sage: parent(chebyshev_T(4, RIF(5))) Real Interval Field with 53 bits of precision sage: RR2 = RealField(5) sage: chebyshev_T(100000,RR2(2)) 8.9e57180 sage: chebyshev_T(5,Qp(3)(2)) 2 + 3^2 + 3^3 + 3^4 + 3^5 + O(3^20) sage: chebyshev_T(100001/2, 2) doctest:...: RuntimeWarning: mpmath failed, keeping expression unevaluated chebyshev_T(100001/2, 2) sage: chebyshev_U._eval_(1.5, Mod(8,9)) is None True """ # n is an integer => evaluate algebraically (as polynomial) if n in ZZ: n = ZZ(n) # Expanded symbolic expression only for small values of n if is_Expression(x) and n.abs() < 32: return self.eval_formula(n, x) return self.eval_algebraic(n, x) if is_Expression(x) or is_Expression(n): # Check for known identities try: return self._eval_special_values_(n, x) except ValueError: # Don't evaluate => keep symbolic return None # n is not an integer and neither n nor x is symbolic. # We assume n and x are real/complex and evaluate numerically try: import sage.libs.mpmath.all as mpmath return self._evalf_(n, x) except mpmath.NoConvergence: warnings.warn("mpmath failed, keeping expression unevaluated", RuntimeWarning) return None except Exception: # Numerical evaluation failed => keep symbolic return None