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