/////////////////////////////////////////////////////////// // // // SAGA // // // // System for Automated Geoscientific Analyses // // // // Application Programming Interface // // // // Library: SAGA_API // // // //-------------------------------------------------------// // // // mat_trend.cpp // // // // Copyright (C) 2006 by // // Olaf Conrad // // // //-------------------------------------------------------// // // // This file is part of 'SAGA - System for Automated // // Geoscientific Analyses'. // // // // This library is free software; you can redistribute // // it and/or modify it under the terms of the GNU Lesser // // General Public License as published by the Free // // Software Foundation, either version 2.1 of the // // License, or (at your option) any later version. // // // // This library is distributed in the hope that it will // // be useful, but WITHOUT ANY WARRANTY; without even the // // implied warranty of MERCHANTABILITY or FITNESS FOR A // // PARTICULAR PURPOSE. See the GNU Lesser General Public // // License for more details. // // // // You should have received a copy of the GNU Lesser // // General Public License along with this program; if // // not, see . // // // //-------------------------------------------------------// // // // contact: Olaf Conrad // // Institute of Geography // // University of Goettingen // // Goldschmidtstr. 5 // // 37077 Goettingen // // Germany // // // // e-mail: oconrad@saga-gis.org // // // //-------------------------------------------------------// // // // Based on the LMFit.h/cpp, Fit.h/cpp source codes of // // A. Ringeler (see 'table_calculus' sub project). // // // /////////////////////////////////////////////////////////// //--------------------------------------------------------- #include "mat_tools.h" /////////////////////////////////////////////////////////// // // // // // // /////////////////////////////////////////////////////////// //--------------------------------------------------------- #define SWAP(a, b) { double temp = (a); (a) = (b); (b) = temp; } //--------------------------------------------------------- #define EPSILON 0.001 /////////////////////////////////////////////////////////// // // // // // // /////////////////////////////////////////////////////////// //--------------------------------------------------------- bool CSG_Trend::CParams::Create(const CSG_String &Variables) { if( m_Variables.Length() != Variables.Length() ) { m_Variables = Variables; m_A .Create(Get_Count()); m_Atry .Create(Get_Count()); m_Beta .Create(Get_Count()); m_dA .Create(Get_Count()); m_dA2 .Create(Get_Count()); m_Alpha.Create(Get_Count(), Get_Count()); m_Covar.Create(Get_Count(), Get_Count()); } m_A.Assign(1.); return( true ); } //--------------------------------------------------------- bool CSG_Trend::CParams::Destroy(void) { m_Variables.Clear(); m_A .Destroy(); m_Atry .Destroy(); m_Beta .Destroy(); m_dA .Destroy(); m_dA2 .Destroy(); m_Alpha.Destroy(); m_Covar.Destroy(); m_Alpha.Destroy(); m_Covar.Destroy(); return( true ); } /////////////////////////////////////////////////////////// // // /////////////////////////////////////////////////////////// //--------------------------------------------------------- CSG_Trend::CSG_Trend(void) { m_Lambda_Max = 10000; m_Iter_Max = 1000; m_bOkay = false; // Set_Formula("a + b * x"); } /////////////////////////////////////////////////////////// // // /////////////////////////////////////////////////////////// //--------------------------------------------------------- bool CSG_Trend::Set_Formula(const CSG_String &Formula) { m_bOkay = false; m_Params.Destroy(); if( m_Formula.Set_Formula(Formula) ) { CSG_String Params, Used(m_Formula.Get_Used_Variables()); for(size_t i=0; i= 'a' && Used[i] <= 'z' && Used[i] != 'x' ) { Params += Used[i]; } } return( m_Params.Create(Params) ); } return( false ); } //--------------------------------------------------------- bool CSG_Trend::Init_Parameter(const SG_Char &Variable, double Value) { for(size_t i=0; i 0 ) { m_Iter_Max = Iterations; return( true ); } return( false ); } //--------------------------------------------------------- bool CSG_Trend::Set_Max_Lambda(double Lambda) { if( Lambda > 0. ) { m_Lambda_Max = Lambda; return( true ); } return( false ); } /////////////////////////////////////////////////////////// // // /////////////////////////////////////////////////////////// //--------------------------------------------------------- bool CSG_Trend::Get_Trend(double *x, double *y, int n, const CSG_String &Formula) { Set_Data(x, y, n, false); return( !Formula.is_Empty() && !Set_Formula(Formula) ? false : Get_Trend() ); } //--------------------------------------------------------- bool CSG_Trend::Get_Trend(const CSG_Points &Data, const CSG_String &Formula) { Set_Data(Data, false); return( !Formula.is_Empty() && !Set_Formula(Formula) ? false : Get_Trend() ); } //--------------------------------------------------------- bool CSG_Trend::Get_Trend(const CSG_String &Formula) { return( !Formula.is_Empty() && !Set_Formula(Formula) ? false : Get_Trend() ); } //--------------------------------------------------------- bool CSG_Trend::Get_Trend(void) { CSG_String sError; if( m_Formula.Get_Error(sError) ) { return( false ); } if( Get_Data_Count() <= 1 ) { return( false ); } //----------------------------------------------------- m_bOkay = true; int i; if( m_Params.Get_Count() > 0 ) { m_Lambda = 0.001; _Get_mrqcof(m_Params.m_A, m_Params.m_Alpha, m_Params.m_Beta); m_ChiSqr_o = m_ChiSqr; for(i=0; i 0. ? y_t / y_o : 0.; return( m_bOkay ); } /////////////////////////////////////////////////////////// // // /////////////////////////////////////////////////////////// //--------------------------------------------------------- CSG_String CSG_Trend::Get_Error(void) { CSG_String Message; if( !m_bOkay ) { if( !m_Formula.Get_Error(Message) ) { Message.Printf(_TL("Error in Trend Calculation")); } } return( Message ); } //--------------------------------------------------------- CSG_String CSG_Trend::Get_Formula(int Type) { CSG_String s; switch( Type ) { case SG_TREND_STRING_Formula: default: s += m_Formula.Get_Formula(); break; case SG_TREND_STRING_Function: s += m_Formula.Get_Formula(); s += "\n"; if( m_Params.Get_Count() > 0 ) { s += "\n"; for(int i=0; i 0 && m_bOkay ) { s += "\n"; for(int i=0; i 0 && m_bOkay ) { s += "\n"; for(int i=0; i 0 && m_bOkay ) { for(int i=0; i0; i--) { for(j=0; j= big ) { big = fabs(m_Params.m_Covar[j][k]); iRow = j; iCol = k; } } else if( ipiv[k] > 1 ) { return( false ); // singular matrix... } } } } if( iCol < 0 || iRow < 0 ) { return( false ); // singular matrix... } //------------------------------------------------- ipiv[iCol]++; if( iRow != iCol ) { for(j=0; j=0; i--) { if( indxr[i] != indxc[i] ) { for(j=0; j 0 ) { m_Order = Order; return( true ); } return( false ); } //--------------------------------------------------------- bool CSG_Trend_Polynom::Clr_Data(void) { m_a.Destroy(); m_y.Destroy(); m_x.Destroy(); return( true ); } //--------------------------------------------------------- bool CSG_Trend_Polynom::Set_Data(double *x, double *y, int n, bool bAdd) { if( !bAdd ) { Clr_Data(); } m_x.Add_Rows(n); m_y.Add_Rows(n); for(int i=0, j=m_x.Get_N()-1; i 0 ) { double y = m_a(0); double d = 1.; for(int i=1; i