def _iter_positive_forms_with_content_and_discriminant(self) : if self.__disc is infinity : raise ValueError, "infinity is not a true filter index" if self.__reduced : for (l, (u,x)) in enumerate(self.__p1list) : if u == 0 : for a in xrange(self.__level, isqrt(self.__disc // 4) + 1, self.__level) : frpa = 4 * a for b in xrange(a+1) : g = gcd(a // self.__level,b) bsq = b**2 for c in xrange(a, (b**2 + (self.__disc - 1))//(4*a) + 1) : yield (((a,b,c), l), gcd(g,c), frpa*c - bsq) else : for a in xrange(1, isqrt(self.__disc // 3) + 1) : frpa = 4 * a for b in xrange(a+1) : g = gcd(a, b) bsq = b**2 ## We need x**2 * a + x * b + c % N == 0 h = (-((x**2 + 1) * a + x * b)) % self.__level for c in xrange( a + h, (b**2 + (self.__disc - 1))//(4*a) + 1, self.__level ) : yield (((a,b,c), l), gcd(g,(x**2 * a + x * b + c) // self.__level), frpa*c - bsq) #! if self.__reduced else : raise NotImplementedError raise StopIteration
def iter_positive_forms_with_content(self) : if self.__disc is infinity : raise ValueError, "infinity is not a true filter index" if self.__reduced : for a in xrange(1,isqrt(self.__disc // 3) + 1) : for b in xrange(a+1) : g = gcd(a, b) for c in xrange(a, (b**2 + (self.__disc - 1))//(4*a) + 1) : yield (a,b,c), gcd(g,c) else : maxtrace = floor(5*self.__disc / 15 + sqrt(self.__disc)/2) for a in xrange(1, maxtrace + 1) : for c in xrange(1, maxtrace - a + 1) : g = gcd(a,c) Bu = isqrt(4*a*c - 1) di = 4*a*c - self.__disc if di >= 0 : Bl = isqrt(di) + 1 else : Bl = 0 for b in xrange(-Bu, -Bl + 1) : yield (a,b,c), gcd(g,b) for b in xrange(Bl, Bu + 1) : yield (a,b,c), gcd(g,b) #! if self.__reduced raise StopIteration
def _calc_iter_reduced_sub4(self) : try : return self.__iter_reduced_sub4 except AttributeError : pass sub3 = self._calc_iter_reduced_sub3() sub4 = list() for (a0,a1,b01,sub3s) in sub3 : sub4s = list() for (a2, b02, b12) in sub3s : sub4ss = list() for a3 in xrange(2, 2 * self.index() + 1, 2) : # obstruction for t[0,3] B1 = isqrt(a0 * a3 - 1) for b03 in xrange(-B1, B1 + 1) : # obstruction for t[1,3] B3 = isqrt(a1 * a3 - 1) for b13 in xrange(-B3, B3 + 1) : # obstruction for the minor [0,1,3] of t if a0*a1*a3 - a0*b12**2 + 2*b01*b13*b03 - b01**2*a3 - a1*b03**2 <= 0 : continue # obstruction for t[2,3] B3 = isqrt(a2 * a3 - 1) for b23 in xrange(-B3, B3 + 1) : # obstruction for the minor [0,2,3] of t if a0*a2*a3 - a0*b23**2 + 2*b02*b23*b03 - b02**2*a3 - a2*b03**2 <= 0 : continue # obstruction for the minor [1,2,3] of t if a1*a2*a3 - a1*b23**2 + 2*b12*b23*b13 - b12**2*a3 - a2*b13**2 <= 0 : continue t = matrix(ZZ, 4, [a0, b01, b02, b03, b01, a1, b12, b13, b02, b12, a2, b23, b03, b13, b23, a3], check = False) if t.det() <= 0 : continue u = t.LLL_gram() if u.transpose() * t * u != t : continue sub4ss.append((a3, b03, b13, b23)) sub4s.append((a2, b02, b12, sub4ss)) sub4.append((a0, a1, b01, sub4s)) self.__iter_reduced_sub4 = sub4 return sub4
def decompositions(self, s) : (a, b, c) = s for a1 in xrange(a + 1) : a2 = a - a1 for c1 in xrange(c + 1) : c2 = c - c1 B1 = isqrt(4*a1*c1) B2 = isqrt(4*a2*c2) for b1 in xrange(max(-B1, b - B2), min(B1 + 1, b + B2 + 1)) : yield ((a1, b1, c1), (a2,b - b1, c2)) raise StopIteration
def decompositions(self, s) : (n, r) = s fm = 4 * self.__m if self.__weak_forms : yield ((0,0), (n,r)) yield ((n,r), (0,0)) msq = self.__m**2 for n1 in xrange(1, n) : n2 = n - n1 for r1 in xrange( max(r - isqrt(fm * n2 + msq), isqrt(fm * n1 + msq - 1) + 1), min( r + isqrt(fm * n2 + msq) + 1, isqrt(fm * n1 + msq) + 1 ) ) : yield ((n1, r1), (n2, r - r1)) else : yield ((0,0), (n,r)) yield ((n,r), (0,0)) for n1 in xrange(1, n) : n2 = n - n1 ##r = r1 + r2 ##r1**2 <= 4 n1 m ## (r - r1)**2 <= 4 n2 m ## r1**2 - 2*r1*r + r**2 - 4 m n2 <= 0 ## r1 <-> r \pm \sqrt{r**2 - r**2 + 4 m n2} for r1 in xrange( max(r - isqrt(fm * n2), isqrt(fm * n1 - 1) + 1), min( r + isqrt(fm * n2) + 1, isqrt(fm * n1) + 1 ) ) : yield ((n1, r1), (n2, r - r1)) raise StopIteration
def duke_imamoglu_lift(self, f, f_k, precision, half_integral_weight = False) : """ INPUT: - ``half_integral_weight`` -- If ``False`` we assume that `f` is the Fourier expansion of a Jacobi form. Otherwise we assume it is the Fourier expansion of a half integral weight elliptic modular form. """ if half_integral_weight : coeff_index = lambda d : d else : coeff_index = lambda d : ((d + (-d % 4)) // 4, (-d) % 4) coeffs = dict() for t in precision.iter_positive_forms() : dt = (-1)**(precision.genus() // 2) * t.det() d = fundamental_discriminant(dt) eps = Integer(isqrt(dt / d)) coeffs[t] = 0 for a in eps.divisors() : d_a = abs(d * (eps // a)**2) coeffs[t] = coeffs[t] + a**(f_k - 1) * self._kohnen_phi(a, t) \ * f[coeff_index(d_a)] return coeffs
def _kohnen_phi(self, a, t) : ## We use a modified power of a, namely for each prime factor p of a ## we use p**floor(v_p(a)/2). This is compensated for in the routine ## of \rho a_modif = 1 for (p,e) in a.factor() : a_modif = a_modif * p**(e // 2) res = 0 for dsq in filter(lambda d: d.is_square(), a.divisors()) : d = isqrt(dsq) for g_diag in itertools.ifilter( lambda diag: prod(diag) == d, itertools.product(*[d.divisors() for _ in xrange(t.nrows())]) ) : for subents in itertools.product(*[xrange(r) for (j,r) in enumerate(g_diag) for _ in xrange(j)]) : columns = [subents[(j * (j - 1)) // 2:(j * (j + 1)) // 2] for j in xrange(t.nrows())] g = diagonal_matrix(list(g_diag)) for j in xrange(t.nrows()) : for i in xrange(j) : g[i,j] = columns[j][i] ginv = g.inverse() tg = ginv.transpose() * t * ginv try : tg= matrix(ZZ, tg) except : continue if any(tg[i,i] % 2 == 1 for i in xrange(tg.nrows())) : continue tg.set_immutable() res = res + self._kohnen_rho(tg, a // dsq) return a_modif * res
def decompositions(self, t) : for diag in itertools.product(*[xrange(t[i,i] + 1) for i in xrange(self.__n)]) : for subents in itertools.product( *[ xrange(-2 * isqrt(diag[i] * diag[j]), 2 * isqrt(diag[i] * diag[j]) + 1) for i in xrange(self.__n - 1) for j in xrange(i + 1, self.__n) ] ) : t1 = matrix(ZZ, [[ 2 * diag[i] if i == j else (subents[self.__n * i - (i * (i + 1)) // 2 + j - i - 1] if i < j else subents[self.__n * j - (j * (j + 1)) // 2 + i - j - 1]) for i in xrange(self.__n) ] for j in xrange(self.__n) ] ) if self._check_definiteness(t1) == -1 : continue t2 = t - t1 if self._check_definiteness(t2) == -1 : continue t1.set_immutable() t2.set_immutable() yield (t1, t2) raise StopIteration
def _by_taylor_expansion_m1(self, f_divs, k, is_integral=False) : r""" This provides special, faster code in the Jacobi index `1` case. """ if is_integral : PS = self.integral_power_series_ring() else : PS = self.power_series_ring() qexp_prec = self._qexp_precision() fderiv = f_divs[(0,0)].derivative().shift(1) f = f_divs[(0,0)] * Integer(k/2) gfderiv = f_divs[(1,0)] - fderiv ab_prec = isqrt(qexp_prec + 1) a1dict = dict(); a0dict = dict() b1dict = dict(); b0dict = dict() for t in xrange(1, ab_prec + 1) : tmp = t**2 a1dict[tmp] = -8*tmp b1dict[tmp] = -2 tmp += t a0dict[tmp] = 8*tmp + 2 b0dict[tmp] = 2 b1dict[0] = -1 a0dict[0] = 2; b0dict[0] = 2 a1 = PS(a1dict); b1 = PS(b1dict) a0 = PS(a0dict); b0 = PS(b0dict) Ifg0 = (self._eta_factor() * (f*a0 + gfderiv*b0)).list() Ifg1 = (self._eta_factor() * (f*a1 + gfderiv*b1)).list() if len(Ifg0) < qexp_prec : Ifg0 += [0]*(qexp_prec - len(Ifg0)) if len(Ifg1) < qexp_prec : Ifg1 += [0]*(qexp_prec - len(Ifg1)) Cphi = dict([(0,0)]) for i in xrange(qexp_prec) : Cphi[-4*i] = Ifg0[i] Cphi[1-4*i] = Ifg1[i] del Ifg0[:], Ifg1[:] phi_coeffs = dict() m = self.__precision.jacobi_index() for r in xrange(2 * self.__precision.jacobi_index()) : for n in xrange(qexp_prec) : k = 4 * m * n - r**2 if k >= 0 : phi_coeffs[(n, r)] = Cphi[-k] return phi_coeffs
def __iter__(self) : if self.__bound is infinity : raise ValueError, "infinity is not a true filter index" if self.__reduced : ##TODO: This is really primitive. We barely reduce arbitrary forms. for diag in itertools.product(*[xrange(self.__bound) for _ in xrange(self.__n)]) : for subents in itertools.product( *[ xrange(-2 * isqrt(diag[i] * diag[j]), 2 * isqrt(diag[i] * diag[j]) + 1) for i in xrange(self.__n - 1) for j in xrange(i + 1, self.__n) ] ) : t = matrix(ZZ, [[ 2 * diag[i] if i == j else (subents[self.__n * i - (i * (i + 1)) // 2 + j - i - 1] if i < j else subents[self.__n * j - (j * (j + 1)) // 2 + i - j - 1]) for i in xrange(self.__n) ] for j in xrange(self.__n) ] ) t = self.__ambient.reduce(t) if t is None : continue t = t[0] t.set_immutable() yield t else : for diag in itertools.product(*[xrange(self.__bound) for _ in xrange(self.__n)]) : for subents in itertools.product( *[ xrange(-2 * isqrt(diag[i] * diag[j]), 2 * isqrt(diag[i] * diag[j]) + 1) for i in xrange(self.__n - 1) for j in xrange(i + 1, self.__n) ] ) : t = matrix(ZZ, [[ 2 * diag[i] if i == j else (subents[self.__n * i - (i * (i + 1)) // 2 + j - i - 1] if i < j else subents[self.__n * j - (j * (j + 1)) // 2 + i - j - 1]) for i in xrange(self.__n) ] for j in xrange(self.__n) ] ) if self._check_definiteness(t) == -1 : continue t.set_immutable() yield t raise StopIteration
def decompositions(self, s) : ((a, b, c), l) = s # r t r^tr = t_1 + t_2 # \Rightleftarrow t = r t_1 r^tr + r t_2 r^tr for a1 in xrange(a + 1) : a2 = a - a1 for c1 in xrange(c + 1) : c2 = c - c1 B1 = isqrt(4*a1*c1) B2 = isqrt(4*a2*c2) for b1 in xrange(max(-B1, b - B2), min(B1 + 1, b + B2 + 1)) : h1 = apply_GL_to_form(self.__p1list[l], (a1, b1, c1)) h2 = apply_GL_to_form(self.__p1list[l], (a2, b - b1, c2)) if h1[2] % self.__level == 0 and h2[2] % self.__level == 0: yield ((h1, 1), (h2,1)) raise StopIteration
def iter_indefinite_forms(self) : r""" Iterate over indices with non-positive discriminant. TESTS:: sage: from psage.modform.jacobiforms.jacobiformd1nn_fourierexpansion import * sage: list(JacobiFormD1NNFilter(2, 2, reduced = False, weak_forms = True).iter_indefinite_forms()) [(0, -1), (1, 3), (0, 0), (1, -3), (0, 1), (0, -2), (0, 2)] sage: list(JacobiFormD1NNFilter(3, 2, reduced = False, weak_forms = True).iter_indefinite_forms()) [(0, -1), (1, 3), (2, -4), (0, 0), (2, 4), (1, -3), (0, 1), (0, -2), (0, 2)] sage: list(JacobiFormD1NNFilter(10, 2, reduced = True, weak_forms = True).iter_indefinite_forms()) [(0, 0), (0, 1), (0, 2)] sage: list(JacobiFormD1NNFilter(10, 3, reduced = True, weak_forms = True).iter_indefinite_forms()) [(0, 0), (0, 1), (0, 2), (0, 3)] sage: list(JacobiFormD1NNFilter(10, 10, reduced = True, weak_forms = True).iter_indefinite_forms()) [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7), (0, 8), (0, 9), (0, 10), (1, 7), (1, 8), (1, 9), (1, 10), (2, 9), (2, 10)] """ B = self.__bound m = self.__m fm = Integer(4 * self.__m) if self.__reduced : if self.__weak_forms : for n in xrange(0, min(self.__m // 4 + 1, self.__bound)) : for r in xrange( isqrt(fm * n - 1) + 1 if n != 0 else 0, self.__m + 1 ) : yield (n, r) else : for r in xrange(0, min(self.__m + 1, isqrt((self.__bound - 1) * fm) + 1) ) : if fm.divides(r**2) : yield (r**2 // fm, r) else : if self.__weak_forms : ## We first determine the reduced indices. for n in xrange(0, min(m // 4 + 1, B)) : if n == 0 : r_iteration = range(-m + 1, m + 1) else : r_iteration = range( -m + 1, -isqrt(fm * n - 1) ) \ + range( isqrt(fm * n - 1) + 1, m + 1 ) for r in r_iteration : for l in range( (- r - isqrt(r**2 - 4 * m * (n - (B - 1))) - 1) // (2 * m) + 1, (- r + isqrt(r**2 - 4 * m * (n - (B - 1)))) // (2 * m) + 1 ) : if n + l * r + m * l**2 >= B : print l, n, r yield (n + l * r + m * l**2, r + 2 * m * l) else : if self.__bound > 0 : yield (0,0) for n in xrange(1, self.__bound) : if (fm * n).is_square() : rt_fmm = isqrt(fm * n) yield(n, rt_fmm) yield(n, -rt_fmm) raise StopIteration
def decompositions(self, s): ((a, b, c), l) = s # r t r^tr = t_1 + t_2 # \Rightleftarrow t = r t_1 r^tr + r t_2 r^tr for a1 in xrange(a + 1): a2 = a - a1 for c1 in xrange(c + 1): c2 = c - c1 B1 = isqrt(4 * a1 * c1) B2 = isqrt(4 * a2 * c2) for b1 in xrange(max(-B1, b - B2), min(B1 + 1, b + B2 + 1)): h1 = apply_GL_to_form(self.__p1list[l], (a1, b1, c1)) h2 = apply_GL_to_form(self.__p1list[l], (a2, b - b1, c2)) if h1[2] % self.__level == 0 and h2[2] % self.__level == 0: yield ((h1, 1), (h2, 1)) raise StopIteration
def iter_positive_forms(self) : if self.__reduced : ##TODO: This is really primitive. We barely reduce arbitrary forms. for diag in itertools.product(*[xrange(self.__bound) for _ in xrange(self.__n)]) : for subents in itertools.product( *[ xrange(-2 * isqrt(diag[i] * diag[j]), 2 * isqrt(diag[i] * diag[j]) + 1) for i in xrange(self.__n - 1) for j in xrange(i + 1, self.__n) ] ) : t = matrix(ZZ, [[ 2 * diag[i] if i == j else (subents[self.__n * i - (i * (i + 1)) // 2 + j - i - 1] if i < j else subents[self.__n * j - (j * (j + 1)) // 2 + i - j - 1]) for i in xrange(self.__n) ] for j in xrange(self.__n) ] ) t = self.__ambient.reduce(t) if t is None : continue t = t[0] if t[0,0] == 0 : continue t.set_immutable() yield t else : for diag in itertools.product(*[xrange(self.__bound) for _ in xrange(self.__n)]) : for subents in itertools.product( *[ xrange(-2 * isqrt(diag[i] * diag[j]), 2 * isqrt(diag[i] * diag[j]) + 1) for i in xrange(self.__n - 1) for j in xrange(i + 1, self.__n) ] ) : t = matrix(ZZ, [[ 2 * diag[i] if i == j else (subents[self.__n * i - (i * (i + 1)) // 2 + j - i - 1] if i < j else subents[self.__n * j - (j * (j + 1)) // 2 + i - j - 1]) for i in xrange(self.__n) ] for j in xrange(self.__n) ] ) if self.__ambient._check_definiteness(t) != 1 : continue t.set_immutable() yield t
def _kohnen_rho(self, t, a): dt = (-1)**(t.nrows() // 2) * t.det() d = fundamental_discriminant(dt) eps = isqrt(dt // d) res = 1 for (p, e) in gcd(a, eps).factor(): pol = self._kohnen_rho_polynomial(t, p).coefficients() if e < len(pol): res = res * pol[e] return res
def _kohnen_rho(self, t, a) : dt = (-1)**(t.nrows() // 2) * t.det() d = fundamental_discriminant(dt) eps = isqrt(dt // d) res = 1 for (p,e) in gcd(a, eps).factor() : pol = self._kohnen_rho_polynomial(t, p).coefficients() if e < len(pol) : res = res * pol[e] return res
def iter_indefinite_forms(self) : fm = Integer(4 * self.__m) if self.__reduced : if self.__weak_forms : msq = self.__m**2 for n in xrange(0, min(self.__m // 4 + 1, self.__bound)) : for r in xrange( isqrt(fm * n - 1) + 1 if n != 0 else 0, isqrt(fm * n + msq + 1) ) : yield (n, r) else : for r in xrange(0, min(self.__m + 1, isqrt((self.__bound - 1) * fm) + 1) ) : if fm.divides(r**2) : yield (r**2 // fm, r) else : if self.__weak_forms : msq = self.__m**2 for n in xrange(0, self.__bound) : for r in xrange( isqrt(fm * n - 1) + 1 if n != 0 else 0, isqrt(fm * n + msq + 1) ) : yield (n, r) else : for n in xrange(0, self.__bound) : if (fm * n).is_square() : yield(n, isqrt(fm * n)) raise StopIteration
def iter_indefinite_forms(self) : fm = Integer(4 * self.__m) if self.__reduced : if self.__weak_forms : msq = self.__m**2 for n in range(0, min(self.__m // 4 + 1, self.__bound)) : for r in range( isqrt(fm * n - 1) + 1 if n != 0 else 0, isqrt(fm * n + msq + 1) ) : yield (n, r) else : for r in range(0, min(self.__m + 1, isqrt((self.__bound - 1) * fm) + 1) ) : if fm.divides(r**2) : yield (r**2 // fm, r) else : if self.__weak_forms : msq = self.__m**2 for n in range(0, self.__bound) : for r in range( isqrt(fm * n - 1) + 1 if n != 0 else 0, isqrt(fm * n + msq + 1) ) : yield (n, r) else : for n in range(0, self.__bound) : if (fm * n).is_square() : yield(n, isqrt(fm * n)) raise StopIteration
def hz_pullback(self, mu): r""" Compute the pullbacks to Hirzebruch--Zagier curves. This computes the pullback f(\tau * \mu, \tau * \mu') of f to the embedded half-plane H * (\mu, \mu') where \mu' is the conjugate of \mu. The result is a modular form of level equal to the norm of \mu. INPUT: - ``mu`` -- a totally-positive integer in the base-field K. OUTPUT: an OrthogonalModularForm for a signature (2, 1) lattice WARNING: the output's weyl vector is not implemented EXAMPLES:: sage: from weilrep import * sage: x = var('x') sage: K.<sqrt13> = NumberField(x * x - 13) sage: HMF(K).eisenstein_series(2, 15).hz_pullback(4 - sqrt13) 1 + 24*q + O(q^2) """ K = self.base_field() mu = K(mu) nn = mu.norm() tt = mu.trace() if tt <= 0 or nn <= 0: raise ValueError( 'You called hz_pullback with a number that is not totally-positive!' ) d = K.discriminant() a = isqrt((tt * tt - 4 * nn) / d) h = self.fourier_expansion() t, = PowerSeriesRing(QQ, 't').gens() d = K.discriminant() prec = floor(h.prec() / (tt / 2 + 2 * a / sqrt(d))) if d % 4: f = sum([ p[n] * t**((i * tt + n * a) / 2) for i, p in enumerate(h.list()) for n in p.exponents() ]) + O(t**prec) else: f = sum([ p[n] * t**((i * tt + 2 * n * a) / 2) for i, p in enumerate(h.list()) for n in p.exponents() ]) + O(t**prec) return OrthogonalModularFormLorentzian(self.weight(), WeilRep(matrix([[-2 * nn]])), f, scale=self.scale(), weylvec=vector([0]), qexp_representation='shimura')
def __iter__(self): if self.__disc is infinity: raise ValueError("infinity is not a true filter index") if self.__reduced: for c in range(0, self._indefinite_content_bound()): yield (0, 0, c) for a in range(1, isqrt(self.__disc // 3) + 1): for b in range(a + 1): for c in range(a, (b**2 + (self.__disc - 1)) // (4 * a) + 1): yield (a, b, c) else: ##FIXME: These are not all matrices for a in range(0, self._indefinite_content_bound()): yield (a, 0, 0) for c in range(1, self._indefinite_content_bound()): yield (0, 0, c) maxtrace = floor(5 * self.__disc / 15 + sqrt(self.__disc) / 2) for a in range(1, maxtrace + 1): for c in range(1, maxtrace - a + 1): Bu = isqrt(4 * a * c - 1) di = 4 * a * c - self.__disc if di >= 0: Bl = isqrt(di) + 1 else: Bl = 0 for b in range(-Bu, -Bl + 1): yield (a, b, c) for b in range(Bl, Bu + 1): yield (a, b, c) #! if self.__reduced raise StopIteration
def _iter_positive_forms_with_content_and_discriminant(self): if self.__disc is infinity: raise ValueError, "infinity is not a true filter index" if self.__reduced: for (l, (u, x)) in enumerate(self.__p1list): if u == 0: for a in xrange(self.__level, isqrt(self.__disc // 4) + 1, self.__level): frpa = 4 * a for b in xrange(a + 1): g = gcd(a // self.__level, b) bsq = b**2 for c in xrange(a, (b**2 + (self.__disc - 1)) // (4 * a) + 1): yield (((a, b, c), l), gcd(g, c), frpa * c - bsq) else: for a in xrange(1, isqrt(self.__disc // 3) + 1): frpa = 4 * a for b in xrange(a + 1): g = gcd(a, b) bsq = b**2 ## We need x**2 * a + x * b + c % N == 0 h = (-((x**2 + 1) * a + x * b)) % self.__level for c in xrange(a + h, (b**2 + (self.__disc - 1)) // (4 * a) + 1, self.__level): yield (((a, b, c), l), gcd(g, (x**2 * a + x * b + c) // self.__level), frpa * c - bsq) #! if self.__reduced else: raise NotImplementedError raise StopIteration
def __init__(self, precision, level, reduced = True) : self.__level = level if isinstance(precision, ParamodularFormD2Filter_trace) : precision = precision.index() elif isinstance(precision, ParamodularFormD2Filter_discriminant) : if precision.index() is infinity : precision = infinity else : precision = isqrt(precision.index() - 1) + 1 self.__trace = precision self.__reduced = reduced self.__p1list = P1List(level)
def iter_positive_forms(self) : r""" TESTS:: sage: from psage.modform.jacobiforms.jacobiformd1nn_fourierexpansion import * sage: list(JacobiFormD1NNFilter(3, 2, reduced = True).iter_positive_forms()) [(1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)] sage: list(JacobiFormD1NNFilter(3, 2, reduced = False).iter_positive_forms()) [(1, 0), (1, 1), (1, -1), (1, 2), (1, -2), (2, 0), (2, 1), (2, -1), (2, 2), (2, -2), (2, 3), (2, -3)] """ fm = 4 * self.__m if self.__reduced : for n in xrange(1, self.__bound) : for r in xrange(min(self.__m + 1, isqrt(fm * n - 1) + 1)) : yield (n, r) else : for n in xrange(1, self.__bound) : yield(n, 0) for r in xrange(1, isqrt(fm * n - 1) + 1) : yield (n, r) yield (n, -r) raise StopIteration
def iter_positive_forms(self): r""" TESTS:: sage: from psage.modform.jacobiforms.jacobiformd1nn_fourierexpansion import * sage: list(JacobiFormD1NNFilter(3, 2, reduced = True).iter_positive_forms()) [(1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)] sage: list(JacobiFormD1NNFilter(3, 2, reduced = False).iter_positive_forms()) [(1, 0), (1, 1), (1, -1), (1, 2), (1, -2), (2, 0), (2, 1), (2, -1), (2, 2), (2, -2), (2, 3), (2, -3)] """ fm = 4 * self.__m if self.__reduced: for n in xrange(1, self.__bound): for r in xrange(min(self.__m + 1, isqrt(fm * n - 1) + 1)): yield (n, r) else: for n in xrange(1, self.__bound): yield (n, 0) for r in xrange(1, isqrt(fm * n - 1) + 1): yield (n, r) yield (n, -r) raise StopIteration
def _calc_iter_reduced_sub3(self): try: return self.__iter_reduced_sub3 except AttributeError: pass sub2 = self._calc_iter_reduced_sub2() sub3 = list() for (a0, a1, b01) in sub2: sub3s = list() for a2 in range(2, 2 * self.index(), 2): # obstruction for t[0,2] B1 = isqrt(a0 * a2 - 1) for b02 in range(-B1, B1 + 1): # obstruction for t[1,2] B3 = isqrt(a1 * a2 - 1) for b12 in range(-B3, B3 + 1): # obstruction for the minor [0,1,2] of t if a0 * a1 * a2 - a0 * b12**2 + 2 * b01 * b12 * b02 - a2 * b01**2 - a1 * b02**2 <= 0: continue t = matrix(ZZ, 3, [a0, b01, b02, b01, a1, b12, b02, b12, a2]) u = t.LLL_gram() if u.transpose() * t * u != t: continue sub3s.append((a2, b02, b12)) sub3.append((a0, a1, b01, sub3s)) self.__iter_reduced_sub3 = sub3 return sub3
def __iter__(self) : if self.__disc is infinity : raise ValueError, "infinity is not a true filter index" if self.__reduced : for c in xrange(0, self._indefinite_content_bound()) : yield (0,0,c) for a in xrange(1,isqrt(self.__disc // 3) + 1) : for b in xrange(a+1) : for c in xrange(a, (b**2 + (self.__disc - 1))//(4*a) + 1) : yield (a,b,c) else : ##FIXME: These are not all matrices for a in xrange(0, self._indefinite_content_bound()) : yield (a,0,0) for c in xrange(1, self._indefinite_content_bound()) : yield (0,0,c) maxtrace = floor(5*self.__disc / 15 + sqrt(self.__disc)/2) for a in xrange(1, maxtrace + 1) : for c in xrange(1, maxtrace - a + 1) : Bu = isqrt(4*a*c - 1) di = 4*a*c - self.__disc if di >= 0 : Bl = isqrt(di) + 1 else : Bl = 0 for b in xrange(-Bu, -Bl + 1) : yield (a,b,c) for b in xrange(Bl, Bu + 1) : yield (a,b,c) #! if self.__reduced raise StopIteration
def iter_positive_forms(self) : fm = 4 * self.__m if self.__reduced : if self.__weak_forms : msq = self.__m**2 for n in range(1, self.__bound) : for r in range(min(self.__m + 1, isqrt(fm * n + msq - 1) + 1)) : yield (n, r) else : for n in range(1, self.__bound) : for r in range(min(self.__m + 1, isqrt(fm * n - 1) + 1)) : yield (n, r) else : if self.__weak_forms : msq = self.__m**2 for n in range(1, self.__bound) : for r in range(isqrt(fm * n + msq - 1) + 1) : yield (n, r) else : for n in range(1, self.__bound) : for r in range(isqrt(fm * n - 1) + 1) : yield (n, r) raise StopIteration
def iter_positive_forms(self) : fm = 4 * self.__m if self.__reduced : if self.__weak_forms : msq = self.__m**2 for n in xrange(1, self.__bound) : for r in xrange(min(self.__m + 1, isqrt(fm * n + msq - 1) + 1)) : yield (n, r) else : for n in xrange(1, self.__bound) : for r in xrange(min(self.__m + 1, isqrt(fm * n - 1) + 1)) : yield (n, r) else : if self.__weak_forms : msq = self.__m**2 for n in xrange(1, self.__bound) : for r in xrange(isqrt(fm * n + msq - 1) + 1) : yield (n, r) else : for n in xrange(1, self.__bound) : for r in xrange(isqrt(fm * n - 1) + 1) : yield (n, r) raise StopIteration
def _calc_iter_reduced_sub3(self) : try : return self.__iter_reduced_sub3 except AttributeError : pass sub2 = self._calc_iter_reduced_sub2() sub3 = list() for (a0, a1, b01) in sub2 : sub3s = list() for a2 in xrange(2, 2 * self.index(), 2) : # obstruction for t[0,2] B1 = isqrt(a0 * a2 - 1) for b02 in xrange(-B1, B1 + 1) : # obstruction for t[1,2] B3 = isqrt(a1 * a2 - 1) for b12 in xrange(-B3, B3 + 1) : # obstruction for the minor [0,1,2] of t if a0*a1*a2 - a0*b12**2 + 2*b01*b12*b02 - a2*b01**2 - a1*b02**2 <= 0 : continue t = matrix(ZZ, 3, [a0, b01, b02, b01, a1, b12, b02, b12, a2]) u = t.LLL_gram() if u.transpose() * t * u != t : continue sub3s.append((a2, b02, b12)) sub3.append((a0, a1, b01, sub3s)) self.__iter_reduced_sub3 = sub3 return sub3
def init_ecdb_stats(self): if self._stats: return logger.debug("Computing elliptic curve stats...") ecdb = self.ecdb counts = self._counts stats = {} rank_counts = [] for r in range(counts['max_rank']+1): ncu = ecdb.find({'rank': r}).count() ncl = ecdb.find({'rank': r, 'number': 1}).count() prop = format_percentage(ncl,counts['nclasses']) rank_counts.append({'r': r, 'ncurves': ncu, 'nclasses': ncl, 'prop': prop}) stats['rank_counts'] = rank_counts tor_counts = [] tor_counts2 = [] ncurves = counts['ncurves'] for t in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 16]: ncu = ecdb.find({'torsion': t}).count() if t in [4,8,12]: # two possible structures ncyc = ecdb.find({'torsion_structure': [str(t)]}).count() gp = "\(C_{%s}\)"%t prop = format_percentage(ncyc,ncurves) tor_counts.append({'t': t, 'gp': gp, 'ncurves': ncyc, 'prop': prop}) nncyc = ncu-ncyc gp = "\(C_{2}\\times C_{%s}\)"%(t//2) prop = format_percentage(nncyc,ncurves) tor_counts2.append({'t': t, 'gp': gp, 'ncurves': nncyc, 'prop': prop}) elif t==16: # all C_2 x C_8 gp = "\(C_{2}\\times C_{8}\)" prop = format_percentage(ncu,ncurves) tor_counts2.append({'t': t, 'gp': gp, 'ncurves': ncu, 'prop': prop}) else: # all cyclic gp = "\(C_{%s}\)"%t prop = format_percentage(ncu,ncurves) tor_counts.append({'t': t, 'gp': gp, 'ncurves': ncu, 'prop': prop}) stats['tor_counts'] = tor_counts+tor_counts2 stats['max_sha'] = ecdb.find().sort('sha', DESCENDING).limit(1)[0]['sha'] sha_counts = [] from sage.misc.functional import isqrt for s in range(1,1+isqrt(stats['max_sha'])): s2 = s*s nc = ecdb.find({'sha': s2}).count() if nc: sha_counts.append({'s': s, 'ncurves': nc}) stats['sha_counts'] = sha_counts self._stats = stats logger.debug("... finished computing elliptic curve stats.")
def __iter__(self): r""" Iterate over all GL(2,Z)-reduced semi positive forms which are within the bounds of this precision. EXAMPLES:: sage: from sage.modular.siegel.siegel_modular_form_prec import SiegelModularFormPrecision sage: prec = SiegelModularFormPrecision(11) sage: for k in prec.__iter__(): print k (0, 0, 0) (0, 0, 1) (0, 0, 2) (1, 0, 1) (1, 0, 2) (1, 1, 1) (1, 1, 2) NOTE The forms are enumerated in lexicographic order. """ if self.__type == 'disc': bound = self.get_contents_bound_for_semi_definite_forms() for c in range(0, bound): yield (0,0,c) atop = isqrt(self.__prec // 3) if 3*atop*atop == self.__prec: atop -= 1 for a in range(1,atop + 1): for b in range(a+1): for c in range(a, ceil((b**2 + self.__prec)/(4*a))): yield (a,b,c) elif 'box' == self.__type: (am, bm, cm) = self.__prec for a in range(am): for b in range(min(bm,a+1)): for c in range(a, cm): yield (a,b,c) else: raise RuntimeError("Unexpected value of self.__type") raise StopIteration
def __iter__(self): r""" Iterate over all GL(2,Z)-reduced semi positive forms which are within the bounds of this precision. EXAMPLES:: sage: from sage.modular.siegel.siegel_modular_form_prec import SiegelModularFormPrecision sage: prec = SiegelModularFormPrecision(11) sage: for k in prec.__iter__(): print k (0, 0, 0) (0, 0, 1) (0, 0, 2) (1, 0, 1) (1, 0, 2) (1, 1, 1) (1, 1, 2) NOTE The forms are enumerated in lexicographic order. """ if self.__type == 'disc': bound = self.get_contents_bound_for_semi_definite_forms() for c in xrange(0, bound): yield (0,0,c) atop = isqrt(self.__prec // 3) if 3*atop*atop == self.__prec: atop -= 1 for a in xrange(1,atop + 1): for b in xrange(a+1): for c in xrange(a, ceil((b**2 + self.__prec)/(4*a))): yield (a,b,c) elif 'box' == self.__type: (am, bm, cm) = self.__prec for a in xrange(am): for b in xrange( min(bm,a+1)): for c in xrange(a, cm): yield (a,b,c) else: raise RuntimeError, "Unexpected value of self.__type" raise StopIteration
def _calc_iter_reduced_sub2(self): try: return self.__iter_reduced_sub2 except AttributeError: pass sub2 = list() for a0 in range(2, 2 * self.index(), 2): for a1 in range(a0, 2 * self.index(), 2): # obstruction for t[0,1] B1 = isqrt(a0 * a1 - 1) for b01 in range(0, min(B1, a0 // 2) + 1): sub2.append((a0, a1, -b01)) self.__iter_reduced_sub2 = sub2 return sub2
def _jacobi_forms_by_taylor_expansion_coords(index, weight, precision) : global _jacobi_forms_by_taylor_expansion_coords_cache key = (index, weight) try : return _jacobi_forms_by_taylor_expansion_coords_cache[key] except KeyError : if precision < (index - 1) // 4 + 1 : precision = (index - 1) // 4 + 1 weak_forms = _all_weak_jacobi_forms_by_taylor_expansion(index, weight, precision) weak_index_matrix = matrix(ZZ, [ [ f[(n,r)] for n in xrange((index - 1) // 4 + 1) for r in xrange(isqrt(4 * n * index) + 1, index + 1) ] for f in weak_forms] ) _jacobi_forms_by_taylor_expansion_coords_cache[key] = \ weak_index_matrix.left_kernel().echelonized_basis() return _jacobi_forms_by_taylor_expansion_coords_cache[key]
def _calc_iter_reduced_sub2(self) : try : return self.__iter_reduced_sub2 except AttributeError : pass sub2 = list() for a0 in xrange(2, 2 * self.index(), 2) : for a1 in xrange(a0, 2 * self.index(), 2) : # obstruction for t[0,1] B1 = isqrt(a0 * a1 - 1) for b01 in xrange(0, min(B1, a0 // 2) + 1) : sub2.append((a0,a1,-b01)) self.__iter_reduced_sub2 = sub2 return sub2
def __init__( self, q): """ We initialize by a list of integers $[a_1,...,a_N]$. The lattice self is then $L = (L,\beta) = (G^{-1}\ZZ^n/\ZZ^n, G[x])$, where $G$ is the symmetric matrix $G=[a_1,...,a_n;*,a_{n+1},....;..;* ... * a_N]$, i.e.~the $a_j$ denote the elements above the diagonal of $G$. """ self.__form = q # We compute the rank N = len(q) assert is_square( 1+8*N) n = Integer( (-1+isqrt(1+8*N))/2) self.__rank = n # We set up the Gram matrix self.__G = matrix( IntegerRing(), n, n) i = j = 0 for a in q: self.__G[i,j] = self.__G[j,i] = Integer(a) if j < n-1: j += 1 else: i += 1 j = i # We compute the level Gi = self.__G**-1 self.__Gi = Gi a = lcm( map( lambda x: x.denominator(), Gi.list())) I = Gi.diagonal() b = lcm( map( lambda x: (x/2).denominator(), I)) self.__level = lcm( a, b) # We define the undelying module and the ambient space self.__module = FreeModule( IntegerRing(), n) self.__space = self.__module.ambient_vector_space() # We compute a shadow vector self.__shadow_vector = self.__space([(a%2)/2 for a in self.__G.diagonal()])*Gi # We define a basis M = Matrix( IntegerRing(), n, n, 1) self.__basis = self.__module.basis() # We prepare a cache self.__dual_vectors = None self.__values = None self.__chi = {}
def _kohnen_phi(self, a, t): ## We use a modified power of a, namely for each prime factor p of a ## we use p**floor(v_p(a)/2). This is compensated for in the routine ## of \rho a_modif = 1 for (p, e) in a.factor(): a_modif = a_modif * p**(e // 2) res = 0 for dsq in [d for d in a.divisors() if d.is_square()]: d = isqrt(dsq) for g_diag in filter( lambda diag: prod(diag) == d, itertools.product( *[d.divisors() for _ in range(t.nrows())])): for subents in itertools.product(*[ range(r) for (j, r) in enumerate(g_diag) for _ in range(j) ]): columns = [ subents[(j * (j - 1)) // 2:(j * (j + 1)) // 2] for j in range(t.nrows()) ] g = diagonal_matrix(list(g_diag)) for j in range(t.nrows()): for i in range(j): g[i, j] = columns[j][i] ginv = g.inverse() tg = ginv.transpose() * t * ginv try: tg = matrix(ZZ, tg) except: continue if any(tg[i, i] % 2 == 1 for i in range(tg.nrows())): continue tg.set_immutable() res = res + self._kohnen_rho(tg, a // dsq) return a_modif * res
def _jacobi_forms_by_taylor_expansion_coords(index, weight, precision): global _jacobi_forms_by_taylor_expansion_coords_cache key = (index, weight) try: return _jacobi_forms_by_taylor_expansion_coords_cache[key] except KeyError: if precision < (index - 1) // 4 + 1: precision = (index - 1) // 4 + 1 weak_forms = _all_weak_jacobi_forms_by_taylor_expansion( index, weight, precision) weak_index_matrix = matrix(ZZ, [[ f[(n, r)] for n in xrange((index - 1) // 4 + 1) for r in xrange(isqrt(4 * n * index) + 1, index + 1) ] for f in weak_forms]) _jacobi_forms_by_taylor_expansion_coords_cache[key] = \ weak_index_matrix.left_kernel().echelonized_basis() return _jacobi_forms_by_taylor_expansion_coords_cache[key]
def decompositions(self, s): (n, r) = s fm = 4 * self.__m if self.__weak_forms: yield ((0, 0), (n, r)) yield ((n, r), (0, 0)) msq = self.__m**2 for n1 in xrange(1, n): n2 = n - n1 for r1 in xrange( max(r - isqrt(fm * n2 + msq), isqrt(fm * n1 + msq - 1) + 1), min(r + isqrt(fm * n2 + msq) + 1, isqrt(fm * n1 + msq) + 1)): yield ((n1, r1), (n2, r - r1)) else: yield ((0, 0), (n, r)) yield ((n, r), (0, 0)) for n1 in xrange(1, n): n2 = n - n1 ##r = r1 + r2 ##r1**2 <= 4 n1 m ## (r - r1)**2 <= 4 n2 m ## r1**2 - 2*r1*r + r**2 - 4 m n2 <= 0 ## r1 <-> r \pm \sqrt{r**2 - r**2 + 4 m n2} for r1 in xrange( max(r - isqrt(fm * n2), isqrt(fm * n1 - 1) + 1), min(r + isqrt(fm * n2) + 1, isqrt(fm * n1) + 1)): yield ((n1, r1), (n2, r - r1)) raise StopIteration
def iter_positive_forms(self): if self.__disc is infinity: raise ValueError("infinity is not a true filter index") if self.__reduced: for (l, (u, x)) in enumerate(self.__p1list): if u == 0: for a in range(self.__level, self.__trace, self.__level): for c in range(a, self.__trace - a): for b in range( 2 * isqrt(a * c - 1) + 2 if a * c != 1 else 1, 2 * isqrt(a * c)): yield ((a, b, c), l) else: for a in range(1, self.__trace): for b in range(a + 1): ## We need x**2 * a + x * b + c % N == 0 h = ((x**2 + 1) * a + x * b) % self.__level if x == 0 and h == 0: h = 1 for c in range( h, self.__trace - x * b - (x**2 + 1) * a, self.__level): yield ((a, b, c), l) #! if self.__reduced else: for (l, (u, x)) in enumerate(self.__p1list): if u == 0: for a in range(self.__level, self.__trace, self.__level): for c in range(1, self.__trace - a): for b in range( 2 * isqrt(a * c - 1) + 2 if a * c != 1 else 1, 2 * isqrt(a * c)): yield ((a, b, c), l) else: for a in range(1, self.__trace): for c in range(self.__level, self.__trace - a, self.__level): for b in range( 2 * isqrt(a * c - 1) + 2 if a * c != 1 else 1, 2 * isqrt(a * c)): yield ((a, b - 2 * x * a, c - x * b - x**2 * a), l) #! else self.__reduced raise StopIteration
def iter_positive_forms(self) : if self.__disc is infinity : raise ValueError, "infinity is not a true filter index" if self.__reduced : for (l, (u,x)) in enumerate(self.__p1list) : if u == 0 : for a in xrange(self.__level, self.__trace, self.__level) : for c in xrange(a, self.__trace - a) : for b in xrange( 2 * isqrt(a * c - 1) + 2 if a*c != 1 else 1, 2 * isqrt(a * c) ) : yield ((a,b,c), l) else : for a in xrange(1, self.__trace) : for b in xrange(a+1) : ## We need x**2 * a + x * b + c % N == 0 h = ((x**2 + 1) * a + x * b) % self.__level if x == 0 and h == 0 : h = 1 for c in xrange( h, self.__trace - x * b - (x**2 + 1) * a, self.__level ) : yield ((a,b,c), l) #! if self.__reduced else : for (l, (u,x)) in enumerate(self.__p1list) : if u == 0 : for a in xrange(self.__level, self.__trace, self.__level) : for c in xrange(1, self.__trace - a) : for b in xrange( 2 * isqrt(a * c - 1) + 2 if a*c != 1 else 1, 2 * isqrt(a * c) ) : yield ((a,b,c), l) else : for a in xrange(1, self.__trace) : for c in xrange(self.__level, self.__trace - a, self.__level) : for b in xrange( 2 * isqrt(a * c - 1) + 2 if a*c != 1 else 1, 2 * isqrt(a * c) ) : yield ((a, b - 2 * x * a, c - x * b - x**2 * a), l) #! else self.__reduced raise StopIteration
def init_ecdb_stats(self): if self._stats: return logger.debug("Computing elliptic curve stats...") ecdbstats = db.ec_curves.stats counts = self._counts stats = {} rank_counts = [] rdict = dict(ecdbstats.get_oldstat('rank')['counts']) crdict = dict(ecdbstats.get_oldstat('class/rank')['counts']) for r in range(counts['max_rank']+1): try: ncu = rdict[str(r)] ncl = crdict[str(r)] except KeyError: ncu = rdict[r] ncl = crdict[r] prop = format_percentage(ncl,counts['nclasses']) rank_counts.append({'r': r, 'ncurves': ncu, 'nclasses': ncl, 'prop': prop}) stats['rank_counts'] = rank_counts tor_counts = [] tor_counts2 = [] ncurves = counts['ncurves'] tdict = dict(ecdbstats.get_oldstat('torsion')['counts']) tsdict = dict(ecdbstats.get_oldstat('torsion_structure')['counts']) for t in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 16]: try: ncu = tdict[t] except KeyError: ncu = tdict[str(t)] if t in [4,8,12]: # two possible structures ncyc = tsdict[str(t)] gp = "\(C_{%s}\)"%t prop = format_percentage(ncyc,ncurves) tor_counts.append({'t': t, 'gp': gp, 'ncurves': ncyc, 'prop': prop}) nncyc = ncu-ncyc gp = "\(C_{2}\\times C_{%s}\)"%(t//2) prop = format_percentage(nncyc,ncurves) tor_counts2.append({'t': t, 'gp': gp, 'ncurves': nncyc, 'prop': prop}) elif t==16: # all C_2 x C_8 gp = "\(C_{2}\\times C_{8}\)" prop = format_percentage(ncu,ncurves) tor_counts2.append({'t': t, 'gp': gp, 'ncurves': ncu, 'prop': prop}) else: # all cyclic gp = "\(C_{%s}\)"%t prop = format_percentage(ncu,ncurves) tor_counts.append({'t': t, 'gp': gp, 'ncurves': ncu, 'prop': prop}) stats['tor_counts'] = tor_counts+tor_counts2 shadict = dict(ecdbstats.get_oldstat('sha')['counts']) stats['max_sha'] = max([int(s) for s in shadict]) sha_counts = [] from sage.misc.functional import isqrt sha_is_int = True try: nc = shadict[1] except KeyError: sha_is_int = False for s in range(1,1+isqrt(stats['max_sha'])): s2 = s*s if sha_is_int: nc = shadict.get(s2,0) else: nc = shadict.get(str(s2),0) if nc: sha_counts.append({'s': s, 'ncurves': nc}) stats['sha_counts'] = sha_counts self._stats = stats logger.debug("... finished computing elliptic curve stats.")
def maass_form(self, f, g, k=None, is_integral=False): r""" Return the Siegel modular form `I(f,g)` (Notation as in [Sko]). INPUT: - `f` -- modular form of level `1` - `g` -- cusp form of level `1` and weight = ``weight of f + 2`` - ``is_integral`` -- ``True`` if the result is garanteed to have integer coefficients """ ## we introduce an abbreviations if is_integral: PS = self.integral_power_series_ring() else: PS = self.power_series_ring() fismodular = isinstance(f, ModularFormElement) gismodular = isinstance(g, ModularFormElement) ## We only check the arguments if f and g are ModularFormElements. ## Otherwise we trust in the user if fismodular and gismodular: assert( f.weight() + 2 == g.weight() | (f==0) | (g==0)), \ "incorrect weights!" assert ( g.q_expansion(1) == 0), "second argument is not a cusp form" qexp_prec = self._get_maass_form_qexp_prec() if qexp_prec is None: # there are no forms below prec return dict() if fismodular: k = f.weight() if f == f.parent()(0): f = PS(0, qexp_prec) else: f = PS(f.qexp(qexp_prec), qexp_prec) elif f == 0: f = PS(0, qexp_prec) else: f = PS(f(qexp_prec), qexp_prec) if gismodular: k = g.weight() - 2 if g == g.parent()(0): g = PS(0, qexp_prec) else: g = PS(g.qexp(qexp_prec), qexp_prec) elif g == 0: g = PS(0, qexp_prec) else: g = PS(g(qexp_prec), qexp_prec) if k is None: raise ValueError, "if neither f nor g are not ModularFormElements " + \ "you must pass k" fderiv = f.derivative().shift(1) f *= Integer(k / 2) gfderiv = g - fderiv ## Form A and B - the Jacobi forms used in [Sko]'s I map. ## This is not necessary if we multiply Ifg0 and Ifg1 by etapow # (A0,A1,B0,B1) = (a0*etapow, a1*etapow, b0*etapow, b1*etapow) ## Calculate the image of the pair of modular forms (f,g) under ## [Sko]'s isomorphism I : M_{k} \oplus S_{k+2} -> J_{k,1}. # Multiplication of big polynomials may take > 60 GB, so wie have # to do it in small parts; This is only implemented for integral # coefficients. """ Create the Jacobi form I(f,g) as in [Sko]. It suffices to construct for all Jacobi forms phi only the part sum_{r=0,1;n} c_phi(r^2-4n) q^n zeta^r. When, in this code part, we speak of Jacobi form we only mean this part. We need to compute Ifg = \sum_{r=0,1; n} c(r^2-4n) q^n zeta^r up to 4n-r^2 <= Dtop, i.e. n < precision """ ## Create the Jacobi forms A=a*etapow and B=b*etapow in stages. ## Recall a = sum_{s != r mod 2} s^2*(-1)^r*q^((s^2+r^2-1)/4)*zeta^r ## b = sum_{s != r mod 2} (-1)^r*q^((s^2+r^2-1)/4)*zeta^r ## r, s run over ZZ but with opposite parities. ## For r=0, we need s odd, (s^2-1)/4 < precision, with s=2t+1 hence t^2+t < precision. ## For r=1, we need s even, s^2/4 < precision, with s=2t hence t^2 < precision. ## we use a slightly overestimated ab_prec ab_prec = isqrt(qexp_prec + 1) a1dict = dict() a0dict = dict() b1dict = dict() b0dict = dict() for t in xrange(1, ab_prec + 1): tmp = t**2 a1dict[tmp] = -8 * tmp b1dict[tmp] = -2 tmp += t a0dict[tmp] = 8 * tmp + 2 b0dict[tmp] = 2 b1dict[0] = -1 a0dict[0] = 2 b0dict[0] = 2 a1 = PS(a1dict) b1 = PS(b1dict) a0 = PS(a0dict) b0 = PS(b0dict) ## Finally: I(f,g) is given by the formula below: ## We multiply by etapow explecitely and save two multiplications # Ifg0 = k/2*f*A0 - fderiv*B0 + g*B0 + O(q^precision) # Ifg1 = k/2*f*A1 - fderiv*B1 + g*B1 + O(q^precision) Ifg0 = (self._eta_power() * (f * a0 + gfderiv * b0)).list() Ifg1 = (self._eta_power() * (f * a1 + gfderiv * b1)).list() if len(Ifg0) < qexp_prec: Ifg0 += [0] * (qexp_prec - len(Ifg0)) if len(Ifg1) < qexp_prec: Ifg1 += [0] * (qexp_prec - len(Ifg1)) ## For applying the Maass' lifting to genus 2 modular forms. ## we put the coefficients of Ifg into a dictionary Chi ## so that we can access the coefficient corresponding to ## discriminant D by going Chi[D]. Cphi = dict([(0, 0)]) for i in xrange(qexp_prec): Cphi[-4 * i] = Ifg0[i] Cphi[1 - 4 * i] = Ifg1[i] del Ifg0[:], Ifg1[:] """ Create the Maas lift F := VI(f,g) as in [Sko]. """ ## The constant term is given by -Cphi[0]*B_{2k}/(4*k) ## (note in [Sko] this coeff has typos). ## For nonconstant terms, ## The Siegel coefficient of q^n * zeta^r * qdash^m is given ## by the formula \sum_{ a | gcd(n,r,m) } Cphi[D/a^2] where ## D = r^2-4*n*m is the discriminant. ## Hence in either case the coefficient ## is fully deterimined by the pair (D,gcd(n,r,m)). ## Put (D,t) -> \sum_{ a | t } Cphi[D/a^2] ## in a dictionary (hash table) maassc. maass_coeffs = dict() divisor_dict = self._divisor_dict() ## First calculate maass coefficients corresponding to strictly positive definite matrices: for disc in self._negative_fundamental_discriminants(): for s in xrange( 1, isqrt((-self.__precision.discriminant()) // disc) + 1): ## add (disc*s^2,t) as a hash key, for each t that divides s for t in divisor_dict[s]: maass_coeffs[(disc * s**2,t)] = \ sum( a**(k-1) * Cphi[disc * s**2 / a**2] for a in divisor_dict[t] ) ## Compute the coefficients of the Siegel form $F$: siegel_coeffs = dict() for (n, r, m), g in self.__precision.iter_positive_forms_with_content(): siegel_coeffs[(n, r, m)] = maass_coeffs[(r**2 - 4 * m * n, g)] ## Secondly, deal with the singular part. ## Include the coeff corresponding to (0,0,0): ## maass_coeffs = {(0,0): -bernoulli(k)/(2*k)*Cphi[0]} siegel_coeffs[(0, 0, 0)] = -bernoulli(k) / (2 * k) * Cphi[0] if is_integral: siegel_coeffs[(0, 0, 0)] = Integer(siegel_coeffs[(0, 0, 0)]) ## Calculate the other discriminant-zero maass coefficients. ## Since sigma is quite cheap it is faster to estimate the bound and ## save the time for repeated calculation for i in xrange(1, self.__precision._indefinite_content_bound()): ## maass_coeffs[(0,i)] = sigma(i, k-1) * Cphi[0] siegel_coeffs[(0, 0, i)] = sigma(i, k - 1) * Cphi[0] return siegel_coeffs
def init_ecdb_stats(self): if self._stats: return logger.debug("Computing elliptic curve stats...") ecdbstats = db.ec_curves.stats counts = self._counts stats = {} rank_counts = [] rdict = dict(ecdbstats.get_oldstat('rank')['counts']) crdict = dict(ecdbstats.get_oldstat('class/rank')['counts']) for r in range(counts['max_rank'] + 1): try: ncu = rdict[str(r)] ncl = crdict[str(r)] except KeyError: ncu = rdict[r] ncl = crdict[r] prop = format_percentage(ncl, counts['nclasses']) rank_counts.append({ 'r': r, 'ncurves': ncu, 'nclasses': ncl, 'prop': prop }) stats['rank_counts'] = rank_counts tor_counts = [] tor_counts2 = [] ncurves = counts['ncurves'] tdict = dict(ecdbstats.get_oldstat('torsion')['counts']) tsdict = dict(ecdbstats.get_oldstat('torsion_structure')['counts']) for t in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 16]: try: ncu = tdict[t] except KeyError: ncu = tdict[str(t)] if t in [4, 8, 12]: # two possible structures ncyc = tsdict[str(t)] gp = "\(C_{%s}\)" % t prop = format_percentage(ncyc, ncurves) tor_counts.append({ 't': t, 'gp': gp, 'ncurves': ncyc, 'prop': prop }) nncyc = ncu - ncyc gp = "\(C_{2}\\times C_{%s}\)" % (t // 2) prop = format_percentage(nncyc, ncurves) tor_counts2.append({ 't': t, 'gp': gp, 'ncurves': nncyc, 'prop': prop }) elif t == 16: # all C_2 x C_8 gp = "\(C_{2}\\times C_{8}\)" prop = format_percentage(ncu, ncurves) tor_counts2.append({ 't': t, 'gp': gp, 'ncurves': ncu, 'prop': prop }) else: # all cyclic gp = "\(C_{%s}\)" % t prop = format_percentage(ncu, ncurves) tor_counts.append({ 't': t, 'gp': gp, 'ncurves': ncu, 'prop': prop }) stats['tor_counts'] = tor_counts + tor_counts2 shadict = dict(ecdbstats.get_oldstat('sha')['counts']) stats['max_sha'] = max([int(s) for s in shadict]) sha_counts = [] from sage.misc.functional import isqrt sha_is_int = True try: nc = shadict[1] except KeyError: sha_is_int = False for s in range(1, 1 + isqrt(stats['max_sha'])): s2 = s * s if sha_is_int: nc = shadict.get(s2, 0) else: nc = shadict.get(str(s2), 0) if nc: sha_counts.append({'s': s, 'ncurves': nc}) stats['sha_counts'] = sha_counts self._stats = stats logger.debug("... finished computing elliptic curve stats.")
def maass_form( self, f, g, k = None, is_integral = False) : r""" Return the Siegel modular form `I(f,g)` (Notation as in [Sko]). INPUT: - `f` -- modular form of level `1` - `g` -- cusp form of level `1` and weight = ``weight of f + 2`` - ``is_integral`` -- ``True`` if the result is garanteed to have integer coefficients """ ## we introduce an abbreviations if is_integral : PS = self.integral_power_series_ring() else : PS = self.power_series_ring() fismodular = isinstance(f, ModularFormElement) gismodular = isinstance(g, ModularFormElement) ## We only check the arguments if f and g are ModularFormElements. ## Otherwise we trust in the user if fismodular and gismodular : assert( f.weight() + 2 == g.weight() | (f==0) | (g==0)), \ "incorrect weights!" assert( g.q_expansion(1) == 0), "second argument is not a cusp form" qexp_prec = self._get_maass_form_qexp_prec() if qexp_prec is None : # there are no forms below prec return dict() if fismodular : k = f.weight() if f == f.parent()(0) : f = PS(0, qexp_prec) else : f = PS(f.qexp(qexp_prec), qexp_prec) elif f == 0 : f = PS(0, qexp_prec) else : f = PS(f(qexp_prec), qexp_prec) if gismodular : k = g.weight() - 2 if g == g.parent()(0) : g = PS(0, qexp_prec) else : g = PS(g.qexp(qexp_prec), qexp_prec) elif g == 0 : g = PS(0, qexp_prec) else : g = PS(g(qexp_prec), qexp_prec) if k is None : raise ValueError, "if neither f nor g are not ModularFormElements " + \ "you must pass k" fderiv = f.derivative().shift(1) f *= Integer(k/2) gfderiv = g - fderiv ## Form A and B - the Jacobi forms used in [Sko]'s I map. ## This is not necessary if we multiply Ifg0 and Ifg1 by etapow # (A0,A1,B0,B1) = (a0*etapow, a1*etapow, b0*etapow, b1*etapow) ## Calculate the image of the pair of modular forms (f,g) under ## [Sko]'s isomorphism I : M_{k} \oplus S_{k+2} -> J_{k,1}. # Multiplication of big polynomials may take > 60 GB, so wie have # to do it in small parts; This is only implemented for integral # coefficients. """ Create the Jacobi form I(f,g) as in [Sko]. It suffices to construct for all Jacobi forms phi only the part sum_{r=0,1;n} c_phi(r^2-4n) q^n zeta^r. When, in this code part, we speak of Jacobi form we only mean this part. We need to compute Ifg = \sum_{r=0,1; n} c(r^2-4n) q^n zeta^r up to 4n-r^2 <= Dtop, i.e. n < precision """ ## Create the Jacobi forms A=a*etapow and B=b*etapow in stages. ## Recall a = sum_{s != r mod 2} s^2*(-1)^r*q^((s^2+r^2-1)/4)*zeta^r ## b = sum_{s != r mod 2} (-1)^r*q^((s^2+r^2-1)/4)*zeta^r ## r, s run over ZZ but with opposite parities. ## For r=0, we need s odd, (s^2-1)/4 < precision, with s=2t+1 hence t^2+t < precision. ## For r=1, we need s even, s^2/4 < precision, with s=2t hence t^2 < precision. ## we use a slightly overestimated ab_prec ab_prec = isqrt(qexp_prec + 1) a1dict = dict(); a0dict = dict() b1dict = dict(); b0dict = dict() for t in xrange(1, ab_prec + 1) : tmp = t**2 a1dict[tmp] = -8*tmp b1dict[tmp] = -2 tmp += t a0dict[tmp] = 8*tmp + 2 b0dict[tmp] = 2 b1dict[0] = -1 a0dict[0] = 2; b0dict[0] = 2 a1 = PS(a1dict); b1 = PS(b1dict) a0 = PS(a0dict); b0 = PS(b0dict) ## Finally: I(f,g) is given by the formula below: ## We multiply by etapow explecitely and save two multiplications # Ifg0 = k/2*f*A0 - fderiv*B0 + g*B0 + O(q^precision) # Ifg1 = k/2*f*A1 - fderiv*B1 + g*B1 + O(q^precision) Ifg0 = (self._eta_power() * (f*a0 + gfderiv*b0)).list() Ifg1 = (self._eta_power() * (f*a1 + gfderiv*b1)).list() if len(Ifg0) < qexp_prec : Ifg0 += [0]*(qexp_prec - len(Ifg0)) if len(Ifg1) < qexp_prec : Ifg1 += [0]*(qexp_prec - len(Ifg1)) ## For applying the Maass' lifting to genus 2 modular forms. ## we put the coefficients of Ifg into a dictionary Chi ## so that we can access the coefficient corresponding to ## discriminant D by going Chi[D]. Cphi = dict([(0,0)]) for i in xrange(qexp_prec) : Cphi[-4*i] = Ifg0[i] Cphi[1-4*i] = Ifg1[i] del Ifg0[:], Ifg1[:] """ Create the Maas lift F := VI(f,g) as in [Sko]. """ ## The constant term is given by -Cphi[0]*B_{2k}/(4*k) ## (note in [Sko] this coeff has typos). ## For nonconstant terms, ## The Siegel coefficient of q^n * zeta^r * qdash^m is given ## by the formula \sum_{ a | gcd(n,r,m) } Cphi[D/a^2] where ## D = r^2-4*n*m is the discriminant. ## Hence in either case the coefficient ## is fully deterimined by the pair (D,gcd(n,r,m)). ## Put (D,t) -> \sum_{ a | t } Cphi[D/a^2] ## in a dictionary (hash table) maassc. maass_coeffs = dict() divisor_dict = self._divisor_dict() ## First calculate maass coefficients corresponding to strictly positive definite matrices: for disc in self._negative_fundamental_discriminants() : for s in xrange(1, isqrt((-self.__precision.discriminant()) // disc) + 1) : ## add (disc*s^2,t) as a hash key, for each t that divides s for t in divisor_dict[s] : maass_coeffs[(disc * s**2,t)] = \ sum( a**(k-1) * Cphi[disc * s**2 / a**2] for a in divisor_dict[t] ) ## Compute the coefficients of the Siegel form $F$: siegel_coeffs = dict() for (n,r,m), g in self.__precision.iter_positive_forms_with_content() : siegel_coeffs[(n,r,m)] = maass_coeffs[(r**2 - 4*m*n, g)] ## Secondly, deal with the singular part. ## Include the coeff corresponding to (0,0,0): ## maass_coeffs = {(0,0): -bernoulli(k)/(2*k)*Cphi[0]} siegel_coeffs[(0,0,0)] = -bernoulli(k)/(2*k)*Cphi[0] if is_integral : siegel_coeffs[(0,0,0)] = Integer(siegel_coeffs[(0,0,0)]) ## Calculate the other discriminant-zero maass coefficients. ## Since sigma is quite cheap it is faster to estimate the bound and ## save the time for repeated calculation for i in xrange(1, self.__precision._indefinite_content_bound()) : ## maass_coeffs[(0,i)] = sigma(i, k-1) * Cphi[0] siegel_coeffs[(0,0,i)] = sigma(i, k-1) * Cphi[0] return siegel_coeffs
def iter_positive_forms(self) : if self.__disc is infinity : raise ValueError, "infinity is not a true filter index" if self.__reduced : for (l, (u,x)) in enumerate(self.__p1list) : if u == 0 : for a in xrange(self.__level, isqrt(self.__disc // 4) + 1, self.__level) : for b in xrange(a+1) : for c in xrange(a, (b**2 + (self.__disc - 1))//(4*a) + 1) : yield ((a,b,c), l) else : for a in xrange(1, isqrt(self.__disc // 3) + 1) : for b in xrange(a+1) : ## We need x**2 * a + x * b + c % N == 0 h = (-((x**2 + 1) * a + x * b)) % self.__level for c in xrange( a + h, (b**2 + (self.__disc - 1))//(4*a) + 1, self.__level ) : yield ((a,b,c), l) #! if self.__reduced else : maxtrace = floor(self.__disc / Integer(3) + sqrt(self.__disc / Integer(3))) for (l, (u,x)) in enumerate(self.__p1list) : if u == 0 : for a in xrange(self.__level, maxtrace + 1, self.__level) : for c in xrange(1, maxtrace - a + 1) : Bu = isqrt(4*a*c - 1) di = 4*a*c - self.__disc if di >= 0 : Bl = isqrt(di) + 1 else : Bl = 0 for b in xrange(-Bu, -Bl + 1) : yield ((a,b,c), l) for b in xrange(Bl, Bu + 1) : yield ((a,b,c), l) else : for a in xrange(1, maxtrace + 1) : for c in xrange(1, maxtrace - a + 1) : Bu = isqrt(4*a*c - 1) di = 4*a*c - self.__disc if di >= 0 : Bl = isqrt(di) + 1 else : Bl = 0 h = (-x * a - int(Mod(x, self.__level)**-1) * c - Bu) % self.__level \ if x != 0 else \ (-Bu) % self.__level for b in xrange(-Bu + self.__level - h, -Bl + 1, self.__level) : yield ((a,b,c), l) h = (-x * a - int(Mod(x, self.__level)**-1) * c + Bl) % self.__level \ if x !=0 else \ Bl % self.__level for b in xrange(Bl + self.__level - h, Bu + 1, self.__level) : yield ((a,b,c), l) #! else self.__reduced raise StopIteration
def _by_taylor_expansion_m1(self, f_divs, k, is_integral=False): r""" This provides faster implementation of by_taylor_expansion in the case of Jacobi index `1` (and even weight). It avoids the computation of the Wronskian by providing an explicit formula. """ raise RuntimeError( "This code is known to have a bug. Use, for example,JacobiFormD1NNFactory_class._test__by_taylor_expansion(200, 10, 1) to check." ) if is_integral: PS = self.integral_power_series_ring() else: PS = self.power_series_ring() qexp_prec = self._qexp_precision() fderiv = f_divs[(0, 0)].derivative().shift(1) f = f_divs[(0, 0)] * Integer(k / 2) gfderiv = f_divs[(1, 0)] - fderiv ab_prec = isqrt(qexp_prec + 1) a1dict = dict() a0dict = dict() b1dict = dict() b0dict = dict() for t in xrange(1, ab_prec + 1): tmp = t**2 a1dict[tmp] = -8 * tmp b1dict[tmp] = -2 tmp += t a0dict[tmp] = 8 * tmp + 2 b0dict[tmp] = 2 b1dict[0] = -1 a0dict[0] = 2 b0dict[0] = 2 a1 = PS(a1dict) b1 = PS(b1dict) a0 = PS(a0dict) b0 = PS(b0dict) Ifg0 = (self._wronskian_invdeterminant() * (f * a0 + gfderiv * b0)).list() Ifg1 = (self._wronskian_invdeterminant() * (f * a1 + gfderiv * b1)).list() if len(Ifg0) < qexp_prec: Ifg0 += [0] * (qexp_prec - len(Ifg0)) if len(Ifg1) < qexp_prec: Ifg1 += [0] * (qexp_prec - len(Ifg1)) Cphi = dict([(0, 0)]) for i in xrange(qexp_prec): Cphi[-4 * i] = Ifg0[i] Cphi[1 - 4 * i] = Ifg1[i] del Ifg0[:], Ifg1[:] phi_coeffs = dict() for r in xrange(2): for n in xrange(qexp_prec): k = 4 * n - r**2 if k >= 0: phi_coeffs[(n, r)] = Cphi[-k] return phi_coeffs
def _theta_factors(self, p = None) : r""" Return the factor `W^\# (\theta_0, .., \theta_{2m - 1})^{\mathrm{T}}` as a list. The `q`-expansion is shifted by `-(m + 1)(2*m + 1) / 24` which will be compensated for by the eta factor. """ try : if p is None : return self.__theta_factors else : P = PowerSeriesRing(GF(p), 'q') return [map(P, facs) for facs in self.__theta_factors] except AttributeError : qexp_prec = self._qexp_precision() if p is None : PS = self.integral_power_series_ring() else : PS = PowerSeriesRing(GF(p), 'q') m = self.__precision.jacobi_index() twom = 2 * m frmsq = twom ** 2 thetas = dict( ((i, j), dict()) for i in xrange(m + 1) for j in xrange(m + 1) ) ## We want to calculate \hat \theta_{j,l} = sum_r (2 m r + j)**2l q**(m r**2 + j r). for r in xrange(0, isqrt((qexp_prec - 1 + m)//m) + 2) : for j in [0,m] : fact = (twom*r + j)**2 coeff = 2 for l in xrange(0, m + 1) : thetas[(j,l)][m*r**2 + r*j] = coeff coeff = coeff * fact thetas[(0,0)][0] = 1 for r in xrange(0, isqrt((qexp_prec - 1 + m)//m) + 2) : for j in xrange(1, m) : fact_p = (twom*r + j)**2 fact_m = (twom*r - j)**2 coeff_p = 2 coeff_m = 2 for l in xrange(0, m + 1) : thetas[(j,l)][m*r**2 + r*j] = coeff_p thetas[(j,l)][m*r**2 - r*j] = coeff_m coeff_p = coeff_p * fact_p coeff_m = coeff_m * fact_m thetas = dict( ( k, PS(th).add_bigoh(qexp_prec) ) for (k,th) in thetas.iteritems() ) W = matrix(PS, m + 1, [ thetas[(j, l)] for j in xrange(m + 1) for l in xrange(m + 1) ]) ## Since the adjoint of matrices with entries in a general ring ## is extremely slow for matrices of small size, we hard code the ## the cases `m = 2` and `m = 3`. The expressions are obtained by ## computing the adjoint of a matrix with entries `w_{i,j}` in a ## polynomial algebra. if m == 2 and qexp_prec > 10**5 : adj00 = W[1,1] * W[2,2] - W[2,1] * W[1,2] adj01 = - W[1,0] * W[2,2] + W[2,0] * W[1,2] adj02 = W[1,0] * W[2,1] - W[2,0] * W[1,1] adj10 = - W[0,1] * W[2,2] + W[2,1] * W[0,2] adj11 = W[0,0] * W[2,2] - W[2,0] * W[0,2] adj12 = - W[0,0] * W[2,1] + W[2,0] * W[0,1] adj20 = W[0,1] * W[1,2] - W[1,1] * W[0,2] adj21 = - W[0,0] * W[1,2] + W[1,0] * W[0,2] adj22 = W[0,0] * W[1,1] - W[1,0] * W[0,1] Wadj = matrix(PS, [ [adj00, adj01, adj02], [adj10, adj11, adj12], [adj20, adj21, adj22] ]) elif m == 3 and qexp_prec > 10**5 : adj00 = -W[0,2]*W[1,1]*W[2,0] + W[0,1]*W[1,2]*W[2,0] + W[0,2]*W[1,0]*W[2,1] - W[0,0]*W[1,2]*W[2,1] - W[0,1]*W[1,0]*W[2,2] + W[0,0]*W[1,1]*W[2,2] adj01 = -W[0,3]*W[1,1]*W[2,0] + W[0,1]*W[1,3]*W[2,0] + W[0,3]*W[1,0]*W[2,1] - W[0,0]*W[1,3]*W[2,1] - W[0,1]*W[1,0]*W[2,3] + W[0,0]*W[1,1]*W[2,3] adj02 = -W[0,3]*W[1,2]*W[2,0] + W[0,2]*W[1,3]*W[2,0] + W[0,3]*W[1,0]*W[2,2] - W[0,0]*W[1,3]*W[2,2] - W[0,2]*W[1,0]*W[2,3] + W[0,0]*W[1,2]*W[2,3] adj03 = -W[0,3]*W[1,2]*W[2,1] + W[0,2]*W[1,3]*W[2,1] + W[0,3]*W[1,1]*W[2,2] - W[0,1]*W[1,3]*W[2,2] - W[0,2]*W[1,1]*W[2,3] + W[0,1]*W[1,2]*W[2,3] adj10 = -W[0,2]*W[1,1]*W[3,0] + W[0,1]*W[1,2]*W[3,0] + W[0,2]*W[1,0]*W[3,1] - W[0,0]*W[1,2]*W[3,1] - W[0,1]*W[1,0]*W[3,2] + W[0,0]*W[1,1]*W[3,2] adj11 = -W[0,3]*W[1,1]*W[3,0] + W[0,1]*W[1,3]*W[3,0] + W[0,3]*W[1,0]*W[3,1] - W[0,0]*W[1,3]*W[3,1] - W[0,1]*W[1,0]*W[3,3] + W[0,0]*W[1,1]*W[3,3] adj12 = -W[0,3]*W[1,2]*W[3,0] + W[0,2]*W[1,3]*W[3,0] + W[0,3]*W[1,0]*W[3,2] - W[0,0]*W[1,3]*W[3,2] - W[0,2]*W[1,0]*W[3,3] + W[0,0]*W[1,2]*W[3,3] adj13 = -W[0,3]*W[1,2]*W[3,1] + W[0,2]*W[1,3]*W[3,1] + W[0,3]*W[1,1]*W[3,2] - W[0,1]*W[1,3]*W[3,2] - W[0,2]*W[1,1]*W[3,3] + W[0,1]*W[1,2]*W[3,3] adj20 = -W[0,2]*W[2,1]*W[3,0] + W[0,1]*W[2,2]*W[3,0] + W[0,2]*W[2,0]*W[3,1] - W[0,0]*W[2,2]*W[3,1] - W[0,1]*W[2,0]*W[3,2] + W[0,0]*W[2,1]*W[3,2] adj21 = -W[0,3]*W[2,1]*W[3,0] + W[0,1]*W[2,3]*W[3,0] + W[0,3]*W[2,0]*W[3,1] - W[0,0]*W[2,3]*W[3,1] - W[0,1]*W[2,0]*W[3,3] + W[0,0]*W[2,1]*W[3,3] adj22 = -W[0,3]*W[2,2]*W[3,0] + W[0,2]*W[2,3]*W[3,0] + W[0,3]*W[2,0]*W[3,2] - W[0,0]*W[2,3]*W[3,2] - W[0,2]*W[2,0]*W[3,3] + W[0,0]*W[2,2]*W[3,3] adj23 = -W[0,3]*W[2,2]*W[3,1] + W[0,2]*W[2,3]*W[3,1] + W[0,3]*W[2,1]*W[3,2] - W[0,1]*W[2,3]*W[3,2] - W[0,2]*W[2,1]*W[3,3] + W[0,1]*W[2,2]*W[3,3] adj30 = -W[1,2]*W[2,1]*W[3,0] + W[1,1]*W[2,2]*W[3,0] + W[1,2]*W[2,0]*W[3,1] - W[1,0]*W[2,2]*W[3,1] - W[1,1]*W[2,0]*W[3,2] + W[1,0]*W[2,1]*W[3,2] adj31 = -W[1,3]*W[2,1]*W[3,0] + W[1,1]*W[2,3]*W[3,0] + W[1,3]*W[2,0]*W[3,1] - W[1,0]*W[2,3]*W[3,1] - W[1,1]*W[2,0]*W[3,3] + W[1,0]*W[2,1]*W[3,3] adj32 = -W[1,3]*W[2,2]*W[3,0] + W[1,2]*W[2,3]*W[3,0] + W[1,3]*W[2,0]*W[3,2] - W[1,0]*W[2,3]*W[3,2] - W[1,2]*W[2,0]*W[3,3] + W[1,0]*W[2,2]*W[3,3] adj33 = -W[1,3]*W[2,2]*W[3,1] + W[1,2]*W[2,3]*W[3,1] + W[1,3]*W[2,1]*W[3,2] - W[1,1]*W[2,3]*W[3,2] - W[1,2]*W[2,1]*W[3,3] + W[1,1]*W[2,2]*W[3,3] Wadj = matrix(PS, [ [adj00, adj01, adj02, adj03], [adj10, adj11, adj12, adj13], [adj20, adj21, adj22, adj23], [adj30, adj31, adj32, adj33] ]) else : Wadj = W.adjoint() theta_factors = [ [ Wadj[i,r] for i in xrange(m + 1) ] for r in xrange(m + 1) ] if p is None : self.__theta_factors = theta_factors return theta_factors
def _by_taylor_expansion_m1(self, f_divs, k, is_integral=False): r""" This provides special, faster code in the Jacobi index `1` case. """ if is_integral: PS = self.integral_power_series_ring() else: PS = self.power_series_ring() qexp_prec = self._qexp_precision() fderiv = f_divs[(0, 0)].derivative().shift(1) f = f_divs[(0, 0)] * Integer(k / 2) gfderiv = f_divs[(1, 0)] - fderiv ab_prec = isqrt(qexp_prec + 1) a1dict = dict() a0dict = dict() b1dict = dict() b0dict = dict() for t in xrange(1, ab_prec + 1): tmp = t**2 a1dict[tmp] = -8 * tmp b1dict[tmp] = -2 tmp += t a0dict[tmp] = 8 * tmp + 2 b0dict[tmp] = 2 b1dict[0] = -1 a0dict[0] = 2 b0dict[0] = 2 a1 = PS(a1dict) b1 = PS(b1dict) a0 = PS(a0dict) b0 = PS(b0dict) Ifg0 = (self._eta_factor() * (f * a0 + gfderiv * b0)).list() Ifg1 = (self._eta_factor() * (f * a1 + gfderiv * b1)).list() if len(Ifg0) < qexp_prec: Ifg0 += [0] * (qexp_prec - len(Ifg0)) if len(Ifg1) < qexp_prec: Ifg1 += [0] * (qexp_prec - len(Ifg1)) Cphi = dict([(0, 0)]) for i in xrange(qexp_prec): Cphi[-4 * i] = Ifg0[i] Cphi[1 - 4 * i] = Ifg1[i] del Ifg0[:], Ifg1[:] phi_coeffs = dict() m = self.__precision.jacobi_index() for r in xrange(2 * self.__precision.jacobi_index()): for n in xrange(qexp_prec): k = 4 * m * n - r**2 if k >= 0: phi_coeffs[(n, r)] = Cphi[-k] return phi_coeffs
def __iter__(self): if self.index() is infinity: raise ValueError("infinity is not a true filter index") if self.is_reduced(): ## We only iterate positive definite matrices ## and later build the semidefinite ones ## We first find possible upper left matrices sub2 = self._calc_iter_reduced_sub2() sub3 = self._calc_iter_reduced_sub3() sub4 = self._calc_iter_reduced_sub4() t = zero_matrix(ZZ, 4) t.set_immutable() yield t for a0 in range(2, 2 * self.index(), 2): t = zero_matrix(ZZ, 4) t[3, 3] = a0 t.set_immutable() yield t for (a0, a1, b01) in sub2: t = zero_matrix(ZZ, 4) t[2, 2] = a0 t[3, 3] = a1 t[2, 3] = b01 t[3, 2] = b01 t.set_immutable() yield t for (a0, a1, b01, sub3s) in sub3: t = zero_matrix(ZZ, 4) t[1, 1] = a0 t[2, 2] = a1 t[1, 2] = b01 t[2, 1] = b01 for (a2, b02, b12) in sub3s: ts = copy(t) ts[3, 3] = a2 ts[1, 3] = b02 ts[3, 1] = b02 ts[2, 3] = b12 ts[3, 2] = b12 ts.set_immutable() yield ts for (a0, a1, b01, sub4s) in sub4: t = zero_matrix(ZZ, 4) t[0, 0] = a0 t[1, 1] = a1 t[0, 1] = b01 t[1, 0] = b01 for (a2, b02, b12, sub4ss) in sub4s: ts = copy(t) ts[2, 2] = a2 ts[0, 2] = b02 ts[2, 0] = b02 ts[1, 2] = b12 ts[2, 1] = b12 for (a3, b03, b13, b23) in sub4ss: tss = copy(ts) tss[3, 3] = a3 tss[0, 1] = b01 tss[1, 0] = b01 tss[0, 2] = b02 tss[2, 0] = b02 tss[0, 3] = b03 tss[3, 0] = b03 tss.set_immutable() yield tss #! if self.is_reduced() else: ## We first find possible upper left matrices sub2 = list() for a0 in range(2 * self.index(), 2): for a1 in range(2 * self.index(), 2): # obstruction for t[0,1] B1 = isqrt(a0 * a1) for b01 in range(-B1, B1 + 1): sub2.append((a0, a1, b01)) sub3 = list() for (a0, a1, b01) in sub2: sub3s = list() for a2 in range(2 * self.index(), 2): # obstruction for t[0,2] B1 = isqrt(a0 * a2) for b02 in range(-B1, B1 + 1): # obstruction for t[1,2] B3 = isqrt(a1 * a2) for b12 in range(-B3, B3 + 1): # obstruction for the minor [0,1,2] of t if a0 * a1 * a2 - a0 * b12**2 + 2 * b01 * b12 * b02 - b01**2 * a2 - a1 * b02**2 < 0: continue sub3s.append((a2, b02, b12)) sub3.append((a0, a1, b01, sub3s)) for (a0, a1, b01, sub3s) in sub3: for (a2, b02, b12) in sub3s: for a3 in range(2 * self.index(), 2): # obstruction for t[0,3] B1 = isqrt(a0 * a3) for b03 in range(-B1, B1 + 1): # obstruction for t[1,3] B3 = isqrt(a1 * a3) for b13 in range(-B3, B3 + 1): # obstruction for the minor [0,1,3] of t if a0 * a1 * a3 - a0 * b13**2 + 2 * b01 * b13 * b03 - b01**2 * a3 - a1 * b03**2 < 0: continue # obstruction for t[2,3] B3 = isqrt(a2 * a3) for b23 in range(-B3, B3 + 1): # obstruction for the minor [0,2,3] of t if a0 * a2 * a3 - a0 * b23**2 + 2 * b02 * b23 * b03 - b02**2 * a3 - a2 * b03**2 < 0: continue # obstruction for the minor [1,2,3] of t if a1 * a2 * a3 - a1 * b23**2 + 2 * b12 * b23 * b13 - b12**2 * a3 - a2 * b13**2 < 0: continue t = matrix(ZZ, 4, [ a0, b01, b02, b03, b01, a1, b12, b13, b02, b12, a2, b23, b03, b13, b23, a3 ], check=False) if t.det() < 0: continue t.set_immutable() yield t raise StopIteration
def _theta_factors(self, p=None): r""" Return the factor `W^\# (\theta_0, .., \theta_{2m - 1})^{\mathrm{T}}` as a list. The `q`-expansion is shifted by `-(m + 1)(2*m + 1) / 24` which will be compensated for by the eta factor. """ try: if p is None: return self.__theta_factors else: P = PowerSeriesRing(GF(p), 'q') return [map(P, facs) for facs in self.__theta_factors] except AttributeError: qexp_prec = self._qexp_precision() if p is None: PS = self.integral_power_series_ring() else: PS = PowerSeriesRing(GF(p), 'q') m = self.__precision.jacobi_index() twom = 2 * m frmsq = twom**2 thetas = dict( ((i, j), dict()) for i in xrange(m + 1) for j in xrange(m + 1)) ## We want to calculate \hat \theta_{j,l} = sum_r (2 m r + j)**2l q**(m r**2 + j r). for r in xrange(0, isqrt((qexp_prec - 1 + m) // m) + 2): for j in [0, m]: fact = (twom * r + j)**2 coeff = 2 for l in xrange(0, m + 1): thetas[(j, l)][m * r**2 + r * j] = coeff coeff = coeff * fact thetas[(0, 0)][0] = 1 for r in xrange(0, isqrt((qexp_prec - 1 + m) // m) + 2): for j in xrange(1, m): fact_p = (twom * r + j)**2 fact_m = (twom * r - j)**2 coeff_p = 2 coeff_m = 2 for l in xrange(0, m + 1): thetas[(j, l)][m * r**2 + r * j] = coeff_p thetas[(j, l)][m * r**2 - r * j] = coeff_m coeff_p = coeff_p * fact_p coeff_m = coeff_m * fact_m thetas = dict((k, PS(th).add_bigoh(qexp_prec)) for (k, th) in thetas.iteritems()) W = matrix( PS, m + 1, [thetas[(j, l)] for j in xrange(m + 1) for l in xrange(m + 1)]) ## Since the adjoint of matrices with entries in a general ring ## is extremely slow for matrices of small size, we hard code the ## the cases `m = 2` and `m = 3`. The expressions are obtained by ## computing the adjoint of a matrix with entries `w_{i,j}` in a ## polynomial algebra. if m == 2 and qexp_prec > 10**5: adj00 = W[1, 1] * W[2, 2] - W[2, 1] * W[1, 2] adj01 = -W[1, 0] * W[2, 2] + W[2, 0] * W[1, 2] adj02 = W[1, 0] * W[2, 1] - W[2, 0] * W[1, 1] adj10 = -W[0, 1] * W[2, 2] + W[2, 1] * W[0, 2] adj11 = W[0, 0] * W[2, 2] - W[2, 0] * W[0, 2] adj12 = -W[0, 0] * W[2, 1] + W[2, 0] * W[0, 1] adj20 = W[0, 1] * W[1, 2] - W[1, 1] * W[0, 2] adj21 = -W[0, 0] * W[1, 2] + W[1, 0] * W[0, 2] adj22 = W[0, 0] * W[1, 1] - W[1, 0] * W[0, 1] Wadj = matrix(PS, [[adj00, adj01, adj02], [adj10, adj11, adj12], [adj20, adj21, adj22]]) elif m == 3 and qexp_prec > 10**5: adj00 = -W[0, 2] * W[1, 1] * W[2, 0] + W[0, 1] * W[1, 2] * W[ 2, 0] + W[0, 2] * W[1, 0] * W[2, 1] - W[0, 0] * W[ 1, 2] * W[2, 1] - W[0, 1] * W[1, 0] * W[2, 2] + W[ 0, 0] * W[1, 1] * W[2, 2] adj01 = -W[0, 3] * W[1, 1] * W[2, 0] + W[0, 1] * W[1, 3] * W[ 2, 0] + W[0, 3] * W[1, 0] * W[2, 1] - W[0, 0] * W[ 1, 3] * W[2, 1] - W[0, 1] * W[1, 0] * W[2, 3] + W[ 0, 0] * W[1, 1] * W[2, 3] adj02 = -W[0, 3] * W[1, 2] * W[2, 0] + W[0, 2] * W[1, 3] * W[ 2, 0] + W[0, 3] * W[1, 0] * W[2, 2] - W[0, 0] * W[ 1, 3] * W[2, 2] - W[0, 2] * W[1, 0] * W[2, 3] + W[ 0, 0] * W[1, 2] * W[2, 3] adj03 = -W[0, 3] * W[1, 2] * W[2, 1] + W[0, 2] * W[1, 3] * W[ 2, 1] + W[0, 3] * W[1, 1] * W[2, 2] - W[0, 1] * W[ 1, 3] * W[2, 2] - W[0, 2] * W[1, 1] * W[2, 3] + W[ 0, 1] * W[1, 2] * W[2, 3] adj10 = -W[0, 2] * W[1, 1] * W[3, 0] + W[0, 1] * W[1, 2] * W[ 3, 0] + W[0, 2] * W[1, 0] * W[3, 1] - W[0, 0] * W[ 1, 2] * W[3, 1] - W[0, 1] * W[1, 0] * W[3, 2] + W[ 0, 0] * W[1, 1] * W[3, 2] adj11 = -W[0, 3] * W[1, 1] * W[3, 0] + W[0, 1] * W[1, 3] * W[ 3, 0] + W[0, 3] * W[1, 0] * W[3, 1] - W[0, 0] * W[ 1, 3] * W[3, 1] - W[0, 1] * W[1, 0] * W[3, 3] + W[ 0, 0] * W[1, 1] * W[3, 3] adj12 = -W[0, 3] * W[1, 2] * W[3, 0] + W[0, 2] * W[1, 3] * W[ 3, 0] + W[0, 3] * W[1, 0] * W[3, 2] - W[0, 0] * W[ 1, 3] * W[3, 2] - W[0, 2] * W[1, 0] * W[3, 3] + W[ 0, 0] * W[1, 2] * W[3, 3] adj13 = -W[0, 3] * W[1, 2] * W[3, 1] + W[0, 2] * W[1, 3] * W[ 3, 1] + W[0, 3] * W[1, 1] * W[3, 2] - W[0, 1] * W[ 1, 3] * W[3, 2] - W[0, 2] * W[1, 1] * W[3, 3] + W[ 0, 1] * W[1, 2] * W[3, 3] adj20 = -W[0, 2] * W[2, 1] * W[3, 0] + W[0, 1] * W[2, 2] * W[ 3, 0] + W[0, 2] * W[2, 0] * W[3, 1] - W[0, 0] * W[ 2, 2] * W[3, 1] - W[0, 1] * W[2, 0] * W[3, 2] + W[ 0, 0] * W[2, 1] * W[3, 2] adj21 = -W[0, 3] * W[2, 1] * W[3, 0] + W[0, 1] * W[2, 3] * W[ 3, 0] + W[0, 3] * W[2, 0] * W[3, 1] - W[0, 0] * W[ 2, 3] * W[3, 1] - W[0, 1] * W[2, 0] * W[3, 3] + W[ 0, 0] * W[2, 1] * W[3, 3] adj22 = -W[0, 3] * W[2, 2] * W[3, 0] + W[0, 2] * W[2, 3] * W[ 3, 0] + W[0, 3] * W[2, 0] * W[3, 2] - W[0, 0] * W[ 2, 3] * W[3, 2] - W[0, 2] * W[2, 0] * W[3, 3] + W[ 0, 0] * W[2, 2] * W[3, 3] adj23 = -W[0, 3] * W[2, 2] * W[3, 1] + W[0, 2] * W[2, 3] * W[ 3, 1] + W[0, 3] * W[2, 1] * W[3, 2] - W[0, 1] * W[ 2, 3] * W[3, 2] - W[0, 2] * W[2, 1] * W[3, 3] + W[ 0, 1] * W[2, 2] * W[3, 3] adj30 = -W[1, 2] * W[2, 1] * W[3, 0] + W[1, 1] * W[2, 2] * W[ 3, 0] + W[1, 2] * W[2, 0] * W[3, 1] - W[1, 0] * W[ 2, 2] * W[3, 1] - W[1, 1] * W[2, 0] * W[3, 2] + W[ 1, 0] * W[2, 1] * W[3, 2] adj31 = -W[1, 3] * W[2, 1] * W[3, 0] + W[1, 1] * W[2, 3] * W[ 3, 0] + W[1, 3] * W[2, 0] * W[3, 1] - W[1, 0] * W[ 2, 3] * W[3, 1] - W[1, 1] * W[2, 0] * W[3, 3] + W[ 1, 0] * W[2, 1] * W[3, 3] adj32 = -W[1, 3] * W[2, 2] * W[3, 0] + W[1, 2] * W[2, 3] * W[ 3, 0] + W[1, 3] * W[2, 0] * W[3, 2] - W[1, 0] * W[ 2, 3] * W[3, 2] - W[1, 2] * W[2, 0] * W[3, 3] + W[ 1, 0] * W[2, 2] * W[3, 3] adj33 = -W[1, 3] * W[2, 2] * W[3, 1] + W[1, 2] * W[2, 3] * W[ 3, 1] + W[1, 3] * W[2, 1] * W[3, 2] - W[1, 1] * W[ 2, 3] * W[3, 2] - W[1, 2] * W[2, 1] * W[3, 3] + W[ 1, 1] * W[2, 2] * W[3, 3] Wadj = matrix(PS, [[adj00, adj01, adj02, adj03], [adj10, adj11, adj12, adj13], [adj20, adj21, adj22, adj23], [adj30, adj31, adj32, adj33]]) else: Wadj = W.adjoint() theta_factors = [[Wadj[i, r] for i in xrange(m + 1)] for r in xrange(m + 1)] if p is None: self.__theta_factors = theta_factors return theta_factors
def decompositions(self, t): ## We find all decompositions t1 + t2 = t ## We first find possible upper left matrices sub2 = list() for a0 in range(0, t[0, 0] + 1, 2): for a1 in range(0, t[1, 1] + 1, 2): # obstruction for t1[0,1] B1 = isqrt(a0 * a1) # obstruction for t2[0,1] B2 = isqrt((t[0, 0] - a0) * (t[1, 1] - a1)) for b01 in range(max(-B1, t[0, 1] - B2), min(B1, t[0, 1] + B2) + 1): sub2.append((a0, a1, b01)) sub3 = list() for (a0, a1, b01) in sub2: sub3s = list() for a2 in range(0, t[2, 2] + 1, 2): # obstruction for t1[0,2] B1 = isqrt(a0 * a2) # obstruction for t2[0,2] B2 = isqrt((t[0, 0] - a0) * (t[2, 2] - a2)) for b02 in range(max(-B1, t[0, 2] - B2), min(B1, t[0, 2] + B2) + 1): # obstruction for t1[1,2] B3 = isqrt(a1 * a2) # obstruction for t2[1,2] B4 = isqrt((t[1, 1] - a1) * (t[2, 2] - a2)) for b12 in range(max(-B3, t[1, 2] - B4), min(B3, t[1, 2] + B4) + 1): # obstruction for the minor [0,1,2] of t1 if a0 * a1 * a2 - a0 * b12**2 + 2 * b01 * b12 * b02 - b01**2 * a2 - a1 * b02**2 < 0: continue # obstruction for the minor [0,1,2] of t2 if (t[0,0] - a0)*(t[1,1] - a1)*(t[2,2] - a2) - (t[0,0] - a0)*(t[1,2] - b12)**2 \ + 2*(t[0,1] - b01)*(t[1,2] - b12)*(t[0,2] - b02) - (t[0,1] - b01)**2*(t[2,2] - a2) \ - (t[1,1] - a1)*(t[0,2] - b02)**2 < 0: continue sub3s.append((a2, b02, b12)) sub3.append((a0, a1, b01, sub3s)) for (a0, a1, b01, sub3s) in sub3: for (a2, b02, b12) in sub3s: for a3 in range(0, t[3, 3] + 1, 2): # obstruction for t1[0,3] B1 = isqrt(a0 * a3) # obstruction for t2[0,3] B2 = isqrt((t[0, 0] - a0) * (t[3, 3] - a3)) for b03 in range(max(-B1, t[0, 3] - B2), min(B1, t[0, 3] + B2) + 1): # obstruction for t1[1,3] B3 = isqrt(a1 * a3) # obstruction for t2[1,3] B4 = isqrt((t[1, 1] - a1) * (t[3, 3] - a3)) for b13 in range(max(-B3, t[1, 3] - B4), min(B3, t[1, 3] + B4) + 1): # obstruction for the minor [0,1,3] of t1 if a0 * a1 * a3 - a0 * b13**2 + 2 * b01 * b13 * b03 - b01**2 * a3 - a1 * b03**2 < 0: continue # obstruction for the minor [0,1,3] of t2 if (t[0,0] - a0)*(t[1,1] - a1)*(t[3,3] - a3) - (t[0,0] - a0)*(t[1,3] - b13)**2 \ + 2*(t[0,1] - b01)*(t[1,3] - b13)*(t[0,3] - b03) - (t[0,1] - b01)**2*(t[3,3] - a3) \ - (t[1,1] - a1)*(t[0,3] - b03)**2 < 0: continue # obstruction for t1[2,3] B3 = isqrt(a2 * a3) # obstruction for t2[2,3] B4 = isqrt((t[2, 2] - a2) * (t[3, 3] - a3)) for b23 in range(max(-B3, t[2, 3] - B4), min(B3, t[2, 3] + B4) + 1): # obstruction for the minor [0,2,3] of t1 if a0 * a2 * a3 - a0 * b23**2 + 2 * b02 * b23 * b03 - b02**2 * a3 - a2 * b03**2 < 0: continue # obstruction for the minor [0,2,3] of t2 if (t[0,0] - a0)*(t[2,2] - a2)*(t[3,3] - a3) - (t[0,0] - a0)*(t[2,3] - b23)**2 \ + 2*(t[0,2] - b02)*(t[2,3] - b23)*(t[0,3] - b03) - (t[0,2] - b02)**2*(t[3,3] - a3) \ - (t[2,2] - a2)*(t[0,3] - b03)**2 < 0: continue # obstruction for the minor [1,2,3] of t1 if a1 * a2 * a3 - a1 * b23**2 + 2 * b12 * b23 * b13 - b12**2 * a3 - a2 * b13**2 < 0: continue # obstruction for the minor [1,2,3] of t2 if (t[1,1] - a1)*(t[2,2] - a2)*(t[3,3] - a3) - (t[1,1] - a1)*(t[2,3] - b23)**2 \ + 2*(t[1,2] - b12)*(t[2,3] - b23)*(t[1,3] - b13) - (t[1,2] - b12)**2*(t[3,3] - a3) \ - (t[2,2] - a2)*(t[1,3] - b13)**2 < 0: continue t1 = matrix( ZZ, 4, [ a0, b01, b02, b03, b01, a1, b12, b13, b02, b12, a2, b23, b03, b13, b23, a3 ], check=False) if t1.det() < 0: continue t2 = t - t1 if t2.det() < 0: continue t1.set_immutable() t2.set_immutable() yield (t1, t2) raise StopIteration
def iter_indefinite_forms(self): r""" Iterate over indices with non-positive discriminant. TESTS:: sage: from psage.modform.jacobiforms.jacobiformd1nn_fourierexpansion import * sage: list(JacobiFormD1NNFilter(2, 2, reduced = False, weak_forms = True).iter_indefinite_forms()) [(0, -1), (1, 3), (0, 0), (1, -3), (0, 1), (0, -2), (0, 2)] sage: list(JacobiFormD1NNFilter(3, 2, reduced = False, weak_forms = True).iter_indefinite_forms()) [(0, -1), (1, 3), (2, -4), (0, 0), (2, 4), (1, -3), (0, 1), (0, -2), (0, 2)] sage: list(JacobiFormD1NNFilter(10, 2, reduced = True, weak_forms = True).iter_indefinite_forms()) [(0, 0), (0, 1), (0, 2)] sage: list(JacobiFormD1NNFilter(10, 3, reduced = True, weak_forms = True).iter_indefinite_forms()) [(0, 0), (0, 1), (0, 2), (0, 3)] sage: list(JacobiFormD1NNFilter(10, 10, reduced = True, weak_forms = True).iter_indefinite_forms()) [(0, 0), (0, 1), (0, 2), (0, 3), (0, 4), (0, 5), (0, 6), (0, 7), (0, 8), (0, 9), (0, 10), (1, 7), (1, 8), (1, 9), (1, 10), (2, 9), (2, 10)] """ B = self.__bound m = self.__m fm = Integer(4 * self.__m) if self.__reduced: if self.__weak_forms: for n in xrange(0, min(self.__m // 4 + 1, self.__bound)): for r in xrange( isqrt(fm * n - 1) + 1 if n != 0 else 0, self.__m + 1): yield (n, r) else: for r in xrange( 0, min(self.__m + 1, isqrt((self.__bound - 1) * fm) + 1)): if fm.divides(r**2): yield (r**2 // fm, r) else: if self.__weak_forms: ## We first determine the reduced indices. for n in xrange(0, min(m // 4 + 1, B)): if n == 0: r_iteration = range(-m + 1, m + 1) else: r_iteration = range( -m + 1, -isqrt(fm * n - 1) ) \ + range( isqrt(fm * n - 1) + 1, m + 1 ) for r in r_iteration: for l in range( (-r - isqrt(r**2 - 4 * m * (n - (B - 1))) - 1) // (2 * m) + 1, (-r + isqrt(r**2 - 4 * m * (n - (B - 1)))) // (2 * m) + 1): if n + l * r + m * l**2 >= B: print l, n, r yield (n + l * r + m * l**2, r + 2 * m * l) else: if self.__bound > 0: yield (0, 0) for n in xrange(1, self.__bound): if (fm * n).is_square(): rt_fmm = isqrt(fm * n) yield (n, rt_fmm) yield (n, -rt_fmm) raise StopIteration
def _wronskian_adjoint(self, weight_parity=0, p=None): r""" The matrix `W^\# \pmod{p}`, mentioned on page 142 of Nils Skoruppa's thesis. This matrix is represented by a list of lists of q-expansions. The q-expansion is shifted by `-(m + 1) (2*m + 1) / 24` in the case of even weights, and it is shifted by `-(m - 1) (2*m - 3) / 24` otherwise. This is compensated by the missing q-powers returned by _wronskian_invdeterminant. INPUT: - `p` -- A prime or ``None``. - ``weight_parity`` -- An integer (default: `0`). """ try: if weight_parity % 2 == 0: wronskian_adjoint = self.__wronskian_adjoint_even else: wronskian_adjoint = self.__wronskian_adjoint_ood if p is None: return wronskian_adjoint else: P = PowerSeriesRing(GF(p), 'q') return [map(P, row) for row in wronskian_adjoint] except AttributeError: qexp_prec = self._qexp_precision() if p is None: PS = self.integral_power_series_ring() else: PS = PowerSeriesRing(GF(p), 'q') m = self.jacobi_index() twom = 2 * m frmsq = twom**2 thetas = dict( ((i, j), dict()) for i in xrange(m + 1) for j in xrange(m + 1)) ## We want to calculate \hat \theta_{j,l} = sum_r (2 m r + j)**2l q**(m r**2 + j r) ## in the case of even weight, and \hat \theta_{j,l} = sum_r (2 m r + j)**(2l + 1) q**(m r**2 + j r), ## otherwise. for r in xrange(isqrt((qexp_prec - 1 + m) // m) + 2): for j in (xrange(m + 1) if weight_parity % 2 == 0 else range(1, m)): fact_p = (twom * r + j)**2 fact_m = (twom * r - j)**2 if weight_parity % 2 == 0: coeff_p = 2 coeff_m = 2 else: coeff_p = 2 * (twom * r + j) coeff_m = -2 * (twom * r - j) for l in (xrange(m + 1) if weight_parity % 2 == 0 else range(1, m)): thetas[(j, l)][m * r**2 + r * j] = coeff_p thetas[(j, l)][m * r**2 - r * j] = coeff_m coeff_p = coeff_p * fact_p coeff_m = coeff_m * fact_m if weight_parity % 2 == 0: thetas[(0, 0)][0] = 1 thetas = dict((k, PS(th).add_bigoh(qexp_prec)) for (k, th) in thetas.iteritems()) W = matrix(PS, m + 1 if weight_parity % 2 == 0 else (m - 1), [ thetas[(j, l)] for j in (xrange(m + 1) if weight_parity % 2 == 0 else range(1, m)) for l in (xrange(m + 1) if weight_parity % 2 == 0 else range(1, m)) ]) ## Since the adjoint of matrices with entries in a general ring ## is extremely slow for matrices of small size, we hard code the ## the cases `m = 2` and `m = 3`. The expressions are obtained by ## computing the adjoint of a matrix with entries `w_{i,j}` in a ## polynomial algebra. if W.nrows() == 1: Wadj = matrix(PS, [[1]]) elif W.nrows() == 2: Wadj = matrix(PS, [[W[1, 1], -W[0, 1]], [-W[1, 0], W[0, 0]]]) elif W.nrows() == 3 and qexp_prec > 10**5: adj00 = W[1, 1] * W[2, 2] - W[2, 1] * W[1, 2] adj01 = -W[1, 0] * W[2, 2] + W[2, 0] * W[1, 2] adj02 = W[1, 0] * W[2, 1] - W[2, 0] * W[1, 1] adj10 = -W[0, 1] * W[2, 2] + W[2, 1] * W[0, 2] adj11 = W[0, 0] * W[2, 2] - W[2, 0] * W[0, 2] adj12 = -W[0, 0] * W[2, 1] + W[2, 0] * W[0, 1] adj20 = W[0, 1] * W[1, 2] - W[1, 1] * W[0, 2] adj21 = -W[0, 0] * W[1, 2] + W[1, 0] * W[0, 2] adj22 = W[0, 0] * W[1, 1] - W[1, 0] * W[0, 1] Wadj = matrix(PS, [[adj00, adj01, adj02], [adj10, adj11, adj12], [adj20, adj21, adj22]]) elif W.nrows() == 4 and qexp_prec > 10**5: adj00 = -W[0, 2] * W[1, 1] * W[2, 0] + W[0, 1] * W[1, 2] * W[ 2, 0] + W[0, 2] * W[1, 0] * W[2, 1] - W[0, 0] * W[ 1, 2] * W[2, 1] - W[0, 1] * W[1, 0] * W[2, 2] + W[ 0, 0] * W[1, 1] * W[2, 2] adj01 = -W[0, 3] * W[1, 1] * W[2, 0] + W[0, 1] * W[1, 3] * W[ 2, 0] + W[0, 3] * W[1, 0] * W[2, 1] - W[0, 0] * W[ 1, 3] * W[2, 1] - W[0, 1] * W[1, 0] * W[2, 3] + W[ 0, 0] * W[1, 1] * W[2, 3] adj02 = -W[0, 3] * W[1, 2] * W[2, 0] + W[0, 2] * W[1, 3] * W[ 2, 0] + W[0, 3] * W[1, 0] * W[2, 2] - W[0, 0] * W[ 1, 3] * W[2, 2] - W[0, 2] * W[1, 0] * W[2, 3] + W[ 0, 0] * W[1, 2] * W[2, 3] adj03 = -W[0, 3] * W[1, 2] * W[2, 1] + W[0, 2] * W[1, 3] * W[ 2, 1] + W[0, 3] * W[1, 1] * W[2, 2] - W[0, 1] * W[ 1, 3] * W[2, 2] - W[0, 2] * W[1, 1] * W[2, 3] + W[ 0, 1] * W[1, 2] * W[2, 3] adj10 = -W[0, 2] * W[1, 1] * W[3, 0] + W[0, 1] * W[1, 2] * W[ 3, 0] + W[0, 2] * W[1, 0] * W[3, 1] - W[0, 0] * W[ 1, 2] * W[3, 1] - W[0, 1] * W[1, 0] * W[3, 2] + W[ 0, 0] * W[1, 1] * W[3, 2] adj11 = -W[0, 3] * W[1, 1] * W[3, 0] + W[0, 1] * W[1, 3] * W[ 3, 0] + W[0, 3] * W[1, 0] * W[3, 1] - W[0, 0] * W[ 1, 3] * W[3, 1] - W[0, 1] * W[1, 0] * W[3, 3] + W[ 0, 0] * W[1, 1] * W[3, 3] adj12 = -W[0, 3] * W[1, 2] * W[3, 0] + W[0, 2] * W[1, 3] * W[ 3, 0] + W[0, 3] * W[1, 0] * W[3, 2] - W[0, 0] * W[ 1, 3] * W[3, 2] - W[0, 2] * W[1, 0] * W[3, 3] + W[ 0, 0] * W[1, 2] * W[3, 3] adj13 = -W[0, 3] * W[1, 2] * W[3, 1] + W[0, 2] * W[1, 3] * W[ 3, 1] + W[0, 3] * W[1, 1] * W[3, 2] - W[0, 1] * W[ 1, 3] * W[3, 2] - W[0, 2] * W[1, 1] * W[3, 3] + W[ 0, 1] * W[1, 2] * W[3, 3] adj20 = -W[0, 2] * W[2, 1] * W[3, 0] + W[0, 1] * W[2, 2] * W[ 3, 0] + W[0, 2] * W[2, 0] * W[3, 1] - W[0, 0] * W[ 2, 2] * W[3, 1] - W[0, 1] * W[2, 0] * W[3, 2] + W[ 0, 0] * W[2, 1] * W[3, 2] adj21 = -W[0, 3] * W[2, 1] * W[3, 0] + W[0, 1] * W[2, 3] * W[ 3, 0] + W[0, 3] * W[2, 0] * W[3, 1] - W[0, 0] * W[ 2, 3] * W[3, 1] - W[0, 1] * W[2, 0] * W[3, 3] + W[ 0, 0] * W[2, 1] * W[3, 3] adj22 = -W[0, 3] * W[2, 2] * W[3, 0] + W[0, 2] * W[2, 3] * W[ 3, 0] + W[0, 3] * W[2, 0] * W[3, 2] - W[0, 0] * W[ 2, 3] * W[3, 2] - W[0, 2] * W[2, 0] * W[3, 3] + W[ 0, 0] * W[2, 2] * W[3, 3] adj23 = -W[0, 3] * W[2, 2] * W[3, 1] + W[0, 2] * W[2, 3] * W[ 3, 1] + W[0, 3] * W[2, 1] * W[3, 2] - W[0, 1] * W[ 2, 3] * W[3, 2] - W[0, 2] * W[2, 1] * W[3, 3] + W[ 0, 1] * W[2, 2] * W[3, 3] adj30 = -W[1, 2] * W[2, 1] * W[3, 0] + W[1, 1] * W[2, 2] * W[ 3, 0] + W[1, 2] * W[2, 0] * W[3, 1] - W[1, 0] * W[ 2, 2] * W[3, 1] - W[1, 1] * W[2, 0] * W[3, 2] + W[ 1, 0] * W[2, 1] * W[3, 2] adj31 = -W[1, 3] * W[2, 1] * W[3, 0] + W[1, 1] * W[2, 3] * W[ 3, 0] + W[1, 3] * W[2, 0] * W[3, 1] - W[1, 0] * W[ 2, 3] * W[3, 1] - W[1, 1] * W[2, 0] * W[3, 3] + W[ 1, 0] * W[2, 1] * W[3, 3] adj32 = -W[1, 3] * W[2, 2] * W[3, 0] + W[1, 2] * W[2, 3] * W[ 3, 0] + W[1, 3] * W[2, 0] * W[3, 2] - W[1, 0] * W[ 2, 3] * W[3, 2] - W[1, 2] * W[2, 0] * W[3, 3] + W[ 1, 0] * W[2, 2] * W[3, 3] adj33 = -W[1, 3] * W[2, 2] * W[3, 1] + W[1, 2] * W[2, 3] * W[ 3, 1] + W[1, 3] * W[2, 1] * W[3, 2] - W[1, 1] * W[ 2, 3] * W[3, 2] - W[1, 2] * W[2, 1] * W[3, 3] + W[ 1, 1] * W[2, 2] * W[3, 3] Wadj = matrix(PS, [[adj00, adj01, adj02, adj03], [adj10, adj11, adj12, adj13], [adj20, adj21, adj22, adj23], [adj30, adj31, adj32, adj33]]) else: Wadj = W.adjoint() if weight_parity % 2 == 0: wronskian_adjoint = [[Wadj[i, r] for i in xrange(m + 1)] for r in xrange(m + 1)] else: wronskian_adjoint = [[Wadj[i, r] for i in xrange(m - 1)] for r in xrange(m - 1)] if p is None: if weight_parity % 2 == 0: self.__wronskian_adjoint_even = wronskian_adjoint else: self.__wronskian_adjoint_odd = wronskian_adjoint return wronskian_adjoint