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" */3/**************************************************************************\4@---------------------------------------------------------------------------5@---------------------------------------------------------------------------6@ FILE: MP_gauss.c7@---------------------------------------------------------------------------8@---------------------------------------------------------------------------9@10\**************************************************************************/111213/************************************************************************\14@-------------------------------------------------------------------------15@ int MP_trf_gauss(M, Trf, rows, cols)16@ MP_INT **M, **Trf;17@ int rows, cols;18@ The Matrix M is transformed to a matrix M such that19@ M_new = Trf * M_old is Gauss-reduced, with Trf integral with20@ determinant +-1.21@ CAUTION: The entries of the matrix M are changed.22@-------------------------------------------------------------------------23\************************************************************************/2425int MP_trf_gauss(M, Trf, rows, cols)26MP_INT **M, **Trf;27int rows, cols;28{29int i,j,k;30int n;31int step;32MP_INT a1,a2,gcd, *v, f;33int tester;34int spos = 0;35MP_INT x1,x2,y1,y2;36MP_INT Mi, Ms;3738n = rows;39mpz_init(&f); mpz_init(&a1); mpz_init(&a2); mpz_init(&gcd);40mpz_init(&x1); mpz_init(&x2);41mpz_init(&y1); mpz_init(&y2);42mpz_init(&Ms); mpz_init(&Mi);43for(i=0;i<n;i++)44for(j=0;j<n; j++)45mpz_set_si(&Trf[i][j], 0);46for(i=0;i<n;i++)47mpz_set_si(&Trf[i][i], 1);48for(step = 0; step < n; step++)49{50tester = FALSE;51while(tester == FALSE)52{53i = step;54while(i<n && mpz_cmp_si(&M[i][spos], 0) == 0)55i++;56if(i<n)57{58tester = TRUE;59if(i != step)60{61v = M[i];62M[i] = M[step];63M[step] = v;64v = Trf[i];65Trf[i] = Trf[step];66Trf[step] = v;67}68}69else70spos++;71if(spos == cols)72{73mpz_clear(&f); mpz_clear(&a1); mpz_clear(&a2); mpz_clear(&gcd);74mpz_clear(&x1); mpz_clear(&x2);75mpz_clear(&y1); mpz_clear(&y2);76mpz_clear(&Ms); mpz_clear(&Mi);77return(step);78}79}80for(i=step+1;i<n;i++)81{82if(mpz_cmp_si(&M[i][spos], 0) != 0)83{84mpz_gcdext(&gcd, &a1, &a2, &M[step][spos], &M[i][spos]);85if(mpz_cmp_si(&a1, 0) == 0)86{87v = M[step];88M[step] = M[i];89M[i] = v;90v = Trf[step];91Trf[step] = Trf[i];92Trf[i] = v;93mpz_set(&f, &a1); mpz_set(&a1, &a2); mpz_set(&a2, &f);94}95mpz_div(&Ms, &M[step][spos], &gcd);96mpz_div(&Mi, &M[i][spos], &gcd);97mpz_set(&M[step][spos], &Ms);98mpz_set(&M[i][spos], &Mi);99for(j=0;j<n;j++)100{101mpz_mul(&x1, &Trf[step][j], &a1);102mpz_mul(&x2, &Trf[i][j], &a2);103mpz_mul(&y1, &Trf[i][j], &Ms);104mpz_mul(&y2, &Trf[step][j], &Mi);105mpz_add(&Trf[step][j], &x1, &x2);106mpz_sub(&Trf[i][j], &y1, &y2);107/**************************108x = Trf->array.SZ[step][j];109y = Trf->array.SZ[i][j];110Trf->array.SZ[step][j] = a1 * x + a2 * y;111Trf->array.SZ[i][j] = Ms * y - Mi * x;112**************************/113}114for(j=spos + 1; j<cols; j++)115{116mpz_mul(&x1, &M[step][j], &a1);117mpz_mul(&x2, &M[i][j], &a2);118mpz_mul(&y1, &M[i][j], &Ms);119mpz_mul(&y2, &M[step][j], &Mi);120mpz_add(&M[step][j], &x1, &x2);121mpz_sub(&M[i][j], &y1, &y2);122/****************************123x = M->array.SZ[step][j];124y = M->array.SZ[i][j];125M->array.SZ[step][j] = a1 * x + a2 * y;126M->array.SZ[i][j] = Ms * y - Mi * x;127**************************/128}129mpz_set(&M[step][spos], &gcd);130mpz_set_si(&M[i][spos], 0);131}132}133}134mpz_clear(&f); mpz_clear(&a1); mpz_clear(&a2); mpz_clear(&gcd);135mpz_clear(&x1); mpz_clear(&x2);136mpz_clear(&y1); mpz_clear(&y2);137mpz_clear(&Ms); mpz_clear(&Mi);138return(n);139}140141142/**************************************************************************\143@---------------------------------------------------------------------------144@ int MP_row_gauss(M, rows, cols)145@ MP_INT **M;146@ int rows, cols;147@148@ The same as MP_trf_gauss without calulating the transformation149@ matrix.150@---------------------------------------------------------------------------151@152\**************************************************************************/153154int MP_row_gauss(M, rows, cols)155MP_INT **M;156int rows, cols;157{158int i,j,k;159int n;160int step;161MP_INT a1,a2,gcd, *v, f;162int tester;163int spos = 0;164MP_INT x1,x2,y1,y2;165MP_INT Mi, Ms;166167n = rows;168mpz_init(&f); mpz_init(&a1); mpz_init(&a2); mpz_init(&gcd);169mpz_init(&x1); mpz_init(&x2);170mpz_init(&y1); mpz_init(&y2);171mpz_init(&Ms); mpz_init(&Mi);172for(step = 0; step < n; step++)173{174tester = FALSE;175while(tester == FALSE)176{177i = step;178while(i<n && mpz_cmp_si(&M[i][spos], 0) == 0)179i++;180if(i<n)181{182tester = TRUE;183if(i != step)184{185v = M[i];186M[i] = M[step];187M[step] = v;188}189}190else191spos++;192if(spos == cols)193{194mpz_clear(&f); mpz_clear(&a1); mpz_clear(&a2); mpz_clear(&gcd);195mpz_clear(&x1); mpz_clear(&x2);196mpz_clear(&y1); mpz_clear(&y2);197mpz_clear(&Ms); mpz_clear(&Mi);198return(step);199}200}201for(i=step+1;i<n;i++)202{203if(mpz_cmp_si(&M[i][spos], 0) != 0)204{205mpz_gcdext(&gcd, &a1, &a2, &M[step][spos], & M[i][spos]);206if(mpz_cmp_si(&a1, 0) == 0)207{208v = M[step];209M[step] = M[i];210M[i] = v;211mpz_set(&f, &a1); mpz_set(&a1, &a2); mpz_set(&a2, &f);212}213mpz_div(&Ms, &M[step][spos], &gcd);214mpz_div(&Mi, &M[i][spos], &gcd);215mpz_set(&M[step][spos], &Ms);216mpz_set(&M[i][spos], &Mi);217for(j=spos + 1; j<cols; j++)218{219mpz_mul(&x1, &M[step][j], &a1);220mpz_mul(&x2, &M[i][j], &a2);221mpz_mul(&y1, &M[i][j], &Ms);222mpz_mul(&y2, &M[step][j], &Mi);223mpz_add(&M[step][j], &x1, &x2);224mpz_sub(&M[i][j], &y1, &y2);225/****************************226x = M->array.SZ[step][j];227y = M->array.SZ[i][j];228M->array.SZ[step][j] = a1 * x + a2 * y;229M->array.SZ[i][j] = Ms * y - Mi * x;230**************************/231}232mpz_set(&M[step][spos], &gcd);233mpz_set_si(&M[i][spos], 0);234}235}236}237mpz_clear(&f); mpz_clear(&a1); mpz_clear(&a2); mpz_clear(&gcd);238mpz_clear(&x1); mpz_clear(&x2);239mpz_clear(&y1); mpz_clear(&y2);240mpz_clear(&Ms); mpz_clear(&Mi);241return(n);242}243244245/**************************************************************************\246@---------------------------------------------------------------------------247@ int MP_row_gauss_simultaneous(M, rows, cols, B, Bcols)248@ MP_INT **M, **B;249@ int rows, cols, Bcols;250@251@ applies an integral gaussian algorithm (on the rows) to to 2-dimensional252@ array 'M' and does the simultaneous row operations on B.253@---------------------------------------------------------------------------254@255\**************************************************************************/256int MP_row_gauss_simultaneous(M, rows, cols, B, Bcols)257MP_INT **M, **B;258int rows, cols, Bcols;259{260int i,j,k;261int n;262int step;263MP_INT a1,a2,gcd, *v, f;264int tester;265int spos = 0;266MP_INT x1,x2,y1,y2;267MP_INT Mi, Ms;268269n = rows;270mpz_init(&f); mpz_init(&a1); mpz_init(&a2); mpz_init(&gcd);271mpz_init(&x1); mpz_init(&x2);272mpz_init(&y1); mpz_init(&y2);273mpz_init(&Ms); mpz_init(&Mi);274for(step = 0; step < n; step++)275{276tester = FALSE;277while(tester == FALSE)278{279i = step;280while(i<n && mpz_cmp_si(&M[i][spos], 0) == 0)281i++;282if(i<n)283{284tester = TRUE;285if(i != step)286{287v = M[i];288M[i] = M[step];289M[step] = v;290v = B[i];291B[i] = B[step];292B[step] = v;293}294}295else296spos++;297if(spos == cols)298{299mpz_clear(&f); mpz_clear(&a1); mpz_clear(&a2); mpz_clear(&gcd);300mpz_clear(&x1); mpz_clear(&x2);301mpz_clear(&y1); mpz_clear(&y2);302mpz_clear(&Ms); mpz_clear(&Mi);303return(step);304}305}306for(i=step+1;i<n;i++)307{308if(mpz_cmp_si(&M[i][spos], 0) != 0)309{310mpz_gcdext(&gcd, &a1, &a2, &M[step][spos], & M[i][spos]);311if(mpz_cmp_si(&a1, 0) == 0)312{313v = M[step];314M[step] = M[i];315M[i] = v;316v = B[step];317B[step] = B[i];318B[i] = v;319mpz_set(&f, &a1); mpz_set(&a1, &a2); mpz_set(&a2, &f);320}321mpz_div(&Ms, &M[step][spos], &gcd);322mpz_div(&Mi, &M[i][spos], &gcd);323mpz_set(&M[step][spos], &Ms);324mpz_set(&M[i][spos], &Mi);325for(j=0;j<Bcols;j++)326{327mpz_mul(&x1, &B[step][j], &a1);328mpz_mul(&x2, &B[i][j], &a2);329mpz_mul(&y1, &B[i][j], &Ms);330mpz_mul(&y2, &B[step][j], &Mi);331mpz_add(&B[step][j], &x1, &x2);332mpz_sub(&B[i][j], &y1, &y2);333/**************************334x = Trf->array.SZ[step][j];335y = Trf->array.SZ[i][j];336Trf->array.SZ[step][j] = a1 * x + a2 * y;337Trf->array.SZ[i][j] = Ms * y - Mi * x;338**************************/339}340for(j=spos + 1; j<cols; j++)341{342mpz_mul(&x1, &M[step][j], &a1);343mpz_mul(&x2, &M[i][j], &a2);344mpz_mul(&y1, &M[i][j], &Ms);345mpz_mul(&y2, &M[step][j], &Mi);346mpz_add(&M[step][j], &x1, &x2);347mpz_sub(&M[i][j], &y1, &y2);348/****************************349x = M->array.SZ[step][j];350y = M->array.SZ[i][j];351M->array.SZ[step][j] = a1 * x + a2 * y;352M->array.SZ[i][j] = Ms * y - Mi * x;353**************************/354}355mpz_set(&M[step][spos], &gcd);356mpz_set_si(&M[i][spos], 0);357}358}359}360mpz_clear(&f); mpz_clear(&a1); mpz_clear(&a2); mpz_clear(&gcd);361mpz_clear(&x1); mpz_clear(&x2);362mpz_clear(&y1); mpz_clear(&y2);363mpz_clear(&Ms); mpz_clear(&Mi);364return(n);365}366367368/*************************************************************************369@370@------------------------------------------------------------------------371@372@ void MP_row_gauss_reverse(MP_INT **A,int rows,int cols,int option)373@374@ Performs a manhattan style gauss algorithm on the MP_INT matrix375@ M, which has to be gauss reduced by MP_row_gauss before.376@ The algorithm is not done complete for sake of speed!377@378@ MP_INT **A : The matrix in question. It will be changed!379@ int rows : the rows of A. It is suffisient to feed the rank in here.380@ int cols : the number of columns of A.381@ int option : this flag determines the behaviour of the function:382@ for option == 0 it will only perform Z elementary383@ tranformations, for option == 1 it will divide every384@ row by the gcd of it's entries (so do it Q style)!385@------------------------------------------------------------------------386@387*************************************************************************/388void MP_row_gauss_reverse(MP_INT **A,int rows,int cols,int option)389{390int i,391j,392k,393actcol;394395MP_INT x,396y;397398mpz_init(&x);399mpz_init(&y);400401for (k=rows-1;k>=0;k--){402403/* find the first non zero entry in the k-th row of A */404for (actcol=0;actcol<cols && (mpz_cmp_si(A[k]+actcol,0) ==0);actcol++);405406/* make the first entry in this row positive for nice purposes */407if (mpz_cmp_si(A[k]+actcol,0)<0)408for (j=actcol;j<cols;j++) mpz_neg(A[k]+j,A[k]+j);409410/* bare in mind: option == 1 means we are doing gauss over Q, so411divide the row by the gcd of it's entries */412if (option == 1){413mpz_set(&x,A[k]+actcol);414for (i=actcol+1;i<cols;i++) mpz_gcd(&x,&x,A[k]+i);415mpz_abs(&x,&x);416if (mpz_cmp_si(&x,1) != 0)417for (i=actcol;i<cols;i++) mpz_div(A[k]+i,A[k]+i,&x);418}419420for (i=0;i<k;i++){421mpz_div(&x,A[i]+actcol,A[k]+actcol);422for (j=actcol;j<cols;j++){423mpz_mul(&y,&x,A[k]+j);424mpz_sub(A[i]+j,A[i]+j,&y);425}426}427}428429mpz_clear(&x);430mpz_clear(&y);431432return;433}434435436437