GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#include "typedef.h"1#include "matrix.h"2#include "tools.h"34/**************************************************************************\5@---------------------------------------------------------------------------6@---------------------------------------------------------------------------7@ FILE: construct_mat.c8@---------------------------------------------------------------------------9@---------------------------------------------------------------------------10@11\**************************************************************************/12/*13|14| matrices/construct.c -- Funktionen, die Matrizen erzeugen15|16|17| exportiert die Funktionen18|19| init_mat20| copy_mat21| free_mat22| Check_mat23|24| importiert die Funktionen25| GGT, calloc2dim, malloc2dim, memcpy2dim, free2dim26| importiert die Variable27| act_prime28|29*/3031extern int GGT (int, int);32extern int act_prime;3334/*{{{}}}*/35/*{{{ init_mat*/36/*{{{ Documentation*/37/*38@39@ void init_mat( cols, rows, Optionen );40@ generaates a matrix with the options described below41| Erzeugt eine Matrix gemaess der uebergebenen Parameter, s.u.42@43@ Args:44@ int cols, int rows -- number of rows and columns45@ char *Optionen -- String consistin of numbers and letters 'c', 'e', 'd',46@ 's', 'r', 'p'47| Die Bedeutung der einzelnen Optionen:48@ Explanation of the options:49@50@ Options51@ ==========================================================================52@ 's' : symmetric matrix | mat->flags.Symmetric=153@ --------------------------------------------------------------------------54@ 'd' : diagonal matrix, implies 's' | mat->flags.Diagonal=155@ | mat->flags.Symmetric=156@ --------------------------------------------------------------------------57@ 'c', 'e': scalar matrix, implies 'd' und 's' | mat->flags.Scalar=158@ | mat->flags.Diagonal=159@ | mat->flags.Symmetric=160@ --------------------------------------------------------------------------61@ numerical letter from 0 .. 9. | mat->flags.Scalar=162@ The same as 'c' and 'e', but the matrix | mat->flags.Diagonal=163@ is initialized with the number | mat->flags.Symmetric=164@ --------------------------------------------------------------------------65@ 'p' : Matrix over GF(p) | mat->flags.Integral= 166@ | mat->prime= act_prime (glob. Variable)67@ | mat->array.N= NULL68@ --------------------------------------------------------------------------69@ 'r': rational matrix, | mat->flags.Integral= 070@ | mat->array.N= malloc( was auch immer );71@72| falls 'r' und 'p' gleichzeitig gesetzt werden, so hat 'p' Vorrang.73| mat->flags.Integral ist immer gesetzt, es sei denn, 'r' waere74| angegeben worden oder mat->kgv != 175@ if 'r' and 'p' are used at the same time, 'p' has priority76@77| mat->kgv wird bei einer Bruchmatrix als Hauptnenner aller Eintraege78| benutzt. Bei einer Matrix ueber Z ist mat->kgv= 1. Falls mat->kgv != 1,79| so ist mat->array.N = NULL.80@ mat->kgv is used by a rational matrix a least common divisor81@ over the denomonatop of all entries. An integral matrix has mat->kgv = 1.82@ If mat->kgv != 1 then mat->array.N = NULL.83@84| Nullmatrizen werden nicht besonders gekennzeichnet. Das verschwendet85| zwar Rechenzeit, ist aber Programmtechnisch weniger aufwendig.86| Insgesamt sollte bei 6x6 Matrizen die Performance nicht allzusehr87| leiden.88@ Zero matrices have no extra labeling89@90| Wichtig: falls im Optionen-String keine Zahlen vorkommen, so erzeugt91| init_mat() eine Nullmatrix, alle Eintraege sind also mit '0' initialisiert92@ if no numerical numbers are conatained in the string, all entries93@ of the matrix are initialized with 0.94@95*/96/*}}} */97/*{{{ Source-Code*/98matrix_TYP *init_mat(rows, cols, option)99int cols, rows;100char *option;101{102int i;103matrix_TYP *mat;104int val;105char *temp;106char *tempN;107108mat = NULL;109mat = (matrix_TYP *)malloc(sizeof(matrix_TYP));110111/*{{{ parse the options*/112if (strpbrk(option,"pP") != NULL)113{114mat->prime = act_prime; /* ist auf -1 gesetzt vor dem ersten Aufruf von */115/* init_prime(). */116mat->flags.Integral = 1;117}118else119{120mat->prime= 0;121mat->flags.Integral = strpbrk(option, "rR") == NULL ? TRUE: FALSE;122}123/* changed tilman 29/07/97 to cope with negative integers from124if ( (strpbrk(option, "cC") != NULL) || (strpbrk(option, "eE") != NULL)125|| ( (temp = strpbrk(option, "0123456789")) != NULL )126) to : */127if ( (strpbrk(option, "cC") != NULL) || (strpbrk(option, "eE") != NULL)128|| ( (temp = strpbrk(option, "-0123456789")) != NULL )129)130{131mat->flags.Scalar=132mat->flags.Diagonal=133mat->flags.Symmetric= TRUE;134}135else136{137mat->flags.Scalar= FALSE;138if ( strpbrk(option, "dD") != NULL )139{140mat->flags.Diagonal=141mat->flags.Symmetric= TRUE;142}143else144{145mat->flags.Diagonal= FALSE;146mat->flags.Symmetric = strpbrk(option, "sS") != NULL ? TRUE: FALSE;147}148}149if ( ( tempN = strpbrk(option, "/")) != NULL ) {150if ( ( tempN = strpbrk(tempN, "0123456789")) != NULL ) {151mat->flags.Integral = FALSE;152}153}154/*}}} */155156mat->kgv= 1;157mat->cols = cols;158mat->rows = rows;159160/*{{{ alloc SZ (is always done)*/161mat->array.SZ= (int **) calloc2dim( rows, cols, sizeof(int) );162if(temp != NULL)163{164sscanf(temp,"%d", &val);165for(i = 0; i < rows; i++) mat->array.SZ[i][i] = val;166}167/*}}} */168if ( !mat->flags.Integral )169{170if (tempN != NULL) {171sscanf(tempN,"%d", &val);172} else {173val = 1;174}175mat->array.N= (int **) calloc2dim( rows, cols, sizeof(int) );176memset2dim( (char **)mat->array.N,rows,cols,sizeof(int), (char *)&val);177}178else179mat->array.N = NULL;180181return(mat);182}183184/*}}} */185/*}}} */186/*{{{ copy_mat*/187/*188@-----------------------------------------------------------------189@ matrix_TYP *copy_mat( matrix_TYP *old );190@191| kopiert die Matrix "old", Rueckgabewert ist die Kopie192@ copies the matrix 'old' and returns the copy.193@-----------------------------------------------------------------194*/195196matrix_TYP *copy_mat( old )197matrix_TYP *old;198{199matrix_TYP *new= NULL;200201if ( old )202{203new= (matrix_TYP *)malloc( sizeof(matrix_TYP));204if ( new )205{206memcpy( (char *)new, (char *)old, sizeof(matrix_TYP) );207if ( new->array.SZ )208{209new->array.SZ= (int **)malloc2dim( old->rows, old->cols, sizeof(int) );210memcpy2dim( (char **)new->array.SZ, (char **)old->array.SZ,211old->rows, old->cols, sizeof(int) );212}213if ( new->array.N )214{215new->array.N= (int **)malloc2dim( old->rows, old->cols, sizeof(int) );216memcpy2dim( (char **)new->array.N,(char **)old->array.N,217old->rows, old->cols, sizeof(int) );218}219}220}221return new;222}223224/*}}} */225/*{{{ free_mat*/226/*227@--------------------------------------------------------------228@ void free_mat ( mat )229@ matrix_TYP *mat;230| -- gibt den Speicher frei, den mat benutzt231@232@ clear the storage allocated for mat233@--------------------------------------------------------------234*/235236void free_mat (mat)237matrix_TYP *mat;238{239240if ( mat->array.N )241free2dim( (char **)mat->array.N, mat->rows);242if ( mat->array.SZ )243free2dim( (char **)mat->array.SZ, mat->rows);244free( (int *)mat );245246}247248/*}}} */249/*{{{ Check_mat*/250/*251@--------------------------------------------------------------252@ void Check_mat( mat )253@ matrix_TYP *mat;254@255| Ueberprueft die mat->flags und korrigiert diese ggf. Kuerzt256| Bruchmatrizen (sowohl matrix->array.N als auch mat->kgv )257| Normiert die Darstellung modulo mat->prime, so dass 0 <= Eintrag < prime258@ Checks mat->flags and corrects it if necessary.259@ Reduces rational matrices (mat->array.N and also mat->kgv)260@ Normalizes modulo mat->prime, such that 0<= entry < prime.261@--------------------------------------------------------------262*/263264void Check_mat(mat)265matrix_TYP *mat;266{267int i,j;268int g;269int **Z;270271if (mat->kgv == 0) mat->kgv = 1;272if ( mat->array.N )273{274if ( mat->kgv != 1 ) {275fprintf(stderr,"Check_mat: Error: denominator matrix with lcd != 1 detected.\n");276exit(3);277}278/*279* Beim Kuerzen wird Integral richtig gesetzt.280*/281mat->flags.Integral= TRUE;282/*{{{ kuerzen*/283for ( i=0; i < mat->rows; i++ ) {284for ( j=0; j < mat->cols; j++ ) {285if ( mat->array.N[i][j] == 0 ) {286fprintf (stderr,"Check_mat: Error: divide by zero\n");287exit (3);288}289if ( mat->array.SZ[i][j] == 0 ) {290mat->array.N[i][j]= 1;291} else {292g = GGT (mat->array.SZ[i][j], mat->array.N[i][j]);293mat->array.SZ[i][j] /= g;294mat->array.N[i][j] /= g;295if ( mat->array.N[i][j] < 0) {296mat->array.N[i][j] = -mat->array.N[i][j];297mat->array.SZ[i][j] = -mat->array.SZ[i][j];298}299}300if ( mat->array.N[i][j] != 1 ) {301mat->flags.Integral = FALSE;302}303}304}305/*}}} */306/*{{{ mat->flags setzen*/307if ( mat->cols != mat->rows ) {308mat->flags.Symmetric= mat->flags.Diagonal= mat->flags.Scalar= FALSE;309} else {310mat->flags.Diagonal= mat->flags.Symmetric= TRUE;311for ( i=0; i < mat->rows-1 && mat->flags.Symmetric;i++ ) {312for ( j=i+1;j < mat->cols && mat->flags.Symmetric; j++ ) {313if ( mat->array.SZ[i][j] != mat->array.SZ[j][i] ||314mat->array.N [i][j] != mat->array.N [j][i] ) {315mat->flags.Symmetric= mat->flags.Diagonal= FALSE;316} else if ( mat->flags.Diagonal ) {317mat->flags.Diagonal= mat->array.SZ[i][j] == 0;318}319}320}321mat->flags.Scalar = mat->flags.Diagonal;322for ( i=0;i < mat->rows-1 && mat->flags.Scalar; i++) {323if ( mat->array.SZ[i][i] != mat->array.SZ[i+1][i+1]324|| mat->array.N [i][i] != mat->array.N [i+1][i+1] ) {325mat->flags.Scalar= FALSE;326}327}328}329/*330* release array.N if all denominators are equal to 1331*/332if ( mat->flags.Integral ) {333free2dim( (char **)mat->array.N, mat->rows );334mat->array.N = NULL;335}336/*}}} */337} else { /* hoechstens noch Hauptnenner */338Z = mat->array.SZ;339if ( mat->prime != 0 ) { /* Matrix ueber GF(p) */340/*{{{ normalisieren 0 <= zahl < p*/341mat->flags.Integral= 1;342if ( mat->prime != -1 ) /* passiert, wenn init_mat( ... , "p" ) vor */343{ /* init_prime() aufgerufen wird */344for (i = 0; i < mat->rows; i++)345for (j = 0; j < mat->cols; j++)346if ( (Z[i][j] %= mat->prime) < 0)347Z[i][j] += mat->prime;348}349/*}}} */350}351/*{{{ flags setzen*/352if ( mat->cols != mat->rows )353mat->flags.Symmetric= mat->flags.Diagonal= mat->flags.Scalar= FALSE;354else355{356mat->flags.Diagonal= mat->flags.Symmetric= TRUE;357for ( i=0; i < mat->rows-1 && mat->flags.Symmetric;i++ )358for ( j=i+1;j < mat->cols && mat->flags.Symmetric; j++ )359{360if ( mat->array.SZ[i][j] != mat->array.SZ[j][i] )361{362mat->flags.Symmetric= mat->flags.Diagonal= FALSE;363}364else if ( mat->flags.Diagonal )365mat->flags.Diagonal= mat->array.SZ[i][j] == 0;366}367mat->flags.Scalar = mat->flags.Diagonal;368for ( i=0;i < mat->rows-1 && mat->flags.Scalar; i++)369{370if ( mat->array.SZ[i][i] != mat->array.SZ[i+1][i+1] )371mat->flags.Scalar= FALSE;372}373}374/*}}} */375if ( mat->prime == 0 )376{377/*{{{ kgv > 0 machen*/378if ( mat->kgv < 0 )379{380mat->kgv= - mat->kgv;381Z = mat->array.SZ;382if(mat->flags.Diagonal)383for (i = 0; i < mat->rows; i++) Z[i][i] = -Z[i][i];384else385for (i = 0; i < mat->rows; i++)386for (j = 0; j < mat->cols; j++)387Z[i][j] = -Z[i][j];388}389/*}}} */390/*{{{ kgv gegen alle Matrixelemente kuerzen*/391g= mat->kgv;392if( mat->flags.Scalar == FALSE )393{394if ( mat->flags.Diagonal == FALSE )395{396if ( mat->flags.Symmetric == FALSE )397{398for (i=0; i < mat->rows && g != 1;i++ )399for ( j=0;j < mat->cols && g != 1; j++ )400g= GGT ( g, mat->array.SZ[i][j] );401}402else403{404for (i=0; i < mat->rows && g != 1;i++ )405for ( j=0;j <=i && g != 1; j++ )406g= GGT ( g, mat->array.SZ[i][j] );407}408}409else410for ( i=0; i < mat->rows && g != 1;i++) g= GGT( g, mat->array.SZ[i][i] );411}412/* timan 11/05/99: changed from413else414to : (to handle this rare case of a matrix without entries) */415else if (mat->rows > 0 && mat->cols > 0)416g = GGT(g, mat->array.SZ[0][0]);417mat->kgv /= g;418if(g != 1)419{420if ( mat->flags.Diagonal )421for ( i=0; i < mat->rows;i++) mat->array.SZ[i][i] /= g;422else423for (i=0; i < mat->rows;i++ )424for ( j=0;j < mat->cols; j++ )425mat->array.SZ[i][j] /= g;426}427mat->flags.Integral = (mat->kgv == 1);428}429}430}431432/*}}} */433434435436