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