/* nr3matlab.h */ // version 0.8 // This file is a version of nr3.h with hooks that // make it easy to write Matlab mex files, in particular // ones that use NR3 routines. // See http://www.nr.com/nr3_matlab.html #include "mex.h" #define _CHECKBOUNDS_ 1 // all the system #include's we'll ever need #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; // macro-like inline functions template inline T SQR(const T a) {return a*a;} template inline const T &MAX(const T &a, const T &b) {return b > a ? (b) : (a);} inline float MAX(const double &a, const float &b) {return b > a ? (b) : float(a);} inline float MAX(const float &a, const double &b) {return b > a ? float(b) : (a);} template inline const T &MIN(const T &a, const T &b) {return b < a ? (b) : (a);} inline float MIN(const double &a, const float &b) {return b < a ? (b) : float(a);} inline float MIN(const float &a, const double &b) {return b < a ? float(b) : (a);} template inline T SIGN(const T &a, const T &b) {return b >= 0 ? (a >= 0 ? a : -a) : (a >= 0 ? -a : a);} inline float SIGN(const float &a, const double &b) {return b >= 0 ? (a >= 0 ? a : -a) : (a >= 0 ? -a : a);} inline float SIGN(const double &a, const float &b) {return (float)(b >= 0 ? (a >= 0 ? a : -a) : (a >= 0 ? -a : a));} template inline void SWAP(T &a, T &b) {T dum=a; a=b; b=dum;} // exception handling when executing underneath Matlab #ifdef _MSC_VER #define throw(message) \ {char msg[1024]; sprintf_s(msg,1024,"%s in file %s at line %d\n", \ message,__FILE__,__LINE__); mexErrMsgTxt(msg);} #else #define throw(message) \ {char msg[1024]; sprintf(msg,"%s in file %s at line %d\n", \ message,__FILE__,__LINE__); mexErrMsgTxt(msg);} #endif // basic type names (put here so can use for Matlab stuff) typedef int Int; // 32 bit integer typedef unsigned int Uint; #ifdef _MSC_VER typedef __int64 Llong; // 64 bit integer typedef unsigned __int64 Ullong; #else typedef long long int Llong; // 64 bit integer typedef unsigned long long int Ullong; #endif typedef char Char; // 8 bit integer typedef unsigned char Uchar; typedef double Doub; // default floating type typedef long double Ldoub; typedef complex Complex; // default complex type typedef bool Bool; // NaN: you should test by verifying that (NaN != NaN) is true (see nr3.h) static const Doub NaN = numeric_limits::quiet_NaN(); // get mxClassID of any type T template inline mxClassID mxT() {return mxUNKNOWN_CLASS;} template <> inline mxClassID mxT() {return mxDOUBLE_CLASS;} template <> inline mxClassID mxT() {return mxSINGLE_CLASS;} template <> inline mxClassID mxT() {return mxINT32_CLASS;} template <> inline mxClassID mxT() {return mxUINT32_CLASS;} template <> inline mxClassID mxT() {return mxCHAR_CLASS;} template <> inline mxClassID mxT() {return mxUINT8_CLASS;} template <> inline mxClassID mxT() {return mxINT64_CLASS;} template <> inline mxClassID mxT() {return mxUINT64_CLASS;} template <> inline mxClassID mxT() { if (sizeof(Bool)==1) return mxLOGICAL_CLASS; else throw("bool and mxLOGICAL_CLASS have incompatible sizes"); } inline mxClassID mxT(const mxArray *p) {return mxGetClassID(p);} // functions to map Matlab scalars template const T& mxScalar(const mxArray *prhs) { if (mxGetClassID(prhs) != mxT()) throw("attempt to assign scalar ref to wrong type"); return *(T*)mxGetData(prhs); } template T& mxScalar(mxArray* &plhs) { plhs = mxCreateNumericMatrix(1,1,mxT(),mxREAL); return *(T*)mxGetData(plhs); } template const T& mxScalar(const char *varname) { const mxArray* mxptr = mexGetVariablePtr("base",varname); if (mxptr == NULL) throw("attempt to get nonexistent variable"); if (mxGetClassID(mxptr) != mxT()) throw("attempt to assign scalar ref to wrong type"); return *(T*)mxGetData(mxptr); } template void mxScalar(T val, const char *varname) { mxClassID mxclass = mxT(); if (mxclass == mxUNKNOWN_CLASS) throw("no corresponding Matlab type"); mxArray* mxdum = mxCreateNumericMatrix(1,1,mxclass,mxREAL); *(T*)mxGetData(mxdum) = val; if (mexPutVariable("base",varname,mxdum)) throw("failed to send data to Matlab variable by name"); mxDestroyArray(mxdum); } // Vector and Matrix Classes template class NRvector { private: int nn; // size of array. upper index is nn-1 int own; // 1 if own data, 0 if Matlab's T *v; public: NRvector(); explicit NRvector(int n); // Zero-based array NRvector(int n, const T &a); //initialize to constant value NRvector(int n, const T *a); // Initialize to array NRvector(const NRvector &rhs); // Copy constructor NRvector & operator=(const NRvector &rhs); //assignment typedef T value_type; // make T available externally inline T & operator[](const int i); //i'th element inline const T & operator[](const int i) const; inline int size() const; void resize(int newn); // resize (contents not preserved) void assign(int newn, const T &a); // resize and assign a constant value ~NRvector(); NRvector(const mxArray *prhs); // map Matlab rhs to vector (read-only) NRvector(int n, mxArray* &plhs); // create Matlab lhs and map to vector NRvector(const char *varname); // import Matlab variable by name (read-only) void put(const char *varname); // export vector to a named Matlab variable }; template NRvector::NRvector(const mxArray* prhs) : own(0) { if (mxGetClassID(prhs) != mxT()) throw("constructing VecDoub from a different Matlab type prhs"); nn = mxGetNumberOfElements(prhs); v = (T*)mxGetData(prhs); } template NRvector::NRvector(int n, mxArray* &plhs) : nn(n), own(0) { mxClassID mxclass = mxT(); if (mxclass == mxUNKNOWN_CLASS) throw("no corresponding Matlab type for plhs"); plhs = mxCreateNumericMatrix(1,nn,mxclass,mxREAL); v = (T*)mxGetData(plhs); } template NRvector::NRvector(const char *varname) : own(0) { const mxArray* mxptr = mexGetVariablePtr("base",varname); if (mxptr == NULL) throw("attempt to get nonexistent variable"); if (mxGetClassID(mxptr) != mxT()) throw("constructing a VecDoub from a different Matlab type"); nn = mxGetNumberOfElements(mxptr); v = (T*)mxGetData(mxptr); } template void NRvector::put(const char *varname) { mxClassID mxclass = mxT(); if (mxclass == mxUNKNOWN_CLASS) throw("no corresponding Matlab type"); mxArray* mxdum = mxCreateNumericMatrix(1,1,mxclass,mxREAL); void* sav = mxGetData(mxdum); mxSetN(mxdum,nn); mxSetData(mxdum,v); if (mexPutVariable("base",varname,mxdum)) throw("failed to send data to Matlab variable by name"); mxSetData(mxdum,sav); mxSetN(mxdum,1); mxDestroyArray(mxdum); } template NRvector::NRvector() : nn(0), own(1), v(NULL) {} template NRvector::NRvector(int n) : nn(n), own(1), v(n>0 ? new T[n] : NULL) {} template NRvector::NRvector(int n, const T& a) : nn(n), own(1), v(n>0 ? new T[n] : NULL) { for(int i=0; i NRvector::NRvector(int n, const T *a) : nn(n), own(1), v(n>0 ? new T[n] : NULL) { for(int i=0; i NRvector::NRvector(const NRvector &rhs) : nn(rhs.nn), own(1), v(nn>0 ? new T[nn] : NULL) { for(int i=0; i NRvector & NRvector::operator=(const NRvector &rhs) // postcondition: normal assignment via copying has been performed; // if vector and rhs were different sizes, vector // has been resized to match the size of rhs { if (this != &rhs) { if (nn != rhs.nn) { if (!own) throw("resize of mxArray by assignment not allowed"); if (v != NULL) delete [] (v); nn=rhs.nn; v= nn>0 ? new T[nn] : NULL; } for (int i=0; i inline T & NRvector::operator[](const int i) //subscripting { #ifdef _CHECKBOUNDS_ if (i<0 || i>=nn) { throw("NRvector subscript out of bounds"); } #endif return v[i]; } template inline const T & NRvector::operator[](const int i) const //subscripting { #ifdef _CHECKBOUNDS_ if (i<0 || i>=nn) { throw("NRvector subscript out of bounds"); } #endif return v[i]; } template inline int NRvector::size() const { return nn; } template void NRvector::resize(int newn) { if (newn != nn) { if (!own) throw("resize of mxArray not allowed"); if (v != NULL) delete[] (v); nn = newn; v = nn > 0 ? new T[nn] : NULL; } } template void NRvector::assign(int newn, const T& a) { if (newn != nn) { if (!own) throw("resize of mxArray by assign method not allowed"); if (v != NULL) delete[] (v); nn = newn; v = nn > 0 ? new T[nn] : NULL; } for (int i=0;i NRvector::~NRvector() { if (own && v != NULL) delete[] (v); } // end of NRvector definitions template class NRmatrix { private: int nn; int mm; int own; // owned by self 1, vs Matlab 0 T **v; public: NRmatrix(); NRmatrix(int n, int m); // Zero-based array NRmatrix(int n, int m, const T &a); //Initialize to constant NRmatrix(int n, int m, const T *a); // Initialize to array NRmatrix(const NRmatrix &rhs); // Copy constructor NRmatrix & operator=(const NRmatrix &rhs); //assignment typedef T value_type; // make T available externally inline T* operator[](const int i); //subscripting: pointer to row i inline const T* operator[](const int i) const; inline int nrows() const; inline int ncols() const; void resize(int newn, int newm); // resize (contents not preserved) void assign(int newn, int newm, const T &a); // resize and assign a constant value ~NRmatrix(); NRmatrix(const mxArray *prhs); // map Matlab rhs to matrix (read-only) NRmatrix(int n, int m, mxArray* &plhs); // create Matlab lhs and map to matrix NRmatrix(const char *varname); // import Matlab variable by name (read-only) void put(const char *varname); // export matrix to a named Matlab variable }; template void NRmatrix::put(const char *varname) { mxClassID mxclass = mxT(); if (mxclass == mxUNKNOWN_CLASS) throw("no corresponding Matlab type"); mxArray* mxdum = mxCreateNumericMatrix(1,1,mxclass,mxREAL); void* sav = mxGetData(mxdum); mxSetN(mxdum,nn); mxSetM(mxdum,mm); mxSetData(mxdum,v[0]); if (mexPutVariable("base",varname,mxdum)) throw("failed to send data to Matlab variable by name"); mxSetData(mxdum,sav); mxSetN(mxdum,1); mxSetM(mxdum,1); mxDestroyArray(mxdum); } template NRmatrix::NRmatrix(const char *varname) : own(0) { const mxArray* mxptr = mexGetVariablePtr("base",varname); if (mxptr == NULL) throw("attempt to get nonexistent variable"); if (mxGetClassID(mxptr) != mxT()) throw("constructing an NRmatrix from a different type Matlab variable"); nn = mxGetN(mxptr); mm = mxGetM(mxptr); v = nn>0 ? new T*[nn] : NULL; if (v) v[0] = (T*)mxGetData(mxptr); for (int i=1;i NRmatrix::NRmatrix(const mxArray *prhs) : own(0) { if (mxGetClassID(prhs) != mxT()) throw("constructing NRmatrix from a different type Matlab prhs"); nn = mxGetN(prhs); mm = mxGetM(prhs); v = nn>0 ? new T*[nn] : NULL; if (v) v[0] = (T*)mxGetData(prhs); for (int i=1;i NRmatrix::NRmatrix(int n, int m, mxArray* &plhs) : nn(n), mm(m), own(0) { mxClassID mxclass = mxT(); if (mxclass == mxUNKNOWN_CLASS) throw("no corresponding Matlab type for plhs"); plhs = mxCreateNumericMatrix(mm,nn,mxclass,mxREAL); v = nn>0 ? new T*[nn] : NULL; if (v) v[0] = (T*)mxGetData(plhs); for (int i=1;i NRmatrix::NRmatrix() : nn(0), mm(0), own(1), v(NULL) {} template NRmatrix::NRmatrix(int n, int m) : nn(n), mm(m), own(1), v(n>0 ? new T*[n] : NULL) { int i,nel=m*n; if (v) v[0] = nel>0 ? new T[nel] : NULL; for (i=1;i NRmatrix::NRmatrix(int n, int m, const T &a) : nn(n), mm(m), own(1), v(n>0 ? new T*[n] : NULL) { int i,j,nel=m*n; if (v) v[0] = nel>0 ? new T[nel] : NULL; for (i=1; i< n; i++) v[i] = v[i-1] + m; for (i=0; i< n; i++) for (j=0; j NRmatrix::NRmatrix(int n, int m, const T *a) : nn(n), mm(m), own(1), v(n>0 ? new T*[n] : NULL) { int i,j,nel=m*n; if (v) v[0] = nel>0 ? new T[nel] : NULL; for (i=1; i< n; i++) v[i] = v[i-1] + m; for (i=0; i< n; i++) for (j=0; j NRmatrix::NRmatrix(const NRmatrix &rhs) : nn(rhs.nn), mm(rhs.mm), own(1), v(nn>0 ? new T*[nn] : NULL) { int i,j,nel=mm*nn; if (v) v[0] = nel>0 ? new T[nel] : NULL; for (i=1; i< nn; i++) v[i] = v[i-1] + mm; for (i=0; i< nn; i++) for (j=0; j NRmatrix & NRmatrix::operator=(const NRmatrix &rhs) // postcondition: normal assignment via copying has been performed; // if matrix and rhs were different sizes, matrix // has been resized to match the size of rhs { if (this != &rhs) { int i,j,nel; if (nn != rhs.nn || mm != rhs.mm) { if (!own) throw("resize of mxArray by assignment not allowed"); if (v != NULL) { delete[] (v[0]); delete[] (v); } nn=rhs.nn; mm=rhs.mm; v = nn>0 ? new T*[nn] : NULL; nel = mm*nn; if (v) v[0] = nel>0 ? new T[nel] : NULL; for (i=1; i< nn; i++) v[i] = v[i-1] + mm; } for (i=0; i< nn; i++) for (j=0; j inline T* NRmatrix::operator[](const int i) //subscripting: pointer to row i { #ifdef _CHECKBOUNDS_ if (i<0 || i>=nn) { throw("NRmatrix subscript out of bounds"); } #endif return v[i]; } template inline const T* NRmatrix::operator[](const int i) const { #ifdef _CHECKBOUNDS_ if (i<0 || i>=nn) { throw("NRmatrix subscript out of bounds"); } #endif return v[i]; } template inline int NRmatrix::nrows() const { return nn; } template inline int NRmatrix::ncols() const { return mm; } template void NRmatrix::resize(int newn, int newm) { int i,nel; if (newn != nn || newm != mm) { if (!own) throw("resize of mxArray not allowed"); if (v != NULL) { delete[] (v[0]); delete[] (v); } nn = newn; mm = newm; v = nn>0 ? new T*[nn] : NULL; nel = mm*nn; if (v) v[0] = nel>0 ? new T[nel] : NULL; for (i=1; i< nn; i++) v[i] = v[i-1] + mm; } } template void NRmatrix::assign(int newn, int newm, const T& a) { int i,j,nel; if (newn != nn || newm != mm) { if (!own) throw("resize of mxArray by assign function not allowed"); if (v != NULL) { delete[] (v[0]); delete[] (v); } nn = newn; mm = newm; v = nn>0 ? new T*[nn] : NULL; nel = mm*nn; if (v) v[0] = nel>0 ? new T[nel] : NULL; for (i=1; i< nn; i++) v[i] = v[i-1] + mm; } for (i=0; i< nn; i++) for (j=0; j NRmatrix::~NRmatrix() { if (v != NULL) { if (own) delete[] (v[0]); delete[] (v); } } template class NRMat3d { private: int nn; int mm; int kk; T ***v; public: NRMat3d(); NRMat3d(int n, int m, int k); inline T** operator[](const int i); //subscripting: pointer to row i inline const T* const * operator[](const int i) const; inline int dim1() const; inline int dim2() const; inline int dim3() const; ~NRMat3d(); }; template NRMat3d::NRMat3d(): nn(0), mm(0), kk(0), v(NULL) {} template NRMat3d::NRMat3d(int n, int m, int k) : nn(n), mm(m), kk(k), v(new T**[n]) { int i,j; v[0] = new T*[n*m]; v[0][0] = new T[n*m*k]; for(j=1; j inline T** NRMat3d::operator[](const int i) //subscripting: pointer to row i { return v[i]; } template inline const T* const * NRMat3d::operator[](const int i) const { return v[i]; } template inline int NRMat3d::dim1() const { return nn; } template inline int NRMat3d::dim2() const { return mm; } template inline int NRMat3d::dim3() const { return kk; } template NRMat3d::~NRMat3d() { if (v != NULL) { delete[] (v[0][0]); delete[] (v[0]); delete[] (v); } } // vector types typedef const NRvector VecInt_I; typedef NRvector VecInt, VecInt_O, VecInt_IO; typedef const NRvector VecUint_I; typedef NRvector VecUint, VecUint_O, VecUint_IO; typedef const NRvector VecLlong_I; typedef NRvector VecLlong, VecLlong_O, VecLlong_IO; typedef const NRvector VecUllong_I; typedef NRvector VecUllong, VecUllong_O, VecUllong_IO; typedef const NRvector VecChar_I; typedef NRvector VecChar, VecChar_O, VecChar_IO; typedef const NRvector VecCharp_I; typedef NRvector VecCharp, VecCharp_O, VecCharp_IO; typedef const NRvector VecUchar_I; typedef NRvector VecUchar, VecUchar_O, VecUchar_IO; typedef const NRvector VecDoub_I; typedef NRvector VecDoub, VecDoub_O, VecDoub_IO; typedef const NRvector VecDoubp_I; typedef NRvector VecDoubp, VecDoubp_O, VecDoubp_IO; typedef const NRvector VecComplex_I; typedef NRvector VecComplex, VecComplex_O, VecComplex_IO; typedef const NRvector VecBool_I; typedef NRvector VecBool, VecBool_O, VecBool_IO; // matrix types typedef const NRmatrix MatInt_I; typedef NRmatrix MatInt, MatInt_O, MatInt_IO; typedef const NRmatrix MatUint_I; typedef NRmatrix MatUint, MatUint_O, MatUint_IO; typedef const NRmatrix MatLlong_I; typedef NRmatrix MatLlong, MatLlong_O, MatLlong_IO; typedef const NRmatrix MatUllong_I; typedef NRmatrix MatUllong, MatUllong_O, MatUllong_IO; typedef const NRmatrix MatChar_I; typedef NRmatrix MatChar, MatChar_O, MatChar_IO; typedef const NRmatrix MatUchar_I; typedef NRmatrix MatUchar, MatUchar_O, MatUchar_IO; typedef const NRmatrix MatDoub_I; typedef NRmatrix MatDoub, MatDoub_O, MatDoub_IO; typedef const NRmatrix MatBool_I; typedef NRmatrix MatBool, MatBool_O, MatBool_IO; // 3D matrix types typedef const NRMat3d Mat3DDoub_I; typedef NRMat3d Mat3DDoub, Mat3DDoub_O, Mat3DDoub_IO;