1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #ifndef INCLUDED_SC_SOURCE_CORE_INC_INTERPRE_HXX
21 #define INCLUDED_SC_SOURCE_CORE_INC_INTERPRE_HXX
22 
23 #include <rtl/math.hxx>
24 #include <rtl/ustring.hxx>
25 #include <unotools/textsearch.hxx>
26 #include <formula/errorcodes.hxx>
27 #include <formula/tokenarray.hxx>
28 #include <scdllapi.h>
29 #include <types.hxx>
30 #include <externalrefmgr.hxx>
31 #include <calcconfig.hxx>
32 #include <token.hxx>
33 #include <math.hxx>
34 #include "parclass.hxx"
35 
36 #include <map>
37 #include <memory>
38 #include <vector>
39 #include <limits>
40 #include <ostream>
41 
42 namespace sfx2 { class LinkManager; }
43 
44 class ScDocument;
45 class SbxVariable;
46 class ScFormulaCell;
47 class ScDBRangeBase;
48 struct ScQueryParam;
49 struct ScDBQueryParamBase;
50 struct ScQueryEntry;
51 
52 struct ScSingleRefData;
53 struct ScComplexRefData;
54 struct ScInterpreterContext;
55 
56 class ScJumpMatrix;
57 struct ScRefCellValue;
58 
59 namespace sc {
60 
61 struct CompareOptions;
62 
63 struct ParamIfsResult
64 {
65     double mfSum = 0.0;
66     double mfMem = 0.0;
67     double mfCount = 0.0;
68     double mfMin = std::numeric_limits<double>::max();
69     double mfMax = std::numeric_limits<double>::lowest();
70 };
71 
72 template<typename charT, typename traits>
operator <<(std::basic_ostream<charT,traits> & stream,const ParamIfsResult & rRes)73 inline std::basic_ostream<charT, traits> & operator <<(std::basic_ostream<charT, traits> & stream, const ParamIfsResult& rRes)
74 {
75     stream << "{" <<
76         "sum=" << rRes.mfSum << "," <<
77         "mem=" << rRes.mfMem << "," <<
78         "count=" << rRes.mfCount << "," <<
79         "min=" << rRes.mfMin << "," <<
80         "max=" << rRes.mfMax << "," <<
81         "}";
82 
83     return stream;
84 }
85 
86 }
87 
88 namespace svl {
89 
90 class SharedStringPool;
91 
92 }
93 
94 /// Arbitrary 256MB result string length limit.
95 constexpr sal_Int32 kScInterpreterMaxStrLen = SAL_MAX_INT32 / 8;
96 
97 #define MAXSTACK      (4096 / sizeof(formula::FormulaToken*))
98 
99 class ScTokenStack
100 {
101 public:
102     const formula::FormulaToken* pPointer[ MAXSTACK ];
103 };
104 
105 enum ScIterFunc {
106     ifSUM,                              // Add up
107     ifSUMSQ,                            // Sums of squares
108     ifPRODUCT,                          // Product
109     ifAVERAGE,                          // Average
110     ifCOUNT,                            // Count Values
111     ifCOUNT2,                           // Count Values (not empty)
112     ifMIN,                              // Minimum
113     ifMAX                               // Maximum
114 };
115 
116 enum ScIterFuncIf
117 {
118     ifSUMIF,                            // Conditional sum
119     ifAVERAGEIF                         // Conditional average
120 };
121 
122 enum ScETSType
123 {
124     etsAdd,
125     etsMult,
126     etsSeason,
127     etsPIAdd,
128     etsPIMult,
129     etsStatAdd,
130     etsStatMult
131 };
132 
133 struct FormulaTokenRef_less
134 {
operator ()FormulaTokenRef_less135     bool operator () ( const formula::FormulaConstTokenRef& r1, const formula::FormulaConstTokenRef& r2 ) const
136         { return r1.get() < r2.get(); }
137 };
138 typedef ::std::map< const formula::FormulaConstTokenRef, formula::FormulaConstTokenRef, FormulaTokenRef_less> ScTokenMatrixMap;
139 
140 class ScInterpreter
141 {
142     // distribution function objects need the GetxxxDist methods
143     friend class ScGammaDistFunction;
144     friend class ScBetaDistFunction;
145     friend class ScTDistFunction;
146     friend class ScFDistFunction;
147     friend class ScChiDistFunction;
148     friend class ScChiSqDistFunction;
149 
150 public:
151     static void SetGlobalConfig(const ScCalcConfig& rConfig);
152     static const ScCalcConfig& GetGlobalConfig();
153 
154     static void GlobalExit();           // called by ScGlobal::Clear()
155 
156     /// Could string be a regular expression?
157     /// if regularExpressions are disabled the function returns false regardless
158     /// of the string content.
159     static bool MayBeRegExp( const OUString& rStr, bool bIgnoreWildcards = false );
160 
161     /** Could string be a wildcard (*,?,~) expression?
162         If wildcards are disabled the function returns false regardless of the
163         string content.
164      */
165     static bool MayBeWildcard( const OUString& rStr );
166 
167     /** Detect if string should be used as regular expression or wildcard
168         expression or literal string.
169      */
170     static utl::SearchParam::SearchType DetectSearchType( const OUString& rStr, const ScDocument* pDoc );
171 
172     /// Fail safe division, returning a FormulaError::DivisionByZero coded into a double
173     /// if denominator is 0.0
174     static inline double div( const double& fNumerator, const double& fDenominator );
175 
176     ScMatrixRef GetNewMat(SCSIZE nC, SCSIZE nR, bool bEmpty = false);
177 
178     ScMatrixRef GetNewMat(SCSIZE nC, SCSIZE nR, const std::vector<double>& rValues);
179 
180     enum VolatileType {
181         VOLATILE,
182         VOLATILE_MACRO,
183         NOT_VOLATILE
184     };
185 
GetVolatileType() const186     VolatileType GetVolatileType() const { return meVolatileType;}
187 
188 private:
189     static ScCalcConfig& GetOrCreateGlobalConfig();
190     static ScCalcConfig *mpGlobalConfig;
191 
192     static thread_local std::unique_ptr<ScTokenStack>  pGlobalStack;
193     static thread_local bool                           bGlobalStackInUse;
194 
195     ScCalcConfig maCalcConfig;
196     formula::FormulaTokenIterator aCode;
197     ScAddress   aPos;
198     ScTokenArray* pArr;
199     ScInterpreterContext& mrContext;
200     ScDocument* pDok;
201     sfx2::LinkManager* mpLinkManager;
202     svl::SharedStringPool& mrStrPool;
203     formula::FormulaConstTokenRef  xResult;
204     ScJumpMatrix*   pJumpMatrix;        // currently active array condition, if any
205     std::unique_ptr<ScTokenMatrixMap> pTokenMatrixMap;  // map FormulaToken* to formula::FormulaTokenRef if in array condition
206     ScFormulaCell* pMyFormulaCell;      // the cell of this formula expression
207     SvNumberFormatter* pFormatter;
208 
209     const formula::FormulaToken* pCur;  // current token
210     ScTokenStack* pStackObj;            // contains the stacks
211     const formula::FormulaToken ** pStack;  // the current stack
212     FormulaError nGlobalError;          // global (local to this formula expression) error
213     sal_uInt16  sp;                     // stack pointer
214     sal_uInt16  maxsp;                  // the maximal used stack pointer
215     sal_uInt32  nFuncFmtIndex;          // NumberFormatIndex of a function
216     sal_uInt32  nCurFmtIndex;           // current NumberFormatIndex
217     sal_uInt32  nRetFmtIndex;           // NumberFormatIndex of an expression, if any
218     SvNumFormatType nFuncFmtType;       // NumberFormatType of a function
219     SvNumFormatType nCurFmtType;        // current NumberFormatType
220     SvNumFormatType nRetFmtType;        // NumberFormatType of an expression
221     FormulaError  mnStringNoValueError; // the error set in ConvertStringToValue() if no value
222     SubtotalFlags mnSubTotalFlags;      // flags for subtotal and aggregate functions
223     sal_uInt8   cPar;                   // current count of parameters
224     bool const  bCalcAsShown;           // precision as shown
225     bool        bMatrixFormula;         // formula cell is a matrix formula
226 
227     VolatileType meVolatileType;
228 
229     void MakeMatNew(ScMatrixRef& rMat, SCSIZE nC, SCSIZE nR);
230 
231     /// Merge global and document specific settings.
232     void MergeCalcConfig();
233 
234     // nMust <= nAct <= nMax ? ok : PushError
235     inline bool MustHaveParamCount( short nAct, short nMust );
236     inline bool MustHaveParamCount( short nAct, short nMust, short nMax );
237     inline bool MustHaveParamCountMin( short nAct, short nMin );
238     void PushParameterExpected();
239     void PushIllegalParameter();
240     void PushIllegalArgument();
241     void PushNoValue();
242     void PushNA();
243 
244     // Functions for accessing a document
245 
246     void ReplaceCell( ScAddress& );     // for TableOp
247     bool IsTableOpInRange( const ScRange& );
248     sal_uInt32 GetCellNumberFormat( const ScAddress& rPos, ScRefCellValue& rCell );
249     double ConvertStringToValue( const OUString& );
250 public:
251     static double ScGetGCD(double fx, double fy);
252     /** For matrix back calls into the current interpreter.
253         Uses rError instead of nGlobalError and rCurFmtType instead of nCurFmtType. */
254     double ConvertStringToValue( const OUString&, FormulaError& rError, SvNumFormatType& rCurFmtType );
255 private:
256     double GetCellValue( const ScAddress&, ScRefCellValue& rCell );
257     double GetCellValueOrZero( const ScAddress&, ScRefCellValue& rCell );
258     double GetValueCellValue( const ScAddress&, double fOrig );
259     void GetCellString( svl::SharedString& rStr, ScRefCellValue& rCell );
260     static FormulaError GetCellErrCode( const ScRefCellValue& rCell );
261 
262     bool CreateDoubleArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
263                          SCCOL nCol2, SCROW nRow2, SCTAB nTab2, sal_uInt8* pCellArr);
264     bool CreateStringArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
265                          SCCOL nCol2, SCROW nRow2, SCTAB nTab2, sal_uInt8* pCellArr);
266     bool CreateCellArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
267                        SCCOL nCol2, SCROW nRow2, SCTAB nTab2, sal_uInt8* pCellArr);
268 
269     // Stack operations
270 
271     /** Does substitute with formula::FormulaErrorToken in case nGlobalError is set and the token
272         passed is not formula::FormulaErrorToken.
273         Increments RefCount of the original token if not substituted. */
274     void Push( const formula::FormulaToken& r );
275 
276     /** Does not substitute with formula::FormulaErrorToken in case nGlobalError is set.
277         Used to push RPN tokens or from within Push() or tokens that are already
278         explicit formula::FormulaErrorToken. Increments RefCount. */
279     void PushWithoutError( const formula::FormulaToken& r );
280 
281     /** Does substitute with formula::FormulaErrorToken in case nGlobalError is set and the token
282         passed is not formula::FormulaErrorToken.
283         Increments RefCount of the original token if not substituted.
284         ATTENTION! The token had to be allocated with `new' and must not be used
285         after this call if no RefCount was set because possibly it gets immediately
286         deleted in case of a FormulaError::StackOverflow or if substituted with formula::FormulaErrorToken! */
287     void PushTempToken( formula::FormulaToken* );
288 
289     /** Pushes the token or substitutes with formula::FormulaErrorToken in case
290         nGlobalError is set and the token passed is not formula::FormulaErrorToken.
291         Increments RefCount of the original token if not substituted. */
292     void PushTokenRef( const formula::FormulaConstTokenRef& );
293 
294     /** Does not substitute with formula::FormulaErrorToken in case nGlobalError is set.
295         Used to push tokens from within PushTempToken() or tokens that are already
296         explicit formula::FormulaErrorToken. Increments RefCount.
297         ATTENTION! The token had to be allocated with `new' and must not be used
298         after this call if no RefCount was set because possibly it gets immediately
299         decremented again and thus deleted in case of a FormulaError::StackOverflow! */
300     void PushTempTokenWithoutError( const formula::FormulaToken* );
301 
302     /** If nGlobalError is set push formula::FormulaErrorToken.
303         If nGlobalError is not set do nothing.
304         Used in PushTempToken() and alike to simplify handling.
305         @return: <TRUE/> if nGlobalError. */
IfErrorPushError()306     bool IfErrorPushError()
307     {
308         if (nGlobalError != FormulaError::NONE)
309         {
310             PushTempTokenWithoutError( new formula::FormulaErrorToken( nGlobalError));
311             return true;
312         }
313         return false;
314     }
315 
316     /** Obtain cell result / content from address and push as temp token.
317 
318         @param  bDisplayEmptyAsString
319                 is passed to ScEmptyCell in case of an empty cell result.
320 
321         @param  pRetTypeExpr
322         @param  pRetIndexExpr
323                 Obtain number format and type if _both_, type and index pointer,
324                 are not NULL.
325 
326         @param  bFinalResult
327                 If TRUE, only a standard FormulaDoubleToken is pushed.
328                 If FALSE, PushDouble() is used that may push either a
329                 FormulaDoubleToken or a FormulaTypedDoubleToken.
330      */
331     void PushCellResultToken( bool bDisplayEmptyAsString, const ScAddress & rAddress,
332             SvNumFormatType * pRetTypeExpr, sal_uInt32 * pRetIndexExpr, bool bFinalResult = false );
333 
334     formula::FormulaConstTokenRef PopToken();
335     void Pop();
336     void PopError();
337     double PopDouble();
338     svl::SharedString PopString();
339     void ValidateRef( const ScSingleRefData & rRef );
340     void ValidateRef( const ScComplexRefData & rRef );
341     void ValidateRef( const ScRefList & rRefList );
342     void SingleRefToVars( const ScSingleRefData & rRef, SCCOL & rCol, SCROW & rRow, SCTAB & rTab );
343     void PopSingleRef( ScAddress& );
344     void PopSingleRef(SCCOL& rCol, SCROW &rRow, SCTAB& rTab);
345     void DoubleRefToRange( const ScComplexRefData&, ScRange&, bool bDontCheckForTableOp = false );
346     /** If formula::StackVar formula::svDoubleRef pop ScDoubleRefToken and return values of
347         ScComplexRefData.
348         Else if StackVar svRefList return values of the ScComplexRefData where
349         rRefInList is pointing to. rRefInList is incremented. If rRefInList was the
350         last element in list pop ScRefListToken and set rRefInList to 0, else
351         rParam is incremented (!) to allow usage as in
352         while(nParamCount--) PopDoubleRef(aRange,nParamCount,nRefInList);
353       */
354     void PopDoubleRef( ScRange & rRange, short & rParam, size_t & rRefInList );
355     void PopDoubleRef( ScRange&, bool bDontCheckForTableOp = false );
356     void DoubleRefToVars( const formula::FormulaToken* p,
357             SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
358             SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2 );
359     ScDBRangeBase* PopDBDoubleRef();
360     void PopDoubleRef(SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
361                               SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2 );
362 
363     void PopExternalSingleRef(sal_uInt16& rFileId, OUString& rTabName, ScSingleRefData& rRef);
364 
365     /** Guarantees that nGlobalError is set if rToken could not be obtained. */
366     void PopExternalSingleRef(ScExternalRefCache::TokenRef& rToken, ScExternalRefCache::CellFormat* pFmt = nullptr);
367 
368     /** Guarantees that nGlobalError is set if rToken could not be obtained. */
369     void PopExternalSingleRef(sal_uInt16& rFileId, OUString& rTabName, ScSingleRefData& rRef,
370                               ScExternalRefCache::TokenRef& rToken, ScExternalRefCache::CellFormat* pFmt = nullptr);
371 
372     void PopExternalDoubleRef(sal_uInt16& rFileId, OUString& rTabName, ScComplexRefData& rRef);
373     void PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArray);
374     void PopExternalDoubleRef(ScMatrixRef& rMat);
375     void GetExternalDoubleRef(sal_uInt16 nFileId, const OUString& rTabName, const ScComplexRefData& aData, ScExternalRefCache::TokenArrayRef& rArray);
376     bool PopDoubleRefOrSingleRef( ScAddress& rAdr );
377     void PopDoubleRefPushMatrix();
378     void PopRefListPushMatrixOrRef();
379     // If MatrixFormula: convert svDoubleRef to svMatrix, create JumpMatrix.
380     // Else convert area reference parameters marked as ForceArray to array.
381     // Returns true if JumpMatrix created.
382     bool ConvertMatrixParameters();
383     // If MatrixFormula: ConvertMatrixJumpConditionToMatrix()
384     inline void MatrixJumpConditionToMatrix();
385     // For MatrixFormula (preconditions already checked by
386     // MatrixJumpConditionToMatrix()): convert svDoubleRef to svMatrix, or if
387     // JumpMatrix currently in effect convert also other types to svMatrix so
388     // another JumpMatrix will be created by jump commands.
389     void ConvertMatrixJumpConditionToMatrix();
390     // If MatrixFormula or ForceArray: ConvertMatrixParameters()
391     inline bool MatrixParameterConversion();
392     // If MatrixFormula or ForceArray. Can be used within spreadsheet functions
393     // that do not depend on the formula cell's matrix size, for which only
394     // bMatrixFormula can be used.
395     inline bool IsInArrayContext() const;
396     ScMatrixRef PopMatrix();
397     sc::RangeMatrix PopRangeMatrix();
398     void QueryMatrixType(const ScMatrixRef& xMat, SvNumFormatType& rRetTypeExpr, sal_uInt32& rRetIndexExpr);
399 
400     formula::FormulaToken* CreateFormulaDoubleToken( double fVal, SvNumFormatType nFmt = SvNumFormatType::NUMBER );
401     formula::FormulaToken* CreateDoubleOrTypedToken( double fVal );
402 
403     void PushDouble(double nVal);
404     void PushInt( int nVal );
405     void PushStringBuffer( const sal_Unicode* pString );
406     void PushString( const OUString& rStr );
407     void PushString( const svl::SharedString& rString );
408     void PushSingleRef(SCCOL nCol, SCROW nRow, SCTAB nTab);
409     void PushDoubleRef(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
410                        SCCOL nCol2, SCROW nRow2, SCTAB nTab2);
411     void PushExternalSingleRef(sal_uInt16 nFileId, const OUString& rTabName,
412                                SCCOL nCol, SCROW nRow, SCTAB nTab);
413     void PushExternalDoubleRef(sal_uInt16 nFileId, const OUString& rTabName,
414                                SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
415                                SCCOL nCol2, SCROW nRow2, SCTAB nTab2);
416     void PushSingleRef( const ScRefAddress& rRef );
417     void PushDoubleRef( const ScRefAddress& rRef1, const ScRefAddress& rRef2 );
418     void PushMatrix( const sc::RangeMatrix& rMat );
419     void PushMatrix(const ScMatrixRef& pMat);
420     void PushError( FormulaError nError );
421     /// Raw stack type without default replacements.
422     formula::StackVar GetRawStackType();
423     /// Stack type with replacement of defaults, e.g. svMissing and formula::svEmptyCell will result in formula::svDouble.
424     formula::StackVar GetStackType();
425     // peek StackType of Parameter, Parameter 1 == TOS, 2 == TOS-1, ...
426     formula::StackVar GetStackType( sal_uInt8 nParam );
GetByte() const427     sal_uInt8 GetByte() const { return cPar; }
428     // reverse order of stack
429     void ReverseStack( sal_uInt8 nParamCount );
430     // generates a position-dependent SingleRef out of a DoubleRef
431     bool DoubleRefToPosSingleRef( const ScRange& rRange, ScAddress& rAdr );
432     double GetDoubleFromMatrix(const ScMatrixRef& pMat);
433     double GetDouble();
434     double GetDoubleWithDefault(double nDefault);
435     bool IsMissing() const;
436     sal_Int32 double_to_int32(double fVal);
437     /** if GetDouble() not within int32 limits sets nGlobalError and returns SAL_MAX_INT32 */
438     sal_Int32 GetInt32();
439     /** if GetDoubleWithDefault() not within int32 limits sets nGlobalError and returns SAL_MAX_INT32 */
440     sal_Int32 GetInt32WithDefault( sal_Int32 nDefault );
441     /** if GetDouble() not within int16 limits sets nGlobalError and returns SAL_MAX_INT16 */
442     sal_Int16 GetInt16();
443     /** if GetDouble() not within uint32 limits sets nGlobalError and returns SAL_MAX_UINT32 */
444     sal_uInt32 GetUInt32();
GetBool()445     bool GetBool() { return GetDouble() != 0.0; }
446     /// returns TRUE if double (or error, check nGlobalError), else FALSE
447     bool GetDoubleOrString( double& rValue, svl::SharedString& rString );
448     svl::SharedString GetString();
449     svl::SharedString GetStringFromMatrix(const ScMatrixRef& pMat);
450     svl::SharedString GetStringFromDouble( const double fVal);
451     // pop matrix and obtain one element, upper left or according to jump matrix
452     ScMatValType GetDoubleOrStringFromMatrix( double& rDouble, svl::SharedString& rString );
453     ScMatrixRef CreateMatrixFromDoubleRef( const formula::FormulaToken* pToken,
454             SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
455             SCCOL nCol2, SCROW nRow2, SCTAB nTab2 );
456     inline ScTokenMatrixMap& GetTokenMatrixMap();
457     static std::unique_ptr<ScTokenMatrixMap> CreateTokenMatrixMap();
458     ScMatrixRef GetMatrix();
459     ScMatrixRef GetMatrix( short & rParam, size_t & rInRefList );
460     sc::RangeMatrix GetRangeMatrix();
461 
462     void ScTableOp();                                       // repeated operations
463 
464     // common helper functions
465 
CurFmtToFuncFmt()466     void CurFmtToFuncFmt()
467         { nFuncFmtType = nCurFmtType; nFuncFmtIndex = nCurFmtIndex; }
468 
469     /** Check if a double is suitable as string position or length argument.
470 
471         If fVal is Inf or NaN it is changed to -1, if it is less than 0 it is
472         sanitized to 0, if it is greater than some implementation defined max
473         string length it is sanitized to that max.
474 
475         @return TRUE if double value fVal is suitable as string argument and was
476                 not sanitized.
477                 FALSE if not and fVal was adapted.
478      */
479     static inline bool CheckStringPositionArgument( double & fVal );
480 
481     /** Obtain a sal_Int32 suitable as string position or length argument.
482         Returns -1 if the number is Inf or NaN or less than 0 or greater than some
483         implementation defined max string length. In these cases also sets
484         nGlobalError to FormulaError::IllegalArgument, if not already set. */
485     inline sal_Int32 GetStringPositionArgument();
486 
487     // Check for String overflow of rResult+rAdd and set error and erase rResult
488     // if so. Return true if ok, false if overflow
489     inline bool CheckStringResultLen( OUString& rResult, const OUString& rAdd );
490 
491     // Check for String overflow of rResult+rAdd and set error and erase rResult
492     // if so. Return true if ok, false if overflow
493     inline bool CheckStringResultLen( OUStringBuffer& rResult, const OUString& rAdd );
494 
495     // Set error according to rVal, and set rVal to 0.0 if there was an error.
496     inline void TreatDoubleError( double& rVal );
497     // Lookup using ScLookupCache, @returns true if found and result address
498     bool LookupQueryWithCache( ScAddress & o_rResultPos,
499             const ScQueryParam & rParam ) const;
500 
501     void ScIfJump();
502     void ScIfError( bool bNAonly );
503     void ScChooseJump();
504 
505     // Be sure to only call this if pStack[sp-nStackLevel] really contains a
506     // ScJumpMatrixToken, no further checks are applied!
507     // Returns true if last jump was executed and result matrix pushed.
508     bool JumpMatrix( short nStackLevel );
509 
510     double Compare( ScQueryOp eOp );
511     /** @param pOptions
512             NULL means case sensitivity document option is to be used!
513      */
514     sc::RangeMatrix CompareMat( ScQueryOp eOp, sc::CompareOptions* pOptions = nullptr );
515     ScMatrixRef QueryMat( const ScMatrixRef& pMat, sc::CompareOptions& rOptions );
516     void ScEqual();
517     void ScNotEqual();
518     void ScLess();
519     void ScGreater();
520     void ScLessEqual();
521     void ScGreaterEqual();
522     void ScAnd();
523     void ScOr();
524     void ScXor();
525     void ScNot();
526     void ScNeg();
527     void ScPercentSign();
528     void ScIntersect();
529     void ScRangeFunc();
530     void ScUnionFunc();
531     void ScPi();
532     void ScRandom();
533     void ScTrue();
534     void ScFalse();
535     void ScDeg();
536     void ScRad();
537     void ScSin();
538     void ScCos();
539     void ScTan();
540     void ScCot();
541     void ScArcSin();
542     void ScArcCos();
543     void ScArcTan();
544     void ScArcCot();
545     void ScSinHyp();
546     void ScCosHyp();
547     void ScTanHyp();
548     void ScCotHyp();
549     void ScArcSinHyp();
550     void ScArcCosHyp();
551     void ScArcTanHyp();
552     void ScArcCotHyp();
553     void ScCosecant();
554     void ScSecant();
555     void ScCosecantHyp();
556     void ScSecantHyp();
557     void ScExp();
558     void ScLn();
559     void ScLog10();
560     void ScSqrt();
561     void ScIsEmpty();
562     bool IsString();
563     void ScIsString();
564     void ScIsNonString();
565     void ScIsLogical();
566     void ScType();
567     void ScCell();
568     void ScCellExternal();
569     void ScIsRef();
570     void ScIsValue();
571     void ScIsFormula();
572     void ScFormula();
573     void ScRoman();
574     void ScArabic();
575     void ScIsNV();
576     void ScIsErr();
577     void ScIsError();
578     bool IsEven();
579     void ScIsEven();
580     void ScIsOdd();
581     void ScN();
582     void ScCode();
583     void ScTrim();
584     void ScUpper();
585     void ScProper();
586     void ScLower();
587     void ScLen();
588     void ScT();
589     void ScValue();
590     void ScNumberValue();
591     void ScClean();
592     void ScChar();
593     void ScJis();
594     void ScAsc();
595     void ScUnicode();
596     void ScUnichar();
597     void ScMin( bool bTextAsZero = false );
598     void ScMax( bool bTextAsZero = false );
599     /** Check for array of references to determine the maximum size of a return
600         column vector if in array context. */
601     size_t GetRefListArrayMaxSize( short nParamCount );
602     /** Switch to array reference list if current TOS is one and create/init or
603         update matrix and return true. Else return false. */
604     bool SwitchToArrayRefList( ScMatrixRef& xResMat, SCSIZE nMatRows, double fCurrent,
605             const std::function<void( SCSIZE i, double fCurrent )>& MatOpFunc, bool bDoMatOp );
606     void IterateParameters( ScIterFunc, bool bTextAsZero = false );
607     void ScSumSQ();
608     void ScSum();
609     void ScProduct();
610     void ScAverage( bool bTextAsZero = false );
611     void ScCount();
612     void ScCount2();
613     void GetStVarParams( bool bTextAsZero, double(*VarResult)( double fVal, size_t nValCount ) );
614     void ScVar( bool bTextAsZero = false );
615     void ScVarP( bool bTextAsZero = false );
616     void ScStDev( bool bTextAsZero = false );
617     void ScStDevP( bool bTextAsZero = false );
618     void ScRawSubtract();
619     void ScColumns();
620     void ScRows();
621     void ScSheets();
622     void ScColumn();
623     void ScRow();
624     void ScSheet();
625     void ScMatch();
626     void IterateParametersIf( ScIterFuncIf );
627     void ScCountIf();
628     void ScSumIf();
629     void ScAverageIf();
630     void IterateParametersIfs( double(*ResultFunc)( const sc::ParamIfsResult& rRes ) );
631     void ScSumIfs();
632     void ScAverageIfs();
633     void ScCountIfs();
634     void ScCountEmptyCells();
635     void ScLookup();
636     void ScHLookup();
637     void ScVLookup();
638     void ScSubTotal();
639 
640     // If upon call rMissingField==true then the database field parameter may be
641     // missing (Xcl DCOUNT() syntax), or may be faked as missing by having the
642     // value 0.0 or being exactly the entire database range reference (old SO
643     // compatibility). If this was the case then rMissingField is set to true upon
644     // return. If rMissingField==false upon call all "missing cases" are considered
645     // to be an error.
646     std::unique_ptr<ScDBQueryParamBase> GetDBParams( bool& rMissingField );
647 
648     void DBIterator( ScIterFunc );
649     void ScDBSum();
650     void ScDBCount();
651     void ScDBCount2();
652     void ScDBAverage();
653     void ScDBGet();
654     void ScDBMax();
655     void ScDBMin();
656     void ScDBProduct();
657     void GetDBStVarParams( double& rVal, double& rValCount );
658     void ScDBStdDev();
659     void ScDBStdDevP();
660     void ScDBVar();
661     void ScDBVarP();
662     void ScIndirect();
663     void ScAddressFunc();
664     void ScOffset();
665     void ScIndex();
666     void ScMultiArea();
667     void ScAreas();
668     void ScCurrency();
669     void ScReplace();
670     void ScFixed();
671     void ScFind();
672     void ScExact();
673     void ScLeft();
674     void ScRight();
675     void ScSearch();
676     void ScMid();
677     void ScText();
678     void ScSubstitute();
679     void ScRept();
680     void ScRegex();
681     void ScConcat();
682     void ScConcat_MS();
683     void ScTextJoin_MS();
684     void ScIfs_MS();
685     void ScSwitch_MS();
686     void ScMinIfs_MS();
687     void ScMaxIfs_MS();
688     void ScExternal();
689     void ScMissing();
690     void ScMacro();
691     bool SetSbxVariable( SbxVariable* pVar, const ScAddress& );
692     FormulaError GetErrorType();
693     void ScErrorType();
694     void ScErrorType_ODF();
695     void ScDBArea();
696     void ScColRowNameAuto();
697     void ScGetPivotData();
698     void ScHyperLink();
699     void ScBahtText();
700     void ScBitAnd();
701     void ScBitOr();
702     void ScBitXor();
703     void ScBitRshift();
704     void ScBitLshift();
705     void ScTTT();
706     void ScDebugVar();
707 
708     /** Obtain the date serial number for a given date.
709         @param bStrict
710             If false, nYear < 100 takes the two-digit year setting into account,
711             and rollover of invalid calendar dates takes place, e.g. 1999-02-31 =>
712             1999-03-03.
713             If true, the date passed must be a valid Gregorian calendar date. No
714             two-digit expanding or rollover is done.
715 
716         Date must be Gregorian, i.e. >= 1582-10-15.
717      */
718     double GetDateSerial( sal_Int16 nYear, sal_Int16 nMonth, sal_Int16 nDay, bool bStrict );
719 
720     void ScGetActDate();
721     void ScGetActTime();
722     void ScGetYear();
723     void ScGetMonth();
724     void ScGetDay();
725     void ScGetDayOfWeek();
726     void ScGetWeekOfYear();
727     void ScGetIsoWeekOfYear();
728     void ScWeeknumOOo();
729     void ScEasterSunday();
730     FormulaError GetWeekendAndHolidayMasks( const sal_uInt8 nParamCount, const sal_uInt32 nNullDate,
731             ::std::vector<double>& rSortArray, bool bWeekendMask[ 7 ] );
732     FormulaError GetWeekendAndHolidayMasks_MS( const sal_uInt8 nParamCount, const sal_uInt32 nNullDate,
733             ::std::vector<double>& rSortArray, bool bWeekendMask[ 7 ], bool bWorkdayFunction );
734     static inline sal_Int16 GetDayOfWeek( sal_Int32 n );
735     void ScNetWorkdays( bool bOOXML_Version );
736     void ScWorkday_MS();
737     void ScGetHour();
738     void ScGetMin();
739     void ScGetSec();
740     void ScPlusMinus();
741     void ScAbs();
742     void ScInt();
743     void ScEven();
744     void ScOdd();
745     void ScCeil( bool bODFF );
746     void ScCeil_MS();
747     void ScCeil_Precise();
748     void ScFloor( bool bODFF );
749     void ScFloor_MS();
750     void ScFloor_Precise();
751     void RoundNumber( rtl_math_RoundingMode eMode );
752     void ScRound();
753     void ScRoundUp();
754     void ScRoundDown();
755     void ScGetDateValue();
756     void ScGetTimeValue();
757     void ScArcTan2();
758     void ScLog();
759     void ScGetDate();
760     void ScGetTime();
761     void ScGetDiffDate();
762     void ScGetDiffDate360();
763     void ScGetDateDif();
764     void ScPower();
765     void ScAmpersand();
766     void ScAdd();
767     void ScSub();
768     void ScMul();
769     void ScDiv();
770     void ScPow();
771     void ScCurrent();
772     void ScStyle();
773     void ScDde();
774     void ScBase();
775     void ScDecimal();
776     void ScConvertOOo();
777     void ScEuroConvert();
778     void ScRoundSignificant();
779     static void RoundSignificant( double fX, double fDigits, double &fRes );
780 
781     // financial functions
782     void ScNPV();
783     void ScIRR();
784     void ScMIRR();
785     void ScISPMT();
786 
787     static double ScGetPV(double fRate, double fNper, double fPmt,
788                           double fFv, bool bPayInAdvance);
789     void ScPV();
790     void ScSYD();
791     static double ScGetDDB(double fCost, double fSalvage, double fLife,
792                            double fPeriod, double fFactor);
793     void ScDDB();
794     void ScDB();
795     static double ScInterVDB(double fCost, double fSalvage, double fLife, double fLife1,
796                              double fPeriod, double fFactor);
797     void ScVDB();
798     void ScPDuration();
799     void ScSLN();
800     static double ScGetPMT(double fRate, double fNper, double fPv,
801                            double fFv, bool bPayInAdvance);
802     void ScPMT();
803     void ScRRI();
804     static double ScGetFV(double fRate, double fNper, double fPmt,
805                           double fPv, bool bPayInAdvance);
806     void ScFV();
807     void ScNper();
808     static bool RateIteration(double fNper, double fPayment, double fPv,
809                               double fFv, bool bPayType, double& fGuess);
810     void ScRate();
811     double ScGetIpmt(double fRate, double fPer, double fNper, double fPv,
812                                  double fFv, bool bPayInAdvance, double& fPmt);
813     void ScIpmt();
814     void ScPpmt();
815     void ScCumIpmt();
816     void ScCumPrinc();
817     void ScEffect();
818     void ScNominal();
819     void ScMod();
820     void ScIntercept();
821     void ScGCD();
822     void ScLCM();
823 
824     // matrix functions
825     void ScMatValue();
826     static void MEMat(const ScMatrixRef& mM, SCSIZE n);
827     void ScMatDet();
828     void ScMatInv();
829     void ScMatMult();
830     void ScMatTrans();
831     void ScEMat();
832     void ScMatRef();
833     ScMatrixRef MatConcat(const ScMatrixRef& pMat1, const ScMatrixRef& pMat2);
834     void ScSumProduct();
835     void ScSumX2MY2();
836     void ScSumX2DY2();
837     void ScSumXMY2();
838     void ScGrowth();
839     bool CalculateSkew(double& fSum,double& fCount,double& vSum,std::vector<double>& values);
840     void CalculateSkewOrSkewp( bool bSkewp );
841     void CalculateSlopeIntercept(bool bSlope);
842     void CalculateSmallLarge(bool bSmall);
843     void CalculatePearsonCovar( bool _bPearson, bool _bStexy, bool _bSample );  //fdo#70000 argument _bSample is ignored if _bPearson == true
844     bool CalculateTest( bool _bTemplin
845                        ,const SCSIZE nC1, const SCSIZE nC2,const SCSIZE nR1,const SCSIZE nR2
846                        ,const ScMatrixRef& pMat1,const ScMatrixRef& pMat2
847                        ,double& fT,double& fF);
848     void CalculateLookup(bool bHLookup);
849     bool FillEntry(ScQueryEntry& rEntry);
850     void CalculateAddSub(bool _bSub);
851     void CalculateTrendGrowth(bool _bGrowth);
852     void CalculateRGPRKP(bool _bRKP);
853     void CalculateSumX2MY2SumX2DY2(bool _bSumX2DY2);
854     void CalculateMatrixValue(const ScMatrix* pMat,SCSIZE nC,SCSIZE nR);
855     bool CheckMatrix(bool _bLOG,sal_uInt8& nCase,SCSIZE& nCX,SCSIZE& nCY,SCSIZE& nRX,SCSIZE& nRY,SCSIZE& M,SCSIZE& N,ScMatrixRef& pMatX,ScMatrixRef& pMatY);
856     void ScLinest();
857     void ScLogest();
858     void ScForecast();
859     void ScForecast_Ets( ScETSType eETSType );
860     void ScFourier();
861     void ScNoName();
862     void ScBadName();
863     // Statistics:
864     static double taylor(const double* pPolynom, sal_uInt16 nMax, double x);
865     static double gauss(double x);
866 
867 public:
868     static SC_DLLPUBLIC double phi(double x);
869     static SC_DLLPUBLIC double integralPhi(double x);
870     static SC_DLLPUBLIC double gaussinv(double x);
871     static SC_DLLPUBLIC double GetPercentile( ::std::vector<double> & rArray, double fPercentile );
872 
873 
874 private:
875     double GetBetaDist(double x, double alpha, double beta);  //cumulative distribution function
876     double GetBetaDistPDF(double fX, double fA, double fB); //probability density function)
877     double GetChiDist(double fChi, double fDF);     // for LEGACY.CHIDIST, returns right tail
878     double GetChiSqDistCDF(double fX, double fDF);  // for CHISQDIST, returns left tail
879     static double GetChiSqDistPDF(double fX, double fDF);  // probability density function
880     double GetFDist(double x, double fF1, double fF2);
881     double GetTDist( double T, double fDF, int nType );
882     double Fakultaet(double x);
883     static double BinomKoeff(double n, double k);
884     double GetGamma(double x);
885     static double GetLogGamma(double x);
886     double GetBeta(double fAlpha, double fBeta);
887     static double GetLogBeta(double fAlpha, double fBeta);
888     double GetBinomDistPMF(double x, double n, double p); //probability mass function
889     double GetHypGeomDist( double x, double n, double M, double N );
890     void ScLogGamma();
891     void ScGamma();
892     void ScPhi();
893     void ScGauss();
894     void ScStdNormDist();
895     void ScStdNormDist_MS();
896     void ScFisher();
897     void ScFisherInv();
898     void ScFact();
899     void ScNormDist( int nMinParamCount );
900     void ScGammaDist( bool bODFF );
901     void ScGammaInv();
902     void ScExpDist();
903     void ScBinomDist();
904     void ScPoissonDist( bool bODFF );
905     void ScCombin();
906     void ScCombinA();
907     void ScPermut();
908     void ScPermutationA();
909     void ScB();
910     void ScHypGeomDist( int nMinParamCount );
911     void ScLogNormDist( int nMinParamCount );
912     void ScLogNormInv();
913     void ScTDist();
914     void ScTDist_MS();
915     void ScTDist_T( int nTails );
916     void ScFDist();
917     void ScFDist_LT();
918     void ScChiDist( bool bODFF);   // for LEGACY.CHIDIST, returns right tail
919     void ScChiSqDist(); // returns left tail or density
920     void ScChiSqDist_MS();
921     void ScChiSqInv(); // inverse to CHISQDIST
922     void ScWeibull();
923     void ScBetaDist();
924     void ScBetaDist_MS();
925     void ScFInv();
926     void ScFInv_LT();
927     void ScTInv( int nType );
928     void ScChiInv();
929     void ScBetaInv();
930     void ScCritBinom();
931     void ScNegBinomDist();
932     void ScNegBinomDist_MS();
933     void ScKurt();
934     void ScHarMean();
935     void ScGeoMean();
936     void ScStandard();
937     void ScSkew();
938     void ScSkewp();
939     void ScMedian();
940     double GetMedian( ::std::vector<double> & rArray );
941     double GetPercentileExclusive( ::std::vector<double> & rArray, double fPercentile );
942     std::vector<double> GetTopNumberArray( SCSIZE& rCol, SCSIZE& rRow );
943     void GetNumberSequenceArray( sal_uInt8 nParamCount, ::std::vector<double>& rArray, bool bConvertTextInArray );
944     void GetSortArray( sal_uInt8 nParamCount, ::std::vector<double>& rSortArray, ::std::vector<long>* pIndexOrder, bool bConvertTextInArray, bool bAllowEmptyArray );
945     static void QuickSort(::std::vector<double>& rSortArray, ::std::vector<long>* pIndexOrder);
946     void ScModalValue();
947     void ScModalValue_MS( bool bSingle );
948     void ScAveDev();
949     void ScAggregate();
950     void ScDevSq();
951     void ScZTest();
952     void ScTTest();
953     void ScFTest();
954     void ScChiTest();
955     void ScRank( bool bAverage );
956     void ScPercentile( bool bInclusive );
957     void ScPercentrank( bool bInclusive );
958     static double GetPercentrank( ::std::vector<double> & rArray, double fVal, bool bInclusive );
959     void ScLarge();
960     void ScSmall();
961     void ScFrequency();
962     void ScQuartile( bool bInclusive );
963     void ScNormInv();
964     void ScSNormInv();
965     void ScConfidence();
966     void ScConfidenceT();
967     void ScTrimMean();
968     void ScProbability();
969     void ScCorrel();
970     void ScCovarianceP();
971     void ScCovarianceS();
972     void ScPearson();
973     void ScRSQ();
974     void ScSTEYX();
975     void ScSlope();
976     void ScTrend();
977     void ScInfo();
978     void ScLenB();
979     void ScRightB();
980     void ScLeftB();
981     void ScMidB();
982     void ScReplaceB();
983     void ScFindB();
984     void ScSearchB();
985 
986     void ScFilterXML();
987     void ScWebservice();
988     void ScEncodeURL();
989     void ScColor();
990     void ScErf();
991     void ScErfc();
992 
993     static const double fMaxGammaArgument;
994 
995     double GetGammaContFraction(double fA,double fX);
996     double GetGammaSeries(double fA,double fX);
997     double GetLowRegIGamma(double fA,double fX);    // lower regularized incomplete gamma function, GAMMAQ
998     double GetUpRegIGamma(double fA,double fX);     // upper regularized incomplete gamma function, GAMMAP
999     // probability density function; fLambda is "scale" parameter
1000     double GetGammaDistPDF(double fX, double fAlpha, double fLambda);
1001     // cumulative distribution function; fLambda is "scale" parameter
1002     double GetGammaDist(double fX, double fAlpha, double fLambda);
1003     double GetTInv( double fAlpha, double fSize, int nType );
1004 
1005 public:
1006     ScInterpreter( ScFormulaCell* pCell, ScDocument* pDoc, ScInterpreterContext& rContext,
1007                     const ScAddress&, ScTokenArray&, bool bForGroupThreading = false );
1008     ~ScInterpreter();
1009 
1010     // Used only for threaded formula-groups.
1011     // Resets the interpreter object, allowing reuse of interpreter object for each cell
1012     // in the group.
1013     void Init( ScFormulaCell* pCell, const ScAddress& rPos, ScTokenArray& rTokArray );
1014 
1015     formula::StackVar Interpret();
1016 
SetError(FormulaError nError)1017     void SetError(FormulaError nError)
1018             { if (nError != FormulaError::NONE && nGlobalError == FormulaError::NONE) nGlobalError = nError; }
1019     void AssertFormulaMatrix();
1020 
SetLinkManager(sfx2::LinkManager * pLinkMgr)1021     void SetLinkManager(sfx2::LinkManager* pLinkMgr)
1022             { mpLinkManager = pLinkMgr; }
1023 
GetError() const1024     FormulaError                GetError() const            { return nGlobalError; }
GetResultType() const1025     formula::StackVar           GetResultType() const       { return xResult->GetType(); }
1026     svl::SharedString GetStringResult() const;
GetNumResult() const1027     double                      GetNumResult() const        { return xResult->GetDouble(); }
GetResultToken() const1028     const formula::FormulaConstTokenRef& GetResultToken() const { return xResult; }
GetRetFormatType() const1029     SvNumFormatType             GetRetFormatType() const    { return nRetFmtType; }
GetRetFormatIndex() const1030     sal_uLong                   GetRetFormatIndex() const   { return nRetFmtIndex; }
1031 };
1032 
IsInArrayContext() const1033 inline bool ScInterpreter::IsInArrayContext() const
1034 {
1035     return bMatrixFormula || pCur->IsInForceArray();
1036 }
1037 
MatrixJumpConditionToMatrix()1038 inline void ScInterpreter::MatrixJumpConditionToMatrix()
1039 {
1040     if (IsInArrayContext())
1041         ConvertMatrixJumpConditionToMatrix();
1042 }
1043 
MatrixParameterConversion()1044 inline bool ScInterpreter::MatrixParameterConversion()
1045 {
1046     if ( (IsInArrayContext() || ScParameterClassification::HasForceArray( pCur->GetOpCode())) &&
1047             !pJumpMatrix && sp > 0 )
1048         return ConvertMatrixParameters();
1049     return false;
1050 }
1051 
GetTokenMatrixMap()1052 inline ScTokenMatrixMap& ScInterpreter::GetTokenMatrixMap()
1053 {
1054     if (!pTokenMatrixMap)
1055         pTokenMatrixMap = CreateTokenMatrixMap();
1056     return *pTokenMatrixMap;
1057 }
1058 
MustHaveParamCount(short nAct,short nMust)1059 inline bool ScInterpreter::MustHaveParamCount( short nAct, short nMust )
1060 {
1061     if ( nAct == nMust )
1062         return true;
1063     if ( nAct < nMust )
1064         PushParameterExpected();
1065     else
1066         PushIllegalParameter();
1067     return false;
1068 }
1069 
MustHaveParamCount(short nAct,short nMust,short nMax)1070 inline bool ScInterpreter::MustHaveParamCount( short nAct, short nMust, short nMax )
1071 {
1072     if ( nMust <= nAct && nAct <= nMax )
1073         return true;
1074     if ( nAct < nMust )
1075         PushParameterExpected();
1076     else
1077         PushIllegalParameter();
1078     return false;
1079 }
1080 
MustHaveParamCountMin(short nAct,short nMin)1081 inline bool ScInterpreter::MustHaveParamCountMin( short nAct, short nMin )
1082 {
1083     if ( nAct >= nMin )
1084         return true;
1085     PushParameterExpected();
1086     return false;
1087 }
1088 
CheckStringPositionArgument(double & fVal)1089 inline bool ScInterpreter::CheckStringPositionArgument( double & fVal )
1090 {
1091     if (!rtl::math::isFinite( fVal))
1092     {
1093         fVal = -1.0;
1094         return false;
1095     }
1096     else if (fVal < 0.0)
1097     {
1098         fVal = 0.0;
1099         return false;
1100     }
1101     else if (fVal > SAL_MAX_INT32)
1102     {
1103         fVal = static_cast<double>(SAL_MAX_INT32);
1104         return false;
1105     }
1106     return true;
1107 }
1108 
GetStringPositionArgument()1109 inline sal_Int32 ScInterpreter::GetStringPositionArgument()
1110 {
1111     double fVal = rtl::math::approxFloor( GetDouble());
1112     if (!CheckStringPositionArgument( fVal))
1113     {
1114         fVal = -1.0;
1115         SetError( FormulaError::IllegalArgument);
1116     }
1117     return static_cast<sal_Int32>(fVal);
1118 }
1119 
CheckStringResultLen(OUString & rResult,const OUString & rAdd)1120 inline bool ScInterpreter::CheckStringResultLen( OUString& rResult, const OUString& rAdd )
1121 {
1122     if (rAdd.getLength() > kScInterpreterMaxStrLen - rResult.getLength())
1123     {
1124         SetError( FormulaError::StringOverflow );
1125         rResult.clear();
1126         return false;
1127     }
1128     return true;
1129 }
1130 
CheckStringResultLen(OUStringBuffer & rResult,const OUString & rAdd)1131 inline bool ScInterpreter::CheckStringResultLen( OUStringBuffer& rResult, const OUString& rAdd )
1132 {
1133     if (rAdd.getLength() > kScInterpreterMaxStrLen - rResult.getLength())
1134     {
1135         SetError( FormulaError::StringOverflow );
1136         rResult = OUStringBuffer();
1137         return false;
1138     }
1139     return true;
1140 }
1141 
TreatDoubleError(double & rVal)1142 inline void ScInterpreter::TreatDoubleError( double& rVal )
1143 {
1144     if ( !::rtl::math::isFinite( rVal ) )
1145     {
1146         FormulaError nErr = GetDoubleErrorValue( rVal );
1147         if ( nErr != FormulaError::NONE )
1148             SetError( nErr );
1149         else
1150             SetError( FormulaError::NoValue );
1151         rVal = 0.0;
1152     }
1153 }
1154 
div(const double & fNumerator,const double & fDenominator)1155 inline double ScInterpreter::div( const double& fNumerator, const double& fDenominator )
1156 {
1157     return sc::div(fNumerator, fDenominator);
1158 }
1159 
GetDayOfWeek(sal_Int32 n)1160 inline sal_Int16 ScInterpreter::GetDayOfWeek( sal_Int32 n )
1161 {   // monday = 0, ..., sunday = 6
1162     return static_cast< sal_Int16 >( ( n - 1 ) % 7 );
1163 }
1164 
1165 #endif
1166 
1167 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1168