void I_RAT_mul( RAT a, RAT b, RAT *c ) { int r; RAT aa,bb; aa = a; bb = b; if ((r = igcd(a.num,b.den.i)) > 1) { b.den.i /= r; a.num /= r; } if ((r = igcd(b.num,a.den.i)) > 1) { a.den.i /= r; b.num /= r; } if (a.num == 0) c->num = 0; else { c->num = a.num*b.num; if (c->num/a.num != b.num) { arith_overflow_func(1,I_RAT_mul,aa,bb,c); return; } } c->den.i = a.den.i*b.den.i; if (c->den.i/a.den.i != b.den.i) arith_overflow_func(1,I_RAT_mul,aa,bb,c); }
void I_RAT_sub( RAT a, RAT b, RAT *c ) { int r,x,y1,y2,z1,z2,an,bn; if (a.den.i == b.den.i) { c->den.i = a.den.i; c->num = a.num-b.num; if (c->num+b.num != a.num) { arith_overflow_func(1,I_RAT_sub,a,b,c); return; } } else { c->den.i = (x = (a.den.i/igcd(a.den.i,b.den.i)))*b.den.i; an = (y1 = a.num)*(y2 = (c->den.i/a.den.i)); bn = (z1 = b.num)*(z2 = (c->den.i/b.den.i)); c->num = an-bn; if ((c->den.i/b.den.i != x) || (an/y2 != y1) || (bn/z2 != z1) || (c->num+bn != an)) { arith_overflow_func(1,I_RAT_sub,a,b,c); return; } } if ((r = igcd(c->num,c->den.i)) > 1) { c->den.i /= r; c->num /= r; } }
int omega(int n,int *matrix[],int *w) { int i,j,k,g,sign=1,det=0; int **minor; if (n==1) return matrix[0][0]; minor=new int* [n-1]; for (i=0;i<n;i++) { for (j=k=0;j<n-1;j++) { if (j==i) k++; // skip i-th row minor[j]=&matrix[k++][1]; } w[i]=sign*matrix[i][0]*determinant(n-1,minor); // calculate co-factor det+=w[i]; sign=-sign; } delete [] minor; if (det==0) return 0; // singular matrix if (det<0) { // deal with -ve sign det=-det; for (i=0;i<n;i++) w[i]=-w[i]; } // remove common factors g=det; for (i=0;i<n;i++) g=igcd(g,absval(w[i])); det/=g; for (i=0;i<n;i++) w[i]/=g; return det; }
/* Compute the derived values of a halftone tile. */ void gx_compute_cell_values(gx_ht_cell_params_t * phcp) { const int M = phcp->M, N = phcp->N, M1 = phcp->M1, N1 = phcp->N1; const uint m = any_abs(M), n = any_abs(N); const uint m1 = any_abs(M1), n1 = any_abs(N1); const ulong C = phcp->C = (ulong)m * m1 + (ulong)n * n1; const int D = phcp->D = igcd(m1, n); const int D1 = phcp->D1 = igcd(m, n1); phcp->W = C / D, phcp->W1 = C / D1; /* Compute the shift value. */ /* If M1 or N is zero, the shift is zero. */ if (M1 && N) { int h = 0, k = 0, dy = 0; int shift; /* * There may be a faster way to do this: see Knuth vol. 2, * section 4.5.2, Algorithm X (p. 302) and exercise 15 * (p. 315, solution p. 523). */ while (dy != D) if (dy > D) { if (M1 > 0) ++k; else --k; dy -= m1; } else { if (N > 0) ++h; else --h; dy += n; } shift = h * M + k * N1; /* We just computed what amounts to a right shift; */ /* what we want is a left shift. */ phcp->S = imod(-shift, phcp->W); } else phcp->S = 0; if_debug12('h', "[h]MNR=(%d,%d)/%d, M'N'R'=(%d,%d)/%d => C=%lu, D=%d, D'=%d, W=%u, W'=%u, S=%d\n", M, N, phcp->R, M1, N1, phcp->R1, C, D, D1, phcp->W, phcp->W1, phcp->S); }
void fpmul(_MIPD_ flash x,int n,int d,flash y) { /* multiply x by small fraction n/d - y=x*n/d */ int r,g; #ifdef MR_OS_THREADS miracl *mr_mip=get_mip(); #endif if (mr_mip->ERNUM) return; if (n==0 || size(x)==0) { zero(y); return; } if (n==d) { copy(x,y); return; } MR_IN(42) if (d<0) { d=(-d); n=(-n); } numer(_MIPP_ x,mr_mip->w1); denom(_MIPP_ x,mr_mip->w2); r=subdiv(_MIPP_ mr_mip->w1,d,mr_mip->w3); g=igcd(d,r); r=subdiv(_MIPP_ mr_mip->w2,n,mr_mip->w3); g*=igcd(n,r); mr_mip->check=OFF; premult(_MIPP_ mr_mip->w1,n,mr_mip->w5); premult(_MIPP_ mr_mip->w2,d,mr_mip->w6); subdiv(_MIPP_ mr_mip->w5,g,mr_mip->w5); subdiv(_MIPP_ mr_mip->w6,g,mr_mip->w6); mr_mip->check=ON; if (fit(mr_mip->w5,mr_mip->w6,mr_mip->nib)) fpack(_MIPP_ mr_mip->w5,mr_mip->w6,y); else mround(_MIPP_ mr_mip->w5,mr_mip->w6,y); MR_OUT }
void I_RAT_add( RAT a, RAT b, RAT *c ) { int r,x,y1,y2,z1,z2,na,nb; if (a.den.i == b.den.i) { c->den.i = a.den.i; c->num = a.num+b.num; if (c->num-b.num != a.num) { arith_overflow_func(1,I_RAT_add,a,b,c); return; } } else { c->den.i = (x = (a.den.i/igcd(a.den.i,b.den.i)))*b.den.i; na = (y1 = a.num)*(y2 = (c->den.i/a.den.i)); nb = (z1 = b.num)*(z2 = (c->den.i/b.den.i)); c->num = na+nb; if ((c->den.i/b.den.i != x) || (na/y2 != y1) || (nb/z2 != z1) || (c->num-nb != na)) { arith_overflow_func(1,I_RAT_add,a,b,c); return; } } if ((r = igcd(c->num,c->den.i)) > 1) { c->den.i /= r; c->num /= r; } }
int main() { /* factoring program using Lenstras Elliptic Curve method */ int phase,m,k,nc,iv,pos,btch,u,v; long i,p,pa,interval; big q,x,z,a,x1,z1,x2,z2,xt,zt,n,fvw; static big fu[1+MULT/2]; static BOOL cp[1+MULT/2]; mip=mirsys(30,0); q=mirvar(0); x=mirvar(0); z=mirvar(0); a=mirvar(0); x1=mirvar(0); z1=mirvar(0); x2=mirvar(0); z2=mirvar(0); n=mirvar(0); t=mirvar(0); s1=mirvar(0); d1=mirvar(0); s2=mirvar(0); d2=mirvar(0); ak=mirvar(0); xt=mirvar(0); zt=mirvar(0); fvw=mirvar(0); w=mirvar(0); gprime(LIMIT1); for (m=1;m<=MULT/2;m+=2) if (igcd(MULT,m)==1) { fu[m]=mirvar(0); cp[m]=TRUE; } else cp[m]=FALSE; printf("input number to be factored\n"); cinnum(n,stdin); if (isprime(n)) { printf("this number is prime!\n"); return 0; } prepare_monty(n); for (nc=1,k=6;k<100;k++) { /* try a new curve */ /* generating an elliptic curve */ u=k*k-5; v=4*k; convert(u,x); nres(x,x); convert(v,z); nres(z,z); nres_modsub(z,x,a); /* a=v-u */ copy(x,t); nres_modmult(x,x,x); nres_modmult(x,t,x); /* x=u^3 */ copy(z,t); nres_modmult(z,z,z); nres_modmult(z,t,z); /* z=v^3 */ copy(a,t); nres_modmult(t,t,t); nres_modmult(t,a,t); /* t=(v-u)^3 */ convert(3*u,a); nres(a,a); convert(v,ak); nres(ak,ak); nres_modadd(a,ak,a); nres_modmult(t,a,t); /* t=(v-u)^3.(3u+v) */ convert(u,a); nres(a,a); copy(a,ak); nres_modmult(a,a,a); nres_modmult(a,ak,a); /* a=u^3 */ convert(v,ak); nres(ak,ak); nres_modmult(a,ak,a); /* a=u^3.v */ nres_premult(a,16,a); nres_moddiv(t,a,ak); /* ak=(v-u)^3.(3u+v)/16u^3v */ nc++; phase=1; p=0; i=0; btch=50; printf("phase 1 - trying all primes less than %d\n",LIMIT1); printf("prime= %8ld",p); forever { /* main loop */ if (phase==1) { p=mip->PRIMES[i]; if (mip->PRIMES[i+1]==0) { /* now change gear */ phase=2; printf("\nphase 2 - trying last prime less than %ld\n", LIMIT2); printf("prime= %8ld",p); copy(x,xt); copy(z,zt); nres_modadd(x,z,s2); nres_modsub(x,z,d2); /* P = (s2,d2) */ duplication(s2,d2,x,z); nres_modadd(x,z,s1); nres_modsub(x,z,d1); /* 2.P = (s1,d1) */ nres_moddiv(x1,z1,fu[1]); /* fu[1] = x1/z1 */ addition(x1,z1,s1,d1,s2,d2,x2,z2); /* 3.P = (x2,z2) */ for (m=5;m<=MULT/2;m+=2) { /* calculate m.P = (x,z) and store fu[m] = x/z */ nres_modadd(x2,z2,s2); nres_modsub(x2,z2,d2); addition(x1,z1,s2,d2,s1,d1,x,z); copy(x2,x1); copy(z2,z1); copy(x,x2); copy(z,z2); if (!cp[m]) continue; copy(z2,fu[m]); nres_moddiv(x2,fu[m],fu[m]); } ellipse(xt,zt,MULT,x,z,x2,z2); nres_modadd(x,z,xt); nres_modsub(x,z,zt); /* MULT.P = (xt,zt) */ iv=(int)(p/MULT); if (p%MULT>MULT/2) iv++; interval=(long)iv*MULT; p=interval+1; ellipse(x,z,iv,x1,z1,x2,z2); /* (x1,z1) = iv.MULT.P */ nres_moddiv(x1,z1,fvw); /* fvw = x1/z1 */ nres_modsub(fvw,fu[p%MULT],q); marks(interval); btch*=100; i++; continue; } pa=p; while ((LIMIT1/p) > pa) pa*=p; ellipse(x,z,(int)pa,x1,z1,x2,z2); copy(x1,x); copy(z1,z); copy(z,q); } else { /* phase 2 - looking for last large prime factor of (p+1+d) */ p+=2; pos=(int)(p%MULT); if (pos>MULT/2) { /* increment giant step */ iv++; interval=(long)iv*MULT; p=interval+1; marks(interval); pos=1; nres_moddiv(x2,z2,fvw); nres_modadd(x2,z2,s2); nres_modsub(x2,z2,d2); addition(x1,z1,s2,d2,xt,zt,x,z); copy(x2,x1); copy(z2,z1); copy(x,x2); copy(z,z2); } if (!cp[pos]) continue; /* if neither interval +/- pos is prime, don't bother */ if (!plus[pos] && !minus[pos]) continue; nres_modsub(fvw,fu[pos],t); nres_modmult(q,t,q); } if (i++%btch==0) { /* try for a solution */ printf("\b\b\b\b\b\b\b\b%8ld",p); fflush(stdout); egcd(q,n,t); if (size(t)==1) { if (p>LIMIT2) break; else continue; } if (compare(t,n)==0) { printf("\ndegenerate case"); break; } printf("\nfactors are\n"); if (isprime(t)) printf("prime factor "); else printf("composite factor "); cotnum(t,stdout); divide(n,t,n); if (isprime(n)) printf("prime factor "); else printf("composite factor "); cotnum(n,stdout); return 0; } } if (nc>NCURVES) break; printf("\ntrying a different curve %d\n",nc); } printf("\nfailed to factor\n"); return 0; }
Ps_ZZn operator*(Ps_ZZn& a,Ps_ZZn& b) { Ps_ZZn prod; ZZn t; term_ps_zzn *aptr,*bptr,*pos; int ka,kb,i,pa,pb,d,deg,g; if (a.IsInt()) { if (a.start==NULL) return prod; else return (a.start->an*b); } if (b.IsInt()) { if (b.start==NULL) return prod; else return (b.start->an*a); } g=igcd(a.pwr,b.pwr); deg=psN/g; #ifdef FFT if (deg>=FFT_BREAK_EVEN) { // use fast methods big *A,*B,*C; A=(big *)mr_alloc(deg,sizeof(big)); B=(big *)mr_alloc(deg,sizeof(big)); C=(big *)mr_alloc(deg,sizeof(big)); char *memc=(char *)memalloc(deg); for (i=0;i<deg;i++) C[i]=mirvar_mem(memc,i); ka=a.pwr/g; a.decompress(ka); aptr=a.start; while (aptr!=NULL) { d=aptr->n; if (d >= deg) break; A[d]=getbig(aptr->an); aptr=aptr->next; } kb=b.pwr/g; b.decompress(kb); bptr=b.start; while (bptr!=NULL) { d=bptr->n; if (d >= deg) break; B[d]=getbig(bptr->an); bptr=bptr->next; } mr_ps_zzn_mul(deg,A,B,C); pos=NULL; for (d=0;d<deg;d++) { t=C[d]; if (t.iszero()) continue; pos=prod.addterm(t,d*g,pos); } memkill(memc,deg); a.compress(ka); b.compress(kb); mr_free(C); mr_free(B); mr_free(A); } else { #endif bptr=b.start; while (bptr!=NULL) { aptr=a.start; pb=bptr->n*b.pwr-b.offset; pos=NULL; while (aptr!=NULL) { pa=aptr->n*a.pwr-a.offset; if (pb+pa>=psN) break; pos=prod.addterm(aptr->an*bptr->an,pa+pb,pos); aptr=aptr->next; } bptr=bptr->next; } #ifdef FFT } #endif if (prod.start!=NULL) prod.offset=a.offset+b.offset; return prod; }
Ps_ZZn& Ps_ZZn::operator*=(Ps_ZZn& b) { term_ps_zzn *ptr,*bptr; int g,d,deg,ka,kb; if (IsInt()) { if (start!=NULL) *this = start->an*b; return *this; } if (b.IsInt()) { if (b.start==NULL) clear(); else *this *=(b.start->an); return *this; } g=igcd(pwr,b.pwr); deg=psN/g; #ifdef FFT if (deg>=FFT_BREAK_EVEN) { big *A,*B; A=(big *)mr_alloc(deg,sizeof(big)); B=(big *)mr_alloc(deg,sizeof(big)); ka=pwr/g; decompress(ka); pad(); ptr=start; while (ptr!=NULL) { d=ptr->n; if (d>=deg) break; A[d]=getbig(ptr->an); ptr=ptr->next; } kb=b.pwr/g; b.decompress(kb); bptr=b.start; while (bptr!=NULL) { d=bptr->n; if (d>=deg) break; B[d]=getbig(bptr->an); bptr=bptr->next; } mr_ps_zzn_mul(deg,A,B,A); mr_free(B); mr_free(A); b.compress(kb); } else { #endif *this=*this*b; return *this; #ifdef FFT } #endif norm(); offset+=b.offset; return *this; }
term_ps_zzn* Ps_ZZn::addterm(const ZZn& a,int power,term_ps_zzn* pos) { term_ps_zzn* newone; term_ps_zzn* ptr; term_ps_zzn *t,*iptr; int dc,pw; ptr=start; iptr=NULL; // // intelligently determine the most compressed form to use // for example if coefficient a=1 always, and power = -7 -5 -3 -1 1 3.... // then set pwr=2, offset=7 and PS = 1 + x + x^2 // pw=power+offset; if (one_term() && pw!=0) { // when PS has only one term, pwr is undefined if (pw<0) pwr=-pw; else pwr=pw; } dc=igcd(pw,pwr); if (dc != pwr) decompress(pwr/dc); power=pw/pwr; // quick scan through to detect if term exists already // and to find insertion point if (pos!=NULL) ptr=pos; while (ptr!=NULL) { if (ptr->n==power) { ptr->an+=a; if (ptr->an.iszero()) { // delete term if (ptr==start) { // delete first one start=ptr->next; delete ptr; norm(); return start; } iptr=ptr; ptr=start; while (ptr->next!=iptr)ptr=ptr->next; ptr->next=iptr->next; delete iptr; return ptr; } return ptr; } if (ptr->n<power) iptr=ptr; // determines order else break; ptr=ptr->next; } newone=new term_ps_zzn; newone->next=NULL; newone->an=a; newone->n=power; pos=newone; if (start==NULL) { start=newone; norm(); return pos; } // insert at the start if (iptr==NULL) { t=start; start=newone; newone->next=t; norm(); return pos; } // insert new term t=iptr->next; iptr->next=newone; newone->next=t; return pos; }
int main() { /* factoring program using Williams (p+1) method */ int k,phase,m,nt,iv,pos,btch; long i,p,pa,interval; big b,q,n,fp,fvw,fd,fn,t; static big fu[1+MULT/2]; static BOOL cp[1+MULT/2]; mip=mirsys(30,0); b=mirvar(0); q=mirvar(0); n=mirvar(0); t=mirvar(0); fp=mirvar(0); fvw=mirvar(0); fd=mirvar(0); fn=mirvar(0); gprime(LIMIT1); for (m=1;m<=MULT/2;m+=2) if (igcd(MULT,m)==1) { fu[m]=mirvar(0); cp[m]=TRUE; } else cp[m]=FALSE; printf("input number to be factored\n"); cinnum(n,stdin); if (isprime(n)) { printf("this number is prime!\n"); return 0; } for (nt=0,k=3;k<10;k++) { /* try more than once for p+1 condition (may be p-1) */ convert(k,b); /* try b=3,4,5.. */ convert((k*k-4),t); if (egcd(t,n,t)!=1) continue; /* check (b*b-4,n)!=0 */ nt++; phase=1; p=0; btch=50; i=0; printf("phase 1 - trying all primes less than %d\n",LIMIT1); printf("prime= %8ld",p); forever { /* main loop */ if (phase==1) { /* looking for all factors of p+1 < LIMIT1 */ p=mip->PRIMES[i]; if (mip->PRIMES[i+1]==0) { /* now change gear */ phase=2; printf("\nphase 2 - trying last prime less than %ld\n" ,LIMIT2); printf("prime= %8ld",p); copy(b,fu[1]); copy(b,fp); mad(b,b,b,n,n,fd); decr(fd,2,fd); negify(b,t); mad(fd,b,t,n,n,fn); for (m=5;m<=MULT/2;m+=2) { /* store fu[m] = Vm(b) */ negify(fp,t); mad(fn,fd,t,n,n,t); copy(fn,fp); copy(t,fn); if (!cp[m]) continue; copy(t,fu[m]); } convert(MULT,t); lucas(b,t,n,fp,fd); iv=(int)(p/MULT); if (p%MULT>MULT/2) iv++; interval=(long)iv*MULT; p=interval+1; convert(iv,t); lucas(fd,t,n,fp,fvw); negify(fp,fp); subtract(fvw,fu[p%MULT],q); marks(interval); btch*=100; i++; continue; } pa=p; while ((LIMIT1/p) > pa) pa*=p; convert((int)pa,t); lucas(b,t,n,fp,q); copy(q,b); decr(q,2,q); } else { /* phase 2 - looking for last large prime factor of (p+1) */ p+=2; pos=(int)(p%MULT); if (pos>MULT/2) { /* increment giant step */ iv++; interval=(long)iv*MULT; p=interval+1; marks(interval); pos=1; copy(fvw,t); mad(fvw,fd,fp,n,n,fvw); negify(t,fp); } if (!cp[pos]) continue; /* if neither interval+/-pos is prime, don't bother */ if (!plus[pos] && !minus[pos]) continue; subtract(fvw,fu[pos],t); mad(q,t,t,n,n,q); /* batching gcds */ } if (i++%btch==0) { /* try for a solution */ printf("\b\b\b\b\b\b\b\b%8ld",p); fflush(stdout); egcd(q,n,t); if (size(t)==1) { if (p>LIMIT2) break; else continue; } if (compare(t,n)==0) { printf("\ndegenerate case"); break; } printf("\nfactors are\n"); if (isprime(t)) printf("prime factor "); else printf("composite factor "); cotnum(t,stdout); divide(n,t,n); if (isprime(n)) printf("prime factor "); else printf("composite factor "); cotnum(n,stdout); return 0; } } if (nt>=NTRYS) break; printf("\ntrying again\n"); } printf("\nfailed to factor\n"); return 0; }