GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
/****************************************************************************1@2@ ----------------------------------------------------------------------------3@4@ FILE: normalop.c5@6@ ----------------------------------------------------------------------------7@8******************************************************************************/910#include <typedef.h>11#include <getput.h>12#include <matrix.h>13#include <base.h>14#include <gmp.h>15#include <zass.h>16#include <longtools.h>17#include <orbit.h>18#include <sort.h>19#include <bravais.h>20#include <contrib.h>2122#define TWOTO21 20971522324extern int INFO_LEVEL;2526static void mod(int *a,int b)27{28a[0] = a[0] % b;29if (a[0]<0) a[0] += b;30}3132void valuation(matrix_TYP *x,matrix_TYP *D,MP_INT *val)33{34int first,35last,36i;3738MP_INT prod,39tmp;4041mpz_init_set_si(&prod,1);42mpz_set_si(val,0);43mpz_init(&tmp);4445/* set first and last */46for (first = 0;first<D->cols && D->array.SZ[first][first] == 1;first++);47for (last = 0;last<D->cols && D->array.SZ[last][last] != 0;last++);4849for (i=first;i<last;i++){50mod(x->array.SZ[i-first],D->array.SZ[i][i]);51mpz_mul_ui(&tmp,&prod,(unsigned long ) x->array.SZ[i-first][0]);52mpz_add(val,val,&tmp);53mpz_mul_ui(&prod,&prod,(unsigned long) D->array.SZ[i][i]);54}5556mpz_clear(&prod);57mpz_clear(&tmp);5859return;60} /* valuation(.....) */6162static int hash(struct tree *p,MP_INT *valuations,MP_INT *new_val,int pos)63{6465int cmp;6667if ((p==NULL) || (p->no <0)){68fprintf(stderr,"fehler in hash\n");69}7071cmp = mpz_cmp(new_val,valuations+p->no);7273if (cmp < 0){74if (p->left == NULL){75if (pos != -1){76p->left = (struct tree *) calloc(1,sizeof(struct tree));77p->left->no = pos;78}79return -1;80}81else{82return hash(p->left,valuations,new_val,pos);83}84}85else if (cmp > 0){86if (p->right == NULL){87if (pos != -1){88p->right = (struct tree *) calloc(1,sizeof(struct tree));89p->right->no = pos;90}91return -1;92}93else{94return hash(p->right,valuations,new_val,pos);95}96}97else{98return p->no;99}100101} /* static int hash(...) */102103static int smallest(struct tree *p)104{105if (p==NULL){106printf("error in smallest\n");107exit(3);108}109110if (p->left == NULL){111return p->no;112}113else{114return smallest(p->left);115}116117} /* static int smallest(...) */118119/**************************************************************************120@121@ -------------------------------------------------------------------------122@123@ matrix_TYP *orbit_rep(matrix_TYP *x,124@ matrix_TYP **N,125@ int nanz,126@ matrix_TYP *D,127@ int option,128@ char *B,129@ MP_INT *l,130@ int *anz,131@ int **word,132@ int word_flag,133@ int ***WORDS,134@ int *NUMBER_OF_WORDS)135@136@137@ option: an integer controling the behaviours of the function.138@ option = 0: return the length of the orbit via anz[0] and139@ the smallest representative via return.140@ option = 1: return straight if we found a smaller141@ representative, and return this one.142@ anz[0] has no defined meaning in this case.143@ char *B:144@145@ l: the valuation of the representative returned is via146@ this pointer.147@148@ int **word: needed only for word_flag==TRUE:149@ returns a list of integers word with the following property:150@ N[word[0][1]] * N[word[0][2]] * ... *N[word[0][word[0][0]]151@ is a word representing the smallest representative in the152@ orbit.153@ int word_flag: drives the behaviour of the function:154@ for word_flag == TRUE it calculates such a word described155@ above, otherwise it will not change word[0] (hopefully).156@ int ***WORDS:157@ int *NUMBER_OF_WORDS:158@159@ Neither the matrices given nor any global variable is changed.160@161@ -------------------------------------------------------------------------162@163***************************************************************************/164matrix_TYP *orbit_rep(matrix_TYP *x,165matrix_TYP **N,166int nanz,167matrix_TYP *D,168int option,169char *B,170MP_INT *l,171int *anz,172int **word,173int word_flag,174int ***WORDS,175int *NUMBER_OF_WORDS)176{177int first,178last,179i,180j,181k,182h,183**orb_words,184speicher; /* the number of allocated memory for valuations185and orbit, and orb_words */186MP_INT *valuations,187new_val; /* the valuation of the newly calculated vector */188189matrix_TYP *erg,190**orbit,191*tmp;192193struct tree *p;194195/* set first and last */196for (first = 0;first<D->cols && D->array.SZ[first][first] == 1;first++);197for (last = 0;last<D->cols && D->array.SZ[last][last] != 0;last++);198199/* get memory */200p = (struct tree *) calloc(1,sizeof(struct tree));201speicher = MIN_SPEICHER;202valuations = (MP_INT *) malloc(speicher * sizeof(MP_INT));203for (i=0;i<speicher;i++) mpz_init(&valuations[i]);204mpz_init(&new_val);205orbit = (matrix_TYP **) malloc(speicher * sizeof(matrix_TYP*));206orbit[0] = copy_mat(x);207if (word_flag){208orb_words = (int **) malloc(speicher * sizeof(int ));209orb_words[0] = (int *) malloc(sizeof(int));210orb_words[0][0] = 0;211}212valuation(x,D,&valuations[0]);213214/* anz[0] is the length of the orbit so far */215anz[0] = 1;216erg = NULL;217218for (i=0;i<anz[0] && erg == NULL;i++){219for (j=0;j<nanz && erg == NULL;j++){220tmp = mat_mul(N[j],orbit[i]);221222/* normalize tmp modulo the diagonal entries of D */223for (k=first;k<last;k++)224mod(tmp->array.SZ[k-first],D->array.SZ[k][k]);225226valuation(tmp,D,&new_val);227228h = hash(p,valuations,&new_val,anz[0]);229230if (h != (-1)){231/* the element is not new */232free_mat(tmp);233234/* inserted this case to handle the stabilizer of a cozycle235as well: tilman 15.03. */236if (WORDS){237238/* we got a new generator of the stabilizer of the cozycle */239WORDS[0][NUMBER_OF_WORDS[0]] = (int *) calloc(240orb_words[h][0]+orb_words[i][0]+2, sizeof(int));241WORDS[0][NUMBER_OF_WORDS[0]][0] =242orb_words[h][0]+orb_words[i][0]+1;243for (k=1;k<=orb_words[h][0];k++){244WORDS[0][NUMBER_OF_WORDS[0]][k] =245-orb_words[h][orb_words[h][0] - k + 1] - 1;246}247WORDS[0][NUMBER_OF_WORDS[0]][orb_words[h][0]+1] = j+1;248for (k=1;k<=orb_words[i][0];k++){249WORDS[0][NUMBER_OF_WORDS[0]][orb_words[h][0]+1+k] =250orb_words[i][k] + 1;251}252253NUMBER_OF_WORDS[0]++;254if (NUMBER_OF_WORDS[0] % MIN_SPEICHER)255WORDS[0] = (int **) realloc( WORDS[0] ,256(NUMBER_OF_WORDS[0]+MIN_SPEICHER) * sizeof(int));257}258}259else{260/* the element is new */261262/* get more memory is nessesary */263if (anz[0] >= speicher){264speicher += MIN_SPEICHER;265valuations = (MP_INT *) realloc(valuations,266speicher * sizeof(MP_INT));267for (k=anz[0];k<speicher;k++) mpz_init(&valuations[k]);268orbit = (matrix_TYP **) realloc(orbit,269speicher * sizeof(matrix_TYP *));270if (word_flag){271orb_words = realloc(orb_words,speicher * sizeof(int));272}273}274275mpz_set(valuations+anz[0],&new_val);276orbit[anz[0]] = tmp;277anz[0]++;278279if (word_flag){280orb_words[anz[0]-1] = (int *) malloc( (orb_words[i][0] + 2)281* sizeof(int));282memcpy(orb_words[anz[0]-1]+2,orb_words[i]+1,(orb_words[i][0])283* sizeof(int));284orb_words[anz[0]-1][0] = orb_words[i][0] + 1;285orb_words[anz[0]-1][1] = j;286}287288/* here is the place to check whether the option allows us289to exit straigth if tmp is small enough */290if ((option == 1) && (mpz_cmp(&new_val,&valuations[0])<0)){291erg = tmp;292mpz_set(l,&new_val);293anz[0]--;294}295296/* mark this element got in the element list B */297if (B!= NULL) B[mpz_get_ui(&new_val)] = TRUE;298}299}300}301302/* now get the smallest representative if nessesary */303if (option == 0 || (option == 1 && erg == NULL)){304k = smallest(p);305erg = copy_mat(orbit[k]);306mpz_set(l,&valuations[k]);307if (word_flag){308word[0] = orb_words[k];309/* just malloced to be able to free it */310orb_words[k] = (int *) malloc(1*sizeof(int));311}312}313314/* cleaning up */315for (i=0;i<anz[0];i++) free_mat(orbit[i]);316free(orbit);317for (i=0;i<speicher;i++) mpz_clear(valuations+i);318free(valuations);319free_tree(p);320mpz_clear(&new_val);321if (word_flag){322for (i=0;i<anz[0];i++) free(orb_words[i]);323free(orb_words);324}325326return erg;327}328329330331/**************************************************************************332@333@ -------------------------------------------------------------------------334@335@ matrix_TYP *normalop(matrix_TYP *cozycle,matrix_TYP *D,matrix_TYP *R,336@ bravais_TYP *G,matrix_TYP *N)337@338@ Calculates the action of the matrix N on the cohomology group H^1(G,*)339@ described by the matrices cozycle, D, R, which are in turn output of340@ cohomology.341@342@ CAUTION: The matrix returned describes the action on rows, and it is343@ not checked whether N is realy an element of the normalizer of G!344@345@ matrix_TYP *cozycle: the first return value of cohomology for G.346@ matrix_TYP *D: the second return value of cohomology for G.347@ matrix_TYP *R: the third return value of cohomology for G.348@ bravais_TYP *G: the group. only the field generator is realy needed.349@ matrix_TYP *N: the matrix in question.350@ int opt:351@352@ No global variables nor the arguments are changed (hopefully).353@354@ -------------------------------------------------------------------------355@356***************************************************************************/357matrix_TYP *normalop(matrix_TYP *cozycle,358matrix_TYP *D,359matrix_TYP *R,360bravais_TYP *G,361matrix_TYP *N,362int opt)363364{365int i,366j,367k,368denominator,369first, /* first index such that D[i][i] != 1 */370last; /* last index with D[i][i] !=0 */371372int **words; /* the words which give the original generators373will be stored in here by reget_gen */374375matrix_TYP *tmp,376*tmp2,377*sols,378*new_coz, /* the mapped cozycle */379*Ninv, /* hold's the inverse of N */380**map, /* hold's the map of a pair generator/cozycle under N */381*erg; /* describes the result */382383static matrix_TYP *GLS;384385Ninv = mat_inv(N);386erg = init_mat(cozycle->cols,cozycle->cols,"");387map = (matrix_TYP **) malloc(G->gen_no * sizeof(matrix_TYP *));388for (i=0;i<G->gen_no;i++){389map[i] = init_mat(G->dim+1,G->dim+1,"1");390}391392/* get memory for the words */393words = (int **) malloc(G->gen_no * sizeof(int *));394395/* set first and last */396for (first = 0;first<D->cols && D->array.SZ[first][first] == 1;first++);397for (last = 0;last<D->cols && D->array.SZ[last][last] != 0;last++);398399if (GLS == NULL){400GLS = long_mat_inv(R);401}402403if (INFO_LEVEL & 4){404fprintf(stderr,"entered normalop\n");405put_mat(N,NULL,"N",2);406put_mat(Ninv,NULL,"Ninv",2);407put_mat(GLS,NULL,"GLS",2);408}409410/* we take a generating set of the cozycles and let this411normalizer element operate */412for (i=first;i<last;i++){413/* map the i-th cozycle */414for (j=0;j<G->gen_no;j++){415/* map the jth generator */416tmp = mat_kon(N,G->gen[j],Ninv);417418/* store it in the right place */419for (k=0;k<tmp->rows;k++){420memcpy(map[j]->array.SZ[k],tmp->array.SZ[k],421sizeof(int) * tmp->cols);422}423424free_mat(tmp);425426/* now map the cozycle */427tmp = init_mat(G->dim,1,"");428for (k=0;k<tmp->rows;k++)429tmp->array.SZ[k][0] = cozycle->array.SZ[j*G->dim + k][i-first];430431tmp2 = mat_mul(N,tmp);432free_mat(tmp);433434for (k=0;k<tmp->rows;k++)435map[j]->array.SZ[k][G->dim] = tmp2->array.SZ[k][0];436free_mat(tmp2);437438if (INFO_LEVEL & 16){439Check_mat(map[j]);440printf("map of the %d-th gen/coz\n",j);441put_mat(map[j],NULL,"map[j]",2);442}443}444445/* reget the original generators of the group,446bare in mind that we got words for i>first already */447new_coz = reget_gen(map,G->gen_no,G,words,i==first);448449/* now we are able to express this new cozycle in terms of the "basis" */450/* solve the resulting linear system of equations */451sols = mat_mul(GLS,new_coz);452453if (INFO_LEVEL & 16){454put_mat(sols,NULL,"sols",2);455put_mat(new_coz,NULL,"new_coz",2);456}457458/* copy the solution to the COLUMNS of erg, so erg will459act on COLUMNS as well */460for (k=0;k<erg->rows;k++){461j = sols->array.SZ[k+first][0] * D->array.SZ[k+first][k+first];462denominator = D->array.SZ[i][i];463if ((j % denominator)!=0){464fprintf(stderr,"error in normalop\n");465exit(3);466}467else{468erg->array.SZ[k][i-first] = (j / denominator) %469D->array.SZ[k+first][k+first];470if (erg->array.SZ[k][i-first] < 0)471erg->array.SZ[k][i-first] += D->array.SZ[k+first][k+first];472}473}474475free_mat(sols);476free_mat(new_coz);477478}479480/* cleaning up */481free_mat(Ninv);482for (i=0;i<G->gen_no;i++){483free_mat(map[i]);484free(words[i]);485}486free(map);487free(words);488489if (opt){490free_mat(GLS);491GLS = NULL;492}493494return erg;495}496497498void translation(matrix_TYP *TR,499matrix_TYP *rep,500matrix_TYP *ext,501matrix_TYP *cocycle,502matrix_TYP *D,503bravais_TYP *G)504{505506int i,507j,508k,509first,510**WORDS;511512matrix_TYP *tmp,513*tmp2,514**MAP;515516/* set first */517for (first = 0;first<D->cols && D->array.SZ[first][first] == 1;first++);518519WORDS = (int **) calloc(G->gen_no , sizeof(int*));520521tmp2 = long_mat_inv(TR);522MAP = (matrix_TYP **) malloc(G->gen_no * sizeof(matrix_TYP *));523for (j=0;j<G->gen_no;j++){524MAP[j] = copy_mat(G->gen[j]);525real_mat(MAP[j],MAP[j]->rows+1,MAP[j]->cols);526real_mat(MAP[j],MAP[j]->rows,MAP[j]->cols+1);527MAP[j]->array.SZ[G->dim][G->dim] = 1;528for (k=0;k<G->dim;k++){529MAP[j]->array.SZ[k][G->dim]=ext->array.SZ[j*G->dim+k][0];530}531tmp = mat_kon(TR,MAP[j],tmp2);532free_mat(MAP[j]);533MAP[j] = tmp;534}535tmp = reget_gen(MAP,G->gen_no,G,WORDS,TRUE);536tmp->kgv = ext->kgv;537538for (i=0;i<G->gen_no;i++){539free_mat(MAP[i]);540free(WORDS[i]);541}542free(MAP);543free(WORDS);544545for (i=0;i<rep->rows;i++){546k = rep->array.SZ[i][0] * tmp->kgv / D->array.SZ[first+i][first+i];547if (k != 0){548for (j=0;j<tmp->rows;j++){549tmp->array.SZ[j][0] -= k * cocycle->array.SZ[j][i];550}551}552}553554coboundary(G,tmp,TR);555free_mat(tmp2);556free_mat(tmp);557558return;559560}561562/**************************************************************************563@564@--------------------------------------------------------------------------565@566@ matrix_TYP **identify(matrix_TYP *cozycle,567@ matrix_TYP *D,568@ matrix_TYP *R,569@ bravais_TYP *G,570@ matrix_TYP **extension,571@ MP_INT *a,572@ int number,573@ int transform_flag,574@ int ***WORDS,575@ int *NUMBER_OF_WORDS)576@577@ Identifies the space groups described by the cozycles in extension,578@ i.e. gives them different number iff they are not isomorphic.579@ The return value depends on the value of transform_flag. If580@ (transform_flag == TRUE) it will return a list of "number" matrices in581@ the normalizer of the point group which transforms each given extension582@ into it's least representative. This is usefull to calculate the583@ isomorphism between two extensions which get the same name.584@ NOTE: the name given to an extension is 0 (interpreted as MP_INT) iff585@ the extension splits.586@587@ matrix_TYP *cozykle: 1st matrix returned by cohomolgy for G.588@ matrix_TYP *D: 2nd matrix returned by cohomolgy for G.589@ matrix_TYP *R: 3rd matrix returned by cohomolgy for G.590@ bravais_TYP *G: the group in question. Needed are the591@ fields G->gen, G->gen_no, G->cen,G->cen_no,592@ G->normal,G->normal_no.593@ Important for the correctness of the result594@ is that the matrices in G->cen, G->normal595@ generate N_GL_n(Z) (G) /G.596@ matrix_TYP **extension: matrices discribing a cozycles for the group G.597@ So each matrix in the list discribes a spacegroup.598@ MP_int *a: The names for the groups will be returned599@ via this field. The space has to be allocated600@ via malloc and to be mpz_init-ed for each601@ entry before calling the function.602@ int number: The number of matrices in extension.603@ int transform_flag: if (transform_flag) the function will return604@ a pointer containing "number" matrices which605@ transform each extension into it's least606@ representative. Otherwise it will return NULL.607@ int ***WORDS: words in the generators of the normalizer608@ which generate the stabilizer og this cozykle609@ as a subgroup. If == NULL, this is not calculated.610@ Otherwise it is an address of a dynamic pointer611@ to at least MIN_SPEICHER entries of type *int.612@ int *NUMBER_OF_WORDS: number of words WORDS.613@--------------------------------------------------------------------------614@615***************************************************************************/616matrix_TYP **identify(matrix_TYP *cozycle,617matrix_TYP *D,618matrix_TYP *R,619bravais_TYP *G,620matrix_TYP **extension,621MP_INT *a,622int number,623int transform_flag,624int ***WORDS,625int *NUMBER_OF_WORDS)626{627628int i,629j,630k,631denominator,632first,633*word, /* the function orbit_rep will return634a word representing the least extension635by this pointer */636Nanz= G->cen_no+G->normal_no;637638matrix_TYP **N,639**TR, /* holds the result, ie. the transformation640matrices */641*GLS,642*tmp,643*coz,644*rep;645646/* set first */647for (first = 0;first<D->cols && D->array.SZ[first][first] == 1;first++);648649if (transform_flag)650TR = (matrix_TYP **) malloc(number * sizeof(matrix_TYP *));651else652TR = NULL;653654GLS = mat_inv(R);655N = (matrix_TYP **) malloc(Nanz * sizeof(matrix_TYP*));656for (i=0;i<Nanz;i++){657if (i<G->cen_no){658N[i] = normalop(cozycle,D,R,G,G->cen[i],i == (Nanz-1));659}660else{661N[i] = normalop(cozycle,D,R,G,G->normal[i-G->cen_no],i == (Nanz-1));662}663if (INFO_LEVEL & 16){664put_mat(N[i],NULL,"N[i]",2);665}666}667668coz = init_mat(N[0]->rows,1,"");669670for (i=0;i<number;i++){671672/* firstly calculate a representative, and translate it into673the representation of C_d1 X ..... X C_dn */674tmp = mat_mul(GLS,extension[i]);675676/* and now calculate the smallest representative in the orbit under677the action of the normalizer, and it's valuation */678for (k=0;k<coz->rows;k++){679j = tmp->array.SZ[k+first][0] * D->array.SZ[k+first][k+first];680denominator = tmp->kgv;681if ((j % denominator)!=0){682fprintf(stderr,"error in identify: are you sure this is a cozycle?\n");683fprintf(stderr,"If so, please report to the authors: [email protected]\n");684exit(3);685}686else{687coz->array.SZ[k][0] = (j / denominator) %688D->array.SZ[k+first][k+first];689while (coz->array.SZ[k][0] < 0)690coz->array.SZ[k][0] += D->array.SZ[k+first][k+first];691}692}693694rep = orbit_rep(coz,N,Nanz,D,0,NULL,a+i,&j,&word,695transform_flag,WORDS,NUMBER_OF_WORDS);696697if (transform_flag){698TR[i] = init_mat(G->dim,G->dim,"1");699for (j=1;j<=word[0];j++){700if (word[j] < G->cen_no){701mat_muleq(TR[i],G->cen[word[j]]);702}703else{704mat_muleq(TR[i],G->normal[word[j]-G->cen_no]);705}706}707free(word);708709/* now calculate the coboundary to get it physically nailed */710real_mat(TR[i],TR[i]->rows,TR[i]->cols+1);711real_mat(TR[i],TR[i]->rows+1,TR[i]->cols);712TR[i]->array.SZ[G->dim][G->dim] = 1;713714if (transform_flag == 3){715translation(TR[i],rep,extension[i],cozycle,D,G);716}717}718719/* we are done, so clean up */720free_mat(tmp);721free_mat(rep);722723}724725/* clean up N, coz and GLS */726for (i=0;i<Nanz;i++) free_mat(N[i]);727free(N);728free_mat(coz);729free_mat(GLS);730731return TR;732}733734735static int gives_rise_to_torsionfree_space_group(736bravais_TYP *G,737matrix_TYP *D,738matrix_TYP *cocycle,739matrix_TYP *x)740{741742bravais_TYP *R; /* holds the space group */743744int i,745j,746k,747*res;748749matrix_TYP *C;750751752R = init_bravais(G->dim+1);753C = convert_to_cozycle(x,cocycle,D);754755R->gen = (matrix_TYP **) malloc(G->gen_no * sizeof(matrix_TYP *));756R->gen_no = G->gen_no;757for (i=0;i<G->gen_no;i++){758R->gen[i] = copy_mat(G->gen[i]);759real_mat(R->gen[i],G->dim+1,G->dim+1);760R->gen[i]->array.SZ[G->dim][G->dim] = 1;761iscal_mul(R->gen[i],C->kgv);762R->gen[i]->kgv = C->kgv;763}764765/* stick the cocycle in the last column of the matrices generating R */766k = 0;767for (i=0;i<R->gen_no;i++){768for (j=0;j<G->dim;j++){769R->gen[i]->array.SZ[j][G->dim] = C->array.SZ[k][0];770k++;771}772Check_mat(R->gen[i]);773}774775res = torsionfree(R,&i,&j);776i = res[0] ; free(res);777778free_bravais(R);779free_mat(C);780781return i;782}783784/**************************************************************************785@786@ -------------------------------------------------------------------------787@788@ matrix_TYP **extensions(matrix_TYP *cozycle,789@ matrix_TYP *D,790@ matrix_TYP *R,791@ bravais_TYP *G,792@ int **lengths,793@ MP_INT **names,794@ int *number_of_orbits,795@ int option)796@797@ Returns the cozycles which generate the isomorphims classes of798@ extensions of G by the natural ZG-module. The split extension is799@ represented by an all zero matrix.800@801@ The arguments are:802@ matrix_TYP *cozykle: 1st matrix returned by cohomolgy for G.803@ matrix_TYP *D: 2nd matrix returned by cohomolgy for G.804@ matrix_TYP *R: 3rd matrix returned by cohomolgy for G.805@ bravais_TYP *G: the group in question.806@ int **lengths: length[0] returns a pointer to the lengths807@ of the orbits respectively808@ MP_INT **names: names[0] returns a pointer to the names of809@ the cozycles as they would appear in a call810@ of identify(.....).811@ int *number_of_orbits: the number of orbits the normalizer induces812@ on the cohomology group.813@ int option : controls the behaviour of the function:814@ option & 1: construct only torsion free extensions815@ -------------------------------------------------------------------------816@817***************************************************************************/818matrix_TYP **extensions(matrix_TYP *cozycle,819matrix_TYP *D,820matrix_TYP *R,821bravais_TYP *G,822int **lengths,823MP_INT **names,824int *number_of_orbits,825int option )826{827int i,828Nanz = G->normal_no + G->cen_no,829orbit_length;830831char *tested;832833MP_INT act_val,834new_val,835got_size,836coho_size; /* holds the size of the cohomology group */837838matrix_TYP *x,839*y,840**N,841**erg; /* stores the representatives of the orbits=isomorphism842classes of extensions as rational matrices */843844if (INFO_LEVEL & 7){845fprintf(stderr,"entered extensions\n");846}847848number_of_orbits[0] = 0; /* should be changed to a calculation via burnside's849lemma */850851mpz_init_set_si(&act_val,0);852mpz_init_set_si(&coho_size,1);853mpz_init_set_si(&got_size,0);854mpz_init(&new_val);855/* the order of the cohomology group in the product of those elementary856divisors which are not equal 0 */857for (i=0;i<D->cols && D->array.SZ[i][i] != 0;i++)858mpz_mul_ui(&coho_size,&coho_size,(unsigned long) D->array.SZ[i][i]);859860erg = (matrix_TYP **) malloc(sizeof(matrix_TYP *));861lengths[0] = (int *) malloc(sizeof(int));862names[0] = (MP_INT *) malloc(sizeof(MP_INT));863N = (matrix_TYP **) malloc(Nanz * sizeof(matrix_TYP *));864865if (mpz_get_ui(&coho_size) < TWOTO21)866tested = (char *) calloc(mpz_get_ui(&coho_size), sizeof(char));867else868tested = NULL;869870for (i=0;i<Nanz;i++){871if (i<G->cen_no){872N[i] = normalop(cozycle,D,R,G,G->cen[i],i == (Nanz-1));873}874else{875N[i] = normalop(cozycle,D,R,G,G->normal[i-G->cen_no],i == (Nanz-1));876}877if (INFO_LEVEL & 16){878put_mat(N[i],NULL,"N[i]",2);879}880}881882if (is_option('v')){883fprintf(stderr,"The 1-cohomology group has ");884mpz_out_str(stderr,10,&coho_size);885}886887while((mpz_cmp(&got_size,&coho_size)<0) && (mpz_cmp(&act_val,&coho_size)<0)){888889if (INFO_LEVEL == 17 ||890is_option('v')){891fprintf(stderr,"Got %d extensions so far\n",*number_of_orbits);892}893894if (tested == NULL || !tested[mpz_get_ui(&act_val)]){895896if (tested != NULL) tested[mpz_get_ui(&act_val)] = TRUE;897898x = reverse_valuation(&act_val,D);899y = orbit_rep(x,N,Nanz,D,1,tested,&new_val,&orbit_length,900NULL,FALSE,NULL,NULL);901902if (INFO_LEVEL & 4){903printf("act_val %d\n",(int ) mpz_get_ui(&act_val));904put_mat(x,NULL,"x",2);905put_mat(y,NULL,"y",2);906}907908if (mpz_cmp(&new_val,&act_val) == 0 &&909(!(option & 1) ||910gives_rise_to_torsionfree_space_group( G, D, cozycle, x))){911if (number_of_orbits[0] % MIN_SPEICHER == 0){912erg = (matrix_TYP **) realloc(erg,913(number_of_orbits[0] + MIN_SPEICHER)*sizeof(matrix_TYP*));914lengths[0] = (int *) realloc(lengths[0],915(number_of_orbits[0] + MIN_SPEICHER)*sizeof(int));916names[0] = (MP_INT *) realloc(names[0],917(number_of_orbits[0] + MIN_SPEICHER)*sizeof(MP_INT));918}919erg[number_of_orbits[0]] = convert_to_cozycle(x,cozycle,D);920lengths[0][number_of_orbits[0]] = orbit_length;921mpz_init_set(names[0]+number_of_orbits[0],&act_val);922number_of_orbits[0]++;923mpz_add_ui(&got_size,&got_size,(unsigned long) orbit_length);924}925926/* clean up and increase act_val */927free_mat(y);928free_mat(x);929}930mpz_add_ui(&act_val,&act_val,1);931}932933for (i=0;i<Nanz;i++) free_mat(N[i]);934free(N);935if (tested != NULL ) free(tested);936mpz_clear(&act_val);937mpz_clear(&new_val);938mpz_clear(&got_size);939mpz_clear(&coho_size);940941return erg;942} /* extensions (.... ) */943944static matrix_TYP **calc_elements(matrix_TYP **N,matrix_TYP **Ninv,int Nanz,945matrix_TYP *D,unsigned long *no_of_elements)946{947int i,948j,949k,950l,951pos, /* position returned by hash_mat */952dim, /* the rank of the Z-module the N[i] are acting on */953first, /* first index such that D[i][i] != 1 */954last; /* last index with D[i][i] !=0 */955956matrix_TYP *tmp,957**erg; /* holds all elements of the group */958959struct tree *hash;960961/* set first and last */962for (first = 0;first<D->cols && D->array.SZ[first][first] == 1;first++);963for (last = 0;last<D->cols && D->array.SZ[last][last] != 0;last++);964dim = last-first;965966erg = (matrix_TYP **) malloc(MIN_SPEICHER * sizeof(matrix_TYP *));967erg[0] = init_mat(dim,dim,"1");968*no_of_elements = 1;969hash = (struct tree *) malloc(1*sizeof(struct tree));970hash->no = 0;971hash->left = hash->right = NULL;972973/* we won't need inverses for the orbit calculation, everything is finite */974for (i=0;i<*no_of_elements;i++){975for (j=0;j<Nanz;j++){976tmp = mat_mul(erg[i],N[j]);977978/* normalize tmp */979for (k=0;k<dim;k++)980for (l=0;l<dim;l++)981mod(tmp->array.SZ[k]+l,D->array.SZ[k+first][k+first]);982983pos = hash_mat(hash,erg,tmp,*no_of_elements);984985if (pos != -1){986if (Ninv!=NULL && pos==0) Ninv[j] = erg[i];987free_mat(tmp);988}989else{990if (*no_of_elements % MIN_SPEICHER == 0)991erg = (matrix_TYP **) realloc(erg,992(*no_of_elements + MIN_SPEICHER)*sizeof(matrix_TYP *));993994erg[*no_of_elements] = tmp;995no_of_elements[0]++;996}997}998}9991000free_tree(hash);10011002return erg;1003} /* calc_elements(....) */100410051006/****************************************************************************1007@1008@----------------------------------------------------------------------------1009@1010@ static void no_of_fixpoints(MP_INT *res,matrix_TYP *A,matrix_TYP *D)1011@1012@1013@ CAUTION: A->array.SZ, A->cols WILL BE CHANGED!!!!1014@----------------------------------------------------------------------------1015@1016*****************************************************************************/1017static void no_of_fixpoints(MP_INT *res,matrix_TYP *A,matrix_TYP *D)1018{1019int i,1020first;10211022matrix_TYP *tmp;10231024/* set first */1025for (first = 0;first<D->cols && D->array.SZ[first][first] == 1;first++);10261027/* build a matrix (A-I | D') in A (D' = those parts of D which have non1028trivial elementary divisors) */1029real_mat(A,A->rows,A->cols+A->rows);1030for (i=0;i<A->rows;i++){1031A->array.SZ[i][i]--;1032A->array.SZ[i][i+A->rows] = D->array.SZ[i+first][i+first];1033}10341035tmp = long_elt_mat(NULL,A,NULL);10361037mpz_set_ui(res,1);1038for (i=0;i<tmp->rows;i++) mpz_mul_ui(res,res,tmp->array.SZ[i][i]);10391040free_mat(tmp);1041}10421043static int deal_with_small_cohomology_group(matrix_TYP *cozycle,1044matrix_TYP *D,1045matrix_TYP *R,1046bravais_TYP *G,1047MP_INT *erg)1048{10491050int i,1051anz,1052order_of_H=1,1053*len;10541055MP_INT *names;10561057matrix_TYP **Y;10581059if (G->dim < 5){1060return FALSE;1061}10621063/* if the cohomology is small, it might be better to calculate all1064extensions then to calculate all elements of the acting group1065example: H^1 = C_6^3, G_acting = GL_3(Z/6Z) */1066for (i=0;i < D->cols &&1067i < D->rows &&1068order_of_H < 10000 &&1069D->array.SZ[i][i] != 0;i++,order_of_H *= D->array.SZ[i][i]);1070if (order_of_H < 10000){1071Y = extensions(cozycle,D,R,G,&len,&names,&anz,0);10721073for (i=0;i<anz;i++){1074free_mat(Y[i]);1075mpz_clear(names+i);1076}1077free(names);1078free(Y);1079free(len);1080mpz_set_si(erg,anz);1081return TRUE;1082}10831084return FALSE;10851086}10871088/************************************************************************1089@1090@------------------------------------------------------------------------1091@1092@ void no_of_extensions(matrix_TYP *cozycle,matrix_TYP *D,1093@ matrix_TYP *R,bravais_TYP *G,MP_INT *erg)1094@1095@------------------------------------------------------------------------1096@1097*************************************************************************/1098void no_of_extensions(matrix_TYP *cozycle,matrix_TYP *D,1099matrix_TYP *R,bravais_TYP *G,MP_INT *erg)1100{11011102int Nanz=G->cen_no+G->normal_no,1103i;11041105unsigned long no_of_elements; /* the order of the image of the1106normalizer under the map to the1107automorphism group of H^1(...) */11081109MP_INT sum, /* holds the sum over the image of N_GL(Z) in1110Aut(H^1(...)) of the number fixpoint */1111tmp2,1112tmp3;11131114matrix_TYP **N,1115**elements,1116*id;11171118if (deal_with_small_cohomology_group(cozycle, D, R, G, erg)){1119return;1120}11211122mpz_init(&sum);1123mpz_set_si(&sum,0);1124mpz_init(&tmp2);1125mpz_set_si(&tmp2,0);1126mpz_init(&tmp3);1127mpz_set_si(&tmp3,0);11281129N = (matrix_TYP **) malloc(Nanz * sizeof(matrix_TYP *));1130for (i=0;i<Nanz;i++){1131if (i<G->cen_no){1132N[i] = normalop(cozycle,D,R,G,G->cen[i],i == (Nanz-1));1133}1134else{1135N[i] = normalop(cozycle,D,R,G,G->normal[i-G->cen_no],i == (Nanz-1));1136}1137if (INFO_LEVEL & 16){1138put_mat(N[i],NULL,"N[i]",2);1139}1140}11411142/* remove those generators which are == identity for speeding up things */1143if (Nanz > 0){1144id = init_mat(N[0]->rows,N[0]->rows,"1");1145for (i=0;i<Nanz;i++){1146if (mat_comp(id,N[i]) == 0){1147free_mat(N[i]);1148Nanz--;1149N[i] = N[Nanz];1150}1151}1152}11531154if (is_option('v')){1155fprintf(stderr,"calculated the action of the normalizer on the\n");1156fprintf(stderr,"cohomology group\n");1157}11581159elements = calc_elements(N,NULL,Nanz,D,&no_of_elements);11601161if (is_option('v')){1162fprintf(stderr,"Now I got all elements in the image.\n");1163}11641165for (i=0;i<no_of_elements;i++){1166no_of_fixpoints(&tmp2,elements[i],D);11671168if (INFO_LEVEL & 4){1169mpz_out_str(stdout,10,&tmp2);1170printf("\n");1171}11721173mpz_add(&tmp3,&sum,&tmp2);1174mpz_set(&sum,&tmp3);1175/* we won't need this element anymore */1176free_mat(elements[i]);11771178if (is_option('v') && (i % 10 == 0)){1179fprintf(stderr,"Done approximately %d percent of the calculation\n",1180(int ) ((i*100)/no_of_elements));1181}11821183}11841185/* divide sum by the image order, and check whether this is possible1186at all */1187mpz_divmod_ui(&tmp3,&tmp2,&sum,no_of_elements);1188mpz_set(erg,&tmp3);11891190if (INFO_LEVEL & 4){1191mpz_out_str(stdout,10,&sum);1192printf("\n");1193mpz_out_str(stdout,10,erg);1194printf("\n");1195mpz_out_str(stdout,10,&tmp2);1196printf("\n");1197}11981199if (mpz_cmp_si(&tmp2,0) != 0){1200printf("error in no_of_extensions\n");1201exit(3);1202}12031204for (i=0;i<Nanz;i++) free_mat(N[i]);1205free(N);1206free(elements);1207mpz_clear(&sum);1208mpz_clear(&tmp2);1209mpz_clear(&tmp3);12101211return;1212} /* no_of_extensions(....) */121312141215