mexutils.h
Go to the documentation of this file.
00001 
00006 /*
00007 Copyright (C) 2007-12 Andrea Vedaldi and Brian Fulkerson.
00008 All rights reserved.
00009 
00010 This file is part of the VLFeat library and is made available under
00011 the terms of the BSD license (see the COPYING file).
00012 */
00013 
00014 #ifndef MEXUTILS_H
00015 #define MEXUTILS_H
00016 
00017 #include"mex.h"
00018 #include<vl/generic.h>
00019 #include<vl/array.h>
00020 #include<vl/stringop.h>
00021 #include<ctype.h>
00022 #include<string.h>
00023 #include<stdio.h>
00024 #include<stdarg.h>
00025 
00026 #ifdef VL_COMPILER_MSC
00027 #define snprintf _snprintf
00028 #define vsnprintf _vsnprintf
00029 #endif
00030 
00031 #if (! defined(MX_API_VER) || (MX_API_VER < 0x07030000)) && \
00032   (! defined(HAVE_OCTAVE))
00033 typedef vl_uint32 mwSize ;
00034 typedef vl_int32 mwIndex ;
00035 #endif
00036 
00038 #undef IN
00039 #define IN(x) (in[IN_ ## x])
00040 
00042 #undef OUT
00043 #define OUT(x) (out[OUT_ ## x])
00044 
00045 #ifdef HAVE_OCTAVE
00046 static void *
00047 mxReallocOctaveWorkaround(void * ptr, size_t size)
00048 {
00049   /*  mexPrintf("fixed realloc\n") ; */
00050   if (ptr) {
00051     return mxRealloc(ptr, size) ;
00052   } else {
00053     return mxMalloc(size) ;
00054   }
00055 }
00056 #define mxRealloc mxReallocOctaveWorkaround
00057 static int
00058 mxSetDimensionsOctaveWorkaround(mxArray * array, const mwSize  *dims, int ndims)
00059 {
00060   mwSize * dims_ = mxMalloc(sizeof(mwSize)*ndims) ;
00061   int i ;
00062   for (i = 0 ; i < ndims ; ++i) dims_[i] = dims[i] ;
00063   mxSetDimensions(array,dims_,ndims) ;
00064   return 0 ;
00065 }
00066 #define mxSetDimensions mxSetDimensionsOctaveWorkaround
00067 
00068 #endif
00069 
00076 #define VL_USE_MATLAB_ENV \
00077   vl_set_alloc_func (mxMalloc, mxRealloc, mxCalloc, mxFree) ; \
00078   vl_set_printf_func ((printf_func_t)mexPrintf) ;
00079 
00080 
00172 /* these attributes suppress undefined symbols warning with GCC */
00173 #ifdef VL_COMPILER_GNUC
00174 #if (! defined(HAVE_OCTAVE))
00175 EXTERN_C void __attribute__((noreturn))
00176 mexErrMsgIdAndTxt (const char * identifier, const char * err_msg, ...) ;
00177 #else
00178 extern void __attribute__((noreturn))
00179 mexErrMsgIdAndTxt (const char *id, const char *s, ...);
00180 #endif
00181 #endif
00182 
00183 #define MEXUTILS_RAISE_HELPER_A \
00184   char const * errorString ; \
00185   char formattedErrorId [512] ; \
00186   char formattedErrorMessage [1024] ; \
00187   \
00188   switch (errorId) { \
00189     case vlmxErrAlloc : errorString = "outOfMemory" ; break ; \
00190     case vlmxErrInvalidArgument : errorString = "invalidArgument" ; break ; \
00191     case vlmxErrNotEnoughInputArguments : errorString = "notEnoughInputArguments" ; break ; \
00192     case vlmxErrTooManyInputArguments : errorString = "tooManyInputArguments" ; break ; \
00193     case vlmxErrNotEnoughOutputArguments : errorString = "notEnoughOutputArguments" ; break ; \
00194     case vlmxErrTooManyOutputArguments : errorString = "tooManyOutputArguments" ; break ; \
00195     case vlmxErrInvalidOption : errorString = "invalidOption" ; break ; \
00196     case vlmxErrInconsistentData : errorString = "inconsistentData" ; break ; \
00197     default : errorString = "undefinedError" ; break ; \
00198   } \
00199   \
00200   if (! errorMessage) { \
00201     switch (errorId) { \
00202       case vlmxErrAlloc: errorMessage = "Out of memory." ; break ; \
00203       case vlmxErrInvalidArgument: errorMessage = "Invalid argument." ; break ; \
00204       case vlmxErrNotEnoughInputArguments: errorMessage = "Not enough input arguments." ; break ; \
00205       case vlmxErrTooManyInputArguments: errorMessage = "Too many input arguments." ; break ; \
00206       case vlmxErrNotEnoughOutputArguments: errorMessage = "Not enough output arguments." ; break ; \
00207       case vlmxErrTooManyOutputArguments: errorMessage = "Too many output arguments." ; break ; \
00208       case vlmxErrInconsistentData: errorMessage = "Inconsistent data." ; break ; \
00209       case vlmxErrInvalidOption: errorMessage = "Invalid option." ; break ; \
00210       default: errorMessage = "Undefined error message." ; \
00211     } \
00212   }
00213 
00214 #ifdef VL_COMPILER_LCC
00215 #define MEXUTILS_RAISE_HELPER_B \
00216 { \
00217   va_list args ; \
00218   va_start(args, errorMessage) ; \
00219   sprintf(formattedErrorId, \
00220           "vl:%s", errorString) ; \
00221   vsprintf(formattedErrorMessage, \
00222            errorMessage, args) ; \
00223   va_end(args) ; \
00224 }
00225 #else
00226 #define MEXUTILS_RAISE_HELPER_B \
00227 { \
00228   va_list args ; \
00229   va_start(args, errorMessage) ; \
00230   snprintf(formattedErrorId, \
00231            sizeof(formattedErrorId)/sizeof(char), \
00232            "vl:%s", errorString) ; \
00233   vsnprintf(formattedErrorMessage, \
00234             sizeof(formattedErrorMessage)/sizeof(char), \
00235             errorMessage, args) ; \
00236   va_end(args) ; \
00237 }
00238 #endif
00239 
00240 #define MEXUTILS_RAISE_HELPER MEXUTILS_RAISE_HELPER_A MEXUTILS_RAISE_HELPER_B
00241 
00247 typedef enum _VlmxErrorId {
00248   vlmxErrAlloc = 1,
00249   vlmxErrInvalidArgument,
00250   vlmxErrNotEnoughInputArguments,
00251   vlmxErrTooManyInputArguments,
00252   vlmxErrNotEnoughOutputArguments,
00253   vlmxErrTooManyOutputArguments,
00254   vlmxErrInvalidOption,
00255   vlmxErrInconsistentData
00256 } VlmxErrorId ;
00257 
00258 
00268 #if defined(VL_COMPILER_GNUC) & ! defined(__DOXYGEN__)
00269 static void __attribute__((noreturn))
00270 #else
00271 static void
00272 #endif
00273 vlmxError (VlmxErrorId errorId, char const * errorMessage, ...)
00274 {
00275   MEXUTILS_RAISE_HELPER ;
00276   mexErrMsgIdAndTxt (formattedErrorId, formattedErrorMessage) ;
00277 }
00278 
00287 static void
00288 vlmxWarning (VlmxErrorId errorId, char const * errorMessage, ...)
00289 {
00290   MEXUTILS_RAISE_HELPER ;
00291   mexWarnMsgIdAndTxt (formattedErrorId, formattedErrorMessage) ;
00292 }
00293 
00307 VL_INLINE vl_bool
00308 vlmxIsOfClass (mxArray const * array, mxClassID classId)
00309 {
00310   return mxGetClassID (array) == classId ;
00311 }
00312 
00320 VL_INLINE vl_bool
00321 vlmxIsReal (mxArray const * array)
00322 {
00323   return mxIsNumeric (array) && ! mxIsComplex (array) ;
00324 }
00325 
00338 VL_INLINE vl_bool
00339 vlmxIsScalar (mxArray const * array)
00340 {
00341   return (! mxIsSparse (array)) && (mxGetNumberOfElements (array) == 1)  ;
00342 }
00343 
00352 static vl_bool
00353 vlmxIsVector (mxArray const * array, vl_index numElements)
00354 {
00355   vl_size numDimensions = (unsigned) mxGetNumberOfDimensions (array) ;
00356   mwSize const * dimensions = mxGetDimensions (array) ;
00357   vl_uindex di ;
00358 
00359   /* check that it is not sparse */
00360   if (mxIsSparse (array)) {
00361     return VL_FALSE ;
00362   }
00363 
00364   /* check that the number of elements is the prescribed one */
00365   if ((numElements >= 0) && ((unsigned) mxGetNumberOfElements (array) !=
00366                              (unsigned) numElements)) {
00367     return VL_FALSE ;
00368   }
00369 
00370   /* check that all but at most one dimension is singleton */
00371   for (di = 0 ;  di < numDimensions ; ++ di) {
00372     if (dimensions[di] != 1) break ;
00373   }
00374   for (++ di ; di < numDimensions ; ++di) {
00375     if (dimensions[di] != 1) return VL_FALSE ;
00376   }
00377   return VL_TRUE ;
00378 }
00379 
00389 static vl_bool
00390 vlmxIsMatrix (mxArray const * array, vl_index M, vl_index N)
00391 {
00392   vl_size numDimensions = (unsigned) mxGetNumberOfDimensions (array) ;
00393   mwSize const * dimensions = mxGetDimensions (array) ;
00394   vl_uindex di ;
00395 
00396   /* check that it is not sparse */
00397   if (mxIsSparse (array)) {
00398     return VL_FALSE ;
00399   }
00400 
00401   /* check that the number of elements is the prescribed one */
00402   if ((M >= 0) && ((unsigned) mxGetM (array) != (unsigned) M)) {
00403     return VL_FALSE;
00404   }
00405   if ((N >= 0) && ((unsigned) mxGetN (array) != (unsigned) N)) {
00406     return VL_FALSE;
00407   }
00408 
00409   /* ok if empty and either M = 0 or N = 0 */
00410   if ((mxGetNumberOfElements (array) == 0) && (mxGetM (array) == 0 || mxGetN (array) == 0)) {
00411     return VL_TRUE ;
00412   }
00413 
00414   /* ok if any dimension beyond the first two is singleton */
00415   for (di = 2 ; ((unsigned)dimensions[di] == 1) && di < numDimensions ; ++ di) ;
00416   return di == numDimensions ;
00417 }
00418 
00419 
00433 static vl_bool
00434 vlmxIsArray (mxArray const * array, vl_index numDimensions, vl_index* dimensions)
00435 {
00436   if (numDimensions >= 0) {
00437     vl_index d ;
00438     mwSize const * actualDimensions = mxGetDimensions (array) ;
00439 
00440     if ((unsigned) mxGetNumberOfDimensions (array) != (unsigned) numDimensions) {
00441       return VL_FALSE ;
00442     }
00443 
00444     if(dimensions != NULL) {
00445       for(d = 0 ; d < numDimensions ; ++d) {
00446         if (dimensions[d] >= 0 && (unsigned) dimensions[d] != (unsigned) actualDimensions[d])
00447           return VL_FALSE ;
00448       }
00449     }
00450   }
00451   return VL_TRUE ;
00452 }
00453 
00466  VL_INLINE vl_bool
00467  vlmxIsPlain (mxArray const * array)
00468  {
00469  return
00470    vlmxIsReal (array) &&
00471    vlmxIsOfClass (array, mxDOUBLE_CLASS) ;
00472  }
00473 
00474 
00482 VL_INLINE vl_bool
00483 vlmxIsPlainScalar (mxArray const * array)
00484 {
00485   return vlmxIsPlain (array) && vlmxIsScalar (array) ;
00486 }
00487 
00496 VL_INLINE vl_bool
00497 vlmxIsPlainVector (mxArray const * array, vl_index numElements)
00498 {
00499   return vlmxIsPlain (array) && vlmxIsVector (array, numElements) ;
00500 }
00501 
00502 
00512 VL_INLINE vl_bool
00513 vlmxIsPlainMatrix (mxArray const * array, vl_index M, vl_index N)
00514 {
00515   return vlmxIsPlain (array) && vlmxIsMatrix (array, M, N) ;
00516 }
00517 
00530 static int
00531 vlmxIsString (const mxArray* array, vl_index length)
00532 {
00533   mwSize M = (mwSize) mxGetM (array) ;
00534   mwSize N = (mwSize) mxGetN (array) ;
00535 
00536   return
00537     mxIsChar(array) &&
00538     mxGetNumberOfDimensions(array) == 2 &&
00539     (M == 1 || (M == 0 && N == 0)) &&
00540     (length < 0 || (signed)N == length) ;
00541 }
00542 
00543 
00552 static mxArray *
00553 vlmxCreatePlainScalar (double x)
00554 {
00555   mxArray * array = mxCreateDoubleMatrix (1,1,mxREAL) ;
00556   *mxGetPr(array) = x ;
00557   return array ;
00558 }
00559 
00566 static mxArray *
00567 vlmxCreateArrayFromVlArray (VlArray const * x)
00568 {
00569   mwSize dimensions [VL_ARRAY_MAX_NUM_DIMENSIONS] ;
00570   mxArray * array = NULL ;
00571   mxClassID classId = (mxClassID)0 ;
00572   vl_uindex d ;
00573   vl_size numElements = vl_array_get_num_elements(x) ;
00574   vl_size numDimensions  = vl_array_get_num_dimensions(x) ;
00575   vl_size const * xdimensions = vl_array_get_dimensions(x) ;
00576   vl_type type = vl_array_get_data_type(x) ;
00577   vl_size typeSize = vl_get_type_size(type) ;
00578 
00579   for (d = 0 ; d < numDimensions ; ++d) {
00580     dimensions[d] = (mwSize) xdimensions[d] ;
00581   }
00582 
00583   switch (type) {
00584     case VL_TYPE_FLOAT   : classId = mxSINGLE_CLASS ; break ;
00585     case VL_TYPE_DOUBLE  : classId = mxDOUBLE_CLASS ; break ;
00586     case VL_TYPE_INT8    : classId = mxINT8_CLASS ; break ;
00587     case VL_TYPE_INT16   : classId = mxINT16_CLASS ; break ;
00588     case VL_TYPE_INT32   : classId = mxINT32_CLASS ; break ;
00589     case VL_TYPE_INT64   : classId = mxINT64_CLASS ; break ;
00590     case VL_TYPE_UINT8   : classId = mxUINT8_CLASS ; break ;
00591     case VL_TYPE_UINT16  : classId = mxUINT16_CLASS ; break ;
00592     case VL_TYPE_UINT32  : classId = mxUINT32_CLASS ; break ;
00593     case VL_TYPE_UINT64  : classId = mxUINT64_CLASS ; break ;
00594     default: assert(VL_FALSE) ;
00595   }
00596 
00597   array = mxCreateNumericArray(numDimensions,
00598                                dimensions,
00599                                classId,
00600                                mxREAL) ;
00601 
00602   if (array == NULL) return NULL ;
00603 
00604   memcpy(mxGetData(array), vl_array_get_data(x), typeSize * numElements) ;
00605 
00606   return array ;
00607 }
00608 
00616 static VlArray *
00617 vlmxEnvelopeArrayInVlArray (VlArray * v, mxArray * x)
00618 {
00619   vl_size numDimensions = mxGetNumberOfDimensions(x) ;
00620   mwSize const * dimensions = mxGetDimensions(x) ;
00621   mxClassID classId = mxGetClassID(x) ;
00622   vl_size vdimensions [VL_ARRAY_MAX_NUM_DIMENSIONS] ;
00623   vl_type type ;
00624   vl_uindex d ;
00625 
00626   for (d = 0 ; d < numDimensions ; ++d) {
00627     vdimensions[d] = dimensions[d] ;
00628   }
00629 
00630   switch (classId) {
00631     case mxSINGLE_CLASS: type =  VL_TYPE_FLOAT  ; break ;
00632     case mxDOUBLE_CLASS: type =  VL_TYPE_DOUBLE ; break ;
00633     case mxINT8_CLASS  : type =  VL_TYPE_INT8   ; break ;
00634     case mxINT16_CLASS : type =  VL_TYPE_INT16  ; break ;
00635     case mxINT32_CLASS : type =  VL_TYPE_INT32  ; break ;
00636     case mxINT64_CLASS : type =  VL_TYPE_INT64  ; break ;
00637     case mxUINT8_CLASS : type =  VL_TYPE_UINT8  ; break ;
00638     case mxUINT16_CLASS: type =  VL_TYPE_UINT16 ; break ;
00639     case mxUINT32_CLASS: type =  VL_TYPE_UINT32 ; break ;
00640     case mxUINT64_CLASS: type =  VL_TYPE_UINT64 ; break ;
00641     default: assert(VL_FALSE) ; abort() ;
00642   }
00643 
00644   vl_array_init_envelope(v, mxGetData(x), type, numDimensions, vdimensions) ;
00645   return v ;
00646 }
00647 
00659 static int
00660 vlmxCompareStringsI(const char *s1, const char *s2)
00661 {
00662   /*
00663    Since tolower has an int argument, characters must be unsigned
00664    otherwise will be sign-extended when converted to int.
00665    */
00666   while (tolower((unsigned char)*s1) == tolower((unsigned char)*s2))
00667   {
00668     if (*s1 == 0) return 0 ; /* implies *s2 == 0 */
00669     s1++;
00670     s2++;
00671   }
00672   return tolower((unsigned char)*s1) - tolower((unsigned char)*s2) ;
00673 }
00674 
00686 static int
00687 vlmxCompareToStringI(mxArray const * array, char const  * string)
00688 {
00689   mxChar const * s1 = (mxChar const *) mxGetData(array) ;
00690   char unsigned const * s2 = (char unsigned const*) string ;
00691   vl_size n = mxGetNumberOfElements(array) ;
00692 
00693   /*
00694    Since tolower has an int argument, characters must be unsigned
00695    otherwise will be sign-extended when converted to int.
00696    */
00697   while (n && tolower((unsigned)*s1) == tolower(*s2)) {
00698     if (*s2 == 0) return 1 ; /* s2 terminated on 0, but s1 did not terminate yet */
00699     s1 ++ ;
00700     s2 ++ ;
00701     n -- ;
00702   }
00703   return tolower(n ? (unsigned)*s1 : 0) - tolower(*s2) ;
00704 }
00705 
00713 static int
00714 vlmxIsEqualToStringI(mxArray const * array, char const  * string)
00715 {
00716   return vlmxCompareToStringI(array, string) == 0 ;
00717 }
00718 
00719 /* ---------------------------------------------------------------- */
00720 /*                        Options handling                          */
00721 /* ---------------------------------------------------------------- */
00722 
00725 struct _vlmxOption
00726 {
00727   const char *name ; 
00728   int has_arg ;      
00729   int val ;          
00730 } ;
00731 
00734 typedef struct _vlmxOption vlmxOption  ;
00735 
00764 static int
00765 vlmxNextOption (mxArray const *args[], int nargs,
00766                 vlmxOption  const *options,
00767                 int *next,
00768                 mxArray const **optarg)
00769 {
00770   char name [1024] ;
00771   int opt = -1, i;
00772 
00773   if (*next >= nargs) {
00774     return opt ;
00775   }
00776 
00777   /* check the array is a string */
00778   if (! vlmxIsString (args [*next], -1)) {
00779     vlmxError (vlmxErrInvalidOption,
00780                "The option name is not a string (argument number %d)",
00781                *next + 1) ;
00782   }
00783 
00784   /* retrieve option name */
00785   if (mxGetString (args [*next], name, sizeof(name))) {
00786     vlmxError (vlmxErrInvalidOption,
00787                "The option name is too long (argument number %d)",
00788                *next + 1) ;
00789   }
00790 
00791   /* advance argument list */
00792   ++ (*next) ;
00793 
00794   /* now lookup the string in the option table */
00795   for (i = 0 ; options[i].name != 0 ; ++i) {
00796     if (vlmxCompareStringsI(name, options[i].name) == 0) {
00797       opt = options[i].val ;
00798       break ;
00799     }
00800   }
00801 
00802   /* unknown argument */
00803   if (opt < 0) {
00804     vlmxError (vlmxErrInvalidOption, "Unknown option '%s'.", name) ;
00805   }
00806 
00807   /* no argument */
00808   if (! options [i].has_arg) {
00809     if (optarg) *optarg = 0 ;
00810     return opt ;
00811   }
00812 
00813   /* argument */
00814   if (*next >= nargs) {
00815     vlmxError(vlmxErrInvalidOption,
00816               "Option '%s' requires an argument.", options[i].name) ;
00817   }
00818 
00819   if (optarg) *optarg = args [*next] ;
00820   ++ (*next) ;
00821   return opt ;
00822 }
00823 
00831 static VlEnumerator *
00832 vlmxDecodeEnumeration (mxArray const *name_array,
00833                        VlEnumerator const *enumeration,
00834                        vl_bool caseInsensitive)
00835 {
00836   char name [1024] ;
00837 
00838   /* check the array is a string */
00839   if (! vlmxIsString (name_array, -1)) {
00840     vlmxError (vlmxErrInvalidArgument, "The array is not a string.") ;
00841   }
00842 
00843   /* retrieve option name */
00844   if (mxGetString (name_array, name, sizeof(name))) {
00845     vlmxError (vlmxErrInvalidArgument, "The string array is too long.") ;
00846   }
00847 
00848   if (caseInsensitive) {
00849     return vl_enumeration_get_casei(enumeration, name) ;
00850   } else {
00851     return vl_enumeration_get(enumeration, name) ;
00852   }
00853 }
00854 
00855 /* MEXUTILS_H */
00856 #endif


libvlfeat
Author(s): Andrea Vedaldi
autogenerated on Thu Jun 6 2019 20:25:51