diff options
Diffstat (limited to 'theta_lib/basis_change/base_change_dim2.py')
-rw-r--r-- | theta_lib/basis_change/base_change_dim2.py | 150 |
1 files changed, 0 insertions, 150 deletions
diff --git a/theta_lib/basis_change/base_change_dim2.py b/theta_lib/basis_change/base_change_dim2.py deleted file mode 100644 index 4994529..0000000 --- a/theta_lib/basis_change/base_change_dim2.py +++ /dev/null @@ -1,150 +0,0 @@ -from sage.all import * - -import itertools - -def complete_symplectic_matrix_dim2(C, D, n=4): - Zn = Integers(n) - - # Compute first row - F = D.stack(-C).transpose() - xi = F.solve_right(vector(Zn, [1, 0])) - - # Rearrange TODO: why? - v = vector(Zn, [xi[2], xi[3], -xi[0], -xi[1]]) - - # Compute second row - F2 = F.stack(v) - yi = F2.solve_right(vector(Zn, [0, 1, 0])) - M = Matrix(Zn, - [ - [xi[0], yi[0], C[0, 0], C[0, 1]], - [xi[1], yi[1], C[1, 0], C[1, 1]], - [xi[2], yi[2], D[0, 0], D[0, 1]], - [xi[3], yi[3], D[1, 0], D[1, 1]], - ], - ) - - return M - -def block_decomposition(M): - """ - Given a 4x4 matrix, return the four 2x2 matrices as blocks - """ - A = M.matrix_from_rows_and_columns([0, 1], [0, 1]) - B = M.matrix_from_rows_and_columns([2, 3], [0, 1]) - C = M.matrix_from_rows_and_columns([0, 1], [2, 3]) - D = M.matrix_from_rows_and_columns([2, 3], [2, 3]) - return A, B, C, D - -def is_symplectic_matrix_dim2(M): - A, B, C, D = block_decomposition(M) - if B.transpose() * A != A.transpose() * B: - return False - if C.transpose() * D != D.transpose() * C: - return False - if A.transpose() * D - B.transpose() * C != identity_matrix(2): - return False - return True - -def base_change_theta_dim2(M, zeta): - r""" - Computes the matrix N (in row convention) of the new level 2 - theta coordinates after a symplectic base change of A[4] given - by M\in Sp_4(Z/4Z). We have: - (theta'_i)=N*(theta_i) - where the theta'_i are the new theta coordinates and theta_i, - the theta coordinates induced by the product theta structure. - N depends on the fourth root of unity zeta=e_4(Si,Ti) (where - (S0,S1,T0,T1) is a symplectic basis if A[4]). - - Inputs: - - M: symplectic base change matrix. - - zeta: a primitive 4-th root of unity induced by the Weil-pairings - of the symplectic basis of A[4]. - - Output: Matrix N of base change of theta-coordinates. - """ - # Split 4x4 matrix into 2x2 blocks - A, B, C, D = block_decomposition(M) - - # Initialise N to 4x4 zero matrix - N = [[0 for _ in range(4)] for _ in range(4)] - - def choose_non_vanishing_index(C, D, zeta): - """ - Choice of reference non-vanishing index (ir0,ir1) - """ - for ir0, ir1 in itertools.product([0, 1], repeat=2): - L = [0, 0, 0, 0] - for j0, j1 in itertools.product([0, 1], repeat=2): - k0 = C[0, 0] * j0 + C[0, 1] * j1 - k1 = C[1, 0] * j0 + C[1, 1] * j1 - - l0 = D[0, 0] * j0 + D[0, 1] * j1 - l1 = D[1, 0] * j0 + D[1, 1] * j1 - - e = -(k0 + 2 * ir0) * l0 - (k1 + 2 * ir1) * l1 - L[ZZ(k0 + ir0) % 2 + 2 * (ZZ(k1 + ir1) % 2)] += zeta ** (ZZ(e)) - - # Search if any L value in L is not zero - if any([x != 0 for x in L]): - return ir0, ir1 - - ir0, ir1 = choose_non_vanishing_index(C, D, zeta) - - for i0, i1, j0, j1 in itertools.product([0, 1], repeat=4): - k0 = A[0, 0] * i0 + A[0, 1] * i1 + C[0, 0] * j0 + C[0, 1] * j1 - k1 = A[1, 0] * i0 + A[1, 1] * i1 + C[1, 0] * j0 + C[1, 1] * j1 - - l0 = B[0, 0] * i0 + B[0, 1] * i1 + D[0, 0] * j0 + D[0, 1] * j1 - l1 = B[1, 0] * i0 + B[1, 1] * i1 + D[1, 0] * j0 + D[1, 1] * j1 - - e = i0 * j0 + i1 * j1 - (k0 + 2 * ir0) * l0 - (k1 + 2 * ir1) * l1 - N[i0 + 2 * i1][ZZ(k0 + ir0) % 2 + 2 * (ZZ(k1 + ir1) % 2)] += zeta ** (ZZ(e)) - - return Matrix(N) - -def montgomery_to_theta_matrix_dim2(zero12,N=identity_matrix(4),return_null_point=False): - r""" - Computes the matrix that transforms Montgomery coordinates on E1*E2 into theta coordinates - with respect to a certain theta structure given by a base change matrix N. - - Input: - - zero12: theta-null point for the product theta structure on E1*E2[2]: - zero12=[zero1[0]*zero2[0],zero1[1]*zero2[0],zero1[0]*zero2[1],zero1[1]*zero2[1]], - where the zeroi are the theta-null points of Ei for i=1,2. - - N: base change matrix from the product theta-structure. - - return_null_point: True if the theta-null point obtained after applying N to zero12 is returned. - - Output: - - Matrix for the change of coordinates: - (X1*X2,Z1*X2,X1*Z2,Z1*Z2)-->(theta_00,theta_10,theta_01,theta_11). - - If return_null_point, the theta-null point obtained after applying N to zero12 is returned. - """ - - Fp2=zero12[0].parent() - - M=zero_matrix(Fp2,4,4) - - for i in range(4): - for j in range(4): - M[i,j]=N[i,j]*zero12[j] - - M2=[] - for i in range(4): - M2.append([M[i,0]+M[i,1]+M[i,2]+M[i,3],-M[i,0]-M[i,1]+M[i,2]+M[i,3],-M[i,0]+M[i,1]-M[i,2]+M[i,3],M[i,0]-M[i,1]-M[i,2]+M[i,3]]) - - if return_null_point: - null_point=[M[i,0]+M[i,1]+M[i,2]+M[i,3] for i in range(4)] - return Matrix(M2), null_point - else: - return Matrix(M2) - -def apply_base_change_theta_dim2(N,P): - Q=[] - for i in range(4): - Q.append(0) - for j in range(4): - Q[i]+=N[i,j]*P[j] - return Q - |