GF(2^n) arithmetics in bitvector
This commit is contained in:
		
							parent
							
								
									f0325ba6f5
								
							
						
					
					
						commit
						1e00570f66
					
				
							
								
								
									
										65
									
								
								bitvector.cc
									
									
									
									
									
								
							
							
						
						
									
										65
									
								
								bitvector.cc
									
									
									
									
									
								
							@ -296,12 +296,13 @@ return n;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
//NOTE: naive algorithm, just for testing
 | 
					//NOTE: naive algorithm, just for testing
 | 
				
			||||||
//does not perform modulo irreducible polynomial, is NOT GF(2^n) multiplication
 | 
					//does not perform modulo irreducible polynomial, is NOT GF(2^n) multiplication
 | 
				
			||||||
bitvector bitvector::operator*(const bitvector &rhs) const
 | 
					bitvector bitvector::multiply(const bitvector &rhs, bool autoresize) const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
bitvector r(size()+rhs.size());
 | 
					int maxsize=size(); if(rhs.size()>maxsize) maxsize=rhs.size();
 | 
				
			||||||
 | 
					bitvector r(autoresize?size()+rhs.size():maxsize);
 | 
				
			||||||
r.clear();
 | 
					r.clear();
 | 
				
			||||||
bitvector tmp(rhs);
 | 
					bitvector tmp(rhs);
 | 
				
			||||||
tmp.resize(size()+rhs.size(),true);
 | 
					if(autoresize) tmp.resize(size()+rhs.size(),true);
 | 
				
			||||||
for(int i=0; i<=degree(); ++i)
 | 
					for(int i=0; i<=degree(); ++i)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
	if((*this)[i]) r+= tmp;
 | 
						if((*this)[i]) r+= tmp;
 | 
				
			||||||
@ -310,6 +311,60 @@ for(int i=0; i<=degree(); ++i)
 | 
				
			|||||||
return r;
 | 
					return r;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//this is GF(2^n) multiplication
 | 
				
			||||||
 | 
					bitvector bitvector::field_mult(const bitvector &rhs, const bitvector &irpolynom) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					int d=irpolynom.degree();
 | 
				
			||||||
 | 
					if(d>size()||d>rhs.size()) laerror("inconsistent dimensions in field_mult");
 | 
				
			||||||
 | 
					bitvector r(size());
 | 
				
			||||||
 | 
					r.clear();
 | 
				
			||||||
 | 
					bitvector tmp(*this);
 | 
				
			||||||
 | 
					tmp.resize(size()+1,true);
 | 
				
			||||||
 | 
					int rd=rhs.degree();
 | 
				
			||||||
 | 
					for(int i=0; i<=rd; ++i) //avoid making a working copy of rhs and shifting it
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					        if(rhs[i]) r+= tmp;
 | 
				
			||||||
 | 
					        tmp.leftshift(1,false);
 | 
				
			||||||
 | 
					  	if(tmp[d]) tmp -= irpolynom;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//this is GF(2^n) multiplicative inverseion
 | 
				
			||||||
 | 
					//cf. https://en.wikipedia.org/wiki/Extended_Euclidean_algorithm
 | 
				
			||||||
 | 
					bitvector bitvector::field_inv(const bitvector &irpolynom) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					int d=irpolynom.degree();
 | 
				
			||||||
 | 
					if(d>size()) laerror("inconsistent dimensions in field_inv");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bitvector t(size()); t.clear();
 | 
				
			||||||
 | 
					bitvector newt(size()); newt.clear(); newt.set(0);
 | 
				
			||||||
 | 
					bitvector r(irpolynom); r.copyonwrite();
 | 
				
			||||||
 | 
					bitvector newr(*this); if(r.size()>newr.size()) newr.resize(r.size(),true); newr.copyonwrite();
 | 
				
			||||||
 | 
					int rs=r.size();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					while(!newr.is_zero())
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
						//std::cout <<"r "<<r<<" newr "<<newr <<" "; std::cout <<"t "<<t<<" newt "<<newt; std::cout <<std::endl;
 | 
				
			||||||
 | 
						bitvector remainder(rs);
 | 
				
			||||||
 | 
						bitvector quotient = r.division(newr,remainder);
 | 
				
			||||||
 | 
						r=newr; newr=remainder;
 | 
				
			||||||
 | 
						remainder= t - quotient.multiply(newt,false); //avoid size growth
 | 
				
			||||||
 | 
						t=newt; newt=remainder;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(r.degree()>0) laerror("field_inv: polynomial is not irreducible or input is its multiple");
 | 
				
			||||||
 | 
					if(!r[0]) laerror("zero in field_inv");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					return t;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void bitvector::resize(const unsigned int n, bool preserve)
 | 
					void bitvector::resize(const unsigned int n, bool preserve)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
int old=size(); 
 | 
					int old=size(); 
 | 
				
			||||||
@ -338,9 +393,9 @@ while((d=remainder.degree()) >= rhsd)
 | 
				
			|||||||
	{
 | 
						{
 | 
				
			||||||
	unsigned int pos = d-rhsd;
 | 
						unsigned int pos = d-rhsd;
 | 
				
			||||||
	r.set(pos);
 | 
						r.set(pos);
 | 
				
			||||||
	remainder -= (rhs<<pos);
 | 
						remainder -= rhs<<pos;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					remainder.resize(rhs.size(),true);
 | 
				
			||||||
return r;
 | 
					return r;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										10
									
								
								bitvector.h
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								bitvector.h
									
									
									
									
									
								
							@ -83,13 +83,17 @@ public:
 | 
				
			|||||||
	bitvector operator^(const bitvector &rhs) const {return bitvector(*this) ^= rhs;};
 | 
						bitvector operator^(const bitvector &rhs) const {return bitvector(*this) ^= rhs;};
 | 
				
			||||||
	bitvector operator+(const bitvector &rhs) const {return *this ^ rhs;}; //addition modulo 2
 | 
						bitvector operator+(const bitvector &rhs) const {return *this ^ rhs;}; //addition modulo 2
 | 
				
			||||||
	bitvector operator-(const bitvector &rhs) const {return *this ^ rhs;}; //subtraction modulo 2
 | 
						bitvector operator-(const bitvector &rhs) const {return *this ^ rhs;}; //subtraction modulo 2
 | 
				
			||||||
	bitvector operator*(const bitvector &rhs) const; //multiplication of polynomials over GF(2) NOTE: naive algorithm, does not employ CLMUL nor fft-like approach, only for short vectors!!!
 | 
						bitvector multiply(const bitvector &rhs, bool autoresize=true) const; //use autoresize=false only if you know it will not overflow!
 | 
				
			||||||
 | 
						bitvector operator*(const bitvector &rhs) const {return multiply(rhs,true);}  //multiplication of polynomials over GF(2) NOTE: naive algorithm, does not employ CLMUL nor fft-like approach, only for short vectors!!!
 | 
				
			||||||
 | 
						bitvector field_mult(const bitvector &rhs, const bitvector &irpolynom) const; //multiplication in GF(2^n)
 | 
				
			||||||
 | 
						bitvector field_inv(const bitvector &irpolynom) const; //multiplication in GF(2^n)
 | 
				
			||||||
 | 
						bitvector field_div(const bitvector &rhs, const bitvector &irpolynom) const {return field_mult(rhs.field_inv(irpolynom),irpolynom);};
 | 
				
			||||||
	bitvector division(const bitvector &rhs,  bitvector &remainder) const;
 | 
						bitvector division(const bitvector &rhs,  bitvector &remainder) const;
 | 
				
			||||||
	bitvector operator/(const bitvector &rhs) const {bitvector rem(rhs.size()); return division(rhs,rem);};
 | 
						bitvector operator/(const bitvector &rhs) const {bitvector rem(rhs.size()); return division(rhs,rem);};
 | 
				
			||||||
	bitvector operator%(const bitvector &rhs) const {bitvector rem(rhs.size()); division(rhs,rem); return rem;};
 | 
						bitvector operator%(const bitvector &rhs) const {bitvector rem(rhs.size()); division(rhs,rem); return rem;};
 | 
				
			||||||
	bitvector gcd(const bitvector &rhs) const;
 | 
						bitvector gcd(const bitvector &rhs) const; //as a polynomial over GF2
 | 
				
			||||||
	bitvector lcm(const bitvector &rhs) const {return (*this)*rhs/this->gcd(rhs);};
 | 
						bitvector lcm(const bitvector &rhs) const {return (*this)*rhs/this->gcd(rhs);};
 | 
				
			||||||
        unsigned int bitdiff(const bitvector &y) const; //number of differing bits
 | 
					        unsigned int bitdiff(const bitvector &y) const; //number of differing bits (Hamming distance)
 | 
				
			||||||
	unsigned int population(const unsigned int before=0) const; //number of 1's
 | 
						unsigned int population(const unsigned int before=0) const; //number of 1's
 | 
				
			||||||
	unsigned int nlz() const; //number of leading zeroes
 | 
						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 degree() const {if(iszero()) return 0; else return size()-nlz()-1;}; //interprested as a polynomial over GF(2)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										14
									
								
								t.cc
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								t.cc
									
									
									
									
									
								
							@ -2939,11 +2939,23 @@ if(!(u%g).is_zero()) laerror("error in gcd");
 | 
				
			|||||||
if(!(v%g).is_zero()) laerror("error in gcd");
 | 
					if(!(v%g).is_zero()) laerror("error in gcd");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if(1)
 | 
					if(0)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
uint64_t n;
 | 
					uint64_t n;
 | 
				
			||||||
cin >>n;
 | 
					cin >>n;
 | 
				
			||||||
cout <<factorization(n)<<" phi = "<<eulerphi(n)<<endl;
 | 
					cout <<factorization(n)<<" phi = "<<eulerphi(n)<<endl;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if(1)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					bitvector ir; cin >>ir;
 | 
				
			||||||
 | 
					bitvector a; cin >>a;
 | 
				
			||||||
 | 
					bitvector ai = a.field_inv(ir);
 | 
				
			||||||
 | 
					cout<< "inverse = "<<ai<<endl;
 | 
				
			||||||
 | 
					cout<<"check1 " <<(a*ai)%ir<<endl;
 | 
				
			||||||
 | 
					cout<<"check2 " <<a.field_mult(ai,ir)<<endl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user