GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
/***************************************************************************1@2@ --------------------------------------------------------------------------3@4@ FILE: base.h5@6@ some algorithms connected with the schreier-sims algorithm are collected.7@8@ --------------------------------------------------------------------------9@10****************************************************************************/1112#include <typedef.h>13#include <longtools.h>14#include <getput.h>15#include <matrix.h>16#include <tools.h>17#include <sort.h>1819extern int INFO_LEVEL;2021void free_tree(struct tree *p)22{23if (p!=NULL){24free_tree(p->left);25free_tree(p->right);26free(p);27}28}293031int hash_mat(struct tree *p,matrix_TYP **v,matrix_TYP *x,int pos)32{33int cmp;3435if ((p==NULL) || (p->no <0)){36fprintf(stderr,"fehler in hash_mat\n");37}3839cmp = mat_comp(v[p->no],x);40if (cmp < 0){41if (p->left == NULL){42if (pos != -1){43p->left = (struct tree *) calloc(1,sizeof(struct tree));44p->left->no = pos;45}46return -1;47}48else{49return hash_mat(p->left,v,x,pos);50}51}52else if (cmp > 0){53if (p->right == NULL){54if (pos != -1){55p->right = (struct tree *) calloc(1,sizeof(struct tree));56p->right->no = pos;57}58return -1;59}60else{61return hash_mat(p->right,v,x,pos);62}63}64else{65return p->no;66}6768}6970/**************************************************************************71@72@ --------------------------------------------------------------------------73@74@ void init_bahn(bahn *a)75@ initialises the struct bahn, i.e. get's memory for the pointers, and76@ sets all other values to zero.77@78@ --------------------------------------------------------------------------79@80***************************************************************************/81extern void init_bahn(bahn *a)82{83a->length = 0;84a->speicher = MIN_SPEICHER;85a->orbit = (matrix_TYP **) calloc(MIN_SPEICHER , sizeof(matrix_TYP *));86a->representatives = (matrix_TYP **) calloc(MIN_SPEICHER87, sizeof(matrix_TYP *));88a->rep_invs = (matrix_TYP **) calloc(MIN_SPEICHER89, sizeof(matrix_TYP *));90a->words = (int **) calloc(MIN_SPEICHER, sizeof(int *));91a->generators = (matrix_TYP **) calloc(MIN_SPEICHER92, sizeof(matrix_TYP *));93a->hash = (struct tree *) malloc(1*sizeof(struct tree));94a->hash->left = NULL;95a->hash->right = NULL;96a->hash->no = -1;9798}99100101/**************************************************************************102@103@ --------------------------------------------------------------------------104@105@ extern void extend_bahn(bahn **a)106@107@ bahn **a108@109@ reallocated the pointers a[0]->orbit, a[0]->generators and110@ a[0]->representatives by the amount MIN_SPEICHER, and increases111@ a[0]->speicher by this ammount.112@113@ --------------------------------------------------------------------------114@115***************************************************************************/116extern void extend_bahn(bahn **a)117{118if (a[0]->speicher == 0){119printf("error in extend_bahn\n");120exit(3);121}122a[0]->speicher = a[0]->speicher+MIN_SPEICHER;123a[0]->orbit = (matrix_TYP **) realloc(a[0]->orbit,124sizeof(matrix_TYP *) * a[0]->speicher);125a[0]->representatives = (matrix_TYP **) realloc(a[0]->representatives,126sizeof(matrix_TYP *) * a[0]->speicher);127a[0]->rep_invs = (matrix_TYP **) realloc(a[0]->rep_invs,128sizeof(matrix_TYP *) * a[0]->speicher);129a[0]->words = (int **) realloc(a[0]->words,sizeof(int*));130a[0]->generators = (matrix_TYP **) realloc(a[0]->generators,131sizeof(matrix_TYP *) * a[0]->speicher);132}133134/***************************************************************************135@136@ --------------------------------------------------------------------------137@138@ void free_bahn(bahn *a)139@140@ --------------------------------------------------------------------------141@142***************************************************************************/143extern void free_bahn(bahn *a)144{145int i;146147for (i=0;i<a->length;i++){148if (a->orbit[i] != NULL){149free_mat(a->orbit[i]);150}151if (a->representatives[i] != NULL){152free_mat(a->representatives[i]);153}154if (a->rep_invs[i] != NULL){155free_mat(a->rep_invs[i]);156}157if (a->words[i] != NULL){158free(a->words[i]);159}160}161a->length =0;162a->gen_no = 0;163a->speicher = 0;164free(a->orbit);165free(a->representatives);166free(a->rep_invs);167free(a->words);168free(a->generators);169a->orbit = NULL;170a->representatives = NULL;171a->generators = NULL;172173free_tree(a->hash);174a->hash = NULL;175}176177static int position(matrix_TYP **a,matrix_TYP *x,int n)178/* returns the first index i<n such that a[i] == x, and179-1 if none exists */180{181int i=0;182183while (i<n){184if (mat_comp(a[i],x) == 0){185return i;186}187i++;188}189return -1;190}191192static void inv_word(int *w,193int *w_to_inv)194{195int i,196j;197198for (i=1,j=w_to_inv[0];i<=w_to_inv[0];i++,j--)199w[i] = -w_to_inv[j];200201w[0] = w_to_inv[0];202203return;204} /* inv_word */205206static int *get_word_to_generator(bahn *A,207matrix_TYP *h)208{209210int i,211*w;212213for (i=0;i<A->length && mat_comp(A->representatives[i],h) ; i++);214215w = (int *) malloc((A->words[i][0]+1)*sizeof(int));216memcpy(w,A->words[i],(A->words[i][0]+1)*sizeof(int));217218return w;219220} /* get_word_to_generator */221222223224/***************************************************************************225@226@ --------------------------------------------------------------------------227@228@ int einordnen(bahn** erg,229@ matrix_TYP *h,230@ matrix_TYP *new_vec,231@ int *w,232@ int l,233@ int flag)234@235@ bahn **erg : the set of base/strong generators for a finite236@ group G. it's the ONLY variable to be changed.237@ matrix_TYP *h :238@ matrix_TYP *new_vec : this value is not asked for in the case239@ described here, so any variable with the right240@ type will do.241@ int l : -1 ALLWAYS242@ int flag : TRUE ALLWAYS!!!!!243@244@ Inserts a new generator h into the list of strong generators for245@ any FINITE group G.246@ Therefore erg has to be the result of a call of strong_generators(..)247@ for some bravais_TYP *G.248@ The function calls itself recursively, and therefore the convention to249@ use it is somewhat cryptical. In all cases for the 'end user' l has to250@ be -1, and flag has to be TRUE (no garanties otherwise).251@ THE FUNCTION DOES NOT COPY THE VARIABLE h INTO erg[0]->generators,252@ (IT JUST STORES THE POINTER THERE), THEREFORE THE USER IS ASKED TO253@ ASSURE THAT h STAY'S IN THE SAME PLACE WHILE USING erg !!!!!!!!!!254@ The function does not check whether the new generator h is really needed,255@ so better check is out before calling this function by a call of is_element!256@ --------------------------------------------------------------------------257@258***************************************************************************/259static int einordnen(bahn** erg,260matrix_TYP *h,261matrix_TYP *new_vec,262int *w,263int l,264int flag)265{266int tmp = erg[0]->representatives[0]->cols,267tmp2,268i,269*wn;270271matrix_TYP *hinv,272*nv,273*nh;274275if (INFO_LEVEL & 2){276fprintf(stderr,"entering einordnen with l = %d\n",l);277}278279if (l>=tmp){280return FALSE;281}282else{283284if (l!=(-1)){285tmp2 = hash_mat(erg[l]->hash,erg[l]->orbit,new_vec,erg[l]->length);286}287else{288tmp2 = (-1);289}290291if (tmp2!= (-1)){292/* we got an element of the stabilizer, */293/* calculate it then! */294free_mat(new_vec);295296/* in the last stage we won't need an element of297the stabilizer anymore, so we won't calculate it */298if (((l+1)<tmp) && (mat_comp(h,erg[l]->representatives[tmp2])!=0)){299/* hinv = mat_inv(h);300free_mat(h);301mat_muleq(hinv,erg[l]->representatives[tmp2]);302h = hinv;303new_vec = mat_mul(h,erg[l+1]->orbit[0]); */304hinv = mat_mul(erg[l]->rep_invs[tmp2],h);305free_mat(h);306h = hinv;307new_vec = mat_mul(h,erg[l+1]->orbit[0]);308309if (w){310wn = (int *) malloc((erg[l]->words[tmp2][0]+w[0]+1)311*sizeof(int));312inv_word(wn,erg[l]->words[tmp2]);313memcpy(wn+wn[0]+1,w+1,w[0]*sizeof(int));314wn[0] = wn[0] + w[0];315free(w);316}317else{318wn = NULL;319}320}321else{322/* only clean up memory */323free_mat(h);324if (w) free(w);325return FALSE;326}327328/* enter the next stage */329flag = einordnen(erg,h,new_vec,wn,++l,TRUE);330}331else{332if (l != (-1)){333if (erg[l]->speicher<=erg[l]->length){334extend_bahn(erg+l);335336/* this is so seldom used that we might as well check wheter337the group is infinite, find a solution later !! */338}339erg[l]->orbit[erg[l]->length]=new_vec;340erg[l]->representatives[erg[l]->length]=h;341/* inserted to reduce the number of mat_inv s */342erg[l]->rep_invs[erg[l]->length] = mat_inv(h);343344if (w){345/* deal with the words */346erg[l]->words[erg[l]->length]347= (int *) malloc((w[0]+1) * sizeof(int));348memcpy(erg[l]->words[erg[l]->length],w,(w[0]+1) * sizeof(int));349free(w);350}351erg[l]->length++;352353if (INFO_LEVEL & 1){354fprintf(stderr,"l = %d, lenght in this stage %d\n"355,l,erg[l]->length);356}357}358359if (flag){360361if (l == (-1)) l =0;362363/* firstly put this element on the generator list */364erg[l]->generators[erg[l]->gen_no] = h;365erg[l]->gen_no++;366367}368369}370}371372if (flag){373/* do a new orbit-calculation */374/* apply all generators to the previous orbit elements */375for(tmp=0;tmp<erg[l]->length;tmp++){376for (tmp2=l;tmp2<erg[0]->representatives[0]->cols;tmp2++){377for (i=erg[tmp2]->gen_no-1;i>=0;i--){378h = erg[tmp2]->generators[i];379nv = mat_mul(h,erg[l]->orbit[tmp]);380nh = mat_mul(h,erg[l]->representatives[tmp]);381if (w){382wn = get_word_to_generator(erg[tmp2],h);383wn = (int *) realloc(wn,384(wn[0]+erg[l]->words[tmp][0]+1) * sizeof(int));385memcpy(wn+wn[0]+1,erg[l]->words[tmp]+1,386erg[l]->words[tmp][0] * sizeof(int));387wn[0] = wn[0] + erg[l]->words[tmp][0];388}389else{390wn = NULL;391}392einordnen(erg,nh,nv,wn,l,FALSE);393}394}395}396}397398return flag;399} /* einordnen(..........) */400401/***********************************************************************402@403@-----------------------------------------------------------------------404@405@ bahn **strong_generators(matrix_TYP **base,bravais_TYP *U)406@407@ matrix_TYP **base:408@ bravais_TYP *U :409@410@ Calculates a strong generating set according to the sims algorithm411@ for the FINITE group U and the given base.412@ This function initialises the result according to the conventions413@ made in this file. It doesn't change neither **base nor *U.414@ for U only the entries U->dim, U->gen and U->gen_no are used.415@-----------------------------------------------------------------------416@417************************************************************************/418bahn **strong_generators(matrix_TYP **base,bravais_TYP *U,int OPT)419{420bahn **erg;421422int i,423j,424k,425m,426dim = U->dim,427*w;428429matrix_TYP **gen=U->gen,430*new_vec,431*g,432*h;433434435/* geting the memory for the result */436erg = (bahn **) calloc(dim,sizeof(bahn *));437for (i=0;i<dim;i++){438erg[i] = (bahn *) calloc(1,sizeof(bahn));439init_bahn(erg[i]);440}441442for (i=0;i<dim;i++){443erg[i]->representatives[0] = init_mat(U->dim,U->dim,"1");444erg[i]->rep_invs[0] = init_mat(U->dim,U->dim,"1");445erg[i]->words[0] = (int *) malloc(sizeof(int));446erg[i]->words[0][0] = 0;447erg[i]->orbit[0] = copy_mat(base[i]);448erg[i]->length = 1;449erg[i]->hash->no = 0;450}451452/* doing the orbit-calculation */453for (j=0;j<erg[0]->length;j++){454for (k=0;k<U->gen_no;k++){455456if (INFO_LEVEL & 4){457/* printing all results for debugging */458for (i=0;i<dim;i++){459for (m=0;m<erg[i]->length;m++){460printf("i=%d m=%d\n",i,m);461if (erg[i]->representatives[m]->rows != dim ||462erg[i]->orbit[m]->rows != dim){463printf("fehler in strong_generators\n");464exit(3);465}466put_mat(erg[i]->representatives[m],NULL,"represe",2);467put_mat(erg[i]->orbit[m],NULL,"orbit",2);468}469}470}471472/* decide which group element will act */473g=gen[k];474475if (INFO_LEVEL & 4 ){476put_mat(g,NULL,"angewandter erzeuger",2);477}478479h = mat_mul(g,erg[0]->representatives[j]);480new_vec = mat_mul(g,erg[0]->orbit[j]);481482483if (OPT){484w = (int *) malloc((erg[0]->words[j][0] + 2) * sizeof(int));485w[0] = erg[0]->words[j][0] + 1;486w[1] = k+1;487memcpy(w+2,erg[0]->words[j]+1,erg[0]->words[j][0] * sizeof(int));488}489else{490w = NULL;491}492einordnen(erg,h,new_vec,w,0,FALSE);493494}495}496497return erg;498} /* strong_generators */499500extern matrix_TYP **get_base(bravais_TYP *U)501/* will only return a standart basis */502{503matrix_TYP **erg;504505int dim=U->dim,506i;507508erg = (matrix_TYP **) malloc(dim * sizeof(matrix_TYP *));509510for (i=0;i<dim;i++){511erg[i] = init_mat(dim,1,"i");512erg[i]->array.SZ[i][0] = 1;513}514515return erg;516} /* get_base */517518/*************************************************************************519@520@ --------------------------------------------------------------------------521@522@ int is_element(matrix_TYP *x,bravais_TYP *G,bahn **strong,int **w)523@524@ matrix_TYP *x: the matrix in question525@ bravais_TYP *G: actually the only thing asked for is G->dim!526@ bahn **strong: the result of a call of strong_generators(..)527@ for the group G.528@529@ Decides whether the matrix represented by *x is contained in the530@ group described by **strong and *G respectively.531@ strong has to be the result of a call of strong_generators(..)532@ for the group G.533@ The function returns TRUE if x in G, and FALSE otherwise.534@ None of the given variables is changed.535@536@ --------------------------------------------------------------------------537@538***************************************************************************/539extern int is_element(matrix_TYP *x,bravais_TYP *G,bahn **strong,int **w)540{541int erg=TRUE,542dim = G->dim,543i=0,544pos,545*w2;546547matrix_TYP *g_neu,548*bild,549*h;550551g_neu = copy_mat(x);552553while (erg && (i<dim)){554555/* map the basepoint by the element which got to be in556the pointwise stabilizer of the basepoints b_0,..b_{i-1} */557bild = mat_mul(g_neu,strong[i]->orbit[0]);558559/* test whether this image is an image also produced by G */560pos = hash_mat(strong[i]->hash,strong[i]->orbit,bild,-1);561562if (pos == (-1)){563erg = FALSE;564free_mat(bild);565}566else{567/* h = mat_inv(g_neu);568free_mat(g_neu);569free_mat(bild);570g_neu = mat_mul(h,strong[i]->representatives[pos]);571free_mat(h); */572free_mat(bild);573h = mat_mul(strong[i]->rep_invs[pos],g_neu);574free_mat(g_neu);575g_neu = h;576577if (w){578if (w[0]){579w2 = (int *) calloc(w[0][0]+strong[i]->words[pos][0]+1,580sizeof(int));581w2[0] = w[0][0]+strong[i]->words[pos][0];582memcpy(w2+1,w[0]+1,w[0][0] * sizeof(int));583memcpy(w2+w[0][0]+1,(strong[i]->words[pos])+1,584strong[i]->words[pos][0]* sizeof(int));585free(w[0]);586}587else{588w2 = (int *) calloc(strong[i]->words[pos][0]+1,sizeof(int));589w2[0] = strong[i]->words[pos][0];590memcpy(w2+1,strong[i]->words[pos]+1,strong[i]->words[pos][0]*591sizeof(int));592}593w[0] = w2;594}595i++;596597}598}599600free_mat(g_neu);601602return erg;603} /* is_element */604605/**************************************************************************606@607@ --------------------------------------------------------------------------608@609@ int size(bahn **a)610@611@ bahn **a: the result of a call strong_generators(...) for some612@ bravais_TYP *G.613@614@ Under this condition, the function will return the order of the group G.615@ Actually calculated is the product of a[i]->length in some ranges.616@617@ --------------------------------------------------------------------------618@619**************************************************************************/620extern int size(bahn **a)621{622int i,623size = 1;624625for (i=0;i<a[0]->representatives[0]->cols;i++){626size = size*a[i]->length;627}628629return size;630}631632/**************************************************************************633@634@ --------------------------------------------------------------------------635@636@ matrix_TYP **normalizer_in_N(bravais_TYP *U,bravais_TYP *N,int *anz,637@ int finite)638@639@ calculates a generating set for the normalizer of the FINITE group640@ U in the group N, and N is interpreted as generated by N->gen, N->cen and641@ N->normal. The assumption is, that U^N is FINITE.642@ bravais_TYP *U643@ bravais_TYP *N644@ int *anz645@ int finite646@ It returns the elements of the normalizer via return, and the647@ number of these via anz[0].648@ no global variables nor U or N are changed.649@ If finite == true the program assumes that the calculated normalizer650@ is finite, and tries to get hold of a set of base/strong generators651@ for it. THIS WILL WORK IFF THE CALCULATED NORMALIZER IS INDEED FINITE.652@ The program will get the record U->order and U->divisors!653@654@ --------------------------------------------------------------------------655@656***************************************************************************/657extern matrix_TYP **normalizer_in_N(bravais_TYP *U,bravais_TYP *N,int *anz,658int finite)659{660matrix_TYP **erz_N,661**erg,662**orbit,663*test_subgroup,664**base,665*tmp,666*tmp2,667*tmp3,668*stab_element;669670bravais_TYP BN;671672bahn **strong,673**strong_N;674675int i,676j,677k,678l,679flag,680gefunden,681gen_no,682dim = U->dim,683speicher,684erg_speicher;685686/* getting the standart basis for the vectorspace */687base = get_base(U);688strong = strong_generators(base,U,FALSE);689690/* set the order of U */691U->order = size(strong);692factorize_new(U->order,U->divisors);693694if (INFO_LEVEL & 4){695printf("calculated the base for U\n");696}697698/* we are going to need the inverse of each generator anyway699for conjugation, so calculate them now and stick them700in the right position */701gen_no = N->gen_no + N->normal_no + N->cen_no;702703erz_N = (matrix_TYP **) malloc(gen_no * sizeof(matrix_TYP *));704705for (i=0;i<gen_no;i++){706if (i<N->gen_no){707erz_N[i] = copy_mat(N->gen[i]);708}709else if(i<N->gen_no + N->cen_no){710erz_N[i] = copy_mat(N->cen[i - N->gen_no]);711}712else {713erz_N[i] = copy_mat(N->normal[i-N->gen_no-N->cen_no]);714}715}716717/* the subgroups will be represented by the element that718conjugates them */719orbit = (matrix_TYP **) malloc(MIN_SPEICHER * sizeof(matrix_TYP *));720speicher = MIN_SPEICHER;721orbit[0] = init_mat(dim,dim,"1");722gefunden = 1;723724/* getting memory for the result */725erg = (matrix_TYP **) malloc(MIN_SPEICHER * sizeof(matrix_TYP *));726erg_speicher = MIN_SPEICHER;727anz[0] = 0;728729/* strong orbit calculation yields the normalizer */730for (i=0;i<gefunden;i++){731732if (INFO_LEVEL & 1){733fprintf(stderr,"found %d conjugated subgroups,\n",gefunden);734fprintf(stderr,"dealt with %d of these.\n",i);735}736737for (j=0;j<(gen_no);j++){738739/* we only have do deal with the generators, because, we740assume that the orbits are finite */741test_subgroup = mat_mul(erz_N[j],orbit[i]);742743/* now look, whether we already got this subgroup */744/* it's a fiddly part, because I can't think of a */745/* ordering for these subgroups */746k=0;747flag = FALSE;748tmp = mat_inv(test_subgroup);749750while (!flag && (k<gefunden)){751752if (INFO_LEVEL & 4){753put_mat(tmp,NULL,"tmp",2);754put_mat(orbit[k],NULL,"orbit[k]",2);755printf("k= %d\n",k);756}757stab_element = mat_mul(tmp,orbit[k]);758759if (INFO_LEVEL & 4){760put_mat(stab_element,NULL,NULL,2);761}762763/* calculate the conjugates of the generators of U764and decide whether they are in U */765l=0;766while (l<U->gen_no){767if (INFO_LEVEL & 4){768put_mat(stab_element,NULL,"stab_el",2);769}770tmp2 = mat_inv(stab_element);771tmp3 = mat_mul(tmp2,U->gen[l]);772free_mat(tmp2);773tmp2 = mat_mul(tmp3,stab_element);774free_mat(tmp3);775776if (INFO_LEVEL & 4){777printf("l= %d\n",l);778}779780if (!is_element(tmp2,U,strong,NULL)){781l = U->gen_no + 1;782}783l++;784free_mat(tmp2);785}786787if (l==U->gen_no){788flag=TRUE;789}790else{791free_mat(stab_element);792stab_element = NULL;793}794k++;795796}/* while (!flag .. */797798free_mat(tmp);799800/* so now we see whether the element was really in the801stabilizer */802if (flag){803free_mat(test_subgroup);804805/* we might already got this element of the normalizer,806so better check it out */807if ((position(erg,stab_element,anz[0])> (-1)) &&808(stab_element != NULL)){809free_mat(stab_element);810}811else if (finite){812/* if we assume the normalizer to be finite, we will813have an even better test for a new element */814if (anz[0] == 0){815erg[0] = stab_element;816anz[0]++;817BN.gen = erg;818BN.gen_no = 1;819BN.dim = dim;820strong_N = strong_generators(base,&BN,FALSE);821strong_N[0]->generators[0] = stab_element;822strong_N[0]->gen_no = 1;823}824else{825/* we might already got this element in our stabilizer */826if (is_element(stab_element,&BN,strong_N,NULL)){827free_mat(stab_element);828stab_element = NULL;829}830else{831/* this element is new */832anz[0]++;833if (erg_speicher <= anz[0]){834erg_speicher = erg_speicher+MIN_SPEICHER;835erg = (matrix_TYP **) realloc(erg,836erg_speicher*sizeof(matrix_TYP *));837}838erg[anz[0]-1] = stab_element;839einordnen(strong_N,stab_element,840stab_element,NULL,-1,TRUE);841}842}843}844else{845anz[0]++;846if (erg_speicher<=anz[0]){847erg_speicher = erg_speicher+MIN_SPEICHER;848erg = (matrix_TYP **) realloc(erg,849erg_speicher*sizeof(matrix_TYP *));850}851erg[anz[0]-1] = stab_element;852}853}854else{855if (INFO_LEVEL & 4){856put_mat(stab_element,NULL,NULL,2);857}858859if (stab_element != NULL) free_mat(stab_element);860861gefunden++;862863if (speicher<=gefunden){864speicher = speicher+MIN_SPEICHER;865orbit = (matrix_TYP **) realloc(orbit,866speicher*sizeof(matrix_TYP *));867}868orbit[gefunden-1] = test_subgroup;869}870871}/* for (j=0 .. */872}/* for (i=0 .., ie the orbit calculation */873874/* cleaning up the memory */875for (i=0;i<dim;i++){876free_mat(base[i]);877free_bahn(strong[i]);878free(strong[i]);879if (finite){880free_bahn(strong_N[i]);881free(strong_N[i]);882}883}884if ((INFO_LEVEL & 1) && finite){885fprintf(stderr,"Order of the normalizer: %d\n",size(strong_N));886}887free(base);888free(strong);889if (finite) free(strong_N);890891for (i=0;i<gen_no;i++){892free_mat(erz_N[i]);893}894free(erz_N);895896for (i=0;i<gefunden;i++){897free_mat(orbit[i]);898}899free(orbit);900901return erg;902} /* normalizer_in_N */903904/**************************************************************************905@906@--------------------------------------------------------------------------907@908@ int red_gen(bravais_TYP *G,matrix_TYP **base,bahn ***strong,int i)909@910@ Tries to reduce the number of generators for the group G, and returns911@ |G|.912@913@ bravais_TYP *G: the group in question914@ matrix_TYP **base: a basis for the vectorspace on which G is acting915@ bahn ***strong: after the call of this function strong[0] will916@ contain a set of base/strong generating set for917@ the group G.918@ There are two cases for the call of this function919@ 1st: strong[0] == NULL920@ the pfunction reduces the number of generators921@ for G.922@ 2nd: strong[0] != NULL923@ the function assummes strong[0] to contain a set924@ of base/strong generators for the group generated925@ by the first i generators of G, and kills926@ those of the other generators which does not927@ give a bigger group.928@ int i: see above929@930@ SIDEEFFECTS: the entries of G->gen may be changed, and they931@ may be shuffled. G->gen_no may be changed to932@ the number of relevant matrices.933@ strong[0] returns a set of base/strong generators934@ for G, NO OTHER GLOBAL VARIABLE IS CHANGED.935@936@--------------------------------------------------------------------------937@938***************************************************************************/939extern int red_gen(bravais_TYP *G,matrix_TYP **base,bahn ***strong,int i)940{941int G_gen_no= G->gen_no;942943if (strong[0] == NULL){944G->gen_no = 1;945i=1;946strong[0] = strong_generators(base,G,FALSE);947strong[0][0]->gen_no = 1;948strong[0][0]->generators[0] = G->gen[0];949}950951/* this will free all irrelevant generators */952while (i<G_gen_no){953if (!is_element(G->gen[i],G,strong[0],NULL)){954einordnen(strong[0],G->gen[i],G->gen[i],NULL,-1,TRUE);955}956else{957free_mat(G->gen[i]);958G->gen[i] = NULL;959}960i++;961}962963G->gen_no = G_gen_no;964for (i=0;i<G->gen_no;i++){965if (G->gen[i] == NULL){966G->gen[i] = G->gen[G->gen_no-1];967G->gen_no--;968i--;969}970}971972/* just for sanity */973G->gen = (matrix_TYP **) realloc(G->gen, G->gen_no * sizeof(matrix_TYP *));974975return size(strong[0]);976}977978979