X-Git-Url: https://git.octo.it/?p=rrdtool.git;a=blobdiff_plain;f=src%2Frrd_rpncalc.c;h=73bef2f5a8bd936d668ef718d2c0c9ad9e708b95;hp=94796d183500dbca75886514c7ff9794d3be8bb5;hb=bac209eb1d120c27acc1ede8fa7dfef81f3eaaf1;hpb=251d863a751bf92a41693228ede784a0cc77ff52 diff --git a/src/rrd_rpncalc.c b/src/rrd_rpncalc.c index 94796d1..73bef2f 100644 --- a/src/rrd_rpncalc.c +++ b/src/rrd_rpncalc.c @@ -1,5 +1,5 @@ /**************************************************************************** - * RRDtool 1.0.28 Copyright Tobias Oetiker, 1997 - 2002 + * RRDtool 1.2rc3 Copyright by Tobi Oetiker, 1997-2005 **************************************************************************** * rrd_rpncalc.c RPN calculator functions ****************************************************************************/ @@ -97,7 +97,7 @@ void rpn_compact2str(rpn_cdefds_t *rpnc,ds_def_t *ds_def,char **str) if (rpnc[i].op == OP_NUMBER) { /* convert a short into a string */ -#ifdef WIN32 +#if defined(WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__) _itoa(rpnc[i].val,buffer,10); #else sprintf(buffer,"%d",rpnc[i].val); @@ -154,7 +154,10 @@ void rpn_compact2str(rpn_cdefds_t *rpnc,ds_def_t *ds_def,char **str) add_op(OP_LTIME,LTIME) add_op(OP_TIME,TIME) add_op(OP_ATAN,ATAN) - + add_op(OP_SQRT,SQRT) + add_op(OP_SORT,SORT) + add_op(OP_REV,REV) + add_op(OP_TREND,TREND) #undef add_op } (*str)[offset] = '\0'; @@ -316,14 +319,17 @@ rpn_parse(void *key_hash,char *expr,long (*lookup)(void *,char*)){ match_op(OP_NEGINF,NEGINF) match_op(OP_NE,NE) match_op(OP_COUNT,COUNT) - match_op_param(OP_PREV_OTHER,PREV) + match_op_param(OP_PREV_OTHER,PREV) match_op(OP_PREV,PREV) match_op(OP_INF,INF) match_op(OP_ISINF,ISINF) match_op(OP_NOW,NOW) match_op(OP_TIME,TIME) match_op(OP_ATAN,ATAN) - + match_op(OP_SQRT,SQRT) + match_op(OP_SORT,SORT) + match_op(OP_REV,REV) + match_op(OP_TREND,TREND) #undef match_op @@ -367,6 +373,14 @@ rpnstack_free(rpnstack_t *rpnstack) rpnstack -> dc_stacksize = 0; } +static int +rpn_compare_double(const void *x, const void *y) +{ + double diff = *((const double *)x) - *((const double *)y); + + return (diff < 0) ? -1 : (diff > 0) ? 1 : 0; +} + /* rpn_calc: run the RPN calculator; also performs variable substitution; * moved and modified from data_calc() originally included in rrd_graph.c * arguments: @@ -660,6 +674,61 @@ rpn_calc(rpnp_t *rpnp, rpnstack_t *rpnstack, long data_idx, stackunderflow(0); rpnstack->s[stptr] = isinf(rpnstack->s[stptr]) ? 1.0 : 0.0; break; + case OP_SQRT: + stackunderflow(0); + rpnstack -> s[stptr] = sqrt(rpnstack -> s[stptr]); + break; + case OP_SORT: + stackunderflow(0); + { + int spn = (int)rpnstack -> s[stptr--]; + + stackunderflow(spn-1); + qsort(rpnstack -> s + stptr-spn+1, spn, sizeof(double), + rpn_compare_double); + } + break; + case OP_REV: + stackunderflow(0); + { + int spn = (int)rpnstack -> s[stptr--]; + double *p, *q; + + stackunderflow(spn-1); + + p = rpnstack -> s + stptr-spn+1; + q = rpnstack -> s + stptr; + while (p < q) { + double x = *q; + + *q-- = *p; + *p++ = x; + } + } + break; + case OP_TREND: + stackunderflow(1); + if ((rpi < 2) || (rpnp[rpi-2].op != OP_VARIABLE)) { + rrd_set_error("malformed trend arguments"); + return -1; + } else { + 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)) { + 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); + } else + rpnstack -> s[--stptr] = DNAN; + } + break; case OP_END: break; }