def _multiply_theta_char(l, f): r""" Return the coefficient at ``f`` of the theta series `\prod_t \theta_t` where `t` runs through the list ``l`` of theta characteristics. INPUT: - ``l`` -- a list of quadruples `t` in `{0,1}^4` - ``f`` -- a triple `(a,b,c)` of rational numbers such that the quadratic form `[a,b,c]` is semi positive definite (i.e. `a,c \geq 0` and `b^2-4ac \leq 0`). EXAMPLES:: sage: from sage.modular.siegel.theta_constant import _multiply_theta_char sage: from sage.modular.siegel.theta_constant import _compute_theta_char_poly sage: tc = [(1, 1, 0, 0), (0, 0, 1, 1), (1, 1, 0, 0), (0, 0, 1, 1)] sage: _multiply_theta_char(tc, [2, 0, 6]) -32 sage: _multiply_theta_char(tc, [2, 0, 10]) 32 sage: _multiply_theta_char(tc, [0, 0, 0]) 0 """ if 0 == len(l): return (1 if (0, 0, 0) == f else 0) a, b, c = f m1, m2, m3, m4 = l[0] # if the characteristic is not even: if 1 == (m1 * m3 + m2 * m4) % 2: return 0 coeff = 0 from sage.misc.all import isqrt, xsrange for u in xsrange(m1, isqrt(a) + 1, 2): for v in xsrange(m2, isqrt(c) + 1, 2): if 0 == u and 0 == v: coeff += _multiply_theta_char(l[1:], (a, b, c)) continue ap, bp, cp = (a - u * u, b - 2 * u * v, c - v * v) if bp * bp - 4 * ap * cp <= 0: val = (2 if 0 == (u * m3 + v * m4) % 4 else -2) coeff += val * _multiply_theta_char(l[1:], (ap, bp, cp)) if u != 0 and v != 0: ap, bp, cp = (a - u * u, b + 2 * u * v, c - v * v) if bp * bp - 4 * ap * cp <= 0: val = (2 if 0 == (u * m3 - v * m4) % 4 else -2) coeff += val * _multiply_theta_char(l[1:], (ap, bp, cp)) return coeff
def _multiply_theta_char(l, f): r""" Return the coefficient at ``f`` of the theta series `\prod_t \theta_t` where `t` runs through the list ``l`` of theta characteristics. INPUT: - ``l`` -- a list of quadruples `t` in `{0,1}^4` - ``f`` -- a triple `(a,b,c)` of rational numbers such that the quadratic form `[a,b,c]` is semi positive definite (i.e. `a,c \geq 0` and `b^2-4ac \leq 0`). EXAMPLES:: sage: from sage.modular.siegel.theta_constant import _multiply_theta_char sage: from sage.modular.siegel.theta_constant import _compute_theta_char_poly sage: tc = [(1, 1, 0, 0), (0, 0, 1, 1), (1, 1, 0, 0), (0, 0, 1, 1)] sage: _multiply_theta_char(tc, [2, 0, 6]) -32 sage: _multiply_theta_char(tc, [2, 0, 10]) 32 sage: _multiply_theta_char(tc, [0, 0, 0]) 0 """ if 0 == len(l): return (1 if (0, 0, 0) == f else 0) a, b, c = f m1, m2, m3, m4 = l[0] # if the characteristic is not even: if 1 == (m1*m3 + m2*m4)%2: return 0 coeff = 0 from sage.misc.all import isqrt, xsrange for u in xsrange(m1, isqrt(a)+1, 2): for v in xsrange(m2, isqrt(c)+1, 2): if 0 == u and 0 == v: coeff += _multiply_theta_char(l[1:], (a, b, c)) continue ap, bp, cp = (a-u*u, b-2*u*v, c-v*v) if bp*bp-4*ap*cp <= 0: val = (2 if 0 == (u*m3 + v*m4)%4 else -2) coeff += val * _multiply_theta_char(l[1:], (ap, bp, cp)) if u != 0 and v != 0: ap, bp, cp = (a-u*u, b+2*u*v, c-v*v) if bp*bp-4*ap*cp <= 0: val = (2 if 0 == (u*m3 - v*m4)%4 else -2) coeff += val * _multiply_theta_char(l[1:], (ap, bp, cp)) return coeff
def BinaryQF_reduced_representatives(D, primitive_only=False): r""" Returns a list of inequivalent reduced representatives for the equivalence classes of positive definite binary forms of discriminant D. INPUT: - `D` -- (integer) A negative discriminant. - ``primitive_only`` -- (bool, default False) flag controlling whether only primitive forms are included. OUTPUT: (list) A lexicographically-ordered list of inequivalent reduced representatives for the equivalence classes of positive definite binary 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 `Q(\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(5) Traceback (most recent call last): ... ValueError: discriminant must be negative and congruent to 0 or 1 modulo 4 """ D = ZZ(D) if not ( D < 0 and (D % 4 in [0,1])): raise ValueError, "discriminant must be negative and congruent to 0 or 1 modulo 4" # 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.misc.all import xsrange from sage.rings.arith import gcd # 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])) form_list.sort() return form_list
def BinaryQF_reduced_representatives(D, primitive_only=False): r""" Returns a list of inequivalent reduced representatives for the equivalence classes of positive definite binary forms of discriminant D. INPUT: - `D` -- (integer) A negative discriminant. - ``primitive_only`` -- (bool, default False) flag controlling whether only primitive forms are included. OUTPUT: (list) A lexicographically-ordered list of inequivalent reduced representatives for the equivalence classes of positive definite binary 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 `Q(\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(5) Traceback (most recent call last): ... ValueError: discriminant must be negative and congruent to 0 or 1 modulo 4 """ D = ZZ(D) if not (D < 0 and (D % 4 in [0, 1])): raise ValueError, "discriminant must be negative and congruent to 0 or 1 modulo 4" # 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.misc.all import xsrange from sage.rings.arith import gcd # 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])) form_list.sort() return form_list