barry: Your go-to motif accountant  0.0-1
Full enumeration of sample space and fast count of sufficient statistics for binary arrays
barray-meat.hpp
Go to the documentation of this file.
1 // #include <stdexcept>
2 // #include "barray-bones.hpp"
3 
4 template<typename Cell_Type>
5 class Cell;
6 
7 template<typename Cell_Type>
8 class Cell_const;
9 
10 #ifndef BARRY_BARRAY_MEAT_HPP
11 #define BARRY_BARRAY_MEAT_HPP
12 
13 #define ROW(a) this->el_ij[a]
14 #define COL(a) this->el_ji[a]
15 
16 
17 template<typename Cell_Type, typename Data_Type>
19 
20 
21 // Edgelist with data
22 template<typename Cell_Type, typename Data_Type> inline BArray<Cell_Type, Data_Type>::BArray (
23  size_t N_, size_t M_,
24  const std::vector< size_t > & source,
25  const std::vector< size_t > & target,
26  const std::vector< Cell_Type > & value,
27  bool add
28 ) {
29 
30  if (source.size() != target.size())
31  throw std::length_error("-source- and -target- don't match on length.");
32  if (source.size() != value.size())
33  throw std::length_error("-sorce- and -value- don't match on length.");
34 
35  // Initializing
36  N = N_;
37  M = M_;
38 
39  el_ij.resize(N);
40  el_ji.resize(M);
41 
42 
43  // Writing the data
44  for (size_t i = 0u; i < source.size(); ++i) {
45 
46  // Checking range
47  bool empty = this->is_empty(source[i], target[i], true);
48  if (add && !empty) {
49  ROW(source[i])[target[i]].add(value[i]);
50  continue;
51  }
52 
53  if (!empty)
54  throw std::logic_error("The value already exists. Use 'add = true'.");
55 
56  this->insert_cell(source[i], target[i], value[i], false, false);
57  }
58 
59  return;
60 
61 }
62 
63 // Edgelist with data
64 template<typename Cell_Type, typename Data_Type>
66  size_t N_, size_t M_,
67  const std::vector< size_t > & source,
68  const std::vector< size_t > & target,
69  bool add
70 ) {
71 
72  std::vector< Cell_Type > value(source.size(), (Cell_Type) 1.0);
73 
74  if (source.size() != target.size())
75  throw std::length_error("-source- and -target- don't match on length.");
76  if (source.size() != value.size())
77  throw std::length_error("-sorce- and -value- don't match on length.");
78 
79  // Initializing
80  N = N_;
81  M = M_;
82 
83  el_ij.resize(N);
84  el_ji.resize(M);
85 
86 
87  // Writing the data
88  for (size_t i = 0u; i < source.size(); ++i) {
89 
90  // Checking range
91  if ((source[i] >= N_) || (target[i] >= M_))
92  throw std::range_error("Either source or target point to an element outside of the range by (N,M).");
93 
94  // Checking if it exists
95  auto search = ROW(source[i]).find(target[i]);
96  if (search != ROW(source[i]).end()) {
97  if (!add)
98  throw std::logic_error("The value already exists. Use 'add = true'.");
99 
100  // Increasing the value (this will automatically update the
101  // other value)
102  ROW(source[i])[target[i]].add(value[i]);
103  continue;
104  }
105 
106  // Adding the value and creating a pointer to it
107  ROW(source[i]).emplace(
108  std::pair<size_t, Cell< Cell_Type> >(
109  target[i],
110  Cell< Cell_Type >(value[i], visited)
111  )
112  );
113 
114  COL(target[i]).emplace(
115  source[i],
116  &ROW(source[i])[target[i]]
117  );
118 
119  NCells++;
120 
121  }
122 
123  return;
124 
125 }
126 
127 template<typename Cell_Type, typename Data_Type>
129  const BArray<Cell_Type,Data_Type> & Array_,
130  bool copy_data
131 ) : N(Array_.N), M(Array_.M)
132 {
133 
134  // Dimensions
135  // el_ij.resize(N);
136  // el_ji.resize(M);
137 
138  std::copy(Array_.el_ij.begin(), Array_.el_ij.end(), std::back_inserter(el_ij));
139  std::copy(Array_.el_ji.begin(), Array_.el_ji.end(), std::back_inserter(el_ji));
140 
141  // Taking care of the pointers
142  for (size_t i = 0u; i < N; ++i)
143  {
144 
145  for (auto& r: row(i, false))
146  COL(r.first)[i] = &ROW(i)[r.first];
147 
148  }
149 
150  this->NCells = Array_.NCells;
151  this->visited = Array_.visited;
152 
153  // Data
154  if (Array_.data != nullptr)
155  {
156 
157  if (copy_data)
158  {
159 
160  data = new Data_Type(* Array_.data );
161  delete_data = true;
162 
163  } else {
164 
165  data = Array_.data;
166  delete_data = false;
167 
168  }
169 
170  }
171 
172  return;
173 
174 }
175 
176 template<typename Cell_Type, typename Data_Type>
178  const BArray<Cell_Type,Data_Type> & Array_
179 ) {
180 
181  // Clearing
182  if (this != &Array_)
183  {
184 
185  this->clear(true);
186  this->resize(Array_.N, Array_.M);
187 
188  // Entries
189  for (size_t i = 0u; i < N; ++i)
190  {
191 
192  if (Array_.nnozero() == nnozero())
193  break;
194 
195  for (auto& r : Array_.row(i, false))
196  this->insert_cell(i, r.first, r.second.value, false, false);
197 
198  }
199 
200  // Data
201  if (data != nullptr)
202  {
203 
204  if (delete_data)
205  delete data;
206 
207  data = nullptr;
208  delete_data = false;
209 
210  }
211 
212  if (Array_.data != nullptr)
213  {
214 
215  data = new Data_Type(*Array_.data);
216  delete_data = true;
217 
218  }
219 
220  }
221 
222  return *this;
223 
224 }
225 
226 template<typename Cell_Type, typename Data_Type> inline BArray<Cell_Type, Data_Type>::BArray (
228  ) noexcept :
229  N(0u), M(0u), NCells(0u),
230  data(nullptr),
231  delete_data(x.delete_data)
232  {
233 
234  this->clear(true);
235  this->resize(x.N, x.M);
236 
237  // Entries
238  for (size_t i = 0u; i < N; ++i) {
239 
240  if (x.nnozero() == nnozero())
241  break;
242 
243  for (auto& r : x.row(i, false))
244  this->insert_cell(i, r.first, r.second.value, false, false);
245 
246  }
247 
248  // Managing data
249  if (x.data != nullptr)
250  {
251 
252  if (x.delete_data)
253  {
254 
255  data = new Data_Type(*x.data);
256  delete_data = true;
257 
258  } else {
259  data = x.data;
260  delete_data = false;
261  }
262 
263 
264  }
265 
266 }
267 
268 template<typename Cell_Type, typename Data_Type> inline BArray<Cell_Type, Data_Type> & BArray<Cell_Type, Data_Type>:: operator= (
270 ) noexcept {
271 
272  // Clearing
273  if (this != &x) {
274 
275  this->clear(true);
276  this->resize(x.N, x.M);
277 
278  // Entries
279  for (size_t i = 0u; i < N; ++i) {
280 
281  if (x.nnozero() == nnozero())
282  break;
283 
284  for (auto& r : x.row(i, false))
285  this->insert_cell(i, r.first, r.second.value, false, false);
286 
287  }
288 
289  // Data
290  if (data != nullptr)
291  {
292 
293  if (delete_data)
294  delete data;
295  data = nullptr;
296  delete_data = false;
297 
298  }
299 
300  if (x.data != nullptr)
301  {
302 
303  data = new Data_Type( *x.data );
304  delete_data = true;
305 
306  }
307 
308  // x.data = nullptr;
309  // x.delete_data = false;
310 
311  }
312 
313  return *this;
314 
315 }
316 
317 template<typename Cell_Type, typename Data_Type> inline bool BArray<Cell_Type, Data_Type>:: operator== (
318  const BArray<Cell_Type, Data_Type> & Array_
319 ) {
320 
321  // Dimension and number of cells used
322  if ((N != Array_.nrow()) | (M != Array_.ncol()) | (NCells != Array_.nnozero()))
323  return false;
324 
325  // One holds, and the other doesn't.
326  if ((!data & Array_.data) | (data & !Array_.data))
327  return false;
328 
329  if (this->el_ij != Array_.el_ij)
330  return false;
331 
332  return true;
333 }
334 
335 template<typename Cell_Type, typename Data_Type> inline BArray<Cell_Type, Data_Type>::~BArray () {
336 
337  if (delete_data && (data != nullptr))
338  delete data;
339 
340  return;
341 }
342 
343 template<typename Cell_Type, typename Data_Type> inline void BArray<Cell_Type, Data_Type>:: set_data (
344  Data_Type * data_, bool delete_data_
345 ) {
346 
347  if ((data != nullptr) && delete_data)
348  delete data;
349 
350  data = data_;
351  delete_data = delete_data_;
352 
353  return;
354 
355 }
356 
357 template<typename Cell_Type, typename Data_Type> inline Data_Type * BArray<Cell_Type, Data_Type>:: D_ptr ()
358 {
359  return this->data;
360 }
361 
362 template<typename Cell_Type, typename Data_Type>
363 inline const Data_Type * BArray<Cell_Type,Data_Type>::D_ptr() const
364 {
365  return this->data;
366 }
367 
368 template<typename Cell_Type, typename Data_Type> inline Data_Type & BArray<Cell_Type, Data_Type>:: D ()
369 {
370  return *this->data;
371 }
372 
373 template<typename Cell_Type, typename Data_Type>
374 inline const Data_Type & BArray<Cell_Type,Data_Type>::D() const
375 {
376  return *this->data;
377 }
378 
379 template<typename Cell_Type, typename Data_Type>
381 {
382 
383  if (delete_data)
384  {
385  delete data;
386  delete_data = false;
387  }
388 
389  data = nullptr;
390 
391  return;
392 
393 }
394 
395 template<typename Cell_Type, typename Data_Type> inline void BArray<Cell_Type, Data_Type>:: out_of_range (
396  size_t i,
397  size_t j
398 ) const {
399 
400  if (i >= N)
401  throw std::range_error("The row is out of range.");
402  else if (j >= M)
403  throw std::range_error("The column is out of range.");
404  return;
405 
406 }
407 
408 template<typename Cell_Type, typename Data_Type> inline Cell_Type BArray<Cell_Type, Data_Type>:: get_cell (
409  size_t i,
410  size_t j,
411  bool check_bounds
412 ) const {
413 
414  // Checking boundaries
415  if (check_bounds)
416  out_of_range(i,j);
417 
418  if (ROW(i).size() == 0u)
419  return (Cell_Type) 0.0;
420 
421  // If it is not empty, then find and return
422  auto search = ROW(i).find(j);
423  if (search != ROW(i).end())
424  return search->second.value;
425 
426  // This is if it is empty
427  return (Cell_Type) 0.0;
428 
429 }
430 
431 template<typename Cell_Type, typename Data_Type> inline std::vector< Cell_Type > BArray<Cell_Type, Data_Type>:: get_row_vec (
432  size_t i,
433  bool check_bounds
434 ) const {
435 
436  // Checking boundaries
437  if (check_bounds)
438  out_of_range(i, 0u);
439 
440  std::vector< Cell_Type > ans(ncol(), (Cell_Type) false);
441  for (const auto & iter : row(i, false))
442  ans[iter.first] = iter.second.value; //this->get_cell(i, iter->first, false);
443 
444 
445  return ans;
446 }
447 
448 template<typename Cell_Type, typename Data_Type> inline void BArray<Cell_Type, Data_Type>:: get_row_vec (
449  std::vector< Cell_Type > * x,
450  size_t i,
451  bool check_bounds
452 ) const {
453 
454  // Checking boundaries
455  if (check_bounds)
456  out_of_range(i, 0u);
457 
458  for (const auto & iter : row(i, false))
459  x->at(iter.first) = iter.second.value; // this->get_cell(i, iter->first, false);
460 
461 }
462 
463 template<typename Cell_Type, typename Data_Type> inline std::vector< Cell_Type > BArray<Cell_Type, Data_Type>:: get_col_vec (
464  size_t i,
465  bool check_bounds
466 ) const {
467 
468  // Checking boundaries
469  if (check_bounds)
470  out_of_range(0u, i);
471 
472  std::vector< Cell_Type > ans(nrow(), (Cell_Type) false);
473  for (const auto iter : col(i, false))
474  ans[iter.first] = iter.second->value;//this->get_cell(iter->first, i, false);
475 
476  return ans;
477 
478 }
479 
480 template<typename Cell_Type, typename Data_Type> inline void BArray<Cell_Type, Data_Type>:: get_col_vec (
481  std::vector<Cell_Type> * x,
482  size_t i,
483  bool check_bounds
484 ) const {
485 
486  // Checking boundaries
487  if (check_bounds)
488  out_of_range(0u, i);
489 
490  for (const auto & iter : col(i, false))
491  x->at(iter.first) = iter.second->value;//this->get_cell(iter->first, i, false);
492 
493 }
494 
495 template<typename Cell_Type, typename Data_Type> inline const Row_type< Cell_Type > & BArray<Cell_Type, Data_Type>:: row (
496  size_t i,
497  bool check_bounds
498 ) const {
499 
500  if (check_bounds)
501  out_of_range(i, 0u);
502 
503  return this->el_ij[i];
504 
505 }
506 
507 template<typename Cell_Type, typename Data_Type> inline const Col_type< Cell_Type > & BArray<Cell_Type, Data_Type>:: col (
508  size_t i,
509  bool check_bounds
510 ) const {
511 
512  if (check_bounds)
513  out_of_range(0u, i);
514 
515  return this->el_ji[i];
516 
517 }
518 
519 template<typename Cell_Type, typename Data_Type> inline Entries< Cell_Type > BArray<Cell_Type, Data_Type>:: get_entries () const {
520 
521  Entries<Cell_Type> res(NCells);
522 
523  for (size_t i = 0u; i < N; ++i) {
524 
525  if (ROW(i).size() == 0u)
526  continue;
527 
528  for (auto col = ROW(i).begin(); col != ROW(i).end(); ++col) {
529  res.source.push_back(i),
530  res.target.push_back(col->first),
531  res.val.push_back(col->second.value);
532  }
533  }
534 
535  return res;
536 }
537 
538 template<typename Cell_Type, typename Data_Type> inline bool BArray<Cell_Type, Data_Type>:: is_empty (
539  size_t i,
540  size_t j,
541  bool check_bounds
542 ) const {
543 
544  if (check_bounds)
545  out_of_range(i, j);
546 
547  if (ROW(i).size() == 0u)
548  return true;
549  else if (COL(j).size() == 0u)
550  return true;
551 
552  if (ROW(i).find(j) == ROW(i).end())
553  return true;
554 
555  return false;
556 
557 }
558 
559 
560 template<typename Cell_Type, typename Data_Type> inline size_t BArray<Cell_Type, Data_Type>:: nrow () const noexcept {
561  return N;
562 }
563 
564 
565 template<typename Cell_Type, typename Data_Type> inline size_t BArray<Cell_Type, Data_Type>:: ncol () const noexcept {
566  return M;
567 }
568 
569 
570 template<typename Cell_Type, typename Data_Type> inline size_t BArray<Cell_Type, Data_Type>:: nnozero () const noexcept {
571  return NCells;
572 }
573 
574 template<typename Cell_Type, typename Data_Type> inline Cell< Cell_Type > BArray<Cell_Type, Data_Type>:: default_val () const {
575  return this->Cell_default;
576 }
577 
578 template<typename Cell_Type, typename Data_Type> inline BArray<Cell_Type, Data_Type> & BArray<Cell_Type, Data_Type>:: operator+= (
579  const std::pair<size_t,size_t> & coords
580 ) {
581 
582  this->insert_cell(
583  coords.first,
584  coords.second,
585  this->Cell_default,
586  true, true
587  );
588 
589  return *this;
590 
591 }
592 
593 template<typename Cell_Type, typename Data_Type> inline BArray<Cell_Type, Data_Type> & BArray<Cell_Type, Data_Type>:: operator-= (
594  const std::pair<size_t,size_t> & coords
595 ) {
596 
597  this->rm_cell(
598  coords.first,
599  coords.second,
600  true, true
601  );
602 
603  return *this;
604 
605 }
606 
607 template<typename Cell_Type, typename Data_Type>
609  size_t i,
610  size_t j,
611  bool check_bounds
612 ) {
613 
614  return BArrayCell<Cell_Type,Data_Type>(this, i, j, check_bounds);
615 
616 }
617 
618 template<typename Cell_Type, typename Data_Type>
619 inline const Cell_Type BArray<Cell_Type, Data_Type>::operator() (
620  size_t i,
621  size_t j,
622  bool check_bounds
623 ) const {
624 
625  return get_cell(i, j, check_bounds);
626 
627 }
628 
629 template<typename Cell_Type, typename Data_Type> inline void BArray<Cell_Type, Data_Type>:: rm_cell (
630  size_t i,
631  size_t j,
632  bool check_bounds,
633  bool check_exists
634 ) {
635 
636  // Checking the boundaries
637  if (check_bounds)
638  out_of_range(i,j);
639 
640  if (check_exists) {
641  // Nothing to do
642  if (ROW(i).size() == 0u)
643  return;
644 
645  // Checking the counter part
646  if (COL(j).size() == 0u)
647  return;
648 
649  // Hard work, need to remove it from both, if it exist
650  if (ROW(i).find(j) == ROW(i).end())
651  return;
652  }
653 
654  // Remove the pointer first (so it wont point to empty)
655  COL(j).erase(i);
656  ROW(i).erase(j);
657 
658  NCells--;
659 
660  return;
661 
662 }
663 
664 template<typename Cell_Type, typename Data_Type> inline void BArray<Cell_Type, Data_Type>:: insert_cell (
665  size_t i,
666  size_t j,
667  const Cell< Cell_Type> & v,
668  bool check_bounds,
669  bool check_exists
670  ) {
671 
672  if (check_bounds)
673  out_of_range(i,j);
674 
675  if (check_exists) {
676 
677  // Checking if nothing here, then we move along
678  if (ROW(i).size() == 0u) {
679 
680  ROW(i).insert(std::pair< size_t, Cell<Cell_Type>>(j, v));
681  COL(j).emplace(i, &ROW(i)[j]);
682  NCells++;
683  return;
684 
685  }
686 
687  // In this case, the row exists, but we are checking that the value is empty
688  if (ROW(i).find(j) == ROW(i).end()) {
689 
690  ROW(i).insert(std::pair< size_t, Cell<Cell_Type>>(j, v));
691  COL(j).emplace(i, &ROW(i)[j]);
692  NCells++;
693 
694  } else {
695  throw std::logic_error("The cell already exists.");
696  }
697 
698 
699  } else {
700 
701  ROW(i).insert(std::pair< size_t, Cell<Cell_Type>>(j, v));
702  COL(j).emplace(i, &ROW(i)[j]);
703  NCells++;
704 
705  }
706 
707  return;
708 
709 }
710 
711 template<typename Cell_Type, typename Data_Type> inline void BArray<Cell_Type, Data_Type>:: insert_cell (
712  size_t i,
713  size_t j,
714  Cell< Cell_Type> && v,
715  bool check_bounds,
716  bool check_exists
717  ) {
718 
719  if (check_bounds)
720  out_of_range(i,j);
721 
722  if (check_exists) {
723 
724  // Checking if nothing here, then we move along
725  if (ROW(i).size() == 0u) {
726 
727  ROW(i).insert(std::pair< size_t, Cell<Cell_Type>>(j, v));
728  COL(j).emplace(i, &ROW(i)[j]);
729  NCells++;
730  return;
731 
732  }
733 
734  // In this case, the row exists, but we are checking that the value is empty
735  if (ROW(i).find(j) == ROW(i).end()) {
736 
737  ROW(i).insert(std::pair< size_t, Cell<Cell_Type>>(j, v));
738  COL(j).emplace(i, &ROW(i)[j]);
739  NCells++;
740 
741  } else {
742  throw std::logic_error("The cell already exists.");
743  }
744 
745 
746  } else {
747 
748  ROW(i).insert(std::pair< size_t, Cell<Cell_Type>>(j, v));
749  COL(j).emplace(i, &ROW(i)[j]);
750  NCells++;
751 
752  }
753 
754  return;
755 
756 }
757 
758 template<typename Cell_Type, typename Data_Type> inline void BArray<Cell_Type, Data_Type>:: insert_cell (
759  size_t i,
760  size_t j,
761  Cell_Type v,
762  bool check_bounds,
763  bool check_exists
764 ) {
765 
766  return insert_cell(i, j, Cell<Cell_Type>(v, visited), check_bounds, check_exists);
767 
768 }
769 
770 template<typename Cell_Type, typename Data_Type> inline void BArray<Cell_Type, Data_Type>:: swap_cells (
771  size_t i0, size_t j0,
772  size_t i1, size_t j1,
773  bool check_bounds,
774  int check_exists,
775  int * report
776 ) {
777 
778  if (check_bounds) {
779  out_of_range(i0,j0);
780  out_of_range(i1,j1);
781  }
782 
783  // Simplest case, we know both exists, so we don't need to check anything
784  if (check_exists == CHECK::NONE)
785  {
786 
787  // Just in case, if this was passed
788  if (report != nullptr)
789  (*report) = EXISTS::BOTH;
790 
791  // If source and target coincide, we do nothing
792  if ((i0 == i1) && (j0 == j1))
793  return;
794 
795  // Using the initializing by move, after this, the cell becomes
796  // invalid. We use pointers instead as this way we access the Heap memory,
797  // which should be faster to access.
798  Cell<Cell_Type> c0(std::move(ROW(i0)[j0]));
799  rm_cell(i0, j0, false, false);
800  Cell<Cell_Type> c1(std::move(ROW(i1)[j1]));
801  rm_cell(i1, j1, false, false);
802 
803  // Inserting the cells by reference, these will be deleted afterwards
804  insert_cell(i0, j0, c1, false, false);
805  insert_cell(i1, j1, c0, false, false);
806 
807  return;
808 
809  }
810 
811  bool check0, check1;
812  if (check_exists == CHECK::BOTH)
813  {
814 
815  check0 = !is_empty(i0, j0, false);
816  check1 = !is_empty(i1, j1, false);
817 
818  } else if (check_exists == CHECK::ONE) {
819 
820  check0 = !is_empty(i0, j0, false);
821  check1 = true;
822 
823  } else if (check_exists == CHECK::TWO) {
824 
825  check0 = true;
826  check1 = !is_empty(i1, j1, false);
827 
828  }
829 
830  if (report != nullptr)
831  (*report) = EXISTS::NONE;
832 
833  // If both cells exists
834  if (check0 & check1)
835  {
836 
837  if (report != nullptr)
838  (*report) = EXISTS::BOTH;
839 
840  // If source and target coincide, we do nothing
841  if ((i0 == i1) && (j0 == j1))
842  return;
843 
844  Cell<Cell_Type> c0(std::move(ROW(i0)[j0]));
845  rm_cell(i0, j0, false, false);
846  Cell<Cell_Type> c1(std::move(ROW(i1)[j1]));
847  rm_cell(i1, j1, false, false);
848 
849  insert_cell(i0, j0, c1, false, false);
850  insert_cell(i1, j1, c0, false, false);
851 
852  } else if (!check0 & check1) { // If only the second exists
853 
854  if (report != nullptr)
855  (*report) = EXISTS::TWO;
856 
857  insert_cell(i0, j0, ROW(i1)[j1], false, false);
858  rm_cell(i1, j1, false, false);
859 
860  } else if (check0 & !check1) {
861 
862  if (report != nullptr)
863  (*report) = EXISTS::ONE;
864 
865  insert_cell(i1, j1, ROW(i0)[j0], false, false);
866  rm_cell(i0, j0, false, false);
867 
868  }
869 
870  return;
871 }
872 
873 template<typename Cell_Type, typename Data_Type> inline void BArray<Cell_Type, Data_Type>:: toggle_cell (
874  size_t i,
875  size_t j,
876  bool check_bounds,
877  int check_exists
878 ) {
879 
880  if (check_bounds)
881  out_of_range(i, j);
882 
883  if (check_exists == EXISTS::UKNOWN) {
884 
885  if (is_empty(i, j, false)) {
887  ROW(i)[j].visited = visited;
888  } else
889  rm_cell(i, j, false, false);
890 
891  } else if (check_exists == EXISTS::AS_ONE) {
892 
893  rm_cell(i, j, false, false);
894 
895  } else if (check_exists == EXISTS::AS_ZERO) {
896 
898  ROW(i)[j].visited = visited;
899 
900  }
901 
902  return;
903 
904 }
905 
906 template<typename Cell_Type, typename Data_Type> inline void BArray<Cell_Type, Data_Type>:: swap_rows (
907  size_t i0,
908  size_t i1,
909  bool check_bounds
910 ) {
911 
912  if (check_bounds) {
913  out_of_range(i0,0u);
914  out_of_range(i1,0u);
915  }
916 
917  bool move0=true, move1=true;
918  if (ROW(i0).size() == 0u) move0 = false;
919  if (ROW(i1).size() == 0u) move1 = false;
920 
921  if (!move0 && !move1)
922  return;
923 
924  // Swapping happens naturally, need to take care of the pointers
925  // though
926  ROW(i0).swap(ROW(i1));
927 
928  // Delete the thing
929  if (move0)
930  for (auto& i: row(i1, false))
931  COL(i.first).erase(i0);
932 
933  if (move1)
934  for (auto& i: row(i0, false))
935  COL(i.first).erase(i1);
936 
937  // Now, point to the thing, if it has something to point at. Recall that
938  // the indices swapped.
939  if (move1)
940  for (auto& i: row(i0, false))
941  COL(i.first)[i0] = &ROW(i0)[i.first];
942 
943  if (move0)
944  for (auto& i: row(i1, false))
945  COL(i.first)[i1] = &ROW(i1)[i.first];
946 
947  return;
948 
949 }
950 
951 // This swapping is more expensive overall
952 template<typename Cell_Type, typename Data_Type> inline void BArray<Cell_Type, Data_Type>:: swap_cols (
953  size_t j0,
954  size_t j1,
955  bool check_bounds
956 ) {
957 
958  if (check_bounds) {
959  out_of_range(0u, j0);
960  out_of_range(0u, j1);
961  }
962 
963  // Which ones need to be checked
964  bool check0 = true, check1 = true;
965  if (COL(j0).size() == 0u) check0 = false;
966  if (COL(j1).size() == 0u) check1 = false;
967 
968  if (check0 && check1) {
969 
970  // Just swapping one at a time
971  int status;
972  Col_type<Cell_Type> col_tmp = COL(j1);
973  Col_type<Cell_Type> col1 = COL(j0);
974  for (auto iter = col1.begin(); iter != col1.end(); ++iter) {
975 
976  // Swapping values (col-wise)
977  swap_cells(iter->first, j0, iter->first, j1, false, CHECK::TWO, &status);
978 
979  // Need to remove it, so we don't swap that as well
980  if (status == EXISTS::BOTH)
981  col_tmp.erase(iter->first);
982  }
983 
984  // If there's anything left to move, we start moving it, otherwise, we just
985  // skip it
986  if (col_tmp.size() != 0u) {
987 
988  for (auto iter = col_tmp.begin(); iter != col_tmp.end(); ++iter) {
989  insert_cell(iter->first, j0, *iter->second, false, false);
990  rm_cell(iter->first, j1);
991  }
992 
993  }
994 
995  } else if (check0 && !check1) {
996 
997  // 1 is empty, so we just add new cells and remove the other ones
998  for (auto iter = COL(j0).begin(); iter != COL(j0).begin(); ++iter)
999  insert_cell(iter->first, j1, *iter->second, false, false);
1000 
1001  // Setting the column to be zero
1002  COL(j0).empty();
1003 
1004  } else if (!check0 && check1) {
1005 
1006  // 1 is empty, so we just add new cells and remove the other ones
1007  for (auto iter = COL(j1).begin(); iter != COL(j1).begin(); ++iter) {
1008 
1009  // Swapping values (col-wise)
1010  insert_cell(iter->first, j0, *iter->second, false, false);
1011 
1012  }
1013 
1014  // Setting the column to be zero
1015  COL(j1).empty();
1016 
1017  }
1018 
1019 
1020  return;
1021 }
1022 
1023 template<typename Cell_Type, typename Data_Type> inline void BArray<Cell_Type, Data_Type>:: zero_row (
1024  size_t i,
1025  bool check_bounds
1026 ) {
1027 
1028  if (check_bounds)
1029  out_of_range(i, 0u);
1030 
1031  // Nothing to do
1032  if (ROW(i).size() == 0u)
1033  return;
1034 
1035  // Else, remove all elements
1036  auto row0 = ROW(i);
1037  for (auto row = row0.begin(); row != row0.end(); ++row)
1038  rm_cell(i, row->first, false, false);
1039 
1040  return;
1041 
1042 }
1043 
1044 template<typename Cell_Type, typename Data_Type> inline void BArray<Cell_Type, Data_Type>:: zero_col (
1045  size_t j,
1046  bool check_bounds
1047 ) {
1048 
1049  if (check_bounds)
1050  out_of_range(0u, j);
1051 
1052  // Nothing to do
1053  if (COL(j).size() == 0u)
1054  return;
1055 
1056  // Else, remove all elements
1057  auto col0 = COL(j);
1058  for (auto col = col0.begin(); col != col0.end(); ++col)
1059  rm_cell(col->first, j, false, false);
1060 
1061  return;
1062 
1063 }
1064 
1065 template<typename Cell_Type, typename Data_Type> inline void BArray<Cell_Type, Data_Type>:: transpose () {
1066 
1067  // Start by flipping the switch
1068  visited = !visited;
1069 
1070  // Do we need to resize (increase) either?
1071  if (N > M) el_ji.resize(N);
1072  else if (N < M) el_ij.resize(M);
1073 
1074  // size_t N0 = N, M0 = M;
1075  int status;
1076  for (size_t i = 0u; i < N; ++i)
1077  {
1078 
1079  // Do we need to move anything?
1080  if (ROW(i).size() == 0u)
1081  continue;
1082 
1083  // We now iterate changing rows
1085  for (auto col = row.begin(); col != row.end(); ++col)
1086  {
1087 
1088  // Skip if in the diagoal
1089  if (i == col->first)
1090  {
1091  ROW(i)[i].visited = visited;
1092  continue;
1093  }
1094 
1095  // We have not visited this yet, we need to change that
1096  if (ROW(i)[col->first].visited != visited)
1097  {
1098 
1099  // First, swap the contents
1100  swap_cells(i, col->first, col->first, i, false, CHECK::TWO, &status);
1101 
1102  // Changing the switch
1103  if (status == EXISTS::BOTH)
1104  ROW(i)[col->first].visited = visited;
1105 
1106  ROW(col->first)[i].visited = visited;
1107 
1108  }
1109 
1110  }
1111 
1112  }
1113 
1114  // Shreding. Note that no information should have been lost since, hence, no
1115  // change in NCells.
1116  if (N > M) el_ij.resize(M);
1117  else if (N < M) el_ji.resize(N);
1118 
1119  // Swapping the values
1120  std::swap(N, M);
1121 
1122  return;
1123 
1124 }
1125 
1126 template<typename Cell_Type, typename Data_Type> inline void BArray<Cell_Type, Data_Type>:: clear (
1127  bool hard
1128 ) {
1129 
1130  if (hard)
1131  {
1132 
1133  el_ji.clear();
1134  el_ij.clear();
1135 
1136  el_ij.resize(N);
1137  el_ji.resize(M);
1138  NCells = 0u;
1139 
1140  } else {
1141 
1142  for (size_t i = 0u; i < N; ++i)
1143  zero_row(i, false);
1144 
1145  }
1146 
1147  return;
1148 
1149 }
1150 
1151 template<typename Cell_Type, typename Data_Type> inline void BArray<Cell_Type, Data_Type>:: resize (
1152  size_t N_,
1153  size_t M_
1154 ) {
1155 
1156  // Removing rows
1157  if (N_ < N)
1158  for (size_t i = N_; i < N; ++i)
1159  zero_row(i, false);
1160 
1161  // Removing cols
1162  if (M_ < M)
1163  for (size_t j = M_; j < M; ++j)
1164  zero_col(j, false);
1165 
1166  // Resizing will invalidate pointers and values out of range
1167  if (M_ != M) {
1168  el_ji.resize(M_);
1169  M = M_;
1170  }
1171 
1172  if (N_ != N) {
1173  el_ij.resize(N_);
1174  N = N_;
1175  }
1176 
1177 
1178  return;
1179 
1180 }
1181 
1182 template<typename Cell_Type, typename Data_Type>
1184 #ifdef BARRAY_USE_UNORDERED_MAP
1185  for (size_t i = 0u; i < N; i++)
1186  ROW(i).reserve(M);
1187 
1188  for (size_t i = 0u; i < M; i++)
1189  COL(i).reserve(N);
1190 #endif
1191  return;
1192 
1193 }
1194 
1195 template<typename Cell_Type, typename Data_Type>
1197  const char * fmt,
1198  ...
1199 ) const {
1200 
1201 
1202  std::va_list args;
1203  va_start(args, fmt);
1204  print_n(N, M, fmt, args);
1205  va_end(args);
1206 
1207  return;
1208 
1209 }
1210 
1211 template<typename Cell_Type, typename Data_Type>
1213  size_t nrow,
1214  size_t ncol,
1215  const char * fmt,
1216  ...
1217 ) const {
1218 
1219  if (nrow > N)
1220  nrow = N;
1221 
1222  if (ncol > M)
1223  ncol = M;
1224 
1225  std::va_list args;
1226  va_start(args, fmt);
1227  printf_barry(fmt, args);
1228  va_end(args);
1229 
1230  for (size_t i = 0u; i < nrow; ++i)
1231  {
1232 
1233  #ifdef BARRY_DEBUG_LEVEL
1234  #if BARRY_DEBUG_LEVEL > 1
1235  printf_barry("%s [%3i,]", BARRY_DEBUG_HEADER, i);
1236  #endif
1237  #else
1238  printf_barry("[%3i,] ", i);
1239  #endif
1240  for (size_t j = 0u; j < ncol; ++j) {
1241  if (this->is_empty(i, j, false))
1242  printf_barry(" . ");
1243  else
1244  printf_barry(" %.2f ", static_cast<double>(this->get_cell(i, j, false)));
1245 
1246  }
1247 
1248  printf_barry("\n");
1249 
1250  }
1251 
1252  if (nrow < N)
1253  printf_barry("Skipping %lu rows. ", N - nrow);
1254 
1255  if (ncol < M)
1256  printf_barry("Skipping %lu columns. ", M - ncol);
1257 
1258  if (nrow < N || ncol < M)
1259  printf_barry("\n");
1260 
1261 
1262  return;
1263 
1264 }
1265 
1266 #undef ROW
1267 #undef COL
1268 
1269 #endif
1270 
return * this
#define ROW(a)
Definition: barray-meat.hpp:13
#define COL(a)
Definition: barray-meat.hpp:14
#define printf_barry
Baseline class for binary arrays.
void flush_data()
void transpose()
size_t nnozero() const noexcept
void print(const char *fmt=nullptr,...) const
BArray< Cell_Type, Data_Type > & operator-=(const std::pair< size_t, size_t > &coords)
void swap_rows(size_t i0, size_t i1, bool check_bounds=true)
void out_of_range(size_t i, size_t j) const
BArray()
Zero-size array.
Cell< Cell_Type > default_val() const
bool operator==(const BArray< Cell_Type, Data_Type > &Array_)
void swap_cols(size_t j0, size_t j1, bool check_bounds=true)
void zero_col(size_t j, bool check_bounds=true)
Data_Type * D_ptr()
friend class BArrayCell< Cell_Type, Data_Type >
void zero_row(size_t i, bool check_bounds=true)
void print_n(size_t nrow, size_t ncol, const char *fmt=nullptr,...) const
void reserve()
void resize(size_t N_, size_t M_)
void clear(bool hard=true)
const Col_type< Cell_Type > & col(size_t i, bool check_bounds=true) const
BArrayCell< Cell_Type, Data_Type > operator()(size_t i, size_t j, bool check_bounds=true)
void rm_cell(size_t i, size_t j, bool check_bounds=true, bool check_exists=true)
void toggle_cell(size_t i, size_t j, bool check_bounds=true, int check_exists=EXISTS::UKNOWN)
void insert_cell(size_t i, size_t j, const Cell< Cell_Type > &v, bool check_bounds, bool check_exists)
Data_Type & D()
size_t ncol() const noexcept
BArray< Cell_Type, Data_Type > & operator=(const BArray< Cell_Type, Data_Type > &Array_)
Assignment constructor.
BArray< Cell_Type, Data_Type > & operator+=(const std::pair< size_t, size_t > &coords)
Cell_Type get_cell(size_t i, size_t j, bool check_bounds=true) const
bool is_empty(size_t i, size_t j, bool check_bounds=true) const
void swap_cells(size_t i0, size_t j0, size_t i1, size_t j1, bool check_bounds=true, int check_exists=CHECK::BOTH, int *report=nullptr)
Entries< Cell_Type > get_entries() const
Get the edgelist.
void set_data(Data_Type *data_, bool delete_data_=false)
Set the data object.
const Row_type< Cell_Type > & row(size_t i, bool check_bounds=true) const
std::vector< Cell_Type > get_col_vec(size_t i, bool check_bounds=true) const
size_t nrow() const noexcept
bool visited
std::vector< Cell_Type > get_row_vec(size_t i, bool check_bounds=true) const
Entries in BArray. For now, it only has two members:
Definition: cell-bones.hpp:10
A wrapper class to store source, target, val from a BArray object.
Definition: typedefs.hpp:78
return res
Data_Type &&counter_ data(std::move(counter_.data))
size_t size_t j
size_t i
Data_Type &&counter_ noexcept
Data_Type Counter_fun_type< Array_Type, Data_Type > Hasher_fun_type< Array_Type, Data_Type > Data_Type data_
const int TWO
Definition: typedefs.hpp:30
const int NONE
Definition: typedefs.hpp:28
const int BOTH
Definition: typedefs.hpp:27
const int ONE
Definition: typedefs.hpp:29
const int AS_ZERO
Definition: typedefs.hpp:44
const int BOTH
Definition: typedefs.hpp:38
const int NONE
Definition: typedefs.hpp:39
const int ONE
Definition: typedefs.hpp:40
const int AS_ONE
Definition: typedefs.hpp:45
const int UKNOWN
Definition: typedefs.hpp:43
const int TWO
Definition: typedefs.hpp:41
EmptyArray clear()
current_stats resize(counters->size(), 0.0)
Map< size_t, Cell< Cell_Type > > Row_type
Definition: typedefs.hpp:67
Map< size_t, Cell< Cell_Type > * > Col_type
Definition: typedefs.hpp:70