GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
/* last change: 26.09.00 by Oliver Heidbuechel */12#include <typedef.h>3#include <matrix.h>4#include <bravais.h>5#include <base.h>6#include <graph.h>7#include <sort.h>8#include <zass.h>9#include <longtools.h>101112/* --------------------------------------------------------------------------- */13/* Add two cocycles in standard representation C_d1 x ... x C_dn and */14/* transform the result into standard representation */15/* --------------------------------------------------------------------------- */16matrix_TYP *add_mod_D(matrix_TYP *A,17matrix_TYP *B,18matrix_TYP *D,19int first,20int diff)21{22int i;2324matrix_TYP *sol;252627sol = init_mat(diff, 1, "");28for (i = 0; i < diff; i++){29sol->array.SZ[i][0] = (A->array.SZ[i][0] + B->array.SZ[i][0]) %30D->array.SZ[i + first][i + first];31if (sol->array.SZ[i][0] < 0)32sol->array.SZ[i][0] += D->array.SZ[i + first][i + first];33}3435return(sol);36}37383940/* --------------------------------------------------------------------------- */41/* return min(a,b) */42/* --------------------------------------------------------------------------- */43static int min(int a,44int b)45{46if (a < b)47return(a);48else49return(b);50}51525354/* --------------------------------------------------------------------------- */55/* which affine classes are in the image */56/* --------------------------------------------------------------------------- */57/* names: names for the affine classes */58/* aff_no: total number of affine classes */59/* image_gen: generating system of the image */60/* D: the second return value of cohomology */61/* anz: save the number of affine classes in the image here */62/* --------------------------------------------------------------------------- */63int *aff_classes_in_image(MP_INT *names,64int aff_no,65int coho_size,66matrix_TYP **orbit,67matrix_TYP **image_gen,68int gen_no,69matrix_TYP *D,70int *anz)71{72int i, j, k, pos, /* m, */73first, last, diff,74insg, flag = 0,75*list, *aff_list;7677matrix_TYP *tmp;7879MP_INT val;808182mpz_init(&val);83aff_list = (int *)calloc(aff_no, sizeof(int));84list = (int *)calloc(coho_size, sizeof(int));85list[0] = -1;86anz[0] = 1;87aff_list[0] = 1;88for (first = 0; first < D->cols && D->array.SZ[first][first] == 1; first++);89for (last = first; last < D->cols && D->array.SZ[last][last] != 0; last++);90diff = last - first;91if (orbit[0] == NULL)92orbit[0] = init_mat(diff, 1, "");93/* m = coho_size; */9495/* orbit algorithm */96for (i = 0; i < coho_size && anz[0] < aff_no; i++){97if (list[i] == -1){98for (j = 0; j < gen_no; j++){99tmp = add_mod_D(orbit[i], image_gen[j], D, first, diff);100valuation(tmp, D, &val);101pos = mpz_get_ui(&val);102if (list[pos] == 0){103/* new element in the orbit */104list[pos] = -1;105if (orbit[pos] == NULL){106orbit[pos] = tmp;107tmp = NULL;108}109for (k = 0; k < aff_no; k++){110if (mpz_cmp(&val, &names[k]) == 0){111/* found representative of the k-th affine class */112aff_list[k] = 1;113anz[0]++;114break;115}116}117}118if (tmp != NULL)119free_mat(tmp);120/*121if (list[pos] == -1){122m = min(pos, m);123}124*/125}126list[i] = 1;127/*128if (m == i){129m = coho_size;130}131else{132i = m - 1;133}134*/135i = -1;136}137}138139/* clean */140mpz_clear(&val);141free(list);142143return(aff_list);144}145146147148149150/* --------------------------------------------------------------------------- */151/* calculate all elements in the group generated by M */152/* in the cohomology group given by the second return value of cohomology */153/* the elements of M have to be in in this cohomology group */154/* return list, which number/element of the cohomology group is in our group */155/* --------------------------------------------------------------------------- */156/* M: generating system */157/* D: the second return value of cohomology */158/* anz: save the order of the group here */159/* elements: save the elements of the group (at the correct place in the */160/* cohomology group) here */161/* coho_size: size of the cohomology group */162/* --------------------------------------------------------------------------- */163int *aufspannen(int coho_size,164matrix_TYP **elements,165matrix_TYP **M,166int gen_no,167matrix_TYP *D,168int *anz)169{170int i, j, pos, /* m, */171first, last, diff,172*list;173174matrix_TYP *tmp;175176MP_INT val;177178179mpz_init(&val);180list = (int *)calloc(coho_size, sizeof(int));181list[0] = -1;182anz[0] = 1;183for (first = 0; first < D->cols && D->array.SZ[first][first] == 1; first++);184for (last = first; last < D->cols && D->array.SZ[last][last] != 0; last++);185diff = last - first;186if (elements[0] == NULL)187elements[0] = init_mat(diff, 1, "");188/* m = coho_size; */189190/* orbit algorithm */191for (i = 0; i < coho_size && anz[0] < coho_size; i++){192if (list[i] == -1){193for (j = 0; j < gen_no; j++){194tmp = add_mod_D(elements[i], M[j], D, first, diff);195valuation(tmp, D, &val);196pos = mpz_get_ui(&val);197if (list[pos] == 0){198/* new element in the orbit */199anz[0]++;200list[pos] = -1;201if (elements[pos] == NULL){202elements[pos] = tmp;203tmp = NULL;204}205}206if (tmp != NULL)207free_mat(tmp);208/*209if (list[pos] == -1){210m = min(pos, m);211}212*/213}214list[i] = 1;215/*216if (m == i){217m = coho_size;218}219else{220i = m - 1;221}222*/223i = -1;224}225}226227for (i = 0; i < coho_size; i++){228if (list[i] == -1)229list[i] = 1;230}231232/* clean */233mpz_clear(&val);234235return(list);236}237238239240/* ----------------------------------------------------------------------------- */241static void mod(int *a,242int b)243{244a[0] %= b;245if (a[0] < 0)246a[0] += b;247}248249250251/* ----------------------------------------------------------------------------- */252static int search_next(int *list,253int *ker_list,254int coho_size)255{256int i;257258if (ker_list != NULL){259for (i = 1; i < coho_size; i++){260if (ker_list[i] == 1 && list[i] == 0)261return(i);262}263}264else{265for (i = 1; i < coho_size; i++){266if (list[i] == 0)267return(i);268}269}270271return(-1);272}273274275/* ----------------------------------------------------------------------------- */276/* calculate the representation of S on H^1(...)/Ker(phi) */277/* ----------------------------------------------------------------------------- */278matrix_TYP **new_representation(matrix_TYP **S,279int S_no,280H1_mod_ker_TYP H1_mod_ker,281matrix_TYP *A)282{283int i, j, k, d, s,284erz_no, A_first;285286matrix_TYP **rep,287*tmp, *temp;288289290erz_no = H1_mod_ker.erz_no;291rep = (matrix_TYP **)calloc(S_no, sizeof(matrix_TYP *));292for (A_first = 0; A_first < A->cols && A->array.SZ[A_first][A_first] == 1; A_first++);293294for (i = 0; i < S_no; i++){295rep[i] = init_mat(erz_no, erz_no, "");296for (j = 0; j < erz_no; j++){297298/* bilde Basiselement ab mit Erzeuger von S1 */299tmp = mat_mul(S[i], H1_mod_ker.M[j]);300for (k = 0; k < tmp->rows; k++){301tmp->array.SZ[k][0] %= A->array.SZ[k + A_first][k + A_first];302if (tmp->array.SZ[k][0] < 0)303tmp->array.SZ[k][0] += A->array.SZ[k + A_first][k + A_first];304}305306/* Berechne Standardform als Element von H^1/Ker */307temp = mat_mul(H1_mod_ker.i, tmp);308free_mat(tmp);309for (k = 0; k < temp->rows; k++){310temp->array.SZ[k][0] %= H1_mod_ker.D->array.SZ[k][k];311if (temp->array.SZ[k][0] < 0)312temp->array.SZ[k][0] += H1_mod_ker.D->array.SZ[k][k];313}314315/* trage in Matrix ein */316for (k = 0; k < erz_no; k++){317rep[i]->array.SZ[k][j] = temp->array.SZ[k + H1_mod_ker.D_first][0];318}319free_mat(temp);320}321}322return(rep);323}324325326327/* ----------------------------------------------------------------------------- */328/* from the H^1/Ker representation to the H^1 representation */329/* ----------------------------------------------------------------------------- */330static matrix_TYP *back_to_H1(matrix_TYP *elem,331H1_mod_ker_TYP Hk)332{333int i;334335matrix_TYP *mat;336337rational eins, zahl;338339eins.z = eins.n = zahl.n = 1;340341342mat = copy_mat(Hk.M[0]);343for (i = 0; i < mat->rows; i++){344mat->array.SZ[i][0] *= elem->array.SZ[0][0];345}346347for (i = 1; i < Hk.erz_no; i++){348if (elem->array.SZ[i][0] != 0){349zahl.z = elem->array.SZ[i][0];350mat = mat_addeq(mat, Hk.M[i], eins, zahl);351}352}353354return(mat);355}356357358359/* ----------------------------------------------------------------------------- */360/* orbit algorithm: act with S on H^1(...)/Ker(phi) */361/* in orbit 0 is only the 0 element */362/* save WORDS for the stabilizers of ksi + Ker(phi) for a representative in */363/* each orbit */364/* start = NULL: berechne alle Orbits */365/* start != NULL: berechne nur den Orbit von start */366/* ----------------------------------------------------------------------------- */367matrix_TYP ***H1_mod_ker_orbit_alg(H1_mod_ker_TYP H1_mod_ker,368matrix_TYP **S,369int S_no,370int *anz,371int **length,372int ****WORDS,373int **WORDS_no,374matrix_TYP *start)375{376matrix_TYP *D,377*tmp,378**elem,379***rep;380381int i, j, k, /* m, */ i__,382pos, number, addmem,383*list, *smallest, **words,384coho_size, erz_no, counter = 0;385386MP_INT val, cohom_size, MP_i;387388389mpz_init(&val);390erz_no = H1_mod_ker.erz_no;391D = init_mat(erz_no, erz_no, "");392for (i = 0; i < erz_no; i++){393D->array.SZ[i][i] = H1_mod_ker.D->array.SZ[i + H1_mod_ker.D_first][i + H1_mod_ker.D_first];394}395cohom_size = cohomology_size(D);396coho_size = mpz_get_ui(&cohom_size);397elem = (matrix_TYP **)calloc(coho_size, sizeof(matrix_TYP *));398list = (int *)calloc(coho_size, sizeof(int));399length[0] = (int *)calloc(coho_size + 1, sizeof(int));400smallest = (int *)calloc(coho_size + 1, sizeof(int));401WORDS[0] = (int ***)calloc(coho_size + 1, sizeof(int **));402WORDS_no[0] = (int *)calloc(coho_size + 1, sizeof(int));403404if (start == NULL){405if (coho_size > 1)406i = 1;407else408i = -1;409anz[0] = 1;410counter = length[0][0] = 1;411smallest[0] = 0;412}413else{414anz[0] = 1;415for (k = 0; k < erz_no; k++)416mod(start->array.SZ[k], D->array.SZ[k][k]);417valuation(start, D, &val);418i = mpz_get_ui(&val);419}420421422while (i != -1){423WORDS[0][anz[0]] = (int **)calloc(1024, sizeof(int *));424words = (int **)calloc(coho_size, sizeof(int *));425list[i] = -anz[0];426smallest[anz[0]] = i;427length[0][anz[0]] = 1;428mpz_init_set_si(&MP_i, i);429elem[i] = reverse_valuation(&MP_i, D);430mpz_clear(&MP_i);431/* m = coho_size; */432for (; i < coho_size && counter < coho_size; i++){433if (list[i] == -anz[0]){434for (j = 0; j < S_no; j++){435tmp = mat_mul(S[j], elem[i]);436for (k = 0; k < erz_no; k++)437mod(tmp->array.SZ[k], D->array.SZ[k][k]);438valuation(tmp, D, &val);439pos = mpz_get_ui(&val);440441/* paranoia test */442if (list[pos] != 0 && abs(list[pos]) != anz[0]){443fprintf(stderr, "ERROR in H1_mod_ker_orbit_alg!\n");444exit(8);445}446447if (list[pos] == 0){448/* new element in the orbit */449/*words[pos] = (int *)calloc(MIN_SPEICHER, sizeof(int));*/450if (i != smallest[anz[0]]){451words[pos] = (int *)calloc(words[i][0] + 2, sizeof(int)); /*N*/452/*memcpy(words[pos], words[i], (words[i][0] + 1) * sizeof(int));*/453for (i__ = 0; i__ < words[i][0] + 1; i__++){454words[pos][i__] = words[i][i__];455}456words[pos][words[i][0] + 1] = -(j+1);457words[pos][0]++;458}459else{460words[pos] = (int *)calloc(2, sizeof(int)); /*N*/461words[pos][0] = 1;462words[pos][1] = -(j+1);463}464list[pos] = -anz[0];465counter++;466length[0][anz[0]]++;467elem[pos] = tmp;468tmp = NULL;469}470else{471/* we got this element already */472if (WORDS_no[0][anz[0]] % 1024 == 0){ /*N*/473WORDS[0][anz[0]] = (int **)realloc(WORDS[0][anz[0]],474(1024 + WORDS_no[0][anz[0]]) * sizeof(int *));475}476477/*WORDS[0][anz[0]][WORDS_no[0][anz[0]]] = (int *)calloc(MIN_SPEICHER, sizeof(int));*/478if (pos != smallest[anz[0]]){ /*N*/479addmem = words[pos][0];480}481else{482addmem = 0;483}484if (i != smallest[anz[0]]){485WORDS[0][anz[0]][WORDS_no[0][anz[0]]] = (int *)calloc(words[i][0] + 2 + addmem, sizeof(int));/*N*/486/*memcpy(WORDS[0][anz[0]][WORDS_no[0][anz[0]]], words[i], (words[i][0] + 1) * sizeof(int)); */487for (i__ = 0; i__ < words[i][0] + 1; i__++){488WORDS[0][anz[0]][WORDS_no[0][anz[0]]][i__] = words[i][i__];489}490WORDS[0][anz[0]][WORDS_no[0][anz[0]]][words[i][0] + 1] = -(j+1);491WORDS[0][anz[0]][WORDS_no[0][anz[0]]][0]++;492}493else{494WORDS[0][anz[0]][WORDS_no[0][anz[0]]] = (int *)calloc(2 + addmem, sizeof(int));/*N*/495WORDS[0][anz[0]][WORDS_no[0][anz[0]]][0] = 1;496WORDS[0][anz[0]][WORDS_no[0][anz[0]]][1] = -(j+1);497}498if (pos != smallest[anz[0]]){499number = WORDS[0][anz[0]][WORDS_no[0][anz[0]]][0] + words[pos][0];500for (k = 0; k < words[pos][0]; k++){501WORDS[0][anz[0]][WORDS_no[0][anz[0]]][number - k] = -words[pos][k + 1];502}503WORDS[0][anz[0]][WORDS_no[0][anz[0]]][0] = number;504}505WORDS_no[0][anz[0]]++;506507508free_mat(tmp);509}510/*511if (list[pos] == -anz[0]){512m = min(pos, m);513}514*/515}516list[i] = anz[0];517/*518if (m == i){519m = coho_size;520}521else{522i = m - 1;523}524*/525i = -1;526}527}528if (start == NULL){529i = search_next(list, NULL, coho_size);530}531else{532i = -1;533}534anz[0]++;535for (j = 0; j < coho_size; j++)536if (words[j] != NULL)537free(words[j]);538free(words);539}540541542/* representatives */543rep = (matrix_TYP ***)calloc(anz[0], sizeof(matrix_TYP **));544for (i = 1; i < anz[0]; i++){545rep[i] = (matrix_TYP **)calloc(length[0][i], sizeof(matrix_TYP *));546counter = 0;547for (j = 0; j < coho_size; j++){548if ((list[j] == i || list[j] == -i) && counter < length[0][i]){549rep[i][counter] = back_to_H1(elem[j], H1_mod_ker);550counter++;551}552}553}554555/* clean */556mpz_clear(&cohom_size);557mpz_clear(&val);558free_mat(D);559free(list);560free(smallest);561for (i = 1; i < coho_size; i++)562if (elem[i] != NULL)563free_mat(elem[i]);564free(elem);565566567return(rep);568}569570571/* ----------------------------------------------------------------------------- */572/* orbitalgorithm on a subgroup of H^1 */573/* ker_elements: list of elements in the subgroup */574/* H^1 is given by D, the second return value of cohomology */575/* coho_size: size of H^1 */576/* N: operating group */577/* no: number of elements in N */578/* ker_list: list, which element of the cohomology group is in the subgroup */579/* ker_order: order of the subgroup */580/* anz: save the number of orbits here */581/* length: save the length of an orbit here */582/* ----------------------------------------------------------------------------- */583/* in orbit 0 is only the 0-element */584/* ----------------------------------------------------------------------------- */585matrix_TYP **orbit_ker(matrix_TYP **ker_elements,586int ker_order,587matrix_TYP *D,588matrix_TYP **N,589int no,590int coho_size,591int *ker_list,592int *anz,593int **length)594{595int i, j, k, /* m, */ pos,596first, last, diff, counter,597ttt = 0,598*list, *smallest;599600matrix_TYP **orbit_rep,601*tmp;602603MP_INT val;604605606for (first = 0; first < D->cols && D->array.SZ[first][first] == 1; first++);607for (last = first; last < D->cols && D->array.SZ[last][last] != 0; last++);608diff = last - first;609length[0] = (int *)calloc(coho_size, sizeof(int));610anz[0] = counter = length[0][0] = 1;611for (i = 1; i < coho_size; i++){612if (ker_list[i] == 1)613break;614}615616/* only 0-element in the subgroup */617if (i == coho_size){618orbit_rep = (matrix_TYP **)calloc(1, sizeof(matrix_TYP *));619orbit_rep[0] = init_mat(diff, 1, "");620return(orbit_rep);621}622623mpz_init(&val);624list = (int *)calloc(coho_size, sizeof(int));625smallest = (int *)calloc(coho_size, sizeof(int));626627/* orbit algorithm */628while (i != -1){629list[i] = -anz[0];630smallest[anz[0]] = i;631length[0][anz[0]] = 1;632/* m = coho_size; */633for (; i < coho_size && counter < ker_order; i++){634if (list[i] == -anz[0]){635for (j = 0; j < no; j++){636tmp = mat_mul(N[j], ker_elements[i]);637for (k = first; k < last; k++)638mod(tmp->array.SZ[k-first], D->array.SZ[k][k]);639valuation(tmp, D, &val);640pos = mpz_get_ui(&val);641642/* paranoia test */643if (ker_list[pos] != 1 || (list[pos] != 0 && abs(list[pos]) != anz[0])){644fprintf(stderr, "ERROR in orbit_ker!\n");645exit(7);646}647648if (list[pos] == 0){649/* new element in the orbit */650list[pos] = -anz[0];651counter++;652length[0][anz[0]]++;653}654free_mat(tmp);655/*656if (list[pos] == -anz[0]){657m = min(pos, m);658}659*/660}661list[i] = anz[0];662/*663if (m == i){664m = coho_size;665}666else{667i = m - 1;668}669*/670i = -1;671}672}673i = search_next(list, ker_list, coho_size);674anz[0]++;675}676677/* save representatives */678orbit_rep = (matrix_TYP **)calloc(anz[0], sizeof(matrix_TYP *));679for (i = 0; i < anz[0]; i++){680orbit_rep[i] = copy_mat(ker_elements[smallest[i]]);681if (GRAPH_DEBUG)682ttt += length[0][i];683}684685if (GRAPH_DEBUG){686if (ttt != ker_order){687fprintf(stderr, "NEIN!!!!!!!!!!!!\n");688exit(5);689}690}691692/* clean */693mpz_clear(&val);694free(smallest);695free(list);696697return(orbit_rep);698}699700701702703/* ----------------------------------------------------------------------------- */704/* orbitalgorithm on a ksi + ker, where ker is a subgroup of H^1 */705/* ker_elements: list of elements in the subgroup */706/* H^1 is given by D, the second return value of cohomology */707/* coho_size: size of H^1 */708/* N: operating group (IS CHANGED !!!) */709/* no: number of elements in N */710/* ker_list: list, which element of the cohomology group is in the subgroup */711/* ker_order: order of the subgroup */712/* anz: save the number of orbits here */713/* length: save the length of an orbit here */714/* ----------------------------------------------------------------------------- */715/* in orbit 0 is only the 0-element */716/* ----------------------------------------------------------------------------- */717matrix_TYP **orbit_ksi_plus_ker(matrix_TYP *ksi,718matrix_TYP **ker_elements,719int ker_order,720matrix_TYP *D,721matrix_TYP **N,722int no,723int coho_size,724int *ker_list,725int *anz,726int **length)727{728int i, j, k, /* m, */ rows, first, last, diff, pos,729ttt = 0,730*list, *smallest, counter;731732matrix_TYP *tmp, **orbit_rep;733734rational eins, minuseins;735736MP_INT val;737738739740rows = ker_elements[0]->rows - 1;741742if (ker_order > 1){743eins.z = eins.n = minuseins.n = 1;744minuseins.z = -1;745for (first = 0; first < D->cols && D->array.SZ[first][first] == 1; first++);746for (last = first; last < D->cols && D->array.SZ[last][last] != 0; last++);747diff = last - first;748749for (i = 0; i < no; i++){750tmp = mat_mul(N[i], ksi);751mat_addeq(tmp, ksi, eins, minuseins);752for (j = 0; j < rows; j++){753tmp->array.SZ[j][0] %= D->array.SZ[j + first][j + first];754if (tmp->array.SZ[j][0] < 0){755tmp->array.SZ[j][0] += D->array.SZ[j + first][j + first];756}757}758real_mat(N[i], rows + 1, rows);759real_mat(N[i], rows + 1, rows + 1);760N[i]->array.SZ[rows][rows] = 1;761for (j = 0; j < rows; j++){762N[i]->array.SZ[j][rows] = tmp->array.SZ[j][0];763}764free_mat(tmp);765}766767mpz_init(&val);768list = (int *)calloc(coho_size, sizeof(int));769smallest = (int *)calloc(coho_size, sizeof(int));770length[0] = (int *)calloc(coho_size, sizeof(int));771counter = anz[0] = 1;772i = 0;773774/* orbit algorithm */775while (i != -1){776list[i] = -anz[0];777smallest[anz[0] - 1] = i;778length[0][anz[0] - 1] = 1;779/* m = coho_size; */780for (; i < coho_size && counter < ker_order; i++){781if (list[i] == -anz[0]){782for (j = 0; j < no; j++){783tmp = mat_mul(N[j], ker_elements[i]);784for (k = first; k < last; k++)785mod(tmp->array.SZ[k-first], D->array.SZ[k][k]);786valuation(tmp, D, &val);787pos = mpz_get_ui(&val);788789/* paranoia test */790if (ker_list[pos] != 1 || (list[pos] != 0 && abs(list[pos]) != anz[0])){791fprintf(stderr, "ERROR in orbit_ksi_plus_ker!\n");792exit(7);793}794795if (list[pos] == 0){796/* new element in the orbit */797list[pos] = -anz[0];798counter++;799length[0][anz[0] - 1]++;800}801free_mat(tmp);802/*803if (list[pos] == -anz[0]){804m = min(pos, m);805}806*/807}808list[i] = anz[0];809/*810if (m == i){811m = coho_size;812}813else{814i = m - 1;815}816*/817i = -1;818}819}820i = search_next(list, ker_list, coho_size);821anz[0]++;822}823824/* save representatives */825anz[0]--;826orbit_rep = (matrix_TYP **)calloc(anz[0], sizeof(matrix_TYP *));827for (i = 0; i < anz[0]; i++){828orbit_rep[i] = copy_mat(ker_elements[smallest[i]]);829real_mat(orbit_rep[i], rows, 1);830if (GRAPH_DEBUG){831ttt += length[0][i];832}833}834835if (GRAPH_DEBUG){836if (ttt != ker_order){837fprintf(stderr, "NEIN!!!!!!!!!!!!\n");838exit(5);839}840}841842/* clean */843mpz_clear(&val);844free(smallest);845free(list);846}847else{848/* trivial part */849length[0] = (int *)calloc(1, sizeof(int));850length[0][0] = anz[0] = 1;851orbit_rep = (matrix_TYP **)calloc(1, sizeof(matrix_TYP *));852orbit_rep[0] = init_mat(rows, 1, "");853}854855return(orbit_rep);856}857858859860/* -------------------------------------------------------------------- */861static int search_pos(matrix_TYP *mat, matrix_TYP **menge, int anz)862{863int i;864865for (i = 0; i < anz; i++){866if (cmp_mat(mat, menge[i]) == 0)867return(i);868}869return(-1);870}871872873874/* -------------------------------------------------------------------- */875/* orbit_on_lattices */876/* Let R be a (affine) space group and P its pointgroup. */877/* Calculation of the orbits of the P-invariant max. sublattices or min.*/878/* superlattices (saved in gitter) under the operation of the linear */879/* part of the affine normalizer of R. */880/* return number of orbits */881/* -------------------------------------------------------------------- */882/* gitter: lattices in normal form */883/* gitter_no: number of lattices (>= 1 !!!) */884/* N: affine_normalizer of R (linear part) */885/* N_no: number of generators of the normalizer */886/* list: list, which lattice is in which orbit */887/* length: list with the lengthes of the orbits */888/* smallest: for each orbit, lowest number of the elements in it */889/* conj: if conj, save conjugating matrices here */890/* -------------------------------------------------------------------- */891int orbit_on_lattices(matrix_TYP **gitter,892int gitter_no,893matrix_TYP **N,894int N_no,895int *list,896int *length,897int *smallest,898matrix_TYP **conj)899{900int i, j, m, pos, counter, anz, dim;901902matrix_TYP *tmp;903904905dim = gitter[0]->rows;906anz = i = counter = 0;907908/* orbit algorithm */909while (i != -1){910anz++;911counter++;912list[i] = -anz;913if (conj)914conj[i] = init_mat(dim, dim, "1");915length[anz] = 1;916smallest[anz] = i;917for (; i < gitter_no && counter < gitter_no; i++){918if (list[i] == -anz){919m = gitter_no;920for (j = 0; j < N_no; j++){921tmp = mat_mul(N[j], gitter[i]);922long_col_hnf(tmp);923pos = search_pos(tmp, gitter, gitter_no);924925/* paranoia test */926if (pos == -1 || (list[pos] != 0 && abs(list[pos]) != anz)){927fprintf(stderr, "ERROR in operiere_gitter!\n");928exit(7);929}930931if (list[pos] == 0){932/* new element in the orbit */933list[pos] = -anz;934counter++;935length[anz]++;936if (conj){937conj[pos] = mat_mul(N[j], conj[i]);938}939}940free_mat(tmp);941if (list[pos] == -anz){942m = min(pos, m);943}944}945list[i] = anz;946i = m - 1;947}948}949i = search_next(list, NULL, gitter_no);950}951952for (i = 0; i < gitter_no; i++){953if (list[i] < 0) list[i] *= (-1);954}955956return(anz);957}958959960961/* -------------------------------------------------------------------- */962static matrix_TYP *add_mod_lattice(matrix_TYP *A,963matrix_TYP *B,964matrix_TYP *D,965matrix_TYP *Ti,966matrix_TYP *T,967int dim,968int erz_no)969{970int i, j;971972rational eins;973974matrix_TYP *C, *tmp, *tmp2;975976977eins.z = eins.n = 1;978979C = mat_add(A, B, eins, eins);980tmp = mat_mul(Ti, C);981for (i = 0; i < erz_no; i++){982for (j = 0; j < dim; j++){983tmp->array.SZ[i * dim + j][0] %= D->array.SZ[j][j];984if (tmp->array.SZ[i * dim + j][0] < 0)985tmp->array.SZ[i * dim + j][0] += D->array.SZ[j][j];986}987}988989tmp2 = mat_mul(T, tmp);990free_mat(tmp);991free_mat(C);992return(tmp2);993}994995996997/* -------------------------------------------------------------------- */998/* calculate information about Ker phi | B^1 */999/* -------------------------------------------------------------------- */1000matrix_TYP **kernel_factor_fct(matrix_TYP **translationen,1001int translanz,1002int erz_no,1003matrix_TYP *lattice,1004int *anz)1005{1006int i, j, dim, pos, size = 1024;10071008matrix_TYP *tmp, **elem, *D, *R, *Li, *Li_d, *L_d, *L;100910101011anz[0] = 1;1012dim = lattice->rows;1013elem = (matrix_TYP **)calloc(size, sizeof(matrix_TYP *));1014elem[0] = init_mat(erz_no * dim, 1, "");1015L = init_mat(dim, dim, "1");1016R = init_mat(dim, dim, "1");1017D = long_elt_mat(L, lattice, R);1018Li = mat_inv(L);1019L_d = matrix_on_diagonal(L, erz_no);1020Li_d = matrix_on_diagonal(Li, erz_no);10211022for (i = 0; i < anz[0]; i++){1023for (j = 0; j < translanz; j++){1024tmp = add_mod_lattice(elem[i], translationen[j], D, L_d, Li_d, dim, erz_no);1025pos = search_pos(tmp, elem, anz[0]);1026if (pos == -1){1027if (anz[0] >= size){1028size += 1024;1029elem = realloc(elem, size * sizeof(matrix_TYP *));1030}1031elem[anz[0]] = tmp;1032tmp = NULL;1033anz[0]++;1034}1035else{1036free_mat(tmp);1037}1038}1039}10401041/* clean */1042free_mat(D);1043free_mat(R);1044free_mat(L);1045free_mat(Li);1046free_mat(L_d);1047free_mat(Li_d);10481049return(elem);1050}105110521053105410551056105710581059106010611062106310641065