Tomographer  v1.0a
Tomographer C++ Framework Documentation
ezmatio.h
Go to the documentation of this file.
1 /* This file is part of the Tomographer project, which is distributed under the
2  * terms of the MIT license.
3  *
4  * The MIT License (MIT)
5  *
6  * Copyright (c) 2015 ETH Zurich, Institute for Theoretical Physics, Philippe Faist
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to deal
10  * in the Software without restriction, including without limitation the rights
11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  * copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  * SOFTWARE.
25  */
26 
27 #ifndef _TOMOGRAPHER_TOOLS_EZMATIO_H
28 #define _TOMOGRAPHER_TOOLS_EZMATIO_H
29 
30 #include <cstdint>
31 #include <cerrno>
32 
33 #include <complex>
34 #include <string>
35 #include <vector>
36 #include <algorithm>
37 #include <iostream>
38 #include <stdexcept>
39 #include <sstream>
40 #include <initializer_list>
41 #include <utility>
42 
43 extern "C" {
44 # include <matio.h>
45 }
46 
47 #include <Eigen/Core>
48 
49 #include <tomographer/qit/util.h>
50 #include <tomographer/tools/fmt.h>
51 
52 
60 namespace Tomographer
61 {
62 // namespace doc in doc/doxdocs/namespaces.cxx
63 namespace MAT
64 {
65 
66 
69 class Exception : public std::exception
70 {
71  std::string p_heading;
72  std::string p_message;
73  std::string p_final;
74 public:
75  Exception(std::string msg) : p_message(msg) { update_final(); }
76  Exception(std::string heading, std::string msg) : p_heading(heading), p_message(msg) { update_final(); }
77  virtual ~Exception() noexcept { }
78 
79  virtual const char * what() const noexcept { return p_final.c_str(); }
80 
81 protected:
82  inline void setHeading(const std::string heading) {
83  p_heading = heading;
84  update_final();
85  }
86  inline void setMessage(const std::string message) {
87  p_message = message;
88  update_final();
89  }
90 private:
91  inline void update_final() {
92  p_final = p_heading + p_message;
93  }
94 };
95 
98 class VarError : public Exception
99 {
100 public:
101  VarError(std::string msg) : Exception("", msg) { }
102  VarError(std::string varname, std::string msg) : Exception(heading(varname), msg) { }
103  virtual ~VarError() noexcept { }
104 
105  void setVarName(std::string varname) { setHeading(heading(varname)); }
106 
107 private:
108  static std::string heading(std::string varname) { return "Variable " + varname + ": "; }
109 };
110 
112 class VarReadError : public VarError
113 {
114 public:
115  VarReadError(const std::string varname)
116  : VarError(varname, "Can't read variable")
117  {
118  }
119  virtual ~VarReadError() noexcept { }
120 };
121 
123 class VarTypeError : public VarError
124 {
125 public:
126  VarTypeError(const std::string varname, const std::string msg)
127  : VarError(varname, msg)
128  {
129  }
130  virtual ~VarTypeError() noexcept { }
131 };
132 
134 class VarMatTypeError : public VarError {
135 public:
136  VarMatTypeError(const std::string msg)
137  : VarError(msg)
138  {
139  }
140  VarMatTypeError(const std::string varname, const std::string msg)
141  : VarError(varname, msg)
142  {
143  }
144  virtual ~VarMatTypeError() noexcept { }
145 };
146 
148 class FileOpenError : public Exception
149 {
150 public:
151  FileOpenError(const std::string fname, const std::string errmsg = std::string())
152  : Exception(heading(fname), "Error opening file" + (errmsg.size() ? "': "+errmsg : ""))
153  {
154  }
155  virtual ~FileOpenError() noexcept { }
156 
157  void setFileName(const std::string fname) {
158  setHeading(heading(fname));
159  }
160 
161 private:
162  static std::string heading(std::string fname) { return "File `"+fname+"`: "; }
163 };
164 
165 /*
166 class InvalidOperationError : public Exception {
167 public:
168  InvalidOperationError(const std::string& msg)
169  : Exception("Invalid operation", msg)
170  {
171  }
172  virtual ~InvalidOperationError() noexcept { }
173  };
174 */
175 
177 class InvalidIndexError : public Exception {
178 public:
179  InvalidIndexError(const std::string msg) : Exception("Invalid index: ", msg) { }
180  virtual ~InvalidIndexError() noexcept { }
181 };
182 
183 
184 
185 
186 
187 class Var;
188 
189 
201 class File
202 {
203 public:
209  File(const std::string fname)
210  {
211  errno = 0;
212  p_matfp = Mat_Open(fname.c_str(), MAT_ACC_RDONLY);
213  if ( p_matfp == NULL ) {
214  throw FileOpenError(fname, strerror(errno));
215  }
216  }
217  File(const File& other) = delete;
218 
224  File(File&& other)
225  {
226  // move constructor. Steal the other object's MAT file handle
227  p_matfp = other.p_matfp;
228  other.p_matfp = NULL;
229  }
230 
231  ~File()
232  {
233  if ( p_matfp != NULL ) {
234  Mat_Close(p_matfp);
235  }
236  }
237 
247  inline Var var(const std::string varname, bool load_data = true);
248 
249 
256 
262  mat_t * getMatPtr()
263  {
264  return p_matfp;
265  }
266 
272  File& operator=(File&& other)
273  {
274  // move assignment operator. Steal the other object's MAT file handle
275  p_matfp = other.p_matfp;
276  other.p_matfp = NULL;
277  return *this;
278  }
279  File& operator=(const File& other) = delete;
280 
281 private:
282  mat_t *p_matfp;
283 };
284 
285 
291 template<typename It, typename ValueType = typename std::iterator_traits<It>::value_type>
292 ValueType get_numel(It begin, It end)
293 {
294  ValueType n = 1;
295  for (It it = begin; it != end; ++it) {
296  n *= (*it);
297  }
298  return n;
299 }
300 
301 
314 class DimList : public std::vector<int>
315 {
316 public:
317  DimList() : std::vector<int>() { }
318 
319  template<typename VectorType>
320  DimList(VectorType&& dims)
321  : std::vector<int>(std::forward<VectorType>(dims))
322  {
323  }
324  template<typename T, TOMOGRAPHER_ENABLED_IF_TMPL(std::is_convertible<T,int>::value)>
326  : std::vector<int>(init)
327  {
328  }
329  template<class It>
330  DimList(It b, It e) : std::vector<int>(b, e)
331  {
332  }
333 
338  inline int numel() const { return get_numel(begin(), end()); }
339 
345  inline int ndims() const { return (int)size(); }
346 
350  inline bool matchesWanted(const DimList& wanted) const
351  {
352  if (size() != wanted.size()) {
353  return false;
354  }
355  for (std::size_t k = 0; k < size(); ++k) {
356  if (wanted[k] >= 0 && this->operator[](k) != wanted[k]) {
357  return false;
358  }
359  }
360  return true;
361  }
362 
363  DimList& operator<<(int dim) {
364  push_back(dim);
365  return *this;
366  }
367  DimList& operator<<(const std::vector<int>& moredims) {
368  insert(end(), moredims.begin(), moredims.end());
369  return *this;
370  }
371 };
372 
374 inline std::ostream& operator<<(std::ostream& out, const DimList& dlist)
375 {
376  out << "[";
377  for (DimList::const_iterator it = dlist.begin(); it != dlist.end(); ++it) {
378  if (it != dlist.begin()) {
379  out << " ";
380  }
381  if (*it == -1) {
382  // usually meant for arbitrary size requirement. In any case, it is not a physical
383  // array size.
384  out << '*';
385  } else {
386  out << *it;
387  }
388  }
389  out << "]";
390  return out;
391 }
392 
415 template<bool IsRowMajor_ = false>
416 class IndexList : public std::vector<int>
417 {
418 public:
420  static constexpr bool IsRowMajor = IsRowMajor_;
423 
429  IndexList(const std::vector<int>& dims = std::vector<int>(), int linearindex = -1)
430  : std::vector<int>(dims.size()), p_dims(dims)
431  {
432  if (get_numel(dims.begin(), dims.end()) <= 0) {
433  throw InvalidIndexError("zero-sized array given by dimension list");
434  }
435  if (linearindex >= 0) {
436  setLinearIndex(linearindex);
437  }
438  }
445  // the reason we dont have template<typename... VectorArgs> for std::vector<>
446  // constructor is that g++ 4.6 if I remember correctly can't unpack arguments into a
447  // fixed number of arguments (TODO: CHECK THIS!)
448  template<typename VectorIntInitializer>
449  IndexList(const std::vector<int>& dims, VectorIntInitializer&& index)
450  : std::vector<int>(std::forward<VectorIntInitializer>(index)), p_dims(dims)
451  {
452  if (get_numel(dims.begin(), dims.end()) <= 0) {
453  throw InvalidIndexError("zero-sized array given by dimension list");
454  }
455  }
456 
464  TOMOGRAPHER_ENABLED_IF(IsRowMajor)
465  void setLinearIndex(int linearindex)
466  {
467  const int ndims = (int)p_dims.size();
468  for (int k = ndims-1; k >= 0; --k) {
469  this->at(k) = linearindex % p_dims[k];
470  linearindex /= p_dims[k]; // integer division
471  }
472  }
480  TOMOGRAPHER_ENABLED_IF(!IsRowMajor)
481  void setLinearIndex(int linearindex)
482  {
483  const int ndims = (int)p_dims.size();
484  for (int k = 0; k < ndims; ++k) {
485  this->at(k) = linearindex % p_dims[k];
486  linearindex /= p_dims[k]; // integer division
487  // std::cout << "k = " << k << "; p_dims = " << p_dims << "; at(k) = " << this->at(k)
488  // << "; linearindex=" << linearindex << "\n";
489  }
490  }
491 
496  TOMOGRAPHER_ENABLED_IF(IsRowMajor)
497  int linearIndex() const
498  {
499  int linindex = 0;
500  for (int k = 0; k < (int)p_dims.size(); ++k) {
501  linindex *= p_dims[k];
502  linindex += this->at(k);
503  }
504  return linindex;
505  }
510  TOMOGRAPHER_ENABLED_IF(!IsRowMajor)
511  int linearIndex() const
512  {
513  int linindex = 0;
514  for (int k = (int)p_dims.size()-1; k >= 0; --k) {
515  linindex *= p_dims[k];
516  linindex += this->at(k);
517  }
518  return linindex;
519  }
520 
523  inline const std::vector<int> & index() const
524  {
525  return *this;
526  }
527 
532  inline const std::vector<int> & dims() const
533  {
534  return p_dims;
535  }
536 
544  IndexList& operator<<(int ind) {
545  push_back(ind);
546  return *this;
547  }
548 
557  IndexList& operator<<(const std::vector<int>& moredims) {
558  insert(end(), moredims.begin(), moredims.end());
559  return *this;
560  }
561 
562 
563 
564  // for internal use:
565 
566  template<bool IsRowMajor2 = false>
567  static const std::vector<int> & forward_index(const IndexList<IsRowMajor2> & index)
568  {
569  return index;
570  }
571  template<bool IsRowMajor2 = false>
572  static std::vector<int> && forward_index(IndexList<IsRowMajor2> && index)
573  {
574  return std::move(index);
575  }
576 
577 private:
578  const std::vector<int> p_dims;
579 };
580 
581 
583 template<bool IsRowMajor>
584 inline std::ostream& operator<<(std::ostream& str, const IndexList<IsRowMajor> & indexlist)
585 {
586  str << "[";
587  for (std::size_t j = 0; j < indexlist.size(); ++j) {
588  str << indexlist[j];
589  if (j < indexlist.size()) {
590  str << ", ";
591  } else {
592  str << ";";
593  }
594  }
595  return str << "==" << indexlist.linearIndex() << "]";
596 }
597 
598 
602 template<bool IsRowMajor_ = false, typename IntType_ = int>
604 {
605 public:
606  static constexpr bool IsRowMajor = IsRowMajor_;
607  typedef IntType_ IntType;
608  typedef std::vector<IntType> VectorType;
609 
610 private:
611  const std::vector<IntType> p_dims;
612  const IntType p_numel;
613 
614  std::vector<IntType> p_index;
615  IntType p_linearIndex;
616 
617 public:
619  : p_dims(dims),
620  p_numel(get_numel(dims.begin(), dims.end())),
621  p_index(dims.size(), 0),
622  p_linearIndex(0)
623  {
624  if (p_numel <= 0) {
626  ss << "Invalid dimensions: " << p_dims;
627  throw InvalidIndexError(ss.str());
628  }
629  }
630 
631  inline const std::vector<IntType>& index() const
632  {
633  return p_index;
634  }
635 
636  inline IntType linearIndex() const
637  {
638  return p_linearIndex;
639  }
640 
641  inline IntType numel() const
642  {
643  return p_numel;
644  }
645 
646 
647  TOMOGRAPHER_ENABLED_IF(IsRowMajor)
648  IntType increment()
649  {
650  for (int k = p_dims.size() - 1; k >= 0; --k) {
651  p_index[k]++;
652  if (p_index[k] < p_dims[k]) {
653  // if this increment succeeded and stays in range, ok and stop.
654  break;
655  } else {
656  // otherwise continue the loop and increment the next value, while resetting
657  // this one to zero.
658  p_index[k] = 0;
659  }
660  }
661  return ++p_linearIndex;
662  }
663 
664  TOMOGRAPHER_ENABLED_IF(!IsRowMajor)
665  IntType increment()
666  {
667  for (int k = 0; k < (int)p_dims.size(); ++k) {
668  p_index[k]++;
669  if (p_index[k] < p_dims[k]) {
670  // if this increment succeeded and stays in range, ok and stop.
671  break;
672  } else {
673  // otherwise continue the loop and increment the next value, while resetting
674  // this one to zero.
675  p_index[k] = 0;
676  }
677  }
678  return ++p_linearIndex;
679  }
680 
681  IntType operator++() {
682  return increment();
683  }
684 
685  bool valid() const
686  {
687  return Tools::is_positive<IntType>(p_linearIndex) && p_linearIndex < p_numel;
688  }
689 
690 
691  // for internal use:
692 
693  template<bool IsRowMajor2 = false, typename IntType2 = int>
694  static const std::vector<IntType2> &
695  forward_index(const IndexListIterator<IsRowMajor2,IntType2> & index)
696  {
697  return index.p_index;
698  }
699  template<bool IsRowMajor2 = false, typename IntType2 = int>
700  static std::vector<IntType2> &&
701  forward_index(IndexListIterator<IsRowMajor2,IntType2> && index)
702  {
703  return std::move(index.p_index);
704  }
705 
706 };
707 
708 
710 template<bool IsRowMajor, typename IntType>
711 inline std::ostream& operator<<(std::ostream& str, const IndexListIterator<IsRowMajor, IntType> & indexlistit)
712 {
713  std::vector<int> indexlist{indexlistit.index()};
714 
715  str << "[";
716  for (std::size_t j = 0; j < indexlist.size(); ++j) {
717  str << indexlist[j];
718  if (j < indexlist.size()) {
719  str << ", ";
720  } else {
721  str << ";";
722  }
723  }
724  return str << "==" << indexlistit.linearIndex() << "]";
725 }
726 
727 
728 
729 
730 
759 template<typename T, typename Enabled = void>
761 {
767  typedef T RetType;
768 
775  static inline void checkShape(const Var & var)
776  {
777  (void)var; // silence "unused parameter" warnings
778  }
779 
794  static inline RetType decodeValue(const Var & var);
795 };
796 
797 
798 namespace tomo_internal {
799  // has_params_member<T>::value is true if T has a type member named Params,
800  // i.e. typename T::Params, else it is false.
801  template<typename T, typename Enabled = void>
802  struct has_params_member {
803  enum { value = 0 };
804  };
805  // if T has no Params member, following will fail by SFINAE
806  template<typename T>
807  struct has_params_member<T, typename T::Params>
808  {
809  enum { value = 1 };
810  };
811 }; // namespace tomo_internal
812 
813 
814 
815 class Var;
816 
817 template<typename T>
818 inline typename VarValueDecoder<T>::RetType value(const Var& var)
819 {
822 }
823 
824 template<typename T, TOMOGRAPHER_ENABLED_IF_TMPL( tomo_internal::has_params_member<VarValueDecoder<T> >::value )>
825 inline typename VarValueDecoder<T>::RetType value(const Var& var,
826  const typename VarValueDecoder<T>::Params & params)
827 {
828  VarValueDecoder<T>::checkShape(var, params);
829  return VarValueDecoder<T>::decodeValue(var, params);
830 }
831 
832 
833 
851 class Var
852 {
853 private:
854  struct VarData {
855  VarData() : refcount(0), p_matvar(NULL) { }
856  int refcount;
857  matvar_t * p_matvar;
858  std::string p_varname;
859  };
860  VarData *p_vardata;
861 
862  Var(matvar_t * varinfo) // take over the struct ownership
863  {
864  if (varinfo == NULL) {
865  throw VarReadError("<unknown>");
866  }
867  p_vardata = new VarData;
868  p_vardata->refcount++;
869  p_vardata->p_matvar = varinfo;
870  p_vardata->p_varname = std::string(varinfo->name);
871  }
872 
873 public:
884  Var(File & matf, const std::string& varname, bool load_data = true)
885  {
886  p_vardata = new VarData;
887  p_vardata->refcount++;
888  if (load_data) {
889  p_vardata->p_matvar = Mat_VarRead(matf.getMatPtr(), varname.c_str());
890  } else {
891  p_vardata->p_matvar = Mat_VarReadInfo(matf.getMatPtr(), varname.c_str());
892  }
893  if (p_vardata->p_matvar == NULL) {
894  delete p_vardata;
895  p_vardata = NULL;
896  throw VarReadError(varname);
897  }
898  p_vardata->p_varname = varname;
899  }
900 
902  Var(const Var& copy)
903  {
904  p_vardata = copy.p_vardata;
905  p_vardata->refcount++;
906  }
907 
909  Var(Var&& other)
910  {
911  // steal the data
912  p_vardata = other.p_vardata;
913  other.p_vardata = NULL;
914  }
915 
916  ~Var() {
917  if (p_vardata != NULL) {
918  p_vardata->refcount--;
919  if (!p_vardata->refcount) {
920  Mat_VarFree(p_vardata->p_matvar);
921  delete p_vardata;
922  }
923  }
924  }
925 
932  static Var takeOver(matvar_t * varinfo)
933  {
934  return Var(varinfo);
935  }
936 
941  inline const std::string & varName() const
942  {
943  assert(p_vardata != NULL);
944  return p_vardata->p_varname;
945  }
946 
951  inline int ndims() const
952  {
953  assert(p_vardata != NULL);
954  return p_vardata->p_matvar->rank;
955  }
960  inline DimList dims() const
961  {
962  assert(p_vardata != NULL);
963  return DimList(&p_vardata->p_matvar->dims[0],
964  &p_vardata->p_matvar->dims[p_vardata->p_matvar->rank]);
965  }
970  inline int numel() const
971  {
972  assert(p_vardata != NULL);
973  return dims().numel();
974  }
983  inline bool isComplex() const
984  {
985  assert(p_vardata != NULL);
986  return p_vardata->p_matvar->isComplex;
987  }
992  inline bool isSquareMatrix() const
993  {
994  assert(p_vardata != NULL);
995  return p_vardata->p_matvar->rank == 2 && p_vardata->p_matvar->dims[0] == p_vardata->p_matvar->dims[1];
996  }
997 
1003  inline bool hasData() const
1004  {
1005  assert(p_vardata != NULL);
1006  return (p_vardata->p_matvar->data != NULL);
1007  }
1008 
1047  template<typename T>
1048  inline typename VarValueDecoder<T>::RetType value() const
1049  {
1050  return Tomographer::MAT::value<T>(*this);
1051  }
1062  template<typename T, TOMOGRAPHER_ENABLED_IF_TMPL( tomo_internal::has_params_member<VarValueDecoder<T> >::value )>
1063  inline typename VarValueDecoder<T>::RetType value(const typename VarValueDecoder<T>::Params & params)
1064  {
1065  return Tomographer::MAT::value<T>(*this, params);
1066  }
1067 
1073  const matvar_t * getMatvarPtr() const
1074  {
1075  assert(p_vardata != NULL);
1076  return p_vardata->p_matvar;
1077  }
1078 
1082  Var& operator=(Var&& other)
1083  {
1084  // steal the data
1085  p_vardata = other.p_vardata;
1086  other.p_vardata = NULL;
1087  return *this;
1088  }
1090  Var& operator=(const Var& copy)
1091  {
1092  p_vardata = copy.p_vardata;
1093  p_vardata->refcount++;
1094  return *this;
1095  }
1096 };
1097 
1098 
1099 // ---------------
1100 
1101 
1102 inline Var File::var(const std::string varname, bool load_data)
1103 {
1104  return Var(*this, varname, load_data);
1105 }
1106 
1108 {
1109  std::vector<Var> varlist;
1110 
1111  Mat_Rewind(p_matfp);
1112  matvar_t * p = NULL;
1113  while ( (p = Mat_VarReadNextInfo(p_matfp)) != NULL ) {
1114  varlist.push_back(Var::takeOver(p));
1115  }
1116 
1117  return varlist;
1118 }
1119 
1120 
1121 template<typename T, typename Enabled>
1122 // static
1124 {
1125  throw std::runtime_error(std::string("Not Implemented: Please specialize MAT::VarValueDecoder<> for ")
1126  + typeid(T).name() + " to decode variable " + var.varName());
1127 }
1128 
1129 
1130 
1131 
1132 
1133 // =============================================================================
1134 // Some basic utilities for dealing with MATLAB variables
1135 // =============================================================================
1136 
1137 
1138 
1150 template<int MatTypeId = -1> struct MatType { };
1152 template<> struct MatType<MAT_T_DOUBLE> { typedef double Type; };
1154 template<> struct MatType<MAT_T_SINGLE> { typedef float Type; };
1156 template<> struct MatType<MAT_T_INT64> { typedef int64_t Type; };
1158 template<> struct MatType<MAT_T_INT32> { typedef int32_t Type; };
1160 template<> struct MatType<MAT_T_INT16> { typedef int16_t Type; };
1162 template<> struct MatType<MAT_T_INT8> { typedef int8_t Type; };
1164 template<> struct MatType<MAT_T_UINT64> { typedef uint64_t Type; };
1166 template<> struct MatType<MAT_T_UINT32> { typedef uint32_t Type; };
1168 template<> struct MatType<MAT_T_UINT16> { typedef uint16_t Type; };
1170 template<> struct MatType<MAT_T_UINT8> { typedef uint8_t Type; };
1171 
1172 
1179 #define MAT_SWITCH_REAL_TYPE(typ, ...) \
1180  do { switch (typ) { \
1181  case MAT_T_DOUBLE: { typedef typename MatType<MAT_T_DOUBLE>::Type Type; { __VA_ARGS__; } break; } \
1182  case MAT_T_SINGLE: { typedef typename MatType<MAT_T_SINGLE>::Type Type; { __VA_ARGS__; } break; } \
1183  case MAT_T_INT64: { typedef typename MatType<MAT_T_INT64>::Type Type; { __VA_ARGS__; } break; } \
1184  case MAT_T_INT32: { typedef typename MatType<MAT_T_INT32>::Type Type; { __VA_ARGS__; } break; } \
1185  case MAT_T_INT16: { typedef typename MatType<MAT_T_INT16>::Type Type; { __VA_ARGS__; } break; } \
1186  case MAT_T_INT8: { typedef typename MatType<MAT_T_INT8>::Type Type; { __VA_ARGS__; } break; } \
1187  case MAT_T_UINT64: { typedef typename MatType<MAT_T_UINT64>::Type Type; { __VA_ARGS__; } break; } \
1188  case MAT_T_UINT32: { typedef typename MatType<MAT_T_UINT32>::Type Type; { __VA_ARGS__; } break; } \
1189  case MAT_T_UINT16: { typedef typename MatType<MAT_T_UINT16>::Type Type; { __VA_ARGS__; } break; } \
1190  case MAT_T_UINT8: { typedef typename MatType<MAT_T_UINT8>::Type Type; { __VA_ARGS__; } break; } \
1191  default: \
1192  throw VarMatTypeError( streamstr("Uknown/unsupported encoded type from matio: " \
1193  <<(typ)) ); \
1194  } \
1195  } while (false)
1196 
1203 #define MAT_SWITCH_COMPLEX_TYPE(typ, ...) \
1204  do { switch (typ) { \
1205  case MAT_T_DOUBLE: { typedef std::complex<typename MatType<MAT_T_DOUBLE>::Type> Type; { __VA_ARGS__; } break; } \
1206  case MAT_T_SINGLE: { typedef std::complex<typename MatType<MAT_T_SINGLE>::Type> Type; { __VA_ARGS__; } break; } \
1207  default: \
1208  throw VarMatTypeError( streamstr("Uknown/unsupported encoded type from matio: " \
1209  <<(typ)) ); \
1210  } \
1211  } while (false)
1212 
1213 
1221 #define MAT_SWITCH_TYPE(matvar_ptr, ...) \
1222  do { \
1223  if (!(matvar_ptr)->isComplex) { \
1224  switch ((matvar_ptr)->data_type) { \
1225  case MAT_T_DOUBLE: { typedef typename MatType<MAT_T_DOUBLE>::Type Type; { __VA_ARGS__; } break; } \
1226  case MAT_T_SINGLE: { typedef typename MatType<MAT_T_SINGLE>::Type Type; { __VA_ARGS__; } break; } \
1227  case MAT_T_INT64: { typedef typename MatType<MAT_T_INT64>::Type Type; { __VA_ARGS__; } break; } \
1228  case MAT_T_INT32: { typedef typename MatType<MAT_T_INT32>::Type Type; { __VA_ARGS__; } break; } \
1229  case MAT_T_INT16: { typedef typename MatType<MAT_T_INT16>::Type Type; { __VA_ARGS__; } break; } \
1230  case MAT_T_INT8: { typedef typename MatType<MAT_T_INT8>::Type Type; { __VA_ARGS__; } break; } \
1231  case MAT_T_UINT64: { typedef typename MatType<MAT_T_UINT64>::Type Type; { __VA_ARGS__; } break; } \
1232  case MAT_T_UINT32: { typedef typename MatType<MAT_T_UINT32>::Type Type; { __VA_ARGS__; } break; } \
1233  case MAT_T_UINT16: { typedef typename MatType<MAT_T_UINT16>::Type Type; { __VA_ARGS__; } break; } \
1234  case MAT_T_UINT8: { typedef typename MatType<MAT_T_UINT8>::Type Type; { __VA_ARGS__; } break; } \
1235  default: \
1236  throw VarMatTypeError( streamstr("Uknown/unsupported encoded type from matio: " \
1237  << (matvar_ptr)->data_type) ); \
1238  } \
1239  } else { \
1240  switch ((matvar_ptr)->data_type) { \
1241  case MAT_T_DOUBLE: { typedef std::complex<typename MatType<MAT_T_DOUBLE>::Type> Type; { __VA_ARGS__; } break; } \
1242  case MAT_T_SINGLE: { typedef std::complex<typename MatType<MAT_T_SINGLE>::Type> Type; { __VA_ARGS__; } break; } \
1243  default: \
1244  throw VarMatTypeError( streamstr("Uknown/unsupported encoded type from matio: " \
1245  << (matvar_ptr)->data_type) ); \
1246  } \
1247  } \
1248  } while (false)
1249 
1250 
1251 
1252 
1253 // =============================================================================
1254 // now, let's define some ways to get variable values.
1255 // =============================================================================
1256 
1257 
1258 
1260 template<typename T>
1262  typename std::enable_if<(std::numeric_limits<T>::is_specialized ||
1263  Tools::is_complex<T>::value)>::type
1264  >
1265 {
1266  typedef T RetType;
1267 
1268  static inline void checkShape(const Var & var)
1269  {
1270  if (var.isComplex() && !Tools::is_complex<T>::value) {
1271  throw VarTypeError(var.varName(),
1272  streamstr("Can't store complex matrix in type " << typeid(T).name()));
1273  }
1274  if (var.numel() != 1) {
1275  throw VarTypeError(var.varName(),
1276  streamstr("Expected scalar but got matrix"));
1277  }
1278  }
1279 
1280  static inline RetType decodeValue(const Var & var)
1281  {
1282  const matvar_t * matvar_ptr = var.getMatvarPtr();
1283 
1284  MAT_SWITCH_TYPE(matvar_ptr,
1285  return get_value<Type>(matvar_ptr, var.varName());
1286  );
1287  // should never reach here
1288  assert(false);
1289  }
1290 
1291 private:
1292  template<typename MATType,
1293  TOMOGRAPHER_ENABLED_IF_TMPL(!Tools::is_complex<RetType>::value &&
1295  static inline RetType get_value(const matvar_t * matvar_ptr, const std::string & )
1296  {
1297  return (RetType) ((const MATType *) matvar_ptr->data)[0];
1298  }
1299 
1300  template<typename MATType,
1301  TOMOGRAPHER_ENABLED_IF_TMPL(Tools::is_complex<RetType>::value &&
1303  static inline RetType get_value(const matvar_t * matvar_ptr, const std::string & )
1304  {
1305  return RetType( ((const MATType *) matvar_ptr->data)[0],
1306  0 );
1307  }
1308 
1309  template<typename MATType,
1310  TOMOGRAPHER_ENABLED_IF_TMPL(!Tools::is_complex<RetType>::value &&
1312  static inline RetType get_value(const matvar_t * /*matvar_ptr*/, const std::string & varname)
1313  {
1314  throw VarTypeError(varname, "Expected real scalar, got complex type");
1315  }
1316 
1317  template<typename MATType,
1318  TOMOGRAPHER_ENABLED_IF_TMPL(Tools::is_complex<RetType>::value &&
1320  static inline RetType get_value(const matvar_t * matvar_ptr, const std::string & )
1321  {
1322  typedef typename Tools::complex_real_scalar<MATType>::type MATRealType;
1323  const mat_complex_split_t * cdata = (mat_complex_split_t*) matvar_ptr->data;
1324 
1325  return RetType( ((const MATRealType *) cdata->Re)[0],
1326  ((const MATRealType *) cdata->Im)[0] );
1327  }
1328 
1329 };
1330 
1331 
1332 
1333 // -----------------------------------------------
1334 
1335 
1336 namespace tomo_internal {
1337 
1339 template<typename OutType, typename MatInnerT>
1340 class VarMatDataAccessor
1341 {
1342  const Var & p_var;
1343 
1344  typedef typename Tools::complex_real_scalar<MatInnerT>::type MatRealInnerT;
1345 
1346  const MatInnerT * p_r_ptr;
1347  const MatRealInnerT * p_cre_ptr;
1348  const MatRealInnerT * p_cim_ptr;
1349 
1350 public:
1351  VarMatDataAccessor(const Var & var)
1352  : p_var(var)
1353  {
1354  const matvar_t * matvar_ptr = var.getMatvarPtr();
1355  assert(matvar_ptr->data != NULL);
1356  if (!matvar_ptr->isComplex) {
1357  // real type
1358  p_r_ptr = (const MatInnerT*) matvar_ptr->data;
1359  p_cre_ptr = NULL;
1360  p_cim_ptr = NULL;
1361  } else {
1362  const mat_complex_split_t * cdata = (mat_complex_split_t*) matvar_ptr->data;
1363  p_r_ptr = NULL;
1364  p_cre_ptr = (const MatRealInnerT*) cdata->Re;
1365  p_cim_ptr = (const MatRealInnerT*) cdata->Im;
1366  assert(p_cre_ptr != NULL);
1367  assert(p_cim_ptr != NULL);
1368  }
1369  }
1370 
1371  virtual ~VarMatDataAccessor() { }
1372 
1373  template<typename IndexListType,
1374  typename OutType__ = OutType, typename MatInnerT__ = MatInnerT,
1375  TOMOGRAPHER_ENABLED_IF_TMPL(!Tools::is_complex<OutType__>::value &&
1376  !Tools::is_complex<MatInnerT__>::value)>
1377  inline OutType value(IndexListType&& index) const
1378  {
1379  assert(p_r_ptr != NULL);
1380 
1381  // real value.
1382  std::size_t lin = linear_index(std::forward<IndexListType>(index));
1383  return p_r_ptr[lin];
1384  }
1385 
1386  template<typename IndexListType,
1387  typename OutType__ = OutType, typename MatInnerT__ = MatInnerT,
1388  TOMOGRAPHER_ENABLED_IF_TMPL(!Tools::is_complex<OutType__>::value &&
1389  Tools::is_complex<MatInnerT__>::value)>
1390  inline OutType value(IndexListType&& ) const
1391  {
1392  throw VarTypeError(p_var.varName(), "Expected real type, got complex");
1393  }
1394 
1395  template<typename IndexListType,
1396  typename OutType__ = OutType, typename MatInnerT__ = MatInnerT,
1397  TOMOGRAPHER_ENABLED_IF_TMPL(Tools::is_complex<OutType__>::value &&
1398  !Tools::is_complex<MatInnerT__>::value)>
1399  inline OutType value(IndexListType&& index) const
1400  {
1401  assert(p_r_ptr != NULL);
1402 
1403  // real value.
1404  std::size_t lin = linear_index(std::forward<IndexListType>(index));
1405  return OutType( p_r_ptr[lin] , 0 );
1406  }
1407 
1408  template<typename IndexListType,
1409  typename OutType__ = OutType, typename MatInnerT__ = MatInnerT,
1410  TOMOGRAPHER_ENABLED_IF_TMPL(Tools::is_complex<OutType__>::value &&
1411  Tools::is_complex<MatInnerT__>::value)>
1412  inline OutType value(IndexListType&& index) const
1413  {
1414  assert(p_cre_ptr != NULL);
1415  assert(p_cim_ptr != NULL);
1416 
1417  // complex value
1418  std::size_t lin = linear_index(std::forward<IndexListType>(index));
1419  return OutType(p_cre_ptr[lin], p_cim_ptr[lin]);
1420  }
1421 
1422 private:
1423  template<typename IndexListType>
1424  std::size_t linear_index(IndexListType && index) const
1425  {
1426  IndexList<false> ind_cmaj{
1427  p_var.dims(),
1429  };
1430  // std::cout << "linear_index: ind_cmaj=" << ind_cmaj << ", -> linear index = " << ind_cmaj.linearIndex() << "\n";
1431  return ind_cmaj.linearIndex();
1432  }
1433 };
1434 
1435 } // namespace tomo_internal
1436 
1437 
1438 // -----------------------------------------------
1439 
1480 struct VarShape
1481 {
1489  const bool is_complex;
1490 
1505  const DimList dims;
1506 
1521  const bool is_square;
1522 
1527  template<typename DimListType>
1528  VarShape(bool is_complex_, DimListType&& dims_, bool is_square_)
1529  : is_complex(is_complex_), dims(std::forward<DimListType>(dims_)), is_square(is_square_)
1530  {
1531  _check_consistency();
1532  }
1533 
1539  VarShape(const Var & var)
1540  : is_complex(var.isComplex()), dims(var.dims()), is_square(var.isSquareMatrix())
1541  {
1542  }
1543 
1544 
1545 private:
1546  void _check_consistency()
1547  {
1548  if (is_square) {
1549  assert(dims.size() == 0 || (dims.size() == 2 && (dims[0] == -1 || dims[1] == -1 || dims[0] == dims[1])));
1550  }
1551  }
1552 
1553 public:
1554 
1562  inline void checkShape(const VarShape & shape);
1563 
1571  inline void checkShape(const Var & var)
1572  {
1573  try {
1574  checkShape(VarShape(var));
1575  } catch (VarTypeError & err) {
1576  err.setVarName(var.varName());
1577  throw;
1578  }
1579  }
1580 };
1581 
1583 inline std::ostream& operator<<(std::ostream& str, const VarShape & varshape)
1584 {
1585  str << ((varshape.is_complex) ? std::string("complex ") : std::string("real "));
1586  if (varshape.dims.size() == 1) {
1587  str << "vector";
1588  } else if (varshape.dims.size() == 2) {
1589  if (varshape.is_square) {
1590  str << "square ";
1591  }
1592  str << "matrix";
1593  } else if (varshape.dims.size() > 0) {
1594  str << varshape.dims.size() << "-D array";
1595  if (varshape.is_square) {
1596  str << " with first two dimensions square";
1597  }
1598  } else {
1599  // empty dims means no requirement
1600  str << "array";
1601  }
1602  if (varshape.dims.size()) {
1603  str << " of shape " << varshape.dims;
1604  }
1605  return str;
1606 }
1607 
1608 inline void VarShape::checkShape(const VarShape& other)
1609 {
1610  const DimList mvardims = other.dims;
1611 
1612  if ((other.is_complex && !is_complex) ||
1613  (mvardims.size() != dims.size() && dims.size() > 0) ||
1614  (is_square && (mvardims.size() != 2 || mvardims[0] != mvardims[1])) ||
1615  (dims.size() > 0 && !mvardims.matchesWanted(dims))) {
1616 
1617  std::stringstream errstr;
1618 
1619  errstr << "Expected "
1620  << *this
1621  << ", got "
1622  << other;
1623 
1624  //fprintf(stderr, "Bad var type for variable %s\n", var.varName().c_str());
1625  throw VarTypeError(std::string(), errstr.str());
1626 
1627  }
1628 }
1629 
1630 
1631 
1632 // -----------------------------------------------------------------------------
1633 
1634 // get an std::vector<T> for a variable.
1635 
1645 template<typename T_, bool IsRowMajor_ = false>
1647  typedef T_ type;
1648  static constexpr bool IsRowMajor = IsRowMajor_;
1649 };
1650 
1652 template<typename T, bool IsRowMajor>
1653 struct VarValueDecoder<GetStdVector<T, IsRowMajor> >
1654 {
1655  typedef std::vector<T> RetType;
1656 
1657  static inline void checkShape(const Var & var)
1658  {
1659  if (var.isComplex() && !Tools::is_complex<T>::value) {
1660  throw VarTypeError(var.varName(),
1661  std::string("can't store complex matrix in type ")
1662  + typeid(T).name());
1663  }
1664  }
1665 
1666  static inline std::vector<T> decodeValue(const Var & var)
1667  {
1668  const matvar_t * matvar_ptr = var.getMatvarPtr();
1669  std::size_t numel = var.numel();
1670  std::vector<T> val(numel);
1671 
1672  MAT_SWITCH_TYPE(matvar_ptr,
1673  tomo_internal::VarMatDataAccessor<T, Type> acc(var);
1674 
1675  for(IndexListIterator<IsRowMajor> il(var.dims()); il.valid(); ++il) {
1676  // std::cout << "index: " << il << "\n";
1677  val[il.linearIndex()] = acc.value(il);
1678  }
1679 
1680  return val;
1681  );
1682  // should never reach here
1683  assert(false);
1684  }
1685 
1686 };
1687 
1688 
1689 
1690 
1691 
1692 
1693 
1694 // =============================================================================
1695 
1696 // get Eigen types.
1697 
1698 namespace tomo_internal {
1699 
1700 
1701 inline DimList dims_stackedcols(DimList vdims)
1702 {
1703  assert(vdims.size() >= 1);
1704  DimList vdimsreshaped;
1705  if (vdims.size() == 1) {
1706  vdimsreshaped = vdims;
1707  vdimsreshaped << 1;
1708  } else if (vdims.size() == 2) {
1709  vdimsreshaped = vdims;
1710  } else if (vdims.size() > 2) {
1711  vdimsreshaped << get_numel(vdims.data(), vdims.data()+vdims.size()-1) << vdims[vdims.size()-1];
1712  }
1713  assert(vdimsreshaped[0] != -1 && vdimsreshaped[1] != -1);
1714  return vdimsreshaped;
1715 }
1716 
1717 template<typename MatrixType, typename MatType,
1718  TOMOGRAPHER_ENABLED_IF_TMPL(Eigen::NumTraits<typename MatrixType::Scalar>::IsComplex &&
1720 void init_eigen_matrix(MatrixType & matrix, const DimList & vdims,
1721  const Var & var, const std::ptrdiff_t data_offset = 0)
1722 {
1723  typedef typename MatrixType::Scalar Scalar;
1724  typedef typename Eigen::NumTraits<Scalar>::Real RealScalar;
1725 
1726  typedef typename Eigen::NumTraits<MatType>::Real MatRealType;
1727 
1728  const matvar_t * matvar_ptr = var.getMatvarPtr();
1729 
1730  const mat_complex_split_t * cdata = (mat_complex_split_t*) matvar_ptr->data;
1731 
1732  DimList vdimsreshaped = dims_stackedcols(vdims);
1733 
1734  matrix = (
1736  (const MatRealType *) cdata->Re + data_offset, vdimsreshaped[0], vdimsreshaped[1]
1737  ).template cast<std::complex<RealScalar> >()
1738  + std::complex<RealScalar>(0,1) *
1740  (const MatRealType *) cdata->Im + data_offset, vdimsreshaped[0], vdimsreshaped[1]
1741  ).template cast<std::complex<RealScalar> >()
1742  );
1743 }
1744 
1745 template<typename MatrixType, typename MatRealType,
1746  TOMOGRAPHER_ENABLED_IF_TMPL(!Eigen::NumTraits<typename MatrixType::Scalar>::IsComplex &&
1748 void init_eigen_matrix(MatrixType & /*matrix*/, const DimList & /*vdims*/,
1749  const Var & var, const std::ptrdiff_t /*data_offset*/ = 0)
1750 {
1751  throw VarTypeError(var.varName(), "Expected real type, but got complex.");
1752 }
1753 
1754 template<typename MatrixType, typename MatRealType,
1755  TOMOGRAPHER_ENABLED_IF_TMPL(!Eigen::NumTraits<MatRealType>::IsComplex)>
1756 void init_eigen_matrix(MatrixType & matrix, const DimList & vdims,
1757  const Var & var, const std::ptrdiff_t data_offset = 0)
1758 {
1759  typedef typename MatrixType::Scalar Scalar;
1760 
1761  const matvar_t * matvar_ptr = var.getMatvarPtr();
1762 
1763  DimList vdimsreshaped = dims_stackedcols(vdims);
1764 
1765  matrix = (
1767  (const MatRealType *) matvar_ptr->data + data_offset, vdimsreshaped[0], vdimsreshaped[1]
1768  )
1769  ).template cast<Scalar>();
1770 }
1771 
1772 } // namespace tomo_internal
1773 
1774 
1775 
1784 template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
1785 struct VarValueDecoder<Eigen::Matrix<Scalar,Rows,Cols,Options,MaxRows,MaxCols> >
1786 {
1788  typedef typename Eigen::NumTraits<Scalar>::Real RealScalar;
1789  typedef MatrixType RetType;
1790 
1791  /* not needed in fact.
1792  struct Params {
1793  Params() : dims{Rows, Cols}
1794  {
1795  }
1796  Params(int rows) : dims{rows, 1}
1797  {
1798  assert(Cols == 1);
1799  assert(Rows == Eigen::Dynamic || Rows == rows);
1800  }
1801  Params(int rows, int cols) : dims{rows, cols}
1802  {
1803  assert(Rows == Eigen::Dynamic || Rows == rows);
1804  assert(Cols == Eigen::Dynamic || Cols == cols);
1805  }
1806  Params(const DimList& dims_) : dims{dims_}
1807  {
1808  assert(dims.size() == 2);
1809  assert(Rows == Eigen::Dynamic || Rows == dims[0]);
1810  assert(Cols == Eigen::Dynamic || Cols == dims[1]);
1811  }
1812 
1813  const DimList dims;
1814  };
1815  */
1816 
1817  static inline void checkShape(const Var & var) //, const Params & p = Params())
1818  {
1819  DimList matdims;
1820  matdims << (Rows!=Eigen::Dynamic ? Rows : -1)
1821  << (Cols!=Eigen::Dynamic ? Cols : -1);
1822 
1824  matdims,
1825  matdims[0] != -1 && matdims[0] == matdims[1]);
1826 
1827  DimList vdims = var.dims();
1828  if (vdims.size() > 2) {
1829  vdims = (DimList() << get_numel(vdims.data(), vdims.data()+vdims.size()-1) << vdims[vdims.size()-1]);
1830  }
1831  try {
1832  shape.checkShape(VarShape(var.isComplex(), vdims, (vdims[0] != -1 && vdims[0] == vdims[1])));
1833  } catch (VarTypeError & err) {
1834  err.setVarName(var.varName());
1835  throw; // re-throw
1836  }
1837  }
1838 
1839  static inline RetType decodeValue(const Var & var) //, const Params & p = Params())
1840  {
1841  const matvar_t * matvar_ptr = var.getMatvarPtr();
1842  DimList vdims{var.dims()};
1843 
1844  if (vdims.size() < 2) {
1845  throw VarTypeError(var.varName(), streamstr("Expected matrix, but variable shape is " << vdims));
1846  }
1847  // if we are stacking several dimensions in the column, force column-major ordering.
1848  if (vdims.size() > 2 &&
1849  ((MatrixType::Options & Eigen::RowMajorBit) == Eigen::RowMajor)) {
1850  throw VarTypeError(var.varName(),
1851  "When collapsing several dimensions into Eigen columns, you must use "
1852  "column-major ordering (sorry).");
1853  }
1854 
1855  const int cols = vdims[vdims.size()-1];
1856  // rest of dimensions.
1857  const int rows = get_numel(vdims.data(), vdims.data()+vdims.size()-1);
1858 
1859  MatrixType matrix(rows, cols);
1860 
1862  matvar_ptr,
1863  tomo_internal::init_eigen_matrix<MatrixType, Type>(
1864  matrix, vdims, var
1865  );
1866  );
1867 
1868  return matrix;
1869  }
1870 
1871 };
1872 
1873 
1874 
1875 
1876 
1886 template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols, typename Alloc>
1887 struct VarValueDecoder<std::vector<Eigen::Matrix<Scalar,Rows,Cols,Options,MaxRows,MaxCols>, Alloc> >
1888 {
1890  typedef typename Eigen::NumTraits<Scalar>::Real RealScalar;
1891 
1893 
1894  static inline void checkShape(const Var & var)
1895  {
1896  DimList matdims;
1897  matdims << (Rows!=Eigen::Dynamic ? Rows : -1)
1898  << (Cols!=Eigen::Dynamic ? Cols : -1)
1899  << -1;
1900 
1902  matdims,
1903  false);
1904 
1905  DimList vdims = var.dims();
1906  if (vdims.size() < 1) {
1907  throw VarTypeError(var.varName(), "Invalid (empty) variable dimensions");
1908  }
1909  if (vdims.size() == 1) {
1910  vdims << 1 << 1;
1911  } else if (vdims.size() == 2) {
1912  vdims << 1;
1913  } else { //if (vdims.size() > 2) {
1914  vdims = (DimList() << vdims[0] << vdims[1] << get_numel(vdims.data()+2, vdims.data()+vdims.size()));
1915  }
1916 
1917  // check shape now:
1918  try {
1919  shape.checkShape(VarShape(var.isComplex(), vdims, false));
1920  } catch (VarTypeError & err) {
1921 
1922  err.setVarName(var.varName());
1923  throw; // re-throw
1924  }
1925 
1926  }
1927 
1928  static inline RetType decodeValue(const Var & var)
1929  {
1930  DimList vardims{var.dims()};
1931 
1932  assert(vardims.size() >= 1);
1933 
1934  DimList innerdims;
1935  std::size_t outerdim = 1;
1936  if (vardims.size() == 1) {
1937  innerdims << vardims[0] << 1;
1938  } else if (vardims.size() == 2) {
1939  innerdims = vardims;
1940  } else {
1941  // more dimensions
1942  innerdims << vardims[0] << vardims[1];
1943  outerdim = get_numel(vardims.data()+2, vardims.data()+vardims.size());
1944  }
1945 
1946  RetType value(outerdim);
1947 
1948  std::ptrdiff_t innernumel = innerdims[0]*innerdims[1];
1949 
1950  std::size_t j;
1951  const matvar_t * matvar_ptr = var.getMatvarPtr();
1952 
1954  matvar_ptr,
1955  for (j = 0; j < outerdim; ++j) {
1956  tomo_internal::init_eigen_matrix<MatrixType,Type>(
1957  value[j], // matrix reference
1958  innerdims, // dimensions of matrix reference
1959  var, // data
1960  j*innernumel // offset
1961  );
1962  }
1963  );
1964 
1965  return value;
1966  }
1967 
1968 };
1969 
1970 
1971 } // namespace MAT
1972 } // namespace Tomographer
1973 
1974 
1975 
1976 
1977 #endif
Utilities for formatting strings.
static void checkShape(const Var &var)
Check that the type and shape of the var are compatible with T.
Definition: ezmatio.h:775
Utility to iterate over a multidim array by increasing linear index.
Definition: ezmatio.h:603
File(File &&other)
Move constructor.
Definition: ezmatio.h:224
bool hasData() const
Whether data for this Var object has been loaded.
Definition: ezmatio.h:1003
bool isComplex() const
Whether this variable is complex or real.
Definition: ezmatio.h:983
Base namespace for the Tomographer project.
Definition: dmmhrw.h:51
IndexList(const std::vector< int > &dims=std::vector< int >(), int linearindex=-1)
Constructor with linear index.
Definition: ezmatio.h:429
Var var(const std::string varname, bool load_data=true)
Find a variable by name.
Definition: ezmatio.h:1102
Invalid index or index list provided to a routine.
Definition: ezmatio.h:177
Unknown type of a variable present in the data file.
Definition: ezmatio.h:134
void checkShape(const Var &var)
Shorthand for checkShape(const VarShape& other) for a shape given by a variable.
Definition: ezmatio.h:1571
Error while reading a variable from the MATLAB data file.
Definition: ezmatio.h:112
int ndims() const
Number of dimensions of this object.
Definition: ezmatio.h:951
static constexpr bool IsRowMajor
Is this class calculating and expecting row-major (true) or column-major (false) format.
Definition: ezmatio.h:420
A MATLAB file open for reading data.
Definition: ezmatio.h:201
STL namespace.
STL class.
Var & operator=(Var &&other)
Move assignment operator as this object implements C++11 move semantics.
Definition: ezmatio.h:1082
int end(int...args)
File(const std::string fname)
Open a data file for reading.
Definition: ezmatio.h:209
bool matchesWanted(const DimList &wanted) const
Test whether our dimensions match the given required list of dimensions.
Definition: ezmatio.h:350
A list of indices with an API for linear or subindices access.
Definition: ezmatio.h:416
Base Exception class for errors within our MAT routines.
Definition: ezmatio.h:69
void setLinearIndex(int linearindex)
Set the linear index.
Definition: ezmatio.h:465
IndexList & operator<<(int ind)
Append index to list.
Definition: ezmatio.h:544
const std::string & varName() const
The variable name.
Definition: ezmatio.h:941
IndexList(const std::vector< int > &dims, VectorIntInitializer &&index)
Constructor with multidimensional index specification.
Definition: ezmatio.h:449
std::vector< Var > getVarInfoList()
Get a list of all variables in this data file.
Definition: ezmatio.h:1107
STL class.
Map matio's constants to C/C++ types.
Definition: ezmatio.h:1150
int at(int...args)
Error while opening a MATLAB file.
Definition: ezmatio.h:148
int push_back(int...args)
static Var takeOver(matvar_t *varinfo)
Take in charge the given C matvar_t pointer.
Definition: ezmatio.h:932
T data(T...args)
Var(Var &&other)
Var implements C++11 move semantics.
Definition: ezmatio.h:909
void checkShape(const VarShape &shape)
Verify that our requirements match the given other shape.
Definition: ezmatio.h:1608
const bool is_complex
Whether the variable is or should be complex.
Definition: ezmatio.h:1489
A MATLAB variable in the MAT file.
Definition: ezmatio.h:851
std::vector< int > VectorType
Base vector type (superclass)
Definition: ezmatio.h:422
bool isSquareMatrix() const
Whether this is a square matrix.
Definition: ezmatio.h:992
VarValueDecoder< T >::RetType value() const
Read this variable data as native C++ object.
Definition: ezmatio.h:1048
int numel() const
The total number of elements in this array or tensor.
Definition: ezmatio.h:970
Ask for this type in Var::value() to get an std::vector of the data.
Definition: ezmatio.h:1646
int ndims() const
Get the number of dimensions in this array.
Definition: ezmatio.h:345
STL class.
T move(T...args)
DimList dims() const
Specific dimensions of this numeric array or tensor.
Definition: ezmatio.h:960
int insert(int...args)
int size(int...args)
std::ostream & operator<<(std::ostream &out, const DimList &dlist)
C++ output stream operators for a DimList.
Definition: ezmatio.h:374
#define MAT_SWITCH_TYPE(matvar_ptr,...)
Useful hack to get C++ type from dynamical MAT type ID.
Definition: ezmatio.h:1221
STL class.
An array of ints which specifies a list of dimensions.
Definition: ezmatio.h:314
T RetType
Type returned by decodeValue()
Definition: ezmatio.h:767
Var & operator=(const Var &copy)
Var objects are copyable. Beware though that the data is shared.
Definition: ezmatio.h:1090
VarShape(bool is_complex_, DimListType &&dims_, bool is_square_)
Construct a VarShape object from given characteristics.
Definition: ezmatio.h:1528
File & operator=(File &&other)
Move assignment operator.
Definition: ezmatio.h:272
int begin(int...args)
VarShape(const Var &var)
Construct a VarShape object reflecting the actual shape of a variable in the data file...
Definition: ezmatio.h:1539
T c_str(T...args)
Specializable template which takes care of decoding values.
Definition: ezmatio.h:760
const std::vector< int > & index() const
Return a reference to *this.
Definition: ezmatio.h:523
Type mismatch (wrong type requested) in a variable read from the MATLAB data file.
Definition: ezmatio.h:123
Exception relating to a MATLAB variable in the data file.
Definition: ezmatio.h:98
Describe shape of variable and whether it is complex.
Definition: ezmatio.h:1480
mat_t * getMatPtr()
Direct access to the underlying C pointer used for the MatIO library.
Definition: ezmatio.h:262
int numel() const
Get the total number of elements in an array of these dimensions.
Definition: ezmatio.h:338
const unsigned int RowMajorBit
int linearIndex() const
Linear index corresponding to the stored multidimensional indices.
Definition: ezmatio.h:497
const std::vector< int > & dims() const
Get the underlying dimensions given to the constructor.
Definition: ezmatio.h:532
#define streamstr(tokens)
Utility macro to format stream tokens to a std::string.
Definition: fmt.h:143
Var(File &matf, const std::string &varname, bool load_data=true)
Read variable from MATLAB data file.
Definition: ezmatio.h:884
Var(const Var &copy)
Var objects are copyable. Beware though that the data is shared.
Definition: ezmatio.h:902
ValueType get_numel(It begin, It end)
Calculate the product of all dimensions.
Definition: ezmatio.h:292
statically determine whether a type is complex
Definition: util.h:61
STL class.
const DimList dims
The dimensions of the variable, or requested dimensions.
Definition: ezmatio.h:1505
static RetType decodeValue(const Var &var)
Decode the variable var into the C++ type T.
Definition: ezmatio.h:1123
RowMajor
Basic utilities for dealing with Eigen matrices and other types.
const bool is_square
Whether the variable's two first dimensions are (or should be) the same.
Definition: ezmatio.h:1521
VarValueDecoder< T >::RetType value(const typename VarValueDecoder< T >::Params &params)
Read this variable data as native C++ object.
Definition: ezmatio.h:1063
const matvar_t * getMatvarPtr() const
Access the underlying C pointer to the MatIO structure. Use with care.
Definition: ezmatio.h:1073