All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
sparse_vector_test.cc
Go to the documentation of this file.
1 /**
2  * @file sparse_vector_test.cc
3  * @brief Implementation tests for a sparse_vector object.
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date April 22, 2014
6  * @version 1.0
7  *
8  * The test program is made of some infrastucture (mostly the TestManagerClass
9  * class) and some test operations.
10  *
11  * The test operations are derived by actions::BaseAction class; while they are
12  * not documented, their content is a good showcase of features of the
13  * sparse_vector class.
14  */
15 
16 
17 // C/C++ standard libraries
18 #include <iostream>
19 #include <algorithm>
20 #include <string>
21 #include <utility> // std::make_pair()
22 #include <sstream>
23 #include <stdexcept> // std::out_of_range
24 
25 // LArSoft (larcore) libraries
27 
28 
29 template <typename T>
30 T abs(T value) { return (value < T(0))? -value: value; }
31 
32 
33 /// Prints a container into a stream
34 template <typename CONT>
35 std::ostream& PrintVector(const CONT& sv, std::ostream& out = std::cout) {
36  out << "(" << sv.size() << ") {";
37  for (auto value: sv) out << " " << value;
38  return out << " }" << std::flush;
39 } // PrintVector()
40 
41 
42 /// Converts a container into a string
43 template <typename CONT>
44 std::string VectorToString(const CONT& sv) {
45  std::ostringstream sstr;
46  PrintVector(sv, sstr);
47  return sstr.str();
48 } // VectorToString()
49 
50 
51 /// Prints a sparse vector highlighting the ranges
52 template <typename T>
53 std::ostream& PrintVectorRanges
54  (const lar::sparse_vector<T>& sv, std::ostream& out = std::cout)
55 {
56  out << "(" << sv.size() << ") [" << sv.get_ranges().size() << "] {";
57  size_t i = 0;
58  for (auto range: sv.get_ranges()) {
59  while (i++ < range.begin_index())
61  out << " [";
62  for (auto value: range) out << " " << value;
63  out << " ]";
64  i += range.size() - 1;
65  }
66  while (i++ < sv.size())
68  return out << " }" << std::flush;
69 } // PrintVectorRanges()
70 
71 
72 //------------------------------------------------------------------------------
73 namespace actions {
74  template <typename T>
75  class BaseAction;
76 } // namespace actions
77 
78 
79 /// Test manager class
80 template <typename T>
82  public:
83  typedef T Data_t;
85  typedef std::vector<Data_t> Vector_t;
88 
89  /// Data structure to document failure of a single action
90  struct FailureInfo_t {
91  unsigned int nAction{0}; ///< ID of the action
92  std::string description; ///< description of the failed action
93  unsigned int nErrors{0}; ///< number of detected errors
94 
97  (This_t& tc, const Action_t& action, unsigned int errors):
98  nAction(tc.nAction), description(action.description(tc)),
99  nErrors(errors)
100  {}
101  }; // FailureInfo_t
102 
103  Vector_t v{}; ///< vector to operate on
104  SparseVector_t sv{}; ///< sparse vector to operate on
105  unsigned int nAction{0}; ///< number of actions taken so far
106  unsigned int nErrors{0}; ///< number of errors accumulated
107  std::vector<FailureInfo_t> failures; ///< documentation of the failures
108 
109  int quietness{0}; ///< verbosity level (larger is less verbose)
110 
111  std::ostream& out; ///< output stream
112 
113  /// Constructor, specify an output stream
114  TestManagerClass(std::ostream& output_stream = std::cout): out(output_stream)
115  {}
116 
117 
118  /// Returns the current size of the STL vector
119  size_t current_vector_size() const { return v.size(); }
120 
121 
122  /// Checks if the sparse vector is valid
123  bool validate() const
124  {
125  const auto ranges = sv.get_ranges();
126  // a sparse vector with no non-null elements can't be detected invalid
127  if (ranges.empty()) {
128  // std::cout << "[vector is void]" << std::endl;
129  return true;
130  }
131  int i = 0;
132  auto iNext = ranges.cbegin(), rend = ranges.cend();
133  while (iNext != rend) {
134  auto iRange = iNext++;
135  if (iRange->empty()) {
136  out << "[range " << i << " is empty]" << std::endl;
137  return false;
138  }
139  if (iNext != rend) {
140  if (!(*iRange < *iNext)) {
141  out << "[range " << i << " comes after range " << (i+1) << "]"
142  << std::endl;
143  return false;
144  }
145  if (!iRange->separate(*iNext)) {
146  out << "[range " << i << " is overlapping or adjacent to "
147  << (i+1) << "]" << std::endl;
148  return false;
149  }
150  }
151  ++i;
152  } // while
153  if (sv.size() < ranges.back().end_index()) {
154  out << "[size is " << sv.size() << ", it should be at least "
155  << ranges.back().end_index() << "]" << std::endl;
156  return false;
157  }
158  return true;
159  } // validate()
160 
161 
162  bool match() const { return std::equal(v.begin(), v.end(), sv.begin()); }
163 
164  unsigned int check()
165  {
166  unsigned int local_errors = 0;
167  if (!validate()) ++local_errors;
168  if (!match()) {
169  out << "*** Mismatch: " << std::string(58, '*') << std::endl;
170  out << "vector: " << VectorToString(v) << std::endl;
171  out << "sparse vector: " << VectorToString(sv) << std::endl;
172  out << std::string(72, '*') << std::endl;
173  ++local_errors;
174  }
175  return local_errors;
176  } // check()
177 
178 
179  void run(const Action_t& action)
180  {
181  action(v);
182  action(sv);
183  } // run()
184 
185 
186  /**
187  * @brief Perform the specified action and evaluate the result
188  * @param action the action to be performed
189  * @param autoCorrect if on failure the sparse vector is copied from vector
190  * @return number of detected errors
191  */
192  unsigned int perform(const Action_t& action, bool autoCorrect = true)
193  {
194  out << "[" << ++nAction << "] ";
195  action.describe(*this);
196  out << std::endl;
197  run(action);
198  if (quietness <= 0) {
199  out << " => ";
200  PrintVectorRanges(sv) << std::endl;
201  }
202  unsigned int errors = check();
203  if (action.expected_errors != 0) {
204  out << " (" << action.expected_errors << " error(s) expected)"
205  << std::endl;
206  }
207  if ((int)errors != action.expected_errors) {
208  int actual_errors = abs(errors - action.expected_errors);
209  nErrors += actual_errors;
210  failures.emplace_back(*this, action, actual_errors);
211  if (autoCorrect) {
212  recover();
213  if (!match())
214  out << " *** recovery from error failed ***" << std::endl;
215  } // if autoCorrect
216  } // if errors
217  return errors;
218  } // perform()
219 
220 
221  int quiet(int nq = 0) { int q = quietness; quietness = nq; return q; }
222 
223 
224  unsigned int operator() (const Action_t& action) { return perform(action); }
225 
226 
227  /// Set the sparse vector as a copy of the vector (lossy!)
228  void recover() { sv.assign(v); sv.optimize(); }
229 
230  /// Set the vector as a copy of the sparse vector
231  void mirror() { v.assign(sv.cbegin(), sv.cend()); }
232 
233  /// Print a summary of the failures
234  int summary() const
235  {
236  out << nAction << " tests performed";
237  if (nErrors == 0) {
238  out << " successfully." << std::endl;
239  }
240  else {
241  out << ", " << nErrors << " unexpected errors occurred in "
242  << failures.size() << " of them:" << std::endl;
243  for (const FailureInfo_t& info: failures) {
244  out << " [" << info.nAction << "] " << info.description
245  << " => " << info.nErrors << " errors" << std::endl;
246  } // for
247  } // if errors
248  return nErrors;
249  } // summary()
250 
251 }; // TestManagerClass<>
252 
253 
254 
255 //------------------------------------------------------------------------------
256 /// Namespace containing all the test actions.
257 namespace actions {
258 
259  /**
260  * @brief Base class for testing actions
261  * @param T the type stored in the containers
262  *
263  * An action class performs a definite action on both a STL vector (Vector_t)
264  * and on a sparse_vector (SparseVector_t).
265  * The interface includes:
266  * - a describe() function describiing the detail of the action
267  * - a operator(SparseVector_t&) on a sparse vector
268  * - a operator(Vector_t&) on a STL vector
269  * In most of the cases, the action on the STL vector mirrors the one in
270  * the sparse one. Therefore each action shows how to do the same thing
271  * in the two different containers.
272  */
273  template <typename T>
274  class BaseAction {
275  public:
278  typedef typename TestClass_t::Data_t Data_t; ///< type stored
279  typedef typename TestClass_t::Vector_t Vector_t; ///< type of STL vector
281  ///< type of sparse vector
282 
283  int expected_errors{0}; ///< number of errors expected for this action
284 
286  BaseAction(int exp_err): expected_errors(exp_err) {}
287 
288  virtual ~BaseAction() {}
289 
291  { expected_errors = exp_err; return *this; }
292 
293  /// Print a description of this action into the specified steam.
294  void describe(TestClass_t& tc, std::ostream& out) const
295  { doDescribe(tc, out); }
296 
297  /// Print a description of this action in the test class stream.
298  void describe(TestClass_t& tc) const { return doDescribe(tc, tc.out); }
299 
300  /// Returns a string with a description of this action.
301  std::string description(TestClass_t& tc) const
302  { std::ostringstream sstr; describe(tc, sstr); return sstr.str(); }
303 
304  /// Action performed on a STL vector.
305  void operator() (Vector_t& v) const { actionOnVector(v); }
306 
307  /// Action performed on a sparse vector.
309 
310  protected:
311  using v_citer_t = typename Vector_t::const_iterator;
312 
313  virtual void doDescribe(TestClass_t&, std::ostream& out) const
314  { out << "no action"; }
315 
316  virtual void actionOnVector(Vector_t&) const {}
317  virtual void actionOnSparseVector(SparseVector_t&) const {}
318 
319  template <typename ITER>
320  static ITER skipRange(ITER start, ITER const end);
321  template <typename ITER>
322  static ITER skipVoid(ITER start, ITER const end);
323  template <typename ITER>
324  static ITER rangeStart(ITER const begin, ITER last);
325  template <typename ITER>
326  static ITER voidStart(ITER const begin, ITER last);
327  template <typename Vector>
328  static auto findRangeBorders(Vector& v, std::size_t pos)
329  {
330  if ((pos>= v.size()) || isVoid(v[pos]))
331  return std::make_pair(v.end(), v.end());
332  auto rbegin = rangeStart(v.begin(), v.begin() + pos);
333  auto rend = skipRange(rbegin, v.end());
334  return std::make_pair(rbegin, rend);
335  }
336 
337 
338  /// Returns iterator to the first element of the i-th range after start.
339  template <typename ITER>
340  static ITER findRangeStart
341  (Vector_t const& v, std::size_t i, ITER start);
342  template <typename ITER>
343  static ITER findRangeStart(Vector_t const& v, std::size_t i)
344  { return findRangeStart(v, i, v.cbegin()); }
345 
346  /// Returns iterator to the first void element of the i-th void area
347  /// after start.
348  template <typename ITER>
349  static ITER findVoidStart(Vector_t const& v, std::size_t i, ITER start);
350 
351  static bool isVoid(Data_t value) { return SparseVector_t::is_zero(value); }
352 
353  }; // BaseAction<>
354 
355 
356  template <typename T>
357  class Print: public BaseAction<T> {
358  public:
360  using typename Base_t::TestClass_t;
361  using typename Base_t::Data_t;
362  using typename Base_t::Vector_t;
363  using typename Base_t::SparseVector_t;
364 
365  protected:
366  virtual void doDescribe(TestClass_t&, std::ostream& out) const override
367  { out << "print the vectors"; }
368 
369  virtual void actionOnVector(Vector_t& v) const override
370  { doPrintVector(v); }
371  virtual void actionOnSparseVector(SparseVector_t& v) const override
372  { doPrintVector(v); }
373 
374  template <typename Vector>
375  static void doPrintVector(Vector const& v) { PrintVector(v) << std::endl; }
376 
377  }; // Print<>
378 
379  template <typename T>
380  class PrintSparseVector: public BaseAction<T> {
381  public:
383  using typename Base_t::TestClass_t;
384  using typename Base_t::Data_t;
385  using typename Base_t::Vector_t;
386  using typename Base_t::SparseVector_t;
387 
388  protected:
389  virtual void doDescribe(TestClass_t&, std::ostream& out) const override
390  { out << "print the sparse vector"; }
391 
392  virtual void actionOnSparseVector(SparseVector_t& v) const override
393  { PrintVector(v) << std::endl; }
394 
395  }; // PrintSparseVector<>
396 
397 
398  template <typename T>
399  class PrintRange: public BaseAction<T> {
400  public:
402  using typename Base_t::TestClass_t;
403  using typename Base_t::Data_t;
404  using typename Base_t::Vector_t;
405  using typename Base_t::SparseVector_t;
406 
407  size_t position;
408 
409  PrintRange(size_t pos): position(pos) {}
410 
411  protected:
412  virtual void doDescribe(TestClass_t&, std::ostream& out) const override
413  { out << "print the range at position " << position; }
414 
415  virtual void actionOnSparseVector(SparseVector_t& v) const override
416  {
417  try {
418  std::string range_str = VectorToString(v.find_range(position));
419  std::cout << " position " << position << " (value: "
420  << v[position] << " is within range " << range_str
421  << std::endl;
422  }
423  catch (std::out_of_range const&) {
424  std::cout << " no range at position " << position << std::endl;
425  }
426  }
427 
428  }; // PrintRange<>
429 
430  template <typename T>
431  class PrintNonVoid: public BaseAction<T> {
432  public:
434  using typename Base_t::TestClass_t;
435  using typename Base_t::Data_t;
436  using typename Base_t::Vector_t;
437  using typename Base_t::SparseVector_t;
438 
439  protected:
440  virtual void doDescribe(TestClass_t&, std::ostream& out) const override
441  { out << "print the elements which are not in the void"; }
442 
443  virtual void actionOnVector(Vector_t& v) const override
444  {
445  typedef typename Base_t::SparseVector_t::value_type (*cmp_t)
447  std::cout << "Non-zero elements in vector: "
448  << (v.size() - std::count_if
449  (v.begin(), v.end(), cmp_t(&Base_t::SparseVector_t::is_zero)))
450  << std::endl;
451  }
452  virtual void actionOnSparseVector(SparseVector_t& v) const override
453  {
454  std::cout << "Non-void elements in sparse vector: "
455  << v.count() << std::endl;
456  }
457 
458  }; // PrintNonVoid<>
459 
460 
461  template <typename T>
462  class Clear: public BaseAction<T> {
463  public:
465  using typename Base_t::TestClass_t;
466  using typename Base_t::Data_t;
467  using typename Base_t::Vector_t;
468  using typename Base_t::SparseVector_t;
469 
470 
471  protected:
472  virtual void doDescribe(TestClass_t&, std::ostream& out) const override
473  { out << "clear the vectors"; }
474 
475  virtual void actionOnVector(Vector_t& v) const override
476  { doClearVector(v); }
477  virtual void actionOnSparseVector(SparseVector_t& v) const override
478  { doClearVector(v); }
479 
480  template <typename Vector>
481  static void doClearVector(Vector& v) { v.clear(); }
482 
483  }; // Clear<>
484 
485 
486  template <typename T>
487  class Resize: public BaseAction<T> {
488  public:
490  using typename Base_t::TestClass_t;
491  using typename Base_t::Data_t;
492  using typename Base_t::Vector_t;
493  using typename Base_t::SparseVector_t;
494 
495 
496  size_t size;
497 
498  Resize(size_t new_size = 0): size(new_size) {}
499 
500  protected:
501  virtual void doDescribe(TestClass_t&, std::ostream& out) const override
502  { out << "resize to " << size << " elements"; }
503 
504  virtual void actionOnVector(Vector_t& v) const override
505  { doResizeVector(v); }
506  virtual void actionOnSparseVector(SparseVector_t& v) const override
507  { doResizeVector(v); }
508 
509  template <typename Vector>
510  void doResizeVector(Vector& v) const { v.resize(size); }
511 
512  }; // Resize<>
513 
514 
515  template <typename T>
516  class Truncate: public Resize<T> {
517  public:
518  using Base_t = Resize<T>;
519  using typename Base_t::TestClass_t;
520 
521  Truncate(size_t new_size = 0): Base_t(new_size) {}
522 
523  protected:
524  virtual void doDescribe(TestClass_t&, std::ostream& out) const override
525  { out << "truncate to " << Base_t::size << " elements"; }
526 
527  }; // Truncate<>
528 
529 
530  template <typename T>
531  class ResizeWith: public BaseAction<T> {
532  public:
534  using typename Base_t::TestClass_t;
535  using typename Base_t::Data_t;
536  using typename Base_t::Vector_t;
537  using typename Base_t::SparseVector_t;
538 
539  size_t size;
541 
542  ResizeWith(size_t new_size, Data_t val): size(new_size), value(val) {}
543 
544  protected:
545  virtual void doDescribe(TestClass_t&, std::ostream& out) const override
546  { out << "resize to " << size << " elements, filling with " << value; }
547 
548  virtual void actionOnVector(Vector_t& v) const override
549  { doResizeVector(v); }
550  virtual void actionOnSparseVector(SparseVector_t& v) const override
551  { doResizeVector(v); }
552 
553  template <typename Vector>
554  void doResizeVector(Vector& v) const { v.resize(size, value); }
555 
556  }; // ResizeWith<>
557 
558 
559  template <typename T>
560  class Assign: public BaseAction<T> {
561  public:
563  using typename Base_t::TestClass_t;
564  using typename Base_t::Data_t;
565  using typename Base_t::Vector_t;
566  using typename Base_t::SparseVector_t;
567 
568 
570 
571  Assign(Vector_t new_data): data(new_data) {}
572 
573  protected:
574  virtual void doDescribe(TestClass_t&, std::ostream& out) const override
575  {
576  out << "assign ";
577  PrintVector(data, out);
578  } // describe()
579 
580  virtual void actionOnVector(Vector_t& v) const override
581  { doAssignVector(v); }
582  virtual void actionOnSparseVector(SparseVector_t& v) const override
583  { doAssignVector(v); }
584 
585  template <typename Vector>
586  void doAssignVector(Vector& v) const { v.assign(data.begin(), data.end()); }
587 
588  }; // Assign<>
589 
590 
591  template <typename T>
592  class AssignMove: public BaseAction<T> {
593  public:
595  using typename Base_t::TestClass_t;
596  using typename Base_t::Data_t;
597  using typename Base_t::Vector_t;
598  using typename Base_t::SparseVector_t;
599 
600 
602 
603  AssignMove(Vector_t new_data): data(new_data) {}
604 
605  protected:
606  virtual void actionOnVector(Vector_t& v) const override
607  {
609  v.swap(local);
610  }
611  virtual void actionOnSparseVector(SparseVector_t& v) const override
612  {
614  v.assign(std::move(local));
615  }
616 
617  virtual void doDescribe(TestClass_t&, std::ostream& out) const override
618  {
619  out << "move ";
620  PrintVector(data, out);
621  out << " into the vector";
622  } // describe()
623 
624  }; // AssignMove<>
625 
626 
627  template <typename T>
628  class Insert: public BaseAction<T> {
629  public:
631  using typename Base_t::TestClass_t;
632  using typename Base_t::Data_t;
633  using typename Base_t::Vector_t;
634  using typename Base_t::SparseVector_t;
635 
636  size_t position;
638 
639  Insert(size_t pos, Vector_t new_data): position(pos), data(new_data) {}
640 
641  protected:
642  virtual void actionOnVector(Vector_t& v) const override
643  {
644  size_t max_size = std::max(v.size(), position + data.size());
645  v.resize(max_size, 0);
646  std::copy(data.begin(), data.end(), v.begin() + position);
647  }
648  virtual void actionOnSparseVector(SparseVector_t& v) const override
649  { v.add_range(position, data); }
650 
651  virtual void doDescribe(TestClass_t&, std::ostream& out) const override
652  {
653  out << "add data vector ";
654  PrintVector(data, out);
655  out << " starting at position " << position;
656  } // describe()
657 
658  }; // Insert<>
659 
660 
661  template <typename T>
662  class Add: public BaseAction<T> {
663  public:
665  using typename Base_t::TestClass_t;
666  using typename Base_t::Data_t;
667  using typename Base_t::Vector_t;
668  using typename Base_t::SparseVector_t;
669 
670  size_t position;
673 
674  Add(size_t pos, Vector_t new_data, Data_t baseline = Data_t(0))
675  : position(pos), data(new_data), baseline(baseline) {}
676 
677  protected:
678  virtual void actionOnVector(Vector_t& v) const override
679  {
680  size_t max_size = std::max(v.size(), position + data.size());
681  v.resize(max_size, 0);
682  // buggy: we have no way to recognise a void element from a 0 one
683  std::transform(data.cbegin(), data.cend(), v.cbegin() + position,
684  v.begin() + position,
685  [this](auto a, auto b){ return a + ((b == 0)? baseline: b); }
686  );
687  }
688  virtual void actionOnSparseVector(SparseVector_t& v) const override
689  { v.combine_range(position, data, std::plus<Data_t>(), baseline); }
690 
691  virtual void doDescribe(TestClass_t&, std::ostream& out) const override
692  {
693  out << "increment by data in ";
694  PrintVector(data, out);
695  out << " with baseline " << baseline
696  << " starting at position " << position;
697  } // describe()
698 
699  }; // Add<>
700 
701 
702  template <typename T>
703  class Erase: public BaseAction<T> {
704  public:
706  using typename Base_t::TestClass_t;
707  using typename Base_t::Data_t;
708  using typename Base_t::Vector_t;
709  using typename Base_t::SparseVector_t;
710 
711  size_t first, last;
712 
713  Erase(size_t from, size_t to): first(from), last(to) {}
714 
715  protected:
716  virtual void actionOnVector(Vector_t& v) const override
717  {
718  std::fill(
719  v.begin() + std::min(first, v.size()),
720  v.begin() + std::min(last, v.size()),
722  );
723  }
724  virtual void actionOnSparseVector(SparseVector_t& v) const override
725  { v.make_void(v.begin() + first, v.begin() + last); }
726 
727  virtual void doDescribe(TestClass_t&, std::ostream& out) const override
728  {
729  out << "render elements from " << first << " to " << last
730  << " void";
731  } // describe()
732 
733  }; // Erase<>
734 
735 
736  template <typename T>
737  class EraseRangeAt: public BaseAction<T> {
738  /*
739  * Note: `EraseRangeAt<>` prediction might be less than perfect since
740  * std::vector does not have information about the ranges.
741  * In that case, `set_expected_errors(1)` should be called before testing,
742  * and `mirror()` after the test.
743  */
744  public:
746  using typename Base_t::TestClass_t;
747  using typename Base_t::Data_t;
748  using typename Base_t::Vector_t;
749  using typename Base_t::SparseVector_t;
750 
751  size_t position;
752 
753  EraseRangeAt(size_t pos): position(pos) {}
754 
755  protected:
756  virtual void actionOnVector(Vector_t& v) const override
757  {
758  auto&& [rstart, rend] = Base_t::findRangeBorders(v, position);
759  std::fill(rstart, rend, SparseVector_t::value_zero);
760  }
761 
762  virtual void actionOnSparseVector(SparseVector_t& v) const override
763  { v.make_void_around(position); }
764 
765  virtual void doDescribe(TestClass_t&, std::ostream& out) const override
766  { out << "void range containing position " << position; }
767 
768  }; // EraseRangeAt<>
769 
770 
771  template <typename T>
772  class Scale: public BaseAction<T> {
773  public:
775  using typename Base_t::TestClass_t;
776  using typename Base_t::Data_t;
777  using typename Base_t::Vector_t;
778  using typename Base_t::SparseVector_t;
779 
780  size_t position;
782 
783  Scale(size_t pos, Data_t factor): position(pos), factor(factor) {}
784 
785  protected:
786  virtual void actionOnVector(Vector_t& v) const override
787  {
788  auto&& [rstart, rend] = Base_t::findRangeBorders(v, position);
789  while (rstart < rend) *(rstart++) *= factor;
790  }
791  virtual void actionOnSparseVector(SparseVector_t& v) const override
792  {
793  auto i = v.find_range_number(position);
794  if (i >= v.n_ranges()) return;
795  for (auto& value: v.range_data(i)) value *= factor;
796  }
797 
798  virtual void doDescribe(TestClass_t&, std::ostream& out) const override
799  {
800  out << "scale data by a factor " << factor
801  << " starting at position " << position;
802  } // describe()
803 
804  }; // Scale<>
805 
806  // fun with C++17:
807  template <typename T>
808  explicit Scale(size_t pos, T factor) -> Scale<T>;
809 
810 
811  template <typename T>
812  class ScaleAll: public BaseAction<T> {
813  public:
815  using typename Base_t::TestClass_t;
816  using typename Base_t::Data_t;
817  using typename Base_t::Vector_t;
818  using typename Base_t::SparseVector_t;
819 
821 
822  ScaleAll(Data_t factor): factor(factor) {}
823 
824  protected:
825  virtual void actionOnVector(Vector_t& v) const override
826  { for (auto& value: v) value *= factor; }
827  virtual void actionOnSparseVector(SparseVector_t& v) const override
828  {
829  for (auto& r: v.iterate_ranges()) {
830  for (auto& value: r) value *= factor;
831  }
832 
833  }
834 
835  virtual void doDescribe(TestClass_t&, std::ostream& out) const override
836  { out << "scale all data by a factor " << factor; }
837 
838  }; // ScaleAll<>
839 
840  template <typename T> explicit ScaleAll(T factor) -> ScaleAll<T>;
841 
842 
843  template <typename T>
844  class SetElement: public BaseAction<T> {
845  public:
847  using typename Base_t::TestClass_t;
848  using typename Base_t::Data_t;
849  using typename Base_t::Vector_t;
850  using typename Base_t::SparseVector_t;
851 
852  size_t position;
854 
855  SetElement(size_t pos, Data_t new_value): position(pos), value(new_value)
856  {}
857 
858  protected:
859  virtual void actionOnVector(Vector_t& v) const override
860  { v[position] = value; }
861  virtual void actionOnSparseVector(SparseVector_t& v) const override
862  { v.set_at(position, value); }
863 
864  virtual void doDescribe(TestClass_t&, std::ostream& out) const override
865  { out << "set the element " << position << " to " << value; }
866 
867  }; // SetElement<>
868 
869 
870  template <typename T>
871  class UnsetElement: public BaseAction<T> {
872  public:
874  using typename Base_t::TestClass_t;
875  using typename Base_t::Data_t;
876  using typename Base_t::Vector_t;
877  using typename Base_t::SparseVector_t;
878 
879  size_t position;
880 
881  UnsetElement(size_t pos): position(pos) {}
882 
883  protected:
884  virtual void actionOnVector(Vector_t& v) const override
886  virtual void actionOnSparseVector(SparseVector_t& v) const override
887  { v.unset_at(position); }
888 
889  virtual void doDescribe(TestClass_t&, std::ostream& out) const override
890  { out << "turn the element " << position << " into the void"; }
891 
892  }; // SetElement<>
893 
894 
895  template <typename T>
896  class PushBack: public BaseAction<T> {
897  public:
899  using typename Base_t::TestClass_t;
900  using typename Base_t::Data_t;
901  using typename Base_t::Vector_t;
902  using typename Base_t::SparseVector_t;
903 
905 
906  PushBack(Data_t val): value(val) {}
907 
908  protected:
909  virtual void actionOnVector(Vector_t& v) const override
910  { v.push_back(value); }
911  virtual void actionOnSparseVector(SparseVector_t& v) const override
912  { v.push_back(value, 0. /* SparseVector_t::value_zero */); }
913 
914  virtual void doDescribe(TestClass_t&, std::ostream& out) const override
915  { out << "add element " << value << " (if non-zero)"; }
916 
917  }; // PushBack<>
918 
919 
920  template <typename T>
921  class SetValue: public BaseAction<T> {
922  public:
924  using typename Base_t::TestClass_t;
925  using typename Base_t::Data_t;
926  using typename Base_t::Vector_t;
927  using typename Base_t::SparseVector_t;
928 
929  size_t position;
931 
932  SetValue(size_t pos, Data_t val): position(pos), value(val) {}
933 
934  protected:
935  virtual void actionOnVector(Vector_t& v) const override
936  { doAssignValue(v); }
937  virtual void actionOnSparseVector(SparseVector_t& v) const override
938  { doAssignValue(v); }
939 
940  virtual void doDescribe(TestClass_t&, std::ostream& out) const override
941  { out << "set element " << position << " to " << value; }
942 
943  template <typename Vector>
944  void doAssignValue(Vector& v) const { v[position] = value; }
945 
946  }; // SetValue<>
947 
948 
949  template <typename T>
950  class FlipSign: public BaseAction<T> {
951  public:
953  using typename Base_t::TestClass_t;
954  using typename Base_t::Data_t;
955  using typename Base_t::Vector_t;
956  using typename Base_t::SparseVector_t;
957 
958  size_t position;
959 
960  FlipSign(size_t pos): position(pos) {}
961 
962  protected:
963  virtual void doDescribe(TestClass_t&, std::ostream& out) const override
964  { out << "change the sign of element " << position; }
965 
966  virtual void actionOnVector(Vector_t& v) const override
967  { doFlipValue(v); }
968  virtual void actionOnSparseVector(SparseVector_t& v) const override
969  { doFlipValue(v); }
970 
971  template <typename Vector>
972  void doFlipValue(Vector& v) const { v[position] = -v[position]; }
973 
974  }; // FlipSign<>
975 
976 
977  template <typename T>
978  class Optimize: public BaseAction<T> {
979  public:
981  using typename Base_t::TestClass_t;
982  using typename Base_t::Data_t;
983  using typename Base_t::Vector_t;
984  using typename Base_t::SparseVector_t;
985 
987 
988  Optimize(int param): opt_param(param) {}
989 
990  protected:
991  virtual void actionOnSparseVector(SparseVector_t& v) const override
992  {
993  if (opt_param < 0) v.optimize();
994  else v.optimize(opt_param);
995  }
996 
997  virtual void doDescribe(TestClass_t&, std::ostream& out) const override
998  {
999  out << "optimize the sparse vector (";
1000  if (opt_param < 0) out << "default settings";
1001  else out << "optimization parameter: " << opt_param;
1002  out << ")";
1003  }
1004 
1005  }; // Optimize<>
1006 
1007 
1008  template <typename T>
1009  class FailTest: public BaseAction<T> {
1010  public:
1012  using typename Base_t::TestClass_t;
1013  using typename Base_t::Data_t;
1014  using typename Base_t::Vector_t;
1015  using typename Base_t::SparseVector_t;
1016 
1017  protected:
1018  virtual void actionOnVector(Vector_t& v) const override
1019  { v.push_back(Data_t(v.size())); }
1020 
1021  virtual void doDescribe(TestClass_t&, std::ostream& out) const override
1022  { out << "designed failure: changes only vector"; }
1023 
1024  }; // FailTest<>
1025 
1026 
1027 } // namespace actions
1028 
1029 
1030 //------------------------------------------------------------------------------
1031 //--- Template implementation
1032 //------------------------------------------------------------------------------
1033 
1034 template <typename T>
1035 template <typename ITER>
1036 ITER actions::BaseAction<T>::skipRange(ITER start, ITER const end) {
1037  for (; start != end; ++start) if (isVoid(*start)) break;
1038  return start;
1039 } // actions::BaseAction::skipRange()
1040 
1041 template <typename T>
1042 template <typename ITER>
1043 ITER actions::BaseAction<T>::skipVoid(ITER start, ITER const end) {
1044  for (; start != end; ++start) if (!isVoid(*start)) break;
1045  return start;
1046 } // actions::BaseAction::skipVoid()
1047 
1048 
1049 template <typename T>
1050 template <typename ITER>
1051 ITER actions::BaseAction<T>::rangeStart(ITER const begin, ITER last)
1052 {
1053  if (last == begin) return begin;
1054  while (--last != begin) if (isVoid(*last)) break;
1055  return std::next(last);
1056 } // actions::BaseAction::rangeStart()
1057 
1058 template <typename T>
1059 template <typename ITER>
1060 ITER actions::BaseAction<T>::voidStart(ITER const begin, ITER last) {
1061  if (last == begin) return begin;
1062  while (--last != begin) if (!isVoid(*last)) break;
1063  return std::next(last);
1064 } // actions::BaseAction::voidStart()
1065 
1066 
1067 template <typename T>
1068 template <typename ITER>
1070  (Vector_t const& v, std::size_t i, ITER start)
1071 {
1072  auto const end = v.cend();
1073 
1074  start = skipVoid(start, end);
1075  while (start != end) {
1076  if (i-- == 0) break;
1077  start = skipRange(start, end);
1078  start = skipVoid(start, end);
1079  } // while
1080  return start;
1081 } // actions::BaseAction::findRangeStart()
1082 
1083 template <typename T>
1084 template <typename ITER>
1086  (Vector_t const& v, std::size_t i, ITER start)
1087 {
1088  auto const end = v.cend();
1089 
1090  start = skipRange(start, end);
1091  while (start != end) {
1092  if (i-- == 0) break;
1093  start = skipVoid(start, end);
1094  start = skipRange(start, end);
1095  } // while
1096  return start;
1097 } // actions::BaseAction::findVoidStart()
1098 
1099 
1100 //------------------------------------------------------------------------------
1101 
1102 /// A simple test suite
1103 int main() {
1104 
1105  // let's test on:
1106  typedef float Data_t;
1107 
1108 // typedef std::vector<Data_t> Vector_t;
1109 // typedef lar::sparse_vector<Data_t> SparseVector_t;
1110 
1111  // first test: instanciate
1113 
1115 
1117 
1118  Test(actions::Assign<Data_t>({ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }));
1119 
1121 
1122  Test(actions::AssignMove<Data_t>({ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }));
1123 
1125 
1126  Test(actions::Insert<Data_t>(5, { 5, 6, 7 }));
1127 
1128  Test(actions::Insert<Data_t>(15, { 15, 16, 17 }));
1129 
1130  Test(actions::Insert<Data_t>(11, { 11, 12, 13 }));
1131 
1132  Test(actions::Insert<Data_t>(3, { 3 }));
1133 
1134  Data_t new_size = Data_t(Test.current_vector_size());
1135  for (Data_t value:
1136  {
1137  new_size++, new_size++ * 0, new_size++,
1138  new_size++, new_size++ * 0, new_size++
1139  })
1141 
1142  Test(actions::ResizeWith<Data_t>(new_size += 2, -1));
1143 
1144  Test(actions::Resize<Data_t>(new_size += 5));
1145 
1146  Test(actions::Insert<Data_t>(7, { 7, 8 }));
1147 
1148  Test(actions::Insert<Data_t>(18, { 18, 19, 20 }));
1149 
1150  Test(actions::Insert<Data_t>(4, { 4, 5 }));
1151 
1152  Test(actions::Insert<Data_t>(22, { 22 }));
1153 
1154  Test(actions::Insert<Data_t>(19, { 19 }));
1155 
1156  Test(actions::Erase<Data_t>(7, 17));
1157 
1158  Test(actions::Erase<Data_t>(21, 23));
1159 
1161 
1162  for (size_t i = 0; i < Test.current_vector_size(); ++i)
1164 
1165  Test(actions::Insert<Data_t>(15, { 15, 16, 17, 18, 19, 20, 21, 22, 23 }));
1166 
1167  Test(actions::Insert<Data_t>(9, { 9, 10 }));
1168 
1169  Test(actions::Erase<Data_t>(9, 11));
1170 
1171  Test(actions::Insert<Data_t>(9, { 9, 10 }));
1172 
1174 
1176 
1177  Test(actions::SetValue<Data_t>(15, -15.));
1178 
1180 
1181  for (size_t i = 13; i < 16; ++i)
1183 
1184  Test(actions::Scale(15U, 4.0F));
1185 
1186  Test(actions::Scale(15U, 0.25F));
1187 
1188  Test(actions::ScaleAll(2.0F));
1189 
1190  Test(actions::ScaleAll(0.5F));
1191 
1193 
1195 
1197 
1199 
1201 
1203 
1205 
1206  // at this point:
1207  // (31) [2] {
1208  // 0 0 0 [ 3 4 5 6 ] 0 0 0
1209  // 0 0 0 0 0 0 [ 16 17 18 19
1210  // 20 21 22 23 -1 ] 0 0 0 0 0
1211  // 0
1212  // }
1213 
1214  Test(actions::Add<Data_t>(5, { 7, 8, 7, 8 }, 10));
1215  // at this point:
1216  // (31) [2] {
1217  // 0 0 0 [ 3 4 12 13 17 18 ] 0
1218  // 0 0 0 0 0 0 [ 16 17 18 19
1219  // 20 21 22 23 -1 ] 0 0 0 0 0
1220  // 0
1221  // }
1222 
1224  (5, { 20, 20, 20, 20, 8, 7, 8, 7, 8, 7, 8, 7 }, 30));
1225  // at this point:
1226  // (31) [2] {
1227  // 0 0 0 [ 3 4 32 33 37 38 38
1228  // 37 38 37 38 37 38 23 17 18 19
1229  // 20 21 22 23 -1 ] 0 0 0 0 0
1230  // 0
1231  // }
1232 
1233  Test(actions::Add<Data_t>(27, { 7, 8, }, 20));
1234  // at this point:
1235  // (31) [2] {
1236  // 0 0 0 [ 3 4 32 33 37 38 38
1237  // 37 38 37 38 37 38 23 17 18 19
1238  // 20 21 22 23 -1 ] 0 0 [ 27 28 ] 0
1239  // 0
1240  // }
1241 
1243  (4, TestManagerClass<Data_t>::Vector_t(22, 10.0), 15.0));
1244  // at this point:
1245  // (31) [2] {
1246  // 0 0 0 [ 3 14 42 43 47 48 48
1247  // 47 48 47 48 47 48 33 27 28 29
1248  // 30 31 32 33 9 25 ] 0 [ 27 28 ] 0
1249  // 0
1250  // }
1251 
1253  (2, TestManagerClass<Data_t>::Vector_t(22, -10.0), 12.0));
1254  // at this point:
1255  // (31) [2] {
1256  // 0 0 [ 2 3 4 32 33 37 38 38
1257  // 37 38 37 38 37 38 23 17 18 19
1258  // 20 21 22 23 -1 25 ] 0 [ 27 28 ] 0
1259  // 0
1260  // }
1261 
1262  Test(actions::Add<Data_t>(26, { 16, 0 }, 10.0));
1263  // at this point:
1264  // (31) [2] {
1265  // 0 0 [ 2 3 4 32 33 37 38 38
1266  // 37 38 37 38 37 38 23 17 18 19
1267  // 20 21 22 23 -1 25 26 27 28 ] 0
1268  // 0
1269  // }
1270 
1271  Test(actions::Truncate<Data_t>(new_size -= 3));
1272 
1274 
1276 
1278 
1280 
1282 
1284 
1285 #ifdef SPARSE_VECTOR_TEST_FAIL
1286  // enable this to verify that the error detection works
1288  Test.recover();
1289 #endif // SPARSE_VECTOR_TEST_FAIL
1290 
1291  return Test.summary();
1292 } // main()
virtual void actionOnVector(Vector_t &v) const override
Base class for testing actions.
virtual void doDescribe(TestClass_t &, std::ostream &out) const override
virtual void actionOnSparseVector(SparseVector_t &v) const override
std::string VectorToString(const CONT &sv)
Converts a container into a string.
virtual void doDescribe(TestClass_t &, std::ostream &out) const override
std::ostream & out
output stream
unsigned int nAction
number of actions taken so far
std::vector< Data_t > Vector_t
size_type n_ranges() const
Returns the internal list of non-void ranges.
void describe(TestClass_t &tc) const
Print a description of this action in the test class stream.
static ITER findRangeStart(Vector_t const &v, std::size_t i, ITER start)
Returns iterator to the first element of the i-th range after start.
Data structure to document failure of a single action.
virtual void actionOnSparseVector(SparseVector_t &v) const override
static constexpr Sample_t transform(Sample_t sample)
virtual void doDescribe(TestClass_t &, std::ostream &out) const override
unsigned int operator()(const Action_t &action)
virtual void actionOnSparseVector(SparseVector_t &v) const override
size_type size() const
Returns the size of the vector.
TestClass_t::Data_t Data_t
type stored
bool validate() const
Checks if the sparse vector is valid.
TestClass_t::Data_t Data_t
type stored
unsigned int check()
virtual void actionOnVector(Vector_t &v) const override
virtual void actionOnSparseVector(SparseVector_t &v) const override
virtual void actionOnVector(Vector_t &v) const override
virtual void actionOnSparseVector(SparseVector_t &v) const override
void recover()
Set the sparse vector as a copy of the vector (lossy!)
static constexpr value_type value_zero
a representation of 0
void operator()(Vector_t &v) const
Action performed on a STL vector.
const datarange_t & add_range(size_type offset, ITER first, ITER last)
Adds a sequence of elements as a range with specified offset.
const range_list_t & get_ranges() const
Returns the internal list of non-void ranges.
virtual void actionOnSparseVector(SparseVector_t &v) const override
virtual void actionOnVector(Vector_t &v) const override
TestClass_t::Data_t Data_t
type stored
void Test(TFile *pFile=nullptr, bool statChecks=true)
unsigned int perform(const Action_t &action, bool autoCorrect=true)
Perform the specified action and evaluate the result.
const_iterator cend() const
virtual void actionOnVector(Vector_t &v) const override
TestManagerClass(std::ostream &output_stream=std::cout)
Constructor, specify an output stream.
virtual void actionOnVector(Vector_t &v) const override
auto range_data(std::size_t i)
Provides direct access to data of i-th non-void range (zero-based)
std::ostream & PrintVectorRanges(const lar::sparse_vector< T > &sv, std::ostream &out=std::cout)
Prints a sparse vector highlighting the ranges.
Scale(size_t pos, T factor) -> Scale< T >
static ITER skipRange(ITER start, ITER const end)
virtual void doDescribe(TestClass_t &, std::ostream &out) const override
virtual void actionOnVector(Vector_t &v) const override
static void doClearVector(Vector &v)
virtual void doDescribe(TestClass_t &, std::ostream &out) const
value_type & set_at(size_type index, value_type value)
Writes into an element (creating or expanding a range if needed)
Data_t value_type
type of the stored values
virtual void actionOnVector(Vector_t &v) const override
virtual void doDescribe(TestClass_t &, std::ostream &out) const override
This_t & set_expected_errors(int exp_err)
auto iterate_ranges() -> decltype(auto)
virtual void actionOnSparseVector(SparseVector_t &v) const override
virtual void actionOnSparseVector(SparseVector_t &v) const override
TestClass_t::SparseVector_t SparseVector_t
type of sparse vector
virtual void actionOnSparseVector(SparseVector_t &v) const override
TestClass_t::Data_t Data_t
type stored
ScaleAll(T factor) -> ScaleAll< T >
process_name gaushit a
TestManagerClass< T > TestClass_t
lar::sparse_vector< Data_t > SparseVector_t
then local
virtual void doDescribe(TestClass_t &, std::ostream &out) const override
virtual void actionOnVector(Vector_t &v) const override
void mirror()
Set the vector as a copy of the sparse vector.
T abs(T value)
Insert(size_t pos, Vector_t new_data)
virtual void doDescribe(TestClass_t &, std::ostream &out) const override
SetValue(size_t pos, Data_t val)
virtual void actionOnSparseVector(SparseVector_t &v) const override
virtual void doDescribe(TestClass_t &, std::ostream &out) const override
static bool isVoid(Data_t value)
virtual void actionOnSparseVector(SparseVector_t &v) const override
static ITER rangeStart(ITER const begin, ITER last)
virtual void actionOnSparseVector(SparseVector_t &v) const override
virtual void doDescribe(TestClass_t &, std::ostream &out) const override
virtual void actionOnVector(Vector_t &v) const override
ScaleAll(Data_t factor)
static ITER voidStart(ITER const begin, ITER last)
void make_void(iterator first, iterator last)
Makes all the elements from first and before last void.
auto end(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:585
virtual void actionOnVector(Vector_t &v) const override
virtual void actionOnSparseVector(SparseVector_t &v) const override
int summary() const
Print a summary of the failures.
void fill(const art::PtrVector< recob::Hit > &hits, int only_plane)
virtual void actionOnSparseVector(SparseVector_t &v) const override
SetElement(size_t pos, Data_t new_value)
void describe(TestClass_t &tc, std::ostream &out) const
Print a description of this action into the specified steam.
virtual void actionOnVector(Vector_t &v) const override
virtual void actionOnVector(Vector_t &v) const override
virtual void doDescribe(TestClass_t &, std::ostream &out) const override
Vector_t v
vector to operate on
static ITER findRangeStart(Vector_t const &v, std::size_t i)
int quietness
verbosity level (larger is less verbose)
static value_type is_zero(value_type v)
Returns whether the value is exactly zero.
virtual void actionOnVector(Vector_t &v) const override
const datarange_t & combine_range(size_type offset, ITER first, ITER last, OP &&op, value_type void_value=value_zero)
Combines a sequence of elements as a range with data at offset.
AssignMove(Vector_t new_data)
unsigned int nErrors
number of errors accumulated
virtual void doDescribe(TestClass_t &, std::ostream &out) const override
void doAssignValue(Vector &v) const
TestClass_t::Data_t Data_t
type stored
virtual void doDescribe(TestClass_t &, std::ostream &out) const override
virtual void doDescribe(TestClass_t &, std::ostream &out) const override
virtual void actionOnSparseVector(SparseVector_t &v) const override
virtual void actionOnSparseVector(SparseVector_t &v) const override
void doResizeVector(Vector &v) const
virtual void doDescribe(TestClass_t &, std::ostream &out) const override
std::vector< FailureInfo_t > failures
documentation of the failures
std::string description(TestClass_t &tc) const
Returns a string with a description of this action.
auto begin(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:573
size_t current_vector_size() const
Returns the current size of the STL vector.
datarange_t make_void_around(size_type index)
Casts the whole range with the specified item into the void.
bool equal(double a, double b)
Comparison tolerance, in centimeters.
virtual void doDescribe(TestClass_t &, std::ostream &out) const override
void doResizeVector(Vector &v) const
virtual void doDescribe(TestClass_t &, std::ostream &out) const override
virtual void actionOnSparseVector(SparseVector_t &v) const override
A sparse vector.
unsigned int nErrors
number of detected errors
int expected_errors
number of errors expected for this action
const datarange_t & find_range(size_type index) const
Returns the range containing the specified index.
Erase(size_t from, size_t to)
static ITER skipVoid(ITER start, ITER const end)
TestClass_t::Vector_t Vector_t
type of STL vector
virtual void doDescribe(TestClass_t &, std::ostream &out) const override
actions::BaseAction< Data_t > Action_t
void unset_at(size_type index)
Casts the element with the specified index into the void.
virtual void actionOnVector(Vector_t &v) const override
std::size_t find_range_number(size_type index) const
Returns the number (0-based) of range containing index.
iterator begin()
Standard iterators interface.
T copy(T const &v)
virtual void actionOnVector(Vector_t &v) const override
virtual void actionOnVector(Vector_t &v) const override
unsigned int nAction
ID of the action.
static void doPrintVector(Vector const &v)
TestManagerClass< Data_t > This_t
virtual void doDescribe(TestClass_t &, std::ostream &out) const override
virtual void actionOnSparseVector(SparseVector_t &v) const override
temporary value
Scale(size_t pos, Data_t factor)
void push_back(value_type value)
const_iterator cbegin() const
virtual void doDescribe(TestClass_t &, std::ostream &out) const override
virtual void doDescribe(TestClass_t &, std::ostream &out) const override
void doFlipValue(Vector &v) const
TestClass_t::Data_t Data_t
type stored
Class defining a sparse vector (holes are zeroes)
int main(int argc, char **argv)
Assign(Vector_t new_data)
virtual void actionOnVector(Vector_t &) const
void doAssignVector(Vector &v) const
Truncate(size_t new_size=0)
virtual void doDescribe(TestClass_t &, std::ostream &out) const override
bool optimize()
Performs internal optimization, returns whether the object was changed.
virtual void actionOnSparseVector(SparseVector_t &v) const override
TestClass_t::Data_t Data_t
type stored
void assign(ITER first, ITER last)
Copies data from a sequence between two iterators.
esac echo uname r
virtual void doDescribe(TestClass_t &, std::ostream &out) const override
recob::tracking::Vector_t Vector_t
void run(const Action_t &action)
void PrintVector(std::ostream &out, Array const &v, std::string name="Vector")
static ITER findVoidStart(Vector_t const &v, std::size_t i, ITER start)
virtual void actionOnSparseVector(SparseVector_t &) const
virtual void actionOnVector(Vector_t &v) const override
std::string description
description of the failed action
typename Vector_t::const_iterator v_citer_t
BEGIN_PROLOG could also be cout
Test manager class.
static auto findRangeBorders(Vector &v, std::size_t pos)
virtual void actionOnVector(Vector_t &v) const override
virtual void actionOnSparseVector(SparseVector_t &v) const override
Resize(size_t new_size=0)
virtual void doDescribe(TestClass_t &, std::ostream &out) const override
virtual void actionOnSparseVector(SparseVector_t &v) const override
ResizeWith(size_t new_size, Data_t val)
TestClass_t::Data_t Data_t
type stored
size_type count() const
Returns the number of non-void cells.