GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#include "typedef.h"1#include "matrix.h"2#include "tools.h"3/**************************************************************************\4@---------------------------------------------------------------------------5@---------------------------------------------------------------------------6@ FILE: elt_div_mat.c7@---------------------------------------------------------------------------8@---------------------------------------------------------------------------9@10\**************************************************************************/1112/*{{{}}}*/13/*{{{ local typedefs*/14/*15* local typedefs, only used in this file.16*/17typedef struct18{19int f1, f2, g1, g2;20} elt_div_pair;21typedef struct22{23int low, hi;24} elt_div_prod;2526/*}}} */27/*{{{ mindivmod, static*/28/*============================================================*\29|| ||30|| Loest azahl = prod.hi * bzahl + prod.low mit (meistens) ||31|| prod.low <= bzahl/2 ||32|| ||33\*============================================================*/3435elt_div_prod ZZ_mindivmod(azahl,bzahl)36int azahl,bzahl;37{38elt_div_prod c;39int q_signum, r_signum;4041c.hi = c.low = 0;42r_signum = azahl ? ( azahl > 0 ? 1 : -1 ) : 0;43q_signum = bzahl ? ( bzahl > 0 ? 1 : -1 ) : 0;44q_signum = r_signum == q_signum ? 1 : -1;4546azahl= abs(azahl);47bzahl= abs(bzahl);48c.hi = azahl / bzahl;49c.low= azahl % bzahl;50if ( (c.low * 2 ) > bzahl ) {51c.hi++;52c.low = bzahl - c.low;53r_signum *= -1;54}55c.hi *= q_signum;56c.low *= r_signum;57return(c);58}5960/*}}} */61/*{{{ euclid, static*/62/*63*64* static elt_div_pair euclid(a,b);65*66* /a\ /ggt(a,b)\67* berechnet Matrix A so, dass A * | | = | |68* \b/ \ 0 /69*70*/71static elt_div_pair euclid(a,b) /* frei nach gap */72int a,b;73{74elt_div_pair r;75elt_div_prod temp;76int s1, t1, s, t, q, d, ha, hb;7778temp.hi =79temp.low =80ha =81hb =82s1 =83t =84q =85d =86r.f1 =87r.f2 =88r.g1 =89r.g2 = 0;90t1 =91s = 1;92if (a < 0) {93s = -1;94}95hb= abs(b);96ha= abs(a);97while (hb != 0) {98temp = ZZ_mindivmod(ha,hb);99q = temp.hi;100temp.hi = 0;101ha = hb;102hb = temp.low;103temp.low = 0;104t1 = t;105t = -t*q + s;106s = t1;107}108r.g1 = t;109r.f1 = s;110s = ha - s * a;111r.f2 = s/b;112t *= a;113r.g2 = - t/b;114return r;115}116117/*}}} */118119/*{{{ elt_func, static*/120static matrix_TYP *elt_func ( mat )121matrix_TYP *mat;122{123int min_sum, sum,**E, h,*v, _min_;124int min_col, min_row, rM, cM, i, j, k,l;125boolean rc_min, flag, Global_flag;126#ifdef DEBUG127char *temp = "tempA";128#endif129matrix_TYP *elt;130elt_div_pair paar;131132Global_flag = FALSE;133134if ( !(mat->flags.Integral & 1)) {135fprintf (stderr, "Elementary divisors of a rational matrix ??\n");136exit (3);137}138/*------------------------------------------------------------*\139| Copy mat->array.SZ into E |140\*------------------------------------------------------------*/141rM = mat->rows;142cM = mat->cols;143h =144_min_ =145min_sum =146sum = 0;147elt = copy_mat(mat);148E = elt->array.SZ;149rc_min = TRUE;150for ( i = 0; i < cM; i++) {151#ifdef DEBUG152if (Global_flag)153put_mat(elt,temp,NULL,0);154temp[4]++;155#endif156/*---------------------------------------------------------*\157| Extended Version: Try to decrease the entries of the |158| matrix by using linear combinations of rows and columns |159\*---------------------------------------------------------*/160if (E[i][i] != 0) {161for(j = i+1; j < rM; j++) {162if((h= min_div(E[j][i],E[i][i])) != 0) {163if( h == 1 ) {164for(k = i; k < cM; k++) {165if (E[i][k] != 0) {166E[j][k] -= E[i][k];167}168}169} else if (h == -1) {170for(k = i; k < cM; k++) {171if (E[i][k] != 0) {172E[j][k] += E[i][k];173}174}175} else {176for(k = i; k < cM; k++) {177if (E[i][k] != 0) {178E[j][k] -= h*E[i][k];179}180}181}182}183}184for(j = i+1; j < cM; j++) {185if((h= min_div(E[i][j],E[i][i])) != 0) {186if(h == 1) {187for(k = i; k < rM; k++) {188if (E[k][i] != 0) {189E[k][j] -= E[k][i];190}191}192} else if (h == -1) {193for(k = i; k < rM; k++) {194if (E[k][i] != 0) {195E[k][j] += E[k][i];196}197}198} else {199for(k = i; k < rM; k++) {200if (E[k][i] != 0) {201E[k][j] -= h*E[k][i];202}203}204}205}206}207}208/* put_mat(elt,NULL,NULL,0); */209/*{{{ */210/*----------------------------------------------------------*\211| Second extension: Trying to decrease the Entries of the |212| matrix by using a modificated pair Reduction. |213| (But it seems to make it slower in some cases)214\*----------------------------------------------------------215if ((i%3) == 0) {216for(l = i+1; (l < rM) && (l < cM); l++) {217if(E[l][l] != 0) {218for(j = i+1; j < rM; j++)219if(j != l) {220if((h= min_div(E[j][l],E[l][l])) != 0) {221if(h == 1)222for(k = i; k < cM; k++) {223if (E[l][k] != 0) E[j][k] -= E[l][k];224}225else if (h == MINUS_1)226for(k = i; k < cM; k++) {227if (E[l][k] != 0) E[j][k] += E[l][k];228}229else230for(k = i; k < cM; k++) {231if (E[l][k] != 0) E[j][k] -= h*E[l][k];232}233}234}235for(j = i+1; j < cM; j++)236if(j != l) {237if((h= min_div(E[l][j],E[l][l])) != 0) {238if(h == 1)239for(k = i; k < rM; k++) {240if (E[k][l] != 0) E[k][j] -= E[k][l];241}242else if (h == MINUS_1)243for(k = i; k < rM; k++) {244if (E[k][l] != 0) E[k][j] += E[k][l];245}246else247for(k = i; k < rM; k++) {248if (E[k][l] != 0) E[k][j] -= h*E[k][l];249}250}251}252}253}254put_mat(elt,NULL,NULL,2);255}*/256/*}}} */257/*---------------------------------------------------------*\258| Find the minimum of all abs. values of non-zero entries |259| in the remaining (rM - i)-dimensional lower right |260| submatrix |261\*---------------------------------------------------------*/262263flag = TRUE;264min_row = min_col = i;265_min_ = 0;266for ( j = i; (j < rM); j++ ) {267for (k = i; (k < cM); k++) {268if ( E[j][k] != 0 ) {269if (_min_ == 0) {270_min_= abs(E[j][k]);271min_row = j;272min_col = k;273if (rc_min) {274min_sum = 0;275for(l = i; l < rM; l++) {276if (E[l][k] < 0) {277min_sum -= E[l][k];278} else {279min_sum += E[l][k];280}281}282}283} else {284flag = abs(E[j][k]) == abs(_min_) ? 0 : (abs(E[j][k]) < abs(_min_) ? -1 : 1 );285if ( flag == -1 ) {286_min_= abs(E[j][k]);287if ((rc_min) && (k != min_col)) {288min_sum = 0;289for(l = i; l < rM; l++) {290if (E[l][k] < 0) {291min_sum -= E[l][k];292} else {293min_sum += E[l][k];294}295}296}297min_row = j;298min_col = k;299} else if((rc_min) && (flag == 0) && (k!= min_col)) {300sum = 0;301for(l = i; l < rM; l++) {302if (E[l][k] < 0) {303sum -= E[l][k];304} else {305sum += E[l][k];306}307}308if(sum < min_sum) {309min_row = j;310min_col = k;311min_sum = sum;312sum = 0;313}314}315}316}317}318}319if( _min_ == 0) {320goto ende;321}322if( _min_ == 1) {323flag = FALSE;324} else {325flag = TRUE;326}327rc_min = TRUE; /* (min & 0); */328329/*---------------------------------------------------------*\330| Swap the min-entry into upper left corner |331\*---------------------------------------------------------*/332v = E[i];333E[i] = E[min_row];334E[min_row] = v;335for ( j = i; j < rM; j++ ) {336h = E[j][i];337E[j][i] = E[j][min_col];338E[j][min_col] = h;339}340h = 0;341342/*------------------------------------------------------*\343| try to decrease the min using linear combinations |344| of rows |345\*------------------------------------------------------*/346marke:347if ( flag ) {348for(j = rM-1; flag && (j > i); j--) {349if ( (h = E[j][i]%_min_) != 0 ) {350paar = euclid (E[i][i], E[j][i]);351/* find differences for momo352sprintf(comment,"%d %d", i,j);353put_mat(elt,NULL,comment,0); */354355for ( k = i; k < cM ; k++) {356h += E[i][k]*paar.f1+E[j][k]*paar.f2;357E[j][k]= E[j][k]*paar.g2+E[i][k]*paar.g1;358E[i][k] = h;359}360if ( (_min_= abs(E[i][i])) == 1 ) {361flag = FALSE;362}363}364}365}366if ( flag ) {367/*------------------------------------------------------*\368| try to decrease the min using linear combinations |369| of columns |370\*------------------------------------------------------*/371for ( j = cM-1; j > i; j--) {372if ( (h= E[i][j]%_min_) != 0 ) {373paar = euclid (E[i][i], E[i][j]);374for ( k = i; k < rM; k++) {375h += E[k][i]*paar.f1+E[k][j]*paar.f2;376E[k][j] = E[k][j]*paar.g2 + E[k][i]*paar.g1;377E[k][i] = h;378}379if ( (_min_ = abs(E[i][i])) == 1 ) {380flag = FALSE;381}382}383}384}385/*---------------------------------------------------------*\386| Clear the i-th column |387\*---------------------------------------------------------*/388for(j = i+1; j < rM ; j++ ) {389h=E[j][i]/E[i][i];390if (h != 0) {391for ( k = i; k < cM ; k++ ) {392if(E[i][k] != 0) {393E[j][k] -= h*E[i][k];394}395}396}397if(E[j][i] != 0) {398goto marke;399}400}401/*---------------------------------------------------------*\402| Clear the i-th row |403\*---------------------------------------------------------*/404E[i][i] = abs(E[i][i]);405for (j = i+1; j < cM; j++) {406E[i][j] = 0;407}408}409ende:410for (i = 1; i < elt->cols; i++) {411if ( (E[i][i] % E[i-1][i-1]) != 0 ) {412h= E[i-1][i-1];413E[i-1][i-1]= GGT( E[i][i], h);414h /= E[i-1][i-1];415E[i][i] *= h;416if (i > 1) {417i -= 2;418}419}420}421for (i = 0; i < elt->cols; i++) {422if ( E[i][i] < 0 ) {423E[i][i] = -E[i][i];424}425}426427for (i = 1; i < elt->cols; i++) {428elt->array.SZ[0][i] = elt->array.SZ[i][i];429}430for (i = 1; i < elt->rows; i++) {431free(elt->array.SZ[i]);432if( elt->array.N != NULL ) {433free(elt->array.N[i]);434}435}436elt->rows = 1;437Check_mat(elt);438return (elt);439}440441/*}}} */442/*{{{ elt_div*/443/*444@-----------------------------------------------------------------445@ matrix_TYP *elt_div(Mat)446@ matrix_TYP *Mat;447@448@ computes elementary divisors of Mat.449@ Result is a matrix with a single row that contains the450@ divisors.451@-----------------------------------------------------------------452*/453matrix_TYP *elt_div(Mat)454matrix_TYP *Mat;455{456matrix_TYP *Elt, *tmp;457458if(null_mat(Mat)) {459Elt = init_mat(1,1,"0");460return(Elt);461}462463if (Mat->rows >= Mat->cols) {464Elt = ggauss(Mat);465tmp = tr_pose(Elt);466free_mat(Elt);467tgauss(tmp);468} else {469tmp = tr_pose(Mat);470Elt = ggauss(tmp);471free_mat(tmp);472tmp = tr_pose(Elt);473free_mat(Elt);474tgauss(tmp);475}476Elt = elt_func(tmp);477free_mat(tmp);478return(Elt);479}480/*}}} */481482483