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 "PotentialRegressionCurveCalculator.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 PotentialRegressionCurveCalculator::PotentialRegressionCurveCalculator() : 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 PotentialRegressionCurveCalculator::~PotentialRegressionCurveCalculator() 54 {} 55 56 // ____ XRegressionCurveCalculator ____ 57 void SAL_CALL PotentialRegressionCurveCalculator::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::isValidAndBothPositive())); 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 double fAverageX = 0.0, fAverageY = 0.0; 77 size_t i = 0; 78 for( i = 0; i < nMax; ++i ) 79 { 80 fAverageX += log( aValues.first[i] ); 81 fAverageY += log( aValues.second[i] ); 82 } 83 84 const double fN = static_cast< double >( nMax ); 85 fAverageX /= fN; 86 fAverageY /= fN; 87 88 double fQx = 0.0, fQy = 0.0, fQxy = 0.0; 89 for( i = 0; i < nMax; ++i ) 90 { 91 double fDeltaX = log( aValues.first[i] ) - fAverageX; 92 double fDeltaY = log( aValues.second[i] ) - fAverageY; 93 94 fQx += fDeltaX * fDeltaX; 95 fQy += fDeltaY * fDeltaY; 96 fQxy += fDeltaX * fDeltaY; 97 } 98 99 m_fSlope = fQxy / fQx; 100 m_fIntercept = fAverageY - m_fSlope * fAverageX; 101 m_fCorrelationCoeffitient = fQxy / sqrt( fQx * fQy ); 102 103 m_fIntercept = exp( m_fIntercept ); 104 } 105 106 double SAL_CALL PotentialRegressionCurveCalculator::getCurveValue( double x ) 107 throw (lang::IllegalArgumentException, 108 uno::RuntimeException) 109 { 110 double fResult; 111 ::rtl::math::setNan( & fResult ); 112 113 if( ! ( ::rtl::math::isNan( m_fSlope ) || 114 ::rtl::math::isNan( m_fIntercept ))) 115 { 116 fResult = m_fIntercept * pow( x, m_fSlope ); 117 } 118 119 return fResult; 120 } 121 122 uno::Sequence< geometry::RealPoint2D > SAL_CALL PotentialRegressionCurveCalculator::getCurveValues( 123 double min, double max, ::sal_Int32 nPointCount, 124 const uno::Reference< chart2::XScaling >& xScalingX, 125 const uno::Reference< chart2::XScaling >& xScalingY, 126 ::sal_Bool bMaySkipPointsInCalculation ) 127 throw (lang::IllegalArgumentException, 128 uno::RuntimeException) 129 { 130 if( bMaySkipPointsInCalculation && 131 isLogarithmicScaling( xScalingX ) && 132 isLogarithmicScaling( xScalingY )) 133 { 134 // optimize result 135 uno::Sequence< geometry::RealPoint2D > aResult( 2 ); 136 aResult[0].X = min; 137 aResult[0].Y = this->getCurveValue( min ); 138 aResult[1].X = max; 139 aResult[1].Y = this->getCurveValue( max ); 140 141 return aResult; 142 } 143 return RegressionCurveCalculator::getCurveValues( min, max, nPointCount, xScalingX, xScalingY, bMaySkipPointsInCalculation ); 144 } 145 146 OUString PotentialRegressionCurveCalculator::ImplGetRepresentation( 147 const uno::Reference< util::XNumberFormatter >& xNumFormatter, 148 ::sal_Int32 nNumberFormatKey ) const 149 { 150 OUStringBuffer aBuf( C2U( "f(x) = " )); 151 152 if( m_fIntercept == 0.0 ) 153 { 154 aBuf.append( sal_Unicode( '0' )); 155 } 156 else if( m_fSlope == 0.0 ) 157 { 158 aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, m_fIntercept )); 159 } 160 else 161 { 162 if( ! rtl::math::approxEqual( m_fIntercept, 1.0 ) ) 163 { 164 aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, m_fIntercept )); 165 aBuf.append( sal_Unicode( ' ' )); 166 } 167 if( m_fSlope != 0.0 ) 168 { 169 aBuf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "x^" )); 170 aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, m_fSlope )); 171 } 172 } 173 174 return aBuf.makeStringAndClear(); 175 } 176 177 } // namespace chart 178