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 d83ab715a04c166ad0e8962b52c0800fb6f2969c Author: Eike Rathke <er...@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 (cherry picked from commit a288bebbcec0b16e1ced09a601de5ffbb6b1bbe0) 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 2205ed7..3212363 100644 --- a/sc/source/core/tool/interpr5.cxx +++ b/sc/source/core/tool/interpr5.cxx @@ -1661,13 +1661,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 8b3cc25..18aeb5d 100644 --- a/sc/source/core/tool/scmatrix.cxx +++ b/sc/source/core/tool/scmatrix.cxx @@ -1511,7 +1511,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) @@ -1582,7 +1582,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) @@ -1598,7 +1598,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); @@ -1611,7 +1611,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); @@ -1629,7 +1629,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 3453879aac287670db6f700ab98b2519912e9355 Author: Eike Rathke <er...@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 (cherry picked from commit c9d037e5e8e5850e9c69372580e7a506b573fc2a) 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 642699a..9122e0a 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(); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits