1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_chart2.hxx" 30 #include "LinearRegressionCurveCalculator.hxx" 31 #include "macros.hxx" 32 #include "RegressionCalculationHelper.hxx" 33 34 #include <rtl/math.hxx> 35 #include <rtl/ustrbuf.hxx> 36 37 using namespace ::com::sun::star; 38 39 using ::rtl::OUString; 40 using ::rtl::OUStringBuffer; 41 42 namespace chart 43 { 44 45 LinearRegressionCurveCalculator::LinearRegressionCurveCalculator() : 46 m_fSlope( 0.0 ), 47 m_fIntercept( 0.0 ) 48 { 49 ::rtl::math::setNan( & m_fSlope ); 50 ::rtl::math::setNan( & m_fIntercept ); 51 } 52 53 LinearRegressionCurveCalculator::~LinearRegressionCurveCalculator() 54 {} 55 56 // ____ XRegressionCurveCalculator ____ 57 void SAL_CALL LinearRegressionCurveCalculator::recalculateRegression( 58 const uno::Sequence< double >& aXValues, 59 const uno::Sequence< double >& aYValues ) 60 throw (uno::RuntimeException) 61 { 62 RegressionCalculationHelper::tDoubleVectorPair aValues( 63 RegressionCalculationHelper::cleanup( 64 aXValues, aYValues, 65 RegressionCalculationHelper::isValid())); 66 67 const size_t nMax = aValues.first.size(); 68 if( nMax == 0 ) 69 { 70 ::rtl::math::setNan( & m_fSlope ); 71 ::rtl::math::setNan( & m_fIntercept ); 72 ::rtl::math::setNan( & m_fCorrelationCoeffitient ); 73 return; 74 } 75 76 const double fN = static_cast< double >( nMax ); 77 double fSumX = 0.0, fSumY = 0.0, fSumXSq = 0.0, fSumYSq = 0.0, fSumXY = 0.0; 78 for( size_t i = 0; i < nMax; ++i ) 79 { 80 fSumX += aValues.first[i]; 81 fSumY += aValues.second[i]; 82 fSumXSq += aValues.first[i] * aValues.first[i]; 83 fSumYSq += aValues.second[i] * aValues.second[i]; 84 fSumXY += aValues.first[i] * aValues.second[i]; 85 } 86 87 m_fSlope = (fN * fSumXY - fSumX * fSumY) / ( fN * fSumXSq - fSumX * fSumX ); 88 m_fIntercept = (fSumY - m_fSlope * fSumX) / fN; 89 90 m_fCorrelationCoeffitient = ( fN * fSumXY - fSumX * fSumY ) / 91 sqrt( ( fN * fSumXSq - fSumX * fSumX ) * 92 ( fN * fSumYSq - fSumY * fSumY ) ); 93 } 94 95 double SAL_CALL LinearRegressionCurveCalculator::getCurveValue( double x ) 96 throw (lang::IllegalArgumentException, 97 uno::RuntimeException) 98 { 99 double fResult; 100 ::rtl::math::setNan( & fResult ); 101 102 if( ! ( ::rtl::math::isNan( m_fSlope ) || 103 ::rtl::math::isNan( m_fIntercept ))) 104 { 105 fResult = m_fSlope * x + m_fIntercept; 106 } 107 108 return fResult; 109 } 110 111 uno::Sequence< geometry::RealPoint2D > SAL_CALL LinearRegressionCurveCalculator::getCurveValues( 112 double min, double max, ::sal_Int32 nPointCount, 113 const uno::Reference< chart2::XScaling >& xScalingX, 114 const uno::Reference< chart2::XScaling >& xScalingY, 115 ::sal_Bool bMaySkipPointsInCalculation ) 116 throw (lang::IllegalArgumentException, 117 uno::RuntimeException) 118 { 119 if( bMaySkipPointsInCalculation && 120 isLinearScaling( xScalingX ) && 121 isLinearScaling( xScalingY )) 122 { 123 // optimize result 124 uno::Sequence< geometry::RealPoint2D > aResult( 2 ); 125 aResult[0].X = min; 126 aResult[0].Y = this->getCurveValue( min ); 127 aResult[1].X = max; 128 aResult[1].Y = this->getCurveValue( max ); 129 130 return aResult; 131 } 132 return RegressionCurveCalculator::getCurveValues( min, max, nPointCount, xScalingX, xScalingY, bMaySkipPointsInCalculation ); 133 } 134 135 OUString LinearRegressionCurveCalculator::ImplGetRepresentation( 136 const uno::Reference< util::XNumberFormatter >& xNumFormatter, 137 ::sal_Int32 nNumberFormatKey ) const 138 { 139 OUStringBuffer aBuf( C2U( "f(x) = " )); 140 141 bool bHaveSlope = false; 142 143 if( m_fSlope != 0.0 ) 144 { 145 if( ::rtl::math::approxEqual( fabs( m_fSlope ), 1.0 )) 146 { 147 if( m_fSlope < 0 ) 148 aBuf.append( UC_MINUS_SIGN ); 149 } 150 else 151 aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, m_fSlope )); 152 aBuf.append( sal_Unicode( 'x' )); 153 bHaveSlope = true; 154 } 155 156 if( bHaveSlope ) 157 { 158 if( m_fIntercept < 0.0 ) 159 { 160 aBuf.append( UC_SPACE ); 161 aBuf.append( UC_MINUS_SIGN ); 162 aBuf.append( UC_SPACE ); 163 aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, fabs( m_fIntercept ))); 164 } 165 else if( m_fIntercept > 0.0 ) 166 { 167 aBuf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " + " )); 168 aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, m_fIntercept )); 169 } 170 } 171 else 172 { 173 aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, m_fIntercept )); 174 } 175 176 return aBuf.makeStringAndClear(); 177 } 178 179 } // namespace chart 180