/****************************************************************************
- * RRDtool 1.2.12 Copyright by Tobi Oetiker, 1997-2005
+ * RRDtool 1.2.15 Copyright by Tobi Oetiker, 1997-2006
****************************************************************************
* rrd__graph.c produce graphs from data in rrdfiles
****************************************************************************/
#include <sys/stat.h>
+#ifdef WIN32
+#include "strftime.h"
+#endif
#include "rrd_tool.h"
-#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)
+#if defined(WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__)
#include <io.h>
#include <fcntl.h>
#endif
{10, 0, TMT_MINUTE,5, TMT_MINUTE,20, TMT_MINUTE,20, 0,"%H:%M"},
{30, 0, TMT_MINUTE,10, TMT_HOUR,1, TMT_HOUR,1, 0,"%H:%M"},
{60, 0, TMT_MINUTE,30, TMT_HOUR,2, TMT_HOUR,2, 0,"%H:%M"},
+ {60, 24*3600, TMT_MINUTE,30, TMT_HOUR,2, TMT_HOUR,4, 0,"%a %H:%M"},
{180, 0, TMT_HOUR,1, TMT_HOUR,6, TMT_HOUR,6, 0,"%H:%M"},
- {180, 1*24*3600, TMT_HOUR,1, TMT_HOUR,6, TMT_HOUR,6, 0,"%a %H:%M"},
+ {180, 24*3600, TMT_HOUR,1, TMT_HOUR,6, TMT_HOUR,12, 0,"%a %H:%M"},
/*{300, 0, TMT_HOUR,3, TMT_HOUR,12, TMT_HOUR,12, 12*3600,"%a %p"}, this looks silly*/
{600, 0, TMT_HOUR,6, TMT_DAY,1, TMT_DAY,1, 24*3600,"%a"},
- {600, 1*24*3600, TMT_HOUR,6, TMT_DAY,1, TMT_DAY,1, 24*3600,"%a %d"},
- {1800, 0, TMT_HOUR,12, TMT_DAY,1, TMT_DAY,2, 24*3600,"%a"},
- {1800, 1*24*3600, TMT_HOUR,12, TMT_DAY,1, TMT_DAY,2, 24*3600,"%a %d"},
- {3600, 0, TMT_DAY,1, TMT_WEEK,1, TMT_WEEK,1, 7*24*3600,"Week %V"},
- {3*3600, 0, TMT_WEEK,1, TMT_MONTH,1, TMT_WEEK,2, 7*24*3600,"Week %V"},
+ {1200, 0, TMT_HOUR,6, TMT_DAY,1, TMT_DAY,1, 24*3600,"%d"},
+ {1800, 0, TMT_HOUR,12, TMT_DAY,1, TMT_DAY,2, 24*3600,"%a %d"},
+ {2400, 0, TMT_HOUR,12, TMT_DAY,1, TMT_DAY,2, 24*3600,"%a"},
+ {3600, 0, TMT_DAY,1, TMT_WEEK,1, TMT_WEEK,1, 7*24*3600,"Week %V"},
+ {3*3600, 0, TMT_WEEK,1, TMT_MONTH,1, TMT_WEEK,2, 7*24*3600,"Week %V"},
{6*3600, 0, TMT_MONTH,1, TMT_MONTH,1, TMT_MONTH,1, 30*24*3600,"%b"},
{48*3600, 0, TMT_MONTH,1, TMT_MONTH,3, TMT_MONTH,3, 30*24*3600,"%b"},
+ {315360, 0, TMT_MONTH,3, TMT_YEAR,1, TMT_YEAR,1, 365*24*3600,"%Y"},
{10*24*3600, 0, TMT_YEAR,1, TMT_YEAR,1, TMT_YEAR,1, 365*24*3600,"%y"},
{-1,0,TMT_MONTH,0,TMT_MONTH,0,TMT_MONTH,0,0,""}
};
-/* sensible logarithmic y label intervals ...
- the first element of each row defines the possible starting points on the
- y axis ... the other specify the */
-
-double yloglab[][12]= {{ 1e9, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 1e3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- { 1e1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
- /* { 1e1, 1, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, */
- { 1e1, 1, 2.5, 5, 7.5, 0, 0, 0, 0, 0, 0, 0 },
- { 1e1, 1, 2, 4, 6, 8, 0, 0, 0, 0, 0, 0 },
- { 1e1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }};
-
/* sensible y label intervals ...*/
ylab_t ylab[]= {
'P', /* 10e15 Peta */
'E', /* 10e18 Exa */
};
-const static int si_symbcenter = 6;
+static const int si_symbcenter = 6;
/* find SI magnitude symbol for the numbers on the y-axis*/
void
break;
}
if (! skip) {
- unsigned long ft_step = im->gdes[i].step ;
+ unsigned long ft_step = im->gdes[i].step ; /* ft_step will record what we got from fetch */
if((rrd_fetch_fn(im->gdes[i].rrd,
im->gdes[i].cf,
return -1;
}
im->gdes[i].data_first = 1;
- im->gdes[i].step = im->step;
if (ft_step < im->gdes[i].step) {
reduce_data(im->gdes[i].cf_reduce,
** relevant for min and max
*/
if (finite(paintval) && im->gdes[ii].gf != GF_TICK ) {
- if (isnan(minval) || paintval < minval)
- minval = paintval;
+ if ((isnan(minval) || paintval < minval ) &&
+ ! (im->logarithmic && paintval <= 0.0))
+ minval = paintval;
if (isnan(maxval) || paintval > maxval)
maxval = paintval;
}
there was no data in the graph ... this is not good ...
lets set these to dummy values then ... */
- if (isnan(minval)) minval = 0.0;
- if (isnan(maxval)) maxval = 1.0;
+ if (im->logarithmic) {
+ if (isnan(minval)) minval = 0.2;
+ if (isnan(maxval)) maxval = 5.1;
+ }
+ else {
+ if (isnan(minval)) minval = 0.0;
+ if (isnan(maxval)) maxval = 1.0;
+ }
/* adjust min and max values */
if (isnan(im->minval)
- /* don't adjust low-end with log scale */
- || ((!im->logarithmic && !im->rigid) && im->minval > minval)
- )
- im->minval = minval;
+ /* don't adjust low-end with log scale */ /* why not? */
+ || ((!im->rigid) && im->minval > minval)
+ ) {
+ if (im->logarithmic)
+ im->minval = minval * 0.5;
+ else
+ im->minval = minval;
+ }
if (isnan(im->maxval)
|| (!im->rigid && im->maxval < maxval)
) {
if (im->logarithmic)
- im->maxval = maxval * 1.1;
+ im->maxval = maxval * 2.0;
else
im->maxval = maxval;
}
{
long i,ii,validsteps;
double printval;
- time_t printtime;
+ struct tm tmvdef;
int graphelement = 0;
long vidx;
int max_ii;
char *si_symb = "";
char *percent_s;
int prlines = 1;
+ /* wow initializing tmvdef is quite a task :-) */
+ time_t now = time(NULL);
+ localtime_r(&now,&tmvdef);
if (im->imginfo) prlines++;
for(i=0;i<im->gdes_c;i++){
switch(im->gdes[i].gf){
vidx = im->gdes[i].vidx;
if (im->gdes[vidx].gf==GF_VDEF) { /* simply use vals */
printval = im->gdes[vidx].vf.val;
- printtime = im->gdes[vidx].vf.when;
+ localtime_r(&im->gdes[vidx].vf.when,&tmvdef);
} else { /* need to calculate max,min,avg etcetera */
max_ii =((im->gdes[vidx].end
- im->gdes[vidx].start)
}
} /* prepare printval */
- if (!strcmp(im->gdes[i].format,"%c")) { /* VDEF time print */
- char ctime_buf[128]; /* PS: for ctime_r, must be >= 26 chars */
- int iii=0;
- ctime_r(&printtime,ctime_buf);
- while(isprint(ctime_buf[iii])){iii++;}
- ctime_buf[iii]='\0';
- if (im->gdes[i].gf == GF_PRINT){
- (*prdata)[prlines-2] = malloc((FMT_LEG_LEN+2)*sizeof(char));
- sprintf((*prdata)[prlines-2],"%s (%lu)",ctime_buf,printtime);
- (*prdata)[prlines-1] = NULL;
- } else {
- sprintf(im->gdes[i].legend,"%s (%lu)",ctime_buf,printtime);
- graphelement = 1;
- }
- } else {
if ((percent_s = strstr(im->gdes[i].format,"%S")) != NULL) {
/* Magfact is set to -1 upon entry to print_calc. If it
* is still less than 0, then we need to run auto_scale.
auto_scale(im,&printval,&si_symb,&magfact);
}
- if (im->gdes[i].gf == GF_PRINT){
+ if (im->gdes[i].gf == GF_PRINT){
(*prdata)[prlines-2] = malloc((FMT_LEG_LEN+2)*sizeof(char));
(*prdata)[prlines-1] = NULL;
- if (bad_format(im->gdes[i].format)) {
- rrd_set_error("bad format for PRINT in '%s'", im->gdes[i].format);
+ if (im->gdes[i].strftm){
+ strftime((*prdata)[prlines-2],FMT_LEG_LEN,im->gdes[i].format,&tmvdef);
+ } else {
+ if (bad_format(im->gdes[i].format)) {
+ rrd_set_error("bad format for PRINT in '%s'", im->gdes[i].format);
return -1;
- }
+ }
+
#ifdef HAVE_SNPRINTF
- snprintf((*prdata)[prlines-2],FMT_LEG_LEN,im->gdes[i].format,printval,si_symb);
+ snprintf((*prdata)[prlines-2],FMT_LEG_LEN,im->gdes[i].format,printval,si_symb);
#else
- sprintf((*prdata)[prlines-2],im->gdes[i].format,printval,si_symb);
+ sprintf((*prdata)[prlines-2],im->gdes[i].format,printval,si_symb);
#endif
- } else {
+ }
+ } else {
/* GF_GPRINT */
- if (bad_format(im->gdes[i].format)) {
+ if (im->gdes[i].strftm){
+ strftime(im->gdes[i].legend,FMT_LEG_LEN,im->gdes[i].format,&tmvdef);
+ } else {
+ if (bad_format(im->gdes[i].format)) {
rrd_set_error("bad format for GPRINT in '%s'", im->gdes[i].format);
return -1;
- }
+ }
#ifdef HAVE_SNPRINTF
- snprintf(im->gdes[i].legend,FMT_LEG_LEN-2,im->gdes[i].format,printval,si_symb);
+ snprintf(im->gdes[i].legend,FMT_LEG_LEN-2,im->gdes[i].format,printval,si_symb);
#else
- sprintf(im->gdes[i].legend,im->gdes[i].format,printval,si_symb);
+ sprintf(im->gdes[i].legend,im->gdes[i].format,printval,si_symb);
#endif
- graphelement = 1;
- }
- }
+ }
+ graphelement = 1;
+ }
break;
case GF_LINE:
case GF_AREA:
case GF_TICK:
+ graphelement = 1;
+ break;
case GF_HRULE:
+ if(isnan(im->gdes[i].yrule)) { /* we must set this here or the legend printer can not decide to print the legend */
+ im->gdes[i].yrule=im->gdes[im->gdes[i].vidx].vf.val;
+ };
+ graphelement = 1;
+ break;
case GF_VRULE:
+ if(im->gdes[i].xrule == 0) { /* again ... the legend printer needs it*/
+ im->gdes[i].xrule = im->gdes[im->gdes[i].vidx].vf.when;
+ };
graphelement = 1;
break;
case GF_COMMENT:
int fill=0, fill_last;
int leg_c = 0;
int leg_x = border, leg_y = im->yimg;
+ int leg_y_prev = im->yimg;
int leg_cc;
int glue = 0;
int i,ii, mark = 0;
} else {
prt_fctn = '\0';
}
+ /* only valid control codes */
+ if (prt_fctn != 'l' &&
+ prt_fctn != 'r' &&
+ prt_fctn != 'j' &&
+ prt_fctn != 'c' &&
+ prt_fctn != 't' &&
+ prt_fctn != '\0' &&
+ prt_fctn != 'g' ) {
+ free(legspace);
+ rrd_set_error("Unknown control code at the end of '%s\\%c'",im->gdes[i].legend,prt_fctn);
+ return -1;
+
+ }
/* remove exess space */
while (prt_fctn=='g' &&
leg_cc > 0 &&
+ legspace[ii]
+ glue;
}
- leg_y += im->text_prop[TEXT_PROP_LEGEND].size*1.8;
- if (prt_fctn == 's') leg_y -= im->text_prop[TEXT_PROP_LEGEND].size;
+ leg_y_prev = leg_y;
+ /* only add y space if there was text on the line */
+ if (leg_x > border || prt_fctn == 's')
+ leg_y += im->text_prop[TEXT_PROP_LEGEND].size*1.8;
+ if (prt_fctn == 's')
+ leg_y -= im->text_prop[TEXT_PROP_LEGEND].size;
fill = 0;
leg_c = 0;
mark = ii;
}
}
- im->yimg = leg_y;
+ im->yimg = leg_y_prev;
+ /* if we did place some legends we have to add vertical space */
+ if (leg_y != im->yimg){
+ im->yimg += im->text_prop[TEXT_PROP_LEGEND].size*1.8;
+ }
free(legspace);
}
return 0;
return 1;
}
+/* this is frexp for base 10 */
+double frexp10(double, double *);
+double frexp10(double x, double *e) {
+ double mnt;
+ int iexp;
+
+ iexp = floor(log(fabs(x)) / log(10));
+ mnt = x / pow(10.0, iexp);
+ if(mnt >= 10.0) {
+ iexp++;
+ mnt = x / pow(10.0, iexp);
+ }
+ *e = iexp;
+ return mnt;
+}
+
+static int AlmostEqual2sComplement (float A, float B, int maxUlps)
+{
+
+ int aInt = *(int*)&A;
+ int bInt = *(int*)&B;
+ int intDiff;
+ /* Make sure maxUlps is non-negative and small enough that the
+ default NAN won't compare as equal to anything. */
+
+ /* assert(maxUlps > 0 && maxUlps < 4 * 1024 * 1024); */
+
+ /* Make aInt lexicographically ordered as a twos-complement int */
+
+ if (aInt < 0)
+ aInt = 0x80000000l - aInt;
+
+ /* Make bInt lexicographically ordered as a twos-complement int */
+
+ if (bInt < 0)
+ bInt = 0x80000000l - bInt;
+
+ intDiff = abs(aInt - bInt);
+
+ if (intDiff <= maxUlps)
+ return 1;
+
+ return 0;
+}
+
/* logaritmic horizontal grid */
int
horizontal_log_grid(image_desc_t *im)
{
- double pixpex;
- int ii,i;
- int minoridx=0, majoridx=0;
- char graph_label[100];
- double X0,X1,Y0;
- double value, pixperstep, minstep;
+ double yloglab[][10] = {
+ {1.0, 10., 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
+ {1.0, 5.0, 10., 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
+ {1.0, 2.0, 5.0, 7.0, 10., 0.0, 0.0, 0.0, 0.0, 0.0},
+ {1.0, 2.0, 4.0, 6.0, 8.0, 10., 0.0, 0.0, 0.0, 0.0},
+ {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.},
+ {0,0,0,0,0, 0,0,0,0,0} /* last line */ };
+
+ int i, j, val_exp, min_exp;
+ double nex; /* number of decades in data */
+ double logscale; /* scale in logarithmic space */
+ int exfrac = 1; /* decade spacing */
+ int mid = -1; /* row in yloglab for major grid */
+ double mspac; /* smallest major grid spacing (pixels) */
+ int flab; /* first value in yloglab to use */
+ double value, tmp, pre_value;
+ double X0,X1,Y0;
+ char graph_label[100];
- /* find grid spaceing */
- pixpex= (double)im->ysize / (log10(im->maxval) - log10(im->minval));
+ nex = log10(im->maxval / im->minval);
+ logscale = im->ysize / nex;
- if (isnan(pixpex)) {
- return 0;
- }
+ /* major spacing for data with high dynamic range */
+ while(logscale * exfrac < 3 * im->text_prop[TEXT_PROP_LEGEND].size) {
+ if(exfrac == 1) exfrac = 3;
+ else exfrac += 3;
+ }
- for(i=0;yloglab[i][0] > 0;i++){
- minstep = log10(yloglab[i][0]);
- for(ii=1;yloglab[i][ii+1] > 0;ii++){
- if(yloglab[i][ii+2]==0){
- minstep = log10(yloglab[i][ii+1])-log10(yloglab[i][ii]);
- break;
+ /* major spacing for less dynamic data */
+ do {
+ /* search best row in yloglab */
+ mid++;
+ for(i = 0; yloglab[mid][i + 1] < 10.0; i++);
+ mspac = logscale * log10(10.0 / yloglab[mid][i]);
+ } while(mspac > 2 * im->text_prop[TEXT_PROP_LEGEND].size && yloglab[mid][0] > 0);
+ if(mid) mid--;
+
+ /* find first value in yloglab */
+ for(flab = 0; yloglab[mid][flab] < 10 && frexp10(im->minval, &tmp) > yloglab[mid][flab] ; flab++);
+ if(yloglab[mid][flab] == 10.0) {
+ tmp += 1.0;
+ flab = 0;
+ }
+ val_exp = tmp;
+ if(val_exp % exfrac) val_exp += abs(-val_exp % exfrac);
+
+ X0=im->xorigin;
+ X1=im->xorigin+im->xsize;
+
+ /* draw grid */
+ pre_value = DNAN;
+ while(1) {
+
+ value = yloglab[mid][flab] * pow(10.0, val_exp);
+ if ( AlmostEqual2sComplement(value,pre_value,4) ) break; /* it seems we are not converging */
+
+ pre_value = value;
+
+ Y0 = ytr(im, value);
+ if(Y0 <= im->yorigin - im->ysize) break;
+
+ /* major grid line */
+ gfx_new_dashed_line ( im->canvas,
+ X0-2,Y0,
+ X1+2,Y0,
+ MGRIDWIDTH, im->graph_col[GRC_MGRID],
+ im->grid_dash_on, im->grid_dash_off);
+
+ /* label */
+ if (im->extra_flags & FORCE_UNITS_SI) {
+ int scale;
+ double pvalue;
+ char symbol;
+
+ scale = floor(val_exp / 3.0);
+ if( value >= 1.0 ) pvalue = pow(10.0, val_exp % 3);
+ else pvalue = pow(10.0, ((val_exp + 1) % 3) + 2);
+ pvalue *= yloglab[mid][flab];
+
+ if ( ((scale+si_symbcenter) < (int)sizeof(si_symbol)) &&
+ ((scale+si_symbcenter) >= 0) )
+ symbol = si_symbol[scale+si_symbcenter];
+ else
+ symbol = '?';
+
+ sprintf(graph_label,"%3.0f %c", pvalue, symbol);
+ } else
+ sprintf(graph_label,"%3.0e", value);
+ gfx_new_text ( im->canvas,
+ X0-im->text_prop[TEXT_PROP_AXIS].size, Y0,
+ im->graph_col[GRC_FONT],
+ im->text_prop[TEXT_PROP_AXIS].font,
+ im->text_prop[TEXT_PROP_AXIS].size,
+ im->tabwidth,0.0, GFX_H_RIGHT, GFX_V_CENTER,
+ graph_label );
+
+ /* minor grid */
+ if(mid < 4 && exfrac == 1) {
+ /* find first and last minor line behind current major line
+ * i is the first line and j tha last */
+ if(flab == 0) {
+ min_exp = val_exp - 1;
+ for(i = 1; yloglab[mid][i] < 10.0; i++);
+ i = yloglab[mid][i - 1] + 1;
+ j = 10;
+ }
+ else {
+ min_exp = val_exp;
+ i = yloglab[mid][flab - 1] + 1;
+ j = yloglab[mid][flab];
+ }
+
+ /* draw minor lines below current major line */
+ for(; i < j; i++) {
+
+ value = i * pow(10.0, min_exp);
+ if(value < im->minval) continue;
+
+ Y0 = ytr(im, value);
+ if(Y0 <= im->yorigin - im->ysize) break;
+
+ /* draw lines */
+ gfx_new_dashed_line ( im->canvas,
+ X0-1,Y0,
+ X1+1,Y0,
+ GRIDWIDTH, im->graph_col[GRC_GRID],
+ im->grid_dash_on, im->grid_dash_off);
+ }
+ }
+ else if(exfrac > 1) {
+ for(i = val_exp - exfrac / 3 * 2; i < val_exp; i += exfrac / 3) {
+ value = pow(10.0, i);
+ if(value < im->minval) continue;
+
+ Y0 = ytr(im, value);
+ if(Y0 <= im->yorigin - im->ysize) break;
+
+ /* draw lines */
+ gfx_new_dashed_line ( im->canvas,
+ X0-1,Y0,
+ X1+1,Y0,
+ GRIDWIDTH, im->graph_col[GRC_GRID],
+ im->grid_dash_on, im->grid_dash_off);
}
}
- pixperstep = pixpex * minstep;
- if(pixperstep > 5){minoridx = i;}
- if(pixperstep > 2 * im->text_prop[TEXT_PROP_LEGEND].size){majoridx = i;}
+
+ /* next decade */
+ if(yloglab[mid][++flab] == 10.0) {
+ flab = 0;
+ val_exp += exfrac;
+ }
}
-
- X0=im->xorigin;
- X1=im->xorigin+im->xsize;
- /* paint minor grid */
- for (value = pow((double)10, log10(im->minval)
- - fmod(log10(im->minval),log10(yloglab[minoridx][0])));
- value <= im->maxval;
- value *= yloglab[minoridx][0]){
- if (value < im->minval) continue;
- i=0;
- while(yloglab[minoridx][++i] > 0){
- Y0 = ytr(im,value * yloglab[minoridx][i]);
- if (Y0 <= im->yorigin - im->ysize) break;
- gfx_new_dashed_line ( im->canvas,
- X0-1,Y0,
- X1+1,Y0,
- GRIDWIDTH, im->graph_col[GRC_GRID],
- im->grid_dash_on, im->grid_dash_off);
+
+ /* draw minor lines after highest major line */
+ if(mid < 4 && exfrac == 1) {
+ /* find first and last minor line below current major line
+ * i is the first line and j tha last */
+ if(flab == 0) {
+ min_exp = val_exp - 1;
+ for(i = 1; yloglab[mid][i] < 10.0; i++);
+ i = yloglab[mid][i - 1] + 1;
+ j = 10;
+ }
+ else {
+ min_exp = val_exp;
+ i = yloglab[mid][flab - 1] + 1;
+ j = yloglab[mid][flab];
+ }
+
+ /* draw minor lines below current major line */
+ for(; i < j; i++) {
+
+ value = i * pow(10.0, min_exp);
+ if(value < im->minval) continue;
+
+ Y0 = ytr(im, value);
+ if(Y0 <= im->yorigin - im->ysize) break;
+
+ /* draw lines */
+ gfx_new_dashed_line ( im->canvas,
+ X0-1,Y0,
+ X1+1,Y0,
+ GRIDWIDTH, im->graph_col[GRC_GRID],
+ im->grid_dash_on, im->grid_dash_off);
+ }
+ }
+ /* fancy minor gridlines */
+ else if(exfrac > 1) {
+ for(i = val_exp - exfrac / 3 * 2; i < val_exp; i += exfrac / 3) {
+ value = pow(10.0, i);
+ if(value < im->minval) continue;
+
+ Y0 = ytr(im, value);
+ if(Y0 <= im->yorigin - im->ysize) break;
+
+ /* draw lines */
+ gfx_new_dashed_line ( im->canvas,
+ X0-1,Y0,
+ X1+1,Y0,
+ GRIDWIDTH, im->graph_col[GRC_GRID],
+ im->grid_dash_on, im->grid_dash_off);
}
}
- /* paint major grid and labels*/
- for (value = pow((double)10, log10(im->minval)
- - fmod(log10(im->minval),log10(yloglab[majoridx][0])));
- value <= im->maxval;
- value *= yloglab[majoridx][0]){
- if (value < im->minval) continue;
- i=0;
- while(yloglab[majoridx][++i] > 0){
- Y0 = ytr(im,value * yloglab[majoridx][i]);
- if (Y0 <= im->yorigin - im->ysize) break;
- gfx_new_dashed_line ( im->canvas,
- X0-2,Y0,
- X1+2,Y0,
- MGRIDWIDTH, im->graph_col[GRC_MGRID],
- im->grid_dash_on, im->grid_dash_off);
-
- if (im->extra_flags & FORCE_UNITS_SI) {
- double pvalue = value * yloglab[majoridx][i];
- double scale = floor( log10( fabs(pvalue)) / 3);
- char symbol;
-
- pvalue /= pow(10, 3*scale);
-
- if ( ((scale+si_symbcenter) < sizeof(si_symbol)) &&
- ((scale+si_symbcenter) >= 0) )
- symbol = si_symbol[(int)scale+si_symbcenter];
- else
- symbol = '?';
-
- sprintf(graph_label,"%3.0f %c", pvalue, symbol);
- } else
- sprintf(graph_label,"%3.0e",value * yloglab[majoridx][i]);
-
- gfx_new_text ( im->canvas,
- X0-im->text_prop[TEXT_PROP_AXIS].size, Y0,
- im->graph_col[GRC_FONT],
- im->text_prop[TEXT_PROP_AXIS].font,
- im->text_prop[TEXT_PROP_AXIS].size,
- im->tabwidth,0.0, GFX_H_RIGHT, GFX_V_CENTER,
- graph_label );
- }
- }
- return 1;
+ return 1;
}
/* yes we are loosing precision by doing tos with floats instead of doubles
but it seems more stable this way. */
-static int AlmostEqual2sComplement (float A, float B, int maxUlps)
-{
-
- int aInt = *(int*)&A;
- int bInt = *(int*)&B;
- int intDiff;
- /* Make sure maxUlps is non-negative and small enough that the
- default NAN won't compare as equal to anything. */
-
- /* assert(maxUlps > 0 && maxUlps < 4 * 1024 * 1024); */
-
- /* Make aInt lexicographically ordered as a twos-complement int */
-
- if (aInt < 0)
- aInt = 0x80000000l - aInt;
-
- /* Make bInt lexicographically ordered as a twos-complement int */
-
- if (bInt < 0)
- bInt = 0x80000000l - bInt;
-
- intDiff = abs(aInt - bInt);
-
- if (intDiff <= maxUlps)
- return 1;
-
- return 0;
-}
/* draw that picture thing ... */
int
switch(im->gdes[i].gf){
case GF_HRULE:
- if(isnan(im->gdes[i].yrule)) { /* fetch variable */
- im->gdes[i].yrule = im->gdes[im->gdes[i].vidx].vf.val;
- };
if(im->gdes[i].yrule >= im->minval
&& im->gdes[i].yrule <= im->maxval)
gfx_new_line(im->canvas,
1.0,im->gdes[i].col);
break;
case GF_VRULE:
- if(im->gdes[i].xrule == 0) { /* fetch variable */
- im->gdes[i].xrule = im->gdes[im->gdes[i].vidx].vf.when;
- };
if(im->gdes[i].xrule >= im->start
&& im->gdes[i].xrule <= im->end)
gfx_new_line(im->canvas,
im->gdes[im->gdes_c-1].col = 0x0;
im->gdes[im->gdes_c-1].legend[0]='\0';
im->gdes[im->gdes_c-1].format[0]='\0';
+ im->gdes[im->gdes_c-1].strftm=0;
im->gdes[im->gdes_c-1].rrd[0]='\0';
im->gdes[im->gdes_c-1].ds=-1;
im->gdes[im->gdes_c-1].cf_reduce=CF_AVERAGE;
case 'o':
im->logarithmic = 1;
- if (isnan(im->minval))
- im->minval=1;
break;
case 'c':
if(sscanf(optarg,
case 'W':
strncpy(im->watermark,optarg,100);
- im->watermark[99]='\0';
+ im->watermark[100]='\0';
break;
case '?':
return;
}
- if (im->logarithmic == 1 && (im->minval <= 0 || isnan(im->minval))){
+ if (im->logarithmic == 1 && im->minval <= 0){
rrd_set_error("for a logarithmic yaxis you must specify a lower-limit > 0");
return;
}
if (cnt) {
if (dst->vf.op == VDEF_TOTAL) {
dst->vf.val = sum*src->step;
- dst->vf.when = cnt*src->step; /* not really "when" */
+ dst->vf.when = 0; /* no time component */
} else {
dst->vf.val = sum/cnt;
dst->vf.when = 0; /* no time component */
if (cnt) {
if (dst->vf.op == VDEF_LSLSLOPE) {
dst->vf.val = slope;
- dst->vf.when = cnt*src->step;
+ dst->vf.when = 0;
} else if (dst->vf.op == VDEF_LSLINT) {
dst->vf.val = y_intercept;
- dst->vf.when = cnt*src->step;
+ dst->vf.when = 0;
} else if (dst->vf.op == VDEF_LSLCORREL) {
dst->vf.val = correl;
- dst->vf.when = cnt*src->step;
+ dst->vf.when = 0;
};
} else {
dst->vf.val = DNAN;
dst->vf.when = 0;
}
- }
- break;
+ }
+ break;
}
return 0;
}