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 *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
cantorPair(int x,int y)62 int cantorPair(int x, int y){
63 return (int)(((x+y)*(x+y+1))/2+y);
64 }
65
cantorPair(int x,int y,int z)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>
is_in_range(T in,T min,T max)81 inline bool is_in_range(T in, T min, T max)
82 {
83 return (in >= min && in <= max);
84 }
85 template<class T>
is_in_range(T in,std::string min,T max)86 inline bool is_in_range(T in, std::string min, T max)
87 {
88 return(in <= max);
89 }
90
91 template<class T>
is_in_range(T in,T min,std::string max)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
Proxyvigra::matlab::ConstStructArray::Proxy162 Proxy(mxArray * matPointer, int index)
163 : matPointer_(matPointer),
164 index_(index)
165 {}
166
operator const mxArray*vigra::matlab::ConstStructArray::Proxy167 operator const mxArray *() const
168 {
169 return mxGetFieldByNumber(matPointer_, 0, index_);
170 }
171 };
172
ConstStructArray(const mxArray * matPointer=0)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
operator [](const char * field_name) const180 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
operator [](std::string field_name) const192 Proxy operator[](std::string field_name) const
193 {
194 return operator[](field_name.c_str());
195 }
196
isValid() const197 bool isValid() const
198 {
199 return matPointer_ != 0;
200 }
201
isValid(const char * field_name) const202 bool isValid(const char * field_name) const
203 {
204 return isValid() && mxGetFieldNumber(matPointer_, field_name) != -1;
205 }
206
isValid(std::string field_name) const207 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
Proxyvigra::matlab::ConstCellArray::Proxy226 Proxy(mxArray * matPointer, int index)
227 : matPointer_(matPointer),
228 index_(index)
229 {}
230
operator const mxArray*vigra::matlab::ConstCellArray::Proxy231 operator const mxArray *() const
232 {
233 return mxGetCell(matPointer_, index_);
234 }
235 };
236
ConstCellArray(const mxArray * matPointer=0)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
operator [](int i) const249 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
size() const256 int size() const
257 {
258 return size_;
259 }
260
isValid(int i) const261 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 {
Proxyvigra::matlab::CellArray::Proxy276 Proxy(mxArray * matPointer, int index)
277 : ConstCellArray::Proxy(matPointer, index)
278 {}
279
operator =vigra::matlab::CellArray::Proxy280 void operator=(mxArray * v)
281 {
282 mxDestroyArray(mxGetCell(matPointer_, index_));
283 mxSetCell(matPointer_, index_, v);
284 }
285 };
286
CellArray(const mxArray * matPointer)287 CellArray(const mxArray * matPointer)
288 : ConstCellArray(matPointer)
289 {}
290
operator [](int i)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
operator [](int i) const298 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>
getTinyVector(mxArray const * t)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
getShape(mxArray const * t)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>
getMultiArray(mxArray const * 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>
createMultiArray(typename MultiArrayShape<DIM>::type const & shape,mxArray * & 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>
createMultiArray(typename MultiArrayShape<DIM>::type const & shape,CellArray::Proxy 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>
getArray(mxArray const * t)409 getArray(mxArray const * t)
410 {
411 return getMultiArray<1, T>(t);
412 }
413
414 template <class T>
415 inline MultiArrayView<1, T>
createArray(MultiArrayIndex size,mxArray * & 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>
createArray(MultiArrayIndex size,CellArray::Proxy 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>
getMatrix(mxArray const * 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>
createMatrix(mwSize rowCount,mwSize columnCount,mxArray * & 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>
createMatrix(mwSize rowCount,mwSize columnCount,CellArray::Proxy 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>
getImage(mxArray const * 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>
createImage(mwSize width,mwSize height,mxArray * & 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>
createImage(mwSize width,mwSize height,CellArray::Proxy 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
getCellArray(mxArray const * t)513 getCellArray(mxArray const * t)
514 {
515 return ConstCellArray(t);
516 }
517
518 inline CellArray
createCellArray(mwSize size,mxArray * & t)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
createCellArray(mwSize size,CellArray::Proxy t)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
getStructArray(mxArray const * t)537 getStructArray(mxArray const * t)
538 {
539 return ConstStructArray(t);
540 }
541
542 template<class T>
543 T
getScalar(mxArray const * 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 *
createScalar(T v)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
getString(mxArray const * t)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:
argumentWasProvided() const584 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
DefaultImpl(T v,bool * argFlag=0)596 DefaultImpl(T v, bool * argFlag = 0)
597 : defaultValue_(v),
598 argumentWasProvided_(argFlag)
599 {
600 if(argumentWasProvided_ != 0)
601 *argumentWasProvided_ = false;
602 }
603
argumentWasProvided() const604 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
OptionalImpl(bool * argFlag=0)616 OptionalImpl(bool * argFlag = 0)
617 : argumentWasProvided_(argFlag)
618 {
619 if(argumentWasProvided_ != 0)
620 *argumentWasProvided_ = false;
621 }
622
argumentWasProvided() const623 void argumentWasProvided() const
624 {
625 if(argumentWasProvided_ != 0)
626 *argumentWasProvided_ = true;
627 }
628 };
629
630 } // namespace detail
631
v_required()632 inline detail::Required v_required()
633 {
634 return detail::Required();
635 }
636
637 template<class T>
v_default(T in)638 inline detail::DefaultImpl<T> v_default(T in)
639 {
640 return detail::DefaultImpl<T>(in);
641 }
642
643 template<class T>
v_default(T in,bool & argFlag)644 inline detail::DefaultImpl<T> v_default(T in, bool & argFlag)
645 {
646 return detail::DefaultImpl<T>(in, &argFlag);
647 }
648
v_optional()649 inline detail::OptionalImpl v_optional()
650 {
651 return detail::OptionalImpl();
652 }
653
v_optional(bool & argFlag)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
createErrMsg(std::string name)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 }
createErrMsg(int pos)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*/
InputArray(size_type size,pointer data)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*/
operator [](difference_type i) const706 const_reference operator[]( difference_type i ) const
707 {
708 if(!isValid(i))
709 mexErrMsgTxt("Too few input arguments.");
710 return data_[i];
711 }
712
operator [](std::string name) const713 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*/
size() const723 size_type size() const
724 {
725 return size_;
726 }
727
isValid(difference_type i) const728 bool isValid( difference_type i ) const
729 {
730 return i >= 0 && i < size_;
731 }
732
isValid(std::string name) const733 bool isValid(std::string name) const
734 {
735 return options_.isValid(name);
736 }
737
isEmpty(difference_type i) const738 bool isEmpty(difference_type i) const
739 {
740 return mxIsEmpty(data_[i]);
741 }
742
isEmpty(std::string name) const743 bool isEmpty(std::string name) const
744 {
745 return mxIsEmpty(options_[name]);
746 }
747
hasData(difference_type i) const748 bool hasData(difference_type i) const
749 {
750 return isValid(i) && !isEmpty(i);
751 }
752
hasData(std::string name) const753 bool hasData(std::string name) const
754 {
755 return isValid(name) && !isEmpty(name);
756 }
757
758 template<class Place>
typeOf(Place posOrName)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>
getEnum(Place posOrName,ReqType req,std::map<std::string,int> const & converter)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>
getString(Place posOrName,ReqType req)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>
getBool(Place posOrName,ReqType req)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>
getMultiArray(Place posOrName,ReqType req)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>
getImage(Place posOrName,ReqType req)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>
getTinyVector(Place posOrName,ReqType req)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>
getShape(Place posOrName,ReqType req)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>
getDimOfInput(Place posOrName,ReqType req)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>
getCellArray(int posOrName,ReqType req)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>
getCellArray(std::string posOrName,ReqType req)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_;
createErrMsgOut(int pos)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
OutputArray(size_type size,pointer data)1012 OutputArray(size_type size, pointer data)
1013 : size_(size),
1014 data_(data)
1015 {}
1016
operator [](difference_type i)1017 reference operator[]( difference_type i )
1018 {
1019 if(!isValid(i))
1020 mexErrMsgTxt("Too few output arguments.");
1021 return data_[i];
1022 }
1023
operator [](difference_type i) const1024 const_reference operator[]( difference_type i ) const
1025 {
1026 if(!isValid(i))
1027 mexErrMsgTxt("Too few output arguments.");
1028 return data_[i];
1029 }
1030
size() const1031 size_type size() const
1032 {
1033 return size_;
1034 }
1035
isValid(difference_type i) const1036 bool isValid( difference_type i ) const
1037 {
1038 return i >= 0 && i < size_;
1039 }
1040
isEmpty(difference_type i)1041 bool isEmpty(difference_type i){
1042 return mxIsEmpty(data_[i]);
1043 }
1044
1045 template <class T>
errorOrDefault(detail::OptionalImpl const & o,int Pos)1046 T errorOrDefault(detail::OptionalImpl const & o, int Pos)
1047 {
1048 return T();
1049 }
1050
1051 template <class T>
errorOrDefault(detail::Required r,int Pos)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>
createMultiArray(int pos,ReqType req,const TinyVector<int,DIM> & shape)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>
createImage(int pos,ReqType req,mwSize width,mwSize height)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>
createImage(int pos,ReqType req,typename MultiArrayShape<2>::type const & shape)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>
createScalar(int pos,ReqType req,T val)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>
createCellArray(int pos,ReqType req,mwSize sze)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 {
operator ()vigra::matlab::ShapeCmp1130 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:
assign(int i=1,int j=1)1147 void assign(int i = 1, int j = 1){
1148 width = j;
1149 length = i;
1150 }
SparseArray(int i=1,int j=1)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>
operator ()(indexType i_,indexType j_)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>
get(indexType i_,indexType j_)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.
mapToMxArray(mxArray * & in)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 */
mexFunction(int nlhs,mxArray * plhs[],int nrhs,const mxArray * prhs[])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
1303