sc/source/core/opencl/op_statistical.cxx |  345 ++++++++++++-------------------
 sc/source/core/opencl/op_statistical.hxx |  125 ++++++-----
 2 files changed, 203 insertions(+), 267 deletions(-)

New commits:
commit ebc0db7acee7a470c4e41cddbb97274343899ce0
Author:     Luboš Luňák <l.lu...@collabora.com>
AuthorDate: Tue Sep 20 18:08:35 2022 +0200
Commit:     Luboš Luňák <l.lu...@collabora.com>
CommitDate: Wed Sep 21 10:23:49 2022 +0200

    fix and simplify opencl functions that calculate difference from mean
    
    ocVar, ocStDev etc. Besides the copy&paste reductions, these also
    need to use fsub_approx() otherwise they can fail with large numbers.
    
    Change-Id: Ic96caaa0d5711d811a27b0e2034db357a71b9fa1
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/140255
    Tested-by: Jenkins
    Reviewed-by: Luboš Luňák <l.lu...@collabora.com>

diff --git a/sc/source/core/opencl/op_statistical.cxx 
b/sc/source/core/opencl/op_statistical.cxx
index 1fbc80e2e00e..6441f8343daa 100644
--- a/sc/source/core/opencl/op_statistical.cxx
+++ b/sc/source/core/opencl/op_statistical.cxx
@@ -15,59 +15,9 @@
 
 using namespace formula;
 
-namespace sc::opencl {
-void OpVar::GenSlidingWindowFunction(outputstream &ss,
-            const std::string &sSymName, SubArguments &vSubArguments)
-{
-    CHECK_PARAMETER_COUNT( 1, 30 );
-    GenerateFunctionDeclaration( sSymName, vSubArguments, ss );
-    ss << "{\n";
-    ss << "    int gid0 = get_global_id(0);\n";
-    ss << "    double fSum = 0.0;\n";
-    ss << "    double fMean = 0.0;\n";
-    ss << "    double vSum = 0.0;\n";
-    ss << "    double fCount = 0.0;\n";
-    GenerateRangeArgs( vSubArguments, ss, SkipEmpty,
-        "        fSum += arg;\n"
-        "        fCount += 1.0;\n"
-        );
-    ss << "    fMean = fSum / fCount;\n";
-    GenerateRangeArgs( vSubArguments, ss, SkipEmpty,
-        "        vSum += (arg - fMean) * (arg - fMean);\n"
-        );
-    ss << "    if (fCount <= 1.0)\n";
-    ss << "        return CreateDoubleError(DivisionByZero);\n";
-    ss << "    else\n";
-    ss << "        return vSum / (fCount - 1.0);\n";
-    ss << "}\n";
-}
+#include "op_math_helpers.hxx"
 
-void OpVarP::GenSlidingWindowFunction(outputstream &ss,
-            const std::string &sSymName, SubArguments &vSubArguments)
-{
-    CHECK_PARAMETER_COUNT( 1, 30 );
-    GenerateFunctionDeclaration( sSymName, vSubArguments, ss );
-    ss << "{\n";
-    ss << "    int gid0 = get_global_id(0);\n";
-    ss << "    double fSum = 0.0;\n";
-    ss << "    double fMean = 0.0;\n";
-    ss << "    double vSum = 0.0;\n";
-    ss << "    double fCount = 0.0;\n";
-    ss << "    double arg = 0.0;\n";
-    GenerateRangeArgs( vSubArguments, ss, SkipEmpty,
-        "        fSum += arg;\n"
-        "        fCount += 1.0;\n"
-        );
-    ss << "    fMean = fSum / fCount;\n";
-    GenerateRangeArgs( vSubArguments, ss, SkipEmpty,
-        "        vSum += (arg - fMean) * (arg - fMean);\n"
-        );
-    ss << "    if (fCount == 0.0)\n";
-    ss << "        return CreateDoubleError(DivisionByZero);\n";
-    ss << "    else\n";
-    ss << "        return vSum / fCount;\n";
-    ss << "}\n";
-}
+namespace sc::opencl {
 
 void OpZTest::BinInlineFun(std::set<std::string>& decls,
     std::set<std::string>& funs)
@@ -371,77 +321,6 @@ void OpWeibull::GenSlidingWindowFunction(outputstream &ss,
     ss << "}\n";
 }
 
-void OpSkew::GenSlidingWindowFunction(outputstream &ss,
-            const std::string &sSymName, SubArguments &vSubArguments)
-{
-    CHECK_PARAMETER_COUNT( 1, 30 );
-    GenerateFunctionDeclaration( sSymName, vSubArguments, ss );
-    ss << "{\n";
-    ss << "    int gid0 = get_global_id(0);\n";
-    ss << "    double fSum = 0.0;\n";
-    ss << "    double fMean = 0.0;\n";
-    ss << "    double vSum = 0.0;\n";
-    ss << "    double fCount = 0.0;\n";
-    GenerateRangeArgs( vSubArguments, ss, SkipEmpty,
-        "        fSum += arg;\n"
-        "        fCount += 1.0;\n"
-        );
-    ss << "    if(fCount <= 2.0)\n";
-    ss << "        return CreateDoubleError(DivisionByZero);\n";
-    ss << "    else\n";
-    ss << "        fMean = fSum / fCount;\n";
-    GenerateRangeArgs( vSubArguments, ss, SkipEmpty,
-        "        vSum += (arg - fMean) * (arg - fMean);\n"
-        );
-    ss << "    double fStdDev = sqrt(vSum / (fCount - 1.0));\n";
-    ss << "    double dx = 0.0;\n";
-    ss << "    double xcube = 0.0;\n";
-    ss << "    if(fStdDev == 0.0)\n";
-    ss << "        return CreateDoubleError(IllegalArgument);\n";
-    GenerateRangeArgs( vSubArguments, ss, SkipEmpty,
-        "        dx = (arg - fMean) / fStdDev;\n"
-        "        xcube = xcube + dx * dx * dx;\n"
-        );
-    ss << "    return ((xcube * fCount) / (fCount - 1.0))";
-    ss << " / (fCount - 2.0);\n";
-    ss << "}\n";
-}
-
-void OpSkewp::GenSlidingWindowFunction(outputstream &ss,
-            const std::string &sSymName, SubArguments &vSubArguments)
-{
-    CHECK_PARAMETER_COUNT( 1, 3 );
-    GenerateFunctionDeclaration( sSymName, vSubArguments, ss );
-    ss << "{\n";
-    ss << "    int gid0 = get_global_id(0);\n";
-    ss << "    double fSum = 0.0;\n";
-    ss << "    double fMean = 0.0;\n";
-    ss << "    double vSum = 0.0;\n";
-    ss << "    double fCount = 0.0;\n";
-    GenerateRangeArgs( vSubArguments, ss, SkipEmpty,
-        "        fSum += arg;\n"
-        "        fCount += 1.0;\n"
-        );
-    ss << "    if(fCount <= 2.0)\n";
-    ss << "        return CreateDoubleError(DivisionByZero);\n";
-    ss << "    else\n";
-    ss << "        fMean = fSum / fCount;\n";
-    GenerateRangeArgs( vSubArguments, ss, SkipEmpty,
-        "        vSum += (arg - fMean) * (arg - fMean);\n"
-        );
-    ss << "    double fStdDev = sqrt(vSum / fCount);\n";
-    ss << "    double dx = 0.0;\n";
-    ss << "    double xcube = 0.0;\n";
-    ss << "    if(fStdDev == 0.0)\n";
-    ss << "        return CreateDoubleError(IllegalArgument);\n";
-    GenerateRangeArgs( vSubArguments, ss, SkipEmpty,
-        "        dx = (arg - fMean) / fStdDev;\n"
-        "        xcube = xcube + dx * dx * dx;\n"
-        );
-    ss << "    return xcube / fCount;\n";
-    ss << "}\n";
-}
-
 void OpTInv::BinInlineFun(std::set<std::string>& decls,
     std::set<std::string>& funs)
 {
@@ -492,58 +371,6 @@ void OpTInv::GenSlidingWindowFunction(outputstream &ss,
     ss << "}\n";
 }
 
-void OpStDev::GenSlidingWindowFunction(outputstream &ss,
-            const std::string &sSymName, SubArguments &vSubArguments)
-{
-    CHECK_PARAMETER_COUNT( 1, 30 );
-    GenerateFunctionDeclaration( sSymName, vSubArguments, ss );
-    ss << "{\n";
-    ss << "    int gid0 = get_global_id(0);\n";
-    ss << "    double fSum = 0.0;\n";
-    ss << "    double vSum = 0.0;\n";
-    ss << "    double fMean = 0.0;\n";
-    ss << "    double fCount = 0.0;\n";
-    GenerateRangeArgs( vSubArguments, ss, SkipEmpty,
-        "        fSum += arg;\n"
-        "        fCount += 1.0;\n"
-        );
-    ss << "    fMean = fSum / fCount;\n";
-    GenerateRangeArgs( vSubArguments, ss, SkipEmpty,
-        "        vSum += (arg - fMean) * (arg - fMean);\n"
-        );
-    ss << "    if (fCount <= 1.0)\n";
-    ss << "        return CreateDoubleError(DivisionByZero);\n";
-    ss << "    else\n";
-    ss << "        return sqrt(vSum / (fCount - 1.0));\n";
-    ss << "}\n";
-}
-
-void OpStDevP::GenSlidingWindowFunction(outputstream &ss,
-            const std::string &sSymName, SubArguments &vSubArguments)
-{
-    CHECK_PARAMETER_COUNT( 1, 30 );
-    GenerateFunctionDeclaration( sSymName, vSubArguments, ss );
-    ss << "{\n";
-    ss << "    int gid0 = get_global_id(0);\n";
-    ss << "    double fSum = 0.0;\n";
-    ss << "    double vSum = 0.0;\n";
-    ss << "    double fMean = 0.0;\n";
-    ss << "    double fCount = 0.0;\n";
-    GenerateRangeArgs( vSubArguments, ss, SkipEmpty,
-        "        fSum += arg;\n"
-        "        fCount += 1.0;\n"
-        );
-    ss << "    fMean = fSum / fCount;\n";
-    GenerateRangeArgs( vSubArguments, ss, SkipEmpty,
-        "        vSum += (arg - fMean) * (arg - fMean);\n"
-        );
-    ss << "    if (fCount <= 1.0)\n";
-    ss << "        return CreateDoubleError(DivisionByZero);\n";
-    ss << "    else\n";
-    ss << "        return sqrt(vSum / fCount);\n";
-    ss << "}\n";
-}
-
 void OpFisher::GenSlidingWindowFunction( outputstream &ss,
     const std::string &sSymName, SubArguments &vSubArguments)
 {
@@ -1163,41 +990,6 @@ void OpMedian::GenSlidingWindowFunction(
     ss <<"     return tmp;\n";
     ss << "}\n";
 }
-void OpKurt:: GenSlidingWindowFunction(outputstream &ss,
-            const std::string &sSymName, SubArguments &vSubArguments)
-{
-    CHECK_PARAMETER_COUNT( 1, 30 );
-    GenerateFunctionDeclaration( sSymName, vSubArguments, ss );
-    ss << "{\n";
-    ss << "    int gid0 = get_global_id(0);\n";
-    ss << "    double fSum = 0.0;\n";
-    ss << "    double vSum = 0.0;\n";
-    ss << "    double totallength=0;\n";
-    GenerateRangeArgs( vSubArguments, ss, SkipEmpty,
-        "        fSum += arg;\n"
-        "        totallength +=1;\n"
-        );
-    ss << "    if( totallength < 4 )\n";
-    ss << "        return CreateDoubleError(DivisionByZero);\n";
-    ss << "    double fMean = fSum / totallength;\n";
-    GenerateRangeArgs( vSubArguments, ss, SkipEmpty,
-        "        vSum += (arg-fMean)*(arg-fMean);\n"
-        );
-    ss << "    double fStdDev = sqrt(vSum / (totallength - 1.0));\n";
-    ss << "    double dx = 0.0;\n";
-    ss << "    double xpower4 = 0.0;\n";
-    GenerateRangeArgs( vSubArguments, ss, SkipEmpty,
-        "        dx = (arg -fMean) / fStdDev;\n"
-        "        xpower4 = xpower4 + (dx * dx * dx * dx);\n"
-        );
-    ss<< "    double k_d = (totallength - 2.0) * (totallength - 3.0);\n";
-    ss<< "    double k_l = totallength * (totallength + 1.0) /";
-    ss<< "((totallength - 1.0) * k_d);\n";
-    ss<< "    double k_t = 3.0 * (totallength - 1.0) * ";
-    ss<< "(totallength - 1.0) / k_d;\n";
-    ss<< "    return xpower4 * k_l - k_t;\n";
-    ss << "}";
-}
 
 void OpLogInv::BinInlineFun(std::set<std::string>& decls,
     std::set<std::string>& funs)
@@ -2394,6 +2186,139 @@ void OpRsq::GenSlidingWindowFunction(
         );
 }
 
+void OpVarStDevBase::BinInlineFun(std::set<std::string>& 
decls,std::set<std::string>& funs)
+{
+    decls.insert(is_representable_integerDecl);
+    funs.insert(is_representable_integer);
+    decls.insert(approx_equalDecl);
+    funs.insert(approx_equal);
+    decls.insert(fsub_approxDecl);
+    funs.insert(fsub_approx);
+}
+
+void OpVarStDevBase::GenerateCode(outputstream &ss, const std::string 
&sSymName, SubArguments &vSubArguments)
+{
+    CHECK_PARAMETER_COUNT( 1, 30 );
+    GenerateFunctionDeclaration( sSymName, vSubArguments, ss );
+    ss << "{\n"; // this must be matched by whoever calls this function
+    ss << "    int gid0 = get_global_id(0);\n";
+    ss << "    double fSum = 0.0;\n";
+    ss << "    double fCount = 0.0;\n";
+    GenerateRangeArgs( vSubArguments, ss, SkipEmpty,
+        "        fSum += arg;\n"
+        "        fCount += 1.0;\n"
+        );
+    ss << "    if (fCount == 0)\n";
+    ss << "        return CreateDoubleError(DivisionByZero);\n";
+    ss << "    double fMean = fSum / fCount;\n";
+    ss << "    double vSum = 0.0;\n";
+    GenerateRangeArgs( vSubArguments, ss, SkipEmpty,
+        "        vSum += pown( fsub_approx(arg, fMean), 2 );\n"
+        );
+}
+
+void OpVar::GenSlidingWindowFunction(outputstream &ss,
+            const std::string &sSymName, SubArguments &vSubArguments)
+{
+    GenerateCode( ss, sSymName, vSubArguments );
+    ss << "    if (fCount <= 1.0)\n";
+    ss << "        return CreateDoubleError(DivisionByZero);\n";
+    ss << "    else\n";
+    ss << "        return vSum / (fCount - 1.0);\n";
+    ss << "}\n";
+}
+
+void OpVarP::GenSlidingWindowFunction(outputstream &ss,
+            const std::string &sSymName, SubArguments &vSubArguments)
+{
+    GenerateCode( ss, sSymName, vSubArguments );
+    ss << "    if (fCount == 0.0)\n";
+    ss << "        return CreateDoubleError(DivisionByZero);\n";
+    ss << "    else\n";
+    ss << "        return vSum / fCount;\n";
+    ss << "}\n";
+}
+
+void OpStDev::GenSlidingWindowFunction(outputstream &ss,
+            const std::string &sSymName, SubArguments &vSubArguments)
+{
+    GenerateCode( ss, sSymName, vSubArguments );
+    ss << "    if (fCount <= 1.0)\n";
+    ss << "        return CreateDoubleError(DivisionByZero);\n";
+    ss << "    else\n";
+    ss << "        return sqrt(vSum / (fCount - 1.0));\n";
+    ss << "}\n";
+}
+
+void OpStDevP::GenSlidingWindowFunction(outputstream &ss,
+            const std::string &sSymName, SubArguments &vSubArguments)
+{
+    GenerateCode( ss, sSymName, vSubArguments );
+    ss << "    if (fCount <= 0.0)\n";
+    ss << "        return CreateDoubleError(DivisionByZero);\n";
+    ss << "    else\n";
+    ss << "        return sqrt(vSum / fCount);\n";
+    ss << "}\n";
+}
+
+void OpSkew::GenSlidingWindowFunction(outputstream &ss,
+            const std::string &sSymName, SubArguments &vSubArguments)
+{
+    GenerateCode( ss, sSymName, vSubArguments );
+    ss << "    if(fCount <= 2.0)\n";
+    ss << "        return CreateDoubleError(DivisionByZero);\n";
+    ss << "    double fStdDev = sqrt(vSum / (fCount - 1.0));\n";
+    ss << "    double dx = 0.0;\n";
+    ss << "    double xcube = 0.0;\n";
+    ss << "    if(fStdDev == 0.0)\n";
+    ss << "        return CreateDoubleError(IllegalArgument);\n";
+    GenerateRangeArgs( vSubArguments, ss, SkipEmpty,
+        "        dx = fsub_approx(arg, fMean) / fStdDev;\n"
+        "        xcube = xcube + dx * dx * dx;\n"
+        );
+    ss << "    return ((xcube * fCount) / (fCount - 1.0)) / (fCount - 2.0);\n";
+    ss << "}\n";
+}
+
+void OpSkewp::GenSlidingWindowFunction(outputstream &ss,
+            const std::string &sSymName, SubArguments &vSubArguments)
+{
+    GenerateCode( ss, sSymName, vSubArguments );
+    ss << "    if(fCount <= 2.0)\n";
+    ss << "        return CreateDoubleError(DivisionByZero);\n";
+    ss << "    double fStdDev = sqrt(vSum / fCount);\n";
+    ss << "    double dx = 0.0;\n";
+    ss << "    double xcube = 0.0;\n";
+    ss << "    if(fStdDev == 0.0)\n";
+    ss << "        return CreateDoubleError(IllegalArgument);\n";
+    GenerateRangeArgs( vSubArguments, ss, SkipEmpty,
+        "        dx = fsub_approx(arg, fMean) / fStdDev;\n"
+        "        xcube = xcube + dx * dx * dx;\n"
+        );
+    ss << "    return xcube / fCount;\n";
+    ss << "}\n";
+}
+
+void OpKurt:: GenSlidingWindowFunction(outputstream &ss,
+            const std::string &sSymName, SubArguments &vSubArguments)
+{
+    GenerateCode( ss, sSymName, vSubArguments );
+    ss << "    if( fCount < 4 )\n";
+    ss << "        return CreateDoubleError(DivisionByZero);\n";
+    ss << "    double fStdDev = sqrt(vSum / (fCount - 1.0));\n";
+    ss << "    double dx = 0.0;\n";
+    ss << "    double xpower4 = 0.0;\n";
+    GenerateRangeArgs( vSubArguments, ss, SkipEmpty,
+        "        dx = (arg -fMean) / fStdDev;\n"
+        "        xpower4 = xpower4 + (dx * dx * dx * dx);\n"
+        );
+    ss<< "    double k_d = (fCount - 2.0) * (fCount - 3.0);\n";
+    ss<< "    double k_l = fCount * (fCount + 1.0) / ((fCount - 1.0) * 
k_d);\n";
+    ss<< "    double k_t = 3.0 * (fCount - 1.0) * (fCount - 1.0) / k_d;\n";
+    ss<< "    return xpower4 * k_l - k_t;\n";
+    ss << "}";
+}
+
 void OpMin::BinInlineFun(std::set<std::string>& decls,std::set<std::string>& 
funs)
 {
     decls.insert(fmin_countDecl);
diff --git a/sc/source/core/opencl/op_statistical.hxx 
b/sc/source/core/opencl/op_statistical.hxx
index e235231ee121..64ca0c1cdf7c 100644
--- a/sc/source/core/opencl/op_statistical.hxx
+++ b/sc/source/core/opencl/op_statistical.hxx
@@ -28,22 +28,6 @@ public:
             const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual std::string BinFuncName() const override { return "ExponDist"; }
 };
-class OpVar: public Normal
-{
-public:
-    virtual void GenSlidingWindowFunction(outputstream &ss,
-            const std::string &sSymName, SubArguments &vSubArguments) override;
-    virtual std::string BinFuncName() const override { return "Var"; }
-    virtual bool canHandleMultiVector() const override { return true; }
-};
-class OpVarP: public Normal
-{
-public:
-    virtual void GenSlidingWindowFunction(outputstream &ss,
-            const std::string &sSymName, SubArguments &vSubArguments) override;
-    virtual std::string BinFuncName() const override { return "VarP"; }
-    virtual bool canHandleMultiVector() const override { return true; }
-};
 class OpZTest: public Normal
 {
 public:
@@ -52,39 +36,6 @@ public:
     virtual void BinInlineFun(std::set<std::string>& ,std::set<std::string>&) 
override;
     virtual std::string BinFuncName() const override { return "ZTest"; }
 };
-class OpStDevP: public Normal
-{
-public:
-    virtual void GenSlidingWindowFunction(outputstream &ss,
-            const std::string &sSymName, SubArguments &vSubArguments) override;
-    virtual std::string BinFuncName() const override { return "StDevP"; }
-    virtual bool canHandleMultiVector() const override { return true; }
-};
-
-class OpStDev: public Normal
-{
-public:
-    virtual void GenSlidingWindowFunction(outputstream &ss,
-            const std::string &sSymName, SubArguments &vSubArguments) override;
-    virtual std::string BinFuncName() const override { return "StDev"; }
-    virtual bool canHandleMultiVector() const override { return true; }
-};
-class OpSkew: public Normal
-{
-public:
-    virtual void GenSlidingWindowFunction(outputstream &ss,
-            const std::string &sSymName, SubArguments &vSubArguments) override;
-    virtual std::string BinFuncName() const override { return "Skew"; }
-    virtual bool canHandleMultiVector() const override { return true; }
-};
-class OpSkewp: public Normal
-{
-public:
-    virtual void GenSlidingWindowFunction(outputstream &ss,
-            const std::string &sSymName, SubArguments &vSubArguments) override;
-    virtual std::string BinFuncName() const override { return "Skewp"; }
-    virtual bool canHandleMultiVector() const override { return true; }
-};
 class OpWeibull: public Normal
 {
 public:
@@ -230,14 +181,6 @@ class OpPhi:public Normal{
             const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual std::string BinFuncName() const override { return "OpPhi"; }
 };
-class OpKurt: public Normal
-{
-public:
-    virtual void GenSlidingWindowFunction(outputstream &ss,
-            const std::string &sSymName, SubArguments &vSubArguments) override;
-    virtual std::string BinFuncName() const override { return "Kurt"; }
-    virtual bool canHandleMultiVector() const override { return true; }
-};
 
 class OpPermut:public Normal{
     public:
@@ -503,6 +446,74 @@ public:
     virtual std::string BinFuncName() const override { return "OpRsq"; }
 };
 
+class OpVarStDevBase : public Normal
+{
+public:
+    virtual void BinInlineFun(std::set<std::string>& 
decls,std::set<std::string>& funs) override;
+    virtual bool canHandleMultiVector() const override { return true; }
+protected:
+    // Generates function setup and checks, then generates a loop that will 
calculate
+    // fMean and fCount from all arguments (ranges) and then a second loop 
that will
+    // calculate vSum (pown(fsub_approx(arg,fMean),2)) from all arguments.
+    void GenerateCode( outputstream& ss, const std::string& sSymName, 
SubArguments &vSubArguments );
+};
+
+class OpVar: public OpVarStDevBase
+{
+public:
+    virtual void GenSlidingWindowFunction(outputstream &ss,
+            const std::string &sSymName, SubArguments &vSubArguments) override;
+    virtual std::string BinFuncName() const override { return "Var"; }
+};
+
+class OpVarP: public OpVarStDevBase
+{
+public:
+    virtual void GenSlidingWindowFunction(outputstream &ss,
+            const std::string &sSymName, SubArguments &vSubArguments) override;
+    virtual std::string BinFuncName() const override { return "VarP"; }
+};
+
+class OpStDev: public OpVarStDevBase
+{
+public:
+    virtual void GenSlidingWindowFunction(outputstream &ss,
+            const std::string &sSymName, SubArguments &vSubArguments) override;
+    virtual std::string BinFuncName() const override { return "StDev"; }
+};
+
+class OpStDevP: public OpVarStDevBase
+{
+public:
+    virtual void GenSlidingWindowFunction(outputstream &ss,
+            const std::string &sSymName, SubArguments &vSubArguments) override;
+    virtual std::string BinFuncName() const override { return "StDevP"; }
+};
+
+class OpSkew: public OpVarStDevBase
+{
+public:
+    virtual void GenSlidingWindowFunction(outputstream &ss,
+            const std::string &sSymName, SubArguments &vSubArguments) override;
+    virtual std::string BinFuncName() const override { return "Skew"; }
+};
+
+class OpSkewp: public OpVarStDevBase
+{
+public:
+    virtual void GenSlidingWindowFunction(outputstream &ss,
+            const std::string &sSymName, SubArguments &vSubArguments) override;
+    virtual std::string BinFuncName() const override { return "Skewp"; }
+};
+
+class OpKurt: public OpVarStDevBase
+{
+public:
+    virtual void GenSlidingWindowFunction(outputstream &ss,
+            const std::string &sSymName, SubArguments &vSubArguments) override;
+    virtual std::string BinFuncName() const override { return "Kurt"; }
+};
+
 class OpMin : public Reduction
 {
 public:

Reply via email to