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" */34/**************************************************************************\5@---------------------------------------------------------------------------6@---------------------------------------------------------------------------7@ FILE: MP_hnf.c8@---------------------------------------------------------------------------9@---------------------------------------------------------------------------10@11@12@ The algorithms do the same as the algorithms in the13@ file MP_gauss.c, the only difference the the matrix is in14@ Hermite-normal-form after the algorithm15@16\**************************************************************************/1718/**************************************************************************\19@---------------------------------------------------------------------------20@ int MP_trf_hnf(M, Trf, rows, cols)21@ MP_INT **M, **Trf;22@ int rows, cols;23@24@---------------------------------------------------------------------------25\**************************************************************************/26/************************************************************************\27| The Matrix M is transformed to a matrix M' such that28| M' = Trf * M is Gauss-reduced, with Trf integral with determinante +-1.29| CAUTION: The entries of the matrix M are changed.30\************************************************************************/3132int MP_trf_hnf(M, Trf, rows, cols)33MP_INT **M, **Trf;34int rows, cols;35{36int i,j,k;37int n;38int step;39MP_INT a1,a2,gcd, *v, f;40int tester;41int spos = 0;42MP_INT x1,x2,y1,y2;43MP_INT Mi, Ms;44int rang = 0;4546n = rows;47mpz_init(&f); mpz_init(&a1); mpz_init(&a2); mpz_init(&gcd);48mpz_init(&x1); mpz_init(&x2);49mpz_init(&y1); mpz_init(&y2);50mpz_init(&Ms); mpz_init(&Mi);51for(i=0;i<n;i++)52for(j=0;j<n; j++)53mpz_set_si(&Trf[i][j], 0);54for(i=0;i<n;i++)55mpz_set_si(&Trf[i][i], 1);56for(step = 0; step < n && spos != cols; step++)57{58tester = FALSE;59while(tester == FALSE && spos != cols)60{61i = step;62while(i<n && mpz_cmp_si(&M[i][spos], 0) == 0)63i++;64if(i<n)65{66tester = TRUE;67if(i != step)68{69v = M[i];70M[i] = M[step];71M[step] = v;72v = Trf[i];73Trf[i] = Trf[step];74Trf[step] = v;75}76}77else78spos++;79}80for(i=step+1;i<n && spos != cols;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}133if(spos != cols)134rang++;135}136mpz_set_si(&y2, 2);137mpz_set_si(&y1, 1);138for(step = 0; step < rang; step++)139{140for(i=0;i<cols && mpz_cmp_si(&M[step][i], 0) == 0;i++);141if(i != cols && mpz_cmp_si(&M[step][i], 0) < 0)142{143for(j=i;j<cols;j++)144mpz_neg(&M[step][j], &M[step][j]);145for(j=0;j<rows;j++)146mpz_neg(&Trf[step][j], &Trf[step][j]);147}148}149for(step = 0; step <rang-1;step++)150{151for(i=step+1;i<rang;i++)152{153for(spos = 0; spos<cols && mpz_cmp_si(&M[i][spos], 0) == 0;spos++);154if(spos != cols)155{156mpz_set_si(&f, 0);157mpz_div(&a1, &M[i][spos], &y2);158if(mpz_cmp(&a1, &M[step][spos]) < 0)159{160mpz_div(&f, &M[step][spos], &M[i][spos]);161mpz_mul(&x1, &f, &M[i][spos]);162mpz_sub(&x2, &M[step][spos], &x1);163if(mpz_cmp(&a1, &x2) < 0)164mpz_add(&f, &f, &y1);165}166mpz_neg(&a1, &a1);167if(mpz_cmp(&a1, &M[step][spos]) > 0)168{169mpz_div(&f, &M[step][spos], &M[i][spos]);170mpz_mul(&x1, &f, &M[i][spos]);171mpz_sub(&x2, &M[step][spos], &x1);172if(mpz_cmp(&a1, &x2) > 0)173mpz_sub(&f, &f, &y1);174mpz_mod(&x1, &M[i][spos], &y2);175if(mpz_cmp_si(&y2, 0) == 0 && mpz_cmp(&a1, &x2) == 0)176mpz_sub(&f, &f, &y1);177}178if(mpz_cmp_si(&f, 0) != 0)179{180for(j=spos;j<cols;j++)181{182mpz_mul(&x1, &f, &M[i][j]);183mpz_sub(&M[step][j], &M[step][j], &x1);184}185for(j=0;j<rows;j++)186{187mpz_mul(&x1, &f, &Trf[i][j]);188mpz_sub(&Trf[step][j], &Trf[step][j], &x1);189}190}191}192}193}194195mpz_clear(&f); mpz_clear(&a1); mpz_clear(&a2); mpz_clear(&gcd);196mpz_clear(&x1); mpz_clear(&x2);197mpz_clear(&y1); mpz_clear(&y2);198mpz_clear(&Ms); mpz_clear(&Mi);199return(rang);200}201202203204205206/**************************************************************************\207@---------------------------------------------------------------------------208@ int MP_hnf(M, rows, cols)209@ MP_INT **M;210@ int rows, cols;211@---------------------------------------------------------------------------212@213\**************************************************************************/214int MP_hnf(M, rows, cols)215MP_INT **M;216int rows, cols;217{218int i,j,k;219int n;220int step;221MP_INT a1,a2,gcd, *v, f;222int tester;223int spos = 0;224MP_INT x1,x2,y1,y2;225MP_INT Mi, Ms;226int rang = 0;227228n = rows;229mpz_init(&f); mpz_init(&a1); mpz_init(&a2); mpz_init(&gcd);230mpz_init(&x1); mpz_init(&x2);231mpz_init(&y1); mpz_init(&y2);232mpz_init(&Ms);233mpz_init(&Mi);234235for(step = 0; step < n && spos != cols; step++)236{237tester = FALSE;238while(tester == FALSE && spos != cols)239{240i = step;241while(i<n && mpz_cmp_si(&M[i][spos], 0) == 0)242i++;243if(i<n)244{245tester = TRUE;246if(i != step)247{248v = M[i];249M[i] = M[step];250M[step] = v;251}252}253else254spos++;255}256for(i=step+1;i<n && spos != cols;i++)257{258if(mpz_cmp_si(&M[i][spos], 0) != 0)259{260mpz_gcdext(&gcd, &a1, &a2, &M[step][spos], & M[i][spos]);261if(mpz_cmp_si(&a1, 0) == 0)262{263v = M[step];264M[step] = M[i];265M[i] = v;266mpz_set(&f, &a1);267mpz_set(&a1, &a2);268mpz_set(&a2, &f);269}270mpz_div(&Ms, &M[step][spos], &gcd);271mpz_div(&Mi, &M[i][spos], &gcd);272mpz_set(&M[step][spos], &Ms);273mpz_set(&M[i][spos], &Mi);274for(j=spos + 1; j<cols; j++)275{276mpz_mul(&x1, &M[step][j], &a1);277mpz_mul(&x2, &M[i][j], &a2);278mpz_mul(&y1, &M[i][j], &Ms);279mpz_mul(&y2, &M[step][j], &Mi);280mpz_add(&M[step][j], &x1, &x2);281mpz_sub(&M[i][j], &y1, &y2);282/****************************283x = M->array.SZ[step][j];284y = M->array.SZ[i][j];285M->array.SZ[step][j] = a1 * x + a2 * y;286M->array.SZ[i][j] = Ms * y - Mi * x;287**************************/288}289mpz_set(&M[step][spos], &gcd);290mpz_set_si(&M[i][spos], 0);291}292}293if(spos != cols)294rang++;295}296mpz_set_si(&y2, 2);297mpz_set_si(&y1, 1);298for(step = 0; step < rang; step++)299{300for(i=0;i<cols && mpz_cmp_si(&M[step][i], 0) == 0;i++);301if(i != cols && mpz_cmp_si(&M[step][i], 0) < 0)302{303for(j=i;j<cols;j++)304mpz_neg(&M[step][j], &M[step][j]);305}306}307for(step = 0; step <rang-1;step++)308{309for(i=step+1;i<rang;i++)310{311for(spos = 0; spos<cols && mpz_cmp_si(&M[i][spos], 0) == 0;spos++);312if(spos != cols)313{314315mpz_div(&f,&M[step][spos],&M[i][spos]);316317if (mpz_cmp_si(&M[step][spos],0) < 0){318mpz_mod(&x1,&M[step][spos],&M[i][spos]);319if (mpz_cmp_si(&x1,0) != 0)320mpz_sub_ui(&f,&f,1);321}322323/*324mpz_set_si(&f, 0);325mpz_div(&a1, &M[i][spos], &y2);326if(mpz_cmp(&a1, &M[step][spos]) < 0)327{328mpz_div(&f, &M[step][spos], &M[i][spos]);329mpz_mul(&x1, &f, &M[i][spos]);330mpz_sub(&x2, &M[step][spos], &x1);331if(mpz_cmp(&a1, &x2) < 0)332mpz_add(&f, &f, &y1);333}334mpz_neg(&a1, &a1);335if(mpz_cmp(&a1, &M[step][spos]) >= 0)336{337mpz_div(&f, &M[step][spos], &M[i][spos]);338mpz_mul(&x1, &f, &M[i][spos]);339mpz_sub(&x2, &M[step][spos], &x1);340if(mpz_cmp(&a1, &x2) > 0)341mpz_sub(&f, &f, &y1);342mpz_mod(&x1, &M[i][spos], &y2);343if(mpz_cmp_si(&y2, 0) == 0 && mpz_cmp(&a1, &x2) == 0)344mpz_sub(&f, &f, &y1);345} */346if(mpz_cmp_si(&f, 0) != 0)347{348for(j=spos;j<cols;j++)349{350mpz_mul(&x1, &f, &M[i][j]);351mpz_sub(&M[step][j], &M[step][j], &x1);352}353i--;354}355}356}357}358mpz_clear(&f); mpz_clear(&a1); mpz_clear(&a2); mpz_clear(&gcd);359mpz_clear(&x1); mpz_clear(&x2);360mpz_clear(&y1); mpz_clear(&y2);361mpz_clear(&Ms);362mpz_clear(&Mi);363364return(rang);365}366367368369/**************************************************************************\370@---------------------------------------------------------------------------371@ int MP_hnf_simultaneous(M, rows, cols, B, Bcols)372@ MP_INT **M, **B;373@ int rows, cols, Bcols;374@375@---------------------------------------------------------------------------376\**************************************************************************/377int MP_hnf_simultaneous(M, rows, cols, B, Bcols)378MP_INT **M, **B;379int rows, cols, Bcols;380{381int i,j,k;382int n;383int step;384MP_INT a1,a2,gcd, *v, f;385int tester;386int spos = 0;387MP_INT x1,x2,y1,y2;388MP_INT Mi, Ms;389int rang = 0;390391n = rows;392mpz_init(&f); mpz_init(&a1); mpz_init(&a2); mpz_init(&gcd);393mpz_init(&x1); mpz_init(&x2);394mpz_init(&y1); mpz_init(&y2);395mpz_init(&Ms); mpz_init(&Mi);396for(step = 0; step < n && spos != cols; step++)397{398tester = FALSE;399while(tester == FALSE && spos != cols)400{401i = step;402while(i<n && mpz_cmp_si(&M[i][spos], 0) == 0)403i++;404if(i<n)405{406tester = TRUE;407if(i != step)408{409v = M[i];410M[i] = M[step];411M[step] = v;412v = B[i];413B[i] = B[step];414B[step] = v;415}416}417else418spos++;419}420for(i=step+1;i<n && spos != cols;i++)421{422if(mpz_cmp_si(&M[i][spos], 0) != 0)423{424mpz_gcdext(&gcd, &a1, &a2, &M[step][spos], & M[i][spos]);425if(mpz_cmp_si(&a1, 0) == 0)426{427v = M[step];428M[step] = M[i];429M[i] = v;430v = B[step];431B[step] = B[i];432B[i] = v;433mpz_set(&f, &a1); mpz_set(&a1, &a2); mpz_set(&a2, &f);434}435mpz_div(&Ms, &M[step][spos], &gcd);436mpz_div(&Mi, &M[i][spos], &gcd);437mpz_set(&M[step][spos], &Ms);438mpz_set(&M[i][spos], &Mi);439for(j=0;j<Bcols;j++)440{441mpz_mul(&x1, &B[step][j], &a1);442mpz_mul(&x2, &B[i][j], &a2);443mpz_mul(&y1, &B[i][j], &Ms);444mpz_mul(&y2, &B[step][j], &Mi);445mpz_add(&B[step][j], &x1, &x2);446mpz_sub(&B[i][j], &y1, &y2);447/**************************448x = Trf->array.SZ[step][j];449y = Trf->array.SZ[i][j];450Trf->array.SZ[step][j] = a1 * x + a2 * y;451Trf->array.SZ[i][j] = Ms * y - Mi * x;452**************************/453}454for(j=spos + 1; j<cols; j++)455{456mpz_mul(&x1, &M[step][j], &a1);457mpz_mul(&x2, &M[i][j], &a2);458mpz_mul(&y1, &M[i][j], &Ms);459mpz_mul(&y2, &M[step][j], &Mi);460mpz_add(&M[step][j], &x1, &x2);461mpz_sub(&M[i][j], &y1, &y2);462/****************************463x = M->array.SZ[step][j];464y = M->array.SZ[i][j];465M->array.SZ[step][j] = a1 * x + a2 * y;466M->array.SZ[i][j] = Ms * y - Mi * x;467**************************/468}469mpz_set(&M[step][spos], &gcd);470mpz_set_si(&M[i][spos], 0);471}472}473if(spos != cols)474rang++;475}476mpz_set_si(&y2, 2);477mpz_set_si(&y1, 1);478for(step = 0; step < rang; step++)479{480for(i=0;i<cols && mpz_cmp_si(&M[step][i], 0) == 0;i++);481if(i != cols && mpz_cmp_si(&M[step][i], 0) < 0)482{483for(j=i;j<cols;j++)484mpz_neg(&M[step][j], &M[step][j]);485for(j=0;j<Bcols;j++)486mpz_neg(&B[step][j], &B[step][j]);487}488}489for(step = 0; step <rang-1;step++)490{491for(i=step+1;i<rang;i++)492{493for(spos = 0; spos<cols && mpz_cmp_si(&M[i][spos], 0) == 0;spos++);494if(spos != cols)495{496mpz_set_si(&f, 0);497mpz_div(&a1, &M[i][spos], &y2);498if(mpz_cmp(&a1, &M[step][spos]) < 0)499{500mpz_div(&f, &M[step][spos], &M[i][spos]);501mpz_mul(&x1, &f, &M[i][spos]);502mpz_sub(&x2, &M[step][spos], &x1);503if(mpz_cmp(&a1, &x2) < 0)504mpz_add(&f, &f, &y1);505}506mpz_neg(&a1, &a1);507if(mpz_cmp(&a1, &M[step][spos]) > 0)508{509mpz_div(&f, &M[step][spos], &M[i][spos]);510mpz_mul(&x1, &f, &M[i][spos]);511mpz_sub(&x2, &M[step][spos], &x1);512if(mpz_cmp(&a1, &x2) > 0)513mpz_sub(&f, &f, &y1);514mpz_mod(&x1, &M[i][spos], &y2);515if(mpz_cmp_si(&y2, 0) == 0 && mpz_cmp(&a1, &x2) == 0)516mpz_sub(&f, &f, &y1);517}518if(mpz_cmp_si(&f, 0) != 0)519{520for(j=spos;j<cols;j++)521{522mpz_mul(&x1, &f, &M[i][j]);523mpz_sub(&M[step][j], &M[step][j], &x1);524}525for(j=0;j<Bcols;j++)526{527mpz_mul(&x1, &f, &B[i][j]);528mpz_sub(&B[step][j], &B[step][j], &x1);529}530}531}532}533}534535mpz_clear(&f); mpz_clear(&a1); mpz_clear(&a2); mpz_clear(&gcd);536mpz_clear(&x1); mpz_clear(&x2);537mpz_clear(&y1); mpz_clear(&y2);538mpz_clear(&Ms); mpz_clear(&Mi);539return(rang);540}541542543