23 #include <document.hxx>
35 double const fHalfMachEps = 0.5 * ::std::numeric_limits<double>::epsilon();
47 double const fBigInv = ::std::numeric_limits<double>::epsilon();
48 double const fBig = 1.0/fBigInv;
51 double fDenom = fX + 2.0-fA;
52 double fPkm1 = fX + 1.0;
54 double fQkm1 = fDenom * fX;
56 double fApprox = fPkm1/fQkm1;
57 bool bFinished =
false;
62 const double fNum = fY * fCount;
64 double fPk = fPkm1 * fDenom - fPkm2 * fNum;
65 const double fQk = fQkm1 * fDenom - fQkm2 * fNum;
68 const double fR = fPk/fQk;
79 fPkm2 = fPkm2 * fBigInv;
80 fPkm1 = fPkm1 * fBigInv;
81 fQkm2 = fQkm2 * fBigInv;
82 fQkm1 = fQkm1 * fBigInv;
84 }
while (!bFinished && fCount<10000);
88 SetError(FormulaError::NoConvergence);
98 double fDenomfactor = fA;
99 double fSummand = 1.0/fA;
100 double fSum = fSummand;
104 fDenomfactor = fDenomfactor + 1.0;
105 fSummand = fSummand * fX/fDenomfactor;
106 fSum = fSum + fSummand;
108 }
while ( fSummand/fSum >
fHalfMachEps && nCount<=10000);
113 SetError(FormulaError::NoConvergence);
122 double fFactor = exp(fLnFactor);
134 double fFactor = exp(fLnFactor);
153 SetError(FormulaError::DivisionByZero);
156 else if (fAlpha == 1)
158 return (1.0 / fLambda);
167 double fXr = fX / fLambda;
171 const double fLogDblMax =
log( ::std::numeric_limits<double>::max());
172 if (
log(fXr) * (fAlpha-1.0) < fLogDblMax && fAlpha < fMaxGammaArgument)
174 return pow( fXr, fAlpha-1.0) * exp(-fXr) / fLambda / GetGamma(fAlpha);
183 if (fAlpha<fMaxGammaArgument)
185 return pow( fXr, fAlpha-1.0) * exp(-fXr) / fLambda / GetGamma(fAlpha);
189 return pow( fXr, fAlpha-1.0) * exp(-fXr) / fLambda / exp(
GetLogGamma(fAlpha));
208 class NumericCellAccumulator
216 void operator() (
const sc::CellStoreType::value_type& rNode,
size_t nOffset,
size_t nDataSize)
225 const double *
p = &sc::numeric_block::at(*rNode.data, nOffset);
232 sc::formula_block::const_iterator it = sc::formula_block::begin(*rNode.data);
233 std::advance(it, nOffset);
234 sc::formula_block::const_iterator itEnd = it;
235 std::advance(itEnd, nDataSize);
236 for (; it != itEnd; ++it)
245 if (nErr != FormulaError::NONE)
262 const KahanSum& getResult()
const {
return maSum; }
265 class NumericCellCounter
269 NumericCellCounter() : mnCount(0) {}
271 void operator() (
const sc::CellStoreType::value_type& rNode,
size_t nOffset,
size_t nDataSize)
276 mnCount += nDataSize;
280 sc::formula_block::const_iterator it = sc::formula_block::begin(*rNode.data);
281 std::advance(it, nOffset);
282 sc::formula_block::const_iterator itEnd = it;
283 std::advance(itEnd, nDataSize);
284 for (; it != itEnd; ++it)
297 size_t getCount()
const {
return mnCount; }
309 FuncCount(
const ScInterpreterContext& rContext) : mrContext(rContext), mpCol(nullptr), mnCount(0), mnNumFmt(0) {}
311 virtual void startColumn(
ScColumn* pCol)
override
317 virtual void execute(
SCROW nRow1,
SCROW nRow2,
bool bVal)
override
322 NumericCellCounter aFunc;
324 mnCount += aFunc.getCount();
328 size_t getCount()
const {
return mnCount; }
329 sal_uInt32 getNumberFormat()
const {
return mnNumFmt; }
344 virtual void startColumn(
ScColumn* pCol)
override
350 virtual void execute(
SCROW nRow1,
SCROW nRow2,
bool bVal)
override
355 if (mnError != FormulaError::NONE)
358 NumericCellAccumulator aFunc;
360 mnError = aFunc.getError();
361 if (mnError != FormulaError::NONE)
365 mfSum += aFunc.getResult();
370 const KahanSum& getSum()
const {
return mfSum; }
371 sal_uInt32 getNumberFormat()
const {
return mnNumFmt; }
384 rFuncFmtType = SvNumFormatType::NUMBER;
396 rCount += pMat->Count(bTextAsZero,
false);
400 rCount += pMat->Count(
true,
true);
424 if (IsInArrayContext())
463 const SCSIZE nMatRows = GetRefListArrayMaxSize( nParamCount);
465 const double ResInitVal = (eFunc ==
ifPRODUCT) ? 1.0 : 0.0;
471 size_t nRefInList = 0;
472 size_t nRefArrayPos = std::numeric_limits<size_t>::max();
473 if ( nGlobalError != FormulaError::NONE && ( eFunc ==
ifCOUNT2 || eFunc ==
ifCOUNT ||
475 nGlobalError = FormulaError::NONE;
476 while (nParamCount-- > 0)
478 switch (GetStackType())
484 OUString
aStr = PopString().getString();
492 nGlobalError = FormulaError::NONE;
493 ConvertStringToValue( aStr );
494 if (nGlobalError == FormulaError::NONE)
517 while (nParamCount-- > 0)
535 case ifSUM: fRes += fVal;
break;
536 case ifSUMSQ: fRes += fVal * fVal;
break;
540 nFuncFmtType = SvNumFormatType::NUMBER;
546 PopExternalSingleRef(pToken, &aFmt);
547 if ( nGlobalError != FormulaError::NONE && ( eFunc ==
ifCOUNT2 || eFunc ==
ifCOUNT ||
548 ( mnSubTotalFlags & SubtotalFlags::IgnoreErrVal ) ) )
550 nGlobalError = FormulaError::NONE;
551 if ( eFunc ==
ifCOUNT2 && !( mnSubTotalFlags & SubtotalFlags::IgnoreErrVal ) )
567 if (nGlobalError != FormulaError::NONE)
568 nGlobalError = FormulaError::NONE;
573 fVal = pToken->GetDouble();
576 nFuncFmtType = aFmt.
mnType;
582 case ifSUM: fRes += fVal;
break;
583 case ifSUMSQ: fRes += fVal * fVal;
break;
586 if ( nGlobalError != FormulaError::NONE )
588 nGlobalError = FormulaError::NONE;
595 else if (bTextAsZero && eType ==
svString)
605 PopSingleRef( aAdr );
606 if (nGlobalError == FormulaError::NoRef)
608 PushError( FormulaError::NoRef);
613 mrDoc.RowFiltered( aAdr.
Row(), aAdr.
Tab() ) ) ||
615 mrDoc.RowHidden( aAdr.
Row(), aAdr.
Tab() ) ) )
619 if ( nGlobalError != FormulaError::NONE && ( eFunc ==
ifCOUNT2 || eFunc ==
ifCOUNT ||
620 ( mnSubTotalFlags & SubtotalFlags::IgnoreErrVal ) ) )
622 nGlobalError = FormulaError::NONE;
623 if ( eFunc ==
ifCOUNT2 && !( mnSubTotalFlags & SubtotalFlags::IgnoreErrVal ) )
635 if ( nGlobalError != FormulaError::NONE )
636 nGlobalError = FormulaError::NONE;
640 fVal = GetCellValue(aAdr, aCell);
641 if (nGlobalError != FormulaError::NONE)
643 if (eFunc ==
ifCOUNT || (mnSubTotalFlags & SubtotalFlags::IgnoreErrVal))
644 nGlobalError = FormulaError::NONE;
652 case ifSUM: fRes += fVal;
break;
653 case ifSUMSQ: fRes += fVal * fVal;
break;
658 else if (bTextAsZero && aCell.
hasString())
672 nRefArrayPos = nRefInList;
679 assert(nMatRows > 0);
680 xResMat = GetNewMat( 1, nMatRows,
true);
681 xResMat->FillDouble( fRes.
get(), 0,0, 0,nMatRows-1);
684 xResCount = GetNewMat( 1, nMatRows,
true);
685 xResCount->FillDouble( nCount, 0,0, 0,nMatRows-1);
692 if (nCount && xResCount)
696 xResCount->PutDouble( xResCount->GetDouble(0,
i) + nCount, 0,
i);
699 if (fRes != ResInitVal)
703 double fVecRes = xResMat->GetDouble(0,
i);
705 fVecRes *= fRes.
get();
707 fVecRes += fRes.
get();
708 xResMat->PutDouble( fVecRes, 0,
i);
719 PopDoubleRef( aRange, nParamCount, nRefInList);
720 if (nGlobalError == FormulaError::NoRef)
722 PushError( FormulaError::NoRef);
726 if ( nGlobalError != FormulaError::NONE && ( eFunc ==
ifCOUNT2 || eFunc ==
ifCOUNT ||
727 ( mnSubTotalFlags & SubtotalFlags::IgnoreErrVal ) ) )
729 nGlobalError = FormulaError::NONE;
730 if ( eFunc ==
ifCOUNT2 && !( mnSubTotalFlags & SubtotalFlags::IgnoreErrVal ) )
738 for (
bool bHas = aIter.
first(); bHas; bHas = aIter.
next())
746 if ( nGlobalError != FormulaError::NONE )
747 nGlobalError = FormulaError::NONE;
749 else if (((eFunc ==
ifSUM && !bCalcAsShown) || eFunc ==
ifCOUNT )
757 if ( eFunc ==
ifSUM )
759 FuncSum aAction(mrContext);
762 if ( nErr != FormulaError::NONE )
767 fRes += aAction.getSum();
770 nFuncFmtIndex = aAction.getNumberFormat();
774 FuncCount aAction(mrContext);
776 nCount += aAction.getCount();
779 nFuncFmtIndex = aAction.getNumberFormat();
786 ScValueIterator aValIter( mrDoc, aRange, mnSubTotalFlags, bTextAsZero );
797 if ( mnSubTotalFlags & SubtotalFlags::IgnoreErrVal )
801 if ( nErr == FormulaError::NONE )
808 while (aValIter.
GetNext(fVal, nErr));
818 while (aValIter.
GetNext(fVal, nErr));
822 if ( mnSubTotalFlags & SubtotalFlags::IgnoreErrVal )
826 if ( nErr == FormulaError::NONE )
833 while (aValIter.
GetNext(fVal, nErr));
843 while (aValIter.
GetNext(fVal, nErr));
849 if ( !( nErr != FormulaError::NONE && ( mnSubTotalFlags & SubtotalFlags::IgnoreErrVal ) ) )
856 while (aValIter.
GetNext(fVal, nErr));
861 if ( nErr == FormulaError::NONE )
864 while (aValIter.
GetNext(fVal, nErr));
871 if (nRefArrayPos != std::numeric_limits<size_t>::max())
875 xResCount->PutDouble( xResCount->GetDouble(0,nRefArrayPos) + nCount, 0,nRefArrayPos);
876 double fVecRes = xResMat->GetDouble(0,nRefArrayPos);
878 fVecRes *= fRes.
get();
880 fVecRes += fRes.
get();
881 xResMat->PutDouble( fVecRes, 0,nRefArrayPos);
885 nRefArrayPos = std::numeric_limits<size_t>::max();
892 PopExternalDoubleRef(pMat);
893 if ( nGlobalError != FormulaError::NONE && !( mnSubTotalFlags & SubtotalFlags::IgnoreErrVal ) )
896 IterateMatrix( pMat, eFunc, bTextAsZero, mnSubTotalFlags, nCount, nFuncFmtType, fRes );
903 IterateMatrix( pMat, eFunc, bTextAsZero, mnSubTotalFlags, nCount, nFuncFmtType, fRes );
909 if ( eFunc ==
ifCOUNT || ( mnSubTotalFlags & SubtotalFlags::IgnoreErrVal ) )
911 nGlobalError = FormulaError::NONE;
913 else if ( eFunc ==
ifCOUNT2 && !( mnSubTotalFlags & SubtotalFlags::IgnoreErrVal ) )
916 nGlobalError = FormulaError::NONE;
921 while (nParamCount-- > 0)
923 SetError(FormulaError::IllegalParameter);
929 if( nFuncFmtType == SvNumFormatType::LOGICAL || eFunc ==
ifCOUNT || eFunc ==
ifCOUNT2 )
930 nFuncFmtType = SvNumFormatType::NUMBER;
937 sal_uLong nVecCount = (xResCount ? nCount + xResCount->GetDouble(0,
i) : nCount);
938 double fVecRes = xResMat->GetDouble(0,
i);
940 fVecRes *= fRes.
get();
942 fVecRes += fRes.
get();
944 xResMat->PutDouble( fVecRes, 0,
i);
946 PushMatrix( xResMat);
961 IterateParameters(
ifSUM );
971 IterateParameters(
ifAVERAGE, bTextAsZero );
992 if (!MustHaveParamCountMin( nParamCount, 2))
996 ReverseStack( nParamCount);
998 double fRes = GetDouble();
1000 while (nGlobalError == FormulaError::NONE && --nParamCount > 0)
1003 fRes -= GetDouble();
1005 while (nParamCount-- > 0)
double GetLowRegIGamma(double fA, double fX)
You must ensure fA>0.0 && fX>0.0)
CellStoreType::const_iterator miCellPos
KahanSum sumArray(const double *pArray, size_t nSize)
Performs the sum of an array.
StoreT::const_iterator ParseBlock(const typename StoreT::const_iterator &itPos, const StoreT &rStore, Func &rFunc, typename StoreT::size_type nStart, typename StoreT::size_type nEnd)
Generic algorithm to parse blocks of multi_type_vector either partially or fully. ...
static void IterateMatrix(const ScMatrixRef &pMat, ScIterFunc eFunc, bool bTextAsZero, SubtotalFlags nSubTotalFlags, sal_uLong &rCount, SvNumFormatType &rFuncFmtType, KahanSum &fRes)
This is very similar to ScCellValue, except that it references the original value instead of copying ...
void ScRawSubtract()
The purpose of RAWSUBTRACT() is exactly to not apply any error correction, approximation etc...
const mdds::mtv::element_t element_type_formula
This class provides LO with Kahan summation algorithm About this algorithm: https://en.wikipedia.org/wiki/Kahan_summation_algorithm For general purpose software we assume first order error is enough.
void ScAverage(bool bTextAsZero=false)
size_t SCSIZE
size_t typedef to be able to find places where code was changed from USHORT to size_t and is used to ...
::boost::intrusive_ptr< ScMatrix > ScMatrixRef
Walk through all cells in an area.
Optimized ColumnSpanSet version that operates on a single ScRange.
void SetInterpreterContext(ScInterpreterContext *context)
double const fHalfMachEps
void InitBlockPosition(sc::ColumnBlockPosition &rBlockPos)
std::string GetLowRegIGamma
double GetGammaDist(double fX, double fAlpha, double fLambda)
Gamma distribution, cumulative distribution function.
size_t GetRefListArrayMaxSize(short nParamCount)
Check for array of references to determine the maximum size of a return column vector if in array con...
virtual const ScRefList * GetRefList() const override
static double lcl_IterResult(ScIterFunc eFunc, double fRes, sal_uLong nCount)
const mdds::mtv::element_t element_type_numeric
Mapped standard element types (for convenience).
double GetUpRegIGamma(double fA, double fX)
You must ensure fA>0.0 && fX>0.0)
sal_uInt32 GetNumberFormat(const ScInterpreterContext &rContext, SCROW nRow) const
const NodeContext & mrContext
double GetGammaContFraction(double fA, double fX)
You must ensure fA>0.0 && fX>0.0 valid results only if fX > fA+1.0 uses continued fraction with odd i...
void IterateParameters(ScIterFunc, bool bTextAsZero=false)
std::string GetGammaContFraction
::formula::FormulaTokenRef TokenRef
bool GetFirst(double &rValue, FormulaError &rErr)
Does NOT reset rValue if no value found!
std::string GetGammaSeries
SvNumFormatType GetNumberFormatType(sal_uInt32 nFIndex) const
Iterator for executing one operation with the matrix data.
double GetGammaSeries(double fA, double fX)
You must ensure fA>0.0 && fX>0.0 valid results only if fX <= fA+1.0 uses power series.
void GetCurNumFmtInfo(const ScInterpreterContext &rContext, SvNumFormatType &nType, sal_uInt32 &nIndex)
bool GetNext(double &rValue, FormulaError &rErr)
Does NOT reset rValue if no value found!
void executeColumnAction(ScDocument &rDoc, sc::ColumnSpanSet::ColumnAction &ac) const
double get() const
Returns the final sum.
bool IsArrayResult() const
double GetGammaDistPDF(double fX, double fAlpha, double fLambda)
Gamma distribution, probability density function.
sc::CellStoreType & GetCellStore()
double div(const double &fNumerator, const double &fDenominator)
Return fNumerator/fDenominator if fDenominator!=0 else #DIV/0! error coded into double.