Binary Quadratic Forms with Integer Coefficients¶
This module provides a specialized class for working with a binary quadratic form ax2+bxy+cy2, 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()
x^2 + 2*y^2
sage: Q(1, 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)¶
Bases:
sage.structure.sage_object.SageObject
A binary quadratic form over Z.
INPUT:
One of the following:
a
– either a 3-tuple of integers, or a quadratic homogeneous polynomial in two variables with integer coefficientsa
,b
,c
– three integers
OUTPUT:
the binary quadratic form a*x^2 + b*x*y + 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
- complex_point()¶
Return the point in the complex upper half-plane associated to
self
.This form, ax2+bxy+cy2, must be definite with negative discriminant b2−4ac<0.
OUTPUT:
the unique complex root of ax2+bx+c with positive imaginary part
EXAMPLES:
sage: Q = BinaryQF([1, 0, 1]) sage: Q.complex_point() 1.00000000000000*I
- content()¶
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
- cycle(proper=False)¶
Return the cycle of reduced forms to which
self
belongs.This is based on Algorithm 6.1 of [BUVO2007].
INPUT:
self
– reduced, indefinite form of non-square discriminantproper
– boolean (default:False
); ifTrue
, 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]
- det()¶
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
- determinant()¶
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
- discriminant()¶
Return the discriminant of
self
.Given a form ax2+bxy+cy2, this returns b2−4ac.
EXAMPLES:
sage: Q = BinaryQF([1, 2, 3]) sage: Q.discriminant() -8
- has_fundamental_discriminant()¶
Return if 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() True sage: Q = BinaryQF([2, 0, 2]) sage: Q.discriminant() -16 sage: Q.has_fundamental_discriminant() False
- is_equivalent(other, proper=True)¶
Return if
self
is equivalent toother
.INPUT:
proper
– bool (default:True
); ifTrue
use proper equivalenceother
– a binary quadratic form
EXAMPLES:
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
Some indefinite examples:
sage: Q1 = BinaryQF(9, 8, -7) sage: Q2 = BinaryQF(9, -8, -7) sage: Q1.is_equivalent(Q2, proper=True) False sage: Q1.is_equivalent(Q2, proper=False) True
- is_indef()¶
Return if
self
is indefinite, i.e., has positive discriminant.EXAMPLES:
sage: Q = BinaryQF(1, 3, -5) sage: Q.is_indef() True
- is_indefinite()¶
Return if
self
is indefinite, i.e., has positive discriminant.EXAMPLES:
sage: Q = BinaryQF(1, 3, -5) sage: Q.is_indef() True
- is_negative_definite()¶
Return
True
ifself
is 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
- is_negdef()¶
Return
True
ifself
is 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
- is_nonsingular()¶
Return if this form is nonsingular, i.e., has non-zero discriminant.
EXAMPLES:
sage: Q = BinaryQF(1, 3, -5) sage: Q.is_nonsingular() True sage: Q = BinaryQF(1, 2, 1) sage: Q.is_nonsingular() False
- is_posdef()¶
Return
True
ifself
is 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
- is_positive_definite()¶
Return
True
ifself
is 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
- is_primitive()¶
Checks if the form ax2+bxy+cy2 satisfies gcd, 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]
- is_reduced()¶
Return if
self
is 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 |\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
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
- is_reducible()¶
Return if 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
- is_singular()¶
Return if
self
is 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
- is_weakly_reduced()¶
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
- is_zero()¶
Return if
self
is 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
- matrix_action_left(M)¶
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
- matrix_action_right(M)¶
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
- polynomial()¶
Return
self
as 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
- reduced_form(transformation=False, algorithm='default')¶
Return a reduced form equivalent to
self
.INPUT:
self
– binary quadratic form of non-square discriminanttransformation
– boolean (default: False): ifTrue
, return both the reduced form and a matrix transformingself
into the reduced form. Currently only implemented for indefinite forms.algorithm
– String. The algorithm to use: Valid options are:'default'
– Let Sage pick an algorithm (default).'pari'
– use PARI'sage'
– use Sage
See also
EXAMPLES:
sage: a = BinaryQF([33, 11, 5]) sage: a.is_reduced() False sage: b = a.reduced_form(); b 5*x^2 - x*y + 27*y^2 sage: b.is_reduced() True sage: a = BinaryQF([15, 0, 15]) sage: a.is_reduced() True sage: b = a.reduced_form(); b 15*x^2 + 15*y^2 sage: b.is_reduced() True
Examples of reducing indefinite forms:
sage: f = BinaryQF(1, 0, -3) sage: f.is_reduced() False sage: g = f.reduced_form(); g x^2 + 2*x*y - 2*y^2 sage: g.is_reduced() True sage: q = BinaryQF(1, 0, -1) sage: q.reduced_form() x^2 + 2*x*y sage: BinaryQF(1, 9, 4).reduced_form(transformation=True) ( [ 0 -1] 4*x^2 + 7*x*y - y^2, [ 1 2] ) sage: BinaryQF(3, 7, -2).reduced_form(transformation=True) ( [1 0] 3*x^2 + 7*x*y - 2*y^2, [0 1] ) sage: BinaryQF(-6, 6, -1).reduced_form(transformation=True) ( [ 0 -1] -x^2 + 2*x*y + 2*y^2, [ 1 -4] )
- small_prime_value(Bmax=1000)¶
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]
- solve_integer(n)¶
Solve Q(x, y) = n in integers x and y where Q is this quadratic form.
INPUT:
n
– 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)]
- sage.quadratic_forms.binary_qf.BinaryQF_reduced_representatives(D, primitive_only=False, proper=True)¶
Return representatives for the classes of binary quadratic forms of discriminant D.
INPUT:
D
– (integer) a discriminantprimitive_only
– (boolean; default:True
): ifTrue
, 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
isTrue
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]