GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#include"typedef.h"1#include"voronoi.h"2#include"longtools.h"3#include"symm.h"4#include"bravais.h"5#include"autgrp.h"6#include"polyeder.h"7#include"matrix.h"8#include"reduction.h"9#include"orbit.h"10#include"datei.h"11#include"tools.h"1213/**************************************************************************\14@---------------------------------------------------------------------------15@---------------------------------------------------------------------------16@ FILE: calc_voronoi_data.c17@---------------------------------------------------------------------------18@---------------------------------------------------------------------------19@20\**************************************************************************/212223/**************************************************************************\24@---------------------------------------------------------------------------25@ void calc_voronoi_basics(V, G, Gtr, prime)26@ voronoi_TYP *V;27@ bravais_TYP *G, *Gtr;28@ int prime;29@30@ For using this function V->gram must be a G-perfect form31@ The function calculates:32@33@ V->SV_no: the number of shortest vectors of V->gram.34@ V->min: the minimum of V->gram.35@ V->pdet: the determinante of V->gram modulo prime.36@ V->prime: = prime.37@ V->vert: the coordinates of the voronoi vertices with38@ respect to the Z-basis of the space of invariant39@ symmetric matrices of G^{tr} given in Gtr->form.40@ V->vert_no: the number of voronoi_vertices.41@ V->red_inv: the pair-reduced of (V->gram)^{-1} (with kgv = 1).42@ V->T: the matrix such that43@ T *(V->gram)^{-1} * T^{tr} = V->red_inv44@ V->Ti: the inverse matrix of V->T45@ V->Gtrred: the bravais_TYP obtained by konjugating Gtr with46@ the transposed of V->Ti with the function47@ 'konj_bravais'48@---------------------------------------------------------------------------49@50\**************************************************************************/51void calc_voronoi_basics(V, G, Gtr, prime)52voronoi_TYP *V;53bravais_TYP *G, *Gtr;54int prime;55{56int i,k;57int anz;58matrix_TYP **XX, *TTri;5960XX = voronoi_vertices(V->gram, G, &anz, &V->min, &V->SV_no);61if(V->vert_no != 0 && V->vert != NULL)62{63for(i=0;i<V->vert_no;i++)64free_wall(&V->vert[i]);65free(V->vert);66}67V->vert_no = anz;68if( (V->vert = (wall_TYP **)malloc(anz *sizeof(wall_TYP *))) == NULL)69{70printf("malloc of 'V->vert' in 'calc_voronoi_data1' failed\n");71exit(2);72}73for(i=0; i<anz;i++)74{75V->vert[i] = init_wall(G->form_no);76form_to_vec(V->vert[i]->gl, XX[i], Gtr->form, Gtr->form_no, &k);77free_mat(XX[i]);78}79free(XX);8081V->pdet = p_mat_det(V->gram, prime);8283V->prime = prime;84if(V->red_inv == NULL)85{86V->T = init_mat(V->gram->cols, V->gram->cols, "");87for(i=0;i<V->gram->cols;i++)88V->T->array.SZ[i][i] = 1;89V->red_inv = pair_red_inv(V->gram, V->T);90V->Ti = long_mat_inv(V->T);91TTri = tr_pose(V->Ti);92V->Gtrred = konj_bravais(Gtr, TTri);93free_mat(TTri);94}95}96979899100/**************************************************************************\101@---------------------------------------------------------------------------102@ void calc_voronoi_pol(V, bifo)103@ voronoi_TYP *V;104@105@ calculates the polyeder_TYP V->pol where the walls of V->pol106@ are the walls in 'V->vert' multiplied with the transposed of bifo,107@ i.e. V->vert[i] * bifo^{tr} 0 <= i <V->vert_no108@ is the input for 'first_polyeder' and 'refine_polyeder' used109@ to calculate 'V->pol'.110@---------------------------------------------------------------------------111@112\**************************************************************************/113void calc_voronoi_pol(V, bifo)114voronoi_TYP *V;115matrix_TYP *bifo;116{117int i,j,k;118int dim, fdim;119wall_TYP **W;120121dim = V->gram->cols;122fdim = bifo->cols;123124if( (W = (wall_TYP **)malloc(V->vert_no *sizeof(wall_TYP *))) == NULL)125{126printf("malloc of 'W' in 'calc_voronoi_full' failed\n");127exit(2);128}129for(i=0;i<V->vert_no;i++)130{131W[i] = init_wall(fdim);132for(j=0;j<fdim;j++)133for(k=0;k<fdim;k++)134W[i]->gl[j] += V->vert[i]->gl[k] * bifo->array.SZ[j][k];135}136V->pol = first_polyeder(W, V->vert_no);137for(i=0;i<V->vert_no;i++)138{139j = refine_polyeder(V->pol, W[i]);140141/* tilman : changed 17/1/97 from142if(j == FALSE){143free_wall(&W[i]);144} to: */145free_wall(&W[i]);146}147free(W);148}149150151152153/**************************************************************************\154@---------------------------------------------------------------------------155@ void calc_voronoi_good_inv(V, Gtr)156@ voronoi_TYP *V;157@ bravais_TYP *Gtr;158@159@ applies 'short_red' and 'mink_red' to V->red_inv to obtain a better160@ form.161@ V->T, V->Ti and V->Gtrred are changed in the same manner as described162@ for 'calc_voronoi_basics'163@164@ Furthermore the shortest vectors of the better reduced form are165@ calculated up to the norm that equals the maximal diagonal entry166@ of V->red_inv.167@---------------------------------------------------------------------------168@169\**************************************************************************/170void calc_voronoi_good_inv(V, Gtr)171voronoi_TYP *V;172bravais_TYP *Gtr;173{174int i,j,maxd;175int dim, mr;176matrix_TYP *A, *T, *T1;177int has_changed;178179dim = V->gram->cols;180has_changed = FALSE;181182T = init_mat(dim, dim, "");183for(i=0;i<dim;i++)184T->array.SZ[i][i] = 1;185A = pr_short_red(V->red_inv, T);186maxd = V->red_inv->array.SZ[0][0];187for(i=1;i<dim;i++)188{ if(V->red_inv->array.SZ[i][i] > maxd)189maxd = V->red_inv->array.SZ[i][i];190}191j = A->array.SZ[0][0];192for(i=1;i<dim;i++)193{ if(A->array.SZ[i][i] > j)194j = A->array.SZ[i][i];195}196if(j<=maxd)197{198has_changed = TRUE;199T1 = mat_mul(T, V->T);200free_mat(V->T);201V->T = T1;202T1 = NULL;203free_mat(T);204T = NULL;205maxd = j;206free_mat(V->red_inv);207V->red_inv = A;208A = NULL;209}210else211free_mat(A);212mr = TRUE;213for(i=0;i<dim;i++)214{215if(V->red_inv->array.SZ[i][i] < maxd)216mr = FALSE;217}218if(mr == FALSE)219{220if(T == NULL)221T = init_mat(dim, dim, "1");222for(i=0;i<dim;i++)223{224for(j=0;j<dim;j++)225T->array.SZ[i][j] = 0;226T->array.SZ[i][i] = 1;227}228/* put_mat(V->red_inv, NULL, "veredinv vor minkred", 2); */229A = mink_red(V->red_inv, T);230/* put_mat(V->red_inv, NULL, "veredinv nach minkred", 2);231put_mat(A, NULL, "A nach minkred", 2); */232j = A->array.SZ[0][0];233for(i=1;i<dim;i++)234{ if(A->array.SZ[i][i] > j)235j = A->array.SZ[i][i];236}237if(j<=maxd)238{239has_changed = TRUE;240T1 = mat_mul(T, V->T);241free_mat(V->T);242V->T = T1;243T1 = NULL;244maxd = j;245free_mat(V->red_inv);246V->red_inv = A;247A = NULL;248}249else250free_mat(A);251}252253/* changed on 14/1/97 tilman: (inserted if (..)) */254if (T!=NULL){255free_mat(T);256}257258if(has_changed == TRUE)259{260free_mat(V->Ti);261V->Ti = long_mat_inv(V->T);262T = tr_pose(V->Ti);263free_bravais(V->Gtrred);264V->Gtrred = konj_bravais(Gtr, T);265free_mat(T);266}267maxd = V->red_inv->array.SZ[0][0];268for(i=0;i<dim;i++)269{270if(V->red_inv->array.SZ[i][i] > maxd)271maxd = V->red_inv->array.SZ[i][i];272}273V->SVi = short_vectors(V->red_inv, maxd, 0, 0, 0, &i);274}275276277278/**************************************************************************\279@---------------------------------------------------------------------------280@ void calc_voronoi_stab(V, G, Gtr, bifo)281@ voronoi_TYP *V;282@ bravais_TYP *G, *Gtr;283@ matrix_TYP *bifo;284@285@ calculates a generating set for286@ H = { h\in GL_n(Z) | h^{tr} * V->gram * h = V->gram and287@ h G h^{-1} = G }288@289@ Furthermore the bravais_TYP* V->linstab is calculated, that290@ describes the linear action for H on the space of G-invariant291@ symmetric matrices with respect to the Z-basis given in292@ G->form (c.f. the function 'nomlin' in directory 'Bravais'293@---------------------------------------------------------------------------294@295\**************************************************************************/296void calc_voronoi_stab(V, G, Gtr, bifo)297voronoi_TYP *V;298bravais_TYP *G, *Gtr;299matrix_TYP *bifo;300{301302int i,j;303int dim,fdim, Vanz;304matrix_TYP *M, **bas, *M1, **W;305bravais_TYP *S;306307dim = V->gram->cols;308fdim = bifo->cols;309310if(V->prime == 0)311calc_voronoi_basics(V, G, Gtr, 101);312Vanz = V->vert_no;313if(V->SVi == NULL)314calc_voronoi_good_inv(V, Gtr);315/*******************************************************************\316| calculate 'bas', a consisting of vertices given as symetric matrices317\*******************************************************************/318M = init_mat(Vanz, fdim, "");319for(i=0;i<Vanz;i++)320for(j=0;j<fdim;j++)321M->array.SZ[i][j] = V->vert[i]->gl[j];322M1 = long_qbase(M);323free_mat(M);324if(M1->rows != fdim)325{326printf("error in 'calc_voronoi_stab': form not G-perfect\n");327exit(3);328}329if( (bas = (matrix_TYP **)malloc(fdim *sizeof(matrix_TYP *))) == NULL)330{331printf("malloc of 'bas' in 'calc_voronoi_stab' failed\n");332exit(2);333}334for(i=0;i<fdim;i++)335bas[i] = vec_to_form(M1->array.SZ[i], V->Gtrred->form, fdim);336free_mat(M1);337338/*******************************************************************\339| calculate 'W', the symmetric matrices given by the vertices in V->vert340\*******************************************************************/341if( (W = (matrix_TYP **) malloc(Vanz *sizeof(matrix_TYP *))) == NULL)342{343printf("malloc of 'W' in 'calc_voronoi_stab' failed\n");344exit(2);345}346for(i=0;i<Vanz;i++)347W[i] = vec_to_form(V->vert[i]->gl, V->Gtrred->form, fdim);348349/*******************************************************************\350| calculate the stabilizer351\*******************************************************************/352S = perfect_normal_autgrp(V->red_inv, V->SVi, V->Gtrred->gen, Gtr->gen_no, NULL, W, Vanz, bas, fdim);353for(i=0;i<fdim;i++)354free_mat(bas[i]);355free(bas);356for(i=0;i<Vanz;i++)357free_mat(W[i]);358free(W);359360V->stab = init_bravais(dim);361V->stab->gen_no = S->gen_no;362if( (V->stab->gen = (matrix_TYP **)malloc(S->gen_no *sizeof(matrix_TYP *))) == NULL)363{364printf("malloc of 'V->stab->gen' in 'cal_voronoi_stab' failed\n");365exit(2);366}367for(i=0;i<S->gen_no;i++)368{369M = tr_pose(S->gen[i]);370M1 = mat_mul(V->Ti, M);371V->stab->gen[i] = mat_mul(M1, V->T);372free_mat(M); free_mat(M1);373}374V->stab->order = S->order;375for(i=0;i<100;i++)376V->stab->divisors[i] = S->divisors[i];377free_bravais(S);378V->linstab = init_bravais(fdim);379if( (V->linstab->gen = (matrix_TYP **)malloc(V->stab->gen_no *sizeof(matrix_TYP *))) == NULL)380{381printf("malloc of 'V->linstab->gen' in 'calc_voronoi_stab' failed\n");382exit(2);383}384V->linstab->gen_no = V->stab->gen_no;385for(i=0;i<V->stab->gen_no;i++)386V->linstab->gen[i] = normlin(G->form, V->stab->gen[i], fdim);387}388389390391392/**************************************************************************\393@---------------------------------------------------------------------------394@ matrix_TYP *calc_voronoi_isometry(V1, V2, G, Gtr, bifo)395@ voronoi_TYP *V1, *V2;396@ bravais_TYP *G, *Gtr;397@ matrix_TYP *bifo;398@399@ calculates a matrix X in GL_N(Z) such that400@ X * V1->gram * X^{tr} = V2->gram and X * G * X^{-1} = G401@---------------------------------------------------------------------------402@403\**************************************************************************/404matrix_TYP *calc_voronoi_isometry(V1, V2, G, Gtr, bifo)405voronoi_TYP *V1, *V2;406bravais_TYP *G, *Gtr;407matrix_TYP *bifo;408{409410int i,j;411int dim,fdim, Vanz;412matrix_TYP *M, **bas, *M1, **W;413matrix_TYP *SV1, *SV2;414matrix_TYP *X, *E;415voronoi_TYP *Vn1, *Vn2;416int md1, md2, md, permute;417418dim = V1->gram->cols;419fdim = bifo->cols;420421if(V1->prime == 0)422calc_voronoi_basics(V1, G, Gtr, 101);423if(V2->prime == 0)424calc_voronoi_basics(V2, G, Gtr, 101);425/****************************************************************\426| make first easy tests, if an isiometry can exist427\****************************************************************/428if(V1->prime == V2->prime && V1->pdet != V2->pdet)429return(NULL);430if(V1->min != V2->min)431return(NULL);432if(V1->SV_no != V2->SV_no)433return(NULL);434if(V1->vert_no != V2->vert_no)435return(NULL);436437Vanz = V1->vert_no;438if(V1->SVi == NULL)439calc_voronoi_good_inv(V1, Gtr);440441/*******************************************************************\442| Check which 'red_inv' has the smaller maximal diagonal entry443\*******************************************************************/444md1 = V1->red_inv->array.SZ[0][0];445md2 = V2->red_inv->array.SZ[0][0];446for(i=1;i<dim;i++)447{448if(V1->red_inv->array.SZ[i][i] > md1)449md1 = V1->red_inv->array.SZ[i][i];450if(V2->red_inv->array.SZ[i][i] > md2)451md2 = V2->red_inv->array.SZ[i][i];452}453if(md2 < md1)454{ permute = TRUE; md = md2; Vn1 = V2; Vn2 = V1;}455else456{ permute = FALSE; md = md1; Vn1 = V1; Vn2 = V2;}457458/*******************************************************************\459| calculate the shortest_vectors460\*******************************************************************/461if(Vn1->SVi != NULL)462SV1 = Vn1->SVi;463else464SV1 = short_vectors(Vn1->red_inv, md, 0, 0, 0, &i);465SV2 = short_vectors(Vn2->red_inv, md, 0, 0, 0, &j);466if(SV1->rows != SV2->rows)467{468if(Vn1->SVi == NULL)469free_mat(SV1);470free_mat(SV2);471/* printf("HIER\n"); */472return(NULL);473}474475476/*******************************************************************\477| calculate 'bas', a basis consisting of vertices of Vn2478| given as symmetric matrices479\*******************************************************************/480M = init_mat(Vanz, fdim, "");481for(i=0;i<Vanz;i++)482for(j=0;j<fdim;j++)483M->array.SZ[i][j] = Vn2->vert[i]->gl[j];484M1 = long_qbase(M);485free_mat(M);486if(M1->rows != fdim)487{488printf("error in 'calc_voronoi_stab': form not G-perfect\n");489exit(3);490}491if( (bas = (matrix_TYP **)malloc(fdim *sizeof(matrix_TYP *))) == NULL)492{493printf("malloc of 'bas' in 'calc_voronoi_stab' failed\n");494exit(2);495}496for(i=0;i<fdim;i++)497bas[i] = vec_to_form(M1->array.SZ[i], Vn2->Gtrred->form, fdim);498free_mat(M1);499500/*******************************************************************\501| calculate 'W', the symmetric matrices given by the vertices502| in Vn1->vert503\*******************************************************************/504if( (W = (matrix_TYP **) malloc(Vanz *sizeof(matrix_TYP *))) == NULL)505{506printf("malloc of 'W' in 'calc_voronoi_stab' failed\n");507exit(2);508}509for(i=0;i<Vanz;i++)510W[i] = vec_to_form(Vn1->vert[i]->gl, Vn1->Gtrred->form, fdim);511512/*******************************************************************\513| calculate an isometry514\*******************************************************************/515516/* output for debugging517put_mat(Vn1->red_inv,NULL,"Vn1->redinv",2);518put_mat(Vn2->red_inv,NULL,"Vn2->redinv",2);519put_mat(SV1,NULL,"SV1",2);520put_mat(SV2,NULL,"SV2",2); */521522523X = perfect_normal_isometry(Vn1->red_inv, Vn2->red_inv, SV1, SV2,524NULL, 0, NULL, W, Vanz, bas, fdim);525for(i=0;i<fdim;i++)526free_mat(bas[i]);527free(bas);528for(i=0;i<Vanz;i++)529free_mat(W[i]);530free(W);531if(Vn1->SVi == NULL)532free_mat(SV1);533free_mat(SV2);534535if(X != NULL)536{537M = long_mat_inv(X);538M1 = mat_mul(Vn1->Ti, M);539E = mat_mul(M1, Vn2->T);540free_mat(M1); free_mat(M);541if(permute == TRUE)542{543M = long_mat_inv(E);544free_mat(E);545E = M;546M = NULL;547}548free_mat(X);549}550else551E = NULL;552return(E);553}554555556557/**************************************************************************\558@---------------------------------------------------------------------------559@ void calc_voronoi_dir_reps(V, G, Gtr, bifo)560@ voronoi_TYP *V;561@ bravais_TYP *G, *Gtr;562@ matrix_TYP *bifo;563@564@ calculates representatives of the orbits of V->stab on the565@ Voronoi-directions given in V->pol->vert.566@ The representatives are stored in V->dir_reps in the following way567@ V->dir_reps->cols is the number of representatives.568@ Each column discribes a representatives569@ The integer in the first row describs the number of the representative,570@ i.e. V->dir_reps->array.SZ[0][i] = k means that V->pol->vert[k]571@ is a representative of the i-th orbit.572@ The entry in the second row is the length of the orbit.573@ The third row is allocated in 'normalizer', where repesentatives574@ V[0],...,V[t] of the G-perfect forms are calculated575@ V->dir_reps->array.SZ[2][i] = k means, that V is a neighbour of576@ V[k] and the Voronoi-direction from V to V[k] is the one577@ given in the first row.578@---------------------------------------------------------------------------579@580\**************************************************************************/581void calc_voronoi_dir_reps(V, G, Gtr, bifo)582voronoi_TYP *V;583bravais_TYP *G, *Gtr;584matrix_TYP *bifo;585{586int i,j;587matrix_TYP **M;588int fdim;589int opt[5], orb_no;590591fdim = G->form_no;592opt[0] = 1;593for(i=1;i<5;i++)594opt[i] = 0;595if(V->prime == 0)596calc_voronoi_basics(V, G, Gtr, 101);597if(V->stab == NULL)598calc_voronoi_stab(V, G, Gtr, bifo);599if(V->pol == NULL)600calc_voronoi_pol(V, bifo);601if( (M = (matrix_TYP **) malloc(V->pol->vert_no *sizeof(matrix_TYP *))) == NULL)602{603printf("malloc of 'M' in 'calc_voronoi_dir_reps' failed\n");604exit(2);605}606for(i=0;i<V->pol->vert_no;i++)607{608M[i] = init_mat(1, fdim, "");609for(j=0;j<fdim;j++)610M[i]->array.SZ[0][j] = V->pol->vert[i]->v[j];611}612V->dir_reps = orbit_representatives(M, V->pol->vert_no, V->linstab, opt, &orb_no, 0);613for(i=0;i<V->pol->vert_no;i++)614free_mat(M[i]);615free(M);616}617618619620/**************************************************************************\621@---------------------------------------------------------------------------622@ void calc_voronoi_complete(V, G, Gtr, bifo, prime)623@ voronoi_TYP *V;624@ bravais_TYP *G, *Gtr;625@ matrix_TYP *bifo;626@ int prime;627@628@ applies:629@ calc_voronoi_basics(V, G, Gtr, prime);630@ calc_voronoi_pol(V, bifo);631@ calc_voronoi_good_inv(V, Gtr);632@ calc_voronoi_stab(V, G, Gtr, bifo);633@ calc_voronoi_dir_reps(V, G, Gtr, bifo);634@---------------------------------------------------------------------------635@636\**************************************************************************/637void calc_voronoi_complete(V, G, Gtr, bifo, prime)638voronoi_TYP *V;639bravais_TYP *G, *Gtr;640matrix_TYP *bifo;641int prime;642{643calc_voronoi_basics(V, G, Gtr, prime);644calc_voronoi_pol(V, bifo);645calc_voronoi_good_inv(V, Gtr);646calc_voronoi_stab(V, G, Gtr, bifo);647calc_voronoi_dir_reps(V, G, Gtr, bifo);648}649650651