GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#include"typedef.h"1#include"matrix.h"2#include"idem.h"3#include"gmp.h"4#include"symm.h"5#include"bravais.h"6#include"longtools.h"78extern int INFO_LEVEL;910/**************************************************************************11@12@--------------------------------------------------------------------------13@--------------------------------------------------------------------------14@ FILE: centr.c15@--------------------------------------------------------------------------16@--------------------------------------------------------------------------17@18***************************************************************************/1920/**************************************************************************21@22@--------------------------------------------------------------------------23@24@ matrix_TYP **solve_endo(matrix_TYP **A,matrix_TYP **B,int anz,int *dim)25@26@ Let A[0],..,A[anz-1] be mxm matrices, and B[0],..,B[anz-1] nxn matrices.27@ The function returns a Q-basis of the space of mxn matrices with28@ A[i] * X = X * B[i] for all i. The dimension is returned via dim[0].29@30@ SIDEEFFECTS: The matrices in A,B are checked with Check_mat and31@ converted with rat2kgv.32@--------------------------------------------------------------------------33@34***************************************************************************/35matrix_TYP **solve_endo(matrix_TYP **A,matrix_TYP **B,int anz,int *dim)36{37int i,38j,39k,40l,41m,42act_row,43Arows=A[0]->rows,44Brows=B[0]->rows;4546matrix_TYP *GLS, /* the linar system of equation to be solved */47**sols, /* the solutions */48**rows; /* the solution as rows */4950if (INFO_LEVEL & 4){51fprintf(stderr,"entered solve_endo\n");52}5354/* check some trivialities to avoid trouble */55for (i=0;i<anz;i++){56if ((A[i]->cols != Arows) || (A[i]->cols != Arows) ||57(B[i]->cols != Brows) || (B[i]->rows != Brows)){58fprintf(stderr,"error in solve_endo\n");59exit(3);60}61rat2kgv(A[i]);62Check_mat(A[i]);63rat2kgv(B[i]);64Check_mat(B[i]);6566/* it shouldn't matter whether or not the matrices are rational67if (A[i]->kgv != 1){68fprintf(stderr,"error in solve_endo\n");69exit(3);70}71if (B[i]->kgv != 1){72fprintf(stderr,"error in solve_endo\n");73exit(3);74} */75}7677/* set the linear system of equations, no big entries will occur */78dim[0] = 0;79GLS = init_mat(anz*Arows*Brows,Arows*Brows,"");8081for (i=0;i<anz;i++){82for (j=0;j<Arows;j++){83for (k=0;k<Brows;k++){8485/* set the (i*Arows*Brows + j*Brows + k)-th row of the86system of equations */87act_row = i*Arows*Brows + j*Brows + k;88for (l=0;l<Arows;l++){89for (m=0;m<Brows;m++){90if (m==k && A[i]->array.SZ[j][l] !=0)91GLS->array.SZ[act_row][l*Brows+m] = A[i]->array.SZ[j][l];92if (l==j && B[i]->array.SZ[m][k] !=0)93GLS->array.SZ[act_row][l*Brows+m] -= B[i]->array.SZ[m][k];94}95}96}97}98}99100Check_mat(GLS);101102if (INFO_LEVEL & 4){103put_mat(GLS,NULL,"GLS",2);104}105106/* we got the relevant system of equations, solve it, and use107multiple precision integer to avoid overflow */108rows = long_solve_mat(GLS,NULL);109110/* we won't need the system of equations anymore */111free_mat(GLS);112113if (rows[0] != NULL){114fprintf(stderr,"error in solve_endo, rows[0] should be NULL\n");115free_mat(rows[0]);116}117118if (rows[1] != NULL){119/* there is a solution */120dim[0] = rows[1]->cols;121sols = (matrix_TYP **) malloc(dim[0] * sizeof(matrix_TYP *));122123for (i=0;i<rows[1]->cols;i++){124sols[i] = init_mat(Arows,Brows,"");125for (l=0;l<Arows;l++)126for (m=0;m<Brows;m++)127sols[i]->array.SZ[l][m] = rows[1]->array.SZ[l*Brows+m][i];128}129free_mat(rows[1]);130}131else{132sols = NULL;133}134135free(rows);136137return sols;138}139140/**************************************************************************141@142@--------------------------------------------------------------------------143@144@ matrix_TYP **calc_ccentralizer(matrix_TYP **centr,int dim_centr,145@ matrix_TYP **gen,int gen_no,int *dim_cc)146@147@148@--------------------------------------------------------------------------149@150***************************************************************************/151matrix_TYP **calc_ccentralizer(matrix_TYP **centr,int dim_centr,152matrix_TYP **gen,int gen_no,int *dim_cc)153{154int anz = dim_centr + gen_no;155156matrix_TYP **tmp,157**erg;158159tmp = (matrix_TYP **) malloc(anz * sizeof(matrix_TYP *));160161/* the first matrices of tmp will be those of centr */162memcpy(tmp,centr,dim_centr * sizeof(matrix_TYP*));163164/* the next will be those of gen */165memcpy(tmp+dim_centr,gen,gen_no * sizeof(matrix_TYP*));166167erg = solve_endo(tmp,tmp,anz,dim_cc);168169free(tmp);170171return erg;172173}174175176int is_zero(matrix_TYP *pol,int x)177{178MP_INT sum,179pot,180tmp;181182int i;183184mpz_init_set_ui(&sum,0);185mpz_init_set_ui(&pot,1);186mpz_init(&tmp);187188for (i=0;i<pol->cols;i++){189mpz_set_si(&tmp,pol->array.SZ[0][i]);190mpz_mul(&tmp,&pot,&tmp);191mpz_add(&sum,&sum,&tmp);192mpz_set_si(&tmp,x);193mpz_mul(&pot,&pot,&tmp);194}195196if (mpz_cmp_si(&sum,0) == 0)197i = TRUE;198else199i = FALSE;200201mpz_clear(&sum);202mpz_clear(&pot);203mpz_clear(&tmp);204205return i;206207}208209void div_by_root(matrix_TYP *pol,int x)210{211int i,212*l;213214l = (int *) malloc((pol->cols-1)*sizeof(int));215216l[pol->cols-2] = pol->array.SZ[0][pol->cols-1];217218for (i=pol->cols-3;i>=0 ;i--){219l[i] = pol->array.SZ[0][i+1] + l[i+1] * x;220}221222pol->cols--;223free(pol->array.SZ[0]);224pol->array.SZ[0] = l;225226}227228/***************************************************************************229@230@---------------------------------------------------------------------------231@232@ matrix_TYP *zeros(matrix_TYP *minpol)233@234@---------------------------------------------------------------------------235@236***************************************************************************/237matrix_TYP *zeros(matrix_TYP *minpol)238{239int i,240j,241found = 0;242243matrix_TYP *erg,244*tmp;245246erg = init_mat(1,minpol->cols,"");247tmp = copy_mat(minpol);248249/* split of all root which are zero */250while(tmp->array.SZ[0][0] == 0){251div_by_root(tmp,0);252erg->array.SZ[0][found] = 0;253found++;254}255256/* and now all others */257for (i=1;i<=abs(tmp->array.SZ[0][0]);i++){258if (tmp->array.SZ[0][0] % i == 0){259for (j= -1;j<=1;j+=2){ /* describes the sign */260if (is_zero(tmp,j*i)){261div_by_root(tmp,i*j);262erg->array.SZ[0][found] = i * j;263found++;264i=0;265j=3;266}267}268}269}270271free_mat(tmp);272real_mat(erg,1,found);273274return erg;275276} /* zeros(...) */277278/**************************************************************************279@280@--------------------------------------------------------------------------281@282@ int pos(matrix_TYP **list,int no,matrix_TYP *x)283@284@--------------------------------------------------------------------------285@286***************************************************************************/287int pos(matrix_TYP **list,int no,matrix_TYP *x)288{289int i;290291for (i=0;i<no;i++)292if (mat_comp(list[i],x) == 0) return i;293294return -1;295} /* pos (....) */296297static matrix_TYP *matrix_in_pol(matrix_TYP *pol,matrix_TYP *x)298{299int i;300301matrix_TYP *erg,302*pot;303304if (x->cols != x->rows && x->flags.Integral == FALSE){305fprintf(stderr,"exit in matrix_in_pol\n");306exit(3);307}308309pot = init_mat(x->cols,x->cols,"1");310erg = init_mat(x->cols,x->cols,"");311312for (i=0;i<pol->cols;i++){313imat_addeq(erg,pot,1,pol->array.SZ[0][i]);314mat_muleq(erg,x);315}316317free_mat(pot);318319return erg;320321} /* matrix_in_pol(...) */322323int min_trace(matrix_TYP **A,int no)324{325326int i,327min,328p,329trac;330331min = trace(A[0]);332p = 0;333if (min % A[0]->kgv != 0){334fprintf(stderr,"error in min_trace\n");335exit(3);336}337else{338min = abs(min/A[0]->kgv);339}340341for (i=1;i<no;i++){342trac = trace(A[i]);343if (trac % A[i]->kgv != 0){344fprintf(stderr,"error in min_trace\n");345exit(3);346}347else{348trac = abs(trac/A[i]->kgv);349}350if (trac < min){351min = trac;352p=i;353}354}355356return p;357}358359/*************************************************************************360@361@-------------------------------------------------------------------------362@363@ static matrix_TYP **get_idem2(matrix_TYP **gen,int number,int *anz)364@365@366@-------------------------------------------------------------------------367@368**************************************************************************/369static matrix_TYP **get_idem2(matrix_TYP **gen,int number,int *anz)370{371int i,372j,373k,374found,375dim_new1,376dim_new2,377vec[100]; /* I don't belivieve we will ever get a378centre of a centralizer which has bigger dimension */379380matrix_TYP *ONE,381*e1,382*e2,383*tmp,384*min,385*zero,386**gentrans,387**gen_new1,388**gen_new2,389**erg;390391/* number == 0 is a technical statement */392if (number == 0){393anz[0] = 0;394return NULL;395}396397/* if the algbra has only got dimension one, we are finished */398if (number == 1){399min = min_pol(gen[0]);400zero = zeros(min);401erg = (matrix_TYP **) malloc(1 * sizeof(matrix_TYP *));402erg[0] = copy_mat(gen[0]);403if (zero->cols == 1)404erg[0]->kgv = zero->array.SZ[0][0];405else406erg[0]->kgv = zero->array.SZ[0][1];407Check_mat(erg[0]);408anz[0] = 1;409free_mat(min);410free_mat(zero);411return erg;412}413414/* calculate the right regular representation */415/* assume the matrices in gen to be a Z-BASIS */416gentrans = (matrix_TYP **) malloc(number * sizeof(matrix_TYP *));417for (i=0;i<number;i++){418gentrans[i] = init_mat(number,number,"");419for (j=0;j<number;j++){420tmp = mat_mul(gen[i],gen[j]);421form_to_vec_modular(gentrans[i]->array.SZ[j],tmp,gen,number);422free_mat(tmp);423}424}425426/* search for a matrix which has a reducible minimal polynomial */427found = FALSE;428for (i=0;i<number && !found;i++){429min = min_pol(gentrans[i]);430431/* here is one part which has to be altered if one want's to432be able to handle bigger fields, ie. do not only check whether433min has got zero, but other factors */434zero = zeros(min);435if (zero->cols > 1 ||436(zero->cols == 1 && min->cols > 3)){437found = TRUE;438}439else{440free_mat(min);441free_mat(zero);442}443}444i--;445446/* calculate the identity in this algebra (which sounds a bit crazy) */447tmp = init_mat(number,number,"1");448form_to_vec(vec,tmp,gentrans,number,&j);449ONE = vec_to_form(vec,gen,number);450ONE->kgv = j;451free_mat(tmp);452453/* free gentrans, which isn't needed anymore */454for (j=0;j<number;j++){455free_mat(gentrans[j]);456}457free(gentrans);458459if (found){460461/* the definition of e1 is the next part which has to be altered462formaly e1 = min/factor (gen[i]). if these two things are changed,463we are able to handle bigger fields */464465/* split the algebra in two of it's components466by multiplying whith the two factors of min */467e1 = imat_add(gen[i],ONE,1,-zero->array.SZ[0][0]);468div_by_root(min,zero->array.SZ[0][0]);469470gen_new1 = (matrix_TYP **) malloc(number * sizeof(matrix_TYP *));471for (j=0;j<number;j++){472gen_new1[j] = mat_mul(gen[j],e1);473}474dim_new1 = long_rein_formspace(gen_new1,number,0);475476/* free space before doing the recursion */477free_mat(zero);478free_mat(min);479free_mat(e1);480481/* do the first recursion */482erg = get_idem2(gen_new1,dim_new1,&i);483484/* now ONE - \sum erg[i] will be an idempotent */485e2 = copy_mat(ONE);486for (j=0;j<i;j++){487tmp = imat_add(e2,erg[j],1,-1);488free_mat(e2);489e2 = tmp;490}491492gen_new2 = (matrix_TYP **) malloc(number * sizeof(matrix_TYP *));493for (j=0;j<number;j++){494gen_new2[j] = mat_mul(gen[j],e2);495gen_new2[j]->kgv = 1;496Check_mat(gen_new2[j]);497}498free_mat(e2);499dim_new2 = long_rein_formspace(gen_new2,number,0);500501/* do the second recursion */502gentrans = get_idem2(gen_new2,dim_new2,&j);503504/* copy the idempotents to the right place */505if (j>0) erg = (matrix_TYP **) realloc(erg,(i+j) * sizeof(matrix_TYP *));506anz[0] = i+j;507for (k=0;k<j;k++) erg[i+k] = gentrans[k];508509/* free the rest of the space */510for (i=0;i<number;i++){511free_mat(gen_new1[i]);512free_mat(gen_new2[i]);513}514free(gen_new1);515free(gen_new2);516if (j>0) free(gentrans);517518/* remove duplicates in erg */519for (i=1;i<anz[0];i++){520if (pos(erg,i,erg[i]) != -1){521free_mat(erg[i]);522anz[0]--;523erg[i] = erg[anz[0]];524}525}526}527else{528erg = (matrix_TYP **) malloc(1 * sizeof(matrix_TYP));529anz[0] = 1;530erg[0] = ONE;531}532533if (found) free_mat(ONE);534535return erg;536}537538void reduce_by_idem(matrix_TYP *id,matrix_TYP **cen,int no,int offset)539{540int i,541j,542k;543544rational one,545minus_one;546547matrix_TYP *lines,548*tmp;549550one.n = 1;551one.z =1;552minus_one.n =1;553minus_one.z =-1;554555for (i=offset;i<no;i++){556put_mat(cen[i],NULL,"red",2);557tmp = mat_mul(id,cen[i]);558mat_addeq(cen[i],tmp,one,minus_one);559Check_mat(cen[i]);560cen[i]->kgv = 1;561put_mat(cen[i],NULL,"red",2);562free_mat(tmp);563}564565lines = init_mat(no-offset,id->rows*id->cols,"");566for (i=offset;i<no;i++)567for (j=0;j<id->rows;j++)568for (k=0;k<id->cols;k++)569lines->array.SZ[i-offset][j*id->cols+k] = cen[i]->array.SZ[j][k];570571tmp = long_rein_mat(lines);572573free_mat(cen[offset]);574cen[offset] = copy_mat(id);575576for (i=offset+1;i<no;i++)577for (j=0;j<id->rows;j++)578for (k=0;k<id->cols;k++)579cen[i]->array.SZ[j][k] = tmp->array.SZ[i-1-offset][j*id->cols + k];580581for (i=0;i<no;i++) Check_mat(cen[i]);582583if (INFO_LEVEL & 4){584put_mat(lines,NULL,"lines",2);585put_mat(tmp,NULL,"tmp",2);586for (i=0;i<no;i++){587put_mat(cen[i],NULL,"cen in reduce_by_idem",2);588}589}590591free_mat(tmp);592free_mat(lines);593594return;595} /* reduce_by_idem(...) */596597/************************************************************************598@599@------------------------------------------------------------------------600@601@ matrix_TYP **idempotente(matrix_TYP **gen,int gen_no,matrix_TYP *form,602@ int *anz,int *dimc,int *dimcc,int *options)603@604@------------------------------------------------------------------------605@606*************************************************************************/607matrix_TYP **idempotente(matrix_TYP **gen,int gen_no,matrix_TYP *form,608int *anz,int *dimc,int *dimcc,int *options)609{610611matrix_TYP **centralizer, /* holds a Q-basis for the centralizer of612QG (as enveloping algebra) */613**ccentralizer, /* holds a Q-basis for the centre of614centralizer */615*tmp,616*tmp2,617*test,618**eigenspace,619*min, /* the minpol of a result to be */620*forminv, /* inverse of form */621*action, /* describes the action of form on622ccentralizer via (form * Z * form^(-1))^Tr */623**idem; /* the result will be stucked in here */624625int i,626j,627*l, /* holds a temporaly vector for vec_to_form */628k,629d,630den,631flag;632633/* transform all generators to kgv format */634for (i=0;i<gen_no;i++){635rat2kgv(gen[i]);636}637638/* calculate the centralizer */639centralizer = solve_endo(gen,gen,gen_no,dimc);640641/* calculate the centre of the centralizer */642ccentralizer = calc_ccentralizer(centralizer,dimc[0],gen,gen_no,dimcc);643644/* output for debugging */645if (INFO_LEVEL & 4){646for (i=0;i<dimc[0];i++) put_mat(centralizer[i],NULL,"cen",2);647for (i=0;i<dimcc[0];i++) put_mat(ccentralizer[i],NULL,"ccen",2);648}649650/* calculate action, actualy d * action, because I don't like denominators.651we calculate action as acting on rows, because this is very convient */652forminv = long_mat_inv(form);653rat2kgv(forminv);654d = forminv->kgv;655forminv->kgv=1;656action = init_mat(dimcc[0],dimcc[0],"");657658for (i=0;i<dimcc[0];i++){659tmp = mat_kon(form,ccentralizer[i],forminv);660tmp2 = tr_pose(tmp);661free_mat(tmp);662tmp = tmp2;663664if (INFO_LEVEL & 4){665for (j=0;j<dimcc[0];j++) put_mat(ccentralizer[j],NULL,"ccen",2);666put_mat(tmp,NULL,"tmp",2);667put_mat(form,NULL,"form",2);668put_mat(forminv,NULL,"forminv",2);669}670671/* express tmp as linear combination of the matrices in672ccentralizer. This is possible in an integral way, because673we have a Z-basis in ccentralizer */674form_to_vec(action->array.SZ[i],tmp,ccentralizer,dimcc[0],&den);675if (den != 1){676fprintf(stderr,"error in idempotente, expression should be possible\n");677fprintf(stderr,"in an integral way\n");678exit(3);679}680free_mat(tmp);681}682683/* calculate the 1 eigenspace of action, or strictly speeking the684d eigenspace of d*action */685for (i=0;i<action->rows;i++) action->array.SZ[i][i] -= d;686tmp = tr_pose(action);687free_mat(action);688action = tmp;689eigenspace = long_solve_mat(action,NULL);690if (eigenspace[0] != NULL || eigenspace[1] == NULL){691fprintf(stderr,"error in idempotente\n");692exit(3);693}694tmp = eigenspace[1];695free(eigenspace);696eigenspace = (matrix_TYP **) malloc(tmp->cols*sizeof(matrix_TYP *));697l = (int *) malloc(dimcc[0] * sizeof(int));698for (i=0;i<tmp->cols;i++){699for (j=0;j<tmp->rows;j++) l[j] = tmp->array.SZ[j][i];700eigenspace[i] = vec_to_form(l,ccentralizer,dimcc[0]);701}702703d = tmp->cols;704705if (INFO_LEVEL & 4){706put_mat(action,NULL,"action",2);707}708709/* clean up again */710free(l);711free_mat(tmp);712free_mat(action);713free_mat(forminv);714715if (INFO_LEVEL & 4){716for (i=0;i<d;i++) put_mat(eigenspace[i],NULL,"eigenspace",2);717}718719idem = get_idem2(eigenspace,d,anz);720721/* clean up the last space */722for (i=0;i<d;i++) free_mat(eigenspace[i]);723free(eigenspace);724725/* put the centralizer and it's centre on the same pointer as idem */726idem = (matrix_TYP **) realloc(idem,(anz[0]+dimc[0]+dimcc[0])727* sizeof(matrix_TYP));728for (i=0;i<dimc[0];i++) idem[anz[0]+i] = centralizer[i];729for (i=0;i<dimcc[0];i++) idem[anz[0]+dimc[0]+i] = ccentralizer[i];730731/* clear the pointer's needed */732free(centralizer);733free(ccentralizer);734735return idem;736737}738739740