/* -*- 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/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
bool skipToken( size_t i, const FormulaToken* const * pp )
{ // Handle all code tokens, and tokens in RPN only if they have a // reference count of 1, which means they are not referenced in the // code array. Doing it the other way would skip code tokens that // are held by flat copied token arrays and thus are shared. For // flat copy arrays the caller has to know what it does and should // discard all RPN, update only one array and regenerate all RPN. if (i == 1)
{ if ((*pp)->GetRef() > 1) returntrue;
if (mbSkipRelName)
{ // Skip (do not adjust) relative references resulting from // named expressions. Resolved expressions are only in RPN. switch ((*pp)->GetType())
{ case svSingleRef: return (*pp)->GetSingleRef()->IsRelName(); case svDoubleRef:
{ const ScComplexRefData& rRef = *(*pp)->GetDoubleRef(); return rRef.Ref1.IsRelName() || rRef.Ref2.IsRelName();
} default:
; // nothing
}
}
}
returnfalse;
}
FormulaToken* getHandledToken( size_t i, FormulaToken* const * pp )
{ if (skipToken( i, pp)) return nullptr;
FormulaToken* p = *pp; if (p->GetOpCode() == ocTableRef)
{ // Return the inner reference token if it is not in RPN.
ScTableRefToken* pTR = dynamic_cast<ScTableRefToken*>(p); if (!pTR) return p;
p = pTR->GetAreaRefRPN(); if (!p) return pTR; if (p->GetRef() > 1) // Reference handled in RPN, but do not return nullptr so // loops will process ocTableRef via pp instead of issuing // a continue. return pTR;
} return p;
}
};
} // namespace
// --- class ScRawToken -----------------------------------------------------
void ScRawToken::SetOpCode( OpCode e )
{
eOp = e; switch (eOp)
{ case ocIf:
eType = svJump;
nJump[ 0 ] = 3; // If, Else, Behind break; case ocIfError: case ocIfNA:
eType = svJump;
nJump[ 0 ] = 2; // If, Behind break; case ocChoose:
eType = svJump;
nJump[ 0 ] = FORMULA_MAXJUMPCOUNT + 1; break; case ocLet:
eType = svJump;
nJump[ 0 ] = FORMULA_MAXPARAMS + 1; break; case ocMissing:
eType = svMissing; break; case ocSep: case ocOpen: case ocClose: case ocArrayRowSep: case ocArrayColSep: case ocArrayOpen: case ocArrayClose: case ocTableRefOpen: case ocTableRefClose:
eType = svSep; break; case ocWhitespace:
eType = svByte;
whitespace.nCount = 1;
whitespace.cChar = 0x20; break; default:
eType = svByte;
sbyte.cByte = 0;
sbyte.eInForceArray = ParamClass::Unknown;
}
}
// memcmp doesn't work because of the alignment byte after bFlags. // After SmartRelAbs only absolute parts have to be compared. return aRange1 == aRange2 && aTemp1.Ref1.FlagValue() == aTemp2.Ref1.FlagValue() && aTemp1.Ref2.FlagValue() == aTemp2.Ref2.FlagValue();
}
StackVar sv1 = rTok1.GetType(); // Doing a RangeOp with RefList is probably utter nonsense, but Xcl // supports it, so do we. if (sv1 != svSingleRef && sv1 != svDoubleRef && sv1 != svRefList
&& sv1 != svExternalSingleRef && sv1 != svExternalDoubleRef) return nullptr;
StackVar sv2 = rTok2.GetType(); if (sv2 != svSingleRef && sv2 != svDoubleRef && sv2 != svRefList) return nullptr;
ScTokenRef xRes; bool bExternal = (sv1 == svExternalSingleRef); if ((sv1 == svSingleRef || bExternal) && sv2 == svSingleRef)
{ // Range references like Sheet1.A1:A2 are generalized and built by // first creating a DoubleRef from the first SingleRef, effectively // generating Sheet1.A1:A1, and then extending that with A2 as if // Sheet1.A1:A1:A2 was encountered, so the mechanisms to adjust the // references apply as well.
/* Given the current structure of external references an external * reference can only be extended if the second reference does not * point to a different sheet. 'file'#Sheet1.A1:A2 is ok, * 'file'#Sheet1.A1:Sheet2.A2 is not. Since we can't determine from a * svSingleRef whether the sheet would be different from the one given * in the external reference, we have to bail out if there is any sheet * specified. NOTE: Xcl does handle external 3D references as in * '[file]Sheet1:Sheet2'!A1:A2 * * FIXME: For OOo syntax be smart and remember an external singleref * encountered and if followed by ocRange and singleref, create an * external singleref for the second singleref. Both could then be * merged here. For Xcl syntax already parse an external range
* reference entirely, cumbersome. */
void ScTableRefToken::SetIndex( sal_uInt16 n )
{
mnIndex = n;
}
sal_Int16 ScTableRefToken::GetSheet() const
{ // Code asking for this may have to be adapted as it might assume an // svIndex token would always be ocName or ocDBArea.
SAL_WARN("sc.core","ScTableRefToken::GetSheet - maybe adapt caller to know about TableRef?"); // Database range is always global. return -1;
}
const ScMatrix* ScMatrixCellResultToken::GetMatrix() const { return xMatrix.get(); } // Non-const GetMatrix() is private and unused but must be implemented to // satisfy vtable linkage.
ScMatrix* ScMatrixCellResultToken::GetMatrix()
{ returnconst_cast<ScMatrix*>(xMatrix.get());
}
if (bThreadingProhibited)
{
mbThreadingEnabled = false; return;
}
OpCode eOp = r.GetOpCode();
if (aThreadedCalcDenyList.find(eOp) != aThreadedCalcDenyList.end())
{
SAL_INFO("sc.core.formulagroup", "opcode " << formula::FormulaCompiler().GetOpCodeMap(sheet::FormulaLanguage::ENGLISH)->getSymbol(eOp)
<< "(" << int(eOp) << ") disables threaded calculation of formula group");
mbThreadingEnabled = false; return;
}
if (eOp != ocPush) return;
switch (r.GetType())
{ case svExternalDoubleRef: case svExternalSingleRef: case svExternalName: case svMatrix:
SAL_INFO("sc.core.formulagroup", "opcode ocPush: variable type " << StackVarEnumToString(r.GetType())
<< " disables threaded calculation of formula group");
mbThreadingEnabled = false; return; default: break;
}
}
void ScTokenArray::CheckToken( const FormulaToken& r )
{ if (mbThreadingEnabled)
CheckForThreading(r);
if (IsFormulaVectorDisabled()) return; // It's already disabled. No more checking needed.
OpCode eOp = r.GetOpCode();
if (SC_OPCODE_START_FUNCTION <= eOp && eOp < SC_OPCODE_STOP_FUNCTION)
{ if (ScInterpreter::GetGlobalConfig().mbOpenCLSubsetOnly &&
ScInterpreter::GetGlobalConfig().mpOpenCLSubsetOpCodes->find(eOp) == ScInterpreter::GetGlobalConfig().mpOpenCLSubsetOpCodes->end())
{
SAL_INFO("sc.opencl", "opcode " << formula::FormulaCompiler().GetOpCodeMap(sheet::FormulaLanguage::ENGLISH)->getSymbol(eOp)
<< "(" << int(eOp) << ") disables vectorisation for formula group");
meVectorState = FormulaVectorDisabledNotInSubSet;
mbOpenCLEnabled = false; return;
}
// We support vectorization for the following opcodes. switch (eOp)
{ case ocAverage: case ocMin: case ocMinA: case ocMax: case ocMaxA: case ocSum: case ocSumIfs: case ocSumProduct: case ocCount: case ocCount2: case ocVLookup: case ocXLookup: case ocXMatch: case ocFilter: case ocSort: case ocSortBy: case ocSLN: case ocIRR: case ocMIRR: case ocPMT: case ocRate: case ocRRI: case ocPpmt: case ocFisher: case ocFisherInv: case ocGamma: case ocGammaLn: case ocNotAvail: case ocGauss: case ocGeoMean: case ocHarMean: case ocSYD: case ocCorrel: case ocNegBinomVert: case ocPearson: case ocRSQ: case ocCos: case ocCosecant: case ocCosecantHyp: case ocISPMT: case ocPDuration: case ocSinHyp: case ocAbs: case ocPV: case ocSin: case ocTan: case ocTanHyp: case ocStandard: case ocWeibull: case ocMedian: case ocDDB: case ocFV: case ocVBD: case ocKurt: case ocNper: case ocNormDist: case ocArcCos: case ocSqrt: case ocArcCosHyp: case ocNPV: case ocStdNormDist: case ocNormInv: case ocSNormInv: case ocPermut: case ocPermutationA: case ocPhi: case ocIpmt: case ocConfidence: case ocIntercept: case ocDB: case ocLogInv: case ocArcCot: case ocCosHyp: case ocCritBinom: case ocArcCotHyp: case ocArcSin: case ocArcSinHyp: case ocArcTan: case ocArcTanHyp: case ocBitAnd: case ocForecast: case ocLogNormDist: case ocGammaDist: case ocLn: case ocRound: case ocCot: case ocCotHyp: case ocFDist: case ocVar: case ocChiDist: case ocPower: case ocOdd: case ocChiSqDist: case ocChiSqInv: case ocGammaInv: case ocFloor: case ocFInv: case ocFTest: case ocB: case ocBetaDist: case ocExp: case ocLog10: case ocExpDist: case ocAverageIfs: case ocCountIfs: case ocCombinA: case ocEven: case ocLog: case ocMod: case ocTrunc: case ocSkew: case ocArcTan2: case ocBitOr: case ocBitLshift: case ocBitRshift: case ocBitXor: case ocChiInv: case ocPoissonDist: case ocSumSQ: case ocSkewp: case ocBinomDist: case ocVarP: case ocCeil: case ocCombin: case ocDevSq: case ocStDev: case ocSlope: case ocSTEYX: case ocZTest: case ocPi: case ocRandom: case ocProduct: case ocHypGeomDist: case ocSumX2MY2: case ocSumX2DY2: case ocBetaInv: case ocTTest: case ocTDist: case ocTInv: case ocSumXMY2: case ocStDevP: case ocCovar: case ocAnd: case ocOr: case ocNot: case ocXor: case ocDBMax: case ocDBMin: case ocDBProduct: case ocDBAverage: case ocDBStdDev: case ocDBStdDevP: case ocDBSum: case ocDBVar: case ocDBVarP: case ocAverageIf: case ocDBCount: case ocDBCount2: case ocDeg: case ocRoundUp: case ocRoundDown: case ocInt: case ocRad: case ocCountIf: case ocIsEven: case ocIsOdd: case ocFact: case ocAverageA: case ocVarA: case ocVarPA: case ocStDevA: case ocStDevPA: case ocSecant: case ocSecantHyp: case ocSumIf: case ocNegSub: case ocAveDev: case ocMatSequence: case ocRandArray: case ocChooseCols: case ocChooseRows: case ocDrop: case ocExpand: case ocHStack: case ocVStack: case ocTake: case ocTextSplit: case ocToCol: case ocToRow: case ocUnique: case ocWrapCols: case ocWrapRows: // Don't change the state. break; default:
SAL_INFO("sc.opencl", "opcode " << formula::FormulaCompiler().GetOpCodeMap(sheet::FormulaLanguage::ENGLISH)->getSymbol(eOp)
<< "(" << int(eOp) << ") disables vectorisation for formula group");
meVectorState = FormulaVectorDisabledByOpCode;
mbOpenCLEnabled = false; return;
}
} elseif (eOp == ocPush)
{ // This is a stack variable. See if this is a reference.
switch (r.GetType())
{ case svByte: case svDouble: case svString: // Don't change the state. break; case svSingleRef: case svDoubleRef: // Depends on the reference state.
meVectorState = FormulaVectorCheckReference; break; case svError: case svEmptyCell: case svExternal: case svExternalDoubleRef: case svExternalName: case svExternalSingleRef: case svFAP: case svHybridCell: case svIndex: case svJump: case svJumpMatrix: case svMatrix: case svMatrixCell: case svMissing: case svRefList: case svSep: case svUnknown: // We don't support vectorization on these.
SAL_INFO("sc.opencl", "opcode ocPush: variable type " << StackVarEnumToString(r.GetType()) << " disables vectorisation for formula group");
meVectorState = FormulaVectorDisabledByStackVariable;
mbOpenCLEnabled = false; return; default:
;
}
} elseif (SC_OPCODE_START_BIN_OP <= eOp && eOp < SC_OPCODE_STOP_UN_OP)
{ if (ScInterpreter::GetGlobalConfig().mbOpenCLSubsetOnly &&
ScInterpreter::GetGlobalConfig().mpOpenCLSubsetOpCodes->find(eOp) == ScInterpreter::GetGlobalConfig().mpOpenCLSubsetOpCodes->end())
{
SAL_INFO("sc.opencl", "opcode " << formula::FormulaCompiler().GetOpCodeMap(sheet::FormulaLanguage::ENGLISH)->getSymbol(eOp)
<< "(" << int(eOp) << ") disables vectorisation for formula group");
meVectorState = FormulaVectorDisabledNotInSubSet;
mbOpenCLEnabled = false; return;
}
} else
{ // All the rest, special commands, separators, error codes, ... switch (eOp)
{ default: // Default is off, no vectorization. // Mentioning some specific values below to indicate why.
case ocName: // Named expression would need "recursive" handling of its // token array for vector state in // ScFormulaCell::InterpretFormulaGroup() and below.
case ocDBArea: // Certainly not a vectorization of the entire area...
case ocTableRef: // May result in a single cell or range reference, depending on // context.
case ocColRowName: // The associated reference is the name cell with which to // create the implicit intersection.
case ocColRowNameAuto: // Auto column/row names lead to references computed in // interpreter.
// Known good, don't change state. case ocStop: case ocExternal: case ocOpen: case ocClose: case ocSep: case ocArrayOpen: case ocArrayRowSep: case ocArrayColSep: case ocArrayClose: case ocMissing: case ocBad: case ocSpaces: case ocWhitespace: case ocSkip: case ocPercentSign: case ocErrNull: case ocErrDivZero: case ocErrValue: case ocErrRef: case ocErrName: case ocErrNum: case ocErrNA: break; case ocIf: case ocIfError: case ocIfNA: case ocChoose: case ocLet: // Jump commands are now supported. break;
}
}
}
// we want to compare for similar not identical formulae // so we can't use actual row & column indices.
size_t HashSingleRef( const ScSingleRefData& rRef )
{
size_t nVal = 0;
bool ScTokenArray::IsFormulaVectorDisabled() const
{ switch (meVectorState)
{ case FormulaVectorDisabled: case FormulaVectorDisabledByOpCode: case FormulaVectorDisabledByStackVariable: case FormulaVectorDisabledNotInSubSet: returntrue; default:
;
}
returnfalse;
}
bool ScTokenArray::IsInvariant() const
{
FormulaToken** p = pCode.get();
FormulaToken** pEnd = p + static_cast<size_t>(nLen); for (; p != pEnd; ++p)
{ switch ((*p)->GetType())
{ case svSingleRef: case svExternalSingleRef:
{ const ScSingleRefData& rRef = *(*p)->GetSingleRef(); if (rRef.IsRowRel()) returnfalse;
} break; case svDoubleRef: case svExternalDoubleRef:
{ const ScComplexRefData& rRef = *(*p)->GetDoubleRef(); if (rRef.Ref1.IsRowRel() || rRef.Ref2.IsRowRel()) returnfalse;
} break; case svIndex: returnfalse; default:
;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.