23 #ifndef COM_DAFER45_TBTK_ARRAY
24 #define COM_DAFER45_TBTK_ARRAY
28 #include "TBTK/MultiCounter.h"
39 template<
typename DataType>
40 class ArrayAlgorithms;
97 template<
typename DataType>
108 explicit Array(
const std::initializer_list<unsigned int> &ranges);
116 const std::initializer_list<unsigned int> &ranges,
117 const DataType &fillValue
123 Array(
const std::vector<DataType> &vector);
128 Array(
const std::vector<std::vector<DataType>> &vector);
146 Array(
const std::string &serialization,
Mode mode);
154 static Array create(
const std::vector<unsigned int> &ranges);
164 const std::vector<unsigned int> &ranges,
165 const DataType &fillValue
173 template<
typename CastType>
182 DataType&
operator[](
const std::vector<unsigned int> &index);
191 const std::vector<unsigned int> &index
212 const DataType&
operator[](
unsigned int n)
const;
251 for(
unsigned int n = 0; n < rhs.
getSize(); n++)
252 result.data[n] = lhs*rhs.data[n];
347 const std::vector<Subindex> &pattern0,
349 const std::vector<Subindex> &pattern1
377 const std::vector<unsigned int> &permutation
388 const std::vector<unsigned int>&
getRanges()
const;
391 template<
typename DT>
393 std::ostream &stream,
422 std::vector<unsigned int> ranges;
427 const std::vector<Subindex> &index,
428 unsigned int subindex,
429 unsigned int offsetSlice,
430 unsigned int offsetOriginal
434 void assertCompatibleRanges(
436 std::string functionName
443 template<
typename DataType>
447 template<
typename DataType>
449 this->ranges = ranges;
450 unsigned int size = 1;
451 for(
unsigned int n = 0; n < this->ranges.size(); n++){
456 "'ranges' must only contain positive numbers."
458 size *= this->ranges[n];
464 template<
typename DataType>
466 const std::initializer_list<unsigned int> &ranges,
467 const DataType &fillValue
469 this->ranges = ranges;
470 unsigned int size = 1;
471 for(
unsigned int n = 0; n < this->ranges.size(); n++){
476 "'ranges' must only contain positive numbers."
478 size *= this->ranges[n];
483 for(
unsigned int n = 0; n < size; n++)
487 template<
typename DataType>
493 "Unable to create an Array from an empty vector."
496 ranges.push_back(vector.size());
498 for(
unsigned int n = 0; n < ranges[0]; n++)
502 template<
typename DataType>
507 "Invalid input. Unable to create an Array from an empty"
512 vector[0].size() != 0,
514 "Invalid input. Unable to create an Array from a vector with"
518 ranges.push_back(vector.size());
519 ranges.push_back(vector[0].size());
521 for(
unsigned int n = 1; n < vector.size(); n++){
523 vector[n].size() == vector[0].size(),
525 "Invalid input. vector[" << n <<
"] has a different"
526 <<
" size than vector[0]",
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];
537 template<
typename DataType>
542 data[n] = (DataType)range[n];
545 template<
typename DataType>
548 validate(serialization,
"Array", mode),
550 "Unable to parse string as Array '" << serialization <<
"'.",
559 = nlohmann::json::parse(serialization);
561 ranges = j.at(
"ranges").get<std::vector<unsigned int>>();
563 catch(nlohmann::json::exception &e){
566 "Unable to parse string as Array '"
567 << serialization <<
"'.",
577 "Unable to parse string as Array '" << serialization
584 template<
typename DataType>
586 const std::vector<unsigned int> &ranges
589 array.ranges = ranges;
590 unsigned int size = 1;
591 for(
unsigned int n = 0; n < array.ranges.size(); n++){
596 "'ranges' must only contain positive numbers."
598 size *= array.ranges[n];
606 template<
typename DataType>
608 const std::vector<unsigned int> &ranges,
609 const DataType &fillValue
612 array.ranges = ranges;
613 unsigned int size = 1;
614 for(
unsigned int n = 0; n < array.ranges.size(); n++){
619 "'ranges' must only contain positive numbers."
621 size *= array.ranges[n];
626 for(
unsigned int n = 0; n < size; n++)
627 array.data[n] = fillValue;
632 template<
typename DataType>
633 template<
typename CastType>
637 for(
unsigned int n = 0; n < data.getSize(); n++)
638 resultData[n] = (CastType)data[n];
643 template<
typename DataType>
645 const std::vector<unsigned int> &index
647 unsigned int idx = 0;
648 for(
unsigned int n = 0; n < index.size(); n++){
657 template<
typename DataType>
659 const std::vector<unsigned int> &index
661 unsigned int idx = 0;
662 for(
unsigned int n = 0; n < index.size(); n++){
671 template<
typename DataType>
676 template<
typename DataType>
681 template<
typename DataType>
685 assertCompatibleRanges(rhs,
"operator+()");
688 for(
unsigned int n = 0; n < data.getSize(); n++)
689 result.data[n] = data[n] + rhs.data[n];
694 template<
typename DataType>
698 assertCompatibleRanges(rhs,
"operator+()");
701 for(
unsigned int n = 0; n < data.getSize(); n++)
702 result.data[n] = data[n] - rhs.data[n];
707 template<
typename DataType>
712 for(
unsigned int n = 0; n < data.getSize(); n++)
713 result.data[n] = data[n]*rhs;
718 template<
typename DataType>
720 switch(ranges.size()){
722 switch(rhs.ranges.size()){
735 {IDX_ALL_(0), IDX_ALL}
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() <<
"'.",
748 switch(rhs.ranges.size()){
752 {IDX_ALL, IDX_ALL_(0)},
759 {IDX_ALL, IDX_ALL_(0)},
761 {IDX_ALL_(0), IDX_ALL}
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() <<
"'.",
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()
785 template<
typename DataType>
788 for(
unsigned int n = 0; n < data.getSize(); n++)
789 result.data[n] = data[n]/rhs;
794 template<
typename DataType>
796 if(ranges.size() != rhs.ranges.size())
798 for(
unsigned int n = 0; n < ranges.size(); n++)
799 if(ranges[n] != rhs.ranges[n])
802 for(
unsigned int n = 0; n < getSize(); n++)
803 if(data[n] != rhs.data[n])
809 template<
typename DataType>
812 const std::vector<Subindex> &pattern0,
814 const std::vector<Subindex> &pattern1
816 const std::vector<unsigned int> &ranges0 = array0.
getRanges();
817 const std::vector<unsigned int> &ranges1 = array1.
getRanges();
819 ranges0.size() == pattern0.size(),
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.",
829 ranges1.size() == pattern1.size(),
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.",
838 for(
unsigned int n = 0; n < pattern0.size(); n++){
840 pattern0[n].isWildcard()
841 || pattern0[n].isLabeledWildcard(),
843 "Invalid pattern. The patterns must only contain"
844 " wildcards or labeled wildcards, but found '"
845 << pattern0[n] <<
"' in position '" << n <<
"' of"
850 for(
unsigned int n = 0; n < pattern1.size(); n++){
852 pattern1[n].isWildcard()
853 || pattern1[n].isLabeledWildcard(),
855 "Invalid pattern. The patterns must only contain"
856 " wildcards or labeled wildcards, but found '"
857 << pattern1[n] <<
"' in position '" << n <<
"' of"
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]);
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]);
881 wildcards0.size() == wildcards1.size(),
883 "Incompatible patterns. The number of labeled wildcards are"
884 <<
" different in 'pattern0' and 'pattern1'.",
887 for(
unsigned int n = 0; n < wildcards0.size(); n++){
888 for(
unsigned int c = n+1; c < wildcards0.size(); c++){
890 wildcards0[n] != wildcards0[c],
892 "Repeated labeled wildcard in 'pattern0'",
897 for(
unsigned int n = 0; n < wildcards1.size(); n++){
898 for(
unsigned int c = n+1; c < wildcards1.size(); c++){
900 wildcards1[n] != wildcards1[c],
902 "Repeated labeled wildcard in 'pattern1'",
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(
919 summationIndicesMap.size() == n + 1,
921 "Incompatible patterns. The labeled wildcard at"
922 <<
" position '" << summationIndices0[n] <<
" in"
923 <<
" 'pattern0' is missing in 'pattern1'.",
928 std::vector<unsigned int> summationRanges;
929 for(
unsigned int n = 0; n < summationIndices0.size(); n++){
931 ranges0[summationIndices0[n]]
932 == ranges1[summationIndicesMap[n]],
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.",
941 summationRanges.push_back(ranges0[summationIndices0[n]]);
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]);
953 if(resultRanges.size() == 0){
954 result =
Array({1}, 0);
956 std::vector<unsigned int> summationInitialValues(
957 summationRanges.size(),
960 std::vector<unsigned int> summationIncrements(
961 summationRanges.size(),
965 summationInitialValues,
970 summationCounter.
reset();
971 !summationCounter.
done();
974 std::vector<unsigned int> index0(
977 std::vector<unsigned int> index1(
982 n < summationCounter.
getSize();
985 index0[summationIndices0[n]]
986 = summationCounter[n];
987 index1[summationIndicesMap[n]]
988 = summationCounter[n];
990 result[{0}] += array0[index0]*array1[index1];
996 std::vector<unsigned int> resultInitialValues(
1000 std::vector<unsigned int> resultIncrements(
1001 resultRanges.size(),
1005 resultInitialValues,
1010 std::vector<unsigned int> summationInitialValues(
1011 summationRanges.size(),
1014 std::vector<unsigned int> summationIncrements(
1015 summationRanges.size(),
1019 summationInitialValues,
1023 for(resultCounter.
reset(); !resultCounter.
done(); ++resultCounter){
1024 std::vector<unsigned int> resultIndex
1025 = (std::vector<unsigned int>)resultCounter;
1027 summationCounter.
reset();
1028 !summationCounter.
done();
1031 std::vector<unsigned int> index0(
1032 resultIndex.begin(),
1033 resultIndex.begin() + ranges0.size()
1034 - summationIndices0.size()
1036 std::vector<unsigned int> index1(
1037 resultIndex.begin() + ranges0.size()
1038 - summationIndices0.size(),
1043 n < summationCounter.
getSize();
1047 index1.begin() + summationIndices1[n],
1053 n < summationCounter.
getSize();
1057 index0.begin() + summationIndices0[n],
1060 index1[summationIndicesMap[n]]
1061 = summationCounter[n];
1063 result[resultCounter] += array0[index0]*array1[index1];
1071 template<
typename DataType>
1074 ranges.size() == index.size(),
1075 "Array::getSlice()",
1076 "Incompatible ranges.",
1077 "'index' must have the same number of dimensions as 'ranges'."
1080 std::vector<unsigned int> newRanges;
1081 for(
unsigned int n = 0; n < ranges.size(); n++){
1083 index[n] < (
int)ranges[n],
1084 "Array::getSlice()",
1085 "'index' out of range.",
1090 index[n].isWildcard(),
1091 "Array::getSlice()",
1093 "'index' can only contain positive numbers or"
1096 newRanges.push_back(ranges[n]);
1102 fillSlice(array, index, 0, 0, 0);
1107 template<
typename DataType>
1109 const std::vector<unsigned int> &permutation
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() <<
"'.",
1120 std::vector<bool> indexIncluded(permutation.size(),
false);
1121 for(
unsigned int n = 0; n < permutation.size(); n++){
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"
1132 indexIncluded[permutation[n]] =
true;
1134 for(
unsigned int n = 0; n < indexIncluded.size(); n++){
1137 "Array::getArrayWithPermutedIndices()",
1138 "Invalid permutation. Missing permutation index '" << n
1144 std::vector<unsigned int> newRanges;
1145 for(
unsigned int n = 0; n < ranges.size(); n++)
1146 newRanges.push_back(ranges[permutation[n]]);
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++){
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];
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);
1174 return getArrayWithPermutedIndices(permutation);
1177 template<
typename DataType>
1180 const std::vector<Subindex> &index,
1181 unsigned int subindex,
1182 unsigned int offsetSlice,
1183 unsigned int offsetOriginal
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]
1190 offsetOriginal*ranges[subindex]
1196 array.data[offsetSlice] = data[
1197 offsetOriginal*ranges[subindex]
1203 if(index[subindex].isWildcard()){
1204 for(
unsigned int n = 0; n < ranges[subindex]; n++){
1209 offsetSlice*ranges[subindex] + n,
1210 offsetOriginal*ranges[subindex] + n
1220 offsetOriginal*ranges[subindex]
1227 template<
typename DataType>
1232 template<
typename DataType>
1234 std::ostream &stream,
1237 switch(array.ranges.size()){
1240 for(
unsigned int n = 0; n < array.ranges[0]; n++){
1243 stream << array[{n}];
1250 for(
unsigned int row = 0; row < array.ranges[0]; row++){
1255 unsigned int column = 0;
1256 column < array.ranges[1];
1261 stream << array[{row, column}];
1270 "Array::operator<<()",
1271 "Unable to print Array of rank '"
1272 << array.ranges.size() <<
"'.",
1280 template<
typename DataType>
1285 template<
typename DataType>
1290 template<
typename DataType>
1292 return data.getSize();
1295 template<
typename DataType>
1302 j[
"data"] = data.serialize(mode);
1303 j[
"ranges"] = ranges;
1309 "Array::serialize()",
1310 "Only Serializable::Mode::JSON is supported yet.",
1316 template<
typename DataType>
1319 std::string functionName
1322 ranges.size() == array.ranges.size(),
1323 "Array::" + functionName,
1324 "Incompatible ranges.",
1325 "Left and right hand sides must have the same number of"
1328 for(
unsigned int n = 0; n < ranges.size(); n++){
1330 ranges[n] == array.ranges[n],
1331 "Array::" + functionName,
1332 "Incompatible ranges.",
1333 "Left and right hand sides must have the same ranges."