]> git.ipfire.org Git - thirdparty/rrdtool-1.x.git/commitdiff
added interpolation for percentile 465/head
authorMartin Sperl <kernel@martin.sperl.org>
Tue, 6 May 2014 21:37:47 +0000 (21:37 +0000)
committerMartin Sperl <kernel@martin.sperl.org>
Tue, 6 May 2014 21:37:47 +0000 (21:37 +0000)
doc/rrdgraph_rpn.pod
src/rrd_rpncalc.c

index 80b427b98ed64c7d5b55fdea15a5141ca6f153bf..fd1f309985a75e7ce6560183b7f39f18f3a0e900 100644 (file)
@@ -253,6 +253,22 @@ This also allows for extrapolation into the future (say a few days)
 - you may need to define the data series whit the optional start= parameter, so that 
 the source data series has enough data to provide prediction also at the beginning of a graph...
 
+The percentile can be between [-100:+100]. 
+The positive percentiles interpolates between values while the negative will take the closest.
+
+Example: you run 7 shifts with a window of 1800seconds. Assuming that the rrd-file
+has a step size of 300 seconds this means we have to do the percentile calculation
+based on a max of 42 distinct values (less if you got NAN). that means that in the 
+best case you get a step rate between values of 2.4 percent.
+so if you ask for the 99th percentile, then you would need to look at the 41.59th
+value. As we only have integers, either the 41st or the 42nd value.
+
+With the positive percentile a linear interpolation between the 2 values is done
+to get the effective value.
+
+The negative returns the closest value distance wise - so in the above case 42nd value,
+which is effectively returning the Percentile100 or the max of the previous 7 days in the window.
+
 Here an example, that will create a 10 day graph that also shows the 
 prediction 3 days into the future with its uncertainty value (as defined by avg+-4*sigma)
 This also shows if the prediction is exceeded at a certain point.
index 80522717200d9d95177e3dad9d3f20b9bd9365aa..1796e47bb89ec1721799408db3d80c3c5f7e09f4 100644 (file)
@@ -855,7 +855,7 @@ short rpn_calc(
                if (rpnp[rpi].op == OP_PREDICTPERC) {
                    stackunderflow(1);
                    percentile = rpnstack->s[--stptr];
-                   if ((percentile<0) || (percentile > 100)) {
+                   if (abs(percentile) > 100) {
                        rrd_set_error("unsupported percentile: %f",percentile);
                        return -1;
                    }
@@ -957,11 +957,19 @@ short rpn_calc(
                        /* sort the numbers */
                        qsort(extra,count,sizeof(double),rpn_compare_double);
                        /* get the percentile selected */
-                       int idx=(int)round(percentile * ((float)count-1.0));
-                       /* maybe we should also do an interpolation between the 2
-                        * neighboring fields, similar to what we do with MEDIAN 
-                        */
-                       val = extra[idx];
+                       double idxf = percentile * ((float)count-1.0);
+                       if (percentile < 0) { /* take the next best */
+                           int idx = round(abs(idxf));
+                           val = extra[idx];
+                       } else { /* interpolate */
+                           int idx = floor(idxf);
+                           double deltax = idxf - idx;
+                           val = extra[idx];
+                           if (deltax) { /* this check also handles the percentile=100 case */
+                             double deltay = extra[idx + 1] - extra[idx];
+                             val += deltay * deltax;
+                           }
+                       }
                    }
                    break;
                default: /* should not get here ... */