TBTK
IndexedDataTree.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_INDEXED_DATA_TREE
24 #define COM_DAFER45_TBTK_INDEXED_DATA_TREE
25 
26 #include "TBTK/ElementNotFoundException.h"
27 #include "TBTK/Index.h"
28 #include "TBTK/Serializable.h"
29 #include "TBTK/TBTKMacros.h"
30 
31 #include <complex>
32 #include <sstream>
33 
34 //This is used to work around incompatibilities between nlohmann::json and
35 //CUDA. This effectively forbids instantiation of IndexedDataTree in CUDA code.
36 #ifndef TBTK_DISABLE_NLOHMANN_JSON
37 # include "TBTK/json.hpp"
38 #endif
39 
40 namespace TBTK{
41 
42 template<typename Data, bool isSerializeable = std::is_base_of<Serializable, Data>::value>
44 public:
47 
55  IndexedDataTree(const std::string &serialization, Mode mode);
56 
58  virtual ~IndexedDataTree();
59 
65  void add(const Data &data, const Index &index);
66 
75  bool get(Data &data, const Index &index) const;
76 
85  Data& get(const Index &index);
86 
95  const Data& get(const Index &index) const;
96 
98  void clear();
99 
103  unsigned int getSizeInBytes() const;
104 
110  virtual std::string serialize(Mode mode) const;
111 
112  class Iterator;
113  class ConstIterator;
114 private:
117  template<bool isConstIterator>
118  class _Iterator{
119  public:
122  typedef typename std::conditional<
123  isConstIterator,
124  const Data&,
125  Data&
126  >::type DataReferenceType;
127 
129  void operator++();
130 
132  DataReferenceType operator*();
133 
135  bool operator==(const _Iterator &rhs) const;
136 
138  bool operator!=(const _Iterator &rhs) const;
139 
141  const Index& getCurrentIndex() const;
142  private:
145  typedef typename std::conditional<
146  isConstIterator,
147  const IndexedDataTree*,
148  IndexedDataTree*
149  >::type IndexedDataTreePointerType;
150 
152  IndexedDataTreePointerType indexedDataTree;
153 
155  Index currentIndex;
156 
159  _Iterator(IndexedDataTreePointerType indexedDataTree, bool end = false);
160 
162  friend class Iterator;
163  friend class ConstIterator;
164  };
165 public:
168  class Iterator : public _Iterator<false>{
169  private:
170  Iterator(
171  IndexedDataTree *indexedDataTree,
172  bool end = false
173  ) : _Iterator<false>(indexedDataTree, end){};
174 
176  friend class IndexedDataTree;
177  };
178 
181  class ConstIterator : public _Iterator<true>{
182  private:
184  const IndexedDataTree *indexedDataTree,
185  bool end = false
186  ) : _Iterator<true>(indexedDataTree, end){};
187 
189  friend class IndexedDataTree;
190  };
191 
196  Iterator begin();
197 
202  ConstIterator begin() const;
203 
208  ConstIterator cbegin() const;
209 
213  Iterator end();
214 
218  ConstIterator end() const;
219 
223  ConstIterator cend() const;
224 private:
226  std::vector<IndexedDataTree> children;
227 
230  bool indexIncluded;
231 
235  bool indexSeparator;
236 
238  Data data;
239 
242  void add(const Data &data, const Index& index, unsigned int subindex);
243 
246  bool get(Data &data, const Index& index, unsigned int subindex) const;
247 
250  const Data& get(const Index& index, unsigned int subindex) const;
251 
253  Index getFirstIndex() const;
254 
257  bool getFirstIndex(Index &index) const;
258 
261  Index getNextIndex(const Index &index) const;
262 
266  bool getNextIndex(
267  const Index &currentIndex,
268  Index &nextIndex
269  ) const;
270 };
271 
272 template<typename Data>
273 class IndexedDataTree<Data, true> : public Serializable{
274 public:
276  IndexedDataTree();
277 
280  IndexedDataTree(const std::string &serialization, Mode mode);
281 
283  virtual ~IndexedDataTree();
284 
286  void add(const Data &data, const Index &index);
287 
289  bool get(Data &data, const Index &index) const;
290 
299  Data& get(const Index &index);
300 
309  const Data& get(const Index &index) const;
310 
312  void clear();
313 
315  unsigned int getSizeInBytes() const;
316 
318  virtual std::string serialize(Mode mode) const;
319 
322  class Iterator;
323  class ConstIterator;
324 private:
325  template<bool isConstIterator>
326  class _Iterator{
327  public:
330  typedef typename std::conditional<
331  isConstIterator,
332  const Data&,
333  Data&
334  >::type DataReferenceType;
335 
337  void operator++();
338 
340  DataReferenceType operator*();
341 
343  bool operator==(const _Iterator &rhs) const;
344 
346  bool operator!=(const _Iterator &rhs) const;
347 
349  const Index& getCurrentIndex() const;
350  private:
353  typedef typename std::conditional<
354  isConstIterator,
355  const IndexedDataTree*,
356  IndexedDataTree*
357  >::type IndexedDataTreePointerType;
358 
360  IndexedDataTreePointerType indexedDataTree;
361 
363  Index currentIndex;
364 
367  _Iterator(IndexedDataTreePointerType indexedDataTree, bool end = false);
368 
370  friend class Iterator;
371  friend class ConstIterator;
372  };
373 public:
376  class Iterator : public _Iterator<false>{
377  private:
378  Iterator(
379  IndexedDataTree *indexedDataTree,
380  bool end = false
381  ) : _Iterator<false>(indexedDataTree, end){};
382 
384  friend class IndexedDataTree;
385  };
386 
389  class ConstIterator : public _Iterator<true>{
390  private:
391  ConstIterator(
392  const IndexedDataTree *indexedDataTree,
393  bool end = false
394  ) : _Iterator<true>(indexedDataTree, end){};
395 
397  friend class IndexedDataTree;
398  };
399 
404  Iterator begin();
405 
410  ConstIterator begin() const;
411 
416  ConstIterator cbegin() const;
417 
421  Iterator end();
422 
426  ConstIterator end() const;
427 
431  ConstIterator cend() const;
432 private:
434  std::vector<IndexedDataTree> children;
435 
438  bool indexIncluded;
439 
443  bool indexSeparator;
444 
446  Data data;
447 
450  void add(const Data &data, const Index& index, unsigned int subindex);
451 
454  bool get(Data &data, const Index& index, unsigned int subindex) const;
455 
458  const Data& get(const Index& index, unsigned int subindex) const;
459 
461  Index getFirstIndex() const;
462 
465  bool getFirstIndex(Index &index) const;
466 
469  Index getNextIndex(const Index &index) const;
470 
474  bool getNextIndex(
475  const Index &currentIndex,
476  Index &nextIndex
477  ) const;
478 };
479 
480 template<typename Data>
481 class IndexedDataTree<Data, false> : public Serializable{
482 public:
484  IndexedDataTree();
485 
488  IndexedDataTree(const std::string &serialization, Mode mode);
489 
491  virtual ~IndexedDataTree();
492 
494  void add(const Data &data, const Index &index);
495 
497  bool get(Data &data, const Index &index) const;
498 
507  Data& get(const Index &index);
508 
517  const Data& get(const Index &index) const;
518 
520  void clear();
521 
523  unsigned int getSizeInBytes() const;
524 
526  virtual std::string serialize(Mode mode) const;
527 
530  class Iterator;
531  class ConstIterator;
532 private:
533  template<bool isConstIterator>
534  class _Iterator{
535  public:
538  typedef typename std::conditional<
539  isConstIterator,
540  const Data&,
541  Data&
542  >::type DataReferenceType;
543 
545  void operator++();
546 
548  DataReferenceType operator*();
549 
551  bool operator==(const _Iterator &rhs) const;
552 
554  bool operator!=(const _Iterator &rhs) const;
555 
557  const Index& getCurrentIndex() const;
558  private:
561  typedef typename std::conditional<
562  isConstIterator,
563  const IndexedDataTree*,
564  IndexedDataTree*
565  >::type IndexedDataTreePointerType;
566 
568  IndexedDataTreePointerType indexedDataTree;
569 
571  Index currentIndex;
572 
575  _Iterator(IndexedDataTreePointerType indexedDataTree, bool end = false);
576 
578  friend class Iterator;
579  friend class ConstIterator;
580  };
581 public:
584  class Iterator : public _Iterator<false>{
585  private:
586  Iterator(
587  IndexedDataTree *indexedDataTree,
588  bool end = false
589  ) : _Iterator<false>(indexedDataTree, end){};
590 
592  friend class IndexedDataTree;
593  };
594 
597  class ConstIterator : public _Iterator<true>{
598  private:
599  ConstIterator(
600  const IndexedDataTree *indexedDataTree,
601  bool end = false
602  ) : _Iterator<true>(indexedDataTree, end){};
603 
605  friend class IndexedDataTree;
606  };
607 
612  Iterator begin();
613 
618  ConstIterator begin() const;
619 
624  ConstIterator cbegin() const;
625 
629  Iterator end();
630 
634  ConstIterator end() const;
635 
639  ConstIterator cend() const;
640 private:
642  std::vector<IndexedDataTree> children;
643 
646  bool indexIncluded;
647 
651  bool indexSeparator;
652 
654  Data data;
655 
658  void add(const Data &data, const Index& index, unsigned int subindex);
659 
662  bool get(Data &data, const Index& index, unsigned int subindex) const;
663 
666  const Data& get(const Index& index, unsigned int subindex) const;
667 
670  Index getFirstIndex() const;
671 
675  bool getFirstIndex(Index &index) const;
676 
679  Index getNextIndex(const Index &index) const;
680 
684  bool getNextIndex(
685  const Index &currentIndex,
686  Index &nextIndex
687  ) const;
688 };
689 
690 //This is used to work around incompatibilities between nlohmann::json and
691 //CUDA. This effectively forbids instantiation of IndexedDataTree in CUDA code.
692 #ifndef TBTK_DISABLE_NLOHMANN_JSON
693 
694 template<typename Data, bool isSerializable>
696  indexIncluded = false;
697  indexSeparator = false;
698 }
699 
700 template<typename Data>
702  indexIncluded = false;
703  indexSeparator = false;
704 }
705 
706 template<typename Data>
708  indexIncluded = false;
709  indexSeparator = false;
710 }
711 
712 template<>
714  const std::string &serialization,
715  Mode mode
716 ){
717  TBTKAssert(
718  validate(serialization, "IndexedDataTree", mode),
719  "IndexedDataTree<bool>::IndexedDataTree()",
720  "Unable to parse string as IndexedDataTree<bool> '"
721  << serialization << "'.",
722  ""
723  );
724 
725  switch(mode){
726  case Mode::JSON:
727  {
728  try{
729  nlohmann::json j = nlohmann::json::parse(
730  serialization
731  );
732  indexIncluded = j.at("indexIncluded").get<bool>();
733  indexSeparator = j.at("indexSeparator").get<bool>();
734  data = j.at("data").get<bool>();
735  try{
736  nlohmann::json children = j.at("children");
737  for(
738  nlohmann::json::iterator it = children.begin();
739  it != children.end();
740  ++it
741  ){
742  this->children.push_back(
744  it->dump(),
745  mode
746  )
747  );
748  }
749  }
750  catch(nlohmann::json::exception &e){
751  //It is valid to not have children.
752  }
753  }
754  catch(nlohmann::json::exception &e){
755  TBTKExit(
756  "IndexedDataTree<bool>::IndexedDataTree()",
757  "Unable to parse string as"
758  << " IndexedDataTree<bool> '"
759  << serialization << "'.",
760  ""
761  );
762  }
763 
764  break;
765  }
766  default:
767  TBTKExit(
768  "IndexedDataTree<bool>::IndexedDataTree()",
769  "Only Serializable::Mode::JSON is supported yet.",
770  ""
771  );
772  }
773 }
774 
775 template<>
777  const std::string &serialization,
778  Mode mode
779 ){
780  TBTKAssert(
781  validate(serialization, "IndexedDataTree", mode),
782  "IndexedDataTree<char>::IndexedDataTree()",
783  "Unable to parse string as IndexedDataTree<char> '"
784  << serialization << "'.",
785  ""
786  );
787 
788  switch(mode){
789  case Mode::JSON:
790  {
791  try{
792  nlohmann::json j = nlohmann::json::parse(
793  serialization
794  );
795  indexIncluded = j.at("indexIncluded").get<bool>();
796  indexSeparator = j.at("indexSeparator").get<bool>();
797  data = j.at("data").get<char>();
798  try{
799  nlohmann::json children = j.at("children");
800  for(
801  nlohmann::json::iterator it = children.begin();
802  it != children.end();
803  ++it
804  ){
805  this->children.push_back(
807  it->dump(),
808  mode
809  )
810  );
811  }
812  }
813  catch(nlohmann::json::exception &e){
814  //It is valid to not have children.
815  }
816  }
817  catch(nlohmann::json::exception &e){
818  TBTKExit(
819  "IndexedDataTree<char>::IndexedDataTree()",
820  "Unable to parse string as"
821  << " IndexedDataTree<char> '"
822  << serialization << "'.",
823  ""
824  );
825  }
826 
827  break;
828  }
829  default:
830  TBTKExit(
831  "IndexedDataTree<char>::IndexedDataTree()",
832  "Only Serializable::Mode::JSON is supported yet.",
833  ""
834  );
835  }
836 }
837 
838 template<>
840  const std::string &serialization,
841  Mode mode
842 ){
843  TBTKAssert(
844  validate(serialization, "IndexedDataTree", mode),
845  "IndexedDataTree<int>::IndexedDataTree()",
846  "Unable to parse string as IndexedDataTree<int> '"
847  << serialization << "'.",
848  ""
849  );
850 
851  switch(mode){
852  case Mode::JSON:
853  {
854  try{
855  nlohmann::json j = nlohmann::json::parse(
856  serialization
857  );
858  indexIncluded = j.at("indexIncluded").get<bool>();
859  indexSeparator = j.at("indexSeparator").get<bool>();
860  data = j.at("data").get<int>();
861  try{
862  nlohmann::json children = j.at("children");
863  for(
864  nlohmann::json::iterator it = children.begin();
865  it != children.end();
866  ++it
867  ){
868  this->children.push_back(
870  it->dump(),
871  mode
872  )
873  );
874  }
875  }
876  catch(nlohmann::json::exception &e){
877  //It is valid to not have children.
878  }
879  }
880  catch(nlohmann::json::exception &e){
881  TBTKExit(
882  "IndexedDataTree<int>::IndexedDataTree()",
883  "Unable to parse string as"
884  << " IndexedDataTree<int> '"
885  << serialization << "'.",
886  ""
887  );
888  }
889 
890  break;
891  }
892  default:
893  TBTKExit(
894  "IndexedDataTree<int>::IndexedDataTree()",
895  "Only Serializable::Mode::JSON is supported yet.",
896  ""
897  );
898  }
899 }
900 
901 template<>
903  const std::string &serialization,
904  Mode mode
905 ){
906  TBTKAssert(
907  validate(serialization, "IndexedDataTree", mode),
908  "IndexedDataTree<float>::IndexedDataTree()",
909  "Unable to parse string as IndexedDataTree<float> '"
910  << serialization << "'.",
911  ""
912  );
913 
914  switch(mode){
915  case Mode::JSON:
916  {
917  try{
918  nlohmann::json j = nlohmann::json::parse(
919  serialization
920  );
921  indexIncluded = j.at("indexIncluded").get<bool>();
922  indexSeparator = j.at("indexSeparator").get<bool>();
923  data = j.at("data").get<float>();
924  try{
925  nlohmann::json children = j.at("children");
926  for(
927  nlohmann::json::iterator it = children.begin();
928  it != children.end();
929  ++it
930  ){
931  this->children.push_back(
933  it->dump(),
934  mode
935  )
936  );
937  }
938  }
939  catch(nlohmann::json::exception &e){
940  //It is valid to not have children.
941  }
942  }
943  catch(nlohmann::json::exception &e){
944  TBTKExit(
945  "IndexedDataTree<float>::IndexedDataTree()",
946  "Unable to parse string as"
947  << " IndexedDataTree<float> '"
948  << serialization << "'.",
949  ""
950  );
951  }
952 
953  break;
954  }
955  default:
956  TBTKExit(
957  "IndexedDataTree<float>::IndexedDataTree()",
958  "Only Serializable::Mode::JSON is supported yet.",
959  ""
960  );
961  }
962 }
963 
964 template<>
966  const std::string &serialization,
967  Mode mode
968 ){
969  TBTKAssert(
970  validate(serialization, "IndexedDataTree", mode),
971  "IndexedDataTree<double>::IndexedDataTree()",
972  "Unable to parse string as IndexedDataTree<double> '"
973  << serialization << "'.",
974  ""
975  );
976 
977  switch(mode){
978  case Mode::JSON:
979  {
980  try{
981  nlohmann::json j = nlohmann::json::parse(
982  serialization
983  );
984  indexIncluded = j.at("indexIncluded").get<bool>();
985  indexSeparator = j.at("indexSeparator").get<bool>();
986  data = j.at("data").get<double>();
987  try{
988  nlohmann::json children = j.at("children");
989  for(
990  nlohmann::json::iterator it = children.begin();
991  it != children.end();
992  ++it
993  ){
994  this->children.push_back(
996  it->dump(),
997  mode
998  )
999  );
1000  }
1001  }
1002  catch(nlohmann::json::exception &e){
1003  //It is valid to not have children.
1004  }
1005  }
1006  catch(nlohmann::json::exception &e){
1007  TBTKExit(
1008  "IndexedDataTree<double>::IndexedDataTree()",
1009  "Unable to parse string as"
1010  << " IndexedDataTree<double> '"
1011  << serialization << "'.",
1012  ""
1013  );
1014  }
1015 
1016  break;
1017  }
1018  default:
1019  TBTKExit(
1020  "IndexedDataTree<double>::IndexedDataTree()",
1021  "Only Serializable::Mode::JSON is supported yet.",
1022  ""
1023  );
1024  }
1025 }
1026 
1027 template<>
1029  const std::string &serialization,
1030  Mode mode
1031 ){
1032  TBTKAssert(
1033  validate(serialization, "IndexedDataTree", mode),
1034  "IndexedDataTree<std::complex<double>>::IndexedDataTree()",
1035  "Unable to parse string as IndexedDataTree<std::complex<double>> '"
1036  << serialization << "'.",
1037  ""
1038  );
1039 
1040  switch(mode){
1041  case Mode::JSON:
1042  {
1043  try{
1044  nlohmann::json j = nlohmann::json::parse(
1045  serialization
1046  );
1047  indexIncluded = j.at("indexIncluded").get<bool>();
1048  indexSeparator = j.at("indexSeparator").get<bool>();
1049  std::string dataString = j.at("data").get<std::string>();
1050  std::stringstream ss(dataString);
1051  ss >> data;
1052 // data = j.at("data").get<std::complex<double>>();
1053  try{
1054  nlohmann::json children = j.at("children");
1055  for(
1056  nlohmann::json::iterator it = children.begin();
1057  it != children.end();
1058  ++it
1059  ){
1060  this->children.push_back(
1061  IndexedDataTree<std::complex<double>>(
1062  it->dump(),
1063  mode
1064  )
1065  );
1066  }
1067  }
1068  catch(nlohmann::json::exception &e){
1069  //It is valid to not have children.
1070  }
1071  }
1072  catch(nlohmann::json::exception &e){
1073  TBTKExit(
1074  "IndexedDataTree<std::complex<double>>::IndexedDataTree()",
1075  "Unable to parse string as"
1076  << " IndexedDataTree<std::complex<double>> '"
1077  << serialization << "'.",
1078  ""
1079  );
1080  }
1081 
1082  break;
1083  }
1084  default:
1085  TBTKExit(
1086  "IndexedDataTree<std::complex<double>>::IndexedDataTree()",
1087  "Only Serializable::Mode::JSON is supported yet.",
1088  ""
1089  );
1090  }
1091 }
1092 
1093 template<typename Data>
1095  const std::string &serialization,
1096  Mode mode
1097 ){
1098  TBTKAssert(
1099  validate(serialization, "IndexedDataTree", mode),
1100  "IndexedDataTree<Data>::IndexedDataTree()",
1101  "Unable to parse string as IndexedDataTree<Data> '"
1102  << serialization << "'.",
1103  ""
1104  );
1105 
1106  switch(mode){
1107  case Mode::JSON:
1108  {
1109  try{
1110  nlohmann::json j = nlohmann::json::parse(
1111  serialization
1112  );
1113  indexIncluded = j.at("indexIncluded").get<bool>();
1114  indexSeparator = j.at("indexSeparator").get<bool>();
1115  std::string dataString = j.at("data").get<std::string>();
1116  data = Data(dataString, mode);
1117 // data = j.at("data").get<Data>();
1118  try{
1119  nlohmann::json children = j.at("children");
1120  for(
1121  nlohmann::json::iterator it = children.begin();
1122  it != children.end();
1123  ++it
1124  ){
1125  this->children.push_back(
1127  it->dump(),
1128  mode
1129  )
1130  );
1131  }
1132  }
1133  catch(nlohmann::json::exception &e){
1134  //It is valid to not have children.
1135  }
1136  }
1137  catch(nlohmann::json::exception &e){
1138  TBTKExit(
1139  "IndexedDataTree<Data>::IndexedDataTree()",
1140  "Unable to parse string as"
1141  << " IndexedDataTree<Data> '"
1142  << serialization << "'.",
1143  ""
1144  );
1145  }
1146 
1147  break;
1148  }
1149  default:
1150  TBTKExit(
1151  "IndexedDataTree<Data>::IndexedDataTree()",
1152  "Only Serializable::Mode::JSON is supported yet.",
1153  ""
1154  );
1155  }
1156 }
1157 
1158 template<typename Data>
1160  const std::string &serialization,
1161  Mode mode
1162 ){
1163  TBTKNotYetImplemented("IndexedDataTree<Data, false>");
1164 /* TBTKAssert(
1165  validate(serialization, "IndexedDataTree", mode),
1166  "IndexedDataTree<Data>::IndexedDataTree()",
1167  "Unable to parse string as IndexedDataTree<Data> '"
1168  << serialization << "'.",
1169  ""
1170  );
1171 
1172  switch(mode){
1173  case Mode::JSON:
1174  {
1175  try{
1176  nlohmann::json j = nlohmann::json::parse(
1177  serialization
1178  );
1179  indexIncluded = j.at("indexIncluded").get<bool>();
1180  std::string dataString = j.at("data").get<std::string>();
1181  data = Data(dataString, mode);
1182 // data = j.at("data").get<Data>();
1183  try{
1184  nlohmann::json children = j.at("children");
1185  for(
1186  nlohmann::json::iterator it = children.begin();
1187  it != children.end();
1188  ++it
1189  ){
1190  this->children.push_back(
1191  IndexedDataTree<Data>(
1192  it->dump(),
1193  mode
1194  )
1195  );
1196  }
1197  }
1198  catch(nlohmann::json::exception e){
1199  //It is valid to not have children.
1200  }
1201  }
1202  catch(nlohmann::json::exception e){
1203  TBTKExit(
1204  "IndexedDataTree<Data>::IndexedDataTree()",
1205  "Unable to parse string as"
1206  << " IndexedDataTree<Data> '"
1207  << serialization << "'.",
1208  ""
1209  );
1210  }
1211 
1212  break;
1213  }
1214  default:
1215  TBTKExit(
1216  "IndexedDataTree<Data>::IndexedDataTree()",
1217  "Only Serializable::Mode::JSON is supported yet.",
1218  ""
1219  );
1220  }*/
1221 }
1222 
1223 template<typename Data, bool isSerializable>
1225 }
1226 
1227 template<typename Data>
1229 }
1230 
1231 template<typename Data>
1233 }
1234 
1235 template<typename Data, bool isSerializable>
1237  const Data &data,
1238  const Index &index
1239 ){
1240  add(data, index, 0);
1241 }
1242 
1243 template<typename Data>
1245  const Data &data,
1246  const Index &index
1247 ){
1248  add(data, index, 0);
1249 }
1250 
1251 template<typename Data>
1253  const Data &data,
1254  const Index &index
1255 ){
1256  add(data, index, 0);
1257 }
1258 
1259 template<typename Data, bool isSerializable>
1261  const Data &data,
1262  const Index &index,
1263  unsigned int subindex
1264 ){
1265  if(subindex < index.getSize()){
1266  //If the current subindex is not the last, the Index is
1267  //propagated to the next node level.
1268 
1269  //Get current subindex
1270  int currentIndex = index.at(subindex);
1271 
1272  if(currentIndex == IDX_SEPARATOR){
1273  if(children.size() == 0){
1274  indexSeparator = true;
1275  }
1276  else{
1277  TBTKAssert(
1278  indexSeparator,
1279  "IndexedDataTree:add()",
1280  "Invalid index '" << index.toString()
1281  << "'. Another Index has already been"
1282  << " added to the tree that has a"
1283  << " conflicting index at the index"
1284  << " separator at subindex '"
1285  << subindex << "'.",
1286  "Note that a separation point between"
1287  << " two indices counts as a subindex."
1288  );
1289  }
1290 
1291  indexSeparator = false;
1292  add(data, index, subindex+1);
1293  indexSeparator = true;
1294  return;
1295  }
1296  else{
1297  TBTKAssert(
1298  !indexSeparator,
1299  "IndexedDataTree:add()",
1300  "Invalid index '" << index.toString() << "'."
1301  << " Another Index has already been added to"
1302  << " the tree that has a conflicting index"
1303  << " separator at subindex '"
1304  << subindex << "'.",
1305  "Note that a separation point between two"
1306  << " indices counts as a subindex."
1307  );
1308  }
1309 
1310  TBTKAssert(
1311  currentIndex >= 0,
1312  "IndexedDataTree::add()",
1313  "Invalid Index. Negative indices not allowed, but the"
1314  << "index " << index.toString() << " have a negative"
1315  << " index" << " in position " << subindex << ".",
1316  "Compound indices such as {{1, 2, 3}, {4, 5, 6}} are"
1317  << " separated by IDX_SEPARATOR with the value '"
1318  << IDX_SEPARATOR << "' and are" << " represented as {1"
1319  << ", 2, 3, " << IDX_SEPARATOR << ", 4, 5, 6}. This is"
1320  << " the only allowed instance of negative numbers."
1321  );
1322 
1323  //If the subindex is bigger than the current number of child
1324  //nodes, create empty nodes.
1325  if(currentIndex >= children.size())
1326  for(int n = children.size(); n <= currentIndex; n++)
1327  children.push_back(IndexedDataTree());
1328  //Error detection:
1329  //If the current node has the indexIncluded flag set, another
1330  //Index with fewer subindices than the current Index have
1331  //previously been added to this node. This is an error because
1332  //different number of subindices is only allowed if the Indices
1333  //differ in one of their common indices.
1334  TBTKAssert(
1335  !indexIncluded,
1336  "IndexedDataTree::add()",
1337  "Incompatible indices. The Index " << index.toString()
1338  << " cannot be added because an Index of length "
1339  << subindex + 1 << " which exactly agrees with the "
1340  << subindex + 1 << " first indices of the current"
1341  << " Index has already been added.",
1342  ""
1343  );
1344 
1345  children.at(currentIndex).add(data, index, subindex+1);
1346  }
1347  else{
1348  //If the current subindex is the last, the index is marked as
1349  //included.
1350 
1351  //Error detection:
1352  //If children is non-zero, another Data with more subindices
1353  //have already been added to this node. This is an error
1354  //because different number of subindices is only allowed if the
1355  // indices differ in one of their common indices.
1356  TBTKAssert(
1357  children.size() == 0,
1358  "IndexedDataTree::add()",
1359  "Incompatible indices. The Index " << index.toString()
1360  << " cannot be added because a longer Index which"
1361  << " exactly agrees with the current Index in the"
1362  << " common indices has already been added.",
1363  ""
1364  );
1365 
1366  indexIncluded = true;
1367  this->data = data;
1368  }
1369 }
1370 
1371 template<typename Data>
1373  const Data &data,
1374  const Index &index,
1375  unsigned int subindex
1376 ){
1377  if(subindex < index.getSize()){
1378  //If the current subindex is not the last, the Index is
1379  //propagated to the next node level.
1380 
1381  //Get current subindex
1382  int currentIndex = index.at(subindex);
1383 
1384  if(currentIndex == IDX_SEPARATOR){
1385  if(children.size() == 0){
1386  indexSeparator = true;
1387  }
1388  else{
1389  TBTKAssert(
1390  indexSeparator,
1391  "IndexedDataTree:add()",
1392  "Invalid index '" << index.toString()
1393  << "'. Another Index has already been"
1394  << " added to the tree that has a"
1395  << " conflicting index at the index"
1396  << " separator at subindex '"
1397  << subindex << "'.",
1398  "Note that a separation point between"
1399  << " two indices counts as a subindex."
1400  );
1401  }
1402 
1403  indexSeparator = false;
1404  add(data, index, subindex+1);
1405  indexSeparator = true;
1406  return;
1407  }
1408  else{
1409  TBTKAssert(
1410  !indexSeparator,
1411  "IndexedDataTree:add()",
1412  "Invalid index '" << index.toString() << "'."
1413  << " Another Index has already been added to"
1414  << " the tree that has a conflicting index"
1415  << " separator at subindex '"
1416  << subindex << "'.",
1417  "Note that a separation point between two"
1418  << " indices counts as a subindex."
1419  );
1420  }
1421 
1422  TBTKAssert(
1423  currentIndex >= 0,
1424  "IndexedDataTree::add()",
1425  "Invalid Index. Negative indices not allowed, but the"
1426  << "index " << index.toString() << " have a negative"
1427  << " index" << " in position " << subindex << ".",
1428  "Compound indices such as {{1, 2, 3}, {4, 5, 6}} are"
1429  << " separated by IDX_SEPARATOR with the value '"
1430  << IDX_SEPARATOR << "' and are" << " represented as {1"
1431  << ", 2, 3, " << IDX_SEPARATOR << ", 4, 5, 6}. This is"
1432  << " the only allowed instance of negative numbers."
1433  );
1434 
1435  //If the subindex is bigger than the current number of child
1436  //nodes, create empty nodes.
1437  if((unsigned int)currentIndex >= children.size())
1438  for(int n = children.size(); n <= currentIndex; n++)
1439  children.push_back(IndexedDataTree());
1440  //Error detection:
1441  //If the current node has the indexIncluded flag set, another
1442  //Index with fewer subindices than the current Index have
1443  //previously been added to this node. This is an error because
1444  //different number of subindices is only allowed if the Indices
1445  //differ in one of their common indices.
1446  TBTKAssert(
1447  !indexIncluded,
1448  "IndexedDataTree::add()",
1449  "Incompatible indices. The Index " << index.toString()
1450  << " cannot be added because an Index of length "
1451  << subindex + 1 << " which exactly agrees with the "
1452  << subindex + 1 << " first indices of the current"
1453  << " Index has already been added.",
1454  ""
1455  );
1456 
1457  children.at(currentIndex).add(data, index, subindex+1);
1458  }
1459  else{
1460  //If the current subindex is the last, the index is marked as
1461  //included.
1462 
1463  //Error detection:
1464  //If children is non-zero, another Data with more subindices
1465  //have already been added to this node. This is an error
1466  //because different number of subindices is only allowed if the
1467  // indices differ in one of their common indices.
1468  TBTKAssert(
1469  children.size() == 0,
1470  "IndexedDataTree::add()",
1471  "Incompatible indices. The Index " << index.toString()
1472  << " cannot be added because a longer Index which"
1473  << " exactly agrees with the current Index in the"
1474  << " common indices has already been added.",
1475  ""
1476  );
1477 
1478  indexIncluded = true;
1479  this->data = data;
1480  }
1481 }
1482 
1483 template<typename Data>
1485  const Data &data,
1486  const Index &index,
1487  unsigned int subindex
1488 ){
1489  if(subindex < index.getSize()){
1490  //If the current subindex is not the last, the Index is
1491  //propagated to the next node level.
1492 
1493  //Get current subindex
1494  int currentIndex = index.at(subindex);
1495 
1496  if(currentIndex == IDX_SEPARATOR){
1497  if(children.size() == 0){
1498  indexSeparator = true;
1499  }
1500  else{
1501  TBTKAssert(
1502  indexSeparator,
1503  "IndexedDataTree:add()",
1504  "Invalid index '" << index.toString()
1505  << "'. Another Index has already been"
1506  << " added to the tree that has a"
1507  << " conflicting index at the index"
1508  << " separator at subindex '"
1509  << subindex << "'.",
1510  "Note that a separation point between"
1511  << " two indices counts as a subindex."
1512  );
1513  }
1514 
1515  indexSeparator = false;
1516  add(data, index, subindex+1);
1517  indexSeparator = true;
1518  return;
1519  }
1520  else{
1521  TBTKAssert(
1522  !indexSeparator,
1523  "IndexedDataTree:add()",
1524  "Invalid index '" << index.toString() << "'."
1525  << " Another Index has already been added to"
1526  << " the tree that has a conflicting index"
1527  << " separator at subindex '"
1528  << subindex << "'.",
1529  "Note that a separation point between two"
1530  << " indices counts as a subindex."
1531  );
1532  }
1533 
1534  TBTKAssert(
1535  currentIndex >= 0,
1536  "IndexedDataTree::add()",
1537  "Invalid Index. Negative indices not allowed, but the"
1538  << "index " << index.toString() << " have a negative"
1539  << " index" << " in position " << subindex << ".",
1540  "Compound indices such as {{1, 2, 3}, {4, 5, 6}} are"
1541  << " separated by IDX_SEPARATOR with the value '"
1542  << IDX_SEPARATOR << "' and are" << " represented as {1"
1543  << ", 2, 3, " << IDX_SEPARATOR << ", 4, 5, 6}. This is"
1544  << " the only allowed instance of negative numbers."
1545  );
1546 
1547  //If the subindex is bigger than the current number of child
1548  //nodes, create empty nodes.
1549  if(currentIndex >= (int)children.size())
1550  for(int n = children.size(); n <= currentIndex; n++)
1551  children.push_back(IndexedDataTree());
1552  //Error detection:
1553  //If the current node has the indexIncluded flag set, another
1554  //Index with fewer subindices than the current Index have
1555  //previously been added to this node. This is an error because
1556  //different number of subindices is only allowed if the Indices
1557  //differ in one of their common indices.
1558  TBTKAssert(
1559  !indexIncluded,
1560  "IndexedDataTree::add()",
1561  "Incompatible indices. The Index " << index.toString()
1562  << " cannot be added because an Index of length "
1563  << subindex + 1 << " which exactly agrees with the "
1564  << subindex + 1 << " first indices of the current"
1565  << " Index has already been added.",
1566  ""
1567  );
1568 
1569  children.at(currentIndex).add(data, index, subindex+1);
1570  }
1571  else{
1572  //If the current subindex is the last, the index is marked as
1573  //included.
1574 
1575  //Error detection:
1576  //If children is non-zero, another Data with more subindices
1577  //have already been added to this node. This is an error
1578  //because different number of subindices is only allowed if the
1579  // indices differ in one of their common indices.
1580  TBTKAssert(
1581  children.size() == 0,
1582  "IndexedDataTree::add()",
1583  "Incompatible indices. The Index " << index.toString()
1584  << " cannot be added because a longer Index which"
1585  << " exactly agrees with the current Index in the"
1586  << " common indices has already been added.",
1587  ""
1588  );
1589 
1590  indexIncluded = true;
1591  this->data = data;
1592  }
1593 }
1594 
1595 template<typename Data, bool isSerializable>
1596 bool IndexedDataTree<Data, isSerializable>::get(Data &data, const Index &index) const{
1597  return get(data, index, 0);
1598 }
1599 
1600 template<typename Data>
1601 bool IndexedDataTree<Data, true>::get(Data &data, const Index &index) const{
1602  return get(data, index, 0);
1603 }
1604 
1605 template<typename Data>
1606 bool IndexedDataTree<Data, false>::get(Data &data, const Index &index) const{
1607  return get(data, index, 0);
1608 }
1609 
1610 template<typename Data, bool isSerializable>
1612  Data &data,
1613  const Index &index,
1614  unsigned int subindex
1615 ) const{
1616  if(subindex < index.getSize()){
1617  //If the current subindex is not the last, continue to the next
1618  //node level.
1619 
1620  //Return false because this is a leaf node without the
1621  //indexIncluded flag set. This means it must have been added to
1622  //pad the parents child vector and not as a consequence of an
1623  //actual Index having been associated with the node.
1624  if(children.size() == 0 && !indexIncluded)
1625  return false;
1626 
1627  //Get current subindex.
1628  int currentIndex = index.at(subindex);
1629 
1630  TBTKAssert(
1631  currentIndex >= 0,
1632  "IndexedDataTree::add()",
1633  "Invalid Index. Negative indices not allowed, but the"
1634  << " index " << index.toString() << " have a negative"
1635  << " index in position " << subindex << ".",
1636  ""
1637  );
1638 
1639  //Return false because the Index is not included.
1640  if(currentIndex >= children.size())
1641  return false;
1642 
1643  return children.at(currentIndex).get(data, index, subindex+1);
1644  }
1645  else{
1646  //If the current subindex is the last, try to extract the data.
1647  //Return true if successful but false if the data does not
1648  //exist.
1649  if(indexIncluded){
1650  data = this->data;
1651 
1652  return true;
1653  }
1654  else{
1655  return false;
1656  }
1657  }
1658 }
1659 
1660 template<typename Data>
1662  Data &data,
1663  const Index &index,
1664  unsigned int subindex
1665 ) const{
1666  if(subindex < index.getSize()){
1667  //If the current subindex is not the last, continue to the next
1668  //node level.
1669 
1670  //Return false because this is a leaf node without the
1671  //indexIncluded flag set. This means it must have been added to
1672  //pad the parents child vector and not as a consequence of an
1673  //actual Index having been associated with the node.
1674  if(children.size() == 0 && !indexIncluded)
1675  return false;
1676 
1677  //Get current subindex.
1678  int currentIndex = index.at(subindex);
1679 
1680  if(currentIndex == IDX_SEPARATOR){
1681  if(indexSeparator){
1682  return get(data, index, subindex+1);
1683  }
1684  else{
1685  TBTKExit(
1686  "IndexedDataTree::get()",
1687  "Invalid Index. Found IDX_SEPARATOR at"
1688  << " subindex '" << subindex << "',"
1689  << " but the node is not an index"
1690  << " separator.",
1691  ""
1692  );
1693  }
1694  }
1695 
1696  TBTKAssert(
1697  currentIndex >= 0,
1698  "IndexedDataTree::get()",
1699  "Invalid Index. Negative indices not allowed, but the"
1700  << "index " << index.toString() << " have a negative"
1701  << " index" << " in position " << subindex << ".",
1702  "Compound indices such as {{1, 2, 3}, {4, 5, 6}} are"
1703  << " separated by IDX_SEPARATOR with the value '"
1704  << IDX_SEPARATOR << "' and are" << " represented as {1"
1705  << ", 2, 3, " << IDX_SEPARATOR << ", 4, 5, 6}. This is"
1706  << " the only allowed instance of negative numbers."
1707  );
1708 
1709  //Return false because the Index is not included.
1710  if((unsigned int)currentIndex >= children.size())
1711  return false;
1712 
1713  return children.at(currentIndex).get(data, index, subindex+1);
1714  }
1715  else{
1716  //If the current subindex is the last, try to extract the data.
1717  //Return true if successful but false if the data does not
1718  //exist.
1719  if(indexIncluded){
1720  data = this->data;
1721 
1722  return true;
1723  }
1724  else{
1725  return false;
1726  }
1727  }
1728 }
1729 
1730 template<typename Data>
1732  Data &data,
1733  const Index &index,
1734  unsigned int subindex
1735 ) const{
1736  if(subindex < index.getSize()){
1737  //If the current subindex is not the last, continue to the next
1738  //node level.
1739 
1740  //Return false because this is a leaf node without the
1741  //indexIncluded flag set. This means it must have been added to
1742  //pad the parents child vector and not as a consequence of an
1743  //actual Index having been associated with the node.
1744  if(children.size() == 0 && !indexIncluded)
1745  return false;
1746 
1747  //Get current subindex.
1748  int currentIndex = index.at(subindex);
1749 
1750  if(currentIndex == IDX_SEPARATOR){
1751  if(indexSeparator){
1752  return get(data, index, subindex+1);
1753  }
1754  else{
1755  TBTKExit(
1756  "IndexedDataTree::get()",
1757  "Invalid Index. Found IDX_SEPARATOR at"
1758  << " subindex '" << subindex << "',"
1759  << " but the node is not an index"
1760  << " separator.",
1761  ""
1762  );
1763  }
1764  }
1765 
1766  TBTKAssert(
1767  currentIndex >= 0,
1768  "IndexedDataTree::get()",
1769  "Invalid Index. Negative indices not allowed, but the"
1770  << "index " << index.toString() << " have a negative"
1771  << " index" << " in position " << subindex << ".",
1772  "Compound indices such as {{1, 2, 3}, {4, 5, 6}} are"
1773  << " separated by IDX_SEPARATOR with the value '"
1774  << IDX_SEPARATOR << "' and are" << " represented as {1"
1775  << ", 2, 3, " << IDX_SEPARATOR << ", 4, 5, 6}. This is"
1776  << " the only allowed instance of negative numbers."
1777  );
1778 
1779  //Return false because the Index is not included.
1780  if(currentIndex >= (int)children.size())
1781  return false;
1782 
1783  return children.at(currentIndex).get(data, index, subindex+1);
1784  }
1785  else{
1786  //If the current subindex is the last, try to extract the data.
1787  //Return true if successful but false if the data does not
1788  //exist.
1789  if(indexIncluded){
1790  data = this->data;
1791 
1792  return true;
1793  }
1794  else{
1795  return false;
1796  }
1797  }
1798 }
1799 
1800 template<typename Data>
1802  //Casting is safe because we do not guarantee that the IndexedDataTree
1803  //is not modified. Casting away const from the returned reference is
1804  //therefore not a violation of any promisse made by this function.
1805  //See also "Avoiding Duplication in const and Non-const Member
1806  //Function" in S. Meyers, Effective C++.
1807  return const_cast<Data&>(
1808  static_cast<const IndexedDataTree<Data, true>*>(
1809  this
1810  )->get(index, 0)
1811  );
1812 }
1813 
1814 template<typename Data>
1815 const Data& IndexedDataTree<Data, true>::get(const Index &index) const{
1816  return get(index, 0);
1817 }
1818 
1819 template<typename Data>
1821  //Casting is safe because we do not guarantee that the IndexedDataTree
1822  //is not modified. Casting away const from the returned reference is
1823  //therefore not a violation of any promisse made by this function.
1824  //See also "Avoiding Duplication in const and Non-const Member
1825  //Function" in S. Meyers, Effective C++.
1826  return const_cast<Data&>(
1827  static_cast<const IndexedDataTree<Data, false>*>(
1828  this
1829  )->get(index, 0)
1830  );
1831 }
1832 
1833 template<typename Data>
1834 const Data& IndexedDataTree<Data, false>::get(const Index &index) const{
1835  return get(index, 0);
1836 }
1837 
1838 template<typename Data>
1840  const Index &index,
1841  unsigned int subindex
1842 ) const{
1843  if(subindex < index.getSize()){
1844  //If the current subindex is not the last, continue to the next
1845  //node level.
1846 
1847  //Throw ElementNotFoundException if the Index is not included.
1848  //This statement is executed if this is a leaf node without the
1849  //indexIncluded flag set. This means it must have been added to
1850  //pad the parents child vector and not as a consequence of an
1851  //actual Index having been associated with the node.
1852  if(children.size() == 0 && !indexIncluded){
1854  "IndexedDataTree()",
1855  TBTKWhere,
1856  "Tried to get element with Index '"
1857  + index.toString() + "', but no such element"
1858  + " exists.",
1859  ""
1860  );
1861  }
1862 
1863  //Get current subindex.
1864  int currentIndex = index.at(subindex);
1865 
1866  if(currentIndex == IDX_SEPARATOR){
1867  if(indexSeparator){
1868  return get(index, subindex+1);
1869  }
1870  else{
1871  TBTKExit(
1872  "IndexedDataTree::get()",
1873  "Invalid Index. Found IDX_SEPARATOR at"
1874  << " subindex '" << subindex << "',"
1875  << " but the node is not an index"
1876  << " separator.",
1877  ""
1878  );
1879  }
1880  }
1881 
1882  TBTKAssert(
1883  currentIndex >= 0,
1884  "IndexedDataTree::get()",
1885  "Invalid Index. Negative indices not allowed, but the"
1886  << "index " << index.toString() << " have a negative"
1887  << " index" << " in position " << subindex << ".",
1888  "Compound indices such as {{1, 2, 3}, {4, 5, 6}} are"
1889  << " separated by IDX_SEPARATOR with the value '"
1890  << IDX_SEPARATOR << "' and are" << " represented as {1"
1891  << ", 2, 3, " << IDX_SEPARATOR << ", 4, 5, 6}. This is"
1892  << " the only allowed instance of negative numbers."
1893  );
1894 
1895  //Throw ElementNotFoundException if the Index is not included.
1896  if((unsigned int)currentIndex >= children.size()){
1898  "IndexedDataTree()",
1899  TBTKWhere,
1900  "Tried to get element with Index '"
1901  + index.toString() + "', but no such element"
1902  + " exists.",
1903  ""
1904  );
1905  }
1906 
1907  return children.at(currentIndex).get(index, subindex+1);
1908  }
1909  else{
1910  //If the current subindex is the last, try to extract the data.
1911  //Return data if successful but throw ElementNotFoundException if the
1912  //data does not exist.
1913  if(indexIncluded){
1914  return data;
1915  }
1916  else{
1918  "IndexedDataTree()",
1919  TBTKWhere,
1920  "Tried to get element with Index '"
1921  + index.toString() + "', but no such element"
1922  + " exists.",
1923  ""
1924  );
1925  }
1926  }
1927 }
1928 
1929 template<typename Data>
1931  const Index &index,
1932  unsigned int subindex
1933 ) const{
1934  if(subindex < index.getSize()){
1935  //If the current subindex is not the last, continue to the next
1936  //node level.
1937 
1938  //Throw ElementNotFoundException if the Index is not included.
1939  //This statement is executed if this is a leaf node without the
1940  //indexIncluded flag set. This means it must have been added to
1941  //pad the parents child vector and not as a consequence of an
1942  //actual Index having been associated with the node.
1943  if(children.size() == 0 && !indexIncluded){
1945  "IndexedDataTree()",
1946  TBTKWhere,
1947  "Tried to get element with Index '"
1948  + index.toString() + "', but no such element"
1949  + " exists.",
1950  ""
1951  );
1952  }
1953 
1954  //Get current subindex.
1955  int currentIndex = index.at(subindex);
1956 
1957  if(currentIndex == IDX_SEPARATOR){
1958  if(indexSeparator){
1959  return get(index, subindex+1);
1960  }
1961  else{
1962  TBTKExit(
1963  "IndexedDataTree::get()",
1964  "Invalid Index. Found IDX_SEPARATOR at"
1965  << " subindex '" << subindex << "',"
1966  << " but the node is not an index"
1967  << " separator.",
1968  ""
1969  );
1970  }
1971  }
1972 
1973  TBTKAssert(
1974  currentIndex >= 0,
1975  "IndexedDataTree::get()",
1976  "Invalid Index. Negative indices not allowed, but the"
1977  << "index " << index.toString() << " have a negative"
1978  << " index" << " in position " << subindex << ".",
1979  "Compound indices such as {{1, 2, 3}, {4, 5, 6}} are"
1980  << " separated by IDX_SEPARATOR with the value '"
1981  << IDX_SEPARATOR << "' and are" << " represented as {1"
1982  << ", 2, 3, " << IDX_SEPARATOR << ", 4, 5, 6}. This is"
1983  << " the only allowed instance of negative numbers."
1984  );
1985 
1986  //Throw ElementNotFoundException if the Index is not included.
1987  if((unsigned int)currentIndex >= children.size()){
1989  "IndexedDataTree()",
1990  TBTKWhere,
1991  "Tried to get element with Index '"
1992  + index.toString() + "', but no such element"
1993  + " exists.",
1994  ""
1995  );
1996  }
1997 
1998  return children.at(currentIndex).get(index, subindex+1);
1999  }
2000  else{
2001  //If the current subindex is the last, try to extract the data.
2002  //Return data if successful but throw ElementNotFoundException
2003  //if the data does not exist.
2004  if(indexIncluded){
2005  return data;
2006  }
2007  else{
2009  "IndexedDataTree()",
2010  TBTKWhere,
2011  "Tried to get element with Index '"
2012  + index.toString() + "', but no such element"
2013  + " exists.",
2014  ""
2015  );
2016  }
2017  }
2018 }
2019 
2020 template<typename Data>
2022  Index index;
2023  getFirstIndex(index);
2024 
2025  return index;
2026 }
2027 
2028 template<typename Data>
2030  Index index;
2031  getFirstIndex(index);
2032 
2033  return index;
2034 }
2035 
2036 template<typename Data>
2038  if(indexIncluded)
2039  return true;
2040 
2041  if(indexSeparator)
2042  index.push_back(IDX_SEPARATOR);
2043 
2044  for(unsigned int n = 0; n < children.size(); n++){
2045  index.push_back(n);
2046  if(children[n].getFirstIndex(index))
2047  return true;
2048 
2049  index.popBack();
2050  }
2051 
2052  if(indexSeparator)
2053  index.popBack();
2054 
2055  return false;
2056 }
2057 
2058 template<typename Data>
2060  if(indexIncluded)
2061  return true;
2062 
2063  if(indexSeparator)
2064  index.push_back(IDX_SEPARATOR);
2065 
2066  for(unsigned int n = 0; n < children.size(); n++){
2067  index.push_back(n);
2068  if(children[n].getFirstIndex(index))
2069  return true;
2070 
2071  index.popBack();
2072  }
2073 
2074  if(indexSeparator)
2075  index.popBack();
2076 
2077  return false;
2078 }
2079 
2080 template<typename Data>
2082  if(index.getSize() == 0)
2083  return Index();
2084 
2085  Index nextIndex;
2086  getNextIndex(index, nextIndex);
2087 
2088  return nextIndex;
2089 }
2090 
2091 template<typename Data>
2093  if(index.getSize() == 0)
2094  return Index();
2095 
2096  Index nextIndex;
2097  getNextIndex(index, nextIndex);
2098 
2099  return nextIndex;
2100 }
2101 
2102 template<typename Data>
2104  const Index &currentIndex,
2105  Index &nextIndex
2106 ) const{
2107  if(indexIncluded){
2108  if(currentIndex.equals(nextIndex))
2109  return false;
2110 
2111  return true;
2112  }
2113 
2114  if(indexSeparator)
2115  nextIndex.push_back(IDX_SEPARATOR);
2116 
2117  bool hasSameIndexStructure = true;
2118  if(currentIndex.getSize() > nextIndex.getSize()){
2119  for(unsigned int n = 0; n < nextIndex.getSize(); n++){
2120  if(currentIndex[n] != nextIndex[n]){
2121  hasSameIndexStructure = false;
2122  break;
2123  }
2124  }
2125  }
2126  else{
2127  hasSameIndexStructure = false;
2128  }
2129 
2130  unsigned int startIndex = 0;
2131  if(hasSameIndexStructure)
2132  startIndex = currentIndex[nextIndex.getSize()];
2133  for(unsigned int n = startIndex; n < children.size(); n++){
2134  nextIndex.push_back(n);
2135  if(children[n].getNextIndex(currentIndex, nextIndex))
2136  return true;
2137 
2138  nextIndex.popBack();
2139  }
2140 
2141  if(indexSeparator)
2142  nextIndex.popBack();
2143 
2144  return false;
2145 }
2146 
2147 template<typename Data>
2149  const Index &currentIndex,
2150  Index &nextIndex
2151 ) const{
2152  if(indexIncluded){
2153  if(currentIndex.equals(nextIndex))
2154  return false;
2155 
2156  return true;
2157  }
2158 
2159  if(indexSeparator)
2160  nextIndex.push_back(IDX_SEPARATOR);
2161 
2162  bool hasSameIndexStructure = true;
2163  if(currentIndex.getSize() > nextIndex.getSize()){
2164  for(unsigned int n = 0; n < nextIndex.getSize(); n++){
2165  if(currentIndex[n] != nextIndex[n]){
2166  hasSameIndexStructure = false;
2167  break;
2168  }
2169  }
2170  }
2171  else{
2172  hasSameIndexStructure = false;
2173  }
2174 
2175  unsigned int startIndex = 0;
2176  if(hasSameIndexStructure)
2177  startIndex = currentIndex[nextIndex.getSize()];
2178  for(unsigned int n = startIndex; n < children.size(); n++){
2179  nextIndex.push_back(n);
2180  if(children[n].getNextIndex(currentIndex, nextIndex))
2181  return true;
2182 
2183  nextIndex.popBack();
2184  }
2185 
2186  if(indexSeparator)
2187  nextIndex.popBack();
2188 
2189  return false;
2190 }
2191 
2192 template<typename Data, bool isSerializable>
2194  indexIncluded = false;
2195  children.clear();
2196 }
2197 
2198 template<typename Data>
2200  indexIncluded = false;
2201  children.clear();
2202 }
2203 
2204 template<typename Data>
2206  indexIncluded = false;
2207  children.clear();
2208 }
2209 
2210 template<typename Data, bool isSerializable>
2212  unsigned int size = sizeof(IndexedDataTree<Data>);
2213  for(unsigned int n = 0; n < children.size(); n++)
2214  size += children.at(n).getSizeInBytes();
2215 
2216  return size;
2217 }
2218 
2219 template<typename Data>
2221  unsigned int size = sizeof(IndexedDataTree<Data>);
2222  for(unsigned int n = 0; n < children.size(); n++)
2223  size += children.at(n).getSizeInBytes();
2224 
2225  return size;
2226 }
2227 
2228 template<typename Data>
2230  unsigned int size = sizeof(IndexedDataTree<Data>);
2231  for(unsigned int n = 0; n < children.size(); n++)
2232  size += children.at(n).getSizeInBytes();
2233 
2234  return size;
2235 }
2236 
2237 template<>
2238 inline std::string IndexedDataTree<bool, false>::serialize(Mode mode) const{
2239  switch(mode){
2240  case Mode::JSON:
2241  {
2242  nlohmann::json j;
2243  j["id"] = "IndexedDataTree";
2244  j["indexIncluded"] = indexIncluded;
2245  j["indexSeparator"] = indexSeparator;
2246  j["data"] = data;
2247  for(unsigned int n = 0; n < children.size(); n++){
2248  j["children"].push_back(
2249  nlohmann::json::parse(
2250  children.at(n).serialize(mode)
2251  )
2252  );
2253  }
2254 
2255  return j.dump();
2256  }
2257  default:
2258  TBTKExit(
2259  "IndexedDataTree<Data>::serialize()",
2260  "Only Serializable::Mode::JSON is supported yet.",
2261  ""
2262  );
2263  }
2264 }
2265 
2266 template<>
2267 inline std::string IndexedDataTree<char, false>::serialize(Mode mode) const{
2268  switch(mode){
2269  case Mode::JSON:
2270  {
2271  nlohmann::json j;
2272  j["id"] = "IndexedDataTree";
2273  j["indexIncluded"] = indexIncluded;
2274  j["indexSeparator"] = indexSeparator;
2275  j["data"] = data;
2276  for(unsigned int n = 0; n < children.size(); n++){
2277  j["children"].push_back(
2278  nlohmann::json::parse(
2279  children.at(n).serialize(mode)
2280  )
2281  );
2282  }
2283 
2284  return j.dump();
2285  }
2286  default:
2287  TBTKExit(
2288  "IndexedDataTree<Data>::serialize()",
2289  "Only Serializable::Mode::JSON is supported yet.",
2290  ""
2291  );
2292  }
2293 }
2294 
2295 template<>
2296 inline std::string IndexedDataTree<int, false>::serialize(Mode mode) const{
2297  switch(mode){
2298  case Mode::JSON:
2299  {
2300  nlohmann::json j;
2301  j["id"] = "IndexedDataTree";
2302  j["indexIncluded"] = indexIncluded;
2303  j["indexSeparator"] = indexSeparator;
2304  j["data"] = data;
2305  for(unsigned int n = 0; n < children.size(); n++){
2306  j["children"].push_back(
2307  nlohmann::json::parse(
2308  children.at(n).serialize(mode)
2309  )
2310  );
2311  }
2312 
2313  return j.dump();
2314  }
2315  default:
2316  TBTKExit(
2317  "IndexedDataTree<Data>::serialize()",
2318  "Only Serializable::Mode::JSON is supported yet.",
2319  ""
2320  );
2321  }
2322 }
2323 
2324 template<>
2325 inline std::string IndexedDataTree<float, false>::serialize(Mode mode) const{
2326  switch(mode){
2327  case Mode::JSON:
2328  {
2329  nlohmann::json j;
2330  j["id"] = "IndexedDataTree";
2331  j["indexIncluded"] = indexIncluded;
2332  j["indexSeparator"] = indexSeparator;
2333  j["data"] = data;
2334  for(unsigned int n = 0; n < children.size(); n++){
2335  j["children"].push_back(
2336  nlohmann::json::parse(
2337  children.at(n).serialize(mode)
2338  )
2339  );
2340  }
2341 
2342  return j.dump();
2343  }
2344  default:
2345  TBTKExit(
2346  "IndexedDataTree<Data>::serialize()",
2347  "Only Serializable::Mode::JSON is supported yet.",
2348  ""
2349  );
2350  }
2351 }
2352 
2353 template<>
2354 inline std::string IndexedDataTree<double, false>::serialize(Mode mode) const{
2355  switch(mode){
2356  case Mode::JSON:
2357  {
2358  nlohmann::json j;
2359  j["id"] = "IndexedDataTree";
2360  j["indexIncluded"] = indexIncluded;
2361  j["indexSeparator"] = indexSeparator;
2362  j["data"] = data;
2363  for(unsigned int n = 0; n < children.size(); n++){
2364  j["children"].push_back(
2365  nlohmann::json::parse(
2366  children.at(n).serialize(mode)
2367  )
2368  );
2369  }
2370 
2371  return j.dump();
2372  }
2373  default:
2374  TBTKExit(
2375  "IndexedDataTree<Data>::serialize()",
2376  "Only Serializable::Mode::JSON is supported yet.",
2377  ""
2378  );
2379  }
2380 }
2381 
2382 template<>
2383 inline std::string IndexedDataTree<std::complex<double>, false>::serialize(Mode mode) const{
2384  switch(mode){
2385  case Mode::JSON:
2386  {
2387  nlohmann::json j;
2388  j["id"] = "IndexedDataTree";
2389  j["indexIncluded"] = indexIncluded;
2390  j["indexSeparator"] = indexSeparator;
2391  std::stringstream ss;
2392  ss << "(" << real(data) << "," << imag(data) << ")";
2393  j["data"] = ss.str();
2394  for(unsigned int n = 0; n < children.size(); n++){
2395  j["children"].push_back(
2396  nlohmann::json::parse(
2397  children.at(n).serialize(mode)
2398  )
2399  );
2400  }
2401 
2402  return j.dump();
2403  }
2404  default:
2405  TBTKExit(
2406  "IndexedDataTree<Data>::serialize()",
2407  "Only Serializable::Mode::JSON is supported yet.",
2408  ""
2409  );
2410  }
2411 }
2412 
2413 template<typename Data>
2415  switch(mode){
2416  case Mode::JSON:
2417  {
2418  nlohmann::json j;
2419  j["id"] = "IndexedDataTree";
2420  j["indexIncluded"] = indexIncluded;
2421  j["indexSeparator"] = indexSeparator;
2422  j["data"] = data.serialize(mode);
2423  for(unsigned int n = 0; n < children.size(); n++){
2424  j["children"].push_back(
2425  nlohmann::json::parse(
2426  children.at(n).serialize(mode)
2427  )
2428  );
2429  }
2430 
2431  return j.dump();
2432  }
2433  default:
2434  TBTKExit(
2435  "IndexedDataTree<Data>::serialize()",
2436  "Only Serializable::Mode::JSON is supported yet.",
2437  ""
2438  );
2439  }
2440 }
2441 
2442 template<typename Data>
2444  TBTKNotYetImplemented("IndexedDataTree<Data, false>");
2445 /* switch(mode){
2446  case Mode::JSON:
2447  {
2448  nlohmann::json j;
2449  j["id"] = "IndexedDataTree";
2450  j["indexIncluded"] = indexIncluded;
2451  j["indexSeparator"] = indexSeparator;
2452  j["data"] = data.serialize(mode);
2453  for(unsigned int n = 0; n < children.size(); n++){
2454  j["children"].push_back(
2455  nlohmann::json::parse(
2456  children.at(n).serialize(mode)
2457  )
2458  );
2459  }
2460 
2461  return j.dump();
2462  }
2463  default:
2464  TBTKExit(
2465  "IndexedDataTree<Data>::serialize()",
2466  "Only Serializable::Mode::JSON is supported yet.",
2467  ""
2468  );
2469  }*/
2470 }
2471 
2472 template<typename Data>
2474  return Iterator(this);
2475 }
2476 
2477 template<typename Data>
2479  return ConstIterator(this);
2480 }
2481 
2482 template<typename Data>
2484  return Iterator(this);
2485 }
2486 
2487 template<typename Data>
2489  return ConstIterator(this);
2490 }
2491 
2492 template<typename Data>
2494  return ConstIterator(this);
2495 }
2496 
2497 template<typename Data>
2499  return ConstIterator(this);
2500 }
2501 
2502 template<typename Data>
2504  return Iterator(this, true);
2505 }
2506 
2507 template<typename Data>
2509  return ConstIterator(this, true);
2510 }
2511 
2512 template<typename Data>
2514  return Iterator(this, true);
2515 }
2516 
2517 template<typename Data>
2519  return ConstIterator(this, true);
2520 }
2521 
2522 template<typename Data>
2524  return ConstIterator(this, true);
2525 }
2526 
2527 template<typename Data>
2529  return ConstIterator(this, true);
2530 }
2531 
2532 template<typename Data> template<bool isConstIterator>
2534  currentIndex = indexedDataTree->getNextIndex(currentIndex);
2535 }
2536 
2537 template<typename Data> template<bool isConstIterator>
2539  currentIndex = indexedDataTree->getNextIndex(currentIndex);
2540 }
2541 
2542 template<typename Data> template<bool isConstIterator>
2543 typename IndexedDataTree<Data, true>::template _Iterator<
2544  isConstIterator
2545 >::DataReferenceType IndexedDataTree<Data, true>::_Iterator<
2546  isConstIterator
2547 >::operator*(){
2548  return indexedDataTree->get(currentIndex);
2549 }
2550 
2551 template<typename Data> template<bool isConstIterator>
2552 typename IndexedDataTree<Data, false>::template _Iterator<
2553  isConstIterator
2554 >::DataReferenceType IndexedDataTree<Data, false>::_Iterator<
2555  isConstIterator
2556 >::operator*(){
2557  return indexedDataTree->get(currentIndex);
2558 }
2559 
2560 template<typename Data> template<bool isConstIterator>
2563 ) const{
2564  if(
2565  indexedDataTree == rhs.indexedDataTree
2566  && currentIndex.equals(rhs.currentIndex)
2567  ){
2568  return true;
2569  }
2570  else{
2571  return false;
2572  }
2573 }
2574 
2575 template<typename Data> template<bool isConstIterator>
2578 ) const{
2579  if(
2580  indexedDataTree == rhs.indexedDataTree
2581  && currentIndex.equals(rhs.currentIndex)
2582  ){
2583  return true;
2584  }
2585  else{
2586  return false;
2587  }
2588 }
2589 
2590 template<typename Data> template<bool isConstIterator>
2593 ) const{
2594  if(
2595  indexedDataTree != rhs.indexedDataTree
2596  || !currentIndex.equals(rhs.currentIndex)
2597  ){
2598  return true;
2599  }
2600  else{
2601  return false;
2602  }
2603 }
2604 
2605 template<typename Data> template<bool isConstIterator>
2608 ) const{
2609  if(
2610  indexedDataTree != rhs.indexedDataTree
2611  || !currentIndex.equals(rhs.currentIndex)
2612  ){
2613  return true;
2614  }
2615  else{
2616  return false;
2617  }
2618 }
2619 
2620 template<typename Data> template<bool isConstIterator>
2622 ) const{
2623  return currentIndex;
2624 }
2625 
2626 template<typename Data> template<bool isConstIterator>
2628 ) const{
2629  return currentIndex;
2630 }
2631 
2632 template<typename Data> template<bool isConstIterator>
2634  IndexedDataTreePointerType indexedDataTree,
2635  bool end
2636 ){
2637  this->indexedDataTree = indexedDataTree;
2638  if(end)
2639  currentIndex = Index();
2640  else
2641  currentIndex = indexedDataTree->getFirstIndex();
2642 }
2643 
2644 template<typename Data> template<bool isConstIterator>
2646  IndexedDataTreePointerType indexedDataTree,
2647  bool end
2648 ){
2649  this->indexedDataTree = indexedDataTree;
2650  if(end)
2651  currentIndex = Index();
2652  else
2653  currentIndex = indexedDataTree->getFirstIndex();
2654 }
2655 
2656 //This is used to work around incompatibilities between nlohmann::json and
2657 //CUDA. This effectively forbids instantiation of IndexedDataTree in CUDA code.
2658 #endif
2659 
2660 }; //End of namesapce TBTK
2661 
2662 #endif
unsigned int getSizeInBytes() const
Definition: IndexedDataTree.h:2211
ConstIterator cbegin() const
FockStateRuleSet operator*(const LadderOperator< BitRegister > &ladderOperator, const FockStateRuleSet &fockStateRuleSet)
Definition: FockStateRuleSet.h:103
virtual ~IndexedDataTree()
Definition: IndexedDataTree.h:1224
Flexible physical index.
bool equals(const Index &index, bool allowWildcard=false) const
Definition: Index.h:326
Precompiler macros.
Definition: Serializable.h:40
Definition: IndexedDataTree.h:181
friend class Index
Definition: Serializable.h:172
Definition: ElementNotFoundException.h:10
Definition: IndexedDataTree.h:273
Definition: IndexedDataTree.h:43
void push_back(int subindex)
Definition: Index.h:367
IndexedDataTree()
Definition: IndexedDataTree.h:695
virtual std::string serialize(Mode mode) const
Flexible physical index.
Definition: Index.h:69
Definition: IndexedDataTree.h:481
Definition: IndexedDataTree.h:168
Definition: ModelFactory.h:35
unsigned int getSize() const
Definition: Index.h:359
void add(const Data &data, const Index &index)
Definition: IndexedDataTree.h:1236
ConstIterator cend() const
Mode
Definition: Serializable.h:44
bool get(Data &data, const Index &index) const
Definition: IndexedDataTree.h:1596
static bool validate(const std::string &serialization, const std::string &id, Mode mode)
void clear()
Definition: IndexedDataTree.h:2193
Abstract base class for serializable objects.
int & at(unsigned int n)
Definition: Index.h:351
std::string toString() const
Definition: Index.h:282
int popBack()
Definition: Index.h:378