sc/Library_sc.mk                         |    1 
 sc/qa/unit/opencl-test.cxx               |   29 ++++
 sc/source/core/opencl/formulagroupcl.cxx |  193 +++++++++++++++----------------
 sc/source/core/opencl/op_addin.cxx       |    4 
 sc/source/core/opencl/op_addin.hxx       |    5 
 sc/source/core/opencl/op_array.cxx       |    6 
 sc/source/core/opencl/op_array.hxx       |    7 -
 sc/source/core/opencl/op_database.cxx    |   22 +--
 sc/source/core/opencl/op_database.hxx    |   23 +--
 sc/source/core/opencl/op_financial.cxx   |  106 ++++++++---------
 sc/source/core/opencl/op_financial.hxx   |  107 ++++++++---------
 sc/source/core/opencl/op_logical.cxx     |   10 -
 sc/source/core/opencl/op_logical.hxx     |   11 -
 sc/source/core/opencl/op_math.cxx        |  130 ++++++++++----------
 sc/source/core/opencl/op_math.hxx        |  127 ++++++++++----------
 sc/source/core/opencl/op_spreadsheet.cxx |    2 
 sc/source/core/opencl/op_spreadsheet.hxx |    3 
 sc/source/core/opencl/op_statistical.cxx |  134 ++++++++++-----------
 sc/source/core/opencl/op_statistical.hxx |  135 ++++++++++-----------
 sc/source/core/opencl/opbase.cxx         |   28 ++--
 sc/source/core/opencl/opbase.hxx         |   31 ++--
 sc/source/core/opencl/utils.cxx          |   87 +++++++++++++
 sc/source/core/opencl/utils.hxx          |   51 ++++++++
 23 files changed, 717 insertions(+), 535 deletions(-)

New commits:
commit 35ed13eba1ceb6ddab8a9a72c5ef46ab3aff8224
Author:     Luboš Luňák <l.lu...@collabora.com>
AuthorDate: Wed Aug 31 16:45:34 2022 +0200
Commit:     Luboš Luňák <l.lu...@collabora.com>
CommitDate: Thu Sep 1 12:03:33 2022 +0200

    make sure opencl generated code doesn't lose numbers precision
    
    The default precision of both iostreams and stdio is 6 decimal places.
    This means that e.g. =POWER(1.0000001,2) becomes 1, since buf << number
    will write that first number simply as '1'.
    Moroever some generated code actually doesn't compile because ambiguous
    overloads, because '1' is an integer and not a double, thus floor(1)
    is ambiguous, as there are only floating point overloads (and C/C++
    are stupid about these conversions).
    So force using a wrapper class that forces a higher precision and
    the decimal separator. For debug builds, also avoid excessive precision.
    Apparently, neither iostreams nor stdio are capable of simply printing
    a reasonable floating point representation that wouldn't be too precise
    or imprecise.
    
    Change-Id: Ifa045712d90e6a6bbe5781ac3c805c989673dc8e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139073
    Tested-by: Jenkins
    Reviewed-by: Luboš Luňák <l.lu...@collabora.com>

diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index f8e097d538a3..4fcae3e5f408 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -725,6 +725,7 @@ $(call gb_Library_add_exception_objects,sc,\
     sc/source/core/opencl/op_array \
     sc/source/core/opencl/op_logical \
     sc/source/core/opencl/op_spreadsheet \
+    sc/source/core/opencl/utils \
 )))
 
 ifeq ($(OS),LINUX)
diff --git a/sc/qa/unit/opencl-test.cxx b/sc/qa/unit/opencl-test.cxx
index 7260a9221962..71275ec2d6cf 100644
--- a/sc/qa/unit/opencl-test.cxx
+++ b/sc/qa/unit/opencl-test.cxx
@@ -33,6 +33,7 @@ public:
      * loaded and before performing formula calculation.
      */
     void enableOpenCL();
+    void disableOpenCL();
 
     virtual void setUp() override;
     virtual void tearDown() override;
@@ -67,6 +68,7 @@ public:
     void testFinacialDollardeFormula();
     void testCompilerString();
     void testCompilerInEq();
+    void testCompilerPrecision();
     void testFinacialDollarfrFormula();
     void testFinacialSYDFormula();
     void testStatisticalFormulaCorrel();
@@ -295,6 +297,7 @@ public:
     CPPUNIT_TEST(testFinacialDollardeFormula);
     CPPUNIT_TEST(testCompilerString);
     CPPUNIT_TEST(testCompilerInEq);
+    CPPUNIT_TEST(testCompilerPrecision);
     CPPUNIT_TEST(testFinacialDollarfrFormula);
     CPPUNIT_TEST(testFinacialSYDFormula);
     CPPUNIT_TEST(testStatisticalFormulaCorrel);
@@ -535,6 +538,11 @@ void ScOpenCLTest::enableOpenCL()
     sc::FormulaGroupInterpreter::enableOpenCL_UnitTestsOnly();
 }
 
+void ScOpenCLTest::disableOpenCL()
+{
+    sc::FormulaGroupInterpreter::disableOpenCL_UnitTestsOnly();
+}
+
 void ScOpenCLTest::testCompilerHorizontal()
 {
     if(!initTestEnv(u"opencl/compiler/horizontal.", FORMAT_ODS, false))
@@ -613,6 +621,27 @@ void ScOpenCLTest::testCompilerInEq()
     }
 }
 
+void ScOpenCLTest::testCompilerPrecision()
+{
+    if(!initTestEnv(u"opencl/compiler/precision.", FORMAT_ODS, false))
+        return;
+    ScDocument& rDoc = xDocSh->GetDocument();
+    ScDocument& rDocRes = xDocShRes->GetDocument();
+    // Check that values with and without opencl are the same/similar enough.
+    enableOpenCL();
+    rDoc.CalcAll();
+    disableOpenCL();
+    rDoc.CalcAll();
+
+    // Check the results of formula cells in the shared formula range.
+    for (SCROW i = 1; i < 3; ++i)
+    {
+        double fOpenCL = rDoc.GetValue(ScAddress(0, i, 0));
+        double fNormal = rDocRes.GetValue(ScAddress(0, i, 0));
+        CPPUNIT_ASSERT_DOUBLES_EQUAL(fNormal, fOpenCL, fabs(1e-14*fOpenCL));
+    }
+}
+
 #if 0
 void ScOpenCLTest::testSharedFormulaXLSStockHistory()
 {
diff --git a/sc/source/core/opencl/formulagroupcl.cxx 
b/sc/source/core/opencl/formulagroupcl.cxx
index eb2ea2fcc98b..8d959cc42dbe 100644
--- a/sc/source/core/opencl/formulagroupcl.cxx
+++ b/sc/source/core/opencl/formulagroupcl.cxx
@@ -151,7 +151,7 @@ namespace {
 
 std::string linenumberify(const std::string& s)
 {
-    std::stringstream ss;
+    outputstream ss;
     int linenumber = 1;
     size_t start = 0;
     size_t newline;
@@ -186,53 +186,57 @@ OUString LimitedString( const OUString& str )
 }
 
 // Returns formatted contents of the data (possibly shortened), to be used in 
debug output.
-OUString DebugPeekData(const FormulaToken* ref, int doubleRefIndex = 0)
+std::string DebugPeekData(const FormulaToken* ref, int doubleRefIndex = 0)
 {
     if (ref->GetType() == formula::svSingleVectorRef)
     {
         const formula::SingleVectorRefToken* pSVR =
             static_cast<const formula::SingleVectorRefToken*>(ref);
-        OUStringBuffer buf = "SingleRef {";
+        outputstream buf;
+        buf << "SingleRef {";
         for( size_t i = 0; i < std::min< size_t >( 4, pSVR->GetArrayLength()); 
++i )
         {
             if( i != 0 )
-                buf.append( "," );
+                buf << ",";
             if( pSVR->GetArray().mpNumericArray != nullptr )
-                buf.append( pSVR->GetArray().mpNumericArray[ i ] );
+                buf << pSVR->GetArray().mpNumericArray[ i ];
             else if( pSVR->GetArray().mpStringArray != nullptr )
-                buf.append( LimitedString( OUString( 
pSVR->GetArray().mpStringArray[ i ] )));
+                buf << LimitedString( OUString( 
pSVR->GetArray().mpStringArray[ i ] ));
         }
         if( pSVR->GetArrayLength() > 4 )
-            buf.append( ",..." );
-        buf.append( "}" );
-        return buf.makeStringAndClear();
+            buf << ",...";
+        buf << "}";
+        return buf.str();
     }
     else if (ref->GetType() == formula::svDoubleVectorRef)
     {
         const formula::DoubleVectorRefToken* pDVR =
             static_cast<const formula::DoubleVectorRefToken*>(ref);
-        OUStringBuffer buf = "DoubleRef {";
+        outputstream buf;
+        buf << "DoubleRef {";
         for( size_t i = 0; i < std::min< size_t >( 4, pDVR->GetArrayLength()); 
++i )
         {
             if( i != 0 )
-                buf.append( "," );
+                buf << ",";
             if( pDVR->GetArrays()[doubleRefIndex].mpNumericArray != nullptr )
-                buf.append( pDVR->GetArrays()[doubleRefIndex].mpNumericArray[ 
i ] );
+                buf << pDVR->GetArrays()[doubleRefIndex].mpNumericArray[ i ];
             else if( pDVR->GetArrays()[doubleRefIndex].mpStringArray != 
nullptr )
-                buf.append( LimitedString( OUString( 
pDVR->GetArrays()[doubleRefIndex].mpStringArray[ i ] )));
+                buf << LimitedString( OUString( 
pDVR->GetArrays()[doubleRefIndex].mpStringArray[ i ] ));
         }
         if( pDVR->GetArrayLength() > 4 )
-            buf.append( ",..." );
-        buf.append( "}" );
-        return buf.makeStringAndClear();
+            buf << ",...";
+        buf << "}";
+        return buf.str();
     }
     else if (ref->GetType() == formula::svString)
     {
-        return "String " + LimitedString( ref->GetString().getString());
+        outputstream buf;
+        buf << "String " << LimitedString( ref->GetString().getString());
+        return buf.str();
     }
     else if (ref->GetType() == formula::svDouble)
     {
-        return OUString::number(ref->GetDouble());
+        return preciseFloat(ref->GetDouble());
     }
     else
     {
@@ -241,19 +245,20 @@ OUString DebugPeekData(const FormulaToken* ref, int 
doubleRefIndex = 0)
 }
 
 // Returns formatted contents of a doubles buffer, to be used in debug output.
-OUString DebugPeekDoubles(const double* data, int size)
+std::string DebugPeekDoubles(const double* data, int size)
 {
-    OUStringBuffer buf = "{";
+    outputstream buf;
+    buf << "{";
     for( int i = 0; i < std::min( 4, size ); ++i )
     {
         if( i != 0 )
-            buf.append( "," );
-        buf.append( data[ i ] );
+            buf << ",";
+        buf << data[ i ];
     }
     if( size > 4 )
-        buf.append( ",..." );
-    buf.append( "}" );
-    return buf.makeStringAndClear();
+        buf << ",...";
+    buf << "}";
+    return buf.str();
 }
 
 } // anonymous namespace
@@ -357,21 +362,21 @@ public:
         const FormulaTreeNodeRef& ft ) :
         DynamicKernelArgument(config, s, ft) { }
     /// Generate declaration
-    virtual void GenDecl( std::stringstream& ss ) const override
+    virtual void GenDecl( outputstream& ss ) const override
     {
         ss << "unsigned " << mSymName;
     }
-    virtual void GenDeclRef( std::stringstream& ss ) const override
+    virtual void GenDeclRef( outputstream& ss ) const override
     {
         ss << GenSlidingWindowDeclRef();
     }
-    virtual void GenSlidingWindowDecl( std::stringstream& ss ) const override
+    virtual void GenSlidingWindowDecl( outputstream& ss ) const override
     {
         GenDecl(ss);
     }
     virtual std::string GenSlidingWindowDeclRef( bool = false ) const override
     {
-        std::stringstream ss;
+        outputstream ss;
         if (GetFormulaToken()->GetType() != formula::svString)
             throw Unhandled(__FILE__, __LINE__);
         FormulaToken* Tok = GetFormulaToken();
@@ -413,15 +418,15 @@ public:
         const FormulaTreeNodeRef& ft ) :
         DynamicKernelArgument(config, s, ft) { }
     /// Generate declaration
-    virtual void GenDecl( std::stringstream& ss ) const override
+    virtual void GenDecl( outputstream& ss ) const override
     {
         ss << "double " << mSymName;
     }
-    virtual void GenDeclRef( std::stringstream& ss ) const override
+    virtual void GenDeclRef( outputstream& ss ) const override
     {
         ss << mSymName;
     }
-    virtual void GenSlidingWindowDecl( std::stringstream& ss ) const override
+    virtual void GenSlidingWindowDecl( outputstream& ss ) const override
     {
         GenDecl(ss);
     }
@@ -448,7 +453,7 @@ public:
         OpenCLZone zone;
         double tmp = GetDouble();
         // Pass the scalar result back to the rest of the formula kernel
-        SAL_INFO("sc.opencl", "Kernel " << k << " arg " << argno << ": double: 
" << tmp);
+        SAL_INFO("sc.opencl", "Kernel " << k << " arg " << argno << ": double: 
" << preciseFloat( tmp ));
         cl_int err = clSetKernelArg(k, argno, sizeof(double), 
static_cast<void*>(&tmp));
         if (CL_SUCCESS != err)
             throw OpenCLError("clSetKernelArg", err, __FILE__, __LINE__);
@@ -463,15 +468,15 @@ public:
         const FormulaTreeNodeRef& ft ) :
         DynamicKernelArgument(config, s, ft) { }
     /// Generate declaration
-    virtual void GenDecl( std::stringstream& ss ) const override
+    virtual void GenDecl( outputstream& ss ) const override
     {
         ss << "double " << mSymName;
     }
-    virtual void GenDeclRef( std::stringstream& ss ) const override
+    virtual void GenDeclRef( outputstream& ss ) const override
     {
         ss << "3.14159265358979";
     }
-    virtual void GenSlidingWindowDecl( std::stringstream& ss ) const override
+    virtual void GenSlidingWindowDecl( outputstream& ss ) const override
     {
         GenDecl(ss);
     }
@@ -489,7 +494,7 @@ public:
         OpenCLZone zone;
         double tmp = 0.0;
         // Pass the scalar result back to the rest of the formula kernel
-        SAL_INFO("sc.opencl", "Kernel " << k << " arg " << argno << ": double: 
" << tmp << " (PI)");
+        SAL_INFO("sc.opencl", "Kernel " << k << " arg " << argno << ": double: 
" << preciseFloat( tmp ) << " (PI)");
         cl_int err = clSetKernelArg(k, argno, sizeof(double), 
static_cast<void*>(&tmp));
         if (CL_SUCCESS != err)
             throw OpenCLError("clSetKernelArg", err, __FILE__, __LINE__);
@@ -504,15 +509,15 @@ public:
         const FormulaTreeNodeRef& ft ) :
         DynamicKernelArgument(config, s, ft) { }
     /// Generate declaration
-    virtual void GenDecl( std::stringstream& ss ) const override
+    virtual void GenDecl( outputstream& ss ) const override
     {
         ss << "double " << mSymName;
     }
-    virtual void GenDeclRef( std::stringstream& ss ) const override
+    virtual void GenDeclRef( outputstream& ss ) const override
     {
         ss << mSymName;
     }
-    virtual void GenSlidingWindowDecl( std::stringstream& ss ) const override
+    virtual void GenSlidingWindowDecl( outputstream& ss ) const override
     {
         ss << "int " << mSymName;
     }
@@ -520,7 +525,7 @@ public:
     {
         return mSymName + "_Random(" + mSymName + ")";
     }
-    virtual void GenSlidingWindowFunction( std::stringstream& ss ) override
+    virtual void GenSlidingWindowFunction( outputstream& ss ) override
     {
         // This string is from the pi_opencl_kernel.i file as
         // generated when building the Random123 examples. Unused
@@ -871,13 +876,13 @@ public:
         const FormulaTreeNodeRef& ft, int index = 0 ) :
         VectorRef(config, s, ft, index) { }
 
-    virtual void GenSlidingWindowFunction( std::stringstream& ) override { }
+    virtual void GenSlidingWindowFunction( outputstream& ) override { }
     /// Generate declaration
-    virtual void GenDecl( std::stringstream& ss ) const override
+    virtual void GenDecl( outputstream& ss ) const override
     {
         ss << "__global unsigned int *" << mSymName;
     }
-    virtual void GenSlidingWindowDecl( std::stringstream& ss ) const override
+    virtual void GenSlidingWindowDecl( outputstream& ss ) const override
     {
         DynamicKernelStringArgument::GenDecl(ss);
     }
@@ -985,21 +990,21 @@ public:
     DynamicKernelMixedArgument( const ScCalcConfig& config, const std::string& 
s,
         const FormulaTreeNodeRef& ft ) :
         VectorRef(config, s, ft), mStringArgument(config, s + "s", ft) { }
-    virtual void GenSlidingWindowDecl( std::stringstream& ss ) const override
+    virtual void GenSlidingWindowDecl( outputstream& ss ) const override
     {
         VectorRef::GenSlidingWindowDecl(ss);
         ss << ", ";
         mStringArgument.GenSlidingWindowDecl(ss);
     }
-    virtual void GenSlidingWindowFunction( std::stringstream& ) override { }
+    virtual void GenSlidingWindowFunction( outputstream& ) override { }
     /// Generate declaration
-    virtual void GenDecl( std::stringstream& ss ) const override
+    virtual void GenDecl( outputstream& ss ) const override
     {
         VectorRef::GenDecl(ss);
         ss << ", ";
         mStringArgument.GenDecl(ss);
     }
-    virtual void GenDeclRef( std::stringstream& ss ) const override
+    virtual void GenDeclRef( outputstream& ss ) const override
     {
         VectorRef::GenDeclRef(ss);
         ss << ",";
@@ -1007,7 +1012,7 @@ public:
     }
     virtual std::string GenSlidingWindowDeclRef( bool nested ) const override
     {
-        std::stringstream ss;
+        outputstream ss;
         ss << "(!isnan(" << VectorRef::GenSlidingWindowDeclRef();
         ss << ")?" << VectorRef::GenSlidingWindowDeclRef();
         ss << ":" << mStringArgument.GenSlidingWindowDeclRef(nested);
@@ -1016,13 +1021,13 @@ public:
     }
     virtual std::string GenDoubleSlidingWindowDeclRef( bool = false ) const 
override
     {
-        std::stringstream ss;
+        outputstream ss;
         ss << VectorRef::GenSlidingWindowDeclRef();
         return ss.str();
     }
     virtual std::string GenStringSlidingWindowDeclRef( bool = false ) const 
override
     {
-        std::stringstream ss;
+        outputstream ss;
         ss << mStringArgument.GenSlidingWindowDeclRef();
         return ss.str();
     }
@@ -1067,12 +1072,12 @@ public:
             (!GetStartFixed() && !GetEndFixed()));
     }
 
-    virtual void GenSlidingWindowFunction( std::stringstream& ) { }
+    virtual void GenSlidingWindowFunction( outputstream& ) { }
 
     std::string GenSlidingWindowDeclRef( bool nested = false ) const
     {
         size_t nArrayLength = mpDVR->GetArrayLength();
-        std::stringstream ss;
+        outputstream ss;
         if (!bIsStartFixed && !bIsEndFixed)
         {
             if (nested)
@@ -1093,7 +1098,7 @@ public:
     }
     /// Controls how the elements in the DoubleVectorRef are traversed
     size_t GenReductionLoopHeader(
-        std::stringstream& ss, bool& needBody )
+        outputstream& ss, bool& needBody )
     {
         assert(mpDVR);
         size_t nCurWindowSize = mpDVR->GetRefRowSize();
@@ -1119,7 +1124,7 @@ public:
             {
                 ss << "tmpBottom = " << mpCodeGen->GetBottom() << ";\n\t";
                 ss << "{int i;\n\t";
-                std::stringstream temp1, temp2;
+                outputstream temp1, temp2;
                 int outLoopSize = UNROLLING_FACTOR;
                 if (nCurWindowSize / outLoopSize != 0)
                 {
@@ -1165,7 +1170,7 @@ public:
                 ss << "\n\t";
                 ss << "tmpBottom = " << mpCodeGen->GetBottom() << ";\n\t";
                 ss << "{int i;\n\t";
-                std::stringstream temp1, temp2;
+                outputstream temp1, temp2;
                 int outLoopSize = UNROLLING_FACTOR;
                 if (nCurWindowSize / outLoopSize != 0)
                 {
@@ -1233,21 +1238,21 @@ public:
         VectorRef(config, s, ft),
         mDoubleArgument(mCalcConfig, s, ft, CodeGen, index),
         mStringArgument(mCalcConfig, s + "s", ft, CodeGen, index) { }
-    virtual void GenSlidingWindowDecl( std::stringstream& ss ) const override
+    virtual void GenSlidingWindowDecl( outputstream& ss ) const override
     {
         mDoubleArgument.GenSlidingWindowDecl(ss);
         ss << ", ";
         mStringArgument.GenSlidingWindowDecl(ss);
     }
-    virtual void GenSlidingWindowFunction( std::stringstream& ) override { }
+    virtual void GenSlidingWindowFunction( outputstream& ) override { }
     /// Generate declaration
-    virtual void GenDecl( std::stringstream& ss ) const override
+    virtual void GenDecl( outputstream& ss ) const override
     {
         mDoubleArgument.GenDecl(ss);
         ss << ", ";
         mStringArgument.GenDecl(ss);
     }
-    virtual void GenDeclRef( std::stringstream& ss ) const override
+    virtual void GenDeclRef( outputstream& ss ) const override
     {
         mDoubleArgument.GenDeclRef(ss);
         ss << ",";
@@ -1255,7 +1260,7 @@ public:
     }
     virtual std::string GenSlidingWindowDeclRef( bool nested ) const override
     {
-        std::stringstream ss;
+        outputstream ss;
         ss << "(!isnan(" << mDoubleArgument.GenSlidingWindowDeclRef();
         ss << ")?" << mDoubleArgument.GenSlidingWindowDeclRef();
         ss << ":" << mStringArgument.GenSlidingWindowDeclRef(nested);
@@ -1264,13 +1269,13 @@ public:
     }
     virtual std::string GenDoubleSlidingWindowDeclRef( bool = false ) const 
override
     {
-        std::stringstream ss;
+        outputstream ss;
         ss << mDoubleArgument.GenSlidingWindowDeclRef();
         return ss.str();
     }
     virtual std::string GenStringSlidingWindowDeclRef( bool = false ) const 
override
     {
-        std::stringstream ss;
+        outputstream ss;
         ss << mStringArgument.GenSlidingWindowDeclRef();
         return ss.str();
     }
@@ -1297,7 +1302,7 @@ public:
     const DynamicKernelArgument* DeclRefArg(const ScCalcConfig& config, const 
FormulaTreeNodeRef&,
                                             
std::shared_ptr<SlidingFunctionBase> pCodeGen, int nResultSize);
     /// Used to generate sliding window helpers
-    void DumpSlidingWindowFunctions( std::stringstream& ss )
+    void DumpSlidingWindowFunctions( outputstream& ss )
     {
         for (auto const& argument : mParams)
         {
@@ -1350,11 +1355,11 @@ public:
     }
 
     /// Emit the definition for the auxiliary reduction kernel
-    virtual void GenSlidingWindowFunction( std::stringstream& ss );
+    virtual void GenSlidingWindowFunction( outputstream& ss );
 
     virtual std::string GenSlidingWindowDeclRef( bool ) const
     {
-        std::stringstream ss;
+        outputstream ss;
         if (!bIsStartFixed && !bIsEndFixed)
             ss << Base::GetName() << "[i + gid0]";
         else
@@ -1364,7 +1369,7 @@ public:
 
     /// Controls how the elements in the DoubleVectorRef are traversed
     size_t GenReductionLoopHeader(
-        std::stringstream& ss, int nResultSize, bool& needBody );
+        outputstream& ss, int nResultSize, bool& needBody );
 
     virtual size_t Marshal( cl_kernel k, int argno, int w, cl_program 
mpProgram );
 
@@ -1406,12 +1411,12 @@ public:
     typedef DynamicKernelSlidingArgument<DynamicKernelStringArgument> 
StringRange;
     typedef ParallelReductionVectorRef<VectorRef> ParallelNumericRange;
 
-    virtual bool HandleNaNArgument( std::stringstream&, unsigned, 
SubArguments& ) const
+    virtual bool HandleNaNArgument( outputstream&, unsigned, SubArguments& ) 
const
     {
         return false;
     }
 
-    virtual void GenSlidingWindowFunction( std::stringstream& ss,
+    virtual void GenSlidingWindowFunction( outputstream& ss,
         const std::string& sSymName, SubArguments& vSubArguments ) override
     {
         ss << "\ndouble " << sSymName;
@@ -1526,7 +1531,7 @@ public:
 class Binary : public SlidingFunctionBase
 {
 public:
-    virtual void GenSlidingWindowFunction( std::stringstream& ss,
+    virtual void GenSlidingWindowFunction( outputstream& ss,
         const std::string& sSymName, SubArguments& vSubArguments ) override
     {
         ss << "\ndouble " << sSymName;
@@ -1552,7 +1557,7 @@ public:
 class SumOfProduct : public SlidingFunctionBase
 {
 public:
-    virtual void GenSlidingWindowFunction( std::stringstream& ss,
+    virtual void GenSlidingWindowFunction( outputstream& ss,
         const std::string& sSymName, SubArguments& vSubArguments ) override
     {
         size_t nCurWindowSize = 0;
@@ -1585,7 +1590,7 @@ public:
         ss << "int currentCount0;\n";
         for (size_t i = 0; i < vSubArguments.size() - 1; i++)
             ss << "int currentCount" << i + 1 << ";\n";
-        std::stringstream temp3, temp4;
+        outputstream temp3, temp4;
         int outLoopSize = UNROLLING_FACTOR;
         if (nCurWindowSize / outLoopSize != 0)
         {
@@ -1771,7 +1776,7 @@ public:
     virtual std::string GetBottom() override { return "0"; }
     virtual std::string Gen2( const std::string& lhs, const std::string& rhs ) 
const override
     {
-        std::stringstream ss;
+        outputstream ss;
         ss << "(isnan(" << lhs << ")?" << rhs << ":" << rhs << "+1.0)";
         return ss.str();
     }
@@ -1785,7 +1790,7 @@ public:
     virtual std::string GetBottom() override { return "0"; }
     virtual std::string Gen2( const std::string& lhs, const std::string& rhs ) 
const override
     {
-        std::stringstream ss;
+        outputstream ss;
         ss << "approx_equal(" << lhs << "," << rhs << ")";
         return ss.str();
     }
@@ -1798,7 +1803,7 @@ public:
     virtual std::string GetBottom() override { return "0"; }
     virtual std::string Gen2( const std::string& lhs, const std::string& rhs ) 
const override
     {
-        std::stringstream ss;
+        outputstream ss;
         ss << "!approx_equal(" << lhs << "," << rhs << ")";
         return ss.str();
     }
@@ -1811,7 +1816,7 @@ public:
     virtual std::string GetBottom() override { return "0"; }
     virtual std::string Gen2( const std::string& lhs, const std::string& rhs ) 
const override
     {
-        std::stringstream ss;
+        outputstream ss;
         ss << "(approx_equal(" << lhs << "," << rhs << ") || " << lhs << "<=" 
<< rhs << ")";
         return ss.str();
     }
@@ -1824,7 +1829,7 @@ public:
     virtual std::string GetBottom() override { return "0"; }
     virtual std::string Gen2( const std::string& lhs, const std::string& rhs ) 
const override
     {
-        std::stringstream ss;
+        outputstream ss;
         ss << "(" << lhs << "<" << rhs << ")";
         return ss.str();
     }
@@ -1837,7 +1842,7 @@ public:
     virtual std::string GetBottom() override { return "0"; }
     virtual std::string Gen2( const std::string& lhs, const std::string& rhs ) 
const override
     {
-        std::stringstream ss;
+        outputstream ss;
         ss << "(" << lhs << ">" << rhs << ")";
         return ss.str();
     }
@@ -1850,7 +1855,7 @@ public:
     virtual std::string GetBottom() override { return "0"; }
     virtual std::string Gen2( const std::string& lhs, const std::string& rhs ) 
const override
     {
-        std::stringstream ss;
+        outputstream ss;
         ss << "(approx_equal(" << lhs << "," << rhs << ") || " << lhs << ">=" 
<< rhs << ")";
         return ss.str();
     }
@@ -1865,7 +1870,7 @@ public:
     virtual std::string GetBottom() override { return "0"; }
     virtual std::string Gen2( const std::string& lhs, const std::string& rhs ) 
const override
     {
-        std::stringstream ss;
+        outputstream ss;
         ss << "fsum_approx((" << lhs << "),(" << rhs << "))";
         return ss.str();
     }
@@ -1882,7 +1887,7 @@ public:
     virtual std::string GetBottom() override { return "0"; }
     virtual std::string Gen2( const std::string& lhs, const std::string& rhs ) 
const override
     {
-        std::stringstream ss;
+        outputstream ss;
         ss << "fsum_count(" << lhs << "," << rhs << ", &nCount)";
         return ss.str();
     }
@@ -1931,7 +1936,7 @@ public:
     }
     virtual std::string BinFuncName() const override { return "fdiv"; }
 
-    virtual bool HandleNaNArgument( std::stringstream& ss, unsigned argno, 
SubArguments& vSubArguments ) const override
+    virtual bool HandleNaNArgument( outputstream& ss, unsigned argno, 
SubArguments& vSubArguments ) const override
     {
         if (argno == 1)
         {
@@ -1996,7 +2001,7 @@ public:
 };
 
 template<class Base>
-void ParallelReductionVectorRef<Base>::GenSlidingWindowFunction( 
std::stringstream& ss )
+void ParallelReductionVectorRef<Base>::GenSlidingWindowFunction( outputstream& 
ss )
 {
     if (!dynamic_cast<OpAverage*>(mpCodeGen.get()))
     {
@@ -2178,7 +2183,7 @@ void 
ParallelReductionVectorRef<Base>::GenSlidingWindowFunction( std::stringstre
 
 template<class Base>
 size_t ParallelReductionVectorRef<Base>::GenReductionLoopHeader(
-    std::stringstream& ss, int nResultSize, bool& needBody )
+    outputstream& ss, int nResultSize, bool& needBody )
 {
     assert(mpDVR);
     size_t nCurWindowSize = mpDVR->GetRefRowSize();
@@ -2499,7 +2504,7 @@ public:
                     if (vclmem[j].mCLMem)
                         SAL_INFO("sc.opencl", "Kernel " << redKernel << " arg 
" << j << ": cl_mem: " << vclmem[j].mCLMem);
                     else
-                        SAL_INFO("sc.opencl", "Kernel " << redKernel << " arg 
" << j << ": double: " << vclmem[j].mConst);
+                        SAL_INFO("sc.opencl", "Kernel " << redKernel << " arg 
" << j << ": double: " << preciseFloat( vclmem[j].mConst ));
                     err = clSetKernelArg(redKernel, j,
                         vclmem[j].mCLMem ? sizeof(cl_mem) : sizeof(double),
                         vclmem[j].mCLMem ? 
static_cast<void*>(&vclmem[j].mCLMem) :
@@ -2548,13 +2553,13 @@ public:
         return i;
     }
 
-    virtual void GenSlidingWindowFunction( std::stringstream& ss ) override
+    virtual void GenSlidingWindowFunction( outputstream& ss ) override
     {
         for (DynamicKernelArgumentRef & rArg : mvSubArguments)
             rArg->GenSlidingWindowFunction(ss);
         mpCodeGen->GenSlidingWindowFunction(ss, mSymName, mvSubArguments);
     }
-    virtual void GenDeclRef( std::stringstream& ss ) const override
+    virtual void GenDeclRef( outputstream& ss ) const override
     {
         for (size_t i = 0; i < mvSubArguments.size(); i++)
         {
@@ -2563,7 +2568,7 @@ public:
             mvSubArguments[i]->GenDeclRef(ss);
         }
     }
-    virtual void GenDecl( std::stringstream& ss ) const override
+    virtual void GenDecl( outputstream& ss ) const override
     {
         for (SubArgumentsType::const_iterator it = mvSubArguments.begin(), e = 
mvSubArguments.end(); it != e;
             ++it)
@@ -2587,7 +2592,7 @@ public:
     }
 
     /// When declared as input to a sliding window function
-    virtual void GenSlidingWindowDecl( std::stringstream& ss ) const override
+    virtual void GenSlidingWindowDecl( outputstream& ss ) const override
     {
         for (SubArgumentsType::const_iterator it = mvSubArguments.begin(), e = 
mvSubArguments.end(); it != e;
             ++it)
@@ -2601,7 +2606,7 @@ public:
     /// or directly inline it if we are already inside a loop
     virtual std::string GenSlidingWindowDeclRef( bool nested = false ) const 
override
     {
-        std::stringstream ss;
+        outputstream ss;
         if (!nested)
         {
             ss << mSymName << "_" << mpCodeGen->BinFuncName() << "(";
@@ -2744,7 +2749,7 @@ 
DynamicKernelSoPArguments::DynamicKernelSoPArguments(const ScCalcConfig& config,
         if (!pChild)
             throw Unhandled(__FILE__, __LINE__);
         OpCode opc = pChild->GetOpCode();
-        std::stringstream tmpname;
+        outputstream tmpname;
         tmpname << s << "_" << i;
         std::string ts = tmpname.str();
         switch (opc)
@@ -3922,7 +3927,7 @@ void DynamicKernel::CodeGen()
     // Traverse the tree of expression and declare symbols used
     const DynamicKernelArgument* DK = 
mSyms.DeclRefArg<DynamicKernelSoPArguments>(mCalcConfig, mpRoot, 
std::make_shared<OpNop>(mnResultSize), mnResultSize);
 
-    std::stringstream decl;
+    outputstream decl;
     if (openclwrapper::gpuEnv.mnKhrFp64Flag)
     {
         decl << "#if __OPENCL_VERSION__ < 120\n";
@@ -3968,7 +3973,7 @@ std::string const & DynamicKernel::GetMD5()
 {
     if (mKernelHash.empty())
     {
-        std::stringstream md5s;
+        outputstream md5s;
         // Compute MD5SUM of kernel body to obtain the name
         sal_uInt8 result[RTL_DIGEST_LENGTH_MD5];
         rtl_digest_MD5(
@@ -4152,7 +4157,7 @@ const DynamicKernelArgument* 
SymbolTable::DeclRefArg(const ScCalcConfig& config,
     if (it == mSymbols.end())
     {
         // Allocate new symbols
-        std::stringstream ss;
+        outputstream ss;
         ss << "tmp" << mCurId++;
         DynamicKernelArgumentRef new_arg = std::make_shared<T>(config, 
ss.str(), t, std::move(pCodeGen), nResultSize);
         mSymbols[ref] = new_arg;
diff --git a/sc/source/core/opencl/op_addin.cxx 
b/sc/source/core/opencl/op_addin.cxx
index 8a42de3232ff..78a98a9bf9db 100644
--- a/sc/source/core/opencl/op_addin.cxx
+++ b/sc/source/core/opencl/op_addin.cxx
@@ -16,7 +16,7 @@ using namespace formula;
 
 namespace sc::opencl {
 
-void OpBesselj::GenSlidingWindowFunction(std::stringstream &ss,
+void OpBesselj::GenSlidingWindowFunction(outputstream &ss,
     const std::string &sSymName, SubArguments &vSubArguments)
 {
     CHECK_PARAMETER_COUNT( 2, 2 );
@@ -177,7 +177,7 @@ void OpBesselj::GenSlidingWindowFunction(std::stringstream 
&ss,
     ss << "}";
 }
 void OpGestep::GenSlidingWindowFunction(
-    std::stringstream &ss,const std::string &sSymName,
+    outputstream &ss,const std::string &sSymName,
     SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
diff --git a/sc/source/core/opencl/op_addin.hxx 
b/sc/source/core/opencl/op_addin.hxx
index 96f89968b341..5a5799377c1e 100644
--- a/sc/source/core/opencl/op_addin.hxx
+++ b/sc/source/core/opencl/op_addin.hxx
@@ -10,20 +10,21 @@
 #pragma once
 
 #include "opbase.hxx"
+#include "utils.hxx"
 
 namespace sc::opencl {
 
 class OpBesselj: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
         const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual std::string BinFuncName() const override { return "Besselj"; }
 };
 class OpGestep: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
         const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual std::string BinFuncName() const override { return "Gestep"; }
 };
diff --git a/sc/source/core/opencl/op_array.cxx 
b/sc/source/core/opencl/op_array.cxx
index c745ec8a154b..cf54a5be8b92 100644
--- a/sc/source/core/opencl/op_array.cxx
+++ b/sc/source/core/opencl/op_array.cxx
@@ -16,7 +16,7 @@ using namespace formula;
 
 namespace sc::opencl {
 
-void OpSumX2MY2::GenSlidingWindowFunction(std::stringstream &ss,
+void OpSumX2MY2::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -73,7 +73,7 @@ void OpSumX2MY2::GenSlidingWindowFunction(std::stringstream 
&ss,
     ss << "}";
 }
 
-void OpSumX2PY2::GenSlidingWindowFunction(std::stringstream &ss,
+void OpSumX2PY2::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -129,7 +129,7 @@ void OpSumX2PY2::GenSlidingWindowFunction(std::stringstream 
&ss,
     ss << "    return tmp;\n";
     ss << "}";
 }
-void OpSumXMY2::GenSlidingWindowFunction(std::stringstream &ss,
+void OpSumXMY2::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
diff --git a/sc/source/core/opencl/op_array.hxx 
b/sc/source/core/opencl/op_array.hxx
index cd0ba8c135a9..20ee011887de 100644
--- a/sc/source/core/opencl/op_array.hxx
+++ b/sc/source/core/opencl/op_array.hxx
@@ -9,13 +9,14 @@
 #pragma once
 
 #include "opbase.hxx"
+#include "utils.hxx"
 
 namespace sc::opencl {
 
 class OpSumX2MY2: public CheckVariables
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual std::string BinFuncName() const override { return "SumX2MY2"; }
 };
@@ -23,7 +24,7 @@ public:
 class OpSumX2PY2: public CheckVariables
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual std::string BinFuncName() const override { return "SumX2PY2"; }
 };
@@ -31,7 +32,7 @@ public:
 class OpSumXMY2: public CheckVariables
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual std::string BinFuncName() const override { return "SumXMY2"; }
 };
diff --git a/sc/source/core/opencl/op_database.cxx 
b/sc/source/core/opencl/op_database.cxx
index b3fc72d408c3..2a76a4171501 100644
--- a/sc/source/core/opencl/op_database.cxx
+++ b/sc/source/core/opencl/op_database.cxx
@@ -14,7 +14,7 @@
 
 namespace sc::opencl {
 
-void OpDmax::GenSlidingWindowFunction(std::stringstream &ss,
+void OpDmax::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -141,7 +141,7 @@ void OpDmax::GenSlidingWindowFunction(std::stringstream &ss,
     ss << "}";
 }
 
-void OpDmin::GenSlidingWindowFunction(std::stringstream &ss,
+void OpDmin::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -269,7 +269,7 @@ void OpDmin::GenSlidingWindowFunction(std::stringstream &ss,
     ss << "}";
 }
 
-void OpDproduct::GenSlidingWindowFunction(std::stringstream &ss,
+void OpDproduct::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -395,7 +395,7 @@ void OpDproduct::GenSlidingWindowFunction(std::stringstream 
&ss,
     ss << "}";
 }
 
-void OpDaverage::GenSlidingWindowFunction(std::stringstream &ss,
+void OpDaverage::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -526,7 +526,7 @@ void OpDaverage::GenSlidingWindowFunction(std::stringstream 
&ss,
     ss << "}";
 }
 
-void OpDstdev::GenSlidingWindowFunction(std::stringstream &ss,
+void OpDstdev::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -708,7 +708,7 @@ void OpDstdev::GenSlidingWindowFunction(std::stringstream 
&ss,
     ss << "}";
 }
 
-void OpDstdevp::GenSlidingWindowFunction(std::stringstream &ss,
+void OpDstdevp::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -890,7 +890,7 @@ void OpDstdevp::GenSlidingWindowFunction(std::stringstream 
&ss,
     ss << "}";
 }
 
-void OpDsum::GenSlidingWindowFunction(std::stringstream &ss,
+void OpDsum::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -1017,7 +1017,7 @@ void OpDsum::GenSlidingWindowFunction(std::stringstream 
&ss,
     ss << "}";
 }
 
-void OpDvar::GenSlidingWindowFunction(std::stringstream &ss,
+void OpDvar::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -1199,7 +1199,7 @@ void OpDvar::GenSlidingWindowFunction(std::stringstream 
&ss,
     ss << "}";
 }
 
-void OpDvarp::GenSlidingWindowFunction(std::stringstream &ss,
+void OpDvarp::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -1381,7 +1381,7 @@ void OpDvarp::GenSlidingWindowFunction(std::stringstream 
&ss,
     ss << "}";
 }
 
-void OpDcount::GenSlidingWindowFunction(std::stringstream &ss,
+void OpDcount::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -1509,7 +1509,7 @@ void OpDcount::GenSlidingWindowFunction(std::stringstream 
&ss,
     ss << "}";
 }
 
-void OpDcount2::GenSlidingWindowFunction(std::stringstream &ss,
+void OpDcount2::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
diff --git a/sc/source/core/opencl/op_database.hxx 
b/sc/source/core/opencl/op_database.hxx
index effacc1235f2..462b491d7265 100644
--- a/sc/source/core/opencl/op_database.hxx
+++ b/sc/source/core/opencl/op_database.hxx
@@ -10,13 +10,14 @@
 #pragma once
 
 #include "opbase.hxx"
+#include "utils.hxx"
 
 namespace sc::opencl {
 
 class OpDmax: public CheckVariables
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
              const std::string &sSymName, SubArguments &vSubArguments) 
override;
     virtual std::string BinFuncName() const override { return "Dmax"; }
 };
@@ -24,7 +25,7 @@ public:
 class OpDmin: public CheckVariables
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
              const std::string &sSymName, SubArguments &vSubArguments) 
override;
     virtual std::string BinFuncName() const override { return "Dmin"; }
 };
@@ -32,7 +33,7 @@ public:
 class OpDproduct: public CheckVariables
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
              const std::string &sSymName, SubArguments &vSubArguments) 
override;
     virtual std::string BinFuncName() const override { return "Dproduct"; }
 };
@@ -40,7 +41,7 @@ public:
 class OpDaverage: public CheckVariables
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
              const std::string &sSymName, SubArguments &vSubArguments) 
override;
     virtual std::string BinFuncName() const override { return "Daverage"; }
 };
@@ -48,7 +49,7 @@ public:
 class OpDstdev: public CheckVariables
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
              const std::string &sSymName, SubArguments &vSubArguments) 
override;
     virtual std::string BinFuncName() const override { return "Dstdev"; }
 };
@@ -56,7 +57,7 @@ public:
 class OpDstdevp: public CheckVariables
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
              const std::string &sSymName, SubArguments &vSubArguments) 
override;
     virtual std::string BinFuncName() const override { return "Dstdevp"; }
 };
@@ -64,7 +65,7 @@ public:
 class OpDsum: public CheckVariables
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
              const std::string &sSymName, SubArguments &vSubArguments) 
override;
     virtual std::string BinFuncName() const override { return "Dsum"; }
 };
@@ -72,7 +73,7 @@ public:
 class OpDvar: public CheckVariables
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
              const std::string &sSymName, SubArguments &vSubArguments) 
override;
     virtual std::string BinFuncName() const override { return "Dvar"; }
 };
@@ -80,7 +81,7 @@ public:
 class OpDvarp: public CheckVariables
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
              const std::string &sSymName, SubArguments &vSubArguments) 
override;
     virtual std::string BinFuncName() const override { return "Dvarp"; }
 };
@@ -88,7 +89,7 @@ public:
 class OpDcount: public CheckVariables
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
              const std::string &sSymName, SubArguments &vSubArguments) 
override;
     virtual std::string BinFuncName() const override { return "Dcount"; }
 };
@@ -96,7 +97,7 @@ public:
 class OpDcount2: public CheckVariables
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
              const std::string &sSymName, SubArguments &vSubArguments) 
override;
     virtual std::string BinFuncName() const override { return "Dcount2"; }
 };
diff --git a/sc/source/core/opencl/op_financial.cxx 
b/sc/source/core/opencl/op_financial.cxx
index 342bd67b2657..e3362ed08441 100644
--- a/sc/source/core/opencl/op_financial.cxx
+++ b/sc/source/core/opencl/op_financial.cxx
@@ -19,7 +19,7 @@ namespace sc::opencl {
 #include "opinlinefun_finacial.cxx"
 
 void RRI::GenSlidingWindowFunction(
-    std::stringstream &ss, const std::string &sSymName, SubArguments 
&vSubArguments)
+    outputstream &ss, const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
     ss << "_"<< BinFuncName() <<"(";
@@ -88,7 +88,7 @@ void RRI::GenSlidingWindowFunction(
 }
 
 void OpNominal::GenSlidingWindowFunction(
-    std::stringstream &ss, const std::string &sSymName, SubArguments &
+    outputstream &ss, const std::string &sSymName, SubArguments &
 vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -146,7 +146,7 @@ vSubArguments)
 }
 
 void OpDollarde::GenSlidingWindowFunction(
-    std::stringstream &ss, const std::string &sSymName, SubArguments 
&vSubArguments)
+    outputstream &ss, const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
     ss << "_"<< BinFuncName() <<"(";
@@ -196,7 +196,7 @@ void OpDollarde::GenSlidingWindowFunction(
     ss << "}";
 }
 
-void OpDollarfr::GenSlidingWindowFunction(std::stringstream &ss,
+void OpDollarfr::GenSlidingWindowFunction(outputstream &ss,
         const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -256,7 +256,7 @@ void OpDISC::BinInlineFun(std::set<std::string>& decls,
     funs.insert(DaysInMonth);funs.insert(IsLeapYear);
 }
 
-void OpDISC::GenSlidingWindowFunction(std::stringstream& ss,
+void OpDISC::GenSlidingWindowFunction(outputstream& ss,
     const std::string &sSymName, SubArguments& vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -327,7 +327,7 @@ void OpINTRATE::BinInlineFun(std::set<std::string>& decls,
     funs.insert(IsLeapYear);
 }
 
-void OpINTRATE::GenSlidingWindowFunction(std::stringstream& ss,
+void OpINTRATE::GenSlidingWindowFunction(outputstream& ss,
     const std::string &sSymName, SubArguments& vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -391,7 +391,7 @@ void OpFV::BinInlineFun(std::set<std::string>& decls,
     funs.insert(GetFV);
 }
 
-void OpFV::GenSlidingWindowFunction(std::stringstream& ss,
+void OpFV::GenSlidingWindowFunction(outputstream& ss,
     const std::string &sSymName, SubArguments& vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -441,7 +441,7 @@ void OpIPMT::BinInlineFun(std::set<std::string>& decls,
     funs.insert(GetFV);
 }
 
-void OpIPMT::GenSlidingWindowFunction(std::stringstream& ss,
+void OpIPMT::GenSlidingWindowFunction(outputstream& ss,
     const std::string &sSymName, SubArguments& vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -509,7 +509,7 @@ void OpIPMT::GenSlidingWindowFunction(std::stringstream& ss,
     ss << "    return tmp;\n";
     ss << "}";
 }
-void OpISPMT::GenSlidingWindowFunction(std::stringstream& ss,
+void OpISPMT::GenSlidingWindowFunction(outputstream& ss,
     const std::string &sSymName, SubArguments& vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -563,7 +563,7 @@ void OpISPMT::GenSlidingWindowFunction(std::stringstream& 
ss,
     ss << "}";
 }
 
-void OpPDuration::GenSlidingWindowFunction(std::stringstream& ss,
+void OpPDuration::GenSlidingWindowFunction(outputstream& ss,
     const std::string &sSymName, SubArguments& vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -629,7 +629,7 @@ void OpDuration_ADD::BinInlineFun(std::set<std::string>& 
decls,
     funs.insert(DaysInMonth);funs.insert(IsLeapYear);
 }
 
-void OpDuration_ADD::GenSlidingWindowFunction(std::stringstream& ss,
+void OpDuration_ADD::GenSlidingWindowFunction(outputstream& ss,
     const std::string &sSymName, SubArguments& vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -689,7 +689,7 @@ void OpMDuration::BinInlineFun(std::set<std::string>& decls,
     funs.insert(DaysInMonth);funs.insert(IsLeapYear);
 }
 
-void OpMDuration::GenSlidingWindowFunction(std::stringstream& ss,
+void OpMDuration::GenSlidingWindowFunction(outputstream& ss,
     const std::string &sSymName, SubArguments& vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -748,7 +748,7 @@ void 
OpMDuration::GenSlidingWindowFunction(std::stringstream& ss,
     ss << "}";
 }
 void Fvschedule::GenSlidingWindowFunction(
-    std::stringstream &ss, const std::string &sSymName, SubArguments 
&vSubArguments)
+    outputstream &ss, const std::string &sSymName, SubArguments &vSubArguments)
 {
     CHECK_PARAMETER_COUNT( 2, 2 );
     FormulaToken* pCur = vSubArguments[1]->GetFormulaToken();
@@ -793,7 +793,7 @@ void Cumipmt::BinInlineFun(std::set<std::string>& decls,
     funs.insert(GetPMT_new);funs.insert(GetFV_new);
 }
 void Cumipmt::GenSlidingWindowFunction(
-    std::stringstream &ss, const std::string &sSymName, SubArguments &
+    outputstream &ss, const std::string &sSymName, SubArguments &
 vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -907,7 +907,7 @@ vSubArguments)
     ss <<"}";
 }
 
-void IRR::GenSlidingWindowFunction(std::stringstream &ss,
+void IRR::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -1068,7 +1068,7 @@ void IRR::GenSlidingWindowFunction(std::stringstream &ss,
 }
 
 void XNPV::GenSlidingWindowFunction(
-    std::stringstream &ss, const std::string &sSymName, SubArguments 
&vSubArguments)
+    outputstream &ss, const std::string &sSymName, SubArguments &vSubArguments)
 {
     FormulaToken *pCur = vSubArguments[1]->GetFormulaToken();
     assert(pCur);
@@ -1179,7 +1179,7 @@ void XNPV::GenSlidingWindowFunction(
     funs.insert(DaysInMonth);funs.insert(IsLeapYear);
 }
 void PriceMat::GenSlidingWindowFunction(
-    std::stringstream &ss, const std::string &sSymName, SubArguments 
&vSubArguments)
+    outputstream &ss, const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
     ss << "_"<< BinFuncName() <<"(";
@@ -1289,7 +1289,7 @@ void PriceMat::GenSlidingWindowFunction(
     ss<<"}\n";
 }
 
-void OpSYD::GenSlidingWindowFunction(std::stringstream &ss,
+void OpSYD::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -1373,7 +1373,7 @@ void OpSYD::GenSlidingWindowFunction(std::stringstream 
&ss,
 }
 
 void MIRR::GenSlidingWindowFunction(
-    std::stringstream &ss, const std::string &sSymName, SubArguments 
&vSubArguments)
+    outputstream &ss, const std::string &sSymName, SubArguments &vSubArguments)
 {
     FormulaToken* pCur = vSubArguments[0]->GetFormulaToken();
     assert(pCur);
@@ -1446,7 +1446,7 @@ void MIRR::GenSlidingWindowFunction(
     ss << "}";
 }
 
-void OpEffective::GenSlidingWindowFunction(std::stringstream& ss,
+void OpEffective::GenSlidingWindowFunction(outputstream& ss,
     const std::string &sSymName, SubArguments& vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -1511,7 +1511,7 @@ void 
OpEffective::GenSlidingWindowFunction(std::stringstream& ss,
     funs.insert(IsLeapYear);
 }
 void OpTbilleq::GenSlidingWindowFunction(
-    std::stringstream &ss, const std::string &sSymName, SubArguments 
&vSubArguments)
+    outputstream &ss, const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
     ss << "_"<< BinFuncName() <<"(";
@@ -1588,7 +1588,7 @@ void OpCumprinc::BinInlineFun(std::set<std::string>& 
decls,
     decls.insert(GetPMT_newDecl); decls.insert(GetFV_newDecl);
     funs.insert(GetPMT_new);funs.insert(GetFV_new);
 }
-void OpCumprinc::GenSlidingWindowFunction(std::stringstream &ss,
+void OpCumprinc::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -1714,7 +1714,7 @@ void OpAccrint::BinInlineFun(std::set<std::string>& decls,
     funs.insert(GetNullDate);funs.insert(GetDiffDate);
 }
 void OpAccrint::GenSlidingWindowFunction(
-    std::stringstream &ss, const std::string &sSymName,
+    outputstream &ss, const std::string &sSymName,
     SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -1829,7 +1829,7 @@ void OpAccrintm::BinInlineFun(std::set<std::string>& 
decls,
     funs.insert(GetNullDate);funs.insert(GetDiffDate);
 }
 void OpAccrintm::GenSlidingWindowFunction(
-    std::stringstream &ss, const std::string &sSymName, SubArguments 
&vSubArguments)
+    outputstream &ss, const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
     ss << "_"<< BinFuncName() <<"(";
@@ -1956,7 +1956,7 @@ void OpAccrintm::GenSlidingWindowFunction(
 }
 
 void OpYield::GenSlidingWindowFunction(
-    std::stringstream &ss, const std::string &sSymName, SubArguments 
&vSubArguments)
+    outputstream &ss, const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
     ss << "_"<< BinFuncName() <<"(";
@@ -2095,7 +2095,7 @@ void OpYield::GenSlidingWindowFunction(
     ss << "}";
 }
 
-void OpSLN::GenSlidingWindowFunction(std::stringstream &ss,
+void OpSLN::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -2172,7 +2172,7 @@ void OpSLN::GenSlidingWindowFunction(std::stringstream 
&ss,
 }
 
 void OpYieldmat::GenSlidingWindowFunction(
-    std::stringstream &ss, const std::string &sSymName, SubArguments 
&vSubArguments)
+    outputstream &ss, const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
     ss << "_"<< BinFuncName() <<"(";
@@ -2294,7 +2294,7 @@ void OpYieldmat::GenSlidingWindowFunction(
     ss << "}";
 }
 
-void OpPMT::GenSlidingWindowFunction(std::stringstream &ss,
+void OpPMT::GenSlidingWindowFunction(outputstream &ss,
         const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -2354,7 +2354,7 @@ void OpPMT::GenSlidingWindowFunction(std::stringstream 
&ss,
     ss<<"}";
 }
 
-void OpNPV::GenSlidingWindowFunction(std::stringstream &ss,
+void OpNPV::GenSlidingWindowFunction(outputstream &ss,
     const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -2484,7 +2484,7 @@ void OpNPV::GenSlidingWindowFunction(std::stringstream 
&ss,
     funs.insert(lcl_Getcoupnum_new);
     funs.insert(coupnum_new);funs.insert(getPrice_new);
  }
-void OpPrice::GenSlidingWindowFunction(std::stringstream &ss,
+void OpPrice::GenSlidingWindowFunction(outputstream &ss,
           const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -2558,7 +2558,7 @@ void OpOddlprice::BinInlineFun(std::set<std::string>& 
decls,
     funs.insert(DaysToDate);funs.insert(DateToDays);
     funs.insert(GetYearFrac);
 }
-void OpOddlprice::GenSlidingWindowFunction(std::stringstream &ss,
+void OpOddlprice::GenSlidingWindowFunction(outputstream &ss,
           const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -2655,7 +2655,7 @@ void OpOddlyield::BinInlineFun(std::set<std::string>& 
decls,
     funs.insert(DateToDays);
     funs.insert(GetYearFrac);funs.insert(GetOddlyield);
 }
-void OpOddlyield::GenSlidingWindowFunction(std::stringstream &ss,
+void OpOddlyield::GenSlidingWindowFunction(outputstream &ss,
           const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -2756,7 +2756,7 @@ void OpPriceDisc::BinInlineFun(std::set<std::string>& 
decls,
     funs.insert(DaysToDate);funs.insert(DaysInMonth);
     funs.insert(IsLeapYear);funs.insert(GetDiffDate);
 }
-void OpPriceDisc::GenSlidingWindowFunction(std::stringstream &ss,
+void OpPriceDisc::GenSlidingWindowFunction(outputstream &ss,
           const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -2816,7 +2816,7 @@ void 
OpPriceDisc::GenSlidingWindowFunction(std::stringstream &ss,
     ss <<"    return tmp;\n";
     ss <<"}";
 }
-void OpNper::GenSlidingWindowFunction(std::stringstream &ss,
+void OpNper::GenSlidingWindowFunction(outputstream &ss,
          const std::string &sSymName, SubArguments &vSubArguments)
  {
     ss << "\ndouble " << sSymName;
@@ -2889,7 +2889,7 @@ void OpPPMT::BinInlineFun(std::set<std::string>& decls,
     funs.insert(GetFV);
 }
 
-void OpPPMT::GenSlidingWindowFunction(std::stringstream &ss,
+void OpPPMT::GenSlidingWindowFunction(outputstream &ss,
         const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -2993,7 +2993,7 @@ void OpCoupdaybs::BinInlineFun(std::set<std::string>& 
decls,
     funs.insert(coupdaybs_new);
 }
 void OpCoupdaybs::GenSlidingWindowFunction(
-    std::stringstream &ss, const std::string &sSymName, SubArguments &
+    outputstream &ss, const std::string &sSymName, SubArguments &
 vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -3084,7 +3084,7 @@ void OpCoupdays::BinInlineFun(std::set<std::string>& 
decls,
     funs.insert(coupdays_new);
 }
 void OpCoupdays::GenSlidingWindowFunction(
-    std::stringstream &ss, const std::string &sSymName, SubArguments &
+    outputstream &ss, const std::string &sSymName, SubArguments &
 vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -3170,7 +3170,7 @@ void OpCouppcd::BinInlineFun(std::set<std::string>& decls,
     funs.insert(lcl_GetCouppcd);
 }
 void OpCouppcd::GenSlidingWindowFunction(
-    std::stringstream &ss, const std::string &sSymName,
+    outputstream &ss, const std::string &sSymName,
     SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -3257,7 +3257,7 @@ void OpCoupncd::BinInlineFun(std::set<std::string>& decls,
     funs.insert(lcl_GetCoupncd);
 }
 void OpCoupncd::GenSlidingWindowFunction(
-    std::stringstream &ss, const std::string &sSymName, SubArguments &
+    outputstream &ss, const std::string &sSymName, SubArguments &
 vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -3357,7 +3357,7 @@ void OpCoupdaysnc::BinInlineFun(std::set<std::string>& 
decls,
     funs.insert(coupdays_new);
 }
 void OpCoupdaysnc::GenSlidingWindowFunction(
-    std::stringstream &ss, const std::string &sSymName,
+    outputstream &ss, const std::string &sSymName,
     SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -3443,7 +3443,7 @@ void OpCoupnum::BinInlineFun(std::set<std::string>& decls,
     funs.insert(addMonths);funs.insert(lcl_Getcoupnum_new);
     funs.insert(coupnum_new);
 }
-void OpCoupnum::GenSlidingWindowFunction(std::stringstream &ss,
+void OpCoupnum::GenSlidingWindowFunction(outputstream &ss,
         const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -3522,7 +3522,7 @@ void OpAmordegrc::BinInlineFun(std::set<std::string>& 
decls,
     funs.insert(DaysToDate);funs.insert(DateToDays);
     funs.insert(GetNullDate);funs.insert(GetYearFrac);
 }
-void OpAmordegrc::GenSlidingWindowFunction(std::stringstream &ss,
+void OpAmordegrc::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -3677,7 +3677,7 @@ void OpAmorlinc::BinInlineFun(std::set<std::string>& 
decls,
     funs.insert(DaysToDate);funs.insert(DateToDays);
     funs.insert(GetYearFrac);
 }
-void OpAmorlinc::GenSlidingWindowFunction(std::stringstream &ss,
+void OpAmorlinc::GenSlidingWindowFunction(outputstream &ss,
              const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -3815,7 +3815,7 @@ void OpReceived::BinInlineFun(std::set<std::string>& 
decls,
     funs.insert(GetYearDiff);
 }
 
-void OpReceived::GenSlidingWindowFunction(std::stringstream &ss,
+void OpReceived::GenSlidingWindowFunction(outputstream &ss,
         const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -3913,7 +3913,7 @@ void 
OpReceived::GenSlidingWindowFunction(std::stringstream &ss,
     funs.insert(DaysInMonth);funs.insert(IsLeapYear);
 }
 void OpYielddisc::GenSlidingWindowFunction(
-    std::stringstream &ss, const std::string &sSymName, SubArguments 
&vSubArguments)
+    outputstream &ss, const std::string &sSymName, SubArguments &vSubArguments)
 {
     CHECK_PARAMETER_COUNT(5,5);
     ss << "\ndouble " << sSymName;
@@ -4034,7 +4034,7 @@ void OpYielddisc::GenSlidingWindowFunction(
 }
 
 void OpTbillprice::GenSlidingWindowFunction(
-    std::stringstream &ss, const std::string &sSymName, SubArguments 
&vSubArguments)
+    outputstream &ss, const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
     ss << "_"<< BinFuncName() <<"(";
@@ -4069,7 +4069,7 @@ void OpTbillprice::GenSlidingWindowFunction(
 }
 
 void RATE::GenSlidingWindowFunction(
-    std::stringstream &ss, const std::string &sSymName, SubArguments 
&vSubArguments)
+    outputstream &ss, const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
     ss << "_"<< BinFuncName() <<"(";
@@ -4208,7 +4208,7 @@ void RATE::GenSlidingWindowFunction(
 }
 
 void OpTbillyield::GenSlidingWindowFunction(
-    std::stringstream &ss, const std::string &sSymName, SubArguments 
&vSubArguments)
+    outputstream &ss, const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
     ss << "_"<< BinFuncName() <<"(";
@@ -4282,7 +4282,7 @@ void OpTbillyield::GenSlidingWindowFunction(
     ss <<"    return tmp;\n";
     ss << "}\n";
 }
-void OpDDB::GenSlidingWindowFunction(std::stringstream& ss,
+void OpDDB::GenSlidingWindowFunction(outputstream& ss,
             const std::string &sSymName, SubArguments& vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -4383,7 +4383,7 @@ void OpDDB::GenSlidingWindowFunction(std::stringstream& 
ss,
     ss <<"}";
 }
 void OpPV::GenSlidingWindowFunction(
-    std::stringstream &ss, const std::string &sSymName, SubArguments &
+    outputstream &ss, const std::string &sSymName, SubArguments &
 vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -4519,7 +4519,7 @@ tmpCur4);
 }
 
 void OpVDB::GenSlidingWindowFunction(
-    std::stringstream &ss, const std::string &sSymName, SubArguments 
&vSubArguments)
+    outputstream &ss, const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
     ss << "_"<< BinFuncName() <<"(";
@@ -4561,7 +4561,7 @@ void OpVDB::GenSlidingWindowFunction(
 
 }
 
-void OpXirr::GenSlidingWindowFunction(std::stringstream &ss,
+void OpXirr::GenSlidingWindowFunction(outputstream &ss,
              const std::string &sSymName, SubArguments &vSubArguments)
 {
     FormulaToken *tmpCur = vSubArguments[0]->GetFormulaToken();
@@ -4679,7 +4679,7 @@ void OpXirr::GenSlidingWindowFunction(std::stringstream 
&ss,
     }
 
 }
-void OpDB::GenSlidingWindowFunction(std::stringstream& ss,
+void OpDB::GenSlidingWindowFunction(outputstream& ss,
             const std::string &sSymName, SubArguments& vSubArguments)
 {
     ss << "\ndouble " << sSymName;
diff --git a/sc/source/core/opencl/op_financial.hxx 
b/sc/source/core/opencl/op_financial.hxx
index 87469c824c11..a485e09fa349 100644
--- a/sc/source/core/opencl/op_financial.hxx
+++ b/sc/source/core/opencl/op_financial.hxx
@@ -10,13 +10,14 @@
 #pragma once
 
 #include "opbase.hxx"
+#include "utils.hxx"
 
 namespace sc::opencl {
 
 class RRI: public SlidingFunctionBase
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual bool takeString() const override { return false; }
     virtual bool takeNumeric() const override { return true; }
@@ -32,7 +33,7 @@ public:
 class OpNominal: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual std::string BinFuncName() const override { return "NOMINAL_ADD"; }
 };
@@ -42,7 +43,7 @@ class OpDollarde:public Normal
 public:
         virtual std::string GetBottom() override { return "0"; }
 
-        virtual void GenSlidingWindowFunction(std::stringstream &ss,
+        virtual void GenSlidingWindowFunction(outputstream &ss,
         const std::string &sSymName, SubArguments &vSubArguments) override;
 
         virtual std::string BinFuncName() const override { return "Dollarde"; }
@@ -54,7 +55,7 @@ class OpDollarfr:public Normal
 public:
         virtual std::string GetBottom() override { return "0"; }
 
-        virtual void GenSlidingWindowFunction(std::stringstream &ss,
+        virtual void GenSlidingWindowFunction(outputstream &ss,
         const std::string &sSymName, SubArguments &vSubArguments) override;
 
         virtual std::string BinFuncName() const override { return "Dollarfr"; }
@@ -66,7 +67,7 @@ class OpDISC: public Normal
 public:
     virtual std::string GetBottom() override { return "0"; }
 
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual void BinInlineFun(std::set<std::string>& ,std::set<std::string>& ) 
override;
 
@@ -78,7 +79,7 @@ class OpINTRATE: public Normal
 public:
     virtual std::string GetBottom() override { return "0"; }
 
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual void BinInlineFun(std::set<std::string>& ,std::set<std::string>& ) 
override;
 
@@ -90,7 +91,7 @@ class OpFV: public Normal
 public:
     virtual std::string GetBottom() override { return "0"; }
 
-    virtual void GenSlidingWindowFunction(std::stringstream& ss,
+    virtual void GenSlidingWindowFunction(outputstream& ss,
             const std::string &sSymName, SubArguments& vSubArguments) override;
     virtual void BinInlineFun(std::set<std::string>& ,
         std::set<std::string>& ) override;
@@ -104,7 +105,7 @@ class OpIPMT: public Normal
 public:
     virtual std::string GetBottom() override { return "0"; }
 
-    virtual void GenSlidingWindowFunction(std::stringstream& ss,
+    virtual void GenSlidingWindowFunction(outputstream& ss,
             const std::string &sSymName, SubArguments& vSubArguments) override;
     virtual void BinInlineFun(std::set<std::string>& ,
         std::set<std::string>& ) override;
@@ -118,7 +119,7 @@ class OpISPMT: public Normal
 public:
     virtual std::string GetBottom() override { return "0"; }
 
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
 
     virtual std::string BinFuncName() const override { return "ISPMT"; }
@@ -129,7 +130,7 @@ class OpPDuration: public Normal
 public:
     virtual std::string GetBottom() override { return "0"; }
 
-    virtual void GenSlidingWindowFunction(std::stringstream& ss,
+    virtual void GenSlidingWindowFunction(outputstream& ss,
             const std::string &sSymName, SubArguments& vSubArguments) override;
 
     virtual std::string BinFuncName() const override { return "Duration"; }
@@ -140,7 +141,7 @@ class OpDuration_ADD: public Normal
 public:
     virtual std::string GetBottom() override { return "0"; }
 
-    virtual void GenSlidingWindowFunction(std::stringstream& ss,
+    virtual void GenSlidingWindowFunction(outputstream& ss,
             const std::string &sSymName, SubArguments& vSubArguments) override;
     virtual void BinInlineFun(std::set<std::string>& ,
                                      std::set<std::string>& ) override;
@@ -153,7 +154,7 @@ class OpMDuration: public Normal
 public:
     virtual std::string GetBottom() override { return "0"; }
 
-    virtual void GenSlidingWindowFunction(std::stringstream& ss,
+    virtual void GenSlidingWindowFunction(outputstream& ss,
             const std::string &sSymName, SubArguments& vSubArguments) override;
     virtual void BinInlineFun(std::set<std::string>& ,
         std::set<std::string>& ) override;
@@ -164,14 +165,14 @@ public:
 class Fvschedule: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
 };
 
 class Cumipmt: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual void BinInlineFun(std::set<std::string>& ,std::set<std::string>& ) 
override;
 };
@@ -179,7 +180,7 @@ public:
 class IRR: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
 };
 
@@ -193,21 +194,21 @@ public:
 class XNPV: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
 };
 
 class PriceMat: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual void BinInlineFun(std::set<std::string>& ,std::set<std::string>& ) 
override;
 };
 class OpSYD: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
 
      virtual std::string BinFuncName() const override { return "SYD"; }
@@ -216,7 +217,7 @@ public:
 class MIRR: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
 };
 
@@ -225,7 +226,7 @@ class OpEffective:public Normal
 public:
     virtual std::string GetBottom() override { return "0"; }
 
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
         const std::string &sSymName, SubArguments &vSubArguments) override;
 
     virtual std::string BinFuncName() const override { return "Effect_Add"; }
@@ -249,7 +250,7 @@ public:
 class OpTbilleq: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
 
     virtual std::string BinFuncName() const override { return "fTbilleq"; }
@@ -260,7 +261,7 @@ class OpCumprinc: public Normal
 {
 public:
     virtual std::string GetBottom() override { return "0"; }
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual void BinInlineFun(std::set<std::string>& ,std::set<std::string>& ) 
override;
     virtual std::string BinFuncName() const override { return "cumprinc"; }
@@ -271,7 +272,7 @@ class OpAccrintm: public Normal
  public:
     virtual std::string GetBottom() override { return "0"; }
     virtual void BinInlineFun(std::set<std::string>& ,std::set<std::string>& ) 
override;
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual std::string BinFuncName() const override { return "Accrintm"; }
 };
@@ -279,7 +280,7 @@ class OpAccrint: public Normal
 {
  public:
     virtual void BinInlineFun(std::set<std::string>& ,std::set<std::string>&) 
override;
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual std::string BinFuncName() const override { return "Accrint"; }
 };
@@ -287,7 +288,7 @@ class OpAccrint: public Normal
 class OpYield: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual std::string BinFuncName() const override { return "Yield"; }
      virtual void BinInlineFun(std::set<std::string>& ,std::set<std::string>& 
) override;
@@ -296,7 +297,7 @@ public:
 class OpSLN: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual std::string BinFuncName() const override { return "SLN"; }
 };
@@ -311,7 +312,7 @@ public:
 class OpYieldmat: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual std::string BinFuncName() const override { return "Yieldmat"; }
      virtual void BinInlineFun(std::set<std::string>& ,std::set<std::string>& 
) override;
@@ -320,14 +321,14 @@ public:
 class OpPMT: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual std::string BinFuncName() const override { return "PMT"; }
 };
 class OpNPV: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual std::string BinFuncName() const override { return "NPV"; }
 };
@@ -335,7 +336,7 @@ public:
 class OpPrice: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
         const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual void BinInlineFun(std::set<std::string>& ,std::set<std::string>& ) 
override;
     virtual std::string BinFuncName() const override { return "Price"; }
@@ -344,14 +345,14 @@ public:
 class OpNper: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
         const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual std::string BinFuncName() const override { return "NPER"; }
 };
 class OpOddlprice: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
         const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual void BinInlineFun(std::set<std::string>&,
         std::set<std::string>& ) override;
@@ -360,7 +361,7 @@ public:
 class OpOddlyield: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
         const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual void BinInlineFun(std::set<std::string>& ,
         std::set<std::string>& ) override;
@@ -369,7 +370,7 @@ public:
 class OpPriceDisc: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
         const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual void BinInlineFun(std::set<std::string>&,
         std::set<std::string>& ) override;
@@ -378,7 +379,7 @@ public:
 class OpPPMT: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
         const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual void BinInlineFun(std::set<std::string>& ,std::set<std::string>& ) 
override;
     virtual std::string BinFuncName() const override { return "PPMT"; }
@@ -388,7 +389,7 @@ class OpCoupdaybs:public Normal
 {
 public:
     virtual std::string GetBottom() override { return "0";}
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
         const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual void BinInlineFun(std::set<std::string>& ,std::set<std::string>& ) 
override;
     virtual std::string BinFuncName() const override { return "Coupdaybs"; }
@@ -399,7 +400,7 @@ class OpCoupdays:public Normal
 {
 public:
     virtual std::string GetBottom() override { return "0";}
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
         const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual void BinInlineFun(std::set<std::string>& ,std::set<std::string>& ) 
override;
     virtual std::string BinFuncName() const override { return "Coupdays";}
@@ -410,7 +411,7 @@ class OpCoupdaysnc:public Normal
 {
 public:
     virtual std::string GetBottom() override { return "0";}
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
         const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual void BinInlineFun(std::set<std::string>& ,std::set<std::string>& ) 
override;
     virtual std::string BinFuncName() const override { return "Coupdaysnc"; }
@@ -420,7 +421,7 @@ public:
 class OpCouppcd:public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
         const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual void BinInlineFun(std::set<std::string>& ,std::set<std::string>& ) 
override;
     virtual std::string BinFuncName() const override { return "Couppcd"; }
@@ -430,7 +431,7 @@ public:
 class OpCoupncd:public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
         const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual void BinInlineFun(std::set<std::string>& ,std::set<std::string>&) 
override;
     virtual std::string BinFuncName() const override { return "Coupncd"; }
@@ -441,7 +442,7 @@ class OpCoupnum:public Normal
 {
 public:
     virtual std::string GetBottom() override { return "0";}
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
         const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual void BinInlineFun(std::set<std::string>& ,std::set<std::string>&) 
override;
     virtual std::string BinFuncName() const override { return "Coupnum"; }
@@ -450,7 +451,7 @@ public:
 class OpDDB:public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
 
      virtual std::string BinFuncName() const override { return "DDB"; }
@@ -458,7 +459,7 @@ public:
 class OpDB:public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
 
      virtual std::string BinFuncName() const override { return "DB"; }
@@ -467,7 +468,7 @@ class OpAmordegrc:public Normal
 {
 public:
     virtual std::string GetBottom() override { return "0";}
-    virtual void GenSlidingWindowFunction(std::stringstream& ss,
+    virtual void GenSlidingWindowFunction(outputstream& ss,
         const std::string &sSymName, SubArguments& vSubArguments) override;
     virtual void BinInlineFun(std::set<std::string>& ,std::set<std::string>&) 
override;
     virtual std::string BinFuncName() const override { return "Amordegrc"; }
@@ -476,7 +477,7 @@ class OpAmorlinc:public Normal
 {
 public:
     virtual std::string GetBottom() override { return "0";}
-    virtual void GenSlidingWindowFunction(std::stringstream& ss,
+    virtual void GenSlidingWindowFunction(outputstream& ss,
         const std::string &sSymName, SubArguments& vSubArguments) override;
     virtual void BinInlineFun(std::set<std::string>& ,std::set<std::string>&) 
override;
     virtual std::string BinFuncName() const override { return "Amorlinc"; }
@@ -486,7 +487,7 @@ class OpReceived:public Normal
 {
 public:
     virtual std::string GetBottom() override { return "0"; }
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
         const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual std::string BinFuncName() const override { return "Received"; }
     virtual void BinInlineFun(std::set<std::string>& ,std::set<std::string>& ) 
override;
@@ -495,7 +496,7 @@ public:
 class OpYielddisc: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
         const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual std::string BinFuncName() const override { return "Yielddisc"; }
     virtual void BinInlineFun(std::set<std::string>& ,std::set<std::string>& ) 
override;
@@ -504,7 +505,7 @@ public:
 class OpTbillprice: public CheckVariables
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual std::string BinFuncName() const override { return "fTbillprice"; }
     virtual void BinInlineFun(std::set<std::string>& ,std::set<std::string>& ) 
override;
@@ -520,7 +521,7 @@ public:
 class RATE: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual void BinInlineFun(std::set<std::string>& ,std::set<std::string>& ) 
override;
 };
@@ -533,7 +534,7 @@ public:
 class OpTbillyield: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
 
     virtual std::string BinFuncName() const override { return "fTbillyield"; }
@@ -550,7 +551,7 @@ public:
 class OpPV: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
                 const std::string &sSymName, SubArguments &vSubArguments) 
override;
     virtual std::string BinFuncName() const override { return "PV"; }
 };
@@ -558,7 +559,7 @@ public:
 class OpVDB: public CheckVariables
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
 
     virtual std::string BinFuncName() const override { return "VDB"; }
@@ -568,7 +569,7 @@ public:
 class OpXirr: public CheckVariables
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
 
     virtual std::string BinFuncName() const override { return "Xirr"; }
diff --git a/sc/source/core/opencl/op_logical.cxx 
b/sc/source/core/opencl/op_logical.cxx
index b9c70a1c7413..969b63d0ee7b 100644
--- a/sc/source/core/opencl/op_logical.cxx
+++ b/sc/source/core/opencl/op_logical.cxx
@@ -15,7 +15,7 @@
 using namespace formula;
 
 namespace sc::opencl {
-void OpAnd::GenSlidingWindowFunction(std::stringstream &ss,
+void OpAnd::GenSlidingWindowFunction(outputstream &ss,
     const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -100,7 +100,7 @@ void OpAnd::GenSlidingWindowFunction(std::stringstream &ss,
     ss << "}\n";
 }
 
-void OpOr::GenSlidingWindowFunction(std::stringstream &ss,
+void OpOr::GenSlidingWindowFunction(outputstream &ss,
     const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -179,7 +179,7 @@ void OpOr::GenSlidingWindowFunction(std::stringstream &ss,
     ss << "    return t;\n";
     ss << "}\n";
 }
-void OpNot::GenSlidingWindowFunction(std::stringstream &ss,
+void OpNot::GenSlidingWindowFunction(outputstream &ss,
     const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -216,7 +216,7 @@ void OpNot::GenSlidingWindowFunction(std::stringstream &ss,
     ss << "}\n";
 }
 
-void OpXor::GenSlidingWindowFunction(std::stringstream &ss,
+void OpXor::GenSlidingWindowFunction(outputstream &ss,
     const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -295,7 +295,7 @@ void OpXor::GenSlidingWindowFunction(std::stringstream &ss,
     ss << "    return t;\n";
     ss << "}\n";
 }
-void OpIf::GenSlidingWindowFunction(std::stringstream &ss,
+void OpIf::GenSlidingWindowFunction(outputstream &ss,
     const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
diff --git a/sc/source/core/opencl/op_logical.hxx 
b/sc/source/core/opencl/op_logical.hxx
index 2f04cae6a035..18cb0b59001f 100644
--- a/sc/source/core/opencl/op_logical.hxx
+++ b/sc/source/core/opencl/op_logical.hxx
@@ -10,13 +10,14 @@
 #pragma once
 
 #include "opbase.hxx"
+#include "utils.hxx"
 
 namespace sc::opencl {
 
 class OpAnd: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual std::string BinFuncName() const override { return "And"; }
     virtual bool canHandleMultiVector() const override { return true; }
@@ -25,7 +26,7 @@ public:
 class OpOr: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual std::string BinFuncName() const override { return "Or"; }
     virtual bool canHandleMultiVector() const override { return true; }
@@ -33,14 +34,14 @@ public:
 class OpNot: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual std::string BinFuncName() const override { return "Not"; }
 };
 class OpXor: public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual std::string BinFuncName() const override { return "Xor"; }
     virtual bool canHandleMultiVector() const override { return true; }
@@ -48,7 +49,7 @@ public:
 class OpIf:public Normal
 {
 public:
-    virtual void GenSlidingWindowFunction(std::stringstream &ss,
+    virtual void GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments) override;
     virtual std::string BinFuncName() const override { return "IF"; }
 };
diff --git a/sc/source/core/opencl/op_math.cxx 
b/sc/source/core/opencl/op_math.cxx
index 817da13dc732..21bc24eee2c1 100644
--- a/sc/source/core/opencl/op_math.cxx
+++ b/sc/source/core/opencl/op_math.cxx
@@ -17,7 +17,7 @@ using namespace formula;
 
 namespace sc::opencl {
 
-void OpCos::GenSlidingWindowFunction(std::stringstream &ss,
+void OpCos::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
         ss << "\ndouble " << sSymName;
@@ -65,7 +65,7 @@ void OpCos::GenSlidingWindowFunction(std::stringstream &ss,
         ss << "}";
 
 }
-void OpSec::GenSlidingWindowFunction(std::stringstream &ss,
+void OpSec::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     FormulaToken *tmpCur = vSubArguments[0]->GetFormulaToken();
@@ -96,7 +96,7 @@ void OpCosh::BinInlineFun(std::set<std::string>& decls,
     decls.insert(local_coshDecl);
     funs.insert(local_cosh);
 }
-void OpSecH::GenSlidingWindowFunction(std::stringstream &ss,
+void OpSecH::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     FormulaToken *tmpCur = vSubArguments[0]->GetFormulaToken();
@@ -121,7 +121,7 @@ void OpSecH::GenSlidingWindowFunction(std::stringstream &ss,
     ss << "    return 1.0 / cosh(arg0);\n";
     ss << "}";
 }
-void OpMROUND::GenSlidingWindowFunction(std::stringstream &ss,
+void OpMROUND::GenSlidingWindowFunction(outputstream &ss,
         const std::string &sSymName, SubArguments &vSubArguments)
 {
     CHECK_PARAMETER_COUNT(2, 2);
@@ -178,7 +178,7 @@ void OpMROUND::GenSlidingWindowFunction(std::stringstream 
&ss,
     ss<<"    return tmp;\n";
     ss<<"}";
 }
-void OpCosh::GenSlidingWindowFunction(std::stringstream &ss,
+void OpCosh::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     FormulaToken *tmpCur = vSubArguments[0]->GetFormulaToken();
@@ -205,7 +205,7 @@ void OpCosh::GenSlidingWindowFunction(std::stringstream &ss,
     ss << "}";
 }
 
-void OpCot::GenSlidingWindowFunction(std::stringstream &ss,
+void OpCot::GenSlidingWindowFunction(outputstream &ss,
     const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -263,7 +263,7 @@ void OpCoth::BinInlineFun(std::set<std::string>& decls,
     funs.insert(local_coth);
 }
 
-void OpCoth::GenSlidingWindowFunction(std::stringstream &ss,
+void OpCoth::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     FormulaToken *tmpCur = vSubArguments[0]->GetFormulaToken();
@@ -297,7 +297,7 @@ void OpCombinA::BinInlineFun(std::set<std::string>& decls,
     funs.insert(bik);
 }
 
-void OpCombinA::GenSlidingWindowFunction(std::stringstream &ss,
+void OpCombinA::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -351,7 +351,7 @@ void OpCombinA::GenSlidingWindowFunction(std::stringstream 
&ss,
     ss << "    return tem;\n";
     ss << "}";
 }
-void OpEven::GenSlidingWindowFunction(std::stringstream &ss,
+void OpEven::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     FormulaToken *tmpCur = vSubArguments[0]->GetFormulaToken();
@@ -385,7 +385,7 @@ void OpEven::GenSlidingWindowFunction(std::stringstream &ss,
     ss << "}";
 }
 
-void OpMod::GenSlidingWindowFunction(std::stringstream &ss,
+void OpMod::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -419,7 +419,7 @@ void OpMod::GenSlidingWindowFunction(std::stringstream &ss,
     ss << "    return tem;\n";
     ss << "}";
 }
-void OpLog::GenSlidingWindowFunction(std::stringstream &ss,
+void OpLog::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -468,7 +468,7 @@ void OpLog::GenSlidingWindowFunction(std::stringstream &ss,
     ss << "}";
 }
 void OpCsc::GenSlidingWindowFunction(
-    std::stringstream &ss, const std::string &sSymName, SubArguments 
&vSubArguments)
+    outputstream &ss, const std::string &sSymName, SubArguments &vSubArguments)
 {
     FormulaToken *tmpCur = vSubArguments[0]->GetFormulaToken();
     const formula::SingleVectorRefToken*tmpCurDVR= static_cast<const
@@ -493,7 +493,7 @@ void OpCsc::GenSlidingWindowFunction(
     ss << "return tmp;\n";
     ss << "}";
 }
-void OpCountIfs::GenSlidingWindowFunction(std::stringstream &ss,
+void OpCountIfs::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     FormulaToken *tmpCur = vSubArguments[0]->GetFormulaToken();
@@ -519,7 +519,7 @@ void OpCountIfs::GenSlidingWindowFunction(std::stringstream 
&ss,
     ss<< "    int singleIndex =gid0;\n";
     int m=0;
 
-    std::stringstream tmpss;
+    outputstream tmpss;
 
     for(size_t j=0;j<vSubArguments.size();j+=2,m++)
     {
@@ -547,7 +547,7 @@ void OpCountIfs::GenSlidingWindowFunction(std::stringstream 
&ss,
     ss << "return tmp;\n";
     ss << "}";
 }
-void OpSumIfs::GenSlidingWindowFunction(std::stringstream &ss,
+void OpSumIfs::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     FormulaToken *tmpCur = vSubArguments[0]->GetFormulaToken();
@@ -760,7 +760,7 @@ void OpSumIfs::GenSlidingWindowFunction(std::stringstream 
&ss,
     ss << "}";
 }
 void OpCscH::GenSlidingWindowFunction(
-    std::stringstream &ss, const std::string &sSymName, SubArguments 
&vSubArguments)
+    outputstream &ss, const std::string &sSymName, SubArguments &vSubArguments)
 {
     FormulaToken *tmpCur = vSubArguments[0]->GetFormulaToken();
     const formula::SingleVectorRefToken*tmpCurDVR= static_cast<const
@@ -785,7 +785,7 @@ void OpCscH::GenSlidingWindowFunction(
     ss << "return tmp;\n";
     ss << "}";
 }
-void OpExp::GenSlidingWindowFunction(std::stringstream &ss,
+void OpExp::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -833,7 +833,7 @@ void OpExp::GenSlidingWindowFunction(std::stringstream &ss,
     ss << "}";
 }
 
-void OpAverageIfs::GenSlidingWindowFunction(std::stringstream &ss,
+void OpAverageIfs::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     FormulaToken *tmpCur = vSubArguments[0]->GetFormulaToken();
@@ -858,7 +858,7 @@ void 
OpAverageIfs::GenSlidingWindowFunction(std::stringstream &ss,
     GenTmpVariables(ss,vSubArguments);
     ss<< "    int singleIndex =gid0;\n";
     int m=0;
-    std::stringstream tmpss;
+    outputstream tmpss;
     for(size_t j=1;j<vSubArguments.size();j+=2,m++)
     {
         CheckSubArgumentIsNan(tmpss,vSubArguments,j);
@@ -893,7 +893,7 @@ void 
OpAverageIfs::GenSlidingWindowFunction(std::stringstream &ss,
     ss << "}";
 }
 
-void OpLog10::GenSlidingWindowFunction(std::stringstream &ss,
+void OpLog10::GenSlidingWindowFunction(outputstream &ss,
                const std::string &sSymName, SubArguments &vSubArguments)
 {
     FormulaToken *tmpCur = vSubArguments[0]->GetFormulaToken();
@@ -920,7 +920,7 @@ void OpLog10::GenSlidingWindowFunction(std::stringstream 
&ss,
     ss << "}";
 }
 
-void OpSinh::GenSlidingWindowFunction(std::stringstream &ss,
+void OpSinh::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -942,7 +942,7 @@ void OpSinh::GenSlidingWindowFunction(std::stringstream &ss,
     ss << "    return tmp;\n";
     ss << "}";
 }
-void OpSin::GenSlidingWindowFunction(std::stringstream &ss,
+void OpSin::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -991,7 +991,7 @@ void OpSin::GenSlidingWindowFunction(std::stringstream &ss,
     ss << "}";
 }
 
-void OpAbs::GenSlidingWindowFunction(std::stringstream &ss,
+void OpAbs::GenSlidingWindowFunction(outputstream &ss,
     const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -1027,7 +1027,7 @@ void OpArcCos::BinInlineFun(std::set<std::string>& decls,
     decls.insert(atan2Decl);
     funs.insert(atan2Content);
 }
-void OpArcCos::GenSlidingWindowFunction(std::stringstream &ss,
+void OpArcCos::GenSlidingWindowFunction(outputstream &ss,
     const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -1053,7 +1053,7 @@ void OpArcCos::GenSlidingWindowFunction(std::stringstream 
&ss,
     ss << "    return arctan2(sqrt(1.0 - pow(tmp, 2)), tmp);\n";
     ss << "}";
 }
-void OpArcCosHyp::GenSlidingWindowFunction(std::stringstream &ss,
+void OpArcCosHyp::GenSlidingWindowFunction(outputstream &ss,
     const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -1096,7 +1096,7 @@ void 
OpArcCosHyp::GenSlidingWindowFunction(std::stringstream &ss,
     ss << "    return  log( tmp + pow( (pown(tmp, 2) - 1.0), 0.5));\n";
     ss << "}";
 }
-void OpTan::GenSlidingWindowFunction(std::stringstream &ss,
+void OpTan::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -1144,7 +1144,7 @@ void OpTan::GenSlidingWindowFunction(std::stringstream 
&ss,
     ss << "    return sinpi(arg0) / cospi(arg0);\n";
     ss << "}";
 }
-void OpTanH::GenSlidingWindowFunction(std::stringstream &ss,
+void OpTanH::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     FormulaToken *tmpCur = vSubArguments[0]->GetFormulaToken();
@@ -1171,7 +1171,7 @@ void OpTanH::GenSlidingWindowFunction(std::stringstream 
&ss,
     ss << "    return tmp;\n";
     ss << "}";
 }
-void OpPower::GenSlidingWindowFunction(std::stringstream &ss,
+void OpPower::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -1239,7 +1239,7 @@ void OpPower::GenSlidingWindowFunction(std::stringstream 
&ss,
     ss << "    return pow(arg[0],arg[1]);\n";
     ss << "}";
 }
-void OpSqrt::GenSlidingWindowFunction(std::stringstream &ss,
+void OpSqrt::GenSlidingWindowFunction(outputstream &ss,
             const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -1294,7 +1294,7 @@ void OpSqrt::GenSlidingWindowFunction(std::stringstream 
&ss,
     ss << "    return sqrt(arg0);\n";
     ss << "}";
 }
-void OpArcCot::GenSlidingWindowFunction(std::stringstream &ss,
+void OpArcCot::GenSlidingWindowFunction(outputstream &ss,
     const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -1319,7 +1319,7 @@ void OpArcCot::GenSlidingWindowFunction(std::stringstream 
&ss,
     ss << "    return M_PI_2 - atan(tmp);\n";
     ss << "}";
 }
-void OpArcCotHyp::GenSlidingWindowFunction(std::stringstream &ss,
+void OpArcCotHyp::GenSlidingWindowFunction(outputstream &ss,
     const std::string &sSymName, SubArguments &vSubArguments)
 {
     ss << "\ndouble " << sSymName;
@@ -1373,7 +1373,7 @@ void OpArcSin::BinInlineFun(std::set<std::string>& decls,
     decls.insert(atan2Decl);
     funs.insert(atan2Content);
 }

... etc. - the rest is truncated

Reply via email to