#ifndef cwMtx_h #define cwMtx_h namespace cw { namespace mtx { enum { kAliasReleaseFl = 0x01, // do not allocate memory, use the passed data pointer, and eventually release it kAliasNoReleaseFl = 0x02, // do not allocate memory, use the passed data pointer, and do not ever release it kDuplDataFl = 0x04, // allocate data space and copy the data in kZeroFl = 0x08, // zero the newly allocated data }; template< typename T > struct mtx_str { unsigned flags = 0; unsigned dimN = 0; unsigned* dimV = nullptr; T* base = nullptr; unsigned allocEleN = 0; // always 0 if data is aliased }; template< typename T > void release( struct mtx_str*& m ) { if( m != nullptr ) { mem::release(m->dimV); if( cwIsNotFlag(m->flags,kAliasNoReleaseFl) ) mem::release(m->base); mem::release(m); } } template< typename T > struct mtx_str* _init( struct mtx_str* m, unsigned dimN, const unsigned* dimV, T* base=nullptr, unsigned flags=0 ) { // if a pre-allocated mtx obj was not given then allocate one if( m == nullptr ) m = mem::allocZ>(1); // if the pre-allocd mtx obj has more dim's then the new one if( m->dimN >= dimN ) m->dimN = dimN; else // else expand dimV[] { m->dimV = mem::resize(m->dimV,dimN); m->dimN = dimN; } // update dimV[] with the new extents and calc. the new ele count unsigned eleN = 0; for(unsigned i=0; idimV[i] = dimV[i]; eleN = (i==0 ? 1 : eleN) * dimV[i]; } bool aliasFl = cwIsFlag(flags, kAliasNoReleaseFl | kAliasReleaseFl ); // if the new object data is aliased if( aliasFl ) { // release any memory the pre-allocated obj may own if( cwIsNotFlag(m->flags,kAliasNoReleaseFl) ) mem::release(m->base); m->base = base; m->allocEleN = 0; // always 0 when data is aliased } else // the new object is not aliased { // if the current data space is too small then reallocate it if( eleN > m->allocEleN ) { // don't allow an alias-no-release ptr to be released if( cwIsFlag(m->flags,kAliasNoReleaseFl) ) m->base = nullptr; m->base = mem::resize(m->base, eleN, cwIsFlag(flags,kZeroFl) ? mem::kZeroAllFl : 0 ); m->allocEleN = eleN; } } // if duplication was requested if( cwIsFlag(flags,kDuplDataFl) ) { assert( aliasFl == false ); memcpy(m->base,base, eleN*sizeof(T) ); } m->flags = flags; return m; } // Allocate the matrix w/o zeroing the initial contents template< typename T > struct mtx_str* alloc( unsigned dimN, const unsigned* dimV ) { return _init( nullptr, dimN, dimV, nullptr, 0); } // Allocate the matrix and zero the contents template< typename T > struct mtx_str* allocZ( unsigned dimN, const unsigned* dimV ) { return _init( nullptr, dimN, dimV, nullptr, kZeroFl); } // Allocate the matrix and copy the data from base[] template< typename T > struct mtx_str* allocDupl( unsigned dimN, const unsigned* dimV, const T* base ) { return _init( nullptr, dimN, dimV, const_cast(base), kDuplDataFl); } // Allocate a matrix and use base[] as the data. Release base[] when it is no longer needed. template< typename T > struct mtx_str* allocAlias( unsigned dimN, const unsigned* dimV, T* base ) { return _init( nullptr, dimN, dimV, base, kAliasReleaseFl); } // Allocate a mtrix and use base[] as the data - do NOT release base[]. template< typename T > struct mtx_str* allocAliasNoRelease( unsigned dimN, const unsigned* dimV, const T* base ) { return _init( nullptr, dimN, dimV, const_cast(base), kAliasNoReleaseFl); } template< typename T > struct mtx_str* alloc( unsigned dimN, const unsigned* dimV, T* base=nullptr, unsigned flags=0 ) { return _init( nullptr, dimN, dimV, base, flags); } // resize m[] template< typename T > struct mtx_str* resize( struct mtx_str* m, const unsigned* dimV, unsigned dimN, T* base=nullptr, unsigned flags=0 ) { return _init( m, dimN, dimV, base, flags ); } // resize y[] to have the same size as x[] template< typename T > struct mtx_str* resize( struct mtx_str* y, const struct mtx_str& x ) { return resize(y,x->dimV,x->dimN); } // Return 'true' if the matrices have the same size. template< typename T > bool is_size_equal( const struct mtx_str& x0, const struct mtx_str& x1 ) { if( x0.dimN != x1.dimN ) return false; for(unsigned i=0; idimN; ++i) if( x0.dimV[i] != x1.dimV[i] ) return false; return true; } // Return the count of elements in the matrix template< typename T > bool ele_count( const struct mtx_str& x ) { unsigned eleN = 1; for(unsigned i=0; i void mult( struct mtx_str& y, const struct mtx_str& x0, const struct mtx_str& x1 ) { assert( is_size_equal(x0,x1) ); resize(&y,x0); // resize y to the same dim's as m unsigned n = ele_count(x0); for(unsigned i=0; i void mult( struct mtx_str& y, const struct mtx_str& x ) { assert( is_size_equal(y,x) ); unsigned n = ele_count(x); for(unsigned i=0; i void mult( struct mtx_str& y, const struct mtx_str& x, const T& scalar ) { resize(&y,x); // resize y to the same dim's as m unsigned n = ele_count(x); for(unsigned i=0; i void mult( struct mtx_str& y, const T& scalar ) { unsigned n = ele_count(y); for(unsigned i=0; i void add( struct mtx_str& y, const struct mtx_str& x0, const struct mtx_str& x1 ) { assert( is_size_equal(x0,x1) ); resize(&y,x0); // resize y to the same dim's as m unsigned n = ele_count(x0); for(unsigned i=0; i void add( struct mtx_str& y, const struct mtx_str& x ) { assert( is_size_equal(y,x) ); unsigned n = ele_count(x); for(unsigned i=0; i void add( struct mtx_str& y, const struct mtx_str& x, const T& scalar ) { resize(&y,x); unsigned n = ele_count(y); for(unsigned i=0; i void add( struct mtx_str& y, const T& scalar ) { unsigned n = ele_count(y); for(unsigned i=0; i void mtx_mul( struct mtx_str& y, const struct mtx_str& m, const struct mtx_str& x ) { } typedef struct mtx_str fmtx_t; } } #endif