waveview/lib/dataset.c

348 lines
8.1 KiB
C

/*
* dataset.c - dataset interface functions
*
* include LICENSE
*/
#include <stdio.h>
#include <string.h>
#include <strmem.h>
#include <dataset.h>
#include <wavevar.h>
#ifdef TRACE_MEM
#include <tracemem.h>
#endif
/*
*** \brief Allocates memory for a new WDataSet object.
*/
WDataSet *dataset_new( int ncols, AppClass *wt, int tblno )
{
WDataSet *wds;
wds = app_new0(WDataSet, 1);
dataset_construct( wds, ncols, wt, tblno );
app_class_overload_destroy( (AppClass *) wds, dataset_destroy );
return wds;
}
/** \brief Constructor for the WDataSet object. */
void dataset_construct( WDataSet *wds, int ncols, AppClass *wt, int tblno )
{
app_class_construct( (AppClass *) wds );
wds->ncols = ncols;
wds->datas = g_ptr_array_new ();
wds->vars = g_ptr_array_new ();
wds->colMin = g_array_new (FALSE, FALSE, sizeof (double) );
wds->colMax = g_array_new (FALSE, FALSE, sizeof (double) );
wds->swvals = g_array_new (FALSE, FALSE, sizeof (double) );
wds->wvtable = wt;
wds->tblno = tblno;
wds->varmap = g_array_new (FALSE, FALSE, sizeof (int) );
wds->mapshift = 1;
}
/** \brief Destructor for the WDataSet object. */
void dataset_destroy(void *wds)
{
WDataSet *this = (WDataSet *) wds;
if (wds == NULL) {
return;
}
app_free(this->setname);
dataset_remove_all_vars( this);
g_ptr_array_free (this->vars, FALSE);
g_ptr_array_free (this->datas, TRUE);
g_array_free (this->colMin, TRUE);
g_array_free (this->colMax, TRUE);
g_array_free (this->swvals, TRUE);
g_array_free (this->varmap, TRUE);
app_class_destroy( wds );
}
/*
* given a col num, return the corresponding var index
*/
int dataset_map_col_to_var( WDataSet *wds, int icol )
{
int map = g_array_index (wds->varmap, int, icol );
return (map >> wds->mapshift);
}
void dataset_varmap_remap(WDataSet *wds, int ncols)
{
int shift = wds->mapshift;
int oldmap;
int i;
while ( (1 << shift) < ncols ) {
shift <<= 1;
}
for ( i = 0 ; i < wds->ncols ; i++ ) {
oldmap = g_array_index (wds->varmap, int, i );
int col = oldmap & ((1 << wds->mapshift) - 1);
int varno = oldmap >> wds->mapshift;
g_array_index (wds->varmap, int, i ) = ( varno << shift) + col;
}
wds->mapshift = shift;
}
void dataset_col_add(WDataSet *wds, int ncols)
{
int i ;
int map;
double val;
if ( (1 << wds->mapshift) < ncols ) {
dataset_varmap_remap(wds, ncols);
}
for ( i = 0 ; i < ncols ; i++ ) {
map = (wds->numVars << wds->mapshift) + i ;
g_array_append_val(wds->varmap, map ); /* at curcol */
GArray *ary = g_array_new (FALSE, FALSE, sizeof (double) );
g_ptr_array_add (wds->datas, (gpointer) ary);
val = G_MAXDOUBLE;
g_array_append_val(wds->colMin, val);
val = -G_MAXDOUBLE;
g_array_append_val(wds->colMax, val );
wds->ncols++;
}
}
void dataset_var_add(WDataSet *wds, char *varName, int type, int ncols)
{
WaveVar *var = wavevar_new(wds, varName, type, wds->ncols, ncols);
dataset_col_add(wds, ncols);
wavevar_set_wavetable(var, wds->wvtable, wds->tblno );
g_ptr_array_add (wds->vars, (gpointer) var);
wds->numVars++;
}
void dataset_col_remove(WDataSet *wds, int colno, int ncols)
{
for ( ; ncols > 0 ; ncols-- ) {
GArray *ary = g_ptr_array_index( wds->datas, colno + ncols - 1 );
g_array_remove_index ( wds->varmap, colno + ncols - 1 );
g_ptr_array_remove (wds->datas, (gpointer) ary);
g_array_free (ary, TRUE);
wds->ncols--;
}
}
/*
* if ivar != numVars - 1 we should renumber
* all the vars beeteen ivar and numVars - 1 !!!
*/
void dataset_var_remove(WDataSet *wds, int ivar)
{
WaveVar *var = g_ptr_array_index( wds->vars, ivar );
dataset_col_remove(wds, var->colno, var->ncols);
g_ptr_array_remove (wds->vars, (gpointer) var);
wavevar_destroy( var);
wds->numVars--;
}
void dataset_remove_all_vars(WDataSet *wds)
{
int nvars = wds->numVars ;
for ( ; nvars ; nvars-- ) {
dataset_var_remove(wds, nvars - 1);
}
}
void dataset_min_max_init( WDataSet *wds, int col )
{
g_array_index (wds->colMin, double, col ) = G_MAXDOUBLE;
g_array_index (wds->colMax, double, col ) = -G_MAXDOUBLE;
}
void dataset_val_set_min_max( WDataSet *wds, int col, double val )
{
double *prev = &g_array_index (wds->colMin, double, col );
if ( val < *prev ) {
g_array_index (wds->colMin, double, col ) = val;
}
prev = &g_array_index (wds->colMax, double, col );
if ( *prev < val ) {
g_array_index (wds->colMax, double, col ) = val;
}
}
double dataset_val_get_min(WDataSet *wds, int col )
{
double *min = &g_array_index (wds->colMin, double, col );
return *min;
}
double dataset_val_get_max(WDataSet *wds, int col )
{
double *max = &g_array_index (wds->colMax, double, col );
return *max;
}
/*
* add or replace val in an array
*/
void dataset_col_val_add (WDataSet *wds, int row, int col, double val)
{
GArray *ary = g_ptr_array_index( wds->datas, col );
if ( row < 0 || row >= ary->len ){
g_array_append_val(ary, val );
} else {
g_array_index (ary, double, row ) = val;
}
dataset_val_set_min_max( wds, col, val );
}
/*
* add a cell to array and set a value in a cell
* supposing ncols is set previously and
* val comes sequentially
*/
void dataset_val_add (WDataSet *wds, double val)
{
dataset_col_val_add( wds, -1, wds->curcol, val );
if ( ++wds->curcol >= wds->ncols ) {
wds->currow++; /* currow is not used */
wds->curcol = 0;
wds->nrows++;
}
}
/*
* add a sweep val to the dataset
*/
void dataset_swval_add (WDataSet *wds, double val)
{
g_array_append_val(wds->swvals, val );
wds->nswvals++;
}
double dataset_val_get(WDataSet *wds, int row, int col )
{
GArray *ary = g_ptr_array_index( wds->datas, col );
double *val = &g_array_index (ary, double, row );
return *val;
}
double dataset_swval_get(WDataSet *wds, int index )
{
double *val = &g_array_index (wds->swvals, double, index );
return *val;
}
void dataset_dup_var_name(WDataSet *wds, char *varName, int idx)
{
WaveVar *var = g_ptr_array_index( wds->vars, idx );
wavevar_dup_name(var, varName);
}
void dataset_dup_setname(WDataSet *wds, char *setname)
{
wds->setname = app_strdup(setname);
}
char *dataset_get_setname(WDataSet *wds)
{
return wds->setname;
}
int dataset_get_nrows(WDataSet *wds )
{
return wds->nrows;
}
int dataset_get_ncols(WDataSet *wds )
{
return wds->ncols;
}
AppClass *dataset_get_wavevar(WDataSet *wds, int ivar )
{
WaveVar *var = g_ptr_array_index( wds->vars, ivar );
return (AppClass *) var;
}
AppClass *dataset_get_var_for_name(WDataSet *wds, char *varName )
{
int i;
for ( i = 0 ; i < wds->numVars ; i++ ) {
WaveVar *var = (WaveVar *) dataset_get_wavevar( wds, i );
if ( app_strcmp( varName, var->varName ) == 0 ){
return (AppClass *) var;
}
}
return (AppClass *) NULL;
}
int dataset_get_wavevar_type(WDataSet *wds, int ivar )
{
WaveVar *var = (WaveVar *) dataset_get_wavevar( wds, ivar );
return wavevar_get_type( var );
}
void dataset_set_wavevar_type(WDataSet *wds, int ivar, int type )
{
WaveVar *var = (WaveVar *) dataset_get_wavevar( wds, ivar );
wavevar_set_type( var, type );
}
/*
* Use a binary search to return the index of the point
* whose value is the largest not greater than ival.
* if ival is equal or greater than the max value of the
* independent variable, return the index of the last point.
*
* Only works on independent-variables, which we require to
* be nondecreasing and have only a single column.
*
* Further, if there are duplicate values, returns the highest index
* that has the same value.
*/
int dataset_find_row_index( WDataSet *wds, double ival)
{
double cval;
int a = 0;
int b;
b = wds->nrows - 1;
double colMax = dataset_val_get_max( wds, 0 );
if (ival >= colMax) {
return b;
}
while ( a + 1 < b) {
cval = dataset_val_get( wds, (a + b) / 2, 0 ); /* row, col */
// printf(" a=%d b=%d ival=%g cval=%g\n", a, b, ival, cval);
if (ival < cval){
b = ( a + b) / 2;
} else {
a = (a + b) / 2;
}
}
return a;
}