diff --git a/src/rrd_graph.c b/src/rrd_graph.c
index 6b8a46dbf1f8753edbfd234337c23e9919ebae01..fb3c7e9c1381d29f519f90f6c6e3f567a25624f3 100644 (file)
--- a/src/rrd_graph.c
+++ b/src/rrd_graph.c
/****************************************************************************
- * RRDtool 1.2.23 Copyright by Tobi Oetiker, 1997-2007
+ * RRDtool 1.2.99907080300 Copyright by Tobi Oetiker, 1997-2007
****************************************************************************
* rrd__graph.c produce graphs from data in rrdfiles
****************************************************************************/
image_desc_t *im)
{
unsigned long i, ii;
- cairo_status_t status;
+ cairo_status_t status = 0;
if (im == NULL)
return 0;
if (im->font_options)
cairo_font_options_destroy(im->font_options);
- status = cairo_status(im->cr);
-
- if (im->cr)
+ if (im->cr) {
+ status = cairo_status(im->cr);
cairo_destroy(im->cr);
+ }
if (im->surface)
cairo_surface_destroy(im->surface);
if (status)
return 0;
}
+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;
+}
+
/* massage data so, that we get one value for each x coordinate in the graph */
int data_proc(
image_desc_t *im)
}
/* adjust min and max values */
+ /* for logscale we add something on top */
if (isnan(im->minval)
- /* don't adjust low-end with log scale *//* why not? */
|| ((!im->rigid) && im->minval > minval)
) {
if (im->logarithmic)
else
im->maxval = maxval;
}
+
/* make sure min is smaller than max */
if (im->minval > im->maxval) {
- im->minval = 0.99 * im->maxval;
+ if (im->minval > 0)
+ im->minval = 0.99 * im->maxval;
+ else
+ im->minval = 1.01 * im->maxval;
}
/* make sure min and max are not equal */
- if (im->minval == im->maxval) {
- im->maxval *= 1.01;
- if (!im->logarithmic) {
- im->minval *= 0.99;
- }
+ if (AlmostEqual2sComplement(im->minval,im->maxval,4)) {
+ if (im->maxval > 0)
+ im->maxval *= 1.01;
+ else
+ im->maxval *= 0.99;
+
/* make sure min and max are not both zero */
- if (im->maxval == 0.0) {
+ if (AlmostEqual2sComplement(im->maxval,0,4)) {
im->maxval = 1.0;
}
}
/* 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;
-}
/* logaritmic horizontal grid */
int horizontal_log_grid(
long long_tmp;
struct rrd_time_value start_tv, end_tv;
long unsigned int color;
- char *old_locale = "";
+ char *old_locale = "";
/* defines for long options without a short equivalent. should be bytes,
and may not collide with (the ASCII value of) short options */
int option_index = 0;
int opt;
int col_start, col_end;
+
opt = getopt_long(argc, argv,
"s:e:x:y:v:w:h:D:iu:l:rb:oc:n:m:t:f:a:I:zgjFYAMEX:L:S:T:NR:B:W:",
long_options, &option_index);
case LONGOPT_UNITS_SI:
if (im->extra_flags & FORCE_UNITS) {
rrd_set_error("--units can only be used once!");
- setlocale(LC_NUMERIC,old_locale);
+ setlocale(LC_NUMERIC, old_locale);
return;
}
if (strcmp(optarg, "si") == 0)
im->forceleftspace = 1;
break;
case 'T':
- old_locale = setlocale(LC_NUMERIC,"C");
+ old_locale = setlocale(LC_NUMERIC, "C");
im->tabwidth = atof(optarg);
- setlocale(LC_NUMERIC,old_locale);
+ setlocale(LC_NUMERIC, old_locale);
break;
case 'S':
- old_locale = setlocale(LC_NUMERIC,"C");
+ old_locale = setlocale(LC_NUMERIC, "C");
im->step = atoi(optarg);
- setlocale(LC_NUMERIC,old_locale);
+ setlocale(LC_NUMERIC, old_locale);
break;
case 'N':
im->gridfit = 0;
im->draw_y_grid = 0;
break;
};
- old_locale=setlocale(LC_NUMERIC,"C");
+ old_locale = setlocale(LC_NUMERIC, "C");
if (sscanf(optarg, "%lf:%d", &im->ygridstep, &im->ylabfact) == 2) {
- setlocale(LC_NUMERIC,old_locale);
+ setlocale(LC_NUMERIC, old_locale);
if (im->ygridstep <= 0) {
rrd_set_error("grid step must be > 0");
return;
return;
}
} else {
- setlocale(LC_NUMERIC,old_locale);
+ setlocale(LC_NUMERIC, old_locale);
rrd_set_error("invalid y-grid format");
return;
}
im->ylegend[150] = '\0';
break;
case 'u':
- old_locale=setlocale(LC_NUMERIC,"C");
+ old_locale = setlocale(LC_NUMERIC, "C");
im->maxval = atof(optarg);
- setlocale(LC_NUMERIC,old_locale);
+ setlocale(LC_NUMERIC, old_locale);
break;
case 'l':
- old_locale=setlocale(LC_NUMERIC,"C");
+ old_locale = setlocale(LC_NUMERIC, "C");
im->minval = atof(optarg);
- setlocale(LC_NUMERIC,old_locale);
+ setlocale(LC_NUMERIC, old_locale);
break;
case 'b':
im->base = atol(optarg);
char prop[15];
double size = 1;
char font[1024] = "";
- old_locale = setlocale(LC_NUMERIC,"C");
+
+ old_locale = setlocale(LC_NUMERIC, "C");
if (sscanf(optarg, "%10[A-Z]:%lf:%1000s", prop, &size, font) >= 2) {
int sindex, propidx;
-
- setlocale(LC_NUMERIC,old_locale);
+
+ setlocale(LC_NUMERIC, old_locale);
if ((sindex = text_prop_conv(prop)) != -1) {
for (propidx = sindex; propidx < TEXT_PROP_LAST;
propidx++) {
rrd_set_error("invalid fonttag '%s'", prop);
return;
}
- } else {
- setlocale(LC_NUMERIC,old_locale);
+ } else {
+ setlocale(LC_NUMERIC, old_locale);
rrd_set_error("invalid text property format");
return;
}
break;
}
case 'm':
- old_locale=setlocale(LC_NUMERIC,"C");
+ old_locale = setlocale(LC_NUMERIC, "C");
im->zoom = atof(optarg);
- setlocale(LC_NUMERIC,old_locale);
+ setlocale(LC_NUMERIC, old_locale);
if (im->zoom <= 0.0) {
rrd_set_error("zoom factor must be > 0");
return;
double param;
char func[30];
int n;
- char *old_locale;
+ char *old_locale;
n = 0;
- old_locale = setlocale(LC_NUMERIC,"C");
+ old_locale = setlocale(LC_NUMERIC, "C");
sscanf(str, "%le,%29[A-Z]%n", ¶m, func, &n);
- setlocale(LC_NUMERIC,old_locale);
+ setlocale(LC_NUMERIC, old_locale);
if (n == (int) strlen(str)) { /* matched */
;
} else {
gdes->vf.op = VDEF_MAXIMUM;
else if (!strcmp("AVERAGE", func))
gdes->vf.op = VDEF_AVERAGE;
+ else if (!strcmp("STDEV", func))
+ gdes->vf.op = VDEF_STDEV;
else if (!strcmp("MINIMUM", func))
gdes->vf.op = VDEF_MINIMUM;
else if (!strcmp("TOTAL", func))
break;
case VDEF_MAXIMUM:
case VDEF_AVERAGE:
+ case VDEF_STDEV:
case VDEF_MINIMUM:
case VDEF_TOTAL:
case VDEF_FIRST:
}
break;
case VDEF_TOTAL:
+ case VDEF_STDEV:
case VDEF_AVERAGE:{
int cnt = 0;
double sum = 0.0;
+ double average = 0.0;
for (step = 0; step < steps; step++) {
if (finite(data[step * src->ds_cnt])) {
if (dst->vf.op == VDEF_TOTAL) {
dst->vf.val = sum * src->step;
dst->vf.when = 0; /* no time component */
- } else {
+ } else if (dst->vf.op == VDEF_AVERAGE) {
dst->vf.val = sum / cnt;
dst->vf.when = 0; /* no time component */
+ } else {
+ average = sum / cnt;
+ sum = 0.0;
+ for (step = 0; step < steps; step++) {
+ if (finite(data[step * src->ds_cnt])) {
+ sum += pow((data[step * src->ds_cnt] - average), 2.0);
+ };
+ }
+ dst->vf.val = pow(sum / cnt, 0.5);
+ dst->vf.when = 0; /* no time component */
};
} else {
dst->vf.val = DNAN;