GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#include "typedef.h"1#include "gmp.h"2/* #include "gmp-impl.h" */34extern int INFO_LEVEL;56/**************************************************************************\7@---------------------------------------------------------------------------8@---------------------------------------------------------------------------9@ FILE: MP_solve.c10@---------------------------------------------------------------------------11@---------------------------------------------------------------------------12@13\**************************************************************************/1415/************************************************************************\16@-------------------------------------------------------------------------17@ MP_INT ***MP_solve_mat(M, rows, cols, B, Bcols, X1cols, X0kgv)18@ MP_INT **M, **B, *X0kgv;19@ int rows, cols, Bcols, *X1cols;20@21@ MP_solve_mat(M) calculates Matrix X[0] with MX[0] = B, and22@ a matrix X[1] with MX[1] = 0, such that23@ the cols of X[1] are a Z-basis of the solution space.24@ The number of the cols of X[1] are returned via the pointer 'X1cols'.25@ CAUTION: the function changes the values of M;26@-------------------------------------------------------------------------27@28\************************************************************************/29MP_INT ***MP_solve_mat(M, rows, cols, B, Bcols, X1cols, X0kgv)30MP_INT **M, **B, *X0kgv;31int rows, cols, Bcols, *X1cols;32{33MP_INT **Mt, **Trf, ***erg, *Y, *Z;34MP_INT kgv, altkgv, merk, merk1, g;35MP_INT zaehler, nenner, b;36int i,j,k,l,rang, n;37int tester, dim;38int waste;3940extern matrix_TYP *copy_mat();41extern matrix_TYP *tr_pose();42extern matrix_TYP *init_mat();43extern matrix_TYP *mat_mul();4445mpz_init(&zaehler); mpz_init(&nenner); mpz_init(&b);46if(B == NULL || Bcols == 0)47rang = MP_row_gauss(M, rows, cols);48else49rang = MP_row_gauss_simultaneous(M, rows, cols, B, Bcols);50if((Mt = (MP_INT **)malloc(cols *sizeof(MP_INT *))) == 0)51{52printf("malloc of 'Mt' in 'MP_solve_mat' failed\n");53exit(2);54}55for(i=0;i<cols;i++)56{57if((Mt[i] = (MP_INT *)malloc(rows *sizeof(MP_INT))) == 0)58{59printf("malloc of 'Mt[%d]' in 'MP_solve_mat' failed\n", i);60exit(2);61}62}63for(i=0;i<rows;i++)64for(j=0;j<cols;j++)65mpz_init_set(&Mt[j][i], &M[i][j]);66if((Trf = (MP_INT **)malloc(cols *sizeof(MP_INT *))) == 0)67{68printf("malloc of 'Trf' in 'MP_solve_mat' failed\n");69exit(2);70}71for(i=0;i<cols;i++)72{73if((Trf[i] = (MP_INT *)malloc(cols *sizeof(MP_INT))) == 0)74{75printf("malloc of 'Trf[%d]' in 'MP_solve_mat' failed\n", i);76exit(2);77}78for(j=0;j<cols;j++)79mpz_init(&Trf[i][j]);80mpz_set_si(&Trf[i][i], 1);81}82mpz_init_set_si(&kgv,1);8384/* transform the transposed Mt of M to be gauss reduced */85rang = MP_trf_gauss(Mt, Trf, cols, rows);8687/* now we are able to predict the dimension of the homogenous solution */88dim = cols - rang;89*X1cols = dim;9091if((erg = (MP_INT ***)malloc(2 *sizeof(MP_INT **))) == 0)92{93printf("malloc of 'erg' in 'MP_solve_mat' failed\n");94exit(2);95}9697{98/*********************************************************************\99| calculate a solution of the homogenous equation100| Write this solution to erg[1]101\*********************************************************************/102if(dim == 0)103{104erg[1] = NULL;105}106else107{108if((erg[1] = (MP_INT **)malloc(dim *sizeof(MP_INT *))) == 0)109{110printf("malloc of 'erg[1]' in 'MP_solve_mat' failed\n");111exit(2);112}113114for(i=0;i<dim;i++)115{116if((erg[1][i] = (MP_INT *)malloc(cols *sizeof(MP_INT))) == 0)117{118printf("malloc of 'erg[1][%d]' in 'MP_solve_mat' failed\n", i);119exit(2);120}121}122for(i=0;i<dim;i++)123for(j=0;j<cols;j++)124mpz_init_set(&erg[1][i][j], &Trf[i+rang][j]);125}126if(dim > 1)127MP_hnf(erg[1], dim, cols);128}129if(B != NULL && Bcols != 0)130{131132/* test whether there is an solution at all */133/* does work this way because M and B were gauss reduced134simultaneusly */135tester = TRUE;136for(i=rang;i<rows && tester == TRUE;i++)137for(j=0;j<Bcols && tester == TRUE;j++)138{139if(mpz_cmp_si(&B[i][j], 0) != 0)140tester = FALSE;141}142143if(tester == FALSE)144erg[0] = NULL;145else146{147/*********************************************************************\148| calculate a solution of the inhomogenous equation149| Write this solution to erg[0]150\*********************************************************************/151if ((erg[0] = (MP_INT **)malloc(cols *sizeof(MP_INT *))) == NULL)152{153printf("malloc of 'erg[0]' in 'MP_solve_mat' failed\n");154exit(2);155}156157for(i=0;i<cols;i++)158{159if((erg[0][i] = (MP_INT *)malloc(Bcols *sizeof(MP_INT))) == 0)160{161printf("malloc of 'erg[0][%d]' in 'MP_solve_mat' failed\n", i);162exit(2);163}164for(j=0;j<Bcols;j++)165mpz_init(&erg[0][i][j]);166}167if ((Y = (MP_INT *)malloc(cols *sizeof(MP_INT))) == NULL)168{169printf("malloc of 'Y' in 'MP_solve_mat' failed\n");170exit(2);171}172for(i=0;i<cols;i++)173mpz_init(&Y[i]);174if ((Z = (MP_INT *)malloc(cols *sizeof(MP_INT))) == NULL)175{176printf("malloc of 'Z' in 'MP_solve_mat' failed\n");177exit(2);178}179for(i=0;i<cols;i++)180mpz_init(&Z[i]);181mpz_init_set_si(&altkgv,1);182mpz_init(&merk); mpz_init(&merk1);183mpz_init(&g);184for(i=0;i<Bcols;i++)185{186187/* output for debugging */188if (INFO_LEVEL & 4){189dump_MP_mat(M,rows,cols,"M");190dump_MP_mat(Mt,cols,rows,"Mt");191dump_MP_mat(B,rows,Bcols,"B");192}193194/* changed 30/1/97 tilman from195for(j=0;j<cols && j< rows;j++)196to : */197for(j=0;j<cols && j< rang;j++)198{199200if (INFO_LEVEL & 4){201dump_MP_mat(&Y,1,cols,"Y");202dump_MP_mat(&Z,1,cols,"Z");203}204205mpz_set_si(&Y[j], 0);206mpz_set_si(&Z[j], 1);207for(k=0;k<j;k++)208{209mpz_mul(&merk1, &Y[k], &Mt[k][j]);210mpz_mul(&merk1, &merk1, &Z[j]);211mpz_mul(&Y[j], &Y[j], &Z[k]);212mpz_add(&Y[j], &Y[j], &merk1);213mpz_mul(&Z[j], &Z[j], &Z[k]);214215mpz_gcd(&g, &Y[j], &Z[j]);216mpz_div(&Y[j], &Y[j], &g);217mpz_div(&Z[j], &Z[j], &g);218}219mpz_mul(&merk, &B[j][i], &Z[j]);220mpz_sub(&Y[j], &merk, &Y[j]);221mpz_mul(&Z[j], &Z[j], &Mt[j][j]);222223mpz_gcd(&g, &Y[j], &Z[j]);224225mpz_div(&Y[j], &Y[j], &g);226mpz_div(&Z[j], &Z[j], &g);227228/* normalising the sign of Z[j] */229if(mpz_cmp_si(&Z[j], 0) < 0){230mpz_neg(&Y[j], &Y[j]);231mpz_neg(&Z[j], &Z[j]);232}233}234235/* changed 30/1/97 from:236for(j=rows;j<cols;j++)237to :*/238for(j=rang;j<cols;j++)239{240mpz_set_si(&Y[j], 0);241mpz_set_si(&Z[j], 1);242}243/* calculate the lcm of kgv and Z[j], 1<=j<=cols */244mpz_set(&merk, &kgv);245for(j=0;j<cols && j < rows;j++)246{247mpz_gcd(&g, &Z[j], &merk);248mpz_div(&merk1, &Z[j], &g);249mpz_mul(&merk, &merk, &merk1);250}251for(j=0;j<cols;j++)252{253mpz_div(&g, &merk, &Z[j]);254mpz_mul(&Y[j], &Y[j], &g);255}256if(mpz_cmp(&merk, &kgv) != 0)257{258mpz_div(&g, &merk, &kgv);259mpz_set(&kgv, &merk);260for(j=0;j<Bcols;j++)261{262if(j != i)263{264for(k=0;k<cols;k++)265mpz_mul(&erg[0][k][j], &erg[0][k][j], &g);266}267}268}269for(j=0;j<cols;j++)270{271mpz_set_si(&erg[0][j][i], 0);272for(k=0;k<cols;k++)273{274mpz_mul(&merk, &Y[k], &Trf[k][j]);275mpz_add(&erg[0][j][i], &erg[0][j][i], &merk);276}277}278}279280/* output for debugging */281if (INFO_LEVEL & 4){282fprintf(stderr,"kgv = ");283mpz_out_str(stderr,10,&kgv);284fprintf(stderr,"\n");285dump_MP_mat(erg[0],cols,Bcols,"erg[0]");286}287288mpz_clear(&altkgv);289mpz_clear(&merk); mpz_clear(&merk1);290mpz_clear(&g);291for(i=0;i<cols;i++)292mpz_clear(&Y[i]);293free(Y);294for(i=0;i<cols;i++)295mpz_clear(&Z[i]);296free(Z);297}298mpz_set(X0kgv, &kgv);299}300else301erg[0] = NULL;302303for(i=0;i<cols;i++)304{305for(j=0;j<cols;j++)306mpz_clear(&Trf[i][j]);307free(Trf[i]);308}309free(Trf);310for(i=0;i<rows;i++)311for(j=0;j<cols;j++)312mpz_clear(&Mt[j][i]);313for(i=0;i<cols;i++)314free(Mt[i]);315free(Mt);316317mpz_clear(&zaehler);318mpz_clear(&nenner);319mpz_clear(&b);320mpz_clear(&kgv);321322return(erg);323}324325326