From 85cd072198d9024c20b741c04a20ef99fc9b5910 Mon Sep 17 00:00:00 2001 From: Regina Henschel Date: Mon, 6 Apr 2015 15:51:04 +0000 Subject: #i95167 XIRR() function gives Err:502 Patch by: Driss Ben Zoubeir Review by: Regina Henschel --- scaddins/source/analysis/financial.cxx | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) (limited to 'scaddins') diff --git a/scaddins/source/analysis/financial.cxx b/scaddins/source/analysis/financial.cxx index 706897f14ce1..148a0a59969d 100644 --- a/scaddins/source/analysis/financial.cxx +++ b/scaddins/source/analysis/financial.cxx @@ -545,16 +545,36 @@ double SAL_CALL AnalysisAddIn::getXirr( // Newton's method - try to find a fResultRate, so that lcl_sca_XirrResult() returns 0. double fNewRate, fRateEps, fResultValue; sal_Int32 nIter = 0; - bool bContLoop; + sal_Int32 nIterScan = 0; + bool bContLoop = false; + bool bResultRateScanEnd = false; + + // First the inner while-loop will be executed using the default Value fResultRate + // or the user guessed fResultRate if those do not deliver a solution for the + // Newton's method then the range from -0.99 to +0.99 will be scanned with a + // step size of 0.01 to find fResultRate's value which can deliver a solution do { - fResultValue = lcl_sca_XirrResult( aValues, aDates, fResultRate ); - fNewRate = fResultRate - fResultValue / lcl_sca_XirrResult_Deriv1( aValues, aDates, fResultRate ); - fRateEps = fabs( fNewRate - fResultRate ); - fResultRate = fNewRate; - bContLoop = (fRateEps > fMaxEps) && (fabs( fResultValue ) > fMaxEps); + if (nIterScan >=1) + fResultRate = -0.99 + (nIterScan -1)* 0.01; + do + { + fResultValue = lcl_sca_XirrResult( aValues, aDates, fResultRate ); + fNewRate = fResultRate - fResultValue / lcl_sca_XirrResult_Deriv1( aValues, aDates, fResultRate ); + fRateEps = fabs( fNewRate - fResultRate ); + fResultRate = fNewRate; + bContLoop = (fRateEps > fMaxEps) && (fabs( fResultValue ) > fMaxEps); + } + while( bContLoop && (++nIter < nMaxIter) ); + nIter = 0; + if ( ::rtl::math::isNan(fResultRate) || ::rtl::math::isInf(fResultRate) + ||::rtl::math::isNan(fResultValue) || ::rtl::math::isInf(fResultValue)) + bContLoop = true; + + ++nIterScan; + bResultRateScanEnd = (nIterScan >= 200); } - while( bContLoop && (++nIter < nMaxIter) ); + while(bContLoop && !bResultRateScanEnd); if( bContLoop ) THROW_IAE; -- cgit