atlas  0.6
bitvector.h
Go to the documentation of this file.
1 /*
2  This is bitvector.h
3 
4  Copyright (C) 2004,2005 Fokko du Cloux
5  part of the Atlas of Lie Groups and Representations
6 
7  For license information see the LICENSE file
8 */
9 
10 #ifndef BITVECTOR_H /* guard against multiple inclusions */
11 #define BITVECTOR_H
12 
13 #include "../Atlas.h"
14 
15 #include <vector>
16 #include <cassert>
17 
18 #include "bitset.h" // so users will see complete types; also needed for inline
19 #include "matrix.h" // for |matrix::Vector|
20 
21 /******** function declarations **********************************************/
22 
23 namespace atlas {
24 
25 namespace bitvector {
26 
27 /* Put in |v| the $Z/2Z$-linear combination of the |BitVector|s of |b|
28  (each of size |n|) given by the bits of |e|.
29 */
30 template<size_t dim>
31  BitVector<dim> combination
32  (const std::vector<BitVector<dim> >& b,
33  size_t n,
34  const BitSet<dim>& e);
35 
36 // version with |BitSet|s instead of |BitVector|s; functional (size no issue)
37 template<size_t dim>
38  BitSet<dim> combination(const std::vector<BitSet<dim> >&,
39  const BitSet<dim>&);
40 
41 
42 /*
43  Find out whether any combination of the vectos in |b| adds to |rhs|, and if
44  so flag such a combination in the bits of |c|. Nothing changes when |false|.
45 */
46 template<size_t dim>
47  bool combination_exists(const std::vector<BitVector<dim> >& b,
48  const BitVector<dim>& rhs,
49  BitSet<dim>& c);
50 
51 /*
52  Either find a solution of the system of equations |eqn|, putting it
53  into |sol| and returning |true|, or return |false| if no solition exists.
54 
55  Here |eqns| holds a system of equations, the last bit of each being
56  interpreted as the right hand side.
57 
58  If there is a solution, |sol| will be resized to to number of
59  indeterminates, which is one less than the size of each equation; however,
60  if the set of equations is empty, |sol| is left unchanged.
61 */
62 template<size_t dimsol, size_t dimeq>
63  bool solvable(const std::vector<BitVector<dimeq> >& eqns,
64  BitVector<dimsol>& sol);
65 
66 template<size_t dim> void identityMatrix(BitMatrix<dim>&, size_t);
67 
68 template<size_t dim> void initBasis(std::vector<BitVector<dim> >&, size_t);
69 
70 template<size_t dim>
71  void Gauss_Jordan(BitSet<dim>&, std::vector<BitVector<dim> >&);
72 
73 template<size_t dim>
74  void normalSpanAdd(std::vector<BitVector<dim> >&, std::vector<size_t>&,
75  const BitVector<dim>&);
76 /* unused functions
77 template<size_t dim>
78  void complement(BitSet<dim>&, const std::vector<BitVector<dim> >&,
79  size_t);
80 
81 template<size_t dim> bool isIndependent(const std::vector<BitVector<dim> >&);
82 
83 template<size_t dim>
84  void projection(BitMatrix<dim>& p, const std::vector<BitVector<dim> >& b,
85  size_t d);
86 
87 template<size_t dim>
88  void reflectionMatrix(BitMatrix<dim>&, const BitVector<dim>&,
89  const BitVector<dim>&);
90 
91 template<size_t dim>
92  void relations(std::vector<BitVector<dim> >&,
93  const std::vector<BitVector<dim> >&);
94 */
95 
96 template<size_t dim>
97  void spanAdd(std::vector<BitVector<dim> >&, std::vector<size_t>&,
98  const BitVector<dim>&);
99 
100 template<size_t dim> int_Vector lift(const BitVector<dim>& v);
101 
102 /******** type definitions **************************************************/
103 
104 /*
105  The template class |BitVector<dim>| represents a number |size| with
106  |0<=size<=dim|, and a vector in the (Z/2Z)-vector space (Z/2Z)^size.
107 
108  The software envisions dim between 0 and four times the machine word length
109  (precisely, four times the constant |longBits|, which is the number of bits
110  in an unsigned long integer). What is now fully implemented allows |dim| to
111  be one or two times the word length (see the discussion in the description
112  of the class BitSet<n>). It seems that only BitVector<RANK_MAX> and
113  BitVector<2*RANK_MAX> are now instantiated, (that is <16> or <32>), so |dim|
114  is not very relevant; one could imagine |dim==longBits| throughout.
115 
116  Let the integer |m| be \f$\lceil dim/longBits \rceil\f$ (quotient rounded
117  upwards) . The vector is stored as the BitSet<dim> |d_data|, which is a
118  (fixed size) array of |m| words of memory. (On a 32 bit machine with
119  RANK_MAX=16 one always has |m==1|, so that |d_data| is a single word of
120  memory.) We look only at the first |d_size| bits of |d_data|; but |d_size|
121  can be changed by manipulators (like the member functions resize and
122  pushBack). [Maybe |d_size| never exceeds |RANK_MAX+1|, even for variables
123  declared as |BitVector<2*RANK_MAX>| MvL]
124 
125  Given the number of methods that are passed on to the |BitSet<dim>| field
126  |d_data|, one might wonder if it would not have been better to publicly
127  derive from |BitSet<dim>|, MvL.
128 
129  A |BitVector| should be thought of as a column vector. A |Bitmatrix| will in
130  general act on it on the left, just like a |LatticeMatrix| on a |Weight|.
131  This does not stop |BitVector|s from being used most for coweights modulo 2.
132 */
133 
134 template<size_t dim> class BitVector
135 {
136  public:
137  typedef BitSet<dim> base_set;
138  private:
139  base_set d_data;
140  unsigned short int d_size; // this is more than large enough for all uses
141 
142  public:
143 
144  // constructors and destructors
145  explicit BitVector(size_t n) // initialised to 0 in $Z/2Z$
146  : d_data(), d_size(n)
147  {}
148 
149  BitVector(size_t n, size_t j) // canonical basis vector $e_j$ in $(Z/2Z)^n$
150  : d_data(), d_size(n)
151  {
152  set(j);
153  }
154 
155  BitVector(BitSet<dim> data, size_t n) // view |data| as |BitVector|
156  : d_data(data), d_size(n)
157  {}
158 
159  template<typename C>
160  explicit BitVector(const matrix::Vector<C>& weight); // reduce weight mod 2
161 
162 // copy and assignment
164  :d_data(v.d_data),
165  d_size(v.d_size)
166  {}
167 
169  d_data = v.d_data;
170  d_size = v.d_size;
171  return *this;
172  }
173 
174 // accessors
175 
176  bool operator< (const BitVector& v) const
177  {
178  assert(d_size==v.d_size);
179  return d_data<v.d_data;
180  }
181 
182  bool operator== (const BitVector& v) const
183  {
184  assert(d_size==v.d_size);
185  return d_data == v.d_data;
186  }
187 
188  bool operator!= (const BitVector& v) const
189  {
190  assert(d_size==v.d_size);
191  return d_data != v.d_data;
192  }
193 
194  bool operator[] (size_t i) const
195  {
196  assert(i<d_size);
197  return d_data[i];
198  }
199 
200  size_t size() const { return d_size; }
201 
202  const BitSet<dim>& data() const { return d_data; }
203 
204  size_t firstBit() const { return d_data.firstBit(); }
205 
206  size_t count() { return d_data.count(); }
207 
208  bool isZero() const { return d_data.none(); }
209 
210  bool nonZero() const { return d_data.any(); }
211 
212  // scalar product with value in $\Z/2$
213  bool dot(const BitVector& v) const
214  { return ((d_data & v.d_data).count()&1u)!=0; }
215 
217  { BitVector<dim> result(*this); result+=v; return result; }
218 
219  // the same operation as the previous method, under different name
220  // the destinction may sometimes be useful for documentation purposes
222  { BitVector<dim> result(*this); result-=v; return result; }
223 
224  template<typename C>
225 #ifdef incompletecpp11
226  operator matrix::Vector<C>() const
227 #else
228  explicit operator matrix::Vector<C>() const
229 #endif
230  { matrix::Vector<C> result(size());
231  for (unsigned int i=size(); i-->0;)
232  result[i]=d_data[i];
233  return result;
234  }
235 
236 // manipulators
237 
239  {
240  assert(d_size==v.d_size);
241  d_data ^= v.d_data;
242  return *this;
243  }
244 
245  BitVector& operator-= (const BitVector& v) // same thing as +=
246  {
247  assert(d_size==v.d_size);
248  d_data ^= v.d_data;
249  return *this;
250  }
251 
252  BitVector& operator&= (const BitVector& v) // bitwise multiply
253  {
254  assert(d_size==v.d_size);
255  d_data &= v.d_data;
256  return *this;
257  }
258 
259  BitVector& operator>>= (size_t pos) { d_data >>= pos; return *this; }
260  BitVector& operator<<= (size_t pos) { d_data <<= pos; return *this; }
261 
262  BitVector& flip(size_t i)
263  {
264  assert(i<d_size);
265  d_data.flip(i);
266  return *this;
267  }
268 
269  BitVector& pushBack(bool);
270 
271  BitVector& set(size_t i)
272  {
273  assert(i<d_size);
274  d_data.set(i);
275  return *this;
276  }
277 
278  void set(size_t i, bool b) { assert(i<d_size); d_data.set(i,b); }
279 
280  void set_mod2(size_t i, unsigned long v) { set(i,(v&1)!=0); }
281 
282  BitVector& reset() { d_data.reset(); return *this; }
283 
284  BitVector& reset(size_t i)
285  {
286  assert(i<d_size);
287  d_data.reset(i);
288  return *this;
289  }
290 
291  void resize(size_t n) { assert(n<=dim); d_size = n; }
292 
293  void slice(const BitSet<dim>& mask);
294  void unslice(BitSet<dim> mask, size_t new_size);
295 }; // class BitVector
296 
297 /* the following template inherits everything from |std::vector| but after
298  some constructors that mimick those of |BitVector|, we also provide a
299  constructor that converts from |WeightList|, reducing coefficients mod 2
300  */
301 template<size_t dim> class BitVectorList
302  : public std::vector<BitVector<dim> >
303 {
304  public:
305  // default constructor
306  BitVectorList() : std::vector<BitVector<dim> >() {}
307 
308  // dimension-only constructor
309  BitVectorList(size_t n) : std::vector<BitVector<dim> >(n) {}
310 
311  // fixed element constructor
313  : std::vector<BitVector<dim> >(n,model)
314  {}
315 
316  // also allow explicit consversion (implicit would be too dangerous)
317  explicit BitVectorList(const std::vector<BitVector<dim> >& v)
318  : std::vector<BitVector<dim> >(v) // copy
319  {}
320 
321  /* reduction mod 2 is done via range-constructor of vector, which on its
322  turn calls |BitVector<dim> (const LatticeElt&)| on the elements */
323  BitVectorList(const std::vector<matrix::Vector<int> >& l)
324  : std::vector<BitVector<dim> >(l.begin(),l.end())
325  {}
326 
327  template<typename I> // input iterator
328  BitVectorList(I begin, I end)
329  : std::vector<BitVector<dim> >(begin,end)
330  {}
331 };
332 
333 
334 // note that the elements in d_data are the _column_ vectors of the matrix
335 
336 /*
337  A rectangular matrix with entries in Z/2Z.
338 
339  The number of rows |d_rows| should be less than or equal to the template
340  parameter |dim|. The present |BitSet| implementation allows |dim| at most
341  twice the machine word size, and what is used is the case |dim==RANK_MAX|.
342 
343  At least when |d_columns<=dim|, the matrix can act on the left on a
344  |BitVector| of size |d_columns|; in this setting each column of the matrix
345  is the image of one of the standard basis vectors in the domain.
346 
347  What is stored in |d_data|, as |BitSet|'s, are the column vectors of the
348  matrix. Construction of a matrix is therefore most efficient when columns
349  are added to it.
350 
351  Notice that the columns are stored as |BitSets| and not |BitVectors|. A
352  |BitVector| is a larger data structure than a |BitSet|, including also an
353  integer |d_size| saying how many of the available bits are significant. In a
354  |BitMatrix| this integer must be the same for all of the columns, so it is
355  easier and safer to store it once for the whole |BitMatrix|, and also to
356  modify it just once when the matrix is resized.
357 */
358 template<size_t dim> class BitMatrix
359 {
360 /*
361  A vector of |d_columns| |BitSet| values (each to be thought of as a vector
362  of size |d_rows|), the columns of the |BitMatrix|. Thus
363  |d_data.size()==d_columns| at all times.
364 */
365  std::vector<BitSet<dim> > d_data;
366 
367  // Number of rows of the BitMatrix. Cannot exceed template argument |dim|
368  unsigned short int d_rows;
369 
370  // Number of columns of the BitMatrix. This field is redundant, see |d_data|.
371  unsigned short int d_columns;
372 
373  public:
374 
375 // constructors and destructors
376  explicit BitMatrix(size_t n) // square matrix
377  : d_data(n) // make |n| default constructed |BitSet|s as columns
378  , d_rows(n)
379  , d_columns(n)
380  {
381  assert(n<=dim);
382  }
383 
384  BitMatrix(size_t m, size_t n)
385  : d_data(n) // make |n| default constructed |BitSet|s as columns
386  , d_rows(m)
387  , d_columns(n)
388  {
389  assert(m<=dim); // having |n>dim| is not immediately fatal
390  }
391 
392  explicit BitMatrix(const std::vector<BitVector<dim> >&, // set by columns
393  unsigned short int num_rows); // all of size |num_rows|
394  explicit BitMatrix(const matrix::Matrix<int>& m); // set modulo 2
395 
396  static BitMatrix identity(unsigned int n)
397  { BitMatrix M(n);
398  for (size_t i=0; i<n; ++i)
399  M.set(i,i);
400  return M;
401  }
402 
403 // copy and assignment (implicitly generated ones will do)
404 
405 // accessors
406 
408  bool test(size_t i, size_t j) const
409  {
410  assert(i<d_rows);
411  assert(j<d_columns);
412  return d_data[j].test(i);
413  }
414 
415  BitVector<dim> operator*(const BitVector<dim>& src) const; // matrix * vector
416 
417 
418  template<typename I, typename O> void apply(const I&, const I&, O) const;
419 
420  BitVectorList<dim> image() const; // free generators of image of matrix
421  BitVectorList<dim> kernel() const; // free generators of kernel of matrix
422 
423  size_t numColumns() const { return d_columns; } // the number of columns
424  size_t numRows() const { return d_rows; } // the number of rows
425 
426  BitVector<dim> row(size_t i) const;
427 
429  BitVector<dim> column(size_t j) const
430  {
431  assert(j<d_columns);
432  return BitVector<dim>(d_data[j],d_rows);
433  }
434  void get_column(BitVector<dim>& c, size_t j) const { c=column(j); }
435 
436 
437 // manipulators
438 
440 
441  BitMatrix& operator*= (const BitMatrix&);
442 
443  // Add |f| as a new column at the end to the |BitMatrix|.
444  void addColumn(const BitSet<dim>& f) {
445  d_data.push_back(f);
446  ++d_columns;
447  }
448 
449  void addColumn(const BitVector<dim>& c) {
450  assert(c.size()==d_rows);
451  addColumn(c.data()); // call previous method, which does |++d_columns|
452  }
453 
454  // Add the BitVector |v| to column |j| of the BitMatrix.
455  void addToColumn(size_t j, const BitVector<dim>& v) {
456  assert(v.size()==d_rows);
457  d_data[j] ^= v.data();
458  }
459 
460  // matrix $B$ such that $ABA=A$, will be inverse if $A$ invertible
461  BitMatrix section() const;
462 
463  // Put a 1 in row |i| and column |j| of the |BitMatrix|.
464  BitMatrix& set(size_t i, size_t j) {
465  assert(i<d_rows);
466  assert(j<d_columns);
467  d_data[j].set(i);
468  return *this;
469  }
470 
471  BitMatrix& reset(size_t i, size_t j) {
472  assert(i<d_rows);
473  assert(j<d_columns);
474  d_data[j].reset(i);
475  return *this;
476  }
477 
478  void set(size_t i, size_t j, bool b) {
479  if (b) set(i,j); else reset(i,j);
480  }
481 
482  void set_mod2(size_t i, size_t j, unsigned long v) {
483  set(i,j, (v&1)!=0 );
484  }
485 
486  void reset();
487 
488 
489  /* Resize the BitMatrix to an |n| by |n| square.
490 
491  NOTE: it is the caller's responsibility to check that |n<=dim|.
492  */
493  void resize(size_t n) { resize(n,n); }
494 
495  void resize(size_t m, size_t n);
496 
497  // Puts |data| in column j of the BitMatrix.
498  void setColumn(size_t j, const BitSet<dim>& data)
499  {
500  assert(j<d_columns);
501  d_data[j] = data;
502  }
503 
504  void swap(BitMatrix& m);
505 
506 /*
507  Transpose the BitMatrix
508 
509  NOTE: it is the caller's responsibility to check that |d_columns<=dim|.
510 */
511  BitMatrix& transpose();
512 }; // |class BitMatrix|
513 
514 // Inlined function definition
515 
516 inline
518  {
519  BinaryEquation eqn(lhs.data(),lhs.size());
520  eqn.pushBack(rhs);
521  return eqn;
522  }
523 
524 
525 } // |namespace bitvector|
526 
527 } // |namespace atlas|
528 
529 
530 #endif
void unslice(BitSet< dim > mask, size_t new_size)
Definition: bitvector.cpp:112
void addToColumn(size_t j, const BitVector< dim > &v)
Definition: bitvector.h:455
BitVector< dim > combination(const std::vector< BitVector< dim > > &b, size_t n, const BitSet< dim > &e)
Puts in |v| the linear combination of the elements of |b| given by |e|.
Definition: bitvector.cpp:470
matrix::Vector< int > int_Vector
Definition: Atlas.h:149
BitVector operator-(const BitVector &v) const
Definition: bitvector.h:221
BitVector< constants::RANK_MAX > SmallBitVector
Definition: Atlas.h:181
BitMatrix & reset(size_t i, size_t j)
Definition: bitvector.h:471
void addColumn(const BitVector< dim > &c)
Definition: bitvector.h:449
BitMatrix(size_t m, size_t n)
Definition: bitvector.h:384
bool operator[](size_t i) const
Definition: bitvector.h:194
BitVector & reset(size_t i)
Definition: bitvector.h:284
void initBasis(std::vector< BitVector< dim > > &b, size_t n)
Initializes b to the canonical basis in dimension n.
Definition: bitvector.cpp:642
Definition: Atlas.h:176
unsigned short int d_size
Definition: bitvector.h:140
BitVectorList(const std::vector< matrix::Vector< int > > &l)
Definition: bitvector.h:323
void identityMatrix(BitMatrix< dim > &m, size_t n)
Puts in m the identity matrix in rank n.
Definition: bitvector.cpp:629
bool test(size_t i, size_t j) const
The (i,j) entry of the BitMatrix.
Definition: bitvector.h:408
BitVectorList()
Definition: bitvector.h:306
bool nonZero() const
Definition: bitvector.h:210
void swap(simple_list< T, Alloc > &x, simple_list< T, Alloc > &y)
Definition: sl_list.h:674
void resize(size_t n)
Definition: bitvector.h:291
bool isZero() const
Definition: bitvector.h:208
BitVectorList(size_t n)
Definition: bitvector.h:309
size_t numColumns() const
Definition: bitvector.h:423
void resize(size_t n)
Definition: bitvector.h:493
Definition: Atlas.h:174
BitMatrix & set(size_t i, size_t j)
Definition: bitvector.h:464
BitVector< dim > column(size_t j) const
Column $j$ of the BitMatrix, as a BitVector.
Definition: bitvector.h:429
void normalSpanAdd(std::vector< BitVector< dim > > &a, std::vector< size_t > &f, const BitVector< dim > &v)
Definition: bitvector.cpp:740
BitVectorList(size_t n, BitVector< dim > model)
Definition: bitvector.h:312
LatticeMatrix kernel(const LatticeMatrix &M)
Definition: lattice.cpp:130
BitVector & reset()
Definition: bitvector.h:282
BitMatrix(size_t n)
Definition: bitvector.h:376
static BitMatrix identity(unsigned int n)
Definition: bitvector.h:396
BitVector< constants::RANK_MAX+1 > BinaryEquation
Definition: Atlas.h:183
BitVector(size_t n)
Definition: bitvector.h:145
size_t firstBit() const
Definition: bitvector.h:204
Definition: Atlas.h:175
void slice(const BitSet< dim > &mask)
Definition: bitvector.cpp:83
RationalVector< C2 > operator*(const matrix::Matrix< C1 > &M, const RationalVector< C2 > &v)
Definition: ratvec.cpp:158
unsigned short int d_columns
Definition: bitvector.h:371
void addColumn(const BitSet< dim > &f)
Definition: bitvector.h:444
base_set d_data
Definition: bitvector.h:139
size_t size() const
Definition: bitvector.h:200
void set_mod2(size_t i, unsigned long v)
Definition: bitvector.h:280
size_t numRows() const
Definition: bitvector.h:424
int_Vector lift(const BitVector< dim > &v)
Definition: bitvector.cpp:819
BitVector & pushBack(bool)
Definition: bitvector.cpp:58
std::vector< BitSet< dim > > d_data
Definition: bitvector.h:365
BitVector & operator>>=(size_t pos)
Definition: bitvector.h:259
bool operator<(const BitVector &v) const
Definition: bitvector.h:176
BitVector & flip(size_t i)
Definition: bitvector.h:262
bool operator==(const BitVector &v) const
Definition: bitvector.h:182
BitVector & operator+=(const BitVector &v)
Definition: bitvector.h:238
bool dot(const BitVector &v) const
Definition: bitvector.h:213
BinaryEquation make_equation(const SmallBitVector &lhs, bool rhs)
Definition: bitvector.h:517
unsigned short int d_rows
Definition: bitvector.h:368
void setColumn(size_t j, const BitSet< dim > &data)
Definition: bitvector.h:498
Definition: Atlas.h:78
bool combination_exists(const std::vector< BitVector< dim > > &b, const BitVector< dim > &rhs, BitSet< dim > &c)
Definition: bitvector.cpp:505
BitVector(const BitVector &v)
Definition: bitvector.h:163
BitVector(BitSet< dim > data, size_t n)
Definition: bitvector.h:155
bool solvable(const std::vector< BitVector< dimeq > > &eqns, BitVector< dimsol > &sol)
Either find a solution of the system of equations |eqn|, putting it into |sol| and returning |true|...
Definition: bitvector.cpp:586
BitVector & operator-=(const BitVector &v)
Definition: bitvector.h:245
unsigned long n
Definition: axis.cpp:77
const BitSet< dim > & data() const
Definition: bitvector.h:202
BitVector & operator<<=(size_t pos)
Definition: bitvector.h:260
simple_list< T, Alloc >::const_iterator end(const simple_list< T, Alloc > &l)
Definition: sl_list.h:650
size_t count()
Definition: bitvector.h:206
BitSet< dim > base_set
Definition: bitvector.h:137
Definition: Atlas.h:38
BitVector(size_t n, size_t j)
Definition: bitvector.h:149
bool operator!=(const BitVector &v) const
Definition: bitvector.h:188
void spanAdd(std::vector< BitVector< dim > > &a, std::vector< size_t > &f, const BitVector< dim > &v)
Enlarges the basis |a| so as to span |v|.
Definition: bitvector.cpp:795
void set_mod2(size_t i, size_t j, unsigned long v)
Definition: bitvector.h:482
Class definitions and function declarations for the BitSet class.
void Gauss_Jordan(BitSet< dim > &t, std::vector< BitVector< dim > > &b)
Replaces |b| by the ordered canonical basis of the vector space $V$ it spans. Flags in |t| the set of...
Definition: bitvector.cpp:681
const expr & e
Definition: axis.cpp:95
Definition: common.h:36
BitVector & operator&=(const BitVector &v)
Definition: bitvector.h:252
BitVector operator+(const BitVector &v) const
Definition: bitvector.h:216
void get_column(BitVector< dim > &c, size_t j) const
Definition: bitvector.h:434
BitVector & operator=(const BitVector &v)
Definition: bitvector.h:168
BitVectorList(const std::vector< BitVector< dim > > &v)
Definition: bitvector.h:317
void transpose(Endomorphism &e, const FiniteAbelianGroup &A)
Definition: abelian.cpp:675
Vertex v
Definition: graph.cpp:116
Definition: Atlas.h:80
BitVectorList(I begin, I end)
Definition: bitvector.h:328