// Copyright: Tian Chen and Michael Monagan, 2022 #define LONG long long int #include #include #include "int128g.c" /******************************************************************************************/ /* Zp arithmetic */ /******************************************************************************************/ 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; } /* c^(-1) mod p assuming 0 < c < p < 2^63 */ LONG inv64s( LONG c, LONG p ) { // if c = 0, returns 0 LONG d,r,q,r1,c1,d1; d = p; c1 = 1; d1 = 0; while( d != 0 ) { q = c / d; r = c - q*d; r1 = c1 - q*d1; c = d; c1 = d1; d = r; d1 = r1; } if( c!=1 ) return( 0 ); if( c1 < 0 ) c1 += p; return( c1 ); } LONG *array( LONG n ) { LONG *A; A = (LONG *) malloc( 8*n ); if( A==0 ) { printf("out of memory\n"); exit(1); } return A; } LONG *matrix64s( int n ) { LONG *A; LONG N; N = n; N = n*N; N = sizeof(LONG) * N; A = (LONG *) malloc(N); return A; } /* print an array in form [a0,a1,...,an-1] */ void vecprint64s( LONG *A, int n ){ int i; printf("["); for( i=0; i0 && k%100 == 0 ) printf("elimination at row %d\n",k); for( i=k; i=n ) { d = 0; break; } if( i!=k ) { // interchange row k with row i for( j=k; j=0 && V[d]==0; d-- ); // d = deg(f) for (i=1; i<=d; i++) // convert to standard basis using inplace Horner for (j=d-i; j<=d-1; j++) V[j] = sub64s(V[j],mulrec64(A[d-i],V[j+1],P),p); return d; } LONG poleval(LONG *f, LONG d, LONG a, LONG p, recint P ) { LONG y,i; if( d<0 ) return 0; y = f[d]; for( i=d-1; i>=0; i-- ) y = add64s(f[i],mulrec64(y,a,P),p); return y; } /* LONG interp2var( LONG *beta, int n, int vi, int vj, LONG di, LONG dj, LONG dmax, LONG *xx, LONG *I, LONG *M, LONG p, LONG CNT ) { // beta is an array of n evaluation points, di=deg(a,xi),dj=deg(a,xj),dmax=max(di,dj), // xx and I are interpolation points and pre-computed inverses, respectively, both have sizes dmax+1 // Result is stored onto M, a long array of size (dj+1)*(di+1), coeffs of a(xi,xj). LONG i,j, *alpha=array(n), *Ytemp=array(dj+1), *V=array(dmax+1); int k; for ( k=0; k> 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; i