1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "interpre.hxx"
21 #include "columnspanset.hxx"
23 #include "document.hxx"
24 #include "cellvalue.hxx"
25 #include "dociter.hxx"
26 #include "mtvcellfunc.hxx"
27 #include "scmatrix.hxx"
29 #include <formula/token.hxx>
31 using namespace formula
;
33 double const fHalfMachEps
= 0.5 * ::std::numeric_limits
<double>::epsilon();
35 // The idea how this group of gamma functions is calculated, is
36 // based on the Cephes library
37 // online http://www.moshier.net/#Cephes [called 2008-02]
39 /** You must ensure fA>0.0 && fX>0.0
40 valid results only if fX > fA+1.0
41 uses continued fraction with odd items */
42 double ScInterpreter::GetGammaContFraction( double fA
, double fX
)
45 double const fBigInv
= ::std::numeric_limits
<double>::epsilon();
46 double const fBig
= 1.0/fBigInv
;
49 double fDenom
= fX
+ 2.0-fA
;
50 double fPkm1
= fX
+ 1.0;
52 double fQkm1
= fDenom
* fX
;
54 double fApprox
= fPkm1
/fQkm1
;
55 bool bFinished
= false;
60 const double fNum
= fY
* fCount
;
62 double fPk
= fPkm1
* fDenom
- fPkm2
* fNum
;
63 const double fQk
= fQkm1
* fDenom
- fQkm2
* fNum
;
66 const double fR
= fPk
/fQk
;
67 bFinished
= (fabs( (fApprox
- fR
)/fR
) <= fHalfMachEps
);
76 // reduce a fraction does not change the value
77 fPkm2
= fPkm2
* fBigInv
;
78 fPkm1
= fPkm1
* fBigInv
;
79 fQkm2
= fQkm2
* fBigInv
;
80 fQkm1
= fQkm1
* fBigInv
;
82 } while (!bFinished
&& fCount
<10000);
83 // most iterations, if fX==fAlpha+1.0; approx sqrt(fAlpha) iterations then
86 SetError(errNoConvergence
);
91 /** You must ensure fA>0.0 && fX>0.0
92 valid results only if fX <= fA+1.0
94 double ScInterpreter::GetGammaSeries( double fA
, double fX
)
96 double fDenomfactor
= fA
;
97 double fSummand
= 1.0/fA
;
98 double fSum
= fSummand
;
102 fDenomfactor
= fDenomfactor
+ 1.0;
103 fSummand
= fSummand
* fX
/fDenomfactor
;
104 fSum
= fSum
+ fSummand
;
106 } while ( fSummand
/fSum
> fHalfMachEps
&& nCount
<=10000);
107 // large amount of iterations will be carried out for huge fAlpha, even
108 // if fX <= fAlpha+1.0
111 SetError(errNoConvergence
);
116 /** You must ensure fA>0.0 && fX>0.0) */
117 double ScInterpreter::GetLowRegIGamma( double fA
, double fX
)
119 double fLnFactor
= fA
* log(fX
) - fX
- GetLogGamma(fA
);
120 double fFactor
= exp(fLnFactor
); // Do we need more accuracy than exp(ln()) has?
121 if (fX
>fA
+1.0) // includes fX>1.0; 1-GetUpRegIGamma, continued fraction
122 return 1.0 - fFactor
* GetGammaContFraction(fA
,fX
);
123 else // fX<=1.0 || fX<=fA+1.0, series
124 return fFactor
* GetGammaSeries(fA
,fX
);
127 /** You must ensure fA>0.0 && fX>0.0) */
128 double ScInterpreter::GetUpRegIGamma( double fA
, double fX
)
131 double fLnFactor
= fA
*log(fX
)-fX
-GetLogGamma(fA
);
132 double fFactor
= exp(fLnFactor
); //Do I need more accuracy than exp(ln()) has?;
133 if (fX
>fA
+1.0) // includes fX>1.0
134 return fFactor
* GetGammaContFraction(fA
,fX
);
135 else //fX<=1 || fX<=fA+1, 1-GetLowRegIGamma, series
136 return 1.0 -fFactor
* GetGammaSeries(fA
,fX
);
139 /** Gamma distribution, probability density function.
140 fLambda is "scale" parameter
141 You must ensure fAlpha>0.0 and fLambda>0.0 */
142 double ScInterpreter::GetGammaDistPDF( double fX
, double fAlpha
, double fLambda
)
145 return 0.0; // see ODFF
147 // in this case 0^0 isn't zero
151 SetError(errDivisionByZero
); // should be #DIV/0
154 else if (fAlpha
== 1)
156 return (1.0 / fLambda
);
165 double fXr
= fX
/ fLambda
;
166 // use exp(ln()) only for large arguments because of less accuracy
169 const double fLogDblMax
= log( ::std::numeric_limits
<double>::max());
170 if (log(fXr
) * (fAlpha
-1.0) < fLogDblMax
&& fAlpha
< fMaxGammaArgument
)
172 return pow( fXr
, fAlpha
-1.0) * exp(-fXr
) / fLambda
/ GetGamma(fAlpha
);
176 return exp( (fAlpha
-1.0) * log(fXr
) - fXr
- log(fLambda
) - GetLogGamma(fAlpha
));
179 else // fXr near to zero
181 if (fAlpha
<fMaxGammaArgument
)
183 return pow( fXr
, fAlpha
-1.0) * exp(-fXr
) / fLambda
/ GetGamma(fAlpha
);
187 return pow( fXr
, fAlpha
-1.0) * exp(-fXr
) / fLambda
/ exp( GetLogGamma(fAlpha
));
193 /** Gamma distribution, cumulative distribution function.
194 fLambda is "scale" parameter
195 You must ensure fAlpha>0.0 and fLambda>0.0 */
196 double ScInterpreter::GetGammaDist( double fX
, double fAlpha
, double fLambda
)
201 return GetLowRegIGamma( fAlpha
, fX
/ fLambda
);
206 class NumericCellAccumulator
212 NumericCellAccumulator() : mfSum(0.0), mnError(0) {}
214 void operator() (size_t, double fVal
)
219 void operator() (size_t, const ScFormulaCell
* pCell
)
222 // Skip all the rest if we have an error.
227 ScFormulaCell
& rCell
= const_cast<ScFormulaCell
&>(*pCell
);
228 if (!rCell
.GetErrorOrValue(nErr
, fVal
))
229 // The cell has neither error nor value. Perhaps string result.
242 sal_uInt16
getError() const { return mnError
; }
243 double getSum() const { return mfSum
; }
246 class NumericCellCounter
250 NumericCellCounter() : mnCount(0) {}
252 void operator() (const sc::CellStoreType::value_type
& rNode
, size_t nOffset
, size_t nDataSize
)
256 case sc::element_type_numeric
:
257 mnCount
+= nDataSize
;
259 case sc::element_type_formula
:
261 sc::formula_block::const_iterator it
= sc::formula_block::begin(*rNode
.data
);
262 std::advance(it
, nOffset
);
263 sc::formula_block::const_iterator itEnd
= it
;
264 std::advance(itEnd
, nDataSize
);
265 for (; it
!= itEnd
; ++it
)
267 ScFormulaCell
& rCell
= const_cast<ScFormulaCell
&>(**it
);
268 if (rCell
.IsValueNoError())
278 size_t getCount() const { return mnCount
; }
281 class FuncCount
: public sc::ColumnSpanSet::ColumnAction
283 sc::ColumnBlockConstPosition maPos
;
289 FuncCount() : mpCol(0), mnCount(0), mnNumFmt(0) {}
291 virtual void startColumn(ScColumn
* pCol
) SAL_OVERRIDE
294 mpCol
->InitBlockPosition(maPos
);
297 virtual void execute(SCROW nRow1
, SCROW nRow2
, bool bVal
) SAL_OVERRIDE
302 NumericCellCounter aFunc
;
303 maPos
.miCellPos
= sc::ParseBlock(maPos
.miCellPos
, mpCol
->GetCellStore(), aFunc
, nRow1
, nRow2
);
304 mnCount
+= aFunc
.getCount();
305 mnNumFmt
= mpCol
->GetNumberFormat(nRow2
);
308 size_t getCount() const { return mnCount
; }
309 sal_uInt32
getNumberFormat() const { return mnNumFmt
; }
312 class FuncSum
: public sc::ColumnSpanSet::ColumnAction
314 sc::ColumnBlockConstPosition maPos
;
321 FuncSum() : mpCol(0), mfSum(0.0), mnError(0), mnNumFmt(0) {}
323 virtual void startColumn(ScColumn
* pCol
) SAL_OVERRIDE
326 mpCol
->InitBlockPosition(maPos
);
329 virtual void execute(SCROW nRow1
, SCROW nRow2
, bool bVal
) SAL_OVERRIDE
337 NumericCellAccumulator aFunc
;
338 maPos
.miCellPos
= sc::ParseFormulaNumeric(maPos
.miCellPos
, mpCol
->GetCellStore(), nRow1
, nRow2
, aFunc
);
339 mnError
= aFunc
.getError();
343 mfSum
+= aFunc
.getSum();
344 mnNumFmt
= mpCol
->GetNumberFormat(nRow2
);
347 sal_uInt16
getError() const { return mnError
; }
348 double getSum() const { return mfSum
; }
349 sal_uInt32
getNumberFormat() const { return mnNumFmt
; }
353 const ScMatrixRef
& pMat
, ScIterFunc eFunc
, bool bTextAsZero
,
354 sal_uLong
& rCount
, short& rFuncFmtType
, double& fRes
, double& fMem
, bool& bNull
)
359 // TODO fdo73148 take mnSubTotalFlags into account
360 rFuncFmtType
= css::util::NumberFormat::NUMBER
;
366 ScMatrix::IterateResult aRes
= pMat
->Sum(bTextAsZero
);
374 fRes
+= aRes
.mfFirst
+ aRes
.mfRest
;
375 rCount
+= aRes
.mnCount
;
379 rCount
+= pMat
->Count(bTextAsZero
);
382 rCount
+= pMat
->Count(true);
386 ScMatrix::IterateResult aRes
= pMat
->Product(bTextAsZero
);
387 fRes
*= aRes
.mfFirst
;
389 rCount
+= aRes
.mnCount
;
394 ScMatrix::IterateResult aRes
= pMat
->SumSquare(bTextAsZero
);
395 fRes
+= aRes
.mfFirst
;
397 rCount
+= aRes
.mnCount
;
407 double ScInterpreter::IterateParameters( ScIterFunc eFunc
, bool bTextAsZero
)
409 short nParamCount
= GetByte();
410 double fRes
= ( eFunc
== ifPRODUCT
) ? 1.0 : 0.0;
412 double fMem
= 0.0; // first numeric value.
414 sal_uLong nCount
= 0;
417 size_t nRefInList
= 0;
418 if ( nGlobalError
&& ( eFunc
== ifCOUNT2
|| eFunc
== ifCOUNT
||
419 ( mnSubTotalFlags
& SUBTOTAL_IGN_ERR_VAL
) ) )
421 while (nParamCount
-- > 0)
423 switch (GetStackType())
427 if( eFunc
== ifCOUNT
)
429 OUString aStr
= PopString().getString();
434 // Only check if string can be converted to number, no
435 // error propagation.
436 sal_uInt16 nErr
= nGlobalError
;
438 ConvertStringToValue( aStr
);
457 if ( eFunc
== ifPRODUCT
)
462 while (nParamCount
-- > 0)
464 SetError( errNoValue
);
482 if ( bNull
&& fVal
!= 0.0 )
490 case ifSUMSQ
: fRes
+= fVal
* fVal
; break;
491 case ifPRODUCT
: fRes
*= fVal
; break;
492 default: ; // nothing
494 nFuncFmtType
= css::util::NumberFormat::NUMBER
;
496 case svExternalSingleRef
:
498 ScExternalRefCache::TokenRef pToken
;
499 ScExternalRefCache::CellFormat aFmt
;
500 PopExternalSingleRef(pToken
, &aFmt
);
501 if ( nGlobalError
&& ( eFunc
== ifCOUNT2
|| eFunc
== ifCOUNT
||
502 ( mnSubTotalFlags
& SUBTOTAL_IGN_ERR_VAL
) ) )
505 if ( eFunc
== ifCOUNT2
&& !( mnSubTotalFlags
& SUBTOTAL_IGN_ERR_VAL
) )
513 StackVar eType
= pToken
->GetType();
514 if (eFunc
== ifCOUNT2
)
516 if ( eType
!= formula::svEmptyCell
&&
517 ( ( pToken
->GetOpCode() != ocSubTotal
&&
518 pToken
->GetOpCode() != ocAggregate
) ||
519 ( mnSubTotalFlags
& SUBTOTAL_IGN_NESTED_ST_AG
) ) )
524 else if (eType
== formula::svDouble
)
527 fVal
= pToken
->GetDouble();
530 nFuncFmtType
= aFmt
.mnType
;
531 nFuncFmtIndex
= aFmt
.mnIndex
;
537 if ( bNull
&& fVal
!= 0.0 )
545 case ifSUMSQ
: fRes
+= fVal
* fVal
; break;
546 case ifPRODUCT
: fRes
*= fVal
; break;
554 default: ; // nothing
557 else if (bTextAsZero
&& eType
== formula::svString
)
560 if ( eFunc
== ifPRODUCT
)
567 PopSingleRef( aAdr
);
568 if ( nGlobalError
&& ( eFunc
== ifCOUNT2
|| eFunc
== ifCOUNT
||
569 ( mnSubTotalFlags
& SUBTOTAL_IGN_ERR_VAL
) ) )
572 if ( eFunc
== ifCOUNT2
&& !( mnSubTotalFlags
& SUBTOTAL_IGN_ERR_VAL
) )
576 if ( ( mnSubTotalFlags
& SUBTOTAL_IGN_FILTERED
) &&
577 pDok
->RowFiltered( aAdr
.Row(), aAdr
.Tab() ) )
581 ScRefCellValue aCell
;
582 aCell
.assign(*pDok
, aAdr
);
583 if (!aCell
.isEmpty())
585 if( eFunc
== ifCOUNT2
)
587 CellType eCellType
= aCell
.meType
;
588 if ( eCellType
!= CELLTYPE_NONE
)
593 else if (aCell
.hasNumeric())
596 fVal
= GetCellValue(aAdr
, aCell
);
602 if ( bNull
&& fVal
!= 0.0 )
610 case ifSUMSQ
: fRes
+= fVal
* fVal
; break;
611 case ifPRODUCT
: fRes
*= fVal
; break;
619 default: ; // nothing
622 else if (bTextAsZero
&& aCell
.hasString())
625 if ( eFunc
== ifPRODUCT
)
634 PopDoubleRef( aRange
, nParamCount
, nRefInList
);
635 if ( nGlobalError
&& ( eFunc
== ifCOUNT2
|| eFunc
== ifCOUNT
||
636 ( mnSubTotalFlags
& SUBTOTAL_IGN_ERR_VAL
) ) )
639 if ( eFunc
== ifCOUNT2
&& !( mnSubTotalFlags
& SUBTOTAL_IGN_ERR_VAL
) )
641 if ( eFunc
== ifCOUNT2
|| eFunc
== ifCOUNT
)
644 if( eFunc
== ifCOUNT2
)
646 ScCellIterator
aIter( pDok
, aRange
, mnSubTotalFlags
);
647 for (bool bHas
= aIter
.first(); bHas
; bHas
= aIter
.next())
649 if ( !aIter
.hasEmptyData() )
660 ScValueIterator
aValIter( pDok
, aRange
, mnSubTotalFlags
, bTextAsZero
);
662 if (aValIter
.GetFirst(fVal
, nErr
))
664 // placed the loop on the inside for performance reasons:
665 aValIter
.GetCurNumFmtInfo( nFuncFmtType
, nFuncFmtIndex
);
670 if ( mnSubTotalFlags
& SUBTOTAL_IGN_ERR_VAL
)
677 if ( bNull
&& fVal
!= 0.0 )
687 while (aValIter
.GetNext(fVal
, nErr
));
694 if ( bNull
&& fVal
!= 0.0 )
703 while (aValIter
.GetNext(fVal
, nErr
));
707 if ( mnSubTotalFlags
& SUBTOTAL_IGN_ERR_VAL
)
718 while (aValIter
.GetNext(fVal
, nErr
));
728 while (aValIter
.GetNext(fVal
, nErr
));
734 if ( !( nErr
&& ( mnSubTotalFlags
& SUBTOTAL_IGN_ERR_VAL
) ) )
741 while (aValIter
.GetNext(fVal
, nErr
));
749 while (aValIter
.GetNext(fVal
, nErr
));
751 default: ; // nothing
758 case svExternalDoubleRef
:
761 PopExternalDoubleRef(pMat
);
762 if ( nGlobalError
&& !( mnSubTotalFlags
& SUBTOTAL_IGN_ERR_VAL
) )
765 IterateMatrix(pMat
, eFunc
, bTextAsZero
, nCount
, nFuncFmtType
, fRes
, fMem
, bNull
);
770 ScMatrixRef pMat
= PopMatrix();
771 IterateMatrix(pMat
, eFunc
, bTextAsZero
, nCount
, nFuncFmtType
, fRes
, fMem
, bNull
);
777 if ( eFunc
== ifCOUNT
|| ( mnSubTotalFlags
& SUBTOTAL_IGN_ERR_VAL
) )
781 else if ( eFunc
== ifCOUNT2
&& !( mnSubTotalFlags
& SUBTOTAL_IGN_ERR_VAL
) )
789 while (nParamCount
-- > 0)
791 SetError(errIllegalParameter
);
796 case ifSUM
: fRes
= ::rtl::math::approxAdd( fRes
, fMem
); break;
797 case ifAVERAGE
: fRes
= div(::rtl::math::approxAdd( fRes
, fMem
), nCount
); break;
799 case ifCOUNT
: fRes
= nCount
; break;
800 case ifPRODUCT
: if ( !nCount
) fRes
= 0.0; break;
801 default: ; // nothing
803 // Bei Summen etc. macht ein bool-Ergebnis keinen Sinn
804 // und Anzahl ist immer Number (#38345#)
805 if( eFunc
== ifCOUNT
|| nFuncFmtType
== css::util::NumberFormat::LOGICAL
)
806 nFuncFmtType
= css::util::NumberFormat::NUMBER
;
810 void ScInterpreter::ScSumSQ()
812 PushDouble( IterateParameters( ifSUMSQ
) );
815 void ScInterpreter::ScSum()
817 if ( mnSubTotalFlags
)
818 PushDouble( IterateParameters( ifSUM
) );
821 short nParamCount
= GetByte();
826 size_t nRefInList
= 0;
827 while (nParamCount
-- > 0)
829 switch (GetStackType())
833 while (nParamCount
-- > 0)
835 SetError( errNoValue
);
841 nFuncFmtType
= css::util::NumberFormat::NUMBER
;
843 case svExternalSingleRef
:
845 ScExternalRefCache::TokenRef pToken
;
846 ScExternalRefCache::CellFormat aFmt
;
847 PopExternalSingleRef(pToken
, &aFmt
);
852 StackVar eType
= pToken
->GetType();
853 if (eType
== formula::svDouble
)
855 fVal
= pToken
->GetDouble();
858 nFuncFmtType
= aFmt
.mnType
;
859 nFuncFmtIndex
= aFmt
.mnIndex
;
868 PopSingleRef( aAdr
);
870 ScRefCellValue aCell
;
871 aCell
.assign(*pDok
, aAdr
);
872 if (!aCell
.isEmpty())
874 if (aCell
.hasNumeric())
876 fVal
= GetCellValue(aAdr
, aCell
);
886 PopDoubleRef( aRange
, nParamCount
, nRefInList
);
888 sc::ColumnSpanSet
aSet(false);
889 aSet
.set(aRange
, true);
892 aSet
.executeColumnAction(*pDok
, aAction
);
893 sal_uInt16 nErr
= aAction
.getError();
899 fRes
+= aAction
.getSum();
901 // Get the number format of the last iterated cell.
902 nFuncFmtIndex
= aAction
.getNumberFormat();
903 nFuncFmtType
= pDok
->GetFormatTable()->GetType(nFuncFmtIndex
);
906 case svExternalDoubleRef
:
909 PopExternalDoubleRef(pMat
);
913 sal_uLong nCount
= 0;
916 IterateMatrix(pMat
, ifSUM
, false, nCount
, nFuncFmtType
, fRes
, fMem
, bNull
);
922 ScMatrixRef pMat
= PopMatrix();
923 sal_uLong nCount
= 0;
926 IterateMatrix(pMat
, ifSUM
, false, nCount
, nFuncFmtType
, fRes
, fMem
, bNull
);
936 while (nParamCount
-- > 0)
938 SetError(errIllegalParameter
);
942 if (nFuncFmtType
== css::util::NumberFormat::LOGICAL
)
943 nFuncFmtType
= css::util::NumberFormat::NUMBER
;
949 void ScInterpreter::ScProduct()
951 PushDouble( IterateParameters( ifPRODUCT
) );
954 void ScInterpreter::ScAverage( bool bTextAsZero
)
956 PushDouble( IterateParameters( ifAVERAGE
, bTextAsZero
) );
959 void ScInterpreter::ScCount()
961 if ( mnSubTotalFlags
)
962 PushDouble( IterateParameters( ifCOUNT
) );
965 short nParamCount
= GetByte();
966 sal_uLong nCount
= 0;
969 size_t nRefInList
= 0;
973 while (nParamCount
-- > 0)
975 switch (GetRawStackType())
979 OUString aStr
= PopString().getString();
980 // Only check if string can be converted to number, no
981 // error propagation.
982 sal_uInt16 nErr
= nGlobalError
;
984 ConvertStringToValue( aStr
);
993 nFuncFmtType
= css::util::NumberFormat::NUMBER
;
995 case svExternalSingleRef
:
997 ScExternalRefCache::TokenRef pToken
;
998 ScExternalRefCache::CellFormat aFmt
;
999 PopExternalSingleRef(pToken
, &aFmt
);
1009 StackVar eType
= pToken
->GetType();
1010 if (eType
== formula::svDouble
)
1015 nFuncFmtType
= aFmt
.mnType
;
1016 nFuncFmtIndex
= aFmt
.mnIndex
;
1029 PopSingleRef( aAdr
);
1035 ScRefCellValue aCell
;
1036 aCell
.assign(*pDok
, aAdr
);
1037 if (!aCell
.isEmpty())
1039 if (aCell
.hasNumeric())
1055 PopDoubleRef( aRange
, nParamCount
, nRefInList
);
1062 sc::ColumnSpanSet
aSet(false);
1063 aSet
.set(aRange
, true);
1066 aSet
.executeColumnAction(*pDok
, aAction
);
1067 nCount
+= aAction
.getCount();
1069 // Get the number format of the last iterated cell.
1070 nFuncFmtIndex
= aAction
.getNumberFormat();
1071 nFuncFmtType
= pDok
->GetFormatTable()->GetType(nFuncFmtIndex
);
1074 case svExternalDoubleRef
:
1077 PopExternalDoubleRef(pMat
);
1081 double fMem
= 0.0, fRes
= 0.0;
1083 IterateMatrix(pMat
, ifCOUNT
, false, nCount
, nFuncFmtType
, fRes
, fMem
, bNull
);
1088 ScMatrixRef pMat
= PopMatrix();
1089 double fMem
= 0.0, fRes
= 0.0;
1091 IterateMatrix(pMat
, ifCOUNT
, false, nCount
, nFuncFmtType
, fRes
, fMem
, bNull
);
1101 while (nParamCount
-- > 0)
1103 SetError(errIllegalParameter
);
1107 nFuncFmtType
= css::util::NumberFormat::NUMBER
;
1113 void ScInterpreter::ScCount2()
1115 PushDouble( IterateParameters( ifCOUNT2
) );
1118 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */