/* Pari
/* Hecke matrix
/* Author: Joachim Wehler
*/
default(format, "g.10" ); 

print ("===================================================="); 
print ( "Hecke_matrix_02, Start \n");
default(parisizemax, "16G");

order_4 		= 4;
order_3 		= 3;
debug			= 0;		

/* Create space of cusp forms */
S 		= mfinit([1,28],1);
weight 	= mfparams(S)[2];
level 	= mfparams(S)[1];
dim 	= mfdim(S);
/* Index Hecke operator */
m       = 2;

S_string = "S_";
S_string = concat(S_string, weight);
S_string = concat(S_string, "(Gamma_0(");
S_string = concat(S_string, level);
S_string = concat(S_string, "))");

E_4 		= mfEk(4);
f1			= mfmul(mfDelta, mfpow(E_4,4));
f1_coefs 	= mfcoefs(f1,order_4);
f1_ser		= Ser(f1_coefs,q);
f2 		= mfmul(mfpow(mfDelta,2),E_4);
f2_coefs 	= mfcoefs(f2,order_4);
f2_ser		= Ser(f2_coefs,q);

print("Hecke operator T_", m,": ", S_string , " ---> ", S_string, "\n");
print("Basis of ", S_string, ": f1 = Delta * E_4^4, f2 = Delta^2 * E_4 with Fourier series: ","\n");
print("f1_ser: ", f1_ser,"\n");
print("f2_ser: ", f2_ser);
print("-----------------------------------","\n");

/* Compute Hecke transforms */
heck_2_f1 		= mfhecke(S,f1,m);
heck_2_f1_coefs = mfcoefs(heck_2_f1,order_4);
heck_2_f1_ser	= Ser(heck_2_f1_coefs,q,order_4);
heck_2_f2 		= mfhecke(S,f2,m);
heck_2_f2_coefs = mfcoefs(heck_2_f2,order_4);
heck_2_f2_ser	= Ser(heck_2_f2_coefs,q,order_4);

print("heck_2_f1_ser: ", heck_2_f1_ser,"\n");
print("heck_2_f2_ser: ", heck_2_f2_ser);
print("-----------------------------------","\n");

/* Compute Hecke matrix with respect to (f1,f2) */

a 	= f1_coefs[2];
b	= f2_coefs[2];
c	= f1_coefs[3];
d 	= f2_coefs[3];
A  	= [a,b; c,d];

/* First Hecke transform */
image_1 					= [heck_2_f1_coefs[2]; heck_2_f1_coefs[3]];
sol_1 						= matsolve(A,image_1);
hecke_2_f1_basis_repr 		= sol_1[1,1] * f1_coefs + sol_1[2,1] * f2_coefs;
hecke_2_f1_basis_repr_ser	= Ser(hecke_2_f1_basis_repr,q,order_3);

/* Second Hecke transform */
image_2 					= [heck_2_f2_coefs[2]; heck_2_f2_coefs[3]];
sol_2 						= matsolve(A,image_2);
hecke_2_f2_basis_repr		= sol_2[1,1] * f1_coefs + sol_2[2,1] * f2_coefs; 
hecke_2_f2_basis_repr_ser	= Ser(hecke_2_f2_basis_repr,q,order_3);

hecke_matrix = [sol_1[1,1], sol_2[1,1]; sol_1[2,1], sol_2[2,1]];

print("Matrix of Hecke operator T_", m, " with respect to basis (f1,f2): ", hecke_matrix);
print("-----------------------------------","\n");

/* Check result */
if (debug == 1, \
{
	print("Check result.", "\n");
	result_1 = mflinear( [mflinear([f1], [hecke_matrix[1,1]]), mflinear([f2],[hecke_matrix[2,1]])],[1,1] );
	result_2 = mflinear( [mflinear([f1], [hecke_matrix[1,2]]), mflinear([f2],[hecke_matrix[2,2]])],[1,1] );
	print("result_1: ", mfcoefs(result_1,order_3), "\n");
	print("result_2: ", mfcoefs(result_2,order_3), "\n");
	print("result_1 equal Tf1? ", mfisequal(result_1, heck_2_f1 ), ", result_2 equal Tf2? ", mfisequal(result_2, heck_2_f2 ),"\n");
	print("-----------------------------------","\n");
});

/* Compute eigenvalues and eigenvectors of Hecke matrix, normalize eigenvectors */
eigendata = mateigen(hecke_matrix,1);

if(debug == 1, print("eigendata: ", eigendata,"\n"));
N 		= eigendata[2];
diag 	= 1/matdet(N) * matadjoint(N) * hecke_matrix * N;

if(debug == 1, print("diag: ", diag, "\n") );

v_1 		= mflinear( [mflinear([f1], [N[1,1]]), mflinear([f2],[N[2,1]])], [1,1] );
v_1_linear 	= mfcoefs(v_1, 2)[2];
v_1			= mflinear( [v_1] , [1/v_1_linear ] );
v_2 		= mflinear( [mflinear([f1], [N[1,2]]), mflinear([f2],[N[2,2]])], [1,1] );
v_2_linear 	= mfcoefs(v_2, 2)[2];
v_2			= mflinear( [v_2] , [1/v_2_linear] );

hecke_v_1	= mfhecke(S,v_1,m);
hecke_v_2	= mfhecke(S,v_2,m);

lambda_1     		= eigendata[1][1];
lambda_1_v_1 		= mflinear([v_1], [lambda_1]);

lambda_2     		= eigendata[1][2];
lambda_2_v_2 		= mflinear([v_2], [lambda_2]);

print("Eigenvalues: ", lambda_1, ", " lambda_2);
print("-----------------------------------","\n");
print("Normalized eigenvectors","\n");
print("v_1: ", Ser(mfcoefs(v_1,4),q),"\n");
print("v_2: ", Ser(mfcoefs(v_2,4),q));

if(debug == 1, \
{
	print("lambda_1_v_1: ", mfcoefs(lambda_1_v_1,order_4), "\n");
	print("Tv_1: ", mfcoefs(hecke_v_1, order_4),"\n");	

	print("lambda_2_v_2: ", mfcoefs(lambda_2_v_2,order_4), "\n");
	print("Tv_2: ", mfcoefs(hecke_v_2, order_4),"\n");	
});

print("-----------------------------------","\n");
print("v_1 = ", (1/v_1_linear) * N[1,1], " * f1 + ", (1/v_1_linear) * N[2,1], " * f2", "\n");
print("v_2 = ", (1/v_2_linear) * N[1,2], " * f1 + ", (1/v_2_linear) * N[2,2], " * f2");
print("-----------------------------------","\n");

if(debug == 1, \
{
	print("Computation according to Kilford", "\n");

	lambda_1 	= -4140 + 108*sqrt(18209);
	lambda_2 	= -4140 - 108*sqrt(18209);
	fact_1 		= -5076 + 108*sqrt(18209);
	fact_2 		= -5076 - 108*sqrt(18209);

	print("fact_1: ", fact_1,", fact_2: ", fact_2, "\n");

	v_1	   		= mflinear ( [f1, mflinear([ f2], [fact_1])], [1,1]);
	v_2	   		= mflinear ( [f1, mflinear([ f2], [fact_2])], [1,1]);

	hecke_v_1	= mfhecke(S,v_1,m);
	hecke_v_2	= mfhecke(S,v_2,m);

	lambda_1_v_1 = mflinear( [v_1],[lambda_1]);
	lambda_2_v_2 = mflinear( [v_2],[lambda_2]);

	print("T_2(v_1): ", mfcoefs(hecke_v_1,4),"\n");
	print("lambda_1_v_1: ", mfcoefs(lambda_1_v_1,order_4),"\n");
	print("lambda_1: ", lambda_1,"\n");
	print("v_1: ", mfcoefs(v_1,4),"\n");
	print("-----------------------------------","\n");

	print("T_2(v_2): ", mfcoefs(hecke_v_2,4),"\n");
	print("lambda_2_v_2: ", mfcoefs(lambda_2_v_2,order_4),"\n");
	print("lambda_2: ", lambda_2,"\n");
	print("v_2: ", mfcoefs(v_2,4),"\n");
});

print ("Hecke_matrix_02, End");
print("====================================================");


