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