def _prec_for_solve_diff_eqn(M, p): r""" A helper function for determining the (absolute) precision of the input to solve_diff_eqn required in order obtain an answer with (absolute) precision ``M``. The parameter ``p`` is the prime. Given input (absolute) precision `M_\text{in}`, the output of solve_diff_eqn has (absolute) precision .. MATH:: M = M_\text{in} - \lfloor\log_p(M_\text{in})\rfloor - 1. ::EXAMPLES: sage: from sage.modular.pollack_stevens.modsym_OMS_space import _prec_for_solve_diff_eqn sage: [_prec_for_solve_diff_eqn(M, p) for p in [3,7,11,29] for M in [1,3,10,20]] [2, 5, 13, 23, 2, 4, 12, 22, 2, 4, 12, 22, 2, 4, 11, 21] """ if M < 1: raise ValueError("Desired precision M(=%s) must be at least 1." % (M)) # A good guess to begin: M_in = ZZ(1 + M + ZZ(M).exact_log(p)) # It looks like usually there are no iterations while M > M_in - M_in.exact_log(p) - 1: M_in += 1 #print("An iteration in _prec_solve_diff_eqn") return M_in
def dirichlet_coefficients(self, ncoeffs=20): from sage.rings.power_series_ring import PowerSeriesRing from sage.misc.misc import srange #from sage.misc.mrange import mrange ncoeffs = ZZ(ncoeffs) ps = prime_range(ncoeffs + 1) num_ps = len(ps) exps = [ncoeffs.exact_log(p) + 1 for p in ps] M = ncoeffs.exact_log(2) + 1 #print ps, exps, M PS = PowerSeriesRing(QQ, 'x', M) euler_factors = dict([[ps[i], ~PS(self.euler_factor(ps[i]), exps[i] + 1)] for i in range(num_ps)]) ans = [] for n in srange(1, ncoeffs + 1): ans.append(prod([euler_factors[p][e] for p, e in n.factor()])) #ans = [0] * ncoeffs #is_zeroes = True #for e in mrange(exps): # if is_zeroes: # is_zeroes = False # ans[0] = QQ.one() # continue # n = 1 # an = QQ.one() # breaker = False # for i in range(num_ps): # if exps[i] == 0: # continue # n *= ps[i] ** e[i] # if n > ncoeffs: # breaker = True # break # an *= euler_factors[i][e[i]] # #print n, an, e # if breaker: # continue # ans[n-1] = an return ans
def solve_diff_eqn(self): r""" Solves the difference equation. See Theorem 4.5 and Lemma 4.4 of [PS]. INPUT: - ``self`` - an overconvergent distribution `\mu` of absolute precision `M` OUTPUT: - an overconvergent distribution `\nu` of absolute precision `M - \lfloor\log_p(M)\rfloor - 1` such that .. math:: \nu|\Delta = \mu,\text{ where }\Delta=\begin{pmatrix}1&1\\0&1 \end{pmatrix} - 1. EXAMPLES:: sage: D = OverconvergentDistributions(0,7,base=ZpCA(7,5)) sage: D10 = D.change_precision(10) sage: mu10 = D10((O(7^10), 4 + 6*7 + 5*7^3 + 2*7^4 + 5*7^5 + O(7^9), 5 + 7^3 + 5*7^4 + 6*7^5 + 7^6 + 6*7^7 + O(7^8), 2 + 7 + 6*7^2 + 6*7^4 + 7^5 + 7^6 + O(7^7), 3*7 + 4*7^2 + 4*7^3 + 3*7^4 + 3*7^5 + O(7^6), 5 + 3*7 + 2*7^2 + 7^3 + 3*7^4 + O(7^5), 1 + 7^2 + 7^3 + O(7^4), 6*7 + 6*7^2 + O(7^3), 2 + 3*7 + O(7^2), 1 + O(7))) sage: nu10 = mu10.solve_diff_eqn() sage: MS = OverconvergentModularSymbols(14, coefficients=D) sage: MR = MS.source() sage: Id = MR.gens()[0] sage: nu10 * MR.gammas[Id] - nu10 - mu10 7^8 * () sage: D = OverconvergentDistributions(0,7,base=Qp(7,5)) sage: D10 = D.change_precision(10) sage: mu10 = D10((O(7^10), 4 + 6*7 + 5*7^3 + 2*7^4 + 5*7^5 + O(7^9), 5 + 7^3 + 5*7^4 + 6*7^5 + 7^6 + 6*7^7 + O(7^8), 2 + 7 + 6*7^2 + 6*7^4 + 7^5 + 7^6 + O(7^7), 3*7 + 4*7^2 + 4*7^3 + 3*7^4 + 3*7^5 + O(7^6), 5 + 3*7 + 2*7^2 + 7^3 + 3*7^4 + O(7^5), 1 + 7^2 + 7^3 + O(7^4), 6*7 + 6*7^2 + O(7^3), 2 + 3*7 + O(7^2), 1 + O(7))) sage: nu10 = mu10.solve_diff_eqn() sage: MS = OverconvergentModularSymbols(14, coefficients=D); sage: MR = MS.source(); sage: Id = MR.gens()[0] sage: nu10 * MR.gammas[Id] - nu10 - mu10 7^8 * () sage: R = ZpCA(5, 5); D = OverconvergentDistributions(0,base=R); sage: nu = D((R(O(5^5)), R(5 + 3*5^2 + 4*5^3 + O(5^4)), R(5 + O(5^3)), R(2*5 + O(5^2), 2 + O(5)))); sage: nu.solve_diff_eqn() 5 * (1 + 3*5 + O(5^2), O(5)) Check input of relative precision 2:: sage: from sage.modular.pollack_stevens.coeffmod_OMS_element import CoeffMod_OMS_element sage: R = ZpCA(3, 9) sage: D = OverconvergentDistributions(0, base=R, prec_cap=4) sage: V = D.approx_module(2) sage: nu = CoeffMod_OMS_element(V([R(0, 9), R(2*3^2 + 2*3^4 + 2*3^7 + 3^8 + O(3^9))]), D, ordp=0, check=False) sage: mu = nu.solve_diff_eqn() sage: mu 3 * () """ #RH: see tests.sage for randomized verification that this function works correctly p = self.parent().prime() abs_prec = ZZ(self.precision_absolute()) if self.is_zero(): mu = self.parent()(0) mu.ordp = abs_prec - abs_prec.exact_log(p) - 1 return mu if self._unscaled_moment(0) != 0: raise ValueError("Distribution must have total measure 0 to be in image of difference operator.") M = ZZ(len(self._moments)) ## RP: This should never happen -- the distribution must be 0 at this point if M==1 if M == 1: return self.parent()(0) if M == 2: if p == 2: raise ValueError("Not enough accuracy to return anything") else: out_prec = abs_prec - abs_prec.exact_log(p) - 1 if self.ordp >= out_prec: mu = self.parent()(0) mu.ordp = out_prec return mu mu = self.parent()(self._unscaled_moment(1)) mu.ordp = self.ordp return mu R = self.parent().base_ring() K = R.fraction_field() bern = [bernoulli(i) for i in range(0,M-1,2)] minhalf = ~K(-2) #bernoulli(1) # bernoulli(1) = -1/2; the only nonzero odd bernoulli number v = [minhalf * self.moment(m) for m in range(M-1)] #(m choose m-1) * B_1 * mu[m]/m for m in range(1,M): scalar = K(self.moment(m)) * (~K(m)) for j in range(m-1,M-1,2): v[j] += binomial(j,m-1) * bern[(j-m+1)//2] * scalar ordp = min(a.valuation() for a in v) #Is this correct in ramified extensions of QQp? verbose("abs_prec: %s, ordp: %s"%(abs_prec, ordp), level=2) if ordp != 0: new_M = abs_prec - 1 - (abs_prec).exact_log(p) - ordp verbose("new_M: %s"%(new_M), level=2) V = self.parent().approx_module(new_M) v = V([R(v[i] >> ordp) for i in range(new_M)]) else: new_M = abs_prec - abs_prec.exact_log(p) - 1 verbose("new_M: %s"%(new_M), level=2) V = self.parent().approx_module(new_M) v = V([R(v[i]) for i in range(new_M)]) v[new_M-1] = v[new_M-1].add_bigoh(1) #To force normalize to deal with this properly. May not be necessary any more. mu = CoeffMod_OMS_element(v, self.parent(), ordp=ordp, check=False) verbose("mu.ordp: %s, mu._moments: %s"%(mu.ordp, mu._moments), level=2) return mu.normalize()