X-Git-Url: https://git.octo.it/?p=rrdtool.git;a=blobdiff_plain;f=src%2Frrd_rpncalc.c;h=2bd1474e67c92b72686e43fc49629060db85a5b0;hp=7c77fdc086fa2886604e26b71538599211fc30b4;hb=9da3f4059b2daf265ebdd1e080f7ddf0d8e86f85;hpb=daf8e7ff715a59e1f9827080d1b785ffb3c5a4b1 diff --git a/src/rrd_rpncalc.c b/src/rrd_rpncalc.c index 7c77fdc..2bd1474 100644 --- a/src/rrd_rpncalc.c +++ b/src/rrd_rpncalc.c @@ -1,14 +1,16 @@ /**************************************************************************** - * RRDtool 1.3rc7 Copyright by Tobi Oetiker, 1997-2008 + * RRDtool 1.4.3 Copyright by Tobi Oetiker, 1997-2010 **************************************************************************** * rrd_rpncalc.c RPN calculator functions ****************************************************************************/ +#include +#include +#include + #include "rrd_tool.h" #include "rrd_rpncalc.h" // #include "rrd_graph.h" -#include -#include short addop2str( enum op_en op, @@ -31,8 +33,8 @@ short rpn_compact( while (rpnp[*count].op != OP_END) (*count)++; if (++(*count) > DS_CDEF_MAX_RPN_NODES) { - rrd_set_error("Maximum %d RPN nodes permitted", - DS_CDEF_MAX_RPN_NODES); + rrd_set_error("Maximum %d RPN nodes permitted. Got %d RPN nodes at present.", + DS_CDEF_MAX_RPN_NODES-1,(*count)-1); return -1; } @@ -70,10 +72,12 @@ rpnp_t *rpn_expand( /* 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) { @@ -106,7 +110,7 @@ void rpn_compact2str( (*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 */ @@ -132,7 +136,7 @@ void rpn_compact2str( #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, -) @@ -174,6 +178,8 @@ void rpn_compact2str( 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) @@ -230,9 +236,11 @@ void parseCDEF_DS( * occur too often. */ for (i = 0; rpnp[i].op != OP_END; i++) { if (rpnp[i].op == OP_TIME || rpnp[i].op == OP_LTIME || - rpnp[i].op == OP_PREV || rpnp[i].op == OP_COUNT) { + rpnp[i].op == OP_PREV || rpnp[i].op == OP_COUNT || + rpnp[i].op == OP_TREND || rpnp[i].op == OP_TRENDNAN || + rpnp[i].op == OP_PREDICT || rpnp[i].op == OP_PREDICTSIGMA ) { rrd_set_error - ("operators time, ltime, prev and count not supported with DS COMPUTE"); + ("operators TIME, LTIME, PREV COUNT TREND TRENDNAN PREDICT PREDICTSIGMA are not supported with DS COMPUTE"); free(rpnp); return; } @@ -291,7 +299,8 @@ rpnp_t *rpn_parse( char vname[MAX_VNAME_LEN + 10]; char *old_locale; - old_locale = setlocale(LC_NUMERIC, "C"); + old_locale = setlocale(LC_NUMERIC, NULL); + setlocale(LC_NUMERIC, "C"); rpnp = NULL; expr = (char *) expr_const; @@ -371,6 +380,8 @@ rpnp_t *rpn_parse( 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) @@ -461,7 +472,7 @@ short rpn_calc( 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) { @@ -784,6 +795,84 @@ short rpn_calc( } } 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;loops[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)&&(offset0) { + 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); @@ -794,7 +883,7 @@ short rpn_calc( time_t dur = (time_t) rpnstack->s[stptr]; time_t step = (time_t) rpnp[rpi - 2].step; - if (output_idx > (int) ceil((float) dur / (float) step)) { + if (output_idx + 1 >= (int) ceil((float) dur / (float) step)) { int ignorenan = (rpnp[rpi].op == OP_TREND); double accum = 0.0; int i = 0;