GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
/***** This file includes some routines for1the preprocessing of the algorithm *****/2#include"typedef.h"34/************************************************************************\5| removes those vectors from V.v, which6| have other norm combinations than the base-vectors7\************************************************************************/8static void checkvecs(V, F, norm)9veclist *V, norm;10invar F;11{12int i, j, k, dim, *normvec, *Vvi;1314dim = F.dim;15if ((normvec = (int*)malloc(norm.dim * sizeof(int))) == 0)16exit (2);17j = 0;18for (i = 1; i <= V->n; ++i)19{20Vvi = V->v[i];21for (k = 0; k < F.n; ++k)22{23Vvi[dim+k] = scp(Vvi, F.A[k], Vvi, dim);24normvec[k] = Vvi[dim+k];25}26if (abs(numberof(normvec, norm)) > dim)27/* the vector V->V[i] has a different norm combination from those in the list28norm.v and is therefore deleted */29{30free(Vvi);31++j;32}33else34V->v[i-j] = Vvi;35}36V->n -= j;37free(normvec);38}3940/************************************************************************\41| checks, whether g fixes the invariant forms42\************************************************************************/43static int checkgen(g, F)44int **g;45invar F;46{47int i, j, k, fix, **FAk;4849fix = 1;50for (k = 0; k < F.n && fix == 1; ++k)51{52FAk = F.A[k];53for (i = 0; i < F.dim && fix == 1; ++i)54{55for (j = 0; j <= i && fix == 1; ++j)56{57if (scp(g[i], FAk, g[j], F.dim) != FAk[i][j])58fix = 0;59}60}61}62return(fix);63}6465/************************************************************************\66| a permutation per := fp.per for the order of the basis-vectors is chosen67| such that in every step the number of possible continuations is minimal,68| for j from per[i] to per[dim-1] the value f[i][j] in the fingerprint f is69| the number of vectors, which have the same scalar product with the70| basis-vectors per[0]...per[i-1] as the basis-vector j and the same length as71| this vector with respect to all invariant forms72\************************************************************************/73static void fingerprint(fp, F, V)74fpstruct *fp;75invar F;76veclist V;77{78int i, j, k, dim, min, tmp, **f, *Vvj;7980dim = F.dim;81if ((f = (int**)malloc(dim * sizeof(int*))) == 0)82exit (2);83for (i = 0; i < dim; ++i)84{85if ((f[i] = (int*)malloc(dim * sizeof(int))) == 0)86exit (2);87for (j = 0; j < dim; ++j)88f[i][j] = 0;89}90for (i = 0; i < dim; ++i)91fp->per[i] = i;92/* the first row of the fingerprint has as entry nr. i the number of93vectors, which have the same length as the i-th basis-vector with94respect to every invariant form */95for (j = 1; j <= V.n; ++j)96{97Vvj = V.v[j];98for (i = 0; i < dim; ++i)99{100for (k = 0; k < F.n && Vvj[dim+k] == F.A[k][i][i]; ++k);101if (k == F.n)102f[0][i] += 2;103}104}105for (i = 0; i < dim-1; ++i)106{107/* a minimal entry != 0 in the i-th row is chosen */108min = i;109for (j = i+1; j < dim; ++j)110{111if (f[i][fp->per[j]] < f[i][fp->per[min]])112min = j;113}114tmp = fp->per[i];115fp->per[i] = fp->per[min];116fp->per[min] = tmp;117/* the column below the minimal entry is set to 0 */118for (j = i+1; j < dim; ++j)119f[j][fp->per[i]] = 0;120/* compute the row i+1 of the fingerprint */121for (j = i+1; j < dim; ++j)122f[i+1][fp->per[j]] = possible(F, V, fp->per, i, fp->per[j]);123}124/* only the diagonal of f will be needed later */125for (i = 0; i < dim; ++i)126{127fp->diag[i] = f[i][fp->per[i]];128free(f[i]);129}130free(f);131}132133/************************************************************************\134| returns the number of vectors,135| which have the same scalar products with the136| basis-vectors nr. per[0]...per[I] as the137| basis-vector nr. J and the same length138| as this vector with respect to all invariant forms139\************************************************************************/140static int possible(F, V, per, I, J)141invar F;142veclist V;143int *per, I, J;144{145int i, j, k, dim, count, *Vvj;146147dim = F.dim;148count = 0;149for (j = 1; j <= V.n; ++j)150{151Vvj = V.v[j];152i = I+1;153/* check the length of the vector */154for (k = 0; k < F.n && i > I && Vvj[dim+k] == F.A[k][J][J]; ++k)155/* check the scalar products with the basis-vectors */156for (i = 0; i <= I && F.v[k][j][per[i]] == F.A[k][per[i]][J]; ++i);157if (k == F.n && i > I)158++count;159/* the same for the negative vector */160i = I+1;161for (k = 0; k < F.n && i > I && Vvj[dim+k] == F.A[k][J][J]; ++k)162for (i = 0; i <= I && F.v[k][j][per[i]] == -F.A[k][per[i]][J]; ++i);163if (k == F.n && i > I)164++count;165}166return(count);167}168169/************************************************************************\170| calculates the scalar products of the vector w with the base171| vectors v[b[I]] down to v[b[I-dep+1]] with respect to172| all invariant forms and puts them on scpvec173\************************************************************************/174static void scpvector(scpvec, w, b, I, dep, F)175invar F;176int *scpvec, *w, *b, I, dep;177{178int i, j, dim, bi;179180dim = F.dim;181for (i = I; i >= 0 && i > I-dep; --i)182{183if ((bi = b[i]) > 0)184{185for (j = 0; j < F.n; ++j)186scpvec[j*dep + I-i] = sscp(w, F.v[j][bi], dim);187}188else189{190for (j = 0; j < F.n; ++j)191scpvec[j*dep + I-i] = -sscp(w, F.v[j][-bi], dim);192}193}194}195196/************************************************************************\197| computes the list of scalar product198| combinations of the vectors in V.v with199| the basis-vectors in b200\************************************************************************/201static void scpvecs(list, vec, I, b, dep, V, F)202veclist *list, V;203invar F;204int ***vec, I, *b, dep;205{206int i, j, dim, len, *scpvec, nr, sign, *tmp;207int *Vvj, *vecnr, *listvn, *vecn, **listv;208209dim = F.dim;210len = F.n * dep;211/* scpvec is the vector for the scalar product combination */212if ((scpvec = (int*)malloc(len * sizeof(int))) == 0)213exit (2);214/* the first vector in the list is the 0-vector and is not counted */215if ((list->v = (int**)malloc(1 * sizeof(int*))) == 0)216exit (2);217list->dim = len;218list->len = len;219if ((list->v[0] = (int*)malloc(len * sizeof(int))) == 0)220exit (1);221for (i = 0; i < len; ++i)222list->v[0][i] = 0;223list->n = 0;224if ((*vec = (int**)malloc(1 * sizeof(int*))) == 0)225exit (2);226if (((*vec)[0] = (int*)malloc(dim * sizeof(int))) == 0)227exit (2);228for (i = 0; i < dim; ++i)229(*vec)[0][i] = 0;230for (j = 1; j <= V.n; ++j)231{232Vvj = V.v[j];233for (i = 0; i < len; ++i)234scpvec[i] = 0;235scpvector(scpvec, Vvj, b, I, dep, F);236for (i = 0; i < len && scpvec[i] == 0; ++i);237if (i == len)238/* if scpvec is the 0-vector, nr is set to 0, since numberof never returns 0 */239nr = 0;240else241{242nr = numberof(scpvec, *list);243sign = nr > 0 ? 1 : -1;244nr = abs(nr);245}246/* scpvec is already in list */247if (nr <= list->n && nr > 0)248{249vecnr = (*vec)[nr];250for (i = 0; i < dim; ++i)251vecnr[i] += sign * Vvj[i];252}253/* scpvec is a new scalar product combination */254else if (nr >= list->n+1)255{256++list->n;257if ((list->v = (int**)realloc(list->v, (list->n+1) * sizeof(int*))) == 0)258exit (2);259if ((list->v[list->n] = (int*)malloc(len * sizeof(int))) == 0)260exit (2);261/* numberof changes the sign of scpvec if the first nonzero entry is < 0,262hence this is correct */263listvn = list->v[list->n];264for (i = 0; i < len; ++i)265listvn[i] = scpvec[i];266if ((*vec = (int**)realloc(*vec, (list->n+1) * sizeof(int*))) == 0)267exit (2);268if (((*vec)[list->n] = (int*)malloc(dim * sizeof(int))) == 0)269exit (2);270vecn = (*vec)[list->n];271for (i = 0; i < dim; ++i)272vecn[i] = sign * Vvj[i];273/* shuffle the new vector to the correct position, this should be quick enough,274since the length of the list should not exceed some hundreds */275listv = list->v;276for (i = list->n; i > nr+1-list->n; --i)277{278tmp = listv[i];279listv[i] = listv[i-1];280listv[i-1] = tmp;281tmp = (*vec)[i];282(*vec)[i] = (*vec)[i-1];283(*vec)[i-1] = tmp;284}285}286}287free(scpvec);288}289290/************************************************************************\291| computes a basis b for the lattice generated by the vectors in v,292| puts a transformation matrix on T, i.e. b = T*v,293| uses LLL-reduction with respect to F294\************************************************************************/295static void base(com, b, v, F, dim)296scpcomb *com;297int ***b, **v, **F, dim;298{299int i, j, k, nv, rank, max, **Fv, **f, **tr, *perm, *norm, tmp;300int *vi, *Fvi, *comtr, *fj;301302nv = com->list.n + 1;303max = 1;304/* get the maximal entry in the vector sums */305for (i = 0; i < nv; ++i)306{307for (j = 0; j < dim; ++j)308{309if (abs(v[i][j]) > max)310max = abs(v[i][j]);311}312}313/* Fv is the list of products of F with the vectors in v, scalar products314with respect to F can be calculated as standard scalar products of315vectors in v with vectors in Fv */316if ((Fv = (int**)malloc(nv * sizeof(int*))) == 0)317exit (2);318/* the product of the maximal entry in the vector sums with the maximal entry319in the product of the Gram-matrices with the vector sums should not exceed320MAXNORM to avoid overflow */321max = MAXNORM / max;322for (i = 0; i < nv; ++i)323{324if ((Fv[i] = (int*)malloc(dim * sizeof(int))) == 0)325exit (2);326Fvi = Fv[i];327for (j = 0; j < dim; ++j)328{329Fvi[j] = sscp(F[j], v[i], dim);330if (abs(Fvi[j]) > max)331/* an entry in F.v[i] is too large */332{333fprintf(stderr, "Error: Found entry %d in vector sum.\nTo avoid overflow, the entries should not exceed %d.\nTry without option -D or use -D with higher value.\n", Fvi[j], max);334exit (3);335}336}337}338/* b is the basis for the lattice */339if ((*b = (int**)malloc(1 * sizeof(int*))) == 0)340exit (2);341if (((*b)[0] = (int*)malloc(dim * sizeof(int))) == 0)342exit (2);343/* com->trans is the transformation matrix */344if ((com->trans = (int**)malloc(1 * sizeof(int*))) == 0)345exit (2);346if ((com->trans[0] = (int*)malloc(nv * sizeof(int))) == 0)347exit (2);348/* f is the Gram-matrix for the basis b with respect to the form F */349if ((f = (int**)malloc(1 * sizeof(int*))) == 0)350exit (2);351if ((f[0] = (int*)malloc(1 * sizeof(int))) == 0)352exit (2);353/* tr is the transformation matrix for the LLL-reduced lattice */354if ((tr = (int**)malloc(1 * sizeof(int*))) == 0)355exit (2);356if ((tr[0] = (int*)malloc(1 * sizeof(int))) == 0)357exit (2);358/* perm is the new order in which the vectors in v are added to the lattice359generated by the preceding vectors */360if ((perm = (int*)malloc(nv * sizeof(int))) == 0)361exit (2);362if ((norm = (int*)malloc(nv * sizeof(int))) == 0)363exit (2);364/* bubble sort with respect to the norm of the vectors in v with respect to the365Gram-matrix F, which is assumed to be positive definite,366this should stabilize the LLL-reduction,367the bubble sort should be sufficient since the number of vectors here is368assumed to be rather small (at most some hundreds) */369for (i = 0; i < nv; ++i)370{371norm[i] = sscp(v[i], Fv[i], dim);372if (norm[i] > MAXNORM)373{374exit (3);375}376perm[i] = i;377}378i = 0;379while (i < nv-1)380{381if (norm[perm[i]] > norm[perm[i+1]])382{383tmp = perm[i];384perm[i] = perm[i+1];385perm[i+1] = tmp;386if (i > 0)387--i;388}389else390++i;391}392free(norm);393/* jump over possible 0-vectors */394i = 0;395for (j = 0; j < dim && v[perm[i]][j] == 0; ++j);396while (j == dim && i < nv)397{398++i;399if (i < nv)400for (j = 0; j < dim && v[perm[i]][j] == 0; ++j);401}402rank = 0;403while (i < nv)404{405/* v[perm[i]] is the candidate to enlarge the lattice generated by the406base vectors in b */407vi = v[perm[i]];408Fvi = Fv[perm[i]];409for (j = 0; j < rank; ++j)410{411f[j][rank] = sscp((*b)[j], Fvi, dim);412f[rank][j] = f[j][rank];413}414f[rank][rank] = sscp(vi, Fvi, dim);415if (lll(f, tr, rank+1) > rank)416/* the rank of the lattice generated by v[perm[i]] and the vectors in b is417rank+1, i.e. one higher than without v[perm[i]] */418{419++rank;420for (j = 0; j < dim; ++j)421(*b)[rank-1][j] = vi[j];422comtr = com->trans[rank-1];423for (j = 0; j < nv; ++j)424comtr[j] = 0;425comtr[perm[i]] = 1;426/* transform basis and transformation matrix */427change(*b, rank, tr, dim);428change(com->trans, rank, tr, nv);429if ((*b = (int**)realloc(*b, (rank+1) * sizeof(int*))) == 0)430exit (2);431if (((*b)[rank] = (int*)malloc(dim * sizeof(int))) == 0)432exit (2);433if ((com->trans = (int**)realloc(com->trans, (rank+1) * sizeof(int*))) == 0)434exit (2);435if ((com->trans[rank] = (int*)malloc(nv * sizeof(int))) == 0)436exit (2);437if ((f = (int**)realloc(f, (rank+1) * sizeof(int*))) == 0)438exit (2);439for (j = 0; j < rank; ++j)440{441if ((f[j] = (int*)realloc(f[j], (rank+1) * sizeof(int))) == 0)442exit (2);443}444if ((f[rank] = (int*)malloc((rank+1) * sizeof(int))) == 0)445exit (2);446for (j = 0; j < rank; ++j)447{448fj = f[j];449for (k = 0; k <= j; ++k)450{451fj[k] = scp((*b)[j], F, (*b)[k], dim);452f[k][j] = fj[k];453}454}455if ((tr = (int**)realloc(tr, (rank+1) * sizeof(int*))) == 0)456exit (2);457for (j = 0; j < rank; ++j)458{459if ((tr[j] = (int*)realloc(tr[j], (rank+1) * sizeof(int))) == 0)460exit (2);461}462if ((tr[rank] = (int*)malloc((rank+1) * sizeof(int))) == 0)463exit (2);464}465else if (abs(tr[rank][rank]) > 1)466/* v[perm[i]] enlarges the lattice generated by the vectors in b by a finite467index |tr[rank][rank]| */468{469for (j = 0; j < dim; ++j)470(*b)[rank][j] = vi[j];471comtr = com->trans[rank];472for (j = 0; j < nv; ++j)473comtr[j] = 0;474comtr[perm[i]] = 1;475/* transform basis and transformation matrix */476change(*b, rank+1, tr, dim);477change(com->trans, rank+1, tr, nv);478for (j = 0; j < rank; ++j)479{480fj = f[j];481for (k = 0; k <= j; ++k)482{483fj[k] = scp((*b)[j], F, (*b)[k], dim);484f[k][j] = fj[k];485}486}487}488++i;489}490com->rank = rank;491for (i = 0; i < nv; ++i)492free(Fv[i]);493free(Fv);494for (i = 0; i <= rank; ++i)495{496free(f[i]);497free(tr[i]);498}499free(f);500free(tr);501free(perm);502}503504/************************************************************************\505| expresses the vectors in v in the basis b,506| puts the transformation matrix on com->coef, i.e. v = com->coef * b,507| uses LLL-reduction with respect to F to obtain the coefficients508\************************************************************************/509static void coef(com, b, v, F, dim)510scpcomb *com;511int **b, **v, **F, dim;512{513int i, j, **Fb, nb, **Fv, nv, **f, **tr, sign;514int *fi, *fnb, *trnb, *Fvi, *comci;515516if ((com->coef = (int**)malloc((com->list.n+1) * sizeof(int*))) == 0)517exit (2);518for (i = 0; i <= com->list.n; ++i)519{520if ((com->coef[i] = (int*)malloc(com->rank * sizeof(int))) == 0)521exit (2);522}523nb = com->rank;524nv = com->list.n + 1;525/* Fv is the list of products of F with the vectors in v, scalar products526with respect to F can be calculated as standard scalar products of527vectors in v with vectors in Fv */528if ((Fv = (int**)malloc(nv * sizeof(int*))) == 0)529exit (2);530for (i = 0; i < nv; ++i)531{532if ((Fv[i] = (int*)malloc(dim * sizeof(int))) == 0)533exit (2);534for (j = 0; j < dim; ++j)535Fv[i][j] = sscp(F[j], v[i], dim);536}537/* Fb is the list of products of F with the vectors in b */538if ((Fb = (int**)malloc(nb * sizeof(int*))) == 0)539exit (2);540for (i = 0; i < nb; ++i)541{542if ((Fb[i] = (int*)malloc(dim * sizeof(int))) == 0)543exit (2);544for (j = 0; j < dim; ++j)545Fb[i][j] = sscp(F[j], b[i], dim);546}547if ((f = (int**)malloc((nb+1) * sizeof(int*))) == 0)548exit (2);549for (i = 0; i <= nb; ++i)550{551if ((f[i] = (int*)malloc((nb+1) * sizeof(int))) == 0)552exit (2);553}554for (i = 0; i < nb; ++i)555{556fi = f[i];557for (j = 0; j <= i; ++j)558{559fi[j] = sscp(b[i], Fb[j], dim);560f[j][i] = fi[j];561}562}563if ((tr = (int**)malloc((nb+1) * sizeof(int*))) == 0)564exit (2);565for (i = 0; i <= nb; ++i)566{567if ((tr[i] = (int*)malloc((nb+1) * sizeof(int))) == 0)568exit (2);569}570fnb = f[nb];571trnb = tr[nb];572for (i = 0; i < nv; ++i)573{574Fvi = Fv[i];575for (j = 0; j < nb; ++j)576{577f[j][nb] = sscp(b[j], Fvi, dim);578fnb[j] = f[j][nb];579}580fnb[nb] = sscp(v[i], Fvi, dim);581/* if the vector v[i] is in the lattice generated by the base b, the rank of the582Gram-matrix f must be nb and the last row of the transformation matrix tr583expresses the 0-vector, in particular |tr[nb][nb]| must be <=1, since584otherwise the vector v[i] would enlarge the lattice be an index585|tr[nb][nb]| */586if (lll(f, tr, nb+1) > nb || abs(trnb[nb]) > 1)587{588fprintf(stderr, "Error: vector lies not in lattice\n");589exit (3);590}591else592{593comci = com->coef[i];594sign = trnb[nb];595for (j = 0; j < nb; ++j)596comci[j] = -sign * trnb[j];597}598}599for (i = 0; i < nv; ++i)600free(Fv[i]);601free(Fv);602for (i = 0; i < nb; ++i)603free(Fb[i]);604free(Fb);605for (i = 0; i <= nb; ++i)606{607free(f[i]);608free(tr[i]);609}610free(f);611free(tr);612}613614/************************************************************************\615| com->F[i] is the Gram-matrix of the basis b with respect to F.A[i]616\************************************************************************/617static void scpforms(com, b, F)618scpcomb *com;619invar F;620int **b;621{622int i, j, k, dim, **Fbi, nb, **FAi, *comFij;623624dim = F.dim;625nb = com->rank;626if ((com->F = (int***)malloc(F.n * sizeof(int**))) == 0)627exit (2);628/* Fbi is the list of products of F.A[i] with the vectors in b */629if ((Fbi = (int**)malloc(nb * sizeof(int*))) == 0)630exit (2);631for (j = 0; j < nb; ++j)632{633if ((Fbi[j] = (int*)malloc(dim * sizeof(int))) == 0)634exit (2);635}636for (i = 0; i < F.n; ++i)637{638if ((com->F[i] = (int**)malloc(nb * sizeof(int*))) == 0)639exit (2);640FAi = F.A[i];641for (j = 0; j < nb; ++j)642{643for (k = 0; k < dim; ++k)644Fbi[j][k] = sscp(FAi[k], b[j], dim);645}646for (j = 0; j < nb; ++j)647{648if ((com->F[i][j] = (int*)malloc(nb * sizeof(int))) == 0)649exit (2);650comFij = com->F[i][j];651for (k = 0; k < nb; ++k)652comFij[k] = sscp(b[j], Fbi[k], dim);653}654}655for (j = 0; j < nb; ++j)656free(Fbi[j]);657free(Fbi);658}659660661