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 "bravais.h"34/**************************************************************************\5@---------------------------------------------------------------------------6@---------------------------------------------------------------------------7@ FILE: lincomb.c8@---------------------------------------------------------------------------9@---------------------------------------------------------------------------10@11\**************************************************************************/1213/**************************************************************************\14@---------------------------------------------------------------------------15@ matrix_TYP *vec_to_form(v, F, Fanz)16@ int *v;17@ matrix_TYP **F;18@ int Fanz;19@20@ calculates the matrix v[1] F[1] + v[2] F[2] +....+v[Fanz-1] F[Fanz-1}21@---------------------------------------------------------------------------22@23\**************************************************************************/2425matrix_TYP *vec_to_form(v, F, Fanz)26int *v;27matrix_TYP **F;28int Fanz;29{30int i,j,k, n,m;31matrix_TYP *M;32int sym;3334n = F[0]->rows;35m = F[0]->cols;36for(i=1;i<Fanz;i++)37{38if(F[i]->rows != n || F[i]->cols != m)39{40printf(" Different size of matrices in vec_to_form\n");41exit(3);42}43}44i=0; sym = TRUE;45while(i<Fanz && F[i]->flags.Symmetric == TRUE)46i++;47if(i<Fanz)48sym = FALSE;4950if(sym == FALSE)51{52M = init_mat(n,m, "");53for(i=0;i<Fanz;i++)54{55if(v[i] != 0)56{57for(j=0;j<n;j++)58for(k=0;k<m;k++)59M->array.SZ[j][k] += v[i] * F[i]->array.SZ[j][k];60}61}62}63else64{65M = init_mat(n,m, "s");66for(i=0;i<Fanz;i++)67{68if(v[i] != 0)69{70for(j=0;j<n;j++)71for(k=0; k<=j; k++)72M->array.SZ[j][k] += v[i] * F[i]->array.SZ[j][k];73}74}75for(j=0;j<n;j++)76for(k=0;k<j;k++)77M->array.SZ[k][j] = M->array.SZ[j][k];78}79Check_mat(M);80return(M);81}82838485/**************************************************************************\86@---------------------------------------------------------------------------87@ void form_to_vec(erg, A, F, Fanz, denominator)88@ int *erg;89@ matrix_TYP *A, **F;90@ int Fanz, *denominator;91@92@ calculates a vector v such that A = 1/d(v[0]F[0] +...+v[Fanz-1]F[Fanz-1]93@ and writes it onto the vector erg.94@ the space for erg must be allocated before using this function.95@ the integer d is returned via the pointer denominator.96@---------------------------------------------------------------------------97@98\**************************************************************************/99void form_to_vec(erg, A, F, Fanz, denominator)100int *erg;101matrix_TYP *A, **F;102int Fanz, *denominator;103{104int i,j,k,l, n,m,r;105matrix_TYP *X, *X1, *Trf;106int sym, rang;107108n = F[0]->rows;109m = F[0]->cols;110for(i=1;i<Fanz;i++)111{112if(F[i]->rows != n || F[i]->cols != m)113{114printf(" Different size of matrices in form_to_vec\n");115exit(3);116}117}118i=0; sym = TRUE;119while(i<Fanz && F[i]->flags.Symmetric == TRUE)120i++;121if(i<Fanz)122sym = FALSE;123124if(sym == FALSE)125{126r = n*m;127X = init_mat(r,Fanz+1, "");128for(i=0;i<Fanz;i++)129{130l = 0;131for(j=0;j<n;j++)132for(k=0;k<n;k++)133{ X->array.SZ[l][i] = F[i]->array.SZ[j][k]; l++;}134}135l = 0;136for(j=0;j<n;j++)137for(k=0;k<n;k++)138{ X->array.SZ[l][Fanz] = A->array.SZ[j][k]; l++;}139}140else141{142r = (n*(n+1))/2;143X = init_mat(r,Fanz+1, "");144for(i=0;i<Fanz;i++)145{146l = 0;147for(j=0;j<n;j++)148for(k=0;k<=j;k++)149{ X->array.SZ[l][i] = F[i]->array.SZ[j][k]; l++;}150}151l = 0;152for(j=0;j<n;j++)153for(k=0;k<=j;k++)154{ X->array.SZ[l][Fanz] = A->array.SZ[j][k]; l++;}155}156X->rows = Fanz-1;157do158{159X->rows++;160161/* tilman: changed 02/09/97 from (to avoid overflow)162rang = long_row_gauss(X); */163rang = long_row_basis(X,FALSE);164165}while(X->rows < r && rang != Fanz);166167if(X->rows == r && rang != Fanz)168{169printf("Matrices F in form_to_vec are not linear independent\n");170exit(3);171}172X->rows = rang;173X1 = tr_pose(X);174X->rows = r;175free_mat(X);176Trf = init_mat(X1->rows, X1->rows, "");177long_row_trf_gauss(X1, Trf);178free_mat(X1);179if(Trf->array.SZ[Fanz][Fanz] == 0)180{181printf("Matrices F in form_to_vec are not linear independent\n");182exit(3);183}184if(Trf->array.SZ[Fanz][Fanz] < 0)185{186for(i=0;i<Fanz;i++)187erg[i] = Trf->array.SZ[Fanz][i];188*denominator = - Trf->array.SZ[Fanz][Fanz];189}190if(Trf->array.SZ[Fanz][Fanz] > 0)191{192for(i=0;i<Fanz;i++)193erg[i] = - Trf->array.SZ[Fanz][i];194*denominator = Trf->array.SZ[Fanz][Fanz];195}196free_mat(Trf);197}198199/**************************************************************************\200@---------------------------------------------------------------------------201@ vertex_TYP *form_to_vertex(A, F, Fanz, denominator)202@ matrix_TYP *A, **F;203@204@ calculates a vector v such that A = 1/d(v[0]F[0] +...+v[Fanz-1]F[Fanz-1]205@ and returns it as V->v in a vertex_TYP V..206@ The integer d is returned via the pointer denominator.207@---------------------------------------------------------------------------208@209\**************************************************************************/210vertex_TYP *form_to_vertex(A, F, Fanz, denominator)211matrix_TYP *A, **F;212int Fanz, *denominator;213{214vertex_TYP *v;215extern vertex_TYP *init_vertex();216v = init_vertex(Fanz, 0);217form_to_vec(v->v, A, F, Fanz, denominator);218}219220221/**************************************************************************\222@---------------------------------------------------------------------------223@ void form_to_vec_modular(erg, A, F, Fanz)224@ matrix_TYP *A, **F;225@ int *erg, Fanz;226@227@ the same as form_to_vec, but works only if the linear combination is228@ integral, i.e. the denominator is assumed to be 1.229@ the function calculated the result modulo big primes and fits it230@ together with the chinese remainder theorem.231@ This is faster as form_to_vec and avoids overflow.232@---------------------------------------------------------------------------233@234\**************************************************************************/235void form_to_vec_modular(erg, A, F, Fanz)236matrix_TYP *A, **F;237int *erg, Fanz;238{239240int i,j,k,l;241int p1, p2, a1, a2, y1, y2;242matrix_TYP **X1, **X2;243matrix_TYP *G1, *G2;244int X1anz, X2anz;245int n, m;246double q, res, q1, q2;247double waste;248int symmetric;249250p1 = 65521; p2 = 65519;251n = A->cols;252for(i=0;i<Fanz;i++)253{254if(F[i]->cols != n)255{256printf("error: matrices in 'form_to_vec_modular' have different number of cols\n");257exit(3);258}259}260n = A->rows;261for(i=0;i<Fanz;i++)262{263if(F[i]->rows != n)264{265printf("error: matrices in 'form_to_vec_modular' have different number of rows\n");266exit(3);267}268}269270symmetric = A->flags.Symmetric;271for(i=0;i<Fanz;i++)272{273if(F[i]->flags.Symmetric == FALSE)274symmetric = FALSE;275}276if(symmetric)277n = (A->cols * (A->cols + 1))/2;278else279n = A->cols * A->rows;280G1 = init_mat(n, Fanz, "");281G2 = init_mat(n, 1, "");282if(symmetric)283{284l = 0;285for(i=0;i<A->cols;i++)286for(j=0;j<=i;j++)287{288for(k=0;k<Fanz;k++)289G1->array.SZ[l][k] = F[k]->array.SZ[i][j];290G2->array.SZ[l][0] = A->array.SZ[i][j];291l++;292}293}294else295{296l = 0;297for(i=0;i<A->rows;i++)298for(j=0;j<A->cols;j++)299{300for(k=0;k<Fanz;k++)301G1->array.SZ[l][k] = F[k]->array.SZ[i][j];302G2->array.SZ[l][0] = A->array.SZ[i][j];303l++;304}305}306307X1 = p_lse_solve(G1, G2, &X1anz, p1);308X2 = p_lse_solve(G1, G2, &X2anz, p2);309if(X1anz == 0 || X2anz == 0)310{311printf("error in 'form_to_vec_modular':\n");312printf("The matrix A is not in the Z-span of the matrices F[0],..,F[%d],\n", (Fanz-1));313exit(3);314}315if(X1anz != 1 || X2anz != 1)316{317printf("error in 'form_to_vec_modular':\n");318printf("The matrix A is not in the Z-span of the matrices F[0],..,F[%d],\n", (Fanz-1));319printf("or F[0],...,F[%d] are not independent over the field with");320if(X1anz != 1) printf(" %d ", p1);321if(X2anz != 1) printf(" %d ", p2);322printf("elements\n");323exit(3);324}325a1 = p_inv(p2, p1);326a2 = p_inv(p1, p2);327q = ((double) p1) * ((double) p2);328q1 = ((double) p2) * ((double) a1);329q2 = ((double) p1) * ((double) a2);330331for(i=0;i<Fanz;i++)332{333erg[i] = 0;334y1 = X1[0]->array.SZ[i][0];335y2 = X2[0]->array.SZ[i][0];336if(y1 == y2)337erg[i] = y1;338else339{340res = ((double) y1) * q1 + ((double) y2) * q2;341modf(res/q, &waste);342res = res - waste * q;343while( (res/q) > 0.5)344res = res -q;345while( (res/q) < -0.5)346res = res + q;347erg[i] = ((int) res);348}349}350/*****************************************************************\351| Ckeck if the modular result is also integrally correct352\*****************************************************************/353for(i=0; i<n;i++)354{355y1 = -(G2->array.SZ[i][0]);356for(k=0;k<Fanz;k++)357y1 += G1->array.SZ[i][k] * erg[k];358if(y1 != 0)359{360printf("Sorry: Overflow in 'form_to_vec_modular'\n");361exit(3);362}363}364free_mat(X1[0]); free_mat(X2[0]);365free(X1); free(X2);366free_mat(G1); free_mat(G2);367}368369370