TBTK
Need a break? Support the development by playing Polarity Puzzles
Array.h
Go to the documentation of this file.
1 /* Copyright 2017 Kristofer Björnson
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
23 #ifndef COM_DAFER45_TBTK_ARRAY
24 #define COM_DAFER45_TBTK_ARRAY
25 
26 #include "TBTK/CArray.h"
27 #include "TBTK/Index.h"
28 #include "TBTK/MultiCounter.h"
29 #include "TBTK/Range.h"
30 #include "TBTK/Serializable.h"
31 #include "TBTK/TBTKMacros.h"
32 
33 #include <vector>
34 
35 namespace TBTK{
36 
37 //Forward declation
38 namespace Math{
39  template<typename DataType>
40  class ArrayAlgorithms;
41 }; //End of namespace Math
42 
97 template<typename DataType>
98 class Array : public Serializable{
99 public:
100  //TBTKFeature Utilities.Array.construction.1 2019-10-31
102  Array();
103 
104  //TBTKFeature Utilities.Array.construction.2 2019-10-31
108  explicit Array(const std::initializer_list<unsigned int> &ranges);
109 
110  //TBTKFeature Utilities.Array.construction.3 2019-10-31
115  Array(
116  const std::initializer_list<unsigned int> &ranges,
117  const DataType &fillValue
118  );
119 
123  Array(const std::vector<DataType> &vector);
124 
128  Array(const std::vector<std::vector<DataType>> &vector);
129 
138  Array(const Range &range);
139 
146  Array(const std::string &serialization, Mode mode);
147 
154  static Array create(const std::vector<unsigned int> &ranges);
155 
163  static Array create(
164  const std::vector<unsigned int> &ranges,
165  const DataType &fillValue
166  );
167 
173  template<typename CastType>
174  operator Array<CastType>() const;
175 
176  //TBTKFeature Utilities.Array.operatorArraySubscript.1 2019-10-31
182  DataType& operator[](const std::vector<unsigned int> &index);
183 
184  //TBTKFeature Utilities.Array.operatorArraySubscript.2 2019-10-31
190  const DataType& operator[](
191  const std::vector<unsigned int> &index
192  ) const;
193 
194  //TBTKFeature Utilities.Array.operatorArraySubscript.3 2019-10-31
202  DataType& operator[](unsigned int n);
203 
204  //TBTKFeature Utilities.Array.opreatorArraySubscript.4 2019-10-31
212  const DataType& operator[](unsigned int n) const;
213 
214  //TBTKFeature Utilities.Array.operatorAddition.1 2019-10-31
215  //TBTKFeature Utilities.Array.operatorAddition.2 2019-10-31
216  //TBTKFeature Utilities.Array.operatorAddition.3 2019-10-31
222  Array operator+(const Array &rhs) const;
223 
224  //TBTKFeature Utilities.Array.operatorSubtraction.1 2019-10-31
225  //TBTKFeature Utilities.Array.operatorSubtraction.2 2019-10-31
226  //TBTKFeature Utilities.Array.operatorSubtraction.3 2019-10-31
232  Array operator-(const Array &rhs) const;
233 
234  //TBTKFeature Utilities.Array.operatorMultiplication.1 2019-10-31
240  Array operator*(const DataType &rhs) const;
241 
242  //TBTKFeature Utilities.Array.operatorMultiplication.2 2019-10-31
249  friend Array operator*(const DataType &lhs, const Array &rhs){
250  Array<DataType> result = Array<DataType>::create(rhs.ranges);
251  for(unsigned int n = 0; n < rhs.getSize(); n++)
252  result.data[n] = lhs*rhs.data[n];
253 
254  return result;
255  }
256 
291  Array operator*(const Array &rhs) const;
292 
293  //TBTKFeature Utilities.Array.operatorDivision.1 2019-10-31
299  Array operator/(const DataType &rhs) const;
300 
307  bool operator==(const Array &rhs) const;
308 
345  static Array contract(
346  const Array &array0,
347  const std::vector<Subindex> &pattern0,
348  const Array &array1,
349  const std::vector<Subindex> &pattern1
350  );
351 
352  //TBTKFeature Utilities.Array.getSlice.1
367  Array<DataType> getSlice(const std::vector<Subindex> &index) const;
368 
377  const std::vector<unsigned int> &permutation
378  ) const;
379 
384 
388  const std::vector<unsigned int>& getRanges() const;
389 
391  template<typename DT>
392  friend std::ostream& operator<<(
393  std::ostream &stream,
394  const Array<DT> &array
395  );
396 
397  //TBTKFeature Utilities.Array.getData.1 2019-10-31
403 
404  //TBTKFeature Utilities.Array.getData.2.C++ 2019-10-31
409  const CArray<DataType>& getData() const;
410 
411  //TBTKFeature Utilities.Array.getSize.1 2019-10-31
413  unsigned int getSize() const;
414 
416  std::string serialize(Mode mode) const;
417 private:
419  CArray<DataType> data;
420 
422  std::vector<unsigned int> ranges;
423 
425  void fillSlice(
426  Array &array,
427  const std::vector<Subindex> &index,
428  unsigned int subindex,
429  unsigned int offsetSlice,
430  unsigned int offsetOriginal
431  ) const;
432 
434  void assertCompatibleRanges(
435  const Array &array,
436  std::string functionName
437  ) const;
438 
440  friend class Math::ArrayAlgorithms<DataType>;
441 };
442 
443 template<typename DataType>
445 }
446 
447 template<typename DataType>
448 Array<DataType>::Array(const std::initializer_list<unsigned int> &ranges){
449  this->ranges = ranges;
450  unsigned int size = 1;
451  for(unsigned int n = 0; n < this->ranges.size(); n++){
452  TBTKAssert(
453  this->ranges[n] > 0,
454  "Array::Array()",
455  "Invalid ranges.",
456  "'ranges' must only contain positive numbers."
457  );
458  size *= this->ranges[n];
459  }
460 
461  data = CArray<DataType>(size);
462 }
463 
464 template<typename DataType>
466  const std::initializer_list<unsigned int> &ranges,
467  const DataType &fillValue
468 ){
469  this->ranges = ranges;
470  unsigned int size = 1;
471  for(unsigned int n = 0; n < this->ranges.size(); n++){
472  TBTKAssert(
473  this->ranges[n] > 0,
474  "Array::Array()",
475  "Invalid ranges.",
476  "'ranges' must only contain positive numbers."
477  );
478  size *= this->ranges[n];
479  }
480 
481  data = CArray<DataType>(size);
482 
483  for(unsigned int n = 0; n < size; n++)
484  data[n] = fillValue;
485 }
486 
487 template<typename DataType>
488 Array<DataType>::Array(const std::vector<DataType> &vector){
489  TBTKAssert(
490  vector.size() != 0,
491  "Array::Array()",
492  "Invalid input.",
493  "Unable to create an Array from an empty vector."
494  );
495 
496  ranges.push_back(vector.size());
497  data = CArray<DataType>(ranges[0]);
498  for(unsigned int n = 0; n < ranges[0]; n++)
499  data[n] = vector[n];
500 }
501 
502 template<typename DataType>
503 Array<DataType>::Array(const std::vector<std::vector<DataType>> &vector){
504  TBTKAssert(
505  vector.size() != 0,
506  "Array::Array()",
507  "Invalid input. Unable to create an Array from an empty"
508  << " vector.",
509  ""
510  );
511  TBTKAssert(
512  vector[0].size() != 0,
513  "Array::Array()",
514  "Invalid input. Unable to create an Array from a vector with"
515  << " an empty row.",
516  ""
517  );
518  ranges.push_back(vector.size());
519  ranges.push_back(vector[0].size());
520 
521  for(unsigned int n = 1; n < vector.size(); n++){
522  TBTKAssert(
523  vector[n].size() == vector[0].size(),
524  "Array::Array()",
525  "Invalid input. vector[" << n << "] has a different"
526  << " size than vector[0]",
527  ""
528  );
529  }
530 
531  data = CArray<DataType>(ranges[0]*ranges[1]);
532  for(unsigned int x = 0; x < ranges[0]; x++)
533  for(unsigned int y = 0; y < ranges[1]; y++)
534  data[ranges[1]*x + y] = vector[x][y];
535 }
536 
537 template<typename DataType>
539  ranges.push_back(range.getResolution());
540  data = CArray<DataType>(range.getResolution());
541  for(unsigned int n = 0; n < range.getResolution(); n++)
542  data[n] = (DataType)range[n];
543 }
544 
545 template<typename DataType>
546 Array<DataType>::Array(const std::string &serialization, Mode mode){
547  TBTKAssert(
548  validate(serialization, "Array", mode),
549  "Array::Array()",
550  "Unable to parse string as Array '" << serialization << "'.",
551  ""
552  );
553 
554  switch(mode){
555  case Mode::JSON:
556  {
557  try{
558  nlohmann::json j
559  = nlohmann::json::parse(serialization);
560  data = CArray<DataType>(j.at("data"), mode);
561  ranges = j.at("ranges").get<std::vector<unsigned int>>();
562  }
563  catch(nlohmann::json::exception &e){
564  TBTKExit(
565  "Array::Array()",
566  "Unable to parse string as Array '"
567  << serialization << "'.",
568  ""
569  );
570  }
571 
572  break;
573  }
574  default:
575  TBTKExit(
576  "Array::Array()",
577  "Unable to parse string as Array '" << serialization
578  << "'.",
579  ""
580  );
581  }
582 }
583 
584 template<typename DataType>
586  const std::vector<unsigned int> &ranges
587 ){
588  Array<DataType> array;
589  array.ranges = ranges;
590  unsigned int size = 1;
591  for(unsigned int n = 0; n < array.ranges.size(); n++){
592  TBTKAssert(
593  array.ranges[n] > 0,
594  "Array::Array()",
595  "Invalid ranges.",
596  "'ranges' must only contain positive numbers."
597  );
598  size *= array.ranges[n];
599  }
600 
601  array.data = CArray<DataType>(size);
602 
603  return array;
604 }
605 
606 template<typename DataType>
608  const std::vector<unsigned int> &ranges,
609  const DataType &fillValue
610 ){
611  Array<DataType> array;
612  array.ranges = ranges;
613  unsigned int size = 1;
614  for(unsigned int n = 0; n < array.ranges.size(); n++){
615  TBTKAssert(
616  array.ranges[n] > 0,
617  "Array::Array()",
618  "Invalid ranges.",
619  "'ranges' must only contain positive numbers."
620  );
621  size *= array.ranges[n];
622  }
623 
624  array.data = CArray<DataType>(size);
625 
626  for(unsigned int n = 0; n < size; n++)
627  array.data[n] = fillValue;
628 
629  return array;
630 }
631 
632 template<typename DataType>
633 template<typename CastType>
635  Array<CastType> result = Array<CastType>::create(ranges);
636  CArray<CastType> &resultData = result.getData();
637  for(unsigned int n = 0; n < data.getSize(); n++)
638  resultData[n] = (CastType)data[n];
639 
640  return result;
641 }
642 
643 template<typename DataType>
645  const std::vector<unsigned int> &index
646 ){
647  unsigned int idx = 0;
648  for(unsigned int n = 0; n < index.size(); n++){
649  if(n != 0)
650  idx *= ranges[n];
651  idx += index[n];
652  }
653 
654  return data[idx];
655 }
656 
657 template<typename DataType>
658 inline const DataType& Array<DataType>::operator[](
659  const std::vector<unsigned int> &index
660 ) const{
661  unsigned int idx = 0;
662  for(unsigned int n = 0; n < index.size(); n++){
663  if(n != 0)
664  idx *= ranges[n];
665  idx += index[n];
666  }
667 
668  return data[idx];
669 }
670 
671 template<typename DataType>
672 inline DataType& Array<DataType>::operator[](unsigned int n){
673  return data[n];
674 }
675 
676 template<typename DataType>
677 inline const DataType& Array<DataType>::operator[](unsigned int n) const{
678  return data[n];
679 }
680 
681 template<typename DataType>
683  const Array<DataType> &rhs
684 ) const{
685  assertCompatibleRanges(rhs, "operator+()");
686 
687  Array<DataType> result = Array<DataType>::create(ranges);
688  for(unsigned int n = 0; n < data.getSize(); n++)
689  result.data[n] = data[n] + rhs.data[n];
690 
691  return result;
692 }
693 
694 template<typename DataType>
696  const Array<DataType> &rhs
697 ) const{
698  assertCompatibleRanges(rhs, "operator+()");
699 
700  Array<DataType> result = Array<DataType>::create(ranges);
701  for(unsigned int n = 0; n < data.getSize(); n++)
702  result.data[n] = data[n] - rhs.data[n];
703 
704  return result;
705 }
706 
707 template<typename DataType>
709  const DataType &rhs
710 ) const{
711  Array<DataType> result = Array<DataType>::create(ranges);
712  for(unsigned int n = 0; n < data.getSize(); n++)
713  result.data[n] = data[n]*rhs;
714 
715  return result;
716 }
717 
718 template<typename DataType>
720  switch(ranges.size()){
721  case 1:
722  switch(rhs.ranges.size()){
723  case 1:
724  return contract(
725  *this,
726  {IDX_ALL_(0)},
727  rhs,
728  {IDX_ALL_(0)}
729  );
730  case 2:
731  return contract(
732  *this,
733  {IDX_ALL_(0)},
734  rhs,
735  {IDX_ALL_(0), IDX_ALL}
736  );
737  default:
738  TBTKExit(
739  "Array::operator*()",
740  "Unsupported Array rank. Multiplication is"
741  << " only possible for Arrays of rank one or"
742  << " two, but the left hand side has rank '"
743  << ranges.size() << "'.",
744  ""
745  );
746  }
747  case 2:
748  switch(rhs.ranges.size()){
749  case 1:
750  return contract(
751  *this,
752  {IDX_ALL, IDX_ALL_(0)},
753  rhs,
754  {IDX_ALL_(0)}
755  );
756  case 2:
757  return contract(
758  *this,
759  {IDX_ALL, IDX_ALL_(0)},
760  rhs,
761  {IDX_ALL_(0), IDX_ALL}
762  );
763  default:
764  TBTKExit(
765  "Array::operator*()",
766  "Unsupported Array rank. Multiplication is"
767  << " only possible for Arrays of rank one or"
768  << " two, but the left hand side has rank '"
769  << ranges.size() << "'.",
770  ""
771  );
772  }
773  default:
774  TBTKExit(
775  "Array::operator*()",
776  "Unsupported Array rank. Multiplication is only"
777  << " possible for Arrays of rank one or two, but the"
778  << " left hand side has rank '" << ranges.size()
779  << "'.",
780  ""
781  );
782  }
783 }
784 
785 template<typename DataType>
786 inline Array<DataType> Array<DataType>::operator/(const DataType &rhs) const{
787  Array<DataType> result = Array<DataType>::create(ranges);
788  for(unsigned int n = 0; n < data.getSize(); n++)
789  result.data[n] = data[n]/rhs;
790 
791  return result;
792 }
793 
794 template<typename DataType>
795 inline bool Array<DataType>::operator==(const Array<DataType> &rhs) const{
796  if(ranges.size() != rhs.ranges.size())
797  return false;
798  for(unsigned int n = 0; n < ranges.size(); n++)
799  if(ranges[n] != rhs.ranges[n])
800  return false;
801 
802  for(unsigned int n = 0; n < getSize(); n++)
803  if(data[n] != rhs.data[n])
804  return false;
805 
806  return true;
807 }
808 
809 template<typename DataType>
811  const Array &array0,
812  const std::vector<Subindex> &pattern0,
813  const Array &array1,
814  const std::vector<Subindex> &pattern1
815 ){
816  const std::vector<unsigned int> &ranges0 = array0.getRanges();
817  const std::vector<unsigned int> &ranges1 = array1.getRanges();
818  TBTKAssert(
819  ranges0.size() == pattern0.size(),
820  "Array::contract()",
821  "Incompatible pattern size. The number of elements in"
822  << " 'pattern0' must be the same as the number of ranges in"
823  << " 'array0', but 'pattern0' has '" << pattern0.size() << "'"
824  << " elements while 'array0' has '"
825  << ranges0.size() << "' ranges.",
826  ""
827  );
828  TBTKAssert(
829  ranges1.size() == pattern1.size(),
830  "Array::contract()",
831  "Incompatible pattern size. The number of elements in"
832  << " 'pattern1' must be the same as the number of ranges in"
833  << " 'array1', but 'pattern1' has '" << pattern1.size() << "'"
834  << " elements while 'array1' has '"
835  << ranges1.size() << "' ranges.",
836  ""
837  );
838  for(unsigned int n = 0; n < pattern0.size(); n++){
839  TBTKAssert(
840  pattern0[n].isWildcard()
841  || pattern0[n].isLabeledWildcard(),
842  "Array::contract()",
843  "Invalid pattern. The patterns must only contain"
844  " wildcards or labeled wildcards, but found '"
845  << pattern0[n] << "' in position '" << n << "' of"
846  << " 'pattern0'.",
847  ""
848  );
849  }
850  for(unsigned int n = 0; n < pattern1.size(); n++){
851  TBTKAssert(
852  pattern1[n].isWildcard()
853  || pattern1[n].isLabeledWildcard(),
854  "Array::contract()",
855  "Invalid pattern. The patterns must only contain"
856  " wildcards or labeled wildcards, but found '"
857  << pattern1[n] << "' in position '" << n << "' of"
858  << " 'pattern1'.",
859  ""
860  );
861  }
862 
863  std::vector<unsigned int> summationIndices0;
864  std::vector<Subindex> wildcards0;
865  for(unsigned int n = 0; n < pattern0.size(); n++){
866  if(pattern0[n].isLabeledWildcard()){
867  summationIndices0.push_back(n);
868  wildcards0.push_back(pattern0[n]);
869  }
870  }
871  std::vector<unsigned int> summationIndices1;
872  std::vector<Subindex> wildcards1;
873  for(unsigned int n = 0; n < pattern1.size(); n++){
874  if(pattern1[n].isLabeledWildcard()){
875  summationIndices1.push_back(n);
876  wildcards1.push_back(pattern1[n]);
877  }
878  }
879 
880  TBTKAssert(
881  wildcards0.size() == wildcards1.size(),
882  "Array::contract()",
883  "Incompatible patterns. The number of labeled wildcards are"
884  << " different in 'pattern0' and 'pattern1'.",
885  ""
886  );
887  for(unsigned int n = 0; n < wildcards0.size(); n++){
888  for(unsigned int c = n+1; c < wildcards0.size(); c++){
889  TBTKAssert(
890  wildcards0[n] != wildcards0[c],
891  "Array::contract()",
892  "Repeated labeled wildcard in 'pattern0'",
893  ""
894  );
895  }
896  }
897  for(unsigned int n = 0; n < wildcards1.size(); n++){
898  for(unsigned int c = n+1; c < wildcards1.size(); c++){
899  TBTKAssert(
900  wildcards1[n] != wildcards1[c],
901  "Array::contract()",
902  "Repeated labeled wildcard in 'pattern1'",
903  ""
904  );
905  }
906  }
907 
908  std::vector<unsigned int> summationIndicesMap;
909  for(unsigned int n = 0; n < wildcards0.size(); n++){
910  for(unsigned int c = 0; c < wildcards1.size(); c++){
911  if(wildcards0[n] == wildcards1[c]){
912  summationIndicesMap.push_back(
913  summationIndices1[c]
914  );
915  break;
916  }
917  }
918  TBTKAssert(
919  summationIndicesMap.size() == n + 1,
920  "Array::contract()",
921  "Incompatible patterns. The labeled wildcard at"
922  << " position '" << summationIndices0[n] << " in"
923  << " 'pattern0' is missing in 'pattern1'.",
924  ""
925  );
926  }
927 
928  std::vector<unsigned int> summationRanges;
929  for(unsigned int n = 0; n < summationIndices0.size(); n++){
930  TBTKAssert(
931  ranges0[summationIndices0[n]]
932  == ranges1[summationIndicesMap[n]],
933  "Array::contract()",
934  "Incompatible summation indices. Unable to contract"
935  << " the Subindex at position '"
936  << summationIndices0[n] << "' in 'array0' with the"
937  << " Subindex at position '" << summationIndicesMap[n]
938  << "' in 'array1' since they have different range.",
939  ""
940  );
941  summationRanges.push_back(ranges0[summationIndices0[n]]);
942  }
943 
944  std::vector<unsigned int> resultRanges;
945  for(unsigned int n = 0; n < ranges0.size(); n++)
946  if(pattern0[n].isWildcard())
947  resultRanges.push_back(ranges0[n]);
948  for(unsigned int n = 0; n < ranges1.size(); n++)
949  if(pattern1[n].isWildcard())
950  resultRanges.push_back(ranges1[n]);
951 
952  Array result;
953  if(resultRanges.size() == 0){
954  result = Array({1}, 0);
955 
956  std::vector<unsigned int> summationInitialValues(
957  summationRanges.size(),
958  0
959  );
960  std::vector<unsigned int> summationIncrements(
961  summationRanges.size(),
962  1
963  );
964  MultiCounter<unsigned int> summationCounter(
965  summationInitialValues,
966  summationRanges,
967  summationIncrements
968  );
969  for(
970  summationCounter.reset();
971  !summationCounter.done();
972  ++summationCounter
973  ){
974  std::vector<unsigned int> index0(
975  summationCounter.getSize()
976  );
977  std::vector<unsigned int> index1(
978  summationCounter.getSize()
979  );
980  for(
981  unsigned int n = 0;
982  n < summationCounter.getSize();
983  n++
984  ){
985  index0[summationIndices0[n]]
986  = summationCounter[n];
987  index1[summationIndicesMap[n]]
988  = summationCounter[n];
989  }
990  result[{0}] += array0[index0]*array1[index1];
991  }
992  }
993  else{
994  result = Array::create(resultRanges, 0);
995 
996  std::vector<unsigned int> resultInitialValues(
997  resultRanges.size(),
998  0
999  );
1000  std::vector<unsigned int> resultIncrements(
1001  resultRanges.size(),
1002  1
1003  );
1004  MultiCounter<unsigned int> resultCounter(
1005  resultInitialValues,
1006  resultRanges,
1007  resultIncrements
1008  );
1009 
1010  std::vector<unsigned int> summationInitialValues(
1011  summationRanges.size(),
1012  0
1013  );
1014  std::vector<unsigned int> summationIncrements(
1015  summationRanges.size(),
1016  1
1017  );
1018  MultiCounter<unsigned int> summationCounter(
1019  summationInitialValues,
1020  summationRanges,
1021  summationIncrements
1022  );
1023  for(resultCounter.reset(); !resultCounter.done(); ++resultCounter){
1024  std::vector<unsigned int> resultIndex
1025  = (std::vector<unsigned int>)resultCounter;
1026  for(
1027  summationCounter.reset();
1028  !summationCounter.done();
1029  ++summationCounter
1030  ){
1031  std::vector<unsigned int> index0(
1032  resultIndex.begin(),
1033  resultIndex.begin() + ranges0.size()
1034  - summationIndices0.size()
1035  );
1036  std::vector<unsigned int> index1(
1037  resultIndex.begin() + ranges0.size()
1038  - summationIndices0.size(),
1039  resultIndex.end()
1040  );
1041  for(
1042  unsigned int n = 0;
1043  n < summationCounter.getSize();
1044  n++
1045  ){
1046  index1.insert(
1047  index1.begin() + summationIndices1[n],
1048  0
1049  );
1050  }
1051  for(
1052  unsigned int n = 0;
1053  n < summationCounter.getSize();
1054  n++
1055  ){
1056  index0.insert(
1057  index0.begin() + summationIndices0[n],
1058  summationCounter[n]
1059  );
1060  index1[summationIndicesMap[n]]
1061  = summationCounter[n];
1062  }
1063  result[resultCounter] += array0[index0]*array1[index1];
1064  }
1065  }
1066  }
1067 
1068  return result;
1069 }
1070 
1071 template<typename DataType>
1072 Array<DataType> Array<DataType>::getSlice(const std::vector<Subindex> &index) const{
1073  TBTKAssert(
1074  ranges.size() == index.size(),
1075  "Array::getSlice()",
1076  "Incompatible ranges.",
1077  "'index' must have the same number of dimensions as 'ranges'."
1078  );
1079 
1080  std::vector<unsigned int> newRanges;
1081  for(unsigned int n = 0; n < ranges.size(); n++){
1082  TBTKAssert(
1083  index[n] < (int)ranges[n],
1084  "Array::getSlice()",
1085  "'index' out of range.",
1086  ""
1087  );
1088  if(index[n] < 0){
1089  TBTKAssert(
1090  index[n].isWildcard(),
1091  "Array::getSlice()",
1092  "Invalid symbol.",
1093  "'index' can only contain positive numbers or"
1094  << " 'IDX_ALL'."
1095  );
1096  newRanges.push_back(ranges[n]);
1097  }
1098  }
1099 
1100  Array array = Array::create(newRanges);
1101 
1102  fillSlice(array, index, 0, 0, 0);
1103 
1104  return array;
1105 }
1106 
1107 template<typename DataType>
1109  const std::vector<unsigned int> &permutation
1110 ) const{
1111  TBTKAssert(
1112  permutation.size() == ranges.size(),
1113  "Array::getArrayWithPermutedIndices()",
1114  "The number of permutation indices '" << permutation.size()
1115  << "' must be the same a the number of ranges '"
1116  << ranges.size() << "'.",
1117  ""
1118  );
1119 
1120  std::vector<bool> indexIncluded(permutation.size(), false);
1121  for(unsigned int n = 0; n < permutation.size(); n++){
1122  TBTKAssert(
1123  permutation[n] >= 0
1124  && permutation[n] < permutation.size(),
1125  "Array::getArrayWithPermutedIndices()",
1126  "Invalid permutation values 'permutation[" << n << "]"
1127  << " = " << permutation[n] << "'. Must be a number"
1128  << " between 0 and N-1, where N is the number of"
1129  << " ranges.",
1130  ""
1131  );
1132  indexIncluded[permutation[n]] = true;
1133  }
1134  for(unsigned int n = 0; n < indexIncluded.size(); n++){
1135  TBTKAssert(
1136  indexIncluded[n],
1137  "Array::getArrayWithPermutedIndices()",
1138  "Invalid permutation. Missing permutation index '" << n
1139  << "'.",
1140  ""
1141  );
1142  }
1143 
1144  std::vector<unsigned int> newRanges;
1145  for(unsigned int n = 0; n < ranges.size(); n++)
1146  newRanges.push_back(ranges[permutation[n]]);
1147  Array<DataType> newArray = Array<DataType>::create(newRanges);
1148 
1149  std::vector<unsigned int> begin = newRanges;
1150  std::vector<unsigned int> end = newRanges;
1151  std::vector<unsigned int> increment = newRanges;
1152  for(unsigned int n = 0; n < newRanges.size(); n++){
1153  begin[n] = 0;
1154  increment[n] = 1;
1155  }
1156  MultiCounter<unsigned int> counter(begin, end, increment);
1157  for(counter.reset(); !counter.done(); ++counter){
1158  std::vector<unsigned int> newArrayIndex = counter;
1159  std::vector<unsigned int> arrayIndex(newArrayIndex.size());
1160  for(unsigned int c = 0; c < newArrayIndex.size(); c++)
1161  arrayIndex[permutation[c]] = newArrayIndex[c];
1162  newArray[newArrayIndex] = (*this)[arrayIndex];
1163  }
1164 
1165  return newArray;
1166 }
1167 
1168 template<typename DataType>
1170  std::vector<unsigned int> permutation;
1171  for(unsigned int n = 0; n < ranges.size(); n++)
1172  permutation.push_back(ranges.size() - n - 1);
1173 
1174  return getArrayWithPermutedIndices(permutation);
1175 }
1176 
1177 template<typename DataType>
1179  Array &array,
1180  const std::vector<Subindex> &index,
1181  unsigned int subindex,
1182  unsigned int offsetSlice,
1183  unsigned int offsetOriginal
1184 ) const{
1185  if(subindex == index.size()-1){
1186  if(index[subindex].isWildcard()){
1187  for(unsigned int n = 0; n < ranges[subindex]; n++){
1188  array.data[offsetSlice*ranges[subindex] + n]
1189  = data[
1190  offsetOriginal*ranges[subindex]
1191  + n
1192  ];
1193  }
1194  }
1195  else{
1196  array.data[offsetSlice] = data[
1197  offsetOriginal*ranges[subindex]
1198  + index[subindex]
1199  ];
1200  }
1201  }
1202  else{
1203  if(index[subindex].isWildcard()){
1204  for(unsigned int n = 0; n < ranges[subindex]; n++){
1205  fillSlice(
1206  array,
1207  index,
1208  subindex+1,
1209  offsetSlice*ranges[subindex] + n,
1210  offsetOriginal*ranges[subindex] + n
1211  );
1212  }
1213  }
1214  else{
1215  fillSlice(
1216  array,
1217  index,
1218  subindex+1,
1219  offsetSlice,
1220  offsetOriginal*ranges[subindex]
1221  + index[subindex]
1222  );
1223  }
1224  }
1225 }
1226 
1227 template<typename DataType>
1228 inline const std::vector<unsigned int>& Array<DataType>::getRanges() const{
1229  return ranges;
1230 }
1231 
1232 template<typename DataType>
1233 inline std::ostream& operator<<(
1234  std::ostream &stream,
1235  const Array<DataType> &array
1236 ){
1237  switch(array.ranges.size()){
1238  case 1:
1239  stream << "[";
1240  for(unsigned int n = 0; n < array.ranges[0]; n++){
1241  if(n != 0)
1242  stream << ", ";
1243  stream << array[{n}];
1244  }
1245  stream << "]";
1246 
1247  break;
1248  case 2:
1249  stream << "[";
1250  for(unsigned int row = 0; row < array.ranges[0]; row++){
1251  if(row != 0)
1252  stream << "\n";
1253  stream << "[";
1254  for(
1255  unsigned int column = 0;
1256  column < array.ranges[1];
1257  column++
1258  ){
1259  if(column != 0)
1260  stream << ", ";
1261  stream << array[{row, column}];
1262  }
1263  stream << "]";
1264  }
1265  stream << "]";
1266 
1267  break;
1268  default:
1269  TBTKExit(
1270  "Array::operator<<()",
1271  "Unable to print Array of rank '"
1272  << array.ranges.size() << "'.",
1273  ""
1274  );
1275  }
1276 
1277  return stream;
1278 }
1279 
1280 template<typename DataType>
1282  return data;
1283 }
1284 
1285 template<typename DataType>
1286 inline const CArray<DataType>& Array<DataType>::getData() const{
1287  return data;
1288 }
1289 
1290 template<typename DataType>
1291 inline unsigned int Array<DataType>::getSize() const{
1292  return data.getSize();
1293 }
1294 
1295 template<typename DataType>
1296 inline std::string Array<DataType>::serialize(Mode mode) const{
1297  switch(mode){
1298  case Mode::JSON:
1299  {
1300  nlohmann::json j;
1301  j["id"] = "Array";
1302  j["data"] = data.serialize(mode);
1303  j["ranges"] = ranges;
1304 
1305  return j.dump();
1306  }
1307  default:
1308  TBTKExit(
1309  "Array::serialize()",
1310  "Only Serializable::Mode::JSON is supported yet.",
1311  ""
1312  );
1313  }
1314 }
1315 
1316 template<typename DataType>
1318  const Array<DataType> &array,
1319  std::string functionName
1320 ) const{
1321  TBTKAssert(
1322  ranges.size() == array.ranges.size(),
1323  "Array::" + functionName,
1324  "Incompatible ranges.",
1325  "Left and right hand sides must have the same number of"
1326  << " dimensions."
1327  );
1328  for(unsigned int n = 0; n < ranges.size(); n++){
1329  TBTKAssert(
1330  ranges[n] == array.ranges[n],
1331  "Array::" + functionName,
1332  "Incompatible ranges.",
1333  "Left and right hand sides must have the same ranges."
1334  );
1335  }
1336 }
1337 
1338 }; //End of namesapce TBTK
1339 
1340 #endif
TBTK::Array
Multi-dimensional array.
Definition: Array.h:98
TBTK::Array::operator==
bool operator==(const Array &rhs) const
Definition: Array.h:795
TBTK::Array::operator+
Array operator+(const Array &rhs) const
Definition: Array.h:682
TBTK::Array::getData
CArray< DataType > & getData()
Definition: Array.h:1281
Index.h
Physical index.
TBTK::Array::operator/
Array operator/(const DataType &rhs) const
Definition: Array.h:786
TBTK::CArray
Container for a C style array.
Definition: CArray.h:44
TBTK::Range
One-dimensional range.
Definition: Range.h:52
TBTK::MultiCounter
Helper class for flattening nested loops.
Definition: MultiCounter.h:42
TBTK::MultiCounter::reset
void reset()
Definition: MultiCounter.h:174
TBTK::Array::operator[]
DataType & operator[](const std::vector< unsigned int > &index)
Definition: Array.h:644
TBTK::MultiCounter::getSize
unsigned int getSize() const
Definition: MultiCounter.h:184
TBTK::Array::operator*
friend Array operator*(const DataType &lhs, const Array &rhs)
Definition: Array.h:249
TBTK::Array::serialize
std::string serialize(Mode mode) const
Definition: Array.h:1296
TBTK::Array::operator-
Array operator-(const Array &rhs) const
Definition: Array.h:695
TBTK::Serializable
Definition: Serializable.h:43
Range.h
Helper class for flattening nested looping.
Serializable.h
Abstract base class for serializable objects.
TBTK::Array::getArrayWithPermutedIndices
Array< DataType > getArrayWithPermutedIndices(const std::vector< unsigned int > &permutation) const
Definition: Array.h:1108
TBTK::Array::getSize
unsigned int getSize() const
Definition: Array.h:1291
TBTK::Array::getRanges
const std::vector< unsigned int > & getRanges() const
Definition: Array.h:1228
TBTK::Array::getArrayWithReversedIndices
Array< DataType > getArrayWithReversedIndices() const
Definition: Array.h:1169
TBTK::Array::operator*
Array operator*(const DataType &rhs) const
Definition: Array.h:708
TBTK::Array::operator<<
friend std::ostream & operator<<(std::ostream &stream, const Array< DT > &array)
TBTK::Array::contract
static Array contract(const Array &array0, const std::vector< Subindex > &pattern0, const Array &array1, const std::vector< Subindex > &pattern1)
Definition: Array.h:810
TBTKMacros.h
Precompiler macros.
TBTK::operator<<
std::ostream & operator<<(std::ostream &stream, const HoppingAmplitude &hoppingAmplitude)
Definition: HoppingAmplitude.h:315
TBTK::Range::getResolution
unsigned int getResolution() const
Definition: Range.h:115
TBTK::MultiCounter::done
bool done() const
Definition: MultiCounter.h:179
TBTK::Array::getSlice
Array< DataType > getSlice(const std::vector< Subindex > &index) const
Definition: Array.h:1072
TBTK::Serializable::Mode
Mode
Definition: Serializable.h:47
TBTK::Math::ArrayAlgorithms
Definition: ArrayAlgorithms.h:34
TBTK::Array::create
static Array create(const std::vector< unsigned int > &ranges)
Definition: Array.h:585
CArray.h
Container for a C style array.
TBTK::Array::Array
Array()
Definition: Array.h:444