prepare for the release of rrdtool-1.2.5
[rrdtool.git] / src / rrd_rpncalc.c
index 75c24cf..82683d7 100644 (file)
@@ -1,5 +1,5 @@
 /****************************************************************************
- * RRDtool 1.0.28  Copyright Tobias Oetiker, 1997 - 2002
+ * RRDtool 1.2.5  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);
@@ -157,7 +157,7 @@ void rpn_compact2str(rpn_cdefds_t *rpnc,ds_def_t *ds_def,char **str)
          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';
@@ -319,7 +319,7 @@ 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)
@@ -329,6 +329,7 @@ rpn_parse(void *key_hash,char *expr,long (*lookup)(void *,char*)){
        match_op(OP_SQRT,SQRT)
        match_op(OP_SORT,SORT)
        match_op(OP_REV,REV)
+       match_op(OP_TREND,TREND)
 #undef match_op
 
 
@@ -427,7 +428,8 @@ rpn_calc(rpnp_t *rpnp, rpnstack_t *rpnstack, long data_idx,
                rpnstack -> s[++stptr] = rpnp[rpi].val;
                break;
            case OP_VARIABLE:
-               /* Sanity check: VDEFs shouldn't make it here */
+            case OP_PREV_OTHER:
+           /* Sanity check: VDEFs shouldn't make it here */
                if (rpnp[rpi].ds_cnt == 0) {
                    rrd_set_error("VDEF made it into rpn_calc... aborting");
                    return -1;
@@ -438,7 +440,16 @@ rpn_calc(rpnp_t *rpnp, rpnstack_t *rpnstack, long data_idx,
                     * row in the rra (skip over non-relevant
                     * data sources)
                     */
-                   rpnstack -> s[++stptr] =  *(rpnp[rpi].data);
+                   if (rpnp[rpi].op == OP_VARIABLE) {
+                       rpnstack -> s[++stptr] =  *(rpnp[rpi].data);
+                   } else {
+                       if ((output_idx) <= 0) {
+                           rpnstack -> s[++stptr] = DNAN;
+                       } else {                            
+                           rpnstack -> s[++stptr] =  *(rpnp[rpi].data-rpnp[rpi].ds_cnt);
+                       }
+                      
+                   }              
                    if (data_idx % rpnp[rpi].step == 0){
                        rpnp[rpi].data += rpnp[rpi].ds_cnt;
                    }
@@ -453,15 +464,8 @@ rpn_calc(rpnp_t *rpnp, rpnstack_t *rpnstack, long data_idx,
                } else {
                    rpnstack -> s[++stptr] = output[output_idx-1];
                }
-               break;
-       case OP_PREV_OTHER:
-         if ((output_idx) <= 0) {
-               rpnstack -> s[++stptr] = DNAN;
-         } else {
-               rpnstack -> s[++stptr] = rpnp[rpnp[rpi].ptr].data[output_idx-1];
-         }
-         break;
-           case OP_UNKN:
+               break;
+        case OP_UNKN:
                rpnstack -> s[++stptr] = DNAN; 
                break;
            case OP_INF:
@@ -705,6 +709,29 @@ rpn_calc(rpnp_t *rpnp, rpnstack_t *rpnstack, long data_idx,
                    }
                }
                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;
        }