Ryan Rueger

ryan@rueg.re / picture / key / home
aboutsummaryrefslogtreecommitdiffhomepage
path: root/theta_lib/isogenies/isogeny_dim4.py
diff options
context:
space:
mode:
authorPierrick-Dartois <pierrickdartois@icloud.com>2025-05-22 18:51:58 +0200
committerPierrick-Dartois <pierrickdartois@icloud.com>2025-05-22 18:51:58 +0200
commitcb6080eaa4f326d9fce5f0a9157be46e91d55e09 (patch)
tree4d080ade8db9faa0da5268ab420dad2b02a4e248 /theta_lib/isogenies/isogeny_dim4.py
parentd40de259097c5e8d8fd35539560ca7c3d47523e7 (diff)
downloadpegasis-cb6080eaa4f326d9fce5f0a9157be46e91d55e09.tar.gz
pegasis-cb6080eaa4f326d9fce5f0a9157be46e91d55e09.tar.bz2
pegasis-cb6080eaa4f326d9fce5f0a9157be46e91d55e09.zip
Clean up PEGASIS submodule inclusion
Diffstat (limited to 'theta_lib/isogenies/isogeny_dim4.py')
-rw-r--r--theta_lib/isogenies/isogeny_dim4.py162
1 files changed, 0 insertions, 162 deletions
diff --git a/theta_lib/isogenies/isogeny_dim4.py b/theta_lib/isogenies/isogeny_dim4.py
deleted file mode 100644
index 2f483bf..0000000
--- a/theta_lib/isogenies/isogeny_dim4.py
+++ /dev/null
@@ -1,162 +0,0 @@
-from sage.all import *
-
-from ..theta_structures.Theta_dim4 import ThetaStructureDim4
-from ..theta_structures.theta_helpers_dim4 import hadamard, squared, batch_inversion
-from .tree import Tree
-
-class IsogenyDim4:
- def __init__(self,domain,K_8,codomain=None,precomputation=None):
- r"""
- Input:
- - domain: a ThetaStructureDim4.
- - K_8: a list of 4 points of 8-torision (such that 4*K_8 is a kernel basis), used to compute the codomain.
- - codomain: a ThetaStructureDim4 (for the codomain, used only when K_8 is None).
- - precomputation: list of inverse of dual theta constants of the codomain, used to compute the image.
- """
-
- if not isinstance(domain, ThetaStructureDim4):
- raise ValueError("Argument domain should be a ThetaStructureDim4 object.")
- self._domain = domain
- self._precomputation=None
- if K_8!=None:
- self._compute_codomain(K_8)
- else:
- self._codomain=codomain
- self._precomputation=precomputation
-
- def _compute_codomain(self,K_8):
- r"""
- Input:
- - K_8: a list of 4 points of 8-torision (such that 4*K_8 is a kernel basis).
-
- Output:
- - codomain of the isogeny.
- Also initializes self._precomputation, containing the inverse of theta-constants.
- """
- HSK_8=[hadamard(squared(P.coords())) for P in K_8]
-
- # Choice of reference index j_0<->chi_0 corresponding to a non-vanishing theta-constant.
- found_tree=False
- j_0=0
- while not found_tree:
- found_k0=False
- for k in range(4):
- if j_0>15:
- raise NotImplementedError("The codomain of this 2-isogeny could not be computed.\nWe may have encountered a product of abelian varieties\nsomewhere unexpected along the chain.\nThis is exceptionnal and should not happen in larger characteristic.")
- if HSK_8[k][j_0]!=0:
- k_0=k
- found_k0=True
- break
- if not found_k0:
- j_0+=1
- else:
- j0pk0=j_0^(2**k_0)
- # List of tuples of indices (index chi of the denominator: HS(f(P_k))_chi,
- #index chi.chi_k of the numerator: HS(f(P_k))_chi.chi_k, index k).
- L_ratios_ind=[(j_0,j0pk0,k_0)]
- L_covered_ind=[j_0,j0pk0]
-
- # Tree containing the the theta-null points indices as nodes and the L_ratios_ind reference indices as edges.
- tree_ratios=Tree(j_0)
- tree_ratios.add_child(Tree(j0pk0),k_0)
-
- # Filling in the tree
- tree_filled=False
- while not tree_filled:
- found_j=False
- for j in L_covered_ind:
- for k in range(4):
- jpk=j^(2**k)
- if jpk not in L_covered_ind and HSK_8[k][j]!=0:
- L_covered_ind.append(jpk)
- L_ratios_ind.append((j,jpk,k))
- tree_j=tree_ratios.look_node(j)
- tree_j.add_child(Tree(jpk),len(L_ratios_ind)-1)
- found_j=True
- break
- if found_j:
- break
- if not found_j or len(L_covered_ind)==16:
- tree_filled=True
- if len(L_covered_ind)!=16:
- j_0+=1
- else:
- found_tree=True
-
- L_denom=[HSK_8[t[2]][t[0]] for t in L_ratios_ind]
- L_denom_inv=batch_inversion(L_denom)
- L_num=[HSK_8[t[2]][t[1]] for t in L_ratios_ind]
- L_ratios=[L_num[i]*L_denom_inv[i] for i in range(15)]
-
- L_coords_ind=tree_ratios.edge_product(L_ratios)
-
- O_coords=[ZZ(0) for i in range(16)]
- for t in L_coords_ind:
- O_coords[t[1]]=t[0]
-
- # Precomputation
- # TODO: optimize inversions
- L_prec=[]
- L_prec_ind=[]
- for i in range(16):
- if O_coords[i]!=0:
- L_prec.append(O_coords[i])
- L_prec_ind.append(i)
- L_prec_inv=batch_inversion(L_prec)
- precomputation=[None for i in range(16)]
- for i in range(len(L_prec)):
- precomputation[L_prec_ind[i]]=L_prec_inv[i]
-
- self._precomputation=precomputation
- # Assumes there is no zero theta constant. Otherwise, squared(precomputation) will raise an error (None**2 does not exist)
- self._codomain=ThetaStructureDim4(hadamard(O_coords),null_point_dual=O_coords)
-
- def codomain(self):
- return self._codomain
-
- def domain(self):
- return self._domain
-
- def image(self,P):
- HS_P=list(hadamard(squared(P.coords())))
-
- for i in range(16):
- HS_P[i] *=self._precomputation[i]
-
- return self._codomain(hadamard(HS_P))
-
- def dual(self):
- return DualIsogenyDim4(self._codomain,self._domain, hadamard=True)
-
- def __call__(self,P):
- return self.image(P)
-
-
-class DualIsogenyDim4:
- def __init__(self,domain,codomain,hadamard=True):
- # domain and codomain are respectively the domain and codomain of \tilde{f}: domain-->codomain,
- # so respectively the codomain and domain of f: codomain-->domain.
- # By convention, domain input is given in usual coordinates (ker(\tilde{f})=K_2).
- # codomain is in usual coordinates if hadamard, in dual coordinates otherwise.
- self._domain=domain.hadamard()
- self._hadamard=hadamard
- if hadamard:
- self._codomain=codomain.hadamard()
- self._precomputation=batch_inversion(codomain.zero().coords())
- else:
- self._codomain=codomain
- self._precomputation=batch_inversion(codomain.zero().coords())
-
- def image(self,P):
- # When ker(f)=K_2, ker(\tilde{f})=K_1 so ker(\tilde{f})=K_2 after hadamard transformation of the
- # new domain (ex codomain)
- HS_P=list(hadamard(squared(P.coords())))
- for i in range(16):
- HS_P[i] *=self._precomputation[i]
- if self._hadamard:
- return self._codomain(hadamard(HS_P))
- else:
- return self._codomain(HS_P)
-
- def __call__(self,P):
- return self.image(P)