Ilya Zakharevich on Sat, 29 Sep 2001 11:51:05 -0400 |
[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]
[PATCH CVS] 2-adic shift |
This adds a flag to shift() which changes the behaviour for right-shift of negative numbers: instead of preserving-but-ignoring the sign, the shift is performed as if modulo big power of 2. This enables compatibility of shift() with 2-complement semantic of negative numbers. Enjoy, Ilya P.S. Tested with shiftr(x,n)=if(x<0&&n<0,shift(x+1,n)-1,shift(x,n)) lim=66 for(s=0,lim,print1(".");forvec(X=[[0,lim],[0,lim]],n=2^X[2]-2^X[1];r=shift(-n,-s,1);r1=shiftr(-n,-s);if(r==r1,,print("shift(-"n",-"s",1) = "r" != "r1)),1)) Index: src/basemath/gen3.c =================================================================== RCS file: /home/megrez/cvsroot/pari/src/basemath/gen3.c,v retrieving revision 1.31 diff -p -u -r1.31 gen3.c --- src/basemath/gen3.c 2001/09/05 17:33:31 1.31 +++ src/basemath/gen3.c 2001/09/29 15:43:38 @@ -890,13 +890,19 @@ gdivround(GEN x, GEN y) GEN gshift(GEN x, long n) { + return gshift3(x, n, 0); +} + +GEN +gshift3(GEN x, long n, long flag) +{ long i,l,lx, tx = typ(x); GEN y; switch(tx) { case t_INT: - return shifti(x,n); + return shifti3(x,n,flag); case t_REAL: return shiftr(x,n); Index: src/headers/paridecl.h =================================================================== RCS file: /home/megrez/cvsroot/pari/src/headers/paridecl.h,v retrieving revision 1.99 diff -p -u -r1.99 paridecl.h --- src/headers/paridecl.h 2001/09/05 17:33:32 1.99 +++ src/headers/paridecl.h 2001/09/29 15:43:41 @@ -895,6 +895,7 @@ GEN greal(GEN x); GEN grndtoi(GEN x, long *e); GEN ground(GEN x); GEN gshift(GEN x, long n); +GEN gshift3(GEN x, long n, long flag); GEN gsubst(GEN x, long v, GEN y); GEN gtopoly(GEN x, long v); GEN gtopolyrev(GEN x, long v); @@ -1029,6 +1030,7 @@ int ratlift(GEN x, GEN m, GEN *a, GE GEN resss(long x, long y); double rtodbl(GEN x); GEN shifti(GEN x, long n); +GEN shifti3(GEN x, long n, long flag); long smodsi(long x, GEN y); GEN sqri(GEN x); GEN truedvmdii(GEN x, GEN y, GEN *z); Index: src/kernel/none/mp.c =================================================================== RCS file: /home/megrez/cvsroot/pari/src/kernel/none/mp.c,v retrieving revision 1.46 diff -p -u -r1.46 mp.c --- src/kernel/none/mp.c 2001/08/28 17:55:36 1.46 +++ src/kernel/none/mp.c 2001/09/29 15:43:43 @@ -259,6 +259,12 @@ affrr(GEN x, GEN y) GEN shifti(GEN x, long n) { + return shifti3(x, n, 0); +} + +GEN +shifti3(GEN x, long n, long flag) +{ const long s=signe(x); long lx,ly,i,m; GEN y; @@ -285,19 +291,50 @@ shifti(GEN x, long n) } else { + long lyorig; + n = -n; - ly = lx - (n>>TWOPOTBITS_IN_LONG); - if (ly<3) return gzero; + ly = lyorig = lx - (n>>TWOPOTBITS_IN_LONG); + if (ly<3) + return flag ? stoi(-1) : gzero; y = new_chunk(ly); m = n & (BITS_IN_LONG-1); - if (!m) for (i=2; i<ly; i++) y[i]=x[i]; - else - { + if (m) { shift_right(y,x, 2,ly, 0,m); if (y[2] == 0) { - if (ly==3) { avma = (long)(y+3); return gzero; } + if (ly==3) { avma = (long)(y+3); return flag ? stoi(-1) : gzero; } ly--; avma = (long)(++y); + } + } else { + for (i=2; i<ly; i++) y[i]=x[i]; + } + /* With FLAG: round up instead of rounding down */ + if (flag) { /* Check low bits of x */ + i = lx; + flag = 0; + while (--i >= lyorig) { + if (x[i]) { + flag = 1; /* Need to increment y by 1 */ + break; + } + } + if (!flag && m) + flag = x[lyorig - 1] & ((1<<m) - 1); + } + if (flag) { /* Increment i */ + i = ly; + while (1) { + if (--i < 2) { /* Need to extend y on the left */ + if (avma <= bot) + err(errpile); + avma = (long)(--y); ly++; + y[2] = 1; + break; + } + if (++y[i]) + break; + /* Now we need to propagate the bit into the next longword... */ } } } Index: src/language/helpmsg.c =================================================================== RCS file: /home/megrez/cvsroot/pari/src/language/helpmsg.c,v retrieving revision 1.26 diff -p -u -r1.26 helpmsg.c --- src/language/helpmsg.c 2001/04/07 19:43:57 1.26 +++ src/language/helpmsg.c 2001/09/29 15:43:44 @@ -421,7 +421,7 @@ char *helpmessages_basic[]={ "setrand(n): reset the seed of the random number generator to n", "setsearch(x,y,{flag=0}): looks if y belongs to the set x. If flag is 0 or omitted, returns 0 if it is not, otherwise returns the index j such that y==x[j]. If flag is non-zero, return 0 if y belongs to x, otherwise the index j where it should be inserted", "setunion(x,y): union of the sets x and y", - "shift(x,n): shift x left n bits if n>=0, right -n bits if n<0", + "shift(x,n,{flag=0}): shift x left n bits if n>=0, right -n bits if n<0. If flag is true and n is negative, will treat negative integer x as if modulo big power of 2, otherwise sign of x is ignored but preserved", "shiftmul(x,n): multiply x by 2^n (n>=0 or n<0)", "sigma(x,{k=1}): sum of the k-th powers of the divisors of x. k is optional and if omitted is assumed to be equal to 1", "sign(x): sign of x, of type integer, real or fraction", Index: src/language/init.c =================================================================== RCS file: /home/megrez/cvsroot/pari/src/language/init.c,v retrieving revision 1.89 diff -p -u -r1.89 init.c --- src/language/init.c 2001/08/26 13:46:34 1.89 +++ src/language/init.c 2001/09/29 15:43:45 @@ -2122,7 +2122,7 @@ entree functions_basic[]={ {"setrand",99,(void*)setrand,11,"lL"}, {"setsearch",99,(void*)setsearch,8,"lGGD0,L,"}, {"setunion",2,(void*)setunion,8,"GG"}, -{"shift",99,(void*)gshift,1,"GL"}, +{"shift",99,(void*)gshift3,1,"GLD0,L,"}, {"shiftmul",99,(void*)gmul2n,1,"GL"}, {"sigma",99,(void*)gsumdivk,4,"GD1,L,"}, {"sign",10,(void*)gsigne,1,"lG"},