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 "longtools.h"3#include "matrix.h"4/**************************************************************************\5@---------------------------------------------------------------------------6@---------------------------------------------------------------------------7@ FILE: long_rein_mat.c8@---------------------------------------------------------------------------9@---------------------------------------------------------------------------10@11\**************************************************************************/121314/**************************************************************************\15@---------------------------------------------------------------------------16@ matrix_TYP *long_rein_mat(Mat)17@ matrix_TYP *Mat;18@19@ long_rein_mat calculates a matrix M such that the rows of M20@ form a Z-basis of the lattice of all integral points in the21@ the vectorspace generated by the rows of Mat.22@---------------------------------------------------------------------------23@24\**************************************************************************/25matrix_TYP *long_rein_mat(Mat)26matrix_TYP *Mat;27{2829int i,j,k, step, stepclear;30int cols, rows, rang;31MP_INT **trf, **M, **Mt, **M1, **M2, **M3, **M4, **T1, *merkpointer;32matrix_TYP *erg;33MP_INT a1, a2, x1, x2, y1, y2, merk, g, f;3435cols = Mat->cols;36rows = Mat->rows;37mpz_init(&a1), mpz_init(&a2);38mpz_init(&x1), mpz_init(&x2);39mpz_init(&y1), mpz_init(&y2);40mpz_init(&f), mpz_init(&g);41mpz_init(&merk);42/***************************************************************\43| Set Mt= Mat^{tr} transform Mt to Hermite normal form.44\***************************************************************/45if((Mt = (MP_INT **)malloc(cols *sizeof(MP_INT *))) == NULL)46{47printf("malloc of 'Mt' in 'long_elt_mat' failed\n");48exit(2);49}50for(i=0;i<cols;i++)51{52if((Mt[i] = (MP_INT *)malloc(rows *sizeof(MP_INT))) == NULL)53{54printf("malloc of 'Mt[%d]' in 'long_elt_mat' failed\n", i);55exit(2);56}57for(j=0;j<rows;j++)58mpz_init_set_si(&Mt[i][j], Mat->array.SZ[j][i]);59}6061rang = MP_hnf(Mt, cols, rows);62/***************************************************************\63| Set trf = left_tans64\***************************************************************/65if((trf = (MP_INT **)malloc(rows *sizeof(MP_INT *))) == NULL)66{67printf("malloc of 'trf' in 'long_elt_mat' failed\n");68exit(2);69}70for(i=0;i<rows;i++)71{72if((trf[i] = (MP_INT *)malloc(rows *sizeof(MP_INT))) == NULL)73{74printf("malloc of 'trf[%d]' in 'long_elt_mat' failed\n", i);75exit(2);76}77for(j=0;j<rows;j++)78mpz_init_set_si(&trf[i][j], 0);79mpz_set_si(&trf[i][i], 1);80}81/***************************************************************\82| Set M= Mt^{tr} transform Mt to Hermite normal form.83\***************************************************************/84if((M = (MP_INT **)malloc(rows *sizeof(MP_INT *))) == NULL)85{86printf("malloc of 'M' in 'long_elt_mat' failed\n");87exit(2);88}89for(i=0;i<rows;i++)90{91if((M[i] = (MP_INT *)malloc(cols *sizeof(MP_INT))) == NULL)92{93printf("malloc of 'M[%d]' in 'long_elt_mat' failed\n", i);94exit(2);95}96for(j=0;j<cols;j++)97mpz_init_set(&M[i][j], &Mt[j][i]);98}99100/* output for debugging purposes101dump_MP_mat(trf,rows,rows,"trf");102dump_MP_mat(M,rows,rows,"M"); */103104rang = MP_hnf_simultaneous(M, rows, cols, trf, rows);105106/* output for debugging purposes107dump_MP_mat(trf,rows,rows,"trf");108dump_MP_mat(M,rows,rows,"M"); */109110/***************************************************************\111| Clear the space allocated for 'Mt'112\***************************************************************/113for(i=0;i<cols;i++)114{115for(j=0;j<rows;j++)116mpz_clear(&Mt[i][j]);117free(Mt[i]);118}119free(Mt);120121/***************************************************************\122| Now the elementary divisor algorithm starts123\***************************************************************/124for(step = 0; step < rang;step++)125{126do127{128/*------------------------------------------------------*\129| Clear the 'step'^th row of M130\*------------------------------------------------------*/131for(i=step;i<rang && mpz_cmp_si(&M[step][i], 0) == 0; i++);132if(i!=step)133{134135/* swap the step-th col with the i-th col */136for(j=step;j<rang;j++)137{138mpz_set(&merk, &M[j][step]);139mpz_set(&M[j][step], &M[j][i]);140mpz_set(&M[j][i], &merk);141}142}143if(mpz_cmp_si(&M[step][step], 0) < 0)144{145for(i=step;i<rows;i++)146mpz_neg(&M[i][step], &M[i][step]);147}148for(i=step+1;i<rang;i++)149{150if(mpz_cmp_si(&M[step][i], 0) != 0)151{152if(mpz_cmp_si(&M[step][step], 1) == 0)153{154mpz_set(&f, &M[step][i]);155for(j=step+1;j<rang;j++)156{157mpz_mul(&merk, &M[j][step], &f);158mpz_sub(&M[j][i], &M[j][i], &merk);159}160mpz_set_si(&M[step][i], 0);161162/*163for(j=0;j<rows;j++)164{165mpz_mul(&merk, &trf[j][step], &f);166mpz_sub(&trf[j][i], &trf[j][i], &merk);167}*/168}169else170{171/* changed 11/06/99 (tilman) from172mpz_gcdext(&g, &a1, &a2, &M[step][step], &M[step][i]); to */173mpz_abs( &g,&M[step][i]);174if (mpz_cmp(&M[step][step],&g) == 0){175mpz_set_si(&a1,1);176mpz_set_si(&a2,0);177}178else{179mpz_gcdext(&g, &a1, &a2, &M[step][step], &M[step][i]);180}181182183mpz_div(&x1, &M[step][i], &g);184mpz_div(&x2, &M[step][step], &g);185mpz_neg(&x2, &x2);186187for(j=step+1; j<rang;j++)188{189mpz_mul(&y1, &a1, &M[j][step]);190mpz_mul(&merk, &a2, &M[j][i]);191mpz_add(&y1, &y1, &merk);192193mpz_mul(&y2, &x1, &M[j][step]);194mpz_mul(&merk, &x2, &M[j][i]);195mpz_add(&y2, &y2, &merk);196197mpz_set(&M[j][step], &y1);198mpz_set(&M[j][i], &y2);199}200mpz_set(&M[step][step], &g);201mpz_set_si(&M[step][i], 0);202203/*204for(j=0; j<rows;j++)205{206mpz_mul(&y1, &a1, &trf[j][step]);207mpz_mul(&merk, &a2, &trf[j][i]);208mpz_add(&y1, &y1, &merk);209210mpz_mul(&y2, &x1, &trf[j][step]);211mpz_mul(&merk, &x2, &trf[j][i]);212mpz_add(&y2, &y2, &merk);213214mpz_set(&trf[j][step], &y1);215mpz_set(&trf[j][i], &y2);216}*/217}218}219}220/*------------------------------------------------------*\221| Clear the 'step'^th column of M222\*------------------------------------------------------*/223for(i=step;i<rang && mpz_cmp_si(&M[i][step], 0) == 0; i++);224if(i!=step)225{226merkpointer = M[step];227M[step] = M[i];228M[i] = merkpointer;229230merkpointer = trf[step];231trf[step] = trf[i];232trf[i] = merkpointer;233}234if(mpz_cmp_si(&M[step][step], 0) < 0)235{236for(i=step;i<rows;i++)237mpz_neg(&M[i][step], &M[i][step]);238}239for(i=step+1;i<rang;i++)240{241if(mpz_cmp_si(&M[i][step], 0) != 0)242{243if(mpz_cmp_si(&M[step][step], 1) == 0)244{245mpz_set(&f, &M[i][step]);246for(j=step+1;j<rang;j++)247{248mpz_mul(&merk, &M[step][j], &f);249mpz_sub(&M[i][j], &M[i][j], &merk);250}251mpz_set_si(&M[i][step], 0);252253/* inserted the next 4 lines: tilman 4/12/96 */254for (j=0;j<rang;j++){255mpz_mul(&merk, &trf[step][j], &f);256mpz_sub(&trf[i][j], &trf[i][j], &merk);257}258259}260else261{262/* changed on 8/1/97 tilman from263mpz_gcdext(&g, &a1, &a2, &M[step][step], &M[i][step]);264to : */265mpz_abs( &g,&M[i][step]);266if (mpz_cmp(&M[step][step],&g) == 0){267mpz_set_si(&a1,1);268mpz_set_si(&a2,0);269}270else{271mpz_gcdext(&g, &a1, &a2, &M[step][step], &M[i][step]);272}273274mpz_div(&x1, &M[i][step], &g);275mpz_div(&x2, &M[step][step], &g);276mpz_neg(&x2, &x2);277278for(j=step+1; j<rang;j++)279{280mpz_mul(&y1, &a1, &M[step][j]);281mpz_mul(&merk, &a2, &M[i][j]);282mpz_add(&y1, &y1, &merk);283284mpz_mul(&y2, &x1, &M[step][j]);285mpz_mul(&merk, &x2, &M[i][j]);286mpz_add(&y2, &y2, &merk);287288mpz_set(&M[step][j], &y1);289mpz_set(&M[i][j], &y2);290}291292/* inserted the next 12 lines: 4/12/96 tilman */293for (j=0;j<rows;j++){294mpz_mul(&y1, &a1, &trf[step][j]);295mpz_mul(&merk, &a2, &trf[i][j]);296mpz_add(&y1, &y1, &merk);297298mpz_mul(&y2, &x1, &trf[step][j]);299mpz_mul(&merk, &x2, &trf[i][j]);300mpz_add(&y2, &y2, &merk);301302mpz_set(&trf[step][j], &y1);303mpz_set(&trf[i][j], &y2);304}305306mpz_set(&M[step][step], &g);307mpz_set_si(&M[i][step], 0);308}309}310}311/*------------------------------------------------------*\312| Check whether the column and row are both clear313\*------------------------------------------------------*/314stepclear = TRUE;315for(i=step+1;i<cols && stepclear == TRUE;i++)316{317if(mpz_cmp_si(&M[step][i], 0) != 0)318stepclear = FALSE;319}320for(i=step+1;i<rows && stepclear == TRUE;i++)321{322if(mpz_cmp_si(&M[i][step], 0) != 0)323stepclear = FALSE;324}325}while(stepclear == FALSE);326if(mpz_cmp_si(&M[step][step], 0) < 0)327mpz_neg(&M[step][step], &M[step][step]);328329/* output for debugging purposes330printf("step = %d\n",step);331dump_MP_mat(trf,rows,rows,"trf");332dump_MP_mat(M,rows,rows,"M"); */333334}335336/* output for debugging purposes337dump_MP_mat(trf,rows,rows,"trf");338dump_MP_mat(M,rows,rows,"M"); */339340/*-------------------------------------------------------------------*\341| Multiply trf with Mat342\*-------------------------------------------------------------------*/343M1 = matrix_to_MP_mat(Mat);344if( (M2 = (MP_INT **)malloc(rang *sizeof(MP_INT *))) == NULL)345{346printf("malloc of 'M2' in 'long_rein_mat'failed\n");347exit(2);348}349for(i=0;i<rang;i++)350{351if( (M2[i] = (MP_INT *)malloc(cols *sizeof(MP_INT))) == NULL)352{353printf("malloc of 'M2[%d]' in 'long_rein_mat'failed\n", i);354exit(2);355}356for(j=0;j<cols;j++)357mpz_init(&M2[i][j]);358}359for(i=0;i<rang;i++)360for(j=0;j<cols;j++)361{362for(k=0;k<rows;k++)363{364mpz_mul(&merk, &trf[i][k], &M1[k][j]);365mpz_add(&M2[i][j], &M2[i][j], &merk);366}367368/* changed 4/12/96 tilman from:369mpz_div(&M2[i][j], &M2[i][i], &M[i][i]);370to : */371mpz_div(&M2[i][j], &M2[i][j], &M[i][i]);372373}374375/* output for debugging purposes376dump_MP_mat(M2,rows,rows,"M2"); */377378/***************************************************************\379| make a pair_reduction to the rows of M2380\***************************************************************/381M3 = init_MP_mat(rang, rang);382for(i=0;i<rang;i++)383for(j=0;j<=i;j++)384{385for(k=0;k<cols;k++)386{387mpz_mul(&merk, &M2[i][k], &M2[j][k]);388mpz_add(&M3[i][j], &merk, &M3[i][j]);389}390}391for(i=0;i<rang;i++)392for(j=0;j<i;j++)393mpz_set(&M3[j][i], &M3[i][j]);394395/* output for debugging purposes396dump_MP_mat(M3,rows,rows,"M3"); */397398T1 = init_MP_mat(rang, rang);399for(i=0;i<rang;i++)400mpz_set_si(&T1[i][i], 1);401MP_pair_red(M3, T1, rang);402403/* output for debugging purposes404dump_MP_mat(T1,rows,rows,"T1"); */405406M4 = init_MP_mat(rang, cols);407for(i=0;i<rang;i++)408for(j=0;j<cols;j++)409for(k=0;k<rang;k++)410{411mpz_mul(&merk, &T1[i][k], &M2[k][j]);412mpz_add(&M4[i][j], &M4[i][j], &merk);413}414415/* output for debugging purposes416dump_MP_mat(M4,rows,rows,"M4"); */417418erg = MP_mat_to_matrix(M4, rang, cols);419420free_MP_mat(M, rows, cols); free(M);421free_MP_mat(M1, rows, cols); free(M1);422free_MP_mat(M2, rang, cols); free(M2);423free_MP_mat(M3, rang, rang); free(M3);424free_MP_mat(M4, rang, cols); free(M4);425free_MP_mat(trf, rows,rows); free(trf);426/* changed 11/3/97 tilman from427free_MP_mat(T1, rang, rang); free(M2);428to: */429free_MP_mat(T1, rang, rang); free(T1);430merkpointer = NULL;431mpz_clear(&a1), mpz_clear(&a2);432mpz_clear(&x1), mpz_clear(&x2);433mpz_clear(&y1), mpz_clear(&y2);434mpz_clear(&f), mpz_clear(&g);435mpz_clear(&merk);436return(erg);437}438439/*************************************************************************440@441@------------------------------------------------------------------------442@443@ void long_rein_formspace(matrix_TYP **forms,int number,int option)444@445@ option: drives the behaviour of the function, for446@ option == 0 there is no assumption on the symetry447@ of these matrices made.448@ option == 1 the matrices are assumed to be symetric.449@ option == 2 the matrices are assumed to be skew symetric.450@451@------------------------------------------------------------------------452@453**************************************************************************/454int long_rein_formspace(matrix_TYP **forms,int number,int option)455{456int i,457j,458k,459l,460rank,461dim = forms[0]->cols;462463matrix_TYP *rein,464*res;465466if (option == 0){467rein = init_mat(number,dim*dim,"");468}469else if (option == 1){470rein = init_mat(number,(dim*(dim+1))/2,"");471}472else if (option == 2){473rein = init_mat(number,(dim*(dim+2))/2,"");474}475else{476fprintf(stderr,"you must specify one of the options 0,1,2 in");477fprintf(stderr," long_rein_formspace\n");478exit(1);479}480481for (i=0;i<number;i++){482l=0;483for (j=0;j<dim;j++){484if (option == 0){485for (k=0;k<dim;k++){486rein->array.SZ[i][l] = forms[i]->array.SZ[j][k];487l++;488}489}490else if (option == 1){491for (k=0;k<=j;k++){492rein->array.SZ[i][l] = forms[i]->array.SZ[j][k];493l++;494}495}496else{497for (k=0;k<j;k++){498rein->array.SZ[i][l] = forms[i]->array.SZ[j][k];499l++;500}501}502}503}504505res = long_rein_mat(rein);506507for (i=0;i<res->rows;i++){508l=0;509for (j=0;j<dim;j++){510if (option == 0){511for (k=0;k<dim;k++){512forms[i]->array.SZ[j][k] = res->array.SZ[i][l];513l++;514}515}516else if (option == 1){517for (k=0;k<=j;k++){518forms[i]->array.SZ[j][k] = res->array.SZ[i][l];519forms[i]->array.SZ[k][j] = res->array.SZ[i][l];520l++;521}522}523else{524for (k=0;k<j;k++){525forms[i]->array.SZ[j][k] = res->array.SZ[i][l];526forms[i]->array.SZ[k][j] = -res->array.SZ[i][l];527l++;528}529forms[i]->array.SZ[j][j] = 0;530}531}532}533534rank = res->rows;535536for (i=0;i<number;i++) Check_mat(forms[i]);537538free_mat(rein);539free_mat(res);540541return rank;542}543544545