304 lines
7.0 KiB
C
304 lines
7.0 KiB
C
/*
|
|
* wavevar.c - wavevar interface functions
|
|
*
|
|
* include LICENSE
|
|
*/
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include <wavetable.h>
|
|
#include <wavevar.h>
|
|
#include <strmem.h>
|
|
#include <util.h>
|
|
#include <duprintf.h>
|
|
|
|
#ifdef TRACE_MEM
|
|
#include <tracemem.h>
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
*** \brief Allocates memory for a new WaveVar object.
|
|
*/
|
|
|
|
WaveVar *wavevar_new( WDataSet *wds, char *varName, int type, int colno, int ncols )
|
|
{
|
|
WaveVar *wv;
|
|
|
|
wv = app_new0(WaveVar, 1);
|
|
wavevar_construct( wv, wds, varName, type, colno, ncols );
|
|
app_class_overload_destroy( (AppClass *) wv, wavevar_destroy );
|
|
return wv;
|
|
}
|
|
|
|
/** \brief Constructor for the WaveVar object. */
|
|
|
|
void wavevar_construct( WaveVar *wv, WDataSet *wds, char *varName,
|
|
int type, int colno , int ncols )
|
|
{
|
|
app_class_construct( (AppClass *) wv );
|
|
|
|
wv->wds = wds;
|
|
wv->varName = app_strdup(varName);
|
|
wv->type = type;
|
|
wv->colno = colno ;
|
|
wv->ncols = ncols ;
|
|
}
|
|
|
|
/** \brief Destructor for the WaveVar object. */
|
|
|
|
void wavevar_destroy(void *wv)
|
|
{
|
|
WaveVar *this = (WaveVar *) wv;
|
|
|
|
if (wv == NULL) {
|
|
return;
|
|
}
|
|
app_free(this->varName);
|
|
|
|
app_class_destroy( wv );
|
|
}
|
|
|
|
char *wavevar_get_name(WaveVar *wv )
|
|
{
|
|
return wv->varName;
|
|
}
|
|
|
|
int wavevar_get_type(WaveVar *wv )
|
|
{
|
|
return wv->type;
|
|
}
|
|
|
|
void wavevar_set_type(WaveVar *wv, int type )
|
|
{
|
|
wv->type = type;
|
|
}
|
|
|
|
void wavevar_set_wavetable(WaveVar *var, AppClass *wt, int tblno )
|
|
{
|
|
var->wvtable = wt;
|
|
var->tblno = tblno;
|
|
}
|
|
|
|
void wavevar_dup_name(WaveVar *wv, char *varName )
|
|
{
|
|
wv->varName = app_strdup(varName);
|
|
}
|
|
|
|
double wavevar_val_get_col_min(WaveVar *var, int col )
|
|
{
|
|
return dataset_val_get_min(var->wds, var->colno + col);
|
|
}
|
|
|
|
double wavevar_val_get_col_max(WaveVar *var, int col )
|
|
{
|
|
return dataset_val_get_max(var->wds, var->colno + col);
|
|
}
|
|
|
|
double wavevar_val_get_min(WaveVar *var )
|
|
{
|
|
return wavevar_val_get_col_min(var, 0 );
|
|
}
|
|
|
|
double wavevar_val_get_max(WaveVar *var )
|
|
{
|
|
return wavevar_val_get_col_max(var, 0);
|
|
}
|
|
|
|
/*
|
|
* get the value of ivar at row
|
|
*/
|
|
double wavevar_ivar_get(WaveVar *var, int row )
|
|
{
|
|
return dataset_val_get(var->wds, row, 0 );
|
|
}
|
|
|
|
/*
|
|
* get the value of var at row
|
|
*/
|
|
double wavevar_val_get(WaveVar *var, int row )
|
|
{
|
|
return dataset_val_get(var->wds, row, var->colno );
|
|
}
|
|
|
|
int wavevar_nrows_get(WaveVar *var)
|
|
{
|
|
return dataset_get_nrows(var->wds);
|
|
}
|
|
|
|
/*
|
|
* get the min value of the independant variable of the dataset
|
|
*/
|
|
double wavevar_ivar_get_min(WaveVar *var )
|
|
{
|
|
WaveVar *ivar= (WaveVar *) dataset_get_wavevar(var->wds, 0 );
|
|
|
|
return wavevar_val_get_col_min(ivar, 0 );
|
|
}
|
|
|
|
double wavevar_ivar_get_max(WaveVar *var )
|
|
{
|
|
WaveVar *ivar= (WaveVar *) dataset_get_wavevar(var->wds, 0 );
|
|
|
|
return wavevar_val_get_col_max(ivar, 0);
|
|
}
|
|
|
|
|
|
/*
|
|
* return the value of the dependent variable dv at the point where
|
|
* its associated independent variable has the value ival.
|
|
*
|
|
* FIXME:tell
|
|
* make this fill in an array of dependent values,
|
|
* one for each column in the specified dependent variable.
|
|
* This will be better than making the client call us once for each column,
|
|
* because we'll only have to search for the independent value once.
|
|
* (quick hack until we need support for complex and other multicolumn vars:
|
|
* just return first column's value.)
|
|
*/
|
|
double wavevar_interp_value(WaveVar *dv, double ival)
|
|
{
|
|
int li, ri; /* index of points to left and right of desired value */
|
|
double lx, rx; /* independent variable's value at li and ri */
|
|
double ly, ry; /* dependent variable's value at li and ri */
|
|
WDataSet *wds = dv->wds;
|
|
int nrows = dataset_get_nrows(wds);
|
|
|
|
if ( nrows <= 0 ) {
|
|
return 0.0;
|
|
}
|
|
|
|
li = dataset_find_row_index(wds, ival);
|
|
ri = li + 1;
|
|
if (ri >= nrows ) {
|
|
return dataset_val_get(wds, nrows - 1, dv->colno );
|
|
}
|
|
|
|
lx = dataset_val_get(wds, li, 0 );
|
|
rx = dataset_val_get(wds, ri, 0 );
|
|
if (li > 0 && lx > ival) {
|
|
msg_error(_("assertion failed: lx <= ival for %s: ival=%g li=%d lx=%g"),
|
|
dv->varName, ival, li, lx);
|
|
}
|
|
|
|
ly = dataset_val_get(wds, li, dv->colno );
|
|
ry = dataset_val_get(wds, ri, dv->colno );
|
|
|
|
if (ival > rx ) { /* no extrapolation allowed! */
|
|
return ry;
|
|
}
|
|
|
|
//double val = ly + (ry - ly) * ((ival - lx)/(rx - lx));
|
|
//fprintf(stderr, "ival = %f, li = %d ri = %d, lx = %g, rx = %g, ly = %g, ry = %g, val = %g\n",
|
|
// ival, li, ri, lx, rx, ly, ry, val);
|
|
return ly + (ry - ly) * ((ival - lx) / (rx - lx));
|
|
}
|
|
|
|
/*
|
|
* map npoints data to 1 point pixel
|
|
*/
|
|
double wavevar_maxof_value(WaveVar *dv, double ival, int npoints)
|
|
{
|
|
WDataSet *wds = dv->wds;
|
|
int i;
|
|
double val;
|
|
double yval0 = G_MAXDOUBLE;
|
|
double yval1 = -G_MAXDOUBLE;
|
|
int ri; /* index of points to left and right of desired value */
|
|
int nrows = dataset_get_nrows(wds);
|
|
|
|
if ( nrows <= 0 ) {
|
|
return 0.0;
|
|
}
|
|
|
|
ri = dataset_find_row_index(wds, ival);
|
|
val = dataset_val_get(wds, ri, 0 );
|
|
if (ival != val ) {
|
|
ri++;
|
|
}
|
|
|
|
// fprintf(stderr, "ri %d, ival = %f val %f\n", ri, ival, val);
|
|
|
|
for ( i = 0 ; i < npoints ; i++ ) {
|
|
if (ri >= nrows ) {
|
|
ri = nrows - 1;
|
|
}
|
|
val = dataset_val_get(wds, ri, dv->colno );
|
|
yval0 = MIN( yval0, val);
|
|
yval1 = MAX( yval1, val);
|
|
// fprintf(stderr, "ri %d, val = %f, yval = %g\n", ri, val, yval);
|
|
ri++;
|
|
}
|
|
// fprintf(stderr, "\n");
|
|
val = yval1;
|
|
if ( yval0 == yval1 ) {
|
|
val = yval0;
|
|
} else if ( yval0 < dv->prev_y2 ) {
|
|
val = yval0;
|
|
}
|
|
dv->prev_y2 = dv->prev_y1;
|
|
dv->prev_y1 = val;
|
|
return val;
|
|
}
|
|
|
|
double wavevar_get_yvalue(WaveVar *dv, double ival, int npoints)
|
|
{
|
|
if ( npoints < 3 ){
|
|
return wavevar_interp_value( dv, ival);
|
|
} else {
|
|
return wavevar_maxof_value( dv, ival, npoints);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* create buuton label
|
|
* if tag < 0 , we are in a list window, do not indicate file tag.
|
|
*/
|
|
|
|
char *wavevar_get_label(WaveVar *var, int tag )
|
|
{
|
|
char buf[16];
|
|
|
|
buf[0] = 0;
|
|
if ( tag >= 0 ){
|
|
snprintf(buf, 16, "%d: ", tag );
|
|
}
|
|
if ( wavetable_is_multisweep( (WaveTable *) var->wvtable) ) {
|
|
return app_strdup_printf( "%s%s @ %s=%g", buf, var->varName,
|
|
wavetable_swvar_name_get( (WaveTable *) var->wvtable, 0),
|
|
dataset_swval_get( var->wds, 0) );
|
|
} else if ( wavetable_get_ntables ( (WaveTable *) var->wvtable) > 1 ) {
|
|
/* multitable anyway */
|
|
return app_strdup_printf( "%s%s : %d", buf, var->varName, var->tblno );
|
|
}
|
|
return app_strdup_printf( "%s%s", buf, var->varName) ;
|
|
}
|
|
/*
|
|
* convert variable type string from spice3 raw file to
|
|
* our type numbers
|
|
*/
|
|
|
|
NameValue strtype[] = {
|
|
{ "unknown", UNKNOWN },
|
|
{ "time", TIME },
|
|
{ "voltage", VOLTAGE },
|
|
{ "current", CURRENT },
|
|
{ "frequency", FREQUENCY },
|
|
};
|
|
|
|
int wavevar_str2type( char *s)
|
|
{
|
|
return uti_nv_find_in_table( s, strtype,
|
|
sizeof( strtype ) / sizeof( strtype[0] ) );
|
|
}
|
|
|
|
|
|
char *wavevar_type2str( int type)
|
|
{
|
|
return uti_nv_find_in_table_str( type, strtype ,
|
|
sizeof( strtype ) / sizeof( strtype[0] ) );
|
|
}
|
|
|
|
|