def modform_cusp_info(calc, S, l, precLimit): """ This goes through all the cusps and compares the space given by `(f|R)[S]` with the space of Elliptic modular forms expansion at those cusps. """ assert l == S.det() assert list(calc.curlS) == [S] D = calc.D HermWeight = calc.HermWeight reducedCurlFSize = calc.matrixColumnCount herm_modform_fe_expannsion = FreeModule(QQ, reducedCurlFSize) if not Integer(l).is_squarefree(): # The calculation of the cusp expansion space takes very long here, thus # we skip them for now. return None for cusp in Gamma0(l).cusps(): if cusp == Infinity: continue M = cusp_matrix(cusp) try: gamma, R, tM = solveR(M, S, space=CurlO(D)) except Exception: print (M, S) raise R.set_immutable() # for caching, we need it hashable herm_modforms = herm_modform_fe_expannsion.echelonized_basis_matrix().transpose() ell_R_denom, ell_R_order, M_R = calcMatrixTrans(calc, R) CycloDegree_R = CyclotomicField(ell_R_order).degree() print "M_R[0] nrows, ell_R_denom, ell_R_order, Cyclo degree:", \ M_R[0].nrows(), ell_R_denom, ell_R_order, CycloDegree_R # The maximum precision we can use is M_R[0].nrows(). # However, that can be quite huge (e.g. 600). ce_prec = min(precLimit, M_R[0].nrows()) ce = cuspExpansions(level=l, weight=2*HermWeight, prec=ce_prec) ell_M_denom, ell_M = ce.expansion_at(SL2Z(M)) print "ell_M_denom, ell_M nrows:", ell_M_denom, ell_M.nrows() ell_M_order = ell_R_order # not sure here. just try the one from R. toCyclPowerBase would fail if this doesn't work # CyclotomicField(l / prod(l.prime_divisors())) should also work. # Transform to same denom. denom_lcm = int(lcm(ell_R_denom, ell_M_denom)) ell_M = addRows(ell_M, denom_lcm / ell_M_denom) M_R = [addRows(M_R_i, denom_lcm / ell_R_denom) for M_R_i in M_R] ell_R_denom = ell_M_denom = denom_lcm print "new denom:", denom_lcm assert ell_R_denom == ell_M_denom # ell_M rows are the elliptic FE. M_R[i] columns are the elliptic FE. # We expect that M_R gives a higher precision for the ell FE. I'm not sure # if this is always true but we expect it here (maybe not needed, though). print "precision of M_R[0], ell_M, wanted:", M_R[0].nrows(), ell_M.ncols(), ce_prec assert ell_M.ncols() >= ce_prec prec = min(M_R[0].nrows(), ell_M.ncols()) # cut to have same precision M_R = [M_R_i[:prec,:] for M_R_i in M_R] ell_M = ell_M[:,:prec] assert ell_M.ncols() == M_R[0].nrows() == prec print "M_R[0] rank, herm rank, mult rank:", \ M_R[0].rank(), herm_modforms.rank(), (M_R[0] * herm_modforms).rank() ell_R = [M_R_i * herm_modforms for M_R_i in M_R] # I'm not sure on this. Seems to be true and it simplifies things in the following. assert ell_M_order <= ell_R_order, "{0}".format((ell_M_order, ell_R_order)) assert ell_R_order % ell_M_order == 0, "{0}".format((ell_M_order, ell_R_order)) # Transform to same Cyclomotic Field in same power base. ell_M2 = toCyclPowerBase(ell_M, ell_M_order) ell_R2 = toLowerCyclBase(ell_R, ell_R_order, ell_M_order) # We must work with the matrix. maybe we should transform hf_M instead to a # higher order field instead, if this ever fails (I'm not sure). assert ell_R2 is not None assert len(ell_M2) == len(ell_R2) # They should have the same power base & same degree now. print "ell_M2[0], ell_R2[0] rank with order %i:" % ell_M_order, ell_M2[0].rank(), ell_R2[0].rank() assert len(M_R) == len(ell_M2) for i in range(len(ell_M2)): ell_M_space = ell_M2[i].row_space() ell_R_space = ell_R2[i].column_space() merged = ell_M_space.intersection(ell_R_space) herm_modform_fe_expannsion_Ci = M_R[i].solve_right( merged.basis_matrix().transpose() ) herm_modform_fe_expannsion_Ci_module = herm_modform_fe_expannsion_Ci.column_module() herm_modform_fe_expannsion_Ci_module += M_R[i].right_kernel() extra_check_on_herm_superspace( vs=herm_modform_fe_expannsion_Ci_module, D=D, B_cF=calc.B_cF, HermWeight=HermWeight ) herm_modform_fe_expannsion = herm_modform_fe_expannsion.intersection( herm_modform_fe_expannsion_Ci_module ) print "power", i, merged.dimension(), herm_modform_fe_expannsion_Ci_module.dimension(), \ herm_modform_fe_expannsion.dimension() current_dimension = herm_modform_fe_expannsion.dimension() return herm_modform_fe_expannsion