//polynomial bivariate functions, miscellaneous univariate ones #define DEBUG 0 #define M_INT long long int #define LONG long long int #define ULONG unsigned long long int #define UINT32 unsigned int #define UINT64 unsigned long long typedef enum{false, true} bool; #include #include #include #include //#include "int128g.c" #include "polyalg8.c" //My Algorithms //set all values in an array to 0 void cleanArray64s(LONG *A, int len){ int i; for(i=0;i=0;i--){ for(j=dx;j>=0;j--){ if(A[i*(dx+1)+j] != 0 && i*(dx+1)+j != 0){ printf("%lld*%s^%d*%s^%d+",A[i*(dx+1)+j],x,j,y,i); } } } printf("%lld",A[0]); return; } ULONG convol64s(LONG *A, LONG *B, LONG min, LONG max, LONG d, LONG p){ int i; ULONG z[2]; z[0] =0; z[1] = 0; if( p < 1LL << 50 ) { // if p < 2^50 i = min; while(i=p ) z[1] -= p; zfma(z,A[i],B[d-i]); i++; zfma(z,A[i],B[d-i]); i++; if( z[1]>=p ) z[1] -= p; zfma(z,A[i],B[d-i]); i++; } while( i<=max ) { zfma(z,A[i],B[d-i]); i++; if( z[1]>=p ) z[1] -= p; } } zmod(z,p); return z[0]; } void poladdFast(LONG *A,LONG *B, LONG *C,int dx, LONG p){ int i; for(i=0;i<=dx;i++)C[i] = add64s(A[i],B[i],p); } void addPol(LONG *A, int dz, LONG p){ int j,k; for(k=0;k=k;j--) A[j] = add64s(A[j],A[j+1],p); } //Expands a polynomial with dy factors (y-alpha) void ExpandOutBivar(LONG *A,int dx, int dy, LONG alpha, LONG p){ //local variables LONG alpha2,*MUL,*TEMP,t; int p1,p2,i,j,k; MUL = array(dy+1); TEMP = array(dy+1); cleanArray64s(MUL,dy+1); for (i=1;i<=dy;i++) { //initial iteration if(i==1) { //setup initial y-alpha alpha2 = p - alpha; MUL[0] = alpha2; MUL[1] = 1; //do multiplication p1 = i*(dx+1); for(j=0;j y for(i=0;i=k;j--){ poladdFast(pA,pA2,pA,dx,p); pA2 -= (dx+1); pA -= (dx+1); } } } //if there are multiple blocks of code else{ //For each main block of data, compress Data, add it, then return it for(i=1;i=k;j--){ //poladdFast(&W[j*blockSize],&W[(j+1)*blockSize],&W[j*blockSize],blockSize-1,p); poladdFast(pW,pW2,pW,blockSize-1,p); pW2 = pW; pW -= blockSize; } } T2 = clock(); s2 = s2+ T2-T1; T1 = clock(); pW = W; pA = &A[(i-1)*blockSize]; for(j=0;j<=dz;j++){ for(k=0;k0){ T1 = clock(); pW = W; pA = &A[(blocks-1)*blockSize]; for(j=0;j<=dz;j++){ for(k=0;k=k;j--){ poladdFast(pW,pW2,pW,b-1,p); pW2 = pW; pW -= b; } } T2 = clock(); s2 = s2 + T2-T1; T1 = clock(); pW = W; pA = &A[(blocks-1)*blockSize]; for(j=0;j<=dz;j++){ for(k=0;k0; i-- ) { // compute g[i] = alpha^i/i! mod p g[i] = mulrec64(fac,g[i],P); fac = mulrec64((LONG) i,fac,P); }*/ h = array(2*n+1); //FFTpolmul64s(f,g,h,n,n,p); //polmul64s(f,g,h,n,n,p); //altarnately can use this polmul64s(f,g,h,n,n,p); polrev64s(h,n); f[0] = h[0]; //fac = inv; for( i=n; i>0; i-- ) { // compute f[i] = h[i]/i! mod p f[i] = mulrec64(dF[i],h[i],P); //fac = mulrec64(fac,(LONG) i,P); } //free(g); free(h); return; } //Custom Functions LONG DotProduct(LONG *A, LONG *B, int d, LONG p){ int i,j,k; ULONG z[2]; z[0] = 0; z[1] = 0; i=0; while(i<=d-3){ zfma(z,A[i],B[i]);i++; zfma(z,A[i],B[i]);i++; zfma(z,A[i],B[i]);i++; } while(i<=d){ zfma(z,A[i],B[i]);i++; } zmod(z,p); return z[0]; } LONG DotProductP(LONG *A, LONG *B, int d, LONG p){ int i,j,k; ULONG z[2]; z[0] = 0; z[1] = 0; i=0; while(i<=d-2){ zfma(z,A[i],B[i]);i++;//if(z[1]>=p){z[1] -=p;} zfma(z,A[i],B[i]);i++;if(z[1]>=p){z[1] -=p;} } while(i<=d){ zfma(z,A[i],B[i]);i++;if(z[1]>=p){z[1] -=p;} } zmod(z,p); return z[0]; } ULONG fastPolyMult(LONG *poly1,LONG *poly2, LONG *T, int deg1, int deg2, LONG p){ //local variables int k,m,min,max; ULONG z[2]; //clean T //cleanArray64s(T,deg1+deg2); for(k=0;k<=deg1+deg2;k++){ min = max32s(0,k-deg2); max = min32s(k,deg1); z[0] = 0; z[1] = 0; m = min; while(m<=max-3){ zfma(z,poly1[m],poly2[k-m]);m++; zfma(z,poly1[m],poly2[k-m]);m++; zfma(z,poly1[m],poly2[k-m]);m++; } while(m<=max){ zfma(z,poly1[m],poly2[k-m]);m++; } zmod(z,p); T[k] = add64s(z[0],T[k],p); } } //perform the Extended Euclidean Algorithm int MultiEEA(LONG *U, int d, int n, LONG *M, LONG *W, LONG p){ //size of U = n*(d+1) //size of M = ... //size of W = 2*((n-1)*d+1) + d+1 //local variables int i,j,du,dm,ds,dt,dg,dmCalc,mPos,point; LONG *u,*m,*mCalc,*g,*Wptr,t,alpha2; //clean array cleanArray64s(W,4*(n*d+1) + (d+1)); //set initial array pointers mCalc = W; g = mCalc + (n-1)*d+1; //define initial position in the M array mPos = 0; for(i=n-1;i>1;i--){ mPos = mPos + i*d+1; } mCalc[0] = 1; dmCalc = 0; //Main loop u = U + (n-1)*(d+1); for (i=n;i>=2;i--){ //calculate mcalc*U_i dmCalc = polmul64s(mCalc,u,mCalc,dmCalc,d,p); //add new mcalc to M polcopy64s(mCalc,dmCalc,M+mPos); mPos = mPos - ((n-i+2)*d + 1); //update u pointer u -= d+1; } //make sure gcd(u_i,M_i) = 1 for all M u = g + (n-1)*d+1; Wptr = u + d+1; dmCalc = (n-1)*d; mPos = 0; for(i=0;i0) return -1; dmCalc -= d; mPos += (n-i-1)*d+1; } return 0; } void generateGcdexS(LONG *U, int n, int du, LONG *M, int dx, LONG *S, int *sDeg, LONG *W, LONG p){ //local variables int i,j,k,du2,dm,dg,ds,wTemp,dt,mPos; LONG *uTemp,*mTemp,*g,*wPtr; cleanArray64s(W,4*n*(du+1)); uTemp = W; mTemp = uTemp + du+1; g = mTemp + (n-1)*du+1; wPtr = g + n*du+1; mPos = 0; //Calculate the sigma term and subtract it from C for (i=1;i= 0){ da = polgcd64s(cont,W,da,db,p); } i++; } return da; } void scalefactors( LONG *F, LONG *F0, int r, LONG du, LONG dx, LONG dy, LONG p ) { // Input: F is the answer of BHL (HenselLiftCubic), where f[rr][(dx+1)*j+i] = coeff( coeff(f[rr],y-alpha,j), x, i) // f[1] is at F[0], f[2] at F[2*(dx+1)*(dy+1)], f[3] at F[4*(dx+1)*(dy+1)] etc. f[r] at F[(r-1)*2*(dx+1)*(dy+1)] // r is the number of factors, F0 is the list of initial factors f0[rr], rr=1..r. // Output: Scale the answer to satisfy Eval(f[rr],y=alpha) mod p = f0[rr], rr=1..r. LONG *Temp, temp, i, j, k, dfx, c, LCF, LCF0; int rr; for ( rr=1; rr<=r; rr++ ) { Temp = &F[2*(rr-1)*(dx+1)*(dy+1) + dx]; k = dx; while (k>=0) { if (*Temp == 0) { Temp--; k--; } else break; } dfx = k; LCF = *Temp; printf("dfx = %d, LCF = %d\n",dfx, LCF); LCF0 = F0[(rr-1)*(du+1)+dfx]; printf("LCF0 = %d\n",LCF0); c = mul64s( modinv64s( LCF, p ), LCF0, p ); printf("c=%d\n",c); for ( i=0; i=0; k-- ) { for ( i=k; i<=d-1; i++ ) a[i] = add64s( a[i],mul64s(b,a[i+1],p),p ); } return d; } void ExpandF2( LONG *F, int r, LONG dx, LONG dy, LONG alpha, LONG p) { // Input: F is the answer of BHL (scaled), where f[rr][(dx+1)*j+i] = coeff( coeff(f[rr],y-alpha,j), x, i) // f[1] is at F[0], f[2] at F[2*(dx+1)*(dy+1)], f[3] at F[4*(dx+1)*(dy+1)] etc. f[r] at F[(r-1)*2*(dx+1)*(dy+1)] // r is the number of factors. The input alpha is p - alpha[j] in CMSHL Maple code // Output: returns expanded f onto F LONG *Temp=array(dy+1), i, j, k, d; int rr; for ( rr=1; rr<=r; rr++ ) { for ( i=0; i=0 ) { if ( Temp[k] == 0 ) k--; else break; } d = k; TaylorShift2( Temp, d, alpha, p ); for ( j=0; j=2 polynomials //utilizes evaluation-interpolation int polmulbivarN64s(LONG ** A, LONG* C, int * dxA, int * dzA, int dx, int dz, int n, LONG p, LONG *W){ //The amount of space used is: (dx+1)^2 + (dx+3)(dz+1) + n(dz+1) + 2dx+6 //where dx = sum(dxA)+1 and dz = sum(dzA) //local variables int DX, DZ; LONG i,j,k, m, r; LONG *p1, *V, *TEMP, *evalPoints, *lagInterpPolys, *evalProducts, *evalFactors, *vector; DX = dx; DZ = dz; if(DX%2==1){DX += 1;} //assign space V = W; TEMP = V; V += (DZ+1); evalPoints = V; V += (DX+1); lagInterpPolys = V; V += (DX+1)*(DX+1); evalProducts = V; V += (DX+1)*(DZ+1); evalFactors = V; V += n*(DZ+1); vector = V; V += (DX+1); //set evaluation points evalPoints[0] = 0; p1 = evalPoints+1; for(i=1;i<=dx/2;i++){ p1[0] = i; p1[1] = p-i; p1 +=2; } //set up polynomials for interpolation LagInterpSetup(lagInterpPolys,evalPoints,DX,V,p); //perform evaluation + multiplication cleanArray64s(evalProducts,(DX+1)*(DZ+1)); for(j=0;j<=DX;j++){ //for each evaluation point cleanArray64s(evalFactors,n*(dz+1)); //evaluate the n polynomials for(i=0;i