Binary quadratic forms with integer coefficients¶
This module provides a specialized class for working with a binary quadratic form \(a x^2 + b x y + c y^2\), stored as a triple of integers \((a, b, c)\).
EXAMPLES:
sage: Q = BinaryQF([1, 2, 3])
sage: Q
x^2 + 2*x*y  + 3*y^2
sage: Q.discriminant()
-8
sage: Q.reduced_form()                                                              # needs sage.libs.pari
x^2 + 2*y^2
sage: Q(1, 1)
6
>>> from sage.all import *
>>> Q = BinaryQF([Integer(1), Integer(2), Integer(3)])
>>> Q
x^2 + 2*x*y  + 3*y^2
>>> Q.discriminant()
-8
>>> Q.reduced_form()                                                              # needs sage.libs.pari
x^2 + 2*y^2
>>> Q(Integer(1), Integer(1))
6
AUTHORS:
- Jon Hanke (2006-08-08): - Appended to add the methods - BinaryQF_reduced_representatives(),- is_reduced(), and- __add__on 8-3-2006 for Coding Sprint #2.
- Added Documentation and - complex_point()method on 8-8-2006.
 
- Nick Alexander: add doctests and clean code for Doc Days 2 
- William Stein (2009-08-05): composition; some ReSTification. 
- William Stein (2009-09-18): make immutable. 
- Justin C. Walker (2011-02-06): Add support for indefinite forms. 
- class sage.quadratic_forms.binary_qf.BinaryQF(a, b=None, c=None)[source]¶
- Bases: - SageObject- A binary quadratic form over \(\ZZ\). - INPUT: - One of the following: - a– either a 3-tuple of integers, or a quadratic homogeneous polynomial in two variables with integer coefficients
- a,- b,- c– three integers
 - OUTPUT: the binary quadratic form \(a x^2 + b xy + c y^2\) - EXAMPLES: - sage: b = BinaryQF([1, 2, 3]) sage: b.discriminant() -8 sage: b1 = BinaryQF(1, 2, 3) sage: b1 == b True sage: R.<x, y> = ZZ[] sage: BinaryQF(x^2 + 2*x*y + 3*y^2) == b True sage: BinaryQF(1, 0, 1) x^2 + y^2 - >>> from sage.all import * >>> b = BinaryQF([Integer(1), Integer(2), Integer(3)]) >>> b.discriminant() -8 >>> b1 = BinaryQF(Integer(1), Integer(2), Integer(3)) >>> b1 == b True >>> R = ZZ['x, y']; (x, y,) = R._first_ngens(2) >>> BinaryQF(x**Integer(2) + Integer(2)*x*y + Integer(3)*y**Integer(2)) == b True >>> BinaryQF(Integer(1), Integer(0), Integer(1)) x^2 + y^2 - complex_point()[source]¶
- Return the point in the complex upper half-plane associated to - self.- This form, \(ax^2 + b xy + cy^2\), must be definite with negative discriminant \(b^2 - 4 a c < 0\). - OUTPUT: - the unique complex root of \(a x^2 + b x + c\) with positive imaginary part 
 - EXAMPLES: - sage: Q = BinaryQF([1, 0, 1]) sage: Q.complex_point() # needs sage.libs.pari 1.00000000000000*I - >>> from sage.all import * >>> Q = BinaryQF([Integer(1), Integer(0), Integer(1)]) >>> Q.complex_point() # needs sage.libs.pari 1.00000000000000*I 
 - content()[source]¶
- Return the content of the form, i.e., the \(\gcd\) of the coefficients. - EXAMPLES: - sage: Q = BinaryQF(22, 14, 10) sage: Q.content() 2 sage: Q = BinaryQF(4, 4, -15) sage: Q.content() 1 - >>> from sage.all import * >>> Q = BinaryQF(Integer(22), Integer(14), Integer(10)) >>> Q.content() 2 >>> Q = BinaryQF(Integer(4), Integer(4), -Integer(15)) >>> Q.content() 1 
 - cycle(proper=False)[source]¶
- Return the cycle of reduced forms to which - selfbelongs.- This is based on Algorithm 6.1 of [BUVO2007]. - INPUT: - self– reduced, indefinite form of non-square discriminant
- proper– boolean (default:- False); if- True, return the proper cycle
 - The proper cycle of a form \(f\) consists of all reduced forms that are properly equivalent to \(f\). This is useful when testing for proper equivalence (or equivalence) between indefinite forms. - The cycle of \(f\) is a technical tool that is used when computing the proper cycle. Our definition of the cycle is slightly different from the one in [BUVO2007]. In our definition, the cycle consists of all reduced forms \(g\), such that the \(a\)-coefficient of \(g\) has the same sign as the \(a\)-coefficient of \(f\), and \(g\) can be obtained from \(f\) by performing a change of variables, and then multiplying by the determinant of the change-of-variables matrix. It is important to note that \(g\) might not be equivalent to \(f\) (because of multiplying by the determinant). However, either \(g\) or \(-g\) must be equivalent to \(f\). Also note that the cycle does contain \(f\). (Under the definition in [BUVO2007], the cycle might not contain \(f\), because all forms in the cycle are required to have positive \(a\)-coefficient, even if the \(a\)-coefficient of \(f\) is negative.) - EXAMPLES: - sage: Q = BinaryQF(14, 17, -2) sage: Q.cycle() [14*x^2 + 17*x*y - 2*y^2, 2*x^2 + 19*x*y - 5*y^2, 5*x^2 + 11*x*y - 14*y^2] sage: Q.cycle(proper=True) [14*x^2 + 17*x*y - 2*y^2, -2*x^2 + 19*x*y + 5*y^2, 5*x^2 + 11*x*y - 14*y^2, -14*x^2 + 17*x*y + 2*y^2, 2*x^2 + 19*x*y - 5*y^2, -5*x^2 + 11*x*y + 14*y^2] sage: Q = BinaryQF(1, 8, -3) sage: Q.cycle() [x^2 + 8*x*y - 3*y^2, 3*x^2 + 4*x*y - 5*y^2, 5*x^2 + 6*x*y - 2*y^2, 2*x^2 + 6*x*y - 5*y^2, 5*x^2 + 4*x*y - 3*y^2, 3*x^2 + 8*x*y - y^2] sage: Q.cycle(proper=True) [x^2 + 8*x*y - 3*y^2, -3*x^2 + 4*x*y + 5*y^2, 5*x^2 + 6*x*y - 2*y^2, -2*x^2 + 6*x*y + 5*y^2, 5*x^2 + 4*x*y - 3*y^2, -3*x^2 + 8*x*y + y^2] sage: Q = BinaryQF(1, 7, -6) sage: Q.cycle() [x^2 + 7*x*y - 6*y^2, 6*x^2 + 5*x*y - 2*y^2, 2*x^2 + 7*x*y - 3*y^2, 3*x^2 + 5*x*y - 4*y^2, 4*x^2 + 3*x*y - 4*y^2, 4*x^2 + 5*x*y - 3*y^2, 3*x^2 + 7*x*y - 2*y^2, 2*x^2 + 5*x*y - 6*y^2, 6*x^2 + 7*x*y - y^2] - >>> from sage.all import * >>> Q = BinaryQF(Integer(14), Integer(17), -Integer(2)) >>> Q.cycle() [14*x^2 + 17*x*y - 2*y^2, 2*x^2 + 19*x*y - 5*y^2, 5*x^2 + 11*x*y - 14*y^2] >>> Q.cycle(proper=True) [14*x^2 + 17*x*y - 2*y^2, -2*x^2 + 19*x*y + 5*y^2, 5*x^2 + 11*x*y - 14*y^2, -14*x^2 + 17*x*y + 2*y^2, 2*x^2 + 19*x*y - 5*y^2, -5*x^2 + 11*x*y + 14*y^2] >>> Q = BinaryQF(Integer(1), Integer(8), -Integer(3)) >>> Q.cycle() [x^2 + 8*x*y - 3*y^2, 3*x^2 + 4*x*y - 5*y^2, 5*x^2 + 6*x*y - 2*y^2, 2*x^2 + 6*x*y - 5*y^2, 5*x^2 + 4*x*y - 3*y^2, 3*x^2 + 8*x*y - y^2] >>> Q.cycle(proper=True) [x^2 + 8*x*y - 3*y^2, -3*x^2 + 4*x*y + 5*y^2, 5*x^2 + 6*x*y - 2*y^2, -2*x^2 + 6*x*y + 5*y^2, 5*x^2 + 4*x*y - 3*y^2, -3*x^2 + 8*x*y + y^2] >>> Q = BinaryQF(Integer(1), Integer(7), -Integer(6)) >>> Q.cycle() [x^2 + 7*x*y - 6*y^2, 6*x^2 + 5*x*y - 2*y^2, 2*x^2 + 7*x*y - 3*y^2, 3*x^2 + 5*x*y - 4*y^2, 4*x^2 + 3*x*y - 4*y^2, 4*x^2 + 5*x*y - 3*y^2, 3*x^2 + 7*x*y - 2*y^2, 2*x^2 + 5*x*y - 6*y^2, 6*x^2 + 7*x*y - y^2] 
 - det()[source]¶
- Return the determinant of the matrix associated to - self.- The determinant is used by Gauss and by Conway-Sloane, for whom an integral quadratic form has coefficients \((a, 2b, c)\) with \(a\), \(b\), \(c\) integers. - OUTPUT: the determinant of the matrix: - [ a b/2] [b/2 c] - as a rational. - REMARK: - This is just \(-D/4\) where \(D\) is the discriminant. The return type is rational even if \(b\) (and hence \(D\)) is even. - EXAMPLES: - sage: q = BinaryQF(1, -1, 67) sage: q.determinant() 267/4 - >>> from sage.all import * >>> q = BinaryQF(Integer(1), -Integer(1), Integer(67)) >>> q.determinant() 267/4 
 - determinant()[source]¶
- Return the determinant of the matrix associated to - self.- The determinant is used by Gauss and by Conway-Sloane, for whom an integral quadratic form has coefficients \((a, 2b, c)\) with \(a\), \(b\), \(c\) integers. - OUTPUT: the determinant of the matrix: - [ a b/2] [b/2 c] - as a rational. - REMARK: - This is just \(-D/4\) where \(D\) is the discriminant. The return type is rational even if \(b\) (and hence \(D\)) is even. - EXAMPLES: - sage: q = BinaryQF(1, -1, 67) sage: q.determinant() 267/4 - >>> from sage.all import * >>> q = BinaryQF(Integer(1), -Integer(1), Integer(67)) >>> q.determinant() 267/4 
 - discriminant()[source]¶
- Return the discriminant of - self.- Given a form \(ax^2 + bxy + cy^2\), this returns \(b^2 - 4ac\). - EXAMPLES: - sage: Q = BinaryQF([1, 2, 3]) sage: Q.discriminant() -8 - >>> from sage.all import * >>> Q = BinaryQF([Integer(1), Integer(2), Integer(3)]) >>> Q.discriminant() -8 
 - form_class()[source]¶
- Return the class of this form modulo equivalence. - EXAMPLES: - sage: F = BinaryQF([3, -16, 161]) sage: cl = F.form_class(); cl Class of 3*x^2 + 2*x*y + 140*y^2 sage: cl.parent() Form Class Group of Discriminant -1676 sage: cl.parent() is BQFClassGroup(-4*419) True - >>> from sage.all import * >>> F = BinaryQF([Integer(3), -Integer(16), Integer(161)]) >>> cl = F.form_class(); cl Class of 3*x^2 + 2*x*y + 140*y^2 >>> cl.parent() Form Class Group of Discriminant -1676 >>> cl.parent() is BQFClassGroup(-Integer(4)*Integer(419)) True 
 - static from_polynomial(poly)[source]¶
- Construct a - BinaryQFfrom a bivariate polynomial with integer coefficients. Inverse of- polynomial().- EXAMPLES: - sage: R.<u,v> = ZZ[] sage: f = u^2 + 419*v^2 sage: Q = BinaryQF.from_polynomial(f); Q x^2 + 419*y^2 sage: Q.polynomial() x^2 + 419*y^2 sage: Q.polynomial()(R.gens()) == f True - >>> from sage.all import * >>> R = ZZ['u, v']; (u, v,) = R._first_ngens(2) >>> f = u**Integer(2) + Integer(419)*v**Integer(2) >>> Q = BinaryQF.from_polynomial(f); Q x^2 + 419*y^2 >>> Q.polynomial() x^2 + 419*y^2 >>> Q.polynomial()(R.gens()) == f True - The method fails if the given polynomial is not a quadratic form: - sage: BinaryQF.from_polynomial(u^3 - 5*v) Traceback (most recent call last): ... ValueError: polynomial has monomials of degree != 2 - >>> from sage.all import * >>> BinaryQF.from_polynomial(u**Integer(3) - Integer(5)*v) Traceback (most recent call last): ... ValueError: polynomial has monomials of degree != 2 - …or if the coefficients aren’t integers: - sage: BinaryQF.from_polynomial(u^2/7 + v^2) Traceback (most recent call last): ... TypeError: no conversion of this rational to integer - >>> from sage.all import * >>> BinaryQF.from_polynomial(u**Integer(2)/Integer(7) + v**Integer(2)) Traceback (most recent call last): ... TypeError: no conversion of this rational to integer 
 - has_fundamental_discriminant()[source]¶
- Return whether the discriminant \(D\) of this form is a fundamental discriminant (i.e. \(D\) is the smallest element of its squareclass with \(D = 0\) or \(1\) modulo \(4\)). - EXAMPLES: - sage: Q = BinaryQF([1, 0, 1]) sage: Q.discriminant() -4 sage: Q.has_fundamental_discriminant() # needs sage.libs.pari True sage: Q = BinaryQF([2, 0, 2]) sage: Q.discriminant() -16 sage: Q.has_fundamental_discriminant() # needs sage.libs.pari False - >>> from sage.all import * >>> Q = BinaryQF([Integer(1), Integer(0), Integer(1)]) >>> Q.discriminant() -4 >>> Q.has_fundamental_discriminant() # needs sage.libs.pari True >>> Q = BinaryQF([Integer(2), Integer(0), Integer(2)]) >>> Q.discriminant() -16 >>> Q.has_fundamental_discriminant() # needs sage.libs.pari False 
 - is_equivalent(other, proper=True)[source]¶
- Return whether - selfis equivalent to- other.- INPUT: - proper– boolean (default:- True); if- Trueuse proper equivalence
- other– a binary quadratic form
 - EXAMPLES: - sage: # needs sage.libs.pari sage: Q3 = BinaryQF(4, 4, 15) sage: Q2 = BinaryQF(4, -4, 15) sage: Q2.is_equivalent(Q3) True sage: a = BinaryQF([33, 11, 5]) sage: b = a.reduced_form(); b 5*x^2 - x*y + 27*y^2 sage: a.is_equivalent(b) True sage: a.is_equivalent(BinaryQF((3, 4, 5))) False - >>> from sage.all import * >>> # needs sage.libs.pari >>> Q3 = BinaryQF(Integer(4), Integer(4), Integer(15)) >>> Q2 = BinaryQF(Integer(4), -Integer(4), Integer(15)) >>> Q2.is_equivalent(Q3) True >>> a = BinaryQF([Integer(33), Integer(11), Integer(5)]) >>> b = a.reduced_form(); b 5*x^2 - x*y + 27*y^2 >>> a.is_equivalent(b) True >>> a.is_equivalent(BinaryQF((Integer(3), Integer(4), Integer(5)))) False - Some indefinite examples: - sage: Q1 = BinaryQF(9, 8, -7) sage: Q2 = BinaryQF(9, -8, -7) sage: Q1.is_equivalent(Q2, proper=True) # needs sage.libs.pari False sage: Q1.is_equivalent(Q2, proper=False) # needs sage.libs.pari True - >>> from sage.all import * >>> Q1 = BinaryQF(Integer(9), Integer(8), -Integer(7)) >>> Q2 = BinaryQF(Integer(9), -Integer(8), -Integer(7)) >>> Q1.is_equivalent(Q2, proper=True) # needs sage.libs.pari False >>> Q1.is_equivalent(Q2, proper=False) # needs sage.libs.pari True 
 - is_indef()[source]¶
- Return whether - selfis indefinite, i.e., has positive discriminant.- EXAMPLES: - sage: Q = BinaryQF(1, 3, -5) sage: Q.is_indef() True - >>> from sage.all import * >>> Q = BinaryQF(Integer(1), Integer(3), -Integer(5)) >>> Q.is_indef() True 
 - is_indefinite()[source]¶
- Return whether - selfis indefinite, i.e., has positive discriminant.- EXAMPLES: - sage: Q = BinaryQF(1, 3, -5) sage: Q.is_indef() True - >>> from sage.all import * >>> Q = BinaryQF(Integer(1), Integer(3), -Integer(5)) >>> Q.is_indef() True 
 - is_negative_definite()[source]¶
- Return - Trueif- selfis negative definite, i.e., has negative discriminant with \(a < 0\).- EXAMPLES: - sage: Q = BinaryQF(-1, 3, -5) sage: Q.is_positive_definite() False sage: Q.is_negative_definite() True - >>> from sage.all import * >>> Q = BinaryQF(-Integer(1), Integer(3), -Integer(5)) >>> Q.is_positive_definite() False >>> Q.is_negative_definite() True 
 - is_negdef()[source]¶
- Return - Trueif- selfis negative definite, i.e., has negative discriminant with \(a < 0\).- EXAMPLES: - sage: Q = BinaryQF(-1, 3, -5) sage: Q.is_positive_definite() False sage: Q.is_negative_definite() True - >>> from sage.all import * >>> Q = BinaryQF(-Integer(1), Integer(3), -Integer(5)) >>> Q.is_positive_definite() False >>> Q.is_negative_definite() True 
 - is_nonsingular()[source]¶
- Return whether this form is nonsingular, i.e., has nonzero discriminant. - EXAMPLES: - sage: Q = BinaryQF(1, 3, -5) sage: Q.is_nonsingular() True sage: Q = BinaryQF(1, 2, 1) sage: Q.is_nonsingular() False - >>> from sage.all import * >>> Q = BinaryQF(Integer(1), Integer(3), -Integer(5)) >>> Q.is_nonsingular() True >>> Q = BinaryQF(Integer(1), Integer(2), Integer(1)) >>> Q.is_nonsingular() False 
 - is_posdef()[source]¶
- Return - Trueif- selfis positive definite, i.e., has negative discriminant with \(a > 0\).- EXAMPLES: - sage: Q = BinaryQF(195751, 37615, 1807) sage: Q.is_positive_definite() True sage: Q = BinaryQF(195751, 1212121, -1876411) sage: Q.is_positive_definite() False - >>> from sage.all import * >>> Q = BinaryQF(Integer(195751), Integer(37615), Integer(1807)) >>> Q.is_positive_definite() True >>> Q = BinaryQF(Integer(195751), Integer(1212121), -Integer(1876411)) >>> Q.is_positive_definite() False 
 - is_positive_definite()[source]¶
- Return - Trueif- selfis positive definite, i.e., has negative discriminant with \(a > 0\).- EXAMPLES: - sage: Q = BinaryQF(195751, 37615, 1807) sage: Q.is_positive_definite() True sage: Q = BinaryQF(195751, 1212121, -1876411) sage: Q.is_positive_definite() False - >>> from sage.all import * >>> Q = BinaryQF(Integer(195751), Integer(37615), Integer(1807)) >>> Q.is_positive_definite() True >>> Q = BinaryQF(Integer(195751), Integer(1212121), -Integer(1876411)) >>> Q.is_positive_definite() False 
 - is_primitive()[source]¶
- Return whether the form \(ax^2 + bxy + cy^2\) satisfies \(\gcd(a, b, c) = 1\), i.e., is primitive. - EXAMPLES: - sage: Q = BinaryQF([6, 3, 9]) sage: Q.is_primitive() False sage: Q = BinaryQF([1, 1, 1]) sage: Q.is_primitive() True sage: Q = BinaryQF([2, 2, 2]) sage: Q.is_primitive() False sage: rqf = BinaryQF_reduced_representatives(-23*9, primitive_only=False) sage: [qf.is_primitive() for qf in rqf] [True, True, True, False, True, True, False, False, True] sage: rqf [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: [qf for qf in rqf if qf.is_primitive()] [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] - >>> from sage.all import * >>> Q = BinaryQF([Integer(6), Integer(3), Integer(9)]) >>> Q.is_primitive() False >>> Q = BinaryQF([Integer(1), Integer(1), Integer(1)]) >>> Q.is_primitive() True >>> Q = BinaryQF([Integer(2), Integer(2), Integer(2)]) >>> Q.is_primitive() False >>> rqf = BinaryQF_reduced_representatives(-Integer(23)*Integer(9), primitive_only=False) >>> [qf.is_primitive() for qf in rqf] [True, True, True, False, True, True, False, False, True] >>> rqf [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] >>> [qf for qf in rqf if qf.is_primitive()] [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] - See also 
 - is_reduced()[source]¶
- Return whether - selfis reduced.- Let \(f = a x^2 + b xy + c y^2\) be a binary quadratic form of discriminant \(D\). - If \(f\) is positive definite (\(D < 0\) and \(a > 0\)), then \(f\) is reduced if and only if \(|b|\leq a \leq c\), and \(b\geq 0\) if either \(a = b\) or \(a = c\). 
- If \(f\) is negative definite (\(D < 0\) and \(a < 0\)), then \(f\) is reduced if and only if the positive definite form with coefficients \((-a, b, -c)\) is reduced. 
- If \(f\) is indefinite (\(D > 0\)), then \(f\) is reduced if and only if [\(b > 0\), \(ac < 0\) and \((a-c)^2 < D\)] (equivalently if \(|\sqrt{D} - 2|a|| < b < \sqrt{D}\)) or [\(a = 0\) and \(-b < 2c \leq b\)] or [\(c = 0\) and \(-b < 2a \leq b\)]. 
 - EXAMPLES: - sage: Q = BinaryQF([1, 2, 3]) sage: Q.is_reduced() False sage: Q = BinaryQF([2, 1, 3]) sage: Q.is_reduced() True sage: Q = BinaryQF([1, -1, 1]) sage: Q.is_reduced() False sage: Q = BinaryQF([1, 1, 1]) sage: Q.is_reduced() True - >>> from sage.all import * >>> Q = BinaryQF([Integer(1), Integer(2), Integer(3)]) >>> Q.is_reduced() False >>> Q = BinaryQF([Integer(2), Integer(1), Integer(3)]) >>> Q.is_reduced() True >>> Q = BinaryQF([Integer(1), -Integer(1), Integer(1)]) >>> Q.is_reduced() False >>> Q = BinaryQF([Integer(1), Integer(1), Integer(1)]) >>> Q.is_reduced() True - Examples using indefinite forms: - sage: f = BinaryQF(-1, 2, 2) sage: f.is_reduced() True sage: BinaryQF(1, 9, 4).is_reduced() False sage: BinaryQF(1, 5, -1).is_reduced() True - >>> from sage.all import * >>> f = BinaryQF(-Integer(1), Integer(2), Integer(2)) >>> f.is_reduced() True >>> BinaryQF(Integer(1), Integer(9), Integer(4)).is_reduced() False >>> BinaryQF(Integer(1), Integer(5), -Integer(1)).is_reduced() True 
 - is_reducible()[source]¶
- Return whether this form is reducible and cache the result. - A binary form \(q\) is called reducible if it is the product of two linear forms \(q = (a x + b y) (c x + d y)\), or equivalently if its discriminant is a square. - EXAMPLES: - sage: q = BinaryQF([1, 0, -1]) sage: q.is_reducible() True - >>> from sage.all import * >>> q = BinaryQF([Integer(1), Integer(0), -Integer(1)]) >>> q.is_reducible() True - Warning - Despite the similar name, this method is unrelated to reduction of binary quadratic forms as implemented by - reduced_form()and- is_reduced().
 - is_singular()[source]¶
- Return whether - selfis singular, i.e., has zero discriminant.- EXAMPLES: - sage: Q = BinaryQF(1, 3, -5) sage: Q.is_singular() False sage: Q = BinaryQF(1, 2, 1) sage: Q.is_singular() True - >>> from sage.all import * >>> Q = BinaryQF(Integer(1), Integer(3), -Integer(5)) >>> Q.is_singular() False >>> Q = BinaryQF(Integer(1), Integer(2), Integer(1)) >>> Q.is_singular() True 
 - is_weakly_reduced()[source]¶
- Check if the form \(ax^2 + bxy + cy^2\) satisfies \(|b| \leq a \leq c\), i.e., is weakly reduced. - EXAMPLES: - sage: Q = BinaryQF([1, 2, 3]) sage: Q.is_weakly_reduced() False sage: Q = BinaryQF([2, 1, 3]) sage: Q.is_weakly_reduced() True sage: Q = BinaryQF([1, -1, 1]) sage: Q.is_weakly_reduced() True - >>> from sage.all import * >>> Q = BinaryQF([Integer(1), Integer(2), Integer(3)]) >>> Q.is_weakly_reduced() False >>> Q = BinaryQF([Integer(2), Integer(1), Integer(3)]) >>> Q.is_weakly_reduced() True >>> Q = BinaryQF([Integer(1), -Integer(1), Integer(1)]) >>> Q.is_weakly_reduced() True 
 - is_zero()[source]¶
- Return whether - selfis identically zero.- EXAMPLES: - sage: Q = BinaryQF(195751, 37615, 1807) sage: Q.is_zero() False sage: Q = BinaryQF(0, 0, 0) sage: Q.is_zero() True - >>> from sage.all import * >>> Q = BinaryQF(Integer(195751), Integer(37615), Integer(1807)) >>> Q.is_zero() False >>> Q = BinaryQF(Integer(0), Integer(0), Integer(0)) >>> Q.is_zero() True 
 - matrix_action_left(M)[source]¶
- Return the binary quadratic form resulting from the left action of the 2-by-2 matrix \(M\) on - self.- Here the action of the matrix \(M = \begin{pmatrix} a & b \\ c & d \end{pmatrix}\) on the form \(Q(x, y)\) produces the form \(Q(ax+cy, bx+dy)\). - EXAMPLES: - sage: Q = BinaryQF([2, 1, 3]); Q 2*x^2 + x*y + 3*y^2 sage: M = matrix(ZZ, [[1, 2], [3, 5]]) sage: Q.matrix_action_left(M) 16*x^2 + 83*x*y + 108*y^2 - >>> from sage.all import * >>> Q = BinaryQF([Integer(2), Integer(1), Integer(3)]); Q 2*x^2 + x*y + 3*y^2 >>> M = matrix(ZZ, [[Integer(1), Integer(2)], [Integer(3), Integer(5)]]) >>> Q.matrix_action_left(M) 16*x^2 + 83*x*y + 108*y^2 
 - matrix_action_right(M)[source]¶
- Return the binary quadratic form resulting from the right action of the 2-by-2 matrix \(M\) on - self.- Here the action of the matrix \(M = \begin{pmatrix} a & b \\ c & d \end{pmatrix}\) on the form \(Q(x, y)\) produces the form \(Q(ax+by, cx+dy)\). - EXAMPLES: - sage: Q = BinaryQF([2, 1, 3]); Q 2*x^2 + x*y + 3*y^2 sage: M = matrix(ZZ, [[1, 2], [3, 5]]) sage: Q.matrix_action_right(M) 32*x^2 + 109*x*y + 93*y^2 - >>> from sage.all import * >>> Q = BinaryQF([Integer(2), Integer(1), Integer(3)]); Q 2*x^2 + x*y + 3*y^2 >>> M = matrix(ZZ, [[Integer(1), Integer(2)], [Integer(3), Integer(5)]]) >>> Q.matrix_action_right(M) 32*x^2 + 109*x*y + 93*y^2 
 - polynomial()[source]¶
- Return - selfas a homogeneous 2-variable polynomial.- EXAMPLES: - sage: Q = BinaryQF([1, 2, 3]) sage: Q.polynomial() x^2 + 2*x*y + 3*y^2 sage: Q = BinaryQF([-1, -2, 3]) sage: Q.polynomial() -x^2 - 2*x*y + 3*y^2 sage: Q = BinaryQF([0, 0, 0]) sage: Q.polynomial() 0 - >>> from sage.all import * >>> Q = BinaryQF([Integer(1), Integer(2), Integer(3)]) >>> Q.polynomial() x^2 + 2*x*y + 3*y^2 >>> Q = BinaryQF([-Integer(1), -Integer(2), Integer(3)]) >>> Q.polynomial() -x^2 - 2*x*y + 3*y^2 >>> Q = BinaryQF([Integer(0), Integer(0), Integer(0)]) >>> Q.polynomial() 0 
 - static principal(D)[source]¶
- Return the principal binary quadratic form of the given discriminant. - EXAMPLES: - sage: BinaryQF.principal(8) x^2 - 2*y^2 sage: BinaryQF.principal(5) x^2 + x*y - y^2 sage: BinaryQF.principal(4) x^2 - y^2 sage: BinaryQF.principal(1) x^2 + x*y sage: BinaryQF.principal(-3) x^2 + x*y + y^2 sage: BinaryQF.principal(-4) x^2 + y^2 sage: BinaryQF.principal(-7) x^2 + x*y + 2*y^2 sage: BinaryQF.principal(-8) x^2 + 2*y^2 - >>> from sage.all import * >>> BinaryQF.principal(Integer(8)) x^2 - 2*y^2 >>> BinaryQF.principal(Integer(5)) x^2 + x*y - y^2 >>> BinaryQF.principal(Integer(4)) x^2 - y^2 >>> BinaryQF.principal(Integer(1)) x^2 + x*y >>> BinaryQF.principal(-Integer(3)) x^2 + x*y + y^2 >>> BinaryQF.principal(-Integer(4)) x^2 + y^2 >>> BinaryQF.principal(-Integer(7)) x^2 + x*y + 2*y^2 >>> BinaryQF.principal(-Integer(8)) x^2 + 2*y^2 
 - reduced_form(transformation=False, algorithm='default')[source]¶
- Return a reduced form equivalent to - self.- INPUT: - self– binary quadratic form of non-square discriminant
- transformation– boolean (default:- False); if- True, return both the reduced form and a matrix whose- matrix_action_right()transforms- selfinto the reduced form
- algorithm– string; the algorithm to use. Valid options are:- 'default'– let Sage pick an algorithm (default)
- 'pari'– use PARI (pari:qfbred or pari:qfbredsl2)
- 'sage'– use Sage
 
 - See also - EXAMPLES: - sage: a = BinaryQF([33, 11, 5]) sage: a.is_reduced() False sage: b = a.reduced_form(); b # needs sage.libs.pari 5*x^2 - x*y + 27*y^2 sage: b.is_reduced() # needs sage.libs.pari True sage: a = BinaryQF([15, 0, 15]) sage: a.is_reduced() True sage: b = a.reduced_form(); b # needs sage.libs.pari 15*x^2 + 15*y^2 sage: b.is_reduced() # needs sage.libs.pari True - >>> from sage.all import * >>> a = BinaryQF([Integer(33), Integer(11), Integer(5)]) >>> a.is_reduced() False >>> b = a.reduced_form(); b # needs sage.libs.pari 5*x^2 - x*y + 27*y^2 >>> b.is_reduced() # needs sage.libs.pari True >>> a = BinaryQF([Integer(15), Integer(0), Integer(15)]) >>> a.is_reduced() True >>> b = a.reduced_form(); b # needs sage.libs.pari 15*x^2 + 15*y^2 >>> b.is_reduced() # needs sage.libs.pari True - Examples of reducing indefinite forms: - sage: f = BinaryQF(1, 0, -3) sage: f.is_reduced() False sage: g = f.reduced_form(); g # needs sage.libs.pari x^2 + 2*x*y - 2*y^2 sage: g.is_reduced() # needs sage.libs.pari True sage: q = BinaryQF(1, 0, -1) sage: q.reduced_form() # needs sage.libs.pari x^2 + 2*x*y sage: BinaryQF(1, 9, 4).reduced_form(transformation=True) # needs sage.libs.pari ( [ 0 -1] 4*x^2 + 7*x*y - y^2, [ 1 2] ) sage: BinaryQF(3, 7, -2).reduced_form(transformation=True) # needs sage.libs.pari ( [1 0] 3*x^2 + 7*x*y - 2*y^2, [0 1] ) sage: BinaryQF(-6, 6, -1).reduced_form(transformation=True) # needs sage.libs.pari ( [ 0 -1] -x^2 + 2*x*y + 2*y^2, [ 1 -4] ) - >>> from sage.all import * >>> f = BinaryQF(Integer(1), Integer(0), -Integer(3)) >>> f.is_reduced() False >>> g = f.reduced_form(); g # needs sage.libs.pari x^2 + 2*x*y - 2*y^2 >>> g.is_reduced() # needs sage.libs.pari True >>> q = BinaryQF(Integer(1), Integer(0), -Integer(1)) >>> q.reduced_form() # needs sage.libs.pari x^2 + 2*x*y >>> BinaryQF(Integer(1), Integer(9), Integer(4)).reduced_form(transformation=True) # needs sage.libs.pari ( [ 0 -1] 4*x^2 + 7*x*y - y^2, [ 1 2] ) >>> BinaryQF(Integer(3), Integer(7), -Integer(2)).reduced_form(transformation=True) # needs sage.libs.pari ( [1 0] 3*x^2 + 7*x*y - 2*y^2, [0 1] ) >>> BinaryQF(-Integer(6), Integer(6), -Integer(1)).reduced_form(transformation=True) # needs sage.libs.pari ( [ 0 -1] -x^2 + 2*x*y + 2*y^2, [ 1 -4] ) 
 - small_prime_value(Bmax=1000)[source]¶
- Return 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() # needs sage.libs.pari ....: for Q in BinaryQF_reduced_representatives(-23, primitive_only=True)] [23, 2, 2] sage: [Q.small_prime_value() # needs sage.libs.pari ....: for Q in BinaryQF_reduced_representatives(-47, primitive_only=True)] [47, 2, 2, 3, 3] - >>> from sage.all import * >>> [Q.small_prime_value() # needs sage.libs.pari ... for Q in BinaryQF_reduced_representatives(-Integer(23), primitive_only=True)] [23, 2, 2] >>> [Q.small_prime_value() # needs sage.libs.pari ... for Q in BinaryQF_reduced_representatives(-Integer(47), primitive_only=True)] [47, 2, 2, 3, 3] 
 - solve_integer(n, algorithm, _flag)[source]¶
- Solve \(Q(x, y) = n\) in integers \(x\) and \(y\) where \(Q\) is this quadratic form. - INPUT: - n– positive integer or a \(:sage:`~sage.structure.factorization.Factorization\) object
- algorithm–- 'general'(default) or- 'cornacchia'
- _flag–- 1,- 2(default) or- 3; passed onto the pari function``qfbsolve``. For internal use only.
 - To use the Cornacchia algorithm, the quadratic form must have \(a=1\) and \(b=0\) and \(c>0\), and - nmust be a prime or four times a prime (but this is not checked).- OUTPUT: - A tuple \((x, y)\) of integers satisfying \(Q(x, y) = n\), or - Noneif no solution exists.- ALGORITHM: pari:qfbsolve or pari:qfbcornacchia - TODO:: Replace - _flagwith human-readable parameters c.f. Issue #37119- EXAMPLES: - sage: Q = BinaryQF([1, 0, 419]) sage: Q.solve_integer(773187972) # needs sage.libs.pari (4919, 1337) - >>> from sage.all import * >>> Q = BinaryQF([Integer(1), Integer(0), Integer(419)]) >>> Q.solve_integer(Integer(773187972)) # needs sage.libs.pari (4919, 1337) - If \(Q\) is of the form \([1,0,c]\) as above and \(n\) is a prime (or four times a prime whenever \(c \equiv 3 \pmod 4\)), then Cornacchia’s algorithm can be used, which is typically much faster than the general method: - sage: Q = BinaryQF([1, 0, 12345]) sage: n = 2^99 + 5273 sage: Q.solve_integer(n) # needs sage.libs.pari (67446480057659, 7139620553488) sage: Q.solve_integer(n, algorithm='cornacchia') # needs sage.libs.pari (67446480057659, 7139620553488) sage: timeit('Q.solve_integer(n)') # not tested 125 loops, best of 3: 3.13 ms per loop sage: timeit('Q.solve_integer(n, algorithm="cornacchia")') # not tested 625 loops, best of 3: 18.6 μs per loop - >>> from sage.all import * >>> Q = BinaryQF([Integer(1), Integer(0), Integer(12345)]) >>> n = Integer(2)**Integer(99) + Integer(5273) >>> Q.solve_integer(n) # needs sage.libs.pari (67446480057659, 7139620553488) >>> Q.solve_integer(n, algorithm='cornacchia') # needs sage.libs.pari (67446480057659, 7139620553488) >>> timeit('Q.solve_integer(n)') # not tested 125 loops, best of 3: 3.13 ms per loop >>> timeit('Q.solve_integer(n, algorithm="cornacchia")') # not tested 625 loops, best of 3: 18.6 μs per loop - sage: # needs sage.libs.pari 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] [(1, -1), (1, -1), (-1, -1)] - >>> from sage.all import * >>> # needs sage.libs.pari >>> Qs = BinaryQF_reduced_representatives(-Integer(23), primitive_only=True) >>> Qs [x^2 + x*y + 6*y^2, 2*x^2 - x*y + 3*y^2, 2*x^2 + x*y + 3*y^2] >>> [Q.solve_integer(Integer(3)) for Q in Qs] [None, (0, 1), (0, 1)] >>> [Q.solve_integer(Integer(5)) for Q in Qs] [None, None, None] >>> [Q.solve_integer(Integer(6)) for Q in Qs] [(1, -1), (1, -1), (-1, -1)] - sage: # needs sage.libs.pari sage: n = factor(126) sage: Q = BinaryQF([1, 0, 5]) sage: Q.solve_integer(n) (11, -1) - >>> from sage.all import * >>> # needs sage.libs.pari >>> n = factor(Integer(126)) >>> Q = BinaryQF([Integer(1), Integer(0), Integer(5)]) >>> Q.solve_integer(n) (11, -1) 
 
- sage.quadratic_forms.binary_qf.BinaryQF_reduced_representatives(D, primitive_only=False, proper=True)[source]¶
- 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_onlyis- Truethen 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] - >>> from sage.all import * >>> BinaryQF_reduced_representatives(-Integer(4)) [x^2 + y^2] >>> BinaryQF_reduced_representatives(-Integer(163)) [x^2 + x*y + 41*y^2] >>> BinaryQF_reduced_representatives(-Integer(12)) [x^2 + 3*y^2, 2*x^2 + 2*x*y + 2*y^2] >>> BinaryQF_reduced_representatives(-Integer(16)) [x^2 + 4*y^2, 2*x^2 + 2*y^2] >>> BinaryQF_reduced_representatives(-Integer(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() # needs sage.rings.number_field 2 sage: # needs sage.libs.pari sage: p = next_prime(2^20); p 1048583 sage: len(BinaryQF_reduced_representatives(-p)) 689 sage: QuadraticField(-p, 'a').class_number() # needs sage.rings.number_field 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] - >>> from sage.all import * >>> len(BinaryQF_reduced_representatives(-Integer(13)*Integer(4))) 2 >>> QuadraticField(-Integer(13)*Integer(4), 'a').class_number() # needs sage.rings.number_field 2 >>> # needs sage.libs.pari >>> p = next_prime(Integer(2)**Integer(20)); p 1048583 >>> len(BinaryQF_reduced_representatives(-p)) 689 >>> QuadraticField(-p, 'a').class_number() # needs sage.rings.number_field 689 >>> BinaryQF_reduced_representatives(-Integer(23)*Integer(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] >>> BinaryQF_reduced_representatives(-Integer(23)*Integer(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]