Kaydet (Commit) 69047ec1 authored tarafından Kohei Yoshida's avatar Kohei Yoshida

Correctly handle implicit intersection in group interpretation.

Change-Id: I2ea6f41ad4036a6f3f5d99097e83fd988aacd105
üst 2d8a60e5
...@@ -181,6 +181,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\ ...@@ -181,6 +181,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
sc/source/core/data/table5 \ sc/source/core/data/table5 \
sc/source/core/data/table6 \ sc/source/core/data/table6 \
sc/source/core/data/tabprotection \ sc/source/core/data/tabprotection \
sc/source/core/data/types \
sc/source/core/data/userdat \ sc/source/core/data/userdat \
sc/source/core/data/validat \ sc/source/core/data/validat \
sc/source/core/tool/addincfg \ sc/source/core/tool/addincfg \
......
...@@ -33,6 +33,9 @@ ...@@ -33,6 +33,9 @@
#include "scmatrix.hxx" #include "scmatrix.hxx"
#include "calcmacros.hxx" #include "calcmacros.hxx"
// Matrix token constants.
#define MATRIX_TOKEN_HAS_RANGE 1
class ScJumpMatrix; class ScJumpMatrix;
typedef ::std::vector< ScComplexRefData > ScRefList; typedef ::std::vector< ScComplexRefData > ScRefList;
...@@ -176,6 +179,27 @@ public: ...@@ -176,6 +179,27 @@ public:
virtual FormulaToken* Clone() const { return new ScMatrixToken(*this); } virtual FormulaToken* Clone() const { return new ScMatrixToken(*this); }
}; };
/**
* Token storing matrix that represents values in sheet range. It stores
* both the values in matrix form, and the range address the matrix
* represents.
*/
class ScMatrixRangeToken : public ScToken
{
ScMatrixRef mpMatrix;
ScComplexRefData maRef;
public:
ScMatrixRangeToken( const ScMatrixRef& p, const ScComplexRefData& rRef );
ScMatrixRangeToken( const ScMatrixRangeToken& r );
virtual sal_uInt8 GetByte() const;
virtual const ScMatrix* GetMatrix() const;
virtual ScMatrix* GetMatrix();
virtual const ScComplexRefData& GetDoubleRef() const;
virtual ScComplexRefData& GetDoubleRef();
virtual bool operator==( const formula::FormulaToken& rToken ) const;
virtual FormulaToken* Clone() const;
};
class ScExternalSingleRefToken : public ScToken class ScExternalSingleRefToken : public ScToken
{ {
......
...@@ -63,6 +63,19 @@ enum GroupCalcState ...@@ -63,6 +63,19 @@ enum GroupCalcState
GroupCalcDisabled GroupCalcDisabled
}; };
struct RangeMatrix
{
ScMatrixRef mpMat;
sal_Int32 mnCol1;
sal_Int32 mnRow1;
sal_Int32 mnCol2;
sal_Int32 mnRow2;
RangeMatrix();
bool isRangeValid() const;
};
} }
#endif #endif
......
...@@ -3520,7 +3520,9 @@ bool ScFormulaCell::InterpretFormulaGroup() ...@@ -3520,7 +3520,9 @@ bool ScFormulaCell::InterpretFormulaGroup()
return false; return false;
} }
if (mxGroup->mbInvariant) // TODO : Disable invariant formula group interpretation for now in order
// to get implicit intersection to work.
if (mxGroup->mbInvariant && false)
return InterpretInvariantFormulaGroup(); return InterpretInvariantFormulaGroup();
sc::FormulaGroupContext aCxt; sc::FormulaGroupContext aCxt;
......
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include "types.hxx"
#include "scmatrix.hxx"
namespace sc {
RangeMatrix::RangeMatrix() : mpMat(NULL), mnCol1(-1), mnRow1(-1), mnCol2(-1), mnRow2(-1) {}
bool RangeMatrix::isRangeValid() const
{
return mnCol1 >= 0 && mnRow1 >= 0 && mnCol2 >= 0 && mnRow2 >= 0 && mnCol1 <= mnCol2 && mnRow1 <= mnRow2;
}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
...@@ -51,6 +51,12 @@ class ScToken; ...@@ -51,6 +51,12 @@ class ScToken;
class ScJumpMatrix; class ScJumpMatrix;
struct ScRefCellValue; struct ScRefCellValue;
namespace sc {
struct RangeMatrix;
}
#define MAXSTACK (4096 / sizeof(formula::FormulaToken*)) #define MAXSTACK (4096 / sizeof(formula::FormulaToken*))
class ScTokenStack class ScTokenStack
...@@ -298,6 +304,7 @@ inline void MatrixDoubleRefToMatrix(); // if MatrixFormula: PopDoubleRefPus ...@@ -298,6 +304,7 @@ inline void MatrixDoubleRefToMatrix(); // if MatrixFormula: PopDoubleRefPus
// If MatrixFormula or ForceArray: ConvertMatrixParameters() // If MatrixFormula or ForceArray: ConvertMatrixParameters()
inline bool MatrixParameterConversion(); inline bool MatrixParameterConversion();
ScMatrixRef PopMatrix(); ScMatrixRef PopMatrix();
sc::RangeMatrix PopRangeMatrix();
void QueryMatrixType(ScMatrixRef& xMat, short& rRetTypeExpr, sal_uLong& rRetIndexExpr); void QueryMatrixType(ScMatrixRef& xMat, short& rRetTypeExpr, sal_uLong& rRetIndexExpr);
void PushDouble(double nVal); void PushDouble(double nVal);
...@@ -338,6 +345,8 @@ ScMatrixRef CreateMatrixFromDoubleRef( const formula::FormulaToken* pToken, ...@@ -338,6 +345,8 @@ ScMatrixRef CreateMatrixFromDoubleRef( const formula::FormulaToken* pToken,
inline ScTokenMatrixMap& GetTokenMatrixMap(); inline ScTokenMatrixMap& GetTokenMatrixMap();
ScTokenMatrixMap* CreateTokenMatrixMap(); ScTokenMatrixMap* CreateTokenMatrixMap();
ScMatrixRef GetMatrix(); ScMatrixRef GetMatrix();
sc::RangeMatrix GetRangeMatrix();
void ScTableOp(); // repeated operations void ScTableOp(); // repeated operations
void ScErrCell(); // special handling for void ScErrCell(); // special handling for
// error cell // error cell
...@@ -373,7 +382,7 @@ double Compare(); ...@@ -373,7 +382,7 @@ double Compare();
/** @param pOptions /** @param pOptions
NULL means case sensitivity document option is to be used! NULL means case sensitivity document option is to be used!
*/ */
ScMatrixRef CompareMat( ScCompareOptions* pOptions = NULL ); sc::RangeMatrix CompareMat( ScCompareOptions* pOptions = NULL );
ScMatrixRef QueryMat( const ScMatrixRef& pMat, ScCompareOptions& rOptions ); ScMatrixRef QueryMat( const ScMatrixRef& pMat, ScCompareOptions& rOptions );
void ScEqual(); void ScEqual();
void ScNotEqual(); void ScNotEqual();
......
...@@ -93,7 +93,11 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres ...@@ -93,7 +93,11 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres
if (p2->IsStartFixed() && p2->IsEndFixed()) if (p2->IsStartFixed() && p2->IsEndFixed())
{ {
// Cached the converted token for absolute range referene. // Cached the converted token for absolute range referene.
formula::FormulaTokenRef xTok(new ScMatrixToken(pMat)); ScComplexRefData aRef;
ScRange aRefRange = rTopPos;
aRefRange.aEnd.SetRow(rTopPos.Row() + nRowEnd);
aRef.InitRange(aRefRange);
formula::FormulaTokenRef xTok(new ScMatrixRangeToken(pMat, aRef));
aCachedTokens.insert(CachedTokensType::value_type(p, xTok)); aCachedTokens.insert(CachedTokensType::value_type(p, xTok));
aCode2.AddToken(*xTok); aCode2.AddToken(*xTok);
} }
......
...@@ -1794,6 +1794,45 @@ ScMatrixRef ScInterpreter::PopMatrix() ...@@ -1794,6 +1794,45 @@ ScMatrixRef ScInterpreter::PopMatrix()
return NULL; return NULL;
} }
sc::RangeMatrix ScInterpreter::PopRangeMatrix()
{
sc::RangeMatrix aRet;
if (sp)
{
switch (pStack[sp-1]->GetType())
{
case svMatrix:
{
--sp;
FormulaToken* p = pStack[sp];
ScToken* p2 = static_cast<ScToken*>(p);
aRet.mpMat = p2->GetMatrix();
if (aRet.mpMat)
{
aRet.mpMat->SetErrorInterpreter(this);
if (p2->GetByte() == MATRIX_TOKEN_HAS_RANGE)
{
const ScComplexRefData& rRef = p2->GetDoubleRef();
if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() && !rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel())
{
aRet.mnCol1 = rRef.Ref1.Col();
aRet.mnRow1 = rRef.Ref1.Row();
aRet.mnCol2 = rRef.Ref2.Col();
aRet.mnRow2 = rRef.Ref2.Row();
}
}
}
else
SetError( errUnknownVariable);
}
break;
default:
aRet.mpMat = PopMatrix();
}
}
return aRet;
}
void ScInterpreter::QueryMatrixType(ScMatrixRef& xMat, short& rRetTypeExpr, sal_uLong& rRetIndexExpr) void ScInterpreter::QueryMatrixType(ScMatrixRef& xMat, short& rRetTypeExpr, sal_uLong& rRetIndexExpr)
{ {
if (xMat) if (xMat)
......
...@@ -494,6 +494,20 @@ ScMatrixRef ScInterpreter::GetMatrix() ...@@ -494,6 +494,20 @@ ScMatrixRef ScInterpreter::GetMatrix()
return pMat; return pMat;
} }
sc::RangeMatrix ScInterpreter::GetRangeMatrix()
{
sc::RangeMatrix aRet;
switch (GetRawStackType())
{
case svMatrix:
aRet = PopRangeMatrix();
break;
default:
aRet.mpMat = GetMatrix();
}
return aRet;
}
void ScInterpreter::ScMatValue() void ScInterpreter::ScMatValue()
{ {
if ( MustHaveParamCount( GetByte(), 3 ) ) if ( MustHaveParamCount( GetByte(), 3 ) )
......
...@@ -804,6 +804,47 @@ bool ScMatrixToken::operator==( const FormulaToken& r ) const ...@@ -804,6 +804,47 @@ bool ScMatrixToken::operator==( const FormulaToken& r ) const
return FormulaToken::operator==( r ) && pMatrix == static_cast<const ScToken&>(r).GetMatrix(); return FormulaToken::operator==( r ) && pMatrix == static_cast<const ScToken&>(r).GetMatrix();
} }
ScMatrixRangeToken::ScMatrixRangeToken( const ScMatrixRef& p, const ScComplexRefData& rRef ) :
ScToken(formula::svMatrix), mpMatrix(p), maRef(rRef) {}
ScMatrixRangeToken::ScMatrixRangeToken( const ScMatrixRangeToken& r ) :
ScToken(r), mpMatrix(r.mpMatrix), maRef(r.maRef) {}
sal_uInt8 ScMatrixRangeToken::GetByte() const
{
return MATRIX_TOKEN_HAS_RANGE;
}
const ScMatrix* ScMatrixRangeToken::GetMatrix() const
{
return mpMatrix.get();
}
ScMatrix* ScMatrixRangeToken::GetMatrix()
{
return mpMatrix.get();
}
const ScComplexRefData& ScMatrixRangeToken::GetDoubleRef() const
{
return maRef;
}
ScComplexRefData& ScMatrixRangeToken::GetDoubleRef()
{
return maRef;
}
bool ScMatrixRangeToken::operator==( const FormulaToken& r ) const
{
return FormulaToken::operator==(r) && mpMatrix == static_cast<const ScToken&>(r).GetMatrix();
}
FormulaToken* ScMatrixRangeToken::Clone() const
{
return new ScMatrixRangeToken(*this);
}
// ============================================================================ // ============================================================================
ScExternalSingleRefToken::ScExternalSingleRefToken( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& r ) : ScExternalSingleRefToken::ScExternalSingleRefToken( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& r ) :
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment