Code

a nan-safe add operator (ADDNAN) into rrd. I used it to add several incomplete graphs.
authoroetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Fri, 7 Mar 2008 08:57:01 +0000 (08:57 +0000)
committeroetiker <oetiker@a5681a0c-68f1-0310-ab6d-d61299d08faa>
Fri, 7 Mar 2008 08:57:01 +0000 (08:57 +0000)
NaN + NaN => NaN
 x + NaN => x
 NaN + y => y
 x + y => x + y

-- Timo Stripf tstripf gmx.de

git-svn-id: svn://svn.oetiker.ch/rrdtool/trunk@1303 a5681a0c-68f1-0310-ab6d-d61299d08faa

program/doc/rrdgraph_rpn.pod
program/src/rrd_rpncalc.c
program/src/rrd_rpncalc.h

index 3718349cdbba42e80e991fb461511675cf18b48c..aabd7383e43979ae6396d0fc210aa3c879a55563 100644 (file)
@@ -99,6 +99,11 @@ B<+, -, *, /, %>
 
 Add, subtract, multiply, divide, modulo
 
+B<ADDNAN>
+
+NAN-safe addition. If one parameter is NAN/UNKNOWN it'll be treated as
+zero. If both parameters are NAN/UNKNOWN, NAN/UNKNOWN will be returned.
+
 B<SIN, COS, LOG, EXP, SQRT>
 
 Sine and cosine (input in radians), log and exp (natural logarithm),
index ed086626d1d21923aae50e904ad8821ede5ee459..839643b0075101429fe4171b9297f0d3867d11d0 100644 (file)
@@ -178,6 +178,7 @@ void rpn_compact2str(
             add_op(OP_DEG2RAD, DEG2RAD)
             add_op(OP_AVG, AVG)
             add_op(OP_ABS, ABS)
+            add_op(OP_ADDNAN, ADDNAN)
 #undef add_op
     }
     (*str)[offset] = '\0';
@@ -374,6 +375,7 @@ rpnp_t   *rpn_parse(
             match_op(OP_DEG2RAD, DEG2RAD)
             match_op(OP_AVG, AVG)
             match_op(OP_ABS, ABS)
+            match_op(OP_ADDNAN, ADDNAN)
 #undef match_op
             else if ((sscanf(expr, DEF_NAM_FMT "%n", vname, &pos) == 1)
                      && ((rpnp[steps].ptr = (*lookup) (key_hash, vname)) !=
@@ -543,6 +545,19 @@ short rpn_calc(
                 + rpnstack->s[stptr];
             stptr--;
             break;
+        case OP_ADDNAN:
+            stackunderflow(1);
+                       if (isnan(rpnstack->s[stptr - 1])) {
+                   rpnstack->s[stptr - 1] = rpnstack->s[stptr];
+                       } else if (isnan(rpnstack->s[stptr])) {
+                   //rpnstack->s[stptr - 1] = rpnstack->s[stptr - 1];
+                       } else {
+                  rpnstack->s[stptr - 1] = rpnstack->s[stptr - 1]
+                   + rpnstack->s[stptr];
+                       }
+
+            stptr--;
+            break;
         case OP_SUB:
             stackunderflow(1);
             rpnstack->s[stptr - 1] = rpnstack->s[stptr - 1]
index b178f05fa2783cf109007918f5a275b0f946c996..3e4da4c796a5855fa42a08ef66348604a19a7c58 100644 (file)
@@ -18,7 +18,7 @@ enum op_en { OP_NUMBER = 0, OP_VARIABLE, OP_INF, OP_PREV, OP_NEGINF,
     OP_UN, OP_END, OP_LTIME, OP_NE, OP_ISINF, OP_PREV_OTHER, OP_COUNT,
     OP_ATAN, OP_SQRT, OP_SORT, OP_REV, OP_TREND, OP_TRENDNAN,
     OP_ATAN2, OP_RAD2DEG, OP_DEG2RAD,
-    OP_AVG, OP_ABS
+    OP_AVG, OP_ABS, OP_ADDNAN
 };
 
 typedef struct rpnp_t {