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 "LogarithmicRegressionCurveCalculator.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 LogarithmicRegressionCurveCalculator::LogarithmicRegressionCurveCalculator() : 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 LogarithmicRegressionCurveCalculator::~LogarithmicRegressionCurveCalculator() 54 {} 55 56 // ____ XRegressionCurve ____ 57 void SAL_CALL LogarithmicRegressionCurveCalculator::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::isValidAndXPositive())); 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 += 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 = 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 104 double SAL_CALL LogarithmicRegressionCurveCalculator::getCurveValue( double x ) 105 throw (lang::IllegalArgumentException, 106 uno::RuntimeException) 107 { 108 double fResult; 109 ::rtl::math::setNan( & fResult ); 110 111 if( ! ( ::rtl::math::isNan( m_fSlope ) || 112 ::rtl::math::isNan( m_fIntercept ))) 113 { 114 fResult = m_fSlope * log( x ) + m_fIntercept; 115 } 116 117 return fResult; 118 } 119 120 uno::Sequence< geometry::RealPoint2D > SAL_CALL LogarithmicRegressionCurveCalculator::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) 127 { 128 if( bMaySkipPointsInCalculation && 129 isLogarithmicScaling( xScalingX ) && 130 isLinearScaling( xScalingY )) 131 { 132 // optimize result 133 uno::Sequence< geometry::RealPoint2D > aResult( 2 ); 134 aResult[0].X = min; 135 aResult[0].Y = this->getCurveValue( min ); 136 aResult[1].X = max; 137 aResult[1].Y = this->getCurveValue( max ); 138 139 return aResult; 140 } 141 return RegressionCurveCalculator::getCurveValues( min, max, nPointCount, xScalingX, xScalingY, bMaySkipPointsInCalculation ); 142 } 143 144 OUString LogarithmicRegressionCurveCalculator::ImplGetRepresentation( 145 const uno::Reference< util::XNumberFormatter >& xNumFormatter, 146 ::sal_Int32 nNumberFormatKey ) const 147 { 148 OUStringBuffer aBuf( C2U( "f(x) = " )); 149 150 bool bHaveSlope = false; 151 152 if( m_fSlope != 0.0 ) 153 { 154 if( ::rtl::math::approxEqual( fabs( m_fSlope ), 1.0 )) 155 { 156 if( m_fSlope < 0 ) 157 aBuf.append( UC_MINUS_SIGN ); 158 } 159 else 160 { 161 aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, m_fSlope )); 162 aBuf.append( UC_SPACE ); 163 } 164 aBuf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "ln(x)" )); 165 bHaveSlope = true; 166 } 167 168 if( bHaveSlope ) 169 { 170 if( m_fIntercept < 0.0 ) 171 { 172 aBuf.append( UC_SPACE ); 173 aBuf.append( UC_MINUS_SIGN ); 174 aBuf.append( UC_SPACE ); 175 aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, fabs( m_fIntercept ))); 176 } 177 else if( m_fIntercept > 0.0 ) 178 { 179 aBuf.appendAscii( RTL_CONSTASCII_STRINGPARAM( " + " )); 180 aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, m_fIntercept )); 181 } 182 } 183 else 184 { 185 aBuf.append( getFormattedString( xNumFormatter, nNumberFormatKey, m_fIntercept )); 186 } 187 188 return aBuf.makeStringAndClear(); 189 } 190 191 } // namespace chart 192