def _initialize_fat_horizontal(self, s, L): """ Initialise reduction matrices for horizontal reductions for blocks from `s` to `L`. TESTS:: sage: p = 4999 sage: x = PolynomialRing(GF(p),"x").gen() sage: C = CyclicCover(3, x^4 + 4*x^3 + 9*x^2 + 3*x + 1) sage: C._init_frob() sage: C._initialize_fat_horizontal(p, 3) sage: len(C._horizontal_fat_s[p]) 3 """ assert self._sqrtp if s not in self._horizontal_fat_s: N = self._N - 1 # padic precision of self._Zq0 d = self._d L0 = min(L, N) targets = [0] * (2 * L0) for l in range(L0): targets[2 * l] = self._p * l targets[2 * l + 1] = self._p * (l + 1) - d - 1 (m0, m1), (M0, M1) = self._horizontal_matrix_reduction(s) M0, M1 = [elt.change_ring(self._Zq0) for elt in [M0, M1]] D0, D1 = [matrix(self._Zq0, [elt]) for elt in [m0, m1]] MH = interval_products(M0, M1, targets) DH = [elt[0, 0] for elt in interval_products(D0, D1, targets)] if L > N: # Vandermonde interpolation # f^{(r)}(0) p^r / r! for r = 0, ..., N-1, MT = [None] * N DT = [0] * N for r in range(N): MT[r] = matrix(self._Zq0, d, d) for h in range(N): v = self._vandermonde[r, h] for i in range(d): for j in range(d): MT[r][i, j] += v * MH[h][i, j] DT[r] += v * DH[h] for k in range(N, L): M = matrix(self._Zq0, d, d) D = 0 k1pow = self._Zq0(1) # power of k + 1 for h in range(N): for i in range(d): for j in range(d): M[i, j] += k1pow * MT[h][i, j] D += k1pow * DT[h] k1pow *= k + 1 MH.append(M) DH.append(D) iDH = [1 / elt for elt in DH] self._horizontal_fat_s[s] = [(iDH[i], MH[i]) for i in range(L)] assert len(self._horizontal_fat_s[s]) >= L
def _initialize_fat_vertical(self, s0, max_upper_target): """ Initialise reduction matrices for vertical reductions for blocks from `s0` to `s0 + max_upper_target`. TESTS:: sage: p = 4999 sage: x = PolynomialRing(GF(p),"x").gen() sage: C = CyclicCover(3, x^4 + 4*x^3 + 9*x^2 + 3*x + 1) sage: C._init_frob() sage: C._initialize_fat_vertical(1, p + p // 3) sage: len(C._vertical_fat_s[1]) 2 """ L = floor((max_upper_target - self._epsilon) / self._p) + 1 if s0 not in self._vertical_fat_s: (m0, m1), (M0, M1) = self._vertical_matrix_reduction(s0) D0, D1 = map(lambda y: matrix(self._Zq, [y]), [m0, m1]) targets = [0] * (2 * L) for l in reversed(range(L)): targets[2 * l] = max_upper_target - self._p * (L - l) targets[2 * l + 1] = max_upper_target - self._p * (L - 1 - l) if targets[0] < 0: targets[0] = self._epsilon MV = interval_products(M0, M1, targets) DV = interval_products(D0, D1, targets) for l in range(L): D = DV[l][0, 0] if D % self._p == 0: iD = 1 / self._Zq(D.lift() / self._p) MV[l] = matrix( self._Zq, [ [iD * ZZ(elt.lift() / self._p) for elt in row] for row in MV[l].rows() ], ) else: MV[l] *= 1 / D self._vertical_fat_s[s0] = MV assert len(self._vertical_fat_s[s0]) >= L