xref: /trunk/main/chart2/source/tools/PotentialRegressionCurveCalculator.cxx (revision 91144cd0085a7583d2099b982122deb2184ab956)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_charttools.hxx"
26 #include "PotentialRegressionCurveCalculator.hxx"
27 #include "macros.hxx"
28 #include "RegressionCalculationHelper.hxx"
29 
30 #include <rtl/math.hxx>
31 #include <rtl/ustrbuf.hxx>
32 
33 using namespace ::com::sun::star;
34 
35 using ::rtl::OUString;
36 using ::rtl::OUStringBuffer;
37 
38 namespace chart
39 {
40 
PotentialRegressionCurveCalculator()41 PotentialRegressionCurveCalculator::PotentialRegressionCurveCalculator() :
42         m_fSlope( 0.0 ),
43         m_fIntercept( 0.0 )
44 {
45     ::rtl::math::setNan( & m_fSlope );
46     ::rtl::math::setNan( & m_fIntercept );
47 }
48 
~PotentialRegressionCurveCalculator()49 PotentialRegressionCurveCalculator::~PotentialRegressionCurveCalculator()
50 {}
51 
52 // ____ XRegressionCurveCalculator ____
recalculateRegression(const uno::Sequence<double> & aXValues,const uno::Sequence<double> & aYValues)53 void SAL_CALL PotentialRegressionCurveCalculator::recalculateRegression(
54     const uno::Sequence< double >& aXValues,
55     const uno::Sequence< double >& aYValues )
56 {
57     RegressionCalculationHelper::tDoubleVectorPair aValues(
58         RegressionCalculationHelper::cleanup(
59             aXValues, aYValues,
60             RegressionCalculationHelper::isValidAndBothPositive()));
61 
62     const size_t nMax = aValues.first.size();
63     if( nMax == 0 )
64     {
65         ::rtl::math::setNan( & m_fSlope );
66         ::rtl::math::setNan( & m_fIntercept );
67         ::rtl::math::setNan( & m_fCorrelationCoeffitient );
68         return;
69     }
70 
71     double fAverageX = 0.0, fAverageY = 0.0;
72     size_t i = 0;
73     for( i = 0; i < nMax; ++i )
74     {
75         fAverageX += log( aValues.first[i] );
76         fAverageY += log( aValues.second[i] );
77     }
78 
79     const double fN = static_cast< double >( nMax );
80     fAverageX /= fN;
81     fAverageY /= fN;
82 
83     double fQx = 0.0, fQy = 0.0, fQxy = 0.0;
84     for( i = 0; i < nMax; ++i )
85     {
86         double fDeltaX = log( aValues.first[i] ) - fAverageX;
87         double fDeltaY = log( aValues.second[i] ) - fAverageY;
88 
89         fQx  += fDeltaX * fDeltaX;
90         fQy  += fDeltaY * fDeltaY;
91         fQxy += fDeltaX * fDeltaY;
92     }
93 
94     m_fSlope = fQxy / fQx;
95     m_fIntercept = fAverageY - m_fSlope * fAverageX;
96     m_fCorrelationCoeffitient = fQxy / sqrt( fQx * fQy );
97 
98     m_fIntercept = exp( m_fIntercept );
99 }
100 
getCurveValue(double x)101 double SAL_CALL PotentialRegressionCurveCalculator::getCurveValue( double x )
102 {
103     double fResult;
104     ::rtl::math::setNan( & fResult );
105 
106     if( ! ( ::rtl::math::isNan( m_fSlope ) ||
107             ::rtl::math::isNan( m_fIntercept )))
108     {
109         fResult = m_fIntercept * pow( x, m_fSlope );
110     }
111 
112     return fResult;
113 }
114 
getCurveValues(double min,double max,::sal_Int32 nPointCount,const uno::Reference<chart2::XScaling> & xScalingX,const uno::Reference<chart2::XScaling> & xScalingY,::sal_Bool bMaySkipPointsInCalculation)115 uno::Sequence< geometry::RealPoint2D > SAL_CALL PotentialRegressionCurveCalculator::getCurveValues(
116     double min, double max, ::sal_Int32 nPointCount,
117     const uno::Reference< chart2::XScaling >& xScalingX,
118     const uno::Reference< chart2::XScaling >& xScalingY,
119     ::sal_Bool bMaySkipPointsInCalculation )
120 {
121     if( bMaySkipPointsInCalculation &&
122         isLogarithmicScaling( xScalingX ) &&
123         isLogarithmicScaling( xScalingY ))
124     {
125         // optimize result
126         uno::Sequence< geometry::RealPoint2D > aResult( 2 );
127         aResult[0].X = min;
128         aResult[0].Y = this->getCurveValue( min );
129         aResult[1].X = max;
130         aResult[1].Y = this->getCurveValue( max );
131 
132         return aResult;
133     }
134     return RegressionCurveCalculator::getCurveValues( min, max, nPointCount, xScalingX, xScalingY, bMaySkipPointsInCalculation );
135 }
136 
ImplGetRepresentation(const uno::Reference<util::XNumberFormatter> & xNumFormatter,::sal_Int32 nNumberFormatKey) const137 OUString PotentialRegressionCurveCalculator::ImplGetRepresentation(
138     const uno::Reference< util::XNumberFormatter >& xNumFormatter,
139     ::sal_Int32 nNumberFormatKey ) const
140 {
141     OUStringBuffer aBuf( C2U( "f(x) = " ));
142 
143     if( m_fIntercept == 0.0 )
144     {
145         aBuf.append( sal_Unicode( '0' ));
146     }
147     else if( m_fSlope == 0.0 )
148     {
149         aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, m_fIntercept ));
150     }
151     else
152     {
153         if( ! rtl::math::approxEqual( m_fIntercept, 1.0 ) )
154         {
155             aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, m_fIntercept ));
156             aBuf.append( sal_Unicode( ' ' ));
157         }
158         if( m_fSlope != 0.0 )
159         {
160             aBuf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "x^" ));
161             aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, m_fSlope ));
162         }
163     }
164 
165     return aBuf.makeStringAndClear();
166 }
167 
168 } //  namespace chart
169