///////////////////////////////////////////////////////////
// //
// 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