示例#1
0
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
示例#2
0
    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
示例#3
0
    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