[ 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 /* 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

© 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.10.0 (Mon Nov 18 2013)