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