GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#include"typedef.h"1#include"matrix.h"23/**************************************************************************\4@---------------------------------------------------------------------------5@---------------------------------------------------------------------------6@ FILE: rform.c7@---------------------------------------------------------------------------8@---------------------------------------------------------------------------9@10\**************************************************************************/1112#define DEFEPS 10013#define DEFPRIME 514#define MAXDEN 100000015#define MAXSTEP 1000016#define JUMP 517#define EPS 0.0000011819static double ***g, **x, **xt, **t, **t1, diff, diff1;20static int dim, num;21static double **sxt, **st, **st1, err, sdiff, sdiff1;2223242526static int ggt(a, b)27int a, b;28{29int r;3031if (b == 0)32return(abs(a));3334while ((r = a % b) != 0)35{36a = b;37b = r;38}39return (abs(b));40}41424344static void rmatfac(A, m, B, n)45double **A, **B, m;46int n;47{48double *a, *b;49int i, j;505152for (i = 0; i < n; ++i)53{54a = A[i];55b = B[i];56for (j = 0; j < n; ++j)57b[j] = a[j] * m;58}59}60616263static int rmatone(A, n)64double **A;65int n;66{67int i, j;686970for (i = 0; i < n; ++i)71{72if (fabs(A[i][i] - 1.0) > EPS)73return 0;74for (j = 0; j < n; ++j)75{76if (j != i && fabs(A[i][j]) > EPS)77return 0;78}79}80return 1;81}828384static void rmatadd(A, B, C, n)85double **A, **B, **C;86int n;87{88double *a, *b, *c;89int i, j;909192for (i = 0; i < n; ++i)93{94a = A[i];95b = B[i];96c = C[i];97for (j = 0; j < n; ++j)98c[j] = a[j] + b[j];99}100}101102103104static void rmatmul(A, B, C, n)105double **A, **B, **C;106int n;107{108double *a, c;109int i, j, k;110111112for (i = 0; i < n; ++i)113{114a = A[i];115for (j = 0; j < n; ++j)116{117c = 0;118for (k = 0; k < n; ++k)119{120if (a[k] != 0.0 && B[k][j] != 0.0)121c += a[k] * B[k][j];122}123C[i][j] = c;124}125}126}127128129static void rmattrans(A, B, C, n)130double **A, **B, **C;131int n;132{133double **D, *d, c;134int i, j, k;135136137if ((D = (double**)malloc(n * sizeof(double))) == 0)138exit (2);139for (i = 0; i < n; ++i)140{141if ((D[i] = (double*)malloc(n * sizeof(double))) == 0)142exit (2);143}144145rmatmul(B, A, D, n);146147for (i = 0; i < n; ++i)148{149d = D[i];150for (j = 0; j < n; ++j)151{152c = 0;153for (k = 0; k < n; ++k)154c += d[k] * B[j][k];155C[i][j] = c;156}157}158159for (i = 0; i < n; ++i)160free(D[i]);161free(D);162}163164165166167168static int gcd(f, dim)169int **f, dim;170{171int n, i, j;172173n = f[0][0];174for (i = 0; i < dim; ++i)175{176for (j = 0; j < dim; ++j)177{178if (f[i][j] != 0)179n = ggt(n, f[i][j]);180if (n == 1)181return 1;182}183}184if (n == 0)185return 1;186else187return n;188}189190static int rond(X)191double X;192{193if (X >= 0)194return (int)(2*fabs(X) + 1.0) / 2;195else196return -((int)(2*fabs(X) + 1.0) / 2);197}198199static int chain(X, e)200double X, e;201{202double *r, rest;203int i, *a, step, temp, nm = 0, dn = 1;204double cond;205206/* inserted tilman 05/06/97 */207if (e<EPS) e = EPS;208cond = e;209210if ((r = (double*)malloc(sizeof(double))) == 0)211exit (2);212if ((a = (int*)malloc(sizeof(int))) == 0)213exit (2);214temp = fabs(X);215rest = fabs(X) - temp;216step = 0;217r[0] = rest;218219/* added the cond restriction because of numerical problems.220for the formula of it see the expansion of 1/(x + epsilon) */221while ((fabs(rest - (double)nm / (double)dn) > e ) &&222((cond = fabs(cond / r[step]/ r[step]))< 1.0))223{224++step;225if ((r = (double*)realloc(r, (step+1) * sizeof(double))) == 0)226exit (2);227if ((a = (int*)realloc(a, step * sizeof(int))) == 0)228exit (2);229230a[step-1] = rond(1/r[step-1]);231r[step] = 1/r[step-1] - a[step-1];232nm = 1;233dn = a[step-1];234for (i = step-2; i >= 0; --i)235{236temp = dn;237dn = a[i] * dn + nm;238nm = temp;239}240241}242free(r);243free(a);244return abs(dn);245}246247248249static int dtoi(y, f, ep, dim)250double **y, ep;251int **f, dim;252{253int i, j, den, max;254255max = 1;256for (i = 0; i < dim; ++i)257{258for (j = 0; j < dim; ++j)259{260den = 1;261/* changed 05/06/97 tilman from262f[i][j] = y[i][j]; to: */263f[i][j] = floor(y[i][j] + 0.5);264if (fabs(y[i][j] - (double)f[i][j]) >= ep)265{266if (y[i][j] > 0 &&267fabs(y[i][j]-(double)f[i][j]-1.0) < ep)268f[i][j] += 1;269else if (y[i][j] < 0 &&270fabs(y[i][j]-(double)f[i][j]+1.0) < ep)271f[i][j] -= 1;272else273{274den = chain(y[i][j], ep);275if (den > max)276max = den;277}278}279}280}281return max;282}283284285286static int iterate(step, x, g, num, dim)287double **x, ***g;288int step, num, dim;289{290double factor;291int i, j, k;292293rmatfac(x, 1.0, st, dim);294rmatfac(x, 1.0, sxt, dim);295for (k = 0; k < JUMP; ++k)296{297++step;298for (i = 0; i < num; ++i)299{300rmattrans(x, g[i], st1, dim);301rmatadd(st, st1, st, dim);302}303for (i = 0; i < dim; ++i)304{305for (j = 0; j < dim; ++j)306{307st[i][j] *= 1/(double)(num+1);308x[i][j] = st[i][j];309}310}311}312313sdiff1 = 0;314for (i = 0; i < dim; ++i)315{316for (j = 0; j < dim; ++j)317{318if (sdiff1 < fabs(sxt[i][j] - x[i][j]))319sdiff1 = fabs(sxt[i][j] - x[i][j]);320}321}322323rmatfac(x, 1.0, sxt, dim);324for (k = 0; k < JUMP; ++k)325{326++step;327for (i = 0; i < num; ++i)328{329rmattrans(x, g[i], st1, dim);330rmatadd(st, st1, st, dim);331}332for (i = 0; i < dim; ++i)333{334for (j = 0; j < dim; ++j)335{336st[i][j] *= 1/(double)(num+1);337x[i][j] = st[i][j];338}339}340}341342sdiff = 0;343for (i = 0; i < dim; ++i)344{345for (j = 0; j < dim; ++j)346{347if (sdiff < fabs(sxt[i][j] - x[i][j]))348sdiff = fabs(sxt[i][j] - x[i][j]);349}350}351352if (sdiff == 0 || sdiff1 == 0)353err = 0.0;354else355{356factor = pow(sdiff/sdiff1, 1.0/(double)JUMP);357if (factor >= 1)358err = 1;359else360err = sdiff*sdiff/(sdiff1-sdiff);361/* printf("step %d: sdiff = %.12lf err: %.12lf factor: %.12lf\n",362step, sdiff, err, 1/factor); */363}364return step;365}366367368static int symel(x, g, num, dim, eps, f)369double **x, ***g;370int num, dim, eps, **f;371{372int gc, i, j, k, den, maxden, step, neweps;373374if ((sxt = (double**)malloc(dim * sizeof(double*))) == 0)375exit (2);376if ((st = (double**)malloc(dim * sizeof(double*))) == 0)377exit (2);378if ((st1 = (double**)malloc(dim * sizeof(double*))) == 0)379exit (2);380for (i = 0; i < dim; ++i)381{382if ((sxt[i] = (double*)malloc(dim * sizeof(double))) == 0)383exit (2);384if ((st[i] = (double*)malloc(dim * sizeof(double))) == 0)385exit (2);386if ((st1[i] = (double*)malloc(dim * sizeof(double))) == 0)387exit (2);388}389for (i = 0; i < dim; ++i)390{391for (j = 0; j < dim; ++j)392st[i][j] = x[i][j];393}394395step = 0;396err = 1.0;397step = iterate(step, x, g, num, dim);398while (err > 0.3/(double)eps && step < MAXSTEP)399step = iterate(step, x, g, num, dim);400if (step >= MAXSTEP)401{402printf("Verfahren hat nach %d Schritten nicht konvergiert !\n", step);403exit(3);404return 0;405}406den = 0;407while (den != 1)408{409den = dtoi(x, f, 2*err, dim);410if (den != 1)411{412maxden = den+1;413while (maxden > den && maxden < MAXDEN)414{415neweps = (maxden < eps) ? eps*maxden : maxden*maxden;416417/* inserted tilman 09/06/97 */418if (1/(double) neweps < EPS) neweps = 1/EPS;419420while (err > 0.3/(double)neweps && step < MAXSTEP)421step = iterate(step, x, g, num, dim);422if (step >= MAXSTEP)423{424printf("Verfahren hat nach %d Schritten nicht konvergiert !\n", step);425exit(3);426return 0;427}428den = maxden;429/* printf("Versuch mit %d\n", den); */430maxden = dtoi(x, f, 2*err, dim);431}432rmatfac(x, (double)maxden, x, dim);433/* printf("Nenner mit %d multipliziert\n", maxden);*/434err *= maxden;435}436}437438gc = gcd(f, dim);439/* printf("ggt %d\n", gc);440*/ for (i = 0; i < dim; ++i)441{442for (j = 0; j < dim; ++j)443{444f[i][j] /= gc;445st[i][j] = (double)f[i][j];446}447}448for (i = 0; i < num; ++i)449{450rmattrans(st, g[i], st1, dim);451for (j = 0; j < dim; ++j)452{453for (k = 0; k < dim; ++k)454{455if (st1[j][k] != st[j][k])456{457printf("Matrix tuts nicht !\n");458exit(3);459return 0;460}461}462}463}464for(i=0;i<dim;i++)465{ free(sxt[i]); free(st[i]); free(st1[i]);}466free(sxt); free(st); free(st1);467return (step);468}469470471472static double try()473{474double conv;475int i, j, k;476477rmatfac(x, 1.0, t, dim);478for (k = 0; k < 4; ++k)479{480for (i = 0; i < num; ++i)481{482rmattrans(x, g[i], t1, dim);483rmatadd(t, t1, t, dim);484}485for (i = 0; i < dim; ++i)486{487for (j = 0; j < dim; ++j)488{489t[i][j] *= 1/(double)(num+1);490x[i][j] = t[i][j];491}492}493}494495rmatfac(x, 1.0, xt, dim);496for (k = 0; k < 3; ++k)497{498for (i = 0; i < num; ++i)499{500rmattrans(x, g[i], t1, dim);501rmatadd(t, t1, t, dim);502}503for (i = 0; i < dim; ++i)504{505for (j = 0; j < dim; ++j)506{507t[i][j] *= 1/(double)(num+1);508x[i][j] = t[i][j];509}510}511}512513diff1 = 0;514for (i = 0; i < dim; ++i)515{516for (j = 0; j < dim; ++j)517{518if (diff1 < fabs(xt[i][j] - x[i][j]))519diff1 = fabs(xt[i][j] - x[i][j]);520}521}522523rmatfac(x, 1.0, xt, dim);524for (k = 0; k < 3; ++k)525{526for (i = 0; i < num; ++i)527{528rmattrans(x, g[i], t1, dim);529rmatadd(t, t1, t, dim);530}531for (i = 0; i < dim; ++i)532{533for (j = 0; j < dim; ++j)534{535t[i][j] *= 1/(double)(num+1);536x[i][j] = t[i][j];537}538}539}540541diff = 0;542for (i = 0; i < dim; ++i)543{544for (j = 0; j < dim; ++j)545{546if (diff < fabs(xt[i][j] - x[i][j]))547diff = fabs(xt[i][j] - x[i][j]);548}549}550551conv = pow(diff/diff1, 1.0/3.0);552return (1/conv);553}554555556/**************************************************************************\557@---------------------------------------------------------------------------558@ matrix_TYP *rform(B, Banz, Fo, epsilon)559@ matrix_TYP **B;560@ int Banz;561@ matrix_TYP *Fo;562@ int epsilon;563@564@ If G denotes the group generated by B[0],...,B[Banz-1],565@ then 'rform' calculates a matrix A that is the sum over all g in G of566@ g^{tr} * Fo * g567@ This matrix is divided by the gcd of its entries and returned.568@ The algorithm uses an appoximation and the precession is 1/epsilon.569@ If epsilon < 100, the function sets epsilon = 100.570@---------------------------------------------------------------------------571@572\**************************************************************************/573574matrix_TYP *rform(B, Banz, Fo, epsilon)575matrix_TYP **B;576int Banz;577matrix_TYP *Fo;578int epsilon;579{580double try();581double **save, **pres, *fac, factor;582int eps, best, d, i, j, k;583matrix_TYP *erg;584int test;585586eps = epsilon;587if (eps < DEFEPS)588eps = DEFEPS;589dim = B[0]->cols;590if(B[0]->rows != dim)591{592printf("error in rform: non-square matrix in group 'B'\n");593exit(3);594}595for(i=1;i<Banz;i++)596{597if(B[i]->rows != dim || B[i]->cols != dim)598{599printf("error in rform: different dimesion of group elements\n");600exit(3);601}602}603num = Banz;604erg = init_mat(dim,dim, "k");605if ((g = (double***)malloc(num * sizeof(double**))) == 0)606exit (2);607if ((fac = (double*)malloc(num * sizeof(double))) == 0)608exit (2);609for (i = 0; i < num; ++i)610{611if ((g[i] = (double**)malloc(dim * sizeof(double*))) == 0)612exit (2);613for (j = 0; j < dim; ++j)614{615if ((g[i][j] = (double*)malloc(dim*sizeof(double)))==0)616exit (2);617for (k = 0; k < dim; ++k)618g[i][j][k] = (double)B[i]->array.SZ[k][j];619}620}621622if ((x = (double**)malloc(dim * sizeof(double*))) == 0)623exit (2);624if ((xt = (double**)malloc(dim * sizeof(double*))) == 0)625exit (2);626if ((t = (double**)malloc(dim * sizeof(double*))) == 0)627exit (2);628if ((t1 = (double**)malloc(dim * sizeof(double*))) == 0)629exit (2);630if ((save = (double**)malloc(dim * sizeof(double*))) == 0)631exit (2);632if ((pres = (double**)malloc(dim * sizeof(double*))) == 0)633exit (2);634for (i = 0; i < dim; ++i)635{636if ((x[i] = (double*)malloc(dim * sizeof(double))) == 0)637exit (2);638if ((xt[i] = (double*)malloc(dim * sizeof(double))) == 0)639exit (2);640if ((t[i] = (double*)malloc(dim * sizeof(double))) == 0)641exit (2);642if ((t1[i] = (double*)malloc(dim * sizeof(double))) == 0)643exit (2);644if ((save[i] = (double*)malloc(dim * sizeof(double))) == 0)645exit (2);646if ((pres[i] = (double*)malloc(dim * sizeof(double))) == 0)647exit (2);648}649d = Fo->cols;650if (d != dim)651{652printf("Fehler : Unkompatible Dimensionen\n");653exit (3);654}655for (i = 0; i < dim; ++i)656{657for (j = 0; j < dim; ++j)658x[i][j] = (double) Fo->array.SZ[i][j];659}660for (i = 0; i < dim; ++i)661{662for (j = 0; j < dim; ++j)663save[i][j] = x[i][j];664}665666/*667factor = try();668for (i = 0; i < num; ++i)669{670for (j = 0; j < num; ++j)671{672if (j != i)673{674rmatfac(g[i], 1.0, pres, dim);675rmatmul(g[i], g[j], t1, dim);676rmatfac(t1, 1.0, g[i], dim);677fac[j] = try();678rmatfac(pres, 1.0, g[i], dim);679rmatfac(save, 1.0, x, dim);680}681}682fac[i] = factor;683best = i;684for (j = 0; j < num; ++j)685{686if (fac[j] > fac[best])687best = j;688}689if (best != i)690{691rmatmul(g[i], g[best], t1, dim);692rmatfac(t1, 1.0, g[i], dim);693i = -1;694}695factor = fac[best];696}697*/698699test = symel(x, g, num, dim, eps, erg->array.SZ);700701for(i=0;i<num;i++)702{703for(j=0;j<dim;j++)704free(g[i][j]);705free(g[i]);706}707free(g);708for(i=0;i<dim;i++)709{710free(x[i]); free(xt[i]); free(t[i]); free(t1[i]);711free(save[i]); free(pres[i]);712}713free(x); free(xt); free(t); free(t1);714free(save); free(pres);715free(fac);716717if(test != 0)718return(erg);719else720{ free_mat(erg); return(NULL);}721}722723724