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

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

© 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.7.1 (Wed Mar 12 2014)