/*****************************************************************************/ /* */ /* Author: Michael Monagan, June 2024 */ /* */ /* Code to factor a multilinear polynomial of F2 */ /* */ /* f = (abc+a+c+ab) (x+y+1) */ /* */ /*****************************************************************************/ /* */ /* MULMOD7.c Added enlargepoly, mulpoly2, equalpoly, facpoly2 */ /* MULMOD8.c Do two hash tests ==> Prob(error) <= n^2 deg f^2 / (2^63)^2 */ /* MULMOD10.c Add setbit, resizepoly, and printing from 1, mergesort */ /* */ /*****************************************************************************/ #include #include #include #define LONG unsigned long int #define ULONG unsigned long int #define DEBUGfacpoly 0 ULONG * array64u( int n ) { // allocate an array of n ULONG's not n bytes unsigned N; ULONG *A; if( n==0 ) return NULL; N = sizeof(ULONG) * n; A = (ULONG *) malloc(N); if( A==0 ) { printf("out of memory\n"); exit(1); } return A; } typedef struct poly { int n; // number of variables int t; // number of terms ULONG *terms; // bit vector } poly; /************************************************************************/ /* */ /* Encode a boolean polynomial in F2[x0,x1,x2] in an array of bits */ /* If n = 80 use two 64 bit words for each monomial thus 2 t words */ /* f = x0x1 + x0x2 + x1 + x2 is encoded as {3,4,[11,101,10,100]} */ /* g = x0x1x3 + x0x2 + x3 is encoded as {4,3,[1011,101,1000]} */ /* */ /************************************************************************/ int termsize(int n) { return (n+63)/64; } void printpoly( poly *f, char x ) { int n,t,q,r,m,i,j,k,first; ULONG mask, *A, z; n = f->n; t = f->t; if( t==0 ) { printf("0;\n"); return; } A = f->terms; q = n/64; r = n%64; m = termsize(n); for( i=0; i0 ) printf("+"); first = 1; for( n=1,j=0; jn; t = f->t; if( t==0 ) { printf("0;\n"); return; } A = f->terms; q = n/64; r = n%64; m = termsize(n); for( i=0; i0 ) printf("+"); first = 1; for( n=0, j=0; j> 2*k; if( d==1 ) printf("%c%d",x,n); else printf("%c%d^%d",x,n,d); first = 0; } } if( r ) { z = A[j]; for( mask=3, k=0; k> 2*k; if( d==1 ) printf("%c%d",x,n); else printf("%c%d^%d",x,n,d); first = 0; } } if( first ) printf("1"); } printf(";\n"); return; } // constructor for poly poly * newpoly(int n, int t) { int i,m; ULONG *A; poly *f; f = (poly *) malloc( sizeof(poly) ); f->n = n; f->t = t; m = termsize(n); A = array64u(m*t); for( i=0; iterms = A; return f; } // destructor for poly void freepoly(poly *f) { ULONG *A; A = f->terms; free(A); free(f); } // copy constructor poly * copypoly( poly *f ) { int n,t,m,i,j; ULONG *A,*B; poly* g; n = f->n; t = f->t; A = f->terms; m = termsize(n); g = newpoly(n,t); B = g->terms; for( i=0; in; t = f->t; A = f->terms; m = termsize(n); g = newpoly(n,s); B = g->terms; if( t>s ) t = s; for( i=0; if = f; q->next = p; return q; } listpoly *joinpoly(listpoly *p, listpoly *q) { listpoly *r; if( p==NULL ) return q; if( q==NULL ) return p; r = p; while( r->next != NULL ) r = r->next; r->next = q; return p; } ULONG *indetspoly(poly *f) { int n,t,m,i,j; ULONG *A,*X; n = f->n; t = f->t; A = f->terms; m = termsize(n); X = array64u(m); for( j=0; j> 32; seed = mult*seed; y = seed >> 32; x = (x<<32) | y; return(x); } void sortpoly(poly *f); int compare(int m, ULONG *X, ULONG *Y); ULONG * randbits( int m, int n ) { // return X = array64u(n) where X[i] is random on [1,2^m) for 064 ) { printf("randbits: m must be in [1,64]\n"); exit(1); } if( n<1 ) { printf("randbits: n must be > 0\n"); exit(1); } X = array64u(n); mask = 0xFFFFFFFFFFFFFFFFL; mask = mask >> (64-m); for( i=0; iterms; q = n/64; r = n%64; if( r==0 ) m = q; else m = q+1; mask = 0xFFFFFFFFFFFFFFFFL; if( r ) mask = mask >> (64-r); for( i=0; iterms; for( i=0,s=0; it = s; return f; } poly* randpoly1( int n, int k, int t ) { // set the first k bits of each monomial to random, zero out the remaining n-k bits int q,r,m,i,j,s; ULONG mask, *A; poly *f; m = termsize(n); f = newpoly(n,t); A = f->terms; for( i=0; i> (64-r); A = f->terms; for( i=0; iterms; for( i=0,s=0; it = s; return f; } void shiftbits( ULONG *X, int m, int s ) { // shift the bits in X right (up) by s>=0 bits int i,q; ULONG x,y,mask; if( s<0 ) { printf("shiftbits s must be nonnegative\n"); exit(1); } if( s>63 ) { q = s/64; for( i=m-1; i>=q; i-- ) X[i] = X[i-q]; while( i>=0 ) { X[i] = 0; i--; } s = s%64; } if( s==0 ) return; mask = 0xFFFFFFFFFFFFFFFFL; mask = mask << (64-s); for( i=m-1; i>=0; i-- ) { x = X[i] << s; if( i>0 ) { y = X[i-1] & mask; y = y >> (64-s); x = x | y; } X[i] = x; } return; } void shiftpoly( poly *f, int s ) { int n,t,m,i; ULONG *A; n = f->n; t = f->t; A = f->terms; m = termsize(n); for( i=0; i> r) << r; //printf("randpoly2: mask=%lu\n",mask); A = f->terms; for( i=0; iterms; for( i=0,s=0; it = s; return f; } /************ HASHING HERE *************/ ULONG degpoly(ULONG m); ULONG counter; ULONG MULMOD( ULONG a, ULONG b, ULONG m, ULONG B, ULONG M ) { // Given a,b,m in F_2[z] with deg(a)0 // Compute a x b mod m in F_2[z] -- Rem(a*b,m,z) mod 2; in Maple // B=2^deg(b) and M=2^d are bit masks ULONG c; counter++; if( a==0 || b==0 ) return 0; c = 0; while(B) { c = c << 1; // c = 2c if( c&M ) c = c ^ m; // c = c xor m if( b&B ) c = c ^ a; // c = c xor a B = B >> 1; // B = B/2 } return c; } ULONG mulmodGF264( ULONG a, ULONG b, ULONG m, ULONG bbit ) { // Let M = z^64 + a63 z^63 + ... + a1 z + a0 be in GF(2)[z] // Given A,B in GF(2)[z] with deg(A)<64, deg(B)<64 compute AB mod M // The A(z), B(z) and M(z) are input as a=A(2), B=B(2), m=M(2)-2^64 ULONG c,topbit; counter++; if( a==0 || b==0 ) return 0; topbit = 1LU<<63; c = 0; while(bbit) { if( c&topbit ) c = (2*c)^m; else c = 2*c; // c = zc mod m if( b&bbit ) c = c^a; // c = c+a bbit = bbit >> 1; } return c; } ULONG mulmod( ULONG a, ULONG b, ULONG m) { // Compute a x b mod m in Z2[z] (Rem(a*b,m,z) mod 2) ULONG c,B,M; if( a==0 || b==0 ) return 0; if( a>=m ) { printf("a must be in [0,m)\n"); exit(1); } if( b>=m ) { printf("b must be in [0,m)\n"); exit(1); } B = 1L << degpoly(b); M = 1L << degpoly(m); c = MULMOD(a,b,m,B,M); return c; } ULONG hashprod(int n, ULONG *X, ULONG *H, ULONG minpoly, ULONG *B, ULONG M) { // X is a bit vector of length n representing a monomial in n varialbes // H is n (random) elements of F_2[z]/minpoly(z) encoded in an integer // Output product( H[i]^X[i], i=0..n-1 ) mod minpoly(z) int q,r,i,j; ULONG h,mask; q = n/64; r = n%64; h = 1; for( i=0; i1; d++ ) m = m>>1; return d; } int haspoly(poly *f,int x) { // return true iff has(f,x) == degree(f,x)>0 int n,t,m,q,r,i,j; ULONG *A,mask; n = f->n; t = f->t; A = f->terms; if( x<0 || x>=n ) return 0; m = termsize(n); q = x/64; r = x%64; mask = 1LU << r; //if( r==0 ) j = q; else j = q+1; BUG? j = q; for( i=0; i> 1; } printf(";\n"); return; } ULONG hashpoly(poly *f, ULONG *X, ULONG *B, ULONG minpoly) { int i,j,k,n,t,m; ULONG h,x,mask,*A; if( minpoly==0 ) { printf("hashpoly: minpoly=0\n"); exit(1); } mask = 1LU << degpoly(minpoly); n = f->n; t = f->t; A = f->terms; m = termsize(n); h = 0; for( i=0; in; t = f->t; A = f->terms; if( x>=n ) { printf("evalto0: x is out of range\n"); exit(1); } q = n/64; r = n%64; if( r=0 ) termsize = q; else termsize = q+1; q = x/64; r = x%64; mask = 1; mask = mask << r; for( k=0, i=0; in; t = f->t; A = f->terms; m = termsize(n); g = newpoly(n,1); X = g->terms; for( j=0; j x1*x2+x2*x3+x3 int n,t,m,i,j; ULONG *A, *X; poly *g,*h; n = f->n; t = f->t; A = f->terms; m = termsize(n); g = newpoly(n,1); X = g->terms; for( j=0; jterms; for( i=0; in; t = f->t; if( t != 1 ) return 0; m = termsize(n); A = f->terms; for( i=0; in; t = f->t; A = f->terms; q = n/64; r = n%64; if( r==0 ) m = q; else m = q+1; s = numxterms(f,x); B = array64u( m*(t-s) ); g = (poly *) malloc(sizeof( poly )); g->n = n; g->t = t-s; g->terms = B; q = x/64; r = x%64; mask = 1; mask = mask << r; for( k=0,i=0; in; t = f->t; A = f->terms; q = n/64; r = n%64; if( r==0 ) m = q; else m = q+1; s = numxterms(f,x); B = array64u( m*s ); g = (poly *) malloc(sizeof( poly )); g->n = n; g->t = s; g->terms = B; q = x/64; r = x%64; mask = 1; mask = mask << r; for( k=0,i=0; iY, -1 if XY[i] ) return 1; } return 0; } void sortswap(int m, ULONG *X, ULONG *Y) { int i; ULONG t; for( i=0; in; t = f->t; A = f->terms; q = n/64; r = n%64; if( r==0 ) m = q; else m = q+1; for( i=1; i0 && compare(m,A+j*m,A+(j-1)*m)==1; j-- ) sortswap(m,A+j*m,A+(j-1)*m); } return; } int issorted(poly *f) { int n,t,i,j,q,r,m,c,flag; ULONG *A; n = f->n; t = f->t; A = f->terms; q = n/64; r = n%64; if( r==0 ) m = q; else m = q+1; //printf("issorted: "); flag = 1; for( i=1; i"); else printf("="); if( c<0 ) flag = 0; } return flag; } int vec2partition64s(ULONG *D, int n, int b, ULONG *x, ULONG *y ) { int i,j,m; m = n/2; sortmove(b,x,D+m*b); sortmove(b,D+m*b,D+0); for( i=1,j=n-1; j>=i; ) { if( compare(b,D+i*b,x)>0 ) { sortmove(b,D+(i-1)*b,D+i*b); i++; } else { sortswap(b,D+i*b,D+j*b); j--; } } sortmove(b,D+(i-1)*b,x); return i-1; } void vec2sort64s(ULONG *A, int n, int b, ULONG *x, ULONG *y ) { int i; if( n<2 ) return; if( n>30 ) { // use quicksort i = vec2partition64s(A,n,b,x,y); vec2sort64s(A,i,b,x,y); vec2sort64s(A+(i+1)*b,n-i-1,b,x,y); } else { // use insertion sort vec2sort64s(A,n-1,b,x,y); sortmove(b,x,A+(n-1)*b); for( i=n-1; i>0 && compare(b,x,A+(i-1)*b)==1; i-- ) sortmove(b,A+i*b,A+(i-1)*b); sortmove(b,A+i*b,x); } return; } void sortpoly(poly* f) { // quicksort int n,m,t; ULONG *A,*x,*y; n = f->n; t = f->t; A = f->terms; m = termsize(n); x = array64u(m); y = array64u(m); vec2sort64s(A,t,m,x,y); free(x); free(y); return; } void mergesort2(int m, int t, ULONG *A, ULONG *B) { int s,i,j,k,r,c; ULONG *C; if( t<2 ) return; s = t/2; mergesort2(m,s,A,B); mergesort2(m,t-s,A+s,B+s); for( i=0; in; t = f->t; if( t<50 ) return sortpoly(f); m = termsize(n); A = f->terms; B = array64u(t*m); // working storage mergesort2(m,t,A,B); free(B); return; } poly* project( poly *f, ULONG * X ) { // Input f in n variables, X a bit vector of length n // Output Y the projection of f onto the variables in X: Y[i]==1 iff haspoly(f,X[i]) int n,t,m,i,j,k; ULONG *A, *B; poly *g,*h; n = f->n; t = f->t; A = f->terms; g = newpoly(n,t); B = g->terms; m = termsize(n); for( i=0; iterms; for( i=0,k=0; iterms; //for( i=0,k=0; in; if( g->n != n ) { printf("addpoly: f and g must have same variables\n"); exit(1); } s = f->t; t = g->t; if( s!=t ) return 0; A = f->terms; B = g->terms; m = termsize(n); for( i=0; in; if( g->n != n ) { printf("addpoly: f and g must have same variables\n"); exit(1); } s = f->t; t = g->t; A = f->terms; B = g->terms; q = n/64; r = n%64; if( r==0 ) m = q; else m = q+1; h = newpoly(n,s+t); C = h->terms; i=0,j=0,k=0; while( in; if( g->n != n ) { printf("mulpoly: f and g must have same variables\n"); exit(1); } s = f->t; t = g->t; A = f->terms; B = g->terms; q = n/64; r = n%64; if( r==0 ) m = q; else m = q+1; h = newpoly(n,s*t); C = h->terms; k = 0; for( j=0; jn; t = f->t; A = f->terms; g = newpoly(2*n,t); m = termsize(n); B = g->terms; s = termsize(2*n); for( i=0; iterms; return g; } poly* mulpoly2( poly *f, poly *g ) { // f(x0,x1,x2) x g(x3,x4,x5,x6) allowing two bits for monomials // the only difference is we add exponent vectors not xor them int n,s,t,q,r,m,i,j,k,l; ULONG *A,*B,*C; poly *h; n = f->n; if( g->n != n ) { printf("mulpoly: f and g must have same variables\n"); exit(1); } f = enlargepoly(f); g = enlargepoly(g); n = f->n; s = f->t; t = g->t; A = f->terms; B = g->terms; q = n/64; r = n%64; if( r==0 ) m = q; else m = q+1; h = newpoly(n,s*t); C = h->terms; k = 0; for( j=0; jn; t = f->t; if( DEBUGfacpoly ) if( t<20 ) { printf("facpoly: f:="); printpoly(f,'x'); } if( t<=1 ) { printpoly(f,'x'); F = conspoly(f,NULL); return F; } st = clock(); F = NULL; // list of factors g = xfactors(f); // the monomial content of f if( !isonepoly(g) ) { printf("facpoly: moncont(f)="); printpoly(g,'x'); F = conspoly(g,F); f = divxfactors(f); } //pt = clock()-st; pt = 0; if( t<=3 ) { printpoly(f,'x'); F = conspoly(f,F); return F; } ht = 0; dt = 0; counter = 0; // set up hashing into GF(2^63) minpoly = 16422940932436772585LU; d = degpoly(minpoly); X1 = randbits(d,n); Y1 = degrees(n,X1); X2 = randbits(d,n); Y2 = degrees(n,X2); m = termsize(n); // pick the first x such that deg(f,x)>0 x = 0; while( xt,D->t); freepoly(C); freepoly(D); } if( h1 || h2 ) z = z | (1L << (i%64) ); Z[j] = z; } et = clock(); g = project(f,Z); // g is irreducible for( j=0; jt == 1 && h->t > 1 ) { printf("h = "); printpoly(h,'y'); exit(1); } et = clock()-st; if( f->t > 500 ) { double etf,htf,cnt,dtf,ptf; etf = et/1000000.0; // convert to seconds htf = ht/1000000.0; htf = 100*htf/etf; // %age of time in GF(2^63) dtf = dt/1000000.0; dtf = 100*dtf/etf; ptf = pt/1000000.0; ptf = 100*ptf/etf; cnt = counter/1000000.0; printf("facpoly: time=%9.4f (%5.2f\%) (%5.2f\%) (%5.2f\%) #muls=%6.2f million\n",etf,htf,dtf,ptf,cnt); } t = g->t; if( DEBUGfacpoly ) if( t<10 ) { printf("facpoly: g:="); printpoly(g,'x'); } else printf("facpoly: #g=%d\n",t); if( !isonepoly(g) ) F = conspoly(g,F); t = h->t; if( DEBUGfacpoly ) if( t<10 ) { printf("facpoly: h:="); printpoly(h,'x'); } else printf("facpoly: #h=%d\n",t); if( !isonepoly(h) ) { G = facpoly(h); F = joinpoly(F,G); } return F; } listpoly* facpoly2( poly *f ) { // Use the FD explicit algorithm int n,t,i,j,m,x,hash; ULONG z,*Z; poly *g,*h,*A,*B,*C,*D,*AD,*BC; clock_t st,ht,et; listpoly *F; n = f->n; t = f->t; if( t<10 ) { printf("facpoly2: f:="); printpoly(f,'x'); } if( t<=1 ) { printpoly(f,'x'); F = conspoly(f,NULL); return F; } F = NULL; // list of factors g = xfactors(f); // the monomial content of f if( !isonepoly(g) ) { printf("facpoly2: moncont(f)="); printpoly(g,'x'); F = conspoly(g,F); f = divxfactors(f); } if( t<=3 ) { printpoly(f,'x'); F = conspoly(f,F); return F; } st = clock(); ht = 0; // pick the first x such that deg(f,x)>0 x = 0; while( xt,BC->t,hash); ht += clock()-et; freepoly(C); freepoly(D); freepoly(AD); freepoly(BC); } if( hash!=0 ) z = z | (1L << (i%64) ); Z[j] = z; } g = project(f,Z); // g is irreducible for( j=0; jt; if( t<10 ) { printf("facpoly2: g:="); printpoly(g,'x'); } else printf("facpoly2: #g=%d\n",t); if( !isonepoly(g) ) F = conspoly(g,F); t = h->t; if( t<10 ) { printf("facpoly2: h:="); printpoly(h,'x'); } else printf("facpoly2: #h=%d\n",t); if( !isonepoly(h) ) F = conspoly(h,F); if( f->t > 100 ) { double etf,htf,cnt,ptf; etf = et/1000000.0; // convert to seconds htf = ht/1000000.0; htf = 100*htf/etf; // %age of time in GF(2^63) printf("facpoly2: time=%9.4f (%5.2f\%)\n",etf,htf); } return F; } /* int main() { int i,j,k,n,s,t; ULONG a,b,c,m,M,B,*A,*X,*D; poly *f,*g,*h; listpoly *F; a = 13; // 1101; b = 5; // 101; B = 4; // 100; m = 23; // 10111; M = 16; // 10000; extern ULONG seed,mult; seed = 1; mult = 6364136223846793003ll; counter = 0; c = MULMOD(a,b,m,B,M); printf("a=%u b=%u c=%u\n",a,b,c); b = 7; // 111 c = MULMOD(a,b,m,B,M); printf("a=%u b=%u c=%u\n",a,b,c); f = randpoly(10,9); printf("f = "); printpoly(f,'x'); for( i=0; i<3; i++ ) printf("#x%d = %d\n",i,numxterms(f,i)); g = evalxto0(f,2); printf("eval(f,x2=0) = "); printpoly(g,'x'); g = diffpoly(f,2); printf("diff(f,x2) = "); printpoly(g,'x'); M = 6; g = project(f,&M); printf("project(f,x1x2) = "); printpoly(g,'x'); printf("f = "); printpoly(f,'x'); printf("sorted(f): %d\n",issorted(f)); //sortpoly(f); //printf("sorted(f): %d\n",issorted(f)); printf("f = "); printpoly(f,'x'); f = newpoly(4,4); A = f->terms; A[0] = 13; A[1] = 9; A[2] = 15; A[3] = 10; printf("f = "); printpoly(f,'x'); g = xfactors(f); printf("g = "); printpoly(g,'x'); h = divxfactors(f); printf("h = "); printpoly(h,'x'); printf("factoring f = "); printpoly(f,'x'); facpoly(f); printf("factor2 starting\n"); facpoly2(f); f = newpoly(4,4); A = f->terms; A[0] = 5; A[1] = 9; A[2] = 6; A[3] = 10; // f = x0*x1 + x0*x3 + x1*x2 + x2*x4; printf("f = "); printpoly(f,'x'); X = indetspoly(f); printf("indets(f)=%lu\n",X[0]); // f2 = x0*x1 + x0*x1^2 + x0^2*x1 + x0^2*x2^2 printf("f2 = "); printpoly2(f,'x'); facpoly(f); printf("\nfactor2 starting\n"); facpoly2(f); printf("f = "); printpoly(f,'x'); g = enlargepoly(f); printf("enlarge(f) = "); printpoly(g,'x'); M = 12; g = project(f,&M); // project onto x2,x3 printf("g = proj(f,x2x3) = "); printpoly(g,'x'); M = 3; h = project(f,&M); // project onto x0,x1 printf("h = proj(f,x0x1) = "); printpoly(h,'x'); f = mulpoly( h, g ); facpoly(f); printf("\nfactor2 starting\n"); facpoly2(f); printf("g = "); printpoly(g,'x'); printf("h = "); printpoly(h,'x'); printf("g^2 = "); printpoly2(mulpoly2(g,g),'x'); printf("f^2 = "); printpoly2(mulpoly2(f,f),'x'); printf("f = h x g = "); printpoly(f,'x'); h = randpoly1(6,3,5); printf("randpoly1: #=%d ",h->t); printpoly(h,'y'); h = randpoly2(8,4,6); printf("randpoly2: #=%d ",h->t); printpoly(h,'y'); h = randpoly2(10,5,6); printf("randpoly2: #=%d ",h->t); printpoly(h,'y'); h = randpoly1(180,10,2); printf("randpoly1: h= "); printpoly(h,'x'); shiftpoly(h,10); printf("shiftpoly: h= "); printpoly(h,'x'); shiftpoly(h,54); printf("shiftpoly: h= "); printpoly(h,'x'); shiftpoly(h,10); printf("shiftpoly: h= "); printpoly(h,'x'); shiftpoly(h,60); printf("shiftpoly: h= "); printpoly(h,'x'); h = randpoly1(180,10,2); printf("randpoly1: h= "); printpoly(h,'x'); shiftpoly(h,100); printf("randpoly1: h= "); printpoly(h,'x'); { int k; poly *A,*B,*C,*D,*AD,*BC; ULONG a,b,c,d,x,minpoly,*X,*Y,*Z; A = evalxto0(f,0); B = diffpoly(f,0); printf("f="); printpoly(f,'x'); printf("A="); printpoly(A,'x'); printf("B="); printpoly(B,'x'); printf("\n"); printf("f := "); printpoly(f,'x'); minpoly = 64+32+1; // z^6+z^5+1 d = degpoly(minpoly); printf("m := ",minpoly); printhash(minpoly,'z'); n = f->n; X = randbits(d,n); Y = degrees(n,X); for( i=0; iBC\n"); printf("\n"); C = diffpoly(A,2); D = diffpoly(B,2); printf("C := "); printpoly(C,'x'); printf("D := "); printpoly(D,'x'); c = hashpoly(C,X,Y,minpoly); printf("#c = %lu = ",c); printhash(c,'z'); d = hashpoly(D,X,Y,minpoly); printf("#d = %lu = ",d); printhash(d,'z'); x = mulmod(a,d,minpoly) ^ mulmod(b,c,minpoly); printf("#AD-BC=%lu\n",x); printf("H := "); printhash(x,'z'); printf("\n"); AD = mulpoly2(A,D); BC = mulpoly2(B,C); printf("AD = "); printpoly2(AD,'x'); printf("BC = "); printpoly2(BC,'x'); if( equalpoly(AD,BC) ) printf("AD=BC\n"); else printf("AD<>BC\n"); printf("\n"); C = diffpoly(A,3); D = diffpoly(B,3); printf("C := "); printpoly(C,'x'); printf("D := "); printpoly(D,'x'); c = hashpoly(C,X,Y,minpoly); printf("#c = %lu = ",c); printhash(c,'z'); d = hashpoly(D,X,Y,minpoly); printf("#d = %lu = ",d); printhash(d,'z'); x = mulmod(a,d,minpoly) ^ mulmod(b,c,minpoly); printf("#AD-BC=%lu\n",x); printf("H := "); printhash(x,'z'); n = 5; f = newpoly(n,4); Z = f->terms; Z[0] = 3; Z[1] = 5; Z[2] = 6; Z[3] = 7; printf("f = "); printpoly(f,'x'); sortpoly(f); printf("f = "); printpoly(f,'x'); g = newpoly(n,3); Z = g->terms; Z[0] = 8; Z[1] = 16; Z[2] = 0; printf("g = "); printpoly(g,'x'); sortpoly(g); printf("g = "); printpoly(g,'x'); h = mulpoly(f,g); printf("h = "); printpoly(h,'x'); A = evalxto0(h,0); B = diffpoly(h,0); printf("A="); printpoly(A,'x'); printf("B="); printpoly(B,'x'); printf("\n"); for( i=1; if->t); F = F->next; } printf("\n"); //printf("h:="); printpoly(h,'x'); printf("#f=%d #g=%d #h=%d\n",f->n,g->n,h->n); A = evalxto0(h,0); B = diffpoly(h,0); printf("A:="); printpoly(A,'x'); printf("B:="); printpoly(B,'x'); printf("\n"); for( i=1; it,j,g->t,h->t); //F = facpoly2(h); F = facpoly(h); printf("Factors found\n"); while( F!=NULL ) { printf(" #f=%d",F->f->t); F = F->next; } printf("\n"); } printf("\n\n"); } } return 1; } */