exprkt: Add sumIgnoreNaN to ignore the NaN value

Arithmetic with `nan` values is not expected in virtual sensor's case.

Adding a new exprkt function `sumIgnoreNaN` to handle this case,
that it ignores all `nan` values. If all values are `nan` then it
returns `nan`, otherwise it returns the sum of the valid values.

Example usage in json config:
```
"Expression": "sumIgnoreNaN(T0, T1, T2, T3)"
```

Signed-off-by: Lei YU <yulei.sh@bytedance.com>
Change-Id: I0cbd87f038499b4ea3ab722c003adc795a11c2b3
diff --git a/exprtkTools.hpp b/exprtkTools.hpp
index c26a1b1..a11e10a 100644
--- a/exprtkTools.hpp
+++ b/exprtkTools.hpp
@@ -69,3 +69,24 @@
         });
     }
 };
+
+template <typename T>
+struct FuncSumIgnoreNaN : public exprtk::ivararg_function<T>
+{
+    inline T operator()(const std::vector<T>& argList)
+    {
+        return std::reduce(std::begin(argList), std::end(argList),
+                           std::numeric_limits<double>::quiet_NaN(),
+                           [](auto a, auto b) {
+            if (std::isnan(b))
+            {
+                return a;
+            }
+            if (std::isnan(a))
+            {
+                return b;
+            }
+            return a + b;
+        });
+    }
+};
diff --git a/virtualSensor.cpp b/virtualSensor.cpp
index 2e58c3c..ea18c61 100644
--- a/virtualSensor.cpp
+++ b/virtualSensor.cpp
@@ -45,6 +45,7 @@
 {
 
 FuncMaxIgnoreNaN<double> VirtualSensor::funcMaxIgnoreNaN;
+FuncSumIgnoreNaN<double> VirtualSensor::funcSumIgnoreNaN;
 
 void printParams(const VirtualSensor::ParamMap& paramMap)
 {
@@ -367,6 +368,7 @@
     symbols.add_constants();
     symbols.add_package(vecopsPackage);
     symbols.add_function("maxIgnoreNaN", funcMaxIgnoreNaN);
+    symbols.add_function("sumIgnoreNaN", funcSumIgnoreNaN);
 
     expression.register_symbol_table(symbols);
 
diff --git a/virtualSensor.hpp b/virtualSensor.hpp
index bce5116..6c4bbb7 100644
--- a/virtualSensor.hpp
+++ b/virtualSensor.hpp
@@ -170,6 +170,7 @@
     std::unique_ptr<AssociationObject> associationIface;
 
     static FuncMaxIgnoreNaN<double> funcMaxIgnoreNaN;
+    static FuncSumIgnoreNaN<double> funcSumIgnoreNaN;
 
     /** @brief Read config from json object and initialize sensor data
      * for each virtual sensor