diff options
author | Tor Lillqvist <tml@collabora.com> | 2013-11-14 19:30:36 +0200 |
---|---|---|
committer | Michael Meeks <michael.meeks@collabora.com> | 2013-11-20 18:23:05 +0000 |
commit | 2f98f0ecf8964f5fce8e315fbff29760aa6449dd (patch) | |
tree | 6ab4d106bafd3958cabe71ff64800d963d4502ef /sc/source/core/data | |
parent | 25fb3d749c3184b96c79352be4990c9b4fa6c602 (diff) |
WIP: Background ahead-of-time OpenCL compilation
Work in progress, does not work. That's what WIP means.
Change-Id: I31459624a45370384e00392937ac9a5b9cd893c2
Diffstat (limited to 'sc/source/core/data')
-rw-r--r-- | sc/source/core/data/formulacell.cxx | 245 | ||||
-rw-r--r-- | sc/source/core/data/grouptokenconverter.cxx | 236 |
2 files changed, 242 insertions, 239 deletions
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index 321c6af4ea3f..1fbe8956c40e 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -3448,233 +3448,6 @@ ScFormulaCell::CompareState ScFormulaCell::CompareByTokenArray( ScFormulaCell& r return bInvariant ? EqualInvariant : EqualRelativeRef; } -namespace { - -class GroupTokenConverter -{ - ScTokenArray& mrGroupTokens; - ScDocument& mrDoc; - ScFormulaCell& mrCell; - const ScAddress& mrPos; - - bool isSelfReferenceRelative(const ScAddress& rRefPos, SCROW nRelRow) - { - if (rRefPos.Col() != mrPos.Col()) - return false; - - SCROW nLen = mrCell.GetCellGroup()->mnLength; - SCROW nEndRow = mrPos.Row() + nLen - 1; - - if (nRelRow < 0) - { - SCROW nTest = nEndRow; - nTest += nRelRow; - if (nTest >= mrPos.Row()) - return true; - } - else if (nRelRow > 0) - { - SCROW nTest = mrPos.Row(); // top row. - nTest += nRelRow; - if (nTest <= nEndRow) - return true; - } - - return false; - } - - bool isSelfReferenceAbsolute(const ScAddress& rRefPos) - { - if (rRefPos.Col() != mrPos.Col()) - return false; - - SCROW nLen = mrCell.GetCellGroup()->mnLength; - SCROW nEndRow = mrPos.Row() + nLen - 1; - - if (rRefPos.Row() < mrPos.Row()) - return false; - - if (rRefPos.Row() > nEndRow) - return false; - - return true; - } - - SCROW trimLength(SCTAB nTab, SCCOL nCol1, SCCOL nCol2, SCROW nRow, SCROW nRowLen) - { - SCROW nLastRow = nRow + nRowLen - 1; // current last row. - nLastRow = mrDoc.GetLastDataRow(nTab, nCol1, nCol2, nLastRow); - if (nLastRow < (nRow + nRowLen - 1)) - nRowLen = nLastRow - nRow + 1; - else if (nLastRow == 0) - // Column is empty. - nRowLen = 1; - - return nRowLen; - } -public: - GroupTokenConverter(ScTokenArray& rGroupTokens, ScDocument& rDoc, ScFormulaCell& rCell, const ScAddress& rPos) : - mrGroupTokens(rGroupTokens), mrDoc(rDoc), mrCell(rCell), mrPos(rPos) {} - - bool convert(ScTokenArray& rCode) - { -#if 0 - { // debug to start with: - ScCompiler aComp( &mrDoc, mrPos, rCode); - aComp.SetGrammar(formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1); - OUStringBuffer aAsString; - aComp.CreateStringFromTokenArray(aAsString); - } -#endif - - rCode.Reset(); - for (const formula::FormulaToken* p = rCode.First(); p; p = rCode.Next()) - { - // A reference can be either absolute or relative. If it's absolute, - // convert it to a static value token. If relative, convert it to a - // vector reference token. Note: we only care about relative vs - // absolute reference state for row directions. - - const ScToken* pToken = static_cast<const ScToken*>(p); - SCROW nLen = mrCell.GetCellGroup()->mnLength; - switch (pToken->GetType()) - { - case svSingleRef: - { - ScSingleRefData aRef = pToken->GetSingleRef(); - ScAddress aRefPos = aRef.toAbs(mrPos); - if (aRef.IsRowRel()) - { - if (isSelfReferenceRelative(aRefPos, aRef.Row())) - return false; - - // Trim data array length to actual data range. - nLen = trimLength(aRefPos.Tab(), aRefPos.Col(), aRefPos.Col(), aRefPos.Row(), nLen); - - // Fetch double array guarantees that the length of the - // returned array equals or greater than the requested - // length. - - formula::VectorRefArray aArray = mrDoc.FetchVectorRefArray(aRefPos, nLen); - if (!aArray.isValid()) - return false; - - formula::SingleVectorRefToken aTok(aArray, nLen); - mrGroupTokens.AddToken(aTok); - } - else - { - // Absolute row reference. - if (isSelfReferenceAbsolute(aRefPos)) - return false; - - formula::FormulaTokenRef pNewToken = mrDoc.ResolveStaticReference(aRefPos); - if (!pNewToken) - return false; - - mrGroupTokens.AddToken(*pNewToken); - } - } - break; - case svDoubleRef: - { - ScComplexRefData aRef = pToken->GetDoubleRef(); - ScRange aAbs = aRef.toAbs(mrPos); - - // Check for self reference. - if (aRef.Ref1.IsRowRel()) - { - if (isSelfReferenceRelative(aAbs.aStart, aRef.Ref1.Row())) - return false; - } - else if (isSelfReferenceAbsolute(aAbs.aStart)) - return false; - - if (aRef.Ref2.IsRowRel()) - { - if (isSelfReferenceRelative(aAbs.aEnd, aRef.Ref2.Row())) - return false; - } - else if (isSelfReferenceAbsolute(aAbs.aEnd)) - return false; - - // Row reference is relative. - bool bAbsFirst = !aRef.Ref1.IsRowRel(); - bool bAbsLast = !aRef.Ref2.IsRowRel(); - ScAddress aRefPos = aAbs.aStart; - size_t nCols = aAbs.aEnd.Col() - aAbs.aStart.Col() + 1; - std::vector<formula::VectorRefArray> aArrays; - aArrays.reserve(nCols); - SCROW nRefRowSize = aAbs.aEnd.Row() - aAbs.aStart.Row() + 1; - SCROW nArrayLength = nRefRowSize; - if (!bAbsLast) - { - // range end position is relative. Extend the array length. - SCROW nLastRefRowOffset = aAbs.aEnd.Row() - mrPos.Row(); - SCROW nLastRefRow = mrPos.Row() + nLen - 1 + nLastRefRowOffset; - SCROW nNewLength = nLastRefRow - aAbs.aStart.Row() + 1; - if (nNewLength > nArrayLength) - nArrayLength = nNewLength; - } - - // Trim trailing empty rows. - nArrayLength = trimLength(aRefPos.Tab(), aAbs.aStart.Col(), aAbs.aEnd.Col(), aRefPos.Row(), nArrayLength); - - for (SCCOL i = aAbs.aStart.Col(); i <= aAbs.aEnd.Col(); ++i) - { - aRefPos.SetCol(i); - formula::VectorRefArray aArray = mrDoc.FetchVectorRefArray(aRefPos, nArrayLength); - if (!aArray.isValid()) - return false; - - aArrays.push_back(aArray); - } - - formula::DoubleVectorRefToken aTok(aArrays, nArrayLength, nRefRowSize, bAbsFirst, bAbsLast); - mrGroupTokens.AddToken(aTok); - } - break; - case svIndex: - { - // Named range. - ScRangeName* pNames = mrDoc.GetRangeName(); - if (!pNames) - // This should never fail. - return false; - - ScRangeData* pRange = pNames->findByIndex(p->GetIndex()); - if (!pRange) - // No named range exists by that index. - return false; - - ScTokenArray* pNamedTokens = pRange->GetCode(); - if (!pNamedTokens) - // This named range is empty. - return false; - - mrGroupTokens.AddOpCode(ocOpen); - - if (!convert(*pNamedTokens)) - return false; - - mrGroupTokens.AddOpCode(ocClose); - } - break; - default: - mrGroupTokens.AddToken(*pToken); - } - } - - ScCompiler aComp(&mrDoc, mrPos, mrGroupTokens); - aComp.SetGrammar(mrDoc.GetGrammar()); - aComp.CompileTokenArray(); // Regenerate RPN tokens. - - return true; - } -}; - -} - bool ScFormulaCell::InterpretFormulaGroup() { if (!ScInterpreter::GetGlobalConfig().mbOpenCLEnabled) @@ -3704,23 +3477,17 @@ bool ScFormulaCell::InterpretFormulaGroup() if (mxGroup->mbInvariant && false) return InterpretInvariantFormulaGroup(); - ScTokenArray aCode; - ScAddress aTopPos = mxGroup->mpTopCell->aPos; - GroupTokenConverter aConverter(aCode, *pDocument, *this, aTopPos); - if (!aConverter.convert(*pCode)) + ScTokenArray aDummy; + if (mxGroup->meCalcState == sc::GroupCalcEnabled) + mxGroup->meCalcState = sc::GroupCalcRunning; + if (!sc::FormulaGroupInterpreter::getStatic()->interpret(*pDocument, mxGroup->mpTopCell->aPos, mxGroup, aDummy)) { mxGroup->meCalcState = sc::GroupCalcDisabled; return false; } - mxGroup->meCalcState = sc::GroupCalcRunning; - if (!sc::FormulaGroupInterpreter::getStatic()->interpret(*pDocument, aTopPos, mxGroup, aCode)) - { - mxGroup->meCalcState = sc::GroupCalcDisabled; - return false; - } - - mxGroup->meCalcState = sc::GroupCalcEnabled; + if (mxGroup->meCalcState == sc::GroupCalcRunning) + mxGroup->meCalcState = sc::GroupCalcEnabled; return true; } diff --git a/sc/source/core/data/grouptokenconverter.cxx b/sc/source/core/data/grouptokenconverter.cxx new file mode 100644 index 000000000000..55b27092789b --- /dev/null +++ b/sc/source/core/data/grouptokenconverter.cxx @@ -0,0 +1,236 @@ +/* -*- 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 <formula/token.hxx> +#include <formula/vectortoken.hxx> + +#include "compiler.hxx" +#include "grouptokenconverter.hxx" + +using namespace formula; + +bool ScGroupTokenConverter::isSelfReferenceRelative(const ScAddress& rRefPos, SCROW nRelRow) +{ + if (rRefPos.Col() != mrPos.Col()) + return false; + + SCROW nLen = mrCell.GetCellGroup()->mnLength; + SCROW nEndRow = mrPos.Row() + nLen - 1; + + if (nRelRow < 0) + { + SCROW nTest = nEndRow; + nTest += nRelRow; + if (nTest >= mrPos.Row()) + return true; + } + else if (nRelRow > 0) + { + SCROW nTest = mrPos.Row(); // top row. + nTest += nRelRow; + if (nTest <= nEndRow) + return true; + } + + return false; +} + +bool ScGroupTokenConverter::isSelfReferenceAbsolute(const ScAddress& rRefPos) +{ + if (rRefPos.Col() != mrPos.Col()) + return false; + + SCROW nLen = mrCell.GetCellGroup()->mnLength; + SCROW nEndRow = mrPos.Row() + nLen - 1; + + if (rRefPos.Row() < mrPos.Row()) + return false; + + if (rRefPos.Row() > nEndRow) + return false; + + return true; +} + +SCROW ScGroupTokenConverter::trimLength(SCTAB nTab, SCCOL nCol1, SCCOL nCol2, SCROW nRow, SCROW nRowLen) +{ + SCROW nLastRow = nRow + nRowLen - 1; // current last row. + nLastRow = mrDoc.GetLastDataRow(nTab, nCol1, nCol2, nLastRow); + if (nLastRow < (nRow + nRowLen - 1)) + nRowLen = nLastRow - nRow + 1; + else if (nLastRow == 0) + // Column is empty. + nRowLen = 1; + + return nRowLen; +} + +ScGroupTokenConverter::ScGroupTokenConverter(ScTokenArray& rGroupTokens, ScDocument& rDoc, ScFormulaCell& rCell, const ScAddress& rPos) : + mrGroupTokens(rGroupTokens), mrDoc(rDoc), mrCell(rCell), mrPos(rPos) + +{ +} + +bool ScGroupTokenConverter::convert(ScTokenArray& rCode) +{ +#if 0 + { // debug to start with: + ScCompiler aComp( &mrDoc, mrPos, rCode); + aComp.SetGrammar(formula::FormulaGrammar::GRAM_NATIVE_XL_R1C1); + OUStringBuffer aAsString; + aComp.CreateStringFromTokenArray(aAsString); + } +#endif + + rCode.Reset(); + for (const formula::FormulaToken* p = rCode.First(); p; p = rCode.Next()) + { + // A reference can be either absolute or relative. If it's absolute, + // convert it to a static value token. If relative, convert it to a + // vector reference token. Note: we only care about relative vs + // absolute reference state for row directions. + + const ScToken* pToken = static_cast<const ScToken*>(p); + SCROW nLen = mrCell.GetCellGroup()->mnLength; + switch (pToken->GetType()) + { + case svSingleRef: + { + ScSingleRefData aRef = pToken->GetSingleRef(); + ScAddress aRefPos = aRef.toAbs(mrPos); + if (aRef.IsRowRel()) + { + if (isSelfReferenceRelative(aRefPos, aRef.Row())) + return false; + + // Trim data array length to actual data range. + nLen = trimLength(aRefPos.Tab(), aRefPos.Col(), aRefPos.Col(), aRefPos.Row(), nLen); + + // Fetch double array guarantees that the length of the + // returned array equals or greater than the requested + // length. + + formula::VectorRefArray aArray = mrDoc.FetchVectorRefArray(aRefPos, nLen); + if (!aArray.isValid()) + return false; + + formula::SingleVectorRefToken aTok(aArray, nLen); + mrGroupTokens.AddToken(aTok); + } + else + { + // Absolute row reference. + if (isSelfReferenceAbsolute(aRefPos)) + return false; + + formula::FormulaTokenRef pNewToken = mrDoc.ResolveStaticReference(aRefPos); + if (!pNewToken) + return false; + + mrGroupTokens.AddToken(*pNewToken); + } + } + break; + case svDoubleRef: + { + ScComplexRefData aRef = pToken->GetDoubleRef(); + ScRange aAbs = aRef.toAbs(mrPos); + + // Check for self reference. + if (aRef.Ref1.IsRowRel()) + { + if (isSelfReferenceRelative(aAbs.aStart, aRef.Ref1.Row())) + return false; + } + else if (isSelfReferenceAbsolute(aAbs.aStart)) + return false; + + if (aRef.Ref2.IsRowRel()) + { + if (isSelfReferenceRelative(aAbs.aEnd, aRef.Ref2.Row())) + return false; + } + else if (isSelfReferenceAbsolute(aAbs.aEnd)) + return false; + + // Row reference is relative. + bool bAbsFirst = !aRef.Ref1.IsRowRel(); + bool bAbsLast = !aRef.Ref2.IsRowRel(); + ScAddress aRefPos = aAbs.aStart; + size_t nCols = aAbs.aEnd.Col() - aAbs.aStart.Col() + 1; + std::vector<formula::VectorRefArray> aArrays; + aArrays.reserve(nCols); + SCROW nRefRowSize = aAbs.aEnd.Row() - aAbs.aStart.Row() + 1; + SCROW nArrayLength = nRefRowSize; + if (!bAbsLast) + { + // range end position is relative. Extend the array length. + SCROW nLastRefRowOffset = aAbs.aEnd.Row() - mrPos.Row(); + SCROW nLastRefRow = mrPos.Row() + nLen - 1 + nLastRefRowOffset; + SCROW nNewLength = nLastRefRow - aAbs.aStart.Row() + 1; + if (nNewLength > nArrayLength) + nArrayLength = nNewLength; + } + + // Trim trailing empty rows. + nArrayLength = trimLength(aRefPos.Tab(), aAbs.aStart.Col(), aAbs.aEnd.Col(), aRefPos.Row(), nArrayLength); + + for (SCCOL i = aAbs.aStart.Col(); i <= aAbs.aEnd.Col(); ++i) + { + aRefPos.SetCol(i); + formula::VectorRefArray aArray = mrDoc.FetchVectorRefArray(aRefPos, nArrayLength); + if (!aArray.isValid()) + return false; + + aArrays.push_back(aArray); + } + + formula::DoubleVectorRefToken aTok(aArrays, nArrayLength, nRefRowSize, bAbsFirst, bAbsLast); + mrGroupTokens.AddToken(aTok); + } + break; + case svIndex: + { + // Named range. + ScRangeName* pNames = mrDoc.GetRangeName(); + if (!pNames) + // This should never fail. + return false; + + ScRangeData* pRange = pNames->findByIndex(p->GetIndex()); + if (!pRange) + // No named range exists by that index. + return false; + + ScTokenArray* pNamedTokens = pRange->GetCode(); + if (!pNamedTokens) + // This named range is empty. + return false; + + mrGroupTokens.AddOpCode(ocOpen); + + if (!convert(*pNamedTokens)) + return false; + + mrGroupTokens.AddOpCode(ocClose); + } + break; + default: + mrGroupTokens.AddToken(*pToken); + } + } + + ScCompiler aComp(&mrDoc, mrPos, mrGroupTokens); + aComp.SetGrammar(mrDoc.GetGrammar()); + aComp.CompileTokenArray(); // Regenerate RPN tokens. + + return true; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |