From 66f732d513c031a5b542ce1685fcdee93c26d6bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 24 Oct 2023 13:44:16 +0200 Subject: [PATCH 1/2] some cleanup in quadratic forms --- src/sage/combinat/designs/design_catalog.py | 2 +- src/sage/quadratic_forms/binary_qf.py | 10 +- src/sage/quadratic_forms/genera/all.py | 7 +- .../quadratic_form__automorphisms.py | 9 +- .../quadratic_form__count_local_2.py | 6 +- .../quadratic_form__equivalence_testing.py | 2 +- .../quadratic_form__local_field_invariants.py | 6 +- .../quadratic_forms/quadratic_form__mass.py | 40 ++++---- .../quadratic_form__neighbors.py | 3 +- .../quadratic_form__siegel_product.py | 11 ++- .../quadratic_form__split_local_covering.py | 45 +++++---- .../quadratic_form__ternary_Tornaria.py | 92 ++++++++++--------- .../quadratic_forms/quadratic_form__theta.py | 51 +++++----- .../projective/projective_subscheme.py | 2 +- 14 files changed, 144 insertions(+), 142 deletions(-) diff --git a/src/sage/combinat/designs/design_catalog.py b/src/sage/combinat/designs/design_catalog.py index 26b899cb93d..8bf7f14fd0b 100644 --- a/src/sage/combinat/designs/design_catalog.py +++ b/src/sage/combinat/designs/design_catalog.py @@ -118,4 +118,4 @@ 'OAMainFunctions', as_='orthogonal_arrays') lazy_import('sage.combinat.designs.gen_quadrangles_with_spread', - ('generalised_quadrangle_with_spread', 'generalised_quadrangle_hermitian_with_ovoid')) \ No newline at end of file + ('generalised_quadrangle_with_spread', 'generalised_quadrangle_hermitian_with_ovoid')) diff --git a/src/sage/quadratic_forms/binary_qf.py b/src/sage/quadratic_forms/binary_qf.py index c82a343a04e..6516888e3ac 100755 --- a/src/sage/quadratic_forms/binary_qf.py +++ b/src/sage/quadratic_forms/binary_qf.py @@ -910,7 +910,8 @@ def reduced_form(self, transformation=False, algorithm="default"): if algorithm == 'sage': if self.discriminant() <= 0: raise NotImplementedError('reduction of definite binary ' - 'quadratic forms is not implemented in Sage') + 'quadratic forms is not implemented ' + 'in Sage') return self._reduce_indef(transformation) elif algorithm == 'pari': @@ -1154,14 +1155,15 @@ def cycle(self, proper=False): if self.discriminant().is_square(): # Buchmann/Vollmer assume the discriminant to be non-square raise NotImplementedError('computation of cycles is only ' - 'implemented for non-square discriminants') + 'implemented for non-square ' + 'discriminants') if proper: # Prop 6.10.5 in Buchmann Vollmer C = list(self.cycle(proper=False)) # make a copy that we can modify if len(C) % 2: C += C - for i in range(len(C)//2): - C[2*i+1] = C[2*i+1]._Tau() + for i in range(len(C) // 2): + C[2 * i + 1] = C[2 * i + 1]._Tau() return C if not hasattr(self, '_cycle_list'): C = [self] diff --git a/src/sage/quadratic_forms/genera/all.py b/src/sage/quadratic_forms/genera/all.py index 0b1889ba520..b1f48b5b8f6 100644 --- a/src/sage/quadratic_forms/genera/all.py +++ b/src/sage/quadratic_forms/genera/all.py @@ -1,9 +1,8 @@ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2007 David Kohel # # Distributed under the terms of the GNU General Public License (GPL) # -# http://www.gnu.org/licenses/ -#***************************************************************************** - +# https://www.gnu.org/licenses/ +# **************************************************************************** from .genus import Genus, LocalGenusSymbol, is_GlobalGenus diff --git a/src/sage/quadratic_forms/quadratic_form__automorphisms.py b/src/sage/quadratic_forms/quadratic_form__automorphisms.py index d0bf38f71a5..89b2c079478 100644 --- a/src/sage/quadratic_forms/quadratic_form__automorphisms.py +++ b/src/sage/quadratic_forms/quadratic_form__automorphisms.py @@ -115,7 +115,6 @@ def short_vector_list_up_to_length(self, len_bound, up_to_sign_flag=False): A list of lists of vectors such that entry `[i]` contains all vectors of length `i`. - EXAMPLES:: sage: Q = DiagonalQuadraticForm(ZZ, [1,3,5,7]) @@ -143,13 +142,13 @@ def short_vector_list_up_to_length(self, len_bound, up_to_sign_flag=False): [], [(0, 1, 0, 0)], [(1, 1, 0, 0), (1, -1, 0, 0), (2, 0, 0, 0)]] - sage: Q = QuadraticForm(matrix(6, [2, 1, 1, 1, -1, -1, 1, 2, 1, 1, -1, -1, 1, 1, 2, 0, -1, -1, 1, 1, 0, 2, 0, -1, -1, -1, -1, 0, 2, 1, -1, -1, -1, -1, 1, 2])) + sage: m6 = matrix(6, [2, 1, 1, 1, -1, -1, 1, 2, 1, 1, -1, -1, + ....: 1, 1, 2, 0, -1, -1, 1, 1, 0, 2, 0, -1, + ....: -1, -1, -1, 0, 2, 1, -1, -1, -1, -1, 1, 2]) + sage: Q = QuadraticForm(m6) sage: vs = Q.short_vector_list_up_to_length(8) sage: [len(vs[i]) for i in range(len(vs))] [1, 72, 270, 720, 936, 2160, 2214, 3600] - sage: vs = Q.short_vector_list_up_to_length(30) # long time (28s on sage.math, 2014) - sage: [len(vs[i]) for i in range(len(vs))] # long time - [1, 72, 270, 720, 936, 2160, 2214, 3600, 4590, 6552, 5184, 10800, 9360, 12240, 13500, 17712, 14760, 25920, 19710, 26064, 28080, 36000, 25920, 47520, 37638, 43272, 45900, 59040, 46800, 75600] The cases of ``len_bound < 2`` led to exception or infinite runtime before. diff --git a/src/sage/quadratic_forms/quadratic_form__count_local_2.py b/src/sage/quadratic_forms/quadratic_form__count_local_2.py index 999da6428de..b125d8d6840 100644 --- a/src/sage/quadratic_forms/quadratic_form__count_local_2.py +++ b/src/sage/quadratic_forms/quadratic_form__count_local_2.py @@ -68,9 +68,9 @@ def count_congruence_solutions_as_vector(self, p, k, m, zvec, nzvec): return CountAllLocalTypesNaive(self, p, k, m, zvec, nzvec) -##/////////////////////////////////////////// -##/// Front-ends for our counting routines // -##/////////////////////////////////////////// +# ////////////////////////////////////////// +# // Front-ends for our counting routines // +# ////////////////////////////////////////// def count_congruence_solutions(self, p, k, m, zvec, nzvec): r""" diff --git a/src/sage/quadratic_forms/quadratic_form__equivalence_testing.py b/src/sage/quadratic_forms/quadratic_form__equivalence_testing.py index 7b109b3dc01..148fcbd21f2 100644 --- a/src/sage/quadratic_forms/quadratic_form__equivalence_testing.py +++ b/src/sage/quadratic_forms/quadratic_form__equivalence_testing.py @@ -289,7 +289,7 @@ def has_equivalent_Jordan_decomposition_at_prime(self, other, p): # Check O'Meara's condition (ii) when appropriate if norm_list[i + 1] % (4 * norm_list[i]) == 0: if self_hasse_chain_list[i] * hilbert_symbol(norm_list[i] * other_chain_det_list[i], -self_chain_det_list[i], 2) \ - != other_hasse_chain_list[i] * hilbert_symbol(norm_list[i], -other_chain_det_list[i], 2): # Nipp conditions + != other_hasse_chain_list[i] * hilbert_symbol(norm_list[i], -other_chain_det_list[i], 2): # Nipp conditions return False # All tests passed for the prime 2. diff --git a/src/sage/quadratic_forms/quadratic_form__local_field_invariants.py b/src/sage/quadratic_forms/quadratic_form__local_field_invariants.py index 35f64198113..aff8dad2d62 100644 --- a/src/sage/quadratic_forms/quadratic_form__local_field_invariants.py +++ b/src/sage/quadratic_forms/quadratic_form__local_field_invariants.py @@ -5,7 +5,7 @@ quadratic forms over the rationals. """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2007 William Stein and Jonathan Hanke # Copyright (C) 2015 Jeroen Demeyer # @@ -13,8 +13,8 @@ # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# **************************************************************************** ########################################################################### # TO DO: Add routines for hasse invariants at all places, anisotropic diff --git a/src/sage/quadratic_forms/quadratic_form__mass.py b/src/sage/quadratic_forms/quadratic_form__mass.py index 11b581b1dd7..67bf06d888a 100644 --- a/src/sage/quadratic_forms/quadratic_form__mass.py +++ b/src/sage/quadratic_forms/quadratic_form__mass.py @@ -7,27 +7,27 @@ # Import all general mass finding routines from sage.quadratic_forms.quadratic_form__mass__Siegel_densities import \ - mass__by_Siegel_densities, \ - Pall_mass_density_at_odd_prime, \ - Watson_mass_at_2, \ - Kitaoka_mass_at_2, \ - mass_at_two_by_counting_mod_power + mass__by_Siegel_densities, \ + Pall_mass_density_at_odd_prime, \ + Watson_mass_at_2, \ + Kitaoka_mass_at_2, \ + mass_at_two_by_counting_mod_power from sage.quadratic_forms.quadratic_form__mass__Conway_Sloane_masses import \ - parity, \ - is_even, \ - is_odd, \ - conway_species_list_at_odd_prime, \ - conway_species_list_at_2, \ - conway_octane_of_this_unimodular_Jordan_block_at_2, \ - conway_diagonal_factor, \ - conway_cross_product_doubled_power, \ - conway_type_factor, \ - conway_p_mass, \ - conway_standard_p_mass, \ - conway_standard_mass, \ - conway_mass -# conway_generic_mass, \ -# conway_p_mass_adjustment + parity, \ + is_even, \ + is_odd, \ + conway_species_list_at_odd_prime, \ + conway_species_list_at_2, \ + conway_octane_of_this_unimodular_Jordan_block_at_2, \ + conway_diagonal_factor, \ + conway_cross_product_doubled_power, \ + conway_type_factor, \ + conway_p_mass, \ + conway_standard_p_mass, \ + conway_standard_mass, \ + conway_mass +# conway_generic_mass, \ +# conway_p_mass_adjustment ################################################### diff --git a/src/sage/quadratic_forms/quadratic_form__neighbors.py b/src/sage/quadratic_forms/quadratic_form__neighbors.py index 94f6559d51a..fb781e20122 100644 --- a/src/sage/quadratic_forms/quadratic_form__neighbors.py +++ b/src/sage/quadratic_forms/quadratic_form__neighbors.py @@ -389,8 +389,7 @@ def orbits_lines_mod_p(self, p): # but in gap we act from the right!! --> transpose gens = self.automorphism_group().gens() gens = [g.matrix().transpose().change_ring(GF(p)) for g in gens] - orbs = libgap.function_factory( - """function(gens, p) + orbs = libgap.function_factory("""function(gens, p) local one, G, reps, V, n, orb; one:= One(GF(p)); G:=Group(List(gens, g -> g*one)); diff --git a/src/sage/quadratic_forms/quadratic_form__siegel_product.py b/src/sage/quadratic_forms/quadratic_form__siegel_product.py index c439a93f33b..b481f5ad073 100644 --- a/src/sage/quadratic_forms/quadratic_form__siegel_product.py +++ b/src/sage/quadratic_forms/quadratic_form__siegel_product.py @@ -97,12 +97,13 @@ def siegel_product(self, u): verbose(" u = " + str(u) + "\n") # Make the odd generic factors - if ((n % 2) == 1): - m = (n-1) // 2 + if n % 2: + m = (n - 1) // 2 d1 = fundamental_discriminant(((-1)**m) * 2*d * u) # Replaced d by 2d here to compensate for the determinant - f = abs(d1) # gaining an odd power of 2 by using the matrix of 2Q instead - # of the matrix of Q. - # --> Old d1 = CoreDiscriminant((mpz_class(-1)^m) * d * u); + f = abs(d1) + # gaining an odd power of 2 by using the matrix of 2Q instead + # of the matrix of Q. + # --> Old d1 = CoreDiscriminant((mpz_class(-1)^m) * d * u); # Make the ratio of factorials factor: [(2m)! / m!] * prod_{i=1}^m (2*i-1) factor1 = 1 diff --git a/src/sage/quadratic_forms/quadratic_form__split_local_covering.py b/src/sage/quadratic_forms/quadratic_form__split_local_covering.py index 61f8c1a027f..495b439e3ca 100644 --- a/src/sage/quadratic_forms/quadratic_form__split_local_covering.py +++ b/src/sage/quadratic_forms/quadratic_form__split_local_covering.py @@ -14,8 +14,6 @@ from sage.rings.real_double import RDF from sage.matrix.matrix_space import MatrixSpace from sage.matrix.constructor import matrix -from sage.misc.lazy_import import lazy_import -lazy_import("sage.functions.all", "floor") from sage.rings.integer_ring import ZZ from sage.arith.misc import GCD @@ -94,19 +92,19 @@ def cholesky_decomposition(self, bit_prec=53): # 2. Loop on i for i in range(n): - for j in range(i+1, n): - Q[j,i] = Q[i,j] # Is this line redundant? - Q[i,j] = Q[i,j] / Q[i,i] + for j in range(i + 1, n): + Q[j, i] = Q[i, j] # Is this line redundant? + Q[i, j] = Q[i, j] / Q[i, i] # 3. Main Loop - for k in range(i+1, n): + for k in range(i + 1, n): for l in range(k, n): - Q[k,l] = Q[k,l] - Q[k,i] * Q[i,l] + Q[k, l] = Q[k, l] - Q[k, i] * Q[i, l] # 4. Zero out the strictly lower-triangular entries for i in range(n): for j in range(i): - Q[i,j] = 0 + Q[i, j] = 0 return Q @@ -178,7 +176,7 @@ def vectors_by_length(self, bound): # but if eps is too small, roundoff errors may knock off some # vectors of norm = bound (see #7100) eps = RDF(1e-6) - bound = ZZ(floor(max(bound, 0))) + bound = ZZ(max(bound, 0)) # bound is an integer Theta_Precision = bound + eps n = self.dim() @@ -192,7 +190,7 @@ def vectors_by_length(self, bound): # 1. Initialize T = n * [RDF(0)] # Note: We index the entries as 0 --> n-1 U = n * [RDF(0)] - i = n-1 + i = n - 1 T[i] = RDF(Theta_Precision) U[i] = RDF(0) @@ -201,27 +199,27 @@ def vectors_by_length(self, bound): # 2. Compute bounds Z = (T[i] / Q[i][i]).sqrt(extend=False) - L[i] = ( Z - U[i]).floor() + L[i] = (Z - U[i]).floor() x[i] = (-Z - U[i]).ceil() done_flag = False - Q_val = 0 # WARNING: Still need a good way of checking overflow for this value... + Q_val = 0 # WARNING: Still need a good way of checking overflow for this value... # Big loop which runs through all vectors while not done_flag: # 3b. Main loop -- try to generate a complete vector x (when i=0) while (i > 0): - T[i-1] = T[i] - Q[i][i] * (x[i] + U[i]) * (x[i] + U[i]) + T[i - 1] = T[i] - Q[i][i] * (x[i] + U[i]) * (x[i] + U[i]) i = i - 1 U[i] = 0 - for j in range(i+1, n): + for j in range(i + 1, n): U[i] = U[i] + Q[i][j] * x[j] # Now go back and compute the bounds... # 2. Compute bounds Z = (T[i] / Q[i][i]).sqrt(extend=False) - L[i] = ( Z - U[i]).floor() + L[i] = (Z - U[i]).floor() x[i] = (-Z - U[i]).ceil() # carry if we go out of bounds -- when Z is so small that @@ -254,7 +252,7 @@ def vectors_by_length(self, bound): # 3a. Increment (and carry if we go out of bounds) x[i] += 1 - while (x[i] > L[i]) and (i < n-1): + while (x[i] > L[i]) and (i < n - 1): i += 1 x[i] += 1 @@ -284,7 +282,6 @@ def complementary_subform_to_vector(self, v): OUTPUT: a :class:`QuadraticForm` over `\ZZ` - EXAMPLES:: sage: Q1 = DiagonalQuadraticForm(ZZ, [1,3,5,7]) @@ -317,7 +314,7 @@ def complementary_subform_to_vector(self, v): # Find the first non-zero component of v, and call it nz (Note: 0 <= nz < n) nz = 0 - while (nz < n) and (v[nz] == 0): + while nz < n and v[nz] == 0: nz += 1 # Abort if v is the zero vector @@ -334,27 +331,27 @@ def complementary_subform_to_vector(self, v): d = Q1[0, 0] # For each row/column, perform elementary operations to cancel them out. - for i in range(1,n): + for i in range(1, n): # Check if the (i,0)-entry is divisible by d, # and stretch its row/column if not. - if Q1[i,0] % d != 0: - Q1 = Q1.multiply_variable(d / GCD(d, Q1[i, 0]//2), i) + if Q1[i, 0] % d: + Q1 = Q1.multiply_variable(d / GCD(d, Q1[i, 0] // 2), i) # Now perform the (symmetric) elementary operations to cancel out the (i,0) entries/ - Q1 = Q1.add_symmetric(-(Q1[i,0]/2) / (GCD(d, Q1[i,0]//2)), i, 0) + Q1 = Q1.add_symmetric(-(Q1[i, 0] // 2) / (GCD(d, Q1[i, 0] // 2)), i, 0) # Check that we're done! done_flag = True for i in range(1, n): - if Q1[0,i] != 0: + if Q1[0, i] != 0: done_flag = False if not done_flag: raise RuntimeError("There is a problem cancelling out the matrix entries! =O") # Return the complementary matrix - return Q1.extract_variables(range(1,n)) + return Q1.extract_variables(range(1, n)) def split_local_cover(self): diff --git a/src/sage/quadratic_forms/quadratic_form__ternary_Tornaria.py b/src/sage/quadratic_forms/quadratic_form__ternary_Tornaria.py index 6ec8bd8022f..d6d537775b3 100644 --- a/src/sage/quadratic_forms/quadratic_form__ternary_Tornaria.py +++ b/src/sage/quadratic_forms/quadratic_form__ternary_Tornaria.py @@ -89,23 +89,23 @@ def content(self): # in quadratic_form.py -#def is_primitive(self): -# """ -# Checks if the form is a multiple of another form... only over ZZ for now. -# """ -# return self.content() == 1 +# def is_primitive(self): +# """ +# Checks if the form is a multiple of another form... only over ZZ for now. +# """ +# return self.content() == 1 # in quadratic_form.py -#def primitive(self): -# """ -# Return a primitive quadratic forms in the similarity class of the given form. +# def primitive(self): +# """ +# Return a primitive quadratic forms in the similarity class of the given form. # -# This only works when we have GCDs... so over ZZ. -# """ -# c=self.content() -# new_coeffs = [self.base_ring()(a/c) for a in self.__coeffs] -# return QuadraticForm(self.base_ring(), self.dim(), new_coeffs) +# This only works when we have GCDs... so over ZZ. +# """ +# c = self.content() +# new_coeffs = [self.base_ring()(a/c) for a in self.__coeffs] +# return QuadraticForm(self.base_ring(), self.dim(), new_coeffs) def adjoint(self): @@ -155,14 +155,14 @@ def antiadjoint(self): ... ValueError: not an adjoint """ + n = self.dim() + R = self.base_ring() try: - n = self.dim() - R = self.base_ring() - d = R(self.disc()**(ZZ(1)/(n-1))) + d = R(self.disc()**(ZZ.one() / (n - 1))) if is_odd(n): - return self.adjoint().scale_by_factor( R(1) / 4 / d**(n-2) ) + return self.adjoint().scale_by_factor(R.one() / 4 / d**(n - 2)) else: - return self.adjoint().scale_by_factor( R(1) / d**(n-2) ) + return self.adjoint().scale_by_factor(R.one() / d**(n - 2)) except TypeError: raise ValueError("not an adjoint") @@ -189,6 +189,7 @@ def is_adjoint(self) -> bool: def reciprocal(self): r""" This gives the reciprocal quadratic form associated to the given form. + This is defined as the multiple of the primitive adjoint with the same content as the given form. @@ -207,14 +208,13 @@ def reciprocal(self): [ * * 37 ] sage: Q.reciprocal().reciprocal() == Q True - """ - return self.adjoint().primitive() . scale_by_factor( self.content() ) + return self.adjoint().primitive() . scale_by_factor(self.content()) def omega(self): r""" - This is the content of the adjoint of the primitive associated quadratic form. + Return the content of the adjoint of the primitive associated quadratic form. Ref: See Dickson's "Studies in Number Theory". @@ -223,15 +223,15 @@ def omega(self): sage: Q = DiagonalQuadraticForm(ZZ, [1,1,37]) sage: Q.omega() 4 - """ return self.primitive().adjoint().content() def delta(self): r""" - This is the omega of the adjoint form, - which is the same as the omega of the reciprocal form. + Return the omega of the adjoint form. + + This is the same as the omega of the reciprocal form. EXAMPLES:: @@ -244,15 +244,16 @@ def delta(self): def level__Tornaria(self): r""" - Return the level of the quadratic form, - defined as + Return the level of the quadratic form. + + This is defined as - level(`B`) for even dimension, - level(`B`)/4 for odd dimension, where `2Q(x) = x^t\cdot B\cdot x`. - This agrees with the usual level for even dimension... + This agrees with the usual level for even dimension. EXAMPLES:: @@ -265,7 +266,7 @@ def level__Tornaria(self): sage: DiagonalQuadraticForm(ZZ, [1,1,1,1]).level__Tornaria() 4 """ - return self.base_ring()(abs(self.disc())/self.omega()/self.content()**self.dim()) + return self.base_ring()(abs(self.disc()) / self.omega() / self.content()**self.dim()) def discrec(self): @@ -289,7 +290,9 @@ def discrec(self): def hasse_conductor(self): """ - This is the product of all primes where the Hasse invariant equals `-1` + Return the Hasse coductor. + + This is the product of all primes where the Hasse invariant equals `-1`. EXAMPLES:: @@ -307,14 +310,17 @@ def hasse_conductor(self): sage: QuadraticForm(ZZ, 3, [2, -2, 0, 2, 0, 5]).hasse_conductor() # needs sage.libs.pari 10 """ - return prod([x[0] for x in factor(2 * self.level()) - if self.hasse_invariant(x[0]) == -1]) + return prod([x for x, _ in factor(2 * self.level()) + if self.hasse_invariant(x) == -1]) def clifford_invariant(self, p): """ - This is the Clifford invariant, i.e. the class in the Brauer group of the - Clifford algebra for even dimension, of the even Clifford Algebra for odd dimension. + Return the Clifford invariant. + + + This is the class in the Brauer group of the Clifford algebra for + even dimension, of the even Clifford Algebra for odd dimension. See Lam (AMS GSM 67) p. 117 for the definition, and p. 119 for the formula relating it to the Hasse invariant. @@ -348,7 +354,7 @@ def clifford_invariant(self, p): def clifford_conductor(self): """ - This is the product of all primes where the Clifford invariant is `-1` + Return the product of all primes where the Clifford invariant is `-1`. .. NOTE:: @@ -385,15 +391,15 @@ def clifford_conductor(self): sage: (H + H + H + H).clifford_conductor() 1 """ - return prod([x[0] for x in factor(2 * self.level()) - if self.clifford_invariant(x[0]) == -1]) + return prod([x for x, _ in factor(2 * self.level()) + if self.clifford_invariant(x) == -1]) # Genus theory def basiclemma(self, M): """ - Find a number represented by self and coprime to `M`. + Find a number represented by ``self`` and coprime to `M`. EXAMPLES:: @@ -423,24 +429,24 @@ def basiclemmavec(self, M): mod = [] M0 = abs(M) if M0 == 1: - return V(0) + return V.zero() for i in range(self.dim()): - M1 = prime_to_m_part(M0, self[i,i]) + M1 = prime_to_m_part(M0, self[i, i]) if M1 != 1: vec.append(V.gen(i)) mod.append(M1) - M0 = M0/M1 + M0 = M0 / M1 if M0 == 1: return tuple(CRT_vectors(vec, mod)) for i in range(self.dim()): for j in range(i): - M1 = prime_to_m_part(M0, self[i,j]) + M1 = prime_to_m_part(M0, self[i, j]) if M1 != 1: vec.append(V.i + V.j) mod.append(M1) - M0 = M0/M1 + M0 = M0 / M1 if M0 == 1: return tuple(CRT_vectors(vec, mod)) @@ -479,7 +485,7 @@ def xi(self, p): return kronecker_symbol(self.basiclemma(p), p) -def xi_rec(self,p): +def xi_rec(self, p): """ Return Xi(`p`) for the reciprocal form. diff --git a/src/sage/quadratic_forms/quadratic_form__theta.py b/src/sage/quadratic_forms/quadratic_form__theta.py index 7aa257d5e71..e6cd5f2f401 100644 --- a/src/sage/quadratic_forms/quadratic_form__theta.py +++ b/src/sage/quadratic_forms/quadratic_form__theta.py @@ -28,8 +28,8 @@ def theta_series(self, Max=10, var_str='q', safe_flag=True): The ``safe_flag`` allows us to select whether we want a copy of the output, or the original output. It is only meaningful when a vector is returned, otherwise a copy is automatically made in - creating the power series. By default ``safe_flag`` = True, so we - return a copy of the cached information. If this is set to False, + creating the power series. By default ``safe_flag`` = ``True``, so we + return a copy of the cached information. If this is set to ``False``, then the routine is much faster but the return values are vulnerable to being corrupted by the user. @@ -63,12 +63,12 @@ def theta_series(self, Max=10, var_str='q', safe_flag=True): if Max == 'mod_form': raise NotImplementedError("we have to figure out the correct number of Fourier coefficients to use") - #return self.theta_by_pari(sturm_bound(self.level(), self.dim() / ZZ(2)) + 1, var_str, safe_flag) + # return self.theta_by_pari(sturm_bound(self.level(), self.dim() / ZZ(2)) + 1, var_str, safe_flag) else: return self.theta_by_pari(M, var_str, safe_flag) -# ------------- Compute the theta function by using the PARI/GP routine qfrep ------------ +# ---- Compute the theta function by using the PARI/GP routine qfrep ---- def theta_by_pari(self, Max, var_str='q', safe_flag=True): r""" @@ -169,22 +169,21 @@ def theta_by_cholesky(self, q_prec): sage: Theta_list = Theta.list() sage: [m for m in range(len(Theta_list)) if Theta_list[m] == 0] [2, 22] - """ # RAISE AN ERROR -- This routine is deprecated! - #raise NotImplementedError, "This routine is deprecated. Try theta_series(), which uses theta_by_pari()." + # raise NotImplementedError("This routine is deprecated. Try theta_series(), which uses theta_by_pari().") from sage.arith.misc import integer_ceil as ceil, integer_floor as floor from sage.misc.functional import sqrt from sage.rings.real_mpfr import RealField n = self.dim() - theta = [0 for i in range(q_prec+1)] + theta = [0 for i in range(q_prec + 1)] PS = PowerSeriesRing(ZZ, 'q') bit_prec = 53 # TO DO: Set this precision to reflect the appropriate roundoff Cholesky = self.cholesky_decomposition(bit_prec) # error estimate, to be confident through our desired q-precision. - Q = Cholesky # <---- REDUNDANT!!! + Q = Cholesky # <---- REDUNDANT!!! R = RealField(bit_prec) half = R(0.5) @@ -198,16 +197,16 @@ def theta_by_cholesky(self, q_prec): x = [0] * n # 2. Compute bounds - #Z = sqrt(T[i] / Q[i,i]) # IMPORTANT NOTE: sqrt preserves the precision of the real number it's given... which is not so good... =| - #L[i] = floor(Z - U[i]) # Note: This is a Sage Integer - #x[i] = ceil(-Z - U[i]) - 1 # Note: This is a Sage Integer too + # Z = sqrt(T[i] / Q[i,i]) # IMPORTANT NOTE: sqrt preserves the precision of the real number it's given... which is not so good... =| + # L[i] = floor(Z - U[i]) # Note: This is a Sage Integer + # x[i] = ceil(-Z - U[i]) - 1 # Note: This is a Sage Integer too done_flag = False from_step4_flag = False from_step3_flag = True # We start by pretending this, since then we get to run through 2 and 3a once. =) - #double Q_val_double; - #unsigned long Q_val; // WARNING: Still need a good way of checking overflow for this value... + # double Q_val_double; + # unsigned long Q_val; // WARNING: Still need a good way of checking overflow for this value... # Big loop which runs through all vectors while not done_flag: @@ -221,7 +220,7 @@ def theta_by_cholesky(self, q_prec): else: # 2. Compute bounds from_step3_flag = False - Z = sqrt(T[i] / Q[i,i]) + Z = sqrt(T[i] / Q[i, i]) L[i] = floor(Z - U[i]) x[i] = ceil(-Z - U[i]) - 1 @@ -249,9 +248,9 @@ def theta_by_cholesky(self, q_prec): eps = 0.000000001 if abs(Q_val_double - Q_val) > eps: raise RuntimeError("Oh No! We have a problem with the floating point precision... \n" - + " Q_val_double = " + str(Q_val_double) + "\n" - + " Q_val = " + str(Q_val) + "\n" - + " x = " + str(x) + "\n") + + " Q_val_double = " + str(Q_val_double) + "\n" + + " Q_val = " + str(Q_val) + "\n" + + " x = " + str(x) + "\n") if Q_val <= q_prec: theta[Q_val] += 2 @@ -333,18 +332,18 @@ def theta_series_degree_2(Q, prec): max = (X + 1) // 4 v_list = (Q.vectors_by_length(max)) # assume a>0 v_list = [[V(_) for _ in vs] for vs in v_list] # coerce vectors into V - verbose("Computed vectors_by_length" , t) + verbose("Computed vectors_by_length", t) # Deal with the singular part - coeffs = {(0,0,0):ZZ(1)} - for i in range(1,max+1): - coeffs[(0,0,i)] = ZZ(2) * len(v_list[i]) + coeffs = {(0, 0, 0): ZZ.one()} + for i in range(1, max + 1): + coeffs[(0, 0, i)] = ZZ(2) * len(v_list[i]) # Now deal with the non-singular part - a_max = int(floor(sqrt(X/3))) + a_max = int(floor(sqrt(X / 3))) for a in range(1, a_max + 1): t = cputime() - c_max = int(floor((a*a + X)/(4*a))) + c_max = int(floor((a * a + X) / (4 * a))) for c in range(a, c_max + 1): for v1 in v_list[a]: v1_H = v1 * H @@ -353,10 +352,10 @@ def B_v1(v): return v1_H * v2 for v2 in v_list[c]: b = abs(B_v1(v2)) - if b <= a and 4*a*c-b*b <= X: - qf = (a,b,c) + if b <= a and 4 * a * c - b * b <= X: + qf = (a, b, c) count = ZZ(4) if b == 0 else ZZ(2) - coeffs[qf] = coeffs.get(qf, ZZ(0)) + count + coeffs[qf] = coeffs.get(qf, ZZ.zero()) + count verbose("done a = %d" % a, t) return coeffs diff --git a/src/sage/schemes/projective/projective_subscheme.py b/src/sage/schemes/projective/projective_subscheme.py index 8970637882d..0ccfbcd65b9 100644 --- a/src/sage/schemes/projective/projective_subscheme.py +++ b/src/sage/schemes/projective/projective_subscheme.py @@ -1513,4 +1513,4 @@ def local_height_arch(self, i, prec=None): sage: X.local_height_arch(1) 4.61512051684126 """ - return self.Chow_form().local_height_arch(i, prec) \ No newline at end of file + return self.Chow_form().local_height_arch(i, prec) From bf64a650575e2d6a2f29bbfc2c9c430be599288d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 26 Oct 2023 14:38:41 +0200 Subject: [PATCH 2/2] suggested details --- .../quadratic_form__split_local_covering.py | 8 ++++---- .../quadratic_forms/quadratic_form__ternary_Tornaria.py | 3 +-- src/sage/quadratic_forms/quadratic_form__theta.py | 9 +++------ 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/sage/quadratic_forms/quadratic_form__split_local_covering.py b/src/sage/quadratic_forms/quadratic_form__split_local_covering.py index 495b439e3ca..4db788e5e44 100644 --- a/src/sage/quadratic_forms/quadratic_form__split_local_covering.py +++ b/src/sage/quadratic_forms/quadratic_form__split_local_covering.py @@ -239,20 +239,20 @@ def vectors_by_length(self, bound): print(" Float = ", Q_val_double, " Long = ", Q_val) raise RuntimeError("The roundoff error is bigger than 0.001, so we should use more precision somewhere...") - if (Q_val <= bound): + if Q_val <= bound: theta_vec[Q_val].append(deepcopy(x)) # 5. Check if x = 0, for exit condition. =) j = 0 done_flag = True - while (j < n): - if (x[j] != 0): + while j < n: + if x[j] != 0: done_flag = False j += 1 # 3a. Increment (and carry if we go out of bounds) x[i] += 1 - while (x[i] > L[i]) and (i < n - 1): + while i < n - 1 and x[i] > L[i]: i += 1 x[i] += 1 diff --git a/src/sage/quadratic_forms/quadratic_form__ternary_Tornaria.py b/src/sage/quadratic_forms/quadratic_form__ternary_Tornaria.py index d6d537775b3..cc7a6549312 100644 --- a/src/sage/quadratic_forms/quadratic_form__ternary_Tornaria.py +++ b/src/sage/quadratic_forms/quadratic_form__ternary_Tornaria.py @@ -290,7 +290,7 @@ def discrec(self): def hasse_conductor(self): """ - Return the Hasse coductor. + Return the Hasse conductor. This is the product of all primes where the Hasse invariant equals `-1`. @@ -318,7 +318,6 @@ def clifford_invariant(self, p): """ Return the Clifford invariant. - This is the class in the Brauer group of the Clifford algebra for even dimension, of the even Clifford Algebra for odd dimension. diff --git a/src/sage/quadratic_forms/quadratic_form__theta.py b/src/sage/quadratic_forms/quadratic_form__theta.py index e6cd5f2f401..c4f0606df4c 100644 --- a/src/sage/quadratic_forms/quadratic_form__theta.py +++ b/src/sage/quadratic_forms/quadratic_form__theta.py @@ -58,7 +58,7 @@ def theta_series(self, Max=10, var_str='q', safe_flag=True): except TypeError: M = -1 - if (Max not in ['mod_form']) and (not M >= 0): + if Max not in ['mod_form'] and not M >= 0: raise TypeError("Max = {Max} is not an integer >= 0 or an allowed string") if Max == 'mod_form': @@ -205,9 +205,6 @@ def theta_by_cholesky(self, q_prec): from_step4_flag = False from_step3_flag = True # We start by pretending this, since then we get to run through 2 and 3a once. =) - # double Q_val_double; - # unsigned long Q_val; // WARNING: Still need a good way of checking overflow for this value... - # Big loop which runs through all vectors while not done_flag: @@ -226,12 +223,12 @@ def theta_by_cholesky(self, q_prec): # 3a. Main loop x[i] += 1 - while (x[i] > L[i]): + while x[i] > L[i]: i += 1 x[i] += 1 # 3b. Main loop - if (i > 0): + if i > 0: from_step3_flag = True T[i - 1] = T[i] - Q[i, i] * (x[i] + U[i]) * (x[i] + U[i]) i += -1