CASM  1.1.0
A Clusters Approach to Statistical Mechanics
Array.hh
Go to the documentation of this file.
1 
2 #ifndef ARRAY_HH
3 #define ARRAY_HH
4 
5 #include <stdlib.h>
6 
7 #include <cassert>
8 #include <cmath>
9 #include <iostream>
10 #include <new>
11 
13 #include "casm/misc/CASM_TMP.hh"
14 
15 namespace CASM {
16 template <class T>
17 class Array;
18 
19 template <class T>
20 class ReturnArray;
21 
44 template <class T>
45 class Array {
46  private:
47  static Index ARRAY_MIN_EXTRA_SPACE() { return 2; }
48  static double ARRAY_EXTENSION_FACTOR() { return 1.1; }
49 
50  // static const int min_extra_space = 2;
51  // static const double percent_extra_space = 0.1;
52 
55  T *Vals;
56 
57  public:
58  // typedefs for nested Arrays -- Declare using 'Array<T>::XN', where 'N' is
59  // the number of nested indices
60  typedef Array<T> X1;
61  typedef Array<X1> X2;
62  typedef Array<X2> X3;
63  typedef Array<X3> X4;
64  typedef Array<X4> X5;
65  typedef Array<X5> X6;
66  typedef Array<X6> X7;
67  typedef Array<X7> X8;
68  typedef Array<X8> X9;
69 
70  typedef T value_type;
71  typedef Index size_type;
72  typedef T *iterator;
73  typedef const T *const_iterator;
74 
75  // CONSTRUCTORS/DESTRUCTORS
76  Array() : N(0), NMax(0), Vals(nullptr) {}
77 
78  //*******************************************************************************************
79 
80  Array(Index init_N) : N(0), NMax(0), Vals(nullptr) { resize(init_N); }
81 
82  //*******************************************************************************************
83 
84  Array(Index init_N, const T &init_val) : N(0), NMax(0), Vals(nullptr) {
85  resize(init_N, init_val);
86  }
87 
88  //*******************************************************************************************
89 
90  Array(const Array &RHS) : N(0), NMax(0), Vals(nullptr) {
91  reserve(RHS.size());
92  for (Index i = 0; i < RHS.size(); i++) push_back(RHS[i]);
93  }
94 
95  //*******************************************************************************************
96 
97  template <typename Iterator,
99  Array(Iterator begin, Iterator end) : N(0), NMax(0), Vals(nullptr) {
100  reserve(std::distance(begin, end));
101  auto it = begin;
102  for (; it != end; ++it) push_back(*it);
103  }
104 
105  //*******************************************************************************************
106  Array(std::initializer_list<T> in) : N(0), NMax(0), Vals(nullptr) {
107  reserve(in.size());
108  auto it = in.begin();
109  for (; it != in.end(); ++it) push_back(*it);
110  }
111 
112  //*******************************************************************************************
113 
115 
116  ~Array() {
117  clear();
118  if (Vals) operator delete(Vals);
119  }
120 
123  static ReturnArray<T> sequence(const T &initial, const T &final);
124 
128  static ReturnArray<T> sequence(const T &initial, const T &increment,
129  const T &final);
130 
131  Index size() const { return N; }
132 
133  // ASSIGN/REASSIGN
134  Array &operator=(const Array &RHS);
136  void swap(Array<T> &RHS);
137 
138  // ACCESSORS
139 
140  T &at(Index ind) {
141  assert(ind >= 0 && ind < N);
142  return Vals[ind];
143  }
144 
145  const T &at(Index ind) const {
146  assert(ind >= 0 && ind < N);
147  return Vals[ind];
148  }
149 
150  const T &operator[](Index ind) const {
151  assert(ind >= 0 && ind < N);
152  return Vals[ind];
153  }
154 
155  T &operator[](Index ind) {
156  assert(ind >= 0 && ind < N);
157  return Vals[ind];
158  }
159 
160  T &back() { return at(N - 1); }
161  const T &back() const { return at(N - 1); }
162 
163  // Return pointer to the first element
164  T const *begin() const { return Vals; }
165  // Return pointer to the first element
166  T const *cbegin() const { return Vals; }
167  T *begin() { return Vals; }
168 
169  // Return pointer to first point in memory beyond the last element
170  T const *end() const { return Vals + N; }
171  // Return pointer to first point in memory beyond the last element
172  T const *cend() const { return Vals + N; }
173  T *end() { return Vals + N; }
174 
175  // MUTATORS
176  void push_back(const T &toPush);
177 
178  void pop_back() {
179  if (N) Vals[--N].~T();
180  }
181  void remove(Index ind);
182  void clear() {
183  while (N) Vals[--N].~T();
184  }
185 
186  void resize(Index new_N);
187  void resize(Index new_N, const T &fill_val);
188  void reserve(Index new_max);
189 
190  template <typename CompareType>
191  void sort(const CompareType &comp);
192  void sort(Array<Index> &ind_order);
193  void sort();
194  Array &append(const Array &new_tail);
195  Array &append_unique(const Array &new_tail);
196 
197  void swap_elem(Index i, Index j) { std::swap(at(i), at(j)); };
198 
199  Array &permute(const Array<Index> &perm_array);
200  Array &ipermute(const Array<Index> &perm_array);
201  bool next_permute();
202 
205  // INSPECTORS
206 
207  const T &max() const;
208  const T &min() const;
209 
210  // copy portion of *this Array into a new Array
211  ReturnArray<T> sub_array(Index ind_begin, Index ind_end) const;
212 
213  T sum() const;
214 
215  bool is_ascending() const;
216  bool is_descending() const;
217  bool is_constant() const;
218  bool is_permute() const;
219  bool has_fixed_points() const;
220 
221  // COMPARISONS
222 
223  bool operator==(const Array<T> &RHS) const;
224  bool operator!=(const Array<T> &RHS) const { return !((*this) == RHS); }
225  bool operator<(const Array<T> &RHS) const;
226  bool operator>(const Array<T> &RHS) const;
227  bool operator<=(const Array<T> &RHS) const { return !((*this) > RHS); }
228  bool operator>=(const Array<T> &RHS) const { return !((*this) < RHS); }
229 
230  bool all_in(const Array &superset) const;
231  Index coincidence(const Array &superset) const;
232  Index incidences(const T &test_elem) const;
233  Index find(const T &test_elem) const;
235  Index reverse_find(const T &test_elem) const;
236  Index almost_find(const T &test_elem, double tol_val = TOL) const;
238  Index almost_reverse_find(const T &test_elem, double tol_val = TOL) const;
239  bool contains(const T &test_elem) const { return find(test_elem) < N; }
240  bool almost_contains(const T &test_elem, double tol_val = TOL) const {
241  return almost_find(test_elem, tol_val) < N;
242  }
243 
244  // I/O
245  void print_column(std::ostream &stream, const std::string &indent = "") const;
246 };
247 
248 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
249 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
250 
251 template <typename T>
252 class ReturnArray : public Array<T> {
253  public:
254  using Array<T>::swap;
255 
256  ReturnArray(Array<T> &init_tens) { swap(init_tens); }
257 
259  swap(RHS);
260  return *this;
261  }
262 };
263 
264 //*******************************************************************************************
265 
266 template <typename T>
267 Array<T>::Array(ReturnArray<T> &RHS) : N(0), NMax(0), Vals(nullptr) {
268  swap(RHS);
269 }
270 
271 //*******************************************************************************************
274 template <typename T>
275 ReturnArray<T> Array<T>::sequence(const T &initial, const T &final) {
276  Array<T> seq;
277  if (!(initial <= final)) return seq;
278 
279  seq.push_back(initial);
280 
281  while (seq.back() < final) {
282  seq.push_back(seq.back());
283  seq.back()++;
284  }
285  return seq;
286 }
287 
288 //*******************************************************************************************
291 template <typename T>
292 ReturnArray<T> Array<T>::sequence(const T &initial, const T &increment,
293  const T &final) {
294  Array<T> seq;
295  seq.push_back(initial);
296  seq.push_back(initial += increment);
297 
298  if (seq[0] < seq[1]) { // increasing case
299  if (final < seq[1]) {
300  seq.pop_back();
301  if (final < initial) {
302  seq.clear();
303  }
304  return seq;
305  }
306 
307  while (seq.back() < final) {
308  seq.push_back(seq.back());
309  seq.back() += increment;
310  }
311  if (final < seq.back()) seq.pop_back();
312  return seq;
313  } else if (seq[1] < seq[0]) { // decreasing case
314  if (seq[1] < final) {
315  seq.pop_back();
316  if (initial < final) {
317  seq.clear();
318  }
319  return seq;
320  }
321 
322  while (final < seq.back()) {
323  seq.push_back(seq.back());
324  seq.back() += increment;
325  }
326  if (seq.back() < final) seq.pop_back();
327  return seq;
328  } else { // increment=0 case
329  seq.pop_back();
330  if (initial < final || final < initial) seq.clear();
331  return seq;
332  }
333 }
334 
335 //*******************************************************************************************
336 
337 template <typename T>
339  if (this == &RHS) {
340  return *this;
341  }
342 
343  Index i;
344  if (NMax < RHS.size()) {
345  clear();
346  reserve(RHS.size());
347  for (i = 0; i < RHS.size(); i++) push_back(RHS[i]);
348  return *this;
349  }
350 
351  while (N > RHS.size()) pop_back();
352 
353  i = N;
354 
355  while (N < RHS.size()) push_back(RHS[N]);
356 
357  while (i--) Vals[i] = RHS[i];
358 
359  return *this;
360 }
361 
362 //*******************************************************************************************
363 
364 template <typename T>
366  swap(RHS);
367 }
368 
369 //*******************************************************************************************
370 template <typename T>
372  if (this == &RHS) return;
373 
374  Index tN(N), tNMax(NMax);
375  T *tVals(Vals);
376 
377  Vals = RHS.Vals;
378  N = RHS.N;
379  NMax = RHS.NMax;
380 
381  RHS.Vals = tVals;
382  RHS.N = tN;
383  RHS.NMax = tNMax;
384 
385  return;
386 }
387 
388 //*******************************************************************************************
389 template <typename T>
390 void Array<T>::resize(Index new_N) {
391  clear();
392  if (new_N > 0) {
393  reserve(new_N);
394  while (N < new_N) new (Vals + (N++)) T();
395  }
396  return;
397 }
398 
399 //*******************************************************************************************
400 
401 template <typename T>
402 void Array<T>::resize(Index new_N, const T &fill_val) {
403  clear();
404  reserve(new_N);
405  while (N < new_N) new (Vals + (N++)) T(fill_val);
406  return;
407 }
408 
409 //*******************************************************************************************
410 template <typename T>
411 void Array<T>::reserve(Index new_max) {
412  if (new_max <= N) return;
413 
414  T *tVal(nullptr);
415  if (new_max) {
416  tVal = static_cast<T *>(operator new(new_max * sizeof(T)));
417  for (Index i = 0; i < N; i++) {
418  new (tVal + i) T(Vals[i]);
419  Vals[i].~T();
420  }
421  }
422  if (Vals) operator delete(Vals);
423  Vals = tVal;
424  NMax = new_max;
425  return;
426 }
427 
428 //*******************************************************************************************
429 
430 template <typename T>
431 void Array<T>::push_back(const T &toPush) {
432  // If N==NMax, we must reallocate memory. This is not done via
433  // Array::reserve. Instead, we do it within Array::push_back
434  if (N == NMax) {
435  Index new_Max = (N * ARRAY_EXTENSION_FACTOR() > N + ARRAY_MIN_EXTRA_SPACE())
436  ? (Index)(N * ARRAY_EXTENSION_FACTOR())
437  : N + ARRAY_MIN_EXTRA_SPACE();
438 
439  T *tVal(nullptr);
440 
441  tVal = static_cast<T *>(operator new(new_Max * sizeof(T)));
442 
443  // first, add the new element; this prevents aliasing problems
444  new (tVal + N) T(toPush);
445  for (Index i = 0; i < N; i++) {
446  new (tVal + i) T(Vals[i]);
447  Vals[i].~T();
448  }
449 
450  if (Vals) operator delete(Vals);
451  Vals = tVal;
452  NMax = new_Max;
453 
454  N++;
455  } else {
456  new (Vals + (N++)) T(toPush);
457  }
458 }
459 
460 //*******************************************************************************************
461 template <typename T>
463  for (Index i = ind + 1; i < N; i++) at(i - 1) = at(i);
464 
465  Vals[--N].~T();
466 
467  return;
468 }
469 
470 //*******************************************************************************************
471 template <typename T>
472 bool Array<T>::operator==(const Array<T> &RHS) const {
473  if (N != RHS.N) return false;
474 
475  Index i;
476  for (i = 0; i < N; i++) {
477  if (!(at(i) == RHS[i])) {
478  return false;
479  }
480  }
481 
482  return true;
483 }
484 
485 //*******************************************************************************************
486 template <typename T>
487 bool Array<T>::operator<(const Array<T> &RHS) const {
488  if (size() != RHS.size()) return size() < RHS.size();
489 
490  for (Index i = 0; i < size(); i++) {
491  if (at(i) < RHS[i])
492  return true;
493  else if (at(i) > RHS[i])
494  return false;
495  }
496  return false;
497 }
498 
499 //*******************************************************************************************
500 template <typename T>
501 bool Array<T>::operator>(const Array<T> &RHS) const {
502  if (size() != RHS.size()) return size() > RHS.size();
503 
504  for (Index i = 0; i < size(); i++) {
505  if (at(i) > RHS[i])
506  return true;
507  else if (at(i) < RHS[i])
508  return false;
509  }
510  return false;
511 }
512 
513 //*******************************************************************************************
514 template <typename T>
515 const T &Array<T>::max() const {
516  if (!size()) {
517  std::cerr
518  << "ERROR: Tried to find maximum value of empty array! Exiting...\n";
519  assert(0);
520  exit(1);
521  }
522 
523  Index imax = 0;
524 
525  for (Index i = 1; i < size(); i++) {
526  if (at(imax) < at(i)) imax = i;
527  }
528  return at(imax);
529 }
530 
531 //*******************************************************************************************
532 
533 template <typename T>
534 const T &Array<T>::min() const {
535  if (!size()) {
536  std::cerr
537  << "ERROR: Tried to find minimum value of empty array! Exiting...\n";
538  assert(0);
539  exit(1);
540  }
541 
542  Index imin = 0;
543  for (Index i = 1; i < size(); i++) {
544  if (at(i) < at(imin)) imin = i;
545  }
546  return at(imin);
547 }
548 
549 //*******************************************************************************************
550 
551 template <typename T>
552 T Array<T>::sum() const {
553  T result(0);
554  for (Index i = 0; i < size(); i++) {
555  result += at(i);
556  }
557  return result;
558 }
559 
560 //*******************************************************************************************
561 template <typename T>
562 ReturnArray<T> Array<T>::sub_array(Index ind_begin, Index ind_end) const {
563  assert(ind_begin <= ind_end && ind_end < size() &&
564  "Array::operator() indices out of bounds!");
565  Array<T> sub;
566  sub.reserve(ind_end - ind_begin);
567  while (ind_begin <= ind_end) {
568  sub.push_back(at(ind_begin++));
569  }
570  return sub;
571 }
572 //*******************************************************************************************
573 
574 template <typename T>
575 bool Array<T>::all_in(const Array &superset) const {
576  for (Index i = 0; i < N; i++) {
577  if (!superset.contains(at(i))) {
578  return false;
579  }
580  }
581 
582  return true;
583 }
584 
585 //*******************************************************************************************
586 // returns number of elements of *this that are coincident with 'superset',
587 // neglecting order.
588 
589 template <typename T>
590 Index Array<T>::coincidence(const Array &superset) const {
591  Index nco(0);
592  for (Index i = 0; i < N; i++) {
593  if (superset.contains(at(i))) {
594  nco++;
595  }
596  }
597 
598  return nco;
599 }
600 
601 //*******************************************************************************************
602 
603 template <typename T>
604 Index Array<T>::incidences(const T &test_elem) const {
605  Index ni(0);
606  for (Index i = 0; i < N; i++) {
607  if (at(i) == test_elem) {
608  ni++;
609  }
610  }
611 
612  return ni;
613 }
614 
615 //*******************************************************************************************
616 
617 template <typename T>
618 Index Array<T>::find(const T &test_elem) const {
619  for (Index i = 0; i < N; i++) {
620  if (at(i) == test_elem) {
621  return i;
622  }
623  }
624 
625  return N;
626 }
627 
628 //*******************************************************************************************
629 
630 template <typename T>
631 Index Array<T>::reverse_find(const T &test_elem) const {
632  for (Index i = N - 1; i >= 0; i--) {
633  if (at(i) == test_elem) {
634  return i;
635  };
636  };
637 
638  return N;
639 }
640 
641 //************************************************************
642 
643 template <typename T>
644 Index Array<T>::almost_find(const T &test_elem, double tol_val) const {
645  for (Index i = 0; i < N; i++) {
646  if (almost_equal(at(i), test_elem, tol_val)) {
647  return i;
648  }
649  }
650 
651  return N;
652 }
653 
654 //*******************************************************************************************
655 template <typename T>
656 void Array<T>::print_column(std::ostream &stream,
657  const std::string &indent) const {
658  for (Index i = 0; i < N; i++) stream << indent << at(i) << std::endl;
659 }
660 //*******************************************************************************************
661 
662 template <typename T>
663 Index Array<T>::almost_reverse_find(const T &test_elem, double tol_val) const {
664  for (Index i = N - 1; i >= 0; i--) {
665  if (almost_equal(at(i), test_elem, tol_val)) {
666  return i;
667  };
668  };
669 
670  return N;
671 }
672 
673 //************************************************************
674 
675 template <typename T>
676 template <typename CompareType>
677 void Array<T>::sort(const CompareType &comp) {
682  // Adapted from implementation by Brian Puchala
683 
684  int left, right, middle, pivot, curr, i;
685  Array<int> queue_left, queue_right;
686 
687  // estimate queue size
688  int cap = (int)3 * (std::log(size()) / std::log(2));
689  // cout << "cap: " << cap << endl;
690  queue_left.reserve(cap);
691  queue_right.reserve(cap);
692 
693  queue_left.push_back(0);
694  queue_right.push_back(size() - 1);
695 
696  Index max_q = 0;
697 
698  do {
699  left = queue_left[0];
700  right = queue_right[0];
701  queue_left.swap_elem(0, queue_left.size() - 1);
702  queue_left.pop_back();
703 
704  queue_right.swap_elem(0, queue_right.size() - 1);
705  queue_left.pop_back();
706 
707  if (left < right) {
708  // avoid using (right+left) since this could be larger than max allowed
709  // value
710  middle = left + (right - left) / 2;
711 
712  // choose median of (left, middle, right) for pivot
713  if (comp.compare(at(left), at(middle))) {
714  if (comp.compare(at(middle), at(right)))
715  pivot = middle;
716  else {
717  if (comp.compare(at(left), at(right)))
718  pivot = right;
719  else
720  pivot = left;
721  }
722  } else {
723  if (comp.compare(at(right), at(middle)))
724  pivot = middle;
725  else {
726  if (comp.compare(at(right), at(left)))
727  pivot = right;
728  else
729  pivot = left;
730  }
731  }
732 
733  // move pivot to end
734  swap_elem(pivot, right);
735 
736  // in the current region (left:right-1), seperate the values less than the
737  // pivot value (which is now at 'right')
738  curr = left;
739  for (i = left; i < right; i++) {
740  if (comp.compare(at(i), at(right))) {
741  swap_elem(curr, i);
742  curr++;
743  }
744  }
745 
746  // move the pivot value to the 'curr' position
747  swap_elem(curr, right);
748 
749  // now everything in 'left:curr-1' is < *val[curr], and everything in
750  // 'curr+1:right' is >= *val[curr]
751  // so add those two regions to the queue
752 
753  if (curr != 0) {
754  if (left != curr - 1) {
755  // cout << " add region: " << left << ":" << curr-1 << endl;
756  queue_left.push_back(left);
757  queue_right.push_back(curr - 1);
758  }
759  }
760 
761  if (curr + 1 != right) {
762  // cout << " add region: " << curr+1 << ":" << right << endl;
763  queue_left.push_back(curr + 1);
764  queue_right.push_back(right);
765  }
766  // repeat until there is nothing left
767  }
768 
769  if (queue_left.size() > max_q) max_q = queue_left.size();
770 
771  } while (queue_left.size() > 0);
772 
773  // cout << "max_q: " << max_q << endl;
774  // cout << "max_q/cap: " << (1.0*max_q)/(1.0*cap) << endl;
775 }
776 
777 //*******************************************************************************************
778 
779 template <typename T>
780 void Array<T>::sort(Array<Index> &ind_order) {
781  ind_order.clear();
782  for (Index i = 0; i < size(); i++) ind_order.push_back(i);
783 
784  for (Index i = 0; i < size(); i++) {
785  for (Index j = i + 1; j < size(); j++) {
786  if (at(j) < at(i)) {
787  swap_elem(i, j);
788  ind_order.swap_elem(i, j);
789  }
790  }
791  }
792 }
793 
794 //*******************************************************************************************
795 
796 template <typename T>
798  for (Index i = 0; i < size(); i++) {
799  for (Index j = i + 1; j < size(); j++) {
800  if (at(j) < at(i)) {
801  swap_elem(i, j);
802  }
803  }
804  }
805 }
806 //*******************************************************************************************
807 template <typename T>
808 Array<T> &Array<T>::append(const Array<T> &new_tail) {
809  reserve(size() + new_tail.size());
810  Index Nadd(new_tail.size());
811  for (Index i = 0; i < Nadd; i++) push_back(new_tail[i]);
812  return *this;
813 }
814 
815 //*******************************************************************************************
816 
817 template <typename T>
819  Index Nadd(new_tail.size());
820  for (Index i = 0; i < Nadd; i++) {
821  if (!contains(new_tail[i])) push_back(new_tail[i]);
822  }
823 
824  return *this;
825 }
826 
827 //*******************************************************************************************
828 // perm_array gives order of indices after permutation in terms of original
829 // indices. e.g., for my_array={2,3,5,8} and perm_array={3,2,1,4}
830 // my_array.permute(perm_array)={5,3,2,8}
831 template <typename T>
833  assert(perm_array.size() == size());
834  Array<T> after_array;
835  after_array.reserve(size());
836  for (Index i = 0; i < perm_array.size(); i++)
837  after_array.push_back(at(perm_array[i]));
838 
839  swap(after_array);
840  return *this;
841 }
842 
843 //*******************************************************************************************
844 // generate inversely permuted copy of *this
845 // perm_array gives order of indices after permutation in terms of original
846 // indices. e.g., for my_array={2,3,5,8} and perm_array={3,2,1,4}
847 // my_array.permute(perm_array)={5,3,2,8}
848 template <typename T>
850  assert(perm_array.size() == size());
851  Array<T> after_array(*this);
852 
853  for (Index i = 0; i < perm_array.size(); i++) {
854  if (i != perm_array[i]) {
855  after_array[perm_array[i]] = at(i);
856  }
857  }
858  swap(after_array);
859  return *this;
860 }
861 
862 //*******************************************************************************************
863 
864 template <typename T>
866  Index i(N - 2), j(N - 1);
867  bool is_valid = true;
868  while (valid_index(i) && at(i + 1) <= at(i)) i--;
869 
870  if (valid_index(i)) {
871  while (at(j) <= at(i)) j--;
872 
873  swap_elem(i, j);
874  i++;
875  j = N - 1;
876  } else {
877  is_valid = false;
878  i = 0;
879  }
880 
881  while (i < j) swap_elem(i++, j--);
882 
883  return is_valid;
884 }
885 
886 //*******************************************************************************************
887 
891 template <typename T>
893  ReturnArray<Index> iperm_array(size(), 0);
894  for (Index i = 0; i < size(); i++) {
895  iperm_array[at(i)] = i;
896  }
897  return iperm_array;
898 }
899 
900 //*******************************************************************************************
908 
909 template <typename T>
911  const Array<Index> &trans_perm) const {
912  return ((trans_perm.as_perm_inverse()).permute(*this)).permute(trans_perm);
913 }
914 
915 //*******************************************************************************************
916 
917 template <typename T>
919  for (Index i = 0; i < N - 1; i++) {
920  if (at(i + 1) < at(i)) return false;
921  }
922 
923  return true;
924 }
925 
926 //*******************************************************************************************
927 
928 template <typename T>
930  for (Index i = 0; i < N - 1; i++) {
931  if (at(i) < at(i + 1)) return false;
932  }
933 
934  return true;
935 }
936 
937 //*******************************************************************************************
938 
939 template <typename T>
940 bool Array<T>::is_constant() const {
941  for (Index i = 0; i < N - 1; i++) {
942  if (!(at(i) == at(i + 1))) return false;
943  }
944 
945  return true;
946 }
947 
948 //*******************************************************************************************
949 
952 template <typename T>
953 bool Array<T>::is_permute() const {
954  for (Index i = 0; i < size(); i++) {
955  if (at(i) < 0 || at(i) >= size() || find(at(i)) < i) return false;
956  }
957  return true;
958 }
959 
960 //*******************************************************************************************
961 
964 template <typename T>
966  for (Index i = 0; i < size(); i++) {
967  if (at(i) == i) return true;
968  }
969  return false;
970 }
971 
972 //*******************************************************************************************
973 template <class T>
974 Array<T> array_cat(const Array<T> &A1, const Array<T> &A2) {
975  return Array<T>(A1).append(A2);
976 }
977 
978 //*******************************************************************************************
979 template <class T>
980 std::ostream &operator<<(std::ostream &out, const Array<T> &array_out) {
981  if (array_out.size() == 0) out << "[empty] ";
982  for (Index i = 0; i < array_out.size(); i++) {
983  out << array_out[i] << " ";
984  }
985  return out;
986 }
987 
988 //*******************************************************************************************
989 /*
990 template<class T>
991 std::ostream &operator<<(std::ostream &out, const Array<T *> &array_out) {
992  if(array_out.size() == 0)
993  out << "[empty] ";
994  for(Index i = 0; i < array_out.size(); i++) {
995  out << *array_out[i] << " ";
996  }
997  return out;
998 }
999 */
1000 
1001 //*******************************************************************************************
1002 
1003 template <typename T>
1004 void swap(Array<T> &A1, Array<T> &A2) {
1005  A1.swap(A2);
1006  return;
1007 }
1008 
1009 //*******************************************************************************************
1010 
1012  public:
1013  template <typename T>
1014  bool compare(const Array<T> &a, const Array<T> &b) const {
1015  return a.size() < b.size();
1016  }
1017 };
1018 
1021 } // namespace CASM
1022 
1023 #endif /* ARRAY_H_ */
Basic std::vector like container (deprecated)
Definition: Array.hh:45
bool operator!=(const Array< T > &RHS) const
Definition: Array.hh:224
const T & back() const
Definition: Array.hh:161
T & back()
Definition: Array.hh:160
Index size_type
Definition: Array.hh:71
Array< X4 > X5
Definition: Array.hh:64
void pop_back()
Definition: Array.hh:178
Array(Index init_N, const T &init_val)
Definition: Array.hh:84
bool almost_contains(const T &test_elem, double tol_val=TOL) const
Definition: Array.hh:240
const T & operator[](Index ind) const
Definition: Array.hh:150
bool operator>=(const Array< T > &RHS) const
Definition: Array.hh:228
Array< X8 > X9
Definition: Array.hh:68
Array(Iterator begin, Iterator end)
Definition: Array.hh:99
const T & at(Index ind) const
Definition: Array.hh:145
T value_type
Definition: Array.hh:70
T const * end() const
Definition: Array.hh:170
Array< X5 > X6
Definition: Array.hh:65
Array< T > X1
Definition: Array.hh:60
bool contains(const T &test_elem) const
Definition: Array.hh:239
Array< X1 > X2
Definition: Array.hh:61
T & at(Index ind)
Definition: Array.hh:140
T const * begin() const
Definition: Array.hh:164
T & operator[](Index ind)
Definition: Array.hh:155
Array(std::initializer_list< T > in)
Definition: Array.hh:106
T * end()
Definition: Array.hh:173
T * iterator
Definition: Array.hh:72
Array(const Array &RHS)
Definition: Array.hh:90
Index size() const
Definition: Array.hh:131
const T * const_iterator
Definition: Array.hh:73
void swap_elem(Index i, Index j)
Definition: Array.hh:197
Array< X7 > X8
Definition: Array.hh:67
Array(Index init_N)
Definition: Array.hh:80
Index N
Definition: Array.hh:53
static Index ARRAY_MIN_EXTRA_SPACE()
Definition: Array.hh:47
T const * cbegin() const
Definition: Array.hh:166
Array< X6 > X7
Definition: Array.hh:66
Array< X3 > X4
Definition: Array.hh:63
Array< X2 > X3
Definition: Array.hh:62
T * Vals
Definition: Array.hh:55
T const * cend() const
Definition: Array.hh:172
Index NMax
Definition: Array.hh:54
T * begin()
Definition: Array.hh:167
static double ARRAY_EXTENSION_FACTOR()
Definition: Array.hh:48
bool operator<=(const Array< T > &RHS) const
Definition: Array.hh:227
void clear()
Definition: Array.hh:182
bool compare(const Array< T > &a, const Array< T > &b) const
Definition: Array.hh:1014
ReturnArray & operator=(Array< T > &RHS)
Definition: Array.hh:258
ReturnArray(Array< T > &init_tens)
Definition: Array.hh:256
void sort()
Definition: Array.hh:797
bool operator>(const Array< T > &RHS) const
Definition: Array.hh:501
bool all_in(const Array &superset) const
Definition: Array.hh:575
T sum() const
Definition: Array.hh:552
void reserve(Index new_max)
Definition: Array.hh:411
Array & append_unique(const Array &new_tail)
Definition: Array.hh:818
bool is_constant() const
Definition: Array.hh:940
static ReturnArray< T > sequence(const T &initial, const T &increment, const T &final)
Definition: Array.hh:292
ReturnArray< T > sub_array(Index ind_begin, Index ind_end) const
Definition: Array.hh:562
void resize(Index new_N)
Definition: Array.hh:390
Index reverse_find(const T &test_elem) const
Same as find, but starts from the last element of the Array.
Definition: Array.hh:631
ReturnArray< Index > as_perm_inverse() const
Definition: Array.hh:892
const T & max() const
Definition: Array.hh:515
void swap(Array< T > &RHS)
Definition: Array.hh:371
Array & operator=(ReturnArray< T > &RHS)
Definition: Array.hh:365
Array< T > array_cat(const Array< T > &A1, const Array< T > &A2)
Definition: Array.hh:974
bool operator<(const Array< T > &RHS) const
Definition: Array.hh:487
Array & ipermute(const Array< Index > &perm_array)
Definition: Array.hh:849
bool is_descending() const
Definition: Array.hh:929
ReturnArray< Index > as_perm_transform_by(const Array< Index > &trans_perm) const
Definition: Array.hh:910
Index almost_find(const T &test_elem, double tol_val=TOL) const
Definition: Array.hh:644
Array & permute(const Array< Index > &perm_array)
Definition: Array.hh:832
bool is_permute() const
Definition: Array.hh:953
static ReturnArray< T > sequence(const T &initial, const T &final)
Definition: Array.hh:275
void push_back(const T &toPush)
Definition: Array.hh:431
Index coincidence(const Array &superset) const
Definition: Array.hh:590
void sort(const CompareType &comp)
Definition: Array.hh:677
void print_column(std::ostream &stream, const std::string &indent="") const
Definition: Array.hh:656
Index incidences(const T &test_elem) const
Definition: Array.hh:604
void resize(Index new_N, const T &fill_val)
Definition: Array.hh:402
bool is_ascending() const
Definition: Array.hh:918
Array(ReturnArray< T > &RHS)
Definition: Array.hh:267
bool next_permute()
Definition: Array.hh:865
const T & min() const
Definition: Array.hh:534
void sort(Array< Index > &ind_order)
Definition: Array.hh:780
bool operator==(const Array< T > &RHS) const
Definition: Array.hh:472
Array & append(const Array &new_tail)
Definition: Array.hh:808
Index find(const T &test_elem) const
Definition: Array.hh:618
Index almost_reverse_find(const T &test_elem, double tol_val=TOL) const
Same as almost_find, but start from the last element of the Array.
Definition: Array.hh:663
void remove(Index ind)
Definition: Array.hh:462
bool has_fixed_points() const
Definition: Array.hh:965
Array & operator=(const Array &RHS)
Definition: Array.hh:338
void swap(Array< T > &A1, Array< T > &A2)
Definition: Array.hh:1004
Eigen::VectorXd comp(const Configuration &config)
Returns parametric composition, as calculated using PrimClex::param_comp.
std::enable_if< is_iterator< T >::type::value &&std::is_same< typename std::iterator_traits< T >::value_type, V >::type::value, void > enable_if_iterator_of
Template alias to enable a template function via SFINAE for an iterator with value_type V.
Definition: CASM_TMP.hh:75
Main CASM namespace.
Definition: APICommand.hh:8
bool almost_equal(ClusterInvariants const &A, ClusterInvariants const &B, double tol)
Check if ClusterInvariants are equal.
std::ostream & operator<<(std::ostream &_stream, const FormattedPrintable &_formatted)
void swap(ConfigDoF &A, ConfigDoF &B)
Definition: ConfigDoF.cc:260
const double TOL
Definition: definitions.hh:30
Iterator find(Iterator begin, Iterator end, const T &value, BinaryCompare q)
Equivalent to std::find(begin, end, value), but with custom comparison.
Definition: algorithm.hh:16
bool contains(const Container &container, const T &value)
Equivalent to container.end() != std::find(container.begin(), container.end(), value)
Definition: algorithm.hh:83
bool valid_index(Index i)
Definition: definitions.cc:5
INDEX_TYPE Index
For long integer indexing:
Definition: definitions.hh:39
Log & log
Definition: settings.cc:139