From: oetiker Date: Mon, 11 Jun 2007 19:45:42 +0000 (+0000) Subject: added TRENDNAN function -- Timo Stripf X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=5b16d46cb37b99d50005603382c7b0fa11ff4347;p=rrdtool.git added TRENDNAN function -- Timo Stripf git-svn-id: svn://svn.oetiker.ch/rrdtool/trunk/program@1115 a5681a0c-68f1-0310-ab6d-d61299d08faa --- diff --git a/doc/rrdgraph_rpn.pod b/doc/rrdgraph_rpn.pod index b2a84dd..cf62c08 100644 --- a/doc/rrdgraph_rpn.pod +++ b/doc/rrdgraph_rpn.pod @@ -150,7 +150,7 @@ average, ignoring all UNKNOWN values in the process. Example: C -B +B Create a "sliding window" average of another data series. @@ -174,6 +174,12 @@ average is essentially computed as shown here: 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 diff --git a/src/rrd_rpncalc.c b/src/rrd_rpncalc.c index 9078b30..717ad42 100644 --- a/src/rrd_rpncalc.c +++ b/src/rrd_rpncalc.c @@ -172,6 +172,7 @@ void rpn_compact2str( 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) @@ -364,6 +365,7 @@ rpnp_t *rpn_parse( 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) @@ -757,6 +759,7 @@ short rpn_calc( } break; case OP_TREND: + case OP_TRENDNAN: stackunderflow(1); if ((rpi < 2) || (rpnp[rpi - 2].op != OP_VARIABLE)) { rrd_set_error("malformed trend arguments"); @@ -766,16 +769,23 @@ short rpn_calc( 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 cc75136..5477931 100644 --- a/src/rrd_rpncalc.h +++ b/src/rrd_rpncalc.h @@ -16,7 +16,7 @@ enum op_en { OP_NUMBER = 0, OP_VARIABLE, OP_INF, OP_PREV, OP_NEGINF, 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 };