mirror of
https://github.com/dankamongmen/notcurses.git
synced 2024-11-02 09:40:15 +00:00
plots: extract common struct #1976
This commit is contained in:
parent
16c2fff06b
commit
ba830418c7
232
src/lib/plot.c
232
src/lib/plot.c
@ -5,52 +5,57 @@
|
||||
#include <inttypes.h>
|
||||
#include "internal.h"
|
||||
|
||||
// common elements of type-parameterized plots
|
||||
typedef struct ncplot {
|
||||
ncplane* ncp;
|
||||
/* sloutcount-element circular buffer of samples. the newest one (rightmost)
|
||||
is at slots[slotstart]; they get older as you go back (and around).
|
||||
elements. slotcount is max(columns, rangex), less label room. */
|
||||
int64_t slotx; /* x value corresponding to slots[slotstart] (newest x) */
|
||||
uint64_t maxchannels;
|
||||
uint64_t minchannels;
|
||||
uint16_t legendstyle;
|
||||
bool vertical_indep; /* not yet implemented FIXME */
|
||||
const struct blitset* bset;
|
||||
char* title;
|
||||
/* requested number of slots. 0 for automatically setting the number of slots
|
||||
to span the horizontal area. if there are more slots than there are
|
||||
columns, we prefer showing more recent slots to less recent. if there are
|
||||
fewer slots than there are columns, they prefer the left side. */
|
||||
int rangex;
|
||||
/* domain minimum and maximum. if detectdomain is true, these are
|
||||
progressively enlarged/shrunk to fit the sample set. if not, samples
|
||||
outside these bounds are counted, but the displayed range covers only this. */
|
||||
int slotcount;
|
||||
int slotstart; /* index of most recently-written slot */
|
||||
bool labelaxisd; /* label dependent axis (consumes PREFIXCOLUMNS columns) */
|
||||
bool exponentiali; /* exponential independent axis */
|
||||
bool detectdomain; /* is domain detection in effect (stretch the domain)? */
|
||||
bool detectonlymax; /* domain detection applies only to max, not min */
|
||||
bool printsample; /* print the most recent sample */
|
||||
} ncplot;
|
||||
|
||||
#define MAXWIDTH 2
|
||||
#define CREATE(T, X) \
|
||||
typedef struct nc##X##plot { \
|
||||
T* slots; \
|
||||
T miny, maxy; \
|
||||
ncplane* ncp; \
|
||||
/* sloutcount-element circular buffer of samples. the newest one (rightmost) \
|
||||
is at slots[slotstart]; they get older as you go back (and around). \
|
||||
elements. slotcount is max(columns, rangex), less label room. */ \
|
||||
int64_t slotx; /* x value corresponding to slots[slotstart] (newest x) */ \
|
||||
uint64_t maxchannels; \
|
||||
uint64_t minchannels; \
|
||||
uint16_t legendstyle; \
|
||||
bool vertical_indep; /* not yet implemented FIXME */ \
|
||||
const struct blitset* bset; \
|
||||
char* title; \
|
||||
/* requested number of slots. 0 for automatically setting the number of slots \
|
||||
to span the horizontal area. if there are more slots than there are \
|
||||
columns, we prefer showing more recent slots to less recent. if there are \
|
||||
fewer slots than there are columns, they prefer the left side. */ \
|
||||
int rangex; \
|
||||
/* domain minimum and maximum. if detectdomain is true, these are \
|
||||
progressively enlarged/shrunk to fit the sample set. if not, samples \
|
||||
outside these bounds are counted, but the displayed range covers only this. */ \
|
||||
int slotcount; \
|
||||
int slotstart; /* index of most recently-written slot */ \
|
||||
bool labelaxisd; /* label dependent axis (consumes PREFIXCOLUMNS columns) */ \
|
||||
bool exponentiali; /* exponential independent axis */ \
|
||||
bool detectdomain; /* is domain detection in effect (stretch the domain)? */ \
|
||||
bool detectonlymax; /* domain detection applies only to max, not min */ \
|
||||
bool printsample; /* print the most recent sample */ \
|
||||
ncplot plot; \
|
||||
} nc##X##plot; \
|
||||
\
|
||||
int redraw_plot_##T(nc##X##plot* ncp){ \
|
||||
ncplane_erase(ncp->ncp); \
|
||||
const int scale = ncp->bset->width; \
|
||||
ncplane_erase(ncp->plot.ncp); \
|
||||
const int scale = ncp->plot.bset->width; \
|
||||
int dimy, dimx; \
|
||||
ncplane_dim_yx(ncp->ncp, &dimy, &dimx); \
|
||||
ncplane_dim_yx(ncp->plot.ncp, &dimy, &dimx); \
|
||||
const int scaleddim = dimx * scale; \
|
||||
/* each transition is worth this much change in value */ \
|
||||
const size_t states = ncp->bset->height + 1; \
|
||||
const size_t states = ncp->plot.bset->height + 1; \
|
||||
/* FIXME can we not rid ourselves of this meddlesome double? either way, the \
|
||||
interval is one row's range (for linear plots), or the base (base^slots== \
|
||||
maxy-miny) of the range (for exponential plots). */ \
|
||||
double interval; \
|
||||
if(ncp->exponentiali){ \
|
||||
if(ncp->plot.exponentiali){ \
|
||||
if(ncp->maxy > ncp->miny){ \
|
||||
interval = pow(ncp->maxy - ncp->miny, (double)1 / (dimy * states)); \
|
||||
/* fprintf(stderr, "miny: %ju maxy: %ju dimy: %d states: %zu\n", miny, maxy, dimy, states); */ \
|
||||
@ -60,20 +65,21 @@ int redraw_plot_##T(nc##X##plot* ncp){ \
|
||||
}else{ \
|
||||
interval = ncp->maxy < ncp->miny ? 0 : (ncp->maxy - ncp->miny) / ((double)dimy * states); \
|
||||
} \
|
||||
const int startx = ncp->labelaxisd ? PREFIXCOLUMNS : 0; /* plot cols begin here */ \
|
||||
const int startx = ncp->plot.labelaxisd ? PREFIXCOLUMNS : 0; /* plot cols begin here */ \
|
||||
/* if we want fewer slots than there are available columns, our final column \
|
||||
will be other than the plane's final column. most recent x goes here. */ \
|
||||
const int finalx = (ncp->slotcount < scaleddim - 1 - (startx * scale) ? startx + (ncp->slotcount / scale) - 1 : dimx - 1); \
|
||||
ncplane_set_styles(ncp->ncp, ncp->legendstyle); \
|
||||
if(ncp->labelaxisd){ \
|
||||
const int finalx = (ncp->plot.slotcount < scaleddim - 1 - (startx * scale) ? \
|
||||
startx + (ncp->plot.slotcount / scale) - 1 : dimx - 1); \
|
||||
ncplane_set_styles(ncp->plot.ncp, ncp->plot.legendstyle); \
|
||||
if(ncp->plot.labelaxisd){ \
|
||||
/* show the *top* of each interval range */ \
|
||||
for(int y = 0 ; y < dimy ; ++y){ \
|
||||
uint64_t channels = 0; \
|
||||
calc_gradient_channels(&channels, ncp->minchannels, ncp->minchannels, \
|
||||
ncp->maxchannels, ncp->maxchannels, y, 0, dimy, dimx); \
|
||||
ncplane_set_channels(ncp->ncp, channels); \
|
||||
calc_gradient_channels(&channels, ncp->plot.minchannels, ncp->plot.minchannels, \
|
||||
ncp->plot.maxchannels, ncp->plot.maxchannels, y, 0, dimy, dimx); \
|
||||
ncplane_set_channels(ncp->plot.ncp, channels); \
|
||||
char buf[PREFIXSTRLEN + 1]; \
|
||||
if(ncp->exponentiali){ \
|
||||
if(ncp->plot.exponentiali){ \
|
||||
if(y == dimy - 1){ /* we cheat on the top row to exactly match maxy */ \
|
||||
ncmetric(ncp->maxy * 100, 100, buf, 0, 1000, '\0'); \
|
||||
}else{ \
|
||||
@ -82,27 +88,27 @@ int redraw_plot_##T(nc##X##plot* ncp){ \
|
||||
}else{ \
|
||||
ncmetric((ncp->maxy - interval * states * (dimy - y - 1)) * 100, 100, buf, 0, 1000, '\0'); \
|
||||
} \
|
||||
if(y == dimy - 1 && strlen(ncp->title)){ \
|
||||
ncplane_printf_yx(ncp->ncp, dimy - y - 1, PREFIXCOLUMNS - strlen(buf), "%s %s", buf, ncp->title); \
|
||||
if(y == dimy - 1 && strlen(ncp->plot.title)){ \
|
||||
ncplane_printf_yx(ncp->plot.ncp, dimy - y - 1, PREFIXCOLUMNS - strlen(buf), "%s %s", buf, ncp->plot.title); \
|
||||
}else{ \
|
||||
ncplane_printf_yx(ncp->ncp, dimy - y - 1, PREFIXCOLUMNS - strlen(buf), "%s", buf); \
|
||||
ncplane_printf_yx(ncp->plot.ncp, dimy - y - 1, PREFIXCOLUMNS - strlen(buf), "%s", buf); \
|
||||
} \
|
||||
} \
|
||||
}else if(strlen(ncp->title)){ \
|
||||
}else if(strlen(ncp->plot.title)){ \
|
||||
uint64_t channels = 0; \
|
||||
calc_gradient_channels(&channels, ncp->minchannels, ncp->minchannels, \
|
||||
ncp->maxchannels, ncp->maxchannels, dimy - 1, 0, dimy, dimx); \
|
||||
ncplane_set_channels(ncp->ncp, channels); \
|
||||
ncplane_printf_yx(ncp->ncp, 0, PREFIXCOLUMNS - strlen(ncp->title), "%s", ncp->title); \
|
||||
calc_gradient_channels(&channels, ncp->plot.minchannels, ncp->plot.minchannels, \
|
||||
ncp->plot.maxchannels, ncp->plot.maxchannels, dimy - 1, 0, dimy, dimx); \
|
||||
ncplane_set_channels(ncp->plot.ncp, channels); \
|
||||
ncplane_printf_yx(ncp->plot.ncp, 0, PREFIXCOLUMNS - strlen(ncp->plot.title), "%s", ncp->plot.title); \
|
||||
} \
|
||||
ncplane_set_styles(ncp->ncp, NCSTYLE_NONE); \
|
||||
ncplane_set_styles(ncp->plot.ncp, NCSTYLE_NONE); \
|
||||
if(finalx < startx){ /* exit on pathologically narrow planes */ \
|
||||
return 0; \
|
||||
} \
|
||||
if(!interval){ \
|
||||
interval = 1; \
|
||||
} \
|
||||
int idx = ncp->slotstart; /* idx holds the real slot index; we move backwards */ \
|
||||
int idx = ncp->plot.slotstart; /* idx holds the real slot index; we move backwards */ \
|
||||
for(int x = finalx ; x >= startx ; --x){ \
|
||||
/* a single column might correspond to more than 1 ('scale', up to \
|
||||
MAXWIDTH) slot's worth of samples. prepare the working gval set. */ \
|
||||
@ -118,20 +124,20 @@ int redraw_plot_##T(nc##X##plot* ncp){ \
|
||||
} \
|
||||
/* FIXME if there are an odd number, only go up through the valid ones... */ \
|
||||
if(--idx < 0){ \
|
||||
idx = ncp->slotcount - 1; \
|
||||
idx = ncp->plot.slotcount - 1; \
|
||||
} \
|
||||
} \
|
||||
/* starting from the least-significant row, progress in the more significant \
|
||||
direction, drawing egcs from the grid specification, aborting early if \
|
||||
we can't draw anything in a given cell. */ \
|
||||
T intervalbase = ncp->miny; \
|
||||
const wchar_t* egc = ncp->bset->plotegcs; \
|
||||
bool done = !ncp->bset->fill; \
|
||||
const wchar_t* egc = ncp->plot.bset->plotegcs; \
|
||||
bool done = !ncp->plot.bset->fill; \
|
||||
for(int y = 0 ; y < dimy ; ++y){ \
|
||||
uint64_t channels = 0; \
|
||||
calc_gradient_channels(&channels, ncp->minchannels, ncp->minchannels, \
|
||||
ncp->maxchannels, ncp->maxchannels, y, x, dimy, dimx); \
|
||||
ncplane_set_channels(ncp->ncp, channels); \
|
||||
calc_gradient_channels(&channels, ncp->plot.minchannels, ncp->plot.minchannels, \
|
||||
ncp->plot.maxchannels, ncp->plot.maxchannels, y, x, dimy, dimx); \
|
||||
ncplane_set_channels(ncp->plot.ncp, channels); \
|
||||
size_t egcidx = 0, sumidx = 0; \
|
||||
/* if we've got at least one interval's worth on the number of positions \
|
||||
times the number of intervals per position plus the starting offset, \
|
||||
@ -139,7 +145,7 @@ int redraw_plot_##T(nc##X##plot* ncp){ \
|
||||
for(int i = 0 ; i < scale ; ++i){ \
|
||||
sumidx *= states; \
|
||||
if(intervalbase < gvals[i]){ \
|
||||
if(ncp->exponentiali){ \
|
||||
if(ncp->plot.exponentiali){ \
|
||||
/* we want the log-base-interval of gvals[i] */ \
|
||||
double scaled = log(gvals[i] - ncp->miny) / log(interval); \
|
||||
double sival = intervalbase ? log(intervalbase) / log(interval) : 0; \
|
||||
@ -164,18 +170,18 @@ int redraw_plot_##T(nc##X##plot* ncp){ \
|
||||
modes, sumidx == 0 means don't do shit, since we erased earlier. */ \
|
||||
/* if(sumidx)fprintf(stderr, "dimy: %d y: %d x: %d sumidx: %zu egc[%zu]: %lc\n", dimy, y, x, sumidx, sumidx, egc[sumidx]); */ \
|
||||
if(sumidx){ \
|
||||
if(notcurses_canutf8(ncplane_notcurses(ncp->ncp))){ \
|
||||
if(notcurses_canutf8(ncplane_notcurses(ncp->plot.ncp))){ \
|
||||
char utf8[MB_CUR_MAX + 1]; \
|
||||
int bytes = wctomb(utf8, egc[sumidx]); \
|
||||
if(bytes < 0){ \
|
||||
return -1; \
|
||||
} \
|
||||
utf8[bytes] = '\0'; \
|
||||
nccell* c = ncplane_cell_ref_yx(ncp->ncp, dimy - y - 1, x); \
|
||||
nccell* c = ncplane_cell_ref_yx(ncp->plot.ncp, dimy - y - 1, x); \
|
||||
cell_set_bchannel(c, ncchannels_bchannel(channels)); \
|
||||
cell_set_fchannel(c, ncchannels_fchannel(channels)); \
|
||||
nccell_set_styles(c, NCSTYLE_NONE); \
|
||||
if(pool_blit_direct(&ncp->ncp->pool, c, utf8, bytes, 1) <= 0){ \
|
||||
if(pool_blit_direct(&ncp->plot.ncp->pool, c, utf8, bytes, 1) <= 0){ \
|
||||
return -1; \
|
||||
} \
|
||||
}else{ \
|
||||
@ -183,32 +189,32 @@ int redraw_plot_##T(nc##X##plot* ncp){ \
|
||||
const uint64_t swapfg = ncchannels_fchannel(channels); \
|
||||
ncchannels_set_bchannel(&channels, swapfg); \
|
||||
ncchannels_set_fchannel(&channels, swapbg); \
|
||||
ncplane_set_channels(ncp->ncp, channels); \
|
||||
if(ncplane_putchar_yx(ncp->ncp, dimy - y - 1, x, ' ') <= 0){ \
|
||||
ncplane_set_channels(ncp->plot.ncp, channels); \
|
||||
if(ncplane_putchar_yx(ncp->plot.ncp, dimy - y - 1, x, ' ') <= 0){ \
|
||||
return -1; \
|
||||
} \
|
||||
ncchannels_set_bchannel(&channels, swapbg); \
|
||||
ncchannels_set_fchannel(&channels, swapfg); \
|
||||
ncplane_set_channels(ncp->ncp, channels); \
|
||||
ncplane_set_channels(ncp->plot.ncp, channels); \
|
||||
} \
|
||||
} \
|
||||
if(done){ \
|
||||
break; \
|
||||
} \
|
||||
if(ncp->exponentiali){ \
|
||||
if(ncp->plot.exponentiali){ \
|
||||
intervalbase = ncp->miny + pow(interval, (y + 1) * states - 1); \
|
||||
}else{ \
|
||||
intervalbase += (states * interval); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
if(ncp->printsample){ \
|
||||
int lastslot = ncp->slotstart ? ncp->slotstart - 1 : ncp->slotcount - 1; \
|
||||
ncplane_set_styles(ncp->ncp, ncp->legendstyle); \
|
||||
ncplane_set_channels(ncp->ncp, ncp->maxchannels); \
|
||||
ncplane_printf_aligned(ncp->ncp, 0, NCALIGN_RIGHT, "%" PRIu64, (uint64_t)ncp->slots[lastslot]); \
|
||||
if(ncp->plot.printsample){ \
|
||||
int lastslot = ncp->plot.slotstart ? ncp->plot.slotstart - 1 : ncp->plot.slotcount - 1; \
|
||||
ncplane_set_styles(ncp->plot.ncp, ncp->plot.legendstyle); \
|
||||
ncplane_set_channels(ncp->plot.ncp, ncp->plot.maxchannels); \
|
||||
ncplane_printf_aligned(ncp->plot.ncp, 0, NCALIGN_RIGHT, "%" PRIu64, (uint64_t)ncp->slots[lastslot]); \
|
||||
} \
|
||||
ncplane_home(ncp->ncp); \
|
||||
ncplane_home(ncp->plot.ncp); \
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
@ -260,49 +266,49 @@ create_##T(nc##X##plot* ncpp, ncplane* n, const ncplot_options* opts, const T mi
|
||||
return false; \
|
||||
} \
|
||||
int dimx = sdimx; \
|
||||
ncpp->title = strdup(opts->title ? opts->title : ""); \
|
||||
ncpp->rangex = opts->rangex; \
|
||||
ncpp->plot.title = strdup(opts->title ? opts->title : ""); \
|
||||
ncpp->plot.rangex = opts->rangex; \
|
||||
/* if we're sizing the plot based off the plane dimensions, scale it by the \
|
||||
plot geometry's width for all calculations */ \
|
||||
const int scaleddim = dimx * bset->width; \
|
||||
const int scaledprefixlen = PREFIXCOLUMNS * bset->width; \
|
||||
if((ncpp->slotcount = ncpp->rangex) == 0){ \
|
||||
ncpp->slotcount = scaleddim; \
|
||||
if((ncpp->plot.slotcount = ncpp->plot.rangex) == 0){ \
|
||||
ncpp->plot.slotcount = scaleddim; \
|
||||
} \
|
||||
if(dimx < ncpp->rangex){ \
|
||||
ncpp->slotcount = scaleddim; \
|
||||
if(dimx < ncpp->plot.rangex){ \
|
||||
ncpp->plot.slotcount = scaleddim; \
|
||||
} \
|
||||
ncpp->legendstyle = opts->legendstyle; \
|
||||
if( (ncpp->labelaxisd = opts->flags & NCPLOT_OPTION_LABELTICKSD) ){ \
|
||||
if(ncpp->slotcount + scaledprefixlen > scaleddim){ \
|
||||
ncpp->plot.legendstyle = opts->legendstyle; \
|
||||
if( (ncpp->plot.labelaxisd = opts->flags & NCPLOT_OPTION_LABELTICKSD) ){ \
|
||||
if(ncpp->plot.slotcount + scaledprefixlen > scaleddim){ \
|
||||
if(scaleddim > scaledprefixlen){ \
|
||||
ncpp->slotcount = scaleddim - scaledprefixlen; \
|
||||
ncpp->plot.slotcount = scaleddim - scaledprefixlen; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
size_t slotsize = sizeof(*ncpp->slots) * ncpp->slotcount; \
|
||||
size_t slotsize = sizeof(*ncpp->slots) * ncpp->plot.slotcount; \
|
||||
ncpp->slots = malloc(slotsize); \
|
||||
if(ncpp->slots == NULL){ \
|
||||
ncplane_destroy(n); \
|
||||
return false; \
|
||||
} \
|
||||
memset(ncpp->slots, 0, slotsize); \
|
||||
ncpp->ncp = n; \
|
||||
ncpp->maxchannels = opts->maxchannels; \
|
||||
ncpp->minchannels = opts->minchannels; \
|
||||
ncpp->bset = bset; \
|
||||
ncpp->plot.ncp = n; \
|
||||
ncpp->plot.maxchannels = opts->maxchannels; \
|
||||
ncpp->plot.minchannels = opts->minchannels; \
|
||||
ncpp->plot.bset = bset; \
|
||||
ncpp->miny = miny; \
|
||||
ncpp->maxy = maxy; \
|
||||
ncpp->vertical_indep = opts->flags & NCPLOT_OPTION_VERTICALI; \
|
||||
ncpp->exponentiali = opts->flags & NCPLOT_OPTION_EXPONENTIALD; \
|
||||
ncpp->detectonlymax = opts->flags & NCPLOT_OPTION_DETECTMAXONLY; \
|
||||
ncpp->printsample = opts->flags & NCPLOT_OPTION_PRINTSAMPLE; \
|
||||
if( (ncpp->detectdomain = (miny == maxy)) ){ \
|
||||
ncpp->plot.vertical_indep = opts->flags & NCPLOT_OPTION_VERTICALI; \
|
||||
ncpp->plot.exponentiali = opts->flags & NCPLOT_OPTION_EXPONENTIALD; \
|
||||
ncpp->plot.detectonlymax = opts->flags & NCPLOT_OPTION_DETECTMAXONLY; \
|
||||
ncpp->plot.printsample = opts->flags & NCPLOT_OPTION_PRINTSAMPLE; \
|
||||
if( (ncpp->plot.detectdomain = (miny == maxy)) ){ \
|
||||
ncpp->maxy = trueminy; \
|
||||
ncpp->miny = truemaxy; \
|
||||
} \
|
||||
ncpp->slotstart = 0; \
|
||||
ncpp->slotx = 0; \
|
||||
ncpp->plot.slotstart = 0; \
|
||||
ncpp->plot.slotx = 0; \
|
||||
redraw_plot_##T(ncpp); \
|
||||
return true; \
|
||||
} \
|
||||
@ -312,29 +318,29 @@ create_##T(nc##X##plot* ncpp, ncplane* n, const ncplot_options* opts, const T mi
|
||||
reset them, and write the new sample anywhere. otherwise, write it to the \
|
||||
proper slot based on the current newest slot. */ \
|
||||
int window_slide_##T(nc##X##plot* ncp, int64_t x){ \
|
||||
if(x < ncp->slotx - (ncp->slotcount - 1)){ /* x is behind window, won't be counted */ \
|
||||
if(x < ncp->plot.slotx - (ncp->plot.slotcount - 1)){ /* x is behind window, won't be counted */ \
|
||||
return -1; \
|
||||
}else if(x <= ncp->slotx){ /* x is within window, do nothing */ \
|
||||
}else if(x <= ncp->plot.slotx){ /* x is within window, do nothing */ \
|
||||
return 0; \
|
||||
} /* x is newest; we might be keeping some, might not */ \
|
||||
int64_t xdiff = x - ncp->slotx; /* the raw amount we're advancing */ \
|
||||
ncp->slotx = x; \
|
||||
if(xdiff >= ncp->slotcount){ /* we're throwing away all old samples, write to 0 */ \
|
||||
memset(ncp->slots, 0, sizeof(*ncp->slots) * ncp->slotcount); \
|
||||
ncp->slotstart = 0; \
|
||||
int64_t xdiff = x - ncp->plot.slotx; /* the raw amount we're advancing */ \
|
||||
ncp->plot.slotx = x; \
|
||||
if(xdiff >= ncp->plot.slotcount){ /* we're throwing away all old samples, write to 0 */ \
|
||||
memset(ncp->slots, 0, sizeof(*ncp->slots) * ncp->plot.slotcount); \
|
||||
ncp->plot.slotstart = 0; \
|
||||
return 0; \
|
||||
} \
|
||||
/* we're throwing away only xdiff slots, which is less than slotcount. \
|
||||
first, we'll try to clear to the right...number to reset on the right of \
|
||||
the circular buffer. min of (available at current or to right, xdiff) */ \
|
||||
int slotsreset = ncp->slotcount - ncp->slotstart - 1; \
|
||||
int slotsreset = ncp->plot.slotcount - ncp->plot.slotstart - 1; \
|
||||
if(slotsreset > xdiff){ \
|
||||
slotsreset = xdiff; \
|
||||
} \
|
||||
if(slotsreset){ \
|
||||
memset(ncp->slots + ncp->slotstart + 1, 0, slotsreset * sizeof(*ncp->slots)); \
|
||||
memset(ncp->slots + ncp->plot.slotstart + 1, 0, slotsreset * sizeof(*ncp->slots)); \
|
||||
} \
|
||||
ncp->slotstart = (ncp->slotstart + xdiff) % ncp->slotcount; \
|
||||
ncp->plot.slotstart = (ncp->plot.slotstart + xdiff) % ncp->plot.slotcount; \
|
||||
xdiff -= slotsreset; \
|
||||
if(xdiff){ /* throw away some at the beginning */ \
|
||||
memset(ncp->slots, 0, xdiff * sizeof(*ncp->slots)); \
|
||||
@ -344,8 +350,8 @@ int window_slide_##T(nc##X##plot* ncp, int64_t x){ \
|
||||
\
|
||||
/* x must be within n's window at this point */ \
|
||||
void update_sample_##T(nc##X##plot* ncp, int64_t x, T y, bool reset){ \
|
||||
const int64_t diff = ncp->slotx - x; /* amount behind */ \
|
||||
const int idx = (ncp->slotstart + ncp->slotcount - diff) % ncp->slotcount; \
|
||||
const int64_t diff = ncp->plot.slotx - x; /* amount behind */ \
|
||||
const int idx = (ncp->plot.slotstart + ncp->plot.slotcount - diff) % ncp->plot.slotcount; \
|
||||
if(reset){ \
|
||||
ncp->slots[idx] = y; \
|
||||
}else{ \
|
||||
@ -357,12 +363,12 @@ void update_sample_##T(nc##X##plot* ncp, int64_t x, T y, bool reset){ \
|
||||
just set. if we're not, check the result against the known ranges, and \
|
||||
return -1 if the value is outside of that range. */ \
|
||||
int update_domain_##T(nc##X##plot* ncp, uint64_t x){ \
|
||||
const T val = ncp->slots[x % ncp->slotcount]; \
|
||||
if(ncp->detectdomain){ \
|
||||
const T val = ncp->slots[x % ncp->plot.slotcount]; \
|
||||
if(ncp->plot.detectdomain){ \
|
||||
if(val > ncp->maxy){ \
|
||||
ncp->maxy = val; \
|
||||
} \
|
||||
if(!ncp->detectonlymax){ \
|
||||
if(!ncp->plot.detectonlymax){ \
|
||||
if(val < ncp->miny){ \
|
||||
ncp->miny = val; \
|
||||
} \
|
||||
@ -399,18 +405,18 @@ int add_sample_##T(nc##X##plot* ncpp, uint64_t x, T y){ \
|
||||
return redraw_plot_##T(ncpp); \
|
||||
} \
|
||||
int sample_##T(const nc##X##plot* ncp, int64_t x, T* y){ \
|
||||
if(x < ncp->slotx - (ncp->slotcount - 1)){ /* x is behind window */ \
|
||||
if(x < ncp->plot.slotx - (ncp->plot.slotcount - 1)){ /* x is behind window */ \
|
||||
return -1; \
|
||||
}else if(x > ncp->slotx){ /* x is ahead of window */ \
|
||||
}else if(x > ncp->plot.slotx){ /* x is ahead of window */ \
|
||||
return -1; \
|
||||
} \
|
||||
*y = ncp->slots[x % ncp->slotcount]; \
|
||||
*y = ncp->slots[x % ncp->plot.slotcount]; \
|
||||
return 0; \
|
||||
} \
|
||||
void destroy_##T(nc##X##plot* ncpp){ \
|
||||
free(ncpp->title); \
|
||||
free(ncpp->plot.title); \
|
||||
free(ncpp->slots); \
|
||||
ncplane_destroy(ncpp->ncp); \
|
||||
ncplane_destroy(ncpp->plot.ncp); \
|
||||
}
|
||||
|
||||
CREATE(uint64_t, u)
|
||||
@ -432,7 +438,7 @@ ncuplot* ncuplot_create(ncplane* n, const ncplot_options* opts, uint64_t miny, u
|
||||
}
|
||||
|
||||
ncplane* ncuplot_plane(ncuplot* n){
|
||||
return n->ncp;
|
||||
return n->plot.ncp;
|
||||
}
|
||||
|
||||
int ncuplot_add_sample(ncuplot* n, uint64_t x, uint64_t y){
|
||||
@ -466,7 +472,7 @@ ncdplot* ncdplot_create(ncplane* n, const ncplot_options* opts, double miny, dou
|
||||
}
|
||||
|
||||
ncplane* ncdplot_plane(ncdplot* n){
|
||||
return n->ncp;
|
||||
return n->plot.ncp;
|
||||
}
|
||||
|
||||
int ncdplot_add_sample(ncdplot* n, uint64_t x, double y){
|
||||
|
Loading…
Reference in New Issue
Block a user