GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#include "typedef.h"1#include "tools.h"2#include "matrix.h"34/**************************************************************************\5@---------------------------------------------------------------------------6@---------------------------------------------------------------------------7@ FILE: tools_mat.c8@---------------------------------------------------------------------------9@---------------------------------------------------------------------------10@11\**************************************************************************/12/*{{{}}}*/13/*{{{ iset_entry*/14/*15@---------------------------------------------------------------------16@ boolean iset_entry(mat, r, c, v);17@ matrix_TYP *mat;18@ int r,c;19@ int v;20@21@ Set an integer entry in the r-th row and c-th column of mat to v.22@23@-------------------------------------------------------------------------24*/2526boolean iset_entry(mat, r, c, v)27matrix_TYP *mat;28int r,c;29int v;30{31int w;3233/*34* Check rows and columns35*/36if((r >= mat->rows) || (c >= mat->cols)) {37fprintf(stderr,"Error: Limits of coordinates violated \n");38return(FALSE);39}4041if( mat->prime != 0 ) {42if((w = v % mat->prime) < 0) {43w += mat->prime;44}45mat->array.SZ[r][c] = w;46} else if(mat->flags.Integral) {47mat->array.SZ[r][c] = v;48} else {49mat->array.SZ[r][c] = v*mat->kgv;50}51if(mat->flags.Symmetric && (r != c)) { /* Check matrix flags */52mat->flags.Symmetric = FALSE;53Check_mat(mat);54}55return(TRUE);56}5758/*}}} */59/*{{{ rset_entry*/6061/*62@-------------------------------------------------------------------------63@64@ boolean rset_entry(mat, r, c, v);65@ matrix_TYP *mat;66@ int r, c;67@ rational v;68@69@ Set an rational entry in the r-th row and c-th column of mat to v70@71@-------------------------------------------------------------------------72*/73boolean rset_entry(mat, r, c, v)74matrix_TYP *mat;75int r, c;76rational v;77{78int t, t1, t2;79int **Z;80int w;81int i,j;8283if(v.n == 1) { /* rational is actually an integer */84return(iset_entry(mat,r,c,v.z));85}8687t = t1 = t2 = 0;88/* Check rows and columns */89if((r >= mat->rows) || (c >= mat->cols)) {90fprintf(stderr,"Error: Limits of coordinates violated \n");91return(FALSE);92}9394if( mat->prime != 0 ) { /* somehow pathologic, but why not */95w= (v.z%v.n)%mat->prime;96mat->array.SZ[r][c] = w;97} else {98t= GGT(mat->kgv,v.n);99if(t == v.n) {100t1= v.z*mat->kgv/t;101mat->array.SZ[r][c] = t1;102} else {103t1= v.n/t;104mat->kgv *= t1;105Z = mat->array.SZ;106for(i = 0; i < mat->rows; i++) {107for(j = 0; j < mat->cols; j++) {108Z[i][j] *= t1;109}110}111Z[r][c]= v.z*mat->kgv/t;112}113}114115if(mat->flags.Symmetric && (r != c)) { /* Check matrix flags */116mat->flags.Symmetric = FALSE;117Check_mat(mat);118}119return(TRUE);120}121/*}}} */122/*{{{ iscal_mul*/123/*124@-------------------------------------------------------------------------125@126@ void iscal_mul(mat, v);127@ matrix_TYP *mat;128@ int v;129@130@ Multiply matrix with integer scalar131@132@-------------------------------------------------------------------------133*/134void iscal_mul(mat, v)135matrix_TYP *mat;136int v;137{138int i,j;139int **Z;140int t;141142/* handle the trivial cases */143if (v == 1) {144return;145}146if ( null_mat( mat ) ) {147return;148}149if (v == 0) {150t = 0;151memset2dim( (char **)mat->array.SZ, mat->rows, mat->cols, sizeof(int), (char *)&t );152Check_mat(mat);153return;154}155156t= mat->kgv%v;157if ( (mat->prime == 0) && (t == 0)) {158mat->kgv /= v;159if(mat->kgv == 1 || mat->kgv == -1 ) { /* take care of negative values */160mat->flags.Integral = TRUE;161if(mat->kgv == -1) {162mat->kgv = 1;163Z = mat->array.SZ;164if(mat->flags.Diagonal) {165for(i = 0; i < mat->rows; i++) {166Z[i][i] = -Z[i][i];167}168} else {169for(i = 0; i < mat->rows; i++) {170for(j = 0; j < mat->cols; j++) {171Z[i][j] = -Z[i][j];172}173}174}175}176}177return;178}179180/* now the real work */181Z = mat->array.SZ;182if( mat->prime != 0 ) {183if((v %= mat->prime) < 0) {184v += mat->prime;185}186init_prime(mat->prime);187if(mat->flags.Diagonal) {188for(i = 0; i < mat->rows; i++) {189Z[i][i] = P(Z[i][i],v);190}191} else {192for(i = 0; i < mat->rows; i++) {193for(j = 0; j < mat->cols; j++) {194Z[i][j] = P(Z[i][j],v);195}196}197}198} else { /* P_TYP */199t= GGT(mat->kgv,v);200if( t != 1 ) {201mat->kgv /= t;202v /= t;203}204if(mat->flags.Diagonal) {205for(i = 0; i < mat->rows; i++) {206Z[i][i] *= v;207}208} else {209for(i = 0; i < mat->rows; i++) {210for(j = 0; j < mat->cols; j++) {211Z[i][j] *= v;212}213}214}215}216}217218/*}}} */219/*{{{ rscal_mul*/220/*221@-------------------------------------------------------------------------222@223@ void rscal_mul(mat,v);224@ matrix_TYP *mat;225@ rational v;226@227@ Multiply matrix with rational scalar228@229@-------------------------------------------------------------------------230*/231void rscal_mul(mat,v)232matrix_TYP *mat;233rational v;234{235int vz, t;236int pp;237238if( null_mat( mat ) ) {239return;240}241if(v.z == 0) {242t = 0;243memset2dim( (char **)mat->array.SZ, mat->rows, mat->cols, sizeof(int), (char *)&t );244Check_mat(mat);245return;246}247vz =248t = 0;249Normal(&v);250if(v.n == 1) {251iscal_mul(mat, v.z);252return;253}254255if(mat->prime != 0) {256init_prime(mat->prime);257vz= v.z%mat->prime;258t = v.n%mat->prime;259pp = P(vz, t);260iscal_mul(mat,pp);261}262if(mat->flags.Integral) {263mat->kgv= v.n;264mat->flags.Integral = FALSE;265vz= v.z;266} else {267t= GGT(mat->kgv,v.z);268mat->kgv= mat->kgv/t*v.n;269vz= v.z/t;270}271272if(v.z == 1) {273Check_mat(mat);274} else {275iscal_mul(mat,vz);276}277}278/*}}} */279/*{{{ kill_row*/280/*281@-------------------------------------------------------------------------282@283@ boolean kill_row(mat, row);284@ matrix_TYP *mat;285@ int row;286@287@ Kill one row in the matrix288@ The argument 'row' must use the indexing of the matrix, ie.289@ the rows are numbered from 0 to n-1.290@291@-------------------------------------------------------------------------292*/293boolean kill_row(mat, row)294matrix_TYP *mat;295int row;296{297int i;298int **Z;299300if(row >= mat->rows) {301fprintf(stderr,"Error in kill_row: not so many rows!\n");302return(FALSE);303}304305Z = mat->array.SZ;306free( Z[row] );307for(i = row+1; i < mat->rows; i++) {308Z[i-1] = Z[i];309}310mat->rows--;311mat->array.SZ = (int **)realloc(Z,mat->rows*sizeof(int *));312313if( mat->array.N != NULL ) {314Z = mat->array.N;315free(Z[row]);316for(i = row+1; i < mat->rows+1; i++) {317Z[i-1] = Z[i];318}319mat->array.N = (int **)realloc(Z,mat->rows*sizeof(int *));320}321mat->flags.Symmetric = FALSE;322Check_mat(mat);323return(TRUE);324}325/*}}} */326/*{{{ kill_col*/327/*328@-------------------------------------------------------------------------329@330@ boolean kill_col(mat, col);331@ matrix_TYP *mat;332@ int col;333@334@ Kill one column in the matrix335@ The argument 'col' must use the indexing of the matrix, ie.336@ the cols are numbered from 0 to n-1.337@338@-------------------------------------------------------------------------339*/340boolean kill_col(mat, col)341matrix_TYP *mat;342int col;343{344int i, j;345int **Z;346347if(col >= mat->cols) {348fprintf(stderr,"Error in kill_col: not so many cols!\n");349return(FALSE);350}351352Z = mat->array.SZ;353for(i = 0; i < mat->rows; i++) {354for(j = col; j < mat->cols; j++) {355Z[i][j] = Z[i][j+1];356}357Z[i] = (int *)realloc(Z[i], (mat->cols-1)*sizeof(int *));358}359360if( mat->array.N != NULL) {361Z = mat->array.N;362for(i = 0; i < mat->rows; i++) {363for(j = col; j < mat->cols; j++) {364Z[i][j] = Z[i][j+1];365}366Z[i] = (int *)realloc(Z[i], (mat->cols-1)*sizeof(int *));367}368}369370mat->cols--;371mat->flags.Symmetric = FALSE;372Check_mat(mat);373return(TRUE);374}375376/*}}} */377/*{{{ ins_row*/378/*379@-------------------------------------------------------------------------380@ boolean ins_row(mat, row);381@ matrix_TYP *mat;382@ int row;383@384@ Insert one row in the matrix385@ The argument 'row' must use the indexing of the matrix, ie.386@ the rows are numbered from 0 to n-1.387@388@-------------------------------------------------------------------------389*/390boolean ins_row(mat, row)391matrix_TYP *mat;392int row;393{394int i;395int **Z;396397if(row > mat->rows) {398fprintf(stderr,"Error in ins_row: not so many rows!\n");399return(FALSE);400}401402mat->rows++;403Z=(int **)realloc(mat->array.SZ,mat->rows*sizeof(int *));404mat->array.SZ = Z;405for(i = mat->rows-1; i > row; i--) {406Z[i] = Z[i-1];407}408Z[row] = (int *)calloc(mat->cols , sizeof(int ));409410if( mat->array.N) {411Z=(int **)realloc(mat->array.N,mat->rows*sizeof(int *));412mat->array.N = Z;413for(i = mat->rows-1; i > row; i--) {414Z[i] = Z[i-1];415}416Z[row] = (int *)calloc(mat->cols , sizeof(int ));417}418419Check_mat(mat);420return(TRUE);421}422/*}}} */423/*{{{ ins_col*/424/*425@-------------------------------------------------------------------------426@ boolean ins_col(mat, col);427@ matrix_TYP *mat;428@ int col;429@430@ Insert one column in the matrix431@ The argument 'col' must use the indexing of the matrix, ie.432@ the cols are numbered from 0 to n-1.433@434@-------------------------------------------------------------------------435*/436437boolean ins_col(mat, col)438matrix_TYP *mat;439int col;440{441int i, j;442int **Z;443444if(col > mat->cols) {445fprintf(stderr,"Error in kill_col: not so many cols!\n");446return(FALSE);447}448449mat->cols++;450451Z = mat->array.SZ;452for(i = 0; i < mat->rows; i++) {453Z[i] = (int *)realloc(Z[i], mat->cols*sizeof(int));454for(j = mat->cols-1; j > col; j--) {455Z[i][j] = Z[i][j-1];456}457Z[i][col] = 0;458}459if( mat->array.N != NULL) {460Z = mat->array.N;461for(i = 0; i < mat->rows; i++) {462Z[i] = (int *)realloc(Z[i], mat->cols*sizeof(int));463for(j = mat->cols-1; j > col; j--) {464Z[i][j] = Z[i][j-1];465}466Z[i][col] = 0;467}468}469470Check_mat(mat);471return(TRUE);472}473/*}}} */474/*{{{ imul_row*/475/*476@-------------------------------------------------------------------------477@ boolean imul_row(mat, row, v);478@ matrix_TYP *mat;479@ int row, v;480@481@ Multiply row with an integer482@483@-------------------------------------------------------------------------484*/485boolean imul_row(mat, row, v)486matrix_TYP *mat;487int row, v;488{489int j;490int **Z;491492if(row >= mat->rows) {493fprintf(stderr,"Error in imul_row: not so many rows!\n");494return(FALSE);495}496/* handle the trivial cases */497if (v == 1) {498return(TRUE);499}500if ( null_mat( mat ) ) {501return(TRUE);502}503if (v == 0) {504memset( mat->array.SZ[row], '\0', sizeof(int)*mat->cols );505Check_mat(mat);506return(TRUE);507}508Z = mat->array.SZ;509if( mat->prime != 0) {510if( (v %= mat->prime) < 0 ) {511v += mat->prime;512}513if(v == 1) {514return(TRUE);515}516init_prime(mat->prime);517if(mat->flags.Diagonal) {518Z[row][row] = P(Z[row][row],v);519} else {520for(j = 0; j < mat->cols; j++) {521Z[row][j] = P(Z[row][j],v);522}523}524} else { /* flags & P_TYP */525if(mat->flags.Diagonal) {526Z[row][row] *= v;527} else {528for(j = 0; j < mat->cols; j++) {529Z[row][j] *= v;530}531}532}533534if(!(mat->flags.Diagonal)) {535mat->flags.Symmetric = FALSE;536}537Check_mat(mat);538return(TRUE);539}540541/*}}} */542/*{{{ rmul_row*/543/*544@-------------------------------------------------------------------------545@ boolean rmul_row(mat, row, v);546@ matrix_TYP *mat;547@ int row;548@ rational v;549@550@ Multiply row with a rational551@552@-------------------------------------------------------------------------553*/554boolean rmul_row(mat, row, v)555matrix_TYP *mat;556int row;557rational v;558{559int i,j;560int waste, t;561int **Z;562563if(row >= mat->rows) {564fprintf(stderr,"Error in rmul_row: not so many rows!\n");565return(FALSE);566}567if( mat->prime != 0 ) {568t= (v.z%v.n)%mat->prime;569/* modeq(mod(&t,v.z,v.n),int_to_lang(mat->prime)); */570return(imul_row(mat,row,t));571}572imul_row(mat,row,v.z);573if(v.n == 1) {574return(TRUE);575}576577waste = t = 0;578579Z = mat->array.SZ;580if(mat->flags.Diagonal) {581if(Z[row][row] == 0) {582return(TRUE);583}584t= GGT(Z[row][row], v.n);585if(t == v.n) {586Z[row][row] /= v.n;587return(TRUE);588} else {589waste= v.n/t;590Z[row][row] /= t;591mat->kgv *= waste;592for(i = 0; i < row; i++) {593Z[i][i] *= waste;594}595for(i = row+1; i < mat->rows; i++) {596Z[i][i] *= waste;597}598}599} else {600t= v.n;601for(i = 0; i < mat->cols; i++) {602if(Z[row][i] != 0) {603t= GGT(t,Z[row][i]);604if(t == 1) {605i = mat->cols;606}607}608}609if(t != 1) {610for(i = 0; i < mat->cols; i++) {611if(Z[row][i] != 0) {612Z[row][i] /= t;613}614}615waste= v.n/t;616} else {617waste= v.n;618}619if(waste != 1) {620mat->kgv *= waste;621for(j = 0; j < mat->cols; j++) {622for(i = 0; i < row; i++) {623if(Z[i][j] != 0) Z[i][j] *= waste;624}625for(i = row+1; i < mat->rows; i++) {626if(Z[i][j] != 0) Z[i][j] *= waste;627}628}629}630}631632if(!(mat->flags.Diagonal)) {633mat->flags.Symmetric = FALSE;634}635if(mat->kgv != 1) {636mat->flags.Integral = FALSE;637}638Check_mat(mat);639return(TRUE);640}641/*}}} */642/*{{{ imulcol*/643/*644@-------------------------------------------------------------------------645@boolean imul_col(mat, col, v)646@ matrix_TYP *mat;647@ int col, v;648@649@ Multiply col with an integer650@651@-------------------------------------------------------------------------652*/653boolean imul_col(mat, col, v)654matrix_TYP *mat;655int col, v;656{657int j;658int **Z;659660if(col >= mat->cols) {661fprintf(stderr,"Error in imul_col: not so many cols!\n");662return(FALSE);663}664/* handle the trivial cases */665if (v == 1) {666return(TRUE);667}668if ( null_mat( mat ) ) {669return(TRUE);670}671if (v == 0) {672memset( mat->array.SZ[col], '\0', sizeof(int)*mat->rows );673Check_mat(mat);674return(TRUE);675}676677Z = mat->array.SZ;678if( mat->prime != 0 ) {679if((v %= mat->prime) < 0) {680v += mat->prime;681}682if(v == 1) {683return(TRUE);684}685init_prime(mat->prime);686if(mat->flags.Diagonal) {687Z[col][col] = P(Z[col][col],v);688} else {689for(j = 0; j < mat->rows; j++) {690Z[j][col] = P(Z[j][col],v);691}692}693} else {694if(mat->flags.Diagonal) {695Z[col][col] *= v;696} else {697for(j = 0; j < mat->rows; j++) {698Z[j][col] *= v;699}700}701}702if(!(mat->flags.Diagonal)) {703mat->flags.Symmetric = FALSE;704}705Check_mat(mat);706return(TRUE);707}708709/*}}} */710/*{{{ rmul_col*/711/*712@-------------------------------------------------------------------------713@ boolean rmul_col(mat, col, v);714@ matrix_TYP *mat;715@ int col;716@ rational v;717@718@ Multiply column with a rational719@720@-------------------------------------------------------------------------721*/722boolean rmul_col(mat, col, v)723matrix_TYP *mat;724int col;725rational v;726{727int i,j;728int waste, t;729int **Z;730731if(col >= mat->cols) {732fprintf(stderr,"Error in rmul_col: not so many cols!\n");733return(FALSE);734}735if( mat->prime != 0 ) {736t= (v.z%v.n)%mat->prime;737return(imul_col(mat,col,t));738}739740imul_col(mat,col,v.z);741if(v.n == 1) {742return(TRUE);743}744745waste = t = 0;746747Z = mat->array.SZ;748if(mat->flags.Diagonal) {749if(Z[col][col] == 0) {750return(TRUE);751}752t= GGT(Z[col][col], v.n);753if(t == v.n) {754Z[col][col] /= v.n;755return(TRUE);756} else {757waste= v.n/t;758Z[col][col] /= t;759mat->kgv *= waste;760for(i = 0; i < col; i++) {761Z[i][i] *= waste;762}763for(i = col+1; i < mat->cols; i++) {764Z[i][i] *= waste;765}766}767} else {768t= v.n;769for(i = 0; i < mat->rows; i++) {770if(Z[i][col] != 0) {771t= GGT(t,Z[i][col]);772if(t == 1) {773i = mat->cols;774}775}776}777if(t != 1) {778for(i = 0; i < mat->rows; i++) {779if(Z[i][col] != 0) {780Z[i][col] /= t;781}782}783waste= v.n/t;784} else {785waste= v.n;786}787if(waste != 1) {788for(i = 0; i < mat->rows; i++) {789if(Z[i][col] != 0) {790Z[i][col] /= waste;791}792}793mat->kgv *= waste;794for(j = 0; j < mat->rows; j++) {795for(i = 0; i < col; i++) {796Z[j][i] *= waste;797}798for(i = col+1; i < mat->cols; i++) {799Z[j][i] *= waste;800}801}802}803}804805if(!(mat->flags.Diagonal)) {806mat->flags.Symmetric = FALSE;807}808if(mat->kgv != 1) {809mat->flags.Integral = FALSE;810}811Check_mat(mat);812return(TRUE);813}814/*}}} */815816/*{{{ iadd_row*/817/*818@-------------------------------------------------------------------------819@ boolean iadd_row(mat,t_row, d_row, v)820@ matrix_TYP *mat;821@ int t_row, d_row, v;822@823@ Add v-times t_row to d_row of mat, where v is an integer824@825@-------------------------------------------------------------------------826*/827boolean iadd_row(mat,t_row, d_row, v)828matrix_TYP *mat;829int t_row, d_row, v;830{831int **Z, i,j,t;832833if((t_row >= mat->rows) || (d_row >= mat->rows)) {834fprintf(stderr,"Error in iadd_row: not so many rows!\n");835return(FALSE);836}837838if( mat->prime ) {839if((v %= mat->prime) < 0) v += mat->prime;840}841if(v == 0) {842return(TRUE);843}844if((mat->prime == 0) && (mat->kgv == 0)) {845return(TRUE);846}847848if(d_row == t_row) {849fprintf(stderr,"Warning: Same t_row and d_row in iadd_row\n");850return(imul_row(mat,t_row,v+1));851}852853Z = mat->array.SZ;854if( mat->prime != 0 ) {855init_prime(mat->prime);856if(mat->flags.Diagonal) {857Z[d_row][t_row] = P(v,Z[t_row][t_row]);858if(Z[d_row][t_row]) {859mat->flags.Symmetric =860mat->flags.Diagonal = FALSE;861}862} else {863for(i = 0; i < mat->cols; i++) {864Z[d_row][i] = S(Z[d_row][i],P(v,Z[t_row][i]));865}866}867Check_mat(mat);868return(TRUE);869}870if(mat->flags.Diagonal) {871if(Z[t_row][t_row] ) {872i = Z[t_row][t_row] * v;873Z[d_row][t_row] = i;874mat->flags.Symmetric =875mat->flags.Diagonal = FALSE;876}877} else { /* diagonal */878j = find_max_entry( mat );879for(i = 0; i < mat->cols; i++) {880Z[d_row][i] += v * Z[t_row][i];881t = abs(Z[d_row][i]);882if(t > j) {883j = t;884}885}886mat->flags.Symmetric = FALSE;887}888Check_mat(mat);889return(TRUE);890}891/*}}} */892/*{{{ radd_row*/893/*894@-------------------------------------------------------------------------895@ boolean radd_row(mat,t_row, d_row, v)896@ matrix_TYP *mat;897@ int t_row, d_row;898@ rational v;899@900@ Add v-times t_row to d_row of mat, where v is a rational901@902@-------------------------------------------------------------------------903*/904boolean radd_row(mat,t_row, d_row, v)905matrix_TYP *mat;906int t_row, d_row;907rational v;908{909int **Z, i, j;910int waste,t;911912if((t_row >= mat->rows) || (d_row >= mat->rows)) {913fprintf(stderr,"Error in radd_row: not so many rows!\n");914return(FALSE);915}916waste = t = 0;917918if( mat->prime != 0) {919waste= (v.z%v.n)%mat->prime;920return(iadd_row(mat,t_row, d_row, waste));921}922if(v.z == 0) {923return(TRUE);924}925if( null_mat( mat ) ) {926return(TRUE);927}928if(v.n == 1) {929return(iadd_row(mat,t_row, d_row, v.z));930}931932if(d_row == t_row) {933fprintf(stderr,"Warning: Same t_row and d_row in ladd_row\n");934v.z += v.n;935i = rmul_row(mat,t_row,v);936v.z -= v.n;937return(i);938}939940Z = mat->array.SZ;941if(mat->flags.Diagonal) {942if(Z[t_row][t_row] != 0) {943mat->flags.Symmetric =944mat->flags.Diagonal = FALSE;945Z[d_row][t_row]= v.z*Z[t_row][t_row];946waste= GGT(Z[d_row][t_row],v.n);947if(v.n == waste) {948Z[d_row][t_row] /= v.n;949} else {950t= v.n/waste;951Z[d_row][t_row] /= waste;952mat->kgv *= t;953for(i = 0; i < mat->rows; i++) {954Z[i][i] *= t;955}956mat->flags.Integral = FALSE;957}958}959} else {960t= v.n;961for(i = 0; i < mat->cols; i++) {962Z[d_row][i]=Z[d_row][i]*v.n+Z[t_row][i]*v.z;963if((t != 1) && (Z[d_row][i] != 0)) {964waste= GGT(Z[d_row][i],t);965t = waste;966waste = 0;967}968}969if(t == v.n) {/* the lucky case: row-entries divisible by v.n! */970for(i = 0; i < mat->cols; i++) {971Z[d_row][i] /= v.n;972}973} else if( t == 1) { /* the opposite case: no common factor */974mat->kgv *= v.n;975for(j = 0; j < mat->cols; j++) {976for (i = 0; i < d_row; i++) {977Z[i][j] *= v.n;978}979for (i = d_row+1; i < mat->rows; i++) {980Z[i][j] *= v.n;981}982}983mat->flags.Integral = FALSE;984} else { /* something between the last two cases: most work */985waste = v.n / t;986mat->kgv *= waste;987for(j = 0; j < mat->cols; j++) {988for (i = 0; i < d_row; i++) {989Z[i][j] *= waste;990}991for (i = d_row+1; i < mat->rows; i++) {992Z[i][j] *= waste;993}994Z[d_row][j] /= t;995}996mat->flags.Integral = FALSE;997}998}9991000Check_mat(mat);1001return(TRUE);1002}1003/*}}} */100410051006/*{{{ iadd_col*/1007/*1008@-------------------------------------------------------------------------1009@ boolean iadd_col(mat,t_col, d_col, v)1010@ matrix_TYP *mat;1011@ int t_col, d_col, v;1012@1013@ Add v-times t_col to d_col of mat, where v is an integer1014@1015@-------------------------------------------------------------------------1016*/1017boolean iadd_col(mat,t_col, d_col, v)1018matrix_TYP *mat;1019int t_col, d_col, v;1020{1021int **Z, i,j,t;10221023if((t_col >= mat->cols) || (d_col >= mat->cols)) {1024fprintf(stderr,"Error in iadd_row: not so many rows!\n");1025return(FALSE);1026}1027if( mat->prime != 0 ) {1028if((v %= mat->prime) < 0) v += mat->prime;1029}1030if(v == 0) {1031return(TRUE);1032}10331034if( null_mat( mat ) ) {1035return(TRUE);1036}10371038if(d_col == t_col) {1039fprintf(stderr,"Warning: Same t_col and d_col in iadd_col\n");1040return(imul_col(mat,t_col,v+1));1041}10421043Z = mat->array.SZ;1044if( mat->prime != 0 ) {1045init_prime(mat->prime);1046if(mat->flags.Diagonal) {1047Z[t_col][d_col] = P(v,Z[t_col][t_col]);1048if(Z[t_col][d_col]) {1049mat->flags.Symmetric =1050mat->flags.Diagonal = FALSE;1051}1052} else {1053for(i = 0; i < mat->rows; i++) {1054Z[i][d_col] = S(Z[i][d_col],P(v,Z[i][t_col]));1055}1056}1057Check_mat(mat);1058return(TRUE);1059}1060if(mat->flags.Diagonal) {1061if(Z[t_col][t_col] ) {1062i = Z[t_col][t_col] * v;1063Z[t_col][d_col] = i;1064mat->flags.Symmetric =1065mat->flags.Diagonal = FALSE;1066}1067} else {1068j = find_max_entry( mat );1069for(i = 0; i < mat->rows; i++) {1070Z[i][d_col] += v * Z[i][t_col];1071t = abs(Z[i][d_col]);1072if(t > j) {1073j = t;1074}1075}1076mat->flags.Symmetric = FALSE;1077}1078Check_mat(mat);1079return(TRUE);1080}1081/*}}} */1082/*{{{ radd_col*/1083/*1084@-------------------------------------------------------------------------1085@ boolean radd_col(mat,t_col, d_col, v)1086@ matrix_TYP *mat;1087@ int t_col, d_col;1088@ rational v;1089@1090@ Add v-times t_col to d_col of mat, where v is a rational1091@1092@-------------------------------------------------------------------------1093*/1094boolean radd_col(mat,t_col, d_col, v)1095matrix_TYP *mat;1096int t_col, d_col;1097rational v;1098{1099int **Z, i,j;1100int waste,t;11011102if((t_col >= mat->cols) || (d_col >= mat->cols)) {1103fprintf(stderr,"Error in radd_col: not so many cols!\n");1104return(FALSE);1105}1106waste = t = 0;11071108if( mat->prime != 0) {1109return(iadd_col(mat,t_col, d_col, (v.z%v.n)%mat->prime));1110}1111if(v.z == 0) {1112return(TRUE);1113}1114if( null_mat( mat ) ) {1115return(TRUE);1116}1117if(v.n == 1) {1118return(iadd_col(mat,t_col, d_col, v.z));1119}11201121if(d_col == t_col) {1122fprintf(stderr,"Warning: Same t_col and d_col in radd_col\n");1123v.z += v.n;1124i = rmul_row(mat,t_col,v);1125v.z -= v.n;1126return(i);1127}11281129Z = mat->array.SZ;1130if(mat->flags.Diagonal) {1131if(Z[t_col][t_col] != 0) {1132mat->flags.Symmetric =1133mat->flags.Diagonal = FALSE;1134Z[t_col][d_col] = v.z * Z[t_col][t_col];1135waste = GGT(Z[t_col][d_col],v.n);1136if(v.n == waste) {1137Z[t_col][d_col]/= v.n;1138} else {1139t = v.n / waste;1140Z[t_col][d_col] /= waste;1141mat->kgv *= t;1142for(i = 0; i < mat->rows; i++) {1143Z[i][i] *= t;1144}1145mat->flags.Integral = FALSE;1146}1147}1148} else {1149t = v.n;1150for(i = 0; i < mat->rows; i++) {1151Z[i][d_col] = Z[i][d_col] * v.n + Z[i][t_col] * v.z;1152if((t != 1) && (Z[i][d_col] != 0)) {1153waste= GGT(Z[i][d_col],t);1154t = waste;1155waste = 0;1156}1157}1158if( t == v.n ) {/* the lucky case: row-entries divisible by v.n! */1159for(i = 0; i < mat->rows; i++) {1160Z[i][d_col] /= v.n;1161}1162} else if( t == 1) { /* the opposite case: no common factor */1163mat->kgv *= v.n;1164for(j = 0; j < mat->rows; j++) {1165for (i = 0; i < d_col; i++) {1166Z[j][i] *= v.n;1167}1168for (i = d_col+1; i < mat->cols; i++) {1169Z[j][i] *= v.n;1170}1171}1172mat->flags.Integral = FALSE;1173} else { /* something between the last two cases: most work */1174waste= v.n / t;1175mat->kgv *= waste;1176for(j = 0; j < mat->rows; j++) {1177for (i = 0; i < d_col; i++) {1178Z[j][i] *= waste;1179}1180for (i = d_col+1; i < mat->cols; i++) {1181Z[j][i] *= waste;1182}1183Z[j][d_col] /= t;1184}1185mat->flags.Integral = FALSE;1186}1187}1188Check_mat(mat);1189return(TRUE);1190}1191/*}}} */1192/*{{{ normal_rows*/1193/*1194@-------------------------------------------------------------------------1195@ void normal_rows(mat);1196@ matrix_TYP *mat;1197@1198@ Tool for integral Gauss-elimination: the entries of the1199@ rows of mat are divided by their row-gcd.1200@1201@-------------------------------------------------------------------------1202*/1203void normal_rows(mat)1204matrix_TYP *mat;1205{1206int i,j, g;1207int **Z, *S_I;12081209if( mat->flags.Diagonal || (mat->prime != 0) || null_mat( mat) ) {1210return;1211}1212Z = mat->array.SZ;1213g = 0;1214for(i = 0; i < mat->rows; i++) {1215S_I = Z[i];1216g = 0;1217for(j = 0; j < mat->cols; j++) {1218if(S_I[j]) g = GGT(g,S_I[j]);1219if(g == 1) j = mat->cols;1220}1221if(g != 1) {1222for(j = 0; j < mat->cols; j++) {1223if(S_I[j]) {1224S_I[j] /= g;1225}1226}1227}1228}1229}1230/*}}} */1231/*{{{ normal_cols*/1232/*1233@-------------------------------------------------------------------------1234@ void normal_cols(mat)1235@1236@ Analogue to normal_rows() function for cols1237@1238@-------------------------------------------------------------------------1239*/1240void normal_cols(mat)1241matrix_TYP *mat;1242{1243int i,j, g;1244int **Z;12451246if( mat->flags.Diagonal || (mat->prime != 0) || null_mat( mat ) ) {1247return;1248}12491250Z = mat->array.SZ;1251g = 0;1252for(i = 0; i < mat->cols; i++) {1253g = 0;1254for(j = 0; j < mat->rows; j++) {1255if(Z[j][i]) {1256g = GGT(g,Z[j][i]);1257}1258if(g == 1) {1259j = mat->rows;1260}1261}1262if(g != 1) {1263for(j = 0; j < mat->rows; j++) {1264if(Z[j][i]) {1265Z[j][i] /= g;1266}1267}1268}1269}1270}1271/*}}} */1272/*{{{ mat_to_line*/1273/*1274@-------------------------------------------------------------------------1275@ matrix_TYP *mat_to_line(gen, num);1276@ matrix_TYP **gen;1277@ int num;1278@1279@ matrix_TYP **gen;1280@ int num;1281@1282@ converts each matrix of gen into a row-vector, forgets the kgv.1283@ the i-th matrix is converted to the i-th row of the result.1284@ Tool for determine a basis of a vector space of matrices1285@1286@-------------------------------------------------------------------------1287*/1288matrix_TYP *mat_to_line(gen, num)1289matrix_TYP **gen;1290int num;1291{1292matrix_TYP *mat;1293int i, j, k, row, col;1294int **Z, **ZI;12951296row = gen[0]->rows;1297col = gen[0]->cols;1298for(i = 0; i < num; i++) {1299if((row != gen[i]->rows) || (col != gen[i]->cols)) {1300fprintf(stderr,"Fehler: verschiedene Dimensionen in mat_to_line\n");1301exit(3);1302}1303}1304mat = init_mat(num, row * col,"");1305Z = mat->array.SZ;1306for(k = 0; k < num; k++) {1307ZI = gen[k]->array.SZ;1308for(j = 0; j < row; j++) {1309memcpy(Z[k]+j*col,ZI[j],col*sizeof(int));1310}1311}1312return(mat);1313}13141315/*}}} */1316/*{{{ line_to_mat*/1317/*1318@-------------------------------------------------------------------------1319@ matrix_TYP **line_to_mat(mat,row,col)1320@ matrix_TYP *mat;1321@ int row, col;1322@1323@ Inverse function to mat_to_line1324@1325@-------------------------------------------------------------------------1326*/1327matrix_TYP **line_to_mat(mat,row,col)1328matrix_TYP *mat;1329int row, col;1330{1331matrix_TYP **gen;1332int i,k;1333int **Z, **ZI;13341335if(mat->cols != row* col) {1336fprintf(stderr,"Fehler in line_to_mat: Falsche Dimensionierung\n");1337exit(3);1338}1339gen = (matrix_TYP **)malloc(mat->rows * sizeof(matrix_TYP *));13401341for(k = 0; k < mat->rows; k++) {1342Z = mat->array.SZ;1343gen[k] = init_mat(row, col, "");1344ZI = gen[k]->array.SZ;1345for(i = 0; i < mat->cols; i++) {1346ZI[i / col][i % col] = Z[k][i];1347}1348Check_mat(gen[k]);1349}1350return(gen);1351}13521353/*}}} */1354/*{{{ normal_mat*/1355/*1356@-------------------------------------------------------------------------1357@ int normal_mat(mat);1358@ matrix_TYP *mat;1359@1360@ Calculate ggt of mat-entries and divide matrix by it1361@ Return value is the ggt1362@1363@-------------------------------------------------------------------------1364*/1365int normal_mat(mat)1366matrix_TYP *mat;1367{1368int i,j, g;1369int **Z, *S_I;13701371if( null_mat(mat) || (mat->prime != 0)) {1372return(1);1373}13741375Z = mat->array.SZ;1376g = 0;1377if(mat->flags.Diagonal) {1378for(i = 0; i < mat->rows; i++) {1379if(Z[i][i]) g = GGT(g,Z[i][i]);1380if(g == 1) {1381i = mat->rows;1382}1383}1384} else {1385g = 0;1386for(i = 0; i < mat->rows; i++) {1387S_I = Z[i];1388for(j = 0; j < mat->cols; j++) {1389if(S_I[j]) {1390g = GGT(g,S_I[j]);1391}1392if(g == 1) {1393j = mat->cols;1394i = mat->rows;1395}1396}1397}1398}1399if(g != 1) {1400for(i = 0; i < mat->rows; i++) {1401S_I = Z[i];1402for(j = 0; j < mat->cols; j++) {1403if(S_I[j]) S_I[j] /= g;1404}1405}1406}1407return(g);1408}1409/*}}} */1410141114121413