/*
* Copyright (C) 2008,2009,2010 Thorsten Liebig (Thorsten.Liebig@gmx.de)
*
* This program 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 3 of the License, or
* (at your option) any later version.
*
* This program 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 .
*/
#include "ParameterObjects.h"
#include
#include
#include "tinyxml.h"
#include "CSFunctionParser.h"
#include "CSUseful.h"
bool ReadTerm(ParameterScalar &PS, TiXmlElement &elem, const char* attr, double val)
{
double dHelp;
PS.SetValue(val); // set default value
const char* chHelp=elem.Attribute(attr);
if (chHelp==NULL)
return false;
PS.SetValue(chHelp); // set string value if found
return true;
}
void WriteTerm(ParameterScalar &PS, TiXmlElement &elem, const char* attr, bool mode, bool scientific)
{
if (PS.GetMode() && mode)
elem.SetAttribute(attr,PS.GetString().c_str());
else
{
if (PS.GetValue()==NAN)
return;
if (scientific)
{
char doubleVal[50];
sprintf(doubleVal,"%e",PS.GetValue());
elem.SetAttribute(attr,doubleVal);
}
else
elem.SetDoubleAttribute(attr,PS.GetValue());
}
}
bool ReadVectorTerm(ParameterScalar PS[3], TiXmlElement &elem, std::string attr, double val, const char delimiter)
{
return ReadVectorTerm(PS, elem, attr.c_str(), val, delimiter);
}
bool ReadVectorTerm(ParameterScalar PS[3], TiXmlElement &elem, const char* attr, double val, const char delimiter)
{
//initialize with default value
for (int n=0;n<3;++n)
PS[n].SetValue(val);
const char* values = elem.Attribute(attr);
if (values==NULL)
return false;
std::vector val_list = SplitString2Vector(values, delimiter);
if (val_list.size()>3)
return false;
for (int n=0;n<3;++n)
PS[n].SetValue(val);
for (int n=0;n<(int)val_list.size();++n)
{
std::string sHelp=val_list.at(n);
bool ok;
double val = String2Double(sHelp, ok);
if (ok)
PS[n].SetValue(val);
else
PS[n].SetValue(sHelp.c_str());
}
return true;
}
void WriteVectorTerm(ParameterScalar PS[3], TiXmlElement &elem, std::string attr, bool mode, bool scientific, const char delimiter)
{
WriteVectorTerm(PS, elem, attr.c_str(), mode, scientific, delimiter);
}
void WriteVectorTerm(ParameterScalar PS[3], TiXmlElement &elem, const char* attr, bool mode, bool sci, const char delimiter)
{
std::stringstream ss;
if (sci)
ss << std::scientific;
for (int i=0;i<3;++i)
{
if (PS[i].GetMode() && mode)
ss << PS[i].GetString();
else if (PS[i].GetValue()==NAN)
ss << "NAN" << std::endl;
else
ss << PS[i].GetValue();
if (i<2)
ss << delimiter;
}
elem.SetAttribute(attr,ss.str().c_str());
}
Parameter::Parameter()
{
bModified=true;
dValue=0;
Type=Const;
bSweep=true;
// Set=NULL;
}
Parameter::Parameter(const std::string Paraname, double val)
{
sName=Paraname;
SetValue(val);
Type=Const;
bSweep=true;
// Set=NULL;
}
Parameter::~Parameter()
{
// if (Set!=NULL) Set->RemoveParameter(this);
}
void Parameter::PrintSelf(FILE* /*out*/)
{
fprintf(stderr," Parameter: %s Value: %f Type %d\n\n",sName.c_str(),dValue,Type);
}
bool Parameter::Write2XML(TiXmlNode& root)
{
TiXmlElement *elem=NULL;
if (Type==Const)
{
elem = new TiXmlElement("Parameter");
elem->SetAttribute("Type","Const");
}
else elem = root.ToElement();
if (elem==NULL) return false;
elem->SetAttribute("name",sName.c_str());
elem->SetAttribute("Sweep",bSweep);
elem->SetDoubleAttribute("value",dValue);
if (Type==Const) root.LinkEndChild(elem);
return true;
}
bool Parameter::ReadFromXML(TiXmlNode &root)
{
TiXmlElement *elem = root.ToElement();
if (elem==NULL) return false;
int iAtt=0;
if (elem->QueryIntAttribute("Sweep",&iAtt)!=TIXML_SUCCESS) bSweep=true;
else if (iAtt>0) bSweep=true;
else bSweep=false;
double val=0;
if (elem->QueryDoubleAttribute("value",&val)!=TIXML_SUCCESS) return false;
SetValue(val);
const char* att=elem->Attribute("name");
if (att==NULL) sName=std::string();
else sName=std::string(att);
return true;
}
Parameter* Parameter::GetParameterFromXML(TiXmlNode &/*root*/)
{
return NULL;
}
LinearParameter::LinearParameter() : Parameter()
{
Type=Linear;
dMin=dMax=dStep=0;
}
LinearParameter::LinearParameter(const std::string Paraname, double val, double min, double max, double step) : Parameter(Paraname,val)
{
//sName=string(Paraname);
if (maxType==Linear)
{
dMin=parameter->dMin;
dMax=parameter->dMax;
dStep=parameter->dStep;
}
else
{
Type=Linear;
dMin=dMax=dStep=0;
}
SetValue(dValue);
}
void LinearParameter::SetValue(double val)
{
if (val>dMax) val=dMax;
else if (valdMax) dValue=dValue-dStep;
}
bModified=true;
}
bool LinearParameter::IncreaseStep()
{
if (dValue+dStep>dMax) return false;
SetValue(dValue+dStep);
return true;
}
void LinearParameter::PrintSelf(FILE* /*out*/)
{
fprintf(stderr," Parameter: %s Value: %f\n from %f to %f; Stepsize: %f\n",sName.c_str(),dValue,dMin,dMax,dStep);
}
bool LinearParameter::Write2XML(TiXmlNode& root)
{
TiXmlElement para("Parameter");
para.SetAttribute("Type","Linear");
Parameter::Write2XML(para);
para.SetDoubleAttribute("min",dMin);
para.SetDoubleAttribute("max",dMax);
para.SetDoubleAttribute("step",dStep);
root.InsertEndChild(para);
return true;
}
bool LinearParameter::ReadFromXML(TiXmlNode &root)
{
TiXmlElement *elem = root.ToElement();
if (elem==NULL) return false;
if (elem->QueryDoubleAttribute("min",&dMin)!=TIXML_SUCCESS) return false;
if (elem->QueryDoubleAttribute("max",&dMax)!=TIXML_SUCCESS) return false;
if (elem->QueryDoubleAttribute("step",&dStep)!=TIXML_SUCCESS) return false;
if (Parameter::ReadFromXML(root)==false) return false;
// const char* att=elem->Attribute("name");
// if (att==NULL) return false;
// sName=string(att);
// if (elem->QueryDoubleAttribute("value",&dValue)!=TIXML_SUCCESS) return false;
return true;
}
ParameterSet::ParameterSet(void)
{
bModified=true;
}
ParameterSet::~ParameterSet(void)
{
clear();
}
size_t ParameterSet::LinkParameter(Parameter* newPara)
{
vParameter.push_back(newPara);
// newPara->ParameterSet(this);
return vParameter.size();
}
size_t ParameterSet::DeleteParameter(size_t index)
{
if (index>=vParameter.size()) return vParameter.size();
std::vector::iterator pIter=vParameter.begin();
vParameter.erase(pIter+index);
return vParameter.size();
}
size_t ParameterSet::DeleteParameter(Parameter* para)
{
std::vector::iterator pIter=vParameter.begin();
while (pIter!=vParameter.end())
{
if (*pIter==para)
{
vParameter.erase(pIter);
return vParameter.size();
}
++pIter;
}
return vParameter.size();
}
void ParameterSet::clear()
{
for (size_t i=0; iGetModified()==true) return true;
return false;
}
void ParameterSet::SetModified(bool mod)
{
if (mod==true)
{
bModified=true;
return;
}
bModified=false;
for (size_t i=0; iSetModified(false);
}
double* ParameterSet::GetValueArray(double *array)
{
if (array==NULL) return array;
for (size_t i=0; iGetValue();
}
return array;
}
int ParameterSet::CountSweepSteps(int SweepMode)
{
int count=0;
switch (SweepMode)
{
case 1:
for (size_t i=0; iGetSweep())
{
if (count==0) count=vParameter.at(i)->CountSteps();
else count*=vParameter.at(i)->CountSteps();
}
return count;
break;
case 2:
for (size_t i=0; iGetSweep()) count+=vParameter.at(i)->CountSteps();
return count;
break;
}
return 0;
}
void ParameterSet::InitSweep()
{
for (size_t i=0; iGetSweep())
{
vParameter.at(i)->Save();
vParameter.at(i)->InitSweep();
}
SweepPara=0;
}
void ParameterSet::EndSweep()
{
for (size_t i=0; iGetSweep())
{
vParameter.at(i)->Restore();
}
}
bool ParameterSet::NextSweepPos(int SweepMode)
{
switch (SweepMode)
{
case 1:
{
int level=vParameter.size()-1;
while (level>=0)
{
if (vParameter.at(level)->GetSweep())
{
if (vParameter.at(level)->IncreaseStep()) return true;
else
{
vParameter.at(level)->InitSweep();
--level;
}
}
else --level;
}
return false;
break;
}
case 2:
if ((unsigned int)SweepPara>=vParameter.size()) return false;
if (vParameter.at(SweepPara)->GetSweep())
{
if (vParameter.at(SweepPara)->IncreaseStep()) return true;
else ++SweepPara;
return NextSweepPos(SweepMode);
}
else
{
++SweepPara;
return NextSweepPos(SweepMode);
}
break;
}
return false;
}
const std::string ParameterSet::GetParameterString(const std::string spacer)
{
std::string ParameterString;
for (size_t i=0; i0) ParameterString+=spacer;
ParameterString+=vParameter.at(i)->GetName();
}
return ParameterString;
}
const std::string ParameterSet::GetParameterValueString(const std::string spacer, bool ValuesOnly)
{
std::string ParameterValueString;
for (size_t i=0; i0) ParameterValueString+=spacer;
if (!ValuesOnly)
{
ParameterValueString+=vParameter.at(i)->GetName();
ParameterValueString+="=";
}
std::ostringstream os;
os << vParameter.at(i)->GetValue();
ParameterValueString+=os.str();
}
return ParameterValueString.c_str();
}
void ParameterSet::PrintSelf(FILE* out)
{
fprintf(out," Parameter-Set Printout, Qty of Parameter: %d\n",(int)vParameter.size());
for (size_t i=0; iPrintSelf(out);
}
}
bool ParameterSet::Write2XML(TiXmlNode& root)
{
TiXmlElement pSet("ParameterSet");
//pSet.SetAttribute("QtyParameter",(int)vParameter.size());
for (size_t i=0;iWrite2XML(pSet);
root.InsertEndChild(pSet);
return true;
}
bool ParameterSet::ReadFromXML(TiXmlNode &root)
{
TiXmlNode* paraNode = root.FirstChild("Parameter");
while (paraNode!=NULL)
{
TiXmlElement *elem = paraNode->ToElement();
if (elem!=NULL)
{
const char* att=elem->Attribute("Type");
if (att!=NULL)
{
Parameter* newPara=NULL;
if (strcmp(att,"Const")==0) newPara = new Parameter();
else if (strcmp(att,"Linear")==0) newPara = new LinearParameter();
if (newPara!=NULL)
{
if (newPara->ReadFromXML(*elem)==true) this->InsertParameter(newPara);
}
}
}
paraNode=paraNode->NextSiblingElement("Parameter");
};
return true;
}
ParameterScalar::ParameterScalar()
{
clParaSet=NULL;
bModified=true;
ParameterMode=false;
sValue.clear();
dValue=0;
}
ParameterScalar::ParameterScalar(ParameterSet* ParaSet, const std::string value)
{
SetParameterSet(ParaSet);
SetValue(value);
}
ParameterScalar::ParameterScalar(ParameterSet* ParaSet, double value)
{
SetParameterSet(ParaSet);
bModified=true;
SetValue(value);
}
ParameterScalar::ParameterScalar(ParameterScalar* ps)
{
Copy(ps);
}
ParameterScalar::~ParameterScalar()
{
}
void ParameterScalar::SetParameterSet(ParameterSet *paraSet)
{
clParaSet=paraSet;
}
int ParameterScalar::SetValue(const std::string value, bool Eval)
{
if (value.empty()) return -1;
//check if string is only a plain double
char *pEnd;
double val = strtod(value.c_str(),&pEnd);
if (*pEnd == 0)
SetValue(val);
ParameterMode=true;
bModified=true;
sValue=value;
if (Eval) return Evaluate();
return 0;
}
void ParameterScalar::SetValue(double value)
{
ParameterMode=false;
dValue=value;
sValue.clear();
}
double ParameterScalar::GetValue() const
{
return dValue;
}
const std::string ParameterScalar::GetValueString() const
{
if (ParameterMode)
return sValue;
std::stringstream numString;
numString << dValue;
return numString.str();
}
int ParameterScalar::Evaluate()
{
if (ParameterMode==false) return 0;
if (clParaSet!=NULL)
bModified = bModified || clParaSet->GetModified();
if (bModified==false)
return 0;
CSFunctionParser fParse;
dValue=0;
if (clParaSet!=NULL)
fParse.Parse(sValue,clParaSet->GetParameterString());
else
fParse.Parse(sValue,"");
if (fParse.GetParseErrorType()!=FunctionParser::FP_NO_ERROR) return fParse.GetParseErrorType()+100;
bModified=false;
if (clParaSet!=NULL)
{
double *vars = new double[clParaSet->GetQtyParameter()];
vars=clParaSet->GetValueArray(vars);
dValue=fParse.Eval(vars);
delete[] vars;vars=NULL;
}
else
dValue=fParse.Eval(NULL);
return fParse.EvalError();
}
double ParameterScalar::GetEvaluated(double* ParaValues, int &EC)
{
if (ParameterMode==false) return dValue;
CSFunctionParser fParse;
fParse.Parse(sValue,clParaSet->GetParameterString());
if (fParse.GetParseErrorType()!=FunctionParser::FP_NO_ERROR)
{
EC = fParse.GetParseErrorType()+100;
return 0;
}
double dvalue = fParse.Eval(ParaValues);
EC = fParse.EvalError();
return dvalue;
}
void ParameterScalar::Copy(ParameterScalar* ps)
{
SetParameterSet(ps->clParaSet);
bModified=ps->bModified;
ParameterMode=ps->ParameterMode;
sValue=std::string(ps->sValue);
dValue=ps->dValue;
}
std::string PSErrorCode2Msg(int code)
{
std::string msg;
PSErrorCode2Msg(code,&msg);
return msg;
}
void PSErrorCode2Msg(int code, std::string *msg)
{
switch (code)
{
case -1:
msg->append("Internal Error");
break;
case 0:
msg->append("No Error");
break;
case 1:
msg->append("Division by zero");
break;
case 2:
msg->append("sqrt error (sqrt of a negative value)");
break;
case 3:
msg->append("log error (logarithm of a negative value)");
break;
case 4:
msg->append("trigonometric error (asin or acos of illegal value)");
break;
case 5:
msg->append("Maximum recursion level reached");
break;
case 100:
msg->append("Syntax error (check Parameter)");
break;
case 101:
msg->append("Mismatched parenthesis");
break;
case 102:
msg->append("Missing \')\'");
break;
case 103:
msg->append("Empty parentheses");
break;
case 104:
msg->append("Syntax error: Operator expected");
break;
case 105:
msg->append("Not enough memory");
break;
case 106:
msg->append("An unexpected error occurred");
break;
case 107:
msg->append("Syntax error in parameters");
break;
case 108:
msg->append("Illegal number of parameters to function");
break;
case 109:
msg->append("Syntax error: Premature end of string");
break;
case 110:
msg->append("Syntax error: Expecting ( after function");
break;
};
}