diff --git a/src/rrd_rpncalc.c b/src/rrd_rpncalc.c
index c794c22a838ed2bfd448cd1654ab5777c5460907..80eb14450eb432c496dd588b9860b22ee8573d7f 100644 (file)
--- a/src/rrd_rpncalc.c
+++ b/src/rrd_rpncalc.c
/****************************************************************************
- * RRDtool 1.3rc9 Copyright by Tobi Oetiker, 1997-2008
+ * RRDtool 1.4.3 Copyright by Tobi Oetiker, 1997-2010
****************************************************************************
* rrd_rpncalc.c RPN calculator functions
****************************************************************************/
+#include <limits.h>
+#include <locale.h>
+#include <stdlib.h>
+
#include "rrd_tool.h"
#include "rrd_rpncalc.h"
// #include "rrd_graph.h"
-#include <limits.h>
-#include <locale.h>
short addop2str(
enum op_en op,
/* DS_CDEF_MAX_RPN_NODES is small, so at the expense of some wasted
* memory we avoid any reallocs */
rpnp = (rpnp_t *) calloc(DS_CDEF_MAX_RPN_NODES, sizeof(rpnp_t));
- if (rpnp == NULL)
+ if (rpnp == NULL) {
+ rrd_set_error("failed allocating rpnp array");
return NULL;
+ }
for (i = 0; rpnc[i].op != OP_END; ++i) {
- rpnp[i].op = (long) rpnc[i].op;
+ rpnp[i].op = (enum op_en)rpnc[i].op;
if (rpnp[i].op == OP_NUMBER) {
rpnp[i].val = (double) rpnc[i].val;
} else if (rpnp[i].op == OP_VARIABLE || rpnp[i].op == OP_PREV_OTHER) {
(*str)[offset++] = ',';
#define add_op(VV,VVV) \
- if (addop2str(rpnc[i].op, VV, VVV, str, &offset) == 1) continue;
+ if (addop2str((enum op_en)(rpnc[i].op), VV, VVV, str, &offset) == 1) continue;
if (rpnc[i].op == OP_NUMBER) {
/* convert a short into a string */
#undef add_op
#define add_op(VV,VVV) \
- if (addop2str(rpnc[i].op, VV, #VVV, str, &offset) == 1) continue;
+ if (addop2str((enum op_en)rpnc[i].op, VV, #VVV, str, &offset) == 1) continue;
add_op(OP_ADD, +)
add_op(OP_SUB, -)
add_op(OP_REV, REV)
add_op(OP_TREND, TREND)
add_op(OP_TRENDNAN, TRENDNAN)
+ add_op(OP_PREDICT, PREDICT)
+ add_op(OP_PREDICTSIGMA, PREDICTSIGMA)
add_op(OP_RAD2DEG, RAD2DEG)
add_op(OP_DEG2RAD, DEG2RAD)
add_op(OP_AVG, AVG)
match_op(OP_REV, REV)
match_op(OP_TREND, TREND)
match_op(OP_TRENDNAN, TRENDNAN)
+ match_op(OP_PREDICT, PREDICT)
+ match_op(OP_PREDICTSIGMA, PREDICTSIGMA)
match_op(OP_RAD2DEG, RAD2DEG)
match_op(OP_DEG2RAD, DEG2RAD)
match_op(OP_AVG, AVG)
if (stptr + 5 > rpnstack->dc_stacksize) {
/* could move this to a separate function */
rpnstack->dc_stacksize += rpnstack->dc_stackblock;
- rpnstack->s = rrd_realloc(rpnstack->s,
+ rpnstack->s = (double*)rrd_realloc(rpnstack->s,
(rpnstack->dc_stacksize) *
sizeof(*(rpnstack->s)));
if (rpnstack->s == NULL) {
}
}
break;
+ case OP_PREDICT:
+ case OP_PREDICTSIGMA:
+ stackunderflow(2);
+ {
+ /* the local averaging window (similar to trend, but better here, as we get better statistics thru numbers)*/
+ int locstepsize = rpnstack->s[--stptr];
+ /* the number of shifts and range-checking*/
+ int shifts = rpnstack->s[--stptr];
+ stackunderflow(shifts);
+ // handle negative shifts special
+ if (shifts<0) {
+ stptr--;
+ } else {
+ stptr-=shifts;
+ }
+ /* the real calculation */
+ double val=DNAN;
+ /* the info on the datasource */
+ time_t dsstep = (time_t) rpnp[rpi - 1].step;
+ int dscount = rpnp[rpi - 1].ds_cnt;
+ int locstep = (int)ceil((float)locstepsize/(float)dsstep);
+
+ /* the sums */
+ double sum = 0;
+ double sum2 = 0;
+ int count = 0;
+ /* now loop for each position */
+ int doshifts=shifts;
+ if (shifts<0) { doshifts=-shifts; }
+ for(int loop=0;loop<doshifts;loop++) {
+ /* calculate shift step */
+ int shiftstep=1;
+ if (shifts<0) {
+ shiftstep = loop*rpnstack->s[stptr];
+ } else {
+ shiftstep = rpnstack->s[stptr+loop];
+ }
+ if(shiftstep <0) {
+ rrd_set_error("negative shift step not allowed: %i",shiftstep);
+ return -1;
+ }
+ shiftstep=(int)ceil((float)shiftstep/(float)dsstep);
+ /* loop all local shifts */
+ for(int i=0;i<=locstep;i++) {
+ /* now calculate offset into data-array - relative to output_idx*/
+ int offset=shiftstep+i;
+ /* and process if we have index 0 of above */
+ if ((offset>=0)&&(offset<output_idx)) {
+ /* get the value */
+ val =rpnp[rpi - 1].data[-dscount * offset];
+ /* and handle the non NAN case only*/
+ if (! isnan(val)) {
+ sum+=val;
+ sum2+=val*val;
+ count++;
+ }
+ }
+ }
+ }
+ /* do the final calculations */
+ val=DNAN;
+ if (rpnp[rpi].op == OP_PREDICT) { /* the average */
+ if (count>0) {
+ val = sum/(double)count;
+ }
+ } else {
+ if (count>1) { /* the sigma case */
+ val=count*sum2-sum*sum;
+ if (val<0) {
+ val=DNAN;
+ } else {
+ val=sqrt(val/((float)count*((float)count-1.0)));
+ }
+ }
+ }
+ rpnstack->s[stptr] = val;
+ }
+ break;
case OP_TREND:
case OP_TRENDNAN:
stackunderflow(1);