diff options
author | Laurent Balland-Poirier <laurent.balland-poirier@laposte.net> | 2015-04-16 21:45:58 +0200 |
---|---|---|
committer | Philippe Jung <phil.jung@free.fr> | 2015-06-22 09:57:14 +0000 |
commit | cad19fa8414b419f2e0f9ee88139e9b7a2dd4ff4 (patch) | |
tree | 75be9cc3f2048d7e6181d0343529a9d990366dc4 /chart2 | |
parent | Add unit tests for chart2 trend calculators (diff) | |
download | core-cad19fa8414b419f2e0f9ee88139e9b7a2dd4ff4.tar.gz core-cad19fa8414b419f2e0f9ee88139e9b7a2dd4ff4.zip |
tdf#70673 Exponential trendline: enable negative Y values
With a negative intercept, Y values can be negative
Rebase with forced intercept fec037e68f0dea164915fbfe1db4699a3861adf4
Conflicts:
chart2/source/tools/ExponentialRegressionCurveCalculator.cxx
Change-Id: Ie351c006fb1688ef3e657da7ce0789a9da1317f0
Reviewed-on: https://gerrit.libreoffice.org/15353
Reviewed-by: Philippe Jung <phil.jung@free.fr>
Tested-by: Philippe Jung <phil.jung@free.fr>
Diffstat (limited to 'chart2')
3 files changed, 32 insertions, 10 deletions
diff --git a/chart2/source/inc/ExponentialRegressionCurveCalculator.hxx b/chart2/source/inc/ExponentialRegressionCurveCalculator.hxx index 1247d41d6517..782fb57aaca6 100644 --- a/chart2/source/inc/ExponentialRegressionCurveCalculator.hxx +++ b/chart2/source/inc/ExponentialRegressionCurveCalculator.hxx @@ -56,10 +56,11 @@ private: throw (css::lang::IllegalArgumentException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE; - // formula is: f(x) = exp(m_fLogIntercept) * exp( m_fLogSlope * x ) + // formula is: f(x) = m_fSign * exp(m_fLogIntercept) * exp( m_fLogSlope * x ) // mathematical model f(x) = Intercept * Slope^x double m_fLogSlope; double m_fLogIntercept; + double m_fSign; }; } // namespace chart diff --git a/chart2/source/inc/RegressionCalculationHelper.hxx b/chart2/source/inc/RegressionCalculationHelper.hxx index 32456cf8dbb4..2e0e3a4adc53 100644 --- a/chart2/source/inc/RegressionCalculationHelper.hxx +++ b/chart2/source/inc/RegressionCalculationHelper.hxx @@ -102,6 +102,18 @@ public: } }; +class isValidAndYNegative : public ::std::binary_function< double, double, bool > +{ +public: + inline bool operator()( double x, double y ) + { return ! ( ::rtl::math::isNan( x ) || + ::rtl::math::isNan( y ) || + ::rtl::math::isInf( x ) || + ::rtl::math::isInf( y ) || + y >= 0.0 ); + } +}; + class isValidAndBothPositive : public ::std::binary_function< double, double, bool > { public: diff --git a/chart2/source/tools/ExponentialRegressionCurveCalculator.cxx b/chart2/source/tools/ExponentialRegressionCurveCalculator.cxx index 3738d686f683..2e1deddb20a8 100644 --- a/chart2/source/tools/ExponentialRegressionCurveCalculator.cxx +++ b/chart2/source/tools/ExponentialRegressionCurveCalculator.cxx @@ -50,25 +50,34 @@ void SAL_CALL ExponentialRegressionCurveCalculator::recalculateRegression( RegressionCalculationHelper::cleanup( aXValues, aYValues, RegressionCalculationHelper::isValidAndYPositive())); + m_fSign = 1.0; - const size_t nMax = aValues.first.size(); + size_t nMax = aValues.first.size(); if( nMax == 0 ) { - ::rtl::math::setNan( & m_fLogSlope ); - ::rtl::math::setNan( & m_fLogIntercept ); - ::rtl::math::setNan( & m_fCorrelationCoeffitient );// actual it is coefficient of determination - return; + aValues = RegressionCalculationHelper::cleanup( + aXValues, aYValues, + RegressionCalculationHelper::isValidAndYNegative()); + nMax = aValues.first.size(); + if( nMax == 0 ) + { + ::rtl::math::setNan( & m_fLogSlope ); + ::rtl::math::setNan( & m_fLogIntercept ); + ::rtl::math::setNan( & m_fCorrelationCoeffitient );// actual it is coefficient of determination + return; + } + m_fSign = -1.0; } double fAverageX = 0.0, fAverageY = 0.0; - double fLogIntercept = mForceIntercept ? log(mInterceptValue) : 0.0; + double fLogIntercept = ( mForceIntercept && (m_fSign * mInterceptValue)>0 ) ? log(m_fSign * mInterceptValue) : 0.0; std::vector<double> yVector; yVector.resize(nMax, 0.0); size_t i = 0; for( i = 0; i < nMax; ++i ) { - double yValue = log(aValues.second[i]); + double yValue = log( m_fSign *aValues.second[i] ); if (mForceIntercept) { yValue -= fLogIntercept; @@ -111,7 +120,7 @@ double SAL_CALL ExponentialRegressionCurveCalculator::getCurveValue( double x ) if( ! ( ::rtl::math::isNan( m_fLogSlope ) || ::rtl::math::isNan( m_fLogIntercept ))) { - fResult = exp(m_fLogIntercept + x * m_fLogSlope); + fResult = m_fSign * exp(m_fLogIntercept + x * m_fLogSlope); } return fResult; @@ -146,7 +155,7 @@ OUString ExponentialRegressionCurveCalculator::ImplGetRepresentation( const uno::Reference< util::XNumberFormatter >& xNumFormatter, ::sal_Int32 nNumberFormatKey ) const { - double fIntercept = exp(m_fLogIntercept); + double fIntercept = m_fSign * exp(m_fLogIntercept); double fSlope = exp(m_fLogSlope); bool bHasSlope = !rtl::math::approxEqual( fSlope, 1.0 ); bool bHasIntercept = !rtl::math::approxEqual( fIntercept, 1.0 ); |