from sage.all import * from sage.structure.element import get_coercion_model from .theta_helpers_dim4 import ( hadamard, batch_inversion, product_theta_point_dim4, product_to_theta_points_dim4, product_theta_point_dim2_dim4, product_to_theta_points_dim4_dim2, act_point, squared, ) from .Theta_dim1 import ThetaStructureDim1 from .Tuple_point import TuplePoint from ..basis_change.base_change_dim4 import ( apply_base_change_theta_dim4, random_symplectic_matrix, base_change_theta_dim4, ) cm = get_coercion_model() class ThetaStructureDim4: def __init__(self,null_point,null_point_dual=None,inv_null_point_dual_sq=None): r""" INPUT: - null_point: theta-constants. - inv_null_point_dual_sq: inverse of the squares of dual theta-constants, if provided (meant to prevent duplicate computation, since this data is already computed when the codomain of an isogeny is computed). """ if not len(null_point) == 16: raise ValueError("Entry null_point should have 16 coordinates.") self._base_ring = cm.common_parent(*(c.parent() for c in null_point)) self._point = ThetaPointDim4 self._null_point = self._point(self, null_point) self._null_point_dual=null_point_dual self._inv_null_point=None self._inv_null_point_dual_sq=inv_null_point_dual_sq def null_point(self): """ """ return self._null_point def null_point_dual(self): if self._null_point_dual==None: self._null_point_dual=hadamard(self._null_point.coords()) return self._null_point_dual def base_ring(self): """ """ return self._base_ring def zero(self): """ """ return self.null_point() def zero_dual(self): return self.null_point_dual() def __repr__(self): return f"Theta structure over {self.base_ring()} with null point: {self.null_point()}" def __call__(self,coords): return self._point(self,coords) def act_null(self,I,J): r""" Point of 2-torsion. INPUT: - I, J: two 4-tuples of indices in {0,1}. OUTPUT: the action of (I,\chi_J) on the theta null point given by: (I,\chi_J)*P=(\chi_J(I+K)^{-1}P[I+K])_K """ return self.null_point().act_point(I,J) def is_K2(self,B): r""" Given a symplectic decomposition A[2]=K_1\oplus K_2 canonically induced by the theta-null point, determines if B is the canonical basis of K_2 given by act_nul(0,\delta_i)_{1\leq i\leq 4}. INPUT: - B: Basis of 4 points of 2-torsion. OUTPUT: Boolean True if and only if B is the canonical basis of K_2. """ I0=(0,0,0,0) if B[0]!=self.act_null(I0,(1,0,0,0)): return False if B[1]!=self.act_null(I0,(0,1,0,0)): return False if B[2]!=self.act_null(I0,(0,0,1,0)): return False if B[3]!=self.act_null(I0,(0,0,0,1)): return False return True def base_change_struct(self,N): null_coords=self.null_point().coords() new_null_coords=apply_base_change_theta_dim4(N,null_coords) return ThetaStructureDim4(new_null_coords) def base_change_coords(self,N,P): coords=P.coords() new_coords=apply_base_change_theta_dim4(N,coords) return self.__call__(new_coords) #@cached_method def _arithmetic_precomputation(self): r""" Initializes the precomputation containing the inverse of the theta-constants in standard and dual (Hadamard transformed) theta-coordinates. Assumes no theta-constant is zero. """ O=self.null_point() if all([O[k]!=0 for k in range(16)]): self._inv_null_point=batch_inversion(O.coords()) if self._inv_null_point_dual_sq==None: U_chi_0_sq=hadamard(squared(O.coords())) if all([U_chi_0_sq[k]!=0 for k in range(16)]): self._inv_null_point_dual_sq=batch_inversion(U_chi_0_sq) self._arith_base_change=False else: self._arith_base_change=True self._arithmetic_base_change() #print("Zero dual theta constants.\nRandom symplectic base change is being used for duplication.\nDoublings are more costly than expected.") else: self._arith_base_change=True self._arithmetic_base_change() #print("Zero theta constants.\nRandom symplectic base change is being used for duplication.\nDoublings are more costly than expected.") def _arithmetic_base_change(self,max_iter=50): F=self._base_ring if F.degree() == 2: i=self._base_ring.gen() else: assert(F.degree() == 1) Fp2 = GF((F.characteristic(), 2), name='i', modulus=var('x')**2 + 1) i=Fp2.gen() count=0 O=self.null_point() while count