CppAD: A C++ Algorithmic Differentiation Package  20171217
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
sparse_pack.hpp
Go to the documentation of this file.
1 # ifndef CPPAD_LOCAL_SPARSE_PACK_HPP
2 # define CPPAD_LOCAL_SPARSE_PACK_HPP
3 
4 /* --------------------------------------------------------------------------
5 CppAD: C++ Algorithmic Differentiation: Copyright (C) 2003-17 Bradley M. Bell
6 
7 CppAD is distributed under multiple licenses. This distribution is under
8 the terms of the
9  Eclipse Public License Version 1.0.
10 
11 A copy of this license is included in the COPYING file of this distribution.
12 Please visit http://www.coin-or.org/CppAD/ for information on other licenses.
13 -------------------------------------------------------------------------- */
16 
17 namespace CppAD { namespace local { // BEGIN_CPPAD_LOCAL_NAMESPACE
18 /*!
19 \file sparse_pack.hpp
20 Vector of sets of positive integers stored as a packed array of bools.
21 */
22 class sparse_pack_const_iterator;
23 
24 // ==========================================================================
25 /*!
26 Vector of sets of postivie integers, each set stored as a packed boolean array.
27 
28 All the public members for this class are also in the
29 sparse_list and sparse_vecsize classes.
30 This defines the CppAD vector_of_sets concept.
31 */
32 
33 class sparse_pack {
35 private:
36  /// Type used to pack elements (should be the same as corresponding
37  /// typedef in multiple_n_bit() in test_more/sparse_hacobian.cpp)
38  typedef size_t Pack;
39  /// Number of bits per Pack value
40  const size_t n_bit_;
41  /// Number of sets that we are representing
42  /// (set by constructor and resize).
43  size_t n_set_;
44  /// Possible elements in each set are 0, 1, ..., end_ - 1
45  /// (set by constructor and resize).
46  size_t end_;
47  /// Number of \c Pack values necessary to represent \c end_ bits.
48  /// (set by constructor and resize).
49  size_t n_pack_;
50  /// Data for all the sets.
52 // ============================================================================
53  /*!
54  Assign a set equal to the union of a set and a vector;
55 
56  \param target
57  is the index in this sparse_list object of the set being assinged.
58 
59  \param left
60  is the index in this sparse_list object of the
61  left operand for the union operation.
62  It is OK for target and left to be the same value.
63 
64  \param right
65  is a vector of size_t, sorted in accending order.
66  right operand for the union operation.
67  Elements can be repeated in right, but are not be repeated in the
68  resulting set.
69  All of the elements must have value less than end();
70  */
72  size_t target ,
73  size_t left ,
74  const pod_vector<size_t>& right )
75  {
76  // initialize target = left
77  size_t t = target * n_pack_;
78  size_t l = left * n_pack_;
79  size_t j = n_pack_;
80  while(j--)
81  data_[t++] = data_[l++];
82 
83  // add the elements in right
84  for(size_t i = 0; i < right.size(); ++i)
85  add_element(target, right[i]);
86  }
87 public:
88  /// declare a const iterator
90  // -----------------------------------------------------------------
91  /*!
92  Default constructor (no sets)
93  */
94  sparse_pack(void) :
95  n_bit_( std::numeric_limits<Pack>::digits ),
96  n_set_(0) ,
97  end_(0) ,
98  n_pack_(0)
99  { }
100  // -----------------------------------------------------------------
101  /*!
102  Make use of copy constructor an error
103 
104  \param v
105  vector that we are attempting to make a copy of.
106  */
108  n_bit_( std::numeric_limits<Pack>::digits )
109  { // Error:
110  // Probably a sparse_pack argument has been passed by value
112  }
113  // -----------------------------------------------------------------
114  /*!
115  Assignment operator.
116 
117  \param other
118  this sparse_pack will be set to a deep copyof other.
119 
120  */
121  void operator=(const sparse_pack& other)
122  { CPPAD_ASSERT_UNKNOWN( n_bit_ == other.n_bit_);
123  n_set_ = other.n_set_;
124  end_ = other.end_;
125  n_pack_ = other.n_pack_;
126  data_ = other.data_;
127  }
128  // -----------------------------------------------------------------
129  /*!
130  Destructor
131  */
133  { }
134  // -----------------------------------------------------------------
135  /*!
136  Change number of sets, set end, and initialize all sets as empty
137 
138  If \c n_set is zero, any memory currently allocated for this object
139  is freed. Otherwise, new memory may be allocated for the sets (if needed).
140 
141  \param n_set
142  is the number of sets in this vector of sets.
143 
144  \param end
145  is the maximum element plus one. The minimum element is 0 and
146  end must be greater than zero (unless n_set is also zero).
147  If n_set is zero, end must also be zero.
148  */
149  void resize(size_t n_set, size_t end)
150  {
151  n_set_ = n_set;
152  end_ = end;
153  if( n_set_ == 0 )
154  { CPPAD_ASSERT_UNKNOWN( end == 0 );
155  data_.clear();
156  return;
157  }
158  // now start a new vector with empty sets
159  Pack zero(0);
160 
161  n_pack_ = ( 1 + (end_ - 1) / n_bit_ );
162  size_t i = n_set_ * n_pack_;
163 
164  data_.resize(i);
165  while(i--)
166  data_[i] = zero;
167  }
168  // -----------------------------------------------------------------
169  /*!
170  Count number of elements in a set.
171 
172  \param i
173  is the index in of the set we are counting the elements of.
174  */
175  size_t number_elements(size_t i) const
176  { static Pack one(1);
178  size_t count = 0;
179  for(size_t k = 0; k < n_pack_; k++)
180  { Pack unit = data_[ i * n_pack_ + k ];
181  Pack mask = one;
182  size_t n = std::min(n_bit_, end_ - n_bit_ * k);
183  for(size_t bit = 0; bit < n; bit++)
184  { CPPAD_ASSERT_UNKNOWN( mask > one || bit == 0);
185  if( mask & unit )
186  ++count;
187  mask = mask << 1;
188  }
189  }
190  return count;
191  }
192  /*!
193  Post an element for delayed addition to a set.
194 
195  \param i
196  is the index for this set in the vector of sets.
197 
198  \param element
199  is the value of the element that we are posting.
200  The same element may be posted multiple times.
201 
202  \par
203  It is faster to post multiple elements to set i and then call
204  process_post(i) then to add each element individually.
205  It is an error to call any member function,
206  that depends on the value of set i,
207  before processing the posts to set i.
208  */
209  void post_element(size_t i, size_t element)
210  { add_element(i, element); }
211  // -----------------------------------------------------------------
212  /*!
213  process post entries for a specific set.
214 
215  \param i
216  index of the set for which we are processing the post entries.
217 
218  \par post_
219  Upon call, post_[i] is location in data_ of the elements that get
220  added to the i-th set. Upon return, post_[i] is zero.
221  */
222  void process_post(size_t i)
223  { return; }
224  // -----------------------------------------------------------------
225  /*!
226  Add one element to a set.
227 
228  \param i
229  is the index for this set in the vector of sets.
230 
231  \param element
232  is the element we are adding to the set.
233  */
234  void add_element(size_t i, size_t element)
235  { static Pack one(1);
237  CPPAD_ASSERT_UNKNOWN( element < end_ );
238  size_t j = element / n_bit_;
239  size_t k = element - j * n_bit_;
240  Pack mask = one << k;
241  data_[ i * n_pack_ + j] |= mask;
242  }
243  // -----------------------------------------------------------------
244  /*!
245  Is an element of a set.
246 
247  \param i
248  is the index for this set in the vector of sets.
249 
250  \param element
251  is the element we are checking to see if it is in the set.
252  */
253  bool is_element(size_t i, size_t element) const
254  { static Pack one(1);
255  static Pack zero(0);
257  CPPAD_ASSERT_UNKNOWN( element < end_ );
258  size_t j = element / n_bit_;
259  size_t k = element - j * n_bit_;
260  Pack mask = one << k;
261  return (data_[ i * n_pack_ + j] & mask) != zero;
262  }
263  // -----------------------------------------------------------------
264  /*!
265  Assign the empty set to one of the sets.
266 
267  \param target
268  is the index of the set we are setting to the empty set.
269 
270  \par Checked Assertions
271  \li target < n_set_
272  */
273  void clear(size_t target)
274  { // value with all its bits set to false
275  static Pack zero(0);
276  CPPAD_ASSERT_UNKNOWN( target < n_set_ );
277  size_t t = target * n_pack_;
278 
279  size_t j = n_pack_;
280  while(j--)
281  data_[t++] = zero;
282  }
283  // -----------------------------------------------------------------
284  /*!
285  Assign one set equal to another set.
286 
287  \param this_target
288  is the index (in this \c sparse_pack object) of the set being assinged.
289 
290  \param other_value
291  is the index (in the other \c sparse_pack object) of the
292  that we are using as the value to assign to the target set.
293 
294  \param other
295  is the other \c sparse_pack object (which may be the same as this
296  \c sparse_pack object).
297 
298  \par Checked Assertions
299  \li this_target < n_set_
300  \li other_value < other.n_set_
301  \li n_pack_ == other.n_pack_
302  */
304  size_t this_target ,
305  size_t other_value ,
306  const sparse_pack& other )
307  { CPPAD_ASSERT_UNKNOWN( this_target < n_set_ );
308  CPPAD_ASSERT_UNKNOWN( other_value < other.n_set_ );
310  size_t t = this_target * n_pack_;
311  size_t v = other_value * n_pack_;
312 
313  size_t j = n_pack_;
314  while(j--)
315  data_[t++] = other.data_[v++];
316  }
317  // -----------------------------------------------------------------
318  /*!
319  Assing a set equal to the union of two other sets.
320 
321  \param this_target
322  is the index (in this \c sparse_pack object) of the set being assinged.
323 
324  \param this_left
325  is the index (in this \c sparse_pack object) of the
326  left operand for the union operation.
327  It is OK for \a this_target and \a this_left to be the same value.
328 
329  \param other_right
330  is the index (in the other \c sparse_pack object) of the
331  right operand for the union operation.
332  It is OK for \a this_target and \a other_right to be the same value.
333 
334  \param other
335  is the other \c sparse_pack object (which may be the same as this
336  \c sparse_pack object).
337 
338  \par Checked Assertions
339  \li this_target < n_set_
340  \li this_left < n_set_
341  \li other_right < other.n_set_
342  \li n_pack_ == other.n_pack_
343  */
345  size_t this_target ,
346  size_t this_left ,
347  size_t other_right ,
348  const sparse_pack& other )
349  { CPPAD_ASSERT_UNKNOWN( this_target < n_set_ );
350  CPPAD_ASSERT_UNKNOWN( this_left < n_set_ );
351  CPPAD_ASSERT_UNKNOWN( other_right < other.n_set_ );
353 
354  size_t t = this_target * n_pack_;
355  size_t l = this_left * n_pack_;
356  size_t r = other_right * n_pack_;
357 
358  size_t j = n_pack_;
359  while(j--)
360  data_[t++] = ( data_[l++] | other.data_[r++] );
361  }
362  // -----------------------------------------------------------------
363  /*!
364  Assing a set equal to the intersection of two other sets.
365 
366  \param this_target
367  is the index (in this \c sparse_pack object) of the set being assinged.
368 
369  \param this_left
370  is the index (in this \c sparse_pack object) of the
371  left operand for the intersection operation.
372  It is OK for \a this_target and \a this_left to be the same value.
373 
374  \param other_right
375  is the index (in the other \c sparse_pack object) of the
376  right operand for the intersection operation.
377  It is OK for \a this_target and \a other_right to be the same value.
378 
379  \param other
380  is the other \c sparse_pack object (which may be the same as this
381  \c sparse_pack object).
382 
383  \par Checked Assertions
384  \li this_target < n_set_
385  \li this_left < n_set_
386  \li other_right < other.n_set_
387  \li n_pack_ == other.n_pack_
388  */
390  size_t this_target ,
391  size_t this_left ,
392  size_t other_right ,
393  const sparse_pack& other )
394  { CPPAD_ASSERT_UNKNOWN( this_target < n_set_ );
395  CPPAD_ASSERT_UNKNOWN( this_left < n_set_ );
396  CPPAD_ASSERT_UNKNOWN( other_right < other.n_set_ );
398 
399  size_t t = this_target * n_pack_;
400  size_t l = this_left * n_pack_;
401  size_t r = other_right * n_pack_;
402 
403  size_t j = n_pack_;
404  while(j--)
405  data_[t++] = ( data_[l++] & other.data_[r++] );
406  }
407  // -----------------------------------------------------------------
408  /*!
409  Fetch n_set for vector of sets object.
410 
411  \return
412  Number of from sets for this vector of sets object
413  */
414  size_t n_set(void) const
415  { return n_set_; }
416  // -----------------------------------------------------------------
417  /*!
418  Fetch end for this vector of sets object.
419 
420  \return
421  is the maximum element value plus one (the minimum element value is 0).
422  */
423  size_t end(void) const
424  { return end_; }
425  // -----------------------------------------------------------------
426  /*!
427  Amount of memory used by this vector of sets
428 
429  \return
430  The amount of memory in units of type unsigned char memory.
431  */
432  size_t memory(void) const
433  { return data_.capacity() * sizeof(Pack);
434  }
435  /*!
436  Print the vector of sets (used for debugging)
437  */
438  void print(void) const;
439 };
440 // ==========================================================================
441 /*!
442 cons_iterator for one set of positive integers in a sparse_pack object.
443 
444 All the public members for this class are also in the
445 sparse_list_const_iterator and sparse_sizevec_const_iterator classes.
446 This defines the CppAD vector_of_sets iterator concept.
447 */
449 private:
450  /// Type used to pack elements in sparse_pack
452 
453  /// data for the entire vector of sets
455 
456  /// Number of bits per Pack value
457  const size_t n_bit_;
458 
459  /// Number of Pack values necessary to represent end_ bits.
460  const size_t n_pack_;
461 
462  /// Possible elements in each set are 0, 1, ..., end_ - 1;
463  const size_t end_;
464 
465  /// index of this set in the vector of sets;
466  const size_t set_index_;
467 
468  /// value of the next element in this set
469  /// (use end_ for no such element exists; i.e., past end of the set).
471 public:
472  /// construct a const_iterator for a set in a sparse_pack object
473  sparse_pack_const_iterator (const sparse_pack& pack, size_t set_index)
474  :
475  data_ ( pack.data_ ) ,
476  n_bit_ ( pack.n_bit_ ) ,
477  n_pack_ ( pack.n_pack_ ) ,
478  end_ ( pack.end_ ) ,
479  set_index_ ( set_index )
480  { static Pack one(1);
482  //
483  next_element_ = 0;
484  if( next_element_ < end_ )
485  { Pack check = data_[ set_index_ * n_pack_ + 0 ];
486  if( check & one )
487  return;
488  }
489  // element with index zero is not in this set of integers,
490  // advance to first element or end
491  ++(*this);
492  }
493 
494  /// advance to next element in this set
496  { static Pack one(1);
498  if( next_element_ == end_ )
499  return *this;
500  //
501  ++next_element_;
502  if( next_element_ == end_ )
503  return *this;
504  //
505  // initialize packed data index
506  size_t j = next_element_ / n_bit_;
507 
508  // initialize bit index
509  size_t k = next_element_ - j * n_bit_;
510 
511  // initialize mask
512  size_t mask = one << k;
513 
514  // start search at this packed value
515  Pack check = data_[ set_index_ * n_pack_ + j ];
516  //
517  while( true )
518  { // check if this element is in the set
519  if( check & mask )
520  return *this;
521 
522  // increment next element before checking this one
523  next_element_++;
524  if( next_element_ == end_ )
525  return *this;
526 
527  // shift mask to left one bit so corresponds to next_element_
528  // (use mask <<= 1. not one << k, so compiler knows value)
529  k++;
530  mask <<= 1;
531  CPPAD_ASSERT_UNKNOWN( k <= n_bit_ );
532 
533  // check if we must go to next packed data index
534  if( k == n_bit_ )
535  { // get next packed value
536  k = 0;
537  mask = one;
538  j++;
540  check = data_[ set_index_ * n_pack_ + j ];
541  }
542  }
543  // should never get here
544  CPPAD_ASSERT_UNKNOWN(false);
545  return *this;
546  }
547 
548  /// obtain value of this element of the set of positive integers
549  /// (end_ for no such element)
550  size_t operator*(void) const
551  { return next_element_; }
552 };
553 // =========================================================================
554 /*!
555 Print the vector of sets (used for debugging)
556 */
557 inline void sparse_pack::print(void) const
558 { std::cout << "sparse_pack:\n";
559  for(size_t i = 0; i < n_set(); i++)
560  { std::cout << "set[" << i << "] = {";
561  const_iterator itr(*this, i);
562  while( *itr != end() )
563  { std::cout << *itr;
564  if( *(++itr) != end() )
565  std::cout << ",";
566  }
567  std::cout << "}\n";
568  }
569  return;
570 }
571 
572 // ==========================================================================
573 
574 /*!
575 Copy a user vector of sets sparsity pattern to an internal sparse_pack object.
576 
577 \tparam VectorSet
578 is a simple vector with elements of type std::set<size_t>.
579 
580 \param internal
581 The input value of sparisty does not matter.
582 Upon return it contains the same sparsity pattern as \c user
583 (or the transposed sparsity pattern).
584 
585 \param user
586 sparsity pattern that we are placing internal.
587 
588 \param n_set
589 number of sets (rows) in the internal sparsity pattern.
590 
591 \param end
592 end of set value (number of columns) in the interanl sparsity pattern.
593 
594 \param transpose
595 if true, the user sparsity patter is the transposed.
596 
597 \param error_msg
598 is the error message to display if some values in the user sparstiy
599 pattern are not valid.
600 */
601 template<class VectorSet>
603  sparse_pack& internal ,
604  const VectorSet& user ,
605  size_t n_set ,
606  size_t end ,
607  bool transpose ,
608  const char* error_msg )
609 { CPPAD_ASSERT_KNOWN(size_t( user.size() ) == n_set * end, error_msg );
610 
611  // size of internal sparsity pattern
612  internal.resize(n_set, end);
613 
614  if( transpose )
615  { // transposed pattern case
616  for(size_t j = 0; j < end; j++)
617  { for(size_t i = 0; i < n_set; i++)
618  { if( user[ j * n_set + i ] )
619  internal.add_element(i, j);
620  }
621  }
622  return;
623  }
624  else
625  { for(size_t i = 0; i < n_set; i++)
626  { for(size_t j = 0; j < end; j++)
627  { if( user[ i * end + j ] )
628  internal.add_element(i, j);
629  }
630  }
631  }
632  return;
633 }
634 
635 } } // END_CPPAD_LOCAL_NAMESPACE
636 # endif
#define CPPAD_ASSERT_KNOWN(exp, msg)
Check that exp is true, if not print msg and terminate execution.
size_t operator*(void) const
obtain value of this element of the set of positive integers (end_ for no such element) ...
const size_t set_index_
index of this set in the vector of sets;
void resize(size_t n)
resize the vector (existing elements preserved when n &lt;= capacity_).
Definition: pod_vector.hpp:180
void clear(void)
Remove all the elements from this vector and free its memory.
Definition: pod_vector.hpp:246
size_t n_set(void) const
Fetch n_set for vector of sets object.
size_t n_set_
Number of sets that we are representing (set by constructor and resize).
Definition: sparse_pack.hpp:43
const size_t end_
Possible elements in each set are 0, 1, ..., end_ - 1;.
void operator=(const sparse_pack &other)
Assignment operator.
void print(void) const
Print the vector of sets (used for debugging)
void process_post(size_t i)
process post entries for a specific set.
size_t end_
Possible elements in each set are 0, 1, ..., end_ - 1 (set by constructor and resize).
Definition: sparse_pack.hpp:46
Define the CppAD error checking macros (all of which begin with CPPAD_ASSERT_)
const pod_vector< Pack > & data_
data for the entire vector of sets
size_t memory(void) const
Amount of memory used by this vector of sets.
sparse_pack_const_iterator & operator++(void)
advance to next element in this set
size_t end(void) const
Fetch end for this vector of sets object.
void binary_union(size_t this_target, size_t this_left, size_t other_right, const sparse_pack &other)
Assing a set equal to the union of two other sets.
File used to define pod_vector class.
void binary_union(size_t target, size_t left, const pod_vector< size_t > &right)
Assign a set equal to the union of a set and a vector;.
Definition: sparse_pack.hpp:71
~sparse_pack(void)
Destructor.
void post_element(size_t i, size_t element)
Post an element for delayed addition to a set.
sparse_pack_const_iterator const_iterator
declare a const iterator
Definition: sparse_pack.hpp:89
size_t next_element_
value of the next element in this set (use end_ for no such element exists; i.e., past end of the set...
size_t number_elements(size_t i) const
Count number of elements in a set.
void clear(size_t target)
Assign the empty set to one of the sets.
Vector of sets of postivie integers, each set stored as a packed boolean array.
Definition: sparse_pack.hpp:33
sparse_pack_const_iterator(const sparse_pack &pack, size_t set_index)
construct a const_iterator for a set in a sparse_pack object
All tthese defaults correspond to errors.
pod_vector< Pack > data_
Data for all the sets.
Definition: sparse_pack.hpp:51
size_t size(void) const
current number of elements in this vector.
Definition: pod_vector.hpp:79
const size_t n_pack_
Number of Pack values necessary to represent end_ bits.
#define CPPAD_ASSERT_UNKNOWN(exp)
Check that exp is true, if not terminate execution.
bool is_element(size_t i, size_t element) const
Is an element of a set.
void assignment(size_t this_target, size_t other_value, const sparse_pack &other)
Assign one set equal to another set.
const size_t n_bit_
Number of bits per Pack value.
sparse_pack(const sparse_pack &v)
Make use of copy constructor an error.
void add_element(size_t i, size_t element)
Add one element to a set.
size_t n_pack_
Number of Pack values necessary to represent end_ bits. (set by constructor and resize).
Definition: sparse_pack.hpp:49
const size_t n_bit_
Number of bits per Pack value.
Definition: sparse_pack.hpp:40
cons_iterator for one set of positive integers in a sparse_pack object.
sparse_pack(void)
Default constructor (no sets)
Definition: sparse_pack.hpp:94
void binary_intersection(size_t this_target, size_t this_left, size_t other_right, const sparse_pack &other)
Assing a set equal to the intersection of two other sets.
size_t capacity(void) const
current capacity (amount of allocated storage) for this vector.
Definition: pod_vector.hpp:83
size_t Pack
Type used to pack elements (should be the same as corresponding typedef in multiple_n_bit() in test_m...
Definition: sparse_pack.hpp:38
sparse_pack::Pack Pack
Type used to pack elements in sparse_pack.
void sparsity_user2internal(sparse_list &internal, const VectorSet &user, size_t n_set, size_t end, bool transpose, const char *error_msg)
Copy a user vector of sets sparsity pattern to an internal sparse_list object.
void resize(size_t n_set, size_t end)
Change number of sets, set end, and initialize all sets as empty.