[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]
vigra/matlab.hxx | ![]() |
00001 /************************************************************************/ 00002 /* */ 00003 /* Copyright 2008 by Ullrich Koethe */ 00004 /* */ 00005 /* This file is part of the VIGRA computer vision library. */ 00006 /* The VIGRA Website is */ 00007 /* http://hci.iwr.uni-heidelberg.de/vigra/ */ 00008 /* Please direct questions, bug reports, and contributions to */ 00009 /* ullrich.koethe@iwr.uni-heidelberg.de or */ 00010 /* vigra@informatik.uni-hamburg.de */ 00011 /* */ 00012 /* Permission is hereby granted, free of charge, to any person */ 00013 /* obtaining a copy of this software and associated documentation */ 00014 /* files (the "Software"), to deal in the Software without */ 00015 /* Software is furnished to do so, subject to the following */ 00016 /* conditions: */ 00017 /* restriction, including without limitation the rights to use, */ 00018 /* copy, modify, merge, publish, distribute, sublicense, and/or */ 00019 /* sell copies of the Software, and to permit persons to whom the */ 00020 /* */ 00021 /* The above copyright notice and this permission notice shall be */ 00022 /* included in all copies or substantial portions of the */ 00023 /* Software. */ 00024 /* */ 00025 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */ 00026 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */ 00027 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */ 00028 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */ 00029 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ 00030 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ 00031 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ 00032 /* OTHER DEALINGS IN THE SOFTWARE. */ 00033 /* */ 00034 /************************************************************************/ 00035 00036 00037 #ifndef VIGRA_MATLAB_HXX 00038 #define VIGRA_MATLAB_HXX 00039 00040 #include <string> 00041 00042 #include "array_vector.hxx" 00043 #include "sized_int.hxx" 00044 #include "matrix.hxx" 00045 #include <map> 00046 #include <time.h> 00047 // This is needed with visual studio 10 00048 #ifdef _CHAR16T 00049 #define CHAR16_T 00050 #endif 00051 #include <mex.h> 00052 #include "matlab_FLEXTYPE.hxx" 00053 00054 namespace vigra { 00055 00056 namespace matlab { 00057 00058 template <class T> 00059 struct ValueType; 00060 00061 #define VIGRA_MATLAB_VALUETYPE_UTIL(type, functionName, typeID, matTypeName) \ 00062 template <> \ 00063 struct ValueType<type> \ 00064 { \ 00065 static bool check(mxArray const * t) \ 00066 { \ 00067 return mxIs##functionName(t); \ 00068 } \ 00069 \ 00070 static mxClassID const classID = typeID; \ 00071 \ 00072 static std::string typeName() \ 00073 { \ 00074 return #matTypeName; \ 00075 } \ 00076 }; 00077 00078 VIGRA_MATLAB_VALUETYPE_UTIL(double, Double, mxDOUBLE_CLASS, double) 00079 VIGRA_MATLAB_VALUETYPE_UTIL(float, Single, mxSINGLE_CLASS, single) 00080 VIGRA_MATLAB_VALUETYPE_UTIL(Int8, Int8, mxINT8_CLASS, int8) 00081 VIGRA_MATLAB_VALUETYPE_UTIL(UInt8, Uint8, mxUINT8_CLASS, uint8) 00082 VIGRA_MATLAB_VALUETYPE_UTIL(Int16, Int16, mxINT16_CLASS, int16) 00083 VIGRA_MATLAB_VALUETYPE_UTIL(UInt16, Uint16, mxUINT16_CLASS, uint16) 00084 00085 #if VIGRA_BITSOF_INT == 32 00086 VIGRA_MATLAB_VALUETYPE_UTIL(int, Int32, mxINT32_CLASS, int32) 00087 VIGRA_MATLAB_VALUETYPE_UTIL(unsigned int, Uint32, mxUINT32_CLASS, uint32) 00088 #elif VIGRA_BITSOF_INT == 64 00089 VIGRA_MATLAB_VALUETYPE_UTIL(int, Int64, mxINT64_CLASS, int64) 00090 VIGRA_MATLAB_VALUETYPE_UTIL(unsigned int, Uint64, mxUINT64_CLASS, uint64) 00091 #endif 00092 00093 #if VIGRA_BITSOF_LONG == 32 00094 VIGRA_MATLAB_VALUETYPE_UTIL(long, Int32, mxINT32_CLASS, int32) 00095 VIGRA_MATLAB_VALUETYPE_UTIL(unsigned long, Uint32, mxUINT32_CLASS, uint32) 00096 #elif VIGRA_BITSOF_LONG == 64 00097 VIGRA_MATLAB_VALUETYPE_UTIL(long, Int64, mxINT64_CLASS, int64) 00098 VIGRA_MATLAB_VALUETYPE_UTIL(unsigned long, Uint64, mxUINT64_CLASS, uint64) 00099 #endif 00100 00101 #if VIGRA_BITSOF_LONG_LONG == 32 00102 VIGRA_MATLAB_VALUETYPE_UTIL(long long, Int32, mxINT32_CLASS, int32) 00103 VIGRA_MATLAB_VALUETYPE_UTIL(unsigned long long, Uint32, mxUINT32_CLASS, uint32) 00104 #elif VIGRA_BITSOF_LONG_LONG == 64 00105 VIGRA_MATLAB_VALUETYPE_UTIL(long long, Int64, mxINT64_CLASS, int64) 00106 VIGRA_MATLAB_VALUETYPE_UTIL(unsigned long long, Uint64, mxUINT64_CLASS, uint64) 00107 #endif 00108 00109 #undef VIGRA_MATLAB_VALUETYPE_UTIL 00110 00111 class ConstStructArray 00112 { 00113 protected: 00114 mxArray * matPointer_; 00115 00116 public: 00117 00118 struct Proxy 00119 { 00120 mxArray * matPointer_; 00121 int index_; 00122 00123 Proxy(mxArray * matPointer, int index) 00124 : matPointer_(matPointer), 00125 index_(index) 00126 {} 00127 00128 operator const mxArray *() const 00129 { 00130 return mxGetFieldByNumber(matPointer_, 0, index_); 00131 } 00132 }; 00133 00134 ConstStructArray(const mxArray * matPointer = 0) 00135 : matPointer_(const_cast<mxArray *>(matPointer)) 00136 { 00137 if(matPointer != 0 && !mxIsStruct(matPointer)) 00138 mexErrMsgTxt("StructArray(mxArray *): Argument must be a Matlab struct array."); 00139 } 00140 00141 Proxy operator[](const char * field_name) const 00142 { 00143 if(matPointer_ == 0) 00144 mexErrMsgTxt("StructArray::operator[]: Cannot access uninitialized struct array."); 00145 00146 int i = mxGetFieldNumber(matPointer_, field_name); 00147 if(i == -1) 00148 mexErrMsgTxt("StructArray::operator[]: Unknown field name."); 00149 00150 return Proxy(matPointer_, i); 00151 } 00152 00153 Proxy operator[](std::string field_name) const 00154 { 00155 return operator[](field_name.c_str()); 00156 } 00157 00158 bool isValid() const 00159 { 00160 return matPointer_ != 0; 00161 } 00162 00163 bool isValid(const char * field_name) const 00164 { 00165 return isValid() && mxGetFieldNumber(matPointer_, field_name) != -1; 00166 } 00167 00168 bool isValid(std::string field_name) const 00169 { 00170 return isValid(field_name.c_str()); 00171 } 00172 }; 00173 00174 class ConstCellArray 00175 { 00176 protected: 00177 mxArray * matPointer_; 00178 int size_; 00179 00180 public: 00181 00182 struct Proxy 00183 { 00184 mxArray * matPointer_; 00185 int index_; 00186 00187 Proxy(mxArray * matPointer, int index) 00188 : matPointer_(matPointer), 00189 index_(index) 00190 {} 00191 00192 operator const mxArray *() const 00193 { 00194 return mxGetCell(matPointer_, index_); 00195 } 00196 }; 00197 00198 ConstCellArray(const mxArray * matPointer = 0) 00199 : matPointer_(const_cast<mxArray *>(matPointer)), 00200 size_(0) 00201 { 00202 if(matPointer != 0 && !mxIsCell(matPointer)) 00203 mexErrMsgTxt("CellArray(mxArray *): Argument must be a Matlab cell array."); 00204 if(matPointer != 0) 00205 size_ = static_cast<int>(mxGetNumberOfElements(matPointer)); 00206 else 00207 size_ = -1; 00208 } 00209 00210 Proxy operator[](int i) const 00211 { 00212 if(!isValid(i)) 00213 mexErrMsgTxt("CellArray::operator[]: Index out of range."); 00214 return Proxy(matPointer_, i); 00215 } 00216 00217 int size() const 00218 { 00219 return size_; 00220 } 00221 00222 bool isValid( int i ) const 00223 { 00224 return i >= 0 && i < size_; 00225 } 00226 00227 }; 00228 00229 class CellArray 00230 : public ConstCellArray 00231 { 00232 public: 00233 00234 struct Proxy 00235 : public ConstCellArray::Proxy 00236 { 00237 Proxy(mxArray * matPointer, int index) 00238 : ConstCellArray::Proxy(matPointer, index) 00239 {} 00240 00241 void operator=(mxArray * v) 00242 { 00243 mxDestroyArray(mxGetCell(matPointer_, index_)); 00244 mxSetCell(matPointer_, index_, v); 00245 } 00246 }; 00247 00248 CellArray(const mxArray * matPointer) 00249 : ConstCellArray(matPointer) 00250 {} 00251 00252 Proxy operator[](int i) 00253 { 00254 if(!isValid(i)) 00255 mexErrMsgTxt("CellArray::operator[]: Index out of range."); 00256 return Proxy(matPointer_, i); 00257 } 00258 00259 ConstCellArray::Proxy operator[](int i) const 00260 { 00261 if(!isValid(i)) 00262 mexErrMsgTxt("CellArray::operator[]: Index out of range."); 00263 return ConstCellArray::Proxy(matPointer_, i); 00264 } 00265 }; 00266 00267 00268 00269 00270 00271 template <class T, unsigned int SIZE> 00272 TinyVectorView<T, SIZE> 00273 getTinyVector(mxArray const * t) 00274 { 00275 if(!ValueType<T>::check(t)) 00276 { 00277 std::string msg = std::string("Input array must have type ") + 00278 ValueType<T>::typeName() + "."; 00279 mexErrMsgTxt(msg.c_str()); 00280 } 00281 if(SIZE != mxGetNumberOfElements(t)) 00282 { 00283 mexErrMsgTxt("getTinyVector(): Input array has wrong number of elements."); 00284 } 00285 00286 return TinyVectorView<T, SIZE>((T *)mxGetData(t)); 00287 } 00288 00289 template <unsigned int SIZE> 00290 typename MultiArrayShape<SIZE>::type 00291 getShape(mxArray const * t) 00292 { 00293 if(!ValueType<Int32>::check(t)) 00294 { 00295 std::string msg = std::string("Input array must have type 'int32'."); 00296 mexErrMsgTxt(msg.c_str()); 00297 } 00298 if(SIZE != mxGetNumberOfElements(t)) 00299 { 00300 mexErrMsgTxt("getShape(): Input array has wrong number of elements."); 00301 } 00302 TinyVectorView<Int32, SIZE> res((MultiArrayIndex *)mxGetData(t)); 00303 return typename MultiArrayShape<SIZE>::type(res); 00304 } 00305 00306 template <int DIM, class T> 00307 MultiArrayView<DIM, T> 00308 getMultiArray(mxArray const * t) 00309 { 00310 typedef typename MultiArrayView<DIM, T>::difference_type Shape; 00311 00312 if(!ValueType<T>::check(t)) 00313 { 00314 std::string msg = std::string("getMultiArray(): Input array must have type ") + 00315 ValueType<T>::typeName() + "."; 00316 mexErrMsgTxt(msg.c_str()); 00317 } 00318 00319 Shape shape; 00320 if(DIM > 1) 00321 { 00322 int mdim = mxGetNumberOfDimensions(t); 00323 if(DIM < mdim) 00324 { 00325 mexErrMsgTxt("getMultiArray(): Input array has too many dimensions."); 00326 } 00327 const mwSize * matlabShape = mxGetDimensions(t); 00328 for(int k=0; k<mdim; ++k) 00329 { 00330 shape[k] = static_cast<typename Shape::value_type>(matlabShape[k]); 00331 } 00332 for(int k=mdim; k<DIM; ++k) 00333 { 00334 shape[k] = 1; 00335 } 00336 } 00337 else 00338 { 00339 shape[0] = static_cast<typename Shape::value_type>(mxGetNumberOfElements(t)); 00340 } 00341 return MultiArrayView<DIM, T>(shape, (T *)mxGetData(t)); 00342 } 00343 00344 template <int DIM, class T> 00345 MultiArrayView<DIM, T> 00346 createMultiArray(typename MultiArrayShape<DIM>::type const & shape, mxArray * & t) 00347 { 00348 mwSize matlabShape[DIM]; 00349 for(int k=0; k<DIM; ++k) 00350 matlabShape[k] = static_cast<mwSize>(shape[k]); 00351 t = mxCreateNumericArray(DIM, matlabShape, ValueType<T>::classID, mxREAL); 00352 00353 return MultiArrayView<DIM, T>(shape, (T *)mxGetData(t)); 00354 } 00355 00356 template <int DIM, class T> 00357 MultiArrayView<DIM, T> 00358 createMultiArray(typename MultiArrayShape<DIM>::type const & shape, CellArray::Proxy t) 00359 { 00360 mwSize matlabShape[DIM]; 00361 for(int k=0; k<DIM; ++k) 00362 matlabShape[k] = static_cast<mwSize>(shape[k]); 00363 t = mxCreateNumericArray(DIM, matlabShape, ValueType<T>::classID, mxREAL); 00364 00365 return MultiArrayView<DIM, T>(shape, (T *)mxGetData(t)); 00366 } 00367 00368 template <class T> 00369 inline MultiArrayView<1, T> 00370 getArray(mxArray const * t) 00371 { 00372 return getMultiArray<1, T>(t); 00373 } 00374 00375 template <class T> 00376 inline MultiArrayView<1, T> 00377 createArray(MultiArrayIndex size, mxArray * & t) 00378 { 00379 return createMultiArray<1, T>(MultiArrayShape<1>::type(size), t); 00380 } 00381 00382 template <class T> 00383 inline MultiArrayView<1, T> 00384 createArray(MultiArrayIndex size, CellArray::Proxy t) 00385 { 00386 return createMultiArray<1, T>(MultiArrayShape<1>::type(size), t); 00387 } 00388 00389 template <class T> 00390 MultiArrayView<2, T> 00391 getMatrix(mxArray const * t) 00392 { 00393 typedef typename MultiArrayView<2, T>::difference_type Shape; 00394 00395 if(!ValueType<T>::check(t)) 00396 { 00397 std::string msg = std::string("getMatrix(): Input matrix must have type ") + 00398 ValueType<T>::typeName() + "."; 00399 mexErrMsgTxt(msg.c_str()); 00400 } 00401 00402 if(2 != mxGetNumberOfDimensions(t)) 00403 mexErrMsgTxt("getMatrix(): Input matrix must have 2 dimensions."); 00404 00405 const mwSize * matlabShape = mxGetDimensions(t); 00406 Shape shape(static_cast<MultiArrayIndex>(matlabShape[0]), 00407 static_cast<MultiArrayIndex>(matlabShape[1])); 00408 00409 return MultiArrayView<2, T>(shape, (T *)mxGetData(t)); 00410 } 00411 00412 template <class T> 00413 MultiArrayView<2, T> 00414 createMatrix(mwSize rowCount, mwSize columnCount, mxArray * & t) 00415 { 00416 typedef typename MultiArrayView<2, T>::difference_type Shape; 00417 00418 Shape shape(rowCount, columnCount); 00419 t = mxCreateNumericMatrix(rowCount, columnCount, ValueType<T>::classID, mxREAL); 00420 00421 return MultiArrayView<2, T>(shape, (T *)mxGetData(t)); 00422 } 00423 00424 template <class T> 00425 MultiArrayView<2, T> 00426 createMatrix(mwSize rowCount, mwSize columnCount, CellArray::Proxy t) 00427 { 00428 typedef typename MultiArrayView<2, T>::difference_type Shape; 00429 00430 Shape shape(rowCount, columnCount); 00431 t = mxCreateNumericMatrix(rowCount, columnCount, ValueType<T>::classID, mxREAL); 00432 00433 return MultiArrayView<2, T>(shape, (T *)mxGetData(t)); 00434 } 00435 00436 template <class T> 00437 BasicImageView<T> 00438 getImage(mxArray const * t) 00439 { 00440 if(!ValueType<T>::check(t)) 00441 { 00442 std::string msg = std::string("getImage(): Input matrix must have type ") + 00443 ValueType<T>::typeName() + "."; 00444 mexErrMsgTxt(msg.c_str()); 00445 } 00446 00447 if(2 != mxGetNumberOfDimensions(t)) 00448 mexErrMsgTxt("getImage(): Input matrix must have 2 dimensions."); 00449 00450 const mwSize * matlabShape = mxGetDimensions(t); 00451 return BasicImageView<T>((T *)mxGetData(t), static_cast<int>(matlabShape[0]), 00452 static_cast<int>(matlabShape[1])); 00453 } 00454 00455 template <class T> 00456 BasicImageView<T> 00457 createImage(mwSize width, mwSize height, mxArray * & t) 00458 { 00459 t = mxCreateNumericMatrix(width, height, ValueType<T>::classID, mxREAL); 00460 00461 return BasicImageView<T>((T *)mxGetData(t), width, height); 00462 } 00463 00464 template <class T> 00465 BasicImageView<T> 00466 createImage(mwSize width, mwSize height, CellArray::Proxy t) 00467 { 00468 t = mxCreateNumericMatrix(width, height, ValueType<T>::classID, mxREAL); 00469 00470 return BasicImageView<T>((T *)mxGetData(t), width, height); 00471 } 00472 00473 inline ConstCellArray 00474 getCellArray(mxArray const * t) 00475 { 00476 return ConstCellArray(t); 00477 } 00478 00479 inline CellArray 00480 createCellArray(mwSize size, mxArray * & t) 00481 { 00482 mwSize matSize[] = { size }; 00483 t = mxCreateCellArray(1, matSize); 00484 00485 return CellArray(t); 00486 } 00487 00488 inline CellArray 00489 createCellArray(mwSize size, CellArray::Proxy t) 00490 { 00491 mwSize matSize[] = { size }; 00492 t = mxCreateCellArray(1, matSize); 00493 00494 return CellArray(t); 00495 } 00496 00497 inline ConstStructArray 00498 getStructArray(mxArray const * t) 00499 { 00500 return ConstStructArray(t); 00501 } 00502 00503 template<class T> 00504 T 00505 getScalar(mxArray const * t) 00506 { 00507 if(mxIsEmpty(t)) 00508 mexErrMsgTxt("getScalar() on empty input."); 00509 if(!mxIsNumeric(t) && !mxIsLogical(t)) 00510 mexErrMsgTxt("getScalar(): argument is not numeric."); 00511 return static_cast<T>(mxGetScalar(t)); 00512 } 00513 00514 template<class T> 00515 mxArray * 00516 createScalar(T v) 00517 { 00518 mxArray * m; 00519 createMatrix<double>(1, 1, m)(0,0) = static_cast<double>(v); 00520 return m; 00521 } 00522 00523 inline std::string 00524 getString(mxArray const * t) 00525 { 00526 if(mxIsEmpty(t)) 00527 mexErrMsgTxt("getString() on empty input."); 00528 if(!mxIsChar(t)) 00529 mexErrMsgTxt("getString(): argument is not a string."); 00530 int size = static_cast<int>(mxGetNumberOfElements(t) + 1); 00531 ArrayVector<char> buf(size); 00532 mxGetString(t, buf.begin(), size); 00533 return std::string(buf.begin()); 00534 } 00535 00536 00537 00538 class CompileTimeError; 00539 00540 namespace detail { 00541 00542 class Required 00543 { 00544 public: 00545 void argumentWasProvided() const { /* empty because required arguments are always provided */ } 00546 }; 00547 00548 00549 template<class T> 00550 class DefaultImpl 00551 { 00552 public: 00553 00554 T defaultValue_; 00555 mutable bool * argumentWasProvided_; 00556 00557 DefaultImpl(T v, bool * argFlag = 0) 00558 : defaultValue_(v), 00559 argumentWasProvided_(argFlag) 00560 { 00561 if(argumentWasProvided_ != 0) 00562 *argumentWasProvided_ = false; 00563 } 00564 00565 void argumentWasProvided() const 00566 { 00567 if(argumentWasProvided_ != 0) 00568 *argumentWasProvided_ = true; 00569 } 00570 }; 00571 00572 class OptionalImpl 00573 { 00574 public: 00575 mutable bool * argumentWasProvided_; 00576 00577 OptionalImpl(bool * argFlag = 0) 00578 : argumentWasProvided_(argFlag) 00579 { 00580 if(argumentWasProvided_ != 0) 00581 *argumentWasProvided_ = false; 00582 } 00583 00584 void argumentWasProvided() const 00585 { 00586 if(argumentWasProvided_ != 0) 00587 *argumentWasProvided_ = true; 00588 } 00589 }; 00590 00591 } // namespace detail 00592 00593 inline detail::Required v_required() 00594 { 00595 return detail::Required(); 00596 } 00597 00598 template<class T> 00599 inline detail::DefaultImpl<T> v_default(T in) 00600 { 00601 return detail::DefaultImpl<T>(in); 00602 } 00603 00604 template<class T> 00605 inline detail::DefaultImpl<T> v_default(T in, bool & argFlag) 00606 { 00607 return detail::DefaultImpl<T>(in, &argFlag); 00608 } 00609 00610 inline detail::OptionalImpl v_optional() 00611 { 00612 return detail::OptionalImpl(); 00613 } 00614 00615 inline detail::OptionalImpl v_optional(bool& argFlag) 00616 { 00617 return detail::OptionalImpl(&argFlag); 00618 } 00619 00620 // TODO: 00621 // * handle rgb images 00622 // * handle complex matrices 00623 // * handle sparse matrices 00624 00625 class InputArray 00626 { 00627 int size_; 00628 const mxArray ** data_; 00629 00630 std::string createErrMsg(std::string name) 00631 { 00632 std::string s1; 00633 s1 = "Required input '" + name + "' not found in option struct!"; 00634 return s1; 00635 } 00636 std::string createErrMsg(int pos) 00637 { 00638 char tmp[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; 00639 std::string oi(1, tmp[pos%10]); 00640 std::string s1 = "Required input in signature of function at position: '"+ oi+"' has not been supplied"; 00641 return s1; 00642 } 00643 00644 00645 public: 00646 ConstStructArray options_; 00647 00648 /* Local Typedefs */ 00649 typedef const mxArray * value_type; 00650 typedef value_type & reference; 00651 typedef value_type const & const_reference; 00652 typedef value_type * pointer; 00653 typedef value_type const * const_pointer; 00654 typedef int size_type; 00655 typedef int difference_type; 00656 00657 /*Constructor*/ 00658 InputArray(size_type size, pointer data) 00659 : size_(size), 00660 data_(data), 00661 options_(isValid(size-1) && mxIsStruct(data_[size-1]) 00662 ? data_[size-1] 00663 : 0) 00664 {} 00665 00666 /*Operators*/ 00667 const_reference operator[]( difference_type i ) const 00668 { 00669 if(!isValid(i)) 00670 mexErrMsgTxt("Too few input arguments."); 00671 return data_[i]; 00672 } 00673 00674 value_type operator[]( std::string name) const 00675 { 00676 std::string errMsg = "Not Found " + name +" in OptionStruct or OptionStruct not set"; 00677 if(!isValid(name)) 00678 mexErrMsgTxt(errMsg.c_str()); 00679 return options_[name]; 00680 } 00681 00682 00683 /*Some More Helper Func*/ 00684 size_type size() const 00685 { 00686 return size_; 00687 } 00688 00689 bool isValid( difference_type i ) const 00690 { 00691 return i >= 0 && i < size_; 00692 } 00693 00694 bool isValid(std::string name) const 00695 { 00696 return options_.isValid(name); 00697 } 00698 00699 bool isEmpty(difference_type i) const 00700 { 00701 return mxIsEmpty(data_[i]); 00702 } 00703 00704 bool isEmpty(std::string name) const 00705 { 00706 return mxIsEmpty(options_[name]); 00707 } 00708 00709 bool hasData(difference_type i) const 00710 { 00711 return isValid(i) && !isEmpty(i); 00712 } 00713 00714 bool hasData(std::string name) const 00715 { 00716 return isValid(name) && !isEmpty(name); 00717 } 00718 00719 template<class Place> 00720 mxClassID typeOf(Place posOrName) 00721 { 00722 return mxGetClassID((*this)[posOrName]); 00723 } 00724 00725 /*Action to take if value not set*/ 00726 template <class T, class U, class Place> 00727 T errorOrDefault(detail::DefaultImpl<U> const & o, Place posOrName) 00728 { 00729 return o.defaultValue_; 00730 } 00731 00732 template <class T, class Place> 00733 T errorOrDefault(detail::OptionalImpl, Place posOrName) 00734 { 00735 return T(); 00736 } 00737 00738 template <class T, class Place> 00739 T errorOrDefault(detail::Required r, Place posOrName) 00740 { 00741 std::string a = createErrMsg(posOrName); 00742 mexErrMsgTxt( a.c_str()); 00743 return T(); 00744 } 00745 00746 /*getter Func*/ 00747 template <class Place, class ReqType> 00748 int getEnum(Place posOrName, ReqType req, std::map<std::string, int> const & converter) 00749 { 00750 if(!hasData(posOrName)) 00751 { 00752 return errorOrDefault<int>(req, posOrName); 00753 } 00754 std::string enumAsString = matlab::getString((*this)[posOrName]); 00755 typename std::map<std::string, int>::const_iterator m = converter.find(enumAsString); 00756 if(m == converter.end()) 00757 { 00758 std::string msg = std::string("Unknown option: ") + enumAsString + "."; 00759 mexErrMsgTxt(msg.c_str()); 00760 } 00761 00762 req.argumentWasProvided(); 00763 return (*m).second; 00764 } 00765 00766 00767 /*String Type*/ 00768 template <class Place, class ReqType> 00769 std::string getString(Place posOrName, ReqType req) 00770 { 00771 if(!hasData(posOrName)) 00772 { 00773 return errorOrDefault<std::string>(req, posOrName); 00774 } 00775 else 00776 { 00777 req.argumentWasProvided(); 00778 return matlab::getString((*this)[posOrName]); 00779 } 00780 } 00781 00782 /*Scalar Type*/ 00783 template <class T,class Place, class ReqType> 00784 T getScalar(Place posOrName, ReqType req) 00785 { 00786 if(!hasData(posOrName)) 00787 { 00788 return errorOrDefault<T>(req, posOrName); 00789 } 00790 else 00791 { 00792 req.argumentWasProvided(); 00793 return matlab::getScalar<T>((*this)[posOrName]); 00794 } 00795 } 00796 00797 00798 template <class T, class Place, class ReqType, class minClass, class maxClass> 00799 T getScalarMinMax(Place posOrName, ReqType req, minClass min_, maxClass max_) 00800 { 00801 T temp = this->getScalar<T>(posOrName, req); 00802 if (!is_in_range(temp, min_, max_)) 00803 mexErrMsgTxt("Value out of bounds."); 00804 return temp; 00805 } 00806 00807 template <class T, class Place, class ReqType, class iteratorType> 00808 T getScalarVals(Place posOrName, ReqType req, iteratorType begin_, iteratorType end_) 00809 { 00810 T temp = this->getScalar<T>(posOrName, req); 00811 for(iteratorType iter = begin_; iter != end_; ++iter) 00812 { 00813 if((*iter) == temp) return temp; 00814 } 00815 mexErrMsgTxt("Value not allowed"); 00816 } 00817 00818 00819 00820 template <class T, class Place, class ReqType, class iteratorType> 00821 T getScalarVals2D3D(Place posOrName, ReqType req, iteratorType begin2D_, iteratorType end2D_, 00822 iteratorType begin3D_, iteratorType end3D_, 00823 int dimVar) 00824 { 00825 T temp = this->getScalar<T>(posOrName, req); 00826 switch(dimVar) 00827 { 00828 case 2: 00829 for(iteratorType iter = begin2D_; iter != end2D_; ++iter) 00830 { 00831 if((*iter) == temp) return temp; 00832 } 00833 break; 00834 case 3: 00835 for(iteratorType iter = begin3D_; iter != end3D_; ++iter) 00836 { 00837 if((*iter) == temp) return temp; 00838 } 00839 break; 00840 default: 00841 mexErrMsgTxt("dimVar specified must be 2 or 3"); 00842 } 00843 mexErrMsgTxt("Value not allowed"); 00844 } 00845 00846 template <class Place, class ReqType> 00847 bool getBool(Place posOrName, ReqType req) 00848 { 00849 return this->getScalarMinMax<int>(posOrName, req, 0, 1) != 0; 00850 } 00851 00852 /*Array Type*/ 00853 template <unsigned int N, class T, class Place, class ReqType> 00854 MultiArrayView<N,T> getMultiArray(Place posOrName, ReqType req) 00855 { 00856 if(!hasData(posOrName)) 00857 { 00858 return errorOrDefault< MultiArrayView<N,T> >(req, posOrName); 00859 } 00860 else 00861 { 00862 req.argumentWasProvided(); 00863 value_type temp = (*this)[posOrName]; 00864 return matlab::getMultiArray<N,T>(temp); 00865 } 00866 } 00867 00868 template < class T, class Place, class ReqType> 00869 BasicImageView<T> getImage(Place posOrName, ReqType req) 00870 { 00871 if(!hasData(posOrName)) 00872 { 00873 return errorOrDefault<BasicImageView<T> >(req, posOrName); 00874 } 00875 else 00876 { 00877 req.argumentWasProvided(); 00878 value_type temp = (*this)[posOrName]; 00879 return matlab::getImage<T>(temp); 00880 } 00881 } 00882 00883 template<class T,unsigned int sze, class Place, class ReqType> 00884 TinyVectorView< T, sze> getTinyVector(Place posOrName, ReqType req) 00885 { 00886 if(!hasData(posOrName)) 00887 { 00888 return errorOrDefault<TinyVectorView< T, sze> >(req, posOrName); 00889 } 00890 else 00891 { 00892 req.argumentWasProvided(); 00893 value_type temp = (*this)[posOrName]; 00894 return matlab::getTinyVector< T, sze>(temp); 00895 } 00896 } 00897 00898 template< unsigned int sze, class Place, class ReqType> 00899 TinyVectorView<MultiArrayIndex, sze> getShape(Place posOrName, ReqType req) 00900 { 00901 if(!hasData(posOrName)) 00902 { 00903 return errorOrDefault<TinyVectorView<MultiArrayIndex, sze> >(req, posOrName); 00904 } 00905 else 00906 { 00907 req.argumentWasProvided(); 00908 value_type temp = (*this)[posOrName]; 00909 return matlab::getShape<sze>(temp); 00910 } 00911 } 00912 00913 00914 template< class Place, class ReqType> 00915 int getDimOfInput(Place posOrName, ReqType req) 00916 { 00917 if(!hasData(posOrName)) 00918 { 00919 return errorOrDefault<int>(req, posOrName); 00920 } 00921 else 00922 { 00923 req.argumentWasProvided(); 00924 return mxGetNumberOfDimensions((*this)[posOrName]); 00925 } 00926 } 00927 00928 template<class ReqType> 00929 ConstCellArray getCellArray(int posOrName, ReqType req) 00930 { 00931 if(!hasData(posOrName)) 00932 { 00933 return errorOrDefault<ConstCellArray>(req, posOrName); 00934 } 00935 else 00936 { 00937 req.argumentWasProvided(); 00938 value_type temp = (*this)[posOrName]; 00939 return matlab::getCellArray(temp); 00940 } 00941 } 00942 00943 template<class ReqType> 00944 ConstCellArray getCellArray(std::string posOrName, ReqType req) 00945 { 00946 CompileTimeError ERROR__Const_Cell_Array_May_Not_Be_In_Option_Struct; 00947 return ConstCellArray(); //avoid compiler warning 00948 } 00949 00950 }; 00951 00952 class OutputArray 00953 { 00954 int size_; 00955 mxArray ** data_; 00956 std::string createErrMsgOut(int pos) 00957 { 00958 char tmp[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; 00959 std::string oi(1, tmp[pos%10]); 00960 std::string s1 = "Required Output at position: '" + oi + "' has not been supplied"; 00961 return s1; 00962 } 00963 public: 00964 00965 typedef mxArray * value_type; 00966 typedef value_type & reference; 00967 typedef value_type const & const_reference; 00968 typedef value_type * pointer; 00969 typedef value_type const * const_pointer; 00970 typedef int size_type; 00971 typedef int difference_type; 00972 00973 OutputArray(size_type size, pointer data) 00974 : size_(size), 00975 data_(data) 00976 {} 00977 00978 reference operator[]( difference_type i ) 00979 { 00980 if(!isValid(i)) 00981 mexErrMsgTxt("Too few output arguments."); 00982 return data_[i]; 00983 } 00984 00985 const_reference operator[]( difference_type i ) const 00986 { 00987 if(!isValid(i)) 00988 mexErrMsgTxt("Too few output arguments."); 00989 return data_[i]; 00990 } 00991 00992 size_type size() const 00993 { 00994 return size_; 00995 } 00996 00997 bool isValid( difference_type i ) const 00998 { 00999 return i >= 0 && i < size_; 01000 } 01001 01002 bool isEmpty(difference_type i){ 01003 return mxIsEmpty(data_[i]); 01004 } 01005 01006 template <class T> 01007 T errorOrDefault(detail::OptionalImpl const & o, int Pos) 01008 { 01009 return T(); 01010 } 01011 01012 template <class T> 01013 T errorOrDefault(detail::Required r, int Pos) 01014 { 01015 mexErrMsgTxt(createErrMsgOut(Pos).c_str()); 01016 return T(); 01017 } 01018 01019 /* creating func */ 01020 template <unsigned int DIM, class T, class ReqType> 01021 MultiArrayView<DIM, T> createMultiArray(int pos,ReqType req, 01022 const TinyVector<int, DIM> & shape) 01023 { 01024 if(!isValid(pos)) 01025 return errorOrDefault<MultiArrayView<DIM, T> >(req, pos); 01026 req.argumentWasProvided(); 01027 return matlab::createMultiArray<DIM, T>(shape, (*this)[pos]); 01028 } 01029 01030 template <class T, class ReqType> 01031 BasicImageView<T> createImage(int pos, ReqType req, 01032 mwSize width, mwSize height) 01033 { 01034 if(!isValid(pos)) 01035 return errorOrDefault<BasicImageView<T> >(req, pos); 01036 req.argumentWasProvided(); 01037 return matlab::createImage<T>(width, height, (*this)[pos]); 01038 } 01039 01040 template <class T, class ReqType> 01041 BasicImageView<T> createImage( int pos, ReqType req, 01042 typename MultiArrayShape<2>::type const & shape) 01043 { 01044 return createImage<T>(pos, req, shape[1], shape[0]); 01045 } 01046 01047 template <class T, class ReqType> 01048 T* createScalar(int pos, ReqType req) 01049 { 01050 if(!isValid(pos)) 01051 return errorOrDefault<T*>(req, pos); 01052 req.argumentWasProvided(); 01053 BasicImageView<T> temp = matlab::createImage<T>(1, 1, (*this)[pos]); 01054 return &temp(0,0); 01055 } 01056 01057 template <class T, class ReqType> 01058 void createScalar(int pos, ReqType req, T val) 01059 { 01060 if(!isValid(pos)) 01061 { 01062 errorOrDefault<T>(req, pos); 01063 return; 01064 } 01065 req.argumentWasProvided(); 01066 BasicImageView<T> temp = matlab::createImage<T>(1, 1, (*this)[pos]); 01067 temp(0,0) = val; 01068 } 01069 01070 template <class ReqType> 01071 ConstCellArray createCellArray(int pos, ReqType req, mwSize sze) 01072 { 01073 if(!isValid(pos)) 01074 return errorOrDefault<ConstCellArray>(req, pos); 01075 return matlab::createCellArray(sze, (*this)[pos]); 01076 } 01077 }; 01078 01079 01080 01081 /*********************************** 01082 Rahuls code starts here 01083 ************************************/ 01084 using namespace vigra; 01085 01086 01087 /*++++++++++++++++++++++++++HELPERFUNC+++++++++++++++++++++++++++++++* 01088 * This is used for better readability of the test cases . 01089 * Nothing to be done here. 01090 *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 01091 int cantorPair(int x, int y){ 01092 return (int)(((x+y)*(x+y+1))/2+y); 01093 } 01094 01095 int cantorPair(int x, int y, int z){ 01096 return cantorPair(cantorPair(x,y),z); 01097 } 01098 01099 template <int x, int y> 01100 struct cP{ 01101 enum { value = (int)(((x+y)*(x+y+1))/2+y)}; 01102 }; 01103 01104 template <int x, int y, int z> 01105 struct cP3{ 01106 enum { value = cP<cP<x, y>::value, z>::value}; 01107 }; 01108 01109 template <class T> 01110 inline bool is_in_range(T in, T min, T max) 01111 { 01112 return (in >= min && in <= max); 01113 } 01114 template<class T> 01115 inline bool is_in_range(T in, std::string min, T max) 01116 { 01117 return(in <= max); 01118 } 01119 01120 template<class T> 01121 inline bool is_in_range(T in, T min, std::string max) 01122 { 01123 return (in >= min); 01124 } 01125 01126 01127 01128 //Wrapper classes to STL-Map for use as a sparse array. 01129 01130 //This is used for the ordering of the map. Lexicographical ordering of the index pairs. 01131 struct ShapeCmp { 01132 bool operator()( TinyVector<int,2> s1, TinyVector<int,2> s2 ) const { 01133 if(s1[0] != s2[0]){ 01134 return (s1[0] < s2[0]); 01135 } else { 01136 return s1[1] < s2[1]; 01137 } 01138 } 01139 }; 01140 01141 template<class T> 01142 class SparseArray 01143 { 01144 01145 std::map<TinyVector<int,2>, T,ShapeCmp> data; 01146 int width, length; 01147 01148 public: 01149 void assign(int i = 1, int j = 1){ 01150 width = j; 01151 length = i; 01152 } 01153 SparseArray(int i = 1 , int j = 1){ 01154 width = j; 01155 length = i; 01156 } 01157 01158 //Any better idea? i would like to unify the get and operator() functions. 01159 // Problem is that operator() always passes a reference or creates one. 01160 template<class indexType> 01161 T& operator()(indexType i_, indexType j_){ 01162 Int32 i = static_cast<Int32>(i_); 01163 Int32 j = static_cast<Int32>(j_); 01164 TinyVector<int,2> newShapew(i, j); 01165 typename std::map<TinyVector<int,2>, T, ShapeCmp>::iterator iter; 01166 TinyVector<int,2> newShape; 01167 return data[newShapew]; 01168 } 01169 01170 template<class indexType> 01171 const T get(indexType i_, indexType j_){ 01172 Int32 i = static_cast<Int32>(i_); 01173 Int32 j = static_cast<Int32>(j_); 01174 TinyVector<int,2> newShape(i, j); 01175 if(data.find(newShape) == data.end()) return 0; 01176 else return data.find(newShape)->second; 01177 } 01178 01179 //see documentation of mxCreateSparse and the mxGet functions to understand this. 01180 void mapToMxArray(mxArray * & in){ 01181 01182 int len = data.size(); 01183 in = mxCreateSparse(width, length, len, mxREAL); 01184 int* jc = mxGetJc(in); 01185 int* ir = mxGetIr(in); 01186 double* pr = mxGetPr(in); 01187 if(len == 0){ 01188 jc[0] = 1; 01189 return; 01190 } 01191 typename std::map<TinyVector<int,2>, T, ShapeCmp>::iterator iter; 01192 TinyVector<int,2> newShape; 01193 int ii = 0; 01194 int jj = 0; 01195 int curjc = -1; 01196 for( iter = data.begin(); iter != data.end(); ++iter ) { 01197 newShape = iter->first; 01198 ir[ii] = newShape[1]; 01199 pr[ii] = iter->second; 01200 if(newShape[0] != curjc){ 01201 curjc = newShape[0] ; 01202 jc[jj] = ii; 01203 jj++; 01204 } 01205 01206 ii++; 01207 } 01208 jc[jj] = len; 01209 } 01210 01211 }; 01212 01213 enum DataDimension {IMAGE = 2, VOLUME = 3}; 01214 01215 } // namespace matlab 01216 01217 } // namespace vigra 01218 01219 void vigraMexFunction(vigra::matlab::OutputArray, vigra::matlab::InputArray); 01220 01221 #ifndef VIGRA_CUSTOM_MEXFUNCTION 01222 01223 /* 01224 DO NOT Comment out this function. If you are using a 01225 custom mexfunction just #define VIGRA_CUSTOM_MEXFUNCTION 01226 before #including matlab.hxx. 01227 */ 01228 void mexFunction(int nlhs, mxArray *plhs[], 01229 int nrhs, const mxArray *prhs[]) 01230 { 01231 try 01232 { 01233 vigra::matlab::InputArray inputs(nrhs, prhs); 01234 vigra::matlab::OutputArray outputs(nlhs, plhs); 01235 01236 vigraMexFunction(outputs, inputs); 01237 } 01238 catch(std::exception & e) 01239 { 01240 mexErrMsgTxt(e.what()); 01241 } 01242 } 01243 01244 #endif /*CUSTOM_MEXFUNCTION*/ 01245 01246 01247 #define VIGRA_CREATE_ENUM_AND_STD_MAP2(mapName, item1, item2) \ 01248 const int item1 = 1;\ 01249 const int item2 = 2;\ 01250 std::map<std::string,int> mapName;\ 01251 mapName[#item1] = (int)item1;\ 01252 mapName[#item2] = (int)item2;\ 01253 01254 01255 #define VIGRA_CREATE_ENUM_AND_STD_MAP3(mapName, item1, item2, item3) \ 01256 const int item1 = 1;\ 01257 const int item2 = 2;\ 01258 const int item3 = 3;\ 01259 std::map<std::string,int> mapName;\ 01260 mapName[#item1] = (int)item1;\ 01261 mapName[#item2] = (int)item2;\ 01262 mapName[#item3] = (int)item3;\ 01263 01264 01265 #define VIGRA_CREATE_ENUM_AND_STD_MAP4(mapName, item1, item2, item3, item4) \ 01266 const int item1 = 1;\ 01267 const int item2 = 2;\ 01268 const int item3 = 3;\ 01269 const int item4 = 4;\ 01270 std::map<std::string,int> mapName;\ 01271 mapName[#item1] = (int)item1;\ 01272 mapName[#item2] = (int)item2;\ 01273 mapName[#item3] = (int)item3;\ 01274 mapName[#item4] = (int)item4;\ 01275 01276 #define VIGRA_CREATE_ENUM_AND_STD_MAP5(mapName, item1, item2, item3, item4, item5) \ 01277 const int item1 = 1;\ 01278 const int item2 = 2;\ 01279 const int item3 = 3;\ 01280 const int item4 = 4;\ 01281 const int item5 = 5;\ 01282 std::map<std::string, int> mapName;\ 01283 mapName[#item1] = (int)item1;\ 01284 mapName[#item2] = (int)item2;\ 01285 mapName[#item3] = (int)item3;\ 01286 mapName[#item4] = (int)item4;\ 01287 mapName[#item5] = (int)item5;\ 01288 01289 #define VIGRA_CREATE_ENUM_AND_STD_MAP6(mapName, item1, item2, item3, item4, item5, item6) \ 01290 const int item1 = 1;\ 01291 const int item2 = 2;\ 01292 const int item3 = 3;\ 01293 const int item4 = 4;\ 01294 const int item5 = 5;\ 01295 const int item6 = 6;\ 01296 std::map<std::string,int> mapName;\ 01297 mapName[#item1] = (int)item1;\ 01298 mapName[#item2] = (int)item2;\ 01299 mapName[#item3] = (int)item3;\ 01300 mapName[#item4] = (int)item4;\ 01301 mapName[#item5] = (int)item5;\ 01302 mapName[#item6] = (int)item6;\ 01303 01304 #endif // VIGRA_MATLAB_HXX
© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de) |
html generated using doxygen and Python
|