[ 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/*++++++++++++++++++++++++++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
117VIGRA_MATLAB_VALUETYPE_UTIL(double, Double, mxDOUBLE_CLASS, double)
118VIGRA_MATLAB_VALUETYPE_UTIL(float, Single, mxSINGLE_CLASS, single)
119VIGRA_MATLAB_VALUETYPE_UTIL(Int8, Int8, mxINT8_CLASS, int8)
120VIGRA_MATLAB_VALUETYPE_UTIL(UInt8, Uint8, mxUINT8_CLASS, uint8)
121VIGRA_MATLAB_VALUETYPE_UTIL(Int16, Int16, mxINT16_CLASS, int16)
122VIGRA_MATLAB_VALUETYPE_UTIL(UInt16, Uint16, mxUINT16_CLASS, uint16)
123
124#if VIGRA_BITSOF_INT == 32
125VIGRA_MATLAB_VALUETYPE_UTIL(int, Int32, mxINT32_CLASS, int32)
126VIGRA_MATLAB_VALUETYPE_UTIL(unsigned int, Uint32, mxUINT32_CLASS, uint32)
127#elif VIGRA_BITSOF_INT == 64
128VIGRA_MATLAB_VALUETYPE_UTIL(int, Int64, mxINT64_CLASS, int64)
129VIGRA_MATLAB_VALUETYPE_UTIL(unsigned int, Uint64, mxUINT64_CLASS, uint64)
130#endif
131
132#if VIGRA_BITSOF_LONG == 32
133VIGRA_MATLAB_VALUETYPE_UTIL(long, Int32, mxINT32_CLASS, int32)
134VIGRA_MATLAB_VALUETYPE_UTIL(unsigned long, Uint32, mxUINT32_CLASS, uint32)
135#elif VIGRA_BITSOF_LONG == 64
136VIGRA_MATLAB_VALUETYPE_UTIL(long, Int64, mxINT64_CLASS, int64)
137VIGRA_MATLAB_VALUETYPE_UTIL(unsigned long, Uint64, mxUINT64_CLASS, uint64)
138#endif
139
140#if VIGRA_BITSOF_LONG_LONG == 32
141VIGRA_MATLAB_VALUETYPE_UTIL(long long, Int32, mxINT32_CLASS, int32)
142VIGRA_MATLAB_VALUETYPE_UTIL(unsigned long long, Uint32, mxUINT32_CLASS, uint32)
143#elif VIGRA_BITSOF_LONG_LONG == 64
144VIGRA_MATLAB_VALUETYPE_UTIL(long long, Int64, mxINT64_CLASS, int64)
145VIGRA_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>
311TinyVectorView<T, SIZE>
312getTinyVector(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
330getShape(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>
346MultiArrayView<DIM, T>
347getMultiArray(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>
384MultiArrayView<DIM, T>
385createMultiArray(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>
396MultiArrayView<DIM, T>
397createMultiArray(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>
409getArray(mxArray const * t)
410{
411 return getMultiArray<1, T>(t);
412}
413
414 template <class T>
415 inline MultiArrayView<1, T>
416createArray(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>
423createArray(MultiArrayIndex size, CellArray::Proxy t)
424{
425 return createMultiArray<1, T>(MultiArrayShape<1>::type(size), t);
426}
427
428 template <class T>
429MultiArrayView<2, T>
430getMatrix(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>
452MultiArrayView<2, T>
453createMatrix(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>
464MultiArrayView<2, T>
465createMatrix(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>
476BasicImageView<T>
477getImage(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>
495BasicImageView<T>
496createImage(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>
504BasicImageView<T>
505createImage(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
513getCellArray(mxArray const * t)
514{
515 return ConstCellArray(t);
516}
517
518 inline CellArray
519createCellArray(mwSize size, mxArray * & t)
520{
521 mwSize matSize[] = { size };
522 t = mxCreateCellArray(1, matSize);
523
524 return CellArray(t);
525}
526
527 inline CellArray
528createCellArray(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
537getStructArray(mxArray const * t)
538{
539 return ConstStructArray(t);
540}
541
542 template<class T>
543T
544getScalar(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>
554mxArray *
555createScalar(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
563getString(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 mwIndex* jc = mxGetJc(in);
1183 mwIndex* 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
vigra::MultiArrayShape::type
TinyVector< MultiArrayIndex, N > type
Definition multi_shape.hxx:272
vigra::MultiArrayView::difference_type
MultiArrayShape< actual_dimension >::type difference_type
Definition multi_array.hxx:739
vigra::RGBValue
Class for a single RGB value.
Definition rgbvalue.hxx:128
vigra::TinyVectorBase::size
size_type size() const
Definition tinyvector.hxx:913
vigra::acc::get
LookupTag< TAG, A >::result_type get(A const &a)
Definition accumulator.hxx:2942
vigra
vigra::Int16
detail::SelectIntegerType< 16, detail::SignedIntTypes >::type Int16
16-bit signed int
Definition sized_int.hxx:173
vigra::UInt8
detail::SelectIntegerType< 8, detail::UnsignedIntTypes >::type UInt8
8-bit unsigned int
Definition sized_int.hxx:179
vigra::Int8
detail::SelectIntegerType< 8, detail::SignedIntTypes >::type Int8
8-bit signed int
Definition sized_int.hxx:171
vigra::UInt16
detail::SelectIntegerType< 16, detail::UnsignedIntTypes >::type UInt16
16-bit unsigned int
Definition sized_int.hxx:181
vigra::Int64
detail::SelectIntegerType< 64, detail::SignedIntTypes >::type Int64
64-bit signed int
Definition sized_int.hxx:177
vigra::MultiArrayIndex
std::ptrdiff_t MultiArrayIndex
Definition multi_fwd.hxx:60
vigra::Int32
detail::SelectIntegerType< 32, detail::SignedIntTypes >::type Int32
32-bit signed int
Definition sized_int.hxx:175

© 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.12.1