1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "ExponentialRegressionCurveCalculator.hxx"
22 #include "RegressionCalculationHelper.hxx"
24 #include <rtl/math.hxx>
25 #include <rtl/ustrbuf.hxx>
27 using namespace ::com::sun::star
;
32 ExponentialRegressionCurveCalculator::ExponentialRegressionCurveCalculator() :
34 m_fLogIntercept( 0.0 )
36 ::rtl::math::setNan( & m_fLogSlope
);
37 ::rtl::math::setNan( & m_fLogIntercept
);
40 ExponentialRegressionCurveCalculator::~ExponentialRegressionCurveCalculator()
43 // ____ XRegressionCurveCalculator ____
44 void SAL_CALL
ExponentialRegressionCurveCalculator::recalculateRegression(
45 const uno::Sequence
< double >& aXValues
,
46 const uno::Sequence
< double >& aYValues
)
47 throw (uno::RuntimeException
, std::exception
)
49 RegressionCalculationHelper::tDoubleVectorPair
aValues(
50 RegressionCalculationHelper::cleanup(
52 RegressionCalculationHelper::isValidAndYPositive()));
54 const size_t nMax
= aValues
.first
.size();
57 ::rtl::math::setNan( & m_fLogSlope
);
58 ::rtl::math::setNan( & m_fLogIntercept
);
59 ::rtl::math::setNan( & m_fCorrelationCoeffitient
);// actual it is coefficient of determination
63 double fAverageX
= 0.0, fAverageY
= 0.0;
64 double fLogIntercept
= mForceIntercept
? log(mInterceptValue
) : 0.0;
65 std::vector
<double> yVector
;
66 yVector
.resize(nMax
, 0.0);
69 for( i
= 0; i
< nMax
; ++i
)
71 double yValue
= log(aValues
.second
[i
]);
74 yValue
-= fLogIntercept
;
78 fAverageX
+= aValues
.first
[i
];
84 const double fN
= static_cast< double >( nMax
);
88 double fQx
= 0.0, fQy
= 0.0, fQxy
= 0.0;
89 for( i
= 0; i
< nMax
; ++i
)
91 double fDeltaX
= aValues
.first
[i
] - fAverageX
;
92 double fDeltaY
= yVector
[i
] - fAverageY
;
94 fQx
+= fDeltaX
* fDeltaX
;
95 fQy
+= fDeltaY
* fDeltaY
;
96 fQxy
+= fDeltaX
* fDeltaY
;
99 m_fLogSlope
= fQxy
/ fQx
;
100 m_fLogIntercept
= mForceIntercept
? fLogIntercept
: fAverageY
- m_fLogSlope
* fAverageX
;
101 m_fCorrelationCoeffitient
= fQxy
/ sqrt( fQx
* fQy
);
104 double SAL_CALL
ExponentialRegressionCurveCalculator::getCurveValue( double x
)
105 throw (lang::IllegalArgumentException
,
106 uno::RuntimeException
, std::exception
)
109 ::rtl::math::setNan( & fResult
);
111 if( ! ( ::rtl::math::isNan( m_fLogSlope
) ||
112 ::rtl::math::isNan( m_fLogIntercept
)))
114 fResult
= exp(m_fLogIntercept
+ x
* m_fLogSlope
);
120 uno::Sequence
< geometry::RealPoint2D
> SAL_CALL
ExponentialRegressionCurveCalculator::getCurveValues(
121 double min
, double max
, ::sal_Int32 nPointCount
,
122 const uno::Reference
< chart2::XScaling
>& xScalingX
,
123 const uno::Reference
< chart2::XScaling
>& xScalingY
,
124 sal_Bool bMaySkipPointsInCalculation
)
125 throw (lang::IllegalArgumentException
,
126 uno::RuntimeException
, std::exception
)
128 if( bMaySkipPointsInCalculation
&&
129 isLinearScaling( xScalingX
) &&
130 isLogarithmicScaling( xScalingY
))
133 uno::Sequence
< geometry::RealPoint2D
> aResult( 2 );
135 aResult
[0].Y
= this->getCurveValue( min
);
137 aResult
[1].Y
= this->getCurveValue( max
);
142 return RegressionCurveCalculator::getCurveValues( min
, max
, nPointCount
, xScalingX
, xScalingY
, bMaySkipPointsInCalculation
);
145 OUString
ExponentialRegressionCurveCalculator::ImplGetRepresentation(
146 const uno::Reference
< util::XNumberFormatter
>& xNumFormatter
,
147 ::sal_Int32 nNumberFormatKey
) const
149 double fIntercept
= exp(m_fLogIntercept
);
150 double fSlope
= exp(m_fLogSlope
);
151 bool bHasSlope
= !rtl::math::approxEqual( fSlope
, 1.0 );
152 bool bHasIntercept
= !rtl::math::approxEqual( fIntercept
, 1.0 );
154 OUStringBuffer
aBuf( "f(x) = ");
156 if ( fIntercept
== 0.0)
158 // underflow, a true zero is impossible
159 aBuf
.append( "exp( ");
160 aBuf
.append( getFormattedString( xNumFormatter
, nNumberFormatKey
, m_fLogIntercept
) );
161 aBuf
.append( (m_fLogSlope
< 0.0) ? " - " : " + ");
162 aBuf
.append( getFormattedString( xNumFormatter
, nNumberFormatKey
, fabs(m_fLogSlope
)) );
163 aBuf
.append( " x )");
169 aBuf
.append( getFormattedString( xNumFormatter
, nNumberFormatKey
, fIntercept
) );
170 aBuf
.append( " exp( ");
171 aBuf
.append( getFormattedString( xNumFormatter
, nNumberFormatKey
, m_fLogSlope
) );
172 aBuf
.append( " x )");
176 // show logarithmic output, if intercept and slope both are near one
177 // otherwise drop output of intercept, which is 1 here
178 aBuf
.append( " exp( ");
181 aBuf
.append( getFormattedString( xNumFormatter
, nNumberFormatKey
, m_fLogIntercept
) );
182 aBuf
.append( (m_fLogSlope
< 0.0) ? " - " : " + ");
183 aBuf
.append( getFormattedString( xNumFormatter
, nNumberFormatKey
, fabs(m_fLogSlope
)) );
187 aBuf
.append( getFormattedString( xNumFormatter
, nNumberFormatKey
, m_fLogSlope
) );
189 aBuf
.append( " x )");
193 return aBuf
.makeStringAndClear();
198 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */