[Libreoffice-commits] core.git: 2 commits - formula/source include/formula sc/source

Eike Rathke erack at redhat.com
Fri Jun 13 05:22:12 PDT 2014


 formula/source/core/api/token.cxx   |    7 ++++++-
 include/formula/FormulaCompiler.hxx |    6 +++---
 include/formula/errorcodes.hxx      |    4 ++++
 include/formula/token.hxx           |    9 +++++++--
 sc/source/core/inc/interpre.hxx     |    2 +-
 sc/source/core/tool/interpr1.cxx    |    2 +-
 sc/source/core/tool/interpr5.cxx    |   16 ++++++++++++++--
 sc/source/core/tool/scmatrix.cxx    |   10 +++++-----
 8 files changed, 41 insertions(+), 15 deletions(-)

New commits:
commit a288bebbcec0b16e1ced09a601de5ffbb6b1bbe0
Author: Eike Rathke <erack at redhat.com>
Date:   Fri Jun 13 14:16:11 2014 +0200

    resolved fdo#79978 propagate error through DoubleArray of matrix
    
    Regression introduced with 83f77ab0661df992f241e5f9ecb1aa8f8eaeafec.
    
    Interpreter errors are transported using NaN coded doubles, using simple
    setNan()/isNan() to flag and ignore non-numeric values skips all error
    values.
    
    Change-Id: I0d3cb30262bc5ba7ee77e53a2bc45e56569fbc4b

diff --git a/include/formula/errorcodes.hxx b/include/formula/errorcodes.hxx
index cea5787..a92372c 100644
--- a/include/formula/errorcodes.hxx
+++ b/include/formula/errorcodes.hxx
@@ -74,6 +74,10 @@ const sal_uInt16 errNotNumericString     = 534;
 // ScInterpreter internal:  jump matrix already has a result at this position,
 // do not overwrite in case of empty code path.
 const sal_uInt16 errJumpMatHasResult     = 535;
+// ScInterpreter internal:  (matrix) element is not a numeric value, i.e.
+// string or empty, to be distinguished from the general errNoValue NAN and not
+// to be used as result.
+const sal_uInt16 errElementNaN           = 536;
 
 // Interpreter: NA() not available condition, not a real error
 const sal_uInt16 NOTAVAILABLE            = 0x7fff;
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 83393ca..8c86e56 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -5613,7 +5613,7 @@ double ScInterpreter::IterateParametersIfs( ScIterFuncIfs eFunc )
                         continue;
 
                     fVal = *itMain;
-                    if (rtl::math::isNan(fVal))
+                    if (GetDoubleErrorValue(fVal) == errElementNaN)
                         continue;
 
                     ++fCount;
diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx
index a49e87c..944a0ce 100644
--- a/sc/source/core/tool/interpr5.cxx
+++ b/sc/source/core/tool/interpr5.cxx
@@ -1657,13 +1657,25 @@ namespace {
 class SumValues : std::unary_function<double, void>
 {
     double mfSum;
+    bool   mbError;
 public:
-    SumValues() : mfSum(0.0) {}
+    SumValues() : mfSum(0.0), mbError(false) {}
 
     void operator() (double f)
     {
-        if (!rtl::math::isNan(f))
+        if (mbError)
+            return;
+
+        sal_uInt16 nErr = GetDoubleErrorValue(f);
+        if (!nErr)
             mfSum += f;
+        else if (nErr != errElementNaN)
+        {
+            // Propagate the first error encountered, ignore "this is not a
+            // number" elements.
+            mfSum = f;
+            mbError = true;
+        }
     }
 
     double getValue() const { return mfSum; }
diff --git a/sc/source/core/tool/scmatrix.cxx b/sc/source/core/tool/scmatrix.cxx
index 84e3c2a..8874218 100644
--- a/sc/source/core/tool/scmatrix.cxx
+++ b/sc/source/core/tool/scmatrix.cxx
@@ -1507,7 +1507,7 @@ public:
     ToDoubleArray( size_t nSize, bool bEmptyAsZero ) :
         maArray(nSize, 0.0), miPos(maArray.begin()), mbEmptyAsZero(bEmptyAsZero)
     {
-        rtl::math::setNan(&mfNaN);
+        mfNaN = CreateDoubleError( errElementNaN);
     }
 
     void operator() (const MatrixImplType::element_block_node_type& node)
@@ -1578,7 +1578,7 @@ class MergeDoubleArrayFunc : std::unary_function<MatrixImplType::element_block_t
 public:
     MergeDoubleArrayFunc(std::vector<double>& rArray) : mrArray(rArray), miPos(mrArray.begin())
     {
-        rtl::math::setNan(&mfNaN);
+        mfNaN = CreateDoubleError( errElementNaN);
     }
 
     void operator() (const MatrixImplType::element_block_node_type& node)
@@ -1594,7 +1594,7 @@ public:
                 numeric_element_block::const_iterator itEnd = numeric_element_block::end(*node.data);
                 for (; it != itEnd; ++it, ++miPos)
                 {
-                    if (rtl::math::isNan(*miPos))
+                    if (GetDoubleErrorValue(*miPos) == errElementNaN)
                         continue;
 
                     *miPos = op(*miPos, *it);
@@ -1607,7 +1607,7 @@ public:
                 boolean_element_block::const_iterator itEnd = boolean_element_block::end(*node.data);
                 for (; it != itEnd; ++it, ++miPos)
                 {
-                    if (rtl::math::isNan(*miPos))
+                    if (GetDoubleErrorValue(*miPos) == errElementNaN)
                         continue;
 
                     *miPos = op(*miPos, *it ? 1.0 : 0.0);
@@ -1625,7 +1625,7 @@ public:
                 // Empty element is equivalent of having a numeric value of 0.0.
                 for (size_t i = 0; i < node.size; ++i, ++miPos)
                 {
-                    if (rtl::math::isNan(*miPos))
+                    if (GetDoubleErrorValue(*miPos) == errElementNaN)
                         continue;
 
                     *miPos = op(*miPos, 0.0);
commit c9d037e5e8e5850e9c69372580e7a506b573fc2a
Author: Eike Rathke <erack at redhat.com>
Date:   Fri Jun 13 10:50:27 2014 +0200

    resolved fdo#79957 propagate ForceArray through jump tokens
    
    ForceArray parameters weren't propagated and enforced to array arguments
    on svJump tokens (FormulaJumpToken), namely IF, CHOOSE, IFERROR and
    IFNA.
    
    Change-Id: Icf9074f11b826655a52858d778d9a0122d207aa4

diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx
index 8da6dce..0dd8d5c 100644
--- a/formula/source/core/api/token.cxx
+++ b/formula/source/core/api/token.cxx
@@ -287,11 +287,16 @@ bool FormulaFAPToken::operator==( const FormulaToken& r ) const
 {
     return FormulaByteToken::operator==( r ) && pOrigToken == r.GetFAPOrigToken();
 }
+
+
 short* FormulaJumpToken::GetJump() const                     { return pJump; }
+bool FormulaJumpToken::HasForceArray() const                 { return bHasForceArray; }
+void FormulaJumpToken::SetForceArray( bool b )               { bHasForceArray = b; }
 bool FormulaJumpToken::operator==( const FormulaToken& r ) const
 {
     return FormulaToken::operator==( r ) && pJump[0] == r.GetJump()[0] &&
-        memcmp( pJump+1, r.GetJump()+1, pJump[0] * sizeof(short) ) == 0;
+        memcmp( pJump+1, r.GetJump()+1, pJump[0] * sizeof(short) ) == 0 &&
+        bHasForceArray == r.HasForceArray();
 }
 FormulaJumpToken::~FormulaJumpToken()
 {
diff --git a/include/formula/FormulaCompiler.hxx b/include/formula/FormulaCompiler.hxx
index 81277c9..a4fd1af 100644
--- a/include/formula/FormulaCompiler.hxx
+++ b/include/formula/FormulaCompiler.hxx
@@ -356,9 +356,9 @@ private:
 
     static inline void ForceArrayOperator( FormulaTokenRef& rCurr, const FormulaTokenRef& rPrev )
         {
-            if ( rPrev && rPrev->HasForceArray() &&
-                    rCurr->GetType() == svByte && rCurr->GetOpCode() != ocPush
-                    && !rCurr->HasForceArray() )
+            if ( rPrev && rPrev->HasForceArray() && rCurr->GetOpCode() != ocPush &&
+                    (rCurr->GetType() == svByte || rCurr->GetType() == svJump) &&
+                    !rCurr->HasForceArray() )
                 rCurr->SetForceArray( true);
         }
 
diff --git a/include/formula/token.hxx b/include/formula/token.hxx
index d1654cc..2efba0d 100644
--- a/include/formula/token.hxx
+++ b/include/formula/token.hxx
@@ -352,15 +352,18 @@ class FORMULA_DLLPUBLIC FormulaJumpToken : public FormulaToken
 {
 private:
             short*              pJump;
+            bool                bHasForceArray;
 public:
                                 FormulaJumpToken( OpCode e, short* p ) :
-                                    FormulaToken( formula::svJump , e)
+                                    FormulaToken( formula::svJump , e),
+                                    bHasForceArray( false)
                                 {
                                     pJump = new short[ p[0] + 1 ];
                                     memcpy( pJump, p, (p[0] + 1) * sizeof(short) );
                                 }
                                 FormulaJumpToken( const FormulaJumpToken& r ) :
-                                    FormulaToken( r )
+                                    FormulaToken( r ),
+                                    bHasForceArray( r.bHasForceArray)
                                 {
                                     pJump = new short[ r.pJump[0] + 1 ];
                                     memcpy( pJump, r.pJump, (r.pJump[0] + 1) * sizeof(short) );
@@ -369,6 +372,8 @@ public:
     virtual short*              GetJump() const SAL_OVERRIDE;
     virtual bool                operator==( const formula::FormulaToken& rToken ) const SAL_OVERRIDE;
     virtual FormulaToken*       Clone() const SAL_OVERRIDE { return new FormulaJumpToken(*this); }
+    virtual bool                HasForceArray() const SAL_OVERRIDE;
+    virtual void                SetForceArray( bool b ) SAL_OVERRIDE;
 };
 
 
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index 37d7f60..4708e04 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -888,7 +888,7 @@ public:
 
 inline void ScInterpreter::MatrixDoubleRefToMatrix()
 {
-    if ( bMatrixFormula && GetStackType() == formula::svDoubleRef )
+    if ( (bMatrixFormula || pCur->HasForceArray()) && GetStackType() == formula::svDoubleRef )
     {
         GetTokenMatrixMap();    // make sure it exists, create if not.
         PopDoubleRefPushMatrix();


More information about the Libreoffice-commits mailing list