diff --git a/bitvector.cc b/bitvector.cc index c650df5..afd8d7f 100644 --- a/bitvector.cc +++ b/bitvector.cc @@ -103,7 +103,7 @@ bitvector& bitvector::operator&=(const bitvector &rhs) { if(size()=rhs.nn? 0 : rhs.v[i]); return *this; } @@ -111,7 +111,7 @@ bitvector& bitvector::operator|=(const bitvector &rhs) { if(size()>16); return x&0x3f; } #else -//@@@@ use an efficient trick +//@@@@ use an efficient trick too static unsigned int word_popul(unsigned long x) { unsigned int s=0; @@ -222,7 +222,7 @@ if(modulo) return s+word_popul(a); } -unsigned int bitvector::operator%(const bitvector &y) const +unsigned int bitvector::bitdiff(const bitvector &y) const { if(nn!=y.nn) laerror("incompatible size in bitdifference"); @@ -236,6 +236,143 @@ if(modulo) a &= ~mask; } return s+word_popul(a); +} + +static unsigned int nlz64(uint64_t x0) +{ +int64_t x=x0; +uint64_t y; +unsigned int n; +n=0; +y=x; +L: if ( x<0) return n; +if(y==0) return 64-n; +++n; +x<<=1; +y>>=1; +goto L; +} + +static unsigned int ntz64(uint64_t x) +{ +unsigned int n; +if(x==0) return 64; +n=1; +if((x&0xffffffff)==0) {n+=32; x>>=32;} +if((x&0xffff)==0) {n+=16; x>>=16;} +if((x&0xff)==0) {n+=8; x>>=8;} +if((x&0xf)==0) {n+=4; x>>=4;} +if((x&0x3)==0) {n+=2; x>>=2;} +return n-(x&1); +} + +unsigned int bitvector::nlz() const +{ +int leadblock=nn-1; +unsigned int n=0; +while(leadblock>0 && v[leadblock] == 0) + { + --leadblock; + n+=blockbits; + } +n+= nlz64(v[leadblock]); +if(modulo) n-= blockbits-modulo; +return n; +} + +unsigned int bitvector::ntz() const +{ +int tailblock=0; +unsigned int n=0; +if(iszero()) return size(); +while(tailblock::resize((n+blockbits-1)/blockbits,preserve); +modulo=n%blockbits; +if(preserve) //clear newly allocated memory + { + for(int i=old; ireset(i); + } +else clear(); +} + + +bitvector bitvector::division(const bitvector &rhs, bitvector &remainder) const +{ +if(rhs.is_zero()) laerror("division by zero binary polynomial"); +if(is_zero() || rhs.is_one()) {remainder.clear(); return *this;} +bitvector r(size()); +r.clear(); +remainder= *this; +remainder.copyonwrite(); + +int rhsd = rhs.degree(); +int d; +while((d=remainder.degree()) >= rhsd) + { + unsigned int pos = d-rhsd; + r.set(pos); + remainder -= (rhs<=rhs.degree()) + {big= *this; small=rhs;} +else + {big=rhs; small= *this;} + +if(big.is_zero()) + { + if(small.is_zero()) laerror("two zero arguments in gcd"); + return small; + } + +if(small.is_zero()) return big; +if(small.is_one()) return small; +if(big.is_one()) return big; + +do { + bitvector help=small; + small= big%small; + big=help; + } +while(! small.is_zero()); +return big; + + + } void bitvector::read(int fd, bool dimensions, bool transp) @@ -260,4 +397,5 @@ NRVec::put(fd,dimensions,transp); + }//namespace diff --git a/bitvector.h b/bitvector.h index a91c461..7edf0b6 100644 --- a/bitvector.h +++ b/bitvector.h @@ -25,7 +25,7 @@ namespace LA { //compressed storage of large bit vectors -//let's now use 64-bit blocks exclusively +//let's now use 64-bit blocks exclusively for simplicity typedef uint64_t bitvector_block; @@ -48,10 +48,10 @@ public: //operator= seems to be correctly synthetized by the compiler //override dereferencing to address single bits, is however possible //only in the const context (otherwise we would have to define a type which, when assigned to, changes a single bit - possible but probably inefficient) - void resize(const unsigned int n, bool preserve=false) {NRVec::resize((n+blockbits-1)/blockbits,preserve); modulo=n%blockbits;}; + void resize(const unsigned int n, bool preserve=false); //preserve data or clear unsigned int size() const {return (nn*blockbits)-blockbits+(modulo?modulo:blockbits);}; //arguments must be unsigned to keep the resulting assembly code simple and efficient - const bool operator[](const unsigned int i) const {return (v[i/blockbits] >>(i%blockbits))&1UL;}; + const bool operator[](const unsigned int i) const {return (v[i/blockbits] >>(i%blockbits))&1ULL;}; const bool get(const unsigned int i) const {return (*this)[i];}; bitvector_block getblock(const unsigned int i) const {return v[i];}; //integer interpretation void setblock(const unsigned int i, const bitvector_block b) {v[i]=b;}; @@ -62,6 +62,8 @@ public: void clear() {copyonwrite(true); memset(v,0,nn*sizeof(bitvector_block));}; void fill() {memset(v,0xff,nn*sizeof(bitvector_block));}; bool iszero() const {for(int i=0; igcd(rhs);}; + unsigned int bitdiff(const bitvector &y) const; //number of differing bits unsigned int population(const unsigned int before=0) const; //number of 1's + unsigned int nlz() const; //number of leading zeroes + unsigned int degree() const {if(iszero()) return 0; else return size()-nlz()-1;}; //interprested as a polynomial over GF(2) + unsigned int ntz() const; //number of trailing zeroes //extended, truncated const i.e. not on *this but return new entity, take care of modulo's bits //logical shifts bitvector& operator>>=(unsigned int i); bitvector& leftshift(unsigned int i, bool autoresize=false); bitvector& operator<<=(unsigned int i) {return leftshift(i,true);}; - bitvector operator>>(unsigned int i) {bitvector r(*this); return r>>=i;}; - bitvector operator<<(unsigned int i) {bitvector r(*this); return r<<=i;}; + bitvector operator>>(unsigned int i) const {bitvector r(*this); return r>>=i;}; + bitvector operator<<(unsigned int i) const {bitvector r(*this); return r<<=i;}; //logical rotations not implemented yet //unformatted file IO void read(int fd, bool dimensions=1, bool transp=0); diff --git a/polynomial.h b/polynomial.h index f4b21ea..81bdff2 100644 --- a/polynomial.h +++ b/polynomial.h @@ -69,7 +69,7 @@ public: } Polynomial operator+(const Polynomial &rhs) const {return Polynomial(*this) += rhs;}; Polynomial operator-(const Polynomial &rhs) const {return Polynomial(*this) -= rhs;}; - Polynomial operator*(const Polynomial &rhs) const //for very long polynomials FFT should be used + Polynomial operator*(const Polynomial &rhs) const //NOTE: naive implementation! For very long polynomials FFT-based methods should be used { NOT_GPU(*this); Polynomial r(degree()+rhs.degree()); diff --git a/t.cc b/t.cc index 26dc7b7..8ac0a84 100644 --- a/t.cc +++ b/t.cc @@ -2852,7 +2852,7 @@ cout <>n; bitvector v(n); v.randomize(); -//do{ -// cout <>=1; -//}while(!v.iszero()); +do{ + cout <>=1; +}while(!v.iszero()); + cout <>n; +bitvector v(n),u(n); +u.randomize(); +v.randomize(); +bitvector w=u*v; +bitvector z=v*u; +cout <