[ 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 <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)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.7.0 (Thu Aug 25 2011)