Kaydet (Commit) cad19fa8 authored tarafından Laurent Balland-Poirier's avatar Laurent Balland-Poirier Kaydeden (comit) Philippe Jung

tdf#70673 Exponential trendline: enable negative Y values

With a negative intercept, Y values can be negative

Rebase with forced intercept fec037e6

Conflicts:
	chart2/source/tools/ExponentialRegressionCurveCalculator.cxx

Change-Id: Ie351c006fb1688ef3e657da7ce0789a9da1317f0
Reviewed-on: https://gerrit.libreoffice.org/15353Reviewed-by: 's avatarPhilippe Jung <phil.jung@free.fr>
Tested-by: 's avatarPhilippe Jung <phil.jung@free.fr>
üst 733f5887
...@@ -56,10 +56,11 @@ private: ...@@ -56,10 +56,11 @@ private:
throw (css::lang::IllegalArgumentException, throw (css::lang::IllegalArgumentException,
css::uno::RuntimeException, std::exception) SAL_OVERRIDE; 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 // mathematical model f(x) = Intercept * Slope^x
double m_fLogSlope; double m_fLogSlope;
double m_fLogIntercept; double m_fLogIntercept;
double m_fSign;
}; };
} // namespace chart } // namespace chart
......
...@@ -102,6 +102,18 @@ public: ...@@ -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 > class isValidAndBothPositive : public ::std::binary_function< double, double, bool >
{ {
public: public:
......
...@@ -50,8 +50,15 @@ void SAL_CALL ExponentialRegressionCurveCalculator::recalculateRegression( ...@@ -50,8 +50,15 @@ void SAL_CALL ExponentialRegressionCurveCalculator::recalculateRegression(
RegressionCalculationHelper::cleanup( RegressionCalculationHelper::cleanup(
aXValues, aYValues, aXValues, aYValues,
RegressionCalculationHelper::isValidAndYPositive())); RegressionCalculationHelper::isValidAndYPositive()));
m_fSign = 1.0;
const size_t nMax = aValues.first.size(); size_t nMax = aValues.first.size();
if( nMax == 0 )
{
aValues = RegressionCalculationHelper::cleanup(
aXValues, aYValues,
RegressionCalculationHelper::isValidAndYNegative());
nMax = aValues.first.size();
if( nMax == 0 ) if( nMax == 0 )
{ {
::rtl::math::setNan( & m_fLogSlope ); ::rtl::math::setNan( & m_fLogSlope );
...@@ -59,16 +66,18 @@ void SAL_CALL ExponentialRegressionCurveCalculator::recalculateRegression( ...@@ -59,16 +66,18 @@ void SAL_CALL ExponentialRegressionCurveCalculator::recalculateRegression(
::rtl::math::setNan( & m_fCorrelationCoeffitient );// actual it is coefficient of determination ::rtl::math::setNan( & m_fCorrelationCoeffitient );// actual it is coefficient of determination
return; return;
} }
m_fSign = -1.0;
}
double fAverageX = 0.0, fAverageY = 0.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; std::vector<double> yVector;
yVector.resize(nMax, 0.0); yVector.resize(nMax, 0.0);
size_t i = 0; size_t i = 0;
for( i = 0; i < nMax; ++i ) for( i = 0; i < nMax; ++i )
{ {
double yValue = log(aValues.second[i]); double yValue = log( m_fSign *aValues.second[i] );
if (mForceIntercept) if (mForceIntercept)
{ {
yValue -= fLogIntercept; yValue -= fLogIntercept;
...@@ -111,7 +120,7 @@ double SAL_CALL ExponentialRegressionCurveCalculator::getCurveValue( double x ) ...@@ -111,7 +120,7 @@ double SAL_CALL ExponentialRegressionCurveCalculator::getCurveValue( double x )
if( ! ( ::rtl::math::isNan( m_fLogSlope ) || if( ! ( ::rtl::math::isNan( m_fLogSlope ) ||
::rtl::math::isNan( m_fLogIntercept ))) ::rtl::math::isNan( m_fLogIntercept )))
{ {
fResult = exp(m_fLogIntercept + x * m_fLogSlope); fResult = m_fSign * exp(m_fLogIntercept + x * m_fLogSlope);
} }
return fResult; return fResult;
...@@ -146,7 +155,7 @@ OUString ExponentialRegressionCurveCalculator::ImplGetRepresentation( ...@@ -146,7 +155,7 @@ OUString ExponentialRegressionCurveCalculator::ImplGetRepresentation(
const uno::Reference< util::XNumberFormatter >& xNumFormatter, const uno::Reference< util::XNumberFormatter >& xNumFormatter,
::sal_Int32 nNumberFormatKey ) const ::sal_Int32 nNumberFormatKey ) const
{ {
double fIntercept = exp(m_fLogIntercept); double fIntercept = m_fSign * exp(m_fLogIntercept);
double fSlope = exp(m_fLogSlope); double fSlope = exp(m_fLogSlope);
bool bHasSlope = !rtl::math::approxEqual( fSlope, 1.0 ); bool bHasSlope = !rtl::math::approxEqual( fSlope, 1.0 );
bool bHasIntercept = !rtl::math::approxEqual( fIntercept, 1.0 ); bool bHasIntercept = !rtl::math::approxEqual( fIntercept, 1.0 );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment