[ 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 /*    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 <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 <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 <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         return temp;
00800     }
00801 
00802     template <class T, class Place, class ReqType, class iteratorType>
00803     T getScalarVals(Place posOrName, ReqType req, iteratorType begin_, iteratorType end_)
00804     {
00805         T temp = this->getScalar<T>(posOrName, req);
00806         for(iteratorType iter = begin_; iter != end_; ++iter)
00807         {
00808             if((*iter) == temp) return temp;
00809         }
00810         mexErrMsgTxt("Value not allowed");
00811     }
00812 
00813 
00814 
00815     template <class T, class Place, class ReqType, class iteratorType>
00816     T getScalarVals2D3D(Place posOrName, ReqType req, iteratorType begin2D_, iteratorType end2D_,
00817                                                      iteratorType begin3D_, iteratorType end3D_,
00818                                                      int dimVar)
00819     {
00820         T temp = this->getScalar<T>(posOrName, req);
00821         switch(dimVar)
00822         {
00823             case 2:
00824                 for(iteratorType iter = begin2D_; iter != end2D_; ++iter)
00825                 {
00826                     if((*iter) == temp) return temp;
00827                 }
00828                 break;
00829             case 3:
00830                 for(iteratorType iter = begin3D_; iter != end3D_; ++iter)
00831                 {
00832                     if((*iter) == temp) return temp;
00833                 }
00834                 break;
00835             default:
00836                 mexErrMsgTxt("dimVar specified must be 2 or 3");
00837         }
00838         mexErrMsgTxt("Value not allowed");
00839     }
00840 
00841     template <class Place, class ReqType>
00842     bool getBool(Place posOrName, ReqType req)
00843     {
00844         return this->getScalarMinMax<int>(posOrName, req, 0, 1) != 0;
00845     }
00846 
00847     /*Array Type*/
00848     template <unsigned int N, class T, class Place, class ReqType>
00849     MultiArrayView<N,T> getMultiArray(Place posOrName, ReqType req)
00850     {
00851         if(!hasData(posOrName))
00852         {
00853             return errorOrDefault< MultiArrayView<N,T> >(req, posOrName);
00854         }
00855         else
00856         {
00857             req.argumentWasProvided();
00858             value_type temp = (*this)[posOrName];
00859             return matlab::getMultiArray<N,T>(temp);
00860         }
00861     }
00862 
00863     template < class T, class Place, class ReqType>
00864     BasicImageView<T> getImage(Place posOrName, ReqType req)
00865     {
00866         if(!hasData(posOrName))
00867         {
00868             return errorOrDefault<BasicImageView<T> >(req, posOrName);
00869         }
00870         else
00871         {
00872             req.argumentWasProvided();
00873             value_type temp = (*this)[posOrName];
00874             return matlab::getImage<T>(temp);
00875         }
00876     }
00877 
00878     template<class T,unsigned int sze, class Place, class ReqType>
00879     TinyVectorView< T, sze> getTinyVector(Place posOrName, ReqType req)
00880     {
00881         if(!hasData(posOrName))
00882         {
00883             return errorOrDefault<TinyVectorView< T, sze> >(req, posOrName);
00884         }
00885         else
00886         {
00887             req.argumentWasProvided();
00888             value_type temp = (*this)[posOrName];
00889             return matlab::getTinyVector< T, sze>(temp);
00890         }
00891     }
00892 
00893     template< unsigned int sze, class Place, class ReqType>
00894     TinyVectorView<MultiArrayIndex, sze> getShape(Place posOrName, ReqType req)
00895     {
00896         if(!hasData(posOrName))
00897         {
00898             return errorOrDefault<TinyVectorView<MultiArrayIndex, sze> >(req, posOrName);
00899         }
00900         else
00901         {
00902             req.argumentWasProvided();
00903             value_type temp = (*this)[posOrName];
00904             return matlab::getShape<sze>(temp);
00905         }
00906     }
00907 
00908 
00909     template< class Place, class ReqType>
00910     int getDimOfInput(Place posOrName, ReqType req)
00911     {
00912         if(!hasData(posOrName))
00913         {
00914             return errorOrDefault<int>(req, posOrName);
00915         }
00916         else
00917         {
00918             req.argumentWasProvided();
00919             return mxGetNumberOfDimensions((*this)[posOrName]);
00920         }
00921     }
00922 
00923     template<class ReqType>
00924     ConstCellArray getCellArray(int posOrName, ReqType req)
00925     {
00926         if(!hasData(posOrName))
00927         {
00928             return errorOrDefault<ConstCellArray>(req, posOrName);
00929         }
00930         else
00931         {
00932             req.argumentWasProvided();
00933             value_type temp = (*this)[posOrName];
00934             return matlab::getCellArray(temp);
00935         }
00936     }
00937 
00938     template<class ReqType>
00939     ConstCellArray getCellArray(std::string posOrName, ReqType req)
00940     {
00941         CompileTimeError ERROR__Const_Cell_Array_May_Not_Be_In_Option_Struct;
00942         return ConstCellArray(); //avoid compiler warningg
00943     }
00944 
00945 };
00946 
00947 class OutputArray
00948 {
00949     int size_;
00950     mxArray ** data_;
00951     std::string createErrMsgOut(int pos)
00952     {
00953         char tmp[10] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
00954         std::string oi(1, tmp[pos%10]);
00955         std::string s1 =  "Required Output at position: '" + oi + "' has not been supplied";
00956         return s1;
00957     }
00958   public:
00959 
00960     typedef mxArray * value_type;
00961     typedef value_type & reference;
00962     typedef value_type const & const_reference;
00963     typedef value_type * pointer;
00964     typedef value_type const * const_pointer;
00965     typedef int size_type;
00966     typedef int difference_type;
00967 
00968     OutputArray(size_type size, pointer data)
00969     : size_(size),
00970       data_(data)
00971     {}
00972 
00973     reference operator[]( difference_type i )
00974     {
00975         if(!isValid(i))
00976             mexErrMsgTxt("Too few output arguments.");
00977         return data_[i];
00978     }
00979 
00980     const_reference operator[]( difference_type i ) const
00981     {
00982         if(!isValid(i))
00983             mexErrMsgTxt("Too few output arguments.");
00984         return data_[i];
00985     }
00986 
00987     size_type size() const
00988     {
00989         return size_;
00990     }
00991 
00992     bool isValid( difference_type i ) const
00993     {
00994         return i >= 0 && i < size_;
00995     }
00996 
00997     bool isEmpty(difference_type i){
00998         return mxIsEmpty(data_[i]);
00999     }
01000 
01001     template <class T>
01002     T errorOrDefault(detail::OptionalImpl const & o, int Pos)
01003     {
01004         return T();
01005     }
01006 
01007     template <class T>
01008     T errorOrDefault(detail::Required r, int Pos)
01009     {
01010         mexErrMsgTxt(createErrMsgOut(Pos).c_str());
01011         return T();
01012     }
01013 
01014     /* creating func */
01015     template <unsigned int DIM, class T, class ReqType>
01016     MultiArrayView<DIM, T> createMultiArray(int pos,ReqType req,
01017                                             const TinyVector<int, DIM>  & shape)
01018     {
01019         if(!isValid(pos))
01020             return errorOrDefault<MultiArrayView<DIM, T> >(req, pos);
01021         req.argumentWasProvided();
01022         return matlab::createMultiArray<DIM, T>(shape, (*this)[pos]);
01023     }
01024 
01025     template <class T, class ReqType>
01026     BasicImageView<T> createImage(int pos, ReqType req,
01027                                     mwSize width, mwSize height)
01028     {
01029         if(!isValid(pos))
01030             return errorOrDefault<BasicImageView<T> >(req, pos);
01031         req.argumentWasProvided();
01032         return matlab::createImage<T>(width, height, (*this)[pos]);
01033     }
01034 
01035     template <class T, class ReqType>
01036     BasicImageView<T> createImage(  int pos, ReqType req,
01037                                     typename MultiArrayShape<2>::type const & shape)
01038     {
01039         return createImage<T>(pos, req, shape[1], shape[0]);
01040     }
01041 
01042     template <class T, class ReqType>
01043     T* createScalar(int pos, ReqType req)
01044     {
01045         if(!isValid(pos))
01046             return errorOrDefault<T*>(req, pos);
01047         req.argumentWasProvided();
01048         BasicImageView<T> temp = matlab::createImage<T>(1, 1, (*this)[pos]);
01049         return &temp(0,0);
01050     }
01051 
01052     template <class T, class ReqType>
01053     void createScalar(int pos, ReqType req, T val)
01054     {
01055         if(!isValid(pos))
01056         {
01057             errorOrDefault<T>(req, pos);
01058             return;
01059         }
01060         req.argumentWasProvided();
01061         BasicImageView<T> temp = matlab::createImage<T>(1, 1, (*this)[pos]);
01062         temp(0,0) = val;
01063     }
01064 
01065     template <class ReqType>
01066     ConstCellArray createCellArray(int pos, ReqType req, mwSize sze)
01067     {
01068         if(!isValid(pos))
01069             return errorOrDefault<ConstCellArray>(req, pos);
01070         return matlab::createCellArray(sze, (*this)[pos]);
01071     }
01072 };
01073 
01074 
01075 
01076 /***********************************
01077 Rahuls code starts here
01078 ************************************/
01079 using namespace vigra;
01080 
01081 
01082 /*++++++++++++++++++++++++++HELPERFUNC+++++++++++++++++++++++++++++++*
01083  * This is used for better readibility of the test cases            .
01084  * Nothing to be done here.
01085  *+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
01086 int cantorPair(int x, int y){
01087         return (int)(((x+y)*(x+y+1))/2+y);
01088 }
01089 
01090 int cantorPair(int x, int y, int z){
01091         return cantorPair(cantorPair(x,y),z);
01092 }
01093 
01094 template <int x, int y>
01095 struct cP{
01096     enum { value = (int)(((x+y)*(x+y+1))/2+y)};
01097 };
01098 
01099 template <int x, int y, int z>
01100 struct cP3{
01101     enum { value = cP<cP<x, y>::value, z>::value};
01102 };
01103 
01104 template <class T>
01105 inline bool is_in_range(T in, T min, T max)
01106 {
01107     return (in >= min && in <= max);
01108 }
01109 template<class T>
01110 inline bool is_in_range(T in, std::string min, T max)
01111 {
01112     return(in <= max);
01113 }
01114 
01115 template<class T>
01116 inline bool is_in_range(T in, T min, std::string max)
01117 {
01118     return (in >= min);
01119 }
01120 
01121 
01122 
01123 //Wrapper classes to STL-Map for use as a sparse array.
01124 
01125 //This is used for the ordering of the map. Lexicographical ordering of the index pairs.
01126 struct ShapeCmp {
01127   bool operator()( TinyVector<int,2> s1, TinyVector<int,2>  s2 ) const {
01128     if(s1[0] != s2[0]){
01129         return (s1[0] < s2[0]);
01130     } else {
01131         return s1[1] < s2[1];
01132     }
01133   }
01134 };
01135 
01136 template<class T>
01137 class SparseArray
01138 {
01139 
01140     std::map<TinyVector<int,2>, T,ShapeCmp> data;
01141     int width, length;
01142 
01143     public:
01144     void assign(int i = 1, int j = 1){
01145         width = j;
01146         length = i;
01147     }
01148     SparseArray(int i = 1 , int j = 1){
01149         width = j;
01150         length = i;
01151     }
01152 
01153     //Any better idea? i would like to unify the get and operator() functions.
01154     // Problem is that  operator() always passes a reference or creates one.
01155     template<class indexType>
01156     T& operator()(indexType i_, indexType j_){
01157         Int32 i = static_cast<Int32>(i_);
01158         Int32 j = static_cast<Int32>(j_);
01159         TinyVector<int,2> newShapew(i, j);
01160         typename std::map<TinyVector<int,2>, T, ShapeCmp>::iterator iter;
01161         TinyVector<int,2> newShape;
01162         return data[newShapew];
01163     }
01164 
01165     template<class indexType>
01166     const T get(indexType i_, indexType j_){
01167         Int32 i = static_cast<Int32>(i_);
01168         Int32 j = static_cast<Int32>(j_);
01169         TinyVector<int,2> newShape(i, j);
01170         if(data.find(newShape) == data.end()) return 0;
01171         else return data.find(newShape)->second;
01172     }
01173 
01174     //see dokumentation of mxCreateSparse and the mxGet functions to understand this.
01175     void mapToMxArray(mxArray * & in){
01176 
01177         int len = data.size();
01178         in = mxCreateSparse(width, length, len, mxREAL);
01179         int* jc = mxGetJc(in);
01180         int* ir = mxGetIr(in);
01181         double* pr = mxGetPr(in);
01182         if(len == 0){
01183             jc[0] = 1;
01184             return;
01185         }
01186         typename std::map<TinyVector<int,2>, T, ShapeCmp>::iterator iter;
01187         TinyVector<int,2> newShape;
01188         int ii = 0;
01189         int jj = 0;
01190         int curjc = -1;
01191         for( iter = data.begin(); iter != data.end(); ++iter ) {
01192             newShape = iter->first;
01193             ir[ii] = newShape[1];
01194             pr[ii] = iter->second;
01195             if(newShape[0]  != curjc){
01196                 curjc = newShape[0] ;
01197                 jc[jj] = ii;
01198                 jj++;
01199             }
01200 
01201             ii++;
01202         }
01203         jc[jj] = len;
01204     }
01205 
01206 };
01207 
01208 enum DataDimension {IMAGE = 2, VOLUME = 3};
01209 
01210 } // namespace matlab
01211 
01212 } // namespace vigra
01213 
01214 void vigraMexFunction(vigra::matlab::OutputArray, vigra::matlab::InputArray);
01215 
01216 #ifndef VIGRA_CUSTOM_MEXFUNCTION
01217 
01218 /*
01219     DO NOT Comment out this function. If you are using a
01220     custom mexfunction just #define VIGRA_CUSTOM_MEXFUNCTION
01221     before #including matlab.hxx.
01222 */
01223 void mexFunction(int nlhs, mxArray *plhs[],
01224                  int nrhs, const mxArray *prhs[])
01225 {
01226   try
01227   {
01228     vigra::matlab::InputArray inputs(nrhs, prhs);
01229     vigra::matlab::OutputArray outputs(nlhs, plhs);
01230 
01231     vigraMexFunction(outputs, inputs);
01232   }
01233   catch(std::exception & e)
01234   {
01235     mexErrMsgTxt(e.what());
01236   }
01237 }
01238 
01239 #endif /*CUSTOM_MEXFUNCTION*/
01240 
01241 
01242 #define VIGRA_CREATE_ENUM_AND_STD_MAP2(mapName, item1, item2) \
01243     const int item1 = 1;\
01244     const int item2 = 2;\
01245     std::map<std::string,int>  mapName;\
01246     mapName[#item1] = (int)item1;\
01247     mapName[#item2] = (int)item2;\
01248 
01249 
01250 #define VIGRA_CREATE_ENUM_AND_STD_MAP3(mapName, item1, item2, item3) \
01251     const int item1 = 1;\
01252     const int item2 = 2;\
01253     const int item3 = 3;\
01254     std::map<std::string,int>  mapName;\
01255     mapName[#item1] = (int)item1;\
01256     mapName[#item2] = (int)item2;\
01257     mapName[#item3] = (int)item3;\
01258 
01259 
01260 #define VIGRA_CREATE_ENUM_AND_STD_MAP4(mapName, item1, item2, item3, item4) \
01261     const int item1 = 1;\
01262     const int item2 = 2;\
01263     const int item3 = 3;\
01264     const int item4 = 4;\
01265     std::map<std::string,int>  mapName;\
01266     mapName[#item1] = (int)item1;\
01267     mapName[#item2] = (int)item2;\
01268     mapName[#item3] = (int)item3;\
01269     mapName[#item4] = (int)item4;\
01270 
01271 #define VIGRA_CREATE_ENUM_AND_STD_MAP5(mapName, item1, item2, item3, item4, item5) \
01272     const int item1 = 1;\
01273     const int item2 = 2;\
01274     const int item3 = 3;\
01275     const int item4 = 4;\
01276     const int item5 = 5;\
01277     std::map<std::string, int>  mapName;\
01278     mapName[#item1] = (int)item1;\
01279     mapName[#item2] = (int)item2;\
01280     mapName[#item3] = (int)item3;\
01281     mapName[#item4] = (int)item4;\
01282     mapName[#item5] = (int)item5;\
01283 
01284 #define VIGRA_CREATE_ENUM_AND_STD_MAP6(mapName, item1, item2, item3, item4, item5, item6) \
01285     const int item1 = 1;\
01286     const int item2 = 2;\
01287     const int item3 = 3;\
01288     const int item4 = 4;\
01289     const int item5 = 5;\
01290     const int item6 = 6;\
01291     std::map<std::string,int>  mapName;\
01292     mapName[#item1] = (int)item1;\
01293     mapName[#item2] = (int)item2;\
01294     mapName[#item3] = (int)item3;\
01295     mapName[#item4] = (int)item4;\
01296     mapName[#item5] = (int)item5;\
01297     mapName[#item6] = (int)item6;\
01298 
01299 #endif // VIGRA_MATLAB_HXX

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.7.1 (Sun Feb 19 2012)