GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#include "typedef.h"1#include "longtools.h"2#include "longtools.h"3#include "matrix.h"4#include "orbit.h"5#include "idem.h"6#include "datei.h"78extern int INFO_LEVEL;910/******************************************************************************11@12@------------------------------------------------------------------------------13@ FILE: v4_catalog.c14@------------------------------------------------------------------------------15@16*******************************************************************************/1718/******************************************************************************19@20@------------------------------------------------------------------------------21@22@ static matrix_TYP *test_v4(bravais_TYP *G)23@24@ Tests whether the given Bravais group G is isomorphic to V_4 = C_2 x C_2.25@ The order of the group has to be 4, and this order has to sit in G->order.26@27@ The return is NULL if the group is not isomophic to V_4, and otherwise28@ a matrix with non negative trace in G.29@------------------------------------------------------------------------------30@31*******************************************************************************/32static matrix_TYP *test_v4(bravais_TYP *G)33{34static int i,35j,36opt[6];3738matrix_TYP **ELE,39*ID,40*TMP,41*g;4243if (G->order != 4){44return NULL;45}4647opt[2] = 4;48j = 0;4950/* calculate all elements */51ID = init_mat(G->dim,G->dim,"1");52ELE = orbit_alg(ID,G,NULL,opt,&i);5354for (i=0;i<4;i++){55TMP = mat_mul(ELE[i],ELE[i]);56if (mat_comp(ID,TMP)==0)57j++;58free_mat(TMP);59}6061g = NULL;6263/* all elements should have order at most 2 */64if (j==4){65for (i=0;i<4 && g == NULL; i++){66j = trace(ELE[i]);67if ((0<=j) && (j <G->dim)){68g = ELE[i];69ELE[i] = NULL;70}71}72}7374/* clean up */75for (i=0;i<4;i++){76if (ELE[i] != NULL) free_mat(ELE[i]);77}78free(ELE);7980free_mat(ID);8182return g;83}8485/******************************************************************************86@87@------------------------------------------------------------------------------88@89@ static matrix_TYP *basis_part(matrix_TYP *g, matrix_TYP *h,90@ matrix_TYP **plse,int rank2,int eps)91@92@------------------------------------------------------------------------------93@94*******************************************************************************/95static matrix_TYP *basis_part(matrix_TYP *g, matrix_TYP *h,96matrix_TYP **plse,int rank2,int eps)97{9899int i,100j,101k,102old_rank,103rank;104105matrix_TYP *E,106*A,107**tmp,108*tmp2,109*zass_mat,110*RES;111112/* calculate a Z-basis for the eigen space of 0 */113tmp = long_solve_mat(h,NULL);114E = tmp[1];115free(tmp);116117/* avoid trouble if there isn't any psle.. */118if (rank2 == 0){119return E;120}121122/* calculate a Z-basis for the intersection E ^ (e1 + (eps) * g e1 .....) */123zass_mat = init_mat(rank2,2*g->cols,"");124for (i=0;i<rank2;i++){125tmp2 = mat_mul(g,plse[i]);126for (j=0;j<g->cols;j++){127zass_mat->array.SZ[i][j] = plse[i]->array.SZ[j][0]128+ eps * tmp2->array.SZ[j][0];129zass_mat->array.SZ[i][j+g->cols] = zass_mat->array.SZ[i][j];130}131free_mat(tmp2);132}133tmp2 = long_rein_mat(zass_mat);134free_mat(zass_mat);135zass_mat = tmp2;136tmp2 = NULL;137old_rank = zass_mat->rows;138real_mat(zass_mat,zass_mat->rows+E->cols,zass_mat->cols);139for (i=0;i<E->cols;i++){140for (j=0;j<E->rows;j++){141zass_mat->array.SZ[old_rank+i][j] = E->array.SZ[j][i];142}143}144long_row_hnf(zass_mat);145146rank = -1;147i = -1;148while (rank == -1){149i++;150rank = i;151for (j=0;j<g->cols;j++)152if (zass_mat->array.SZ[i][j] != 0){153rank = -1;154}155}156157tmp2 = init_mat(zass_mat->rows-rank,g->cols,"");158for (i=0;i<zass_mat->rows-rank;i++){159for (j=0;j<g->cols;j++){160tmp2->array.SZ[i][j] = zass_mat->array.SZ[i+rank][j+g->cols];161}162}163free_mat(zass_mat);164zass_mat = long_rein_mat(tmp2);165free_mat(tmp2);166tmp2 = zass_mat;167zass_mat=NULL;168169/* now add vectors to give a Z-basis of E */170/* represent the rows of tmp2 as linear combinations of the columns of E */171/* write these in the rows of A */172zass_mat = tr_pose(tmp2);173free_mat(tmp2);174tmp = long_solve_mat(E,zass_mat);175if (tmp[1] != NULL){176fprintf(stderr,"error in basis_part\n");177exit(3);178}179A = tr_pose(tmp[0]);180free_mat(tmp[0]);181free(tmp);182free_mat(zass_mat);183184/* make an gauss as far as possible and add indices */185old_rank = A->rows;186RES = init_mat(g->cols,E->cols-old_rank,"");187for (i=old_rank;i<E->cols;i++){188long_row_hnf(A);189real_mat(A,A->rows+1,A->cols);190191/* search for a "step" */192for (j=0;j<A->rows && A->array.SZ[j][j]!=0;j++);193j--;194195/* add one row vector of A and make sure the lattice stays pure */196if (j < 0){197A->array.SZ[A->rows-1][0] = 1;198}199else{200gcd_darstell(A->array.SZ[j][j],A->array.SZ[j][j+1],201A->array.SZ[A->rows-1]+j+1,A->array.SZ[A->rows-1]+j,&k);202A->array.SZ[A->rows-1][j+1] *= (-1);203}204205/* stick this linear combination into RES */206for (j=0;j<A->cols;j++){207for (k=0;k<RES->rows;k++){208RES->array.SZ[k][i-old_rank] += A->array.SZ[A->rows-1][j]209* E->array.SZ[k][j];210}211}212}213214/* cleanup */215free_mat(A);216free_mat(E);217218return RES;219}220221/******************************************************************************222@223@------------------------------------------------------------------------------224@225@ static matrix_TYP *normalize(matrix_TYP *g,int *dim,int flag)226@227@------------------------------------------------------------------------------228@229*******************************************************************************/230static matrix_TYP *normalize(matrix_TYP *g,int *dim,int flag)231{232233matrix_TYP *h,234*RES,235**plse,236*tmp;237238int i,239j,240k,241rank2;242243/* set h = g - 1 */244h = copy_mat(g);245for (i=0;i<h->cols;i++)246h->array.SZ[i][i]--;247248tmp = copy_mat(h);249modp_mat(tmp,2);250init_prime(2);251rank2 = p_gauss(tmp);252cleanup_prime();253254plse = (matrix_TYP **) malloc(rank2 * sizeof(matrix_TYP *));255for (i=0;i<rank2;i++){256plse[i] = init_mat(h->rows,1,"");257k = 0;258for (j=0;j<tmp->cols && k==0;j++)259k = plse[i]->array.SZ[j][0] = tmp->array.SZ[i][j];260}261free_mat(tmp);262263if (flag || rank2 == dim[0]){264dim[0] = rank2;265266RES = init_mat(g->cols,g->cols,"");267268for (i=0;i<rank2;i++){269for (j=0;j<g->cols;j++){270RES->array.SZ[j][2*i] = plse[i]->array.SZ[j][0];271}272tmp = mat_mul(g,plse[i]);273for (j=0;j<g->cols;j++){274RES->array.SZ[j][2*i+1] = tmp->array.SZ[j][0];275}276free_mat(tmp);277}278279k = 2*rank2;280tmp = basis_part(g,h,plse,rank2,1);281for (i=0;i<tmp->cols;i++){282for (j=0;j<tmp->rows;j++){283RES->array.SZ[j][k] = tmp->array.SZ[j][i];284}285k++;286}287free_mat(tmp);288289for (i=0;i<h->cols;i++)290h->array.SZ[i][i] += 2;291292tmp = basis_part(g,h,plse,rank2,-1);293for (i=0;i<tmp->cols;i++){294for (j=0;j<tmp->rows;j++){295RES->array.SZ[j][k] = tmp->array.SZ[j][i];296}297k++;298}299free_mat(tmp);300}301else{302/* we didn't find an appropriate element */303RES = NULL;304}305306/* free the memory */307for (i=0;i<rank2;i++)308free_mat(plse[i]);309if (plse != NULL) free(plse);310free_mat(h);311312if (RES != NULL){313Check_mat(RES);314}315316return RES;317}318319/******************************************************************************320@321@------------------------------------------------------------------------------322@323@ bravais_TYP *catalog_number_v4(bravais_TYP *G,char *symb,324@ matrix_TYP **TR,int *almost,int *zclass)325@326@ Tests wheter the Bravais group G is isomorphic to C_2 or V_4.327@ In these cases it will return a group which is Z-equivalent to G328@ from the catalog which sits in TOPDIR/tables.329@330@ It will return a transfromation matrix via TR[0], and the position331@ in the catalog via almost[0] and zclass[0].332@333@ bravais_TYP *G : The group in question. Its order must be given.334@ char *symb : The symbol of the group. It can be calculated via symbol(..)335@ matrix_TYP **TR: pointer for the transformation matrix which transforms336@ the given group G to the group returned via konj_bravais,337@ ie. TR[0] * G * TR[0]^-1 = group returned.338@ int *almost : the position of the almost decomposable group in the339@ catalog is returned via this pointer.340@ int *zclass : 2 coordinate of the group in the catalog.341@342@------------------------------------------------------------------------------343@344*******************************************************************************/345bravais_TYP *catalog_number_v4(bravais_TYP *G,char *symb,346matrix_TYP **TR,int *almost,int *zclass)347{348349bravais_TYP *T = NULL,350*H;351352symbol_out *S;353354matrix_TYP *X,355*g,356*g2,357*h,358*h2,359*TG,360*TG2;361362char *file;363364int i,365dim_g_F2;366367if (G->dim > MAXDIM){368fprintf(stderr,"This program does only work up to dimension %d\n",369MAXDIM);370exit(3);371}372373/* check whether we do have the trivial case of <-I_n> */374if ((strcmp(symb,"1") == 0) ||375(strcmp(symb,"1,1") == 0) ||376(strcmp(symb,"1,1,1") == 0) ||377(strcmp(symb,"1,1,1,1") == 0) ||378(strcmp(symb,"1,1,1,1,1") == 0) ||379(strcmp(symb,"1,1,1,1,1,1") == 0)){380almost[0] = 1;381zclass[0] = 1;382S = read_symbol_from_string(symb);383T = S->grp;384free(S);385free(S->fn);386TR[0] = init_mat(G->dim,G->dim,"1");387if (T->zentr_no > 0){388fprintf(stderr,"catalog_number: an error ocurred in the -I_n case\n");389exit(3);390}391return T;392}393394/* firstly test whether we have a group isomorphic to v4 */395g = test_v4(G);396397if (g!= NULL){398/* we got an element of G of order 2, which has non negative trace */399400/* we should only have 1 almost decomposable family */401S = read_symbol_from_string(symb);402H = S->grp;403get_zentr(S);404if (S->fn != NULL){405fprintf(stderr,"catalog_number: an error occured in v4-part\n");406exit(3);407}408free(S);409410/* throw away centralizer & normalizer, ist only hinders */411if (H->cen_no >0){412for (i=0;i<H->cen_no;i++) free_mat(H->cen[i]);413free(H->cen);414H->cen = NULL;415H->cen_no = 0;416}417if (H->normal_no >0){418for (i=0;i<H->normal_no;i++) free_mat(H->normal[i]);419free(H->normal);420H->normal = NULL;421H->normal_no = 0;422}423424/* normalize g */425TG = normalize(g,&dim_g_F2,TRUE);426X = long_mat_inv(TG);427TG2 = mat_kon(X,g,TG);428free_mat(g);429free_mat(X);430g = TG2;431432if (INFO_LEVEL & 4){433put_mat(TG,NULL,"TG",2);434put_mat(g,NULL,"g",2);435}436437/* bare in mind that the trace is Q-invariant */438g2 = test_v4(H);439440almost[0] = 1;441zclass[0] = -1;442TG2 = NULL;443while (TG2 ==0){444445if (zclass[0] == (-1)){446h = copy_mat(g2);447}448else if (zclass[0] >= H->zentr_no){449fprintf(stderr,"bravais_catalog: v4-part: didn't find the group\n");450exit(3);451}452else{453X = mat_inv(H->zentr[zclass[0]]);454h = mat_kon(X,g2,H->zentr[zclass[0]]);455free_mat(X);456}457458TG2 = normalize(h,&dim_g_F2,FALSE);459460if (TG2 != NULL){461/* we found the corresponding group */462/* the transforming matrix is the quotient of TG and TG2 */463if (INFO_LEVEL & 4) put_mat(TG2,NULL,"TG2",2);464X = long_mat_inv(TG);465TR[0] = mat_mul(TG2,X);466if (zclass[0] < 0){467T = H;468H = NULL;469}470else{471T = Z_class(H,H->zentr[zclass[0]]);472}473}474475free_mat(h);476477zclass[0]++;478}479480/* we started off with -1 */481zclass[0]++;482483free_mat(g);484free_mat(g2);485free_mat(TG);486free_mat(TG2);487free_mat(X);488if (H != NULL) free_bravais(H);489490}491492return T;493}494495496