summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 1edac00)
raw | patch | inline | side by side (parent: 1edac00)
author | oetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa> | |
Mon, 11 Jun 2007 19:45:42 +0000 (19:45 +0000) | ||
committer | oetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa> | |
Mon, 11 Jun 2007 19:45:42 +0000 (19:45 +0000) |
doc/rrdgraph_rpn.pod | patch | blob | history | |
src/rrd_rpncalc.c | patch | blob | history | |
src/rrd_rpncalc.h | patch | blob | history |
diff --git a/doc/rrdgraph_rpn.pod b/doc/rrdgraph_rpn.pod
index b2a84dd9daa4a1c55d3a354e9de577918e94cc14..cf62c0800b918466f7e802dd4f8b0fd00184974a 100644 (file)
--- a/doc/rrdgraph_rpn.pod
+++ b/doc/rrdgraph_rpn.pod
Example: C<CDEF:x=a,b,c,d,4,AVG>
-B<TREND>
+B<TREND, TRENDNAN>
Create a "sliding window" average of another data series.
Value at sample (t1) will be the average between (t1-delay) and (t1)
Value at sample (t2) will be the average between (t2-delay) and (t2)
+TRENDNAN is - in contrast to TREND - NAN-safe. If you use TREND and one
+source value is NAN the complete sliding window is affected. The TRENDNAN
+operation ignores all NAN-values in a sliding window and computes the
+average of the remaining values.
+
+
=item Special values
B<UNKN>
diff --git a/src/rrd_rpncalc.c b/src/rrd_rpncalc.c
index 9078b300fb83cee26a027a7b5fdda71bb019ecab..717ad42f5fc5ef8b96ff2e9c7c80ddcc9bf8cc9b 100644 (file)
--- a/src/rrd_rpncalc.c
+++ b/src/rrd_rpncalc.c
add_op(OP_SORT, SORT)
add_op(OP_REV, REV)
add_op(OP_TREND, TREND)
+ add_op(OP_TRENDNAN, TRENDNAN)
add_op(OP_RAD2DEG, RAD2DEG)
add_op(OP_DEG2RAD, DEG2RAD)
add_op(OP_AVG, AVG)
match_op(OP_SORT, SORT)
match_op(OP_REV, REV)
match_op(OP_TREND, TREND)
+ match_op(OP_TRENDNAN, TRENDNAN)
match_op(OP_RAD2DEG, RAD2DEG)
match_op(OP_DEG2RAD, DEG2RAD)
match_op(OP_AVG, AVG)
}
break;
case OP_TREND:
+ case OP_TRENDNAN:
stackunderflow(1);
if ((rpi < 2) || (rpnp[rpi - 2].op != OP_VARIABLE)) {
rrd_set_error("malformed trend arguments");
time_t step = (time_t) rpnp[rpi - 2].step;
if (output_idx > (int) ceil((float) dur / (float) step)) {
- double accum = 0.0;
- int i = 0;
-
- do {
- accum +=
- rpnp[rpi - 2].data[rpnp[rpi - 2].ds_cnt * i--];
- dur -= step;
- } while (dur > 0);
-
- rpnstack->s[--stptr] = (accum / -i);
+ int ignorenan = (rpnp[rpi].op == OP_TREND);
+ double accum = 0.0;
+ int i = 0;
+ int count = 0;
+
+ do {
+ double val =
+ rpnp[rpi - 2].data[rpnp[rpi - 2].ds_cnt * i--];
+ if (ignorenan || !isnan(val)) {
+ accum += val;
+ ++count;
+ }
+
+ dur -= step;
+ } while (dur > 0);
+
+ rpnstack -> s[--stptr] = (count == 0) ? DNAN : (accum / count);
} else
rpnstack->s[--stptr] = DNAN;
}
diff --git a/src/rrd_rpncalc.h b/src/rrd_rpncalc.h
index cc751361c7d0768b47e2e7e751082712c29bc851..54779317c0c09b8ea25789e483584e427e5ee43a 100644 (file)
--- a/src/rrd_rpncalc.h
+++ b/src/rrd_rpncalc.h
OP_COS, OP_LOG, OP_EXP, OP_LT, OP_LE, OP_GT, OP_GE, OP_EQ, OP_IF,
OP_MIN, OP_MAX, OP_LIMIT, OP_FLOOR, OP_CEIL,
OP_UN, OP_END, OP_LTIME, OP_NE, OP_ISINF, OP_PREV_OTHER, OP_COUNT,
- OP_ATAN, OP_SQRT, OP_SORT, OP_REV, OP_TREND,
+ OP_ATAN, OP_SQRT, OP_SORT, OP_REV, OP_TREND, OP_TRENDNAN,
OP_ATAN2, OP_RAD2DEG, OP_DEG2RAD,
OP_AVG, OP_ABS
};