vnl_matlab_read.cxx
Go to the documentation of this file.
1 // This is core/vnl/vnl_matlab_read.cxx
2 #include <ios>
3 #include <iostream>
4 #include <complex>
5 #include <cstring>
6 #include "vnl_matlab_read.h"
7 
8 #include <vnl/vnl_c_vector.h>
9 //:
10 // \file
11 // \author fsm
12 
13 // Provide vcl_destroy() and vcl_construct() : ONLY USED IN vnl_matlab
14 template <class T>
15 inline
16 void vcl_destroy(T *p) { p->~T(); }
17 
18 template <class U, class V>
19 inline
20 void vcl_construct(U * p, V const & value) { new (p) U(value); }
21 
22 //--------------------------------------------------------------------------------
23 
24 void vnl_read_bytes(std::istream &s, void *p, unsigned bytes)
25 {
26  s.read((char *)p, bytes);
27 }
28 
29 template <>
30 void vnl_matlab_read_data(std::istream &s, float *p, unsigned n)
31 { ::vnl_read_bytes(s, p, n*sizeof(*p)); }
32 
33 template <>
34 void vnl_matlab_read_data(std::istream &s, double *p, unsigned n)
35 { ::vnl_read_bytes(s, p, n*sizeof(*p)); }
36 
37 #define implement_read_complex_data(T) \
38 template <> \
39 void vnl_matlab_read_data(std::istream &s, std::complex<T > *ptr, unsigned n) { \
40  T *re = vnl_c_vector<T >::allocate_T(n); \
41  T *im = vnl_c_vector<T >::allocate_T(n); \
42  ::vnl_read_bytes(s, re, n*sizeof(T)); \
43  ::vnl_read_bytes(s, im, n*sizeof(T)); \
44  for (unsigned i=0; i<n; ++i) \
45  ptr[i] = std::complex<T >(re[i], im[i]); \
46  vnl_c_vector<T >::deallocate(re, n); \
47  vnl_c_vector<T >::deallocate(im, n); \
48 }
49 
52 
53 #undef implement_read_complex_data
54 
55 //--------------------------------------------------------------------------------
56 
57 vnl_matlab_readhdr::vnl_matlab_readhdr(std::istream &s_) : s(s_), varname(nullptr), data_read(false), need_swap(false)
58 {
59  read_hdr();
60 }
61 
63 {
64  if (varname)
65  delete [] varname;
66  varname = nullptr;
67 }
68 
69 vnl_matlab_readhdr::operator bool () const
70 {
71  return (s.good() && !s.eof())? true : false; // FIXME
72 }
73 
75 {
76  return (s.good() && !s.eof())? false : true; // FIXME
77 }
78 
80 {
82 }
83 
85 {
87 }
88 
90 {
92 }
93 
94 //: internal
95 // increment 'current', record the file position and read the header.
97 {
98  std::memset(&hdr, 0, sizeof hdr);
99  ::vnl_read_bytes(s, &hdr, sizeof(hdr));
100 
101  // determine if data needs swapping when read
102  // Everything else depends on this; if the header needs swapping
103  // and is not, nothing good will happen.
104  switch (hdr.type)
105  {
106  case 0:
107  // 0 means double-precision values, column-major, little-endian,
108  // so you need to swap if the system is big-endian
109 #if VXL_BIG_ENDIAN
110  need_swap = true;
111 #endif
112  break;
113  case 10:
114  // Regardless of endian-ness, these flag values are
115  // what the writer puts in the header in the native format,
116  // therefore if you see any of them, the file is the same-endian
117  // as the system you're reading on.
118  case 100:
119  case 110:
120  case 1000:
121  case 1100:
122  case 1110:
123  need_swap = false;
124  break;
125  default:
126  // any other values are either gibberish, or need to be byte-swapped
127  // we hope that it means the file needs byte-swapping, and not that
128  // the file is corrupt.
129  need_swap = true;
130  }
131  if (need_swap)
132  {
138  }
139  if (varname)
140  delete [] varname;
141  varname = new char[hdr.namlen+1];
142 #ifdef DEBUG
143  std::cerr << "type:" << hdr.type << std::endl
144  << "rows:" << hdr.rows << std::endl
145  << "cols:" << hdr.cols << std::endl
146  << "imag:" << hdr.imag << std::endl
147  << "namlen:" << hdr.namlen << std::endl;
148 #endif
150  varname[hdr.namlen] = '\0';
151 
152  data_read = false;
153 }
154 
156 {
157  if (!data_read) {
158  // number of bytes to skip :
159  unsigned long n = rows()*cols()*sizeof(float);
160 
161  if (!is_single())
162  n *= 2;
163 
164  if (is_complex())
165  n *= 2;
166  s.seekg(n, std::ios::cur);
167  }
168 
169  read_hdr();
170 }
171 
172 //--------------------------------------------------------------------------------
173 
174 bool vnl_matlab_readhdr::type_chck(float &) { return is_single() && !is_complex(); }
175 bool vnl_matlab_readhdr::type_chck(double &) { return !is_single() && !is_complex(); }
176 bool vnl_matlab_readhdr::type_chck(std::complex<float> &) { return is_single() && is_complex(); }
177 bool vnl_matlab_readhdr::type_chck(std::complex<double> &) { return !is_single() && is_complex(); }
178 
179 #define fsm_define_methods(T) \
180 bool vnl_matlab_readhdr::read_data(T &v) { \
181  if (!type_chck(v)) { std::cerr << "type_check\n"; return false; }\
182  if (rows()!=1U || cols()!=1U) { std::cerr << "size0\n"; return false; } \
183  vnl_matlab_read_data(s, &v, 1); \
184  if (need_swap) { \
185  if (sizeof(v) == 4U) byteswap::swap32(&v); else byteswap::swap64(&v); \
186  } \
187  data_read = true; return !!*this; \
188 } \
189 bool vnl_matlab_readhdr::read_data(T *p) { \
190  if (!type_chck(p[0])) { std::cerr << "type_check\n"; return false; } \
191  if (rows()!=1U && cols()!=1U) { std::cerr << "size1\n"; return false; } \
192  vnl_matlab_read_data(s, p, rows()*cols()); \
193  if (need_swap) { \
194  for (long i = 0; i < rows()*cols(); ++i) { \
195  if (sizeof(*p) == 4U) byteswap::swap32(&(p[i])); else byteswap::swap64(&(p[i])); \
196  } \
197  } \
198  data_read = true; return !!*this; \
199 } \
200 bool vnl_matlab_readhdr::read_data(T * const *m) { \
201  if (!type_chck(m[0][0])) { std::cerr << "type_check\n"; return false; } \
202  T *tmp = vnl_c_vector<T >::allocate_T(rows()*cols()); \
203  vnl_matlab_read_data(s, tmp, rows()*cols()); \
204  if (need_swap) { \
205  for (long i = 0; i < rows()*cols(); ++i) { \
206  if (sizeof(T) == 4U) byteswap::swap32(&(tmp[i])); else byteswap::swap64(&(tmp[i])); \
207  } \
208  } \
209  int a, b; \
210  if (is_rowwise()) { a = cols(); b = 1; } \
211  else { a = 1; b = rows(); } \
212  for (long i=0; i<rows(); ++i) \
213  for (long j=0; j<cols(); ++j) \
214  m[i][j] = tmp[a*i + b*j]; \
215  vnl_c_vector<T >::deallocate(tmp, rows()*cols()); \
216  data_read = true; return !!*this; \
217 }
218 
219 fsm_define_methods(float);
220 fsm_define_methods(double);
221 fsm_define_methods(std::complex<float>);
222 fsm_define_methods(std::complex<double>);
223 #undef fsm_define_methods
224 
225 //--------------------------------------------------------------------------------
226 
227 #include <vnl/vnl_vector.h>
228 #include <vnl/vnl_matrix.h>
229 
230 template <class T>
231 bool vnl_matlab_read_or_die(std::istream &s,
232  vnl_vector<T> &v,
233  char const *name)
234 {
235  vnl_matlab_readhdr h(s);
236  if (!s) // eof?
237  return false;
238  if (name && *name) {
239  if (std::strcmp(name, h.name())!=0) { /*wrong name?*/
240  std::cerr << "vnl_matlab_read_or_die: names do not match\n";
241  std::abort();
242  }
243  }
244  if (v.size() != (unsigned long)(h.rows()*h.cols()))
245  {
246  vcl_destroy(&v);
247  new (&v) vnl_vector<T>(h.rows()*h.cols());
248  }
249  if ( ! h.read_data(v.begin()) ) { /*wrong type?*/
250  std::cerr << "vnl_matlab_read_or_die: failed to read data\n";
251  std::abort();
252  }
253  return true;
254 }
255 
256 template <class T>
257 bool vnl_matlab_read_or_die(std::istream &s,
258  vnl_matrix<T> &M,
259  char const *name)
260 {
261  vnl_matlab_readhdr h(s);
262  if (!s) // eof?
263  return false;
264  if (name && *name) {
265  if (std::strcmp(name, h.name())!=0) { /*wrong name?*/
266  std::cerr << "vnl_matlab_read_or_die: names do not match\n";
267  std::abort();
268  }
269  }
270  if (M.rows() != (unsigned long)(h.rows()) || M.cols() != (unsigned long)(h.cols()))
271  {
272  vcl_destroy(&M);
273  new (&M) vnl_matrix<T>(h.rows(), h.cols());
274  }
275  if ( ! h.read_data(M.data_array()) ) { /*wrong type?*/
276  std::cerr << "vnl_matlab_read_or_die: failed to read data\n";
277  std::abort();
278  }
279  return true;
280 }
281 
282 #define inst(T) \
283 template VNL_EXPORT bool vnl_matlab_read_or_die(std::istream &, vnl_vector<T> &, char const *); \
284 template VNL_EXPORT bool vnl_matlab_read_or_die(std::istream &, vnl_matrix<T> &, char const *);
285 
286 inst(double);
287 inst(float);
bool is_complex() const
unsigned int cols() const
Return the number of columns.
Definition: vnl_matrix.h:183
bool vnl_matlab_read_or_die(std::istream &s, vnl_vector< T > &v, char const *name)
Attempt to read vector or matrix.
An ordinary mathematical matrix.
void read_hdr()
internal.
vnl_matlab_header hdr
void vcl_destroy(T *p)
Read from MATLAB files.
void swap32(void *ptr)
bool is_rowwise() const
#define v
Definition: vnl_vector.h:42
bool is_bigendian() const
void vnl_read_bytes(std::istream &s, void *p, unsigned bytes)
char const * name() const
An ordinary mathematical matrix.
Definition: vnl_adjugate.h:22
bool is_single() const
T const *const * data_array() const
Access the 2D array, so that elements can be accessed with array[row][col] directly.
Definition: vnl_matrix.h:609
#define fsm_define_methods(T)
Mathematical vector class, templated by type of element.
Definition: vnl_fwd.h:16
void vnl_matlab_read_data(std::istream &s, float *p, unsigned n)
bool operator!() const
void vcl_construct(U *p, V const &value)
unsigned int rows() const
Return the number of rows.
Definition: vnl_matrix.h:179
#define implement_read_complex_data(T)
std::istream & s
vnl_matlab_readhdr(std::istream &)
#define inst(T)
Math on blocks of memory.