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>21#include <graph.h>2223#define TWOTO21 20971522425extern int INFO_LEVEL;2627static void mod(int *a,int b)28{29a[0] = a[0] % b;30if (a[0]<0) a[0] += b;31}3233static void valuation_here(matrix_TYP *x,matrix_TYP *D,MP_INT *val)34{35int first,36last,37i;3839MP_INT prod,40tmp;4142mpz_init_set_si(&prod,1);43mpz_set_si(val,0);44mpz_init(&tmp);4546/* set first and last */47for (first = 0;first<D->cols && D->array.SZ[first][first] == 1;first++);48for (last = 0;last<D->cols && D->array.SZ[last][last] != 0;last++);4950for (i=first;i<last;i++){51mod(x->array.SZ[i-first],D->array.SZ[i][i]);52mpz_mul_ui(&tmp,&prod,(unsigned long ) x->array.SZ[i-first][0]);53mpz_add(val,val,&tmp);54mpz_mul_ui(&prod,&prod,(unsigned long) D->array.SZ[i][i]);55}5657mpz_clear(&prod);58mpz_clear(&tmp);5960return;61} /* valuation(.....) */6263static int hash(struct tree *p,MP_INT *valuations,MP_INT *new_val,int pos)64{6566int cmp;6768if ((p==NULL) || (p->no <0)){69fprintf(stderr,"fehler in hash\n");70}7172cmp = mpz_cmp(new_val,valuations+p->no);7374if (cmp < 0){75if (p->left == NULL){76if (pos != -1){77p->left = (struct tree *) calloc(1,sizeof(struct tree));78p->left->no = pos;79}80return -1;81}82else{83return hash(p->left,valuations,new_val,pos);84}85}86else if (cmp > 0){87if (p->right == NULL){88if (pos != -1){89p->right = (struct tree *) calloc(1,sizeof(struct tree));90p->right->no = pos;91}92return -1;93}94else{95return hash(p->right,valuations,new_val,pos);96}97}98else{99return p->no;100}101102} /* static int hash(...) */103104static int smallest(struct tree *p)105{106if (p==NULL){107printf("error in smallest\n");108exit(3);109}110111if (p->left == NULL){112return p->no;113}114else{115return smallest(p->left);116}117118} /* static int smallest(...) */119120/**************************************************************************121@122@ -------------------------------------------------------------------------123@124@ matrix_TYP *orbit_rep(matrix_TYP *x,125@ matrix_TYP **N,126@ int nanz,127@ matrix_TYP *D,128@ int option,129@ char *B,130@ MP_INT *l,131@ int *anz,132@ int **word,133@ int word_flag,134@ int ***WORDS,135@ int *NUMBER_OF_WORDS)136@137@138@ option: an integer controling the behaviours of the function.139@ option = 0: return the length of the orbit via anz[0] and140@ the smallest representative via return.141@ option = 1: return straight if we found a smaller142@ representative, and return this one.143@ anz[0] has no defined meaning in this case.144@ char *B:145@146@ l: the valuation of the representative returned is via147@ this pointer.148@149@ int **word: needed only for word_flag==TRUE:150@ returns a list of integers word with the following property:151@ N[word[0][1]] * N[word[0][2]] * ... *N[word[0][word[0][0]]152@ is a word representing the smallest representative in the153@ orbit.154@ int word_flag: drives the behaviour of the function:155@ for word_flag == TRUE it calculates such a word described156@ above, otherwise it will not change word[0] (hopefully).157@ int ***WORDS:158@ int *NUMBER_OF_WORDS:159@160@ Neither the matrices given nor any global variable is changed.161@162@ -------------------------------------------------------------------------163@164***************************************************************************/165static matrix_TYP *static_orbit_rep(matrix_TYP *x,166matrix_TYP **N,167int nanz,168matrix_TYP *D,169int option,170char *B,171MP_INT *l,172int *anz,173int **word,174int word_flag,175int ***WORDS,176int *NUMBER_OF_WORDS)177{178int first,179last,180i,181j,182k,183h,184**orb_words,185speicher; /* the number of allocated memory for valuations186and orbit, and orb_words */187MP_INT *valuations,188new_val; /* the valuation of the newly calculated vector */189190matrix_TYP *erg,191**orbit,192*tmp;193194struct tree *p;195196/* set first and last */197for (first = 0;first<D->cols && D->array.SZ[first][first] == 1;first++);198for (last = 0;last<D->cols && D->array.SZ[last][last] != 0;last++);199200/* get memory */201p = (struct tree *) calloc(1,sizeof(struct tree));202speicher = MIN_SPEICHER;203valuations = (MP_INT *) malloc(speicher * sizeof(MP_INT));204for (i=0;i<speicher;i++) mpz_init(&valuations[i]);205mpz_init(&new_val);206orbit = (matrix_TYP **) malloc(speicher * sizeof(matrix_TYP*));207orbit[0] = copy_mat(x);208if (word_flag){209orb_words = (int **) malloc(speicher * sizeof(int ));210orb_words[0] = (int *) malloc(sizeof(int));211orb_words[0][0] = 0;212}213valuation_here(x,D,&valuations[0]);214215/* anz[0] is the length of the orbit so far */216anz[0] = 1;217erg = NULL;218219for (i=0;i<anz[0] && erg == NULL;i++){220for (j=0;j<nanz && erg == NULL;j++){221tmp = mat_mul(N[j],orbit[i]);222223/* normalize tmp modulo the diagonal entries of D */224for (k=first;k<last;k++)225mod(tmp->array.SZ[k-first],D->array.SZ[k][k]);226227valuation_here(tmp,D,&new_val);228229h = hash(p,valuations,&new_val,anz[0]);230231if (h != (-1)){232/* the element is not new */233free_mat(tmp);234235/* inserted this case to handle the stabilizer of a cozycle236as well: tilman 15.03. */237if (WORDS){238239/* we got a new generator of the stabilizer of the cozycle */240WORDS[0][NUMBER_OF_WORDS[0]] = (int *) calloc(241orb_words[h][0]+orb_words[i][0]+2, sizeof(int));242WORDS[0][NUMBER_OF_WORDS[0]][0] =243orb_words[h][0]+orb_words[i][0]+1;244for (k=1;k<=orb_words[h][0];k++){245WORDS[0][NUMBER_OF_WORDS[0]][k] =246-orb_words[h][orb_words[h][0] - k + 1] - 1;247}248WORDS[0][NUMBER_OF_WORDS[0]][orb_words[h][0]+1] = j+1;249for (k=1;k<=orb_words[i][0];k++){250WORDS[0][NUMBER_OF_WORDS[0]][orb_words[h][0]+1+k] =251orb_words[i][k] + 1;252}253254NUMBER_OF_WORDS[0]++;255if (NUMBER_OF_WORDS[0] % MIN_SPEICHER)256WORDS[0] = (int **) realloc( WORDS[0] ,257(NUMBER_OF_WORDS[0]+MIN_SPEICHER) * sizeof(int));258}259}260else{261/* the element is new */262263/* get more memory is nessesary */264if (anz[0] >= speicher){265speicher += MIN_SPEICHER;266valuations = (MP_INT *) realloc(valuations,267speicher * sizeof(MP_INT));268for (k=anz[0];k<speicher;k++) mpz_init(&valuations[k]);269orbit = (matrix_TYP **) realloc(orbit,270speicher * sizeof(matrix_TYP *));271if (word_flag){272orb_words = realloc(orb_words,speicher * sizeof(int));273}274}275276mpz_set(valuations+anz[0],&new_val);277orbit[anz[0]] = tmp;278anz[0]++;279280if (word_flag){281orb_words[anz[0]-1] = (int *) malloc( (orb_words[i][0] + 2)282* sizeof(int));283memcpy(orb_words[anz[0]-1]+2,orb_words[i]+1,(orb_words[i][0])284* sizeof(int));285orb_words[anz[0]-1][0] = orb_words[i][0] + 1;286orb_words[anz[0]-1][1] = j;287}288289/* here is the place to check whether the option allows us290to exit straigth if tmp is small enough */291if ((option == 1) && (mpz_cmp(&new_val,&valuations[0])<0)){292erg = tmp;293mpz_set(l,&new_val);294anz[0]--;295}296297/* mark this element got in the element list B */298if (B!= NULL) B[mpz_get_ui(&new_val)] = TRUE;299}300}301}302303/* now get the smallest representative if nessesary */304if (option == 0 || (option == 1 && erg == NULL)){305k = smallest(p);306erg = copy_mat(orbit[k]);307mpz_set(l,&valuations[k]);308if (word_flag){309word[0] = orb_words[k];310/* just malloced to be able to free it */311orb_words[k] = (int *) malloc(1*sizeof(int));312}313}314315/* cleaning up */316for (i=0;i<anz[0];i++) free_mat(orbit[i]);317free(orbit);318for (i=0;i<speicher;i++) mpz_clear(valuations+i);319free(valuations);320free_tree(p);321mpz_clear(&new_val);322if (word_flag){323for (i=0;i<anz[0];i++) free(orb_words[i]);324free(orb_words);325}326327return erg;328}329330331332333static int gives_rise_to_torsionfree_space_group(334bravais_TYP *G,335matrix_TYP *D,336matrix_TYP *cocycle,337matrix_TYP *x)338{339340bravais_TYP *R; /* holds the space group */341342int i,343j,344k,345*res;346347matrix_TYP *C;348349350R = init_bravais(G->dim+1);351C = convert_to_cozycle(x,cocycle,D);352353R->gen = (matrix_TYP **) malloc(G->gen_no * sizeof(matrix_TYP *));354R->gen_no = G->gen_no;355for (i=0;i<G->gen_no;i++){356R->gen[i] = copy_mat(G->gen[i]);357real_mat(R->gen[i],G->dim+1,G->dim+1);358R->gen[i]->array.SZ[G->dim][G->dim] = 1;359iscal_mul(R->gen[i],C->kgv);360R->gen[i]->kgv = C->kgv;361}362363/* stick the cocycle in the last column of the matrices generating R */364k = 0;365for (i=0;i<R->gen_no;i++){366for (j=0;j<G->dim;j++){367R->gen[i]->array.SZ[j][G->dim] = C->array.SZ[k][0];368k++;369}370Check_mat(R->gen[i]);371}372373res = torsionfree(R,&i,&j);374i = res[0] ; free(res);375376free_bravais(R);377free_mat(C);378379return i;380}381382383384385/**************************************************************************386@387@ -------------------------------------------------------------------------388@389@ matrix_TYP **extensions(matrix_TYP *cozycle,390@ matrix_TYP *D,391@ matrix_TYP *R,392@ bravais_TYP *G,393@ int **lengths,394@ MP_INT **names,395@ int *number_of_orbits,396@ int option)397@398@ Returns the cozycles which generate the isomorphims classes of399@ extensions of G by the natural ZG-module. The split extension is400@ represented by an all zero matrix.401@402@ The arguments are:403@ matrix_TYP *cozykle: 1st matrix returned by cohomolgy for G.404@ matrix_TYP *D: 2nd matrix returned by cohomolgy for G.405@ matrix_TYP *R: 3rd matrix returned by cohomolgy for G.406@ bravais_TYP *G: the group in question.407@ int **lengths: length[0] returns a pointer to the lengths408@ of the orbits respectively409@ MP_INT **names: names[0] returns a pointer to the names of410@ the cozycles as they would appear in a call411@ of identify(.....).412@ int *number_of_orbits: the number of orbits the normalizer induces413@ on the cohomology group.414@ MP_INT coho_size: order of the cohomology group415@ int option: controls the behaviour of the function:416@ option & 1: construct only torsion free extensions417@ int *list_of_names: if list_of_names != NULL save of each cocycle the number of the418@ smallest represenatative in it's orbit there419@ -------------------------------------------------------------------------420@421***********************************************************************/422matrix_TYP **extensions_o(matrix_TYP *cozycle,423matrix_TYP *D,424matrix_TYP *R,425bravais_TYP *G,426int **lengths,427MP_INT **names,428int *number_of_orbits,429int ****WORDS,430int **NUMBER_OF_WORDS,431matrix_TYP ***N,432MP_INT coho_size,433int option,434int *list_of_names)435{436int i, j, k, anz, *wort, act_val_int, coho_size_int,437Nanz = G->normal_no + G->cen_no,438orbit_length, **WWW;439440char *tested;441442MP_INT act_val,443new_val,444got_size;445446matrix_TYP *x,447*y,448**erg; /* stores the representatives of the orbits=isomorphism449classes of extensions as rational matrices */450451if (INFO_LEVEL & 7){452fprintf(stderr,"entered extensions\n");453}454455number_of_orbits[0] = 0; /* should be changed to a calculation via burnside's456lemma */457458mpz_init_set_si(&act_val,0);459mpz_init_set_si(&got_size,0);460mpz_init(&new_val);461462erg = (matrix_TYP **) malloc(sizeof(matrix_TYP *));463lengths[0] = (int *) malloc(sizeof(int));464names[0] = (MP_INT *) malloc(sizeof(MP_INT));465N[0] = (matrix_TYP **)calloc(Nanz, sizeof(matrix_TYP *));466467if (list_of_names != NULL){468coho_size_int = mpz_get_ui(&coho_size);469}470471if (mpz_get_ui(&coho_size) < TWOTO21){472tested = (char *)calloc(mpz_get_ui(&coho_size), sizeof(char));473}474else{475tested = NULL;476if (list_of_names != NULL){477fprintf(stderr, "The cohomology group is too big!\n");478fprintf(stderr, "If you are really interested in the graph of group - subgroup relations\n");479fprintf(stderr, "please start the program again with the option -l!\n");480exit(3);481}482}483484for (i=0;i<Nanz;i++){485if (i<G->cen_no){486N[0][i] = normalop(cozycle,D,R,G,G->cen[i],i == (Nanz-1));487}488else{489N[0][i] = normalop(cozycle,D,R,G,G->normal[i-G->cen_no],i == (Nanz-1));490}491if (INFO_LEVEL & 16){492put_mat(N[0][i],NULL,"N[i]",2);493}494}495496if (is_option('v')){497fprintf(stderr,"The 1-cohomology group has ");498mpz_out_str(stderr,10,&coho_size);499}500501while((mpz_cmp(&got_size, &coho_size)<0) && (mpz_cmp(&act_val, &coho_size)<0)){502503if (INFO_LEVEL == 17 ||504is_option('v')){505fprintf(stderr,"Got %d extensions so far\n",*number_of_orbits);506}507508if (tested == NULL || !tested[mpz_get_ui(&act_val)]){509510if (tested != NULL) tested[mpz_get_ui(&act_val)] = TRUE;511512WWW = (int **)calloc(MIN_SPEICHER, sizeof(int *));513anz = 0;514x = reverse_valuation(&act_val,D);515y = static_orbit_rep(x,N[0],Nanz,D,1,tested,&new_val,&orbit_length,516&wort, 1, &WWW, &anz);517free(wort);518519if ((INFO_LEVEL & 4) || list_of_names != NULL)520act_val_int = mpz_get_ui(&act_val);521522if (INFO_LEVEL & 4){523printf("act_val %d\n", act_val_int);524put_mat(x,NULL,"x",2);525put_mat(y,NULL,"y",2);526}527528if (list_of_names != NULL){529for (k = 1; k < coho_size_int; k++){530if (list_of_names[k] == 0 && tested[k] == TRUE)531list_of_names[k] = act_val_int;532}533}534535if (mpz_cmp(&new_val,&act_val) == 0 &&536(!(option & 1) ||537gives_rise_to_torsionfree_space_group( G, D, cozycle, x))){538if (number_of_orbits[0] % MIN_SPEICHER == 0){539erg = (matrix_TYP **) realloc(erg,540(number_of_orbits[0] + MIN_SPEICHER)*sizeof(matrix_TYP*));541lengths[0] = (int *) realloc(lengths[0],542(number_of_orbits[0] + MIN_SPEICHER)*sizeof(int));543names[0] = (MP_INT *) realloc(names[0],544(number_of_orbits[0] + MIN_SPEICHER)*sizeof(MP_INT));545WORDS[0] = (int ***)realloc(WORDS[0],546(number_of_orbits[0] + MIN_SPEICHER)*sizeof(int **));547NUMBER_OF_WORDS[0] = (int *)realloc(NUMBER_OF_WORDS[0],548(number_of_orbits[0] + MIN_SPEICHER)*sizeof(int));549550}551erg[number_of_orbits[0]] = convert_to_cozycle(x,cozycle,D);552lengths[0][number_of_orbits[0]] = orbit_length;553mpz_init_set(names[0]+number_of_orbits[0],&act_val);554mpz_add_ui(&got_size,&got_size,(unsigned long) orbit_length);555WORDS[0][number_of_orbits[0]] = (int **)calloc(anz, sizeof(int *));556for (j = 0; j < anz; j++){557WORDS[0][number_of_orbits[0]][j] = WWW[j];558}559NUMBER_OF_WORDS[0][number_of_orbits[0]] = anz;560free(WWW);561number_of_orbits[0]++;562}563else{564for (j = 0; j < anz; j++)565free(WWW[j]);566free(WWW);567}568569/* clean up and increase act_val */570free_mat(y);571free_mat(x);572}573mpz_add_ui(&act_val,&act_val,1);574}575576if (tested != NULL ) free(tested);577mpz_clear(&act_val);578mpz_clear(&new_val);579mpz_clear(&got_size);580581return erg;582} /* extensions (.... ) */583584585586587/***************************************************************************/588void my_translation(matrix_TYP *TR,589matrix_TYP *preimage,590matrix_TYP *coz,591bravais_TYP *G)592{593594int i,595j,596k,597**WORDS;598599matrix_TYP *tmp,600*tmp2,601**MAP;602603rational eins, minuseins;604605606eins.z = eins.n = minuseins.n = 1; minuseins.z = -1;607WORDS = (int **)calloc(G->gen_no, sizeof(int *));608609tmp2 = long_mat_inv(TR);610MAP = (matrix_TYP **) malloc(G->gen_no * sizeof(matrix_TYP *));611for (j=0;j<G->gen_no;j++){612MAP[j] = copy_mat(G->gen[j]);613real_mat(MAP[j],MAP[j]->rows+1,MAP[j]->cols);614real_mat(MAP[j],MAP[j]->rows,MAP[j]->cols+1);615MAP[j]->array.SZ[G->dim][G->dim] = 1;616for (k=0;k<G->dim;k++){617MAP[j]->array.SZ[k][G->dim]=preimage->array.SZ[j*G->dim+k][0];618}619tmp = mat_kon(TR,MAP[j],tmp2);620free_mat(MAP[j]);621MAP[j] = tmp;622}623tmp = reget_gen(MAP,G->gen_no,G,WORDS,TRUE);624tmp->kgv = preimage->kgv;625626for (i=0;i<G->gen_no;i++){627free_mat(MAP[i]);628free(WORDS[i]);629}630free(MAP);631free(WORDS);632633tmp = mat_addeq(tmp, coz, eins, minuseins);634635coboundary(G,tmp,TR);636free_mat(tmp2);637free_mat(tmp);638639return;640641}642643644645646