// Compile with // gcc -O3 -shared -o evalGP1.so -fPIC evalGP1.c // Copyright Michael Monagan 2025 #include #include #define LONG long long int #define ULONG unsigned long long int /******************************************************************************************/ /* Zp utilities */ /******************************************************************************************/ #define UINT64 unsigned long long #include "int128g.c" //typedef struct { // UINT64 s; /* shift */ // UINT64 v; /* reciprocal of d */ // UINT64 d0; /* divisor shifted up */ // UINT64 d1; //} recint; // //recint recip1(UINT64 p); //UINT64 mulrec64(UINT64 a, UINT64 b, recint v); LONG add64s(LONG a, LONG b, LONG p) { LONG t; t = (a-p)+b; t += (t>>63) & p; return t; } LONG sub64s(LONG a, LONG b, LONG p) { LONG t; t = a-b; t += (t>>63) & p; return t; } LONG neg64s(LONG a, LONG p) { return (a==0) ? 0 : p-a; } LONG mul64s(LONG a, LONG b, LONG p) { LONG q, r; __asm__ __volatile__( \ " mulq %%rdx \n\t" \ " divq %4 \n\t" \ : "=a"(q), "=d"(r) : "0"(a), "1"(b), "rm"(p)); return r; } LONG * array(LONG n) { LONG *A; A = (LONG *) malloc( n*sizeof(LONG) ); if( A==0 ) { printf("out of memory\n"); exit(1); } return A; } int * array32s( LONG n ) { int *A; A = (int *) malloc( n*sizeof(int) ); if( A==0 ) { printf("out of memory\n"); exit(1); } return A; } /*********************************************************************/ /* These routines work with the Maple DAG directly */ /*********************************************************************/ #define NAME 8 #define TABLEREF 10 #define PROD 14 #define SUM 16 #define POLY 17 #define EXPSEQ 31 #define LIST 32 #define SET 38 #define ARRAY 40 #define INTNEG 1 #define INTPOS 2 int ID( LONG *a ) { int id; id = (a[0] >> 32) & 63; return id; } LONG LENGTH( LONG *a ) { LONG len; len = a[0] & ((1LL << 32)-1); return len; } int ISPOLY( LONG *a ) { return( ID(a)==POLY ); } int findindex( LONG x, LONG *A, int n ) { int i; for( i=0; iMAXDEG ) return -1; if( d>D[j] ) D[j] = d; } } else return 0; } return 1; } int evalsumall( LONG *f, LONG *x, int n, LONG **POW, LONG p ) { int i,j,k,t; LONG c,y,z,*m,d; recint P; if( ID(f)!=SUM ) return -1; t = (LENGTH(f)-1)/2; f++; P = recip1(p); y = 0; for( i=0; i=0; j-- ) { d = z & mask; if( d>MAXDEG ) return -1; if( d>D[j] ) D[j] = d; z = z >> numbits; } } return 1; } LONG evalpolyall(LONG *f, int n, LONG **POWERS, LONG p) { // Let f = sum( a_i M_i(x1,...,xn), i=1..t ) stored in the POLY representation. // Let POWERS[i][d] = alpha^d // It is assumed f is in the POLY representation, n>1 and 0 <= a_i < p LONG i, j, t, x, y, z, numbits, mask, d, h; recint P; if( ID(f)!=POLY ) return -1; t = (LENGTH(f)-2)/2; f += 2; P = recip1(p); if( n==1 ) numbits=64; else numbits = 64/(n+1); mask = ((1LL) << numbits) - 1; y = 0; for( i=0; i=p ) z = z%p; if( z<0 ) z = z+p; } else { printf("coefficients must be immediate\n"); exit(1); } for( j=n-1; j>=0; j-- ) { d = x & mask; if( d ) z = mulrec64(z,POWERS[j][d],P); x = x >> numbits; } //printf("i=%d z=%lld\n",i,z); y = add64s(y,z,p); } return y; } LONG evalpolytop(LONG *a, LONG *alpha, int n, LONG p) { int i,j,k,m,s,D[32]; LONG y,*POW[32],*Y,*B,*W; recint P; if( ID(a)!=POLY ) { printf("a is not a POLY\n"); exit(1); } Y = (LONG *) a[1]; if( ID(Y)!=EXPSEQ ) { printf("a is a bad POLY\n"); exit(1); } m = LENGTH(Y); if( m!=n+1 ) { printf("evalpolyall : variable missmatch\n"); exit(1); } getpolydegs64s(a,D,n); for( s=i=0; i