[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

matlab.hxx VIGRA

1 /************************************************************************/
2 /* */
3 /* Copyright 2008 by Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* Software is furnished to do so, subject to the following */
16 /* conditions: */
17 /* restriction, including without limitation the rights to use, */
18 /* copy, modify, merge, publish, distribute, sublicense, and/or */
19 /* sell copies of the Software, and to permit persons to whom the */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35 
36 
37 #ifndef VIGRA_MATLAB_HXX
38 #define VIGRA_MATLAB_HXX
39 
40 #include <string>
41 
42 #include "array_vector.hxx"
43 #include "sized_int.hxx"
44 #include "matrix.hxx"
45 #include <map>
46 #include <time.h>
47 // This is needed with visual studio 10
48 #ifdef _CHAR16T
49 #define CHAR16_T
50 #endif
51 #include <mex.h>
52 #include "matlab_FLEXTYPE.hxx"
53 
54 namespace vigra {
55 
56 namespace matlab {
57 
58 template <class T>
59 struct ValueType;
60 
61 #define VIGRA_MATLAB_VALUETYPE_UTIL(type, functionName, typeID, matTypeName) \
62 template <> \
63 struct ValueType<type> \
64 { \
65  static bool check(mxArray const * t) \
66  { \
67  return mxIs##functionName(t); \
68  } \
69  \
70  static mxClassID const classID = typeID; \
71  \
72  static std::string typeName() \
73  { \
74  return #matTypeName; \
75  } \
76 };
77 
78 VIGRA_MATLAB_VALUETYPE_UTIL(double, Double, mxDOUBLE_CLASS, double)
79 VIGRA_MATLAB_VALUETYPE_UTIL(float, Single, mxSINGLE_CLASS, single)
80 VIGRA_MATLAB_VALUETYPE_UTIL(Int8, Int8, mxINT8_CLASS, int8)
81 VIGRA_MATLAB_VALUETYPE_UTIL(UInt8, Uint8, mxUINT8_CLASS, uint8)
82 VIGRA_MATLAB_VALUETYPE_UTIL(Int16, Int16, mxINT16_CLASS, int16)
83 VIGRA_MATLAB_VALUETYPE_UTIL(UInt16, Uint16, mxUINT16_CLASS, uint16)
84 
85 #if VIGRA_BITSOF_INT == 32
86 VIGRA_MATLAB_VALUETYPE_UTIL(int, Int32, mxINT32_CLASS, int32)
87 VIGRA_MATLAB_VALUETYPE_UTIL(unsigned int, Uint32, mxUINT32_CLASS, uint32)
88 #elif VIGRA_BITSOF_INT == 64
89 VIGRA_MATLAB_VALUETYPE_UTIL(int, Int64, mxINT64_CLASS, int64)
90 VIGRA_MATLAB_VALUETYPE_UTIL(unsigned int, Uint64, mxUINT64_CLASS, uint64)
91 #endif
92 
93 #if VIGRA_BITSOF_LONG == 32
94 VIGRA_MATLAB_VALUETYPE_UTIL(long, Int32, mxINT32_CLASS, int32)
95 VIGRA_MATLAB_VALUETYPE_UTIL(unsigned long, Uint32, mxUINT32_CLASS, uint32)
96 #elif VIGRA_BITSOF_LONG == 64
97 VIGRA_MATLAB_VALUETYPE_UTIL(long, Int64, mxINT64_CLASS, int64)
98 VIGRA_MATLAB_VALUETYPE_UTIL(unsigned long, Uint64, mxUINT64_CLASS, uint64)
99 #endif
100 
101 #if VIGRA_BITSOF_LONG_LONG == 32
102 VIGRA_MATLAB_VALUETYPE_UTIL(long long, Int32, mxINT32_CLASS, int32)
103 VIGRA_MATLAB_VALUETYPE_UTIL(unsigned long long, Uint32, mxUINT32_CLASS, uint32)
104 #elif VIGRA_BITSOF_LONG_LONG == 64
105 VIGRA_MATLAB_VALUETYPE_UTIL(long long, Int64, mxINT64_CLASS, int64)
106 VIGRA_MATLAB_VALUETYPE_UTIL(unsigned long long, Uint64, mxUINT64_CLASS, uint64)
107 #endif
108 
109 #undef VIGRA_MATLAB_VALUETYPE_UTIL
110 
111 class ConstStructArray
112 {
113  protected:
114  mxArray * matPointer_;
115 
116  public:
117 
118  struct Proxy
119  {
120  mxArray * matPointer_;
121  int index_;
122 
123  Proxy(mxArray * matPointer, int index)
124  : matPointer_(matPointer),
125  index_(index)
126  {}
127 
128  operator const mxArray *() const
129  {
130  return mxGetFieldByNumber(matPointer_, 0, index_);
131  }
132  };
133 
134  ConstStructArray(const mxArray * matPointer = 0)
135  : matPointer_(const_cast<mxArray *>(matPointer))
136  {
137  if(matPointer != 0 && !mxIsStruct(matPointer))
138  mexErrMsgTxt("StructArray(mxArray *): Argument must be a Matlab struct array.");
139  }
140 
141  Proxy operator[](const char * field_name) const
142  {
143  if(matPointer_ == 0)
144  mexErrMsgTxt("StructArray::operator[]: Cannot access uninitialized struct array.");
145 
146  int i = mxGetFieldNumber(matPointer_, field_name);
147  if(i == -1)
148  mexErrMsgTxt("StructArray::operator[]: Unknown field name.");
149 
150  return Proxy(matPointer_, i);
151  }
152 
153  Proxy operator[](std::string field_name) const
154  {
155  return operator[](field_name.c_str());
156  }
157 
158  bool isValid() const
159  {
160  return matPointer_ != 0;
161  }
162 
163  bool isValid(const char * field_name) const
164  {
165  return isValid() && mxGetFieldNumber(matPointer_, field_name) != -1;
166  }
167 
168  bool isValid(std::string field_name) const
169  {
170  return isValid(field_name.c_str());
171  }
172 };
173 
174 class ConstCellArray
175 {
176  protected:
177  mxArray * matPointer_;
178  int size_;
179 
180  public:
181 
182  struct Proxy
183  {
184  mxArray * matPointer_;
185  int index_;
186 
187  Proxy(mxArray * matPointer, int index)
188  : matPointer_(matPointer),
189  index_(index)
190  {}
191 
192  operator const mxArray *() const
193  {
194  return mxGetCell(matPointer_, index_);
195  }
196  };
197 
198  ConstCellArray(const mxArray * matPointer = 0)
199  : matPointer_(const_cast<mxArray *>(matPointer)),
200  size_(0)
201  {
202  if(matPointer != 0 && !mxIsCell(matPointer))
203  mexErrMsgTxt("CellArray(mxArray *): Argument must be a Matlab cell array.");
204  if(matPointer != 0)
205  size_ = static_cast<int>(mxGetNumberOfElements(matPointer));
206  else
207  size_ = -1;
208  }
209 
210  Proxy operator[](int i) const
211  {
212  if(!isValid(i))
213  mexErrMsgTxt("CellArray::operator[]: Index out of range.");
214  return Proxy(matPointer_, i);
215  }
216 
217  int size() const
218  {
219  return size_;
220  }
221 
222  bool isValid( int i ) const
223  {
224  return i >= 0 && i < size_;
225  }
226 
227 };
228 
229 class CellArray
230 : public ConstCellArray
231 {
232  public:
233 
234  struct Proxy
235  : public ConstCellArray::Proxy
236  {
237  Proxy(mxArray * matPointer, int index)
238  : ConstCellArray::Proxy(matPointer, index)
239  {}
240 
241  void operator=(mxArray * v)
242  {
243  mxDestroyArray(mxGetCell(matPointer_, index_));
244  mxSetCell(matPointer_, index_, v);
245  }
246  };
247 
248  CellArray(const mxArray * matPointer)
249  : ConstCellArray(matPointer)
250  {}
251 
252  Proxy operator[](int i)
253  {
254  if(!isValid(i))
255  mexErrMsgTxt("CellArray::operator[]: Index out of range.");
256  return Proxy(matPointer_, i);
257  }
258 
259  ConstCellArray::Proxy operator[](int i) const
260  {
261  if(!isValid(i))
262  mexErrMsgTxt("CellArray::operator[]: Index out of range.");
263  return ConstCellArray::Proxy(matPointer_, i);
264  }
265 };
266 
267 
268 
269 
270 
271 template <class T, unsigned int SIZE>
272 TinyVectorView<T, SIZE>
273 getTinyVector(mxArray const * t)
274 {
275  if(!ValueType<T>::check(t))
276  {
277  std::string msg = std::string("Input array must have type ") +
278  ValueType<T>::typeName() + ".";
279  mexErrMsgTxt(msg.c_str());
280  }
281  if(SIZE != mxGetNumberOfElements(t))
282  {
283  mexErrMsgTxt("getTinyVector(): Input array has wrong number of elements.");
284  }
285 
286  return TinyVectorView<T, SIZE>((T *)mxGetData(t));
287 }
288 
289 template <unsigned int SIZE>
290 typename MultiArrayShape<SIZE>::type
291 getShape(mxArray const * t)
292 {
293  if(!ValueType<Int32>::check(t))
294  {
295  std::string msg = std::string("Input array must have type 'int32'.");
296  mexErrMsgTxt(msg.c_str());
297  }
298  if(SIZE != mxGetNumberOfElements(t))
299  {
300  mexErrMsgTxt("getShape(): Input array has wrong number of elements.");
301  }
302  TinyVectorView<Int32, SIZE> res((MultiArrayIndex *)mxGetData(t));
303  return typename MultiArrayShape<SIZE>::type(res);
304 }
305 
306 template <int DIM, class T>
307 MultiArrayView<DIM, T>
308 getMultiArray(mxArray const * t)
309 {
310  typedef typename MultiArrayView<DIM, T>::difference_type Shape;
311 
312  if(!ValueType<T>::check(t))
313  {
314  std::string msg = std::string("getMultiArray(): Input array must have type ") +
315  ValueType<T>::typeName() + ".";
316  mexErrMsgTxt(msg.c_str());
317  }
318 
319  Shape shape;
320  if(DIM > 1)
321  {
322  int mdim = mxGetNumberOfDimensions(t);
323  if(DIM < mdim)
324  {
325  mexErrMsgTxt("getMultiArray(): Input array has too many dimensions.");
326  }
327  const mwSize * matlabShape = mxGetDimensions(t);
328  for(int k=0; k<mdim; ++k)
329  {
330  shape[k] = static_cast<typename Shape::value_type>(matlabShape[k]);
331  }
332  for(int k=mdim; k<DIM; ++k)
333  {
334  shape[k] = 1;
335  }
336  }
337  else
338  {
339  shape[0] = static_cast<typename Shape::value_type>(mxGetNumberOfElements(t));
340  }
341  return MultiArrayView<DIM, T>(shape, (T *)mxGetData(t));
342 }
343 
344 template <int DIM, class T>
345 MultiArrayView<DIM, T>
346 createMultiArray(typename MultiArrayShape<DIM>::type const & shape, mxArray * & t)
347 {
348  mwSize matlabShape[DIM];
349  for(int k=0; k<DIM; ++k)
350  matlabShape[k] = static_cast<mwSize>(shape[k]);
351  t = mxCreateNumericArray(DIM, matlabShape, ValueType<T>::classID, mxREAL);
352 
353  return MultiArrayView<DIM, T>(shape, (T *)mxGetData(t));
354 }
355 
356 template <int DIM, class T>
357 MultiArrayView<DIM, T>
358 createMultiArray(typename MultiArrayShape<DIM>::type const & shape, CellArray::Proxy t)
359 {
360  mwSize matlabShape[DIM];
361  for(int k=0; k<DIM; ++k)
362  matlabShape[k] = static_cast<mwSize>(shape[k]);
363  t = mxCreateNumericArray(DIM, matlabShape, ValueType<T>::classID, mxREAL);
364 
365  return MultiArrayView<DIM, T>(shape, (T *)mxGetData(t));
366 }
367 
368 template <class T>
369 inline MultiArrayView<1, T>
370 getArray(mxArray const * t)
371 {
372  return getMultiArray<1, T>(t);
373 }
374 
375 template <class T>
376 inline MultiArrayView<1, T>
377 createArray(MultiArrayIndex size, mxArray * & t)
378 {
379  return createMultiArray<1, T>(MultiArrayShape<1>::type(size), t);
380 }
381 
382 template <class T>
383 inline MultiArrayView<1, T>
384 createArray(MultiArrayIndex size, CellArray::Proxy t)
385 {
386  return createMultiArray<1, T>(MultiArrayShape<1>::type(size), t);
387 }
388 
389 template <class T>
390 MultiArrayView<2, T>
391 getMatrix(mxArray const * t)
392 {
393  typedef typename MultiArrayView<2, T>::difference_type Shape;
394 
395  if(!ValueType<T>::check(t))
396  {
397  std::string msg = std::string("getMatrix(): Input matrix must have type ") +
398  ValueType<T>::typeName() + ".";
399  mexErrMsgTxt(msg.c_str());
400  }
401 
402  if(2 != mxGetNumberOfDimensions(t))
403  mexErrMsgTxt("getMatrix(): Input matrix must have 2 dimensions.");
404 
405  const mwSize * matlabShape = mxGetDimensions(t);
406  Shape shape(static_cast<MultiArrayIndex>(matlabShape[0]),
407  static_cast<MultiArrayIndex>(matlabShape[1]));
408 
409  return MultiArrayView<2, T>(shape, (T *)mxGetData(t));
410 }
411 
412 template <class T>
413 MultiArrayView<2, T>
414 createMatrix(mwSize rowCount, mwSize columnCount, mxArray * & t)
415 {
416  typedef typename MultiArrayView<2, T>::difference_type Shape;
417 
418  Shape shape(rowCount, columnCount);
419  t = mxCreateNumericMatrix(rowCount, columnCount, ValueType<T>::classID, mxREAL);
420 
421  return MultiArrayView<2, T>(shape, (T *)mxGetData(t));
422 }
423 
424 template <class T>
425 MultiArrayView<2, T>
426 createMatrix(mwSize rowCount, mwSize columnCount, CellArray::Proxy t)
427 {
428  typedef typename MultiArrayView<2, T>::difference_type Shape;
429 
430  Shape shape(rowCount, columnCount);
431  t = mxCreateNumericMatrix(rowCount, columnCount, ValueType<T>::classID, mxREAL);
432 
433  return MultiArrayView<2, T>(shape, (T *)mxGetData(t));
434 }
435 
436 template <class T>
437 BasicImageView<T>
438 getImage(mxArray const * t)
439 {
440  if(!ValueType<T>::check(t))
441  {
442  std::string msg = std::string("getImage(): Input matrix must have type ") +
443  ValueType<T>::typeName() + ".";
444  mexErrMsgTxt(msg.c_str());
445  }
446 
447  if(2 != mxGetNumberOfDimensions(t))
448  mexErrMsgTxt("getImage(): Input matrix must have 2 dimensions.");
449 
450  const mwSize * matlabShape = mxGetDimensions(t);
451  return BasicImageView<T>((T *)mxGetData(t), static_cast<int>(matlabShape[0]),
452  static_cast<int>(matlabShape[1]));
453 }
454 
455 template <class T>
456 BasicImageView<T>
457 createImage(mwSize width, mwSize height, mxArray * & t)
458 {
459  t = mxCreateNumericMatrix(width, height, ValueType<T>::classID, mxREAL);
460 
461  return BasicImageView<T>((T *)mxGetData(t), width, height);
462 }
463 
464 template <class T>
465 BasicImageView<T>
466 createImage(mwSize width, mwSize height, CellArray::Proxy t)
467 {
468  t = mxCreateNumericMatrix(width, height, ValueType<T>::classID, mxREAL);
469 
470  return BasicImageView<T>((T *)mxGetData(t), width, height);
471 }
472 
473 inline ConstCellArray
474 getCellArray(mxArray const * t)
475 {
476  return ConstCellArray(t);
477 }
478 
479 inline CellArray
480 createCellArray(mwSize size, mxArray * & t)
481 {
482  mwSize matSize[] = { size };
483  t = mxCreateCellArray(1, matSize);
484 
485  return CellArray(t);
486 }
487 
488 inline CellArray
489 createCellArray(mwSize size, CellArray::Proxy t)
490 {
491  mwSize matSize[] = { size };
492  t = mxCreateCellArray(1, matSize);
493 
494  return CellArray(t);
495 }
496 
497 inline ConstStructArray
498 getStructArray(mxArray const * t)
499 {
500  return ConstStructArray(t);
501 }
502 
503 template<class T>
504 T
505 getScalar(mxArray const * t)
506 {
507  if(mxIsEmpty(t))
508  mexErrMsgTxt("getScalar() on empty input.");
509  if(!mxIsNumeric(t) && !mxIsLogical(t))
510  mexErrMsgTxt("getScalar(): argument is not numeric.");
511  return static_cast<T>(mxGetScalar(t));
512 }
513 
514 template<class T>
515 mxArray *
516 createScalar(T v)
517 {
518  mxArray * m;
519  createMatrix<double>(1, 1, m)(0,0) = static_cast<double>(v);
520  return m;
521 }
522 
523 inline std::string
524 getString(mxArray const * t)
525 {
526  if(mxIsEmpty(t))
527  mexErrMsgTxt("getString() on empty input.");
528  if(!mxIsChar(t))
529  mexErrMsgTxt("getString(): argument is not a string.");
530  int size = static_cast<int>(mxGetNumberOfElements(t) + 1);
531  ArrayVector<char> buf(size);
532  mxGetString(t, buf.begin(), size);
533  return std::string(buf.begin());
534 }
535 
536 
537 
538 class CompileTimeError;
539 
540 namespace detail {
541 
542 class Required
543 {
544  public:
545  void argumentWasProvided() const { /* empty because required arguments are always provided */ }
546 };
547 
548 
549 template<class T>
550 class DefaultImpl
551 {
552  public:
553 
554  T defaultValue_;
555  mutable bool * argumentWasProvided_;
556 
557  DefaultImpl(T v, bool * argFlag = 0)
558  : defaultValue_(v),
559  argumentWasProvided_(argFlag)
560  {
561  if(argumentWasProvided_ != 0)
562  *argumentWasProvided_ = false;
563  }
564 
565  void argumentWasProvided() const
566  {
567  if(argumentWasProvided_ != 0)
568  *argumentWasProvided_ = true;
569  }
570 };
571 
572 class OptionalImpl
573 {
574  public:
575  mutable bool * argumentWasProvided_;
576 
577  OptionalImpl(bool * argFlag = 0)
578  : argumentWasProvided_(argFlag)
579  {
580  if(argumentWasProvided_ != 0)
581  *argumentWasProvided_ = false;
582  }
583 
584  void argumentWasProvided() const
585  {
586  if(argumentWasProvided_ != 0)
587  *argumentWasProvided_ = true;
588  }
589 };
590 
591 } // namespace detail
592 
593 inline detail::Required v_required()
594 {
595  return detail::Required();
596 }
597 
598 template<class T>
599 inline detail::DefaultImpl<T> v_default(T in)
600 {
601  return detail::DefaultImpl<T>(in);
602 }
603 
604 template<class T>
605 inline detail::DefaultImpl<T> v_default(T in, bool & argFlag)
606 {
607  return detail::DefaultImpl<T>(in, &argFlag);
608 }
609 
610 inline detail::OptionalImpl v_optional()
611 {
612  return detail::OptionalImpl();
613 }
614 
615 inline detail::OptionalImpl v_optional(bool& argFlag)
616 {
617  return detail::OptionalImpl(&argFlag);
618 }
619 
620 // TODO:
621 // * handle rgb images
622 // * handle complex matrices
623 // * handle sparse matrices
624 
625 class InputArray
626 {
627  int size_;
628  const mxArray ** data_;
629 
630  std::string createErrMsg(std::string name)
631  {
632  std::string s1;
633  s1 = "Required input '" + name + "' not found in option struct!";
634  return s1;
635  }
636  std::string createErrMsg(int pos)
637  {
638  char tmp[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
639  std::string oi(1, tmp[pos%10]);
640  std::string s1 = "Required input in signature of function at position: '"+ oi+"' has not been supplied";
641  return s1;
642  }
643 
644 
645  public:
646  ConstStructArray options_;
647 
648  /* Local Typedefs */
649  typedef const mxArray * value_type;
650  typedef value_type & reference;
651  typedef value_type const & const_reference;
652  typedef value_type * pointer;
653  typedef value_type const * const_pointer;
654  typedef int size_type;
655  typedef int difference_type;
656 
657  /*Constructor*/
658  InputArray(size_type size, pointer data)
659  : size_(size),
660  data_(data),
661  options_(isValid(size-1) && mxIsStruct(data_[size-1])
662  ? data_[size-1]
663  : 0)
664  {}
665 
666  /*Operators*/
667  const_reference operator[]( difference_type i ) const
668  {
669  if(!isValid(i))
670  mexErrMsgTxt("Too few input arguments.");
671  return data_[i];
672  }
673 
674  value_type operator[]( std::string name) const
675  {
676  std::string errMsg = "Not Found " + name +" in OptionStruct or OptionStruct not set";
677  if(!isValid(name))
678  mexErrMsgTxt(errMsg.c_str());
679  return options_[name];
680  }
681 
682 
683  /*Some More Helper Func*/
684  size_type size() const
685  {
686  return size_;
687  }
688 
689  bool isValid( difference_type i ) const
690  {
691  return i >= 0 && i < size_;
692  }
693 
694  bool isValid(std::string name) const
695  {
696  return options_.isValid(name);
697  }
698 
699  bool isEmpty(difference_type i) const
700  {
701  return mxIsEmpty(data_[i]);
702  }
703 
704  bool isEmpty(std::string name) const
705  {
706  return mxIsEmpty(options_[name]);
707  }
708 
709  bool hasData(difference_type i) const
710  {
711  return isValid(i) && !isEmpty(i);
712  }
713 
714  bool hasData(std::string name) const
715  {
716  return isValid(name) && !isEmpty(name);
717  }
718 
719  template<class Place>
720  mxClassID typeOf(Place posOrName)
721  {
722  return mxGetClassID((*this)[posOrName]);
723  }
724 
725  /*Action to take if value not set*/
726  template <class T, class U, class Place>
727  T errorOrDefault(detail::DefaultImpl<U> const & o, Place posOrName)
728  {
729  return o.defaultValue_;
730  }
731 
732  template <class T, class Place>
733  T errorOrDefault(detail::OptionalImpl, Place posOrName)
734  {
735  return T();
736  }
737 
738  template <class T, class Place>
739  T errorOrDefault(detail::Required r, Place posOrName)
740  {
741  std::string a = createErrMsg(posOrName);
742  mexErrMsgTxt( a.c_str());
743  return T();
744  }
745 
746  /*getter Func*/
747  template <class Place, class ReqType>
748  int getEnum(Place posOrName, ReqType req, std::map<std::string, int> const & converter)
749  {
750  if(!hasData(posOrName))
751  {
752  return errorOrDefault<int>(req, posOrName);
753  }
754  std::string enumAsString = matlab::getString((*this)[posOrName]);
755  typename std::map<std::string, int>::const_iterator m = converter.find(enumAsString);
756  if(m == converter.end())
757  {
758  std::string msg = std::string("Unknown option: ") + enumAsString + ".";
759  mexErrMsgTxt(msg.c_str());
760  }
761 
762  req.argumentWasProvided();
763  return (*m).second;
764  }
765 
766 
767  /*String Type*/
768  template <class Place, class ReqType>
769  std::string getString(Place posOrName, ReqType req)
770  {
771  if(!hasData(posOrName))
772  {
773  return errorOrDefault<std::string>(req, posOrName);
774  }
775  else
776  {
777  req.argumentWasProvided();
778  return matlab::getString((*this)[posOrName]);
779  }
780  }
781 
782  /*Scalar Type*/
783  template <class T,class Place, class ReqType>
784  T getScalar(Place posOrName, ReqType req)
785  {
786  if(!hasData(posOrName))
787  {
788  return errorOrDefault<T>(req, posOrName);
789  }
790  else
791  {
792  req.argumentWasProvided();
793  return matlab::getScalar<T>((*this)[posOrName]);
794  }
795  }
796 
797 
798  template <class T, class Place, class ReqType, class minClass, class maxClass>
799  T getScalarMinMax(Place posOrName, ReqType req, minClass min_, maxClass max_)
800  {
801  T temp = this->getScalar<T>(posOrName, req);
802  if (!is_in_range(temp, min_, max_))
803  mexErrMsgTxt("Value out of bounds.");
804  return temp;
805  }
806 
807  template <class T, class Place, class ReqType, class iteratorType>
808  T getScalarVals(Place posOrName, ReqType req, iteratorType begin_, iteratorType end_)
809  {
810  T temp = this->getScalar<T>(posOrName, req);
811  for(iteratorType iter = begin_; iter != end_; ++iter)
812  {
813  if((*iter) == temp) return temp;
814  }
815  mexErrMsgTxt("Value not allowed");
816  }
817 
818 
819 
820  template <class T, class Place, class ReqType, class iteratorType>
821  T getScalarVals2D3D(Place posOrName, ReqType req, iteratorType begin2D_, iteratorType end2D_,
822  iteratorType begin3D_, iteratorType end3D_,
823  int dimVar)
824  {
825  T temp = this->getScalar<T>(posOrName, req);
826  switch(dimVar)
827  {
828  case 2:
829  for(iteratorType iter = begin2D_; iter != end2D_; ++iter)
830  {
831  if((*iter) == temp) return temp;
832  }
833  break;
834  case 3:
835  for(iteratorType iter = begin3D_; iter != end3D_; ++iter)
836  {
837  if((*iter) == temp) return temp;
838  }
839  break;
840  default:
841  mexErrMsgTxt("dimVar specified must be 2 or 3");
842  }
843  mexErrMsgTxt("Value not allowed");
844  }
845 
846  template <class Place, class ReqType>
847  bool getBool(Place posOrName, ReqType req)
848  {
849  return this->getScalarMinMax<int>(posOrName, req, 0, 1) != 0;
850  }
851 
852  /*Array Type*/
853  template <unsigned int N, class T, class Place, class ReqType>
854  MultiArrayView<N,T> getMultiArray(Place posOrName, ReqType req)
855  {
856  if(!hasData(posOrName))
857  {
858  return errorOrDefault< MultiArrayView<N,T> >(req, posOrName);
859  }
860  else
861  {
862  req.argumentWasProvided();
863  value_type temp = (*this)[posOrName];
864  return matlab::getMultiArray<N,T>(temp);
865  }
866  }
867 
868  template < class T, class Place, class ReqType>
869  BasicImageView<T> getImage(Place posOrName, ReqType req)
870  {
871  if(!hasData(posOrName))
872  {
873  return errorOrDefault<BasicImageView<T> >(req, posOrName);
874  }
875  else
876  {
877  req.argumentWasProvided();
878  value_type temp = (*this)[posOrName];
879  return matlab::getImage<T>(temp);
880  }
881  }
882 
883  template<class T,unsigned int sze, class Place, class ReqType>
884  TinyVectorView< T, sze> getTinyVector(Place posOrName, ReqType req)
885  {
886  if(!hasData(posOrName))
887  {
888  return errorOrDefault<TinyVectorView< T, sze> >(req, posOrName);
889  }
890  else
891  {
892  req.argumentWasProvided();
893  value_type temp = (*this)[posOrName];
894  return matlab::getTinyVector< T, sze>(temp);
895  }
896  }
897 
898  template< unsigned int sze, class Place, class ReqType>
899  TinyVectorView<MultiArrayIndex, sze> getShape(Place posOrName, ReqType req)
900  {
901  if(!hasData(posOrName))
902  {
903  return errorOrDefault<TinyVectorView<MultiArrayIndex, sze> >(req, posOrName);
904  }
905  else
906  {
907  req.argumentWasProvided();
908  value_type temp = (*this)[posOrName];
909  return matlab::getShape<sze>(temp);
910  }
911  }
912 
913 
914  template< class Place, class ReqType>
915  int getDimOfInput(Place posOrName, ReqType req)
916  {
917  if(!hasData(posOrName))
918  {
919  return errorOrDefault<int>(req, posOrName);
920  }
921  else
922  {
923  req.argumentWasProvided();
924  return mxGetNumberOfDimensions((*this)[posOrName]);
925  }
926  }
927 
928  template<class ReqType>
929  ConstCellArray getCellArray(int posOrName, ReqType req)
930  {
931  if(!hasData(posOrName))
932  {
933  return errorOrDefault<ConstCellArray>(req, posOrName);
934  }
935  else
936  {
937  req.argumentWasProvided();
938  value_type temp = (*this)[posOrName];
939  return matlab::getCellArray(temp);
940  }
941  }
942 
943  template<class ReqType>
944  ConstCellArray getCellArray(std::string posOrName, ReqType req)
945  {
946  CompileTimeError ERROR__Const_Cell_Array_May_Not_Be_In_Option_Struct;
947  return ConstCellArray(); //avoid compiler warning
948  }
949 
950 };
951 
952 class OutputArray
953 {
954  int size_;
955  mxArray ** data_;
956  std::string createErrMsgOut(int pos)
957  {
958  char tmp[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
959  std::string oi(1, tmp[pos%10]);
960  std::string s1 = "Required Output at position: '" + oi + "' has not been supplied";
961  return s1;
962  }
963  public:
964 
965  typedef mxArray * value_type;
966  typedef value_type & reference;
967  typedef value_type const & const_reference;
968  typedef value_type * pointer;
969  typedef value_type const * const_pointer;
970  typedef int size_type;
971  typedef int difference_type;
972 
973  OutputArray(size_type size, pointer data)
974  : size_(size),
975  data_(data)
976  {}
977 
978  reference operator[]( difference_type i )
979  {
980  if(!isValid(i))
981  mexErrMsgTxt("Too few output arguments.");
982  return data_[i];
983  }
984 
985  const_reference operator[]( difference_type i ) const
986  {
987  if(!isValid(i))
988  mexErrMsgTxt("Too few output arguments.");
989  return data_[i];
990  }
991 
992  size_type size() const
993  {
994  return size_;
995  }
996 
997  bool isValid( difference_type i ) const
998  {
999  return i >= 0 && i < size_;
1000  }
1001 
1002  bool isEmpty(difference_type i){
1003  return mxIsEmpty(data_[i]);
1004  }
1005 
1006  template <class T>
1007  T errorOrDefault(detail::OptionalImpl const & o, int Pos)
1008  {
1009  return T();
1010  }
1011 
1012  template <class T>
1013  T errorOrDefault(detail::Required r, int Pos)
1014  {
1015  mexErrMsgTxt(createErrMsgOut(Pos).c_str());
1016  return T();
1017  }
1018 
1019  /* creating func */
1020  template <unsigned int DIM, class T, class ReqType>
1021  MultiArrayView<DIM, T> createMultiArray(int pos,ReqType req,
1022  const TinyVector<int, DIM> & shape)
1023  {
1024  if(!isValid(pos))
1025  return errorOrDefault<MultiArrayView<DIM, T> >(req, pos);
1026  req.argumentWasProvided();
1027  return matlab::createMultiArray<DIM, T>(shape, (*this)[pos]);
1028  }
1029 
1030  template <class T, class ReqType>
1031  BasicImageView<T> createImage(int pos, ReqType req,
1032  mwSize width, mwSize height)
1033  {
1034  if(!isValid(pos))
1035  return errorOrDefault<BasicImageView<T> >(req, pos);
1036  req.argumentWasProvided();
1037  return matlab::createImage<T>(width, height, (*this)[pos]);
1038  }
1039 
1040  template <class T, class ReqType>
1041  BasicImageView<T> createImage( int pos, ReqType req,
1042  typename MultiArrayShape<2>::type const & shape)
1043  {
1044  return createImage<T>(pos, req, shape[1], shape[0]);
1045  }
1046 
1047  template <class T, class ReqType>
1048  T* createScalar(int pos, ReqType req)
1049  {
1050  if(!isValid(pos))
1051  return errorOrDefault<T*>(req, pos);
1052  req.argumentWasProvided();
1053  BasicImageView<T> temp = matlab::createImage<T>(1, 1, (*this)[pos]);
1054  return &temp(0,0);
1055  }
1056 
1057  template <class T, class ReqType>
1058  void createScalar(int pos, ReqType req, T val)
1059  {
1060  if(!isValid(pos))
1061  {
1062  errorOrDefault<T>(req, pos);
1063  return;
1064  }
1065  req.argumentWasProvided();
1066  BasicImageView<T> temp = matlab::createImage<T>(1, 1, (*this)[pos]);
1067  temp(0,0) = val;
1068  }
1069 
1070  template <class ReqType>
1071  ConstCellArray createCellArray(int pos, ReqType req, mwSize sze)
1072  {
1073  if(!isValid(pos))
1074  return errorOrDefault<ConstCellArray>(req, pos);
1075  return matlab::createCellArray(sze, (*this)[pos]);
1076  }
1077 };
1078 
1079 
1080 
1081 /***********************************
1082 Rahuls code starts here
1083 ************************************/
1084 using namespace vigra;
1085 
1086 
1087 /*++++++++++++++++++++++++++HELPERFUNC+++++++++++++++++++++++++++++++*
1088  * This is used for better readability of the test cases .
1089  * Nothing to be done here.
1090  *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
1091 int cantorPair(int x, int y){
1092  return (int)(((x+y)*(x+y+1))/2+y);
1093 }
1094 
1095 int cantorPair(int x, int y, int z){
1096  return cantorPair(cantorPair(x,y),z);
1097 }
1098 
1099 template <int x, int y>
1100 struct cP{
1101  enum { value = (int)(((x+y)*(x+y+1))/2+y)};
1102 };
1103 
1104 template <int x, int y, int z>
1105 struct cP3{
1106  enum { value = cP<cP<x, y>::value, z>::value};
1107 };
1108 
1109 template <class T>
1110 inline bool is_in_range(T in, T min, T max)
1111 {
1112  return (in >= min && in <= max);
1113 }
1114 template<class T>
1115 inline bool is_in_range(T in, std::string min, T max)
1116 {
1117  return(in <= max);
1118 }
1119 
1120 template<class T>
1121 inline bool is_in_range(T in, T min, std::string max)
1122 {
1123  return (in >= min);
1124 }
1125 
1126 
1127 
1128 //Wrapper classes to STL-Map for use as a sparse array.
1129 
1130 //This is used for the ordering of the map. Lexicographical ordering of the index pairs.
1131 struct ShapeCmp {
1132  bool operator()( TinyVector<int,2> s1, TinyVector<int,2> s2 ) const {
1133  if(s1[0] != s2[0]){
1134  return (s1[0] < s2[0]);
1135  } else {
1136  return s1[1] < s2[1];
1137  }
1138  }
1139 };
1140 
1141 template<class T>
1142 class SparseArray
1143 {
1144 
1145  std::map<TinyVector<int,2>, T,ShapeCmp> data;
1146  int width, length;
1147 
1148  public:
1149  void assign(int i = 1, int j = 1){
1150  width = j;
1151  length = i;
1152  }
1153  SparseArray(int i = 1 , int j = 1){
1154  width = j;
1155  length = i;
1156  }
1157 
1158  //Any better idea? i would like to unify the get and operator() functions.
1159  // Problem is that operator() always passes a reference or creates one.
1160  template<class indexType>
1161  T& operator()(indexType i_, indexType j_){
1162  Int32 i = static_cast<Int32>(i_);
1163  Int32 j = static_cast<Int32>(j_);
1164  TinyVector<int,2> newShapew(i, j);
1165  typename std::map<TinyVector<int,2>, T, ShapeCmp>::iterator iter;
1166  TinyVector<int,2> newShape;
1167  return data[newShapew];
1168  }
1169 
1170  template<class indexType>
1171  const T get(indexType i_, indexType j_){
1172  Int32 i = static_cast<Int32>(i_);
1173  Int32 j = static_cast<Int32>(j_);
1174  TinyVector<int,2> newShape(i, j);
1175  if(data.find(newShape) == data.end()) return 0;
1176  else return data.find(newShape)->second;
1177  }
1178 
1179  //see documentation of mxCreateSparse and the mxGet functions to understand this.
1180  void mapToMxArray(mxArray * & in){
1181 
1182  int len = data.size();
1183  in = mxCreateSparse(width, length, len, mxREAL);
1184  int* jc = mxGetJc(in);
1185  int* ir = mxGetIr(in);
1186  double* pr = mxGetPr(in);
1187  if(len == 0){
1188  jc[0] = 1;
1189  return;
1190  }
1191  typename std::map<TinyVector<int,2>, T, ShapeCmp>::iterator iter;
1192  TinyVector<int,2> newShape;
1193  int ii = 0;
1194  int jj = 0;
1195  int curjc = -1;
1196  for( iter = data.begin(); iter != data.end(); ++iter ) {
1197  newShape = iter->first;
1198  ir[ii] = newShape[1];
1199  pr[ii] = iter->second;
1200  if(newShape[0] != curjc){
1201  curjc = newShape[0] ;
1202  jc[jj] = ii;
1203  jj++;
1204  }
1205 
1206  ii++;
1207  }
1208  jc[jj] = len;
1209  }
1210 
1211 };
1212 
1213 enum DataDimension {IMAGE = 2, VOLUME = 3};
1214 
1215 } // namespace matlab
1216 
1217 } // namespace vigra
1218 
1219 void vigraMexFunction(vigra::matlab::OutputArray, vigra::matlab::InputArray);
1220 
1221 #ifndef VIGRA_CUSTOM_MEXFUNCTION
1222 
1223 /*
1224  DO NOT Comment out this function. If you are using a
1225  custom mexfunction just #define VIGRA_CUSTOM_MEXFUNCTION
1226  before #including matlab.hxx.
1227 */
1228 void mexFunction(int nlhs, mxArray *plhs[],
1229  int nrhs, const mxArray *prhs[])
1230 {
1231  try
1232  {
1233  vigra::matlab::InputArray inputs(nrhs, prhs);
1234  vigra::matlab::OutputArray outputs(nlhs, plhs);
1235 
1236  vigraMexFunction(outputs, inputs);
1237  }
1238  catch(std::exception & e)
1239  {
1240  mexErrMsgTxt(e.what());
1241  }
1242 }
1243 
1244 #endif /*CUSTOM_MEXFUNCTION*/
1245 
1246 
1247 #define VIGRA_CREATE_ENUM_AND_STD_MAP2(mapName, item1, item2) \
1248  const int item1 = 1;\
1249  const int item2 = 2;\
1250  std::map<std::string,int> mapName;\
1251  mapName[#item1] = (int)item1;\
1252  mapName[#item2] = (int)item2;\
1253 
1254 
1255 #define VIGRA_CREATE_ENUM_AND_STD_MAP3(mapName, item1, item2, item3) \
1256  const int item1 = 1;\
1257  const int item2 = 2;\
1258  const int item3 = 3;\
1259  std::map<std::string,int> mapName;\
1260  mapName[#item1] = (int)item1;\
1261  mapName[#item2] = (int)item2;\
1262  mapName[#item3] = (int)item3;\
1263 
1264 
1265 #define VIGRA_CREATE_ENUM_AND_STD_MAP4(mapName, item1, item2, item3, item4) \
1266  const int item1 = 1;\
1267  const int item2 = 2;\
1268  const int item3 = 3;\
1269  const int item4 = 4;\
1270  std::map<std::string,int> mapName;\
1271  mapName[#item1] = (int)item1;\
1272  mapName[#item2] = (int)item2;\
1273  mapName[#item3] = (int)item3;\
1274  mapName[#item4] = (int)item4;\
1275 
1276 #define VIGRA_CREATE_ENUM_AND_STD_MAP5(mapName, item1, item2, item3, item4, item5) \
1277  const int item1 = 1;\
1278  const int item2 = 2;\
1279  const int item3 = 3;\
1280  const int item4 = 4;\
1281  const int item5 = 5;\
1282  std::map<std::string, int> mapName;\
1283  mapName[#item1] = (int)item1;\
1284  mapName[#item2] = (int)item2;\
1285  mapName[#item3] = (int)item3;\
1286  mapName[#item4] = (int)item4;\
1287  mapName[#item5] = (int)item5;\
1288 
1289 #define VIGRA_CREATE_ENUM_AND_STD_MAP6(mapName, item1, item2, item3, item4, item5, item6) \
1290  const int item1 = 1;\
1291  const int item2 = 2;\
1292  const int item3 = 3;\
1293  const int item4 = 4;\
1294  const int item5 = 5;\
1295  const int item6 = 6;\
1296  std::map<std::string,int> mapName;\
1297  mapName[#item1] = (int)item1;\
1298  mapName[#item2] = (int)item2;\
1299  mapName[#item3] = (int)item3;\
1300  mapName[#item4] = (int)item4;\
1301  mapName[#item5] = (int)item5;\
1302  mapName[#item6] = (int)item6;\
1303 
1304 #endif // VIGRA_MATLAB_HXX
MultiArrayIndex rowCount(const MultiArrayView< 2, T, C > &x)
Definition: matrix.hxx:669
detail::SelectIntegerType< 8, detail::UnsignedIntTypes >::type UInt8
8-bit unsigned int
Definition: sized_int.hxx:179
std::ptrdiff_t MultiArrayIndex
Definition: multi_fwd.hxx:60
detail::SelectIntegerType< 16, detail::UnsignedIntTypes >::type UInt16
16-bit unsigned int
Definition: sized_int.hxx:181
detail::SelectIntegerType< 64, detail::SignedIntTypes >::type Int64
64-bit signed int
Definition: sized_int.hxx:177
detail::SelectIntegerType< 16, detail::SignedIntTypes >::type Int16
16-bit signed int
Definition: sized_int.hxx:173
detail::SelectIntegerType< 32, detail::SignedIntTypes >::type Int32
32-bit signed int
Definition: sized_int.hxx:175
TinyVector< MultiArrayIndex, N > type
Definition: multi_shape.hxx:250
MultiArrayIndex columnCount(const MultiArrayView< 2, T, C > &x)
Definition: matrix.hxx:682
detail::SelectIntegerType< 8, detail::SignedIntTypes >::type Int8
8-bit signed int
Definition: sized_int.hxx:171

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.11.0