Mercurial > forge
changeset 2398:53ef0a775385 octave-forge
Remove mex code as it is ported to octave 2.9.7
author | adb014 |
---|---|
date | Wed, 23 Aug 2006 21:40:27 +0000 |
parents | 671181dd32f5 |
children | 2e15483a2818 |
files | extra/mex/.cvsignore extra/mex/INSTALL extra/mex/Makefile extra/mex/README extra/mex/TODO extra/mex/configure.add extra/mex/matrix.h extra/mex/mex.1 extra/mex/mex.cc extra/mex/mex.h extra/mex/mex.in extra/mex/myfeval.c extra/mex/myfeval.m extra/mex/myfevalf.f extra/mex/myset.c extra/mex/mystruct.c |
diffstat | 16 files changed, 0 insertions(+), 2115 deletions(-) [+] |
line wrap: on
line diff
--- a/extra/mex/.cvsignore Wed Aug 23 19:38:44 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -mex
--- a/extra/mex/INSTALL Wed Aug 23 19:38:44 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -To use mex, first compile the mex.cc support library. - -a.) If you are using the octaveSF package, then you won't - need to do anything---it was compiled and installed when you - compiled and installed octaveSF. - -b.) If you are using mex with octave 2.0.x, edit the Makefile and - replace 'mkoctfile' with 'mkoctfile -DHAVE_OCTAVE_20'. - -c.) Type make to build mex.so and mex - -d.) To test mex in place, use e.g., - ./mex mystruct.c - LD_LIBRARY_PATH=`pwd` octave - > mystruct(struct('s',{1,2},'t',3)) - -d.) Move mex to your executable path (e.g., ~/bin) and mex.1 to your - man path and you are done
--- a/extra/mex/Makefile Wed Aug 23 19:38:44 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -sinclude ../../Makeconf - -ifndef OCTAVE_FORGE - MKOCTFILE = mkoctfile - OPATH = $(shell pwd) - bindir = /usr/local/bin - mandir = /usr/local/man - INSTALL = /usr/bin/install -c - INSTALL_PROGRAM = $(INSTALL) - INSTALL_DATA = $(INSTALL) -m 644 - LEAVEHERE=1 -endif - -man1dir = $(mandir)/man1 - -.PHONY: install - -LIBPATH=$(OPATH) -MEXLIB=mex.o - -all: $(MEXLIB) mex - -$(MEXLIB): mex.cc mex.h matrix.h - $(MKOCTFILE) -c $(HAVE_OCTAVE_MAP_INDEX) -o $(MEXLIB) mex.cc - -mex: mex.in - cat mex.in | sed -e "s:@MKOCTFILE@:$(MKOCTFILE):;s:@LIBPATH@:$(LIBPATH):g;s:@MEXLIB@:$(MEXLIB):g" \ - -e 's;@AWK@;${AWK};g' > mex - chmod a+x mex - -install: -ifdef LEAVEHERE - @echo "Leaving $(MEXLIB), mex.h and matrix.h in place --- do not remove!" -else - @if ! test -e $(DESTDIR)$(LIBPATH) ; then \ - echo creating $(DESTDIR)$(LIBPATH) ; \ - $(INSTALL) -d $(DESTDIR)$(LIBPATH) ; \ - fi - @if test -d $(DESTDIR)$(LIBPATH) ; then \ - echo installing $(MEXLIB) mex/mex.h mex/matrix.h in $(DESTDIR)$(LIBPATH) ; \ - $(INSTALL_DATA) $(MEXLIB) $(DESTDIR)$(LIBPATH)/$(MEXLIB) ; \ - $(INSTALL_DATA) mex.h $(DESTDIR)$(LIBPATH)/mex.h ; \ - $(INSTALL_DATA) matrix.h $(DESTDIR)$(LIBPATH)/matrix.h ; \ - fi -endif - @if ! test -e $(DESTDIR)$(man1dir) ; then \ - echo creating $(DESTDIR)$(man1dir) ; \ - $(INSTALL) -d $(DESTDIR)$(man1dir) ; \ - fi - @if test -d $(DESTDIR)$(man1dir) ; then \ - echo installing mex/mex.1 in $(DESTDIR)$(man1dir) ; \ - $(RM) $(DESTDIR)$(man1dir)/mex.1; \ - $(INSTALL_DATA) mex.1 $(DESTDIR)$(man1dir)/mex.1 ; \ - fi - @if ! test -e $(DESTDIR)$(bindir) ; then \ - echo creating $(DESTDIR)$(bindir) ; \ - $(INSTALL) -d $(DESTDIR)$(bindir) ; \ - fi - @if test -d $(DESTDIR)$(bindir) ; then \ - echo installing mex/mex in $(DESTDIR)$(bindir) ; \ - $(RM) $(DESTDIR)$(bindir)/mex ; \ - $(INSTALL_SCRIPT) mex $(DESTDIR)$(bindir)/mex ; \ - fi - -clean: ; $(RM) mex mex_* $(MEXLIB) *.o *.oct core octave-core *~
--- a/extra/mex/README Wed Aug 23 19:38:44 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,354 +0,0 @@ - -This is a partial implementation of the Matlab MEX interface for use -in Octave. It is only intended to support existing MEX functions, not -write new ones. That's because every piece of data passed to and -returned from mexFunction and mexCallMATLAB must be copied (but see -TODO). - -See INSTALL for instructions on how to build the mex support library. - -Then for each mex-file blah.f or blah.c that you have, do - mex name.c othersrc.c otherobj.o -L/other/lib/path -lotherlib -Put name.oct somewhere on your Octave LOADPATH and you are done. - -The shell script mex creates an octave DLD file mex_name.cc which -handles the interface between Octave and the symbol mexFunction. - -If you would normally use -V4 as one of your mex options, use -DV4 -instead. This will select the Matlab version 4 interface rather than -the Matlab version 5 interface. - -There are two test programs: - myfeval is a poor implementation of feval which exercises - the mexCallMATLAB function - myset tests mexGetArray and mexPutArray; call it with a - variable name and a value, and it will show the current - value for the variable in the caller and the global space, - and set the new value in the caller space. - -NOTE: for ELF systems running older versions of octave (2.1.57 and earlier), -you will need to include the -Wl,-Bsymbolic on the link line for the mex -file explicitly, otherwise only one mex file can be loaded at a time. -Check the output of - - mkoctfile -p DL_LDFLAGS - -If it is empty, use: - - SH_LDFLAGS="`mkoctfile -p SH_LDFLAGS` -Wl,-Bsymbolic" mex ... - -If it does not contain -Wl,-Bsymbolic, use: - - DL_LDFLAGS="`mkoctfile -p DL_LDFLAGS` -Wl,-Bsymbolic" mex ... - -This is Bourne shell syntax. If using something else, adjust appropriately. - - -The following functions are implemented: - -Types -* mxComplexity (enumerated type: mxREAL, mxCOMPLEX) -* mxArray - -User supplied information -* mexFunctionName -* mexFunction - -Interpreter services -* mexCallMATLAB -* mexEvalString -* mexSetTrapFlag -* mexErrMsgTxt -* mexWarnMsgTxt -* mexPrintf - -Memory management -* mxMalloc -* mxCalloc -* mxRealloc -* mxFree -* mexMakeMemoryPersistent - -Array creation/destruction -* mxCreateDoubleMatrix -* mxCreateFull -* mxDestroyArray -* mxFreeMatrix -* mexMakeArrayPersistent - -Array type -* mxIsFull -* mxIsEmpty -* mxIsNumeric -* mxIsComplex -* mxIsSparse - -Array data -* mxGetM -* mxGetN -* mxGetPi -* mxGetPr -* mxSetM -* mxSetN -* mxSetPi -* mxSetPr -* mxGetScalar -* mxGetNumberOfDimensions - -IEEE floating point support -* mxGetEps -* mxGetInf -* mxGetNaN -* mxIsFinite -* mxIsInf -* mxIsNaN -* mexGetEps -* mexGetInf -* mexGetNaN -* mexIsFinite -* mexIsInf -* mexIsNaN - -String support -* mxIsChar -* mxIsString -* mxCreateString -* mxGetString -* mxArrayToString -* mxCreateCharMatrixFromStrings - - -Symbol table manipulation -x mexPutArray -* mexGetArray -* mexGetArrayPtr -* mexPutMatrix -* mexGetMatrix -* mexGetMatrixPtr -* mexGetGlobal -* mxGetName -* mxSetName - -Struct support -* mxIsStruct -? mxCreateStructMatrix -* mxGetNumberOfFields -* mxGetField -* mxGetFieldByNumber -* mxGetFieldNameByNumber -* mxGetFieldNumber -? mxSetField -? mxSetFieldByNumber - - -The following functions are not implemented: - -Types -x mxClassID -x mxChar - -Interpreter services -x mexAddFlops -x mexAtExit -x mexUnlock -x mexIsLocked -x mexLock - -Debugging -x mxAssert -x mxAssertS - -Plot controls -x mexGet -x mexSet - -Data manipulation -x mxSetAllocFcns -x mxDuplicateArray -x mxIsFromGlobalWS -x mexIsGlobal -x mexPutFull -x mexGetFull - -Generic data handling -x mxGetClassID -x mxGetNumberOfElements -x mxGetElementSize -x mxGetData -x mxSetData -x mxGetImagData -x mxSetImagData - -Precision support -x mxCreateNumericMatrix -x mxIsSingle -x mxIsDouble -x mxIsInt8 -x mxIsInt16 -x mxIsInt32 -x mxIsUint8 -x mxIsUint16 -x mxIsUint32 - -Boolean support -x mxIsLogical -x mxSetLogical -x mxClearLogical - -n-D arrays -x mxCreateNumericArray -x mxCreateCharArray -x mxCreateStructArray -x mxCreateCellArray -x mxCalcSingleSubscript -x mxSetDimensions -x mxGetDimensions - -Cell array support -x mxIsCell -x mxCreateCellMatrix -x mxSetCell -x mxGetCell - -Sparse support -x mxCreateSparse -x mxGetNzmax -x mxSetNzmax -x mxGetIr -x mxGetJc -x mxSetIr -x mxSetJc - -Object support -x mxIsClass -x mxGetClassName -x mxSetClassName - -MAT file interface -x matClose -x matDeleteArray -x matGetArray -x matGetArrayHeader -x matGetDir -x matGetFp -x matGetNextArray -x matGetNextArrayHeader -x matOpen -x matPutArray -x matPutArrayAsGlobal - -MAT file interface (V4 functions) -x matDeleteMatrix -x matGetFull -x matGetMatrix -x matGetNextMatrix -x matGetString -x matPutFull -x matPutMatrix -x matPutString - -DDE Interface -x ddeadv -x ddeexec -x ddeinit -x ddepoke -x ddereq -x determ -x ddeunadv - -The following compute engine routines are implemented by Jesse Bennet in -liboct-0.1 <http://www.octave.org/octave/mailing-lists/help-octave/1999/549> - -* engClose -* engEvalString -* engOpen -* engOutputBuffer -* engGetFull -* engPutFull - -The following compute engine routines are missing - -x engOpenSingleUse -x engGetArray -x engPutArray -x engGetMatrix -x engPutMatrix -x engSetEvalCallback -x engSetEvalTimeout -x engWinInit - -The following FORTRAN routines are implemented - -* mexFunction -* mexPrintf -* mexErrMsgTxt -* mexCallMATLAB - -* mexGetEps -* mexGetInf -* mexGetNaN -* mexIsFinite -* mexIsInf -* mexIsNaN - -* mxMalloc -* mxCalloc -* mxFree - -* mxCreateFull -* mxFreeMatrix - -* mxGetM -* mxGetN -* mxGetPr -* mxGetPi - -* mxSetM -* mxSetN -* mxSetPr -* mxSetPi - -* mxIsComplex -* mxIsDouble -* mxIsNumeric -* mxIsFull -* mxIsSparse - -* mxGetString -* mxIsString - -* mxCopyComplex16ToPtr -* mxCopyPtrToComplex16 -* mxCopyReal8ToPtr -* mxCopyPtrToReal8 - -The following fortran routines are not implemented - -x mexSetTrapFlag -x mexEvalString - -x mexGetGlobal -x mexGetFull -x mexPutFull -x mexGetMatrix -x mexPutMatrix -x mexGetMatrixPtr - -x mxCopyPtrToCharacter -x mxCopyCharacterToPtr -x mxCopyPtrToInteger4 -x mxCopyInteger4ToPtr - -x mxCreateSparse -x mxCreateString -x mxFreeMatrix -x mxGetName - -x mxGetNzmax -x mxGetIr -x mxGetJc -x mxSetNzmax -x mxSetIr -x mxSetJc - -x mxGetScalar
--- a/extra/mex/TODO Wed Aug 23 19:38:44 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,84 +0,0 @@ - -* mex.oct is a shared library. We should rename it libmex.so and link to -it instead of including a separate copy of mex.o in each oct file. Only -thing is, how do we install it beside version of liboctave we are using, -and how do we make the loader find the correct version if we have multiple -versions of octave installed. - -* More complete testing -* Better error handling in mex -* Use tempory files for Octave glue? -* mex should translate -V4 to -DV4 -* mex should remove mex_*.cc when done -* clean up warnings in myset.c - -* If you want to support Octave and Matlab with the same code base -without penalizing either, you will need to write a high level layer -which supports both. - -Particularly, you must prohibit direct modification of the fields of -the mxArray type, which means eliminating mxSet{Pi,Pr,N,M} from your -matlab code. You can get the same functionality by adding the routines: - mxResize (to add/remove rows and columns), - mxReshape (to change the shape without changing the data), - mxMakeComplex (to change a double matrix into a complex matrix), - mxMakeReal (to change a complex matrix into a double matrix), - mxAssign (to replace an array with a new one) -These are all easy enough to define in Matlab. The octave routines -will represent the data using either ComplexMatrix or Matrix so that -an octave value can easily be constructed when it is needed. The -matlab side can continue to use mxArray. - -The function mxGetPr is problematic for values passed from octave. -Because you cannot get a reference to the Matrix in the ocave_value, -you must assign it. Since mxGetPr returns a pointer to the contents -of the array, you must use tmp.fortran_vec(). Since tmp is assigned, -and arrays are copy-on-modify, the simple act of mxGetPr will trigger -a copy. A solution is to trick the compiler: return the const pointer -given by tmp.data(), but declare the function header included in the -mex files as returning a nonconst pointer. - -You will need to hide the difference in storage between complex -arrays, which matlab defines as two matrices (one for real and one for -imaginary), and Octave defines as one matrix (with real and imaginary -values alternating). This is easy to handle by returning Pi as Pr+1, -and multiplying the current matlab index by 2. In octave this would be: - #define mxStride 2 - double *mxGetPr(mxArray *m) { return m->data(); } - double *mxGetPzr(mxArray *m) { return (double *)(cm->data()); } - double *mxGetPzi(mxArray *m) { return (double *)(cm->data()) + 1; } -and for matlab - #define mxStride 1 - #define mxGetPzr mxGetPr - #define mxGetPzi mxGetPi -Then you could implement abs(z) as something like: - int M, N; - double *pr, *pi, *pd; - M = mxGetM(prhs[0]); - N = mxGetN(prhs[0]); - pr = mxGetPzr(prhs[0]); - pi = mxGetPzi(prhs[0]); - plhs[0] = mxCreateDoubleMatrix(M,N); - pd = mxGetPr(plhs[0]); - for (j=0; j < M*N; j++) - pd[j] = sqrt(pr[j*mxStride]*pr[j*mxStride]+pi[j*mxStride]*pi[j*mxStrde]); - -If you have any functions which take real and imaginary parts as -separate arrays, these should be rewritten to accept an mxArray -applying the solution above, otherwise you will have to do something -ugly like: - -#ifdef HAVE_OCTAVE - double *pr, *pi, *newr, *newi; - pr = mxGetPzr(m); - pi = mxGetPzi(m); - newr = mxMalloc(M*N*sizeof(double)); - newi = mxMalloc(M*N*sizeof(double)); - for (j=0; j < M*N*mxStride; j+=mxStride) newr[j]=pr[j], newi[j]=pi[j]; - complex_fun(newr,newi); - for (j=0; j < M*N*mxStride; j+=mxStride) pr[j]=newr[j], pi[j]=newi[j]; - mxFree(newr); - mxFree(newi); -#else - complex_fun(mxGetPr(m),mxGetPi(m)); -#endif
--- a/extra/mex/configure.add Wed Aug 23 19:38:44 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ - -AC_PROG_AWK -
--- a/extra/mex/matrix.h Wed Aug 23 19:38:44 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -#include "mex.h"
--- a/extra/mex/mex.1 Wed Aug 23 19:38:44 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -./" This is the Unix manual page for mex, written in nroff, the standard -./" manual formatter for Unix systems. To format it, type -./" -./" nroff -man mex.man -./" -./" This will print a formatted copy to standard output. If you want -./" to ensure that the output is plain ASCII, free of any control -./" characters that nroff uses for underlining etc, pipe the output -./" through "col -b": -./" -./" nroff -man mex.man | col -b -./" -./" Warning: a leading quote "'" or dot "." will not format correctly -./" -./" I hereby grant this work to the public domain. -./" -.TH mex 1 "September 20, 2001" -.SH NAME -mex \- compile mex file for Octave -.SH SYNOPSIS -.nf -mex [options] mex-file [sources] [objects] [libraries] -.fi -.SH OPTIONS -See mkoctfile for a complete list of options to mex. -.SH DESCRIPTION -mex compiles a file which calls mex functions into an oct-file. It -accepts both FORTRAN and C mex-files. You may include other source -files and object files and libraries in your mex command and they -will be compiled and linked together into the same oct-file, but the -mex-file must be the first file listed. See mkoctfile for details. -.SH BUGS -If you want to use the V4 mex interface, use -DV4 on the command -line instead of -V4. -.SH AUTHOR -.nf -Paul Kienzle -<pkienzle@users.sf.net> -.fi
--- a/extra/mex/mex.cc Wed Aug 23 19:38:44 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1194 +0,0 @@ -// Author: Paul Kienzle -// I grant this code to the public domain. -// 2001-03-22 -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. - -// 2001-06-21 Paul Kienzle <pkienzle@users.sf.net> -// * fix is_numeric so that character strings aren't called numeric. -// * use unsigned short for mxChar rather than char -// 2001-09-20 Paul Kienzle <pkienzle@users.sf.net> -// * Need <float.h> for DBL_EPSILON -// 2001-11-02 Paul Kienzle <pkienzle@users.sf.net> -// * fixed mxGetString to put in the zero-terminator - -#include <cfloat> -#include <iomanip> -#include <set> -#include <string> -typedef void * Pix; -typedef std::set<Pix> MemSet; - -extern "C" { -#include <cstdlib> -#include <csetjmp> - extern const char *mexFunctionName; -} ; - -#include <octave/config.h> -#include <octave/oct.h> -#include <octave/pager.h> -#include <octave/f77-fcn.h> -#include <octave/unwind-prot.h> -#include <octave/lo-mappers.h> -#include <octave/lo-ieee.h> -#include <octave/parse.h> -#include <octave/toplev.h> -#include <octave/variables.h> -#include <octave/oct-map.h> -#include <octave/str-vec.h> - -// ===== Cruft to support ancient versions of octave ======== -#if defined(HAVE_OCTAVE_20) -#include <octave/symtab.h> -class unwind_protect -{ -public: - static void add(cleanup_func fptr, void *ptr) - { - add_unwind_protect (fptr, ptr); - } - static void run(void) - { - run_unwind_protect (); - } -} ; - -static octave_value_list -eval_string (const string& s, int print, int& parse_status, int nargout) -{ - return eval_string(s,print,parse_status); -} - -static int -octave_vformat (std::ostream& os, const char *fmt, va_list args) -{ - int retval = -1; - -#if defined (__GNUG__) - - ostrstream buf; - buf.vform (fmt, args); - buf << ends; - char *s = buf.str (); - os << s; - retval = strlen (s); - delete [] s; - -#else - - char *s = octave_vsnprintf (fmt, args); - if (s) - { - os << s; - retval = strlen (s); - free (s); - } - -#endif - - return retval; -} - -#endif /* defined(HAVE_OCTAVE_20) */ - -#ifndef OCTAVE_LOCAL_BUFFER -#include <vector> -#define OCTAVE_LOCAL_BUFFER(T, buf, size) \ - std::vector<T> buf ## _vector (size); \ - T *buf = &(buf ## _vector[0]) -#endif - -// ============== End cruft support ======================= - -#if 0 -#define TRACEFN cout << __FUNCTION__ << endl << flush -#else -#define TRACEFN do { } while(0) -#endif - -/* ========== mex file context ============= */ -// Class mex keeps track of all memory allocated and frees anything -// not explicitly marked persistent when the it is destroyed. It also -// maintains the setjump/longjump buffer required for non-local exit -// from the mex file, and any other state local to this instance of -// the mex function invocation. -class mxArray; - -class mex { - -public: - mex() { } - ~mex() { if (!memlist.empty()) error("mex: no cleanup performed"); } - - // free all unmarked pointers obtained from malloc and calloc - static void cleanup(void* context); - - // allocate a pointer, and mark it to be freed on exit - Pix malloc(int n); - - // allocate a pointer to be freed on exit, and initialize to 0 - Pix calloc(int n, int t); - - // reallocate a pointer obtained from malloc or calloc - Pix realloc(Pix ptr, int n); - - // free a pointer obtained from malloc or calloc - void free(Pix ptr); - - // mark a pointer so that it will not be freed on exit - void persistent(Pix ptr) { unmark(ptr); } - - // make a new array value and initialize it with zeros; it will be - // freed on exit unless marked as persistent - mxArray *make_value(int nr, int nc, int cmplx); - - // make a new array value and initialize from an octave value; it will be - // freed on exit unless marked as persistent - mxArray *make_value(const octave_value&); - - // make a new structure value and initialize with empty matrices - // XXX FIXME XXX does this leak memory? Is it persistent? - mxArray *make_value(int nr, int nc, const string_vector& keys); - - // free an array and its contents - void free_value(mxArray* ptr); - - // mark an array and its contents so it will not be freed on exit - void persistent(mxArray* ptr); - - // 1 if error should be returned to MEX file, 0 if abort - int trap_feval_error; - - // longjmp return point if mexErrMsgTxt or error - jmp_buf jump; - - // trigger a long jump back to the mex calling function - void abort() { longjmp(jump, 1); } - -private: - - // list of memory resources that need to be freed upon exit - MemSet memlist; - - // mark a pointer to be freed on exit - void mark(Pix p); - - // unmark a pointer to be freed on exit, either because it was - // made persistent, or because it was already freed - void unmark(Pix p); - -} ; - -// Current context -mex* __mex = NULL; - - -// free all unmarked pointers obtained from malloc and calloc -void mex::cleanup(Pix ptr) -{ - mex* context = (mex*)ptr; - for (MemSet::iterator p = context->memlist.begin(); - p != context->memlist.end(); p++) - ::free(*p); - context->memlist.clear(); -} - -// mark a pointer to be freed on exit -void mex::mark(Pix p) -{ -#ifdef DEBUG - if (memlist.find(p) != memlist.end()) - warning("%s: double registration ignored", mexFunctionName); -#endif - memlist.insert(p); -} - -// unmark a pointer to be freed on exit, either because it was -// made persistent, or because it was already freed -void mex::unmark(Pix p) -{ -#ifdef DEBUG - if (memlist.find(p) != memlist.end()) - warning("%s: value not marked", mexFunctionName); -#endif - memlist.erase(p); -} - -// allocate a pointer, and mark it to be freed on exit -Pix mex::malloc(int n) -{ - if (n == 0) return NULL; -#if 0 - // XXX FIXME XXX --- how do you allocate and free aligned, non-typed - // memory in C++? - Pix ptr = Pix(new double[(n+sizeof(double)-1)/sizeof(double)]); -#else - // XXX FIXME XXX --- can we mix C++ and C-style heap management? - Pix ptr = ::malloc(n); - if (ptr == NULL) - { - // XXX FIXME XXX --- could use "octave_new_handler();" instead - error("%s: out of memory", mexFunctionName); - abort(); - } -#endif - - mark(ptr); - return ptr; -} - -// allocate a pointer to be freed on exit, and initialize to 0 -Pix mex::calloc(int n, int t) -{ - Pix v = malloc(n*t); - memset(v, 0, n*t); - return v; -} - -// reallocate a pointer obtained from malloc or calloc -Pix mex::realloc(Pix ptr, int n) -{ -#if 0 - error("%s: cannot reallocate using C++ new/delete operations", - mexFunctionName); - abort(); -#else - Pix v = NULL; - if (n == 0) - free(ptr); - else if (ptr == NULL) - v = malloc(n); - else - { - v = ::realloc(ptr, n); - MemSet::iterator p = memlist.find(ptr); - if (v && p != memlist.end()) - { - memlist.erase(p); - memlist.insert(v); - } - } -#endif - return v; -} - -// free a pointer obtained from malloc or calloc -void mex::free(Pix ptr) -{ - unmark(ptr); -#if 0 - delete [] ptr; -#else - ::free(ptr); -#endif -} - - -/* ============== mxArray data type ============= */ -// Class mxArray is not much more than a struct for keeping together -// dimensions and data. It doesn't even ensure consistency between -// the dimensions and the data. Unfortunately you can't do better -// than this without restricting the operations available in Matlab -// for directly manipulating its mxArray type. - -typedef unsigned short mxChar; -const int mxMAXNAM=64; - -class mxArray { -public: - mxArray() { - nr = nc = -1; - pr = pi = NULL; - keys = NULL; - pmap = NULL; - isstr = false; - aname[0] = '\0'; - } - ~mxArray () { - if (pmap) { - // XXX FIXME XXX why don't string_vectors work? - for (int i=0; i<pmap->length(); i++) delete [] keys[i]; - delete [] keys; - } - } - - octave_value as_octave_value() const; - - int rows() const { return nr; } - int columns() const { return nc; } - void rows(int r) { nr = r; } - void columns(int c) { nc = c; } - int dims() const { return 2; } - - double *imag() const { return pi; } - double *real() const { return pr; } - void imag(double *p) { pi = p; } - void real(double *p) { pr = p; } - - bool is_empty() const { return nr==0 || nc==0; } - bool is_numeric() const { return !isstr && (pr != NULL || nr==0 || nc==0); } - bool is_complex() const { return pi != NULL; } - bool is_sparse() const { return false; } - bool is_struct() const { return pmap != NULL; } - - bool is_string() const { return isstr; } - void is_string(bool set) { isstr = set; } - - const char* name() const { return aname; } - void name(const char *nm) { - strncpy(aname,nm,mxMAXNAM); - aname[mxMAXNAM]='\0'; - } - - // Structure support functions. - /* Matlab uses a fixed field order (the order in which the fields - were added?), but Octave uses an unordered hash for structs. We - can emulate a fixed field order using pmap->keys(), which returns - a string_vector of key names, but these keys will not be in the - same order as the keys given in mxCreateStruct*. Within the - creating function, we can populate the key name vector in the - order given, so the only problem will be those functions which - assume the key order is maintained between calls from Matlab. - Unfortunately, these might exist and I can't detect them :-( - */ - // Return the map value - Octave_map *map(void) const { return pmap; } - // New structure with the given presumed field order (CreateStruct call) - void map(Octave_map *p, const string_vector& mapkeys) { - pmap = p; - keys = mapkeys.c_str_vec(); - } - // New structure with unknown field order (passed in from Octave) - void map(Octave_map *p) { - pmap = p; - if (p) keys = p->keys().c_str_vec(); - } - // Get field given field name - mxArray* field(const std::string& key, const int index) const { - if (pmap && pmap->contains(key)) -#if defined(_Pix_h) - // 2.1.40 - return __mex->make_value(pmap->contents(pmap->seek(key))); -#elif defined(HAVE_OCTAVE_MAP_INDEX) - // 2.1.50 - return __mex->make_value((*pmap)[key](index)); -#else - // 2.1.53 - return __mex->make_value(pmap->contents(key)(index)); -#endif - else - return NULL; - } - // Set field given field name - void field(const std::string& key, const int index, mxArray* value) { -#if defined(HAVE_OCTAVE_MAP_INDEX) || defined(_Pix_h) - // 2.1.50 || 2.1.40 - if (pmap) (*pmap)[key](index) = value->as_octave_value(); -#else - // 2.1.53 - if (pmap) - pmap->assign(octave_value(index+1), - key, Cell(value->as_octave_value())); -#endif - if (error_state) __mex->abort(); - } - // Return number of fields in structure - int num_keys(void) const { return pmap ? pmap->length() : 0; } - // Return field name from field number - const std::string key(const int key_num) const { - if (key_num >= 0 && key_num < pmap->length()) - return keys[key_num]; - else - return NULL; - } - // Return field number from field name - int key(const std::string &key_name) const { - for (int i=0; i<pmap->length(); i++) { - if (key_name == std::string(keys[i])) return i; - } - return -1; - } - // Get field using field number - mxArray* field(const int key_num, const int index) const { - if (key_num >= 0 && key_num < pmap->length()) - return field(keys[key_num], index); - else - return NULL; - } - // Set field using field number - void field(const int key_num, const int index , mxArray* value) { - if (key_num >= 0 && key_num < pmap->length()) - field(keys[key_num], index, value); - } - -private: - int nr, nc; - double *pr, *pi; - /* XXX FIXME XXX need to have a typeid here instead of complex logic on - * isstr, pmap, pr, pi, etc. */ - Octave_map *pmap; - // string_vector keys; - char **keys; - bool isstr; - char aname[mxMAXNAM+1]; -} ; - -octave_value mxArray::as_octave_value() const -{ - octave_value ret; - if (isstr) - { - charMatrix chm(nr,nc); - char *pchm = chm.fortran_vec(); - for (int i=0; i < nr*nc; i++) - pchm[i] = NINT(pr[i]); - ret = octave_value(chm, true); - } - else if (pmap) - { - ret = octave_value(*pmap); - } - else if (pi) - { - ComplexMatrix cm(nr, nc); - Complex *pcm = cm.fortran_vec(); - for (int i=0; i < nr*nc; i++) pcm[i] = Complex(pr[i], pi[i]); - ret = cm; - } - else if (pr) - { - Matrix m(nr,nc); - double *pm = m.fortran_vec(); - memcpy(pm, pr, nr*nc*sizeof(double)); - ret = m; - } - else - ret = Matrix(0,0); - - return ret; -} - - -// ====================== mex/mxArray interface ================== - -// make a new array value and initialize from an octave value; it will be -// freed on exit unless marked as persistent -mxArray* mex::make_value(const octave_value &ov) -{ - int nr=-1, nc=-1; - double *pr = NULL, *pi = NULL; - Octave_map *pmap = NULL; - - if (ov.is_numeric_type() || ov.is_string()) - { - nr = ov.rows(); - nc = ov.columns(); - } - if (ov.is_map()) - { - pmap = new Octave_map(ov.map_value()); - nr = ov.rows(); - nc = ov.columns(); - } - else if (nr > 0 && nc > 0) - { - if (ov.is_string()) - { - // XXX FIXME XXX - must use 16 bit unicode to represent strings. - const Matrix m(ov.matrix_value(1)); - pr = (double *)malloc(nr*nc*sizeof(double)); - memcpy(pr, m.data(), nr*nc*sizeof(double)); - } - else if (ov.is_complex_type()) - { - // XXX FIXME XXX --- may want to consider lazy copying of the - // matrix, but this will only help if the matrix is being - // passed on to octave via callMATLAB later. - const ComplexMatrix cm(ov.complex_matrix_value()); - const Complex * pz = cm.data(); - pr = (double *)malloc(nr*nc*sizeof(double)); - pi = (double *)malloc(nr*nc*sizeof(double)); - for (int i=0; i < nr*nc; i++) - { - pr[i] = real(pz[i]); - pi[i] = imag(pz[i]); - } - } - else - { - const Matrix m(ov.matrix_value()); - pr = (double *)malloc(nr*nc*sizeof(double)); - memcpy(pr, m.data(), nr*nc*sizeof(double)); - } - } - - mxArray *value = (mxArray*)malloc(sizeof(mxArray)); - value->is_string(ov.is_string()); - value->real(pr); - value->imag(pi); - value->map(pmap); - value->rows(nr); - value->columns(nc); - value->name(""); - - return value; -} - -// make a new array value and initialize it with zeros; it will be -// freed on exit unless marked as persistent -mxArray *mex::make_value(int nr, int nc, int cmplx) -{ - - mxArray *value = (mxArray*)malloc(sizeof(mxArray)); - double*p = (double*)calloc(nr*nc, sizeof(double)); - value->real(p); - if (cmplx) value->imag((double*)calloc(nr*nc, sizeof(double))); - else value->imag((double*)Pix(0)); - value->rows(nr); - value->columns(nc); - value->is_string(false); - value->map(NULL); - value->name(""); - - return value; -} - -// make a new structure value and initialize with empty matrices -// XXX FIXME XXX does this leak memory? Is it persistent? -mxArray *mex::make_value(int nr, int nc, const string_vector& keys) -{ - if (keys.length() == 0) return NULL; - -#if defined(HAVE_OCTAVE_MAP_INDEX) || defined(_Pix_h) - // 2.1.50 || 2.1.40 - octave_value_list empty(nr*nc,octave_value()); - Octave_map *pmap = new Octave_map(keys[0],empty); - for (int i=1; i < keys.length(); i++) - pmap->assign(keys[i],empty); -#else - // 2.1.53 - Cell empty(nr,nc); - Octave_map *pmap = new Octave_map(keys[0],empty); - for (int i=1; i < keys.length(); i++) - pmap->assign(keys[i],empty); -#endif - - mxArray *value = (mxArray*)malloc(sizeof(mxArray)); - value->rows(nr); - value->columns(nc); - value->map(pmap,keys); - - return value; -} - -// free an array and its contents -void mex::free_value(mxArray* ptr) -{ - free(ptr->real()); - free(ptr->imag()); - free(ptr); -} - -// mark an array and its contents so it will not be freed on exit -void mex::persistent(mxArray* ptr) -{ - persistent(Pix(ptr->real())); - persistent(Pix(ptr->imag())); - persistent(Pix(ptr)); -} - - -/* ========== Octave interface to mex files ============ */ - -extern "C" { - void F77_FUNC(mexfunction,MEXFUNCTION) - (const int& nargout, mxArray *plhs[], - const int& nargin, mxArray *prhs[]); - void mexFunction(const int nargout, mxArray *plhs[], - const int nargin, mxArray *prhs[]); -} ; - -#if 0 /* Don't bother trapping stop/exit */ -// To trap for STOP in fortran code, this needs to be registered with atexit -static void mex_exit() -{ - if (__mex) { - error("%s: program aborted", mexFunctionName); - __mex->abort(); - } -} -#endif - -enum callstyle { use_fortran, use_C }; - -octave_value_list -call_mex(callstyle cs, const octave_value_list& args, const int nargout) -{ -#if 0 /* Don't bother trapping stop/exit */ - // XXX FIXME XXX ---- should really push "mex_exit" onto the octave - // atexit stack before we start and pop it when we are through, but - // the stack handle isn't exported from toplev.cc, so we can't. mex_exit - // would have to be declared as DEFUN(mex_exit,,,"") of course. - static bool unregistered = true; - if (unregistered) - { - atexit(mex_exit); - unregistered = false; - } -#endif - - // nargout+1 since even for zero specified args, still want to be able - // to return an ans. - const int nargin = args.length(); - OCTAVE_LOCAL_BUFFER(mxArray*, argin, nargin); - OCTAVE_LOCAL_BUFFER(mxArray*, argout, nargout+1); - for (int i=0; i < nargin; i++) argin[i] = NULL; - for (int i=0; i < nargout+1; i++) argout[i] = NULL; - - mex context; - unwind_protect::add(mex::cleanup, Pix(&context)); - - for (int i=0; i < nargin; i++) argin[i] = context.make_value(args(i)); - - unwind_protect_ptr(__mex); // save old mex pointer - if (setjmp(context.jump) == 0) - { - __mex = &context; - if (cs == use_fortran) - F77_FUNC(mexfunction,MEXFUNCTION)(nargout, argout, nargin, argin); - else - mexFunction(nargout, argout, nargin, argin); - } - unwind_protect::run(); // restore old mex pointer - - // convert returned array entries back into octave values - octave_value_list retval; - if (! error_state) - { - for (int i=nargout; i >= 0; i--) { - if (argout[i]) retval(i) = argout[i]->as_octave_value(); - } - //retval(i) = argout[i] ? argout[i]->as_octave_value() : octave_value(); - } - - unwind_protect::run(); // clean up mex resources - return retval; -} - -octave_value_list -Fortran_mex(const octave_value_list& args, const int nargout) -{ - return call_mex(use_fortran, args, nargout); -} - -octave_value_list -C_mex(const octave_value_list& args, const int nargout) -{ - return call_mex(use_C, args, nargout); -} - -/* ============ C interface to mex functions =============== */ -extern "C" { - - void mexErrMsgTxt (const char *s) - { - if (s && strlen(s) > 0) error("%s: %s", mexFunctionName, s); - else error(""); // just set the error state; don't print msg - __mex->abort(); - } - void mexWarnMsgTxt (const char *s) - { - warning("%s", s); - } - void mexPrintf (const char *fmt, ...) - { - va_list args; - va_start (args, fmt); - octave_vformat(octave_diary, fmt, args); - octave_vformat(octave_stdout, fmt, args); - va_end (args); - } - - // floating point representation - int mxIsNaN(const double v) { return (lo_ieee_is_NA(v) || lo_ieee_isnan(v)); } - int mxIsFinite(const double v) { return lo_ieee_finite(v) != 0; } - int mxIsInf(const double v) { return lo_ieee_isinf(v) != 0; } - double mxGetEps() { return DBL_EPSILON; } - double mxGetInf() { return lo_ieee_inf_value(); } - double mxGetNaN() { return lo_ieee_nan_value(); } - - int mexEvalString(const char* s) - { - int parse_status; - octave_value_list ret; - ret = eval_string(s, false, parse_status, 0); - if ( parse_status || error_state ) - { - error_state = 0; - return 1; - } - else - return 0; - } - int mexCallMATLAB(const int nargout, mxArray* argout[], - const int nargin, const mxArray* argin[], - const char* fname) - { - octave_value_list args; - - // XXX FIXME XXX --- do we need unwind protect to clean up args? - // Off hand, I would say that this problem is endemic to Octave - // and we will continue to have memory leaks after Ctrl-C until - // proper exception handling is implemented. longjmp() only - // clears the stack, so any class which allocates data on the - // heap is going to leak. - args.resize(nargin); - for (int i=0; i < nargin; i++) - { - args(i) = argin[i]->as_octave_value(); - } - octave_value_list retval = feval(fname, args, nargout); - - if (error_state && __mex->trap_feval_error == 0) - { - // XXX FIXME XXX --- is this the correct way to clean up? - // abort() is going to trigger a long jump, so the normal - // class destructors will not be called. Hopefully this - // will reduce things to a tiny leak. Maybe create a new - // octave memory tracer type which prints a friendly message - // every time it is created/copied/deleted to check this. - args.resize(0); - retval.resize(0); - __mex->abort(); - } - - int num_to_copy = retval.length(); - if (nargout < retval.length()) num_to_copy = nargout; - for (int i=0; i < num_to_copy; i++) - { - // XXX FIXME XXX --- it would be nice to avoid copying the - // value here, but there is no way to steal memory from a - // matrix, never mind that matrix memory is allocated - // by new[] and mxArray memory is allocated by malloc(). - argout[i] = __mex->make_value(retval(i)); - } - while (num_to_copy < nargout) argout[num_to_copy++] = NULL; - - if (error_state) - { - error_state = 0; - return 1; - } - else - return 0; - } - - void mexSetTrapFlag(int flag) { __mex->trap_feval_error = flag; } - - Pix mxMalloc(int n) { return __mex->malloc(n); } - Pix mxCalloc(int n, int size) { return __mex->calloc(n, size); } - Pix mxRealloc(Pix ptr, int n) { return __mex->realloc(ptr,n); } - void mxFree(Pix ptr) { __mex->free(ptr); } - void mexMakeMemoryPersistent(Pix ptr) { __mex->persistent(ptr); } - - mxArray* mxCreateDoubleMatrix(int nr, int nc, int iscomplex) - { - return __mex->make_value(nr, nc, iscomplex); - } - void mxDestroyArray(mxArray *v) { __mex->free(v); } - void mexMakeArrayPersistent(mxArray *ptr) { __mex->persistent(ptr); } - - int mxIsChar (const mxArray* ptr) { return ptr->is_string(); } - int mxIsSparse (const mxArray* ptr) { return ptr->is_sparse(); } - int mxIsFull(const mxArray* ptr) { return !ptr->is_sparse(); } - int mxIsNumeric (const mxArray* ptr) { return ptr->is_numeric(); } - int mxIsComplex (const mxArray* ptr) { return ptr->is_complex(); } - int mxIsDouble (const mxArray* ptr) { return true; } - int mxIsEmpty (const mxArray* ptr) { return ptr->is_empty(); } - Pix mxGetPr (const mxArray* ptr) { return ptr->real(); } - Pix mxGetPi (const mxArray* ptr) { return ptr->imag(); } - int mxGetM (const mxArray* ptr) { return ptr->rows(); } - int mxGetN (const mxArray* ptr) { return ptr->columns(); } - int mxGetNumberOfDimensions (const mxArray* ptr) { return ptr->dims(); } - int mxGetNumberOfElements (const mxArray* ptr) { return ptr->rows()*ptr->columns(); } - void mxSetM (mxArray* ptr, const int M) { ptr->rows(M); } - void mxSetN (mxArray* ptr, const int N) { ptr->columns(N); } - void mxSetPr (mxArray* ptr, Pix pr) { ptr->real((double *)pr); } - void mxSetPi (mxArray* ptr, Pix pi) { ptr->imag((double *)pi); } - double mxGetScalar (const mxArray* ptr) - { - double *pr = ptr->real(); - if (pr == NULL) mexErrMsgTxt("calling mxGetScalar on an empty matrix"); - return pr[0]; - } - - int mxGetString (const mxArray* ptr, char *buf, int buflen) - { - if (ptr->is_string()) - { - const int nr = ptr->rows(); - const int nc = ptr->columns(); - const int n = nr*nc < buflen ? nr*nc : buflen; - const double *pr = ptr->real(); - for (int i = 0; i < n; i++) buf[i] = NINT(pr[i]); - if (n < buflen) buf[n] = '\0'; - return n >= buflen; - } - else - return 1; - } - - char *mxArrayToString (const mxArray* ptr) - { - const int nr = ptr->rows(); - const int nc = ptr->columns(); - const int n = nr*nc*sizeof(mxChar)+1; - char *buf = (char *)mxMalloc(n); - if (buf) mxGetString(ptr, buf, n); - return buf; - } - - mxArray *mxCreateString(const char *str) - { - const int n = strlen(str); - mxArray *m = __mex->make_value(1, n, 0); - if (m==NULL) return m; - m->is_string(true); - - double *pr = m->real(); - for (int i=0; i < n; i++) pr[i] = str[i]; - return m; - } - - mxArray *mxCreateCharMatrixFromStrings (int n, const char **str) - { - // Find length of the individual strings - Array<int> len(n); - for (int i=0; i < n; i++) len(i) = strlen(str[i]); - - // Find maximum length - int maxlen = 0; - for (int i=0; i < n; i++) if (len(i) > maxlen) maxlen = len(i); - - // Need a place to copy them - mxArray *m = __mex->make_value(n, maxlen, 0); - if (m==NULL) return m; - m->is_string(true); - - // Do the copy (being sure not to exceed the length of any of the - // strings) - double *pr = m->real(); - for (int j = 0; j < maxlen; j++) - for (int i = 0; i < n; i++) - if (j < len(i)) *pr++ = str[i][j]; - else *pr++ = '\0'; - return m; - } - - int mexPutArray(mxArray *ptr, const char *space) - { - if (ptr == NULL) return 1; - const char *name = ptr->name(); - if (name[0]=='\0') return 1; - if (strcmp(space,"global") == 0) - set_global_value (name, ptr->as_octave_value()); - else if (strcmp(space,"caller") == 0) - { - // XXX FIXME XXX --- this belongs in variables.cc - symbol_record *sr = curr_sym_tab->lookup (name, true); - if (sr) sr->define(ptr->as_octave_value()); - else panic_impossible (); - } - else if (strcmp(space,"base") == 0) - mexErrMsgTxt("mexPutArray: 'base' symbol table not implemented"); - else - mexErrMsgTxt("mexPutArray: symbol table does not exist"); - return 0; - } - - mxArray *mexGetArray(const char *name, const char *space) - { - // XXX FIXME XXX --- this should be in variable.cc, but the correct - // functionality is not exported. Particularly, get_global_value() - // generates an error if the symbol is undefined. - symbol_record *sr = NULL; - if (strcmp(space,"global") == 0) - sr = global_sym_tab->lookup (name); - else if (strcmp(space,"caller") == 0) - sr = curr_sym_tab->lookup (name); - else if (strcmp(space,"base") == 0) - mexErrMsgTxt("mexGetArray: 'base' symbol table not implemented"); - else - mexErrMsgTxt("mexGetArray: symbol table does not exist"); - - if (sr) - { -#if defined(HAVE_OCTAVE_20) - octave_value sr_def = sr->variable_value(); -#else - octave_value sr_def = sr->def (); -#endif - if (!sr_def.is_undefined ()) - { - mxArray* ptr = __mex->make_value(sr_def); - ptr->name(name); - return ptr; - } - else - return NULL; - } - else - return NULL; - } - - mxArray *mexGetArrayPtr(const char *name, const char *space) - { - return mexGetArray(name, space); - } - - const char* mxGetName(const mxArray* ptr) - { - return ptr->name(); - } - - void mxSetName(mxArray* ptr, const char*nm) - { - ptr->name(nm); - } - - mxArray *mxCreateStructMatrix(int nr, int nc, int num_keys, - const char **keys) - { - const string_vector ordered_keys(keys,num_keys); - mxArray *m = __mex->make_value(nr, nc, ordered_keys); - return m; - } - mxArray *mxGetField(const mxArray *ptr, int index, const char *key) - { - return ptr->field(key, index); - } - void mxSetField(mxArray *ptr, int index, const char *key, mxArray *val) - { - ptr->field(key,index,val); - } - int mxGetNumberOfFields(const mxArray* ptr) { return ptr->num_keys(); } - int mxIsStruct(const mxArray* ptr) { return ptr->is_struct(); } - const char* mxGetFieldNameByNumber(const mxArray* ptr, int key_num) - { - return ptr->key(key_num).c_str(); - } - int mxGetFieldNumber(const mxArray* ptr, const char *key) - { - return ptr->key(key); - } - mxArray* mxGetFieldByNumber(const mxArray* ptr, int index, int key_num) - { - return ptr->field(key_num,index); - } - void mxSetFieldByNumber(mxArray* ptr, int index, int key_num, mxArray* val) - { - return ptr->field(key_num,index,val); - } - -} ; - -/* ============ Fortran interface to mex functions ============== */ -// Where possible, these call the equivalent C function since that API is -// fixed. It costs and extra function call, but is easier to maintain. -extern "C" { - - void F77_FUNC(mexerrmsgtxt, MEXERRMSGTXT) - (const char *s, const int slen) - { - if (slen > 1 || (slen == 1 && s[0] != ' ') ) - error("%s: %.*s", mexFunctionName, slen, s); - else error(""); // just set the error state; don't print msg - __mex->abort(); - } - - void F77_FUNC(mexprintf,MEXPRINTF) - (const char *s, const int slen) - { - mexPrintf("%.*s\n", slen, s); - } - - double F77_FUNC(mexgeteps,MEXGETEPS)() { return mxGetEps(); } - double F77_FUNC(mexgetinf,MEXGETINF)() { return mxGetInf(); } - double F77_FUNC(mexgetnan,MEXGETNAN)() { return mxGetNaN(); } - int F77_FUNC(mexisfinite,MEXISFINITE)(double v) { return mxIsFinite(v); } - int F77_FUNC(mexisinf,MEXISINF)(double v) { return mxIsInf(v); } - int F77_FUNC(mexisnan,MEXISNAN)(double v) { return mxIsNaN(v); } - - // ====> Array access - Pix F77_FUNC(mxcreatefull,MXCREATEFULL) - (const int& nr, const int& nc, const int& iscomplex) - { - return mxCreateDoubleMatrix(nr,nc,iscomplex); - } - - void F77_FUNC(mxfreematrix,MXFREEMATRIX) - (mxArray* &ptr) - { - mxDestroyArray(ptr); - } - - Pix F77_FUNC(mxcalloc,MXCALLOC)(const int& n, const int& size) - { - return mxCalloc(n,size); - } - - void F77_FUNC(mxfree,MXFREE) - (const Pix &ptr) - { - mxFree(ptr); - } - - int F77_FUNC(mxgetm,MXGETM) - (const mxArray* &ptr) - { - return mxGetM(ptr); - } - - int F77_FUNC(mxgetn,MXGETN) - (const mxArray* &ptr) - { - return mxGetN(ptr); - } - - Pix F77_FUNC(mxgetpi,MXGETPI) - (const mxArray* &ptr) - { - return mxGetPi(ptr); - } - - Pix F77_FUNC(mxgetpr,MXGETPR) - (const mxArray* &ptr) - { - return mxGetPr(ptr); - } - - void F77_FUNC(mxsetm,MXSETM) - (mxArray* &ptr, const int& m) - { - mxSetM(ptr, m); - } - - void F77_FUNC(mxsetn,MXSETN) - (mxArray* &ptr, const int& n) - { - mxSetN(ptr, n); - } - - void F77_FUNC(mxsetpi,MXSETPI) - (mxArray* &ptr, Pix &pi) - { - mxSetPi(ptr, pi); - } - - void F77_FUNC(mxsetpr,MXSETPR) - (mxArray* &ptr, Pix &pr) - { - mxSetPr(ptr, pr); - } - - int F77_FUNC(mxiscomplex,MXISCOMPLEX) - (const mxArray* &ptr) - { - return mxIsComplex(ptr); - } - - int F77_FUNC(mxisdouble,MXISDOUBLE) - (const mxArray* &ptr) - { - return mxIsDouble(ptr); - } - - int F77_FUNC(mxisnumeric,MXISNUMERIC) - (const mxArray* &ptr) - { - return mxIsNumeric(ptr); - } - - int F77_FUNC(mxisfull,MXISFULL) - (const mxArray* &ptr) - { - return 1 - mxIsSparse(ptr); - } - - int F77_FUNC(mxissparse,MXISSPARSE) - (const mxArray* &ptr) - { - return mxIsSparse(ptr); - } - - int F77_FUNC(mxisstring,MXISSTRING) - (const mxArray* &ptr) - { - return mxIsChar(ptr); - } - - int F77_FUNC(mxgetstring,MXGETSTRING) - (const mxArray* &ptr, char *str, const int& len) - { - return mxGetString(ptr, str, len); - } - - int F77_FUNC(mexcallmatlab,MEXCALLMATLAB) - (const int& nargout, mxArray** argout, - const int& nargin, const mxArray** argin, - const char* fname, - const int fnamelen) - { - char str[mxMAXNAM+1]; - strncpy(str, fname, fnamelen<mxMAXNAM?fnamelen:mxMAXNAM); - str[fnamelen] = '\0'; - return mexCallMATLAB(nargout, argout, nargin, argin, str); - } - - // ======> Fake pointer support - void F77_FUNC(mxcopyreal8toptr,MXCOPYREAL8TOPTR) - (const double *d, const int& prref, const int& len) - { - TRACEFN; - double *pr = (double *)prref; - for (int i=0; i < len; i++) pr[i] = d[i]; - } - - void F77_FUNC(mxcopyptrtoreal8,MXCOPYPTRTOREAL8) - (const int& prref, double *d, const int& len) - { - TRACEFN; - double *pr = (double *)prref; - for (int i=0; i < len; i++) d[i] = pr[i]; - } - - void F77_FUNC(mxcopycomplex16toptr,MXCOPYCOMPLEX16TOPTR) - (const double *d, int& prref, int& piref, const int& len) - { - TRACEFN; - double *pr = (double *)prref; - double *pi = (double *)piref; - for (int i=0; i < len; i++) pr[i] = d[2*i], pi[i] = d[2*i+1]; - } - - void F77_FUNC(mxcopyptrtocomplex16,MXCOPYPTRTOCOMPLEX16) - (const int& prref, const int& piref, double *d, const int& len) - { - TRACEFN; - double *pr = (double *)prref; - double *pi = (double *)piref; - for (int i=0; i < len; i++) d[2*i]=pr[i], d[2*i+1] = pi[i]; - } - -} ;
--- a/extra/mex/mex.h Wed Aug 23 19:38:44 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,151 +0,0 @@ -// Author: Paul Kienzle, 2001-03-22 -// I grant this code to the public domain. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -// SUCH DAMAGE. - -// 2001-06-21 Paul Kienzle <pkienzle@users.sf.net> -// * use unsigned short for mxChar rather than char - -/* mex.h is for use in C-programs only; do NOT include it in mex.cc */ - -#ifndef MEX_H -#define MEX_H - -#define HAVE_OCTAVE -typedef void mxArray; -typedef unsigned short mxChar; -enum mxComplexity { mxREAL=0, mxCOMPLEX=1 }; -#if !defined(__cplusplus) -typedef int bool; -#endif - -/* -V4 stuff */ -#if defined(V4) -#define Matrix mxArray -#define REAL mxREAL -#endif - -#define mxMAXNAME 64 - -#if defined(__cplusplus) -extern "C" { -#endif - -#if defined(V4) - void mexFunction(int nlhs, mxArray* plhs[], int nrhs, mxArray* prhs[]); -#else - void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]); -#endif - - /* Floating point representation */ - bool mxIsNaN(double v); - bool mxIsFinite(double v); - bool mxIsInf(double v); - double mxGetEps(void); - double mxGetInf(void); - double mxGetNaN(void); - - /* V4 floating point routines renamed in V5 */ -#define mexIsNaN mxIsNaN -#define mexIsFinite mxIsFinite -#define mexIsInf mxIsInf -#define mexGetEps mxGetEps -#define mexGetInf mxGetInf -#define mexGetNaN mxGetNan - - /* Interface to the interpreter */ - extern const char *mexFunctionName; - int mexCallMATLAB(const int nargout, mxArray* argout[], - const int nargin, const mxArray* argin[], - const char* fname); - void mexSetTrapFlag(int flag); - int mexEvalString (const char *s); - void mexErrMsgTxt (const char *s); - void mexWarnMsgTxt (const char *s); - void mexPrintf (const char *fmt, ...); - - mxArray* mexGetArray(const char *name, const char *space); - mxArray* mexGetArrayPtr(const char *name, const char *space); -#define mexGetGlobal(nm) mexGetArray(nm,"global") -#define mexGetMatrix(nm) mexGetArray(nm,"caller") -#define mexGetMatrixPtr(nm) mexGetArrayPtr(nm,"caller") - int mexPutArray(mxArray* ptr, const char *space); -#define mexPutMatrix(nm) mexPutArray(nm,"caller") - - - /* Memory */ - void *mxMalloc(int n); - void *mxCalloc(int n, int size); - void mxFree(void *ptr); - void mexMakeArrayPersistent(mxArray *ptr); - void mexMakeMemoryPersistent(void *ptr); - - /* interpreter values */ - mxArray* mxCreateDoubleMatrix(int nr, int nc, int iscomplex); -#define mxCreateFull mxCreateDoubleMatrix - void mxDestroyArray(mxArray *v); -#define mxFreeMatrix mxDestroyArray - int mxIsChar (const mxArray* ptr); -#define mxIsString mxIsChar - int mxIsSparse (const mxArray* ptr); - int mxIsStruct (const mxArray* ptr); - int mxIsFull (const mxArray* ptr); - int mxIsDouble (const mxArray* ptr); - int mxIsNumeric (const mxArray* ptr); - int mxIsComplex (const mxArray* ptr); - int mxIsEmpty (const mxArray* ptr); - int mxGetM (const mxArray* ptr); - int mxGetN (const mxArray* ptr); - int mxGetNumberOfDimensions (const mxArray* ptr); - int mxGetNumberOfElements (const mxArray* ptr); - double* mxGetPr (const mxArray* ptr); - - /* structure support */ - int mxIsStruct (const mxArray* ptr); - mxArray* mxGetField(const mxArray* ptr, int index, const char *key); - void mxSetField(mxArray* ptr, int index, const char *key, mxArray* val); - int mxGetNumberOfFields(const mxArray* ptr); - const char* mxGetFieldNameByNumber(const mxArray* ptr, int key_num); - int mxGetFieldNumber(const mxArray* ptr, const char *key); - mxArray* mxGetFieldByNumber(const mxArray* ptr, int index, int key_num); - void mxSetFieldByNumber(mxArray* ptr, int index, int key_num, mxArray* val); - mxArray* mxCreateStructMatrix (int rows, int cols, - int num_keys, const char **keys); -#if 0 - mxArray* mxCreateStructArray (int num_dims, const int * dims, - int numkeys, const char **keys); -#endif - -#if 0 - /* The following cannot be supported in Octave without incurring - * the large runtime penalty of copying arrays to/from matlab format */ - double* mxGetPi (const mxArray* ptr); - void mxSetM (mxArray* ptr, const int M); - void mxSetN (mxArray* ptr, const int N); - void mxSetPr (mxArray* ptr, double* pr); - void mxSetPi (mxArray* ptr, double* pi); -#endif - - - - int mxGetString (const mxArray* ptr, char *buf, int buflen); - char *mxArrayToString (const mxArray* ptr); - mxArray *mxCreateString (const char *str); - - double mxGetScalar (const mxArray* ptr); - -#if defined(__cplusplus) -} -#endif - -#endif /* !defined(MEX_H) */
--- a/extra/mex/mex.in Wed Aug 23 19:38:44 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -#! /bin/sh - -# This program is granted to the public domain - -# 2003-01-03 Paul Kienzle <pkienzle@users.sf.net> -# * eliminate sed --- use direct string interpolation for variables -# * define both the C and fortran names for mexFunction in the oct-file. -# 2001-06-20 Paul Kienzle <pkienzle@users.sf.net> -# * eliminate $(arg:0:1) since it is not available in all sh versions -# 2001-09-20 Paul Kienzle <pkienzle@users.sf.net> -# * use config-like syntax to set the name of mkoctfile and the path to mex - -test $# -lt 1 && echo usage: mex -options file.c && exit 1 - -first="" -for arg in $*; do - case "$arg" in -c) compileonly=1 ;; -*) ;; *) first="$arg"; break ;; esac -done - -if test -z "$first" ; then - @MKOCTFILE@ $* - exit -fi - -if test -n "$compileonly" ; then - set -x - @MKOCTFILE@ -I@LIBPATH@ $* - exit -elif grep -i mexfunction $first >/dev/null ; then - echo building $first -else - echo $first does not contain mexfunction - exit 1 -fi - -# default the name of the octave function from the first filename -dir=`dirname $first` -first=`basename $first` -#echo "first= $first" -ext=`echo $first | sed 's;.*\.;.;g'` -#echo "ext= $ext" -name=`basename $first $ext` -#echo "name=$name ext=$ext" - -case "$ext" in - f*|F*) - invoke=Fortran_mex - otherfn=mexFunction - ;; - *) - invoke=C_mex - otherfn="F77_FUNC(mexfunction,MEXFUNCTION)" - ;; -esac - -# search for a .m file which will be used for the help string -# in the mex function. -if test -f $dir/$name.m ; then - mfile=$dir/$name.m -elif test -f ./$name.m ; then - mfile=./$name.m -else - mfile="" -fi - -cat <<EOF > mex_$name.cc -#include <octave/oct.h> - -extern "C" { - // mex.cc names both mexFunction (c) and MEXFUNCTION (Fortran) - // but the mex file only defines one of them, so define the other - // here just to keep the linker happy, but don't ever call it. - void $otherfn() {} - const char *mexFunctionName = "$name"; -} ; - -DEFUN_DLD($name, args, nargout, -EOF - -if test "X$mfile" = "X" ; then - cat <<EOF >> mex_$name.cc -"\ -$name not directly documented. Try the following:\n\ - type(file_in_loadpath('$name.m'))\n\ -") -EOF -else - @AWK@ 'BEGIN{print "\"\\";printing=0;} - /^[ \t]*[%#]/ {printing=1; - gsub(/^[ \t]*[%#]*/,""); - gsub(/\\/,"\\\\"); - gsub(/"/,"\\\""); - print $0 "\\n\\"; next} - {if (printing) exit;} - END{print "\")"}' \ - $mfile >> mex_$name.cc -fi - -cat <<EOF >> mex_$name.cc -{ - octave_value_list $invoke(const octave_value_list &, const int); - return $invoke(args, nargout); -} -EOF - -if test -f "@MEXLIB@" ; then - MEXPATH=. -else - MEXPATH="@LIBPATH@" -fi - -set -x -@MKOCTFILE@ -o $name.oct mex_$name.cc $MEXPATH/mex.o -I$MEXPATH $*
--- a/extra/mex/myfeval.c Wed Aug 23 19:38:44 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -#include "mex.h" - -void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) -{ - char *str; - mexPrintf("Hello, World!\n"); - mexPrintf("I have %d inputs and %d outputs\n", nrhs, nlhs); - if (nrhs < 1 || !mxIsString(prhs[0])) - mexErrMsgTxt("function name expected"); - str = mxArrayToString (prhs[0]); - mexPrintf("I'm going to call the interpreter function %s\n", str); - mexCallMATLAB(nlhs, plhs, nrhs-1, prhs+1, str); - mxFree(str); -}
--- a/extra/mex/myfeval.m Wed Aug 23 19:38:44 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -function myfeval, -#% [...] = myfeval('fn',...) - % call feval on 'fn' - error("mex version of myfeval isn't available"); -%this is not part of the message
--- a/extra/mex/myfevalf.f Wed Aug 23 19:38:44 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,19 +0,0 @@ - subroutine mexFunction(nlhs, plhs, nrhs, prhs) - implicit none - integer*4 nlhs, nrhs, plhs(*), prhs(*) - - integer*4 mxIsString, mxGetString, mxGetN, mexCallMATLAB - - integer*4 status, len - character*100 str - - call mexPrintf('Hello, World!') - if (nrhs .lt. 1 .or. mxIsString(prhs(1)) .ne. 1) then - call mexErrMsgTxt('function name expected') - endif - len = mxGetN(prhs(1)) - status = mxGetString (prhs(1), str, 100) - call mexPrintf('FORTRAN will call the interpreter now') - status = mexCallMATLAB(nlhs, plhs, nrhs-1, prhs(2), str(1:len)) - return - end
--- a/extra/mex/myset.c Wed Aug 23 19:38:44 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -#include "mex.h" - -void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) -{ - char *str; - mxArray *v; - - if (nrhs != 2 || !mxIsString(prhs[0])) - mexErrMsgTxt("expects symbol name and value"); - str = mxArrayToString (prhs[0]); - v = mexGetArray(str, "global"); - if (v != 0) { - mexPrintf("%s is a global variable with the following value:\n", str); - mexCallMATLAB(0, (mxArray**)0, 1, &v, "disp"); - } - v = mexGetArray(str, "caller"); - if (v != 0) { - mexPrintf("%s is a caller variable with the following value:\n", str); - mexCallMATLAB(0, (mxArray**)0, 1, &v, "disp"); - } - - // WARNING!! Can't do this in MATLAB! Must copy variable first. - mxSetName(prhs[1], str); - mexPutArray(prhs[1], "caller"); -}
--- a/extra/mex/mystruct.c Wed Aug 23 19:38:44 2006 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,29 +0,0 @@ -#include "mex.h" - -void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) -{ - int i,j; - mxArray *v; - const char *keys[] = { "this", "that" }; - - if (nrhs != 1 || !mxIsStruct(prhs[0])) - mexErrMsgTxt("expects struct"); - for (i=0; i < mxGetNumberOfFields(prhs[0]); i++) { - for (j=0; j < mxGetNumberOfElements(prhs[0]); j++) { - mexPrintf("field %s(%d) = ", mxGetFieldNameByNumber(prhs[0],i), j); - v = mxGetFieldByNumber(prhs[0],j,i); - mexCallMATLAB(0, (mxArray**)0, 1, &v, "disp"); - } - } - - v = mxCreateStructMatrix(2,2,2,keys); - mxSetFieldByNumber(v,0,0,mxCreateString("this1")); - mxSetFieldByNumber(v,0,1,mxCreateString("that1")); - mxSetFieldByNumber(v,1,0,mxCreateString("this2")); - mxSetFieldByNumber(v,1,1,mxCreateString("that2")); - mxSetFieldByNumber(v,2,0,mxCreateString("this3")); - mxSetFieldByNumber(v,2,1,mxCreateString("that3")); - mxSetFieldByNumber(v,3,0,mxCreateString("this4")); - mxSetFieldByNumber(v,3,1,mxCreateString("that4")); - if (nlhs) plhs[0] = v; -}