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 "gmp.h"3#include "zass.h"4#include "getput.h"5#include "tools.h"6#include "contrib.h"78/**************************************************************************9@10@--------------------------------------------------------------------------11@12@ FILE: torsionfree.c13@14@--------------------------------------------------------------------------15@16***************************************************************************/1718/* compare two matrix */19static int is_equal(matrix_TYP *x,20matrix_TYP *y)21{22int i,23j,24cols,25rows;2627cols = x->cols;28rows = x->rows;2930for (i = 0 ; i < rows ; i++){31for(j = 0 ; j < cols ; j++){32if ((y->kgv * x->array.SZ[i][j]) != (x->kgv * y->array.SZ[i][j])){33return FALSE;34}35}36}3738return TRUE;39}404142/* compare two matrix (linear part only) */43static int lin_is_equal(matrix_TYP *x,44matrix_TYP *y)45{46int i,47j,48cols,49rows;5051cols = x->cols - 1;52rows = x->rows - 1;5354for (i = 0 ; i < rows ; i++)55for(j = 0 ; j < cols ; j++)56if ((x->array.SZ[i][j] * y->kgv) != (y->array.SZ[i][j] * x->kgv))57return FALSE;58return TRUE;59}606162/* calculate the linear part P of R */63matrix_TYP *lin(matrix_TYP *x)64{65matrix_TYP *y;66y = copy_mat (x);67real_mat (y, y->rows-1, y->cols-1);68Check_mat (y);69return y;70}7172/* calculate the cyclotomic polyn */73static matrix_TYP *pol_cycl(matrix_TYP *x,74int p)75{76rational one;7778int i;7980matrix_TYP *y,81*Id,82*RES;8384one.z = 1;85one.n = 1;8687y = copy_mat(x);88Id = init_mat(x->rows, x->cols, "i1");89RES = init_mat(x->rows, x->cols, "i1");9091for(i=1 ; i < p ; i++){92RES = mat_muleq( RES , y );93RES = mat_addeq( RES, Id , one , one);94}95free_mat (y);96free_mat (Id);9798return RES;99}100101/* calculate the n-power of a matrix */102static matrix_TYP *power(matrix_TYP *x,103int n)104{105int i;106107matrix_TYP *y;108109y = init_mat(x->rows, x->cols, "i1");110if (n == 0){111return y;112}113else{114for(i=0 ; i < n ; i++){115y = mat_muleq( y , x );116}117118return y;119120}121}122123124/* calculate the order of a matrix */125static int ORDER(matrix_TYP *A)126{127128int i = 1;129130matrix_TYP *B;131132B = copy_mat(A);133Check_mat(B);134135while (! ( B->flags.Scalar && B->array.SZ[0][0] == 1)){136mat_muleq(B,A);137Check_mat(B);138i++;139}140141free_mat(B);142return i;143}144145146/**************************************************************************147@148@--------------------------------------------------------------------------149@150@ int *torsionfree(bravais_TYP *R,151@ int *order_out,152@ int *number_of_conjugacy_classes){153@154@ decides whether the space group in R is torsion free, and ONLY155@ IN THIS CASES decides whether the group has trivial center or156@ not.157@ The result is a pointer A, say, which points to two integers with158@ the following convention:159@ A[0] == TRUE iff the group R is torsion free.160@ A[1] == TRUE iff A[0] == TRUE and the group R has trivial center.161@162@ bravais_TYP *R: a bravais_TYP with generators which together163@ with Z^n generate the space group in Question.164@ int *order : The order of the point group is stored here after165@ the calculation has been done166@ int *number_of_conjugacy_classes: The number of conjugacy classes of167@ the point group of R is stored here.168@--------------------------------------------------------------------------169@170***************************************************************************/171int *torsionfree(bravais_TYP *R,172int *order_out,173int *number_of_conjugacy_classes){174175int i,176j,177k,178l,179new_index,180act_number,181dim,182*mirror,183*processed,184*list_primes,185num_gen,186order,187*RES;188189190matrix_TYP **ele,191**gen,192**repres,193**gen_inv,194**gen_ident,195*conj,196*new_elem,197*M,198*X,199*linear,200*w,201*y,202*bahn,203*bahn1,204*bahn2,205*ed1,206*ed2;207208RES = (int *) calloc(2 , sizeof(int));209210num_gen = R->gen_no;211gen = R->gen;212dim = R->dim;213214215ele = (matrix_TYP **) malloc(110000 * sizeof(matrix_TYP *));216gen_inv = (matrix_TYP **) malloc(num_gen * sizeof(matrix_TYP *));217repres = (matrix_TYP **) malloc(110000 * sizeof(matrix_TYP *));218gen_ident = (matrix_TYP **) malloc(num_gen * sizeof(matrix_TYP *));219220/* We will generate a list ele[] of elements of R that are pre image P */221/* "order" is the order of P */222223ele[0] = init_mat(dim, dim, "i1");224225order = 1;226227for(i=0; i < order ; i++){228for(j=0 ; j < num_gen ; j++){229new_elem = mat_mul(ele[i] , gen[j]);230Check_mat(new_elem);231for(k=0 ; k < order && lin_is_equal(new_elem, ele[k])==FALSE; k++);232if (k == order){233ele[order] = new_elem;234order++;235}236else{237free_mat(new_elem);238}239}240}241242/* If P is trivial, then it's torsion-free ( Z^n) */243244if (order == 1){245RES[0] = TRUE;246order_out[0] = 1;247number_of_conjugacy_classes[0] = 1;248free_mat (ele[0]);249free (ele);250}251else{252/* for (i=0 ; i< order ; i++)253put_mat(ele[i] , NULL , "" , 2); */254255order_out[0] = order;256257/* Now we calculate the (pre-images of) conjugacy classes of elements of P */258259mirror = (int *) malloc(order * sizeof(int));260processed = (int *) malloc(order * sizeof(int));261262263act_number = 0 ;264265for( i=0 ; i < order ; i++){266mirror[i] = -1;267processed[i] = 0;268}269270for (i=0; i < num_gen ; i++){271gen_inv[i] = mat_inv(gen[i]);272}273274for (i=0 ; i < order ; i++){275if (mirror[i] == -1){276act_number++;277mirror[i] = act_number;278279for ( j = i ; j < order ; j++){280new_index = j;281if (mirror[j] == act_number && processed[j] == 0){282processed[j] = 1;283284for (k=0 ; k < num_gen ; k++){285conj = mat_kon( gen[k] , ele[j] , gen_inv[k]);286for(l=0 ; l < order && lin_is_equal(conj, ele[l])==FALSE; l++);287mirror[l] = act_number;288if (l < new_index && processed[l] == 0){289new_index = l - 1;290}291free_mat(conj);292}293}294j = new_index;295}296}297}298number_of_conjugacy_classes[0] = act_number;299300for (i=0; i<num_gen; i++)301free_mat (gen_inv[i]);302free (gen_inv);303304/* we will generate a list repres[] of repres of conjug classes */305/* act_number is the number of classes. */306307if(act_number == order){308for (i=0 ; i < order ; i++)309repres[i] = ele[i];310}311else{312for( i=0 ; i < act_number ; i++){313for(j = 0 ; j < order && mirror[j] != i+1 ; j++);314repres[i] = ele[j];315}316}317318free (mirror); free (processed);319320list_primes = factorize(order);321322for (i=2 ; i < 98 ; i++){323if ( list_primes[i] != 0){324for (j = 0 ; j < act_number ; j++){325linear = lin(repres[j]);326if (i == ORDER (linear)){327328bahn = pol_cycl(linear, i);329bahn1 = tr_pose (bahn);330331free_mat (bahn);332free_mat (linear);333334w = power (repres[j],i);335y = init_mat(1,dim - 1,"");336337for (l=0; l < dim-1; l++){338y->array.SZ[0][l] = w->array.SZ[l][dim-1];339}340341bahn2 = copy_mat (bahn1);342real_mat (bahn2 , dim , dim-1);343for (k=0; k < dim-1; k++){344bahn2->array.SZ[dim-1][k] = y->array.SZ[0][k];345}346347ed1 = elt_div(bahn1);348ed2 = elt_div(bahn2);349350if(is_equal(ed1 , ed2) == TRUE){351free (list_primes);352free (gen_ident);353free_mat (bahn1); free_mat (ed1);354free_mat (bahn2); free_mat (ed2);355free_mat (y); free_mat (w);356for (i=0; i<order; i++)357free_mat (ele[i]);358free (ele);359free (repres);360return RES;361}362free_mat (bahn1); free_mat(ed1);363free_mat (bahn2); free_mat(ed2);364free_mat (y); free_mat (w);365}366else{367free_mat (linear);368}369}370}371}372RES[0] = TRUE;373374375376for (i=0; i<order; i++)377free_mat (ele[i]);378free (ele);379free (repres);380free (list_primes);381382383/** CALCULATE THE CENTRE **/384385/* We look for the module L^P, the elements of the lattice386L centralized by P, the point-group */387388/* We create a list of matrix, gen_ident, equal to linear part389of gen minus the Identity */390391for(i=0 ; i < num_gen ; i++){392gen_ident[i] = init_mat(dim-1,dim-1,"");393for (j=0 ; j < dim -1 ; j++){394for (k = 0 ; k < dim - 1 ; k++){395if (k == j ){396gen_ident[i]->array.SZ[j][k] = (gen[i]->array.SZ[j][k]/gen[i]->kgv) - 1;397}398else{399gen_ident[i]->array.SZ[j][k] = gen[i]->array.SZ[j][k]/gen[i]->kgv;400}401}402}403}404405406/* construct a greater matrix M with the ones above */407408409M = init_mat (num_gen*(dim-1) , dim-1 , "");410411for (i = 0 ; i < num_gen ; i++){412for (j = i*(dim-1) ; j < (i+1)*(dim-1) ; j++){413for (k = 0 ; k < dim - 1 ; k++){414M->array.SZ[j][k] = gen_ident[i]->array.SZ[j-i*(dim-1)][k];415}416}417}418419for (i=0; i<num_gen; i++)420free_mat (gen_ident[i]);421free (gen_ident);422423X = solve_mat(M);424/* the rows of X are Z-basis for the solution of MX = 0 */425free_mat (M);426427if (X->rows == 0){428RES[1] = TRUE;429}430else if (X->rows == 1){431for (i = 0 ; i < dim-1 && X->array.SZ[0][i] == 0; i++);432if (i == dim-1){433RES[1] = TRUE;434}435}436free_mat (X);437438}439440return RES;441}442443444