GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#include <signal.h>1#include <stdlib.h>2#include "typedef.h"3#include "voronoi.h"4#include "matrix.h"5#include "tools.h"6#include "ZZ_P.h"7#include "ZZ_cen_fun_P.h"8#include "ZZ_zclass_P.h"9#include "ZZ.h"10#include "longtools.h"1112boolean QUIET = FALSE, TEMPORAER = FALSE, SHORTLIST = FALSE, NURUMF = FALSE,13U_option = TRUE, G_option = TRUE, LLLREDUCED = FALSE;1415int ZCLASS;16extern int *SUB_VEC;17extern matrix_TYP **PrI;1819int COUNTER = 0;20int NUMBER = 1000, SUBDIRECT = FALSE, LEVEL = 500; /*Default-Werte der maximalen Anzahl der berechneten21Zentrierungen bzw. Anzahl der Level */22FILE *ZZ_temp, *ZZ_list;23int MAT_ALLOC = 0;24int constituents = 0;25int verbose = 0;26//changed 09-03-2008: these varaibles are not extern27//extern ZZ_super_TYP **SUPER_info, *SUPER_INFO;28ZZ_super_TYP **SUPER_info, *SUPER_INFO;293031/*------------------------------------------------------------------------------- */32static int suche_mat(matrix_TYP *mat,33matrix_TYP **liste,34int anz)35{36int i;3738for (i = 0; i < anz; i++){39if (cmp_mat(mat, liste[i]) == 0)40return(i);41}42return(-1);43}444546/*------------------------------------------------------------------------------- */47void ZZ_intern (Gram, data, tree, inzidenz)48matrix_TYP *Gram;49ZZ_data_t *data;50ZZ_tree_t *tree;51QtoZ_TYP *inzidenz;52{53ZZ_node_t *act, *new, *nnn;54int g, i, j, k, l, m, n, d, di, end_num, act_anz, flag, nr, NEU, zahl, flagge;55int ABBRUCH = FALSE;56matrix_TYP *gitter, *tmp, *X, *Li;575859act = tree->root;60do {61if (ZCLASS == 1 && GRAPH){62flag = suche_mat(act->U, inzidenz->gitter, inzidenz->anz);63if (flag == -1 && inzidenz->anz != 0){64/* Das aktuelle Gitter kommt nicht vor in der Liste */65fprintf(stderr,"ERROR 1 in ZZ_intern\n");66exit(2);67}68if (flag == -1 && inzidenz->anz == 0){69/* insert start-lattice */70inzidenz->anz++;71inzidenz->gitter[0] = copy_mat(act->U);72inzidenz->tr_gitter[0] = tr_pose(inzidenz->gitter[0]);73inzidenz->inv_tr_gitter[0] = mat_inv(inzidenz->tr_gitter[0]);74inzidenz->entry[0] = (QtoZ_entry_TYP *)calloc(1024, sizeof(QtoZ_entry_TYP));75flag = 0;76}77}78for (i = 0; i < data->p_consts.k; i++) {79for (j = 0; j < data->p_consts.s[i]; j++) {80d = ZZ_epimorphs (data, i, j);81di = d;82end_num = data->EnCo[i][j].hi + 1;83if (d != 0) {84act_anz = 0;85for (k = 1; d > 0; d--, k *= end_num) {86for (n = k; n < 2 * k; n++) {87act_anz++;88ZZ_pick_epi (data, n, i, j);89new = ZZ_center (data, act, i, j);90nr = 0;91NEU = 0;9293if (ZCLASS == 1 && GRAPH){94gitter = tr_pose(new->U);95}96flagge = 0;97ABBRUCH = ZZ_ins_node (Gram, data, tree,98act, new, i, j,99inzidenz, &nr, &NEU, &flagge, &g, &nnn);100if (ZCLASS == 1 && GRAPH){101if (NEU != 1){102/* not a new lattice for the graph or lattice in another zoo */103if (nr == -1){104/* lattice possibly in another zoo */105zahl = inzidenz->entry[flag][0].anz;106if (zahl == 0){107inzidenz->entry[flag][0].I = (int *)calloc(1024,108sizeof(int));109inzidenz->entry[flag][0].J = (int *)calloc(1024,110sizeof(int));111inzidenz->entry[flag][0].flag = (int *)calloc(1024,112sizeof(int));113inzidenz->entry[flag][0].lattice = (matrix_TYP114**)calloc(1024, sizeof(matrix_TYP *));115inzidenz->zoogitter[flag] = (matrix_TYP **)calloc(1024,116sizeof(matrix_TYP *));117}118inzidenz->entry[flag][0].I[zahl] = i;119inzidenz->entry[flag][0].J[zahl] = j;120inzidenz->entry[flag][0].flag[zahl] = -10;121inzidenz->zoogitter[flag][zahl] = gitter;122123/* This isn't the correct conjugating matrix yet! */124inzidenz->entry[flag][0].lattice[zahl] =125copy_mat(inzidenz->inv_tr_gitter[flag]);126gitter = NULL;127inzidenz->entry[flag][0].anz++;128}129else{130/* not a new lattice */131nr++;132zahl = inzidenz->entry[flag][nr].anz;133if (zahl == 0){134inzidenz->entry[flag][nr].I = (int *)calloc(1024,135sizeof(int));136inzidenz->entry[flag][nr].J = (int *)calloc(1024,137sizeof(int));138inzidenz->entry[flag][nr].flag = (int *)calloc(1024,139sizeof(int));140inzidenz->entry[flag][nr].lattice = (matrix_TYP141**)calloc(1024, sizeof(matrix_TYP *));142}143inzidenz->entry[flag][nr].I[zahl] = i;144inzidenz->entry[flag][nr].J[zahl] = j;145inzidenz->entry[flag][nr].flag[zahl] = flagge;146inzidenz->entry[flag][nr].anz++;147148switch (flagge){149case 1:150/*151inzidenz->entry[flag][nr].lattice[zahl] =152mat_mul(inzidenz->inv_tr_gitter[flag],153inzidenz->tr_gitter[nr - 1]);154fprintf(stderr, "F A L L 1!!!!!!!!!!!!!\n");155break;156*/157case 100:158inzidenz->entry[flag][nr].lattice[zahl] =159mat_mul(inzidenz->inv_tr_gitter[flag],160inzidenz->tr_gitter[nr - 1]);161for (l = 0; l < gitter->rows; l++){162for (m = 0; m < gitter->cols; m++){163inzidenz->entry[flag][nr].lattice[zahl]->array.SZ[l][m]164*= g;165}166}167break;168169case 10:170Li = mat_inv(gitter);171X = konjugierende(Li, tree->root->col_group, nnn);172free_mat(Li);173if (X == NULL){174fprintf(stderr, "ERROR 2 in ZZ_intern!\n");175exit(9);176}177inzidenz->entry[flag][nr].lattice[zahl] =178mat_mul(inzidenz->inv_tr_gitter[flag], gitter);179mat_muleq(inzidenz->entry[flag][nr].lattice[zahl], X);180free_mat(X);181break;182}183}184}185else{186/* new lattice in the graph */187inzidenz->gitter[inzidenz->anz] = copy_mat(new->U);188inzidenz->tr_gitter[inzidenz->anz] = tr_pose(new->U);189inzidenz->inv_tr_gitter[inzidenz->anz] =190mat_inv(inzidenz->tr_gitter[inzidenz->anz]);191inzidenz->entry[inzidenz->anz] = (QtoZ_entry_TYP *)calloc(1024,192sizeof(QtoZ_entry_TYP));193inzidenz->anz++;194inzidenz->entry[flag][inzidenz->anz].anz = 1;195inzidenz->entry[flag][inzidenz->anz].I = (int *)calloc(1024,196sizeof(int));197inzidenz->entry[flag][inzidenz->anz].J = (int *)calloc(1024,198sizeof(int));199inzidenz->entry[flag][inzidenz->anz].flag = (int *)calloc(1024,200sizeof(int));201inzidenz->entry[flag][inzidenz->anz].lattice = (matrix_TYP202**)calloc(1024, sizeof(matrix_TYP *));203inzidenz->entry[flag][inzidenz->anz].I[0] = i;204inzidenz->entry[flag][inzidenz->anz].J[0] = j;205inzidenz->entry[flag][inzidenz->anz].flag[0] = 0;206inzidenz->entry[flag][inzidenz->anz].lattice[0] =207mat_mul(inzidenz->inv_tr_gitter[flag],208inzidenz->tr_gitter[inzidenz->anz - 1]);209}210if (gitter != NULL)211free_mat(gitter);212}213}214}215act->anz_tg = act_anz;216217for (k = 0; k < di; k++) {218free_mat (data->epi_base[k]);219}220free (data->epi_base);221data->epi_base = NULL;222}223}224}225} while ((!ABBRUCH) && (ZZ_successor (data, &act)));226ZZ_fput_data (data, tree, ABBRUCH);227nnn = NULL;228}229230231232233/******************************************************************************/234void ZZ_transpose_array (int **array, int size)235{236int i, j, ZZ_swap;237238for (i = 0; i < size; i++) {239for (j = i + 1; j < size; j++) {240ZZ_swap = array[i][j];241array[i][j] = array[j][i];242array[j][i] = ZZ_swap;243}244}245}246247/******************************************************************************248@249@ (void)ZZ( group, gram, divisors, options );250@251@ or252@253@ (void)ZZ( group, gram, divisors, options, num_sublattices, dim1, dim2, ... )254@255@ bravais_TYP *group;256@ matrix_TYP *gram;257@ int *divisors;258@ char *options;259@ int num_sublattices, dim1, ...260@261@ group: bravais group, the algorithm applies the ZZ-algorithm with regard262@ to the prime-divisors of the order of the group.263@ gram: a gram matrix of a quadratic form that is invariant under the group264@ This form must be totally anisotropic.265@ divisors: an array of integers that REALLY MUST HAVE 100 (ONEHUNDRET)266@ entries. The index of the array specifies the prime number and the267@ contents of the array the multiplicity of the prime as divisor of268@ the group order. The ZZ function does not need the multiplicity269@ it just uses a subset of the prime divisors of the group order270@ to compute irreducible constituents of the matrix representation271@ of the group modulo those primes. Thus it is all right to set272@ the entries of the array to some non-zero number, e. g. if one273@ wants to compute the irreducible constituents modulo 2 and274@ modulo 5, then one has to write275@276@ divisors[2] = 1; divisors[5] = 1;277@278@ All other entries must be set to zero. (at least those that belong279@ to prime number indices).280@281@ If one simply wants to compute the irreducible constituents for282@ all divisors of the group order, it suffices to specify the283@ value NULL for the argument divisors.284@285@ options: a string of characters, (i.e. "n30l24rq"), supported are:286@ num_sublattices, dim1, ... : see option "p". Must only be specified if the287@ option "p" was specified288@289@ "n#": terminate after computation of "#" centerings290@ "l#": terminate afer "#" iterations of the algorithm291@ "r" : use the "lll"-algorithm on the Z-bases of the centerings292@ "q" : "quit-mode" - suppress messages on stdout/stderr293@ "v" : "verbose-mode" - opposite of "q"294@ "t" : create a file in the current directory that295@ contains additional information. See also options "ugsb"296@ This feature is on by default and the file name defaults297@ to ZZ.tmp. If this option is given the argument298@ "none", then no output file is created.299@ "u" : computes elementary divisors of the matrices that contain300@ the bases of the invariant sublattices (i.e. of301@ group->zentr[i]) and writes them to the302@ outputfile.303@ "g" : computes the elementary divisors of the gram-matrices of304@ the invariant sublattices and writes them to the output file.305@ Implies option "t".306@ "s" : "shortlist" - prints in short form the messages that are307@ suppressed by "q". Independent of "q" option308@ "b" : "print change of base only" -- suppresses the output of309@ the gram-matrices and elementary devisors to the output file.310@ "p" : "projections" -- compute only thos sublattices, that have311@ surjective projections on a given number of sublattices312@ with a given dimension. The number of the sublattices is313@ given by the first argument after "options", that is, by314@ "num_sublattices". The dimension of the first sublattice315@ is given by "dim1", the second by the argument "dim2" etc316@317@ NOTE: the number of the "dim#" arguments MUST match the318@ "num_sublattices"319@320@ Given this information, the algorithm devides the original321@ lattice in sublattices that are spanned by322@ <e_1, ..., e_dim1>,323@ <e_(dim1+1), ..., e_(dim1+dim2)>, etc324@325@ The computed centerings are stored in "group->zentr" as Z-bases326@ (matrix_TYP **zentr). The number of centerings is stored in327@ "group->zentr_no".328@329@ The functions exits by calling exit() in case of an error of if330@ the parameters are inconsistent.331@332@ NOTE: the bravais group is supposed to operate on a lattice of column333@ vectors. "SPALTENKONVENTION"334@335@ TODO:336@ write more documentation.337@338******************************************************************************/339340static void scan_options (char *options, int *projections, FILE *outputfile)341{342char *optp, *help;343int num_proj;344char *temp_name = "ZZ.tmp";345346SHORTLIST = FALSE;347ZCLASS = 0;348NURUMF = FALSE; /* only write the matrices of change of base to the349* file "ZZ.tmp", i.e. the Z-bases of the invariant350* sublattices.351*/352/*353* Default-Werte der maximalen Anzahl der berechneten354* Zentrierungen bzw. Anzahl der Level355*/356NUMBER = 1000;357LEVEL = 500;358LLLREDUCED = FALSE; /* so what? */359TEMPORAER = TRUE; /* schreibt einige Information ueber die gefundenen360* Zentrierungen in die Datei "ZZ.tmp"361*/362ZZ_temp = NULL;363QUIET = FALSE; /* make less noise */364SUBDIRECT = FALSE; /* berechnet nur solche Untergitter deren365* Projektionen auf bestimmte Teilgitter surjektiv366* sind367*/368U_option = TRUE; /* berechnet Elementarteiler der Basen der369* inv. TG370*/371G_option = TRUE; /* berechnet Elementarteiler der Grammatrizen */372373if ((optp = strchr (options, (int) 'l')) != NULL) {374LEVEL = atoi (optp + 1);375}376if ((optp = strchr (options, (int) 'n')) != NULL) {377NUMBER = atoi (optp + 1);378}379if ((optp = strchr (options, (int) 'r')) != NULL) {380LLLREDUCED = TRUE;381}382if ((optp = strchr (options, (int) 'q')) != NULL) {383QUIET = TRUE;384}385if ((optp = strchr (options, (int) 'v')) != NULL) {386QUIET = FALSE;387}388if ((optp = strchr (options, (int) 'p')) != NULL) {389SUBDIRECT = TRUE;390projections[0] = atoi (optp + 1);391if (projections[0] == 0) {392fprintf (stderr, "\"p\" option requires number of sublattices and their dimensions to be given.\n");393exit (3);394} else if (projections[0] > 8) {395fprintf (stderr, "Maximal dimension is 8\n");396exit(3);397} else {398#if DEBUG399printf ("%d\n", projections[0]);400#endif401help = optp + 1;402for (num_proj = 1;403num_proj <= projections[0];404num_proj++){405if ((help = strchr (help, '/')) != NULL) {406help++;407projections[num_proj] = atoi (help);408if (projections[num_proj] == 0) {409fprintf (stderr, "\"p\" option requires number of sublattices and their dimensions to be given.\n");410exit (3);411}412} else {413fprintf (stderr, "\"p\" option requires number of sublattices and their dimensions to be given.\n");414exit (3);415}416}417}418}419if ((optp = strchr (options, (int) 't')) != NULL) {420if (outputfile == NULL) {421TEMPORAER = FALSE;422} else {423TEMPORAER = TRUE;424ZZ_temp = outputfile;425}426}427if ((optp = strchr (options, (int) 'u')) != NULL) {428U_option = FALSE;429}430if ((optp = strchr (options, (int) 'z')) != NULL) {431ZCLASS = 1;432}433if ((optp = strchr (options, (int) 'Z')) != NULL) {434ZCLASS = 2;435}436if ((optp = strchr (options, (int) 'g')) != NULL) {437G_option = FALSE;438}439if ((optp = strchr (options, (int) 's')) != NULL) {440SHORTLIST = TRUE;441}442if ((optp = strchr (options, (int) 'b')) != NULL) {443NURUMF = TRUE;444}445if (U_option || G_option || NURUMF) {446TEMPORAER = TRUE;447}448/*449* globale Abbruchvariable450*/451COUNTER = 0; /* Anzahl der Zentrierungen */452if (TEMPORAER && ZZ_temp == NULL) {453if ((ZZ_temp = fopen (temp_name, "w+")) == NULL) {454fprintf (stderr, "ZZ: scan_arg: Error, could not open temporary file \n");455TEMPORAER = FALSE;456}457}458}459460void *ZZ(group, gram, divisors, inzidenz, options, outputfile, super_nr, konst_flag)461bravais_TYP *group;462matrix_TYP *gram;463int *divisors;464QtoZ_TYP *inzidenz;465char *options;466FILE *outputfile;467int super_nr;468int konst_flag;469{470ZZ_data_t *data;471ZZ_tree_t *tree;472int i, result = 0;473matrix_TYP *sylv, *help;474int projections[9];475QtoZ_konst_TYP *data_neu;476ZZ_node_t *n, *t;477ZZ_super_TYP *DATEN;478479/* zuerst wird getestet, ob alle noetigen Daten vorhanden sind. */480if (group == NULL) {481printf("ZZ: Error: no bravais group specified.\n");482exit(3);483}484if (gram == NULL) {485printf("ZZ: Error: no gram matrix specified.\n");486exit(3);487}488sylv = dsylv(gram);489for (i=0;i <sylv->rows;i++) {490if (sylv->array.SZ[i][i] <= 0) {491fput_mat( stderr, gram, "Gram", 0);492free_mat(sylv);493printf("ZZ: Error: gram matrix not positiv definite");494exit(3);495}496}497free_mat(sylv);498if (divisors == NULL) {499divisors = group->divisors;500}501result = 0;502for (i = 1; i < 100 && result == 0; i++) {503if (divisors[i] != 0) {504#if DEBUG505printf("divisors[%d] = %d\n", i, divisors[i]);506#endif507result = divisors[i];508}509}510if (result == 0) {511printf("ZZ: Error: prime divisors not specified.\n");512exit(3);513}514if (group->gen_no == 0) {515printf("ZZ: Error: bravais group with unknown number of generators?\n");516exit(3);517}518if (group->gen == NULL) {519printf("ZZ: Error: bravais group without generators?\n");520exit(3);521}522scan_options (options, projections, outputfile);523for (i = 0; i < group->gen_no; i++) {524ZZ_transpose_array(group->gen[i]->array.SZ,525group->gen[i]->cols);526}527/* Now check whether the gram matrix is really invariant under the528* group529*530* NOTE: scal_pr() is a ROW scalar product.531532for (i = 0; i < group->gen_no ; i++) {533int check;534535help = scal_pr(group->gen[i], gram, TRUE);536check = cmp_mat(help, gram);537free_mat(help);538if (check != 0) {539fput_mat( stdout, gram, "form", 0);540printf("i: %d\n", i);541printf("The gram matrix isn't invariant under the group.\n");542exit(3);543}544} */545546547data = (ZZ_data_t *)calloc(1, sizeof(ZZ_data_t));548tree = (ZZ_tree_t *)calloc(1, sizeof(ZZ_tree_t));549550ZZ_get_data (group, gram, divisors, data, tree, projections, konst_flag);551ZZ_intern (gram, data, tree, inzidenz);552ZZ_put_data (group, data, tree);553554if (!GRAPH){555/* free tree and data */556n = tree->root;557do {558t = n->next;559ZZ_free_node (data, n);560} while ((n = t) != NULL);561ZZ_free_data(data);562free(data);563free(tree);564}565else{566DATEN = (ZZ_super_TYP *)calloc(1,sizeof(ZZ_super_TYP));567if (SUBDIRECT) {568if (PrI) {569for (i = 0; i < SUBDIRECT; i++) {570if (PrI[i]) {571free_mat (PrI[i]);572}573}574free (PrI);575PrI = NULL;576}577if (SUB_VEC) {578free (SUB_VEC);579SUB_VEC = NULL;580}581}582DATEN->tree = tree;583DATEN->data = data;584}585586for (i = 0; i < group->zentr_no; i++) {587ZZ_transpose_array(group->zentr[i]->array.SZ,588group->zentr[i]->cols);589}590for (i = 0; i < group->gen_no; i++) {591ZZ_transpose_array (group->gen[i]->array.SZ,592group->gen[i]->cols);593}594595596if (ZCLASS == 2 && GRAPH){597SUPER_INFO = DATEN;598}599if (ZCLASS == 1 && GRAPH){600SUPER_info[super_nr] = DATEN;601}602}603604605606607608609610611612613614615616617618