cwFileSys.h/cpp : Added makeDir().
cwLog.h/cpp : Added cwLogPrint() functions. cwMtx.h : Many addtions. cwObject.h : Added find_child() functions. cwUtility.h/cpp : Added x80ToDouble() and doubleToX80(). cwCommon.h : Added new RC codes cwCommonImpl.h : Added swapping macros and is_int<T>().
This commit is contained in:
parent
1af6b58667
commit
fa33ac00c9
@ -42,7 +42,9 @@ namespace cw
|
|||||||
kDuplicateRC, // 23 - an invalid duplicate was detected
|
kDuplicateRC, // 23 - an invalid duplicate was detected
|
||||||
kAssertFailRC, // 24 - used with cwLogFatal
|
kAssertFailRC, // 24 - used with cwLogFatal
|
||||||
kInvalidDataTypeRC, // 25
|
kInvalidDataTypeRC, // 25
|
||||||
kBaseAppRC // 26
|
kFileNotFoundRC, // 26
|
||||||
|
kTestFailRC, // 27
|
||||||
|
kBaseAppRC // 28
|
||||||
} cwRC_t;
|
} cwRC_t;
|
||||||
|
|
||||||
typedef unsigned rc_t;
|
typedef unsigned rc_t;
|
||||||
|
@ -27,6 +27,47 @@
|
|||||||
|
|
||||||
#define cwStringNullGuard(s) ((s)==nullptr ? "" : (s))
|
#define cwStringNullGuard(s) ((s)==nullptr ? "" : (s))
|
||||||
|
|
||||||
|
// Perform byte swapping on 16 bit values.
|
||||||
|
#define cwSwap16(x) \
|
||||||
|
(((((unsigned short)(x)) & 0x00ff) << 8) | ((((unsigned short)(x)) & 0xff00) >> 8))
|
||||||
|
|
||||||
|
#ifdef OS_LINUX
|
||||||
|
#include <byteswap.h> // gcc specific
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
// Perform byte swapping on 32 bit values on systems were <byteswap.h> is available.
|
||||||
|
#define cwSwap32(x) (bswap_32(x))
|
||||||
|
|
||||||
|
// Perform byte swapping on 64 bit values on systems were <byteswap.h> is available.
|
||||||
|
#define cwSwap64(x) (bswap_64(x))
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef OS_OSX
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
// Perform byte swapping on 32 bit values on systems were <byteswap.h> is not available.
|
||||||
|
#define cwSwap32(x) \
|
||||||
|
((((unsigned)((x) & 0x000000FF)) << 24) | \
|
||||||
|
(((unsigned)((x) & 0x0000FF00)) << 8) | \
|
||||||
|
(((unsigned)((x) & 0x00FF0000)) >> 8) | \
|
||||||
|
(((unsigned)((x) & 0xFF000000)) >> 24))
|
||||||
|
|
||||||
|
// Perform byte swapping on 64 bit values on systems were <byteswap.h> is not available.
|
||||||
|
#define cwSwap64(x) \
|
||||||
|
(((((unsigned long long)(x))<<56) & 0xFF00000000000000ULL) | \
|
||||||
|
((((unsigned long long)(x))<<40) & 0x00FF000000000000ULL) | \
|
||||||
|
((((unsigned long long)(x))<<24) & 0x0000FF0000000000ULL) | \
|
||||||
|
((((unsigned long long)(x))<< 8) & 0x000000FF00000000ULL) | \
|
||||||
|
((((unsigned long long)(x))>> 8) & 0x00000000FF000000ULL) | \
|
||||||
|
((((unsigned long long)(x))>>24) & 0x0000000000FF0000ULL) | \
|
||||||
|
((((unsigned long long)(x))>>40) & 0x000000000000FF00ULL) | \
|
||||||
|
((((unsigned long long)(x))>>56) & 0x00000000000000FFULL))
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define cwAllFlags(f,m) (((f) & (m)) == (m)) // Test if all of a group 'm' of binary flags in 'f' are set.
|
#define cwAllFlags(f,m) (((f) & (m)) == (m)) // Test if all of a group 'm' of binary flags in 'f' are set.
|
||||||
#define cwIsFlag(f,m) (((f) & (m)) ? true : false) // Test if any one of a the bits in 'm' is also set in 'f'.
|
#define cwIsFlag(f,m) (((f) & (m)) ? true : false) // Test if any one of a the bits in 'm' is also set in 'f'.
|
||||||
@ -45,6 +86,9 @@
|
|||||||
|
|
||||||
#define cwCountOf(a) (sizeof(a)/sizeof(a[0]))
|
#define cwCountOf(a) (sizeof(a)/sizeof(a[0]))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Taken from here:
|
// Taken from here:
|
||||||
// https://groups.google.com/forum/#!topic/comp.std.c/d-6Mj5Lko_s
|
// https://groups.google.com/forum/#!topic/comp.std.c/d-6Mj5Lko_s
|
||||||
// and here:
|
// and here:
|
||||||
@ -93,6 +137,23 @@ namespace cw
|
|||||||
#define cwAssert(cond) while(1){ if(!(cond)){ cwLogFatal(kAssertFailRC,"Assert failed on condition:%s",#cond ); } break; }
|
#define cwAssert(cond) while(1){ if(!(cond)){ cwLogFatal(kAssertFailRC,"Assert failed on condition:%s",#cond ); } break; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template< typename T>
|
||||||
|
bool is_int(const T& x)
|
||||||
|
{ return false; }
|
||||||
|
|
||||||
|
template<> inline bool is_int<signed char>( const signed char& x ) { return true; }
|
||||||
|
template<> inline bool is_int<unsigned char>( const unsigned char& x ) { return true; }
|
||||||
|
template<> inline bool is_int<signed short>( const signed short& x ) { return true; }
|
||||||
|
template<> inline bool is_int<unsigned short>( const unsigned short& x ) { return true; }
|
||||||
|
template<> inline bool is_int<signed long>( const signed long& x ) { return true; }
|
||||||
|
template<> inline bool is_int<unsigned long>( const unsigned long& x ) { return true; }
|
||||||
|
template<> inline bool is_int<signed long long>( const signed long long& x ) { return true; }
|
||||||
|
template<> inline bool is_int<unsigned long long>( const unsigned long long& x ) { return true; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template< typename H, typename T >
|
template< typename H, typename T >
|
||||||
T* handleToPtr( H h )
|
T* handleToPtr( H h )
|
||||||
{
|
{
|
||||||
|
@ -656,3 +656,10 @@ cw::filesys::dirEntry_t* cw::filesys::dirEntries( const char* dirStr, unsigned f
|
|||||||
return r.rp;
|
return r.rp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::filesys::makeDir( const char* dirStr )
|
||||||
|
{
|
||||||
|
if( mkdir(dirStr, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0 )
|
||||||
|
return cwLogSysError( kOpFailRC, errno, "The attempt to create the directory '%s' failed.",dirStr);
|
||||||
|
|
||||||
|
return kOkRC;
|
||||||
|
}
|
||||||
|
@ -25,6 +25,7 @@ namespace cw
|
|||||||
char* makeFn( const char* dir, const char* fn, const char* ext, ... );
|
char* makeFn( const char* dir, const char* fn, const char* ext, ... );
|
||||||
|
|
||||||
|
|
||||||
|
// The returned string must be released by a call to mem::release() or mem::free().
|
||||||
char* expandPath( const char* dir );
|
char* expandPath( const char* dir );
|
||||||
|
|
||||||
|
|
||||||
@ -75,6 +76,8 @@ namespace cw
|
|||||||
dirEntry_t* dirEntries( const char* dirStr, unsigned includeFlags, unsigned* dirEntryCntRef );
|
dirEntry_t* dirEntries( const char* dirStr, unsigned includeFlags, unsigned* dirEntryCntRef );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
rc_t makeDir( const char* dirStr );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
16
cwLog.cpp
16
cwLog.cpp
@ -22,6 +22,7 @@ namespace cw
|
|||||||
|
|
||||||
idLabelPair_t logLevelLabelArray[] =
|
idLabelPair_t logLevelLabelArray[] =
|
||||||
{
|
{
|
||||||
|
{ kPrint_LogLevel, "" },
|
||||||
{ kDebug_LogLevel, "debug" },
|
{ kDebug_LogLevel, "debug" },
|
||||||
{ kInfo_LogLevel, "info" },
|
{ kInfo_LogLevel, "info" },
|
||||||
{ kWarning_LogLevel, "warning" },
|
{ kWarning_LogLevel, "warning" },
|
||||||
@ -168,6 +169,18 @@ void cw::log::defaultFormatter( void* cbArg, logOutputCbFunc_t outFunc, void* ou
|
|||||||
if( level < kWarning_LogLevel )
|
if( level < kWarning_LogLevel )
|
||||||
rcStr = "";
|
rcStr = "";
|
||||||
|
|
||||||
|
if( level == kPrint_LogLevel )
|
||||||
|
{
|
||||||
|
const char* fmt = "%s";
|
||||||
|
int n = snprintf(nullptr,0,fmt,msg);
|
||||||
|
cwAssert(n != -1);
|
||||||
|
char s[n+1];
|
||||||
|
int m = snprintf(s,n+1,fmt,msg);
|
||||||
|
cwAssert(m==n);
|
||||||
|
outFunc(outCbArg,level,s);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// levelStr, msg,sys_msg, rc, function, lineno, filename
|
// levelStr, msg,sys_msg, rc, function, lineno, filename
|
||||||
const char* fmt = "%s: %s %s %s %s\n";
|
const char* fmt = "%s: %s %s %s %s\n";
|
||||||
|
|
||||||
@ -176,10 +189,11 @@ void cw::log::defaultFormatter( void* cbArg, logOutputCbFunc_t outFunc, void* ou
|
|||||||
char s[n+1];
|
char s[n+1];
|
||||||
int m = snprintf(s,n+1,fmt,levelStr,msg,syStr,rcStr,loStr);
|
int m = snprintf(s,n+1,fmt,levelStr,msg,syStr,rcStr,loStr);
|
||||||
cwAssert(m==n);
|
cwAssert(m==n);
|
||||||
|
|
||||||
outFunc(outCbArg,level,s);
|
outFunc(outCbArg,level,s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
cw::rc_t cw::log::createGlobal( unsigned level, logOutputCbFunc_t outCb, void* outCbArg, logFormatCbFunc_t fmtCb, void* fmtCbArg )
|
cw::rc_t cw::log::createGlobal( unsigned level, logOutputCbFunc_t outCb, void* outCbArg, logFormatCbFunc_t fmtCb, void* fmtCbArg )
|
||||||
{
|
{
|
||||||
|
6
cwLog.h
6
cwLog.h
@ -9,6 +9,7 @@ namespace cw
|
|||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
kInvalid_LogLevel,
|
kInvalid_LogLevel,
|
||||||
|
kPrint_LogLevel,
|
||||||
kDebug_LogLevel,
|
kDebug_LogLevel,
|
||||||
kInfo_LogLevel,
|
kInfo_LogLevel,
|
||||||
kWarning_LogLevel,
|
kWarning_LogLevel,
|
||||||
@ -50,6 +51,9 @@ namespace cw
|
|||||||
#define cwLogVDebugH(h,rc,fmt, vl) cw::log::msg( h, cw::log::kDebug_LogLevel, __FUNCTION__, __FILE__, __LINE__, 0, rc, fmt, vl )
|
#define cwLogVDebugH(h,rc,fmt, vl) cw::log::msg( h, cw::log::kDebug_LogLevel, __FUNCTION__, __FILE__, __LINE__, 0, rc, fmt, vl )
|
||||||
#define cwLogDebugH( h,rc,fmt,...) cw::log::msg( h, cw::log::kDebug_LogLevel, __FUNCTION__, __FILE__, __LINE__, 0, rc, fmt, ##__VA_ARGS__ )
|
#define cwLogDebugH( h,rc,fmt,...) cw::log::msg( h, cw::log::kDebug_LogLevel, __FUNCTION__, __FILE__, __LINE__, 0, rc, fmt, ##__VA_ARGS__ )
|
||||||
|
|
||||||
|
#define cwLogVPrintH(h,fmt, vl) cw::log::msg( h, cw::log::kPrint_LogLevel, __FUNCTION__, __FILE__, __LINE__, 0, cw::kOkRC, fmt, vl )
|
||||||
|
#define cwLogPrintH( h,fmt,...) cw::log::msg( h, cw::log::kPrint_LogLevel, __FUNCTION__, __FILE__, __LINE__, 0, cw::kOkRC, fmt, ##__VA_ARGS__ )
|
||||||
|
|
||||||
#define cwLogVInfoH(h,fmt, vl) cw::log::msg( h, cw::log::kInfo_LogLevel, __FUNCTION__, __FILE__, __LINE__, 0, cw::kOkRC, fmt, vl )
|
#define cwLogVInfoH(h,fmt, vl) cw::log::msg( h, cw::log::kInfo_LogLevel, __FUNCTION__, __FILE__, __LINE__, 0, cw::kOkRC, fmt, vl )
|
||||||
#define cwLogInfoH( h,fmt,...) cw::log::msg( h, cw::log::kInfo_LogLevel, __FUNCTION__, __FILE__, __LINE__, 0, cw::kOkRC, fmt, ##__VA_ARGS__ )
|
#define cwLogInfoH( h,fmt,...) cw::log::msg( h, cw::log::kInfo_LogLevel, __FUNCTION__, __FILE__, __LINE__, 0, cw::kOkRC, fmt, ##__VA_ARGS__ )
|
||||||
|
|
||||||
@ -83,6 +87,8 @@ namespace cw
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define cwLogVPrint(fmt, vl) cwLogVPrintH( cw::log::globalHandle(), (fmt), (vl) )
|
||||||
|
#define cwLogPrint( fmt,...) cwLogPrintH( cw::log::globalHandle(), (fmt), ##__VA_ARGS__ )
|
||||||
|
|
||||||
#define cwLogVInfo(fmt, vl) cwLogVInfoH( cw::log::globalHandle(), (fmt), (vl) )
|
#define cwLogVInfo(fmt, vl) cwLogVInfoH( cw::log::globalHandle(), (fmt), (vl) )
|
||||||
#define cwLogInfo( fmt,...) cwLogInfoH( cw::log::globalHandle(), (fmt), ##__VA_ARGS__ )
|
#define cwLogInfo( fmt,...) cwLogInfoH( cw::log::globalHandle(), (fmt), ##__VA_ARGS__ )
|
||||||
|
329
cwMtx.h
329
cwMtx.h
@ -1,6 +1,28 @@
|
|||||||
#ifndef cwMtx_h
|
#ifndef cwMtx_h
|
||||||
#define cwMtx_h
|
#define cwMtx_h
|
||||||
|
|
||||||
|
/*
|
||||||
|
Memory Layout:
|
||||||
|
|
||||||
|
3x2 mtx:
|
||||||
|
|
||||||
|
0 3
|
||||||
|
1 4
|
||||||
|
2 5
|
||||||
|
|
||||||
|
3x2x2 mtx
|
||||||
|
|
||||||
|
front back
|
||||||
|
0 3 | 6 9
|
||||||
|
1 4 | 7 10
|
||||||
|
2 5 | 8 11
|
||||||
|
|
||||||
|
|
||||||
|
More about dope and weight vectors.
|
||||||
|
https://stackoverflow.com/questions/30409991/use-a-dope-vector-to-access-arbitrary-axial-slices-of-a-multidimensional-array
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
namespace cw
|
namespace cw
|
||||||
{
|
{
|
||||||
namespace mtx
|
namespace mtx
|
||||||
@ -19,22 +41,31 @@ namespace cw
|
|||||||
unsigned flags = 0;
|
unsigned flags = 0;
|
||||||
unsigned dimN = 0;
|
unsigned dimN = 0;
|
||||||
unsigned* dimV = nullptr;
|
unsigned* dimV = nullptr;
|
||||||
|
unsigned* mulV = nullptr;
|
||||||
T* base = nullptr;
|
T* base = nullptr;
|
||||||
unsigned allocEleN = 0; // always 0 if data is aliased
|
unsigned allocEleN = 0; // always 0 if data is aliased
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
void release( struct mtx_str<T>& m )
|
||||||
|
{
|
||||||
|
mem::release(m.dimV);
|
||||||
|
if( cwIsNotFlag(m.flags,kAliasNoReleaseFl) )
|
||||||
|
mem::release(m.base);
|
||||||
|
}
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
void release( struct mtx_str<T>*& m )
|
void release( struct mtx_str<T>*& m )
|
||||||
{
|
{
|
||||||
if( m != nullptr )
|
if( m != nullptr )
|
||||||
{
|
{
|
||||||
mem::release(m->dimV);
|
release(*m);
|
||||||
if( cwIsNotFlag(m->flags,kAliasNoReleaseFl) )
|
|
||||||
mem::release(m->base);
|
|
||||||
mem::release(m);
|
mem::release(m);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note that dimV[] is always copied and therefore is the reponsibility of the caller to free.
|
||||||
template< typename T >
|
template< typename T >
|
||||||
struct mtx_str<T>* _init( struct mtx_str<T>* m, unsigned dimN, const unsigned* dimV, T* base=nullptr, unsigned flags=0 )
|
struct mtx_str<T>* _init( struct mtx_str<T>* m, unsigned dimN, const unsigned* dimV, T* base=nullptr, unsigned flags=0 )
|
||||||
{
|
{
|
||||||
@ -42,20 +73,24 @@ namespace cw
|
|||||||
if( m == nullptr )
|
if( m == nullptr )
|
||||||
m = mem::allocZ<mtx_str<T>>(1);
|
m = mem::allocZ<mtx_str<T>>(1);
|
||||||
|
|
||||||
// if the pre-allocd mtx obj has more dim's then the new one
|
// if the pre-allocd mtx obj has more dim's than the new one
|
||||||
if( m->dimN >= dimN )
|
if( m->dimN >= dimN )
|
||||||
m->dimN = dimN;
|
m->dimN = dimN;
|
||||||
else // else expand dimV[]
|
else // else expand dimV[]
|
||||||
{
|
{
|
||||||
m->dimV = mem::resize<unsigned>(m->dimV,dimN);
|
m->dimV = mem::resize<unsigned>(m->dimV,dimN*2);
|
||||||
|
m->mulV = m->dimV + dimN;
|
||||||
m->dimN = dimN;
|
m->dimN = dimN;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update dimV[] with the new extents and calc. the new ele count
|
// update dimV[] with the new extents and calc. the new ele count
|
||||||
unsigned eleN = 0;
|
unsigned eleN = 0;
|
||||||
|
unsigned mul = 1;
|
||||||
for(unsigned i=0; i<dimN; ++i)
|
for(unsigned i=0; i<dimN; ++i)
|
||||||
{
|
{
|
||||||
m->dimV[i] = dimV[i];
|
m->dimV[i] = dimV[i];
|
||||||
|
m->mulV[i] = mul;
|
||||||
|
mul *= dimV[i];
|
||||||
eleN = (i==0 ? 1 : eleN) * dimV[i];
|
eleN = (i==0 ? 1 : eleN) * dimV[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,6 +159,86 @@ namespace cw
|
|||||||
{ return _init<T>( nullptr, dimN, dimV, const_cast<T*>(base), kAliasNoReleaseFl); }
|
{ return _init<T>( nullptr, dimN, dimV, const_cast<T*>(base), kAliasNoReleaseFl); }
|
||||||
|
|
||||||
|
|
||||||
|
unsigned _offsetDimV( const unsigned* dimV, unsigned dimN, unsigned* idxV );
|
||||||
|
unsigned _offsetMulV( const unsigned* dimV, unsigned dimN, unsigned* idxV );
|
||||||
|
unsigned _mtx_object_get_degree( const struct object_str* cfg );
|
||||||
|
rc_t _mtx_object_get_shape( const struct object_str* cfg, unsigned i, unsigned* dimV, unsigned dimN, unsigned& eleN );
|
||||||
|
|
||||||
|
// 'i' is the index into 'idxV[]' of the matrix dimension which 'cfg' refers to
|
||||||
|
template< typename T>
|
||||||
|
rc_t _get_mtx_eles_from_cfg( const struct object_str* cfg, struct mtx_str<T>* m, unsigned i, unsigned* idxV )
|
||||||
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
|
// if cfg is not a list then this must be a value
|
||||||
|
if( !cfg->is_list() )
|
||||||
|
{
|
||||||
|
// get the value
|
||||||
|
T v;
|
||||||
|
if(cfg->value(v) != kOkRC )
|
||||||
|
return cwLogError(kSyntaxErrorRC,"Unable to obtain matrix value in dimension index: %i\n",i);
|
||||||
|
|
||||||
|
// and store it in the current idxV[] location
|
||||||
|
m->base[ _offsetMulV(m->mulV,m->dimN,idxV) ] = v;
|
||||||
|
|
||||||
|
return kOkRC;
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise this is a list - and the list must contain lists or values
|
||||||
|
for(unsigned j=0; j<cfg->child_count(); ++j)
|
||||||
|
{
|
||||||
|
// update idxV[] which the dimension of the ith child elment
|
||||||
|
idxV[i] = j;
|
||||||
|
|
||||||
|
// recurse!
|
||||||
|
if((rc = _get_mtx_eles_from_cfg(cfg->child_ele(j) ,m, i+1, idxV)) != kOkRC )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
struct mtx_str<T>* allocCfg( const struct object_str* cfg )
|
||||||
|
{
|
||||||
|
unsigned dimN = 0;
|
||||||
|
|
||||||
|
// get the degree of the matrix
|
||||||
|
dimN = _mtx_object_get_degree(cfg);
|
||||||
|
|
||||||
|
// if 'cfg' does not refer to a matrix
|
||||||
|
if( dimN == 0 )
|
||||||
|
{
|
||||||
|
cwLogError(kSyntaxErrorRC,"The matrix object does not have a list-list syntax.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// allocate the shape vector
|
||||||
|
unsigned dimV[dimN];
|
||||||
|
unsigned idxV[dimN];
|
||||||
|
unsigned eleN = 0;
|
||||||
|
struct mtx_str<T>* m = nullptr;
|
||||||
|
|
||||||
|
// get the shape of the matrix
|
||||||
|
if( _mtx_object_get_shape(cfg,0,dimV,dimN,eleN) != kOkRC )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// allocate the matrix
|
||||||
|
if((m = alloc<T>(dimN,dimV)) == nullptr )
|
||||||
|
cwLogError(kObjAllocFailRC,"A matrix allocation failed.");
|
||||||
|
else
|
||||||
|
//
|
||||||
|
if(_get_mtx_eles_from_cfg<T>(cfg,m,0,idxV) == kOkRC )
|
||||||
|
return m;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template< typename T >
|
template< typename T >
|
||||||
struct mtx_str<T>* alloc( unsigned dimN, const unsigned* dimV, T* base=nullptr, unsigned flags=0 )
|
struct mtx_str<T>* alloc( unsigned dimN, const unsigned* dimV, T* base=nullptr, unsigned flags=0 )
|
||||||
{ return _init<T>( nullptr, dimN, dimV, base, flags); }
|
{ return _init<T>( nullptr, dimN, dimV, base, flags); }
|
||||||
@ -139,6 +254,63 @@ namespace cw
|
|||||||
struct mtx_str<T>* resize( struct mtx_str<T>* y, const struct mtx_str<T>& x )
|
struct mtx_str<T>* resize( struct mtx_str<T>* y, const struct mtx_str<T>& x )
|
||||||
{ return resize(y,x->dimV,x->dimN); }
|
{ return resize(y,x->dimV,x->dimN); }
|
||||||
|
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
unsigned offset( const struct mtx_str<T>* m, const unsigned* idxV )
|
||||||
|
{
|
||||||
|
unsigned offset = 0;
|
||||||
|
for(unsigned i=0; i<m->dimN; ++i)
|
||||||
|
offset += idxV[i] * m->mulV[i];
|
||||||
|
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
unsigned _offset( const struct mtx_str<T>* m, int i, unsigned offs )
|
||||||
|
{ return offs; }
|
||||||
|
|
||||||
|
template< typename T, typename... ARGS>
|
||||||
|
unsigned _offset( const struct mtx_str<T>* m, int i, unsigned offs, unsigned idx, ARGS&&... args)
|
||||||
|
{ return _offset(m,i+1, offs + idx*m->mulV[i], std::forward<ARGS>(args)...); }
|
||||||
|
|
||||||
|
template< typename T, typename... ARGS>
|
||||||
|
unsigned offset( const struct mtx_str<T>* m, unsigned idx, ARGS&&... args)
|
||||||
|
{ return _offset(m,0,0,idx,std::forward<ARGS>(args)...); }
|
||||||
|
|
||||||
|
template< typename T, typename... ARGS>
|
||||||
|
unsigned offset( const struct mtx_str<T>& m, unsigned idx, ARGS&&... args)
|
||||||
|
{ return _offset(&m,0,0,idx,std::forward<ARGS>(args)...); }
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
T* addr( const struct mtx_str<T>* m, const unsigned* idxV )
|
||||||
|
{ return m->base + offset(m,idxV); }
|
||||||
|
|
||||||
|
template< typename T, typename... ARGS>
|
||||||
|
T* addr( struct mtx_str<T>* m, unsigned i, ARGS&&... args)
|
||||||
|
{ return m->base + offset(m,i,std::forward<ARGS>(args)...); }
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
T& ele( const struct mtx_str<T>* m, const unsigned* idxV )
|
||||||
|
{ return *addr(m,idxV); }
|
||||||
|
|
||||||
|
template< typename T, typename... ARGS>
|
||||||
|
T& ele( struct mtx_str<T>* m, unsigned i, ARGS&&... args)
|
||||||
|
{ return *addr(m,i,std::forward<ARGS>(args)...); }
|
||||||
|
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
bool is_col_vector( const struct mtx_str<T>& m )
|
||||||
|
{ return m->dimN==1 || (m->dimN==2 && m->dimV[1]==1); };
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
bool is_row_vector( const struct mtx_str<T>& m )
|
||||||
|
{ return m->dimN==2 && m->dimV[0]==1; }
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
bool is_vector( const struct mtx_str<T>& m )
|
||||||
|
{ return is_col_vector(m) || is_row_vector(m); }
|
||||||
|
|
||||||
// Return 'true' if the matrices have the same size.
|
// Return 'true' if the matrices have the same size.
|
||||||
template< typename T >
|
template< typename T >
|
||||||
bool is_size_equal( const struct mtx_str<T>& x0, const struct mtx_str<T>& x1 )
|
bool is_size_equal( const struct mtx_str<T>& x0, const struct mtx_str<T>& x1 )
|
||||||
@ -146,23 +318,113 @@ namespace cw
|
|||||||
if( x0.dimN != x1.dimN )
|
if( x0.dimN != x1.dimN )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for(unsigned i=0; i<x0->dimN; ++i)
|
for(unsigned i=0; i<x0.dimN; ++i)
|
||||||
if( x0.dimV[i] != x1.dimV[i] )
|
if( x0.dimV[i] != x1.dimV[i] )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
bool is_equal( const struct mtx_str<T>& x0, const struct mtx_str<T>& x1 )
|
||||||
|
{
|
||||||
|
if( !is_size_equal(x0,x1) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
unsigned N = ele_count(x0);
|
||||||
|
for(unsigned i=0; i<N; ++i)
|
||||||
|
if( x0.base[i] != x1.base[i] )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Return the count of elements in the matrix
|
// Return the count of elements in the matrix
|
||||||
template< typename T >
|
template< typename T >
|
||||||
bool ele_count( const struct mtx_str<T>& x )
|
unsigned ele_count( const struct mtx_str<T>& x )
|
||||||
{
|
{
|
||||||
unsigned eleN = 1;
|
unsigned eleN = 1;
|
||||||
for(unsigned i=0; i<eleN; ++i)
|
for(unsigned i=0; i<x.dimN; ++i)
|
||||||
eleN *= x.dimV[i];
|
eleN *= x.dimV[i];
|
||||||
return eleN;
|
return eleN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
void transpose( struct mtx_str<T>& m )
|
||||||
|
{
|
||||||
|
for(unsigned i=0; i<m.dimN/2; ++i)
|
||||||
|
{
|
||||||
|
unsigned x = m.mulV[i];
|
||||||
|
m.mulV[i] = m.mulV[ m.dimN-(i+1) ];
|
||||||
|
m.mulV[ m.dimN-(i+1) ] = x;
|
||||||
|
|
||||||
|
x = m.dimV[i];
|
||||||
|
m.dimV[i] = m.dimV[ m.dimN-(i+1) ];
|
||||||
|
m.dimV[m.dimN-(i+1)] = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
void _print( const struct mtx_str<T>& m, unsigned* idxV, unsigned i, unsigned decPl, unsigned colWidth )
|
||||||
|
{
|
||||||
|
if( i == m.dimN )
|
||||||
|
{
|
||||||
|
double v = ele( &m, idxV );
|
||||||
|
|
||||||
|
// print the value
|
||||||
|
printf("%*.*f ",colWidth,decPl,v);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(unsigned j=0; j<m.dimV[i]; ++j)
|
||||||
|
{
|
||||||
|
if( m.dimN>=2 && i == m.dimN-2 )
|
||||||
|
{
|
||||||
|
// print the dimension index for matrices with 3+ dim's
|
||||||
|
if( i > 0 && j == 0 )
|
||||||
|
printf("%i\n",idxV[i-1]);
|
||||||
|
|
||||||
|
// print the row index for matrices with 2+ dim's
|
||||||
|
if( m.dimN>1 )
|
||||||
|
printf("%i | ",j);
|
||||||
|
}
|
||||||
|
|
||||||
|
idxV[i] = j;
|
||||||
|
_print(m, idxV, i+1, decPl, colWidth );
|
||||||
|
}
|
||||||
|
|
||||||
|
// prevent multiple newlines on last printed line
|
||||||
|
if( m.dimN==1 || (m.dimN>=2 && i > m.dimN-2) )
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
void print( const struct mtx_str<T>& m, unsigned decPl=3, unsigned colWidth=10 )
|
||||||
|
{
|
||||||
|
unsigned idxV[ m.dimN ];
|
||||||
|
memset(idxV,0,sizeof(idxV));
|
||||||
|
|
||||||
|
if( is_int<T>(*m.base) )
|
||||||
|
decPl = 0;
|
||||||
|
|
||||||
|
_print( m, idxV, 0, decPl, colWidth );
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
void report( const struct mtx_str<T>& m, const char* label, unsigned decPl=3, unsigned colWidth=10 )
|
||||||
|
{
|
||||||
|
printf("%s :",label);
|
||||||
|
for(unsigned i=0; i<m.dimN; ++i)
|
||||||
|
printf("%i ", m.dimV[i] );
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
print(m,decPl,colWidth);
|
||||||
|
}
|
||||||
|
|
||||||
// y = m * x (elementwise)
|
// y = m * x (elementwise)
|
||||||
template< typename T >
|
template< typename T >
|
||||||
void mult( struct mtx_str<T>& y, const struct mtx_str<T>& x0, const struct mtx_str<T>& x1 )
|
void mult( struct mtx_str<T>& y, const struct mtx_str<T>& x0, const struct mtx_str<T>& x1 )
|
||||||
@ -244,15 +506,60 @@ namespace cw
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template< typename T >
|
template< typename T0, typename T1 >
|
||||||
void mtx_mul( struct mtx_str<T>& y, const struct mtx_str<T>& m, const struct mtx_str<T>& x )
|
rc_t mtx_mul( struct mtx_str<T0>& y, const struct mtx_str<T0>& m, const struct mtx_str<T1>& x )
|
||||||
{
|
{
|
||||||
|
assert( x.dimN >= 1 && m.dimN >= 1 );
|
||||||
|
|
||||||
|
unsigned xrn = x.dimN==1 ? ele_count<T1>(x) : x.dimV[0];
|
||||||
|
unsigned xcn = x.dimN==1 ? 1 : x.dimV[1];
|
||||||
|
unsigned mrn = m.dimN==1 ? 1 : m.dimV[0];
|
||||||
|
unsigned mcn = m.dimN==1 ? ele_count<T0>(m) : m.dimV[1];
|
||||||
|
unsigned yDimV[] = { mrn, xcn };
|
||||||
|
if( mcn != xrn )
|
||||||
|
return cwLogError(kInvalidArgRC, "Mtx mult. failed. Size mismatch: m[%i,%i] x[%i,%i].",mrn,mcn,xrn,xcn);
|
||||||
|
|
||||||
|
//printf("%i %i : %i %i\n",mrn,mcn,xrn,xcn);
|
||||||
|
|
||||||
|
resize(&y,yDimV, 2 );
|
||||||
|
|
||||||
|
// go across the columns of x
|
||||||
|
for(unsigned i=0; i<xcn; ++i)
|
||||||
|
{
|
||||||
|
// go down the rows of m[]
|
||||||
|
for(unsigned j=0; j<mrn; ++j)
|
||||||
|
{
|
||||||
|
// calc the first memory offset for each mtx
|
||||||
|
unsigned yi = offset(y,j,i);
|
||||||
|
unsigned mi = offset(m,j,0);
|
||||||
|
unsigned xi = offset(x,0,i);
|
||||||
|
|
||||||
|
// calc increment for each offset by calc'ing
|
||||||
|
// the second offset and subtracting the first
|
||||||
|
unsigned dxi = offset(x,1,i) - xi;
|
||||||
|
unsigned dmi = offset(m,j,1) - mi;
|
||||||
|
|
||||||
|
// calc stopping point
|
||||||
|
unsigned mN = mi + (mcn*dmi);
|
||||||
|
|
||||||
|
y.base[ yi ] = 0;
|
||||||
|
|
||||||
|
// go down the rows of x[] and across the columns of m[]
|
||||||
|
for(; mi<mN; mi+=dmi,xi+=dxi)
|
||||||
|
y.base[ yi ] += m.base[ mi ] * x.base[ xi ];
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return kOkRC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct mtx_str<float> fmtx_t;
|
typedef struct mtx_str<float> f_t;
|
||||||
|
typedef struct mtx_str<double> d_t;
|
||||||
|
|
||||||
|
rc_t test( const struct object_str* cfg );
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -131,6 +131,7 @@ namespace cw
|
|||||||
rc_t value( bool& v ) const;
|
rc_t value( bool& v ) const;
|
||||||
rc_t value( char*& v ) const;
|
rc_t value( char*& v ) const;
|
||||||
rc_t value( const char*& v ) const;
|
rc_t value( const char*& v ) const;
|
||||||
|
rc_t value( const struct object_str*& v) const {v=this; return kOkRC; }
|
||||||
|
|
||||||
const char* pair_label() const;
|
const char* pair_label() const;
|
||||||
|
|
||||||
@ -143,6 +144,10 @@ namespace cw
|
|||||||
const struct object_str* find( const char* label, unsigned flags=0 ) const;
|
const struct object_str* find( const char* label, unsigned flags=0 ) const;
|
||||||
struct object_str* find( const char* label, unsigned flags=0 );
|
struct object_str* find( const char* label, unsigned flags=0 );
|
||||||
|
|
||||||
|
const struct object_str* find_child( const char* label ) const { return find(label,kNoRecurseFl); }
|
||||||
|
struct object_str* find_child( const char* label ) { return find(label,kNoRecurseFl); }
|
||||||
|
|
||||||
|
|
||||||
const struct object_str* child_ele( unsigned idx ) const;
|
const struct object_str* child_ele( unsigned idx ) const;
|
||||||
struct object_str* child_ele( unsigned idx );
|
struct object_str* child_ele( unsigned idx );
|
||||||
|
|
||||||
@ -221,6 +226,7 @@ namespace cw
|
|||||||
rc_t objectFromFile( const char* fn, object_t*& objRef );
|
rc_t objectFromFile( const char* fn, object_t*& objRef );
|
||||||
void objectPrintTypes( object_t* o );
|
void objectPrintTypes( object_t* o );
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -35,3 +35,89 @@ void cw::printHex( const void* buf, unsigned bufByteN, bool asciiFl )
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: rewrite to avoid copying
|
||||||
|
// this code comes via csound source ...
|
||||||
|
double cw::x80ToDouble( unsigned char rate[10] )
|
||||||
|
{
|
||||||
|
char sign;
|
||||||
|
short exp = 0;
|
||||||
|
unsigned long mant1 = 0;
|
||||||
|
unsigned long mant0 = 0;
|
||||||
|
double val;
|
||||||
|
unsigned char* p = (unsigned char*)rate;
|
||||||
|
|
||||||
|
exp = *p++;
|
||||||
|
exp <<= 8;
|
||||||
|
exp |= *p++;
|
||||||
|
sign = (exp & 0x8000) ? 1 : 0;
|
||||||
|
exp &= 0x7FFF;
|
||||||
|
|
||||||
|
mant1 = *p++;
|
||||||
|
mant1 <<= 8;
|
||||||
|
mant1 |= *p++;
|
||||||
|
mant1 <<= 8;
|
||||||
|
mant1 |= *p++;
|
||||||
|
mant1 <<= 8;
|
||||||
|
mant1 |= *p++;
|
||||||
|
|
||||||
|
mant0 = *p++;
|
||||||
|
mant0 <<= 8;
|
||||||
|
mant0 |= *p++;
|
||||||
|
mant0 <<= 8;
|
||||||
|
mant0 |= *p++;
|
||||||
|
mant0 <<= 8;
|
||||||
|
mant0 |= *p++;
|
||||||
|
|
||||||
|
/* special test for all bits zero meaning zero
|
||||||
|
- else pow(2,-16383) bombs */
|
||||||
|
if (mant1 == 0 && mant0 == 0 && exp == 0 && sign == 0)
|
||||||
|
return 0.0;
|
||||||
|
else {
|
||||||
|
val = ((double)mant0) * pow(2.0,-63.0);
|
||||||
|
val += ((double)mant1) * pow(2.0,-31.0);
|
||||||
|
val *= pow(2.0,((double) exp) - 16383.0);
|
||||||
|
return sign ? -val : val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: rewrite to avoid copying
|
||||||
|
/*
|
||||||
|
* Convert double to IEEE 80 bit floating point
|
||||||
|
* Should be portable to all C compilers.
|
||||||
|
* 19aug91 aldel/dpwe covered for MSB bug in Ultrix 'cc'
|
||||||
|
*/
|
||||||
|
|
||||||
|
void cw::doubleToX80(double val, unsigned char rate[10])
|
||||||
|
{
|
||||||
|
char sign = 0;
|
||||||
|
short exp = 0;
|
||||||
|
unsigned long mant1 = 0;
|
||||||
|
unsigned long mant0 = 0;
|
||||||
|
unsigned char* p = (unsigned char*)rate;
|
||||||
|
|
||||||
|
if (val < 0.0) { sign = 1; val = -val; }
|
||||||
|
|
||||||
|
if (val != 0.0) /* val identically zero -> all elements zero */
|
||||||
|
{
|
||||||
|
exp = (short)(std::log(val)/std::log(2.0) + 16383.0);
|
||||||
|
val *= pow(2.0, 31.0+16383.0-(double)exp);
|
||||||
|
mant1 =((unsigned)val);
|
||||||
|
val -= ((double)mant1);
|
||||||
|
val *= pow(2.0, 32.0);
|
||||||
|
mant0 =((double)val);
|
||||||
|
}
|
||||||
|
|
||||||
|
*p++ = ((sign<<7)|(exp>>8));
|
||||||
|
*p++ = (u_char)(0xFF & exp);
|
||||||
|
*p++ = (u_char)(0xFF & (mant1>>24));
|
||||||
|
*p++ = (u_char)(0xFF & (mant1>>16));
|
||||||
|
*p++ = (u_char)(0xFF & (mant1>> 8));
|
||||||
|
*p++ = (u_char)(0xFF & (mant1));
|
||||||
|
*p++ = (u_char)(0xFF & (mant0>>24));
|
||||||
|
*p++ = (u_char)(0xFF & (mant0>>16));
|
||||||
|
*p++ = (u_char)(0xFF & (mant0>> 8));
|
||||||
|
*p++ = (u_char)(0xFF & (mant0));
|
||||||
|
|
||||||
|
}
|
||||||
|
@ -5,6 +5,9 @@ namespace cw
|
|||||||
{
|
{
|
||||||
void printHex( const void* buf, unsigned bufByteN, bool asciiFl=true );
|
void printHex( const void* buf, unsigned bufByteN, bool asciiFl=true );
|
||||||
|
|
||||||
|
double x80ToDouble( unsigned char s[10] );
|
||||||
|
void doubleToX80( double v, unsigned char s[10] );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user