\\ In all these functions, G represents a group acting on a free Z-module A. \\ In fact, G is a vector of matrices, each of which is the representation \\ of one generator of the group on some fixed Z-basis of A. Thus each \\ element of G must be an invertible integer matrix, and they must all \\ be the same size. \\ Find H^0(G, A) H0(G) = { local(n,r,M); n = matsize(G)[2]; r = matsize(G[1])[1]; M = matker(G[1] - matid(r)); for(i=2,n, M = matintersect(M, matker(G[i] - matid(r))); ); matrixqz(M,-2); } \\ Gives a HNF basis for the kernel of M acting on Z/mZ^r kermod(M,m) = mathnf(concat(matsolvemod(M,m,0,1)[2] % m, \ matdiagonal(vector(matsize(M)[1],i,m)))); \\ Find H^0(G, A \otimes Z/mZ) H0torsion(G, m) = { local(n,r,M); n = matsize(G)[2]; r = matsize(G[1])[1]; M = kermod(G[1] - matid(r), m); for(i=2,n, M = latticeintersect(M, kermod(G[i] - matid(r), m)); ); M; } \\ Find a set of generators for H^1(G, A)[m], given as elements of \\ A \otimes Z/mZ H1torsion(G, m) = { local(M,N,A,v,B); M = H0torsion(G,m); N = mathnf(concat(H0(G), matdiagonal(vector(matsize(M)[1],i,m)))); \\ Find the quotient group and put it into Smith normal form A = matsnf(M^-1*N,1); v = matsnf(A[3],4); \\ Extract the generators if(v == [], B = [;], B = vecextract(M*A[1]^-1, Str("1.." matsize(v)[2]))); [v, B]; }