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
215 NumericCellAccumulator() : mfFirst(0.0), mfRest(0.0), mnError(
FormulaError::
NONE) {}
217 void operator() (
const sc::CellStoreType::value_type& rNode,
size_t nOffset,
size_t nDataSize)
223 const double *
p = &sc::numeric_block::at(*rNode.data, nOffset);
229 for (i = 0; i < nDataSize; ++i)
250 sc::formula_block::const_iterator it = sc::formula_block::begin(*rNode.data);
251 std::advance(it, nOffset);
252 sc::formula_block::const_iterator itEnd = it;
253 std::advance(itEnd, nDataSize);
254 for (; it != itEnd; ++it)
263 if (nErr != FormulaError::NONE)
283 double getFirst()
const {
return mfFirst; }
284 double getRest()
const {
return mfRest; }
287 class NumericCellCounter
291 NumericCellCounter() : mnCount(0) {}
293 void operator() (
const sc::CellStoreType::value_type& rNode,
size_t nOffset,
size_t nDataSize)
298 mnCount += nDataSize;
302 sc::formula_block::const_iterator it = sc::formula_block::begin(*rNode.data);
303 std::advance(it, nOffset);
304 sc::formula_block::const_iterator itEnd = it;
305 std::advance(itEnd, nDataSize);
306 for (; it != itEnd; ++it)
319 size_t getCount()
const {
return mnCount; }
331 FuncCount(
const ScInterpreterContext& rContext) : mrContext(rContext), mpCol(nullptr), mnCount(0), mnNumFmt(0) {}
333 virtual void startColumn(
ScColumn* pCol)
override
339 virtual void execute(
SCROW nRow1,
SCROW nRow2,
bool bVal)
override
344 NumericCellCounter aFunc;
346 mnCount += aFunc.getCount();
350 size_t getCount()
const {
return mnCount; }
351 sal_uInt32 getNumberFormat()
const {
return mnNumFmt; }
366 virtual void startColumn(
ScColumn* pCol)
override
372 virtual void execute(
SCROW,
SCROW,
bool)
override {}
374 virtual void executeSum(
SCROW nRow1,
SCROW nRow2,
bool bVal,
double& fMem )
override
379 if (mnError != FormulaError::NONE)
382 NumericCellAccumulator aFunc;
384 mnError = aFunc.getError();
385 if (mnError != FormulaError::NONE)
389 mfSum += aFunc.getFirst() + aFunc.getRest();
392 fMem = aFunc.getFirst();
393 mfSum += aFunc.getRest();
400 double getSum()
const {
return mfSum; }
401 sal_uInt32 getNumberFormat()
const {
return mnNumFmt; }
414 rFuncFmtType = SvNumFormatType::NUMBER;
423 if ( !std::isfinite(aRes.
mfFirst) )
425 sal_uInt32 nErr =
reinterpret_cast< sal_math_Double *
>(&aRes.
mfFirst)->nan_parts.fraction_lo;
426 if (nErr & 0xffff0000)
442 rCount += pMat->Count(bTextAsZero,
false);
446 rCount += pMat->Count(
true,
true);
472 if (IsInArrayContext())
492 fRes = ::rtl::math::approxAdd( fRes, fMem );
495 fRes =
sc::div( ::rtl::math::approxAdd( fRes, fMem ), nCount);
514 const SCSIZE nMatRows = GetRefListArrayMaxSize( nParamCount);
516 const double ResInitVal = (eFunc ==
ifPRODUCT) ? 1.0 : 0.0;
517 double fRes = ResInitVal;
523 size_t nRefInList = 0;
524 size_t nRefArrayPos = std::numeric_limits<size_t>::max();
525 if ( nGlobalError != FormulaError::NONE && ( eFunc ==
ifCOUNT2 || eFunc ==
ifCOUNT ||
527 nGlobalError = FormulaError::NONE;
528 while (nParamCount-- > 0)
530 switch (GetStackType())
536 OUString
aStr = PopString().getString();
544 nGlobalError = FormulaError::NONE;
545 ConvertStringToValue( aStr );
546 if (nGlobalError == FormulaError::NONE)
569 while (nParamCount-- > 0)
593 case ifSUMSQ: fRes += fVal * fVal;
break;
597 nFuncFmtType = SvNumFormatType::NUMBER;
603 PopExternalSingleRef(pToken, &aFmt);
604 if ( nGlobalError != FormulaError::NONE && ( eFunc ==
ifCOUNT2 || eFunc ==
ifCOUNT ||
605 ( mnSubTotalFlags & SubtotalFlags::IgnoreErrVal ) ) )
607 nGlobalError = FormulaError::NONE;
608 if ( eFunc ==
ifCOUNT2 && !( mnSubTotalFlags & SubtotalFlags::IgnoreErrVal ) )
624 if (nGlobalError != FormulaError::NONE)
625 nGlobalError = FormulaError::NONE;
630 fVal = pToken->GetDouble();
633 nFuncFmtType = aFmt.
mnType;
645 case ifSUMSQ: fRes += fVal * fVal;
break;
648 if ( nGlobalError != FormulaError::NONE )
650 nGlobalError = FormulaError::NONE;
657 else if (bTextAsZero && eType ==
svString)
667 PopSingleRef( aAdr );
668 if (nGlobalError == FormulaError::NoRef)
670 PushError( FormulaError::NoRef);
675 mrDoc.RowFiltered( aAdr.
Row(), aAdr.
Tab() ) ) ||
677 mrDoc.RowHidden( aAdr.
Row(), aAdr.
Tab() ) ) )
681 if ( nGlobalError != FormulaError::NONE && ( eFunc ==
ifCOUNT2 || eFunc ==
ifCOUNT ||
682 ( mnSubTotalFlags & SubtotalFlags::IgnoreErrVal ) ) )
684 nGlobalError = FormulaError::NONE;
685 if ( eFunc ==
ifCOUNT2 && !( mnSubTotalFlags & SubtotalFlags::IgnoreErrVal ) )
697 if ( nGlobalError != FormulaError::NONE )
698 nGlobalError = FormulaError::NONE;
703 fVal = GetCellValue(aAdr, aCell);
714 case ifSUMSQ: fRes += fVal * fVal;
break;
717 if ( nGlobalError != FormulaError::NONE )
719 nGlobalError = FormulaError::NONE;
726 else if (bTextAsZero && aCell.
hasString())
740 nRefArrayPos = nRefInList;
743 fRes = rtl::math::approxAdd( fRes, fMem);
753 xResMat = GetNewMat( 1, nMatRows,
true);
754 xResMat->FillDouble( fRes, 0,0, 0,nMatRows-1);
757 xResCount = GetNewMat( 1, nMatRows,
true);
758 xResCount->FillDouble( nCount, 0,0, 0,nMatRows-1);
765 if (nCount && xResCount)
767 for (
SCSIZE i=0; i < nMatRows; ++i)
769 xResCount->PutDouble( xResCount->GetDouble(0,i) + nCount, 0,i);
772 if (fRes != ResInitVal)
774 for (
SCSIZE i=0; i < nMatRows; ++i)
776 double fVecRes = xResMat->GetDouble(0,i);
781 xResMat->PutDouble( fVecRes, 0,i);
792 PopDoubleRef( aRange, nParamCount, nRefInList);
793 if (nGlobalError == FormulaError::NoRef)
795 PushError( FormulaError::NoRef);
799 if ( nGlobalError != FormulaError::NONE && ( eFunc ==
ifCOUNT2 || eFunc ==
ifCOUNT ||
800 ( mnSubTotalFlags & SubtotalFlags::IgnoreErrVal ) ) )
802 nGlobalError = FormulaError::NONE;
803 if ( eFunc ==
ifCOUNT2 && !( mnSubTotalFlags & SubtotalFlags::IgnoreErrVal ) )
811 for (
bool bHas = aIter.
first(); bHas; bHas = aIter.
next())
819 if ( nGlobalError != FormulaError::NONE )
820 nGlobalError = FormulaError::NONE;
822 else if (((eFunc ==
ifSUM && !bCalcAsShown) || eFunc ==
ifCOUNT )
830 if ( eFunc ==
ifSUM )
832 FuncSum aAction(mrContext);
835 if ( nErr != FormulaError::NONE )
840 fRes += aAction.getSum();
843 nFuncFmtIndex = aAction.getNumberFormat();
847 FuncCount aAction(mrContext);
849 nCount += aAction.getCount();
852 nFuncFmtIndex = aAction.getNumberFormat();
859 ScValueIterator aValIter( mrDoc, aRange, mnSubTotalFlags, bTextAsZero );
870 if ( mnSubTotalFlags & SubtotalFlags::IgnoreErrVal )
874 if ( nErr == FormulaError::NONE )
884 while (aValIter.
GetNext(fVal, nErr));
897 while (aValIter.
GetNext(fVal, nErr));
901 if ( mnSubTotalFlags & SubtotalFlags::IgnoreErrVal )
905 if ( nErr == FormulaError::NONE )
912 while (aValIter.
GetNext(fVal, nErr));
922 while (aValIter.
GetNext(fVal, nErr));
928 if ( !( nErr != FormulaError::NONE && ( mnSubTotalFlags & SubtotalFlags::IgnoreErrVal ) ) )
935 while (aValIter.
GetNext(fVal, nErr));
940 if ( nErr == FormulaError::NONE )
943 while (aValIter.
GetNext(fVal, nErr));
950 if (nRefArrayPos != std::numeric_limits<size_t>::max())
955 fRes = rtl::math::approxAdd( fRes, fMem);
959 xResCount->PutDouble( xResCount->GetDouble(0,nRefArrayPos) + nCount, 0,nRefArrayPos);
960 double fVecRes = xResMat->GetDouble(0,nRefArrayPos);
965 xResMat->PutDouble( fVecRes, 0,nRefArrayPos);
969 nRefArrayPos = std::numeric_limits<size_t>::max();
976 PopExternalDoubleRef(pMat);
977 if ( nGlobalError != FormulaError::NONE && !( mnSubTotalFlags & SubtotalFlags::IgnoreErrVal ) )
980 IterateMatrix( pMat, eFunc, bTextAsZero, mnSubTotalFlags, nCount, nFuncFmtType, fRes, fMem );
987 IterateMatrix( pMat, eFunc, bTextAsZero, mnSubTotalFlags, nCount, nFuncFmtType, fRes, fMem );
993 if ( eFunc ==
ifCOUNT || ( mnSubTotalFlags & SubtotalFlags::IgnoreErrVal ) )
995 nGlobalError = FormulaError::NONE;
997 else if ( eFunc ==
ifCOUNT2 && !( mnSubTotalFlags & SubtotalFlags::IgnoreErrVal ) )
1000 nGlobalError = FormulaError::NONE;
1005 while (nParamCount-- > 0)
1007 SetError(FormulaError::IllegalParameter);
1013 if( nFuncFmtType == SvNumFormatType::LOGICAL || eFunc ==
ifCOUNT || eFunc ==
ifCOUNT2 )
1014 nFuncFmtType = SvNumFormatType::NUMBER;
1019 for (
SCSIZE i=0; i < nMatRows; ++i)
1021 sal_uLong nVecCount = (xResCount ? nCount + xResCount->GetDouble(0,i) : nCount);
1022 double fVecRes = xResMat->GetDouble(0,i);
1028 xResMat->PutDouble( fVecRes, 0,i);
1030 PushMatrix( xResMat);
1045 IterateParameters(
ifSUM );
1055 IterateParameters(
ifAVERAGE, bTextAsZero );
1071 if (!MustHaveParamCountMin( nParamCount, 2))
1076 PushWithoutError( *p );
1078 double fRes = GetDouble();
1080 while (nGlobalError == FormulaError::NONE && nParamCount > 1)
1083 fRes -= GetDouble();
1086 while (nParamCount-- > 0)
double GetLowRegIGamma(double fA, double fX)
You must ensure fA>0.0 && fX>0.0)
CellStoreType::const_iterator miCellPos
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. ...
This is very similar to ScCellValue, except that it references the original value instead of copying ...
const mdds::mtv::element_t element_type_formula
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 ...
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
::boost::intrusive_ptr< ScMatrix > ScMatrixRef
Walk through all cells in an area.
sal_uInt32 GetNumberFormat(const ScInterpreterContext &rContext, SCROW nRow) const
Optimized ColumnSpanSet version that operates on a single ScRange.
void SetInterpreterContext(ScInterpreterContext *context)
static double lcl_IterResult(ScIterFunc eFunc, double fRes, double fMem, sal_uLong nCount)
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
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)
static void IterateMatrix(const ScMatrixRef &pMat, ScIterFunc eFunc, bool bTextAsZero, SubtotalFlags nSubTotalFlags, sal_uLong &rCount, SvNumFormatType &rFuncFmtType, double &fRes, double &fMem)
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!
if(aStr!=aBuf) UpdateName_Impl(m_xFollowLb.get()
std::string GetGammaSeries
SvNumFormatType GetNumberFormatType(sal_uInt32 nFIndex) const
When adding all numerical matrix elements for a scalar result such as summation, the interpreter want...
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
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.