@@ -72,14 +72,14 @@ def count_modp__by_gauss_sum(n, p, m, Qdet):
7272 neg1 = - 1
7373 if not m % p:
7474 if n % 2 :
75- count = p** (n- 1 )
75+ count = p** (n - 1 )
7676 else :
77- count = p** (n- 1 ) + (p- 1 ) * (p** ((n- 2 ) // 2 )) * kronecker_symbol(((neg1** (n// 2 )) * Qdet) % p, p)
77+ count = p** (n - 1 ) + (p - 1 ) * (p** ((n - 2 ) // 2 )) * kronecker_symbol(((neg1** (n // 2 )) * Qdet) % p, p)
7878 else :
7979 if n % 2 :
80- count = p** (n- 1 ) + p** ((n- 1 ) // 2 ) * kronecker_symbol(((neg1** ((n- 1 ) // 2 )) * Qdet * m) % p, p)
80+ count = p** (n - 1 ) + p** ((n - 1 ) // 2 ) * kronecker_symbol(((neg1** ((n - 1 ) // 2 )) * Qdet * m) % p, p)
8181 else :
82- count = p** (n- 1 ) - p** ((n- 2 ) // 2 ) * kronecker_symbol(((neg1** (n// 2 )) * Qdet) % p, p)
82+ count = p** (n - 1 ) - p** ((n - 2 ) // 2 ) * kronecker_symbol(((neg1** (n // 2 )) * Qdet) % p, p)
8383
8484 # Return the result
8585 return count
@@ -115,13 +115,13 @@ cdef CountAllLocalTypesNaive_cdef(Q, p, k, m, zvec, nzvec):
115115
116116 # Perform a carry (when value = R-1) until we can increment freely
117117 ptr = len (v)
118- while ((ptr > 0 ) and (v[ptr- 1 ] == R- 1 )):
119- v[ptr- 1 ] += 1
118+ while ((ptr > 0 ) and (v[ptr - 1 ] == R - 1 )):
119+ v[ptr - 1 ] += 1
120120 ptr += - 1
121121
122122 # Only increment if we're not already at the zero vector =)
123123 if ptr > 0 :
124- v[ptr- 1 ] += 1
124+ v[ptr - 1 ] += 1
125125
126126 # Evaluate Q(v) quickly
127127 tmp_val = Mod(0 , R)
@@ -239,7 +239,7 @@ cdef local_solution_type_cdef(Q, p, w, zvec, nzvec):
239239 return < long > 1
240240 if p == 2 :
241241 for i in range (n - 1 ):
242- if Q[i, i+ 1 ] % p and (w[i] % p or w[i+ 1 ] % p):
242+ if Q[i, i + 1 ] % p and (w[i] % p or w[i + 1 ] % p):
243243 return < long > 1
244244
245245 # 2: Check Zero-type
@@ -257,11 +257,11 @@ cdef local_solution_type_cdef(Q, p, w, zvec, nzvec):
257257 # Compute the valuation of each index, allowing for off-diagonal terms
258258 if Q[i, i] == 0 :
259259 if i == 0 :
260- val = valuation(Q[i, i+ 1 ], p) # Look at the term to the right
260+ val = valuation(Q[i, i + 1 ], p) # Look at the term to the right
261261 elif i == n - 1 :
262- val = valuation(Q[i- 1 , i], p) # Look at the term above
262+ val = valuation(Q[i - 1 , i], p) # Look at the term above
263263 else :
264- val = valuation(Q[i, i+ 1 ] + Q[i- 1 , i], p) # Finds the valuation of the off-diagonal term since only one isn't zero
264+ val = valuation(Q[i, i + 1 ] + Q[i - 1 , i], p) # Finds the valuation of the off-diagonal term since only one isn't zero
265265 else :
266266 val = valuation(Q[i, i], p)
267267
@@ -281,3 +281,83 @@ cdef local_solution_type_cdef(Q, p, w, zvec, nzvec):
281281 print (" Solution vector is " + str (w))
282282 print (" and Q is \n " + str (Q) + " \n " )
283283 raise RuntimeError (" Error in IsLocalSolutionType: Should not execute this line... =( \n " )
284+
285+
286+ def count_all_local_good_types_normal_form (Q , p , k , m , zvec , nzvec ):
287+ r """
288+ This is an internal routine, which is called by
289+ :meth:`sage. quadratic_forms. quadratic_form. QuadraticForm. local_good_density_congruence_even
290+ QuadraticForm. local_good_density_congruence_even`. See the documentation of
291+ that method for more details.
292+
293+ INPUT:
294+
295+ - ``Q`` -- quadratic form over `\Z Z` in local normal form at p with no zero blocks mod `p^ k`
296+ - ``p`` -- prime number > 0
297+ - ``k`` -- integer > 0
298+ - ``m`` -- non-negative integer ( depending only on mod `p^ k`)
299+ - ``zvec``, ``nzvec`` -- list of integers in ``range( Q. dim( )) ``, or ``None``
300+
301+ OUTPUT:
302+
303+ a non-negative integer giving the number of solutions of Good type.
304+
305+ EXAMPLES::
306+
307+ sage: from sage. quadratic_forms. count_local_2 import count_all_local_good_types_normal_form
308+ sage: Q = DiagonalQuadraticForm( ZZ, [1,2,3 ])
309+ sage: Q_local_at2 = Q. local_normal_form( 2)
310+ sage: Q_local_at3 = Q. local_normal_form( 3)
311+ sage: count_all_local_good_types_normal_form( Q_local_at2, 2, 3, 3, None, None)
312+ 64
313+ sage: count_all_local_good_types_normal_form( Q_local_at2, 2, 3, 3, [0 ], None)
314+ 32
315+ sage: count_all_local_good_types_normal_form( Q_local_at3, 3, 2, 1, None, None)
316+ 54
317+ """
318+ n = Q.dim()
319+ if n == 0 :
320+ return 0
321+
322+ m_range = p** k
323+ if zvec is None :
324+ zvec = []
325+ if nzvec is None :
326+ nzvec = []
327+
328+ # determine local blocks
329+ blocks = []
330+ i = 0
331+ while i < n - 1 :
332+ if Q[i, i + 1 ] != 0 :
333+ blocks += [(i, i + 1 )]
334+ i += 2
335+ else :
336+ blocks += [(i,)]
337+ i += 1
338+ if i < n:
339+ blocks += [(i,)]
340+
341+ solutions = [[0 , 0 ] for _ in range (m_range)] # [good, not good]
342+ solutions[0 ][1 ] = 1
343+ for b in blocks:
344+ Q_part = Q.extract_variables(b)
345+ zvec_local = range (len (b)) if (b[0 ] in zvec) else None
346+ nzvec_local = range (len (b)) if (b[0 ] in nzvec) else None
347+
348+ solutions_part = [[0 , 0 ] for _ in range (m_range)]
349+ for m_part in range (m_range):
350+ cnt = CountAllLocalTypesNaive(Q_part, p, k, m_part, zvec_local, nzvec_local)
351+ solutions_part[m_part][0 ] = cnt[1 ]
352+ solutions_part[m_part][1 ] = cnt[0 ] - cnt[1 ]
353+
354+ # compute convolution of counts
355+ solutions_new = [[0 , 0 ] for _ in range (m_range)]
356+ for m1 in range (m_range):
357+ for m2 in range (m_range):
358+ total = (solutions[m1][0 ] + solutions[m1][1 ]) * (solutions_part[m2][0 ] + solutions_part[m2][1 ])
359+ good = total - solutions[m1][1 ] * solutions_part[m2][1 ]
360+ solutions_new[(m1 + m2) % m_range][0 ] += good
361+ solutions_new[(m1 + m2) % m_range][1 ] += total - good
362+ solutions = solutions_new
363+ return solutions[m % m_range][0 ]
0 commit comments