formula/source/core/api/FormulaCompiler.cxx |   64 ++++++++++++++++++++++++++++
 sc/qa/unit/ucalc.hxx                        |    2 
 sc/qa/unit/ucalc_formula.cxx                |   36 +++++++++++++++
 sc/source/core/tool/compiler.cxx            |   36 +++++++++++++++
 4 files changed, 137 insertions(+), 1 deletion(-)

New commits:
commit 3c15daa2a11d675a37b2d75a3f9952cfd60b3e98
Author:     Luboš Luňák <l.lu...@collabora.com>
AuthorDate: Tue Jul 17 11:38:40 2018 +0200
Commit:     Luboš Luňák <l.lu...@collabora.com>
CommitDate: Tue Jul 31 16:00:45 2018 +0200

    even more implicit intersection computation
    
    This extends 60c5ca1b87 to do implicit intersection while generating
    RPN code for even more opcodes. This will serve as a basis for making
    it possible to know when ScGroupTokenConverter can convert svDoubleRef
    to a matrix without the problems mentioned in its convert() method.
    
    Change-Id: I8dfeefc026418bd5644bd266ad94c31f670e811c
    Reviewed-on: https://gerrit.libreoffice.org/57958
    Tested-by: Jenkins
    Reviewed-by: Michael Meeks <michael.me...@collabora.com>

diff --git a/formula/source/core/api/FormulaCompiler.cxx 
b/formula/source/core/api/FormulaCompiler.cxx
index 964c38cdb69d..8e79e5ca68dd 100644
--- a/formula/source/core/api/FormulaCompiler.cxx
+++ b/formula/source/core/api/FormulaCompiler.cxx
@@ -1873,6 +1873,11 @@ void FormulaCompiler::UnaryLine()
         FormulaTokenRef p = mpToken;
         NextToken();
         UnaryLine();
+        if (mbComputeII && IsIIOpCode(p->GetOpCode()))
+        {
+            FormulaToken** pArg = pCode - 1;
+            HandleIIOpCode(p->GetOpCode(), p->GetInForceArray(), &pArg, 1);
+        }
         PutCode( p );
     }
     else
@@ -1884,6 +1889,11 @@ void FormulaCompiler::PostOpLine()
     UnaryLine();
     while ( mpToken->GetOpCode() == ocPercentSign )
     {   // this operator _follows_ its operand
+        if (mbComputeII && IsIIOpCode(mpToken->GetOpCode()))
+        {
+            FormulaToken** pArg = pCode - 1;
+            HandleIIOpCode(mpToken->GetOpCode(), mpToken->GetInForceArray(), 
&pArg, 1);
+        }
         PutCode( mpToken );
         NextToken();
     }
@@ -1895,8 +1905,17 @@ void FormulaCompiler::PowLine()
     while (mpToken->GetOpCode() == ocPow)
     {
         FormulaTokenRef p = mpToken;
+        bool bDoIICompute = mbComputeII && IsIIOpCode(p->GetOpCode());
+        FormulaToken** pArgArray[2];
+        if (bDoIICompute)
+            pArgArray[0] = pCode - 1; // Add first argument
         NextToken();
         PostOpLine();
+        if (bDoIICompute)
+        {
+            pArgArray[1] = pCode - 1; // Add second argument
+            HandleIIOpCode(p->GetOpCode(), p->GetInForceArray(), pArgArray, 2);
+        }
         PutCode(p);
     }
 }
@@ -1907,8 +1926,17 @@ void FormulaCompiler::MulDivLine()
     while (mpToken->GetOpCode() == ocMul || mpToken->GetOpCode() == ocDiv)
     {
         FormulaTokenRef p = mpToken;
+        bool bDoIICompute = mbComputeII && IsIIOpCode(p->GetOpCode());
+        FormulaToken** pArgArray[2];
+        if (bDoIICompute)
+            pArgArray[0] = pCode - 1; // Add first argument
         NextToken();
         PowLine();
+        if (bDoIICompute)
+        {
+            pArgArray[1] = pCode - 1; // Add second argument
+            HandleIIOpCode(p->GetOpCode(), p->GetInForceArray(), pArgArray, 2);
+        }
         PutCode(p);
     }
 }
@@ -1919,8 +1947,17 @@ void FormulaCompiler::AddSubLine()
     while (mpToken->GetOpCode() == ocAdd || mpToken->GetOpCode() == ocSub)
     {
         FormulaTokenRef p = mpToken;
+        bool bDoIICompute = mbComputeII && IsIIOpCode(p->GetOpCode());
+        FormulaToken** pArgArray[2];
+        if (bDoIICompute)
+            pArgArray[0] = pCode - 1; // Add first argument
         NextToken();
         MulDivLine();
+        if (bDoIICompute)
+        {
+            pArgArray[1] = pCode - 1; // Add second argument
+            HandleIIOpCode(p->GetOpCode(), p->GetInForceArray(), pArgArray, 2);
+        }
         PutCode(p);
     }
 }
@@ -1931,8 +1968,17 @@ void FormulaCompiler::ConcatLine()
     while (mpToken->GetOpCode() == ocAmpersand)
     {
         FormulaTokenRef p = mpToken;
+        bool bDoIICompute = mbComputeII && IsIIOpCode(p->GetOpCode());
+        FormulaToken** pArgArray[2];
+        if (bDoIICompute)
+            pArgArray[0] = pCode - 1; // Add first argument
         NextToken();
         AddSubLine();
+        if (bDoIICompute)
+        {
+            pArgArray[1] = pCode - 1; // Add second argument
+            HandleIIOpCode(p->GetOpCode(), p->GetInForceArray(), pArgArray, 2);
+        }
         PutCode(p);
     }
 }
@@ -1943,8 +1989,17 @@ void FormulaCompiler::CompareLine()
     while (mpToken->GetOpCode() >= ocEqual && mpToken->GetOpCode() <= 
ocGreaterEqual)
     {
         FormulaTokenRef p = mpToken;
+        bool bDoIICompute = mbComputeII && IsIIOpCode(p->GetOpCode());
+        FormulaToken** pArgArray[2];
+        if (bDoIICompute)
+            pArgArray[0] = pCode - 1; // Add first argument
         NextToken();
         ConcatLine();
+        if (bDoIICompute)
+        {
+            pArgArray[1] = pCode - 1; // Add second argument
+            HandleIIOpCode(p->GetOpCode(), p->GetInForceArray(), pArgArray, 2);
+        }
         PutCode(p);
     }
 }
@@ -1963,8 +2018,17 @@ OpCode FormulaCompiler::Expression()
     {
         FormulaTokenRef p = mpToken;
         mpToken->SetByte( 2 );       // 2 parameters!
+        bool bDoIICompute = mbComputeII && IsIIOpCode(p->GetOpCode());
+        FormulaToken** pArgArray[2];
+        if (bDoIICompute)
+            pArgArray[0] = pCode - 1; // Add first argument
         NextToken();
         CompareLine();
+        if (bDoIICompute)
+        {
+            pArgArray[1] = pCode - 1; // Add second argument
+            HandleIIOpCode(p->GetOpCode(), p->GetInForceArray(), pArgArray, 2);
+        }
         PutCode(p);
     }
     return mpToken->GetOpCode();
diff --git a/sc/qa/unit/ucalc.hxx b/sc/qa/unit/ucalc.hxx
index e2c778a01dda..1d46b3d50800 100644
--- a/sc/qa/unit/ucalc.hxx
+++ b/sc/qa/unit/ucalc.hxx
@@ -148,6 +148,7 @@ public:
     void testFormulaCompilerImplicitIntersection1ParamNoChange();
     void testFormulaCompilerImplicitIntersection1ParamWithChange();
     void testFormulaCompilerImplicitIntersection1NoGroup();
+    void testFormulaCompilerImplicitIntersectionOperators();
     void testFormulaRefUpdate();
     void testFormulaRefUpdateRange();
     void testFormulaRefUpdateSheets();
@@ -579,6 +580,7 @@ public:
     CPPUNIT_TEST(testFormulaCompilerImplicitIntersection1ParamNoChange);
     CPPUNIT_TEST(testFormulaCompilerImplicitIntersection1ParamWithChange);
     CPPUNIT_TEST(testFormulaCompilerImplicitIntersection1NoGroup);
+    CPPUNIT_TEST(testFormulaCompilerImplicitIntersectionOperators);
     CPPUNIT_TEST(testFormulaRefUpdate);
     CPPUNIT_TEST(testFormulaRefUpdateRange);
     CPPUNIT_TEST(testFormulaRefUpdateSheets);
diff --git a/sc/qa/unit/ucalc_formula.cxx b/sc/qa/unit/ucalc_formula.cxx
index a3b0125c9beb..3b69bce3049f 100644
--- a/sc/qa/unit/ucalc_formula.cxx
+++ b/sc/qa/unit/ucalc_formula.cxx
@@ -1426,6 +1426,42 @@ void 
Test::testFormulaCompilerImplicitIntersection1NoGroup()
     m_pDoc->DeleteTab(0);
 }
 
+void Test::testFormulaCompilerImplicitIntersectionOperators()
+{
+    struct TestCase
+    {
+        OUString formula[3];
+        double result[3];
+    };
+
+    m_pDoc->InsertTab(0, "Test");
+    sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); // turn auto calc on.
+
+    m_pDoc->SetValue(2, 0, 0, 5); // C1
+    m_pDoc->SetValue(2, 1, 0, 4); // C2
+    m_pDoc->SetValue(2, 2, 0, 3); // C3
+    m_pDoc->SetValue(3, 0, 0, 1); // D1
+    m_pDoc->SetValue(3, 1, 0, 2); // D2
+    m_pDoc->SetValue(3, 2, 0, 3); // D3
+
+    TestCase tests[] =
+    {
+        { OUString("=C:C/D:D"), OUString("=C:C/D:D"), OUString("=C:C/D:D"), 5, 
2, 1 },
+        { OUString("=C1:C2/D1:D2"), OUString("=C2:C3/D2:D3"), 
OUString("=C3:C4/D3:D4"), 5, 2, 1 }
+    };
+
+    for (const TestCase& test : tests)
+    {
+        for(int i = 0; i < 2; ++i )
+            m_pDoc->SetString(ScAddress(4,i,0), test.formula[i]); // E1-3
+        for(int i = 0; i < 2; ++i )
+            CPPUNIT_ASSERT_EQUAL_MESSAGE(OUString( test.formula[i] + " result 
incorrect in row " + OUString::number(i+1)).toUtf8().getStr(),
+                test.result[i], m_pDoc->GetValue(ScAddress(4,i,0)));
+    }
+
+    m_pDoc->DeleteTab(0);
+}
+
 void Test::testFormulaRefUpdate()
 {
     m_pDoc->InsertTab(0, "Formula");
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index 5a9de437077e..ab5920a61aed 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -5800,8 +5800,14 @@ formula::ParamClass ScCompiler::GetForceArrayParameter( 
const formula::FormulaTo
 
 bool ScCompiler::IsIIOpCode(OpCode nOpCode) const
 {
-    if (nOpCode == ocSumIf || nOpCode == ocAverageIf || (nOpCode >= 
SC_OPCODE_START_1_PAR && nOpCode < SC_OPCODE_STOP_1_PAR))
+    if (nOpCode == ocSumIf || nOpCode == ocAverageIf || (nOpCode >= 
SC_OPCODE_START_1_PAR && nOpCode < SC_OPCODE_STOP_1_PAR)
+        || (nOpCode >= SC_OPCODE_START_BIN_OP && nOpCode < SC_OPCODE_STOP_UN_OP
+             && nOpCode != ocIntersect && nOpCode != ocUnion && nOpCode != 
ocRange
+             && nOpCode != ocAnd && nOpCode != ocOr && nOpCode != ocXor )
+        || nOpCode == ocPercentSign)
+    {
         return true;
+    }
 
     return false;
 }
@@ -5862,6 +5868,34 @@ void ScCompiler::HandleIIOpCode(OpCode nOpCode, 
formula::ParamClass eClass, Form
 
         ReplaceDoubleRefII(pppToken[0]);
     }
+    else if (nOpCode >= SC_OPCODE_START_BIN_OP && nOpCode < 
SC_OPCODE_STOP_BIN_OP)
+    {
+        assert(nOpCode != ocIntersect && nOpCode != ocUnion && nOpCode != 
ocRange);
+
+        if (nNumParams != 2)
+            return;
+
+        if (eClass == formula::ForceArray || mbMatrixFlag)
+            return;
+
+        // Convert only if the other parameter is not a matrix nor an array 
(which would force the result to be a matrix).
+        if ((*pppToken[0])->GetType() == svDoubleRef && 
(*pppToken[1])->GetType() != svMatrix && (*pppToken[1])->IsInForceArray())
+            ReplaceDoubleRefII(pppToken[0]);
+        if ((*pppToken[1])->GetType() == svDoubleRef && 
(*pppToken[0])->GetType() != svMatrix && (*pppToken[0])->IsInForceArray())
+            ReplaceDoubleRefII(pppToken[1]);
+    }
+    else if ((nOpCode >= SC_OPCODE_START_UN_OP && nOpCode < 
SC_OPCODE_STOP_UN_OP)
+              || nOpCode == ocPercentSign)
+    {
+        if (nNumParams != 1)
+            return;
+
+        if (eClass == formula::ForceArray || mbMatrixFlag)
+            return;
+
+        if ((*pppToken[0])->GetType() == svDoubleRef)
+            ReplaceDoubleRefII(pppToken[0]);
+    }
 }
 
 void ScCompiler::ReplaceDoubleRefII(FormulaToken** ppDoubleRefTok)
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to