Tomographer  v2.0
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 
51 #include <tomographer2/tools/fmt.h>
52 
53 
61 namespace Tomographer {
62 // namespace doc in doc/doxdocs/namespaces.cxx
63 namespace MAT {
64 
65 
68 class Exception : public std::exception
69 {
70  std::string p_heading;
71  std::string p_message;
72  std::string p_final;
73 public:
74  Exception(std::string msg) : p_message(msg) { update_final(); }
75  Exception(std::string heading, std::string msg) : p_heading(heading), p_message(msg) { update_final(); }
76  virtual ~Exception() noexcept { }
77 
78  virtual const char * what() const noexcept { return p_final.c_str(); }
79 
80 protected:
81  inline void setHeading(const std::string heading) {
82  p_heading = heading;
83  update_final();
84  }
85  inline void setMessage(const std::string message) {
86  p_message = message;
87  update_final();
88  }
89 private:
90  inline void update_final() {
91  p_final = p_heading + p_message;
92  }
93 };
94 
97 class VarError : public Exception
98 {
99 public:
100  VarError(std::string msg) : Exception("", msg) { }
101  VarError(std::string varname, std::string msg) : Exception(heading(varname), msg) { }
102  virtual ~VarError() noexcept { }
103 
104  void setVarName(std::string varname) { setHeading(heading(varname)); }
105 
106 private:
107  static std::string heading(std::string varname) { return "Variable " + varname + ": "; }
108 };
109 
111 class VarReadError : public VarError
112 {
113 public:
114  VarReadError(const std::string varname)
115  : VarError(varname, "Can't read variable")
116  {
117  }
118  virtual ~VarReadError() noexcept { }
119 };
120 
122 class VarTypeError : public VarError
123 {
124 public:
125  VarTypeError(const std::string varname, const std::string msg)
126  : VarError(varname, msg)
127  {
128  }
129  virtual ~VarTypeError() noexcept { }
130 };
131 
133 class VarMatTypeError : public VarError {
134 public:
135  VarMatTypeError(const std::string msg)
136  : VarError(msg)
137  {
138  }
139  VarMatTypeError(const std::string varname, const std::string msg)
140  : VarError(varname, msg)
141  {
142  }
143  virtual ~VarMatTypeError() noexcept { }
144 };
145 
147 class FileOpenError : public Exception
148 {
149 public:
150  FileOpenError(const std::string fname, const std::string errmsg = std::string())
151  : Exception(heading(fname), "Error opening file" + (errmsg.size() ? "': "+errmsg : ""))
152  {
153  }
154  virtual ~FileOpenError() noexcept { }
155 
156  void setFileName(const std::string fname) {
157  setHeading(heading(fname));
158  }
159 
160 private:
161  static std::string heading(std::string fname) { return "File `"+fname+"`: "; }
162 };
163 
164 
166 class InvalidIndexError : public Exception {
167 public:
168  InvalidIndexError(const std::string msg) : Exception("Invalid index: ", msg) { }
169  virtual ~InvalidIndexError() noexcept { }
170 };
171 
172 
173 
174 
175 
176 class Var;
177 
178 
190 class File
191 {
192 public:
198  File(const std::string fname)
199  {
200  errno = 0;
201  p_matfp = Mat_Open(fname.c_str(), MAT_ACC_RDONLY);
202  if ( p_matfp == NULL ) {
203  throw FileOpenError(fname, strerror(errno));
204  }
205  }
206  File(const File& other) = delete;
207 
213  File(File&& other)
214  {
215  // move constructor. Steal the other object's MAT file handle
216  p_matfp = other.p_matfp;
217  other.p_matfp = NULL;
218  }
219 
220  ~File()
221  {
222  if ( p_matfp != NULL ) {
223  Mat_Close(p_matfp);
224  }
225  }
226 
236  inline Var var(const std::string varname, bool load_data = true);
237 
238 
244  inline std::vector<Var> getVarInfoList();
245 
251  mat_t * getMatPtr()
252  {
253  return p_matfp;
254  }
255 
261  File& operator=(File&& other)
262  {
263  // move assignment operator. Steal the other object's MAT file handle
264  p_matfp = other.p_matfp;
265  other.p_matfp = NULL;
266  return *this;
267  }
268  File& operator=(const File& other) = delete;
269 
270 private:
271  mat_t *p_matfp;
272 };
273 
274 
280 template<typename It, typename ValueType = typename std::iterator_traits<It>::value_type>
281 ValueType getNumEl(It begin, It end)
282 {
283  ValueType n = 1;
284  for (It it = begin; it != end; ++it) {
285  n *= (*it);
286  }
287  return n;
288 }
289 
290 
304 class DimList : public std::vector<int>
305 {
306 public:
308  DimList() : std::vector<int>() { }
309 
315  template<typename VectorType>
316  DimList(VectorType&& dims)
317  : std::vector<int>(std::forward<VectorType>(dims))
318  {
319  }
333  : std::vector<int>(init)
334  {
335  }
341  template<class It>
342  DimList(It b, It e) : std::vector<int>(b, e)
343  {
344  }
345 
350  inline int numel() const { return getNumEl(begin(), end()); }
351 
357  inline int ndims() const { return (int)size(); }
358 
362  inline bool matchesWanted(const DimList& wanted) const
363  {
364  if (size() != wanted.size()) {
365  return false;
366  }
367  for (std::size_t k = 0; k < size(); ++k) {
368  if (wanted[k] >= 0 && this->operator[](k) != wanted[k]) {
369  return false;
370  }
371  }
372  return true;
373  }
374 
380  DimList& operator<<(int dim) {
381  push_back(dim);
382  return *this;
383  }
389  DimList& operator<<(const std::vector<int>& moredims) {
390  insert(end(), moredims.begin(), moredims.end());
391  return *this;
392  }
393 };
394 
396 inline std::ostream& operator<<(std::ostream& out, const DimList& dlist)
397 {
398  out << "[";
399  for (DimList::const_iterator it = dlist.begin(); it != dlist.end(); ++it) {
400  if (it != dlist.begin()) {
401  out << " ";
402  }
403  if (*it == -1) {
404  // usually meant for arbitrary size requirement. In any case, it is not a physical
405  // array size.
406  out << '*';
407  } else {
408  out << *it;
409  }
410  }
411  out << "]";
412  return out;
413 }
414 
437 template<bool IsRowMajor_ = false>
438 class IndexList : public std::vector<int>
439 {
440 public:
442  static constexpr bool IsRowMajor = IsRowMajor_;
445 
451  IndexList(const std::vector<int>& dims = std::vector<int>(), int linearindex = -1)
452  : std::vector<int>(dims.size()), p_dims(dims)
453  {
454  if (getNumEl(dims.begin(), dims.end()) <= 0) {
455  throw InvalidIndexError("zero-sized array given by dimension list");
456  }
457  if (linearindex >= 0) {
458  setLinearIndex(linearindex);
459  }
460  }
467  // the reason we dont have template<typename... VectorArgs> for std::vector<>
468  // constructor is that g++ 4.6 if I remember correctly can't unpack arguments into a
469  // fixed number of arguments (TODO: CHECK THIS!)
470  template<typename VectorIntInitializer>
471  IndexList(const std::vector<int>& dims, VectorIntInitializer&& index)
472  : std::vector<int>(std::forward<VectorIntInitializer>(index)), p_dims(dims)
473  {
474  if (getNumEl(dims.begin(), dims.end()) <= 0) {
475  throw InvalidIndexError("zero-sized array given by dimension list");
476  }
477  }
478 
486  TOMOGRAPHER_ENABLED_IF(IsRowMajor)
487  void setLinearIndex(int linearindex)
488  {
489  const int ndims = (int)p_dims.size();
490  for (int k = ndims-1; k >= 0; --k) {
491  this->at(k) = linearindex % p_dims[k];
492  linearindex /= p_dims[k]; // integer division
493  }
494  }
502  TOMOGRAPHER_ENABLED_IF(!IsRowMajor)
503  void setLinearIndex(int linearindex)
504  {
505  const int ndims = (int)p_dims.size();
506  for (int k = 0; k < ndims; ++k) {
507  this->at(k) = linearindex % p_dims[k];
508  linearindex /= p_dims[k]; // integer division
509  // std::cout << "k = " << k << "; p_dims = " << p_dims << "; at(k) = " << this->at(k)
510  // << "; linearindex=" << linearindex << "\n";
511  }
512  }
513 
518  TOMOGRAPHER_ENABLED_IF(IsRowMajor)
519  int linearIndex() const
520  {
521  int linindex = 0;
522  for (int k = 0; k < (int)p_dims.size(); ++k) {
523  linindex *= p_dims[k];
524  linindex += this->at(k);
525  }
526  return linindex;
527  }
532  TOMOGRAPHER_ENABLED_IF(!IsRowMajor)
533  int linearIndex() const
534  {
535  int linindex = 0;
536  for (int k = (int)p_dims.size()-1; k >= 0; --k) {
537  linindex *= p_dims[k];
538  linindex += this->at(k);
539  }
540  return linindex;
541  }
542 
545  inline const std::vector<int> & index() const
546  {
547  return *this;
548  }
549 
554  inline const std::vector<int> & dims() const
555  {
556  return p_dims;
557  }
558 
566  IndexList& operator<<(int ind) {
567  push_back(ind);
568  return *this;
569  }
570 
579  IndexList& operator<<(const std::vector<int>& moredims) {
580  insert(end(), moredims.begin(), moredims.end());
581  return *this;
582  }
583 
584 
585 
586  // for internal use:
587 
588  template<bool IsRowMajor2 = false>
589  static const std::vector<int> & forward_index(const IndexList<IsRowMajor2> & index)
590  {
591  return index;
592  }
593  template<bool IsRowMajor2 = false>
594  static std::vector<int> && forward_index(IndexList<IsRowMajor2> && index)
595  {
596  return std::move(index);
597  }
598 
599 private:
600  const std::vector<int> p_dims;
601 };
602 
603 
605 template<bool IsRowMajor>
606 inline std::ostream& operator<<(std::ostream& str, const IndexList<IsRowMajor> & indexlist)
607 {
608  str << "[";
609  for (std::size_t j = 0; j < indexlist.size(); ++j) {
610  str << indexlist[j];
611  if (j < indexlist.size()) {
612  str << ", ";
613  } else {
614  str << ";";
615  }
616  }
617  return str << "==" << indexlist.linearIndex() << "]";
618 }
619 
620 
624 template<bool IsRowMajor_ = false, typename IntType_ = int>
626 {
627 public:
628  static constexpr bool IsRowMajor = IsRowMajor_;
629  typedef IntType_ IntType;
631 
632 private:
633  const std::vector<IntType> p_dims;
634  const IntType p_numel;
635 
636  std::vector<IntType> p_index;
637  IntType p_linearIndex;
638 
639 public:
641  : p_dims(dims),
642  p_numel(getNumEl(dims.begin(), dims.end())),
643  p_index(dims.size(), 0),
644  p_linearIndex(0)
645  {
646  if (p_numel <= 0) {
648  ss << "Invalid dimensions: " << p_dims;
649  throw InvalidIndexError(ss.str());
650  }
651  }
652 
653  inline const std::vector<IntType>& index() const
654  {
655  return p_index;
656  }
657 
658  inline IntType linearIndex() const
659  {
660  return p_linearIndex;
661  }
662 
663  inline IntType numel() const
664  {
665  return p_numel;
666  }
667 
668 
669  TOMOGRAPHER_ENABLED_IF(IsRowMajor)
670  IntType increment()
671  {
672  for (int k = p_dims.size() - 1; k >= 0; --k) {
673  p_index[k]++;
674  if (p_index[k] < p_dims[k]) {
675  // if this increment succeeded and stays in range, ok and stop.
676  break;
677  } else {
678  // otherwise continue the loop and increment the next value, while resetting
679  // this one to zero.
680  p_index[k] = 0;
681  }
682  }
683  return ++p_linearIndex;
684  }
685 
686  TOMOGRAPHER_ENABLED_IF(!IsRowMajor)
687  IntType increment()
688  {
689  for (int k = 0; k < (int)p_dims.size(); ++k) {
690  p_index[k]++;
691  if (p_index[k] < p_dims[k]) {
692  // if this increment succeeded and stays in range, ok and stop.
693  break;
694  } else {
695  // otherwise continue the loop and increment the next value, while resetting
696  // this one to zero.
697  p_index[k] = 0;
698  }
699  }
700  return ++p_linearIndex;
701  }
702 
703  IntType operator++() {
704  return increment();
705  }
706 
707  bool valid() const
708  {
709  return Tools::isPositive<IntType>(p_linearIndex) && p_linearIndex < p_numel;
710  }
711 
712 
713  // for internal use:
714 
715  template<bool IsRowMajor2 = false, typename IntType2 = int>
716  static const std::vector<IntType2> &
717  forward_index(const IndexListIterator<IsRowMajor2,IntType2> & index)
718  {
719  return index.p_index;
720  }
721  template<bool IsRowMajor2 = false, typename IntType2 = int>
722  static std::vector<IntType2> &&
723  forward_index(IndexListIterator<IsRowMajor2,IntType2> && index)
724  {
725  return std::move(index.p_index);
726  }
727 
728 };
729 
730 
732 template<bool IsRowMajor, typename IntType>
733 inline std::ostream& operator<<(std::ostream& str, const IndexListIterator<IsRowMajor, IntType> & indexlistit)
734 {
735  std::vector<int> indexlist{indexlistit.index()};
736 
737  str << "[";
738  for (std::size_t j = 0; j < indexlist.size(); ++j) {
739  str << indexlist[j];
740  if (j < indexlist.size()) {
741  str << ", ";
742  } else {
743  str << ";";
744  }
745  }
746  return str << "==" << indexlistit.linearIndex() << "]";
747 }
748 
749 
750 
751 
752 
790 template<typename T, typename Enabled = void>
792 {
798  typedef T RetType;
799 
806  static inline void checkShape(const Var & var)
807  {
808  (void)var; // silence "unused parameter" warnings
809  }
810 
825  static inline RetType decodeValue(const Var & var);
826 };
827 
828 
829 namespace tomo_internal {
830  // has_params_member<T>::value is true if T has a type member named Params,
831  // i.e. typename T::Params, else it is false.
832  template<typename T, typename Enabled = void>
833  struct has_params_member {
834  enum { value = 0 };
835  };
836  // if T has no Params member, following will fail by SFINAE
837  template<typename T>
838  struct has_params_member<T, typename T::Params>
839  {
840  enum { value = 1 };
841  };
842 }; // namespace tomo_internal
843 
844 
845 
846 class Var;
847 
853 template<typename T>
854 inline typename VarValueDecoder<T>::RetType value(const Var& var)
855 {
858 }
859 
868 template<typename T, TOMOGRAPHER_ENABLED_IF_TMPL( tomo_internal::has_params_member<VarValueDecoder<T> >::value )>
869 inline typename VarValueDecoder<T>::RetType value(const Var& var,
870  const typename VarValueDecoder<T>::Params & params)
871 {
872  VarValueDecoder<T>::checkShape(var, params);
873  return VarValueDecoder<T>::decodeValue(var, params);
874 }
875 
876 
877 
894 class Var
895 {
896 private:
897  struct VarData {
898  VarData() : refcount(0), p_matvar(NULL) { }
899  int refcount;
900  matvar_t * p_matvar;
901  std::string p_varname;
902  };
903  VarData *p_vardata;
904 
905  Var(matvar_t * varinfo) // take over the struct ownership
906  {
907  if (varinfo == NULL) {
908  throw VarReadError("<unknown>");
909  }
910  p_vardata = new VarData;
911  p_vardata->refcount++;
912  p_vardata->p_matvar = varinfo;
913  p_vardata->p_varname = std::string(varinfo->name);
914  }
915 
916 public:
927  Var(File & matf, const std::string& varname, bool load_data = true)
928  {
929  p_vardata = new VarData;
930  p_vardata->refcount++;
931  if (load_data) {
932  p_vardata->p_matvar = Mat_VarRead(matf.getMatPtr(), varname.c_str());
933  } else {
934  p_vardata->p_matvar = Mat_VarReadInfo(matf.getMatPtr(), varname.c_str());
935  }
936  if (p_vardata->p_matvar == NULL) {
937  delete p_vardata;
938  p_vardata = NULL;
939  throw VarReadError(varname);
940  }
941  p_vardata->p_varname = varname;
942  }
943 
945  Var(const Var& copy)
946  {
947  p_vardata = copy.p_vardata;
948  p_vardata->refcount++;
949  }
950 
952  Var(Var&& other)
953  {
954  // steal the data
955  p_vardata = other.p_vardata;
956  other.p_vardata = NULL;
957  }
958 
959  ~Var() {
960  if (p_vardata != NULL) {
961  p_vardata->refcount--;
962  if (!p_vardata->refcount) {
963  Mat_VarFree(p_vardata->p_matvar);
964  delete p_vardata;
965  }
966  }
967  }
968 
975  static Var takeOver(matvar_t * varinfo)
976  {
977  return Var(varinfo);
978  }
979 
984  inline const std::string & varName() const
985  {
986  tomographer_assert(p_vardata != NULL);
987  return p_vardata->p_varname;
988  }
989 
994  inline int ndims() const
995  {
996  tomographer_assert(p_vardata != NULL);
997  return p_vardata->p_matvar->rank;
998  }
1003  inline DimList dims() const
1004  {
1005  tomographer_assert(p_vardata != NULL);
1006  return DimList(&p_vardata->p_matvar->dims[0],
1007  &p_vardata->p_matvar->dims[p_vardata->p_matvar->rank]);
1008  }
1013  inline int numel() const
1014  {
1015  tomographer_assert(p_vardata != NULL);
1016  return dims().numel();
1017  }
1026  inline bool isComplex() const
1027  {
1028  tomographer_assert(p_vardata != NULL);
1029  return p_vardata->p_matvar->isComplex;
1030  }
1035  inline bool isSquareMatrix() const
1036  {
1037  tomographer_assert(p_vardata != NULL);
1038  return p_vardata->p_matvar->rank == 2 && p_vardata->p_matvar->dims[0] == p_vardata->p_matvar->dims[1];
1039  }
1040 
1046  inline bool hasData() const
1047  {
1048  tomographer_assert(p_vardata != NULL);
1049  return (p_vardata->p_matvar->data != NULL);
1050  }
1051 
1091  template<typename T>
1092  inline typename VarValueDecoder<T>::RetType value() const
1093  {
1094  return Tomographer::MAT::value<T>(*this);
1095  }
1106  template<typename T, TOMOGRAPHER_ENABLED_IF_TMPL( tomo_internal::has_params_member<VarValueDecoder<T> >::value )>
1107  inline typename VarValueDecoder<T>::RetType value(const typename VarValueDecoder<T>::Params & params)
1108  {
1109  return Tomographer::MAT::value<T>(*this, params);
1110  }
1111 
1117  const matvar_t * getMatvarPtr() const
1118  {
1119  tomographer_assert(p_vardata != NULL);
1120  return p_vardata->p_matvar;
1121  }
1122 
1126  Var& operator=(Var&& other)
1127  {
1128  // steal the data
1129  p_vardata = other.p_vardata;
1130  other.p_vardata = NULL;
1131  return *this;
1132  }
1134  Var& operator=(const Var& copy)
1135  {
1136  p_vardata = copy.p_vardata;
1137  p_vardata->refcount++;
1138  return *this;
1139  }
1140 };
1141 
1142 
1143 // ---------------
1144 
1145 
1146 inline Var File::var(const std::string varname, bool load_data)
1147 {
1148  return Var(*this, varname, load_data);
1149 }
1150 
1152 {
1153  std::vector<Var> varlist;
1154 
1155  Mat_Rewind(p_matfp);
1156  matvar_t * p = NULL;
1157  while ( (p = Mat_VarReadNextInfo(p_matfp)) != NULL ) {
1158  varlist.push_back(Var::takeOver(p));
1159  }
1160 
1161  return varlist;
1162 }
1163 
1164 
1165 template<typename T, typename Enabled>
1166 // static
1168 {
1169  throw std::runtime_error(std::string("Not Implemented: Please specialize MAT::VarValueDecoder<> for ")
1170  + typeid(T).name() + " to decode variable " + var.varName());
1171 }
1172 
1173 
1174 
1175 
1176 
1177 // =============================================================================
1178 // Some basic utilities for dealing with MATLAB variables
1179 // =============================================================================
1180 
1181 
1182 
1194 template<int MatTypeId = -1> struct MatType { };
1196 template<> struct MatType<MAT_T_DOUBLE> { typedef double Type; };
1198 template<> struct MatType<MAT_T_SINGLE> { typedef float Type; };
1200 template<> struct MatType<MAT_T_INT64> { typedef int64_t Type; };
1202 template<> struct MatType<MAT_T_INT32> { typedef int32_t Type; };
1204 template<> struct MatType<MAT_T_INT16> { typedef int16_t Type; };
1206 template<> struct MatType<MAT_T_INT8> { typedef int8_t Type; };
1208 template<> struct MatType<MAT_T_UINT64> { typedef uint64_t Type; };
1210 template<> struct MatType<MAT_T_UINT32> { typedef uint32_t Type; };
1212 template<> struct MatType<MAT_T_UINT16> { typedef uint16_t Type; };
1214 template<> struct MatType<MAT_T_UINT8> { typedef uint8_t Type; };
1215 
1216 
1223 #define MAT_SWITCH_REAL_TYPE(typ, ...) \
1224  do { switch (typ) { \
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  <<(typ)) ); \
1238  } \
1239  } while (false)
1240 
1247 #define MAT_SWITCH_COMPLEX_TYPE(typ, ...) \
1248  do { switch (typ) { \
1249  case MAT_T_DOUBLE: { typedef std::complex<typename MatType<MAT_T_DOUBLE>::Type> Type; { __VA_ARGS__; } break; } \
1250  case MAT_T_SINGLE: { typedef std::complex<typename MatType<MAT_T_SINGLE>::Type> Type; { __VA_ARGS__; } break; } \
1251  default: \
1252  throw VarMatTypeError( streamstr("Uknown/unsupported encoded type from matio: " \
1253  <<(typ)) ); \
1254  } \
1255  } while (false)
1256 
1257 
1265 #define MAT_SWITCH_TYPE(matvar_ptr, ...) \
1266  do { \
1267  if (!(matvar_ptr)->isComplex) { \
1268  switch ((matvar_ptr)->data_type) { \
1269  case MAT_T_DOUBLE: { typedef typename MatType<MAT_T_DOUBLE>::Type Type; { __VA_ARGS__; } break; } \
1270  case MAT_T_SINGLE: { typedef typename MatType<MAT_T_SINGLE>::Type Type; { __VA_ARGS__; } break; } \
1271  case MAT_T_INT64: { typedef typename MatType<MAT_T_INT64>::Type Type; { __VA_ARGS__; } break; } \
1272  case MAT_T_INT32: { typedef typename MatType<MAT_T_INT32>::Type Type; { __VA_ARGS__; } break; } \
1273  case MAT_T_INT16: { typedef typename MatType<MAT_T_INT16>::Type Type; { __VA_ARGS__; } break; } \
1274  case MAT_T_INT8: { typedef typename MatType<MAT_T_INT8>::Type Type; { __VA_ARGS__; } break; } \
1275  case MAT_T_UINT64: { typedef typename MatType<MAT_T_UINT64>::Type Type; { __VA_ARGS__; } break; } \
1276  case MAT_T_UINT32: { typedef typename MatType<MAT_T_UINT32>::Type Type; { __VA_ARGS__; } break; } \
1277  case MAT_T_UINT16: { typedef typename MatType<MAT_T_UINT16>::Type Type; { __VA_ARGS__; } break; } \
1278  case MAT_T_UINT8: { typedef typename MatType<MAT_T_UINT8>::Type Type; { __VA_ARGS__; } break; } \
1279  default: \
1280  throw VarMatTypeError( streamstr("Uknown/unsupported encoded type from matio: " \
1281  << (matvar_ptr)->data_type) ); \
1282  } \
1283  } else { \
1284  switch ((matvar_ptr)->data_type) { \
1285  case MAT_T_DOUBLE: { typedef std::complex<typename MatType<MAT_T_DOUBLE>::Type> Type; { __VA_ARGS__; } break; } \
1286  case MAT_T_SINGLE: { typedef std::complex<typename MatType<MAT_T_SINGLE>::Type> Type; { __VA_ARGS__; } break; } \
1287  default: \
1288  throw VarMatTypeError( streamstr("Uknown/unsupported encoded type from matio: " \
1289  << (matvar_ptr)->data_type) ); \
1290  } \
1291  } \
1292  } while (false)
1293 
1294 
1295 
1296 
1297 // =============================================================================
1298 // now, let's define some ways to get variable values.
1299 // =============================================================================
1300 
1301 
1302 
1306 template<typename T>
1308 #ifdef TOMOGRAPHER_PARSED_BY_DOXYGEN
1309  _IS_NUMERIC_TYPE
1310 #else
1311  typename std::enable_if<(std::numeric_limits<T>::is_specialized ||
1312  Tools::isComplex<T>::value)>::type
1313 #endif
1314  >
1315 {
1317  typedef T RetType;
1318 
1320  static inline void checkShape(const Var & var)
1321  {
1322  if (var.isComplex() && !Tools::isComplex<T>::value) {
1323  throw VarTypeError(var.varName(),
1324  streamstr("Can't store complex matrix in type " << typeid(T).name()));
1325  }
1326  if (var.numel() != 1) {
1327  throw VarTypeError(var.varName(),
1328  streamstr("Expected scalar but got matrix"));
1329  }
1330  }
1331 
1333  static inline RetType decodeValue(const Var & var)
1334  {
1335  const matvar_t * matvar_ptr = var.getMatvarPtr();
1336 
1337  MAT_SWITCH_TYPE(matvar_ptr,
1338  return get_value<Type>(matvar_ptr, var.varName());
1339  );
1340  // should never reach here
1341  tomographer_assert(false);
1342  }
1343 
1344 private:
1345  template<typename MATType,
1346  TOMOGRAPHER_ENABLED_IF_TMPL(!Tools::isComplex<RetType>::value &&
1348  static inline RetType get_value(const matvar_t * matvar_ptr, const std::string & )
1349  {
1350  return (RetType) ((const MATType *) matvar_ptr->data)[0];
1351  }
1352 
1353  template<typename MATType,
1354  TOMOGRAPHER_ENABLED_IF_TMPL(Tools::isComplex<RetType>::value &&
1356  static inline RetType get_value(const matvar_t * matvar_ptr, const std::string & )
1357  {
1358  return RetType( ((const MATType *) matvar_ptr->data)[0],
1359  0 );
1360  }
1361 
1362  template<typename MATType,
1363  TOMOGRAPHER_ENABLED_IF_TMPL(!Tools::isComplex<RetType>::value &&
1365  static inline RetType get_value(const matvar_t * /*matvar_ptr*/, const std::string & varname)
1366  {
1367  throw VarTypeError(varname, "Expected real scalar, got complex type");
1368  }
1369 
1370  template<typename MATType,
1371  TOMOGRAPHER_ENABLED_IF_TMPL(Tools::isComplex<RetType>::value &&
1373  static inline RetType get_value(const matvar_t * matvar_ptr, const std::string & )
1374  {
1375  typedef typename Tools::ComplexRealScalar<MATType>::type MATRealType;
1376  const mat_complex_split_t * cdata = (mat_complex_split_t*) matvar_ptr->data;
1377 
1378  return RetType( ((const MATRealType *) cdata->Re)[0],
1379  ((const MATRealType *) cdata->Im)[0] );
1380  }
1381 
1382 };
1383 
1384 
1385 
1386 // -----------------------------------------------
1387 
1388 
1389 namespace tomo_internal {
1390 
1392 template<typename OutType, typename MatInnerT>
1393 class VarMatDataAccessor
1394 {
1395  const Var & p_var;
1396 
1397  typedef typename Tools::ComplexRealScalar<MatInnerT>::type MatRealInnerT;
1398 
1399  const MatInnerT * p_r_ptr;
1400  const MatRealInnerT * p_cre_ptr;
1401  const MatRealInnerT * p_cim_ptr;
1402 
1403 public:
1404  VarMatDataAccessor(const Var & var)
1405  : p_var(var)
1406  {
1407  const matvar_t * matvar_ptr = var.getMatvarPtr();
1408  tomographer_assert(matvar_ptr->data != NULL);
1409  if (!matvar_ptr->isComplex) {
1410  // real type
1411  p_r_ptr = (const MatInnerT*) matvar_ptr->data;
1412  p_cre_ptr = NULL;
1413  p_cim_ptr = NULL;
1414  } else {
1415  const mat_complex_split_t * cdata = (mat_complex_split_t*) matvar_ptr->data;
1416  p_r_ptr = NULL;
1417  p_cre_ptr = (const MatRealInnerT*) cdata->Re;
1418  p_cim_ptr = (const MatRealInnerT*) cdata->Im;
1419  tomographer_assert(p_cre_ptr != NULL);
1420  tomographer_assert(p_cim_ptr != NULL);
1421  }
1422  }
1423 
1424  virtual ~VarMatDataAccessor() { }
1425 
1426  template<typename IndexListType,
1427  typename OutType__ = OutType, typename MatInnerT__ = MatInnerT,
1428  TOMOGRAPHER_ENABLED_IF_TMPL(!Tools::isComplex<OutType__>::value &&
1430  inline OutType value(IndexListType&& index) const
1431  {
1432  tomographer_assert(p_r_ptr != NULL);
1433 
1434  // real value.
1435  std::size_t lin = linear_index(std::forward<IndexListType>(index));
1436  return p_r_ptr[lin];
1437  }
1438 
1439  template<typename IndexListType,
1440  typename OutType__ = OutType, typename MatInnerT__ = MatInnerT,
1441  TOMOGRAPHER_ENABLED_IF_TMPL(!Tools::isComplex<OutType__>::value &&
1443  inline OutType value(IndexListType&& ) const
1444  {
1445  throw VarTypeError(p_var.varName(), "Expected real type, got complex");
1446  }
1447 
1448  template<typename IndexListType,
1449  typename OutType__ = OutType, typename MatInnerT__ = MatInnerT,
1450  TOMOGRAPHER_ENABLED_IF_TMPL(Tools::isComplex<OutType__>::value &&
1452  inline OutType value(IndexListType&& index) const
1453  {
1454  tomographer_assert(p_r_ptr != NULL);
1455 
1456  // real value.
1457  std::size_t lin = linear_index(std::forward<IndexListType>(index));
1458  return OutType( p_r_ptr[lin] , 0 );
1459  }
1460 
1461  template<typename IndexListType,
1462  typename OutType__ = OutType, typename MatInnerT__ = MatInnerT,
1463  TOMOGRAPHER_ENABLED_IF_TMPL(Tools::isComplex<OutType__>::value &&
1465  inline OutType value(IndexListType&& index) const
1466  {
1467  tomographer_assert(p_cre_ptr != NULL);
1468  tomographer_assert(p_cim_ptr != NULL);
1469 
1470  // complex value
1471  std::size_t lin = linear_index(std::forward<IndexListType>(index));
1472  return OutType(p_cre_ptr[lin], p_cim_ptr[lin]);
1473  }
1474 
1475 private:
1476  template<typename IndexListType>
1477  std::size_t linear_index(IndexListType && index) const
1478  {
1479  IndexList<false> ind_cmaj{
1480  p_var.dims(),
1482  };
1483  // std::cout << "linear_index: ind_cmaj=" << ind_cmaj << ", -> linear index = " << ind_cmaj.linearIndex() << "\n";
1484  return ind_cmaj.linearIndex();
1485  }
1486 };
1487 
1488 } // namespace tomo_internal
1489 
1490 
1491 // -----------------------------------------------
1492 
1533 struct VarShape
1534 {
1542  const bool is_complex;
1543 
1558  const DimList dims;
1559 
1574  const bool is_square;
1575 
1580  template<typename DimListType>
1581  VarShape(bool is_complex_, DimListType&& dims_, bool is_square_)
1582  : is_complex(is_complex_), dims(std::forward<DimListType>(dims_)), is_square(is_square_)
1583  {
1584  _check_consistency();
1585  }
1586 
1592  VarShape(const Var & var)
1593  : is_complex(var.isComplex()), dims(var.dims()), is_square(var.isSquareMatrix())
1594  {
1595  }
1596 
1597 
1598 private:
1599  void _check_consistency()
1600  {
1601  if (is_square) {
1602  tomographer_assert(dims.size() == 0 || (dims.size() == 2 && (dims[0] == -1 || dims[1] == -1 || dims[0] == dims[1])));
1603  }
1604  }
1605 
1606 public:
1607 
1615  inline void checkShape(const VarShape & shape);
1616 
1624  inline void checkShape(const Var & var)
1625  {
1626  try {
1627  checkShape(VarShape(var));
1628  } catch (VarTypeError & err) {
1629  err.setVarName(var.varName());
1630  throw;
1631  }
1632  }
1633 };
1634 
1636 inline std::ostream& operator<<(std::ostream& str, const VarShape & varshape)
1637 {
1638  str << ((varshape.is_complex) ? std::string("complex ") : std::string("real "));
1639  if (varshape.dims.size() == 1) {
1640  str << "vector";
1641  } else if (varshape.dims.size() == 2) {
1642  if (varshape.is_square) {
1643  str << "square ";
1644  }
1645  str << "matrix";
1646  } else if (varshape.dims.size() > 0) {
1647  str << varshape.dims.size() << "-D array";
1648  if (varshape.is_square) {
1649  str << " with first two dimensions square";
1650  }
1651  } else {
1652  // empty dims means no requirement
1653  str << "array";
1654  }
1655  if (varshape.dims.size()) {
1656  str << " of shape " << varshape.dims;
1657  }
1658  return str;
1659 }
1660 
1661 inline void VarShape::checkShape(const VarShape& other)
1662 {
1663  const DimList mvardims = other.dims;
1664 
1665  if ((other.is_complex && !is_complex) ||
1666  (mvardims.size() != dims.size() && dims.size() > 0) ||
1667  (is_square && (mvardims.size() != 2 || mvardims[0] != mvardims[1])) ||
1668  (dims.size() > 0 && !mvardims.matchesWanted(dims))) {
1669 
1670  std::stringstream errstr;
1671 
1672  errstr << "Expected "
1673  << *this
1674  << ", got "
1675  << other;
1676 
1677  //fprintf(stderr, "Bad var type for variable %s\n", var.varName().c_str());
1678  throw VarTypeError(std::string(), errstr.str());
1679 
1680  }
1681 }
1682 
1683 
1684 
1685 // -----------------------------------------------------------------------------
1686 
1687 // get an std::vector<T> for a variable.
1688 
1698 template<typename T_, bool IsRowMajor_ = false>
1700  typedef T_ type;
1701  static constexpr bool IsRowMajor = IsRowMajor_;
1702 };
1703 
1705 template<typename T, bool IsRowMajor>
1706 struct VarValueDecoder<GetStdVector<T, IsRowMajor> >
1707 {
1708  typedef std::vector<T> RetType;
1709 
1710  static inline void checkShape(const Var & var)
1711  {
1712  if (var.isComplex() && !Tools::isComplex<T>::value) {
1713  throw VarTypeError(var.varName(),
1714  std::string("can't store complex matrix in type ")
1715  + typeid(T).name());
1716  }
1717  }
1718 
1719  static inline std::vector<T> decodeValue(const Var & var)
1720  {
1721  const matvar_t * matvar_ptr = var.getMatvarPtr();
1722  std::size_t numel = var.numel();
1723  std::vector<T> val(numel);
1724 
1725  MAT_SWITCH_TYPE(matvar_ptr,
1726  tomo_internal::VarMatDataAccessor<T, Type> acc(var);
1727 
1728  for(IndexListIterator<IsRowMajor> il(var.dims()); il.valid(); ++il) {
1729  // std::cout << "index: " << il << "\n";
1730  val[il.linearIndex()] = acc.value(il);
1731  }
1732 
1733  return val;
1734  );
1735  // should never reach here
1736  tomographer_assert(false);
1737  }
1738 
1739 };
1740 
1741 
1742 
1743 
1744 
1745 
1746 
1747 // =============================================================================
1748 
1749 // get Eigen types.
1750 
1751 namespace tomo_internal {
1752 
1753 
1754 inline DimList dims_stackedcols(DimList vdims)
1755 {
1756  tomographer_assert(vdims.size() >= 1);
1757  DimList vdimsreshaped;
1758  if (vdims.size() == 1) {
1759  vdimsreshaped = vdims;
1760  vdimsreshaped << 1;
1761  } else if (vdims.size() == 2) {
1762  vdimsreshaped = vdims;
1763  } else if (vdims.size() > 2) {
1764  vdimsreshaped << getNumEl(vdims.data(), vdims.data()+vdims.size()-1) << vdims[vdims.size()-1];
1765  }
1766  tomographer_assert(vdimsreshaped[0] != -1 && vdimsreshaped[1] != -1);
1767  return vdimsreshaped;
1768 }
1769 
1770 template<typename MatrixType, typename MatType,
1771  TOMOGRAPHER_ENABLED_IF_TMPL(Eigen::NumTraits<typename MatrixType::Scalar>::IsComplex &&
1773 void init_eigen_matrix(MatrixType & matrix, const DimList & vdims,
1774  const Var & var, const std::ptrdiff_t data_offset = 0)
1775 {
1776  typedef typename MatrixType::Scalar Scalar;
1777  typedef typename Eigen::NumTraits<Scalar>::Real RealScalar;
1778 
1779  typedef typename Eigen::NumTraits<MatType>::Real MatRealType;
1780 
1781  const matvar_t * matvar_ptr = var.getMatvarPtr();
1782 
1783  const mat_complex_split_t * cdata = (mat_complex_split_t*) matvar_ptr->data;
1784 
1785  DimList vdimsreshaped = dims_stackedcols(vdims);
1786 
1787  matrix = (
1789  (const MatRealType *) cdata->Re + data_offset, vdimsreshaped[0], vdimsreshaped[1]
1790  ).template cast<std::complex<RealScalar> >()
1791  + std::complex<RealScalar>(0,1) *
1793  (const MatRealType *) cdata->Im + data_offset, vdimsreshaped[0], vdimsreshaped[1]
1794  ).template cast<std::complex<RealScalar> >()
1795  );
1796 }
1797 
1798 template<typename MatrixType, typename MatRealType,
1799  TOMOGRAPHER_ENABLED_IF_TMPL(!Eigen::NumTraits<typename MatrixType::Scalar>::IsComplex &&
1801 void init_eigen_matrix(MatrixType & /*matrix*/, const DimList & /*vdims*/,
1802  const Var & var, const std::ptrdiff_t /*data_offset*/ = 0)
1803 {
1804  throw VarTypeError(var.varName(), "Expected real type, but got complex.");
1805 }
1806 
1807 template<typename MatrixType, typename MatRealType,
1808  TOMOGRAPHER_ENABLED_IF_TMPL(!Eigen::NumTraits<MatRealType>::IsComplex)>
1809 void init_eigen_matrix(MatrixType & matrix, const DimList & vdims,
1810  const Var & var, const std::ptrdiff_t data_offset = 0)
1811 {
1812  typedef typename MatrixType::Scalar Scalar;
1813 
1814  const matvar_t * matvar_ptr = var.getMatvarPtr();
1815 
1816  DimList vdimsreshaped = dims_stackedcols(vdims);
1817 
1818  matrix = (
1820  (const MatRealType *) matvar_ptr->data + data_offset, vdimsreshaped[0], vdimsreshaped[1]
1821  )
1822  ).template cast<Scalar>();
1823 }
1824 
1825 } // namespace tomo_internal
1826 
1827 
1828 
1837 template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols>
1838 struct VarValueDecoder<Eigen::Matrix<Scalar,Rows,Cols,Options,MaxRows,MaxCols> >
1839 {
1841  typedef typename Eigen::NumTraits<Scalar>::Real RealScalar;
1842  typedef MatrixType RetType;
1843 
1844  /* not needed in fact.
1845  struct Params {
1846  Params() : dims{Rows, Cols}
1847  {
1848  }
1849  Params(int rows) : dims{rows, 1}
1850  {
1851  tomographer_assert(Cols == 1);
1852  tomographer_assert(Rows == Eigen::Dynamic || Rows == rows);
1853  }
1854  Params(int rows, int cols) : dims{rows, cols}
1855  {
1856  tomographer_assert(Rows == Eigen::Dynamic || Rows == rows);
1857  tomographer_assert(Cols == Eigen::Dynamic || Cols == cols);
1858  }
1859  Params(const DimList& dims_) : dims{dims_}
1860  {
1861  tomographer_assert(dims.size() == 2);
1862  tomographer_assert(Rows == Eigen::Dynamic || Rows == dims[0]);
1863  tomographer_assert(Cols == Eigen::Dynamic || Cols == dims[1]);
1864  }
1865 
1866  const DimList dims;
1867  };
1868  */
1869 
1870  static inline void checkShape(const Var & var) //, const Params & p = Params())
1871  {
1872  DimList matdims;
1873  matdims << (Rows!=Eigen::Dynamic ? Rows : -1)
1874  << (Cols!=Eigen::Dynamic ? Cols : -1);
1875 
1877  matdims,
1878  matdims[0] != -1 && matdims[0] == matdims[1]);
1879 
1880  DimList vdims = var.dims();
1881  if (vdims.size() > 2) {
1882  vdims = (DimList() << getNumEl(vdims.data(), vdims.data()+vdims.size()-1) << vdims[vdims.size()-1]);
1883  }
1884  try {
1885  shape.checkShape(VarShape(var.isComplex(), vdims, (vdims[0] != -1 && vdims[0] == vdims[1])));
1886  } catch (VarTypeError & err) {
1887  err.setVarName(var.varName());
1888  throw; // re-throw
1889  }
1890  }
1891 
1892  static inline RetType decodeValue(const Var & var) //, const Params & p = Params())
1893  {
1894  const matvar_t * matvar_ptr = var.getMatvarPtr();
1895  DimList vdims{var.dims()};
1896 
1897  if (vdims.size() < 2) {
1898  throw VarTypeError(var.varName(), streamstr("Expected matrix, but variable shape is " << vdims));
1899  }
1900  // if we are stacking several dimensions in the column, force column-major ordering.
1901  if (vdims.size() > 2 &&
1902  ((MatrixType::Options & Eigen::RowMajorBit) == Eigen::RowMajor)) {
1903  throw VarTypeError(var.varName(),
1904  "When collapsing several dimensions into Eigen columns, you must use "
1905  "column-major ordering (sorry).");
1906  }
1907 
1908  const int cols = vdims[vdims.size()-1];
1909  // rest of dimensions.
1910  const int rows = getNumEl(vdims.data(), vdims.data()+vdims.size()-1);
1911 
1912  MatrixType matrix(rows, cols);
1913 
1915  matvar_ptr,
1916  tomo_internal::init_eigen_matrix<MatrixType, Type>(
1917  matrix, vdims, var
1918  );
1919  );
1920 
1921  return matrix;
1922  }
1923 
1924 };
1925 
1926 
1927 
1928 
1929 
1939 template<typename Scalar, int Rows, int Cols, int Options, int MaxRows, int MaxCols, typename Alloc>
1940 struct VarValueDecoder<std::vector<Eigen::Matrix<Scalar,Rows,Cols,Options,MaxRows,MaxCols>, Alloc> >
1941 {
1943  typedef typename Eigen::NumTraits<Scalar>::Real RealScalar;
1944 
1946 
1947  static inline void checkShape(const Var & var)
1948  {
1949  DimList matdims;
1950  matdims << (Rows!=Eigen::Dynamic ? Rows : -1)
1951  << (Cols!=Eigen::Dynamic ? Cols : -1)
1952  << -1;
1953 
1955  matdims,
1956  false);
1957 
1958  DimList vdims = var.dims();
1959  if (vdims.size() < 1) {
1960  throw VarTypeError(var.varName(), "Invalid (empty) variable dimensions");
1961  }
1962  if (vdims.size() == 1) {
1963  vdims << 1 << 1;
1964  } else if (vdims.size() == 2) {
1965  vdims << 1;
1966  } else { //if (vdims.size() > 2) {
1967  vdims = (DimList() << vdims[0] << vdims[1] << getNumEl(vdims.data()+2, vdims.data()+vdims.size()));
1968  }
1969 
1970  // check shape now:
1971  try {
1972  shape.checkShape(VarShape(var.isComplex(), vdims, false));
1973  } catch (VarTypeError & err) {
1974 
1975  err.setVarName(var.varName());
1976  throw; // re-throw
1977  }
1978 
1979  }
1980 
1981  static inline RetType decodeValue(const Var & var)
1982  {
1983  DimList vardims{var.dims()};
1984 
1985  tomographer_assert(vardims.size() >= 1);
1986 
1987  DimList innerdims;
1988  std::size_t outerdim = 1;
1989  if (vardims.size() == 1) {
1990  innerdims << vardims[0] << 1;
1991  } else if (vardims.size() == 2) {
1992  innerdims = vardims;
1993  } else {
1994  // more dimensions
1995  innerdims << vardims[0] << vardims[1];
1996  outerdim = getNumEl(vardims.data()+2, vardims.data()+vardims.size());
1997  }
1998 
1999  RetType value(outerdim);
2000 
2001  std::ptrdiff_t innernumel = innerdims[0]*innerdims[1];
2002 
2003  std::size_t j;
2004  const matvar_t * matvar_ptr = var.getMatvarPtr();
2005 
2007  matvar_ptr,
2008  for (j = 0; j < outerdim; ++j) {
2009  tomo_internal::init_eigen_matrix<MatrixType,Type>(
2010  value[j], // matrix reference
2011  innerdims, // dimensions of matrix reference
2012  var, // data
2013  j*innernumel // offset
2014  );
2015  }
2016  );
2017 
2018  return value;
2019  }
2020 
2021 };
2022 
2023 
2024 } // namespace MAT
2025 } // namespace Tomographer
2026 
2027 
2028 
2029 
2030 #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:806
Utility to iterate over a multidim array by increasing linear index.
Definition: ezmatio.h:625
static void checkShape(const Var &var)
See VarValueDecoder::checkShape()
Definition: ezmatio.h:1320
File(File &&other)
Move constructor.
Definition: ezmatio.h:213
bool hasData() const
Whether data for this Var object has been loaded.
Definition: ezmatio.h:1046
bool isComplex() const
Whether this variable is complex or real.
Definition: ezmatio.h:1026
DimList()
Initializes an empty dimension list.
Definition: ezmatio.h:308
T operator=(T...args)
Base namespace for the Tomographer project.
Definition: densellh.h:44
IndexList(const std::vector< int > &dims=std::vector< int >(), int linearindex=-1)
Constructor with linear index.
Definition: ezmatio.h:451
Var var(const std::string varname, bool load_data=true)
Find a variable by name.
Definition: ezmatio.h:1146
Invalid index or index list provided to a routine.
Definition: ezmatio.h:166
Unknown type of a variable present in the data file.
Definition: ezmatio.h:133
void checkShape(const Var &var)
Shorthand for checkShape(const VarShape& other) for a shape given by a variable.
Definition: ezmatio.h:1624
Error while reading a variable from the MATLAB data file.
Definition: ezmatio.h:111
int ndims() const
Number of dimensions of this object.
Definition: ezmatio.h:994
DimList(VectorType &&dims)
Initialize a dimension list with another list of dimensions.
Definition: ezmatio.h:316
A MATLAB file open for reading data.
Definition: ezmatio.h:190
static RetType decodeValue(const Var &var)
See VarValueDecoder::decodeValue()
Definition: ezmatio.h:1333
STL namespace.
STL class.
Var & operator=(Var &&other)
Move assignment operator as this object implements C++11 move semantics.
Definition: ezmatio.h:1126
statically determine whether a type is complex
Definition: cxxutil.h:341
T end(T...args)
File(const std::string fname)
Open a data file for reading.
Definition: ezmatio.h:198
bool matchesWanted(const DimList &wanted) const
Test whether our dimensions match the given required list of dimensions.
Definition: ezmatio.h:362
#define streamstr(tokens)
Utility macro to format stream tokens to a std::string.
Definition: fmt.h:145
A list of indices with an API for linear or subindices access.
Definition: ezmatio.h:438
Base Exception class for errors within our MAT routines.
Definition: ezmatio.h:68
IndexList & operator<<(int ind)
Append index to list.
Definition: ezmatio.h:566
const std::string & varName() const
The variable name.
Definition: ezmatio.h:984
IndexList(const std::vector< int > &dims, VectorIntInitializer &&index)
Constructor with multidimensional index specification.
Definition: ezmatio.h:471
std::vector< Var > getVarInfoList()
Get a list of all variables in this data file.
Definition: ezmatio.h:1151
STL class.
Map matio&#39;s constants to C/C++ types.
Definition: ezmatio.h:1194
Error while opening a MATLAB file.
Definition: ezmatio.h:147
T push_back(T...args)
static Var takeOver(matvar_t *varinfo)
Take in charge the given C matvar_t pointer.
Definition: ezmatio.h:975
T data(T...args)
Var(Var &&other)
Var implements C++11 move semantics.
Definition: ezmatio.h:952
Basic utilities for dealing with Eigen matrices and other types.
void checkShape(const VarShape &shape)
Verify that our requirements match the given other shape.
Definition: ezmatio.h:1661
const bool is_complex
Whether the variable is or should be complex.
Definition: ezmatio.h:1542
A MATLAB variable in the MAT file.
Definition: ezmatio.h:894
std::vector< int > VectorType
Base vector type (superclass)
Definition: ezmatio.h:444
bool isSquareMatrix() const
Whether this is a square matrix.
Definition: ezmatio.h:1035
VarValueDecoder< T >::RetType value(const Var &var, const typename VarValueDecoder< T >::Params &params)
Access the value of the given variable, as a C++ type.
Definition: ezmatio.h:869
VarValueDecoder< T >::RetType value() const
Read this variable data as native C++ object.
Definition: ezmatio.h:1092
int numel() const
The total number of elements in this array or tensor.
Definition: ezmatio.h:1013
Ask for this type in Var::value<typename T>() to get an std::vector of the data.
Definition: ezmatio.h:1699
Some C++ utilities, with a tad of C++11 tricks.
int ndims() const
Get the number of dimensions in this array.
Definition: ezmatio.h:357
STL class.
T move(T...args)
DimList dims() const
Specific dimensions of this numeric array or tensor.
Definition: ezmatio.h:1003
T size(T...args)
std::ostream & operator<<(std::ostream &out, const DimList &dlist)
C++ output stream operators for a DimList.
Definition: ezmatio.h:396
STL class.
An array of ints which specifies a list of dimensions.
Definition: ezmatio.h:304
T RetType
Type returned by decodeValue()
Definition: ezmatio.h:798
Var & operator=(const Var &copy)
Var objects are copyable. Beware though that the data is shared.
Definition: ezmatio.h:1134
VarShape(bool is_complex_, DimListType &&dims_, bool is_square_)
Construct a VarShape object from given characteristics.
Definition: ezmatio.h:1581
File & operator=(File &&other)
Move assignment operator.
Definition: ezmatio.h:261
T begin(T...args)
#define MAT_SWITCH_TYPE(matvar_ptr,...)
Useful hack to get C++ type from dynamical MAT type ID.
Definition: ezmatio.h:1265
VarShape(const Var &var)
Construct a VarShape object reflecting the actual shape of a variable in the data file...
Definition: ezmatio.h:1592
::value DimList(std::initializer_list< T > init)
Initialize the dimension list with an explicit initializer.
Definition: ezmatio.h:332
VarValueDecoder< T >::RetType value(const Var &var)
Access the value of the given variable, as a C++ type.
Definition: ezmatio.h:854
T c_str(T...args)
Specializable template which takes care of decoding values.
Definition: ezmatio.h:791
const std::vector< int > & index() const
Return a reference to *this.
Definition: ezmatio.h:545
Type mismatch (wrong type requested) in a variable read from the MATLAB data file.
Definition: ezmatio.h:122
Exception relating to a MATLAB variable in the data file.
Definition: ezmatio.h:97
Describe shape of variable and whether it is complex.
Definition: ezmatio.h:1533
mat_t * getMatPtr()
Direct access to the underlying C pointer used for the MatIO library.
Definition: ezmatio.h:251
DimList & operator<<(int dim)
Add (append) a dimension to the dimension list.
Definition: ezmatio.h:380
int numel() const
Get the total number of elements in an array of these dimensions.
Definition: ezmatio.h:350
const unsigned int RowMajorBit
const std::vector< int > & dims() const
Get the underlying dimensions given to the constructor.
Definition: ezmatio.h:554
Var(File &matf, const std::string &varname, bool load_data=true)
Read variable from MATLAB data file.
Definition: ezmatio.h:927
Var(const Var &copy)
Var objects are copyable. Beware though that the data is shared.
Definition: ezmatio.h:945
DimList(It b, It e)
Initialize the dimension list with an iterator range.
Definition: ezmatio.h:342
STL class.
const DimList dims
The dimensions of the variable, or requested dimensions.
Definition: ezmatio.h:1558
static RetType decodeValue(const Var &var)
Decode the variable var into the C++ type T.
Definition: ezmatio.h:1167
RowMajor
ValueType getNumEl(It begin, It end)
Calculate the product of all dimensions.
Definition: ezmatio.h:281
const bool is_square
Whether the variable&#39;s two first dimensions are (or should be) the same.
Definition: ezmatio.h:1574
VarValueDecoder< T >::RetType value(const typename VarValueDecoder< T >::Params &params)
Read this variable data as native C++ object.
Definition: ezmatio.h:1107
const matvar_t * getMatvarPtr() const
Access the underlying C pointer to the MatIO structure. Use with care.
Definition: ezmatio.h:1117