aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/default_data_set.hpp47
-rw-r--r--core/fitter.hpp1043
-rw-r--r--core/freeze_param.hpp204
-rw-r--r--core/opt_exception.hpp106
-rw-r--r--core/opt_traits.hpp64
-rw-r--r--core/optimizer.hpp289
-rw-r--r--guide.pdfbin0 -> 27213 bytes
-rw-r--r--history.log239
-rw-r--r--interface/makefile13
-rw-r--r--interface/opt.cc181
-rw-r--r--interface/opt.h29
-rw-r--r--makefile67
-rw-r--r--methods/gsl_simplex/gsl_simplex.hpp199
-rw-r--r--methods/powell/bas_util.hpp63
-rw-r--r--methods/powell/brent.hpp110
-rw-r--r--methods/powell/linmin.hpp102
-rw-r--r--methods/powell/mnbrak.hpp81
-rw-r--r--methods/powell/powell_method.hpp251
-rw-r--r--misc/bootstrap.hpp132
-rw-r--r--misc/data_loaders.hpp180
-rw-r--r--models/add_model.hpp169
-rw-r--r--models/beta1d.hpp49
-rw-r--r--models/beta2d.hpp60
-rw-r--r--models/beta2d2.hpp73
-rw-r--r--models/bl1d.hpp56
-rw-r--r--models/bpl1d.hpp56
-rw-r--r--models/bremss.hpp44
-rw-r--r--models/constant.hpp42
-rw-r--r--models/dbeta1d.hpp62
-rw-r--r--models/dbeta2d.hpp92
-rw-r--r--models/dbeta2d2.hpp100
-rw-r--r--models/dbeta2d3.hpp91
-rw-r--r--models/dl_model.hpp178
-rw-r--r--models/dlmodel_template.c36
-rw-r--r--models/func_model.hpp57
-rw-r--r--models/gauss1d.hpp47
-rw-r--r--models/lin1d.hpp42
-rw-r--r--models/models.cc176
-rw-r--r--models/models.hpp36
-rw-r--r--models/mul_model.hpp171
-rw-r--r--models/nbeta1d.hpp49
-rw-r--r--models/nfw1d.hpp45
-rw-r--r--models/pl1d.hpp43
-rw-r--r--models/poly1d.hpp67
-rw-r--r--models/pow_model.hpp120
-rw-r--r--models/strmodel1d.cc82
-rw-r--r--models/strmodel1d.hpp39
-rw-r--r--models/vecn.hpp62
-rw-r--r--muparser/makefile16
-rw-r--r--muparser/muParser.cpp259
-rw-r--r--muparser/muParser.h104
-rw-r--r--muparser/muParserBase.cpp1364
-rw-r--r--muparser/muParserBase.h324
-rw-r--r--muparser/muParserBytecode.cpp396
-rw-r--r--muparser/muParserBytecode.h148
-rw-r--r--muparser/muParserCallback.cpp198
-rw-r--r--muparser/muParserCallback.h94
-rw-r--r--muparser/muParserDLL.cpp657
-rw-r--r--muparser/muParserDLL.h123
-rw-r--r--muparser/muParserDef.h239
-rw-r--r--muparser/muParserError.cpp300
-rw-r--r--muparser/muParserError.h160
-rw-r--r--muparser/muParserFixes.h196
-rw-r--r--muparser/muParserInt.cpp264
-rw-r--r--muparser/muParserInt.h93
-rw-r--r--muparser/muParserStack.h120
-rw-r--r--muparser/muParserTest.cpp1125
-rw-r--r--muparser/muParserTest.h176
-rw-r--r--muparser/muParserToken.h464
-rw-r--r--muparser/muParserTokenReader.cpp822
-rw-r--r--muparser/muParserTokenReader.h156
-rwxr-xr-xrun_me5
-rwxr-xr-xsamples/abin0 -> 9817 bytes
-rw-r--r--samples/a.cc36
-rw-r--r--samples/a.dat4
-rw-r--r--samples/bpl.dat901
-rw-r--r--samples/gauss.dat901
-rw-r--r--samples/linear.dat4
-rw-r--r--samples/powerlaw.dat901
-rw-r--r--statistics/chisq.hpp163
-rw-r--r--statistics/cstat.hpp66
-rw-r--r--test.cc142
-rw-r--r--test1.cc149
-rw-r--r--utilities/opt_types.hpp29
-rw-r--r--version_ctrl.cc18
85 files changed, 16661 insertions, 0 deletions
diff --git a/core/default_data_set.hpp b/core/default_data_set.hpp
new file mode 100644
index 0000000..be06c04
--- /dev/null
+++ b/core/default_data_set.hpp
@@ -0,0 +1,47 @@
+#ifndef DEFAULT_DATA_SET
+#define DEFAULT_DATA_SET
+#include "fitter.hpp"
+#include <vector>
+
+
+namespace opt_utilities
+{
+
+template <typename Ty,typename Tx>
+class default_data_set
+ :public data_set<Ty,Tx>
+{
+private:
+ std::vector<data<Ty,Tx> > data_vec;
+
+ data_set<Ty,Tx>* do_clone()const
+ {
+ return new default_data_set<Ty,Tx>(*this);
+ }
+
+
+ const data<Ty,Tx>& do_get_data(int i)const
+ {
+ return data_vec.at(i);
+ }
+
+ int do_size()const
+ {
+ return data_vec.size();
+ }
+
+ void do_push_back(const data<Ty,Tx>& d)
+ {
+ data_vec.push_back(d);
+ }
+
+ void do_clear()
+ {
+ data_vec.clear();
+ }
+
+};
+}
+
+#endif
+//EOF
diff --git a/core/fitter.hpp b/core/fitter.hpp
new file mode 100644
index 0000000..ed90a83
--- /dev/null
+++ b/core/fitter.hpp
@@ -0,0 +1,1043 @@
+#ifndef FITTER_HPP
+#define FITTER_HPP
+#include "opt_exception.hpp"
+#include "optimizer.hpp"
+#include <vector>
+#include <string>
+#include <cstdlib>
+#include <cassert>
+#include <iostream>
+namespace opt_utilities
+{
+
+ ///////////////////////////////////
+ //////class data///////////////////
+ //////contain single data point////
+ ///////////////////////////////////
+ template<typename Ty,typename Tx,typename Tp,typename Ts,typename Tstr>
+ class statistic;
+
+ template<typename Ty,typename Tx,typename Tp,typename Tstr>
+ class param_modifier;
+
+
+ template<typename Ty,typename Tx>
+ class data
+ {
+ private:
+ Tx x,x_lower_err,x_upper_err;
+ Ty y,y_lower_err,y_upper_err;
+ public:
+ data(const Tx& _x,const Ty& _y,const Ty& _y_lower_err,const Ty& _y_upper_err,const Tx& _x_lower_err,const Tx& _x_upper_err)
+ {
+ opt_eq(x,_x);
+ opt_eq(x_lower_err,_x_lower_err);
+ opt_eq(x_upper_err,_x_upper_err);
+ opt_eq(y,_y);
+ opt_eq(y_lower_err,_y_lower_err);
+ opt_eq(y_upper_err,_y_upper_err);
+
+ }
+
+ data()
+ :x(),
+ x_lower_err(),
+ x_upper_err(),
+ y(),
+ y_lower_err(),
+ y_upper_err()
+ {}
+
+ data(const data& rhs)
+ {
+ opt_eq(x,rhs.x);
+ opt_eq(x_lower_err,rhs.x_lower_err);
+ opt_eq(x_upper_err,rhs.x_upper_err);
+ opt_eq(y,rhs.y);
+ opt_eq(y_lower_err,rhs.y_lower_err);
+ opt_eq(y_upper_err,rhs.y_upper_err);
+ }
+
+ data& operator=(const data& rhs)
+ {
+ opt_eq(x,rhs.x);
+ opt_eq(x_lower_err,rhs.x_lower_err);
+ opt_eq(x_upper_err,rhs.x_upper_err);
+ opt_eq(y,rhs.y);
+ opt_eq(y_lower_err,rhs.y_lower_err);
+ opt_eq(y_upper_err,rhs.y_upper_err);
+ return *this;
+ }
+
+ public:
+ const Tx& get_x()const
+ {
+ return x;
+ }
+
+ const Tx& get_x_lower_err()const
+ {
+ return x_lower_err;
+ }
+
+ const Tx& get_x_upper_err()const
+ {
+ return x_upper_err;
+ }
+
+ const Ty& get_y()const
+ {
+ return y;
+ }
+
+ const Ty& get_y_lower_err()const
+ {
+ return y_lower_err;
+ }
+
+ const Ty& get_y_upper_err()const
+ {
+ return y_upper_err;
+ }
+
+
+ void set_x(const Tx& _x)
+ {
+ opt_eq(x,_x);
+ }
+
+ void set_x_lower_err(const Tx& _x)
+ {
+ opt_eq(x_lower_err,_x);
+ }
+
+ void set_x_upper_err(const Tx& _x)
+ {
+ opt_eq(x_upper_err,_x);
+ }
+
+ void set_y(const Ty& _y)
+ {
+ opt_eq(y,_y);
+ }
+
+ void set_y_lower_err(const Ty& _y)
+ {
+ opt_eq(y_lower_err,_y);
+ }
+
+ void set_y_upper_err(const Ty& _y)
+ {
+ opt_eq(y_upper_err,_y);
+ }
+
+
+ };
+
+ ////////////////////////////////////
+ ///class data_set///////////////////
+ ///contain a set of data////////////
+ ////////////////////////////////////
+
+
+ template <typename Ty,typename Tx>
+ class data_set
+ {
+ private:
+
+ virtual const data<Ty,Tx>& do_get_data(int i)const=0;
+ virtual int do_size()const=0;
+ virtual void do_push_back(const data<Ty,Tx>&)=0;
+ virtual void do_clear()=0;
+ virtual data_set<Ty,Tx>* do_clone()const=0;
+
+ virtual void do_destroy()
+ {
+ delete this;
+ }
+ public:
+ const data<Ty,Tx>& get_data(int i)const
+ {
+ return this->do_get_data(i);
+ }
+ int size()const
+ {
+ return do_size();
+ }
+ void push_back(const data<Ty,Tx>& d)
+ {
+ return do_push_back(d);
+ }
+ void clear()
+ {
+ do_clear();
+ }
+
+ data_set<Ty,Tx>* clone()const
+ {
+ return this->do_clone();
+ }
+
+ void destroy()
+ {
+ do_destroy();
+ }
+
+ virtual ~data_set(){}
+
+ };
+
+ ///////////////////////////////////////////////
+ /////class param_info//////////////////////////
+ /////record the information of one parameter///
+ /////including the name, default value/////////
+ ///////////////////////////////////////////////
+
+
+ template <typename Tp,typename Tstr=std::string>
+ class param_info
+ {
+ private:
+ Tstr name;
+ //bool frozen;
+ typename element_type_trait<Tp>::element_type default_value;
+
+ public:
+ param_info(const Tstr& _name,
+ const typename element_type_trait<Tp>::element_type& _v)
+ :name(_name),default_value(_v){}
+
+ param_info()
+ :name()
+ {}
+
+ param_info(const param_info& rhs)
+ :name(rhs.name)
+ {
+ opt_eq(default_value,rhs.default_value);
+ }
+
+ param_info& operator=(const param_info& rhs)
+ {
+ name=rhs.name;
+ opt_eq(default_value,rhs.default_value);
+ return *this;
+ }
+
+ const Tstr& get_name()const
+ {
+ return this->name;
+ }
+
+ const typename element_type_trait<Tp>::element_type& get_default_value()const
+ {
+ return default_value;
+ }
+
+ void set_default_value(const typename element_type_trait<Tp>::element_type& x)
+ {
+ opt_eq(default_value,x);
+ }
+
+ void set_name(const Tstr& _name)
+ {
+ name=_name;
+ }
+ };
+
+
+
+
+
+ template <typename Ty,typename Tx,typename Tp,typename Tstr=std::string>
+ class model
+ {
+ private:
+ std::vector<param_info<Tp> > param_info_list;
+ param_info<Tp> null_param;
+ // int num_free_params;
+ param_modifier<Ty,Tx,Tp,Tstr>* p_param_modifier;
+ private:
+ virtual model<Ty,Tx,Tp,Tstr>* do_clone()const=0;
+
+ virtual void do_destroy()
+ {
+ delete this;
+ }
+ public:
+ model<Ty,Tx,Tp,Tstr>* clone()const
+ {
+ return do_clone();
+ }
+
+ void destroy()
+ {
+ do_destroy();
+ }
+ public:
+ model()
+ :p_param_modifier(0)
+ {}
+
+ model(const model& rhs)
+ :p_param_modifier(0)
+ {
+ if(rhs.p_param_modifier!=0)
+ {
+ set_param_modifier(*(rhs.p_param_modifier));
+ }
+ param_info_list=rhs.param_info_list;
+ null_param=rhs.null_param;
+
+ }
+
+ model& operator=(const model& rhs)
+ {
+ if(this==&rhs)
+ {
+ return *this;
+ }
+ if(rhs.p_param_modifier!=0)
+ {
+ set_param_modifier(*(rhs.p_param_modifier));
+ }
+ param_info_list=rhs.param_info_list;
+ null_param=rhs.null_param;
+ return *this;
+ }
+
+ virtual ~model()
+ {
+ if(p_param_modifier)
+ {
+ //delete p_param_modifier;
+ p_param_modifier->destroy();
+ }
+ }
+
+ void set_param_modifier(const param_modifier<Ty,Tx,Tp,Tstr>& pm)
+ {
+ if(p_param_modifier!=0)
+ {
+ //delete p_param_modifier;
+ p_param_modifier->destroy();
+ }
+ p_param_modifier=pm.clone();
+ p_param_modifier->set_model(*this);
+ }
+
+ void set_param_modifier()
+ {
+ if(p_param_modifier!=0)
+ {
+ //delete p_param_modifier;
+ p_param_modifier->destroy();
+ }
+ p_param_modifier=0;
+ }
+
+ param_modifier<Ty,Tx,Tp,Tstr>& get_param_modifier()
+ {
+ if(p_param_modifier==0)
+ {
+ throw param_modifier_undefined();
+ }
+ return *p_param_modifier;
+ }
+
+ Tstr report_param_status(const Tstr& s)const
+ {
+ if(p_param_modifier==0)
+ {
+ return Tstr();
+ }
+
+ return p_param_modifier->report_param_status(s);
+
+ }
+
+
+ const param_info<Tp,Tstr>& get_param_info(const Tstr& pname)
+ {
+ for(typename std::vector<param_info<Tp,Tstr> >::iterator i=param_info_list.begin();
+ i!=param_info_list.end();++i)
+ {
+ if(i->get_name()==pname)
+ {
+ return *i;
+ }
+ }
+ std::cerr<<"Param unfound!"<<std::endl;
+ assert(false);
+ throw param_not_found();
+ return null_param;
+ }
+
+ const param_info<Tp,Tstr>& get_param_info(int n)const
+ {
+ return param_info_list[n%get_num_params()];
+ }
+
+
+ Tp get_all_params()const
+ {
+ Tp result;
+ resize(result,param_info_list.size());
+ for(size_t i=0;i<param_info_list.size();++i)
+ {
+ //opt_eq(get_element(result,i),param_info_list[i].get_default_value());
+ set_element(result,i,param_info_list[i].get_default_value());
+ //get_element((Tp)result,i);
+ }
+ return result;
+ }
+
+
+ int get_num_params()const
+ {
+ return (int)param_info_list.size();
+ }
+
+ int get_num_free_params()const
+ {
+ if(p_param_modifier)
+ {
+ return (int)p_param_modifier->get_num_free_params();
+ }
+ return get_num_params();
+ }
+
+ void set_param_value(const Tstr& pname,
+ const typename element_type_trait<Tp>::element_type& v)
+ {
+ //int porder=0;
+ for(typename std::vector<param_info<Tp,Tstr> >::iterator i=param_info_list.begin();
+ i!=param_info_list.end();++i)
+ {
+ if(i->get_name()==pname)
+ {
+ i->set_default_value(v);
+ return;
+ }
+ }
+ std::cerr<<"param "<<pname<<" unfound"<<std::endl;
+ throw param_not_found();
+ }
+
+ void set_param_value(const Tp& param)
+ {
+ for(size_t i=0;i<param_info_list.size();++i)
+ {
+ param_info_list[i].set_default_value(get_element(param,i));
+ }
+ }
+
+ int get_param_order(const Tstr& pname)const
+ {
+ for(int i=0;i<(int)param_info_list.size();++i)
+ {
+ if(param_info_list[i].get_name()==pname)
+ {
+ return i;
+ }
+ }
+ // std::cerr<<"param name invalid!"<<std::endl;
+ // assert(false);
+ throw param_not_found();
+ return -1;
+ }
+
+
+
+ protected:
+ void push_param_info(const param_info<Tp,Tstr>& pinfo)
+ {
+ param_info_list.push_back(pinfo);
+ // this->num_free_params++;
+ }
+
+ void clear_param_info()
+ {
+ // this->num_free_params=0;
+ param_info_list.clear();
+ }
+
+
+
+ public:
+ Tstr to_string()const
+ {
+ return do_to_string();
+ }
+
+ Tp reform_param(const Tp& p)const
+ {
+ if(p_param_modifier==0)
+ {
+ return p;
+ }
+ return p_param_modifier->reform(p);
+ }
+
+ Tp deform_param(const Tp& p)const
+ {
+ if(p_param_modifier==0)
+ {
+ return p;
+ }
+ return p_param_modifier->deform(p);
+ }
+
+
+ Ty eval(const Tx& x,const Tp& p)
+ {
+ return do_eval(x,reform_param(p));
+ }
+
+ virtual Ty do_eval(const Tx& x,const Tp& p)=0;
+
+ private:
+ virtual Tstr do_to_string()const
+ {
+ return Tstr();
+ }
+
+ };
+
+
+
+ template<typename Ty,typename Tx,typename Tp,typename Ts=Ty,typename Tstr=std::string>
+ class fitter
+ {
+ public:
+ model<Ty,Tx,Tp,Tstr>* p_model;
+ statistic<Ty,Tx,Tp,Ts,Tstr>* p_statistic;
+ data_set<Ty,Tx>* p_data_set;
+ optimizer<Ts,Tp> optengine;
+ public:
+ fitter()
+ :p_model(0),p_statistic(0),p_data_set(0),optengine()
+ {}
+
+
+ fitter(const fitter& rhs)
+ :p_model(0),p_statistic(0),p_data_set(0),optengine()
+ {
+ if(rhs.p_model!=0)
+ {
+ set_model(*(rhs.p_model));
+ }
+ if(rhs.p_statistic!=0)
+ {
+ set_statistic(*(rhs.p_statistic));
+ assert(p_statistic->p_fitter!=0);
+ }
+ if(rhs.p_data_set!=0)
+ {
+ load_data(*(rhs.p_data_set));
+ }
+ optengine=rhs.optengine;
+ }
+
+ fitter& operator=(const fitter& rhs)
+ {
+ if(this==&rhs)
+ {
+ return *this;
+ }
+ if(rhs.p_model!=0)
+ {
+ set_model(*(rhs.p_model));
+ }
+ if(rhs.p_statistic!=0)
+ {
+ set_statistic(*(rhs.p_statistic));
+ }
+ if(rhs.p_data_set!=0)
+ {
+ load_data(*(rhs.p_data_set));
+ }
+ optengine=rhs.optengine;
+ return *this;
+ }
+
+ virtual ~fitter()
+ {
+ if(p_model!=0)
+ {
+ //delete p_model;
+ p_model->destroy();
+ }
+ if(p_statistic!=0)
+ {
+ //delete p_statistic;
+ p_statistic->destroy();
+ }
+ if(p_data_set!=0)
+ {
+ //delete p_data_set;
+ p_data_set->destroy();
+ }
+ }
+
+
+ Ty eval_model(const Tx& x,const Tp& p)
+ {
+ if(p_model==0)
+ {
+ throw model_undefined();
+ }
+ return p_model->eval(x,p);
+ }
+
+
+ public:
+ void set_model(const model<Ty,Tx,Tp,Tstr>& m)
+ {
+ if(p_model!=0)
+ {
+ //delete p_model;
+ p_model->destroy();
+ }
+ p_model=m.clone();
+ //p_model=&m;
+ // current_param.resize(m.get_num_params());
+ }
+ /*
+ void set(const model<Ty,Tx,Tp>& m)
+ {
+ set_model(m);
+ }
+ */
+ void set_statistic(const statistic<Ty,Tx,Tp,Ts,Tstr>& s)
+ {
+ if(p_statistic!=0)
+ {
+ //delete p_statistic;
+ p_statistic->destroy();
+ }
+ p_statistic=s.clone();
+ //p_statistic=&s;
+ p_statistic->set_fitter(*this);
+ }
+ /*
+ void set(const statistic<Ty,Tx,Tp>& s)
+ {
+ set_statistic(s);
+ }
+ */
+
+ void set_param_modifier(const param_modifier<Ty,Tx,Tp,Tstr>& pm)
+ {
+ if(p_model==0)
+ {
+ throw model_undefined();
+ }
+ p_model->set_param_modifier(pm);
+ }
+
+ void set_param_modifier()
+ {
+ if(p_model==0)
+ {
+ throw model_undefined();
+ }
+ p_model->set_param_modifier();
+ }
+
+ param_modifier<Ty,Tx,Tp,Tstr>& get_param_modifier()
+ {
+ if(p_model==0)
+ {
+ throw model_undefined();
+ }
+ return p_model->get_param_modifier();
+ }
+
+ Tstr report_param_status(const Tstr& s)const
+ {
+ if(p_model==0)
+ {
+ throw model_undefined();
+ }
+ return p_model->report_param_status(s);
+ }
+
+ /*
+ void set(const param_modifier<Ty,Tx,Tp>& pm)
+ {
+ set_param_modifier(pm);
+ }
+ */
+ void load_data(const data_set<Ty,Tx>& da)
+ {
+ if(p_data_set!=0)
+ {
+ //delete p_data_set;
+ p_data_set->destroy();
+ }
+ p_data_set=da.clone();
+ if(p_statistic!=0)
+ {
+ p_statistic->set_fitter(*this);
+ }
+ }
+
+ const data_set<Ty,Tx>& datas()const
+ {
+ if(p_data_set==0)
+ {
+ throw data_unloaded();
+ }
+ return *(this->p_data_set);
+ }
+
+ model<Ty,Tx,Tp,Tstr>& model()
+ {
+ if(p_model==0)
+ {
+ throw model_undefined();
+ }
+ return *(this->p_model);
+ }
+
+ statistic<Ty,Tx,Tp,Ts,Tstr>& statistic()
+ {
+ if(p_statistic==0)
+ {
+ throw statistic_undefined();
+ }
+ return *(this->p_statistic);
+ }
+
+ opt_method<Ts,Tp>& method()
+ {
+ return optengine.method();
+ }
+
+
+ public:
+ void set_param_value(const Tstr& pname,
+ const typename element_type_trait<Tp>::element_type& v)
+ {
+ if(p_model==0)
+ {
+ throw model_undefined();
+ }
+ p_model->set_param_value(pname,v);
+ }
+
+ void set_param_value(const Tp& param)
+ {
+ if(p_model==0)
+ {
+ throw model_undefined();
+ }
+ p_model->set_param_value(param);
+ }
+
+ typename element_type_trait<Tp>::element_type get_param_value(const Tstr& pname)const
+ {
+ if(p_model==0)
+ {
+ throw model_undefined();
+ }
+ return p_model->get_param_info(pname).get_default_value();
+ }
+
+ const param_info<Tp,Tstr>& get_param_info(const Tstr& pname)const
+ {
+ if(p_model==0)
+ {
+ throw model_undefined();
+ }
+ return p_model->get_param_info(pname);
+ }
+
+ const param_info<Tp,Tstr>& get_param_info(int n)const
+ {
+ if(p_model==0)
+ {
+ throw model_undefined();
+ }
+ return p_model->get_param_info(n);
+ }
+
+ const int get_param_order(const Tstr& pname)const
+ {
+ if(p_model==0)
+ {
+ throw model_undefined();
+ }
+ return p_model->get_param_order(pname);
+ }
+
+ int get_num_params()const
+ {
+ if(p_model==0)
+ {
+ throw model_undefined();
+ }
+ return p_model->get_num_params();
+ }
+
+ Tp get_all_params()const
+ {
+ if(p_model==0)
+ {
+ throw model_undefined();
+ }
+ //return current_param;
+ return p_model->get_all_params();
+ }
+
+ void set_method(const opt_method<Ts,Tp>& pm)
+ {
+ //assert(p_optimizer!=0);
+ optengine.set_opt_method(pm);
+ }
+ /*
+ void set(const opt_method<Ty,Tp>& pm)
+ {
+ set_method(pm);
+ }
+ */
+ void set_precision(typename element_type_trait<Tp>::element_type y)
+ {
+ optengine.set_precision(y);
+ }
+
+ Tp fit()
+ {
+ // assert(p_model!=0);
+ if(p_model==0)
+ {
+ throw model_undefined();
+ }
+ if(p_data_set==0)
+ {
+ throw data_unloaded();
+ }
+ //assert(p_optimizer!=0);
+ //assert(p_data_set!=0);
+ //assert(p_statistic!=0);
+ if(p_statistic==0)
+ {
+ throw statistic_undefined();
+ }
+
+ optengine.set_func_obj(*p_statistic);
+ Tp current_param;
+ opt_eq(current_param,p_model->get_all_params());
+ Tp start_point;
+ opt_eq(start_point,p_model->deform_param(current_param));
+ // std::cout<<start_point.size()<<std::endl;
+
+
+ //for(int i=0;i<(int)start_point.size();++i)
+ // {
+ // std::cout<<start_point[i]<<",";
+ // }
+ //std::cout<<std::endl;
+ //assert(start_point.size()!=0);
+ if(get_size(start_point)==0)
+ {
+ //return start_point;
+ return p_model->get_all_params();
+ }
+ optengine.set_start_point(start_point);
+
+ Tp result;
+ opt_eq(result,optengine.optimize());
+
+ Tp decurrent_param;
+ opt_eq(decurrent_param,p_model->reform_param(result));
+ //current_param.resize(decurrent_param.size());
+ resize(current_param,get_size(decurrent_param));
+ opt_eq(current_param,decurrent_param);
+ p_model->set_param_value(current_param);
+ // return current_param;
+ return p_model->get_all_params();
+ }
+
+ };
+
+
+ template<typename Ty,typename Tx,typename Tp,typename Ts,typename Tstr=std::string>
+ class statistic
+ :public func_obj<Ts,Tp>
+ {
+ public:
+ fitter<Ty,Tx,Tp,Ts,Tstr>* p_fitter;
+
+ private:
+ virtual statistic<Ty,Tx,Tp,Ts,Tstr>* do_clone()const=0;
+
+ virtual void do_destroy()
+ {
+ delete this;
+ }
+
+ public:
+ statistic<Ty,Tx,Tp,Ts,Tstr>* clone()const
+ {
+ return this->do_clone();
+ }
+
+ void destroy()
+ {
+ return do_destroy();
+ }
+ statistic()
+ :p_fitter(0)
+ {}
+
+ statistic(const statistic& rhs)
+ :p_fitter(rhs.p_fitter)
+ {}
+
+ statistic& operator=(const statistic& rhs)
+ {
+ if(this==&rhs)
+ {
+ return *this;
+ }
+ p_fitter=rhs.p_fitter;
+ return *this;
+ }
+
+ virtual ~statistic()
+ {}
+
+ virtual void set_fitter(fitter<Ty,Tx,Tp,Ts,Tstr>& pfitter)
+ {
+ p_fitter=&pfitter;
+ }
+
+ virtual const fitter<Ty,Tx,Tp,Ts,Tstr>& get_fitter()const
+ {
+ if(p_fitter==0)
+ {
+ throw fitter_unset();
+ }
+ return *p_fitter;
+ }
+
+ Ty eval_model(const Tx& x,const Tp& p)
+ {
+ if(p_fitter==0)
+ {
+ throw fitter_unset();
+ }
+ return p_fitter->eval_model(x,p);
+ }
+
+
+ const data_set<Ty,Tx>& datas()const
+ {
+ if(p_fitter==0)
+ {
+ throw fitter_unset();
+ }
+ return p_fitter->datas();
+ }
+
+ };
+
+ template <typename Ty,typename Tx,typename Tp,typename Tstr=std::string>
+ class param_modifier
+ {
+ private:
+ model<Ty,Tx,Tp,Tstr>* p_model;
+ public:
+ Tp reform(const Tp& p)const
+ {
+ return do_reform(p);
+ }
+ Tp deform(const Tp& p)const
+ {
+ return do_deform(p);
+ }
+
+ param_modifier<Ty,Tx,Tp,Tstr>* clone()const
+ {
+ return do_clone();
+ }
+
+ void destroy()
+ {
+ do_destroy();
+ }
+
+ public:
+
+ param_modifier()
+ :p_model(0)
+ {}
+
+ param_modifier(const param_modifier& rhs)
+ :p_model(rhs.p_model)
+ {}
+
+ param_modifier& operator=(const param_modifier& rhs)
+ {
+ if(this==&rhs)
+ {
+ return *this;
+ }
+ p_model=rhs.p_model;
+ return *this;
+ }
+
+ public:
+ void set_model(model<Ty,Tx,Tp,Tstr>& pf)
+ {
+ p_model=&pf;
+ update();
+ }
+
+ const model<Ty,Tx,Tp,Tstr>& get_model()const
+ {
+ if(p_model==0)
+ {
+ std::cout<<"dajf;asdjfk;";
+ throw model_undefined();
+ }
+ return *(this->p_model);
+ }
+
+ int get_num_free_params()const
+ {
+ return do_get_num_free_params();
+ }
+
+ Tstr report_param_status(const Tstr& name)const
+ {
+ return do_report_param_status(name);
+ }
+
+
+ virtual ~param_modifier(){}
+ private:
+ virtual Tp do_reform(const Tp& p)const=0;
+ virtual Tp do_deform(const Tp& p)const=0;
+ virtual int do_get_num_free_params()const=0;
+ virtual Tstr do_report_param_status(const Tstr&)const=0;
+ virtual void update(){}
+
+ virtual param_modifier<Ty,Tx,Tp,Tstr>* do_clone()const=0;
+
+ virtual void do_destroy()
+ {
+ delete this;
+ }
+
+ };
+
+
+
+};
+
+
+#endif
+//EOF
diff --git a/core/freeze_param.hpp b/core/freeze_param.hpp
new file mode 100644
index 0000000..8ba677a
--- /dev/null
+++ b/core/freeze_param.hpp
@@ -0,0 +1,204 @@
+#ifndef FREEZE_PARAM_HPP
+#define FREEZE_PARAM_HPP
+#include "fitter.hpp"
+#include <vector>
+#include <set>
+
+namespace opt_utilities
+{
+ template <typename Ty,typename Tx,typename Tp,typename Tstr=std::string>
+ class freeze_param
+ :public param_modifier<Ty,Tx,Tp,Tstr>
+ {
+ private:
+ std::set<Tstr> param_names;
+ std::vector<int> param_num;
+ int num_free;
+
+ public:
+ freeze_param()
+ {
+
+ }
+
+ freeze_param(const Tstr& name)
+ {
+ param_names.insert(name);
+ }
+
+ private:
+ freeze_param<Ty,Tx,Tp,Tstr>* do_clone()const
+ {
+ return new freeze_param<Ty,Tx,Tp,Tstr>(*this);
+ }
+
+
+
+ void update()
+ {
+ param_num.clear();
+ for(typename std::set<Tstr>::const_iterator i=param_names.begin();
+ i!=param_names.end();++i)
+ {
+ try
+ {
+ param_num.push_back(this->get_model().get_param_order(*i));
+ }
+ catch(opt_exception& e)
+ {
+ param_names.erase(*i);
+ throw;
+ }
+
+ }
+ }
+
+ int do_get_num_free_params()const
+ {
+ return this->get_model().get_num_params()-param_num.size();
+ }
+
+ bool is_frozen(int i)const
+ {
+ if(find(param_num.begin(),param_num.end(),i)==param_num.end())
+ {
+ return false;
+ }
+ return true;
+ }
+
+
+ Tp do_reform(const Tp& p)const
+ {
+ int nparams=(this->get_model().get_num_params());
+ Tp reformed_p(nparams);
+ int i=0,j=0;
+ for(i=0;i<(int)nparams;++i)
+ {
+ if(this->is_frozen(i))
+ {
+ const param_info<Tp,Tstr>& pinf=this->get_model().get_param_info(i);
+ //std::cout<<"frozen:"<<pinf.get_name()
+ // <<i<<"\t"<<j
+ // <<std::endl;
+ //opt_eq(get_element(reformed_p,i),pinf.get_default_value());
+ set_element(reformed_p,i,pinf.get_default_value());
+ }
+ else
+ {
+ //opt_eq(get_element(reformed_p,i),get_element(p,j));
+ set_element(reformed_p,i,get_element(p,j));
+ j++;
+ }
+ }
+ /*
+ for(int i=0;i<reformed_p.size();++i)
+ {
+ std::cout<<get_element(reformed_p,i)<<",";
+ }
+ */
+ //std::cout<<"\n";
+ return reformed_p;
+ // return p;
+ }
+
+ Tp do_deform(const Tp& p)const
+ {
+ Tp deformed_p(do_get_num_free_params());
+ int i(0),j(0);
+ assert(get_size(p)==this->get_model().get_num_params());
+ for(;i<(int)get_size(p);++i)
+ {
+ //std::cout<<is_frozen(j)<<"\n";
+ if(!this->is_frozen(i))
+ {
+ //opt_eq(get_element(deformed_p,j),get_element(p,i));
+ set_element(deformed_p,j,get_element(p,i));
+ j++;
+ }
+ }
+
+ assert(j==do_get_num_free_params());
+ return deformed_p;
+ }
+
+
+ Tstr do_report_param_status(const Tstr& name)const
+ {
+ if(param_names.find(name)==param_names.end())
+ {
+ return "thawed";
+ }
+ return "frozen";
+ }
+
+ public:
+ freeze_param operator+(const freeze_param& fp)const
+ {
+ freeze_param result(*this);
+ for(typename std::set<Tstr>::const_iterator i=fp.param_names.begin();
+ i!=fp.param_names.end();
+ ++i)
+ {
+ result.param_names.insert(*i);
+ }
+ return result;
+ }
+
+ freeze_param& operator+=(const freeze_param& fp)
+ {
+ //param_names.insert(param_names.end(),
+ //fp.param_names.begin(),
+ //fp.param_names.end());
+ for(typename std::set<Tstr>::const_iterator i=fp.param_names.begin();
+ i!=fp.param_names.end();
+ ++i)
+ {
+ param_names.insert(*i);
+ }
+ try
+ {
+ update();
+ }
+ catch(opt_exception& e)
+ {
+ throw;
+ }
+ return *this;
+ }
+
+ freeze_param& operator-=(const freeze_param& fp)
+ {
+ //param_names.insert(param_names.end(),
+ //fp.param_names.begin(),
+ //fp.param_names.end());
+ for(typename std::set<Tstr>::const_iterator i=fp.param_names.begin();
+ i!=fp.param_names.end();
+ ++i)
+ {
+ param_names.erase(*i);
+ }
+ try
+ {
+ update();
+ }
+ catch(opt_exception& e)
+ {
+ throw;
+ }
+ return *this;
+ }
+
+ };
+
+ template <typename Ty,typename Tx,typename Tp,typename Tstr>
+ freeze_param<Ty,Tx,Tp,Tstr> freeze(const Tstr& name)
+ {
+ return freeze_param<Ty,Tx,Tp,Tstr>(name);
+ }
+
+};
+
+
+#endif
+//EOF
diff --git a/core/opt_exception.hpp b/core/opt_exception.hpp
new file mode 100644
index 0000000..925e4b5
--- /dev/null
+++ b/core/opt_exception.hpp
@@ -0,0 +1,106 @@
+#ifndef OPT_EXCEPTION
+#define OPT_EXCEPTION
+#include <string>
+#include <exception>
+namespace opt_utilities
+{
+ class opt_exception
+ :public std::exception
+ {
+ private:
+ std::string _what;
+ public:
+ opt_exception()
+ {};
+
+ ~opt_exception()throw()
+ {}
+
+ opt_exception(const std::string& str)
+ :_what(str)
+ {}
+
+ const char* what()const throw()
+ {
+ return _what.c_str();
+ }
+ };
+
+ class target_function_undefined
+ :public opt_exception
+ {
+ public:
+ target_function_undefined()
+ :opt_exception("target function undefined")
+ {}
+ };
+
+ class opt_method_undefined
+ :public opt_exception
+ {
+ public:
+ opt_method_undefined()
+ :opt_exception("opt method undefined")
+ {}
+ };
+
+ class fitter_unset
+ :public opt_exception
+ {
+ public:
+ fitter_unset()
+ :opt_exception("fitter_unset")
+ {}
+ };
+
+ class model_undefined
+ :public opt_exception
+ {
+ public:
+ model_undefined()
+ :opt_exception("model_undefined")
+ {}
+ };
+
+ class data_unloaded
+ :public opt_exception
+ {
+ public:
+ data_unloaded()
+ :opt_exception("data not loaded")
+ {}
+ };
+
+
+ class statistic_undefined
+ :public opt_exception
+ {
+ public:
+ statistic_undefined()
+ :opt_exception("statistic undefined")
+ {}
+ };
+
+ class param_not_found
+ :public opt_exception
+ {
+ public:
+ param_not_found()
+ :opt_exception("param name invalid")
+ {}
+ };
+
+ class param_modifier_undefined
+ :public opt_exception
+ {
+ public:
+ param_modifier_undefined()
+ :opt_exception("param modifier undefined")
+ {}
+ };
+
+};
+
+
+#endif
+//EOF
diff --git a/core/opt_traits.hpp b/core/opt_traits.hpp
new file mode 100644
index 0000000..c539a63
--- /dev/null
+++ b/core/opt_traits.hpp
@@ -0,0 +1,64 @@
+#ifndef ARRAY_OPERATION
+#define ARRAY_OPERATION
+#include <cstddef>
+namespace opt_utilities
+{
+ /////////Useful function///////////////////////////////////
+ template <typename T>
+ inline size_t get_size(const T& x)
+ {
+ return x.size();
+ }
+
+ template <typename T>
+ class element_type_trait
+ {
+ public:
+ typedef typename T::value_type element_type;
+ };
+
+ template <typename T>
+ class return_type_trait
+ {
+ public:
+ typedef T value_type;
+ typedef T& reference_type;
+ typedef const T& const_reference_type;
+ };
+
+ template <typename T>
+ inline typename return_type_trait<typename element_type_trait<T>::element_type>::const_reference_type get_element(const T& x,size_t i)
+ {
+ return x[i];
+ }
+ /*
+ template <typename T>
+ inline typename element_type_trait<T>::element_type& get_element(T& x,size_t i)
+ {
+ return x[i];
+ }
+ */
+
+ template<typename T,typename TX>
+ inline void set_element(T& x,size_t i,
+ const TX& v)
+ {
+ x[i]=v;
+ }
+
+ template <typename T>
+ inline void resize(T& x,size_t s)
+ {
+ x.resize(s);
+ }
+
+ template <typename Tl,typename Tr>
+ inline Tl& opt_eq(Tl& lhs,const Tr& rhs)
+ {
+ return (lhs=rhs);
+ }
+};
+
+
+
+#endif
diff --git a/core/optimizer.hpp b/core/optimizer.hpp
new file mode 100644
index 0000000..ca73775
--- /dev/null
+++ b/core/optimizer.hpp
@@ -0,0 +1,289 @@
+#ifndef OPTIMZER_H_
+#define OPTIMZER_H_
+//#define DEBUG
+#include <cstddef>
+#include "opt_traits.hpp"
+#include "opt_exception.hpp"
+#include <cstdlib>
+#include <functional>
+#ifdef DEBUG
+#include <iostream>
+using namespace std;
+#endif
+
+namespace opt_utilities
+{
+ /////////Forward declare///////////////////////////////////
+ template <typename rT,typename pT>
+ class optimizer;
+
+ template <typename rT,typename pT>
+ class func_obj;
+
+ template <typename rT,typename pT>
+ class opt_method;
+
+
+ //////////////Target Function/////////////////////
+ ///An eval function should be implemented/////////
+ ///The eval function return the function value////
+ ///which is wrapped by the func_obj///////////////
+ //////////////////////////////////////////////////
+ template <typename rT,typename pT>
+ class func_obj
+ :public std::unary_function<pT,rT>
+ {
+ private:
+ virtual rT do_eval(const pT&)=0;
+ virtual func_obj<rT,pT>* do_clone()const=0;
+ virtual void do_destroy()
+ {
+ delete this;
+ }
+
+ public:
+ public:
+ func_obj<rT,pT>* clone()const
+ {
+ return do_clone();
+ }
+
+ void destroy()
+ {
+ do_destroy();
+ }
+
+ rT operator()(const pT& p)
+ {
+ return do_eval(p);
+ }
+
+
+ rT eval(const pT& p)
+ {
+ return do_eval(p);
+ };
+ virtual ~func_obj(){};
+ // virtual XT walk(XT,YT)=0;
+ };
+
+
+ ///////////////Optimization method//////////////////////
+
+ template <typename rT,typename pT>
+ class opt_method
+ {
+ public:
+ virtual void do_set_optimizer(optimizer<rT,pT>&)=0;
+ virtual void do_set_precision(rT)=0;
+ virtual pT do_optimize()=0;
+ virtual void do_set_start_point(const pT& p)=0;
+ virtual opt_method<rT,pT>* do_clone()const=0;
+
+ virtual void do_destroy()
+ {
+ delete this;
+ }
+ public:
+ void set_optimizer(optimizer<rT,pT>& op)
+ {
+ do_set_optimizer(op);
+ };
+
+ void set_precision(rT x)
+ {
+ do_set_precision(x);
+ }
+
+ void set_start_point(const pT& p)
+ {
+ do_set_start_point(p);
+ }
+
+ pT optimize()
+ {
+ return do_optimize();
+ };
+
+ opt_method<rT,pT>* clone()const
+ {
+ return do_clone();
+ }
+
+ void destroy()
+ {
+ do_destroy();
+ }
+
+ virtual ~opt_method(){};
+ };
+
+
+ ///////////Optimizer////////////////////////////////////
+ template <typename rT,typename pT>
+ class optimizer
+ {
+ public:
+
+ private:
+
+ ////////////pointer to an optimization method objection////////////
+ ////////////The optimization method implements a certain method ///
+ ////////////Currently only Mont-carlo method is implemented////////
+ opt_method<rT,pT>* p_opt_method;
+ func_obj<rT,pT>* p_func_obj;
+
+ public:
+ optimizer()
+ :p_opt_method(0),p_func_obj(0)
+ {}
+
+ optimizer(func_obj<rT,pT>& fc,const opt_method<rT,pT>& om)
+ :p_func_obj(fc.clone()),p_opt_method(om.clone())
+ {
+ p_opt_method->set_optimizer(*this);
+ }
+
+ optimizer(const optimizer& rhs)
+ :p_opt_method(0),p_func_obj(0)
+ {
+ if(rhs.p_func_obj!=0)
+ {
+ set_func_obj(*(rhs.p_func_obj));
+ }
+ if(rhs.p_opt_method!=0)
+ {
+ set_opt_method(*(rhs.p_opt_method));
+ }
+ }
+
+ optimizer& operator=(const optimizer& rhs)
+ {
+ if(this==&rhs)
+ {
+ return *this;
+ }
+ if(rhs.p_func_obj!=0)
+ {
+ set_func_obj(*(rhs.p_func_obj));
+ }
+ if(rhs.p_opt_method!=0)
+ {
+ set_opt_method(*(rhs.p_opt_method));
+ }
+ return *this;
+ }
+
+
+ virtual ~optimizer()
+ {
+ if(p_func_obj!=0)
+ {
+ //delete p_func_obj;
+ p_func_obj->destroy();
+ }
+ if(p_opt_method!=0)
+ {
+ //delete p_opt_method;
+ p_opt_method->destroy();
+ }
+ };
+
+ public:
+ ////////////Re-set target function object///////////////////////////
+ void set_func_obj(const func_obj<rT,pT>& fc)
+ {
+ if(p_func_obj!=0)
+ {
+ //delete p_func_obj;
+ p_func_obj->destroy();
+ }
+ p_func_obj=fc.clone();
+ if(p_opt_method!=0)
+ {
+ p_opt_method->set_optimizer(*this);
+ }
+ }
+
+ ////////////Re-set optimization method//////////////////////////////
+ void set_opt_method(const opt_method<rT,pT>& om)
+ {
+ if(p_opt_method!=0)
+ {
+ //delete p_opt_method;
+ p_opt_method->destroy();
+ }
+
+ p_opt_method=om.clone();
+ p_opt_method->set_optimizer(*this);
+ }
+
+ opt_method<rT,pT>& method()
+ {
+ if(p_opt_method==0)
+ {
+ throw opt_method_undefined();
+ }
+ return *(this->p_opt_method);
+ }
+
+ void set_precision(rT x)
+ {
+ if(p_opt_method==0)
+ {
+ throw opt_method_undefined();
+ }
+ p_opt_method->set_precision(x);
+ }
+
+ void set_start_point(const pT& x)
+ {
+ if(p_opt_method==0)
+ {
+ throw opt_method_undefined();
+ }
+ p_opt_method->set_start_point(x);
+ }
+
+ ////////////Just call the eval function in the target function object///
+ ////////////In case the pointer to a target function is uninitialed/////
+ ////////////a zero-value is returned////////////////////////////////////
+ rT eval(const pT& x)
+ {
+ if(p_func_obj==0)
+ {
+ throw target_function_undefined();
+ }
+ return p_func_obj->eval(x);
+ }
+
+
+
+ ////////////Just call the optimize() function in the optimization method//
+ ////////////If no optimization method is given, an zero-value is returned/
+ pT optimize()
+ {
+ if(p_opt_method==0)
+ {
+ throw opt_method_undefined();
+ }
+ if(p_func_obj==0)
+ {
+ throw target_function_undefined();
+ }
+ return p_opt_method->optimize();
+ }
+
+ ////////////Function that offers the access to the target function object///
+ func_obj<rT,pT>* ptr_func_obj()
+ {
+ return p_func_obj;
+ }
+
+ };
+};
+
+#endif
+//EOF
+
+
diff --git a/guide.pdf b/guide.pdf
new file mode 100644
index 0000000..3a8a39d
--- /dev/null
+++ b/guide.pdf
Binary files differ
diff --git a/history.log b/history.log
new file mode 100644
index 0000000..7adefdd
--- /dev/null
+++ b/history.log
@@ -0,0 +1,239 @@
+2008 Jan 21
+ changed all std::string in parameter table to const std::string&
+ version 2.9.12
+2008 Jan 22
+ changed optimizer::eval(pT& x) -> optimizer::eval(const pT& x)
+ version 2.9 13
+2008 Jan 22
+ changed data::set_x(Tx x)->data::set_x(const Tx& x)
+ version 2.9.14
+2008 Jan 22
+ changed the parameter set_param_value to a const reference.
+ version 2.10.1
+
+2008 Jan 23
+ removed the declaration of init_model_map etc. in models.hpp
+ version 2.10.2
+
+2008 Jan 24
+ added get_strm1d() interface to models.hpp and models.cc
+ version 2.10.3
+
+2008 Feb 11
+ modified some mistakes in models/ modified the nr_util, add T() in '?' expressions
+ version 2.11.1
+2008 Feb 12
+ modified powell_method.hpp to enable the lib work around apfloat
+ version 2.11.2
+
+2008 Feb 19
+ modified the design of the data_loaders, add members:load_from, deleted the friend template declear in the class.
+ modified the fitter class, corrected a bug which happens when all parameters are frozen, the fitter will crash.
+ version 2.11.3
+
+
+2008 March 14
+ Added a condition compiling to the dynamical load model
+
+
+2008 March 21
+ Modified a contition compiling to the dynamical load model, changed the marco from LINUX__ to __linux__
+
+2008 March 27
+ Made std::unary_function the base class of func_obj
+ version 2.12.1
+
+2008 April 18
+ Added nbeta1d into the model list
+ version 2.12.2
+
+2008 May 10
+ Added a bremss model
+ Added an opt_type.hpp
+ version 2.12.3
+
+2008 May 12
+ Added the declearation of virtual dstr function to some class
+ version 2.12.4
+
+
+2008 May 13
+ Modified the makefile, to generate liboptutil.a
+ version 2.12.5
+
+2008 May 14
+ Updated the c/fortran callable interface
+ version 2.12.6
+
+2008 May 22
+ Modified the symbol definition of interface
+ version 2.12.7
+
+2008 June 1
+ Added the <cassert> in the file fitter.hpp
+ version 2.12.8
+
+2008 June 12
+ Added NFW1D model
+ Cleaned some warnings
+ version 2.12.9
+
+2008 Jun 19
+ Modified fit2d task. Enables it to write fits file.
+ version 2.12.10
+
+2008 Jun 23
+ Modified the LINUX marco in models.cc
+ version 2.12.11
+
+2008 Jun 25
+ Added a pow_model, to enable power computation on models.
+ version 2.12.12
+
+2008 Jun 27
+ Added the function to query the number of build-in 1d and 2d models.
+ version 2.12.13
+
+
+2008 Jul 1
+ Added a to_string and corresponding do_to_string method to class model.
+ version 2.13.0
+
+
+2008 Jul 1
+ Implemented the do_to_string method in most 1d models
+ version 2.13.1
+
+
+2008 Jul 7
+ Added another gsl_simplex method to perform the optimization.
+ version 2.14.0
+
+2008 Jul 8
+ Modified one bug caused by the head inclusion. The <cmath> should be included.
+ version 2.14.1
+
+
+2008 Jul 8
+ Enables the optcli program to display model infomation
+ version 2.14.2
+
+2008 Jul 8
+ Changed the methods include of head files.
+ Version 2.14.3
+
+2008 Jul 10
+ Corrected the include of optimizer.hpp in gsl_methods/gsl_simplex.hpp
+ version 2.14.4
+
+2008 Jul 12
+ Corrected the ``comparison between signed and unsigned integer'' warning
+ version 2.14.5
+
+2008 Jul 14
+ Modified the interface get_data in data_set class.
+ Changed the return value from data to const data&
+ version 2.15.0
+
+2008 Jul 19
+ Corrected a bug in gsl_simplex.hpp
+ version 2.15.1
+
+2008 Jul 21
+ Corrected the makefile in interface/
+ version 2.15.2
+
+2008 Jul 22
+ Moved some files from core/ to separated folder.
+ version 2.15.3
+
+2008 Jul 22
+ version 2.15.4
+
+2008 Jul 24
+ Modified the makefile
+ version 2.15.5
+
+2008 Jul 24
+ Changed the project name from optimizer to opt_utilities
+ version 2.15.6
+
+2008 Jul 25
+ Enable the 'ls' command to display with color
+ version 2.15.7
+
+2008 Aug 15
+ Changed the x[i] into get_element(x,i),
+ Changed the x.size() into get_size(x).
+ version 2.16.0
+
+2008 Aug 15
+ Some further modification, added opt_eq function to represent '=' operation.
+ version 2.16.1
+
+2008 Aug 15
+ Modified some bugs
+ version 2.16.2
+
+2008 Aug 16
+ Added a set_element function
+ version 2.16.3
+
+2008 Aug 17
+ Changed the argument type of opt_get from single 'T' to 'Tl' and 'Tr'
+ version 2.16.4
+
+2008 Aug 18
+ Make the makefile more standard.
+ version 2.16.5
+
+2008 Aug 22
+ Added the inclusion of <cstddef> in array_operation.h
+ version 2.16.6
+
+2008 Aug 24
+ Added ./termcap to the inclusion of CFLAG
+ version 2.16.7
+
+2008 Aug 25
+ Modified the return type of param_info::get_default_value from T to const T&
+ version 2.16.8
+2008 Aug 25
+ modifier a return type, added a const
+ version 2.16.9
+
+2008 Aug 26
+ Enabled the chisq statistic to take account of the x error
+ version 2.16.10
+
+2008 Sep 2
+ added a virtual function to some classes to enable them to destroy themselves.
+ version 2.16.11
+
+2008 Sep 5
+ changed the name value_type_trait to element_type_trait, added a return_type_trait
+ version 2.16.12
+
+2008 Sep 27
+ Corrected two bugs in the add_model.hpp and mul_model.hpp
+ version 2.16.13
+
+2008 Oct 3
+ Stripped the subpackages that uses GPL from it
+ version 2.17.0
+
+2008 Nov 24
+ Replaced all std::string with an extra template parameter Tstr, enables the ability of treating Unicode strings
+ version 2.18.0
+
+2008 Nov 25
+ Completed the exception tree
+ version 2.19.0
+
+2008 Nov 25
+ modified some string type related codes
+ version 2.19.1
+
+2008 Nov 27
+ corrected const correction in freeze_param.hpp
+ version 2.19.2
diff --git a/interface/makefile b/interface/makefile
new file mode 100644
index 0000000..5cf7a99
--- /dev/null
+++ b/interface/makefile
@@ -0,0 +1,13 @@
+INC=-I../
+
+
+libopt.a:opt.o
+ $(AR) $@ opt.o
+
+opt.o:opt.cc opt.h
+ $(CPP) $< -o $@ $(INC) $(CPPFLAGS)
+
+
+clean:
+ $(RM) *.o
+ $(RM) *~
diff --git a/interface/opt.cc b/interface/opt.cc
new file mode 100644
index 0000000..51762f5
--- /dev/null
+++ b/interface/opt.cc
@@ -0,0 +1,181 @@
+#include "opt.h"
+#include <utilities/opt_types.hpp>
+#include <models/models.hpp>
+#include <map>
+#include <core/freeze_param.hpp>
+#include <core/default_data_set.hpp>
+//#include <iostream>
+
+using namespace std;
+using namespace opt_utilities;
+const static int max_fit_space_num=100;
+struct fit_space;
+static map<int,fit_space> fit_space_map;
+struct fit_space
+{
+ dopt::fitter fit;
+ /// dopt::model model;
+ fit_space()
+ {
+ fit.set_method(dopt::powell_method());
+ dopt::chisq cq;
+ // cq.verbose(true);
+ fit.set_statistic(cq);
+ }
+
+};
+
+
+extern "C"
+{
+
+void alloc_fit_(int& n)
+{
+ n=0;
+ for(int i=1;i<max_fit_space_num;++i)
+ {
+ if(fit_space_map.find(i)==fit_space_map.end())
+ {
+ fit_space_map.insert(make_pair(i,fit_space()));
+ //cout<<i<<endl;
+ //return i;
+ n=i;
+ break;
+ }
+ }
+
+ return;
+}
+
+
+void free_fit_(const int& n)
+{
+ map<int,fit_space>::iterator iter=fit_space_map.find(n);
+ if(iter==fit_space_map.end())
+ {
+ return;
+ }
+ fit_space_map.erase(iter);
+}
+
+void load_data_(const int& nfit,const int& ndatas,double* x,double* y,double* yl,double* yu,double* xl,double* xu)
+{
+ map<int,fit_space>::iterator iter=fit_space_map.find(nfit);
+ if(iter==fit_space_map.end())
+ {
+ return;
+ }
+ // cout<<x[0]<<endl;
+ default_data_set<double,double> ds;
+ for(int i=0;i<ndatas;++i)
+ {
+ data<double,double> d(x[i],y[i],yl[i],(yu==0?yl[i]:yu[i]),(xl==0?0:xl[i]),(xu==0?0:xu[i]));
+ // cout<<x[i]<<" "<<y[i]<<endl;
+ ds.push_back(d);
+ }
+ iter->second.fit.load_data(ds);
+}
+
+
+void set_model_(const int& nfit,const char* model_name)
+{
+ map<int,fit_space>::iterator iter=fit_space_map.find(nfit);
+
+ if(iter==fit_space_map.end())
+ {
+ cerr<<"fit not found"<<endl;
+ return;
+ }
+ try
+ {
+ iter->second.fit.set_model(opt_utilities::get_1dmodel_by_name(model_name));
+ }
+ catch(opt_exception& e)
+ {
+ //cout<<model_name<<endl;
+ cout<<e.what()<<endl;
+ throw e;
+ }
+}
+
+void set_param_(const int& nfit,const char* pname,const double& value)
+{
+ map<int,fit_space>::iterator iter=fit_space_map.find(nfit);
+ cerr<<"pname="<<pname<<endl;
+ cerr<<"value="<<value<<endl;
+ if(iter==fit_space_map.end())
+ {
+ cerr<<"fit not found"<<endl;
+ return;
+ }
+ iter->second.fit.set_param_value(pname,value);
+}
+
+
+void freeze_param_(const int& nfit,const char* pname)
+{
+ map<int,fit_space>::iterator iter=fit_space_map.find(nfit);
+ if(iter==fit_space_map.end())
+ {
+ return;
+ }
+ opt_utilities::freeze_param<double,double,std::vector<double> > fp(pname);
+ try
+ {
+ dynamic_cast<opt_utilities::freeze_param<double,double,vector<double> >& >(iter->second.fit.get_param_modifier())+=fp;
+ }
+ catch(opt_exception& e)
+ {
+ iter->second.fit.set_param_modifier(fp);
+ }
+}
+
+
+void thaw_param_(const int& nfit,const char* pname)
+{
+ map<int,fit_space>::iterator iter=fit_space_map.find(nfit);
+ if(iter==fit_space_map.end())
+ {
+ return;
+ }
+ opt_utilities::freeze_param<double,double,std::vector<double> > fp(pname);
+ try
+ {
+ dynamic_cast<opt_utilities::freeze_param<double,double,vector<double> >& >(iter->second.fit.get_param_modifier())-=fp;
+ }
+ catch(opt_exception& e)
+ {
+ //iter->second.fit.set_param_modifier(fp);
+ }
+}
+
+void perform_fit_(const int& nfit)
+{
+ map<int,fit_space>::iterator iter=fit_space_map.find(nfit);
+ if(iter==fit_space_map.end())
+ {
+ return;
+ }
+ iter->second.fit.fit();
+}
+
+
+void get_param_(const int& nfit,double& r,const char* pname)
+{
+ map<int,fit_space>::iterator iter=fit_space_map.find(nfit);
+ if(iter==fit_space_map.end())
+ {
+ //return 0;
+ cerr<<"fit not found"<<endl;
+ r=0;
+ return;
+ }
+ // cerr<<"fdsaf"<<r<<endl;
+ r=iter->second.fit.get_param_value(pname);
+
+}
+
+
+
+}
+
diff --git a/interface/opt.h b/interface/opt.h
new file mode 100644
index 0000000..e9c3221
--- /dev/null
+++ b/interface/opt.h
@@ -0,0 +1,29 @@
+#ifndef OPT_H
+#define OPT_H
+#define F77
+#ifdef F77
+#define alloc_fit_ alloc_fit__
+#define free_fit_ free_fit__
+#define load_data_ load_data__
+#define set_model_ set_model__
+#define set_param_ set_param__
+#define freeze_param_ freeze_param__
+#define thaw_param_ thaw_param__
+#define perform_fit_ perform_fit__
+#define get_param_ get_param__
+#endif
+
+extern "C"
+{
+ void alloc_fit_(int&);
+ void free_fit_(const int& nxc);
+ void load_data_(const int& nfit,const int& ndatas,double* x,double* y,double* yl,double* yu=0,double* xl=0,double* xu=0);
+ void set_model_(const int& nfit,const char* model_name);
+ void set_param_(const int& nfit,const char* param_name,const double& value);
+ void freeze_param_(const int& nfit,const char* param_name);
+ void thraw_param_(const int& nfit,const char* param_name);
+ void perform_fit_(const int& nfit);
+ void get_param_(const int& nfit,double& r,const char* param_name);
+}
+
+#endif
diff --git a/makefile b/makefile
new file mode 100644
index 0000000..e40ac11
--- /dev/null
+++ b/makefile
@@ -0,0 +1,67 @@
+OPT_HEADS=models/beta1d.hpp statistics/chisq.hpp models/lin1d.hpp\
+ models/pl1d.hpp models/bl1d.hpp\
+ core/fitter.hpp models/models.hpp\
+ core/opt_traits.hpp\
+ methods/powell/powell_method.hpp models/bpl1d.hpp\
+ core/freeze_param.hpp\
+ models/gauss1d.hpp core/optimizer.hpp\
+ misc/bootstrap.hpp\
+ models/dl_model.hpp\
+ models/mul_model.hpp\
+ models/add_model.hpp\
+
+LDL=-ldl
+
+export CPP=g++
+export CC=gcc
+export AR = ar rv
+export RANLIB = ranlib
+export RM=rm -f
+export CFLAGS=-DNDEBUG -g -O2 -Wall -c -I .
+export CPPFLAGS=-DNDEBUG -g -O2 -Wall -c -I . --ansi -DHAVE_X_ERROR
+
+
+INC=-I. -I/usr/include/gsl/
+LIB= -L./muparser $(LDL) -lmuparser -g -lgsl -lgslcblas
+OPT_OBJ=models/models.o version_ctrl.o models/strmodel1d.o
+
+TARGET=liboptcall test_dl.so models/strmodel1d.o models/models.o
+
+all: $(TARGET)
+
+models/models.o:models/models.cc ${OPT_HEADS}
+ $(CPP) -c $< -o $@ ${INC} ${CPPFLAGS}
+
+version_ctrl.o:version_ctrl.cc
+ $(CPP) -c $< ${CPPFLAGS}
+
+bin/test.o:test.cc ${OPT_HEADS}
+ $(CPP) -c $< -o $@ ${INC} ${CPPFLAGS} --ansi
+
+test:${OPT_OBJ} bin/test.o
+ $(CPP) bin/test.o models/strmodel1d.o models/models.o version_ctrl.o -o $@ ${LIB}
+
+test_dl.so:models/dlmodel_template.c
+ gcc $< --shared -o $@
+
+
+models/strmodel1d.o:models/strmodel1d.cc models/strmodel1d.hpp
+ $(CPP) -c $< -o $@ -I./muparser $(INC) $(CPPFLAGS)
+
+
+libmuparser:
+ make -C muparser
+
+liboptcall:
+ make -C interface
+
+clean:
+ rm -f `find .|grep \~`
+ rm -f `find .|grep '\.o'`
+ rm -f muparser/libmuparser.a
+ make -C muparser clean
+ make -C interface clean
+
+distclean:clean
+ rm -f `find . -iname *.a`
+ rm -f $(TARGET)
diff --git a/methods/gsl_simplex/gsl_simplex.hpp b/methods/gsl_simplex/gsl_simplex.hpp
new file mode 100644
index 0000000..442c9f0
--- /dev/null
+++ b/methods/gsl_simplex/gsl_simplex.hpp
@@ -0,0 +1,199 @@
+#ifndef GSL_SIMPLEX_METHOD
+#define GSL_SIMPLEX_METHOD
+#include <core/optimizer.hpp>
+//#include <blitz/array.h>
+#include <vector>
+#include <limits>
+#include <cassert>
+#include <cmath>
+#include <algorithm>
+#include <gsl_multimin.h>
+/*
+ *
+*/
+#include <iostream>
+
+
+namespace opt_utilities
+{
+ template <typename rT,typename pT>
+ double gsl_func_adapter(const gsl_vector* v,void* params)
+ {
+ pT temp;
+ temp.resize(v->size);
+ for(size_t i=0;i<get_size(temp);++i)
+ {
+ set_element(temp,i,gsl_vector_get(v,i));
+ }
+ return ((func_obj<rT,pT>*)params)->eval(temp);
+ }
+
+
+ template <typename rT,typename pT>
+ class gsl_simplex
+ :public opt_method<rT,pT>
+ {
+ public:
+ typedef pT array1d_type;
+ typedef rT T;
+ private:
+ func_obj<rT,pT>* p_fo;
+ optimizer<rT,pT>* p_optimizer;
+
+ //typedef blitz::Array<rT,2> array2d_type;
+
+
+ private:
+ array1d_type start_point;
+ array1d_type end_point;
+
+ private:
+ rT threshold;
+ private:
+ rT func(const pT& x)
+ {
+ assert(p_fo!=0);
+ return p_fo->eval(x);
+ }
+
+
+ public:
+ gsl_simplex()
+ :threshold(1e-4)
+ {}
+
+ virtual ~gsl_simplex()
+ {
+ };
+
+ gsl_simplex(const gsl_simplex<rT,pT>& rhs)
+ :p_fo(rhs.p_fo),p_optimizer(rhs.p_optimizer),
+ start_point(rhs.start_point),
+ end_point(rhs.end_point),
+ threshold(rhs.threshold)
+ {
+ }
+
+ gsl_simplex<rT,pT>& operator=(const gsl_simplex<rT,pT>& rhs)
+ {
+ threshold=rhs.threshold;
+ p_fo=rhs.p_fo;
+ p_optimizer=rhs.p_optimizer;
+ opt_eq(start_point,rhs.start_point);
+ opt_eq(end_point,rhs.end_point);
+ }
+
+ opt_method<rT,pT>* do_clone()const
+ {
+ return new gsl_simplex<rT,pT>(*this);
+ }
+
+ void do_set_start_point(const array1d_type& p)
+ {
+ start_point.resize(get_size(p));
+ opt_eq(start_point,p);
+
+ }
+
+ void do_set_precision(rT t)
+ {
+ threshold=t;
+ }
+
+ void do_set_optimizer(optimizer<rT,pT>& o)
+ {
+ p_optimizer=&o;
+ p_fo=p_optimizer->ptr_func_obj();
+ }
+
+
+
+ pT do_optimize()
+ {
+ const gsl_multimin_fminimizer_type *T =
+ gsl_multimin_fminimizer_nmsimplex;
+ gsl_multimin_fminimizer *s = NULL;
+ gsl_vector *ss, *x;
+ gsl_multimin_function minex_func;
+
+ size_t iter = 0;
+ int status;
+ double size;
+
+ /* Starting point */
+ x = gsl_vector_alloc (get_size(start_point));
+ // gsl_vector_set (x, 0, 5.0);
+ //gsl_vector_set (x, 1, 7.0);
+ for(size_t i=0;i!=get_size(start_point);++i)
+ {
+ gsl_vector_set(x,i,get_element(start_point,i));
+ }
+
+
+ /* Set initial step sizes to 1 */
+ ss = gsl_vector_alloc (get_size(start_point));
+ gsl_vector_set_all (ss, 1.0);
+
+
+ //foo f;
+ /* Initialize method and iterate */
+ minex_func.n = get_size(start_point);
+ minex_func.f = &gsl_func_adapter<double,std::vector<double> >;
+ minex_func.params = (void *)p_fo;
+
+ s = gsl_multimin_fminimizer_alloc (T, get_size(start_point));
+ gsl_multimin_fminimizer_set (s, &minex_func, x, ss);
+
+ do
+ {
+ iter++;
+ status = gsl_multimin_fminimizer_iterate(s);
+
+ if (status)
+ break;
+ //std::cerr<<"threshold="<<threshold<<std::endl;
+ size = gsl_multimin_fminimizer_size (s);
+ status = gsl_multimin_test_size (size, threshold);
+
+ if (status == GSL_SUCCESS)
+ {
+ //printf ("converged to minimum at\n");
+ }
+
+ //printf ("%5d %10.3e %10.3ef f() = %7.3f size = %.3f\n",
+ //iter,
+ //gsl_vector_get (s->x, 0),
+ //gsl_vector_get (s->x, 1),
+ // s->fval, size);
+ }
+ while (status == GSL_CONTINUE && iter < 100);
+
+ /*
+ foo f;
+ gsl_vector_set (x, 0, 0.0);
+ gsl_vector_set (x, 1, 0.0);
+ cout<<"fdsa ";
+ cout<<gsl_func_adapter<double,vector<double> >(x,(void*)&f)<<endl;;
+
+ */
+
+ end_point.resize(get_size(start_point));
+ for(size_t i=0;i<get_size(start_point);++i)
+ {
+ set_element(end_point,i,gsl_vector_get(s->x,i));
+ }
+
+ gsl_vector_free(x);
+ gsl_vector_free(ss);
+ gsl_multimin_fminimizer_free (s);
+
+
+ return end_point;
+ }
+ };
+
+};
+
+
+#endif
+//EOF
diff --git a/methods/powell/bas_util.hpp b/methods/powell/bas_util.hpp
new file mode 100644
index 0000000..743dc3c
--- /dev/null
+++ b/methods/powell/bas_util.hpp
@@ -0,0 +1,63 @@
+#ifndef BAS_UTIL
+#define BAS_UTIL
+#include <core/opt_traits.hpp>
+namespace opt_utilities
+{
+ template <typename T>
+ T tabs(T x)
+ {
+ return T(x)<T(0)?T(-x):T(x);
+ }
+
+ template <typename T>
+ T sqr(T x)
+ {
+ return x*x;
+ }
+
+
+ template <typename T>
+ void shft3(T&a,T& b,T& c,T d)
+ {
+ opt_eq(a,b);
+ opt_eq(b,c);
+ opt_eq(c,d);
+ }
+
+ template <typename T>
+ void shft(T& a,T& b,T& c,T d)
+ {
+ opt_eq(a,b);
+ opt_eq(b,c);
+ opt_eq(c,d);
+ }
+ template <typename T>
+ void swap(T& ax,T& bx)
+ {
+ // swap(ax,bx);
+ T temp;
+ opt_eq(temp,ax);
+ opt_eq(ax,bx);
+ opt_eq(bx=temp);
+ }
+
+ template <typename T>
+ T sign(const T& a,const T& b)
+ {
+ return b>=0?T(a>=0?T(a):T(-a)):T(a>=0?T(-a):T(a));
+ }
+
+ template <typename T>
+ T max(T a,T b)
+ {
+ return b>a?T(b):T(a);
+ }
+
+ template <typename T>
+ void mov3(T& a,T& b,T& c, T& d,T& e,T& f)
+ {
+ opt_eq(a,d);opt_eq(b,e);opt_eq(c,f);
+ }
+}
+
+#endif
diff --git a/methods/powell/brent.hpp b/methods/powell/brent.hpp
new file mode 100644
index 0000000..cb3b962
--- /dev/null
+++ b/methods/powell/brent.hpp
@@ -0,0 +1,110 @@
+#ifndef BRENT_HPP
+#define BRENT_HPP
+#include <iostream>
+#include "bas_util.hpp"
+//#include "optimizer.hpp"
+namespace opt_utilities
+{
+ template<typename T>
+ T brent(T ax,T bx,T cx,func_obj<T,T>& f,T tol,T& xmin)
+ {
+ const int ITMAX=100;
+ const T CGOLD=0.3819660;
+ const T ZEPS=std::numeric_limits<T>::epsilon()*1.e-3;
+
+ int iter;
+ T a=0,b=0,d(0),etemp=0,fu=0,fv=0,fw=0,fx=0,p=0,q=0
+ ,r=0,tol1=0,tol2=0,u=0,v=0,w=0,x=0,xm=0;
+ T e=0.;
+ a=(ax<cx?ax:cx);
+ b=(ax>cx?ax:cx);
+ x=w=v=bx;
+ fw=fv=fx=f.eval(x);
+ for(iter=0;iter<ITMAX;++iter)
+ {
+ xm=.5*(a+b);
+ tol2=2.*(tol1=tol*tabs(x)+ZEPS);
+ if(tabs(T(x-xm))<=(tol2-.5*(b-a)))
+ {
+ xmin=x;
+ return fx;
+ }
+ if(tabs(e)>tol1)
+ {
+ r=(x-w)*(fx-fv);
+ q=(x-v)*(fx-fw);
+ p=(x-v)*q-(x-w)*r;
+ q=2.*(q-r);
+ if(q>0.)
+ {
+ p=-p;
+ }
+ q=tabs(q);
+ etemp=e;
+ e=d;
+ if(tabs(p)>=tabs(T(T(.5)*p*etemp))||p<=q*(a-x)||p>=q*(b-x))
+ {
+ d=CGOLD*(e=(x>=xm?a-x:b-x));
+ }
+ else
+ {
+ d=p/q;
+ u=x+d;
+ if(u-a<tol2||b-u<tol2)
+ {
+ d=sign(tol1,T(xm-x));
+ }
+ }
+
+ }
+ else
+ {
+ d=CGOLD*(e=(x>=xm?a-x:b-x));
+ }
+ u=(tabs(d)>=tol1?x+d:x+sign(tol1,d));
+ fu=f.eval(u);
+ if(fu<=fx)
+ {
+ if(u>=x)
+ {
+ a=x;
+ }
+ else
+ {
+ b=x;
+ }
+ shft3(v,w,x,u);
+ shft3(fv,fw,fx,fu);
+ }
+ else
+ {
+ if(u<x)
+ {
+ a=u;
+ }
+ else
+ {
+ b=u;
+ }
+ if(fu<=fw||w==x)
+ {
+ v=w;
+ w=u;
+ fv=fw;
+ fw=fu;
+ }
+ else if(fu<=fv||v==x||v==w)
+ {
+ v=u;
+ fv=fu;
+ }
+ }
+ }
+ std::cerr<<"Too many iterations in brent"<<std::endl;
+ xmin=x;
+ return fx;
+
+ }
+}
+
+#endif
diff --git a/methods/powell/linmin.hpp b/methods/powell/linmin.hpp
new file mode 100644
index 0000000..5ab5af0
--- /dev/null
+++ b/methods/powell/linmin.hpp
@@ -0,0 +1,102 @@
+#ifndef LINMIN_HPP
+#define LINMIN_HPP
+#include "mnbrak.hpp"
+#include "brent.hpp"
+#include <core/opt_traits.hpp>
+
+namespace opt_utilities
+{
+ template <typename rT,typename pT>
+ class func_adaptor
+ :public func_obj<rT,rT>
+ {
+ private:
+ const pT p1,xi1;
+ const func_obj<rT,pT>* pfoo;
+ func_adaptor(){}
+ func_adaptor(const func_adaptor&){}
+
+ public:
+ /*
+ void set_origin(pT& p2)
+ {
+ p1=p2;
+ }
+
+ void set_direction(pT& xi2)
+ {
+ xi1=xi2;
+ }
+
+ void set_func_obj(func_obj<rT,pT>& foo)
+ {
+ pfoo=&foo;
+ }*/
+ public:
+ func_adaptor(const pT& _p,const pT& _xi,const func_obj<rT,pT>& pf)
+ :p1(_p),xi1(_xi),pfoo(&pf)
+ {}
+
+ private:
+ func_obj<rT,rT>* do_clone()const
+ {
+ return new func_adaptor(*this);
+ }
+
+ rT do_eval(const rT& x)
+ {
+ //assert(p1.size()==xi1.size());
+
+ pT xt;
+ opt_eq(xt,p1);
+ for(size_t i=0;i<get_size(xt);++i)
+ {
+ //get_element(xt,i)+=x*get_element((pT)xi1,i);
+ set_element(xt,i,
+ get_element(xt,i)+x*get_element((pT)xi1,i));
+ //get_element((pT)xi1,i);
+ }
+ return const_cast<func_obj<rT,pT>&>(*pfoo).eval(xt);
+ //return x;
+ }
+ };
+
+
+ template<typename rT,typename pT>
+ void linmin(pT& p,pT& xi,rT& fret,func_obj<rT,pT>& func)
+ {
+
+ // assert(p.size()==10);
+ //assert(xi.size()==10);
+ func_adaptor<rT,pT> fadpt(p,xi,func);
+
+ int j=0;
+ const rT TOL=sqrt(std::numeric_limits<rT>::epsilon());
+ rT xx=0,xmin=0,fx=0,fb=0,fa=0,bx=0,ax=0;
+ int n=(int)get_size(p);
+
+
+ ax=0.;
+ xx=1.;
+
+
+ mnbrak(ax,xx,bx,fa,fx,fb,fadpt);
+ //cout<<xx<<endl;
+ fret=brent(ax,xx,bx,fadpt,TOL,xmin);
+ //cout<<xmin<<endl;
+ for(j=0;j<n;++j)
+ {
+ //get_element(xi,j)*=xmin;
+ set_element(xi,j,
+ get_element(xi,j)*xmin);
+ //get_element(p,j)+=get_element(xi,j);
+ set_element(p,j,
+ get_element(p,j)+get_element(xi,j));
+ }
+ // delete xicom_p;
+ //delete pcom_p;
+ }
+}
+
+
+#endif
diff --git a/methods/powell/mnbrak.hpp b/methods/powell/mnbrak.hpp
new file mode 100644
index 0000000..4887bec
--- /dev/null
+++ b/methods/powell/mnbrak.hpp
@@ -0,0 +1,81 @@
+#ifndef MNBRAK_HPP
+#define MNBRAK_HPP
+//#include "optimizer.hpp"
+#include "bas_util.hpp"
+namespace opt_utilities
+{
+
+
+ template <typename T>
+ void mnbrak(T& ax,T& bx,T& cx,T& fa,T& fb,T& fc,func_obj<T,T>& func)
+ {
+ const T GOLD=1.618034;
+ const T GLIMIT=100;
+ const T TINY=std::numeric_limits<T>::epsilon();
+ T ulim,u,r,q,fu;
+ fa=func.eval(ax);
+ fb=func.eval(bx);
+
+ if(fb>fa)
+ {
+ //shft(dum,ax,bx,dum);
+ //shft(dum,fb,fa,dum);
+ std::swap(ax,bx);
+ std::swap(fa,fb);
+ }
+
+ cx=bx+GOLD*(bx-ax);
+ fc=func.eval(cx);
+ while(fb>fc)
+ {
+ r=(bx-ax)*(fb-fc);
+ q=(bx-cx)*(fb-fa);
+ u=bx-T((bx-cx)*q-(bx-ax)*r)/
+ T(T(2.)*sign(T(max(T(tabs(T(q-r))),T(TINY))),T(q-r)));
+ ulim=bx+GLIMIT*(cx-bx);
+ if((bx-u)*(u-cx)>0.)
+ {
+ fu=func.eval(u);
+ if(fu<fc)
+ {
+ ax=bx;
+ bx=u;
+ fa=fb;
+ fb=fu;
+ return;
+ }
+ else if(fu>fb)
+ {
+ cx=u;
+ fc=fu;
+ return;
+ }
+ u=cx+GOLD*(cx-bx);
+ fu=func.eval(u);
+ }
+ else if((cx-u)*(u-ulim)>0.)
+ {
+ fu=func.eval(u);
+ if(fu<fc)
+ {
+ shft3(bx,cx,u,T(cx+GOLD*(cx-bx)));
+ shft3(fb,fc,fu,func.eval(u));
+ }
+ }
+ else if((u-ulim)*(ulim-cx)>=0)
+ {
+ u=ulim;
+ fu=func.eval(u);
+ }
+ else
+ {
+ u=cx+GOLD*(cx-bx);
+ fu=func.eval(u);
+ }
+ shft3(ax,bx,cx,u);
+ shft3(fa,fb,fc,fu);
+ }
+ }
+}
+
+#endif
diff --git a/methods/powell/powell_method.hpp b/methods/powell/powell_method.hpp
new file mode 100644
index 0000000..bec12b7
--- /dev/null
+++ b/methods/powell/powell_method.hpp
@@ -0,0 +1,251 @@
+#ifndef POWELL_METHOD
+#define POWELL_METHOD
+#include <core/optimizer.hpp>
+//#include <blitz/array.h>
+#include <limits>
+#include <cassert>
+#include <cmath>
+#include "linmin.hpp"
+#include <algorithm>
+/*
+ *
+*/
+#include <iostream>
+
+namespace opt_utilities
+{
+ /*
+ template <typename T>
+ T tabs(T x)
+ {
+ return x<0?-x:x;
+ }
+ */
+
+ template <typename rT,typename pT>
+ class powell_method
+ :public opt_method<rT,pT>
+ {
+ public:
+ typedef pT array1d_type;
+ typedef rT T;
+ private:
+ func_obj<rT,pT>* p_fo;
+ optimizer<rT,pT>* p_optimizer;
+
+ //typedef blitz::Array<rT,2> array2d_type;
+
+
+ private:
+ array1d_type start_point;
+ array1d_type end_point;
+
+ private:
+ int ncom;
+ array1d_type pcom_p;
+ array1d_type xicom_p;
+ rT threshold;
+ T** xi;
+ T* xi_1d;
+ private:
+ rT func(const pT& x)
+ {
+ assert(p_fo!=0);
+ return p_fo->eval(x);
+ }
+
+
+ private:
+ void clear_xi()
+ {
+ if(xi_1d!=0)
+ {
+ delete[] xi_1d;
+ }
+ if(xi!=0)
+ {
+ delete[] xi;
+ }
+ }
+
+ void init_xi(int n)
+ {
+ clear_xi();
+ xi_1d=new T[n*n];
+ xi=new T*[n];
+ for(int i=0;i!=n;++i)
+ {
+ xi[i]=xi_1d+i*n;
+ }
+ for(int i=0;i!=n;++i)
+ {
+ for(int j=0;j!=n;++j)
+ {
+ xi[i][j]=(j==i?1:0);
+ }
+ }
+ }
+
+
+
+ void powell(array1d_type& p,const T ftol,
+ int& iter,T& fret)
+ {
+ const int ITMAX=200;
+ const T TINY=std::numeric_limits<T>::epsilon();
+ int i,j,ibig;
+ T del,fp,fptt,t;
+ int n=(int)get_size(p);
+ array1d_type pt(n);
+ array1d_type ptt(n);
+ array1d_type xit(n);
+ fret=p_fo->eval(p);
+
+ for(j=0;j<n;++j)
+ {
+ //get_element(pt,j)=get_element(p,j);
+ set_element(pt,j,get_element(p,j));
+ }
+ for(iter=0;;++iter)
+ {
+ fp=fret;
+ ibig=0;
+ del=0.0;
+ for(i=0;i<n;++i)
+ {
+ for(j=0;j<n;++j)
+ {
+ //get_element(xit,j)=xi[j][i];
+ set_element(xit,j,xi[j][i]);
+ }
+ fptt=fret;
+ linmin(p,xit,fret,(*p_fo));
+ if((fptt-fret)>del)
+ {
+ del=fptt-fret;
+ ibig=i+1;
+ }
+ }
+ if(T(2.)*(fp-fret)<=ftol*(tabs(fp)+tabs(fret))+TINY)
+ {
+ return;
+ }
+ if(iter==ITMAX)
+ {
+ std::cerr<<"powell exceeding maximun iterations."<<std::endl;
+ return;
+ }
+ for(j=0;j<n;++j)
+ {
+ //get_element(ptt,j)=T(2.)*get_element(p,j)-get_element(pt,j);
+ set_element(ptt,j,T(2.)*get_element(p,j)-get_element(pt,j));
+ //get_element(xit,j)=
+ //get_element(p,j)-get_element(pt,j);
+ set_element(xit,j,get_element(p,j)-get_element(pt,j));
+ //get_element(pt,j)=get_element(p,j);
+ set_element(pt,j,get_element(p,j));
+ }
+ fptt=func(ptt);
+ if(fptt<fp)
+ {
+ t=T(2.)*(fp-T(2.)*fret+fptt)*sqr(T(fp-fret-del))-del*sqr(T(fp-fptt));
+ if(t<T(0.))
+ {
+ linmin(p,xit,fret,*p_fo);
+ for(j=0;j<n;++j)
+ {
+ xi[j][ibig-1]=xi[j][n-1];
+ xi[j][n-1]=get_element(xit,j);
+
+ }
+ }
+ }
+ }
+ }
+
+
+ public:
+
+ powell_method()
+ :threshold(1e-4),xi(0),xi_1d(0)
+ {}
+
+ virtual ~powell_method()
+ {
+ clear_xi();
+ };
+
+ powell_method(const powell_method<rT,pT>& rhs)
+ :p_fo(rhs.p_fo),p_optimizer(rhs.p_optimizer),
+ start_point(rhs.start_point),
+ end_point(rhs.end_point),
+ ncom(rhs.ncom),
+ threshold(rhs.threshold),xi(0),xi_1d(0)
+ {
+ }
+
+ powell_method<rT,pT>& operator=(const powell_method<rT,pT>& rhs)
+ {
+ threshold=rhs.threshold;
+ xi=0;
+ xi_1d=0;
+ p_fo=rhs.p_fo;
+ p_optimizer=rhs.p_optimizer;
+ start_point=rhs.start_point;
+ end_point=rhs.end_point;
+ ncom=rhs.ncom;
+ threshold=rhs.threshold;
+ }
+
+ opt_method<rT,pT>* do_clone()const
+ {
+ return new powell_method<rT,pT>(*this);
+ }
+
+ void do_set_start_point(const array1d_type& p)
+ {
+ resize(start_point,get_size(p));
+ opt_eq(start_point,p);
+
+ }
+
+ void do_set_precision(rT t)
+ {
+ threshold=t;
+ }
+
+ void do_set_optimizer(optimizer<rT,pT>& o)
+ {
+ p_optimizer=&o;
+ p_fo=p_optimizer->ptr_func_obj();
+ }
+
+
+
+ pT do_optimize()
+ {
+
+ init_xi((int)get_size(start_point));
+
+
+ for(int i=0;i<(int)get_size(start_point);++i)
+ {
+ for(int j=0;j<(int)get_size(start_point);++j)
+ {
+ xi[i][j]=(i==j)?1:0;
+ }
+ }
+
+ int iter=100;
+ opt_eq(end_point,start_point);
+ rT fret;
+ powell(end_point,threshold,iter,fret);
+ return end_point;
+ }
+ };
+
+};
+
+
+#endif
+//EOF
diff --git a/misc/bootstrap.hpp b/misc/bootstrap.hpp
new file mode 100644
index 0000000..b46748d
--- /dev/null
+++ b/misc/bootstrap.hpp
@@ -0,0 +1,132 @@
+#ifndef BOOT_STRIP
+#define BOOT_STRIP
+#include <core/fitter.hpp>
+#include <vector>
+#include <cstdlib>
+#include <iostream>
+#include <utility>
+#include <algorithm>
+#include <core/default_data_set.hpp>
+using std::cout;
+namespace opt_utilities
+{
+ template <typename Ty,typename Tx,typename Tp>
+ class bootstrap
+ {
+ private:
+ Ty rand_norm(Ty y0,Ty y_err)const
+ {
+ Ty y;
+ do
+ {
+ y=(rand()/(Ty)RAND_MAX-(Ty).5)*(10*y_err)+y0;
+ }
+ while(rand()/(Ty)RAND_MAX>exp(-(y-y0)*(y-y0)/(y_err*y_err)));
+ return y;
+
+ }
+ public:
+ std::vector<Tp> param_pool;
+ default_data_set<Ty,Tx> current_data_set;
+ default_data_set<Ty,Tx> origin_data_set;
+ fitter<Ty,Tx,Tp>* p_fitter;
+ Tp origin_param;
+ public:
+ bootstrap()
+ :p_fitter(NULL)
+ {}
+
+ void set_fitter(fitter<Ty,Tx,Tp>& pf)
+ {
+ param_pool.clear();
+ p_fitter=&pf;
+ origin_data_set=dynamic_cast<const default_data_set<Ty,Tx>&>(pf.datas());
+ origin_param=pf.get_all_params();
+ }
+
+
+
+ void sample(int n)
+ {
+ if(p_fitter!=NULL)
+ {
+ for(int i=0;i<n;++i)
+ {
+ sample();
+ }
+
+ p_fitter->load_data(origin_data_set);
+ p_fitter->set_param_value(origin_param);
+ }
+ else
+ {
+ throw opt_exception("Fitter unset");
+ }
+ }
+
+ const Tp& get_param(int i)const
+ {
+ return param_pool.at(i);
+ }
+
+ private:
+ void sample()
+ {
+ current_data_set=default_data_set<Ty,Tx>();
+ for(int i=0;i<origin_data_set.size();++i)
+ {
+ data<Ty,Tx> d;
+ d=origin_data_set.get_data(i);
+ d.set_y(rand_norm(d.get_y(),(d.get_y_upper_err()+d.get_y_lower_err())/2));
+ current_data_set.push_back(d);
+ }
+ p_fitter->load_data(current_data_set);
+ p_fitter->set_param_value(origin_param);
+ param_pool.push_back(p_fitter->fit());
+ for(size_t i=0;i<(param_pool.back()).size();++i)
+ {
+ cout<<param_pool.back()[i]<<",";
+ }
+ std::cout<<std::endl;
+ }
+
+ public:
+ std::pair<typename element_type_trait<Tp>::element_type,typename element_type_trait<Tp>::element_type>
+ interval(std::string param_name,double level)
+ {
+ if(p_fitter==NULL)
+ {
+ throw opt_exception("Fitter unset");
+ }
+ if(param_pool.empty())
+ {
+ throw opt_exception("Bootstrap not done");
+ }
+ //sample();
+ std::vector<typename element_type_trait<Tp>::element_type> _tmp;
+ int order=p_fitter->get_param_order(param_name);
+ for(typename std::vector<Tp>::iterator i=param_pool.begin();
+ i!=param_pool.end();++i)
+ {
+ _tmp.push_back((*i)[order]);
+ }
+ sort(_tmp.begin(),_tmp.end());
+ std::pair<typename std::vector<typename element_type_trait<Tp>::element_type>::iterator,
+ typename std::vector<typename element_type_trait<Tp>::element_type>::iterator>
+ itv=equal_range(_tmp.begin(),_tmp.end(),origin_param[order]);
+ int current_param_position=itv.second-_tmp.begin();
+ std::cout<<_tmp.size()<<std::endl;
+ return std::pair<typename element_type_trait<Tp>::element_type,
+ typename element_type_trait<Tp>::element_type>(
+ _tmp.at((int)((1-level)*current_param_position)),
+ _tmp.at((int)(current_param_position+level*(_tmp.size()-current_param_position)))
+ );
+
+ }
+
+ };
+
+};
+
+#endif
+//EOF
diff --git a/misc/data_loaders.hpp b/misc/data_loaders.hpp
new file mode 100644
index 0000000..6d2195d
--- /dev/null
+++ b/misc/data_loaders.hpp
@@ -0,0 +1,180 @@
+#ifndef DATA_LOADERS_H
+#define DATA_LOADERS_H
+#include <core/fitter.hpp>
+#include <core/default_data_set.hpp>
+#include <iostream>
+#include <fstream>
+#include <cmath>
+
+namespace opt_utilities
+{
+ template <typename Ty,typename Tx>
+ class dl_x_y_ye;
+
+ template <typename Ty,typename Tx>
+ std::istream& operator>>(std::istream& ifs,dl_x_y_ye<Ty,Tx>& dl);
+
+ template <typename Ty,typename Tx>
+ class dl_x_xe_y_ye;
+
+ template <typename Ty,typename Tx>
+ std::istream& operator>>(std::istream& ifs,dl_x_xe_y_ye<Ty,Tx>& dl);
+
+ template <typename Ty,typename Tx>
+ class dl_x_xu_xl_y_yu_yl;
+
+ template <typename Ty,typename Tx>
+ std::istream& operator>> (std::istream& ifs,dl_x_xu_xl_y_yu_yl<Ty,Tx>& dl);
+
+ template <typename Ty,typename Tx>
+ class dl_x_y_ye
+ {
+ private:
+ default_data_set<Ty,Tx> ds;
+ public:
+ data_set<Ty,Tx>& get_data_set()
+ {
+ return ds;
+ }
+
+ void load_from(std::istream& ifs)
+ {
+ for(;;)
+ {
+ Tx x;
+ Tx x_err;
+ Ty y;
+ Ty y_err(1);
+
+ ifs>>x>>y>>y_err;
+
+ if(!ifs.good())
+ {
+ break;
+ }
+ data<Ty,Tx> d(x,y,y_err,y_err,x_err,x_err);
+ ds.push_back(d);
+ }
+ //return ifs;
+ }
+
+ void load_from(const char* name)
+ {
+ std::ifstream ifs(name);
+ load_from(ifs);
+
+ }
+ //friend std::istream& operator>> <>(std::istream& ifs,dl_x_y_ye<Ty,Tx>& dl);
+ };
+
+ template <typename Ty,typename Tx>
+ std::istream& operator>>(std::istream& ifs,dl_x_y_ye<Ty,Tx>& dl)
+ {
+ dl.load_from(ifs);
+ return ifs;
+ }
+
+
+ template <typename Ty,typename Tx>
+ class dl_x_xe_y_ye
+ {
+ private:
+ default_data_set<Ty,Tx> ds;
+ public:
+ data_set<Ty,Tx>& get_data_set()
+ {
+ return ds;
+ }
+
+ void load_from(std::istream& ifs)
+ {
+ for(;;)
+ {
+ Tx x;
+ Tx x_err;
+ Ty y;
+ Ty y_err(1);
+
+ ifs>>x>>x_err>>y>>y_err;
+
+ if(!ifs.good())
+ {
+ break;
+ }
+ data<Ty,Tx> d(x,y,y_err,y_err,x_err,x_err);
+ ds.push_back(d);
+ }
+ }
+
+ void load_from(const char* name)
+ {
+ std::ifstream ifs(name);
+ load_from(ifs);
+ }
+ };
+
+ template <typename Ty,typename Tx>
+ std::istream& operator>>(std::istream& ifs,dl_x_xe_y_ye<Ty,Tx>& dl)
+ {
+ dl.load_from(ifs);
+ return ifs;
+ }
+
+ template <typename Ty,typename Tx>
+ class dl_x_xu_xl_y_yu_yl
+ {
+ private:
+
+ default_data_set<Ty,Tx> ds;
+ public:
+ data_set<Ty,Tx>& get_data_set()
+ {
+ return ds;
+ }
+
+ void load_from(std::istream& ifs)
+ {
+ for(;;)
+ {
+ Tx x;
+ Tx xl,xu;
+ Ty y;
+ Ty yl(1),yu(1);
+
+ ifs>>x>>xu>>xl>>y>>yu>>yl;
+
+ xu=std::abs(xu);
+ xl=std::abs(xl);
+ yu=std::abs(yu);
+ yl=std::abs(yl);
+
+ if(!ifs.good())
+ {
+ break;
+ }
+ data<Ty,Tx> d(x,y,yl,yu,xl,xu);
+ ds.push_back(d);
+ }
+ }
+
+ void load_from(const char* name)
+ {
+ std::ifstream ifs(name);
+ load_from(ifs);
+ }
+ };
+
+ template <typename Ty,typename Tx>
+ std::istream& operator>> (std::istream& ifs,dl_x_xu_xl_y_yu_yl<Ty,Tx>& dl)
+ {
+ dl.load_from(ifs);
+ return ifs;
+ }
+
+
+
+}
+
+
+#endif
+//EOF
diff --git a/models/add_model.hpp b/models/add_model.hpp
new file mode 100644
index 0000000..ffac9dc
--- /dev/null
+++ b/models/add_model.hpp
@@ -0,0 +1,169 @@
+#ifndef ADD_MODEL_H_
+#define ADD_MODEL_H_
+#include <core/fitter.hpp>
+#include <cmath>
+
+namespace opt_utilities
+{
+ template <typename Ty,typename Tx,typename Tp,typename Tstr>
+ class add_model
+ :public model<Ty,Tx,Tp,Tstr>
+ {
+ private:
+ model<Ty,Tx,Tp,Tstr>* do_clone()const
+ {
+ return new add_model<Ty,Tx,Tp,Tstr>(*this);
+ }
+ private:
+ add_model()
+ {
+ }
+
+ private:
+ model<Ty,Tx,Tp,Tstr>* pm1;
+ model<Ty,Tx,Tp,Tstr>* pm2;
+
+ public:
+ add_model(const model<Ty,Tx,Tp,Tstr>& m1,
+ const model<Ty,Tx,Tp,Tstr>& m2)
+ :pm1(m1.clone()),pm2(m2.clone())
+ {
+ int np1=m1.get_num_params();
+ int np2=m2.get_num_params();
+ for(int i=0;i<np1;++i)
+ {
+ param_info<Tp,Tstr> p(m1.get_param_info(i));
+ param_info<Tp,Tstr> p1(p.get_name()+"1",p.get_default_value());
+ this->push_param_info(p1);
+ }
+ for(int i=0;i<np2;++i)
+ {
+ param_info<Tp,Tstr> p(m2.get_param_info(i));
+ param_info<Tp,Tstr> p2(p.get_name()+"2",p.get_default_value());
+ this->push_param_info(p2);
+ }
+ }
+
+ add_model(const add_model& rhs)
+ :pm1(NULL),pm2(NULL)
+ {
+ int np1(0),np2(0);
+ if(rhs.pm1)
+ {
+ pm1=rhs.pm1->clone();
+ np1=rhs.pm1->get_num_params();
+ for(int i=0;i<np1;++i)
+ {
+ param_info<Tp,Tstr> p(rhs.pm1->get_param_info(i));
+ param_info<Tp,Tstr> p1(p.get_name()+"1",p.get_default_value());
+ this->push_param_info(p1);
+ }
+ }
+ if(rhs.pm2)
+ {
+ pm2=rhs.pm2->clone();
+ np2=rhs.pm2->get_num_params();
+ for(int i=0;i<np2;++i)
+ {
+ param_info<Tp,Tstr> p(rhs.pm2->get_param_info(i));
+ param_info<Tp,Tstr> p2(p.get_name()+"2",p.get_default_value());
+ this->push_param_info(p2);
+ }
+ }
+ }
+
+ add_model& operator=(const add_model& rhs)
+ {
+ if(this==&rhs)
+ {
+ return *this;
+ }
+ if(!pm1)
+ {
+ //delete pm1;
+ pm1->destroy();
+ }
+ if(!pm2)
+ {
+ //delete pm2;
+ pm2->destroy();
+ }
+ int np1(0),np2(0);
+ if(rhs.pm1)
+ {
+ pm1=rhs.pm1->clone();
+ np1=rhs.pm1->get_num_params();
+ for(int i=0;i<np1;++i)
+ {
+ param_info<Tp,Tstr> p(rhs.pm1->get_param_info(i));
+ param_info<Tp,Tstr> p1(p.get_name()+"1",p.get_default_value());
+ this->push_param_info(p1);
+ }
+ }
+ if(rhs.pm2)
+ {
+ pm2=rhs.pm2->clone();
+ np2=rhs.pm2->get_num_params();
+ for(int i=0;i<np2;++i)
+ {
+ param_info<Tp,Tstr> p(rhs.pm2->get_param_info(i));
+ param_info<Tp,Tstr> p2(p.get_name()+"2",p.get_default_value());
+ this->push_param_info(p2);
+ }
+ }
+ return *this;
+ }
+
+ ~add_model()
+ {
+ if(!pm1)
+ {
+ //delete pm1;
+ pm1->destroy();
+ }
+ if(!pm2)
+ {
+ //delete pm2;
+ pm2->destroy();
+ }
+ }
+
+ public:
+ Ty do_eval(const Tx& x,const Tp& param)
+ {
+ if(!pm1)
+ {
+ throw opt_exception("incomplete model!");
+ }
+ if(!pm2)
+ {
+ throw opt_exception("incomplete model!");
+ }
+ Tp p1(pm1->get_num_params());
+ Tp p2(pm2->get_num_params());
+ int i=0;
+ int j=0;
+ for(i=0;i<pm1->get_num_params();++i,++j)
+ {
+ set_element(p1,i,get_element(param,j));
+ }
+ for(i=0;i<pm2->get_num_params();++i,++j)
+ {
+ set_element(p2,i,get_element(param,j));
+ }
+ return pm1->eval(x,p1)+pm2->eval(x,p2);
+ }
+ };
+
+ template <typename Ty,typename Tx,typename Tp,typename Tstr>
+ add_model<Ty,Tx,Tp,Tstr> operator+(const model<Ty,Tx,Tp,Tstr>& m1,
+ const model<Ty,Tx,Tp,Tstr>& m2)
+ {
+ return add_model<Ty,Tx,Tp,Tstr>(m1,m2);
+ }
+};
+
+
+
+#endif
+//EOF
diff --git a/models/beta1d.hpp b/models/beta1d.hpp
new file mode 100644
index 0000000..e18aa34
--- /dev/null
+++ b/models/beta1d.hpp
@@ -0,0 +1,49 @@
+#ifndef BETA_MODEL_H_
+#define BETA_MODEL_H_
+#include <core/fitter.hpp>
+#include <cmath>
+#include <iostream>
+
+namespace opt_utilities
+{
+ template <typename T>
+ class beta1d
+ :public model<T,T,std::vector<T>,std::string>
+ {
+ private:
+ model<T,T,std::vector<T> >* do_clone()const
+ {
+ return new beta1d<T>(*this);
+ }
+ public:
+ beta1d()
+ {
+ this->push_param_info(param_info<std::vector<T> >("S0",1));
+ this->push_param_info(param_info<std::vector<T> >("rc",10));
+ this->push_param_info(param_info<std::vector<T> >("beta",2./3.));
+ this->push_param_info(param_info<std::vector<T> >("bkg",0));
+ }
+
+
+ T do_eval(const T& x,const std::vector<T>& param)
+ {
+ T S0=get_element(param,0);
+ T r_c=get_element(param,1);
+ T beta=get_element(param,2);
+ T bkg=get_element(param,3);
+
+ return bkg+S0*pow(1+(x*x)/(r_c*r_c),-3*beta+static_cast<T>(.5));
+ }
+
+ std::string do_to_string()const
+ {
+ return "Beta model\n"
+ "S=S0*(1+(r/rc)^2)^(-3*beta+0.5)\n";
+ }
+ };
+};
+
+
+
+#endif
+//EOF
diff --git a/models/beta2d.hpp b/models/beta2d.hpp
new file mode 100644
index 0000000..abb6da1
--- /dev/null
+++ b/models/beta2d.hpp
@@ -0,0 +1,60 @@
+#ifndef BETA_MODEL2d_H_
+#define BETA_MODEL2d_H_
+#include <core/fitter.hpp>
+#include <cmath>
+#include <cassert>
+#include "vecn.hpp"
+
+
+namespace opt_utilities
+{
+
+ template <typename T>
+ class beta2d
+ :public model<T,vecn<T,2>,std::vector<T>,std::string>
+ {
+ private:
+ model<T,vecn<T,2>,std::vector<T> >* do_clone()const
+ {
+ return new beta2d<T>(*this);
+ }
+ public:
+ beta2d()
+ {
+ this->push_param_info(param_info<std::vector<T> >("S0",1));
+ this->push_param_info(param_info<std::vector<T> >("rc1",100));
+ this->push_param_info(param_info<std::vector<T> >("rc2",100));
+ this->push_param_info(param_info<std::vector<T> >("rho",0));
+ this->push_param_info(param_info<std::vector<T> >("x0",100));
+ this->push_param_info(param_info<std::vector<T> >("y0",100));
+ this->push_param_info(param_info<std::vector<T> >("beta",2./3.));
+ this->push_param_info(param_info<std::vector<T> >("bkg",0));
+ }
+
+
+ T do_eval(const vecn<T,2>& xy,const std::vector<T>& param)
+ {
+ T S0=get_element(param,0);
+ T rc1=get_element(param,1);
+ T rc2=get_element(param,2);
+ T rho=get_element(param,3);
+ T x0=get_element(param,4);
+ T y0=get_element(param,5);
+ T beta=get_element(param,6);
+ T bkg=get_element(param,7);
+ T x=xy[0];
+ T y=xy[1];
+
+ T r=(x-x0)*(x-x0)/(rc1*rc1)+(y-y0)*(y-y0)/(rc2*rc2)
+ -2*rho*(x-x0)*(y-y0)/(rc1*rc2);
+ r=r<0?0:r;
+
+ return bkg+S0*pow(1+r,-3*beta+static_cast<T>(.5));
+ }
+ };
+};
+
+
+
+#endif
+//EOF
diff --git a/models/beta2d2.hpp b/models/beta2d2.hpp
new file mode 100644
index 0000000..bb473a3
--- /dev/null
+++ b/models/beta2d2.hpp
@@ -0,0 +1,73 @@
+#ifndef BETA_MODEL2d2_H_
+#define BETA_MODEL2d2_H_
+#include <core/fitter.hpp>
+#include <cmath>
+#include <cassert>
+#include "vecn.hpp"
+
+
+namespace opt_utilities
+{
+
+ template <typename T>
+ class beta2d2
+ :public model<T,vecn<T,2>,std::vector<T>,std::string>
+ {
+ private:
+ model<T,vecn<T,2>,std::vector<T> >* do_clone()const
+ {
+ return new beta2d2<T>(*this);
+ }
+ public:
+ beta2d2()
+ {
+ this->push_param_info(param_info<std::vector<T> >("r0",20));
+ this->push_param_info(param_info<std::vector<T> >("x0",100));
+ this->push_param_info(param_info<std::vector<T> >("y0",100));
+ this->push_param_info(param_info<std::vector<T> >("epsilon",0));
+ this->push_param_info(param_info<std::vector<T> >("theta",100));
+ this->push_param_info(param_info<std::vector<T> >("ampl",3));
+ this->push_param_info(param_info<std::vector<T> >("beta",2./3.));
+ this->push_param_info(param_info<std::vector<T> >("bkg",0));
+ }
+
+
+ T do_eval(const vecn<T,2>& xy,const std::vector<T>& param)
+ {
+ T x=xy[0];
+ T y=xy[1];
+
+ T r0=get_element(param,0);
+ T x0=get_element(param,1);
+ T y0=get_element(param,2);
+ T epsilon=get_element(param,3);
+ T theta=get_element(param,4);
+ T ampl=get_element(param,5);
+ T beta=get_element(param,6);
+ T bkg=get_element(param,7);
+
+ T x_new=(x-x0)*cos(theta)+(y-y0)*sin(theta);
+ T y_new=(y-y0)*cos(theta)-(x-x0)*sin(theta);
+
+ //T _epsilon=sin(epsilon)-0.00001;
+
+ T _epsilon=epsilon;
+
+ // T r=sqrt(x_new*x_new*(1-_epsilon)*(1-_epsilon)
+ // + y_new*y_new);
+
+ //r/=(1-_epsilon);
+ T r_r=x_new*x_new/exp(_epsilon)+y_new*y_new/exp(-_epsilon);
+
+
+ return bkg+ampl*pow(1+r_r/r0/r0,-3*beta+static_cast<T>(.5));
+ }
+
+
+ };
+};
+
+
+
+#endif
+//EOF
diff --git a/models/bl1d.hpp b/models/bl1d.hpp
new file mode 100644
index 0000000..bd0ce7d
--- /dev/null
+++ b/models/bl1d.hpp
@@ -0,0 +1,56 @@
+#ifndef BROKEN_LINE_MODEL_H_
+#define BROKEN_LINE_MODEL_H_
+#include <core/fitter.hpp>
+#include <cmath>
+
+namespace opt_utilities
+{
+ template <typename T>
+ class bl1d
+ :public model<T,T,std::vector<T>,std::string>
+ {
+ private:
+ model<T,T,std::vector<T> >* do_clone()const
+ {
+ return new bl1d<T>(*this);
+ }
+ public:
+ bl1d()
+ {
+ this->push_param_info(param_info<std::vector<T> >("break point y value",1));
+ this->push_param_info(param_info<std::vector<T> >("break point x value",1));
+ this->push_param_info(param_info<std::vector<T> >("slop 1",1));
+ this->push_param_info(param_info<std::vector<T> >("slop 2",1));
+ }
+
+ public:
+ T do_eval(const T& x,const std::vector<T>& param)
+ {
+ T x_b=get_element(param,0);
+ T f_b=get_element(param,1);
+ T k1=get_element(param,2);
+ T k2=get_element(param,3);
+ if(x<x_b)
+ {
+ return k1*(x-x_b)+f_b;
+ }
+ else
+ {
+ return k2*(x-x_b)+f_b;
+ }
+ }
+
+ private:
+ std::string do_to_string()const
+ {
+ return "broken linear model\n"
+ "y=k1*(x-x_b)+y_b for x<x_b\n"
+ "y=k2*(x-x_b)+y_b otherwise\n";
+ }
+ };
+};
+
+
+
+#endif
+//EOF
diff --git a/models/bpl1d.hpp b/models/bpl1d.hpp
new file mode 100644
index 0000000..faf1336
--- /dev/null
+++ b/models/bpl1d.hpp
@@ -0,0 +1,56 @@
+#ifndef BROKEN_POWER_LAW_MODEL_H_
+#define BROKEN_POWER_LAW_MODEL_H_
+#include <core/fitter.hpp>
+#include <cmath>
+
+namespace opt_utilities
+{
+ template <typename T>
+ class bpl1d
+ :public model<T,T,std::vector<T>,std::string>
+ {
+ private:
+ model<T,T,std::vector<T> >* do_clone()const
+ {
+ return new bpl1d<T>(*this);
+ }
+ public:
+ bpl1d()
+ {
+ this->push_param_info(param_info<std::vector<T> >("bpx",1));
+ this->push_param_info(param_info<std::vector<T> >("bpy",1));
+ this->push_param_info(param_info<std::vector<T> >("gamma1",1));
+ this->push_param_info(param_info<std::vector<T> >("gamma2",1));
+ }
+
+ T do_eval(const T& x,const std::vector<T>& param)
+ {
+ T x_b=get_element(param,0);
+ T f_b=get_element(param,1);
+ T gamma1=get_element(param,2);
+ T gamma2=get_element(param,3);
+ if(x<x_b)
+ {
+ return f_b*pow(x,gamma1)/pow(x_b,gamma1);
+ }
+ else
+ {
+ return f_b*pow(x,gamma2)/pow(x_b,gamma2);
+ }
+ }
+
+
+ private:
+ std::string do_to_string()const
+ {
+ return "broken power law\n"
+ "y=y_b*(x/x_b)^gamma1 for x<x_b\n"
+ "y=y_b*(x/x_b)^gamma2 otherwise\n";
+ }
+ };
+};
+
+
+
+#endif
+//EOF
diff --git a/models/bremss.hpp b/models/bremss.hpp
new file mode 100644
index 0000000..9956a3e
--- /dev/null
+++ b/models/bremss.hpp
@@ -0,0 +1,44 @@
+#ifndef BREMSS_MODEL_H_
+#define BREMSS_MODEL_H_
+#include <core/fitter.hpp>
+#include <cmath>
+
+namespace opt_utilities
+{
+ template <typename T>
+ class bremss
+ :public model<T,T,std::vector<T>,std::string>
+ {
+ private:
+ model<T,T,std::vector<T> >* do_clone()const
+ {
+ return new bremss<T>(*this);
+ }
+ public:
+ bremss()
+ {
+ this->push_param_info(param_info<std::vector<T> >("norm",1));
+ this->push_param_info(param_info<std::vector<T> >("kT",1));
+ }
+
+ T do_eval(const T& x,const std::vector<T>& param)
+ {
+ T norm=get_element(param,0);
+ T kT=get_element(param,1);
+
+ return norm*sqrt(kT)*exp(-x/kT);
+ }
+
+ private:
+ std::string do_to_string()const
+ {
+ return "Simplified bremss model\n"
+ "flux=norm*kT^0.5*e^{-E/kT}\n";
+ }
+ };
+};
+
+
+
+#endif
+//EOF
diff --git a/models/constant.hpp b/models/constant.hpp
new file mode 100644
index 0000000..8d06279
--- /dev/null
+++ b/models/constant.hpp
@@ -0,0 +1,42 @@
+#ifndef CONSTANT_MODEL_H_
+#define CONSTANT_MODEL_H_
+#include <core/fitter.hpp>
+#include <cmath>
+
+namespace opt_utilities
+{
+ template <typename T>
+ class constant
+ :public model<T,T,std::vector<T>,std::string>
+ {
+ private:
+ model<T,T,std::vector<T> >* do_clone()const
+ {
+ return new constant<T>(*this);
+ }
+ public:
+ constant()
+ {
+ this->push_param_info(param_info<std::vector<T> >("c",1));
+ }
+
+ public:
+ T do_eval(const T& x,const std::vector<T>& param)
+ {
+ //return x*param[0]+param[1];
+ return get_element(param,0);
+ }
+
+ private:
+ std::string do_to_string()const
+ {
+ return "Constant\n"
+ "y=C\n";
+ }
+ };
+};
+
+
+
+#endif
+//EOF
diff --git a/models/dbeta1d.hpp b/models/dbeta1d.hpp
new file mode 100644
index 0000000..71a1f52
--- /dev/null
+++ b/models/dbeta1d.hpp
@@ -0,0 +1,62 @@
+#ifndef DBETA_MODEL_H_
+#define DBETA_MODEL_H_
+#include <core/fitter.hpp>
+#include <cmath>
+#include <iostream>
+namespace opt_utilities
+{
+ template <typename T>
+ class dbeta1d
+ :public model<T,T,std::vector<T>,std::string>
+ {
+ private:
+ model<T,T,std::vector<T> >* do_clone()const
+ {
+ return new dbeta1d<T>(*this);
+ }
+ public:
+ dbeta1d()
+ {
+ this->push_param_info(param_info<std::vector<T> >("S01",1));
+ this->push_param_info(param_info<std::vector<T> >("rc1",30));
+ this->push_param_info(param_info<std::vector<T> >("beta1",.6));
+
+ this->push_param_info(param_info<std::vector<T> >("S02",.5));
+ this->push_param_info(param_info<std::vector<T> >("rc2",20));
+ this->push_param_info(param_info<std::vector<T> >("beta2",.4));
+
+
+ this->push_param_info(param_info<std::vector<T> >("bkg",0));
+ }
+
+
+ T do_eval(const T& x,const std::vector<T>& param)
+ {
+ T S01=get_element(param,0);
+ T r_c1=get_element(param,1);
+ T beta1=get_element(param,2);
+
+ T S02=get_element(param,3);
+ T r_c2=get_element(param,4);
+ T beta2=get_element(param,5);
+
+
+ T bkg=get_element(param,6);
+
+ return bkg+S01*pow(1+(x*x)/(r_c1*r_c1),-3*beta1+static_cast<T>(.5))
+ +S02*pow(1+(x*x)/(r_c2*r_c2),-3*beta2+static_cast<T>(.5));
+ }
+
+ private:
+ std::string do_to_string()const
+ {
+ return "double 1d beta model\n"
+ "S=beta(S01,beta1,rc1)+beta(S02,beta2,rc2)\n";
+ }
+ };
+};
+
+
+
+#endif
+//EOF
diff --git a/models/dbeta2d.hpp b/models/dbeta2d.hpp
new file mode 100644
index 0000000..6811270
--- /dev/null
+++ b/models/dbeta2d.hpp
@@ -0,0 +1,92 @@
+#ifndef DBETA_MODEL2d_H_
+#define DBETA_MODEL2d_H_
+#include <core/fitter.hpp>
+#include <cmath>
+#include <cassert>
+#include "vecn.hpp"
+
+namespace opt_utilities
+{
+
+ template <typename T>
+ class dbeta2d
+ :public model<T,vecn<T,2>,std::vector<T>,std::string>
+ {
+ private:
+ model<T,vecn<T,2>,std::vector<T> >* do_clone()const
+ {
+ return new dbeta2d<T>(*this);
+ }
+
+
+
+ public:
+ dbeta2d()
+ {
+ push_param_info(param_info<std::vector<T> >("S01",1));
+ push_param_info(param_info<std::vector<T> >("rc11",50));
+ push_param_info(param_info<std::vector<T> >("rc21",50));
+ push_param_info(param_info<std::vector<T> >("rho1",0));
+ push_param_info(param_info<std::vector<T> >("x01",200));
+ push_param_info(param_info<std::vector<T> >("y01",200));
+ push_param_info(param_info<std::vector<T> >("beta1",2./3.));
+
+ push_param_info(param_info<std::vector<T> >("S02",1));
+ push_param_info(param_info<std::vector<T> >("rc12",60));
+ push_param_info(param_info<std::vector<T> >("rc22",60));
+ push_param_info(param_info<std::vector<T> >("rho2",0));
+ push_param_info(param_info<std::vector<T> >("x02",200));
+ push_param_info(param_info<std::vector<T> >("y02",200));
+ push_param_info(param_info<std::vector<T> >("beta2",2./2.5));
+ push_param_info(param_info<std::vector<T> >("bkg",0));
+ }
+
+ T do_eval(const vecn<T,2>& xy,const std::vector<T>& param)
+ {
+ T S01=get_element(param,0);
+ T rc11=get_element(param,1);
+ T rc21=get_element(param,2);
+ T rho1=get_element(param,3);
+ T x01=get_element(param,4);
+ T y01=get_element(param,5);
+ T beta1=get_element(param,6);
+ T S02=get_element(param,7);
+ T rc12=get_element(param,8);
+ T rc22=get_element(param,9);
+ T rho2=get_element(param,10);
+ T x02=get_element(param,11);
+ T y02=get_element(param,12);
+ T beta2=get_element(param,13);
+ T bkg=get_element(param,14);
+
+
+ T x=xy[0];
+ T y=xy[1];
+
+ rho1=rho1>1?1:rho1;
+ rho1=rho1<-1?-1:rho1;
+ rho2=rho2>1?1:rho2;
+ rho2=rho2<-1?-1:rho2;
+
+ T r1=(x-x01)*(x-x01)/(rc11*rc11)+(y-y01)*(y-y01)/(rc21*rc21)
+ -2*rho1*(x-x01)*(y-y01)/(rc11*rc21);
+
+ T r2=(x-x02)*(x-x02)/(rc12*rc12)+(y-y02)*(y-y02)/(rc22*rc22)
+ -2*rho2*(x-x02)*(y-y02)/(rc12*rc22);
+ // r1=r1<0?0:r1;
+ //r2=r2<0?0:r2;
+ assert(r1>=0);
+ assert(r2>=0);
+
+
+ return bkg+S01*pow(1+r1,-3*beta1+static_cast<T>(.5))+
+ S02*pow(1+r2,-3*beta2+static_cast<T>(.5));
+ }
+ };
+};
+
+
+
+#endif
+//EOF
+
diff --git a/models/dbeta2d2.hpp b/models/dbeta2d2.hpp
new file mode 100644
index 0000000..d968dbc
--- /dev/null
+++ b/models/dbeta2d2.hpp
@@ -0,0 +1,100 @@
+#ifndef DDBETA_OOOMODEL2d2_H_
+#define DDBETA_OOOMODEL2d2_H_
+#include <core/fitter.hpp>
+#include <cmath>
+#include <cassert>
+#include "vecn.hpp"
+
+
+namespace opt_utilities
+{
+
+ template <typename T>
+ class dbeta2d2
+ :public model<T,vecn<T,2>,std::vector<T>,std::string>
+ {
+ private:
+ model<T,vecn<T,2>,std::vector<T> >* do_clone()const
+ {
+ return new dbeta2d2<T>(*this);
+ }
+ public:
+ dbeta2d2()
+ {
+ this->push_param_info(param_info<std::vector<T> >("ampl1",1));//0
+ this->push_param_info(param_info<std::vector<T> >("r01",1));//1
+ this->push_param_info(param_info<std::vector<T> >("x01",100));//2
+ this->push_param_info(param_info<std::vector<T> >("y01",100));//3
+ this->push_param_info(param_info<std::vector<T> >("theta1",0));//4
+ this->push_param_info(param_info<std::vector<T> >("beta1",2./3.));//5
+ this->push_param_info(param_info<std::vector<T> >("epsilon1",0));//6
+
+
+ this->push_param_info(param_info<std::vector<T> >("ampl2",1));//7
+ this->push_param_info(param_info<std::vector<T> >("r02",1));//8
+ this->push_param_info(param_info<std::vector<T> >("x02",100));//9
+ this->push_param_info(param_info<std::vector<T> >("y02",100));//10
+ this->push_param_info(param_info<std::vector<T> >("theta2",0));//11
+ this->push_param_info(param_info<std::vector<T> >("beta2",2./4.));//12
+ this->push_param_info(param_info<std::vector<T> >("epsilon2",0));//13
+
+ this->push_param_info(param_info<std::vector<T> >("bkg",0));//14
+ }
+
+
+ T do_eval(const vecn<T,2>& xy,const std::vector<T>& param)
+ {
+ T x=xy[0];
+ T y=xy[1];
+
+ T ampl1=get_element(param,0);
+ T r01=get_element(param,1);
+ T x01=get_element(param,2);
+ T y01=get_element(param,3);
+
+ T theta1=get_element(param,4);
+
+ T beta1=get_element(param,5);
+ T epsilon1=get_element(param,6);
+
+ T ampl2=get_element(param,7);
+ T r02=get_element(param,8);
+ T x02=get_element(param,9);
+ T y02=get_element(param,10);
+
+ T theta2=get_element(param,11);
+
+ T beta2=get_element(param,12);
+
+ T epsilon2=get_element(param,13);
+ T bkg=get_element(param,14);
+
+ T x_new1=(x-x01)*cos(theta1)+(y-y01)*sin(theta1);
+ T y_new1=(y-y01)*cos(theta1)-(x-x01)*sin(theta1);
+
+ //T r1=sqrt(x_new1*x_new1*(1-epsilon1)*(1-epsilon1)
+ // + y_new1*y_new1);
+ //r1/=(1-epsilon1);
+
+ T r1_r1=x_new1*x_new1/exp(epsilon1/30)+y_new1*y_new1/exp(-epsilon1/30);
+
+ T x_new2=(x-x02)*cos(theta2)+(y-y02)*sin(theta2);
+ T y_new2=(y-y02)*cos(theta2)-(x-x02)*sin(theta2);
+
+ T r2_r2=x_new2*x_new2/exp(epsilon2/30)+y_new2*y_new2/exp(-epsilon2/30);
+ // T r2=sqrt(x_new2*x_new2*(1-epsilon2)*(1-epsilon2)
+ // + y_new2*y_new2);
+ //r2/=(1-epsilon2);
+
+
+
+ return bkg+ampl1*pow(1+(r1_r1/r01/r01),-3*beta1+static_cast<T>(.5))
+ +ampl2*pow(1+(r2_r2/r02/r02),-3*beta2+static_cast<T>(.5));
+ }
+ };
+};
+
+
+
+#endif
+//EOF
diff --git a/models/dbeta2d3.hpp b/models/dbeta2d3.hpp
new file mode 100644
index 0000000..e2edb78
--- /dev/null
+++ b/models/dbeta2d3.hpp
@@ -0,0 +1,91 @@
+#ifndef DDBETA3_MODEL2d2_H_
+#define DDBETA3_MODEL2d2_H_
+#include <core/fitter.hpp>
+#include <cmath>
+#include <cassert>
+#include "vecn.hpp"
+
+
+namespace opt_utilities
+{
+
+ template <typename T>
+ class dbeta2d3
+ :public model<T,vecn<T,2>,std::vector<T>,std::string>
+ {
+ private:
+ model<T,vecn<T,2>,std::vector<T> >* do_clone()const
+ {
+ return new dbeta2d3<T>(*this);
+ }
+ public:
+ dbeta2d3()
+ {
+
+ this->push_param_info(param_info<std::vector<T> >("x0",256));//1
+ this->push_param_info(param_info<std::vector<T> >("y0",256));//2
+ this->push_param_info(param_info<std::vector<T> >("epsilon",0));//3
+ this->push_param_info(param_info<std::vector<T> >("theta",0));//4
+
+ this->push_param_info(param_info<std::vector<T> >("ampl1",1));//5
+ this->push_param_info(param_info<std::vector<T> >("beta1",0.6));//6
+ this->push_param_info(param_info<std::vector<T> >("r01",30));//7
+
+ this->push_param_info(param_info<std::vector<T> >("ampl2",.5));//8
+ this->push_param_info(param_info<std::vector<T> >("beta2",.4));//9
+ this->push_param_info(param_info<std::vector<T> >("r02",20));//10
+
+ this->push_param_info(param_info<std::vector<T> >("bkg",0));//11
+
+
+ }
+
+
+ T do_eval(const vecn<T,2>& xy,const std::vector<T>& param)
+ {
+ T x=xy[0];
+ T y=xy[1];
+
+ T x0=get_element(param,0);
+ T y0=get_element(param,1);
+ T epsilon=get_element(param,2);
+ T theta=get_element(param,3);
+
+ T ampl1=(get_element(param,4));
+ T beta1=(get_element(param,5));
+ T r01=(get_element(param,6));
+
+ T ampl2=(get_element(param,7));
+ T beta2=(get_element(param,8));
+ T r02=(get_element(param,9));
+
+ T bkg=get_element(param,10);
+
+ T x_new1=(x-x0)*cos(theta)+(y-y0)*sin(theta);
+ T y_new1=(y-y0)*cos(theta)-(x-x0)*sin(theta);
+
+
+ T r1_r1=x_new1*x_new1/exp(epsilon/30)+y_new1*y_new1/exp(-epsilon/30);
+ //T r1=sqrt(x_new1*x_new1*(1-epsilon)*(1-epsilon)+y_new1*y_new1)/(1-epsilon);
+
+ T x_new2=(x-x0)*cos(theta)+(y-y0)*sin(theta);
+ T y_new2=(y-y0)*cos(theta)-(x-x0)*sin(theta);
+
+ T r2_r2=x_new2*x_new2/exp(epsilon/30)+y_new2*y_new2/exp(-epsilon/30);
+ //T r2=sqrt(x_new2*x_new2*(1-epsilon)*(1-epsilon)+y_new2*y_new2)/(1-epsilon);
+
+
+
+ return bkg+ampl1*pow(1+(r1_r1/r01/r01),-3*beta1+static_cast<T>(.5))
+ +ampl2*pow(1+(r2_r2/r02/r02),-3*beta2+static_cast<T>(.5));
+
+ //return bkg+pow(1+r1*r1/r01/r01,-3*beta1+static_cast<T>(.5))+
+ //pow(1+r2*r2/r02/r02,-3*beta2+static_cast<T>(.5));
+ }
+ };
+};
+
+
+
+#endif
+//EOF
diff --git a/models/dl_model.hpp b/models/dl_model.hpp
new file mode 100644
index 0000000..2fcf227
--- /dev/null
+++ b/models/dl_model.hpp
@@ -0,0 +1,178 @@
+#ifdef __linux__
+
+#ifndef DL_MODEL_H_
+#define DL_MODEL_H_
+#include <core/fitter.hpp>
+#include <cmath>
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <dlfcn.h>
+
+namespace opt_utilities
+{
+ template <typename T>
+ class dl_model
+ :public model<T,T,std::vector<T>,std::string>
+ {
+ private:
+ T (*calc_model)(T x,const T* p);
+ int nparams;
+ mutable void* handle;
+ private:
+ model<T,T,std::vector<T> >* do_clone()const
+ {
+ dl_model<T>* result=new dl_model<T>(*this);
+ this->handle=NULL;
+ return result;
+ }
+
+ // public:
+ public:
+ dl_model()
+ :handle(NULL)
+ {}
+
+
+ public:
+ dl_model(const char* file_name)
+ :handle(NULL)
+ {
+
+ handle=dlopen(file_name,RTLD_LAZY);
+
+ if(!handle)
+ {
+ throw opt_exception("faild loading object");
+ }
+
+ calc_model=(T (*)(T,const T*))dlsym(handle,"calc_model");
+
+ if(!calc_model)
+ {
+ throw opt_exception("symble undefined");
+ }
+
+ const char* (*get_param_name)(int)
+ =(const char* (*)(int))dlsym(handle,"get_param_name");
+
+ if(!get_param_name)
+ {
+ throw opt_exception("symble undefined");
+ }
+
+ int (*get_num_params)()
+ =(int (*)())dlsym(handle,"get_num_params");
+
+ if(!get_num_params)
+ {
+ throw opt_exception("symble undefined");
+ if(!get_num_params)
+ {
+ throw opt_exception("symble undefined");
+ } }
+
+ T (*get_default_value)(int)
+ =(T (*)(int))dlsym(handle,"get_default_value");
+
+ if(!get_default_value)
+ {
+ throw opt_exception("symble undefined");
+ }
+
+ nparams=get_num_params();
+
+ for(int i=0;i!=nparams;++i)
+ {
+ this->push_param_info(param_info<std::vector<T> >(get_param_name(i),
+ get_default_value(i)));
+ }
+ }
+
+ ~dl_model()
+ {
+ if(handle)
+ {
+ dlclose(handle);
+ }
+ }
+
+ void bind(const char* file_name)
+ {
+ if(handle)
+ {
+ dlclose(handle);
+ }
+ this->clear_param_info();
+ handle=dlopen(file_name,RTLD_LAZY);
+
+ if(!handle)
+ {
+ throw opt_exception("faild loading object");
+ }
+
+ calc_model=(T (*)(T,const T*))dlsym(handle,"calc_model");
+
+ if(!calc_model)
+ {
+ throw opt_exception("symble undefined");
+ }
+
+ const char* (*get_param_name)(int)
+ =(const char* (*)(int))dlsym(handle,"get_param_name");
+
+ if(!get_param_name)
+ {
+ throw opt_exception("symble undefined");
+ }
+
+
+ int (*get_num_params)()
+ =(int (*)())dlsym(handle,"get_num_params");
+
+ if(!get_num_params)
+ {
+ throw opt_exception("symble undefined");
+ }
+
+
+ T (*get_default_value)(int)
+ =(T (*)(int))dlsym(handle,"get_default_value");
+
+
+ if(!get_default_value)
+ {
+ throw opt_exception("symble undefined");
+ }
+
+
+ nparams=get_num_params();
+ for(int i=0;i!=nparams;++i)
+ {
+ this->push_param_info(param_info<std::vector<T> >(get_param_name(i),
+ get_default_value(i)));
+ }
+ }
+
+ T do_eval(const T& x,const std::vector<T>& param)
+ {
+ if(handle==NULL)
+ {
+ throw opt_exception("dl object unloaded");
+ }
+ return calc_model(x,&get_element(param,0));
+ }
+
+ std::string do_to_string()const
+ {
+ return "Dynamical load model\n"
+ "Should be loaded from an shared object file\n";
+ }
+ };
+};
+
+
+
+#endif
+#endif
+//EOF
diff --git a/models/dlmodel_template.c b/models/dlmodel_template.c
new file mode 100644
index 0000000..fd7aadb
--- /dev/null
+++ b/models/dlmodel_template.c
@@ -0,0 +1,36 @@
+#include <math.h>
+
+char p1name[2]="k";
+char p2name[2]="b";
+
+int main(int argc,char* argv[])
+{}
+
+
+int get_num_params()
+{
+ return 2;
+}
+
+const char* get_param_name(int n)
+{
+ if(n==0)
+ {
+ return p1name;
+ }
+ return p2name;
+}
+
+double get_default_value(int n)
+{
+ if(n==0)
+ return 1;
+ return 0;
+}
+
+double calc_model(double x,double p[])
+{
+ return p[0]*x+p[1];
+}
+
+
diff --git a/models/func_model.hpp b/models/func_model.hpp
new file mode 100644
index 0000000..4eda8d5
--- /dev/null
+++ b/models/func_model.hpp
@@ -0,0 +1,57 @@
+#ifndef FUNC_MODEL_H_
+#define FUNC_MODEL_H_
+#include <core/fitter.hpp>
+#include <cmath>
+#include <iostream>
+#include <string>
+#include <sstream>
+namespace opt_utilities
+{
+ template <typename T>
+ class func_model
+ :public model<T,T,std::vector<T>,std::string>
+ {
+ private:
+ T (*func)(T x,const T* const& p);
+ int nparams;
+ private:
+ model<T,T,std::vector<T> >* do_clone()const
+ {
+ return new func_model<T>(*this);
+ }
+
+ // public:
+ private:
+ func_model()
+ {}
+
+
+ public:
+ func_model(T (*_func)(T x,const T* const& p),int n)
+ :func(_func),nparams(n)
+ {
+ for(int i=0;i!=n;++i)
+ {
+ std::ostringstream oss;
+ oss<<i;
+ this->push_param_info(param_info<std::vector<T> >(oss.str(),0));
+ }
+ }
+
+
+ T do_eval(const T& x,const std::vector<T>& param)
+ {
+ return func(x,&get_element(param,0));
+ }
+ private:
+ std::string do_to_string()const
+ {
+ return "Wrapper for necked C function\n";
+ }
+ };
+};
+
+
+
+#endif
+//EOF
diff --git a/models/gauss1d.hpp b/models/gauss1d.hpp
new file mode 100644
index 0000000..958cec9
--- /dev/null
+++ b/models/gauss1d.hpp
@@ -0,0 +1,47 @@
+#ifndef GAUSS_MODEL_H_
+#define GAUSS_MODEL_H_
+#include <core/fitter.hpp>
+#include <cmath>
+
+namespace opt_utilities
+{
+ template <typename T>
+ class gauss1d
+ :public model<T,T,std::vector<T>,std::string>
+ {
+ private:
+ model<T,T,std::vector<T> >* do_clone()const
+ {
+ return new gauss1d<T>(*this);
+ }
+ public:
+ gauss1d()
+ {
+ this->push_param_info(param_info<std::vector<T> >("N",1));
+ this->push_param_info(param_info<std::vector<T> >("x0",0));
+ this->push_param_info(param_info<std::vector<T> >("sigma",1));
+ }
+
+ public:
+ T do_eval(const T& x,const std::vector<T>& param)
+ {
+ T N=get_element(param,0);
+ T x0=get_element(param,1);
+ T sigma=get_element(param,2);
+ T y=(x-x0)/sigma;
+ return N*exp(-y*y);
+ }
+
+ private:
+ std::string do_to_string()const
+ {
+ return "Gaussian model\n"
+ "y=N*exp(-(x-x0)^2/sigma^2\n";
+ }
+ };
+};
+
+
+
+#endif
+//EOF
diff --git a/models/lin1d.hpp b/models/lin1d.hpp
new file mode 100644
index 0000000..b0ddd31
--- /dev/null
+++ b/models/lin1d.hpp
@@ -0,0 +1,42 @@
+#ifndef LINEAR_MODEL_H_
+#define LINEAR_MODEL_H_
+#include <core/fitter.hpp>
+#include <cmath>
+
+namespace opt_utilities
+{
+ template <typename T>
+ class lin1d
+ :public model<T,T,std::vector<T>,std::string>
+ {
+ private:
+ model<T,T,std::vector<T> >* do_clone()const
+ {
+ return new lin1d<T>(*this);
+ }
+ public:
+ lin1d()
+ {
+ this->push_param_info(param_info<std::vector<T> >("k",1));
+ this->push_param_info(param_info<std::vector<T> >("b",0));
+ }
+
+ public:
+ T do_eval(const T& x,const std::vector<T>& param)
+ {
+ return x*get_element(param,0)+get_element(param,1);
+ }
+
+ private:
+ std::string do_to_string()const
+ {
+ return "linear model\n"
+ "y=k*x+b\n";
+ }
+ };
+};
+
+
+
+#endif
+//EOF
diff --git a/models/models.cc b/models/models.cc
new file mode 100644
index 0000000..7481b88
--- /dev/null
+++ b/models/models.cc
@@ -0,0 +1,176 @@
+#include "models.hpp"
+#include <core/opt_exception.hpp>
+#include "gauss1d.hpp"
+#include "bl1d.hpp"
+#include "nfw1d.hpp"
+#include "bpl1d.hpp"
+#include "beta1d.hpp"
+#include "nbeta1d.hpp"
+#include "dbeta1d.hpp"
+#include "lin1d.hpp"
+#include "pl1d.hpp"
+#include "poly1d.hpp"
+#include "bremss.hpp"
+#include "beta2d2.hpp"
+#include "beta2d.hpp"
+#include "dbeta2d2.hpp"
+#include "dbeta2d3.hpp"
+#include "dbeta2d.hpp"
+#include "dl_model.hpp"
+#include <iostream>
+using namespace std;
+
+
+namespace opt_utilities
+{
+ strmodel1d strm1d;
+ std::map<std::string,model<double,double,std::vector<double>,std::string>* > model_map;
+ std::map<std::string,model<double,vecn<double,2>,std::vector<double>,std::string>* > model2d_map;
+ std::list<std::string> get_model_name_list()
+ {
+ std::list<std::string> result;
+ for(std::map<std::string,model<double,double,std::vector<double>,std::string>* >::iterator i=model_map.begin();
+ i!=model_map.end();++i)
+ {
+ result.push_back(i->first);
+ }
+ return result;
+ }
+
+ std::list<std::string> get_model2d_name_list()
+ {
+ std::list<std::string> result;
+ for(map<std::string,model<double,vecn<double,2>,std::vector<double>,std::string>* > ::iterator i=model2d_map.begin();
+ i!=model2d_map.end();++i)
+ {
+ result.push_back(i->first);
+ }
+ return result;
+ }
+
+model<double,double,std::vector<double>,std::string>& get_1dmodel_by_name(const char* name)
+ {
+ std::map<std::string,model<double,double,std::vector<double>,std::string >* >::iterator iter;
+ iter=model_map.find(name);
+ if(iter==model_map.end()||iter->second==0)
+ {
+ throw opt_exception("model does not exist");
+ }
+ return *(iter->second);
+ }
+
+ strmodel1d& get_strm1d()
+ {
+ return strm1d;
+ }
+
+model<double,vecn<double,2>,std::vector<double>,std::string>& get_2dmodel_by_name(const char* name)
+ {
+ std::map<std::string,model<double,vecn<double,2>,std::vector<double>,std::string>* >::iterator iter;
+ iter=model2d_map.find(name);
+ if(iter==model2d_map.end()||iter->second==0)
+ {
+ throw opt_exception("model does not exist");
+ }
+ return *(iter->second);
+ }
+
+ int get_n_1dmodels()
+ {
+ return model_map.size();
+ }
+
+ int get_n_2dmodels()
+ {
+ return model2d_map.size();
+ }
+
+ class model_map_keeper_class
+ {
+ private:
+ void init_model_map()
+ {
+
+ //#define DECL_POLY(n) model_map["poly1d##n"]=new poly1d<double,n>;
+
+
+ model_map["lin1d"]=new lin1d<double>;
+ model_map["pl1d"]=new pl1d<double>;
+ model_map["bl1d"]=new bl1d<double>;
+ model_map["bpl1d"]=new bpl1d<double>;
+ model_map["beta1d"]=new beta1d<double>;
+ model_map["bremss"]=new bremss<double>;
+ model_map["nbeta1d"]=new nbeta1d<double>;
+ model_map["2beta1d"]=new dbeta1d<double>;
+ model_map["nfw"]=new nfw1d<double>;
+ model_map["gauss1d"]=new gauss1d<double>;
+ model_map["poly1d2"]=new poly1d<double,2>;
+ model_map["poly1d3"]=new poly1d<double,3>;
+ model_map["poly1d4"]=new poly1d<double,4>;
+ model_map["poly1d5"]=new poly1d<double,5>;
+#ifdef __linux__
+ model_map["dlmodel"]=new dl_model<double>;
+#endif
+ //DECL_POLY(7)
+ }
+
+ void release_model_map()
+ {
+ for(std::map<std::string,model<double,double,std::vector<double>,std::string>* >::iterator i=model_map.begin();
+ i!=model_map.end();++i)
+ {
+ delete i->second;
+ }
+ }
+ public:
+ model_map_keeper_class()
+ {
+ init_model_map();
+ std::cerr<<"1d models Initialized"<<std::endl;
+ }
+
+ ~model_map_keeper_class()
+ {
+ release_model_map();
+ std::cerr<<"1d models Released"<<std::endl;
+ }
+
+ }model_map_keeper;
+
+ class model2d_map_keeper_class
+ {
+ private:
+ void init_model_map()
+ {
+ model2d_map["beta2d"]=new beta2d<double>;
+ model2d_map["beta2d2"]=new beta2d2<double>;
+ model2d_map["dbeta2d"]=new dbeta2d<double>;
+ model2d_map["dbeta2d2"]=new dbeta2d2<double>;
+ model2d_map["dbeta2d3"]=new dbeta2d3<double>;
+ }
+
+ void release_model_map()
+ {
+ for(std::map<std::string,model<double,vecn<double,2>,std::vector<double>,std::string>* >::iterator i=model2d_map.begin();
+ i!=model2d_map.end();++i)
+ {
+ delete i->second;
+ }
+ }
+ public:
+ model2d_map_keeper_class()
+ {
+ init_model_map();
+ std::cerr<<"2d models Initialized"<<std::endl;
+ }
+
+ ~model2d_map_keeper_class()
+ {
+ release_model_map();
+ std::cerr<<"2d models Released"<<std::endl;
+ }
+
+ }model2d_map_keeper;
+
+
+};
diff --git a/models/models.hpp b/models/models.hpp
new file mode 100644
index 0000000..79201e8
--- /dev/null
+++ b/models/models.hpp
@@ -0,0 +1,36 @@
+#ifndef MODELS_HPP
+#define MODELS_HPP
+
+#include <core/fitter.hpp>
+#include <map>
+#include <string>
+#include <list>
+#include "vecn.hpp"
+#include "strmodel1d.hpp"
+
+
+
+namespace opt_utilities
+{
+ extern std::map<std::string,model<double,double,std::vector<double>,std::string>* > model_map;
+ extern std::map<std::string,model<double,vecn<double,2>,std::vector<double>,std::string >* > model2d_map;
+
+ extern strmodel1d strm1d;
+ extern std::list<std::string> get_model_name_list();
+ extern int get_n_1dmodels();
+ // extern void init_model_map();
+ // extern void release_model_map();
+
+ extern std::list<std::string> get_model2d_name_list();
+ // extern void init_model2d_map();
+ // extern void release_model2d_map();
+ extern int get_n_2dmodels();
+
+ extern model<double,double,std::vector<double>,std::string >& get_1dmodel_by_name(const char*);
+ extern model<double,vecn<double,2>,std::vector<double>,std::string >& get_2dmodel_by_name(const char*);
+
+ extern strmodel1d& get_strm1d();
+}
+
+
+#endif
diff --git a/models/mul_model.hpp b/models/mul_model.hpp
new file mode 100644
index 0000000..0e64c1b
--- /dev/null
+++ b/models/mul_model.hpp
@@ -0,0 +1,171 @@
+#ifndef MUL_MODEL_H_
+#define MUL_MODEL_H_
+#include <core/fitter.hpp>
+#include <cmath>
+
+namespace opt_utilities
+{
+ template <typename Ty,typename Tx,typename Tp,typename Tstr>
+ class mul_model
+ :public model<Ty,Tx,Tp,Tstr>
+ {
+ private:
+ model<Ty,Tx,Tp,Tstr>* do_clone()const
+ {
+ return new mul_model<Ty,Tx,Tp,Tstr>(*this);
+ }
+ private:
+ mul_model()
+ {
+ }
+
+ private:
+ model<Ty,Tx,Tp,Tstr>* pm1;
+ model<Ty,Tx,Tp,Tstr>* pm2;
+
+ public:
+ mul_model(const model<Ty,Tx,Tp,Tstr>& m1,
+ const model<Ty,Tx,Tp,Tstr>& m2)
+ :pm1(m1.clone()),pm2(m2.clone())
+ {
+ int np1=m1.get_num_params();
+ int np2=m2.get_num_params();
+ for(int i=0;i<np1;++i)
+ {
+ param_info<Tp,Tstr> p(m1.get_param_info(i));
+ param_info<Tp,Tstr> p1(p.get_name()+"1",p.get_default_value());
+ this->push_param_info(p1);
+ }
+ for(int i=0;i<np2;++i)
+ {
+ param_info<Tp,Tstr> p(m2.get_param_info(i));
+ param_info<Tp,Tstr> p2(p.get_name()+"2",p.get_default_value());
+ this->push_param_info(p2);
+ }
+ }
+
+ mul_model(const mul_model& rhs)
+ :pm1(NULL),pm2(NULL)
+ {
+ int np1(0),np2(0);
+ if(rhs.pm1)
+ {
+ pm1=rhs.pm1->clone();
+ np1=rhs.pm1->get_num_params();
+ for(int i=0;i<np1;++i)
+ {
+ param_info<Tp,Tstr> p(rhs.pm1->get_param_info(i));
+ param_info<Tp,Tstr> p1(p.get_name()+"1",p.get_default_value());
+ this->push_param_info(p1);
+ }
+ }
+ if(rhs.pm2)
+ {
+ pm2=rhs.pm2->clone();
+ np2=rhs.pm2->get_num_params();
+ for(int i=0;i<np2;++i)
+ {
+ param_info<Tp,Tstr> p(rhs.pm2->get_param_info(i));
+ param_info<Tp,Tstr> p2(p.get_name()+"2",p.get_default_value());
+ this->push_param_info(p2);
+ }
+ }
+ }
+
+ mul_model& operator=(const mul_model& rhs)
+ {
+ if(this==&rhs)
+ {
+ return *this;
+ }
+ if(!pm1)
+ {
+ //delete pm1;
+ pm1->destroy();
+ }
+ if(!pm2)
+ {
+ //delete pm2;
+ pm2->destroy();
+ }
+ int np1(0),np2(0);
+ if(rhs.pm1)
+ {
+ pm1=rhs.pm1->clone();
+ np1=rhs.pm1->get_num_params();
+ for(int i=0;i<np1;++i)
+ {
+ param_info<Tp,Tstr> p(rhs.pm1->get_param_info(i));
+ param_info<Tp,Tstr> p1(p.get_name()+"1",p.get_default_value());
+ this->push_param_info(p1);
+ }
+ }
+ if(rhs.pm2)
+ {
+ pm2=rhs.pm2->clone();
+ np2=rhs.pm2->get_num_params();
+ for(int i=0;i<np2;++i)
+ {
+ param_info<Tp,Tstr> p(rhs.pm2->get_param_info(i));
+ param_info<Tp,Tstr> p2(p.get_name()+"2",p.get_default_value());
+ this->push_param_info(p2);
+ }
+ }
+ return *this;
+ }
+
+
+ ~mul_model()
+ {
+ if(!pm1)
+ {
+ //delete pm1;
+ pm1->destroy();
+ }
+ if(!pm2)
+ {
+ //delete pm2;
+ pm2->destroy();
+ }
+ }
+
+ public:
+ Ty do_eval(const Tx& x,const Tp& param)
+ {
+ if(!pm1)
+ {
+ throw opt_exception("incomplete model!");
+ }
+ if(!pm2)
+ {
+ throw opt_exception("incomplete model!");
+ }
+ Tp p1(pm1->get_num_params());
+ Tp p2(pm2->get_num_params());
+ int i=0;
+ int j=0;
+ for(i=0;i<pm1->get_num_params();++i,++j)
+ {
+ set_element(p1,i,get_element(param,j));
+ }
+ for(i=0;i<pm2->get_num_params();++i,++j)
+ {
+ set_element(p2,i,get_element(param,j));
+ }
+ return pm1->eval(x,p1)*pm2->eval(x,p2);
+ }
+ };
+
+ template <typename Ty,typename Tx,typename Tp>
+ mul_model<Ty,Tx,Tp,Tstr> operator*(const model<Ty,Tx,Tp,Tstr>& m1,
+ const model<Ty,Tx,Tp,Tstr>& m2)
+ {
+ return mul_model<Ty,Tx,Tp,Tstr>(m1,m2);
+ }
+
+};
+
+
+
+#endif
+//EOF
diff --git a/models/nbeta1d.hpp b/models/nbeta1d.hpp
new file mode 100644
index 0000000..3806fe9
--- /dev/null
+++ b/models/nbeta1d.hpp
@@ -0,0 +1,49 @@
+#ifndef NBETA_MODEL_H_
+#define NBETA_MODEL_H_
+#include <core/fitter.hpp>
+#include <cmath>
+#include <iostream>
+namespace opt_utilities
+{
+ template <typename T>
+ class nbeta1d
+ :public model<T,T,std::vector<T> ,std::string>
+ {
+ private:
+ model<T,T,std::vector<T> >* do_clone()const
+ {
+ return new nbeta1d<T>(*this);
+ }
+ public:
+ nbeta1d()
+ {
+ this->push_param_info(param_info<std::vector<T> >("S0",1));
+ this->push_param_info(param_info<std::vector<T> >("rc",10));
+ this->push_param_info(param_info<std::vector<T> >("beta",2./3.));
+ this->push_param_info(param_info<std::vector<T> >("bkg",0));
+ }
+
+
+ T do_eval(const T& x,const std::vector<T>& param)
+ {
+ T S0=get_element(param,0);
+ T r_c=get_element(param,1);
+ T beta=get_element(param,2);
+ T bkg=get_element(param,3);
+
+ return bkg+S0*pow(1+(x*x)/(r_c*r_c),-3./2.*beta);
+ }
+
+ private:
+ std::string do_to_string()const
+ {
+ return "density beta model\n"
+ "n=n0*(1+(r/rc)^2)^(-1.5*beta)\n";
+ }
+ };
+};
+
+
+
+#endif
+//EOF
diff --git a/models/nfw1d.hpp b/models/nfw1d.hpp
new file mode 100644
index 0000000..9c2dfd4
--- /dev/null
+++ b/models/nfw1d.hpp
@@ -0,0 +1,45 @@
+#ifndef NFW_MODEL_H_
+#define NFW_MODEL_H_
+#include <core/fitter.hpp>
+#include <cmath>
+#include <iostream>
+namespace opt_utilities
+{
+ template <typename T>
+ class nfw1d
+ :public model<T,T,std::vector<T>,std::string>
+ {
+ private:
+ model<T,T,std::vector<T> >* do_clone()const
+ {
+ return new nfw1d<T>(*this);
+ }
+ public:
+ nfw1d()
+ {
+ this->push_param_info(param_info<std::vector<T> >("rho0",1.));
+ this->push_param_info(param_info<std::vector<T> >("rs",1.));
+ }
+
+
+ T do_eval(const T& x,const std::vector<T>& param)
+ {
+ T rho0=get_element(param,0);
+ T rs=get_element(param,1);
+
+
+ return rho0/(x/rs*(1+x/rs)*(1+x/rs));
+ }
+
+ std::string do_to_string()const
+ {
+ return "NFW model\n"
+ "y=rho0/(r/rs*(1+r/rs)^2\n";
+ }
+ };
+};
+
+
+
+#endif
+//EOF
diff --git a/models/pl1d.hpp b/models/pl1d.hpp
new file mode 100644
index 0000000..50b4c50
--- /dev/null
+++ b/models/pl1d.hpp
@@ -0,0 +1,43 @@
+#ifndef POWER_LAW_MODEL_H_
+#define POWER_LAW_MODEL_H_
+#include <core/fitter.hpp>
+#include <cmath>
+
+namespace opt_utilities
+{
+ template <typename T>
+ class pl1d
+ :public model<T,T,std::vector<T>,std::string>
+ {
+ private:
+ model<T,T,std::vector<T> >* do_clone()const
+ {
+ return new pl1d<T>(*this);
+ }
+ public:
+ pl1d()
+ {
+ this->push_param_info(param_info<std::vector<T> >("Ampl",1));
+ this->push_param_info(param_info<std::vector<T> >("gamma",1));
+ }
+
+ T do_eval(const T& x,const std::vector<T>& param)
+ {
+ T A=get_element(param,0);
+ T gamma=get_element(param,1);
+ return A*pow(x,gamma);
+ }
+
+ private:
+ std::string do_to_string()const
+ {
+ return "Simple power law model\n"
+ "y=A*x^gamma\n";
+ }
+ };
+};
+
+
+
+#endif
+//EOF
diff --git a/models/poly1d.hpp b/models/poly1d.hpp
new file mode 100644
index 0000000..a8c994b
--- /dev/null
+++ b/models/poly1d.hpp
@@ -0,0 +1,67 @@
+#ifndef POLY_MODEL_H_
+#define POLY_MODEL_H_
+#include <core/fitter.hpp>
+#include <cmath>
+#include <sstream>
+#include <cassert>
+
+namespace opt_utilities
+{
+ template <typename T,int n>
+ class poly1d
+ :public model<T,T,std::vector<T>,std::string>
+ {
+ private:
+ model<T,T,std::vector<T> >* do_clone()const
+ {
+ return new poly1d<T,n>(*this);
+ }
+ public:
+ poly1d()
+ {
+ assert(n>=0);
+ for(int i=0;i<=n;++i)
+ {
+ std::ostringstream ostr;
+ ostr<<"a"<<i;
+ this->push_param_info(param_info<std::vector<T> >(ostr.str().c_str(),1));
+ }
+
+ }
+
+ public:
+ T do_eval(const T& x,const std::vector<T>& param)
+ {
+ // return x*get_element(param,0)+get_element(param,1);
+ T result(0);
+ for(int i=0;i<=n;++i)
+ {
+ T xn(1);
+ for(int j=0;j<i;++j)
+ {
+ xn*=x;
+ }
+ result+=get_element(param,i)*xn;
+ }
+ return result;
+ }
+
+ private:
+ std::string do_to_string()const
+ {
+ std::ostringstream ostr;
+ ostr<<n<<"-order polynorminal model\n";
+ for(int i=0;i<n;++i)
+ {
+ ostr<<"a"<<i<<"*x^"<<i<<"+";
+ }
+ ostr<<"a"<<n<<"*x^"<<n;
+ return ostr.str();
+ }
+ };
+};
+
+
+
+#endif
+//EOF
diff --git a/models/pow_model.hpp b/models/pow_model.hpp
new file mode 100644
index 0000000..79baa4b
--- /dev/null
+++ b/models/pow_model.hpp
@@ -0,0 +1,120 @@
+#ifndef POW_MODEL_H_
+#define POW_MODEL_H_
+#include <core/fitter.hpp>
+#include <cmath>
+
+namespace opt_utilities
+{
+ template <typename Ty,typename Tx,typename Tp,typename Tstr>
+ class pow_model
+ :public model<Ty,Tx,Tp,Tstr>
+ {
+ private:
+ model<Ty,Tx,Tp,Tstr>* do_clone()const
+ {
+ return new pow_model<Ty,Tx,Tp,Tstr>(*this);
+ }
+ private:
+ pow_model()
+ {
+ }
+
+ private:
+ model<Ty,Tx,Tp,Tstr>* pm1;
+ typename value_type_trait<Tp>::value_type idx;
+
+ public:
+ pow_model(const model<Ty,Tx,Tp,Tstr>& m1,
+ const typename value_type_trait<Tp>::value_type& index)
+ :pm1(m1.clone()),idx(index)
+ {
+ int np1=m1.get_num_params();
+
+ for(int i=0;i<np1;++i)
+ {
+ param_info<Tp,Tstr> p(m1.get_param_info(i));
+ //param_info<Tp,Tstr> p1(p.get_name(),p.get_default_value());
+ this->push_param_info(p);
+ }
+ }
+
+ pow_model(const pow_model& rhs)
+ :pm1(NULL),idx(0)
+ {
+ int np1(0);
+ if(rhs.pm1)
+ {
+ pm1=rhs.pm1->clone();
+ np1=rhs.pm1->get_num_params();
+ for(int i=0;i<np1;++i)
+ {
+ param_info<Tp,Tstr> p(rhs.pm1->get_param_info(i));
+ param_info<Tp,Tstr> p1(p.get_name()+"1",p.get_default_value());
+ this->push_param_info(p1);
+ }
+ }
+ idx=rhs.idx;
+ }
+
+ pow_model& operator=(const pow_model& rhs)
+ {
+ if(this==&rhs)
+ {
+ return *this;
+ }
+ if(!pm1)
+ {
+ //delete pm1;
+ pm1->destroy();
+ }
+
+ int np1(0);
+ if(rhs.pm1)
+ {
+ pm1=rhs.pm1->clone();
+ np1=rhs.pm1->get_num_params();
+ for(int i=0;i<np1;++i)
+ {
+ param_info<Tp,Tstr> p(rhs.pm1->get_param_info(i));
+ // param_info<Tp,Tstr> p1(p.get_name()+"1",p.get_default_value());
+ this->push_param_info(p);
+ }
+ }
+ idx=rhs.idx;
+
+ return *this;
+ }
+
+ ~pow_model()
+ {
+ if(!pm1)
+ {
+ //delete pm1;
+ pm1->destroy();
+ }
+ }
+
+ public:
+ Ty do_eval(const Tx& x,const Tp& param)
+ {
+ if(!pm1)
+ {
+ throw opt_exception("incomplete model!");
+ }
+
+ return std::pow(pm1->eval(x,param),idx);
+ }
+ };
+
+ template <typename Ty,typename Tx,typename Tp,typename Tstr>
+ pow_model<Ty,Tx,Tp,Tstr> pow(const model<Ty,Tx,Tp,Tstr>& m1,
+ const typename value_type_trait<Tp>::value_type& idx)
+ {
+ return pow_model<Ty,Tx,Tp,Tstr>(m1,idx);
+ }
+};
+
+
+
+#endif
+//EOF
diff --git a/models/strmodel1d.cc b/models/strmodel1d.cc
new file mode 100644
index 0000000..df3cd40
--- /dev/null
+++ b/models/strmodel1d.cc
@@ -0,0 +1,82 @@
+#include "strmodel1d.hpp"
+
+using namespace mu;
+using namespace std;
+using namespace opt_utilities;
+
+strmodel1d* strmodel1d::do_clone()const
+{
+ return new strmodel1d(*this);
+}
+
+strmodel1d::strmodel1d()
+{
+ set_buildin_fun();
+}
+
+strmodel1d::strmodel1d(const strmodel1d& rhs)
+ :expr(rhs.expr),
+ par_names(rhs.par_names),
+ var_name(rhs.var_name),
+ par_vec(rhs.par_vec)
+{
+ set_buildin_fun();
+ set_expr(expr,par_names,var_name);
+}
+
+strmodel1d& strmodel1d::operator=(const strmodel1d& rhs)
+{
+ set_buildin_fun();
+ expr=rhs.expr;
+ par_names=rhs.par_names;
+ var_name=rhs.var_name;
+ par_vec=rhs.par_vec;
+ set_expr(expr,par_names,var_name);
+ return *this;
+}
+
+void strmodel1d::set_buildin_fun()
+{
+ mp.DefineFun("sin",sin);
+ mp.DefineFun("cos",cos);
+ mp.DefineFun("exp",exp);
+ mp.DefineFun("tan",tan);
+ mp.DefineFun("log",log);
+}
+
+
+void strmodel1d::set_expr(const string& _expr,
+ const std::vector<std::string>& _par_names,
+ const std::string& _var_name)
+{
+ expr=_expr;
+ par_names=_par_names;
+ var_name=_var_name;
+ this->clear_param_info();
+ par_vec.resize(par_names.size());
+ mp.ClearVar();
+ // mp.ClearFun();
+ for(int i=0;i<par_vec.size();++i)
+ {
+ mp.DefineVar(par_names[i].c_str(),&par_vec[i]);
+ this->push_param_info(param_info<std::vector<double> >(par_names[i],0));
+ }
+ mp.DefineVar(var_name.c_str(),&x);
+ mp.SetExpr(expr.c_str());
+}
+
+
+double strmodel1d::do_eval(const double& _x,const vector<double>& p)
+{
+ for(int i=0;i<par_vec.size();++i)
+ {
+ //get_element(par_vec,i)=get_element(p,i);
+ set_element(par_vec,i,get_element(p,i));
+ // cout<<par_vec[i]<<" ";
+ }
+ x=_x;
+ // cout<<x<<" ";
+ double result(mp.Eval());
+ // cout<<result<<endl;
+ return result;
+}
diff --git a/models/strmodel1d.hpp b/models/strmodel1d.hpp
new file mode 100644
index 0000000..8d992a0
--- /dev/null
+++ b/models/strmodel1d.hpp
@@ -0,0 +1,39 @@
+#ifndef STRMODEL1D_HPP
+#define STRMODEL1D_HPP
+#include <core/fitter.hpp>
+#include <cmath>
+#include <sstream>
+#include <cassert>
+#include <muparser/muParser.h>
+#include <vector>
+#include <string>
+
+class strmodel1d
+ :public opt_utilities::model<double,double,std::vector<double>,std::string>
+{
+private:
+ mu::Parser mp;
+ strmodel1d* do_clone()const;
+ std::vector<double> par_vec;
+ std::vector<std::string> par_names;
+ std::string expr;
+ std::string var_name;
+ double x;
+ void set_buildin_fun();
+public:
+ double do_eval(const double& x,const std::vector<double>& p);
+ strmodel1d();
+ strmodel1d(const strmodel1d& rhs);
+ strmodel1d& operator=(const strmodel1d& rhs);
+
+
+ void set_expr(const std::string& _expr,
+ const std::vector<std::string>& _par_names,
+ const std::string& _var_name);
+
+};
+
+
+
+#endif
+//EOF
diff --git a/models/vecn.hpp b/models/vecn.hpp
new file mode 100644
index 0000000..cac1436
--- /dev/null
+++ b/models/vecn.hpp
@@ -0,0 +1,62 @@
+#ifndef VECN_HPP
+#define VECN_HPP
+#include <iostream>
+namespace opt_utilities
+{
+ template <typename T,int n>
+ class vecn
+ {
+ public:
+ T data[n];
+ public:
+ T& operator[](int i)
+ {
+ return data[i];
+ }
+
+ const T& operator[](int i)const
+ {
+ return data[i];
+ }
+
+ vecn()
+ {
+ for(int i=0;i<n;++i)
+ {
+ data[i]=0;
+ }
+ }
+
+ };
+
+ template <typename T,int n>
+ std::istream& operator>>(std::istream& is,vecn<T,n>& p)
+ {
+ for(int i=0;i<n;++i)
+ {
+ is>>p[i];
+ // std::cout<<i<<std::endl;
+ }
+ return is;
+ }
+
+
+ template <typename T,int n>
+ std::ostream& operator<<(std::ostream& os,const vecn<T,n>& p)
+ {
+ os<<'[';
+ for(int i=0;i<n;++i)
+ {
+ os<<p[i]<<",";
+ // std::cout<<i<<std::endl;
+ }
+ os<<']';
+ return os;
+ }
+
+
+
+};
+
+#endif
+//EOF
diff --git a/muparser/makefile b/muparser/makefile
new file mode 100644
index 0000000..83d2cd5
--- /dev/null
+++ b/muparser/makefile
@@ -0,0 +1,16 @@
+MUP_OBJ=muParserBase.o muParser.o muParserInt.o\
+ muParserBytecode.o muParserDLL.o\
+ muParserTest.o\
+ muParserCallback.o muParserError.o\
+ muParserTokenReader.o
+
+libmuparser.a:$(MUP_OBJ)
+ $(AR) $@ *.o
+
+.cpp.o:
+ $(CPP) $< $(CPPFLAGS)
+
+clean:
+ $(RM) *.o
+
+
diff --git a/muparser/muParser.cpp b/muparser/muParser.cpp
new file mode 100644
index 0000000..e92b1a2
--- /dev/null
+++ b/muparser/muParser.cpp
@@ -0,0 +1,259 @@
+/*
+ __________
+ _____ __ __\______ \_____ _______ ______ ____ _______
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
+ \/ \/ \/ \/
+ Copyright (C) 2004-2006 Ingo Berg
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ software and associated documentation files (the "Software"), to deal in the Software
+ without restriction, including without limitation the rights to use, copy, modify,
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "muParser.h"
+
+#include <cmath>
+#include <algorithm>
+#include <numeric>
+
+/** \brief Pi (what else?). */
+#define PARSER_CONST_PI 3.141592653589793238462643
+
+/** \brief The eulerian number. */
+#define PARSER_CONST_E 2.718281828459045235360287
+
+using namespace std;
+
+
+/** \brief Namespace for mathematical applications. */
+namespace mu
+{
+
+//---------------------------------------------------------------------------
+// Trigonometric function
+value_type Parser::Sin(value_type v) { return sin(v); }
+value_type Parser::Cos(value_type v) { return cos(v); }
+value_type Parser::Tan(value_type v) { return tan(v); }
+value_type Parser::ASin(value_type v) { return asin(v); }
+value_type Parser::ACos(value_type v) { return acos(v); }
+value_type Parser::ATan(value_type v) { return atan(v); }
+value_type Parser::Sinh(value_type v) { return sinh(v); }
+value_type Parser::Cosh(value_type v) { return cosh(v); }
+value_type Parser::Tanh(value_type v) { return tanh(v); }
+value_type Parser::ASinh(value_type v) { return log(v + sqrt(v * v + 1)); }
+value_type Parser::ACosh(value_type v) { return log(v + sqrt(v * v - 1)); }
+value_type Parser::ATanh(value_type v) { return ((value_type)0.5 * log((1 + v) / (1 - v))); }
+
+//---------------------------------------------------------------------------
+// Logarithm functions
+value_type Parser::Log2(value_type v) { return log(v)/log((value_type)2); } // Logarithm base 2
+value_type Parser::Log10(value_type v) { return log10(v); } // Logarithm base 10
+value_type Parser::Ln(value_type v) { return log(v); } // Logarithm base e (natural logarithm)
+
+//---------------------------------------------------------------------------
+// misc
+value_type Parser::Exp(value_type v) { return exp(v); }
+value_type Parser::Abs(value_type v) { return fabs(v); }
+value_type Parser::Sqrt(value_type v) { return sqrt(v); }
+value_type Parser::Rint(value_type v) { return floor(v + (value_type)0.5); }
+value_type Parser::Sign(value_type v) { return (value_type)((v<0) ? -1 : (v>0) ? 1 : 0); }
+
+//---------------------------------------------------------------------------
+// Conditional (if then else)
+value_type Parser::Ite(value_type v1, value_type v2, value_type v3) { return (v1==1) ? v2 : v3; }
+
+//---------------------------------------------------------------------------
+// Unary operator Callbacks: Infix operators
+value_type Parser::UnaryMinus(value_type v) { return -v; }
+
+//---------------------------------------------------------------------------
+// Functions with variable number of arguments
+// sum
+value_type Parser::Sum(const value_type *a_afArg, int a_iArgc)
+{
+ if (!a_iArgc)
+ throw exception_type(_T("too few arguments for function sum."));
+
+ value_type fRes=0;
+ for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i];
+ return fRes;
+}
+
+//---------------------------------------------------------------------------
+// mean value
+value_type Parser::Avg(const value_type *a_afArg, int a_iArgc)
+{
+ if (!a_iArgc)
+ throw exception_type(_T("too few arguments for function sum."));
+
+ value_type fRes=0;
+ for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i];
+ return fRes/(double)a_iArgc;
+}
+
+//---------------------------------------------------------------------------
+// minimum
+value_type Parser::Min(const value_type *a_afArg, int a_iArgc)
+{
+ if (!a_iArgc)
+ throw exception_type(_T("too few arguments for function min."));
+
+ value_type fRes=a_afArg[0];
+ for (int i=0; i<a_iArgc; ++i) fRes = std::min(fRes, a_afArg[i]);
+
+ return fRes;
+}
+
+//---------------------------------------------------------------------------
+// maximum
+value_type Parser::Max(const value_type *a_afArg, int a_iArgc)
+{
+ if (!a_iArgc)
+ throw exception_type(_T("too few arguments for function min."));
+
+ value_type fRes=a_afArg[0];
+ for (int i=0; i<a_iArgc; ++i) fRes = std::max(fRes, a_afArg[i]);
+
+ return fRes;
+}
+
+//---------------------------------------------------------------------------
+// Default value recognition callback
+bool Parser::IsVal(const char_type *a_szExpr, int &a_iPos, value_type &a_fVal)
+{
+ value_type fVal(0);
+
+// thanks to CodeProject member sailorickm for writing this fix:
+// http://www.codeproject.com/cpp/FastMathParser.asp?msg=1354598#xx1354598xx
+// i cant test it myself, if you see problems please contact me.
+#if defined (__hpux) || (defined __GNUC__ && (__GNUC__ == 3 && (__GNUC_MINOR__ < 3 )))
+ int iEnd = 0;
+ int nAssigned = sscanf(a_szExpr, "%lf%n", &fVal, &iEnd);
+ if (nAssigned == 0)
+ iEnd = -1;
+#else
+ stringstream_type stream(a_szExpr);
+ stream.seekg(0); // todo: check if this really is necessary
+ stream >> fVal;
+ int iEnd = stream.tellg(); // Position after reading
+#endif
+
+ if (iEnd==-1)
+ return false;
+
+ a_iPos += iEnd;
+ a_fVal = fVal;
+ return true;
+}
+
+//---------------------------------------------------------------------------
+/** \brief Constructor.
+
+ Call ParserBase class constructor and trigger Function, Operator and Constant initialization.
+*/
+Parser::Parser()
+ :ParserBase()
+ ,m_fEpsilon((value_type)1e-7)
+{
+ AddValIdent(IsVal);
+
+ InitCharSets();
+ InitFun();
+ InitConst();
+ InitOprt();
+}
+
+//---------------------------------------------------------------------------
+/** Define the character sets. */
+void Parser::InitCharSets()
+{
+ DefineNameChars( _T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") );
+ DefineOprtChars( _T("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-*^/?<>=#!$%&|~'_") );
+ DefineInfixOprtChars( _T("/+-*^?<>=#!$%&|~'_") );
+}
+
+//---------------------------------------------------------------------------
+/** \brief Initialize the default functions. */
+void Parser::InitFun()
+{
+ // trigonometric functions
+ DefineFun(_T("sin"), Sin);
+ DefineFun(_T("cos"), Cos);
+ DefineFun(_T("tan"), Tan);
+ // arcus functions
+ DefineFun(_T("asin"), ASin);
+ DefineFun(_T("acos"), ACos);
+ DefineFun(_T("atan"), ATan);
+ // hyperbolic functions
+ DefineFun(_T("sinh"), Sinh);
+ DefineFun(_T("cosh"), Cosh);
+ DefineFun(_T("tanh"), Tanh);
+ // arcus hyperbolic functions
+ DefineFun(_T("asinh"), ASinh);
+ DefineFun(_T("acosh"), ACosh);
+ DefineFun(_T("atanh"), ATanh);
+ // Logarithm functions
+ DefineFun(_T("log2"), Log2);
+ DefineFun(_T("log10"), Log10);
+ DefineFun(_T("log"), Log10);
+ DefineFun(_T("ln"), Ln);
+ // misc
+ DefineFun(_T("exp"), Exp);
+ DefineFun(_T("sqrt"), Sqrt);
+ DefineFun(_T("sign"), Sign);
+ DefineFun(_T("rint"), Rint);
+ DefineFun(_T("abs"), Abs);
+ DefineFun(_T("if"), Ite);
+ // Functions with variable number of arguments
+ DefineFun(_T("sum"), Sum);
+ DefineFun(_T("avg"), Avg);
+ DefineFun(_T("min"), Min);
+ DefineFun(_T("max"), Max);
+}
+
+//---------------------------------------------------------------------------
+/** \brief Initialize operators. */
+void Parser::InitConst()
+{
+ DefineConst(_T("_pi"), (value_type)PARSER_CONST_PI);
+ DefineConst(_T("_e"), (value_type)PARSER_CONST_E);
+}
+
+//---------------------------------------------------------------------------
+/** \brief Initialize operators. */
+void Parser::InitOprt()
+{
+ DefineInfixOprt(_T("-"), UnaryMinus);
+}
+
+//---------------------------------------------------------------------------
+/** \brief Numerically differentiate with regard to a variable. */
+value_type Parser::Diff(value_type *a_Var, value_type a_fPos) const
+{
+ assert(m_fEpsilon);
+ value_type fEpsilon( (a_fPos==0) ? (value_type)1e-10 : m_fEpsilon * a_fPos ),
+ fRes(0), fBuf(*a_Var), f[4] = {0,0,0,0};
+
+ *a_Var = a_fPos+2*fEpsilon; f[0] = Eval();
+ *a_Var = a_fPos+1*fEpsilon; f[1] = Eval();
+ *a_Var = a_fPos-1*fEpsilon; f[2] = Eval();
+ *a_Var = a_fPos-2*fEpsilon; f[3] = Eval();
+ *a_Var = fBuf; // restore variable
+
+ fRes = (-f[0] + 8*f[1] - 8*f[2] + f[3]) / (12*fEpsilon);
+ return fRes;
+}
+
+} // namespace mu
diff --git a/muparser/muParser.h b/muparser/muParser.h
new file mode 100644
index 0000000..5aff62d
--- /dev/null
+++ b/muparser/muParser.h
@@ -0,0 +1,104 @@
+/*
+ __________
+ _____ __ __\______ \_____ _______ ______ ____ _______
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
+ \/ \/ \/ \/
+ Copyright (C) 2004-2006 Ingo Berg
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ software and associated documentation files (the "Software"), to deal in the Software
+ without restriction, including without limitation the rights to use, copy, modify,
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef MU_PARSER_H
+#define MU_PARSER_H
+
+#include "muParserBase.h"
+#include <vector>
+
+
+namespace mu
+{
+
+/** \brief Mathematical expressions parser (reference implementation).
+
+ Standard implementation of the mathematical expressions parser.
+ Can be used as a reference implementation for subclassing the parser.
+
+ <small>
+ (C) 2004-2006 Ingo Berg<br>
+ ingo_berg(at)gmx.de
+ </small>
+*/
+class Parser : public ParserBase
+{
+private:
+ // Trigonometric functions
+ static value_type Sin(value_type);
+ static value_type Cos(value_type);
+ static value_type Tan(value_type);
+ // arcus functions
+ static value_type ASin(value_type);
+ static value_type ACos(value_type);
+ static value_type ATan(value_type);
+ // hyperbolic functions
+ static value_type Sinh(value_type);
+ static value_type Cosh(value_type);
+ static value_type Tanh(value_type);
+ // arcus hyperbolic functions
+ static value_type ASinh(value_type);
+ static value_type ACosh(value_type);
+ static value_type ATanh(value_type);
+ // Logarithm functions
+ static value_type Log2(value_type); // Logarithm Base 2
+ static value_type Log10(value_type); // Logarithm Base 10
+ static value_type Ln(value_type); // Logarithm Base e (natural logarithm)
+ // misc
+ static value_type Exp(value_type);
+ static value_type Abs(value_type);
+ static value_type Sqrt(value_type);
+ static value_type Rint(value_type);
+ static value_type Sign(value_type);
+ static value_type Ite(value_type, value_type, value_type);
+
+ // Prefix operators
+ // !!! Unary Minus is a MUST if you want to use negative signs !!!
+ static value_type UnaryMinus(value_type);
+
+ // Functions with variable number of arguments
+ static value_type Sum(const value_type*, int); // sum
+ static value_type Avg(const value_type*, int); // mean value
+ static value_type Min(const value_type*, int); // minimum
+ static value_type Max(const value_type*, int); // maximum
+
+ static bool IsVal(const char_type *a_szExpr, int &a_iPos, value_type &a_fVal);
+
+ value_type m_fEpsilon; ///< Epsilon used for numerical differentiation.
+
+public:
+ Parser();
+
+ virtual void InitCharSets();
+ virtual void InitFun();
+ virtual void InitConst();
+ virtual void InitOprt();
+
+ value_type Diff(value_type *a_Var, value_type a_fPos) const;
+};
+
+} // namespace mu
+
+#endif
+
diff --git a/muparser/muParserBase.cpp b/muparser/muParserBase.cpp
new file mode 100644
index 0000000..e81e53e
--- /dev/null
+++ b/muparser/muParserBase.cpp
@@ -0,0 +1,1364 @@
+/*
+ __________
+ _____ __ __\______ \_____ _______ ______ ____ _______
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
+ \/ \/ \/ \/
+ Copyright (C) 2004-2006 Ingo Berg
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ software and associated documentation files (the "Software"), to deal in the Software
+ without restriction, including without limitation the rights to use, copy, modify,
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "muParser.h"
+
+#include <cassert>
+#include <cmath>
+#include <memory>
+#include <vector>
+#include <sstream>
+
+using namespace std;
+
+
+namespace mu
+{
+
+//------------------------------------------------------------------------------
+/** \brief Identifiers for built in binary operators.
+
+ When defining custom binary operators with #AddOprt(...) make sure not to choose
+ names conflicting with these definitions.
+*/
+const char_type* ParserBase::c_DefaultOprt[] =
+{
+ _T("<="), _T(">="), _T("!="),
+ _T("=="), _T("<"), _T(">"),
+ _T("+"), _T("-"), _T("*"),
+ _T("/"), _T("^"), _T("and"),
+ _T("or"), _T("xor"), _T("="),
+ _T("("), _T(")"), _T(","), 0
+};
+
+//------------------------------------------------------------------------------
+/** \brief Constructor.
+ \param a_szFormula the formula to interpret.
+ \throw ParserException if a_szFormula is null.
+*/
+ParserBase::ParserBase()
+ :m_pParseFormula(&ParserBase::ParseString)
+ ,m_pCmdCode(0)
+ ,m_vByteCode()
+ ,m_vStringBuf()
+ ,m_pTokenReader()
+ ,m_FunDef()
+ ,m_PostOprtDef()
+ ,m_InfixOprtDef()
+ ,m_OprtDef()
+ ,m_ConstDef()
+ ,m_StrVarDef()
+ ,m_VarDef()
+ ,m_bOptimize(true)
+ ,m_bUseByteCode(true)
+ ,m_bBuiltInOp(true)
+ ,m_sNameChars()
+ ,m_sOprtChars()
+ ,m_sInfixOprtChars()
+{
+ InitTokenReader();
+}
+
+//---------------------------------------------------------------------------
+/** \brief Copy constructor.
+
+ Implemented by calling Assign(a_Parser)
+*/
+ParserBase::ParserBase(const ParserBase &a_Parser)
+ :m_pParseFormula(&ParserBase::ParseString)
+ ,m_pCmdCode(0)
+ ,m_vByteCode()
+ ,m_vStringBuf()
+ ,m_pTokenReader()
+ ,m_FunDef()
+ ,m_PostOprtDef()
+ ,m_InfixOprtDef()
+ ,m_OprtDef()
+ ,m_ConstDef()
+ ,m_StrVarDef()
+ ,m_VarDef()
+ ,m_bOptimize(true)
+ ,m_bUseByteCode(true)
+ ,m_bBuiltInOp(true)
+{
+ m_pTokenReader.reset(new token_reader_type(this));
+ Assign(a_Parser);
+}
+
+//---------------------------------------------------------------------------
+/** \brief Assignement operator.
+
+ Implemented by calling Assign(a_Parser). Self assignement is suppressed.
+ \param a_Parser Object to copy to this.
+ \return *this
+ \throw nothrow
+*/
+ParserBase& ParserBase::operator=(const ParserBase &a_Parser)
+{
+ Assign(a_Parser);
+ return *this;
+}
+
+//---------------------------------------------------------------------------
+/** \brief Copy state of a parser object to this.
+
+ Clears Variables and Functions of this parser.
+ Copies the states of all internal variables.
+ Resets parse function to string parse mode.
+
+ \param a_Parser the source object.
+*/
+void ParserBase::Assign(const ParserBase &a_Parser)
+{
+ if (&a_Parser==this)
+ return;
+
+ // Don't copy bytecode instead cause the parser to create new bytecode
+ // by resetting the parse function.
+ ReInit();
+
+ m_ConstDef = a_Parser.m_ConstDef; // Copy user define constants
+ m_VarDef = a_Parser.m_VarDef; // Copy user defined variables
+ m_bOptimize = a_Parser.m_bOptimize;
+ m_bUseByteCode = a_Parser.m_bUseByteCode;
+ m_bBuiltInOp = a_Parser.m_bBuiltInOp;
+ m_vStringBuf = a_Parser.m_vStringBuf;
+ m_pTokenReader.reset(a_Parser.m_pTokenReader->Clone(this));
+ m_StrVarDef = a_Parser.m_StrVarDef;
+ m_vStringVarBuf = a_Parser.m_vStringVarBuf;
+
+ // Copy function and operator callbacks
+ m_FunDef = a_Parser.m_FunDef; // Copy function definitions
+ m_PostOprtDef = a_Parser.m_PostOprtDef; // post value unary operators
+ m_InfixOprtDef = a_Parser.m_InfixOprtDef; // unary operators for infix notation
+
+ m_sNameChars = a_Parser.m_sNameChars;
+ m_sOprtChars = a_Parser.m_sOprtChars;
+ m_sInfixOprtChars = a_Parser.m_sInfixOprtChars;
+}
+
+//---------------------------------------------------------------------------
+/** \brief Initialize the token reader.
+
+ Create new token reader object and submit pointers to function, operator,
+ constant and variable definitions.
+
+ \post m_pTokenReader.get()!=0
+ \throw nothrow
+*/
+void ParserBase::InitTokenReader()
+{
+ m_pTokenReader.reset(new token_reader_type(this));
+}
+
+//---------------------------------------------------------------------------
+/** \brief Reset parser to string parsing mode and clear internal buffers.
+
+ Clear bytecode, reset the token reader.
+ \throw nothrow
+*/
+void ParserBase::ReInit() const
+{
+ m_pParseFormula = &ParserBase::ParseString;
+ m_vStringBuf.clear();
+ m_vByteCode.clear();
+ m_pTokenReader->ReInit();
+}
+
+//---------------------------------------------------------------------------
+void ParserBase::AddValIdent(identfun_type a_pCallback)
+{
+ m_pTokenReader->AddValIdent(a_pCallback);
+}
+
+//---------------------------------------------------------------------------
+void ParserBase::SetVarFactory(facfun_type a_pFactory, void *pUserData)
+{
+ m_pTokenReader->SetVarCreator(a_pFactory, pUserData);
+}
+
+//---------------------------------------------------------------------------
+/** \brief Add a function or operator callback to the parser.
+*/
+void ParserBase::AddCallback( const string_type &a_strName,
+ const ParserCallback &a_Callback,
+ funmap_type &a_Storage,
+ const char_type *a_szCharSet )
+{
+ if (a_Callback.GetAddr()==0)
+ Error(ecINVALID_FUN_PTR);
+
+ const funmap_type *pFunMap = &a_Storage;
+
+ // Check for conflicting operator or function names
+ if ( pFunMap!=&m_FunDef && m_FunDef.find(a_strName)!=m_FunDef.end() )
+ Error(ecNAME_CONFLICT);
+
+ if ( pFunMap!=&m_PostOprtDef && m_PostOprtDef.find(a_strName)!=m_PostOprtDef.end() )
+ Error(ecNAME_CONFLICT);
+
+ if ( pFunMap!=&m_InfixOprtDef && pFunMap!=&m_OprtDef && m_InfixOprtDef.find(a_strName)!=m_InfixOprtDef.end() )
+ Error(ecNAME_CONFLICT);
+
+ if ( pFunMap!=&m_InfixOprtDef && pFunMap!=&m_OprtDef && m_OprtDef.find(a_strName)!=m_OprtDef.end() )
+ Error(ecNAME_CONFLICT);
+
+ CheckName(a_strName, a_szCharSet);
+ a_Storage[a_strName] = a_Callback;
+ ReInit();
+}
+
+//---------------------------------------------------------------------------
+/** \brief Check if a name contains invalid characters.
+
+ \throw ParserException if the name contains invalid charakters.
+*/
+void ParserBase::CheckName(const string_type &a_sName,
+ const string_type &a_szCharSet) const
+{
+ if ( !a_sName.length() ||
+ (a_sName.find_first_not_of(a_szCharSet)!=string_type::npos) ||
+ (a_sName[0]>='0' && a_sName[0]<='9'))
+ {
+ Error(ecINVALID_NAME);
+ }
+}
+
+//---------------------------------------------------------------------------
+/** \brief Set the formula.
+ Triggers first time calculation thus the creation of the bytecode and
+ scanning of used variables.
+
+ \param a_strFormula Formula as string_type
+ \throw ParserException in case of syntax errors.
+*/
+void ParserBase::SetExpr(const string_type &a_sExpr)
+{
+ // <ibg> 20060222: Bugfix for Borland-Kylix:
+ // adding a space to the expression will keep Borlands KYLIX from going wild
+ // when calling tellg on a stringstream created from the expression after
+ // reading a value at the end of an expression. (mu::Parser::IsVal function)
+ // (tellg returns -1 otherwise causing the parser to ignore the value)
+ string_type sBuf(a_sExpr + _T(" ") );
+ m_pTokenReader->SetFormula(sBuf);
+ ReInit();
+}
+
+//---------------------------------------------------------------------------
+/** \brief Add a user defined operator.
+ \post Will reset the Parser to string parsing mode.
+*/
+void ParserBase::DefinePostfixOprt(const string_type &a_sName,
+ fun_type1 a_pFun,
+ bool a_bAllowOpt)
+{
+ AddCallback( a_sName,
+ ParserCallback(a_pFun, a_bAllowOpt, prPOSTFIX, cmOPRT_POSTFIX),
+ m_PostOprtDef,
+ ValidOprtChars() );
+}
+
+//---------------------------------------------------------------------------
+/** \brief Add a user defined operator.
+ \post Will reset the Parser to string parsing mode.
+ \param a_sName [in] operator Identifier
+ \param a_pFun [in] Operator callback function
+ \param a_iPrec [in] Operator Precedence (default=prSIGN)
+ \param a_bAllowOpt [in] True if operator is volatile (default=false)
+
+ \sa EPrec
+*/
+void ParserBase::DefineInfixOprt(const string_type &a_sName,
+ fun_type1 a_pFun,
+ int a_iPrec,
+ bool a_bAllowOpt)
+{
+ AddCallback( a_sName,
+ ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, cmOPRT_INFIX),
+ m_InfixOprtDef,
+ ValidOprtChars() );
+}
+
+//---------------------------------------------------------------------------
+void ParserBase::DefineOprt( const string_type &a_sName,
+ fun_type2 a_pFun,
+ unsigned a_iPrec,
+ bool a_bAllowOpt )
+{
+ // Check for conflicts with built in operator names
+ for (int i=0; m_bBuiltInOp && i<cmCOMMA; ++i)
+ if (a_sName == string_type(c_DefaultOprt[i]))
+ Error(ecBUILTIN_OVERLOAD);
+
+ AddCallback( a_sName,
+ ParserCallback(a_pFun, a_bAllowOpt, a_iPrec, cmOPRT_BIN),
+ m_OprtDef,
+ ValidOprtChars() );
+}
+
+//---------------------------------------------------------------------------
+void ParserBase::DefineStrConst(const string_type &a_strName, const string_type &a_strVal)
+{
+ // Test if a constant with that names already exists
+ if (m_StrVarDef.find(a_strName)!=m_StrVarDef.end())
+ Error(ecNAME_CONFLICT);
+
+ CheckName(a_strName, ValidNameChars());
+
+ // Store variable string in internal buffer
+ m_vStringVarBuf.push_back(a_strVal);
+
+ // bind buffer index to variable name
+ m_StrVarDef[a_strName] = m_vStringBuf.size();
+
+ ReInit();
+}
+
+//---------------------------------------------------------------------------
+/** \brief Add a user defined variable.
+ \post Will reset the Parser to string parsing mode.
+ \pre [assert] a_fVar!=0
+ \throw ParserException in case the name contains invalid signs.
+*/
+void ParserBase::DefineVar(const string_type &a_sName, value_type *a_pVar)
+{
+ if (a_pVar==0)
+ Error(ecINVALID_VAR_PTR);
+
+ // Test if a constant with that names already exists
+ if (m_ConstDef.find(a_sName)!=m_ConstDef.end())
+ Error(ecNAME_CONFLICT);
+
+ if (m_FunDef.find(a_sName)!=m_FunDef.end())
+ Error(ecNAME_CONFLICT);
+
+ CheckName(a_sName, ValidNameChars());
+ m_VarDef[a_sName] = a_pVar;
+ ReInit();
+}
+
+//---------------------------------------------------------------------------
+/** \brief Add a user defined constant.
+ \post Will reset the Parser to string parsing mode.
+ \throw ParserException in case the name contains invalid signs.
+*/
+void ParserBase::DefineConst(const string_type &a_sName, value_type a_fVal)
+{
+ CheckName(a_sName, ValidNameChars());
+ m_ConstDef[a_sName] = a_fVal;
+ ReInit();
+}
+
+//---------------------------------------------------------------------------
+/** \brief Get operator priority.
+
+ \throw ParserException if a_Oprt is no operator code
+*/
+int ParserBase::GetOprtPri(const token_type &a_Tok) const
+{
+ switch (a_Tok.GetCode())
+ {
+ // built in operators
+ case cmEND: return -5;
+ case cmCOMMA: return -4;
+ case cmBO :
+ case cmBC : return -2;
+ case cmASSIGN: return -1;
+ case cmAND:
+ case cmXOR:
+ case cmOR: return prLOGIC;
+ case cmLT :
+ case cmGT :
+ case cmLE :
+ case cmGE :
+ case cmNEQ:
+ case cmEQ : return prCMP;
+ case cmADD:
+ case cmSUB: return prADD_SUB;
+ case cmMUL:
+ case cmDIV: return prMUL_DIV;
+ case cmPOW: return prPOW;
+
+ // user defined binary operators
+ case cmOPRT_INFIX:
+ case cmOPRT_BIN: return a_Tok.GetPri();
+ default: Error(ecINTERNAL_ERROR, 5);
+ return 999;
+ }
+}
+
+//---------------------------------------------------------------------------
+/** \brief Return a map containing the used variables only. */
+const varmap_type& ParserBase::GetUsedVar() const
+{
+ try
+ {
+ m_pTokenReader->IgnoreUndefVar(true);
+ ParseString(); // implicitely create or update the map with the
+ // used variables stored in the token reader if not already done
+ m_pTokenReader->IgnoreUndefVar(false);
+ }
+ catch(exception_type &e)
+ {
+ m_pTokenReader->IgnoreUndefVar(false);
+ throw e;
+ }
+
+ // Make sure to stay in string parse mode, dont call ReInit()
+ // because it deletes the array with the used variables
+ m_pParseFormula = &ParserBase::ParseString;
+
+ return m_pTokenReader->GetUsedVar();
+}
+
+//---------------------------------------------------------------------------
+/** \brief Return a map containing the used variables only. */
+const varmap_type& ParserBase::GetVar() const
+{
+ return m_VarDef;
+}
+
+//---------------------------------------------------------------------------
+/** \brief Return a map containing all parser constants. */
+const valmap_type& ParserBase::GetConst() const
+{
+ return m_ConstDef;
+}
+
+//---------------------------------------------------------------------------
+/** \brief Return prototypes of all parser functions.
+
+ The return type is a map of the public type #funmap_type containing the prototype
+ definitions for all numerical parser functions. String functions are not part of
+ this map. The Prototype definition is encapsulated in objects of the class FunProt
+ one per parser function each associated with function names via a map construct.
+ \return #m_FunDef
+ \sa FunProt
+ \throw nothrow
+*/
+const funmap_type& ParserBase::GetFunDef() const
+{
+ return m_FunDef;
+}
+
+//---------------------------------------------------------------------------
+/** \brief Retrieve the formula. */
+const string_type& ParserBase::GetExpr() const
+{
+ return m_pTokenReader->GetFormula();
+}
+
+//---------------------------------------------------------------------------
+ParserBase::token_type ParserBase::ApplyNumFunc( const token_type &a_FunTok,
+ const std::vector<token_type> &a_vArg) const
+{
+ token_type valTok;
+ int iArgCount = (unsigned)a_vArg.size();
+ void *pFunc = a_FunTok.GetFuncAddr();
+ assert(pFunc);
+
+ // Collect the function arguments from the value stack
+ switch(a_FunTok.GetArgCount())
+ {
+ case -1:
+ // Function with variable argument count
+ // copy arguments into a vector<value_type>
+ {
+ /** \todo remove the unnecessary argument vector by changing order in stArg. */
+ std::vector<value_type> vArg;
+ for (int i=0; i<iArgCount; ++i)
+ vArg.push_back(a_vArg[i].GetVal());
+
+ valTok.SetVal( ((multfun_type)a_FunTok.GetFuncAddr())(&vArg[0], (int)vArg.size()) );
+ }
+ break;
+
+ case 1: valTok.SetVal( ((fun_type1)pFunc)(a_vArg[0].GetVal()) ); break;
+ case 2: valTok.SetVal( ((fun_type2)pFunc)(a_vArg[1].GetVal(),
+ a_vArg[0].GetVal()) ); break;
+ case 3: valTok.SetVal( ((fun_type3)pFunc)(a_vArg[2].GetVal(),
+ a_vArg[1].GetVal(),
+ a_vArg[0].GetVal()) ); break;
+ case 4: valTok.SetVal( ((fun_type4)pFunc)(a_vArg[3].GetVal(),
+ a_vArg[2].GetVal(),
+ a_vArg[1].GetVal(),
+ a_vArg[0].GetVal()) ); break;
+ case 5: valTok.SetVal( ((fun_type5)pFunc)(a_vArg[4].GetVal(),
+ a_vArg[3].GetVal(),
+ a_vArg[2].GetVal(),
+ a_vArg[1].GetVal(),
+ a_vArg[0].GetVal()) ); break;
+ default: Error(ecINTERNAL_ERROR, 6);
+ }
+
+ // Find out if the result will depend on a variable
+ /** \todo remove this loop, put content in the loop that takes the argument values.
+
+ (Attention: SetVal will reset Flags.)
+ */
+ bool bVolatile = a_FunTok.IsFlagSet(token_type::flVOLATILE);
+ for (int i=0; (bVolatile==false) && (i<iArgCount); ++i)
+ bVolatile |= a_vArg[i].IsFlagSet(token_type::flVOLATILE);
+
+ if (bVolatile)
+ valTok.AddFlags(token_type::flVOLATILE);
+
+#if defined(_MSC_VER)
+ #pragma warning( disable : 4311 )
+#endif
+
+ // Formula optimization
+ if ( m_bOptimize &&
+ !valTok.IsFlagSet(token_type::flVOLATILE) &&
+ !a_FunTok.IsFlagSet(token_type::flVOLATILE) )
+ {
+ m_vByteCode.RemoveValEntries(iArgCount);
+ m_vByteCode.AddVal( valTok.GetVal() );
+ }
+ else
+ {
+ // operation dosnt depends on a variable or the function is flagged unoptimizeable
+ // we cant optimize here...
+ m_vByteCode.AddFun(pFunc, (a_FunTok.GetArgCount()==-1) ? -iArgCount : iArgCount);
+ }
+
+ return valTok;
+
+#if defined(_MSC_VER)
+ #pragma warning( default : 4311 )
+#endif
+}
+
+//---------------------------------------------------------------------------
+/** \brief Execute a function that takes a single string argument.
+
+ \param a_FunTok Function token.
+ \throw exception_type If the function token is not a string function
+*/
+ParserBase::token_type ParserBase::ApplyStrFunc(const token_type &a_FunTok,
+ const std::vector<token_type> &a_vArg) const
+{
+ if (a_vArg.back().GetCode()!=cmSTRING)
+ Error(ecSTRING_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString());
+
+ token_type valTok;
+ int iArgCount = (unsigned)a_vArg.size();
+ void *pFunc = a_FunTok.GetFuncAddr();
+ assert(pFunc);
+
+ try
+ {
+ // Collect the function arguments from the value stack
+ switch(a_FunTok.GetArgCount())
+ {
+ case 0: valTok.SetVal( ((strfun_type1)pFunc)(a_vArg[0].GetAsString().c_str()) ); break;
+ case 1: valTok.SetVal( ((strfun_type2)pFunc)(a_vArg[1].GetAsString().c_str(),
+ a_vArg[0].GetVal()) ); break;
+ case 2: valTok.SetVal( ((strfun_type3)pFunc)(a_vArg[2].GetAsString().c_str(),
+ a_vArg[1].GetVal(),
+ a_vArg[0].GetVal()) ); break;
+ default: Error(ecINTERNAL_ERROR);
+ }
+ }
+ catch(ParserError& /*e*/)
+ {
+ Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), a_FunTok.GetAsString());
+ }
+
+ // Find out if the result will depend on a variable
+ /** \todo remove this loop, put content in the loop that takes the argument values.
+
+ (Attention: SetVal will reset Flags.)
+ */
+ bool bVolatile = a_FunTok.IsFlagSet(token_type::flVOLATILE);
+ for (int i=0; (bVolatile==false) && (i<iArgCount); ++i)
+ bVolatile |= a_vArg[i].IsFlagSet(token_type::flVOLATILE);
+
+ if (bVolatile)
+ valTok.AddFlags(token_type::flVOLATILE);
+
+ // string functions won't be optimized
+ m_vByteCode.AddStrFun((void*)pFunc, a_FunTok.GetArgCount(), a_vArg.back().GetIdx());
+
+ return valTok;
+}
+
+//---------------------------------------------------------------------------
+/** \brief Apply a function token.
+
+ \param iArgCount Number of Arguments actually gathered used only for multiarg functions.
+ \post Function have been taken from the stack, the result has been pushed
+ \post The function token is removed from the stack
+ \throw exception_type if Argument count does not mach function requirements.
+*/
+void ParserBase::ApplyFunc( ParserStack<token_type> &a_stOpt,
+ ParserStack<token_type> &a_stVal,
+ int a_iArgCount) const
+{
+ assert(m_pTokenReader.get());
+
+ // Operator stack empty or does not contain tokens with callback functions
+ if (a_stOpt.empty() || a_stOpt.top().GetFuncAddr()==0 )
+ return;
+
+ token_type funTok = a_stOpt.pop();
+ assert(funTok.GetFuncAddr());
+
+ // Binary operators must rely on their internal operator number
+ // since counting of operators relies on commas for function arguments
+ // binary operators do not have commas in their expression
+ int iArgCount = ( funTok.GetCode()==cmOPRT_BIN ) ? funTok.GetArgCount() : a_iArgCount;
+
+ if (funTok.GetArgCount()>0 && iArgCount>funTok.GetArgCount())
+ Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos()-1, funTok.GetAsString());
+
+ if ( funTok.GetCode()!=cmOPRT_BIN && iArgCount<funTok.GetArgCount() )
+ Error(ecTOO_FEW_PARAMS, m_pTokenReader->GetPos()-1, funTok.GetAsString());
+
+ if ( funTok.GetCode()==cmFUNC_STR && iArgCount>funTok.GetArgCount() )
+ Error(ecTOO_MANY_PARAMS, m_pTokenReader->GetPos()-1, funTok.GetAsString());
+
+ // Collect the numeric function arguments from the value stack and store them
+ // in a vector
+ std::vector<token_type> stArg;
+ for (int i=0; i<iArgCount; ++i)
+ {
+ stArg.push_back( a_stVal.pop() );
+ if ( stArg.back().GetType()==tpSTR && funTok.GetType()!=tpSTR )
+ Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString());
+ }
+
+ // for string functions add the string argument
+ if (funTok.GetCode()==cmFUNC_STR)
+ {
+ stArg.push_back( a_stVal.pop() );
+ if ( stArg.back().GetType()==tpSTR && funTok.GetType()!=tpSTR )
+ Error(ecVAL_EXPECTED, m_pTokenReader->GetPos(), funTok.GetAsString());
+ }
+
+ // String functions accept only one parameter
+ if (funTok.GetType()==tpSTR)
+ {
+ token_type token( ApplyStrFunc(funTok, stArg) );
+ a_stVal.push( token );
+ }
+ else
+ {
+ token_type token( ApplyNumFunc(funTok, stArg) );
+ a_stVal.push( token );
+ }
+/*
+#ifdef __BORLANDC__
+ // Borland C++ Compiler does not support taking references on
+ // unnamed temporaries
+ if (funTok.GetType()==tpSTR)
+ {
+ ParserToken<value_type, string_type> pt( ApplyStrFunc(funTok, stArg.back()) );
+ a_stVal.push(pt);
+ }
+ else
+ {
+ ParserToken<value_type, string_type> pt( ApplyNumFunc(funTok, stArg) );
+ a_stVal.push(pt);
+ }
+#else
+ // String functions accept only one parameter
+ a_stVal.push( (funTok.GetType()==tpSTR) ? ApplyStrFunc(funTok, stArg) :
+ ApplyNumFunc(funTok, stArg) );
+#endif // __BORLANDC__
+*/
+}
+
+//---------------------------------------------------------------------------
+void ParserBase::ApplyBinOprt( ParserStack<token_type> &a_stOpt,
+ ParserStack<token_type> &a_stVal) const
+{
+ assert(a_stOpt.size());
+
+ // user defined binary operator
+ if (a_stOpt.top().GetCode()==cmOPRT_BIN)
+ {
+ ApplyFunc(a_stOpt, a_stVal, 2);
+ }
+ else
+ {
+ // internal binary operator
+ MUP_ASSERT(a_stVal.size()>=2);
+
+ token_type valTok1 = a_stVal.pop(),
+ valTok2 = a_stVal.pop(),
+ optTok = a_stOpt.pop(),
+ resTok;
+
+ if ( valTok1.GetType()!=valTok2.GetType() ||
+ (valTok1.GetType()==tpSTR && valTok2.GetType()==tpSTR) )
+ Error(ecOPRT_TYPE_CONFLICT, m_pTokenReader->GetPos(), optTok.GetAsString());
+
+ value_type x = valTok2.GetVal(),
+ y = valTok1.GetVal();
+
+ switch (optTok.GetCode())
+ {
+ // built in binary operators
+ case cmAND: resTok.SetVal( (int)x & (int)y ); break;
+ case cmOR: resTok.SetVal( (int)x | (int)y ); break;
+ case cmXOR: resTok.SetVal( (int)x ^ (int)y ); break;
+ case cmLT: resTok.SetVal( x < y ); break;
+ case cmGT: resTok.SetVal( x > y ); break;
+ case cmLE: resTok.SetVal( x <= y ); break;
+ case cmGE: resTok.SetVal( x >= y ); break;
+ case cmNEQ: resTok.SetVal( x != y ); break;
+ case cmEQ: resTok.SetVal( x == y ); break;
+ case cmADD: resTok.SetVal( x + y ); break;
+ case cmSUB: resTok.SetVal( x - y ); break;
+ case cmMUL: resTok.SetVal( x * y ); break;
+ case cmDIV: resTok.SetVal( x / y ); break;
+ case cmPOW: resTok.SetVal(pow(x, y)); break;
+
+ case cmASSIGN:
+ // The assignement operator needs special treatment
+ // it uses a different format when stored in the bytecode!
+ {
+ if (valTok2.GetCode()!=cmVAR)
+ Error(ecINTERNAL_ERROR, 7);
+
+ value_type *pVar = valTok2.GetVar();
+ resTok.SetVal( *pVar = y );
+ a_stVal.push( resTok );
+
+ m_vByteCode.AddAssignOp(pVar);
+ return; // we must return since the following
+ // stuff does not apply
+ }
+
+ default: Error(ecINTERNAL_ERROR, 8);
+ }
+
+ // Create the bytecode entries
+ if (!m_bOptimize)
+ {
+ // Optimization flag is not set
+ m_vByteCode.AddOp(optTok.GetCode());
+ }
+ else if ( valTok1.IsFlagSet(token_type::flVOLATILE) ||
+ valTok2.IsFlagSet(token_type::flVOLATILE) )
+ {
+ // Optimization flag is not set, but one of the value
+ // depends on a variable
+ m_vByteCode.AddOp(optTok.GetCode());
+ resTok.AddFlags(token_type::flVOLATILE);
+ }
+ else
+ {
+ // operator call can be optimized; If optimization is possible
+ // the two previous tokens must be value tokens / they will be removed
+ // and replaced with the result of the pending operation.
+ m_vByteCode.RemoveValEntries(2);
+ m_vByteCode.AddVal(resTok.GetVal());
+ }
+
+ a_stVal.push( resTok );
+ }
+}
+
+//---------------------------------------------------------------------------
+/** \brief Parse the command code.
+
+ Command code contains precalculated stack positions of the values and the
+ associated operators.
+ The Stack is filled beginning from index one the value at index zero is
+ not used at all.
+
+ \sa ParseString(), ParseValue()
+*/
+value_type ParserBase::ParseCmdCode() const
+{
+#if defined(_MSC_VER)
+ #pragma warning( disable : 4312 )
+#endif
+
+ value_type Stack[99];
+ ECmdCode iCode;
+ bytecode_type idx(0);
+ int i(0);
+
+ __start:
+
+ idx = m_pCmdCode[i];
+ iCode = (ECmdCode)m_pCmdCode[i+1];
+ i += 2;
+
+#ifdef _DEBUG
+ if (idx>=99)
+ throw exception_type(ecGENERIC, _T(""), m_pTokenReader->GetFormula(), -1);
+#endif
+
+ switch (iCode)
+ {
+ // built in binary operators
+ case cmAND: Stack[idx] = (int)Stack[idx] & (int)Stack[idx+1]; goto __start;
+ case cmOR: Stack[idx] = (int)Stack[idx] | (int)Stack[idx+1]; goto __start;
+ case cmXOR: Stack[idx] = (int)Stack[idx] ^ (int)Stack[idx+1]; goto __start;
+ case cmLE: Stack[idx] = Stack[idx] <= Stack[idx+1]; goto __start;
+ case cmGE: Stack[idx] = Stack[idx] >= Stack[idx+1]; goto __start;
+ case cmNEQ: Stack[idx] = Stack[idx] != Stack[idx+1]; goto __start;
+ case cmEQ: Stack[idx] = Stack[idx] == Stack[idx+1]; goto __start;
+ case cmLT: Stack[idx] = Stack[idx] < Stack[idx+1]; goto __start;
+ case cmGT: Stack[idx] = Stack[idx] > Stack[idx+1]; goto __start;
+ case cmADD: Stack[idx] += Stack[1+idx]; goto __start;
+ case cmSUB: Stack[idx] -= Stack[1+idx]; goto __start;
+ case cmMUL: Stack[idx] *= Stack[1+idx]; goto __start;
+ case cmDIV: Stack[idx] /= Stack[1+idx]; goto __start;
+ case cmPOW: Stack[idx] = pow(Stack[idx], Stack[1+idx]); goto __start;
+
+ // Assignement needs special treatment
+ case cmASSIGN:
+ {
+ // next is a pointer to the target
+ value_type **pDest = (value_type**)(&m_pCmdCode[i]);
+
+ // advance index according to pointer size
+ i += m_vByteCode.GetPtrSize();
+ // assign the value
+ Stack[idx] = **pDest = Stack[idx+1];
+ }
+ goto __start;
+
+ // user defined binary operators
+ case cmOPRT_BIN:
+ Stack[idx] = (**(fun_type2**)(&m_pCmdCode[i]))(Stack[idx], Stack[idx+1]);
+ ++i;
+ goto __start;
+
+ // variable tokens
+ case cmVAR:
+ Stack[idx] = **(value_type**)(&m_pCmdCode[i]);
+ i += m_vByteCode.GetValSize();
+ goto __start;
+
+ // value tokens
+ case cmVAL:
+ Stack[idx] = *(value_type*)(&m_pCmdCode[i]);
+ i += m_vByteCode.GetValSize();
+ goto __start;
+
+ // Next is treatment of string functions
+ case cmFUNC_STR:
+ {
+ // The function argument count
+ int iArgCount = (int)m_pCmdCode[ i++ ];
+
+ // The index of the string argument in the string table
+ int iIdxStack = (int)m_pCmdCode[ i++ ];
+ MUP_ASSERT( iIdxStack>=0 && iIdxStack<(int)m_vStringBuf.size() );
+
+ switch(iArgCount) // switch according to argument count
+ {
+ case 0: Stack[idx] = (*(strfun_type1*)(&m_pCmdCode[i]))(m_vStringBuf[iIdxStack].c_str()); break;
+ case 1: Stack[idx] = (*(strfun_type2*)(&m_pCmdCode[i]))(m_vStringBuf[iIdxStack].c_str(), Stack[idx]); break;
+ case 2: Stack[idx] = (*(strfun_type3*)(&m_pCmdCode[i]))(m_vStringBuf[iIdxStack].c_str(), Stack[idx], Stack[idx+1]); break;
+ }
+ i += m_vByteCode.GetPtrSize();
+ }
+ goto __start;
+
+ // Next is treatment of numeric functions
+ case cmFUNC:
+ {
+ int iArgCount = (int)m_pCmdCode[i++];
+
+ switch(iArgCount) // switch according to argument count
+ {
+ case 1: Stack[idx] = (*(fun_type1*)(&m_pCmdCode[i]))(Stack[idx]); break;
+ case 2: Stack[idx] = (*(fun_type2*)(&m_pCmdCode[i]))(Stack[idx], Stack[idx+1]); break;
+ case 3: Stack[idx] = (*(fun_type3*)(&m_pCmdCode[i]))(Stack[idx], Stack[idx+1], Stack[idx+2]); break;
+ case 4: Stack[idx] = (*(fun_type4*)(&m_pCmdCode[i]))(Stack[idx], Stack[idx+1], Stack[idx+2], Stack[idx+3]); break;
+ case 5: Stack[idx] = (*(fun_type5*)(&m_pCmdCode[i]))(Stack[idx], Stack[idx+1], Stack[idx+2], Stack[idx+3], Stack[idx+4]); break;
+ default:
+ if (iArgCount>0) // function with variable arguments store the number as a negative value
+ Error(ecINTERNAL_ERROR, 1);
+
+ Stack[idx] =(*(multfun_type*)(&m_pCmdCode[i]))(&Stack[idx], -iArgCount);
+ break;
+ }
+ i += m_vByteCode.GetPtrSize();
+ }
+ goto __start;
+
+ case cmEND:
+ return Stack[1];
+
+ default:
+ Error(ecINTERNAL_ERROR, 2);
+ return 0;
+ }
+
+#if defined(_MSC_VER)
+ #pragma warning( default : 4312 )
+#endif
+}
+
+//---------------------------------------------------------------------------
+/** \brief Return result for constant functions.
+
+ Seems pointless, but for parser functions that are made up of only a value, which occur
+ in real world applications, this speeds up things by removing the parser overhead almost
+ completely.
+*/
+value_type ParserBase::ParseValue() const
+{
+ return *(value_type*)(&m_pCmdCode[2]);
+}
+
+//---------------------------------------------------------------------------
+/** \brief One of the two main parse functions.
+
+ Parse expression from input string. Perform syntax checking and create bytecode.
+ After parsing the string and creating the bytecode the function pointer
+ #m_pParseFormula will be changed to the second parse routine the uses bytecode instead of string parsing.
+
+ \sa ParseCmdCode(), ParseValue()
+*/
+value_type ParserBase::ParseString() const
+{
+#if defined(_MSC_VER)
+ #pragma warning( disable : 4311 )
+#endif
+ if (!m_pTokenReader->GetFormula().length())
+ Error(ecUNEXPECTED_EOF, 0);
+
+ ParserStack<token_type> stOpt, stVal;
+ ParserStack<int> stArgCount;
+ token_type opta, opt; // for storing operators
+ token_type val, tval; // for storing value
+ string_type strBuf; // buffer for string function arguments
+
+ ReInit();
+
+ for(;;)
+ {
+ opt = m_pTokenReader->ReadNextToken();
+
+ switch (opt.GetCode())
+ {
+ //
+ // Next three are different kind of value entries
+ //
+ case cmSTRING:
+ opt.SetIdx((int)m_vStringBuf.size()); // Assign buffer index to token
+ stVal.push(opt);
+ m_vStringBuf.push_back(opt.GetAsString()); // Store string in internal buffer
+ break;
+
+ case cmVAR:
+ stVal.push(opt);
+ m_vByteCode.AddVar( static_cast<value_type*>(opt.GetVar()) );
+ break;
+
+ case cmVAL:
+ stVal.push(opt);
+ m_vByteCode.AddVal( opt.GetVal() );
+ break;
+
+ case cmCOMMA:
+ if (stArgCount.empty())
+ Error(ecUNEXPECTED_COMMA, m_pTokenReader->GetPos());
+ ++stArgCount.top(); // Record number of arguments
+ // fall through...
+ case cmEND:
+ case cmBC:
+ {
+ while ( stOpt.size() && stOpt.top().GetCode() != cmBO)
+ {
+ if (stOpt.top().GetCode()==cmOPRT_INFIX)
+ ApplyFunc(stOpt, stVal, 1); // infix operator
+ else
+ ApplyBinOprt(stOpt, stVal);
+ }
+
+ // <ibg> 20060218 infix operator treatment moved here
+ if (stOpt.size() && stOpt.top().GetCode()==cmOPRT_INFIX)
+ ApplyFunc(stOpt, stVal, 1); // infix operator
+
+ if ( opt.GetCode()!=cmBC || stOpt.size()==0 || stOpt.top().GetCode()!=cmBO )
+ break;
+
+ // if opt is ")" and opta is "(" the bracket has been evaluated, now its time to check
+ // if there is either a function or a sign pending
+ // neither the opening nor the closing bracket will be pushed back to
+ // the operator stack
+ // Check if a function is standing in front of the opening bracket,
+ // if yes evaluate it afterwards check for infix operators
+ assert(stArgCount.size());
+ int iArgCount = stArgCount.pop();
+
+ stOpt.pop(); // Take opening bracket from stack
+
+ if (iArgCount>1 && ( stOpt.size()==0 ||
+ (stOpt.top().GetCode()!=cmFUNC &&
+ stOpt.top().GetCode()!=cmFUNC_STR) ) )
+ Error(ecUNEXPECTED_ARG, m_pTokenReader->GetPos());
+
+ if (stOpt.size() && stOpt.top().GetCode()!=cmOPRT_INFIX)
+ ApplyFunc(stOpt, stVal, iArgCount);
+ } // if bracket content is evaluated
+ break;
+
+ //
+ // Next are the binary operator entries
+ //
+ case cmAND: // built in binary operators
+ case cmOR:
+ case cmXOR:
+ case cmLT:
+ case cmGT:
+ case cmLE:
+ case cmGE:
+ case cmNEQ:
+ case cmEQ:
+ case cmADD:
+ case cmSUB:
+ case cmMUL:
+ case cmDIV:
+ case cmPOW:
+ case cmASSIGN:
+ case cmOPRT_BIN:
+ // A binary operator (user defined or built in) has been found.
+ while ( stOpt.size() && stOpt.top().GetCode() != cmBO)
+ {
+ if (GetOprtPri(stOpt.top()) < GetOprtPri(opt))
+ break;
+
+ if (stOpt.top().GetCode()==cmOPRT_INFIX)
+ ApplyFunc(stOpt, stVal, 1); // infix operator
+ else
+ ApplyBinOprt(stOpt, stVal);
+ } // while ( ... )
+
+ // The operator can't be evaluated right now, push back to the operator stack
+ stOpt.push(opt);
+ break;
+
+ //
+ // Last section contains functions and operators implicitely mapped to functions
+ //
+ case cmBO:
+ stArgCount.push( (stOpt.size() && stOpt.top().GetCode()==cmFUNC_STR) ? 0 : 1 );
+ stOpt.push(opt);
+ break;
+
+ case cmFUNC_STR:
+ case cmFUNC:
+ case cmOPRT_INFIX:
+ stOpt.push(opt);
+ break;
+
+ case cmOPRT_POSTFIX:
+ stOpt.push(opt);
+ ApplyFunc(stOpt, stVal, 1); // this is the postfix operator
+ break;
+
+ default: Error(ecINTERNAL_ERROR, 3);
+ } // end of switch operator-token
+
+ if ( opt.GetCode() == cmEND )
+ {
+ m_vByteCode.Finalize();
+ break;
+ }
+
+#if defined(MUP_DUMP_STACK)
+ StackDump(stVal, stOpt);
+ m_vByteCode.AsciiDump();
+#endif
+ } // while (true)
+
+ // Store pointer to start of bytecode
+ m_pCmdCode = m_vByteCode.GetRawData();
+
+#if defined(MUP_DUMP_CMDCODE)
+ m_vByteCode.AsciiDump();
+#endif
+
+ // get the last value (= final result) from the stack
+ if (stVal.size()!=1)
+ Error(ecEMPTY_EXPRESSION);
+
+ if (stVal.top().GetType()!=tpDBL)
+ Error(ecSTR_RESULT);
+
+ // no error, so change the function pointer for the main parse routine
+ value_type fVal = stVal.top().GetVal(); // Result from String parsing
+
+ if (m_bUseByteCode)
+ {
+ m_pParseFormula = (m_pCmdCode[1]==cmVAL && m_pCmdCode[6]==cmEND) ?
+ &ParserBase::ParseValue :
+ &ParserBase::ParseCmdCode;
+ }
+
+ return fVal;
+
+#if defined(_MSC_VER)
+ #pragma warning( default : 4311 )
+#endif
+}
+
+
+//---------------------------------------------------------------------------
+/** \brief Create an error containing the parse error position.
+
+ This function will create an Parser Exception object containing the error text and
+ its position.
+
+ \param a_iErrc [in] The error code of type #EErrorCodes.
+ \param a_iPos [in] The position where the error was detected.
+ \param a_strTok [in] The token string representation associated with the error.
+ \throw ParserException always throws thats the only purpose of this function.
+*/
+void ParserBase::Error(EErrorCodes a_iErrc, int a_iPos, const string_type &a_sTok) const
+{
+ throw exception_type(a_iErrc, a_sTok, m_pTokenReader->GetFormula(), a_iPos);
+}
+
+//------------------------------------------------------------------------------
+/** \brief Clear all user defined variables.
+
+ Resets the parser to string parsing mode by calling #ReInit.
+ \throw nothrow
+*/
+void ParserBase::ClearVar()
+{
+ m_VarDef.clear();
+ ReInit();
+}
+
+//------------------------------------------------------------------------------
+/** \brief Remove a variable from internal storage.
+
+Removes a variable if it exists. If the Variable does not exist nothing will be done.
+
+\throw nothrow
+*/
+void ParserBase::RemoveVar(const string_type &a_strVarName)
+{
+ varmap_type::iterator item = m_VarDef.find(a_strVarName);
+ if (item!=m_VarDef.end())
+ {
+ m_VarDef.erase(item);
+ ReInit();
+ }
+}
+
+//------------------------------------------------------------------------------
+/** \brief Clear the formula.
+
+Clear the formula and existing bytecode.
+
+\post Resets the parser to string parsing mode.
+\throw nothrow
+*/
+void ParserBase::ClearFormula()
+{
+ m_vByteCode.clear();
+ m_pCmdCode = 0;
+ m_pTokenReader->SetFormula(_T(""));
+ ReInit();
+}
+
+//------------------------------------------------------------------------------
+/** \brief Clear all functions.
+ \post Resets the parser to string parsing mode.
+ \throw nothrow
+*/
+void ParserBase::ClearFun()
+{
+ m_FunDef.clear();
+ ReInit();
+}
+
+//------------------------------------------------------------------------------
+/** \brief Clear all user defined constants.
+
+ Both numeric and string constants will be removed from the internal storage.
+ \post Resets the parser to string parsing mode.
+ \throw nothrow
+*/
+void ParserBase::ClearConst()
+{
+ m_ConstDef.clear();
+ m_StrVarDef.clear();
+ ReInit();
+}
+
+//------------------------------------------------------------------------------
+/** \brief Clear all user defined postfix operators.
+ \post Resets the parser to string parsing mode.
+ \throw nothrow
+*/
+void ParserBase::ClearPostfixOprt()
+{
+ m_PostOprtDef.clear();
+ ReInit();
+}
+
+//------------------------------------------------------------------------------
+/** \brief Clear all user defined binary operators.
+ \post Resets the parser to string parsing mode.
+ \throw nothrow
+*/
+void ParserBase::ClearOprt()
+{
+ m_OprtDef.clear();
+ ReInit();
+}
+
+//------------------------------------------------------------------------------
+/** \brief Clear the user defined Prefix operators.
+ \post Resets the parser to string parser mode.
+ \throw nothrow
+*/
+void ParserBase::ClearInfixOprt()
+{
+ m_InfixOprtDef.clear();
+ ReInit();
+}
+
+//------------------------------------------------------------------------------
+/** \brief Enable or disable the formula optimization feature.
+ \post Resets the parser to string parser mode.
+ \throw nothrow
+*/
+void ParserBase::EnableOptimizer(bool a_bIsOn)
+{
+ m_bOptimize = a_bIsOn;
+ ReInit();
+}
+
+//------------------------------------------------------------------------------
+/** \brief Enable or disable parsing from Bytecode.
+
+ \attention There is no reason to disable bytecode. It will
+ drastically decrease parsing speed.
+*/
+void ParserBase::EnableByteCode(bool a_bIsOn)
+{
+ m_bUseByteCode = a_bIsOn;
+ if (!a_bIsOn)
+ ReInit();
+}
+
+//------------------------------------------------------------------------------
+/** \brief Enable or disable the built in binary operators.
+ \throw nothrow
+ \sa m_bBuiltInOp, ReInit()
+
+ If you disable the built in binary operators there will be no binary operators
+ defined. Thus you must add them manually one by one. It is not possible to
+ disable built in operators selectively. This function will Reinitialize the
+ parser by calling ReInit().
+*/
+void ParserBase::EnableBuiltInOprt(bool a_bIsOn)
+{
+ m_bBuiltInOp = a_bIsOn;
+ ReInit();
+}
+
+//------------------------------------------------------------------------------
+/** \brief Query status of built in variables.
+ \return #m_bBuiltInOp; true if built in operators are enabled.
+ \throw nothrow
+*/
+bool ParserBase::HasBuiltInOprt() const
+{
+ return m_bBuiltInOp;
+}
+
+#if defined(MUP_DUMP_STACK) | defined(MUP_DUMP_CMDCODE)
+
+//------------------------------------------------------------------------------
+/** \brief Dump stack content.
+
+ This function is used for debugging only.
+*/
+void ParserBase::StackDump( const ParserStack<token_type> &a_stVal,
+ const ParserStack<token_type> &a_stOprt ) const
+{
+ ParserStack<token_type> stOprt(a_stOprt),
+ stVal(a_stVal);
+
+ mu::console() << _T("\nValue stack:\n");
+ while ( !stVal.empty() )
+ {
+ token_type val = stVal.pop();
+ if (val.GetType()==tpSTR)
+ mu::console() << _T(" \"") << val.GetAsString() << _T("\" ");
+ else
+ mu::console() << _T(" ") << val.GetVal() << _T(" ");
+ }
+ mu::console() << "\nOperator stack:\n";
+
+ while ( !stOprt.empty() )
+ {
+ if (stOprt.top().GetCode()<=cmASSIGN)
+ {
+ mu::console() << _T("OPRT_INTRNL \"")
+ << ParserBase::c_DefaultOprt[stOprt.top().GetCode()]
+ << _T("\" \n");
+ }
+ else
+ {
+ switch(stOprt.top().GetCode())
+ {
+ case cmVAR: mu::console() << _T("VAR\n"); break;
+ case cmVAL: mu::console() << _T("VAL\n"); break;
+ case cmFUNC: mu::console() << _T("FUNC_NUM \"")
+ << stOprt.top().GetAsString()
+ << _T("\"\n"); break;
+ case cmOPRT_INFIX: mu::console() << _T("OPRT_INFIX \"")
+ << stOprt.top().GetAsString()
+ << _T("\"\n"); break;
+ case cmOPRT_BIN: mu::console() << _T("OPRT_BIN \"")
+ << stOprt.top().GetAsString()
+ << _T("\"\n"); break;
+ case cmFUNC_STR: mu::console() << _T("FUNC_STR\n"); break;
+ case cmEND: mu::console() << _T("END\n"); break;
+ case cmUNKNOWN: mu::console() << _T("UNKNOWN\n"); break;
+ case cmBO: mu::console() << _T("BRACKET \"(\"\n"); break;
+ case cmBC: mu::console() << _T("BRACKET \")\"\n"); break;
+ default: mu::console() << stOprt.top().GetType() << _T(" "); break;
+ }
+ }
+ stOprt.pop();
+ }
+
+ mu::console() << dec << endl;
+}
+
+#endif // defined(MUP_DUMP_STACK) | defined(MUP_DUMP_CMDCODE)
+
+} // namespace mu
+
+
diff --git a/muparser/muParserBase.h b/muparser/muParserBase.h
new file mode 100644
index 0000000..c4cc433
--- /dev/null
+++ b/muparser/muParserBase.h
@@ -0,0 +1,324 @@
+/*
+ __________
+ _____ __ __\______ \_____ _______ ______ ____ _______
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
+ \/ \/ \/ \/
+ Copyright (C) 2004-2006 Ingo Berg
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ software and associated documentation files (the "Software"), to deal in the Software
+ without restriction, including without limitation the rights to use, copy, modify,
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef MU_PARSER_BASE_H
+#define MU_PARSER_BASE_H
+
+#include <cmath>
+#include <string>
+#include <iostream>
+#include <map>
+#include <memory>
+
+#include "muParserDef.h"
+#include "muParserStack.h"
+#include "muParserTokenReader.h"
+#include "muParserBytecode.h"
+#include "muParserError.h"
+
+
+namespace mu
+{
+
+/** \brief Mathematical expressions parser (base parser engine).
+
+ Version 1.27 (20061201)
+
+ This is the implementation of a bytecode based mathematical expressions parser.
+ The formula will be parsed from string and converted into a bytecode.
+ Future calculations will be done with the bytecode instead the formula string
+ resulting in a significant performance increase.
+ Complementary to a set of internally implemented functions the parser is able to handle
+ user defined functions and variables.
+
+ \author (C) 2004-2006 Ingo Berg
+*/
+class ParserBase
+{
+friend class ParserTokenReader;
+
+private:
+ typedef value_type (ParserBase::*ParseFunction)() const;
+ typedef ParserToken<value_type, string_type> token_type;
+ typedef std::vector<string_type> stringbuf_type;
+ typedef ParserTokenReader token_reader_type;
+
+ static const char_type *c_DefaultOprt[];
+
+ public:
+ /** \brief Type of the error class.
+
+ Included for backwards compatibility.
+ */
+ typedef ParserError exception_type;
+
+ ParserBase();
+ ParserBase( const ParserBase &a_Parser );
+ ParserBase& operator=(const ParserBase &a_Parser);
+
+ //---------------------------------------------------------------------------
+ /** \brief Destructor. (trivial)
+
+ \throw nothrow
+ */
+ virtual ~ParserBase()
+ {}
+
+ //---------------------------------------------------------------------------
+ /** \brief Calculate the result.
+
+ A note on const correctness:
+ I consider it important that Calc is a const function.
+ Due to caching operations Calc changes only the state of internal variables with one exception
+ m_UsedVar this is reset during string parsing and accessible from the outside. Instead of making
+ Calc non const GetUsedVar is non const because it explicitely calls Eval() forcing this update.
+
+ \pre A formula must be set.
+ \pre Variables must have been set (if needed)
+
+ \sa #m_pParseFormula
+ \return The evaluation result
+ \throw ParseException if no Formula is set or in case of any other error related to the formula.
+ */
+ inline value_type Eval() const
+ {
+ return (this->*m_pParseFormula)();
+ }
+
+ void SetExpr(const string_type &a_sExpr);
+ void SetVarFactory(facfun_type a_pFactory, void *pUserData = NULL);
+
+ void EnableOptimizer(bool a_bIsOn=true);
+ void EnableByteCode(bool a_bIsOn=true);
+ void EnableBuiltInOprt(bool a_bIsOn=true);
+
+ bool HasBuiltInOprt() const;
+ void AddValIdent(identfun_type a_pCallback);
+
+#define MUP_DEFINE_FUNC(TYPE) \
+ inline void DefineFun(const string_type &a_strName, TYPE a_pFun, bool a_bAllowOpt = true) \
+ { \
+ AddCallback( a_strName, ParserCallback(a_pFun, a_bAllowOpt), \
+ m_FunDef, ValidNameChars() ); \
+ }
+
+ MUP_DEFINE_FUNC(fun_type1)
+ MUP_DEFINE_FUNC(fun_type2)
+ MUP_DEFINE_FUNC(fun_type3)
+ MUP_DEFINE_FUNC(fun_type4)
+ MUP_DEFINE_FUNC(fun_type5)
+ MUP_DEFINE_FUNC(multfun_type)
+ MUP_DEFINE_FUNC(strfun_type1)
+ MUP_DEFINE_FUNC(strfun_type2)
+ MUP_DEFINE_FUNC(strfun_type3)
+#undef MUP_DEFINE_FUNC
+
+ void DefineOprt(const string_type &a_strName, fun_type2 a_pFun, unsigned a_iPri=0, bool a_bAllowOpt = false);
+ void DefineConst(const string_type &a_sName, value_type a_fVal);
+ void DefineStrConst(const string_type &a_sName, const string_type &a_strVal);
+ void DefineVar(const string_type &a_sName, value_type *a_fVar);
+ void DefinePostfixOprt(const string_type &a_strFun, fun_type1 a_pOprt, bool a_bAllowOpt=true);
+ void DefineInfixOprt(const string_type &a_strName, fun_type1 a_pOprt, int a_iPrec=prINFIX, bool a_bAllowOpt=true);
+
+ // Clear user defined variables, constants or functions
+ void ClearVar();
+ void ClearFun();
+ void ClearConst();
+ void ClearInfixOprt();
+ void ClearPostfixOprt();
+ void ClearOprt();
+
+ void RemoveVar(const string_type &a_strVarName);
+ const varmap_type& GetUsedVar() const;
+ const varmap_type& GetVar() const;
+ const valmap_type& GetConst() const;
+ const string_type& GetExpr() const;
+ const funmap_type& GetFunDef() const;
+
+ //---------------------------------------------------------------------------
+ /** \brief Return the strings of all Operator identifiers.
+
+ GetOprt is a const function returning a pinter to an array of const char pointers.
+
+ \return Returns a pointer to the c_DefaultOprt array of const char *.
+ \throw nothrow
+ */
+ const char_type ** GetOprtDef() const
+ {
+ return (const char_type **)(&c_DefaultOprt[0]);
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Define the set of valid characters to be used in names of
+ functions, variables, constants.
+ */
+ void DefineNameChars(const char_type *a_szCharset)
+ {
+ m_sNameChars = a_szCharset;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Define the set of valid characters to be used in names of
+ binary operators and postfix operators.
+ */
+ void DefineOprtChars(const char_type *a_szCharset)
+ {
+ m_sOprtChars = a_szCharset;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Define the set of valid characters to be used in names of
+ infix operators.
+ */
+ void DefineInfixOprtChars(const char_type *a_szCharset)
+ {
+ m_sInfixOprtChars = a_szCharset;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Virtual function that defines the characters allowed in name identifiers.
+ \sa #ValidOprtChars, #ValidPrefixOprtChars
+ */
+ const char_type* ValidNameChars() const
+ {
+ assert(m_sNameChars.size());
+ return m_sNameChars.c_str();
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Virtual function that defines the characters allowed in operator definitions.
+ \sa #ValidNameChars, #ValidPrefixOprtChars
+ */
+ const char_type* ValidOprtChars() const
+ {
+ assert(m_sOprtChars.size());
+ return m_sOprtChars.c_str();
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Virtual function that defines the characters allowed in infix operator definitions.
+ \sa #ValidNameChars, #ValidOprtChars
+ */
+ const char_type* ValidInfixOprtChars() const
+ {
+ assert(m_sInfixOprtChars.size());
+ return m_sInfixOprtChars.c_str();
+ }
+
+ void Error( EErrorCodes a_iErrc,
+ int a_iPos = (int)mu::string_type::npos,
+ const string_type &a_strTok = string_type() ) const;
+
+ protected:
+
+ //---------------------------------------------------------------------------
+ /** \brief Initialize user defined functions.
+
+ Calls the virtual functions InitFun(), InitConst() and InitOprt().
+ */
+ void Init()
+ {
+ InitCharSets();
+ InitFun();
+ InitConst();
+ InitOprt();
+ }
+
+ //---------------------------------------------------------------------------
+ virtual void InitCharSets() = 0;
+ virtual void InitFun() = 0;
+ virtual void InitConst() = 0;
+ virtual void InitOprt() = 0;
+
+ private:
+ void Assign(const ParserBase &a_Parser);
+ void InitTokenReader();
+ void ReInit() const;
+
+ void AddCallback( const string_type &a_strName,
+ const ParserCallback &a_Callback,
+ funmap_type &a_Storage,
+ const char_type *a_szCharSet );
+
+ void ApplyBinOprt(ParserStack<token_type> &a_stOpt,
+ ParserStack<token_type> &a_stVal) const;
+
+ void ApplyFunc(ParserStack<token_type> &a_stOpt,
+ ParserStack<token_type> &a_stVal,
+ int iArgCount) const;
+
+ token_type ApplyNumFunc(const token_type &a_FunTok,
+ const std::vector<token_type> &a_vArg) const;
+
+ token_type ApplyStrFunc(const token_type &a_FunTok,
+ const std::vector<token_type> &a_vArg) const;
+
+ int GetOprtPri(const token_type &a_Tok) const;
+
+ value_type ParseString() const;
+ value_type ParseCmdCode() const;
+ value_type ParseValue() const;
+
+ void ClearFormula();
+ void CheckName(const string_type &a_strName, const string_type &a_CharSet) const;
+
+#if defined(MUP_DUMP_STACK) | defined(MUP_DUMP_CMDCODE)
+ void StackDump(const ParserStack<token_type > &a_stVal,
+ const ParserStack<token_type > &a_stOprt) const;
+#endif
+
+ /** \brief Pointer to the parser function.
+
+ Eval() calls the function whose address is stored there.
+ */
+ mutable ParseFunction m_pParseFormula;
+ mutable const ParserByteCode::map_type *m_pCmdCode; ///< Formula converted to bytecode, points to the data of the bytecode class.
+ mutable ParserByteCode m_vByteCode; ///< The Bytecode class.
+ mutable stringbuf_type m_vStringBuf; ///< String buffer, used for storing string function arguments
+ stringbuf_type m_vStringVarBuf;
+
+ /** \brief Managed pointer to the token reader object. */
+ std::auto_ptr<token_reader_type> m_pTokenReader;
+
+ funmap_type m_FunDef; ///< Map of function names and pointers.
+ funmap_type m_PostOprtDef; ///< Postfix operator callbacks
+ funmap_type m_InfixOprtDef; ///< unary infix operator.
+ funmap_type m_OprtDef; ///< Binary operator callbacks
+ valmap_type m_ConstDef; ///< user constants.
+ strmap_type m_StrVarDef; ///< user defined string constants
+ varmap_type m_VarDef; ///< user defind variables.
+
+ bool m_bOptimize; ///< Flag that indicates if the optimizer is on or off.
+ bool m_bUseByteCode; ///< Flag that indicates if bytecode parsing is on or off.
+ bool m_bBuiltInOp; ///< Flag that can be used for switching built in operators on and off
+
+ string_type m_sNameChars; ///< Charset for names
+ string_type m_sOprtChars; ///< Charset for postfix/ binary operator tokens
+ string_type m_sInfixOprtChars; ///< Charset for infix operator tokens
+};
+
+} // namespace mu
+
+#endif
+
diff --git a/muparser/muParserBytecode.cpp b/muparser/muParserBytecode.cpp
new file mode 100644
index 0000000..7c8db24
--- /dev/null
+++ b/muparser/muParserBytecode.cpp
@@ -0,0 +1,396 @@
+/*
+ __________
+ _____ __ __\______ \_____ _______ ______ ____ _______
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
+ \/ \/ \/ \/
+ Copyright (C) 2004-2006 Ingo Berg
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ software and associated documentation files (the "Software"), to deal in the Software
+ without restriction, including without limitation the rights to use, copy, modify,
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "muParserBytecode.h"
+
+#include <cassert>
+#include <string>
+#include <stack>
+#include <vector>
+#include <iostream>
+
+#include "muParserDef.h"
+#include "muParserError.h"
+#include "muParserToken.h"
+
+
+namespace mu
+{
+
+ //---------------------------------------------------------------------------
+ /** \brief Bytecode default constructor.
+
+ \pre [assert] sizeof(value_type)>=sizeof(map_type)
+ \pre [assert] sizeof(value_type*)>=sizeof(map_type)
+ */
+ ParserByteCode::ParserByteCode()
+ :m_iStackPos(0)
+ ,m_vBase()
+ ,mc_iSizeVal( sizeof(value_type) / sizeof(map_type) )
+ ,mc_iSizePtr( std::max( (int)sizeof(value_type*) /
+ (int)sizeof(map_type), 1 ) )
+ ,mc_iSizeValEntry( 2 + mc_iSizeVal)
+ {
+ m_vBase.reserve(1000);
+ assert( sizeof(value_type)>=sizeof(map_type) );
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Destructor (trivial).*/
+ ParserByteCode::~ParserByteCode()
+ {}
+
+ //---------------------------------------------------------------------------
+ /** \brief Copy constructor.
+
+ Implemented in Terms of Assign(const ParserByteCode &a_ByteCode)
+ */
+ ParserByteCode::ParserByteCode(const ParserByteCode &a_ByteCode)
+ :mc_iSizeVal( sizeof(value_type)/sizeof(map_type) )
+ ,mc_iSizePtr( sizeof(value_type*) / sizeof(map_type) )
+ ,mc_iSizeValEntry( 2 + mc_iSizeVal)
+ {
+ Assign(a_ByteCode);
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Assignment operator.
+
+ Implemented in Terms of Assign(const ParserByteCode &a_ByteCode)
+ */
+ ParserByteCode& ParserByteCode::operator=(const ParserByteCode &a_ByteCode)
+ {
+ Assign(a_ByteCode);
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Store an address in bytecode.
+
+ \param a_pAddr Address to be stored.
+ \throw nothrow
+ */
+ void ParserByteCode::StorePtr(void *a_pAddr)
+ {
+ #if defined(_MSC_VER)
+ #pragma warning( disable : 4311 )
+ #endif
+
+ // demo code for packing / unpacking pointers into bytecode
+// void *ptr(NULL);
+// double **pVal;
+// double fVal;
+// map_type dbg[2];
+// dbg[0] = *( reinterpret_cast<map_type*>(&a_pAddr) ),
+// dbg[1] = *( reinterpret_cast<map_type*>(&a_pAddr) + 1 );
+// Version 1:
+// *( (map_type*)&ptr+0) = dbg[0];
+// *( (map_type*)&ptr+1) = dbg[1];
+// Version 2:
+// memcpy(&ptr, dbg, sizeof(dbg));
+// Version 3:
+// pVal = (double**)dbg;
+// fVal = **(double**)dbg;
+
+ for (int i=0; i<mc_iSizePtr; ++i)
+ {
+ m_vBase.push_back( *( reinterpret_cast<map_type*>(&a_pAddr) + i ) );
+ }
+
+ #if defined(_MSC_VER)
+ #pragma warning( default : 4311 )
+ #endif
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Copy state of another object to this.
+
+ \throw nowthrow
+ */
+ void ParserByteCode::Assign(const ParserByteCode &a_ByteCode)
+ {
+ if (this==&a_ByteCode)
+ return;
+
+ m_iStackPos = a_ByteCode.m_iStackPos;
+ m_vBase = a_ByteCode.m_vBase;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Add a Variable pointer to bytecode.
+ \param a_pVar Pointer to be added.
+ \throw nothrow
+ */
+ void ParserByteCode::AddVar(value_type *a_pVar)
+ {
+ m_vBase.push_back( ++m_iStackPos );
+ m_vBase.push_back( cmVAR );
+
+ StorePtr(a_pVar);
+
+ int iSize = GetValSize()-GetPtrSize();
+ assert(iSize>=0);
+
+ // Make sure variable entries have the same size like value entries.
+ // (necessary for optimization; fill with zeros)
+ for (int i=0; i<iSize; ++i)
+ m_vBase.push_back(0);
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Add a Variable pointer to bytecode.
+
+ Value entries in byte code consist of:
+ <ul>
+ <li>value array position of the value</li>
+ <li>the operator code according to ParserToken::cmVAL</li>
+ <li>the value stored in #mc_iSizeVal number of bytecode entries.</li>
+ </ul>
+
+ \param a_pVal Value to be added.
+ \throw nothrow
+ */
+ void ParserByteCode::AddVal(value_type a_fVal)
+ {
+ m_vBase.push_back( ++m_iStackPos );
+ m_vBase.push_back( cmVAL );
+
+ for (int i=0; i<mc_iSizeVal; ++i)
+ m_vBase.push_back( *(reinterpret_cast<map_type*>(&a_fVal) + i) );
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Add an operator identifier to bytecode.
+
+ Operator entries in byte code consist of:
+ <ul>
+ <li>value array position of the result</li>
+ <li>the operator code according to ParserToken::ECmdCode</li>
+ </ul>
+
+ \sa ParserToken::ECmdCode
+ */
+ void ParserByteCode::AddOp(ECmdCode a_Oprt)
+ {
+ m_vBase.push_back(--m_iStackPos);
+ m_vBase.push_back(a_Oprt);
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Add an assignement operator
+
+ Operator entries in byte code consist of:
+ <ul>
+ <li>cmASSIGN code</li>
+ <li>the pointer of the destination variable</li>
+ </ul>
+
+ \sa ParserToken::ECmdCode
+ */
+ void ParserByteCode::AddAssignOp(value_type *a_pVar)
+ {
+ m_vBase.push_back(--m_iStackPos);
+ m_vBase.push_back(cmASSIGN);
+ StorePtr(a_pVar);
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Add function to bytecode.
+
+ \param a_iArgc Number of arguments, negative numbers indicate multiarg functions.
+ \param a_pFun Pointer to function callback.
+ */
+ void ParserByteCode::AddFun(void *a_pFun, int a_iArgc)
+ {
+ if (a_iArgc>=0)
+ {
+ m_iStackPos = m_iStackPos - a_iArgc + 1;
+ }
+ else
+ {
+ m_iStackPos = m_iStackPos + a_iArgc + 1;
+ }
+
+ m_vBase.push_back(m_iStackPos);
+ m_vBase.push_back(cmFUNC);
+ m_vBase.push_back(a_iArgc);
+
+ StorePtr(a_pFun);
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Add Strung function entry to the parser bytecode.
+ \throw nothrow
+
+ A string function entry consists of the stack position of the return value,
+ followed by a cmSTRFUNC code, the function pointer and an index into the
+ string buffer maintained by the parser.
+ */
+ void ParserByteCode::AddStrFun(void *a_pFun, int a_iArgc, int a_iIdx)
+ {
+ m_iStackPos = m_iStackPos - a_iArgc + 1;
+ m_vBase.push_back(m_iStackPos);
+ m_vBase.push_back(cmFUNC_STR);
+ m_vBase.push_back(a_iArgc);
+ m_vBase.push_back(a_iIdx);
+
+ StorePtr(a_pFun);
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Add end marker to bytecode.
+
+ \throw nothrow
+ */
+ void ParserByteCode::Finalize()
+ {
+ // yes we need the end code three times!! (I forgot why)
+ m_vBase.push_back(cmEND);
+ m_vBase.push_back(cmEND);
+ m_vBase.push_back(cmEND);
+
+ // shrink bytecode vector to fit
+ storage_type(m_vBase).swap(m_vBase);
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Get Pointer to bytecode data storage. */
+ const ParserByteCode::map_type* ParserByteCode::GetRawData() const
+ {
+ assert(m_vBase.size());
+ return &m_vBase[0];
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Delete the bytecode.
+
+ \throw nothrow
+
+ The name of this function is a violation of my own coding guidelines
+ but this way it's more in line with the STL functions thus more
+ intuitive.
+ */
+ void ParserByteCode::clear()
+ {
+ m_vBase.clear();
+ m_iStackPos = 0;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Remove a value number of entries from the bytecode.
+
+ \attention Currently I don't test if the entries are really value entries.
+ */
+ void ParserByteCode::RemoveValEntries(unsigned a_iNumber)
+ {
+ unsigned iSize = a_iNumber * mc_iSizeValEntry;
+ assert( m_vBase.size() >= iSize );
+ m_vBase.resize(m_vBase.size()-iSize);
+
+ assert(m_iStackPos >= a_iNumber);
+ m_iStackPos -= (a_iNumber);
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Dump bytecode (for debugging only!). */
+ void ParserByteCode::AsciiDump()
+ {
+ if (!m_vBase.size())
+ {
+ std::cout << "No bytecode available\n";
+ return;
+ }
+
+ std::cout << "Entries:" << (int)m_vBase.size()
+ << " (ValSize:" << mc_iSizeVal
+ << " entries, PtrSize:" << mc_iSizePtr
+ << " entries, MapSize:" << sizeof(map_type)
+ << " byte)\n";
+ int i = 0;
+
+ while ( m_vBase[i] != cmEND && i<(int)m_vBase.size())
+ {
+ std::cout << "IDX[" << m_vBase[i++] << "]\t";
+ switch (m_vBase[i])
+ {
+ case cmVAL: std::cout << "VAL "; ++i;
+ std::cout << "[" << *( reinterpret_cast<double*>(&m_vBase[i]) ) << "]\n";
+ i += mc_iSizeVal;
+ break;
+
+ case cmVAR: std::cout << "VAR "; ++i;
+ std::cout << "[ADDR: 0x" << std::hex << *(value_type**)&m_vBase[i] << "]\n";
+ i += mc_iSizePtr;
+
+ // Variable entries have the same size like value entries
+ // the remaining spave must be skipped
+ i+= std::max(mc_iSizeVal - mc_iSizePtr, 0);
+ break;
+
+ case cmFUNC:
+ std::cout << "CALL\t"; ++i;
+ std::cout << "[ARG:" << std::dec << m_vBase[i] << "]"; ++i;
+ std::cout << "[ADDR: 0x" << std::hex << *(value_type**)&m_vBase[i] << "]\n";
+ i += mc_iSizePtr;
+ break;
+
+ case cmFUNC_STR:
+ std::cout << "CALL STRFUNC\t"; ++i;
+ std::cout << "[ARG:" << std::dec << m_vBase[i] << "]"; ++i;
+ std::cout << "[IDX:" << std::dec << m_vBase[i] << "]"; ++i;
+ std::cout << "[ADDR: 0x" << *(value_type**)&m_vBase[i] << "]\n";
+ i += mc_iSizePtr;
+ break;
+
+ case cmLT: std::cout << "LT\n"; ++i; break;
+ case cmGT: std::cout << "GT\n"; ++i; break;
+ case cmLE: std::cout << "LE\n"; ++i; break;
+ case cmGE: std::cout << "GE\n"; ++i; break;
+ case cmEQ: std::cout << "EQ\n"; ++i; break;
+ case cmNEQ: std::cout << "NEQ\n"; ++i; break;
+ case cmADD: std::cout << "ADD\n"; ++i; break;
+ case cmAND: std::cout << "AND\n"; ++i; break;
+ case cmOR: std::cout << "OR\n"; ++i; break;
+ case cmXOR: std::cout << "XOR\n"; ++i; break;
+ case cmSUB: std::cout << "SUB\n"; ++i; break;
+ case cmMUL: std::cout << "MUL\n"; ++i; break;
+ case cmDIV: std::cout << "DIV\n"; ++i; break;
+ case cmPOW: std::cout << "POW\n"; ++i; break;
+
+ case cmASSIGN:
+ std::cout << "ASSIGN\t"; ++i;
+ std::cout << "[ADDR: 0x" << *(value_type**)&m_vBase[i] << "]\n";
+ i += mc_iSizePtr;
+ break;
+
+ default: std::cout << "(unknown code: " << m_vBase[i] << ")\n";
+ ++i;
+ break;
+ } // switch cmdCode
+ } // while bytecode
+
+ std::cout << "END" << std::endl;
+ }
+} // namespace mu
diff --git a/muparser/muParserBytecode.h b/muparser/muParserBytecode.h
new file mode 100644
index 0000000..d425990
--- /dev/null
+++ b/muparser/muParserBytecode.h
@@ -0,0 +1,148 @@
+/*
+ __________
+ _____ __ __\______ \_____ _______ ______ ____ _______
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
+ \/ \/ \/ \/
+ Copyright (C) 2004-2006 Ingo Berg
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ software and associated documentation files (the "Software"), to deal in the Software
+ without restriction, including without limitation the rights to use, copy, modify,
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef MU_PARSER_BYTECODE_H
+#define MU_PARSER_BYTECODE_H
+
+#include <cassert>
+#include <string>
+#include <stack>
+#include <vector>
+
+#include "muParserDef.h"
+#include "muParserError.h"
+#include "muParserToken.h"
+
+
+namespace mu
+{
+
+
+/** \brief Bytecode implementation of the Math Parser.
+
+ The bytecode contains the formula converted to revers polish notation stored in a continious
+ memory area. Associated with this data are operator codes, variable pointers, constant
+ values and function pointers. Those are necessary in order to calculate the result.
+ All those data items will be casted to the underlying datatype of the bytecode.
+
+ \author (C) 2004, 2005 Ingo Berg
+*/
+class ParserByteCode
+{
+public:
+ /** \brief Underlying type of the container.
+
+ The bytecode is a vector of this type containing control codes,
+ values and pointers. Values and pointer will be casted to this
+ type before their storage.
+ */
+ typedef bytecode_type map_type;
+
+private:
+
+ /** \brief Token type for internal use only. */
+ typedef ParserToken<value_type, string_type> token_type;
+
+ /** \brief Core type of the bytecode. */
+ typedef std::vector<map_type> storage_type;
+
+ /** \brief Position in the Calculation array. */
+ unsigned m_iStackPos;
+
+ /** \brief Core type of the bytecode. */
+ storage_type m_vBase;
+
+ /** \brief Size of a value entry in the bytecode, relative to TMapType size. */
+ const int mc_iSizeVal;
+
+ /** \brief Size of a pointer, relative to size of underlying TMapType.
+
+ \attention The size is related to the size of TMapType not bytes!
+ */
+ const int mc_iSizePtr;
+
+ /** \brief A value entry requires that much entires in the bytecode.
+
+ Value entry consists of:
+ <ul>
+ <li>One entry for Stack index</li>
+ <li>One entry for Token identifier</li>
+ <li>mc_iSizeVal entries for the value</li>
+ <ul>
+
+ \sa AddVal(TBaseData a_fVal)
+ */
+ const int mc_iSizeValEntry;
+
+ void StorePtr(void *a_pAddr);
+
+public:
+ ParserByteCode();
+ ~ParserByteCode();
+ ParserByteCode(const ParserByteCode &a_ByteCode);
+ ParserByteCode& operator=(const ParserByteCode &a_ByteCode);
+ void Assign(const ParserByteCode &a_ByteCode);
+
+ void AddVar(value_type *a_pVar);
+ void AddVal(value_type a_fVal);
+ void AddOp(ECmdCode a_Oprt);
+ void AddAssignOp(value_type *a_pVar);
+ void AddFun(void *a_pFun, int a_iArgc);
+ void AddStrFun(void *a_pFun, int a_iArgc, int a_iIdx);
+
+ void Finalize();
+ void clear();
+ const map_type* GetRawData() const;
+
+ /** \brief Return size of a value entry.
+
+ That many bytecode entries are necessary to store a value.
+
+ \sa mc_iSizeVal
+ */
+ unsigned GetValSize() const
+ {
+ return mc_iSizeVal;
+ }
+
+ /** \brief Return size of a pointer entry.
+
+ That many bytecode entries are necessary to store a pointer.
+
+ \sa mc_iSizePtr
+ */
+ unsigned GetPtrSize() const
+ {
+ return mc_iSizePtr;
+ }
+
+ void RemoveValEntries(unsigned a_iNumber);
+ void AsciiDump();
+};
+
+} // namespace mu
+
+#endif
+
+
diff --git a/muparser/muParserCallback.cpp b/muparser/muParserCallback.cpp
new file mode 100644
index 0000000..1312ad7
--- /dev/null
+++ b/muparser/muParserCallback.cpp
@@ -0,0 +1,198 @@
+/*
+ __________
+ _____ __ __\______ \_____ _______ ______ ____ _______
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
+ \/ \/ \/ \/
+ Copyright (C) 2004-2006 Ingo Berg
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ software and associated documentation files (the "Software"), to deal in the Software
+ without restriction, including without limitation the rights to use, copy, modify,
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "muParserCallback.h"
+
+
+namespace mu
+{
+
+ ParserCallback::ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec, ECmdCode a_iCode)
+ :m_pFun((void*)a_pFun)
+ ,m_iArgc(1)
+ ,m_iPri(a_iPrec)
+ ,m_iCode(a_iCode)
+ ,m_iType(tpDBL)
+ ,m_bAllowOpti(a_bAllowOpti)
+ {}
+
+
+ ParserCallback::ParserCallback( fun_type2 a_pFun, bool a_bAllowOpti, int a_iPrec, ECmdCode a_iCode)
+ :m_pFun((void*)a_pFun)
+ ,m_iArgc(2)
+ ,m_iPri(a_iPrec)
+ ,m_iCode(a_iCode)
+ ,m_iType(tpDBL)
+ ,m_bAllowOpti(a_bAllowOpti)
+ {}
+
+
+ ParserCallback::ParserCallback(fun_type3 a_pFun, bool a_bAllowOpti)
+ :m_pFun((void*)a_pFun)
+ ,m_iArgc(3)
+ ,m_iPri(-1)
+ ,m_iCode(cmFUNC)
+ ,m_iType(tpDBL)
+ ,m_bAllowOpti(a_bAllowOpti)
+ {}
+
+
+ ParserCallback::ParserCallback(fun_type4 a_pFun, bool a_bAllowOpti)
+ :m_pFun((void*)a_pFun)
+ ,m_iArgc(4)
+ ,m_iPri(-1)
+ ,m_iCode(cmFUNC)
+ ,m_iType(tpDBL)
+ ,m_bAllowOpti(a_bAllowOpti)
+ {}
+
+ ParserCallback::ParserCallback(fun_type5 a_pFun, bool a_bAllowOpti)
+ :m_pFun((void*)a_pFun)
+ ,m_iArgc(5)
+ ,m_iPri(-1)
+ ,m_iCode(cmFUNC)
+ ,m_iType(tpDBL)
+ ,m_bAllowOpti(a_bAllowOpti)
+ {}
+
+ ParserCallback::ParserCallback(multfun_type a_pFun, bool a_bAllowOpti)
+ :m_pFun((void*)a_pFun)
+ ,m_iArgc(-1)
+ ,m_iPri(-1)
+ ,m_iCode(cmFUNC)
+ ,m_iType(tpDBL)
+ ,m_bAllowOpti(a_bAllowOpti)
+ {}
+
+ ParserCallback::ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti)
+ :m_pFun((void*)a_pFun)
+ ,m_iArgc(0)
+ ,m_iPri(-1)
+ ,m_iCode(cmFUNC_STR)
+ ,m_iType(tpSTR)
+ ,m_bAllowOpti(a_bAllowOpti)
+ {}
+
+ ParserCallback::ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti)
+ :m_pFun((void*)a_pFun)
+ ,m_iArgc(1)
+ ,m_iPri(-1)
+ ,m_iCode(cmFUNC_STR)
+ ,m_iType(tpSTR)
+ ,m_bAllowOpti(a_bAllowOpti)
+ {}
+
+ ParserCallback::ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti)
+ :m_pFun((void*)a_pFun)
+ ,m_iArgc(2)
+ ,m_iPri(-1)
+ ,m_iCode(cmFUNC_STR)
+ ,m_iType(tpSTR)
+ ,m_bAllowOpti(a_bAllowOpti)
+ {}
+
+ /** \brief Default constructor.
+
+ \throw nothrow
+ */
+ ParserCallback::ParserCallback()
+ :m_pFun(0)
+ ,m_iArgc(0)
+ ,m_iCode(cmUNKNOWN)
+ ,m_iType(tpVOID)
+ ,m_bAllowOpti(0)
+ {}
+
+ /** \brief Copy constructor.
+
+ \throw nothrow
+ */
+ ParserCallback::ParserCallback(const ParserCallback &a_Fun)
+ {
+ m_pFun = a_Fun.m_pFun;
+ m_iArgc = a_Fun.m_iArgc;
+ m_bAllowOpti = a_Fun.m_bAllowOpti;
+ m_iCode = a_Fun.m_iCode;
+ m_iType = a_Fun.m_iType;
+ m_iPri = a_Fun.m_iPri;
+ }
+
+ /** \brief Clone this instance and return a pointer to the new instance. */
+ ParserCallback* ParserCallback::Clone() const
+ {
+ return new ParserCallback(*this);
+ }
+
+
+ /** \brief Return tru if the function is conservative.
+
+ Conservative functions return always the same result for the same argument.
+ \throw nothrow
+ */
+ bool ParserCallback::IsOptimizable() const
+ {
+ return m_bAllowOpti;
+ }
+
+ /** \brief Get the callback address for the parser function.
+
+ The type of the address is void. It needs to be recasted according to the
+ argument number to the right type.
+
+ \throw nothrow
+ \return #pFun
+ */
+ void* ParserCallback::GetAddr() const
+ {
+ return m_pFun;
+ }
+
+ /** \brief Return the callback code. */
+ ECmdCode ParserCallback::GetCode() const
+ {
+ return m_iCode;
+ }
+
+
+ ETypeCode ParserCallback::GetType() const
+ {
+ return m_iType;
+ }
+
+ /** \brief Return the operator priority.
+
+ Only valid if the callback token is an operator token (binary or infix).
+ */
+ int ParserCallback::GetPri() const
+ {
+ return m_iPri;
+ }
+
+ /** \brief Returns the number of function Arguments. */
+ int ParserCallback::GetArgc() const
+ {
+ return m_iArgc;
+ }
+} // namespace mu
diff --git a/muparser/muParserCallback.h b/muparser/muParserCallback.h
new file mode 100644
index 0000000..9fecddb
--- /dev/null
+++ b/muparser/muParserCallback.h
@@ -0,0 +1,94 @@
+/*
+ __________
+ _____ __ __\______ \_____ _______ ______ ____ _______
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
+ \/ \/ \/ \/
+ Copyright (C) 2004-2006 Ingo Berg
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ software and associated documentation files (the "Software"), to deal in the Software
+ without restriction, including without limitation the rights to use, copy, modify,
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef MU_PARSER_CALLBACK_H
+#define MU_PARSER_CALLBACK_H
+
+#include "muParserDef.h"
+
+
+namespace mu
+{
+
+/** \brief Encapsulation of prototypes for a numerical parser function.
+
+ Encapsulates the prototyp for numerical parser functions. The class
+ stores the number of arguments for parser functions as well
+ as additional flags indication the function is non optimizeable.
+ The pointer to the callback function pointer is stored as void*
+ and needs to be casted according to the argument count.
+ Negative argument counts indicate a parser function with a variable number
+ of arguments.
+ This class is not used for string function prototyping.
+
+ \author (C) 2004-2006 Ingo Berg
+*/
+class ParserCallback
+{
+public:
+ ParserCallback(fun_type1 a_pFun, bool a_bAllowOpti, int a_iPrec = -1, ECmdCode a_iCode=cmFUNC);
+ ParserCallback(fun_type2 a_pFun, bool a_bAllowOpti, int a_iPrec = -1, ECmdCode a_iCode=cmFUNC);
+ ParserCallback(fun_type3 a_pFun, bool a_bAllowOpti);
+ ParserCallback(fun_type4 a_pFun, bool a_bAllowOpti);
+ ParserCallback(fun_type5 a_pFun, bool a_bAllowOpti);
+ ParserCallback(multfun_type a_pFun, bool a_bAllowOpti);
+ ParserCallback(strfun_type1 a_pFun, bool a_bAllowOpti);
+ ParserCallback(strfun_type2 a_pFun, bool a_bAllowOpti);
+ ParserCallback(strfun_type3 a_pFun, bool a_bAllowOpti);
+ ParserCallback();
+ ParserCallback(const ParserCallback &a_Fun);
+
+ ParserCallback* Clone() const;
+
+ bool IsOptimizable() const;
+ void* GetAddr() const;
+ ECmdCode GetCode() const;
+ ETypeCode GetType() const;
+ int GetPri() const;
+ int GetArgc() const;
+
+private:
+ void *m_pFun; ///< Pointer to the callback function, casted to void
+
+ /** \brief Number of numeric function arguments
+
+ This number is negative for functions with variable number of arguments. in this cases
+ they represent the actual number of arguments found.
+ */
+ int m_iArgc;
+ int m_iPri; ///< Valid only for binary and infix operators; Operator precedence.
+ ECmdCode m_iCode;
+ ETypeCode m_iType;
+ bool m_bAllowOpti; ///< Flag indication optimizeability
+};
+
+//------------------------------------------------------------------------------
+/** \brief Container for Callback objects. */
+typedef std::map<string_type, ParserCallback> funmap_type;
+
+} // namespace mu
+
+#endif
+
diff --git a/muparser/muParserDLL.cpp b/muparser/muParserDLL.cpp
new file mode 100644
index 0000000..0f85cb7
--- /dev/null
+++ b/muparser/muParserDLL.cpp
@@ -0,0 +1,657 @@
+/*
+ __________
+ _____ __ __\______ \_____ _______ ______ ____ _______
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
+ \/ \/ \/ \/
+ Copyright (C) 2004-2006 Ingo Berg
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ software and associated documentation files (the "Software"), to deal in the Software
+ without restriction, including without limitation the rights to use, copy, modify,
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+
+#if defined(MUPARSER_DLL) && defined(_WIN32)
+
+#include "muParserDLL.h"
+#include "muParser.h"
+#include "muParserError.h"
+
+
+#define MU_PARSER_TRY \
+ try \
+ {
+
+#define MU_PARSER_CATCH \
+ } \
+ catch(exception_type &e) \
+ { \
+ g_bError = true; \
+ g_ParserError = e; \
+ if (g_pErrHandler) \
+ g_pErrHandler(); \
+ } \
+ catch(...) \
+ { \
+ g_bError = true; \
+ g_ParserError = exception_type(mu::ecINTERNAL_ERROR); \
+ if (g_pErrHandler) \
+ g_pErrHandler(); \
+ }
+
+//---------------------------------------------------------------------------
+typedef mu::ParserBase::exception_type exception_type;
+typedef mu::ParserBase* parser_type;
+
+#if !defined(_UNICODE)
+ typedef std::string string_type;
+#else
+ typedef std::wstring string_type;
+#endif
+
+typedef string_type::value_type char_type;
+
+//---------------------------------------------------------------------------
+//
+//
+// unexported variables
+//
+//
+//---------------------------------------------------------------------------
+
+/** \brief The last exception that was caught.
+*/
+exception_type g_ParserError;
+errhandler_type g_pErrHandler;
+
+//---------------------------------------------------------------------------
+/** \brief Flags indicating an error occured.
+*/
+bool g_bError;
+
+//---------------------------------------------------------------------------
+//
+//
+// unexported functions
+//
+//
+//---------------------------------------------------------------------------
+
+parser_type GetPtr(parser_handle a_hParser)
+{
+ return static_cast<parser_type>(a_hParser);
+}
+
+//---------------------------------------------------------------------------
+/** \brief DLL entry point.
+*/
+BOOL APIENTRY DllMain( HANDLE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*lpReserved*/ )
+{
+ switch (ul_reason_for_call)
+ {
+ case DLL_PROCESS_ATTACH:
+ case DLL_THREAD_ATTACH:
+ g_pErrHandler = 0;
+ g_bError = false;
+ break;
+
+ case DLL_THREAD_DETACH:
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+
+ return TRUE;
+}
+
+//---------------------------------------------------------------------------
+//
+//
+// exported functions
+//
+//
+//---------------------------------------------------------------------------
+
+MU_PARSER_API void mupSetErrorHandler(errhandler_type a_pHandler)
+{
+ g_pErrHandler = a_pHandler;
+}
+
+//---------------------------------------------------------------------------
+MU_PARSER_API void mupSetVarFactory(parser_handle a_hParser, facfun_type a_pFactory, void *pUserData)
+{
+ parser_type p(GetPtr(a_hParser));
+ p->SetVarFactory(a_pFactory, pUserData);
+}
+
+//---------------------------------------------------------------------------
+/** \brief Create a new Parser instance and return its handle.
+*/
+MU_PARSER_API parser_handle mupInit()
+{
+ return (void*)(new mu::Parser());
+}
+
+//---------------------------------------------------------------------------
+/** \brief Release the parser instance related with a parser handle.
+*/
+MU_PARSER_API void mupRelease(parser_handle a_hParser)
+{
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ delete p;
+ MU_PARSER_CATCH
+}
+
+//---------------------------------------------------------------------------
+/** \brief Evaluate the expression.
+*/
+MU_PARSER_API double mupEval(parser_handle a_hParser)
+{
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ return p->Eval();
+ MU_PARSER_CATCH
+
+ return 0;
+}
+
+//---------------------------------------------------------------------------
+MU_PARSER_API void mupSetExpr(parser_handle a_hParser, const char *a_szExpr)
+{
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ p->SetExpr(a_szExpr);
+ MU_PARSER_CATCH
+}
+
+//---------------------------------------------------------------------------
+MU_PARSER_API void mupRemoveVar(parser_handle a_hParser, const char *a_szName)
+{
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ p->RemoveVar( string_type(a_szName) );
+ MU_PARSER_CATCH
+}
+
+//---------------------------------------------------------------------------
+/** \brief Release all parser variables.
+ \param a_hParser Handle to the parser instance.
+*/
+MU_PARSER_API void mupClearVar(parser_handle a_hParser)
+{
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ p->ClearVar();
+ MU_PARSER_CATCH
+}
+
+//---------------------------------------------------------------------------
+/** \brief Release all parser variables.
+ \param a_hParser Handle to the parser instance.
+*/
+MU_PARSER_API void mupClearConst(parser_handle a_hParser)
+{
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ p->ClearConst();
+ MU_PARSER_CATCH
+}
+
+//---------------------------------------------------------------------------
+/** \brief Clear all user defined operators.
+ \param a_hParser Handle to the parser instance.
+*/
+MU_PARSER_API void mupClearOprt(parser_handle a_hParser)
+{
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ p->ClearOprt();
+ MU_PARSER_CATCH
+}
+
+//---------------------------------------------------------------------------
+MU_PARSER_API void mupDefineFun1(parser_handle a_hParser, const char *a_szName, fun_type1 a_pFun, bool a_bAllowOpt)
+{
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt);
+ MU_PARSER_CATCH
+}
+
+//---------------------------------------------------------------------------
+MU_PARSER_API void mupDefineFun2(parser_handle a_hParser, const char *a_szName, fun_type2 a_pFun, bool a_bAllowOpt)
+{
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt);
+ MU_PARSER_CATCH
+}
+
+//---------------------------------------------------------------------------
+MU_PARSER_API void mupDefineFun3(parser_handle a_hParser, const char *a_szName, fun_type3 a_pFun, bool a_bAllowOpt)
+{
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt);
+ MU_PARSER_CATCH
+}
+
+//---------------------------------------------------------------------------
+MU_PARSER_API void mupDefineFun4(parser_handle a_hParser, const char *a_szName, fun_type4 a_pFun, bool a_bAllowOpt)
+{
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt);
+ MU_PARSER_CATCH
+}
+
+//---------------------------------------------------------------------------
+MU_PARSER_API void mupDefineFun5(parser_handle a_hParser, const char *a_szName, fun_type5 a_pFun, bool a_bAllowOpt)
+{
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt);
+ MU_PARSER_CATCH
+}
+
+//---------------------------------------------------------------------------
+MU_PARSER_API void mupDefineStrFun1(parser_handle a_hParser, const char *a_szName, strfun_type1 a_pFun, bool a_bAllowOpt)
+{
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt);
+ MU_PARSER_CATCH
+}
+
+//---------------------------------------------------------------------------
+MU_PARSER_API void mupDefineStrFun2(parser_handle a_hParser, const char *a_szName, strfun_type2 a_pFun, bool a_bAllowOpt)
+{
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt);
+ MU_PARSER_CATCH
+}
+
+//---------------------------------------------------------------------------
+MU_PARSER_API void mupDefineStrFun3(parser_handle a_hParser, const char *a_szName, strfun_type3 a_pFun, bool a_bAllowOpt)
+{
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt);
+ MU_PARSER_CATCH
+}
+
+//---------------------------------------------------------------------------
+MU_PARSER_API void mupDefineMultFun(parser_handle a_hParser, const char *a_szName, multfun_type a_pFun, bool a_bAllowOpt)
+{
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ p->DefineFun(a_szName, a_pFun, a_bAllowOpt);
+ MU_PARSER_CATCH
+}
+
+//---------------------------------------------------------------------------
+MU_PARSER_API void mupDefineOprt(parser_handle a_hParser, const char *a_szName, fun_type2 a_pFun, int a_iPri, bool a_bAllowOpt)
+{
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ p->DefineOprt(a_szName, a_pFun, a_iPri, a_bAllowOpt);
+ MU_PARSER_CATCH
+}
+
+//---------------------------------------------------------------------------
+MU_PARSER_API void mupDefineVar(parser_handle a_hParser, const char *a_szName, double *a_pVar)
+{
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ p->DefineVar(a_szName, a_pVar);
+ MU_PARSER_CATCH
+}
+
+//---------------------------------------------------------------------------
+MU_PARSER_API void mupDefineConst(parser_handle a_hParser, const char *a_szName, double a_fVal)
+{
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ p->DefineConst(a_szName, a_fVal);
+ MU_PARSER_CATCH
+}
+
+//---------------------------------------------------------------------------
+MU_PARSER_API void mupDefineStrConst(parser_handle a_hParser, const char *a_szName, const char *a_szVal)
+{
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ p->DefineStrConst(a_szName, a_szVal);
+ MU_PARSER_CATCH
+}
+
+//---------------------------------------------------------------------------
+MU_PARSER_API const char* mupGetExpr(parser_handle a_hParser)
+{
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ return p->GetExpr().c_str();
+ MU_PARSER_CATCH
+
+ return "";
+}
+
+//---------------------------------------------------------------------------
+MU_PARSER_API void mupDefinePostfixOprt(parser_handle a_hParser,
+ const char *a_szName,
+ fun_type1 a_pOprt,
+ bool a_bAllowOpt)
+{
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ p->DefinePostfixOprt(a_szName, a_pOprt, a_bAllowOpt);
+ MU_PARSER_CATCH
+}
+
+//---------------------------------------------------------------------------
+MU_PARSER_API void mupDefineInfixOprt(parser_handle a_hParser,
+ const char *a_szName,
+ fun_type1 a_pOprt,
+ bool a_bAllowOpt)
+{
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ p->DefineInfixOprt(a_szName, a_pOprt, a_bAllowOpt);
+ MU_PARSER_CATCH
+}
+
+// Define character sets for identifiers
+//---------------------------------------------------------------------------
+MU_PARSER_API void mupDefineNameChars(parser_handle a_hParser, const char *a_szCharset)
+{
+ parser_type p(GetPtr(a_hParser));
+ p->DefineNameChars(a_szCharset);
+}
+
+//---------------------------------------------------------------------------
+MU_PARSER_API void mupDefineOprtChars(parser_handle a_hParser, const char *a_szCharset)
+{
+ parser_type p(GetPtr(a_hParser));
+ p->DefineOprtChars(a_szCharset);
+}
+
+//---------------------------------------------------------------------------
+MU_PARSER_API void mupDefineInfixOprtChars(parser_handle a_hParser, const char *a_szCharset)
+{
+ parser_type p(GetPtr(a_hParser));
+ p->DefineInfixOprtChars(a_szCharset);
+}
+
+//---------------------------------------------------------------------------
+/** \brief Get the number of variables defined in the parser.
+ \param a_hParser [in] Must be a valid parser handle.
+ \return The number of used variables.
+ \sa mupGetExprVar
+*/
+MU_PARSER_API int mupGetVarNum(parser_handle a_hParser)
+{
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ const mu::varmap_type VarMap = p->GetVar();
+ return (int)VarMap.size();
+ MU_PARSER_CATCH
+
+ return 0; // never reached
+}
+
+//---------------------------------------------------------------------------
+/** \brief Return a variable that is used in an expression.
+
+ Prior to calling this function call mupGetExprVarNum in order to get the
+ number of variables in the expression. If the parameter a_iVar is greater
+ than the number of variables both a_szName and a_pVar will be set to zero.
+ As a side effect this function will trigger an internal calculation of the
+ expression undefined variables will be set to zero during this calculation.
+ During the calculation user defined callback functions present in the expression
+ will be called, this is unavoidable.
+
+ \param a_hParser [in] A valid parser handle.
+ \param a_iVar [in] The index of the variable to return.
+ \param a_szName [out] Pointer to the variable name.
+ \param a_pVar [out] Pointer to the variable.
+ \throw nothrow
+*/
+MU_PARSER_API void mupGetVar(parser_handle a_hParser, unsigned a_iVar, const char **a_szName, double **a_pVar)
+{
+ // A static buffer is needed for the name since i cant return the
+ // pointer from the map.
+ static char szName[1024];
+
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ const mu::varmap_type VarMap = p->GetVar();
+
+ if (a_iVar>=VarMap.size())
+ {
+ *a_szName = 0;
+ *a_pVar = 0;
+ return;
+ }
+ mu::varmap_type::const_iterator item;
+
+ item = VarMap.begin();
+ for (unsigned i=0; i<a_iVar; ++i)
+ item++;
+
+ strncpy(szName, item->first.c_str(), sizeof(szName));
+ szName[sizeof(szName)-1] = 0;
+
+ *a_szName = &szName[0];
+ *a_pVar = item->second;
+ return;
+
+ MU_PARSER_CATCH
+
+ *a_szName = 0;
+ *a_pVar = 0;
+}
+
+//---------------------------------------------------------------------------
+/** \brief Get the number of variables used in the expression currently set in the parser.
+ \param a_hParser [in] Must be a valid parser handle.
+ \return The number of used variables.
+ \sa mupGetExprVar
+*/
+MU_PARSER_API int mupGetExprVarNum(parser_handle a_hParser)
+{
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ const mu::varmap_type VarMap = p->GetUsedVar();
+ return (int)VarMap.size();
+ MU_PARSER_CATCH
+
+ return 0; // never reached
+}
+
+//---------------------------------------------------------------------------
+/** \brief Return a variable that is used in an expression.
+
+ Prior to calling this function call mupGetExprVarNum in order to get the
+ number of variables in the expression. If the parameter a_iVar is greater
+ than the number of variables both a_szName and a_pVar will be set to zero.
+ As a side effect this function will trigger an internal calculation of the
+ expression undefined variables will be set to zero during this calculation.
+ During the calculation user defined callback functions present in the expression
+ will be called, this is unavoidable.
+
+ \param a_hParser [in] A valid parser handle.
+ \param a_iVar [in] The index of the variable to return.
+ \param a_szName [out] Pointer to the variable name.
+ \param a_pVar [out] Pointer to the variable.
+ \throw nothrow
+*/
+MU_PARSER_API void mupGetExprVar(parser_handle a_hParser, unsigned a_iVar, const char **a_szName, double **a_pVar)
+{
+ // A static buffer is needed for the name since i cant return the
+ // pointer from the map.
+ static char szName[1024];
+
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ const mu::varmap_type VarMap = p->GetUsedVar();
+
+ if (a_iVar>=VarMap.size())
+ {
+ *a_szName = 0;
+ *a_pVar = 0;
+ return;
+ }
+ mu::varmap_type::const_iterator item;
+
+ item = VarMap.begin();
+ for (unsigned i=0; i<a_iVar; ++i)
+ item++;
+
+ strncpy(szName, item->first.c_str(), sizeof(szName));
+ szName[sizeof(szName)-1] = 0;
+
+ *a_szName = &szName[0];
+ *a_pVar = item->second;
+ return;
+
+ MU_PARSER_CATCH
+
+ *a_szName = 0;
+ *a_pVar = 0;
+}
+
+//---------------------------------------------------------------------------
+/** \brief Return the number of constants defined in a parser. */
+MU_PARSER_API int mupGetConstNum(parser_handle a_hParser)
+{
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ const mu::valmap_type ValMap = p->GetConst();
+ return (int)ValMap.size();
+ MU_PARSER_CATCH
+
+ return 0; // never reached
+}
+
+//---------------------------------------------------------------------------
+/** \brief Retrieve name and value of a single parser constant.
+ \param a_hParser [in] a valid parser handle
+ \param a_iVar [in] Index of the constant to query
+ \param a_pszName [out] pointer to a null terminated string with the constant name
+ \param [out] The constant value
+*/
+MU_PARSER_API void mupGetConst(parser_handle a_hParser, unsigned a_iVar,
+ const char **a_pszName, double &a_fVal)
+{
+ // A static buffer is needed for the name since i cant return the
+ // pointer from the map.
+ static char szName[1024];
+
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ const mu::valmap_type ValMap = p->GetConst();
+
+ if (a_iVar>=ValMap.size())
+ {
+ *a_pszName = 0;
+ a_fVal = 0;
+ return;
+ }
+
+ mu::valmap_type::const_iterator item;
+ item = ValMap.begin();
+ for (unsigned i=0; i<a_iVar; ++i)
+ item++;
+
+ strncpy(szName, item->first.c_str(), sizeof(szName));
+ szName[sizeof(szName)-1] = 0;
+
+ *a_pszName = &szName[0];
+ a_fVal = item->second;
+ return;
+
+ MU_PARSER_CATCH
+
+ *a_pszName = 0;
+ a_fVal = 0;
+}
+
+//---------------------------------------------------------------------------
+/** \brief Add a custom value regognition function.
+*/
+MU_PARSER_API void mupAddValIdent(parser_handle a_hParser, identfun_type a_pFun)
+{
+ MU_PARSER_TRY
+ parser_type p(GetPtr(a_hParser));
+ p->AddValIdent(a_pFun);
+ MU_PARSER_CATCH
+}
+
+//---------------------------------------------------------------------------
+/** \brief Query if an error occured.
+
+ After querying the internal error bit will be reset. So a consecutive call
+ will return false.
+*/
+MU_PARSER_API bool mupError()
+{
+ bool bError(g_bError);
+ g_bError = false;
+ return bError;
+}
+
+//---------------------------------------------------------------------------
+/** \brief Reset the internal error flag.
+*/
+MU_PARSER_API void mupErrorReset()
+{
+ g_bError = false;
+}
+
+//---------------------------------------------------------------------------
+/** \brief Return the message associated with the last error.
+*/
+MU_PARSER_API const char* mupGetErrorMsg()
+{
+ return g_ParserError.GetMsg().c_str();
+}
+
+//---------------------------------------------------------------------------
+/** \brief Return the message associated with the last error.
+*/
+MU_PARSER_API const char* mupGetErrorToken()
+{
+ return g_ParserError.GetToken().c_str();
+}
+
+//---------------------------------------------------------------------------
+/** \brief Return the code associated with the last error.
+*/
+MU_PARSER_API int mupGetErrorCode()
+{
+ return g_ParserError.GetCode();
+}
+
+//---------------------------------------------------------------------------
+/** \brief Return the postion associated with the last error. */
+MU_PARSER_API int mupGetErrorPos()
+{
+ return (int)g_ParserError.GetPos();
+}
+
+
+#endif // MUPARSER_DLL
diff --git a/muparser/muParserDLL.h b/muparser/muParserDLL.h
new file mode 100644
index 0000000..20e2db8
--- /dev/null
+++ b/muparser/muParserDLL.h
@@ -0,0 +1,123 @@
+/*
+ __________
+ _____ __ __\______ \_____ _______ ______ ____ _______
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
+ \/ \/ \/ \/
+ Copyright (C) 2004-2006 Ingo Berg
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ software and associated documentation files (the "Software"), to deal in the Software
+ without restriction, including without limitation the rights to use, copy, modify,
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+// Folgender ifdef-Block ist die Standardmethode zum Erstellen von Makros, die das Exportieren
+// aus einer DLL vereinfachen. Alle Dateien in der DLL werden mit dem MUPARSERLIB_EXPORTS-Symbol
+// kompiliert, das in der Befehlszeile definiert wurde. Das Symbol darf nicht für ein Projekt definiert werden,
+// das diese DLL verwendet. Alle anderen Projekte, deren Quelldateien diese Datei beinhalten, erkennen
+// MUPARSERLIB_API-Funktionen als aus einer DLL importiert, während die DLL mit diesem Makro
+// definierte Symbole als exportiert ansieht.
+#ifndef MU_PARSER_DLL_H
+#define MU_PARSER_DLL_H
+
+#ifdef MUPARSERLIB_EXPORTS
+#define MU_PARSER_API __declspec(dllexport)
+#else
+#define MU_PARSER_API __declspec(dllimport)
+#endif
+
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+typedef void* parser_handle;
+typedef double (*fun_type1)(double);
+typedef double (*fun_type2)(double, double);
+typedef double (*fun_type3)(double, double, double);
+typedef double (*fun_type4)(double, double, double, double);
+typedef double (*fun_type5)(double, double, double, double, double);
+typedef double (*multfun_type)(const double*, int);
+typedef double (*strfun_type1)(const char*);
+typedef double (*strfun_type2)(const char*, double);
+typedef double (*strfun_type3)(const char*, double, double);
+typedef void (*errhandler_type)();
+typedef double* (*facfun_type)(const char*, void *);
+typedef bool (*identfun_type)(const char*, int&, double&);
+
+extern "C"
+{
+
+// Basic operations / initialization
+MU_PARSER_API parser_handle mupInit();
+MU_PARSER_API void mupRelease(parser_handle a_hParser);
+MU_PARSER_API const char* mupGetExpr(parser_handle a_hParser);
+MU_PARSER_API void mupSetExpr(parser_handle a_hParser, const char *a_szExpr);
+MU_PARSER_API void mupSetErrorHandler(errhandler_type a_pErrHandler);
+MU_PARSER_API void mupSetVarFactory(parser_handle a_hParser, facfun_type a_pFactory, void *pUserData);
+
+MU_PARSER_API double mupEval(parser_handle a_hParser);
+
+// Defining callbacks / variables / constants
+MU_PARSER_API void mupDefineFun1(parser_handle a_hParser, const char *a_szName, fun_type1 a_pFun, bool a_bAllowOpt = true);
+MU_PARSER_API void mupDefineFun2(parser_handle a_hParser, const char *a_szName, fun_type2 a_pFun, bool a_bAllowOpt = true);
+MU_PARSER_API void mupDefineFun3(parser_handle a_hParser, const char *a_szName, fun_type3 a_pFun, bool a_bAllowOpt = true);
+MU_PARSER_API void mupDefineFun4(parser_handle a_hParser, const char *a_szName, fun_type4 a_pFun, bool a_bAllowOpt = true);
+MU_PARSER_API void mupDefineFun5(parser_handle a_hParser, const char *a_szName, fun_type5 a_pFun, bool a_bAllowOpt = true);
+// string functions
+MU_PARSER_API void mupDefineStrFun1(parser_handle a_hParser, const char *a_szName, strfun_type1 a_pFun, bool a_bAllowOpt = true);
+MU_PARSER_API void mupDefineStrFun2(parser_handle a_hParser, const char *a_szName, strfun_type2 a_pFun, bool a_bAllowOpt = true);
+MU_PARSER_API void mupDefineStrFun3(parser_handle a_hParser, const char *a_szName, strfun_type3 a_pFun, bool a_bAllowOpt = true);
+
+MU_PARSER_API void mupDefineMultFun(parser_handle a_hParser, const char *a_szName, multfun_type a_pFun, bool a_bAllowOpt = true);
+MU_PARSER_API void mupDefineOprt(parser_handle a_hParser, const char *a_szName, fun_type2 a_pFun, int a_iPri = 0, bool a_bAllowOpt = true);
+MU_PARSER_API void mupDefineConst(parser_handle a_hParser, const char *a_szName, double a_fVal);
+MU_PARSER_API void mupDefineStrConst(parser_handle a_hParser, const char *a_szName, const char *a_sVal);
+MU_PARSER_API void mupDefineVar(parser_handle a_hParser, const char *a_szName, double *a_fVar);
+MU_PARSER_API void mupDefinePostfixOprt(parser_handle a_hParser, const char *a_szName, fun_type1 a_pOprt, bool a_bAllowOpt = true);
+MU_PARSER_API void mupDefineInfixOprt(parser_handle a_hParser, const char *a_szName, fun_type1 a_pOprt, bool a_bAllowOpt=true);
+
+// Define character sets for identifiers
+MU_PARSER_API void mupDefineNameChars(parser_handle a_hParser, const char *a_szCharset);
+MU_PARSER_API void mupDefineOprtChars(parser_handle a_hParser, const char *a_szCharset);
+MU_PARSER_API void mupDefineInfixOprtChars(parser_handle a_hParser, const char *a_szCharset);
+
+// Remove all / single variables
+MU_PARSER_API void mupRemoveVar(parser_handle a_hParser, const char *a_szName);
+MU_PARSER_API void mupClearVar(parser_handle a_hParser);
+MU_PARSER_API void mupClearConst(parser_handle a_hParser);
+MU_PARSER_API void mupClearOprt(parser_handle a_hParser);
+
+// Querying variables / expression variables / constants
+MU_PARSER_API int mupGetExprVarNum(parser_handle a_hParser);
+MU_PARSER_API int mupGetVarNum(parser_handle a_hParser);
+MU_PARSER_API int mupGetConstNum(parser_handle a_hParser);
+MU_PARSER_API void mupGetExprVar(parser_handle a_hParser, unsigned a_iVar, const char **a_pszName, double **a_pVar);
+MU_PARSER_API void mupGetVar(parser_handle a_hParser, unsigned a_iVar, const char **a_pszName, double **a_pVar);
+MU_PARSER_API void mupGetConst(parser_handle a_hParser, unsigned a_iVar, const char **a_pszName, double &a_pVar);
+
+// Add value recognition callbacks
+MU_PARSER_API void mupAddValIdent(parser_handle a_hParser, identfun_type);
+
+// Error handling
+MU_PARSER_API bool mupError();
+MU_PARSER_API void mupErrorReset();
+MU_PARSER_API const char* mupGetErrorMsg();
+MU_PARSER_API int mupGetErrorCode();
+MU_PARSER_API int mupGetErrorPos();
+MU_PARSER_API const char* mupGetErrorToken();
+
+} // extern "C"
+
+#endif
diff --git a/muparser/muParserDef.h b/muparser/muParserDef.h
new file mode 100644
index 0000000..164b882
--- /dev/null
+++ b/muparser/muParserDef.h
@@ -0,0 +1,239 @@
+/*
+ __________
+ _____ __ __\______ \_____ _______ ______ ____ _______
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
+ \/ \/ \/ \/
+ Copyright (C) 2004-2006 Ingo Berg
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ software and associated documentation files (the "Software"), to deal in the Software
+ without restriction, including without limitation the rights to use, copy, modify,
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#ifndef MUP_DEF_H
+#define MUP_DEF_H
+
+#include <iostream>
+#include <string>
+#include <sstream>
+#include <map>
+
+#include "muParserFixes.h"
+
+/** \brief Define the base datatype for values.
+
+ This datatype must be a built in value type. You can not use custom classes.
+ It has been tested with float, double and long double types, int should
+ work as well.
+*/
+#define MUP_BASETYPE double
+
+
+/** \brief Definition of the basic bytecode datatype. */
+#define MUP_BYTECODE_TYPE long
+
+/** \brief Maybe I use this for unicode support later. */
+#if defined(_UNICODE)
+ /** \brief Definition of the basic parser string type. */
+ #define MUP_STRING_TYPE std::wstring
+
+ #if !defined(_T)
+ #define _T(x) L##x
+ #endif // not defined _T
+#else
+ #ifndef _T
+ #define _T
+ #endif
+
+ /** \brief Definition of the basic parser string type. */
+ #define MUP_STRING_TYPE std::string
+#endif
+
+#if defined(_DEBUG)
+ /** \brief Debug macro to force an abortion of the programm with a certain message.
+ */
+ #define MUP_FAIL(MSG) \
+ bool MSG=false; \
+ assert(MSG);
+
+ #ifndef _UNICODE
+ /** \brief An assertion that does not kill the program.
+
+ This macro is neutralised in UNICODE builds. It's
+ too difficult to translate.
+ */
+ #define MUP_ASSERT(COND) \
+ if (!(COND)) \
+ { \
+ stringstream_type ss; \
+ ss << "Assertion \""#COND"\" failed: " \
+ << __FILE__ << " line " \
+ << __LINE__ << "."; \
+ throw ParserError( ss.str() ); \
+ }
+ #else
+ #define MUP_ASSERT(COND)
+ #endif // _UNICODE
+#else
+ #define MUP_FAIL(MSG)
+ #define MUP_ASSERT(COND)
+#endif
+
+//------------------------------------------------------------------------------
+//
+// do not change anything beyond this point...
+//
+// !!! This section is devoted to macros that are used for debugging
+// !!! or for features that are not fully implemented yet.
+//
+//#define MUP_DUMP_STACK
+//#define MUP_DUMP_CMDCODE
+
+
+namespace mu
+{
+#if defined(_UNICODE)
+
+ //------------------------------------------------------------------------------
+ /** \brief Encapsulate wcout. */
+ inline std::wostream& console()
+ {
+ return std::wcout;
+ }
+
+ /** \brief Encapsulate cin. */
+ inline std::wistream& console_in()
+ {
+ return std::wcin;
+ }
+
+#else
+
+ /** \brief Encapsulate cout. */
+ inline std::ostream& console()
+ {
+ return std::cout;
+ }
+
+ /** \brief Encapsulate cin. */
+ inline std::istream& console_in()
+ {
+ return std::cin;
+ }
+
+#endif
+
+ //------------------------------------------------------------------------------
+ /** \brief Bytecode values.
+
+ \attention The order of the operator entries must match the order in ParserBase::c_DefaultOprt!
+ */
+ enum ECmdCode
+ {
+ // The following are codes for built in binary operators
+ // apart from built in operators the user has the opportunity to
+ // add user defined operators.
+ cmLE = 0, ///< Operator item: less or equal
+ cmGE = 1, ///< Operator item: greater or equal
+ cmNEQ = 2, ///< Operator item: not equal
+ cmEQ = 3, ///< Operator item: equals
+ cmLT = 4, ///< Operator item: less than
+ cmGT = 5, ///< Operator item: greater than
+ cmADD = 6, ///< Operator item: add
+ cmSUB = 7, ///< Operator item: subtract
+ cmMUL = 8, ///< Operator item: multiply
+ cmDIV = 9, ///< Operator item: division
+ cmPOW = 10, ///< Operator item: y to the power of ...
+ cmAND = 11, ///< Operator item: logical and
+ cmOR = 12, ///< Operator item: logical or
+ cmXOR = 13, ///< Operator item: logical xor
+ cmASSIGN = 14, ///< Operator item: Assignment operator
+ cmBO = 15, ///< Operator item: opening bracket
+ cmBC = 16, ///< Operator item: closing bracket
+ cmCOMMA = 17, ///< Operator item: comma
+ cmVAR = 18, ///< variable item
+ cmSTRVAR = 19,
+ cmVAL = 20, ///< value item
+
+ cmFUNC = 21, ///< Code for a function item
+ cmFUNC_STR = 22, ///< Code for a function with a string parameter
+
+ cmSTRING = 23, ///< Code for a string token
+ cmOPRT_BIN = 24, ///< user defined binary operator
+ cmOPRT_POSTFIX = 25, ///< code for postfix operators
+ cmOPRT_INFIX = 26, ///< code for infix operators
+ cmEND = 27, ///< end of formula
+ cmUNKNOWN = 28 ///< uninitialized item
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Types internally used by the parser.
+ */
+ enum ETypeCode
+ {
+ tpSTR = 0, ///> String type (Function arguments and constants only, no string variables)
+ tpDBL = 1, ///> Floating point variables
+ tpVOID = 2 ///> Undefined type.
+ };
+
+ //------------------------------------------------------------------------------
+ /** \brief Parser operator precedence values. */
+ enum EPrec
+ {
+ // binary operators
+ prLOGIC = 1, ///> logic operators
+ prCMP = 2, ///> comparsion operators
+ prADD_SUB = 3, ///> addition
+ prMUL_DIV = 4, ///> multiplication/division
+ prPOW = 5, ///> power operator priority (highest)
+
+ // infix operators
+ prINFIX = 4, ///> Signs have a higher priority than ADD_SUB, but lower than power operator
+ prPOSTFIX = 4 ///> Postfix operator priority (currently unused)
+ };
+
+ //------------------------------------------------------------------------------
+ // basic types
+ typedef MUP_BASETYPE value_type;
+ typedef MUP_STRING_TYPE string_type;
+ typedef MUP_BYTECODE_TYPE bytecode_type;
+ typedef string_type::value_type char_type;
+ typedef std::basic_stringstream<char_type,
+ std::char_traits<char_type>,
+ std::allocator<char_type> > stringstream_type;
+
+ // Data container types
+ typedef std::map<string_type, value_type*> varmap_type;
+ typedef std::map<string_type, value_type> valmap_type;
+ typedef std::map<string_type, std::size_t> strmap_type;
+
+ // Parser callbacks
+ typedef value_type (*fun_type1)(value_type);
+ typedef value_type (*fun_type2)(value_type, value_type);
+ typedef value_type (*fun_type3)(value_type, value_type, value_type);
+ typedef value_type (*fun_type4)(value_type, value_type, value_type, value_type);
+ typedef value_type (*fun_type5)(value_type, value_type, value_type, value_type, value_type);
+ typedef value_type (*multfun_type)(const value_type*, int);
+ typedef value_type (*strfun_type1)(const char_type*);
+ typedef value_type (*strfun_type2)(const char_type*, value_type);
+ typedef value_type (*strfun_type3)(const char_type*, value_type, value_type);
+
+ // Parser utility callback functions (unrelated to the math callbacks)
+ typedef bool (*identfun_type)(const char_type*, int&, value_type&);
+ typedef value_type* (*facfun_type)(const char_type*, void*);
+} // end fo namespace
+
+#endif
+
diff --git a/muparser/muParserError.cpp b/muparser/muParserError.cpp
new file mode 100644
index 0000000..237f529
--- /dev/null
+++ b/muparser/muParserError.cpp
@@ -0,0 +1,300 @@
+/*
+ __________
+ _____ __ __\______ \_____ _______ ______ ____ _______
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
+ \/ \/ \/ \/
+ Copyright (C) 2004-2006 Ingo Berg
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ software and associated documentation files (the "Software"), to deal in the Software
+ without restriction, including without limitation the rights to use, copy, modify,
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+#include "muParserError.h"
+
+
+namespace mu
+{
+ const ParserErrorMsg ParserErrorMsg::m_Instance;
+
+ //------------------------------------------------------------------------------
+ const ParserErrorMsg& ParserErrorMsg::Instance()
+ {
+ return m_Instance;
+ }
+
+ //------------------------------------------------------------------------------
+ string_type ParserErrorMsg::operator[](unsigned a_iIdx) const
+ {
+ return (a_iIdx<m_vErrMsg.size()) ? m_vErrMsg[a_iIdx] : string_type();
+ }
+
+
+ //---------------------------------------------------------------------------
+ ParserErrorMsg::~ParserErrorMsg()
+ {}
+
+ //---------------------------------------------------------------------------
+ /** \brief Assignement operator is deactivated.
+ */
+ ParserErrorMsg& ParserErrorMsg::operator=(const ParserErrorMsg& )
+ {
+ assert(false);
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------
+ ParserErrorMsg::ParserErrorMsg(const ParserErrorMsg&)
+ {}
+
+ //---------------------------------------------------------------------------
+ ParserErrorMsg::ParserErrorMsg()
+ :m_vErrMsg(0)
+ {
+ m_vErrMsg.resize(ecCOUNT);
+
+ m_vErrMsg[ecUNASSIGNABLE_TOKEN] = _T("Undefined token \"$TOK$\" found at position $POS$.");
+ m_vErrMsg[ecINTERNAL_ERROR] = _T("Internal error");
+ m_vErrMsg[ecINVALID_NAME] = _T("Invalid function-, variable- or constant name.");
+ m_vErrMsg[ecINVALID_FUN_PTR] = _T("Invalid pointer to callback function.");
+ m_vErrMsg[ecEMPTY_EXPRESSION] = _T("Expression is empty.");
+ m_vErrMsg[ecINVALID_VAR_PTR] = _T("Invalid pointer to variable.");
+ m_vErrMsg[ecUNEXPECTED_OPERATOR] = _T("Unexpected operator \"$TOK$\" found at position $POS$");
+ m_vErrMsg[ecUNEXPECTED_EOF] = _T("Unexpected end of formula at position $POS$");
+ m_vErrMsg[ecUNEXPECTED_COMMA] = _T("Unexpected comma at position $POS$");
+ m_vErrMsg[ecUNEXPECTED_PARENS] = _T("Unexpected parenthesis \"$TOK$\" at position $POS$");
+ m_vErrMsg[ecUNEXPECTED_FUN] = _T("Unexpected function \"$TOK$\" at position $POS$");
+ m_vErrMsg[ecUNEXPECTED_VAL] = _T("Unexpected value \"$TOK$\" found at position $POS$");
+ m_vErrMsg[ecUNEXPECTED_VAR] = _T("Unexpected variable \"$TOK$\" found at position $POS$");
+ m_vErrMsg[ecUNEXPECTED_ARG] = _T("Function arguments used without a function (position: $POS$)");
+ m_vErrMsg[ecMISSING_PARENS] = _T("Missing parenthesis");
+ m_vErrMsg[ecTOO_MANY_PARAMS] = _T("Too many parameters for function \"$TOK$\" at formula position $POS$");
+ m_vErrMsg[ecTOO_FEW_PARAMS] = _T("Too few parameters for function \"$TOK$\" at formula position $POS$");
+ m_vErrMsg[ecDIV_BY_ZERO] = _T("Divide by zero");
+ m_vErrMsg[ecDOMAIN_ERROR] = _T("Domain error");
+ m_vErrMsg[ecNAME_CONFLICT] = _T("Name conflict");
+ m_vErrMsg[ecOPT_PRI] = _T("Invalid value for operator priority (must be greater or equal to zero).");
+ m_vErrMsg[ecBUILTIN_OVERLOAD] = _T("Binary operator identifier conflicts with a built in operator.");
+ m_vErrMsg[ecUNEXPECTED_STR] = _T("Unexpected string token found at position $POS$.");
+ m_vErrMsg[ecUNTERMINATED_STRING] = _T("Unterminated string starting at position $POS$.");
+ m_vErrMsg[ecSTRING_EXPECTED] = _T("String function called with a non string type of argument.");
+ m_vErrMsg[ecVAL_EXPECTED] = _T("String value used where a numerical argument is expected.");
+ m_vErrMsg[ecOPRT_TYPE_CONFLICT] = _T("No suitable overload for operator \"$TOK$\" at position $POS$.");
+ m_vErrMsg[ecGENERIC] = _T("Parser error.");
+ m_vErrMsg[ecSTR_RESULT] = _T("Function result is a string.");
+
+ #if defined(_DEBUG)
+ for (int i=0; i<ecCOUNT; ++i)
+ if (!m_vErrMsg[i].length())
+ assert(false);
+ #endif
+ }
+
+ //---------------------------------------------------------------------------
+ //
+ //
+ //
+ // ParserError class
+ //
+ //
+ //
+ //---------------------------------------------------------------------------
+
+ //------------------------------------------------------------------------------
+ ParserError::ParserError()
+ :m_strMsg()
+ ,m_strFormula()
+ ,m_strTok()
+ ,m_iPos(-1)
+ ,m_iErrc(ecUNDEFINED)
+ ,m_ErrMsg(ParserErrorMsg::Instance())
+ {
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief This Constructor is used for internal exceptions only.
+
+ It does not contain any information but the error code.
+ */
+ ParserError::ParserError(EErrorCodes /*a_iErrc*/)
+ :m_ErrMsg(ParserErrorMsg::Instance())
+ {
+ Reset();
+ m_strMsg = _T("parser error");
+ }
+
+ //------------------------------------------------------------------------------
+ ParserError::ParserError(const string_type &sMsg)
+ :m_ErrMsg(ParserErrorMsg::Instance())
+ {
+ Reset();
+ m_strMsg = sMsg;
+ }
+
+ //------------------------------------------------------------------------------
+ ParserError::ParserError( EErrorCodes a_iErrc,
+ const string_type &sTok,
+ const string_type &sFormula,
+ int a_iPos )
+ :m_strMsg()
+ ,m_strFormula(sFormula)
+ ,m_strTok(sTok)
+ ,m_iPos(a_iPos)
+ ,m_iErrc(a_iErrc)
+ ,m_ErrMsg(ParserErrorMsg::Instance())
+ {
+ m_strMsg = m_ErrMsg[m_iErrc];
+ stringstream_type stream;
+ stream << (int)m_iPos;
+ ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());
+ ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);
+ }
+
+ //------------------------------------------------------------------------------
+ ParserError::ParserError( EErrorCodes a_iErrc, int a_iPos, const string_type &sTok)
+ :m_strMsg()
+ ,m_strFormula()
+ ,m_strTok(sTok)
+ ,m_iPos(a_iPos)
+ ,m_iErrc(a_iErrc)
+ ,m_ErrMsg(ParserErrorMsg::Instance())
+ {
+ m_strMsg = m_ErrMsg[m_iErrc];
+ stringstream_type stream;
+ stream << (int)m_iPos;
+ ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());
+ ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);
+ }
+
+ //------------------------------------------------------------------------------
+ ParserError::ParserError( const char_type *a_szMsg, int a_iPos, const string_type &sTok)
+ :m_strMsg(a_szMsg)
+ ,m_strFormula()
+ ,m_strTok(sTok)
+ ,m_iPos(a_iPos)
+ ,m_iErrc(ecGENERIC)
+ ,m_ErrMsg(ParserErrorMsg::Instance())
+ {
+ stringstream_type stream;
+ stream << (int)m_iPos;
+ ReplaceSubString(m_strMsg, _T("$POS$"), stream.str());
+ ReplaceSubString(m_strMsg, _T("$TOK$"), m_strTok);
+ }
+
+ //------------------------------------------------------------------------------
+ ParserError::ParserError(const ParserError &a_Obj)
+ :m_strMsg(a_Obj.m_strMsg)
+ ,m_strFormula(a_Obj.m_strFormula)
+ ,m_strTok(a_Obj.m_strTok)
+ ,m_iPos(a_Obj.m_iPos)
+ ,m_iErrc(a_Obj.m_iErrc)
+ ,m_ErrMsg(ParserErrorMsg::Instance())
+ {
+ }
+
+ //------------------------------------------------------------------------------
+ ParserError& ParserError::operator=(const ParserError &a_Obj)
+ {
+ if (this==&a_Obj)
+ return *this;
+
+ m_strMsg = a_Obj.m_strMsg;
+ m_strFormula = a_Obj.m_strFormula;
+ m_strTok = a_Obj.m_strTok;
+ m_iPos = a_Obj.m_iPos;
+ m_iErrc = a_Obj.m_iErrc;
+ return *this;
+ }
+
+ //------------------------------------------------------------------------------
+ ParserError::~ParserError()
+ {
+ }
+
+ /** \brief Replace all ocuurences of a substring with another string. */
+ void ParserError::ReplaceSubString( string_type &strSource,
+ const string_type &strFind,
+ const string_type &strReplaceWith)
+ {
+ string_type strResult;
+ string_type::size_type iPos(0), iNext(0);
+
+ for(;;)
+ {
+ iNext = strSource.find(strFind, iPos);
+ strResult.append(strSource, iPos, iNext-iPos);
+
+ if( iNext==string_type::npos )
+ break;
+
+ strResult.append(strReplaceWith);
+ iPos = iNext + strFind.length();
+ }
+
+ strSource.swap(strResult);
+ }
+
+ //------------------------------------------------------------------------------
+ void ParserError::Reset()
+ {
+ m_strMsg = _T("");
+ m_strFormula = _T("");
+ m_strTok = _T("");
+ m_iPos = -1;
+ m_iErrc = ecUNDEFINED;
+ }
+
+ //------------------------------------------------------------------------------
+ void ParserError::SetFormula(const string_type &a_strFormula)
+ {
+ m_strFormula = a_strFormula;
+ }
+
+ //------------------------------------------------------------------------------
+ const string_type& ParserError::GetExpr() const
+ {
+ return m_strFormula;
+ }
+
+ //------------------------------------------------------------------------------
+ const string_type& ParserError::GetMsg() const
+ {
+ return m_strMsg;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Return the formula position related to the error.
+
+ If the error is not related to a distinct position this will return -1
+ */
+ std::size_t ParserError::GetPos() const
+ {
+ return m_iPos;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Return string related with this token (if available). */
+ const string_type& ParserError::GetToken() const
+ {
+ return m_strTok;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Return the error code. */
+ EErrorCodes ParserError::GetCode() const
+ {
+ return m_iErrc;
+ }
+} // namespace mu
diff --git a/muparser/muParserError.h b/muparser/muParserError.h
new file mode 100644
index 0000000..c550eff
--- /dev/null
+++ b/muparser/muParserError.h
@@ -0,0 +1,160 @@
+/*
+ __________
+ _____ __ __\______ \_____ _______ ______ ____ _______
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
+ \/ \/ \/ \/
+ Copyright (C) 2004-2006 Ingo Berg
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ software and associated documentation files (the "Software"), to deal in the Software
+ without restriction, including without limitation the rights to use, copy, modify,
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef MU_PARSER_ERROR_H
+#define MU_PARSER_ERROR_H
+
+#include <cassert>
+#include <stdexcept>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <memory>
+
+#include "muParserDef.h"
+
+
+namespace mu
+{
+
+/** \brief Error codes. */
+enum EErrorCodes
+{
+ // Formula syntax errors
+ ecUNEXPECTED_OPERATOR = 0, ///< Unexpected binary operator found
+ ecUNASSIGNABLE_TOKEN = 1, ///< Token cant be identified.
+ ecUNEXPECTED_EOF = 2, ///< Unexpected end of formula. (Example: "2+sin(")
+ ecUNEXPECTED_COMMA = 3, ///< An unexpected comma has been found. (Example: "1,23")
+ ecUNEXPECTED_ARG = 4, ///< An unexpected argument has been found
+ ecUNEXPECTED_VAL = 5, ///< An unexpected value token has been found
+ ecUNEXPECTED_VAR = 6, ///< An unexpected variable token has been found
+ ecUNEXPECTED_PARENS = 7, ///< Unexpected Parenthesis, opening or closing
+ ecUNEXPECTED_STR = 8, ///< A string has been found at an inapropriate position
+ ecSTRING_EXPECTED = 9, ///< A string function has been called with a different type of argument
+ ecVAL_EXPECTED = 10, ///< A numerical function has been called with a non value type of argument
+ ecMISSING_PARENS = 11, ///< Missing parens. (Example: "3*sin(3")
+ ecUNEXPECTED_FUN = 12, ///< Unexpected function found. (Example: "sin(8)cos(9)")
+ ecUNTERMINATED_STRING = 13, ///< unterminated string constant. (Example: "3*valueof("hello)")
+ ecTOO_MANY_PARAMS = 14, ///< Too many function parameters
+ ecTOO_FEW_PARAMS = 15, ///< Too few function parameters. (Example: "ite(1<2,2)")
+ ecOPRT_TYPE_CONFLICT = 16, ///< binary operators may only be applied to value items of the same type
+ ecSTR_RESULT = 17, ///< result is a string
+
+ // Invalid Parser input Parameters
+ ecINVALID_NAME = 18, ///< Invalid function, variable or constant name.
+ ecBUILTIN_OVERLOAD = 19, ///< Trying to overload builtin operator
+ ecINVALID_FUN_PTR = 20, ///< Invalid callback function pointer
+ ecINVALID_VAR_PTR = 21, ///< Invalid variable pointer
+ ecEMPTY_EXPRESSION = 22, ///< The Expression is empty
+ ecNAME_CONFLICT = 23, ///< Name conflict
+ ecOPT_PRI = 24, ///< Invalid operator priority
+ //
+ ecDOMAIN_ERROR = 25, ///< catch division by zero, sqrt(-1), log(0) (currently unused)
+ ecDIV_BY_ZERO = 26, ///< Division by zero (currently unused)
+ ecGENERIC = 27, ///< Generic error
+
+ // internal errors
+ ecINTERNAL_ERROR = 28, ///< Internal error of any kind.
+
+ // The last two are special entries
+ ecCOUNT, ///< This is no error code, It just stores just the total number of error codes
+ ecUNDEFINED = -1 ///< Undefined message, placeholder to detect unassigned error messages
+};
+
+//---------------------------------------------------------------------------
+class ParserErrorMsg
+{
+public:
+ typedef ParserErrorMsg self_type;
+
+ ParserErrorMsg& operator=(const ParserErrorMsg &);
+ ParserErrorMsg(const ParserErrorMsg&);
+ ParserErrorMsg();
+
+ ~ParserErrorMsg();
+
+ static const ParserErrorMsg& Instance();
+ string_type operator[](unsigned a_iIdx) const;
+
+private:
+ std::vector<string_type> m_vErrMsg;
+ static const self_type m_Instance;
+};
+
+//---------------------------------------------------------------------------
+/** \brief Error class of the parser.
+
+ Part of the math parser package.
+
+ \author Ingo Berg
+*/
+/* final */ class ParserError
+{
+private:
+ //------------------------------------------------------------------------------
+ /** \brief Replace all ocuurences of a substring with another string. */
+ void ReplaceSubString( string_type &strSource,
+ const string_type &strFind,
+ const string_type &strReplaceWith);
+ void Reset();
+
+public:
+ ParserError();
+ explicit ParserError(EErrorCodes a_iErrc);
+ explicit ParserError(const string_type &sMsg);
+ ParserError( EErrorCodes a_iErrc,
+ const string_type &sTok,
+ const string_type &sFormula = string_type(_T("(formula is not available)")),
+ int a_iPos = -1);
+ ParserError( EErrorCodes a_iErrc,
+ int a_iPos,
+ const string_type &sTok);
+ ParserError( const char_type *a_szMsg,
+ int a_iPos = -1,
+ const string_type &sTok = string_type());
+ ParserError(const ParserError &a_Obj);
+ ParserError& operator=(const ParserError &a_Obj);
+ ~ParserError();
+
+ void SetFormula(const string_type &a_strFormula);
+ const string_type& GetExpr() const;
+ const string_type& GetMsg() const;
+ std::size_t GetPos() const;
+ const string_type& GetToken() const;
+ EErrorCodes GetCode() const;
+
+private:
+ string_type m_strMsg; ///< The message string
+ string_type m_strFormula; ///< Formula string
+ string_type m_strTok; ///< Token related with the error
+ int m_iPos; ///< Formula position related to the error
+ EErrorCodes m_iErrc; ///< Error code
+ const ParserErrorMsg &m_ErrMsg;
+};
+
+} // namespace mu
+
+#endif
+
diff --git a/muparser/muParserFixes.h b/muparser/muParserFixes.h
new file mode 100644
index 0000000..02ca007
--- /dev/null
+++ b/muparser/muParserFixes.h
@@ -0,0 +1,196 @@
+/*
+ __________
+ _____ __ __\______ \_____ _______ ______ ____ _______
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
+ \/ \/ \/ \/
+ Copyright (C) 2004-2006 Ingo Berg
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ software and associated documentation files (the "Software"), to deal in the Software
+ without restriction, including without limitation the rights to use, copy, modify,
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef MU_PARSER_FIXES_H
+#define MU_PARSER_FIXES_H
+
+//
+// Compatibility fixes
+//
+
+//---------------------------------------------------------------------------
+//
+// Intel Compiler
+//
+//---------------------------------------------------------------------------
+
+#ifdef __INTEL_COMPILER
+
+// remark #981: operands are evaluated in unspecified order
+// disabled -> completely pointless if the functions do not have side effects
+//
+#pragma warning(disable:981)
+
+// remark #383: value copied to temporary, reference to temporary used
+#pragma warning(disable:383)
+
+// remark #1572: floating-point equality and inequality comparisons are unreliable
+// disabled -> everyone knows it, the parser passes this problem
+// deliberately to the user
+#pragma warning(disable:1572)
+
+#endif
+
+
+//---------------------------------------------------------------------------
+//
+// MSVC6
+//
+//---------------------------------------------------------------------------
+
+
+#if _MSC_VER==1200
+
+/** \brief Macro to replace the MSVC6 auto_ptr with the _my_auto_ptr class.
+
+ Hijack auto_ptr and replace it with a version that actually does
+ what an auto_ptr normally does. If you use std::auto_ptr in your other code
+ it might either explode or work much better. The original crap created
+ by Microsoft, called auto_ptr and bundled with MSVC6 is not standard compliant.
+*/
+#define auto_ptr _my_auto_ptr
+
+// This is another stupidity that needs to be undone in order to de-pollute
+// the global namespace!
+#undef min
+#undef max
+
+
+namespace std
+{
+ typedef ::size_t size_t;
+
+ //---------------------------------------------------------------------------
+ /** \brief MSVC6 fix: Dummy function to put rand into namespace std.
+
+ This is a hack for MSVC6 only. It's dirty, it's ugly and it works, provided
+ inlining is enabled. Necessary because I will not pollute or change my
+ code in order to adopt it to MSVC6 interpretation of how C++ should look like!
+ */
+ inline int rand(void)
+ {
+ return ::rand();
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief MSVC6 fix: Dummy function to put strlen into namespace std.
+
+ This is a hack for MSVC6 only. It's dirty, it's ugly and it works, provided
+ inlining is enabled. Necessary because I will not pollute or change my
+ code in order to adopt it to MSVC6 interpretation of how C++ should look like!
+ */
+ inline size_t strlen(const char *szMsg)
+ {
+ return ::strlen(szMsg);
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief MSVC6 fix: Dummy function to put strncmp into namespace std.
+
+ This is a hack for MSVC6 only. It's dirty, it's ugly and it works, provided
+ inlining is enabled. Necessary because I will not pollute or change my
+ code in order to adopt it to MSVC6 interpretation of how C++ should look like!
+ */
+ inline int strncmp(const char *a, const char *b, size_t len)
+ {
+ return ::strncmp(a,b,len);
+ }
+
+ //---------------------------------------------------------------------------
+ template<typename T>
+ T max(T a, T b)
+ {
+ return (a>b) ? a : b;
+ }
+
+ //---------------------------------------------------------------------------
+ template<typename T>
+ T min(T a, T b)
+ {
+ return (a<b) ? a : b;
+ }
+
+ //---------------------------------------------------------------------------
+ /** Standard compliant auto_ptr redefinition for MSVC6.
+
+ The code is taken from VS.NET 2003, slightly modified to reduce
+ it's dependencies from other classes.
+ */
+ template<class _Ty>
+ class _my_auto_ptr
+ {
+ public:
+ typedef _Ty element_type;
+
+ explicit _my_auto_ptr(_Ty *_Ptr = 0)
+ :_Myptr(_Ptr)
+ {}
+
+ _my_auto_ptr(_my_auto_ptr<_Ty>& _Right)
+ :_Myptr(_Right.release())
+ {}
+
+ template<class _Other>
+ operator _my_auto_ptr<_Other>()
+ {
+ return (_my_auto_ptr<_Other>(*this));
+ }
+
+ template<class _Other>
+ _my_auto_ptr<_Ty>& operator=(_my_auto_ptr<_Other>& _Right)
+ {
+ reset(_Right.release());
+ return (*this);
+ }
+
+ ~auto_ptr() { delete _Myptr; }
+ _Ty& operator*() const { return (*_Myptr); }
+ _Ty *operator->() const { return (&**this); }
+ _Ty *get() const { return (_Myptr); }
+
+ _Ty *release()
+ {
+ _Ty *_Tmp = _Myptr;
+ _Myptr = 0;
+ return (_Tmp);
+ }
+
+ void reset(_Ty* _Ptr = 0)
+ {
+ if (_Ptr != _Myptr)
+ delete _Myptr;
+ _Myptr = _Ptr;
+ }
+
+ private:
+ _Ty *_Myptr;
+ }; // class _my_auto_ptr
+} // namespace std
+
+#endif // Microsoft Visual Studio Version 6.0
+
+#endif // include guard
+
+
diff --git a/muparser/muParserInt.cpp b/muparser/muParserInt.cpp
new file mode 100644
index 0000000..1b072bc
--- /dev/null
+++ b/muparser/muParserInt.cpp
@@ -0,0 +1,264 @@
+/*
+ __________
+ _____ __ __\______ \_____ _______ ______ ____ _______
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
+ \/ \/ \/ \/
+ Copyright (C) 2004-2006 Ingo Berg
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ software and associated documentation files (the "Software"), to deal in the Software
+ without restriction, including without limitation the rights to use, copy, modify,
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "muParserInt.h"
+
+#include <cmath>
+#include <algorithm>
+#include <numeric>
+
+using namespace std;
+
+
+/** \brief Namespace for mathematical applications. */
+namespace mu
+{
+
+value_type ParserInt::Abs(value_type v) { return Round(fabs(v)); }
+value_type ParserInt::Sign(value_type v) { return (Round(v)<0) ? -1 : (Round(v)>0) ? 1 : 0; }
+value_type ParserInt::Ite(value_type v1,
+ value_type v2,
+ value_type v3) { return (Round(v1)==1) ? Round(v2) : Round(v3); }
+value_type ParserInt::Add(value_type v1, value_type v2) { return Round(v1) + Round(v2); }
+value_type ParserInt::Sub(value_type v1, value_type v2) { return Round(v1) - Round(v2); }
+value_type ParserInt::Mul(value_type v1, value_type v2) { return Round(v1) * Round(v2); }
+value_type ParserInt::Div(value_type v1, value_type v2) { return Round(v1) / Round(v2); }
+value_type ParserInt::Mod(value_type v1, value_type v2) { return Round(v1) % Round(v2); }
+value_type ParserInt::Shr(value_type v1, value_type v2) { return Round(v1) >> Round(v2); }
+value_type ParserInt::Shl(value_type v1, value_type v2) { return Round(v1) << Round(v2); }
+value_type ParserInt::LogAnd(value_type v1, value_type v2) { return Round(v1) & Round(v2); }
+value_type ParserInt::LogOr(value_type v1, value_type v2) { return Round(v1) | Round(v2); }
+value_type ParserInt::LogXor(value_type v1, value_type v2) { return Round(v1) ^ Round(v2); }
+value_type ParserInt::And(value_type v1, value_type v2) { return Round(v1) && Round(v2); }
+value_type ParserInt::Or(value_type v1, value_type v2) { return Round(v1) || Round(v2); }
+value_type ParserInt::Less(value_type v1, value_type v2) { return Round(v1) < Round(v2); }
+value_type ParserInt::Greater(value_type v1, value_type v2) { return Round(v1) > Round(v2); }
+value_type ParserInt::LessEq(value_type v1, value_type v2) { return Round(v1) <= Round(v2); }
+value_type ParserInt::GreaterEq(value_type v1, value_type v2) { return Round(v1) >= Round(v2); }
+value_type ParserInt::Equal(value_type v1, value_type v2) { return Round(v1) == Round(v2); }
+value_type ParserInt::NotEqual(value_type v1, value_type v2) { return Round(v1) != Round(v2); }
+value_type ParserInt::Not(value_type v) { return !Round(v); }
+
+//---------------------------------------------------------------------------
+// Unary operator Callbacks: Infix operators
+value_type ParserInt::UnaryMinus(value_type v)
+{
+ return -Round(v);
+}
+
+//---------------------------------------------------------------------------
+value_type ParserInt::Sum(const value_type* a_afArg, int a_iArgc)
+{
+ if (!a_iArgc)
+ throw ParserError(_T("too few arguments for function sum."));
+
+ value_type fRes=0;
+ for (int i=0; i<a_iArgc; ++i)
+ fRes += a_afArg[i];
+
+ return fRes;
+}
+
+//---------------------------------------------------------------------------
+value_type ParserInt::Min(const value_type* a_afArg, int a_iArgc)
+{
+ if (!a_iArgc)
+ throw ParserError( _T("too few arguments for function min.") );
+
+ value_type fRes=a_afArg[0];
+ for (int i=0; i<a_iArgc; ++i)
+ fRes = std::min(fRes, a_afArg[i]);
+
+ return fRes;
+}
+
+//---------------------------------------------------------------------------
+value_type ParserInt::Max(const value_type* a_afArg, int a_iArgc)
+{
+ if (!a_iArgc)
+ throw ParserError(_T("too few arguments for function min."));
+
+ value_type fRes=a_afArg[0];
+ for (int i=0; i<a_iArgc; ++i)
+ fRes = std::max(fRes, a_afArg[i]);
+
+ return fRes;
+}
+
+//---------------------------------------------------------------------------
+// Default value recognition callback
+bool ParserInt::IsVal(const char_type *a_szExpr, int &a_iPos, value_type &a_fVal)
+{
+ stringstream_type stream(a_szExpr);
+ int iVal(0);
+
+ stream >> iVal;
+ int iEnd = stream.tellg(); // Position after reading
+
+ if (iEnd==-1)
+ return false;
+
+ a_iPos += iEnd;
+ a_fVal = (value_type)iVal;
+ return true;
+}
+
+//---------------------------------------------------------------------------
+bool ParserInt::IsHexVal(const char_type *a_szExpr, int &a_iPos, value_type &a_fVal)
+{
+ if (a_szExpr[0]!='$')
+ return false;
+
+ unsigned iVal(0);
+
+// New code based on streams for UNICODE compliance:
+ stringstream_type::pos_type nPos(0);
+ stringstream_type ss(a_szExpr+1);
+ ss >> std::hex >> iVal;
+ nPos = ss.tellg();
+
+ if (nPos==(stringstream_type::pos_type)0)
+ return false;
+
+ a_iPos += 1 + nPos;
+
+/*
+ // original code based on sscanf. Working but not UNICODE compliant!
+ int iLen(0);
+ if (sscanf(a_szExpr+1, "%x%n", &iVal, &iLen)==0)
+ return false;
+
+ a_iPos += iLen+1;
+*/
+
+ a_fVal = iVal;
+ return true;
+}
+
+//---------------------------------------------------------------------------
+bool ParserInt::IsBinVal(const char_type *a_szExpr, int &a_iPos, value_type &a_fVal)
+{
+ if (a_szExpr[0]!='#')
+ return false;
+
+ unsigned iVal(0),
+ iBits(sizeof(iVal)*8),
+ i(0);
+
+ for (i=0; (a_szExpr[i+1]=='0' || a_szExpr[i+1]=='1') && i<iBits; ++i)
+ iVal |= (int)(a_szExpr[i+1]=='1') << ((iBits-1)-i);
+
+ if (i==0)
+ return false;
+
+ if (i==iBits)
+ throw exception_type(_T("Binary to integer conversion error (overflow)."));
+
+ a_fVal = (unsigned)(iVal >> (iBits-i) );
+ a_iPos += i+1;
+
+ return true;
+}
+
+//---------------------------------------------------------------------------
+/** \brief Constructor.
+
+ Call ParserBase class constructor and trigger Function, Operator and Constant initialization.
+*/
+ParserInt::ParserInt()
+:ParserBase()
+{
+ AddValIdent(IsVal);
+ AddValIdent(IsHexVal);
+ AddValIdent(IsBinVal);
+
+ InitCharSets();
+ InitFun();
+ InitOprt();
+}
+
+//---------------------------------------------------------------------------
+void ParserInt::InitConst()
+{
+}
+
+//---------------------------------------------------------------------------
+void ParserInt::InitCharSets()
+{
+ DefineNameChars( _T("0123456789_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") );
+ DefineOprtChars( _T("+-*^/?<>=!%&|~'_") );
+ DefineInfixOprtChars( _T("/+-*^?<>=!%&|~'_") );
+}
+
+//---------------------------------------------------------------------------
+/** \brief Initialize the default functions. */
+void ParserInt::InitFun()
+{
+ DefineFun( _T("sign"), Sign);
+ DefineFun( _T("abs"), Abs);
+ DefineFun( _T("if"), Ite);
+ DefineFun( _T("sum"), Sum);
+ DefineFun( _T("min"), Min);
+ DefineFun( _T("max"), Max);
+}
+
+//---------------------------------------------------------------------------
+/** \brief Initialize operators. */
+void ParserInt::InitOprt()
+{
+ // disable all built in operators, not all of them usefull for integer numbers
+ // (they don't do rounding of values)
+ EnableBuiltInOprt(false);
+
+ // Disable all built in operators, they wont work with integer numbers
+ // since they are designed for floating point numbers
+ DefineInfixOprt( _T("-"), UnaryMinus);
+ DefineInfixOprt( _T("!"), Not);
+
+ DefineOprt( _T("&"), LogAnd, prLOGIC);
+ DefineOprt( _T("|"), LogOr, prLOGIC);
+ DefineOprt( _T("^"), LogXor, prLOGIC);
+ DefineOprt( _T("&&"), And, prLOGIC);
+ DefineOprt( _T("||"), Or, prLOGIC);
+
+ DefineOprt( _T("<"), Less, prCMP);
+ DefineOprt( _T(">"), Greater, prCMP);
+ DefineOprt( _T("<="), LessEq, prCMP);
+ DefineOprt( _T(">="), GreaterEq, prCMP);
+ DefineOprt( _T("=="), Equal, prCMP);
+ DefineOprt( _T("!="), NotEqual, prCMP);
+
+ DefineOprt( _T("+"), Add, prADD_SUB);
+ DefineOprt( _T("-"), Sub, prADD_SUB);
+
+ DefineOprt( _T("*"), Mul, prMUL_DIV);
+ DefineOprt( _T("/"), Div, prMUL_DIV);
+ DefineOprt( _T("%"), Mod, prMUL_DIV);
+
+ DefineOprt( _T(">>"), Shr, prMUL_DIV+1);
+ DefineOprt( _T("<<"), Shl, prMUL_DIV+1);
+}
+
+} // namespace mu
diff --git a/muparser/muParserInt.h b/muparser/muParserInt.h
new file mode 100644
index 0000000..008792d
--- /dev/null
+++ b/muparser/muParserInt.h
@@ -0,0 +1,93 @@
+/*
+ __________
+ _____ __ __\______ \_____ _______ ______ ____ _______
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
+ \/ \/ \/ \/
+ Copyright (C) 2004-2006 Ingo Berg
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ software and associated documentation files (the "Software"), to deal in the Software
+ without restriction, including without limitation the rights to use, copy, modify,
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef MU_PARSER_INT_H
+#define MU_PARSER_INT_H
+
+#include "muParserBase.h"
+#include <vector>
+
+
+namespace mu
+{
+
+/** \brief Mathematical expressions parser.
+
+ This version of the parser handles only integer numbers. It disables the built in operators thus it is
+ slower than muParser. Integer values are stored in the double value_type and converted if needed.
+*/
+class ParserInt : public ParserBase
+{
+private:
+ static int Round(value_type v) { return (int)(v + ((v>=0) ? 0.5 : -0.5) ); };
+
+ static value_type Abs(value_type);
+ static value_type Sign(value_type);
+ static value_type Ite(value_type, value_type, value_type);
+ // !! The unary Minus is a MUST, otherwise you cant use negative signs !!
+ static value_type UnaryMinus(value_type);
+ // Functions with variable number of arguments
+ static value_type Sum(const value_type* a_afArg, int a_iArgc); // sum
+ static value_type Min(const value_type* a_afArg, int a_iArgc); // minimum
+ static value_type Max(const value_type* a_afArg, int a_iArgc); // maximum
+ // binary operator callbacks
+ static value_type Add(value_type v1, value_type v2);
+ static value_type Sub(value_type v1, value_type v2);
+ static value_type Mul(value_type v1, value_type v2);
+ static value_type Div(value_type v1, value_type v2);
+ static value_type Mod(value_type v1, value_type v2);
+ static value_type Shr(value_type v1, value_type v2);
+ static value_type Shl(value_type v1, value_type v2);
+ static value_type LogAnd(value_type v1, value_type v2);
+ static value_type LogOr(value_type v1, value_type v2);
+ static value_type LogXor(value_type v1, value_type v2);
+ static value_type And(value_type v1, value_type v2);
+ static value_type Or(value_type v1, value_type v2);
+ static value_type Xor(value_type v1, value_type v2);
+ static value_type Less(value_type v1, value_type v2);
+ static value_type Greater(value_type v1, value_type v2);
+ static value_type LessEq(value_type v1, value_type v2);
+ static value_type GreaterEq(value_type v1, value_type v2);
+ static value_type Equal(value_type v1, value_type v2);
+ static value_type NotEqual(value_type v1, value_type v2);
+ static value_type Not(value_type v1);
+
+ static bool IsHexVal(const char_type *a_szExpr, int &a_iPos, value_type &a_iVal);
+ static bool IsBinVal(const char_type *a_szExpr, int &a_iPos, value_type &a_iVal);
+ static bool IsVal(const char_type *a_szExpr, int &a_iPos, value_type &a_iVal);
+
+public:
+ ParserInt();
+
+ virtual void InitFun();
+ virtual void InitOprt();
+ virtual void InitConst();
+ virtual void InitCharSets();
+};
+
+} // namespace mu
+
+#endif
+
diff --git a/muparser/muParserStack.h b/muparser/muParserStack.h
new file mode 100644
index 0000000..e035582
--- /dev/null
+++ b/muparser/muParserStack.h
@@ -0,0 +1,120 @@
+/*
+ __________
+ _____ __ __\______ \_____ _______ ______ ____ _______
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
+ \/ \/ \/ \/
+ Copyright (C) 2004-2006 Ingo Berg
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ software and associated documentation files (the "Software"), to deal in the Software
+ without restriction, including without limitation the rights to use, copy, modify,
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef MU_PARSER_STACK_H
+#define MU_PARSER_STACK_H
+
+#include <cassert>
+#include <string>
+#include <stack>
+#include <vector>
+
+#include "muParserError.h"
+#include "muParserToken.h"
+
+
+namespace mu
+{
+
+ /** \brief Parser stack implementation.
+
+ Stack implementation based on a std::stack. The behaviour of pop() had been
+ slightly changed in order to get an error code if the stack is empty.
+ The stack is used within the Parser both as a value stack and as an operator stack.
+
+ \author (C) 2004, 2005 Ingo Berg
+ */
+ template <typename TValueType>
+ class ParserStack
+ {
+ private:
+ /** \brief Type of the underlying stack implementation. */
+ typedef std::stack<TValueType, std::vector<TValueType> > impl_type;
+ impl_type m_Stack;
+
+ public:
+
+ //---------------------------------------------------------------------------
+ ParserStack()
+ :m_Stack()
+ {}
+
+ //---------------------------------------------------------------------------
+ virtual ~ParserStack()
+ {}
+
+ //---------------------------------------------------------------------------
+ /** \brief Pop a value from the stack.
+
+ Unlike the standard implementation this function will return the value that
+ is going to be taken from the stack.
+
+ \throw ParserException in case the stack is empty.
+ \sa pop(int &a_iErrc)
+ */
+ TValueType pop()
+ {
+ if (empty())
+ throw ParserError( _T("stack is empty.") );
+
+ TValueType el = top();
+ m_Stack.pop();
+ return el;
+ }
+
+ /** \brief Push an object into the stack.
+
+ \param a_Val object to push into the stack.
+ \throw nothrow
+ */
+ void push(const TValueType& a_Val)
+ {
+ m_Stack.push(a_Val);
+ }
+
+ /** \brief Return the number of stored elements. */
+ unsigned size() const
+ {
+ return (unsigned)m_Stack.size();
+ }
+
+ /** \brief Returns true if stack is empty false otherwise. */
+ bool empty() const
+ {
+ return m_Stack.size()==0;
+ }
+
+ /** \brief Return reference to the top object in the stack.
+
+ The top object is the one pushed most recently.
+ */
+ TValueType& top()
+ {
+ return m_Stack.top();
+ }
+ };
+} // namespace MathUtils
+
+#endif
diff --git a/muparser/muParserTest.cpp b/muparser/muParserTest.cpp
new file mode 100644
index 0000000..eed6cc4
--- /dev/null
+++ b/muparser/muParserTest.cpp
@@ -0,0 +1,1125 @@
+/*
+ __________
+ _____ __ __\______ \_____ _______ ______ ____ _______
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
+ \/ \/ \/ \/
+ Copyright (C) 2004-2006 Ingo Berg
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ software and associated documentation files (the "Software"), to deal in the Software
+ without restriction, including without limitation the rights to use, copy, modify,
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "muParserTest.h"
+
+#include <cstdio>
+#include <cmath>
+#include <iostream>
+
+#define PARSER_CONST_PI 3.141592653589793238462643
+#define PARSER_CONST_E 2.718281828459045235360287
+
+using namespace std;
+
+
+namespace mu
+{
+ namespace Test
+ {
+ int ParserTester::c_iCount = 0;
+
+ //---------------------------------------------------------------------------
+ ParserTester::ParserTester()
+ :m_vTestFun()
+ {
+ AddTest(&ParserTester::TestNames);
+ AddTest(&ParserTester::TestSyntax);
+ AddTest(&ParserTester::TestPostFix);
+ AddTest(&ParserTester::TestInfixOprt);
+ AddTest(&ParserTester::TestVarConst);
+ AddTest(&ParserTester::TestVolatile);
+ AddTest(&ParserTester::TestMultiArg);
+ AddTest(&ParserTester::TestFormula);
+ AddTest(&ParserTester::TestInterface);
+ AddTest(&ParserTester::TestBinOprt);
+ AddTest(&ParserTester::TestException);
+ AddTest(&ParserTester::TestStrArg);
+
+ ParserTester::c_iCount = 0;
+ }
+
+ //---------------------------------------------------------------------------
+ int ParserTester::TestInterface()
+ {
+ int iStat = 0;
+ mu::console() << _T("testing member functions...");
+
+ // Test RemoveVar
+ value_type afVal[3] = {1,2,3};
+ Parser p;
+
+ try
+ {
+ p.DefineVar( _T("a"), &afVal[0]);
+ p.DefineVar( _T("b"), &afVal[1]);
+ p.DefineVar( _T("c"), &afVal[2]);
+ p.SetExpr( _T("a+b+c") );
+ p.Eval();
+ }
+ catch(...)
+ {
+ iStat += 1; // this is not supposed to happen
+ }
+
+ try
+ {
+ p.RemoveVar( _T("c") );
+ p.Eval();
+ iStat += 1; // not supposed to reach this, nonexisting variable "c" deleted...
+ }
+ catch(...)
+ {
+ // failure is expected...
+ }
+
+ if (iStat==0)
+ mu::console() << _T("passed") << endl;
+ else
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;
+
+ return iStat;
+ }
+
+ //---------------------------------------------------------------------------
+ int ParserTester::TestStrArg()
+ {
+ int iStat = 0;
+ mu::console() << _T("testing string arguments...");
+
+ iStat += EqnTest(_T("valueof(\"aaa\")+valueof(\"bbb\") "), 246, true);
+ iStat += EqnTest(_T("2*(valueof(\"aaa\")-23)+valueof(\"bbb\")"), 323, true);
+ // use in expressions with variables
+ iStat += EqnTest(_T("a*(atof(\"10\")-b)"), 8, true);
+ iStat += EqnTest(_T("a-(atof(\"10\")*b)"), -19, true);
+ // string + numeric arguments
+ iStat += EqnTest(_T("strfun1(\"100\")"), 100, true);
+ iStat += EqnTest(_T("strfun2(\"100\",1)"), 101, true);
+ iStat += EqnTest(_T("strfun3(\"99\",1,2)"), 102, true);
+
+ if (iStat==0)
+ mu::console() << _T("passed") << endl;
+ else
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;
+
+ return iStat;
+ }
+
+ //---------------------------------------------------------------------------
+ int ParserTester::TestBinOprt()
+ {
+ int iStat = 0;
+ mu::console() << _T("testing binary operators...");
+
+ // built in operators
+ // xor operator
+ iStat += EqnTest(_T("1 xor 2"), 3, true);
+ iStat += EqnTest(_T("a xor b"), 3, true); // with a=1 and b=2
+ iStat += EqnTest(_T("1 xor 2 xor 3"), 0, true);
+ iStat += EqnTest(_T("a xor b xor 3"), 0, true); // with a=1 and b=2
+ iStat += EqnTest(_T("a xor b xor c"), 0, true); // with a=1 and b=2
+ iStat += EqnTest(_T("(1 xor 2) xor 3"), 0, true);
+ iStat += EqnTest(_T("(a xor b) xor c"), 0, true); // with a=1 and b=2
+ iStat += EqnTest(_T("(a) xor (b) xor c"), 0, true); // with a=1 and b=2
+ iStat += EqnTest(_T("1 or 2"), 3, true);
+ iStat += EqnTest(_T("a or b"), 3, true); // with a=1 and b=2
+
+ // Assignement operator
+ iStat += EqnTest(_T("a = b"), 2, true);
+ iStat += EqnTest(_T("a = sin(b)"), 0.909297, true);
+ iStat += EqnTest(_T("a = 1+sin(b)"), 1.909297, true);
+
+ // Test user defined binary operators
+ iStat += EqnTestInt(_T("1 | 2"), 3, true);
+ iStat += EqnTestInt(_T("1 || 2"), 1, true);
+ iStat += EqnTestInt(_T("123 & 456"), 72, true);
+ iStat += EqnTestInt(_T("(123 & 456) % 10"), 2, true);
+ iStat += EqnTestInt(_T("1 && 0"), 0, true);
+ iStat += EqnTestInt(_T("123 && 456"), 1, true);
+ iStat += EqnTestInt(_T("1 << 3"), 8, true);
+ iStat += EqnTestInt(_T("8 >> 3"), 1, true);
+ iStat += EqnTestInt(_T("10 ^ 10"), 0, true);
+ iStat += EqnTestInt(_T("10 * 10 ^ 99"), 7, true);
+ iStat += EqnTestInt(_T("9 / 4"), 2, true);
+ iStat += EqnTestInt(_T("9 % 4"), 1, true);
+ iStat += EqnTestInt(_T("if(5%2,1,0)"), 1, true);
+ iStat += EqnTestInt(_T("if(4%2,1,0)"), 0, true);
+ iStat += EqnTestInt(_T("-10+1"), -9, true);
+ iStat += EqnTestInt(_T("1+2*3"), 7, true);
+ iStat += EqnTestInt(_T("const1 != const2"), 1, true);
+ iStat += EqnTestInt(_T("const1 != const2"), 0, false);
+ iStat += EqnTestInt(_T("const1 == const2"), 0, true);
+ iStat += EqnTestInt(_T("const1 == 1"), 1, true);
+ iStat += EqnTestInt(_T("10*(const1 == 1)"), 10, true);
+ iStat += EqnTestInt(_T("2*(const1 | const2)"), 6, true);
+ iStat += EqnTestInt(_T("2*(const1 | const2)"), 7, false);
+ iStat += EqnTestInt(_T("const1 < const2"), 1, true);
+ iStat += EqnTestInt(_T("const2 > const1"), 1, true);
+ iStat += EqnTestInt(_T("const1 <= 1"), 1, true);
+ iStat += EqnTestInt(_T("const2 >= 2"), 1, true);
+ iStat += EqnTestInt(_T("2*(const1 + const2)"), 6, true);
+ iStat += EqnTestInt(_T("2*(const1 - const2)"), -2, true);
+
+ iStat += EqnTestInt(_T("a != b"), 1, true);
+ iStat += EqnTestInt(_T("a != b"), 0, false);
+ iStat += EqnTestInt(_T("a == b"), 0, true);
+ iStat += EqnTestInt(_T("a == 1"), 1, true);
+ iStat += EqnTestInt(_T("10*(a == 1)"), 10, true);
+ iStat += EqnTestInt(_T("2*(a | b)"), 6, true);
+ iStat += EqnTestInt(_T("2*(a | b)"), 7, false);
+ iStat += EqnTestInt(_T("a < b"), 1, true);
+ iStat += EqnTestInt(_T("b > a"), 1, true);
+ iStat += EqnTestInt(_T("a <= 1"), 1, true);
+ iStat += EqnTestInt(_T("b >= 2"), 1, true);
+ iStat += EqnTestInt(_T("2*(a + b)"), 6, true);
+ iStat += EqnTestInt(_T("2*(a - b)"), -2, true);
+ iStat += EqnTestInt(_T("a + (a << b)"), 5, true);
+ iStat += EqnTestInt(_T("-2^2"), -4, true);
+// incorrect: '^' is yor here, not power
+// iStat += EqnTestInt("-(1+2)^2", -9, true);
+// iStat += EqnTestInt("-1^3", -1, true);
+
+ // Test precedence
+ // a=1, b=2, c=3
+ iStat += EqnTestInt(_T("a + b * c"), 7, true);
+ iStat += EqnTestInt(_T("a * b + c"), 5, true);
+ iStat += EqnTestInt(_T("a<b && b>10"), 0, true);
+ iStat += EqnTestInt(_T("a<b && b<10"), 1, true);
+
+ iStat += EqnTestInt(_T("a + b << c"), 17, true);
+ iStat += EqnTestInt(_T("a << b + c"), 7, true);
+ iStat += EqnTestInt(_T("c * b < a"), 0, true);
+ iStat += EqnTestInt(_T("c * b == 6 * a"), 1, true);
+
+ if (iStat==0)
+ mu::console() << _T("passed") << endl;
+ else
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;
+
+ return iStat;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Check muParser name restriction enforcement. */
+ int ParserTester::TestNames()
+ {
+ int iStat= 0,
+ iErr = 0;
+
+ mu::console() << "testing name restriction enforcement...";
+
+ Parser p;
+
+ #define PARSER_THROWCHECK(DOMAIN, FAIL, EXPR, ARG) \
+ iErr = 0; \
+ ParserTester::c_iCount++; \
+ try \
+ { \
+ p.Define##DOMAIN(EXPR, ARG); \
+ } \
+ catch(Parser::exception_type&) \
+ { \
+ iErr = (FAIL==false) ? 0 : 1; \
+ } \
+ iStat += iErr;
+
+ // constant names
+ PARSER_THROWCHECK(Const, false, _T("0a"), 1)
+ PARSER_THROWCHECK(Const, false, _T("9a"), 1)
+ PARSER_THROWCHECK(Const, false, _T("+a"), 1)
+ PARSER_THROWCHECK(Const, false, _T("-a"), 1)
+ PARSER_THROWCHECK(Const, false, _T("a-"), 1)
+ PARSER_THROWCHECK(Const, false, _T("a*"), 1)
+ PARSER_THROWCHECK(Const, false, _T("a?"), 1)
+ PARSER_THROWCHECK(Const, true, _T("a"), 1)
+ PARSER_THROWCHECK(Const, true, _T("a_min"), 1)
+ PARSER_THROWCHECK(Const, true, _T("a_min0"), 1)
+ PARSER_THROWCHECK(Const, true, _T("a_min9"), 1)
+ // variable names
+ value_type a;
+ p.ClearConst();
+ PARSER_THROWCHECK(Var, false, _T("123abc"), &a)
+ PARSER_THROWCHECK(Var, false, _T("9a"), &a)
+ PARSER_THROWCHECK(Var, false, _T("0a"), &a)
+ PARSER_THROWCHECK(Var, false, _T("+a"), &a)
+ PARSER_THROWCHECK(Var, false, _T("-a"), &a)
+ PARSER_THROWCHECK(Var, false, _T("?a"), &a)
+ PARSER_THROWCHECK(Var, false, _T("!a"), &a)
+ PARSER_THROWCHECK(Var, false, _T("a+"), &a)
+ PARSER_THROWCHECK(Var, false, _T("a-"), &a)
+ PARSER_THROWCHECK(Var, false, _T("a*"), &a)
+ PARSER_THROWCHECK(Var, false, _T("a?"), &a)
+ PARSER_THROWCHECK(Var, true, _T("a"), &a)
+ PARSER_THROWCHECK(Var, true, _T("a_min"), &a)
+ PARSER_THROWCHECK(Var, true, _T("a_min0"), &a)
+ PARSER_THROWCHECK(Var, true, _T("a_min9"), &a)
+ PARSER_THROWCHECK(Var, false, _T("a_min9"), 0)
+ // Postfix operators
+ // fail
+ PARSER_THROWCHECK(PostfixOprt, false, _T("(k"), f1of1)
+ PARSER_THROWCHECK(PostfixOprt, false, _T("9+"), f1of1)
+ PARSER_THROWCHECK(PostfixOprt, false, _T("+"), 0)
+ // pass
+ PARSER_THROWCHECK(PostfixOprt, true, _T("-a"), f1of1)
+ PARSER_THROWCHECK(PostfixOprt, true, _T("?a"), f1of1)
+ PARSER_THROWCHECK(PostfixOprt, true, _T("_"), f1of1)
+ PARSER_THROWCHECK(PostfixOprt, true, _T("#"), f1of1)
+ PARSER_THROWCHECK(PostfixOprt, true, _T("&&"), f1of1)
+ PARSER_THROWCHECK(PostfixOprt, true, _T("||"), f1of1)
+ PARSER_THROWCHECK(PostfixOprt, true, _T("&"), f1of1)
+ PARSER_THROWCHECK(PostfixOprt, true, _T("|"), f1of1)
+ PARSER_THROWCHECK(PostfixOprt, true, _T("++"), f1of1)
+ PARSER_THROWCHECK(PostfixOprt, true, _T("--"), f1of1)
+ PARSER_THROWCHECK(PostfixOprt, true, _T("?>"), f1of1)
+ PARSER_THROWCHECK(PostfixOprt, true, _T("?<"), f1of1)
+ PARSER_THROWCHECK(PostfixOprt, true, _T("**"), f1of1)
+ PARSER_THROWCHECK(PostfixOprt, true, _T("xor"), f1of1)
+ PARSER_THROWCHECK(PostfixOprt, true, _T("and"), f1of1)
+ PARSER_THROWCHECK(PostfixOprt, true, _T("or"), f1of1)
+ PARSER_THROWCHECK(PostfixOprt, true, _T("not"), f1of1)
+ PARSER_THROWCHECK(PostfixOprt, true, _T("!"), f1of1)
+ // Binary operator
+ // The following must fail with builtin operators activated
+ // p.EnableBuiltInOp(true); -> this is the default
+ PARSER_THROWCHECK(Oprt, false, _T("+"), f1of2)
+ PARSER_THROWCHECK(Oprt, false, _T("-"), f1of2)
+ PARSER_THROWCHECK(Oprt, false, _T("*"), f1of2)
+ PARSER_THROWCHECK(Oprt, false, _T("/"), f1of2)
+ // without activated built in operators it should work
+ p.EnableBuiltInOprt(false);
+ PARSER_THROWCHECK(Oprt, true, _T("+"), f1of2)
+ PARSER_THROWCHECK(Oprt, true, _T("-"), f1of2)
+ PARSER_THROWCHECK(Oprt, true, _T("*"), f1of2)
+ PARSER_THROWCHECK(Oprt, true, _T("/"), f1of2)
+ #undef PARSER_THROWCHECK
+
+ if (iStat==0)
+ mu::console() << _T("passed") << endl;
+ else
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;
+
+ return iStat;
+ }
+
+ //---------------------------------------------------------------------------
+ int ParserTester::TestSyntax()
+ {
+ int iStat = 0;
+ mu::console() << _T("testing syntax engine...");
+
+ iStat += EqnTest(_T("(1+ 2*a)"), 3, true); // Spaces within formula
+ iStat += EqnTest(_T("(2+"), 0, false); // missing closing bracket
+ iStat += EqnTest(_T("2++4"), 0, false); // unexpected operator
+ iStat += EqnTest(_T("2+-4"), 0, false); // unexpected operator
+ iStat += EqnTest(_T("(2+)"), 0, false); // unexpected closing bracket
+ iStat += EqnTest(_T("--2"), 0, false); // double sign
+ iStat += EqnTest(_T("ksdfj"), 0, false); // unknown token
+ iStat += EqnTest(_T("()"), 0, false); // empty bracket
+ iStat += EqnTest(_T("sin(cos)"), 0, false); // unexpected function
+ iStat += EqnTest(_T("5t6"), 0, false); // unknown token
+ iStat += EqnTest(_T("5 t 6"), 0, false); // unknown token
+ iStat += EqnTest(_T("8*"), 0, false); // unexpected end of formula
+ iStat += EqnTest(_T(",3"), 0, false); // unexpected comma
+ iStat += EqnTest(_T("3,5"), 0, false); // unexpected comma
+ iStat += EqnTest(_T("sin(8,8)"), 0, false); // too many function args
+ iStat += EqnTest(_T("(7,8)"), 0, false); // too many function args
+ iStat += EqnTest(_T("sin)"), 0, false); // unexpected closing bracket
+ iStat += EqnTest(_T("a)"), 0, false); // unexpected closing bracket
+ iStat += EqnTest(_T("pi)"), 0, false); // unexpected closing bracket
+ iStat += EqnTest(_T("sin(())"), 0, false); // unexpected closing bracket
+ iStat += EqnTest(_T("sin()"), 0, false); // unexpected closing bracket
+
+ if (iStat==0)
+ mu::console() << _T("passed") << endl;
+ else
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;
+
+ return iStat;
+ }
+
+ //---------------------------------------------------------------------------
+ int ParserTester::TestVarConst()
+ {
+ int iStat = 0;
+ mu::console() << _T("testing variable/constant name recognition...");
+
+ // distinguish constants with same basename
+ iStat += EqnTest( _T("const"), 1, true);
+ iStat += EqnTest( _T("const1"), 2, true);
+ iStat += EqnTest( _T("const2"), 3, true);
+ iStat += EqnTest( _T("2*const"), 2, true);
+ iStat += EqnTest( _T("2*const1"), 4, true);
+ iStat += EqnTest( _T("2*const2"), 6, true);
+ iStat += EqnTest( _T("2*const+1"), 3, true);
+ iStat += EqnTest( _T("2*const1+1"), 5, true);
+ iStat += EqnTest( _T("2*const2+1"), 7, true);
+ iStat += EqnTest( _T("const"), 0, false);
+ iStat += EqnTest( _T("const1"), 0, false);
+ iStat += EqnTest( _T("const2"), 0, false);
+
+ // distinguish variables with same basename
+ iStat += EqnTest( _T("a"), 1, true);
+ iStat += EqnTest( _T("aa"), 2, true);
+ iStat += EqnTest( _T("2*a"), 2, true);
+ iStat += EqnTest( _T("2*aa"), 4, true);
+ iStat += EqnTest( _T("2*a-1"), 1, true);
+ iStat += EqnTest( _T("2*aa-1"), 3, true);
+
+ // Finally test querying of used variables
+ try
+ {
+ int idx;
+ mu::Parser p;
+ mu::value_type vVarVal[] = { 1, 2, 3, 4, 5};
+ p.DefineVar( _T("a"), &vVarVal[0]);
+ p.DefineVar( _T("b"), &vVarVal[1]);
+ p.DefineVar( _T("c"), &vVarVal[2]);
+ p.DefineVar( _T("d"), &vVarVal[3]);
+ p.DefineVar( _T("e"), &vVarVal[4]);
+
+ // Test lookup of defined variables
+ // 4 used variables
+ p.SetExpr( _T("a+b+c+d") );
+ mu::varmap_type UsedVar = p.GetUsedVar();
+ int iCount = (int)UsedVar.size();
+ if (iCount!=4) throw false;
+
+ mu::varmap_type::const_iterator item = UsedVar.begin();
+ for (idx=0; item!=UsedVar.end(); ++item)
+ {
+ if (&vVarVal[idx++]!=item->second)
+ throw false;
+ }
+
+ // Test lookup of undefined variables
+ p.SetExpr( _T("undef1+undef2+undef3") );
+ UsedVar = p.GetUsedVar();
+ iCount = (int)UsedVar.size();
+ if (iCount!=3) throw false;
+
+ for (item = UsedVar.begin(); item!=UsedVar.end(); ++item)
+ {
+ if (item->second!=0)
+ throw false; // all pointers to undefined variables must be null
+ }
+
+ // 1 used variables
+ p.SetExpr( _T("a+b") );
+ UsedVar = p.GetUsedVar();
+ iCount = (int)UsedVar.size();
+ if (iCount!=2) throw false;
+ item = UsedVar.begin();
+ for (idx=0; item!=UsedVar.end(); ++item)
+ if (&vVarVal[idx++]!=item->second) throw false;
+
+ }
+ catch(...)
+ {
+ iStat += 1;
+ }
+
+ if (iStat==0)
+ mu::console() << _T("passed") << endl;
+ else
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;
+
+ return iStat;
+ }
+
+ //---------------------------------------------------------------------------
+ int ParserTester::TestMultiArg()
+ {
+ int iStat = 0;
+ mu::console() << _T("testing multiarg functions...");
+
+ // picking the right argument
+ iStat += EqnTest( _T("f1of1(1)"), 1, true);
+ iStat += EqnTest( _T("f1of2(1, 2)"), 1, true);
+ iStat += EqnTest( _T("f2of2(1, 2)"), 2, true);
+ iStat += EqnTest( _T("f1of3(1, 2, 3)"), 1, true);
+ iStat += EqnTest( _T("f2of3(1, 2, 3)"), 2, true);
+ iStat += EqnTest( _T("f3of3(1, 2, 3)"), 3, true);
+ iStat += EqnTest( _T("f1of4(1, 2, 3, 4)"), 1, true);
+ iStat += EqnTest( _T("f2of4(1, 2, 3, 4)"), 2, true);
+ iStat += EqnTest( _T("f3of4(1, 2, 3, 4)"), 3, true);
+ iStat += EqnTest( _T("f4of4(1, 2, 3, 4)"), 4, true);
+ iStat += EqnTest( _T("f1of5(1, 2, 3, 4, 5)"), 1, true);
+ iStat += EqnTest( _T("f2of5(1, 2, 3, 4, 5)"), 2, true);
+ iStat += EqnTest( _T("f3of5(1, 2, 3, 4, 5)"), 3, true);
+ iStat += EqnTest( _T("f4of5(1, 2, 3, 4, 5)"), 4, true);
+ iStat += EqnTest( _T("f5of5(1, 2, 3, 4, 5)"), 5, true);
+ // Too few arguments / Too many arguments
+ iStat += EqnTest( _T("f1of1(1,2)"), 0, false);
+ iStat += EqnTest( _T("f1of1()"), 0, false);
+ iStat += EqnTest( _T("f1of2(1, 2, 3)"), 0, false);
+ iStat += EqnTest( _T("f1of2(1)"), 0, false);
+ iStat += EqnTest( _T("f1of3(1, 2, 3, 4)"), 0, false);
+ iStat += EqnTest( _T("f1of3(1)"), 0, false);
+ iStat += EqnTest( _T("f1of4(1, 2, 3, 4, 5)"), 0, false);
+ iStat += EqnTest( _T("f1of4(1)"), 0, false);
+ iStat += EqnTest( _T("(1,2,3)"), 0, false);
+ iStat += EqnTest( _T("1,2,3"), 0, false);
+ iStat += EqnTest( _T("(1*a,2,3)"), 0, false);
+ iStat += EqnTest( _T("1,2*a,3"), 0, false);
+
+ // correct calculation of arguments
+ iStat += EqnTest( _T("min(a, 1)"), 1, true);
+ iStat += EqnTest( _T("min(3*2, 1)"), 1, true);
+ iStat += EqnTest( _T("min(3*2, 1)"), 6, false);
+ // correct calculation of arguments
+ iStat += EqnTest( _T("min(3*a+1, 1)"), 1, true);
+ iStat += EqnTest( _T("max(3*a+1, 1)"), 4, true);
+ iStat += EqnTest( _T("max(3*a+1, 1)*2"), 8, true);
+ iStat += EqnTest( _T("2*max(3*a+1, 1)+2"), 10, true);
+
+ // functions with Variable argument count
+ iStat += EqnTest( _T("sum(1,2,3)"), 6, true);
+ iStat += EqnTest( _T("2*sum(1,2,3)"), 12, true);
+ iStat += EqnTest( _T("2*sum(1,2,3)+2"), 14, true);
+ iStat += EqnTest( _T("2*sum(-1,2,3)+2"), 10, true);
+ iStat += EqnTest( _T("2*sum(-1,2,-(-a))+2"), 6, true);
+ iStat += EqnTest( _T("2*sum(-1,10,-a)+2"), 18, true);
+ iStat += EqnTest( _T("2*sum(1,2,3)*2"), 24, true);
+ iStat += EqnTest( _T("sum(1,-max(1,2),3)*2"), 4, true);
+ iStat += EqnTest( _T("sum(1*3, 4, a+2)"), 10, true);
+ iStat += EqnTest( _T("sum(1*3, 2*sum(1,2,2), a+2)"), 16, true);
+ iStat += EqnTest( _T("sum(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2)"), 24, true);
+
+ // some failures
+ iStat += EqnTest( _T("sum()"), 0, false);
+ iStat += EqnTest( _T("sum(,)"), 0, false);
+ iStat += EqnTest( _T("sum(1,2,)"), 0, false);
+ iStat += EqnTest( _T("sum(,1,2)"), 0, false);
+
+ if (iStat==0)
+ mu::console() << _T("passed") << endl;
+ else
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;
+
+ return iStat;
+ }
+
+
+ //---------------------------------------------------------------------------
+ int ParserTester::TestInfixOprt()
+ {
+ int iStat = 0;
+ mu::console() << "testing infix operators...";
+
+ iStat += EqnTest( _T("-1"), -1, true);
+ iStat += EqnTest( _T("-(-1)"), 1, true);
+ iStat += EqnTest( _T("-(-1)*2"), 2, true);
+ iStat += EqnTest( _T("-(-2)*sqrt(4)"), 4, true);
+ iStat += EqnTest( _T("-a"), -1, true);
+ iStat += EqnTest( _T("-(a)"), -1, true);
+ iStat += EqnTest( _T("-(-a)"), 1, true);
+ iStat += EqnTest( _T("-(-a)*2"), 2, true);
+ iStat += EqnTest( _T("-(8)"), -8, true);
+ iStat += EqnTest( _T("-8"), -8, true);
+ iStat += EqnTest( _T("-(2+1)"), -3, true);
+ iStat += EqnTest( _T("-(f1of1(1+2*3)+1*2)"), -9, true);
+ iStat += EqnTest( _T("-(-f1of1(1+2*3)+1*2)"), 5, true);
+ iStat += EqnTest( _T("-sin(8)"), -0.989358, true);
+ iStat += EqnTest( _T("3-(-a)"), 4, true);
+ iStat += EqnTest( _T("3--a"), 4, true);
+
+ // Postfix / infix priorities
+ iStat += EqnTest( _T("~2#"), 8, true);
+ iStat += EqnTest( _T("~f1of1(2)#"), 8, true);
+ iStat += EqnTest( _T("~(b)#"), 8, true);
+ iStat += EqnTest( _T("(~b)#"), 12, true);
+ iStat += EqnTest( _T("~(2#)"), 8, true);
+ iStat += EqnTest( _T("~(f1of1(2)#)"), 8, true);
+ //
+ iStat += EqnTest( _T("-2^2"),-4, true);
+ iStat += EqnTest( _T("-(a+b)^2"),-9, true);
+ iStat += EqnTest( _T("(-3)^2"),9, true);
+ iStat += EqnTest( _T("-(-2^2)"),4, true);
+ iStat += EqnTest( _T("3+-3^2"),-6, true);
+ // The following assumes use of sqr as postfix operator ("?") together
+ // tiwth a sign operator of low priority:
+ iStat += EqnTest( _T("-2?"), -4, true);
+ iStat += EqnTest( _T("-(1+1)?"),-4, true);
+ iStat += EqnTest( _T("2+-(1+1)?"),-2, true);
+ iStat += EqnTest( _T("2+-2?"), -2, true);
+ // This is the classic behaviour of the infix sign operator (here: "$") which is
+ // now deprecated:
+ iStat += EqnTest( _T("$2^2"),4, true);
+ iStat += EqnTest( _T("$(a+b)^2"),9, true);
+ iStat += EqnTest( _T("($3)^2"),9, true);
+ iStat += EqnTest( _T("$($2^2)"),-4, true);
+ iStat += EqnTest( _T("3+$3^2"),12, true);
+
+ if (iStat==0)
+ mu::console() << _T("passed") << endl;
+ else
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;
+
+ return iStat;
+ }
+
+
+ //---------------------------------------------------------------------------
+ int ParserTester::TestPostFix()
+ {
+ int iStat = 0;
+ mu::console() << _T("testing postfix operators...");
+
+ // application
+ iStat += EqnTest( _T("3m+5"), 5.003, true);
+ iStat += EqnTest( _T("1000m"), 1, true);
+ iStat += EqnTest( _T("1000 m"), 1, true);
+ iStat += EqnTest( _T("(a)m"), 1e-3, true);
+ iStat += EqnTest( _T("-(a)m"), -1e-3, true);
+ iStat += EqnTest( _T("-2m"), -2e-3, true);
+ iStat += EqnTest( _T("f1of1(1000)m"), 1, true);
+ iStat += EqnTest( _T("-f1of1(1000)m"), -1, true);
+ iStat += EqnTest( _T("-f1of1(-1000)m"), 1, true);
+ iStat += EqnTest( _T("f4of4(0,0,0,1000)m"), 1, true);
+ iStat += EqnTest( _T("2+(a*1000)m"), 3, true);
+ // some incorrect results
+ iStat += EqnTest( _T("1000m"), 0.1, false);
+ iStat += EqnTest( _T("(a)m"), 2, false);
+ // failure due to syntax checking
+ iStat += EqnTest( _T("a m"), 0, false);
+ iStat += EqnTest( _T("4 + m"), 0, false);
+ iStat += EqnTest( _T("m4"), 0, false);
+ iStat += EqnTest( _T("sin(m)"), 0, false);
+ iStat += EqnTest( _T("m m"), 0, false);
+ iStat += EqnTest( _T("m(8)"), 0, false);
+ iStat += EqnTest( _T("4,m"), 0, false);
+ iStat += EqnTest( _T("-m"), 0, false);
+ iStat += EqnTest( _T("2(-m)"), 0, false);
+ iStat += EqnTest( _T("2(m)"), 0, false);
+
+ if (iStat==0)
+ mu::console() << _T("passed") << endl;
+ else
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;
+
+ return iStat;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Test volatile (nonoptimizeable functions). */
+ int ParserTester::TestVolatile()
+ {
+ int iStat = 0;
+ mu::console() << "testing volatile/nonvolatile functions...";
+
+ // First test with volatile flag turned on
+ try
+ {
+ mu::Parser p;
+ p.DefineFun( _T("rnd"), Rnd, false);
+ p.DefineFun( _T("valueof"), RndWithString, false);
+
+ // 1st test, compare results from sucessive calculations
+ p.SetExpr( _T("3+rnd(8)") );
+ if (p.Eval()==p.Eval()) iStat += 1;
+
+ // 2nd test, force bytecode creation, compare two results both
+ // calculated from bytecode
+ p.SetExpr( _T("3+rnd(8)") );
+ p.Eval(); //<- Force bytecode creation
+ if (p.Eval()==p.Eval()) iStat += 1;
+
+ p.SetExpr( _T("3*rnd(8)+3") );
+ p.Eval(); //<- Force bytecode creation
+ if (p.Eval()==p.Eval()) iStat += 1;
+
+ p.SetExpr( _T("10+3*sin(rnd(8))-1") );
+ p.Eval(); //<- Force bytecode creation
+ if (p.Eval()==p.Eval()) iStat += 1;
+
+ p.SetExpr( _T("3+rnd(rnd(8))*2") );
+ p.Eval(); //<- Force bytecode creation
+ if (p.Eval()==p.Eval()) iStat += 1;
+
+ p.SetExpr( _T("valueof(\"Das ist ein Test\")") );
+ p.Eval(); //<- Force bytecode creation
+ if (p.Eval()==p.Eval()) iStat += 1;
+ }
+ catch(Parser::exception_type &e)
+ {
+ mu::console() << _T("\n ") << e.GetExpr() << _T(" : ") << e.GetMsg();
+ iStat += 1;
+ }
+
+ // Second test with volatile flag turned off
+ try
+ {
+ mu::Parser p;
+ p.DefineFun( _T("rnd"), Rnd);
+ p.DefineFun( _T("valueof"), RndWithString);
+
+ // compare string parsing with bytecode
+ p.SetExpr( _T("3+rnd(8)") );
+ if (p.Eval()!=p.Eval()) iStat += 1;
+
+ p.SetExpr( _T("3+rnd(8)") );
+ p.Eval(); //<- Force bytecode creation
+ if (p.Eval()!=p.Eval()) iStat += 1;
+
+ p.SetExpr( _T("3*rnd(8)+3") );
+ p.Eval(); //<- Force bytecode creation
+ if (p.Eval()!=p.Eval()) iStat += 1;
+
+ p.SetExpr( _T("10+3*sin(rnd(8))-1") );
+ p.Eval(); //<- Force bytecode creation
+ if (p.Eval()!=p.Eval()) iStat += 1;
+
+ p.SetExpr( _T("3+rnd(rnd(8))*2") );
+ p.Eval(); //<- Force bytecode creation
+ if (p.Eval()!=p.Eval()) iStat += 1;
+ }
+ catch(Parser::exception_type &e)
+ {
+ mu::console() << _T("\n ") << e.GetExpr() << _T(" : ") << e.GetMsg();
+ iStat += 1;
+ }
+
+ if (iStat==0)
+ mu::console() << _T("passed") << endl;
+ else
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;
+
+ return iStat;
+ }
+
+ //---------------------------------------------------------------------------
+ int ParserTester::TestFormula()
+ {
+ int iStat = 0;
+ mu::console() << _T("testing sample formulas...");
+
+ // operator precedencs
+ iStat += EqnTest( _T("1+2-3*4/5^6"), 2.99923, true);
+ iStat += EqnTest( _T("1^2/3*4-5+6"), 2.3333, true);
+ iStat += EqnTest( _T("1+2*3"), 7, true);
+ iStat += EqnTest( _T("1+2*3"), 7, true);
+ iStat += EqnTest( _T("(1+2)*3"), 9, true);
+ iStat += EqnTest( _T("(1+2)*(-3)"), -9, true);
+ iStat += EqnTest( _T("2/4"), 0.5, true);
+
+ iStat += EqnTest( _T("exp(ln(7))"), 7, true);
+ iStat += EqnTest( _T("e^ln(7)"), 7, true);
+ iStat += EqnTest( _T("e^(ln(7))"), 7, true);
+ iStat += EqnTest( _T("(e^(ln(7)))"), 7, true);
+ iStat += EqnTest( _T("1-(e^(ln(7)))"), -6, true);
+ iStat += EqnTest( _T("2*(e^(ln(7)))"), 14, true);
+ iStat += EqnTest( _T("10^log(5)"), 5, true);
+ iStat += EqnTest( _T("10^log10(5)"), 5, true);
+ iStat += EqnTest( _T("2^log2(4)"), 4, true);
+ iStat += EqnTest( _T("-(sin(0)+1)"), -1, true);
+ iStat += EqnTest( _T("-(2^1.1)"), -2.14354692, true);
+
+ iStat += EqnTest( _T("(cos(2.41)/b)"), -0.372056, true);
+
+#if !defined(_UNICODE)
+ // I can't translate the following two tests to unicode without loosing
+ // readability.
+
+ // long formula (Reference: Matlab)
+ iStat += EqnTest(
+ "(((-9))-e/(((((((pi-(((-7)+(-3)/4/e))))/(((-5))-2)-((pi+(-0))*(sqrt((e+e))*(-8))*(((-pi)+(-pi)-(-9)*(6*5))"
+ "/(-e)-e))/2)/((((sqrt(2/(-e)+6)-(4-2))+((5/(-2))/(1*(-pi)+3))/8)*pi*((pi/((-2)/(-6)*1*(-1))*(-6)+(-e)))))/"
+ "((e+(-2)+(-e)*((((-3)*9+(-e)))+(-9)))))))-((((e-7+(((5/pi-(3/1+pi)))))/e)/(-5))/(sqrt((((((1+(-7))))+((((-"
+ "e)*(-e)))-8))*(-5)/((-e)))*(-6)-((((((-2)-(-9)-(-e)-1)/3))))/(sqrt((8+(e-((-6))+(9*(-9))))*(((3+2-8))*(7+6"
+ "+(-5))+((0/(-e)*(-pi))+7)))+(((((-e)/e/e)+((-6)*5)*e+(3+(-5)/pi))))+pi))/sqrt((((9))+((((pi))-8+2))+pi))/e"
+ "*4)*((-5)/(((-pi))*(sqrt(e)))))-(((((((-e)*(e)-pi))/4+(pi)*(-9)))))))+(-pi)", -12.23016549, true);
+
+ // long formula (Reference: Matlab)
+ iStat += EqnTest(
+ "(atan(sin((((((((((((((((pi/cos((a/((((0.53-b)-pi)*e)/b))))+2.51)+a)-0.54)/0.98)+b)*b)+e)/a)+b)+a)+b)+pi)/e"
+ ")+a)))*2.77)", -2.16995656, true);
+#endif
+
+ // long formula (Reference: Matlab)
+ iStat += EqnTest( _T("1+2-3*4/5^6*(2*(1-5+(3*7^9)*(4+6*7-3)))+12"), -7995810.09926, true);
+
+ if (iStat==0)
+ mu::console() << _T("passed") << endl;
+ else
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;
+
+ return iStat;
+ }
+
+
+ //---------------------------------------------------------------------------
+ int ParserTester::TestException()
+ {
+ int iStat = 0;
+ mu::console() << _T("testing error codes...");
+
+ iStat += ThrowTest(_T("3+"), ecUNEXPECTED_EOF);
+ iStat += ThrowTest(_T("3+)"), ecUNEXPECTED_PARENS);
+ iStat += ThrowTest(_T("sin(3,4)"), ecTOO_MANY_PARAMS);
+ iStat += ThrowTest(_T("3,4"), ecUNEXPECTED_COMMA);
+ iStat += ThrowTest(_T("if(3)"), ecTOO_FEW_PARAMS);
+ iStat += ThrowTest(_T("(1+2"), ecMISSING_PARENS);
+ iStat += ThrowTest(_T("sin(3)3"), ecUNEXPECTED_VAL);
+ iStat += ThrowTest(_T("sin(3)xyz"), ecUNASSIGNABLE_TOKEN);
+ iStat += ThrowTest(_T("sin(3)cos(3)"), ecUNEXPECTED_FUN);
+
+ // String function related
+ iStat += ThrowTest( _T("valueof(\"xxx\")"), 999, false);
+ iStat += ThrowTest( _T("valueof()"), ecUNEXPECTED_PARENS);
+ iStat += ThrowTest( _T("1+valueof(\"abc\""), ecMISSING_PARENS);
+ iStat += ThrowTest( _T("valueof(\"abc\""), ecMISSING_PARENS);
+ iStat += ThrowTest( _T("valueof(\"abc"), ecUNTERMINATED_STRING);
+ iStat += ThrowTest( _T("valueof(\"abc\",3)"), ecTOO_MANY_PARAMS);
+ iStat += ThrowTest( _T("valueof(3)"), ecSTRING_EXPECTED);
+ iStat += ThrowTest( _T("sin(\"abc\")"), ecVAL_EXPECTED);
+ iStat += ThrowTest( _T("valueof(\"\\\"abc\\\"\")"), 999, false);
+ iStat += ThrowTest( _T("\"hello world\""), ecSTR_RESULT);
+ iStat += ThrowTest( _T("(\"hello world\")"), ecSTR_RESULT);
+ iStat += ThrowTest( _T("\"abcd\"+100"), ecOPRT_TYPE_CONFLICT);
+ iStat += ThrowTest( _T("\"a\"+\"b\""), ecOPRT_TYPE_CONFLICT);
+ iStat += ThrowTest( _T("strfun1(\"100\",3)"), ecTOO_MANY_PARAMS);
+ iStat += ThrowTest( _T("strfun2(\"100\",3,5)"), ecTOO_MANY_PARAMS);
+ iStat += ThrowTest( _T("strfun3(\"100\",3,5,6)"), ecTOO_MANY_PARAMS);
+ iStat += ThrowTest( _T("strfun2(\"100\")"), ecTOO_FEW_PARAMS);
+ iStat += ThrowTest( _T("strfun3(\"100\",6)"), ecTOO_FEW_PARAMS);
+ iStat += ThrowTest( _T("strfun2(1,1)"), ecSTRING_EXPECTED);
+ iStat += ThrowTest( _T("strfun2(a,1)"), ecSTRING_EXPECTED);
+ iStat += ThrowTest( _T("strfun2(1,1,1)"), ecTOO_MANY_PARAMS);
+ iStat += ThrowTest( _T("strfun2(a,1,1)"), ecTOO_MANY_PARAMS);
+ iStat += ThrowTest( _T("strfun3(1,2,3)"), ecSTRING_EXPECTED);
+ iStat += ThrowTest( _T("strfun3(1, \"100\",3)"), ecSTRING_EXPECTED);
+ iStat += ThrowTest( _T("strfun3(\"1\", \"100\",3)"), ecVAL_EXPECTED);
+ iStat += ThrowTest( _T("strfun3(\"1\", 3, \"100\")"), ecVAL_EXPECTED);
+ iStat += ThrowTest( _T("strfun3(\"1\", \"100\", \"100\", \"100\")"), ecTOO_MANY_PARAMS);
+
+ // assignement operator
+// iStat += ThrowTest("maxspec=0", 0, false);
+ iStat += ThrowTest( _T("3=4"), ecUNEXPECTED_OPERATOR);
+ iStat += ThrowTest( _T("sin(8)=4"), ecUNEXPECTED_OPERATOR);
+ iStat += ThrowTest( _T("\"test\"=a"), ecUNEXPECTED_OPERATOR);
+ iStat += ThrowTest( _T("sin=9"), ecUNEXPECTED_OPERATOR);
+ iStat += ThrowTest( _T("(8)=5"), ecUNEXPECTED_OPERATOR);
+ iStat += ThrowTest( _T("(a)=5"), ecUNEXPECTED_OPERATOR);
+ iStat += ThrowTest( _T("a=\"tttt\""), ecOPRT_TYPE_CONFLICT);
+
+ if (iStat==0)
+ mu::console() << _T("passed") << endl;
+ else
+ mu::console() << _T("\n failed with ") << iStat << _T(" errors") << endl;
+
+ return iStat;
+ }
+
+
+ //---------------------------------------------------------------------------
+ void ParserTester::AddTest(testfun_type a_pFun)
+ {
+ m_vTestFun.push_back(a_pFun);
+ }
+
+ //---------------------------------------------------------------------------
+ void ParserTester::Run()
+ {
+ int iStat = 0;
+ try
+ {
+ for (int i=0; i<(int)m_vTestFun.size(); ++i)
+ iStat += (this->*m_vTestFun[i])();
+ }
+ catch(Parser::exception_type &e)
+ {
+ mu::console() << "\n" << e.GetMsg() << endl;
+ mu::console() << e.GetToken() << endl;
+ Abort();
+ }
+ catch(std::exception &e)
+ {
+ mu::console() << e.what() << endl;
+ Abort();
+ }
+ catch(...)
+ {
+ mu::console() << "Internal error";
+ Abort();
+ }
+
+ if (iStat==0)
+ {
+ mu::console() << "Test passed (" << ParserTester::c_iCount << " expressions)" << endl;
+ }
+ else
+ {
+ mu::console() << "Test failed with " << iStat
+ << " errors (" << ParserTester::c_iCount
+ << " expressions)" << endl;
+ }
+ ParserTester::c_iCount = 0;
+ }
+
+
+ //---------------------------------------------------------------------------
+ int ParserTester::ThrowTest(const string_type &a_str, int a_iErrc, bool a_bFail)
+ {
+ ParserTester::c_iCount++;
+
+ try
+ {
+ double fVal=0;
+ Parser p;
+
+ p.DefineVar( _T("a"), &fVal);
+ p.DefineFun( _T("valueof"), ValueOf);
+ p.DefineFun( _T("strfun1"), StrFun1);
+ p.DefineFun( _T("strfun2"), StrFun2);
+ p.DefineFun( _T("strfun3"), StrFun3);
+ p.SetExpr(a_str);
+ p.Eval();
+ }
+ catch(Parser::exception_type &e)
+ {
+ // output the formula in case of an failed test
+ if (a_bFail==true && a_iErrc!=e.GetCode() )
+ {
+ mu::console() << _T("\n ")
+ << _T("Expression: ") << a_str
+ << _T(" Code:") << e.GetCode()
+ << _T(" Expected:") << a_iErrc;
+ }
+
+ return (a_iErrc==e.GetCode()) ? 0 : 1;
+ }
+
+ // if a_bFail==false no exception is expected
+ bool bRet((a_bFail==false) ? 0 : 1);
+ if (bRet==1)
+ {
+ mu::console() << _T("\n ")
+ << _T("Expression: ") << a_str
+ << _T(" did evaluate; Expected error:") << a_iErrc;
+ }
+
+ return bRet;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Evaluate a tet expression.
+
+ \return 1 in case of a failure, 0 otherwise.
+ */
+ int ParserTester::EqnTest(const string_type &a_str, double a_fRes, bool a_fPass)
+ {
+ ParserTester::c_iCount++;
+ int iRet(0);
+
+ try
+ {
+ Parser *p1, p2, p3; // three parser objects
+ // they will be used for testing copy and assihnment operators
+ // p1 is a pointer since i'm going to delete it in order to test if
+ // parsers after copy construction still refer to members of it.
+ // !! If this is the case this function will crash !!
+
+ p1 = new mu::Parser();
+ // Add constants
+ p1->DefineConst( _T("pi"), (value_type)PARSER_CONST_PI);
+ p1->DefineConst( _T("e"), (value_type)PARSER_CONST_E);
+ p1->DefineConst( _T("const"), 1);
+ p1->DefineConst( _T("const1"), 2);
+ p1->DefineConst( _T("const2"), 3);
+ // variables
+ value_type vVarVal[] = { 1, 2, 3, -2};
+ p1->DefineVar( _T("a"), &vVarVal[0]);
+ p1->DefineVar( _T("aa"), &vVarVal[1]);
+ p1->DefineVar( _T("b"), &vVarVal[1]);
+ p1->DefineVar( _T("c"), &vVarVal[2]);
+ p1->DefineVar( _T("d"), &vVarVal[3]);
+ // functions
+ p1->DefineFun( _T("f1of1"), f1of1); // one parameter
+ p1->DefineFun( _T("f1of2"), f1of2); // two parameter
+ p1->DefineFun( _T("f2of2"), f2of2);
+ p1->DefineFun( _T("f1of3"), f1of3); // three parameter
+ p1->DefineFun( _T("f2of3"), f2of3);
+ p1->DefineFun( _T("f3of3"), f3of3);
+ p1->DefineFun( _T("f1of4"), f1of4); // four parameter
+ p1->DefineFun( _T("f2of4"), f2of4);
+ p1->DefineFun( _T("f3of4"), f3of4);
+ p1->DefineFun( _T("f4of4"), f4of4);
+ p1->DefineFun( _T("f1of5"), f1of5); // five parameter
+ p1->DefineFun( _T("f2of5"), f2of5);
+ p1->DefineFun( _T("f3of5"), f3of5);
+ p1->DefineFun( _T("f4of5"), f4of5);
+ p1->DefineFun( _T("f5of5"), f5of5);
+ // sample functions
+ p1->DefineFun( _T("min"), Min);
+ p1->DefineFun( _T("max"), Max);
+ p1->DefineFun( _T("sum"), Sum);
+ p1->DefineFun( _T("valueof"), ValueOf);
+ p1->DefineFun( _T("atof"), StrToFloat);
+ p1->DefineFun( _T("strfun1"), StrFun1);
+ p1->DefineFun( _T("strfun2"), StrFun2);
+ p1->DefineFun( _T("strfun3"), StrFun3);
+
+ // infix / postfix operator
+ // (identifiers used here do not have any meaning or make any sense at all)
+ p1->DefineInfixOprt( _T("$"), sign, prPOW+1); // sign with high priority
+ p1->DefineInfixOprt( _T("~"), plus2); // high priority
+ p1->DefinePostfixOprt( _T("m"), Milli);
+ p1->DefinePostfixOprt( _T("#"), times3);
+ p1->DefinePostfixOprt( _T("?"), sqr); //
+ p1->SetExpr(a_str);
+
+ // Test bytecode integrity
+ // String parsing and bytecode parsing must yield the same result
+ value_type fVal[4] = {-999, -998, -997, -996}; // initially should be different
+ fVal[0] = p1->Eval(); // result from stringparsing
+ fVal[1] = p1->Eval(); // result from bytecode
+ if (fVal[0]!=fVal[1])
+ throw Parser::exception_type( _T("Bytecode corrupt.") );
+
+ // Test copy and assignement operators
+ try
+ {
+ // Test copy constructor
+ std::vector<mu::Parser> vParser;
+ vParser.push_back(*p1);
+ mu::Parser p2 = vParser[0]; // take parser from vector
+
+ // destroy the originals from p2
+ vParser.clear(); // delete the vector
+ delete p1; // delete the original
+ p1 = 0;
+
+ fVal[2] = p2.Eval();
+
+ // Test assignement operator
+ // additionally disable Optimizer this time
+ mu::Parser p3;
+ p3 = p2;
+ p3.EnableOptimizer(false);
+ fVal[3] = p3.Eval();
+ }
+ catch(std::exception &e)
+ {
+ mu::console() << _T("\n ") << e.what() << _T("\n");
+ }
+
+ // limited floating point accuracy requires the following test
+ bool bCloseEnough(true);
+ for (int i=0; i<4; ++i)
+ {
+ bCloseEnough &= (fabs(a_fRes-fVal[i]) <= fabs(fVal[i]*0.0001));
+ }
+
+ iRet = ((bCloseEnough && a_fPass) || (!bCloseEnough && !a_fPass)) ? 0 : 1;
+ if (iRet==1)
+ {
+ mu::console() << "\n fail: " << a_str.c_str()
+ << " (incorrect result; expected: " << a_fRes
+ << " ;calculated: " << fVal[0]<< ").";
+ }
+ }
+ catch(Parser::exception_type &e)
+ {
+ if (a_fPass)
+ {
+ mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.GetMsg() << _T(")");
+ return 1;
+ }
+ }
+ catch(std::exception &e)
+ {
+ mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (") << e.what() << _T(")");
+ return 1; // always return a failure since this exception is not expected
+ }
+ catch(...)
+ {
+ mu::console() << _T("\n fail: ") << a_str.c_str() << _T(" (unexpected exception)");
+ return 1; // exceptions other than ParserException are not allowed
+ }
+
+ return iRet;
+ }
+
+ //---------------------------------------------------------------------------
+ int ParserTester::EqnTestInt(const string_type &a_str, double a_fRes, bool a_fPass)
+ {
+ ParserTester::c_iCount++;
+
+ value_type vVarVal[] = {1, 2, 3}; // variable values
+ value_type fVal[2] = {-99, -999}; // results: initially should be different
+ int iRet(0);
+
+ try
+ {
+ ParserInt p;
+ p.DefineConst( _T("const1"), 1);
+ p.DefineConst( _T("const2"), 2);
+ p.DefineVar( _T("a"), &vVarVal[0]);
+ p.DefineVar( _T("b"), &vVarVal[1]);
+ p.DefineVar( _T("c"), &vVarVal[2]);
+
+ p.SetExpr(a_str);
+ fVal[0] = p.Eval(); // result from stringparsing
+ fVal[1] = p.Eval(); // result from bytecode
+
+ if (fVal[0]!=fVal[1])
+ throw Parser::exception_type( _T("Bytecode corrupt.") );
+
+ iRet = ( (a_fRes==fVal[0] && a_fPass) ||
+ (a_fRes!=fVal[0] && !a_fPass) ) ? 0 : 1;
+ if (iRet==1)
+ {
+ mu::console() << _T("\n fail: ") << a_str.c_str()
+ << _T(" (incorrect result; expected: ") << a_fRes
+ << _T(" ;calculated: ") << fVal[0]<< _T(").");
+ }
+ }
+ catch(Parser::exception_type &e)
+ {
+ if (a_fPass)
+ mu::console() << _T("\n ") << e.GetExpr() << _T(" : ") << e.GetMsg();
+ }
+ catch(...)
+ {
+ mu::console() << "\n fail: " << a_str.c_str() << " (unexpected exception)";
+ return 1; // exceptions other than ParserException are not allowed
+ }
+
+ return iRet;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Internal error in test class Test is going to be aborted. */
+ void ParserTester::Abort() const
+ {
+ mu::console() << _T("Test failed (internal error in test class)") << endl;
+ while (!getchar());
+ exit(-1);
+ }
+ } // namespace test
+} // namespace mu
+
+
+
diff --git a/muparser/muParserTest.h b/muparser/muParserTest.h
new file mode 100644
index 0000000..fe9bfdd
--- /dev/null
+++ b/muparser/muParserTest.h
@@ -0,0 +1,176 @@
+/*
+ __________
+ _____ __ __\______ \_____ _______ ______ ____ _______
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
+ \/ \/ \/ \/
+ Copyright (C) 2004-2006 Ingo Berg
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ software and associated documentation files (the "Software"), to deal in the Software
+ without restriction, including without limitation the rights to use, copy, modify,
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef MU_PARSER_TEST_H
+#define MU_PARSER_TEST_H
+
+#include <string>
+#include <numeric> // for accumulate
+#include "muParser.h"
+#include "muParserInt.h"
+
+
+namespace mu
+{
+ /** \brief Namespace for test cases. */
+ namespace Test
+ {
+ //------------------------------------------------------------------------------
+ /** \brief Test cases for unit testing.
+
+ (C) 2004-2006 Ingo Berg
+ */
+ class ParserTester // final
+ {
+ private:
+ // Multiarg callbacks
+ static value_type f1of1(value_type v) { return v;};
+
+ static value_type f1of2(value_type v, value_type ) {return v;};
+ static value_type f2of2(value_type , value_type v) {return v;};
+
+ static value_type f1of3(value_type v, value_type , value_type ) {return v;};
+ static value_type f2of3(value_type , value_type v, value_type ) {return v;};
+ static value_type f3of3(value_type , value_type , value_type v) {return v;};
+
+ static value_type f1of4(value_type v, value_type, value_type , value_type ) {return v;}
+ static value_type f2of4(value_type , value_type v, value_type , value_type ) {return v;}
+ static value_type f3of4(value_type , value_type, value_type v, value_type ) {return v;}
+ static value_type f4of4(value_type , value_type, value_type , value_type v) {return v;}
+
+ static value_type f1of5(value_type v, value_type, value_type , value_type , value_type ) { return v; }
+ static value_type f2of5(value_type , value_type v, value_type , value_type , value_type ) { return v; }
+ static value_type f3of5(value_type , value_type, value_type v, value_type , value_type ) { return v; }
+ static value_type f4of5(value_type , value_type, value_type , value_type v, value_type ) { return v; }
+ static value_type f5of5(value_type , value_type, value_type , value_type , value_type v) { return v; }
+
+ static value_type Min(value_type a_fVal1, value_type a_fVal2) { return (a_fVal1<a_fVal2) ? a_fVal1 : a_fVal2; }
+ static value_type Max(value_type a_fVal1, value_type a_fVal2) { return (a_fVal1>a_fVal2) ? a_fVal1 : a_fVal2; }
+
+ static value_type plus2(value_type v1) { return v1+2; }
+ static value_type times3(value_type v1) { return v1*3; }
+ static value_type sqr(value_type v1) { return v1*v1; }
+
+ static value_type sign(value_type v) { return -v; }
+
+ static value_type Sum(const value_type* a_afArg, int a_iArgc)
+ {
+ if (!a_iArgc)
+ throw mu::Parser::exception_type( _T("too few arguments for function sum.") );
+
+ value_type fRes=0;
+ for (int i=0; i<a_iArgc; ++i) fRes += a_afArg[i];
+ return fRes;
+ }
+
+ static value_type Rnd(value_type v)
+ {
+ return (value_type)(1+(v*std::rand()/(RAND_MAX+1.0)));
+ }
+
+ static value_type RndWithString(const char_type*)
+ {
+ return (value_type)( 1 + (1000.0f * std::rand() / (RAND_MAX + 1.0) ) );
+ }
+
+ static value_type ValueOf(const char_type*)
+ {
+ return 123;
+ }
+
+ static value_type StrFun1(const char_type* v1)
+ {
+ int val(0);
+ stringstream_type(v1) >> val;
+ return val;
+ }
+
+ static value_type StrFun2(const char_type* v1, value_type v2)
+ {
+ int val(0);
+ stringstream_type(v1) >> val;
+ return val + v2;
+ }
+
+ static value_type StrFun3(const char_type* v1, value_type v2, value_type v3)
+ {
+ int val(0);
+ stringstream_type(v1) >> val;
+ return val + v2 + v3;
+ }
+
+ static value_type StrToFloat(const char_type* a_szMsg)
+ {
+ double val(0);
+ stringstream_type(a_szMsg) >> val;
+ return val;
+
+// using namespace std; // atof is for some compilers in std for some not...
+// return atof(a_szMsg);
+ }
+
+ // postfix operator callback
+ static value_type Milli(value_type v) { return v/(value_type)1e3; }
+
+ static int c_iCount;
+
+ int TestNames();
+ int TestSyntax();
+ int TestMultiArg();
+ int TestVolatile();
+ int TestPostFix();
+ int TestFormula();
+ int TestInfixOprt();
+ int TestBinOprt();
+ int TestVarConst();
+ int TestInterface();
+ int TestException();
+ int TestStrArg();
+
+ void Abort() const;
+
+ public:
+ typedef int (ParserTester::*testfun_type)();
+
+ ParserTester();
+ void Run();
+
+ private:
+ std::vector<testfun_type> m_vTestFun;
+ void AddTest(testfun_type a_pFun);
+
+ // Test Double Parser
+ int EqnTest(const string_type& a_str, double a_fRes, bool a_fPass);
+ int ThrowTest(const string_type& a_str, int a_iErrc, bool a_bFail = true);
+
+ // Test Int Parser
+ int EqnTestInt(const string_type& a_str, double a_fRes, bool a_fPass);
+ };
+ } // namespace Test
+} // namespace mu
+
+#endif
+
+
diff --git a/muparser/muParserToken.h b/muparser/muParserToken.h
new file mode 100644
index 0000000..b4c7e54
--- /dev/null
+++ b/muparser/muParserToken.h
@@ -0,0 +1,464 @@
+/*
+ __________
+ _____ __ __\______ \_____ _______ ______ ____ _______
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
+ \/ \/ \/ \/
+ Copyright (C) 2004-2006 Ingo Berg
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ software and associated documentation files (the "Software"), to deal in the Software
+ without restriction, including without limitation the rights to use, copy, modify,
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef MU_PARSER_TOKEN_H
+#define MU_PARSER_TOKEN_H
+
+#include <cassert>
+#include <string>
+#include <stack>
+#include <vector>
+#include <memory>
+
+#include "muParserError.h"
+#include "muParserCallback.h"
+
+
+namespace mu
+{
+
+/** \brief Encapsulation of the data for a single formula token.
+
+ Formula token implementation. Part of the Math Parser Package.
+ Formula tokens can be either one of the following:
+ <ul>
+ <li>value</li>
+ <li>variable</li>
+ <li>function with numerical arguments</li>
+ <li>functions with a string as argument</li>
+ <li>prefix operators</li>
+ <li>infix operators</li>
+ <li>binary operator</li>
+ </ul>
+
+ \author (C) 2004 Ingo Berg
+*/
+template<typename TBase, typename TString>
+class ParserToken
+{
+public:
+ /** \brief Additional token flags. */
+ enum ETokFlags
+ {
+ flVOLATILE = 1 ///< Mark a token that depends on a variable or a function that is not conservative
+ };
+
+private:
+ ECmdCode m_iCode; ///< Type of the token; The token type is a constant of type #ECmdCode.
+ ETypeCode m_iType;
+ void *m_pTok; ///< Stores Token pointer; not applicable for all tokens
+ int m_iFlags; ///< Additional flags for the token.
+ int m_iIdx; ///< An otional index to an external buffer storing the token data
+ TString m_strTok; ///< Token string
+ TString m_strVal; ///< Value for string variables
+ value_type m_fVal;
+ std::auto_ptr<ParserCallback> m_pCallback;
+
+public:
+
+ //---------------------------------------------------------------------------
+ /** \brief Constructor (default).
+
+ Sets token to an neutral state of type cmUNKNOWN.
+ \throw nothrow
+ \sa ECmdCode
+ */
+ ParserToken()
+ :m_iCode(cmUNKNOWN)
+ ,m_iType(tpVOID)
+ ,m_pTok(0)
+ ,m_iFlags(0)
+ ,m_iIdx(-1)
+ ,m_strTok()
+ ,m_pCallback()
+ {}
+
+ //------------------------------------------------------------------------------
+ /** \brief Create token from another one.
+
+ Implemented by calling Assign(...)
+ \throw nothrow
+ \post m_iType==cmUNKNOWN
+ \sa #Assign
+ */
+ ParserToken(const ParserToken &a_Tok)
+ {
+ Assign(a_Tok);
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Assignement operator.
+
+ Copy token state from another token and return this.
+ Implemented by calling Assign(...).
+ \throw nothrow
+ */
+ ParserToken& operator=(const ParserToken &a_Tok)
+ {
+ Assign(a_Tok);
+ return *this;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Copy token information from argument.
+
+ \throw nothrow
+ */
+ void Assign(const ParserToken &a_Tok)
+ {
+ m_iCode = a_Tok.m_iCode;
+ m_pTok = a_Tok.m_pTok;
+ m_iFlags = a_Tok.m_iFlags;
+ m_strTok = a_Tok.m_strTok;
+ m_iIdx = a_Tok.m_iIdx;
+ m_strVal = a_Tok.m_strVal;
+ m_iType = a_Tok.m_iType;
+ m_fVal = a_Tok.m_fVal;
+ // create new callback object if a_Tok has one
+ m_pCallback.reset(a_Tok.m_pCallback.get() ? a_Tok.m_pCallback->Clone() : 0);
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Add additional flags to the token.
+
+ Flags are currently used to mark volatile (non optimizeable) functions.
+ \sa m_iFlags, ETokFlags
+ */
+ void AddFlags(int a_iFlags)
+ {
+ m_iFlags |= a_iFlags;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Check if a certain flag ist set.
+
+ \throw nothrow
+ */
+ bool IsFlagSet(int a_iFlags) const
+ {
+ #if defined(_MSC_VER)
+ #pragma warning( disable : 4800 )
+ #endif
+
+ return (bool)(m_iFlags & a_iFlags);
+
+ #if defined(_MSC_VER)
+ #pragma warning( default : 4800 ) // int: Variable set to boolean value (may degrade performance)
+ #endif
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Assign a token type.
+
+ Token may not be of type value, variable or function. Those have seperate set functions.
+
+ \pre [assert] a_iType!=cmVAR
+ \pre [assert] a_iType!=cmVAL
+ \pre [assert] a_iType!=cmFUNC
+ \post m_fVal = 0
+ \post m_pTok = 0
+ */
+ ParserToken& Set(ECmdCode a_iType, const TString &a_strTok=TString())
+ {
+ // The following types cant be set this way, they have special Set functions
+ assert(a_iType!=cmVAR);
+ assert(a_iType!=cmVAL);
+ assert(a_iType!=cmFUNC);
+
+ m_iCode = a_iType;
+ m_iType = tpVOID;
+ m_pTok = 0;
+ m_iFlags = 0;
+ m_strTok = a_strTok;
+ m_iIdx = -1;
+
+ return *this;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Set Callback type. */
+ ParserToken& Set(const ParserCallback &a_pCallback, const TString &a_sTok)
+ {
+ assert(a_pCallback.GetAddr());
+
+ m_iCode = a_pCallback.GetCode();
+ m_iType = tpVOID;
+ m_strTok = a_sTok;
+ m_pCallback.reset(new ParserCallback(a_pCallback));
+
+ m_pTok = 0;
+ m_iFlags = 0;
+ m_iIdx = -1;
+
+ if (!m_pCallback->IsOptimizable())
+ AddFlags(flVOLATILE);
+
+ return *this;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Make this token a value token.
+
+ Member variables not necessary for value tokens will be invalidated.
+ \throw nothrow
+ */
+ ParserToken& SetVal(TBase a_fVal, const TString &a_strTok=TString())
+ {
+ m_iCode = cmVAL;
+ m_iType = tpDBL;
+ m_fVal = a_fVal;
+ m_iFlags = 0;
+ m_strTok = a_strTok;
+ m_iIdx = -1;
+
+ m_pTok = 0;
+ m_pCallback.reset(0);
+
+ return *this;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief make this token a variable token.
+
+ Member variables not necessary for variable tokens will be invalidated.
+ \throw nothrow
+ */
+ ParserToken& SetVar(TBase *a_pVar, const TString &a_strTok)
+ {
+ m_iCode = cmVAR;
+ m_iType = tpDBL;
+ m_iFlags = 0;
+ m_strTok = a_strTok;
+ m_iIdx = -1;
+ m_pTok = (void*)a_pVar;
+ m_pCallback.reset(0);
+
+ AddFlags(ParserToken::flVOLATILE);
+ return *this;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Make this token a variable token.
+
+ Member variables not necessary for variable tokens will be invalidated.
+ \throw nothrow
+ */
+ ParserToken& SetString(const TString &a_strTok, std::size_t a_iSize)
+ {
+ m_iCode = cmSTRING; // cmSTRVAR;
+ m_iType = tpSTR;
+ m_iFlags = 0;
+ m_strTok = a_strTok;
+ m_iIdx = static_cast<int>(a_iSize);
+
+ m_pTok = 0;
+ m_pCallback.reset(0);
+
+ AddFlags(ParserToken::flVOLATILE);
+ return *this;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Make token a string token.
+
+ String tokens are used to store the value of string function arguments.
+ \param a_strTok the string content.
+ \post #m_iType==cmSTRING, #m_strTok==a_strTok
+ \throw nothrow
+ */
+ ParserToken& SetString(const string_type &a_strTok)
+ {
+ m_iCode = cmSTRING;
+ m_iType = tpSTR;
+ m_iFlags = 0;
+ m_iIdx = -1;
+
+ m_pTok = 0;
+ m_pCallback.reset(0);
+
+ m_strTok = a_strTok;
+
+ return *this;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Set an index associated with the token related data.
+
+ In cmSTRFUNC - This is the index to a string table in the main parser.
+ \param a_iIdx The index the string function result will take in the bytecode parser.
+ \throw exception_type if #a_iIdx<0 or #m_iType!=cmSTRING
+ */
+ void SetIdx(int a_iIdx)
+ {
+ if (m_iCode!=cmSTRING || a_iIdx<0)
+ throw ParserError(ecINTERNAL_ERROR);
+
+ m_iIdx = a_iIdx;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Return Index associated with the token related data.
+
+ In cmSTRFUNC - This is the index to a string table in the main parser.
+
+ \throw exception_type if #m_iIdx<0 or #m_iType!=cmSTRING
+ \return The index the result will take in the Bytecode calculatin array (#m_iIdx).
+ */
+ int GetIdx() const
+ {
+ if (m_iIdx<0 || m_iCode!=cmSTRING )
+ throw ParserError(ecINTERNAL_ERROR);
+
+ return m_iIdx;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Return the token type.
+
+ \return #m_iType
+ \throw nothrow
+ */
+ ECmdCode GetCode() const
+ {
+ if (m_pCallback.get())
+ {
+ return m_pCallback->GetCode();
+ }
+ else
+ {
+ return m_iCode;
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ ETypeCode GetType() const
+ {
+ if (m_pCallback.get())
+ {
+ return m_pCallback->GetType();
+ }
+ else
+ {
+ return m_iType;
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ int GetPri() const
+ {
+ if ( !m_pCallback.get())
+ throw ParserError(ecINTERNAL_ERROR);
+
+ if ( m_pCallback->GetCode()!=cmOPRT_BIN && m_pCallback->GetCode()!=cmOPRT_INFIX)
+ throw ParserError(ecINTERNAL_ERROR);
+
+ return m_pCallback->GetPri();
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Return the address of the callback function assoziated with
+ function and operator tokens.
+
+ \return The pointer stored in #m_pTok.
+ \throw exception_type if token type is non of:
+ <ul>
+ <li>cmFUNC</li>
+ <li>cmSTRFUNC</li>
+ <li>cmPOSTOP</li>
+ <li>cmINFIXOP</li>
+ <li>cmOPRT_BIN</li>
+ </ul>
+ \sa ECmdCode
+ */
+ void* GetFuncAddr() const
+ {
+ return (m_pCallback.get()) ? m_pCallback->GetAddr() : 0;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \biref Get value of the token.
+
+ Only applicable to variable and value tokens.
+ \throw exception_type if token is no value/variable token.
+ */
+ TBase GetVal() const
+ {
+ switch (m_iCode)
+ {
+ case cmVAL: return m_fVal;
+ case cmVAR: return *((TBase*)m_pTok);
+ default: throw ParserError(ecVAL_EXPECTED);
+ }
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Get address of a variable token.
+
+ Valid only if m_iType==CmdVar.
+ \throw exception_type if token is no variable token.
+ */
+ TBase* GetVar() const
+ {
+ if (m_iCode!=cmVAR)
+ throw ParserError(ecINTERNAL_ERROR);
+
+ return (TBase*)m_pTok;
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Return the number of function arguments.
+
+ Valid only if m_iType==CmdFUNC.
+ */
+ int GetArgCount() const
+ {
+ assert(m_pCallback.get());
+
+ if (!m_pCallback->GetAddr())
+ throw ParserError(ecINTERNAL_ERROR);
+
+ return m_pCallback->GetArgc();
+ }
+
+ //------------------------------------------------------------------------------
+ /** \brief Return the token identifier.
+
+ If #m_iType is cmSTRING the token identifier is the value of the string argument
+ for a string function.
+ \return #m_strTok
+ \throw nothrow
+ \sa m_strTok
+ */
+ const TString& GetAsString() const
+ {
+ return m_strTok;
+ }
+};
+
+} // namespace mu
+
+#endif
+
+
diff --git a/muparser/muParserTokenReader.cpp b/muparser/muParserTokenReader.cpp
new file mode 100644
index 0000000..99c0a0a
--- /dev/null
+++ b/muparser/muParserTokenReader.cpp
@@ -0,0 +1,822 @@
+/*
+ __________
+ _____ __ __\______ \_____ _______ ______ ____ _______
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
+ \/ \/ \/ \/
+ Copyright (C) 2004-2006 Ingo Berg
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ software and associated documentation files (the "Software"), to deal in the Software
+ without restriction, including without limitation the rights to use, copy, modify,
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <cassert>
+#include <cstdio>
+#include <cstring>
+#include <map>
+#include <stack>
+#include <string>
+
+#include "muParserTokenReader.h"
+#include "muParserBase.h"
+
+
+namespace mu
+{
+
+ // Forward declaration
+ class ParserBase;
+
+ //---------------------------------------------------------------------------
+ /** \brief Copy constructor.
+
+ \sa Assign
+ \throw nothrow
+ */
+ ParserTokenReader::ParserTokenReader(const ParserTokenReader &a_Reader)
+ {
+ Assign(a_Reader);
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Assignement operator.
+
+ Self assignement will be suppressed otherwise #Assign is called.
+
+ \param a_Reader Object to copy to this token reader.
+ \throw nothrow
+ */
+ ParserTokenReader& ParserTokenReader::operator=(const ParserTokenReader &a_Reader)
+ {
+ if (&a_Reader!=this)
+ Assign(a_Reader);
+
+ return *this;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Assign state of a token reader to this token reader.
+
+ \param a_Reader Object from which the state should be copied.
+ \throw nothrow
+ */
+ void ParserTokenReader::Assign(const ParserTokenReader &a_Reader)
+ {
+ m_pParser = a_Reader.m_pParser;
+ m_strFormula = a_Reader.m_strFormula;
+ m_iPos = a_Reader.m_iPos;
+ m_iSynFlags = a_Reader.m_iSynFlags;
+
+ m_UsedVar = a_Reader.m_UsedVar;
+ m_pFunDef = a_Reader.m_pFunDef;
+ m_pConstDef = a_Reader.m_pConstDef;
+ m_pVarDef = a_Reader.m_pVarDef;
+ m_pStrVarDef = a_Reader.m_pStrVarDef;
+ m_pPostOprtDef = a_Reader.m_pPostOprtDef;
+ m_pInfixOprtDef = a_Reader.m_pInfixOprtDef;
+ m_pOprtDef = a_Reader.m_pOprtDef;
+ m_bIgnoreUndefVar = a_Reader.m_bIgnoreUndefVar;
+ m_vIdentFun = a_Reader.m_vIdentFun;
+ m_pFactory = a_Reader.m_pFactory;
+ m_pFactoryData = a_Reader.m_pFactoryData;
+ m_iBrackets = a_Reader.m_iBrackets;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Constructor.
+
+ Create a Token reader and bind it to a parser object.
+
+ \pre [assert] a_pParser may not be NULL
+ \post #m_pParser==a_pParser
+ \param a_pParent Parent parser object of the token reader.
+ */
+ ParserTokenReader::ParserTokenReader(ParserBase *a_pParent)
+ :m_pParser(a_pParent)
+ ,m_strFormula()
+ ,m_iPos(0)
+ ,m_iSynFlags(0)
+ ,m_bIgnoreUndefVar(false)
+ ,m_pFunDef(NULL)
+ ,m_pPostOprtDef(NULL)
+ ,m_pInfixOprtDef(NULL)
+ ,m_pOprtDef(NULL)
+ ,m_pConstDef(NULL)
+ ,m_pStrVarDef(NULL)
+ ,m_pVarDef(NULL)
+ ,m_pFactory(NULL)
+ ,m_pFactoryData(NULL)
+ ,m_vIdentFun()
+ ,m_UsedVar()
+ ,m_fZero(0)
+ ,m_iBrackets(0)
+ {
+ assert(m_pParser);
+ SetParent(m_pParser);
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Destructor (trivial).
+
+ \throw nothrow
+ */
+ ParserTokenReader::~ParserTokenReader()
+ {}
+
+ //---------------------------------------------------------------------------
+ /** \brief Create instance of a ParserTokenReader identical with this
+ and return its pointer.
+
+ This is a factory method the calling function must take care of the object destruction.
+
+ \return A new ParserTokenReader object.
+ \throw nothrow
+ */
+ ParserTokenReader* ParserTokenReader::Clone(ParserBase *a_pParent) const
+ {
+ std::auto_ptr<ParserTokenReader> ptr(new ParserTokenReader(*this));
+ ptr->SetParent(a_pParent);
+ return ptr.release();
+ }
+
+ //---------------------------------------------------------------------------
+ void ParserTokenReader::AddValIdent(identfun_type a_pCallback)
+ {
+ m_vIdentFun.push_back(a_pCallback);
+ }
+
+ //---------------------------------------------------------------------------
+ void ParserTokenReader::SetVarCreator(facfun_type a_pFactory, void *pUserData)
+ {
+ m_pFactory = a_pFactory;
+ m_pFactoryData = pUserData;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Return the current position of the token reader in the formula string.
+
+ \return #m_iPos
+ \throw nothrow
+ */
+ int ParserTokenReader::GetPos() const
+ {
+ return m_iPos;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Return a reference to the formula.
+
+ \return #m_strFormula
+ \throw nothrow
+ */
+ const string_type& ParserTokenReader::GetFormula() const
+ {
+ return m_strFormula;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Return a map containing the used variables only. */
+ const varmap_type& ParserTokenReader::GetUsedVar() const
+ {
+ return m_UsedVar;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Initialize the token Reader.
+
+ Sets the formula position index to zero and set Syntax flags to default for initial formula parsing.
+ \pre [assert] triggered if a_szFormula==0
+ */
+ void ParserTokenReader::SetFormula(const string_type &a_strFormula)
+ {
+ m_strFormula = a_strFormula;
+ ReInit();
+ }
+
+ //---------------------------------------------------------------------------
+ void ParserTokenReader::SetDefs( const funmap_type *a_pFunDef,
+ const funmap_type *a_pOprtDef,
+ const funmap_type *a_pInfixOprtDef,
+ const funmap_type *a_pPostOprtDef,
+ varmap_type *a_pVarDef,
+ const strmap_type *a_pStrVarDef,
+ const valmap_type *a_pConstDef )
+ {
+ m_pFunDef = a_pFunDef;
+ m_pOprtDef = a_pOprtDef;
+ m_pInfixOprtDef = a_pInfixOprtDef;
+ m_pPostOprtDef = a_pPostOprtDef;
+ m_pVarDef = a_pVarDef;
+ m_pStrVarDef = a_pStrVarDef;
+ m_pConstDef = a_pConstDef;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Set Flag that contronls behaviour in case of undefined variables beeing found.
+
+ If true, the parser does not throw an exception if an undefined variable is found.
+ otherwise it does. This variable is used internally only!
+ It supresses a "undefined variable" exception in GetUsedVar().
+ Those function should return a complete list of variables including
+ those the are not defined by the time of it's call.
+ */
+ void ParserTokenReader::IgnoreUndefVar(bool bIgnore)
+ {
+ m_bIgnoreUndefVar = bIgnore;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Reset the token reader to the start of the formula.
+
+ The syntax flags will be reset to a value appropriate for the
+ start of a formula.
+ \post #m_iPos==0, #m_iSynFlags = noOPT | noBC | noPOSTOP | noSTR
+ \throw nothrow
+ \sa ESynCodes
+ */
+ void ParserTokenReader::ReInit()
+ {
+ m_iPos = 0;
+ m_iSynFlags = noOPT | noBC | noPOSTOP | noASSIGN;
+ m_iBrackets = 0;
+ m_UsedVar.clear();
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Read the next token from the string. */
+ ParserTokenReader::token_type ParserTokenReader::ReadNextToken()
+ {
+ assert(m_pParser);
+
+ std::stack<int> FunArgs;
+ const char_type *szFormula = m_strFormula.c_str();
+ token_type tok;
+
+ while (szFormula[m_iPos]==' ')
+ ++m_iPos;
+
+ if ( IsEOF(tok) ) return tok; // Check for end of formula
+ if ( IsOprt(tok) ) return tok; // Check for user defined binary operator
+ if ( IsBuiltIn(tok) ) return tok; // Check built in operators / tokens
+ if ( IsFunTok(tok) ) return tok; // Check for function token
+ if ( IsValTok(tok) ) return tok; // Check for values / constant tokens
+ if ( IsVarTok(tok) ) return tok; // Check for variable tokens
+ if ( IsStrVarTok(tok) ) return tok; // Check for string variables
+ if ( IsString(tok) ) return tok; // Check for String tokens
+ if ( IsInfixOpTok(tok) ) return tok; // Check for unary operators
+ if ( IsPostOpTok(tok) ) return tok; // Check for unary operators
+
+ // Check String for undefined variable token. Done only if a
+ // flag is set indicating to ignore undefined variables.
+ // This is a way to conditionally avoid an error if
+ // undefined variables occur.
+ // The GetUsedVar function must supress the error for
+ // undefined variables in order to collect all variable
+ // names including the undefined ones.
+ if ( (m_bIgnoreUndefVar || m_pFactory) && IsUndefVarTok(tok) ) return tok;
+
+ // Check for unknown token
+ //
+ // !!! From this point on there is no exit without an exception possible...
+ //
+ string_type strTok;
+ int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
+ if (iEnd!=m_iPos)
+ Error(ecUNASSIGNABLE_TOKEN, m_iPos, strTok);
+
+ Error(ecUNASSIGNABLE_TOKEN, m_iPos, m_strFormula.substr(m_iPos));
+ return token_type(); // never reached
+ }
+
+ //---------------------------------------------------------------------------
+ void ParserTokenReader::SetParent(ParserBase *a_pParent)
+ {
+ m_pParser = a_pParent;
+ m_pFunDef = &a_pParent->m_FunDef;
+ m_pOprtDef = &a_pParent->m_OprtDef;
+ m_pInfixOprtDef = &a_pParent->m_InfixOprtDef;
+ m_pPostOprtDef = &a_pParent->m_PostOprtDef;
+ m_pVarDef = &a_pParent->m_VarDef;
+ m_pStrVarDef = &a_pParent->m_StrVarDef;
+ m_pConstDef = &a_pParent->m_ConstDef;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Extract all characters that belong to a certain charset.
+
+ \param a_szCharSet [in] Const char array of the characters allowed in the token.
+ \param a_strTok [out] The string that consists entirely of characters listed in a_szCharSet.
+ \param a_iPos [in] Position in the string from where to start reading.
+ \return The Position of the first character not listed in a_szCharSet.
+ \throw nothrow
+ */
+ int ParserTokenReader::ExtractToken( const char_type *a_szCharSet,
+ string_type &a_sTok, int a_iPos ) const
+ {
+ int iEnd = (int)m_strFormula.find_first_not_of(a_szCharSet, a_iPos);
+
+ if (iEnd==(int)string_type::npos)
+ iEnd = (int)m_strFormula.length();
+
+ a_sTok = string_type( m_strFormula.begin()+a_iPos, m_strFormula.begin()+iEnd);
+ a_iPos = iEnd;
+ return iEnd;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Check if a built in operator or other token can be found
+ \param a_Tok [out] Operator token if one is found. This can either be a binary operator or an infix operator token.
+ \return true if an operator token has been found.
+ */
+ bool ParserTokenReader::IsBuiltIn(token_type &a_Tok)
+ {
+ const char_type **pOprtDef = m_pParser->GetOprtDef();
+ const char_type* szFormula = m_strFormula.c_str();
+
+ // Compare token with function and operator strings
+ // check string for operator/function
+ for (int i=0; pOprtDef[i]; i++)
+ {
+#if !defined _UNICODE
+ std::size_t len = std::strlen( pOprtDef[i] );
+ if ( !std::strncmp(&szFormula[m_iPos], pOprtDef[i], len) )
+#else
+ // this would work for both UNICODE and char but it's so god damn ugly!!
+ // apart from this this cant be fast
+ std::size_t len( std::char_traits<char_type>::length(pOprtDef[i]) );
+ if ( string_type(pOprtDef[i]) == string_type(szFormula + m_iPos, szFormula + m_iPos + len) )
+#endif
+ {
+ switch(i)
+ {
+ case cmAND:
+ case cmOR:
+ case cmXOR:
+ case cmLT:
+ case cmGT:
+ case cmLE:
+ case cmGE:
+ case cmNEQ:
+ case cmEQ:
+ case cmADD:
+ case cmSUB:
+ case cmMUL:
+ case cmDIV:
+ case cmPOW:
+ case cmASSIGN:
+ // The assignement operator need special treatment
+ if (i==cmASSIGN && m_iSynFlags & noASSIGN)
+ Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]);
+
+ if (!m_pParser->HasBuiltInOprt()) continue;
+ if (m_iSynFlags & noOPT)
+ {
+ // Maybe its an infix operator not an operator
+ // Both operator types can share characters in
+ // their identifiers
+ if ( IsInfixOpTok(a_Tok) )
+ return true;
+
+ Error(ecUNEXPECTED_OPERATOR, m_iPos, pOprtDef[i]);
+ }
+
+ m_iSynFlags = noBC | noOPT | noCOMMA | noPOSTOP | noASSIGN;
+ m_iSynFlags |= ( (i != cmEND) && ( i != cmBC) ) ? noEND : 0;
+ break;
+
+ case cmCOMMA:
+ if (m_iSynFlags & noCOMMA)
+ Error(ecUNEXPECTED_COMMA, m_iPos, pOprtDef[i]);
+
+ m_iSynFlags = noBC | noOPT | noEND | noCOMMA | noPOSTOP | noASSIGN;
+ break;
+
+ case cmBO:
+ if (m_iSynFlags & noBO)
+ Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
+
+ m_iSynFlags = noBC | noOPT | noEND | noCOMMA | noPOSTOP | noASSIGN;
+ ++m_iBrackets;
+ break;
+
+ case cmBC:
+ if (m_iSynFlags & noBC)
+ Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
+
+ m_iSynFlags = noBO | noVAR | noVAL | noFUN | noINFIXOP | noSTR | noASSIGN;
+
+ if (--m_iBrackets<0)
+ Error(ecUNEXPECTED_PARENS, m_iPos, pOprtDef[i]);
+ break;
+
+ default: // The operator is listed in c_DefaultOprt, but not here. This is a bad thing...
+ Error(ecINTERNAL_ERROR);
+ } // switch operator id
+
+ m_iPos += (int)len;
+ a_Tok.Set( (ECmdCode)i, pOprtDef[i] );
+ return true;
+ } // if operator string found
+ } // end of for all operator strings
+
+ return false;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Check for End of Formula.
+
+ \return true if an end of formula is found false otherwise.
+ \param a_Tok [out] If an eof is found the corresponding token will be stored there.
+ \throw nothrow
+ \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsString, IsInfixOpTok, IsPostOpTok
+ */
+ bool ParserTokenReader::IsEOF(token_type &a_Tok)
+ {
+ const char_type* szFormula = m_strFormula.c_str();
+
+ // check for EOF
+ if ( !szFormula[m_iPos] || szFormula[m_iPos] == '\n')
+ {
+ if ( m_iSynFlags & noEND )
+ Error(ecUNEXPECTED_EOF, m_iPos);
+
+ if (m_iBrackets>0)
+ Error(ecMISSING_PARENS, m_iPos, _T(")"));
+
+ m_iSynFlags = 0;
+ a_Tok.Set(cmEND);
+ return true;
+ }
+
+ return false;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Check if a string position contains a unary infix operator.
+ \return true if a function token has been found false otherwise.
+ */
+ bool ParserTokenReader::IsInfixOpTok(token_type &a_Tok)
+ {
+ string_type sTok;
+ int iEnd = ExtractToken(m_pParser->ValidInfixOprtChars(), sTok, m_iPos);
+ if (iEnd==m_iPos)
+ return false;
+
+ funmap_type::const_iterator item = m_pInfixOprtDef->find(sTok);
+ if (item==m_pInfixOprtDef->end())
+ return false;
+
+ a_Tok.Set(item->second, sTok);
+ m_iPos = (int)iEnd;
+
+ if (m_iSynFlags & noINFIXOP)
+ Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString());
+
+ m_iSynFlags = noPOSTOP | noINFIXOP | noOPT | noBC | noSTR | noASSIGN;
+ return true;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Check whether the token at a given position is a function token.
+ \param a_Tok [out] If a value token is found it will be placed here.
+ \throw ParserException if Syntaxflags do not allow a function at a_iPos
+ \return true if a function token has been found false otherwise.
+ \pre [assert] m_pParser!=0
+ */
+ bool ParserTokenReader::IsFunTok(token_type &a_Tok)
+ {
+ string_type strTok;
+ int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
+ if (iEnd==m_iPos)
+ return false;
+
+ funmap_type::const_iterator item = m_pFunDef->find(strTok);
+ if (item==m_pFunDef->end())
+ return false;
+
+ a_Tok.Set(item->second, strTok);
+
+ m_iPos = (int)iEnd;
+ if (m_iSynFlags & noFUN)
+ Error(ecUNEXPECTED_FUN, m_iPos-(int)a_Tok.GetAsString().length(), a_Tok.GetAsString());
+
+ m_iSynFlags = noANY ^ noBO;
+ return true;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Check if a string position contains a binary operator.
+ \param a_Tok [out] Operator token if one is found. This can either be a binary operator or an infix operator token.
+ \return true if an operator token has been found.
+ */
+ bool ParserTokenReader::IsOprt(token_type &a_Tok)
+ {
+ string_type strTok;
+ int iEnd = ExtractToken(m_pParser->ValidOprtChars(), strTok, m_iPos);
+ if (iEnd==m_iPos)
+ return false;
+
+ funmap_type::const_iterator item = m_pOprtDef->find(strTok);
+ if (item==m_pOprtDef->end())
+ return false;
+
+ a_Tok.Set(item->second, strTok);
+
+ if (m_iSynFlags & noOPT)
+ {
+ // An operator was found but is not expected to occur at
+ // this position of the formula, maybe it is an infix
+ // operator, not a binary operator. Both operator types
+ // can share characters in their identifiers.
+ if ( IsInfixOpTok(a_Tok) ) return true;
+ // nope, no infix operator
+ Error(ecUNEXPECTED_OPERATOR, m_iPos, a_Tok.GetAsString());
+ }
+
+ m_iPos = (int)iEnd;
+ m_iSynFlags = noBC | noOPT | noCOMMA | noPOSTOP | noEND | noBC | noASSIGN;
+ return true;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Check if a string position contains a unary post value operator. */
+ bool ParserTokenReader::IsPostOpTok(token_type &a_Tok)
+ {
+ // Tricky problem with equations like "3m+5":
+ // m is a postfix operator, + is a valid sign for postfix operators and
+ // for binary operators parser detects "m+" as operator string and
+ // finds no matching postfix operator.
+ //
+ // This is a special case so this routine slightly differs from the other
+ // token readers.
+
+ // Test if there could be a postfix operator
+ string_type sTok;
+ int iEnd = ExtractToken(m_pParser->ValidOprtChars(), sTok, m_iPos);
+ if (iEnd==m_iPos)
+ return false;
+
+ // iteraterate over all postfix operator strings
+ funmap_type::const_iterator item = m_pPostOprtDef->begin();
+ for (item=m_pPostOprtDef->begin(); item!=m_pPostOprtDef->end(); ++item)
+ {
+ if (sTok.find(item->first)!=0)
+ continue;
+
+ a_Tok.Set(item->second, sTok);
+ m_iPos += (int)item->first.length();
+
+ if (m_iSynFlags & noPOSTOP)
+ Error(ecUNEXPECTED_OPERATOR, m_iPos-(int)item->first.length(), item->first);
+
+ m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noSTR | noASSIGN;
+ return true;
+ }
+
+ return false;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Check whether the token at a given position is a value token.
+
+ Value tokens are either values or constants.
+
+ \param a_Tok [out] If a value token is found it will be placed here.
+ \return true if a value token has been found.
+ */
+ bool ParserTokenReader::IsValTok(token_type &a_Tok)
+ {
+ assert(m_pConstDef);
+ assert(m_pParser);
+
+ #if defined(_MSC_VER)
+ #pragma warning( disable : 4244 )
+ #endif
+
+ string_type strTok;
+ value_type fVal(0);
+ int iEnd(0);
+
+ // 2.) Check for user defined constant
+ // Read everything that could be a constant name
+ iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
+ if (iEnd!=m_iPos)
+ {
+ valmap_type::const_iterator item = m_pConstDef->find(strTok);
+ if (item!=m_pConstDef->end())
+ {
+ m_iPos = iEnd;
+ a_Tok.SetVal(item->second, strTok);
+
+ if (m_iSynFlags & noVAL)
+ Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok);
+
+ m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN;
+ return true;
+ }
+ }
+
+ // 3.call the value recognition functions provided by the user
+ // Call user defined value recognition functions
+ std::vector<identfun_type>::const_iterator item = m_vIdentFun.begin();
+ for (item = m_vIdentFun.begin(); item!=m_vIdentFun.end(); ++item)
+ {
+ int iStart = m_iPos;
+ if ( (*item)(m_strFormula.c_str() + m_iPos, m_iPos, fVal) )
+ {
+ strTok.assign(m_strFormula.c_str(), iStart, m_iPos);
+ if (m_iSynFlags & noVAL)
+ Error(ecUNEXPECTED_VAL, m_iPos - (int)strTok.length(), strTok);
+
+ a_Tok.SetVal(fVal, strTok);
+ m_iSynFlags = noVAL | noVAR | noFUN | noBO | noINFIXOP | noSTR | noASSIGN;
+ return true;
+ }
+ }
+
+ return false;
+
+ #if defined(_MSC_VER)
+ #pragma warning( default : 4244 )
+ #endif
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Check wheter a token at a given position is a variable token.
+ \param a_Tok [out] If a variable token has been found it will be placed here.
+ \return true if a variable token has been found.
+ */
+ bool ParserTokenReader::IsVarTok(token_type &a_Tok)
+ {
+ if (!m_pVarDef->size())
+ return false;
+
+ string_type strTok;
+ int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
+ if (iEnd==m_iPos)
+ return false;
+
+ varmap_type::const_iterator item = m_pVarDef->find(strTok);
+ if (item==m_pVarDef->end())
+ return false;
+
+ if (m_iSynFlags & noVAR)
+ Error(ecUNEXPECTED_VAR, m_iPos, strTok);
+
+ m_iPos = iEnd;
+ a_Tok.SetVar(item->second, strTok);
+ m_UsedVar[item->first] = item->second; // Add variable to used-var-list
+
+ m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noINFIXOP | noSTR;
+ return true;
+ }
+
+ //---------------------------------------------------------------------------
+ bool ParserTokenReader::IsStrVarTok(token_type &a_Tok)
+ {
+ if (!m_pStrVarDef || !m_pStrVarDef->size())
+ return false;
+
+ string_type strTok;
+ int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
+ if (iEnd==m_iPos)
+ return false;
+
+ strmap_type::const_iterator item = m_pStrVarDef->find(strTok);
+ if (item==m_pStrVarDef->end())
+ return false;
+
+ if (m_iSynFlags & noSTR)
+ Error(ecUNEXPECTED_VAR, m_iPos, strTok);
+
+ m_iPos = iEnd;
+ if (!m_pParser->m_vStringVarBuf.size())
+ Error(ecINTERNAL_ERROR);
+
+ a_Tok.SetString(m_pParser->m_vStringVarBuf[item->second], m_pParser->m_vStringVarBuf.size() );
+
+ m_iSynFlags = m_iSynFlags = noANY ^ ( noBC | noOPT | noEND | noCOMMA);
+ return true;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Check wheter a token at a given position is an undefined variable.
+
+ \param a_Tok [out] If a variable tom_pParser->m_vStringBufken has been found it will be placed here.
+ \return true if a variable token has been found.
+ \throw nothrow
+ */
+ bool ParserTokenReader::IsUndefVarTok(token_type &a_Tok)
+ {
+ string_type strTok;
+ int iEnd = ExtractToken(m_pParser->ValidNameChars(), strTok, m_iPos);
+ if (iEnd==m_iPos)
+ return false;
+
+ if (m_iSynFlags & noVAR)
+ {
+ // <ibg/> 20061021 added token string strTok instead of a_Tok.GetAsString() as the
+ // token identifier.
+ Error(ecUNEXPECTED_VAR, m_iPos - (int)a_Tok.GetAsString().length(), strTok);
+ }
+
+ // If a factory is available implicitely create new variables
+ if (m_pFactory)
+ {
+ value_type *fVar = m_pFactory(strTok.c_str(), m_pFactoryData);
+ a_Tok.SetVar(fVar, strTok );
+
+ // Do not use m_pParser->DefineVar( strTok, fVar );
+ // in order to define the new variable, it will clear the
+ // m_UsedVar array which will kill previousely defined variables
+ // from the list
+ // This is safe because the new variable can never override an existing one
+ // because they are checked first!
+ (*m_pVarDef)[strTok] = fVar;
+ m_UsedVar[strTok] = fVar; // Add variable to used-var-list
+ }
+ else
+ {
+ a_Tok.SetVar((value_type*)&m_fZero, strTok);
+ m_UsedVar[strTok] = 0; // Add variable to used-var-list
+ }
+
+ m_iPos = iEnd;
+
+ // Call the variable factory in order to let it define a new parser variable
+ m_iSynFlags = noVAL | noVAR | noFUN | noBO | noPOSTOP | noINFIXOP | noSTR;
+ return true;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Check wheter a token at a given position is a string.
+
+ \param a_Tok [out] If a variable token has been found it will be placed here.
+ \return true if a string token has been found.
+ \sa IsOprt, IsFunTok, IsStrFunTok, IsValTok, IsVarTok, IsEOF, IsInfixOpTok, IsPostOpTok
+ \throw nothrow
+ */
+ bool ParserTokenReader::IsString(token_type &a_Tok)
+ {
+ if (m_strFormula[m_iPos]!='"')
+ return false;
+
+ string_type strBuf(&m_strFormula[m_iPos+1]);
+ std::size_t iEnd(0), iSkip(0);
+
+ // parser over escaped '\"' end replace them with '"'
+ for(iEnd=(int)strBuf.find( _T("\"") ); iEnd!=string_type::npos; iEnd=(int)strBuf.find( _T("\""), iEnd))
+ {
+ if (strBuf[iEnd-1]!='\\') break;
+ strBuf.replace(iEnd-1, 2, _T("\"") );
+ iSkip++;
+ }
+
+ if (iEnd==string_type::npos)
+ Error(ecUNTERMINATED_STRING, m_iPos, _T("\"") );
+
+ string_type strTok(strBuf.begin(), strBuf.begin()+iEnd);
+
+ if (m_iSynFlags & noSTR)
+ Error(ecUNEXPECTED_STR, m_iPos, strTok);
+
+ m_pParser->m_vStringBuf.push_back(strTok); // Store string in internal buffer
+ a_Tok.SetString(strTok, m_pParser->m_vStringBuf.size());
+
+ m_iPos += (int)strTok.length() + 2 + (int)iSkip; // +2 wg Anführungszeichen; +iSkip für entfernte escape zeichen
+ m_iSynFlags = m_iSynFlags = noANY ^ ( noCOMMA | noBC | noOPT | noEND );
+
+ return true;
+ }
+
+ //---------------------------------------------------------------------------
+ /** \brief Create an error containing the parse error position.
+
+ This function will create an Parser Exception object containing the error text and its position.
+
+ \param a_iErrc [in] The error code of type #EErrorCodes.
+ \param a_iPos [in] The position where the error was detected.
+ \param a_strTok [in] The token string representation associated with the error.
+ \throw ParserException always throws thats the only purpose of this function.
+ */
+ void ParserTokenReader::Error( EErrorCodes a_iErrc,
+ int a_iPos,
+ const string_type &a_sTok) const
+ {
+ m_pParser->Error(a_iErrc, a_iPos, a_sTok);
+ }
+} // namespace mu
+
diff --git a/muparser/muParserTokenReader.h b/muparser/muParserTokenReader.h
new file mode 100644
index 0000000..122586e
--- /dev/null
+++ b/muparser/muParserTokenReader.h
@@ -0,0 +1,156 @@
+/*
+ __________
+ _____ __ __\______ \_____ _______ ______ ____ _______
+ / \ | | \| ___/\__ \ \_ __ \/ ___/_/ __ \\_ __ \
+ | Y Y \| | /| | / __ \_| | \/\___ \ \ ___/ | | \/
+ |__|_| /|____/ |____| (____ /|__| /____ > \___ >|__|
+ \/ \/ \/ \/
+ Copyright (C) 2004-2006 Ingo Berg
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ software and associated documentation files (the "Software"), to deal in the Software
+ without restriction, including without limitation the rights to use, copy, modify,
+ merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all copies or
+ substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#ifndef MU_PARSER_TOKEN_READER_H
+#define MU_PARSER_TOKEN_READER_H
+
+#include <cassert>
+#include <cstdio>
+#include <cstring>
+#include <map>
+#include <memory>
+#include <stack>
+#include <string>
+
+#include "muParserDef.h"
+#include "muParserToken.h"
+
+
+namespace mu
+{
+
+ // Forward declaration
+ class ParserBase;
+
+ /** \brief Token reader for the ParserBase class.
+
+ */
+ class ParserTokenReader
+ {
+ private:
+ typedef ParserToken<value_type, string_type> token_type;
+
+ private:
+ ParserBase *m_pParser;
+ string_type m_strFormula;
+ int m_iPos;
+ int m_iSynFlags;
+ bool m_bIgnoreUndefVar;
+
+ const funmap_type *m_pFunDef;
+ const funmap_type *m_pPostOprtDef;
+ const funmap_type *m_pInfixOprtDef;
+ const funmap_type *m_pOprtDef;
+ const valmap_type *m_pConstDef;
+ const strmap_type *m_pStrVarDef;
+ varmap_type *m_pVarDef; ///< The only non const pointer to parser internals
+ facfun_type m_pFactory;
+ void *m_pFactoryData;
+ std::vector<identfun_type> m_vIdentFun; ///< Value token identification function
+ varmap_type m_UsedVar;
+ value_type m_fZero; ///< Dummy value of zero, referenced by undefined variables
+ int m_iBrackets;
+
+ //
+ // private Functions
+ //
+ private:
+
+ /** \brief Syntax codes.
+
+ The syntax codes control the syntax check done during the first time parsing of
+ the expression string. They are flags that indicate which tokens are allowed next
+ if certain tokens are identified.
+ */
+ enum ESynCodes
+ {
+ noBO = 1 << 0, ///< to avoid i.e. "cos(7)("
+ noBC = 1 << 1, ///< to avoid i.e. "sin)" or "()"
+ noVAL = 1 << 2, ///< to avoid i.e. "tan 2" or "sin(8)3.14"
+ noVAR = 1 << 3, ///< to avoid i.e. "sin a" or "sin(8)a"
+ noCOMMA = 1 << 4, ///< to avoid i.e. ",," or "+," ...
+ noFUN = 1 << 5, ///< to avoid i.e. "sqrt cos" or "(1)sin"
+ noOPT = 1 << 6, ///< to avoid i.e. "(+)"
+ noPOSTOP = 1 << 7, ///< to avoid i.e. "(5!!)" "sin!"
+ noINFIXOP = 1 << 8, ///< to avoid i.e. "++4" "!!4"
+ noEND = 1 << 9, ///< to avoid unexpected end of formula
+ noSTR = 1 << 10, ///< to block numeric arguments on string functions
+ noASSIGN = 1 << 11, ///< to block assignement to constant i.e. "4=7"
+ noANY = ~0 ///< All of he above flags set
+ };
+
+ ParserTokenReader(const ParserTokenReader &a_Reader);
+ ParserTokenReader& operator=(const ParserTokenReader &a_Reader);
+ void Assign(const ParserTokenReader &a_Reader);
+
+ public:
+ ParserTokenReader(ParserBase *a_pParent);
+ ~ParserTokenReader();
+ ParserTokenReader* Clone(ParserBase *a_pParent) const;
+
+ void AddValIdent(identfun_type a_pCallback);
+ void SetVarCreator(facfun_type a_pFactory, void *pUserData);
+ int GetPos() const;
+ const string_type& GetFormula() const;
+ const varmap_type& GetUsedVar() const;
+ void SetFormula(const string_type &a_strFormula);
+ void SetDefs( const funmap_type *a_pFunDef,
+ const funmap_type *a_pOprtDef,
+ const funmap_type *a_pInfixOprtDef,
+ const funmap_type *a_pPostOprtDef,
+ varmap_type *a_pVarDef,
+ const strmap_type *a_pStrVarDef,
+ const valmap_type *a_pConstDef );
+ void IgnoreUndefVar(bool bIgnore);
+ void ReInit();
+ token_type ReadNextToken();
+
+ //
+ // private functions
+ //
+ private:
+
+ void SetParent(ParserBase *a_pParent);
+ int ExtractToken( const char_type *a_szCharSet,
+ string_type &a_strTok, int a_iPos ) const;
+ bool IsBuiltIn(token_type &a_Tok);
+ bool IsEOF(token_type &a_Tok);
+ bool IsInfixOpTok(token_type &a_Tok);
+ bool IsFunTok(token_type &a_Tok);
+ bool IsPostOpTok(token_type &a_Tok);
+ bool IsOprt(token_type &a_Tok);
+ bool IsValTok(token_type &a_Tok);
+ bool IsVarTok(token_type &a_Tok);
+ bool IsStrVarTok(token_type &a_Tok);
+ bool IsUndefVarTok(token_type &a_Tok);
+ bool IsString(token_type &a_Tok);
+ void Error( EErrorCodes a_iErrc, int a_iPos = -1,
+ const string_type &a_sTok = string_type() ) const;
+ };
+} // namespace mu
+
+#endif
+
+
diff --git a/run_me b/run_me
new file mode 100755
index 0000000..a920e69
--- /dev/null
+++ b/run_me
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+echo "To run the program: type ./optcli"
+echo "To re-build the program, type: make clean;make"
+
diff --git a/samples/a b/samples/a
new file mode 100755
index 0000000..b8b8e8c
--- /dev/null
+++ b/samples/a
Binary files differ
diff --git a/samples/a.cc b/samples/a.cc
new file mode 100644
index 0000000..1cf92df
--- /dev/null
+++ b/samples/a.cc
@@ -0,0 +1,36 @@
+#include <cmath>
+#include <fstream>
+#include <iostream>
+using namespace std;
+
+double powerlaw(double x)
+{
+ return 5*pow(x,-1.1);
+}
+
+double bpl(double x)
+{
+ double x_b=5;
+ double f_b=10;
+ double gamma1=-0.8;
+ double gamma2=-1.5;
+ if(x<x_b)
+ {
+ return f_b*pow(x,gamma1)/pow(x_b,gamma1);
+ }
+ else
+ {
+ return f_b*pow(x,gamma2)/pow(x_b,gamma2);
+ }
+}
+
+
+
+int main()
+{
+ double x,y,x1,x2,y1,y2;
+ while(cin>>x>>x1>>x2>>y>>y1>>y2)
+ {
+ cout<<x<<"\t"<<y<<"\t"<<y-y1<<"\t"<<y+y2<<endl;
+ }
+}
diff --git a/samples/a.dat b/samples/a.dat
new file mode 100644
index 0000000..8ca360f
--- /dev/null
+++ b/samples/a.dat
@@ -0,0 +1,4 @@
+0 4 3 5
+1 7 6 8
+2 10 9 11
+3 13 12 14
diff --git a/samples/bpl.dat b/samples/bpl.dat
new file mode 100644
index 0000000..f7e9490
--- /dev/null
+++ b/samples/bpl.dat
@@ -0,0 +1,901 @@
+1 0 0 36.239 .01 .01
+1.01 0 0 35.9517 .01 .01
+1.02 0 0 35.6694 .01 .01
+1.03 0 0 35.3921 .01 .01
+1.04 0 0 35.1196 .01 .01
+1.05 0 0 34.8517 .01 .01
+1.06 0 0 34.5885 .01 .01
+1.07 0 0 34.3296 .01 .01
+1.08 0 0 34.0751 .01 .01
+1.09 0 0 33.8248 .01 .01
+1.1 0 0 33.5785 .01 .01
+1.11 0 0 33.3363 .01 .01
+1.12 0 0 33.098 .01 .01
+1.13 0 0 32.8635 .01 .01
+1.14 0 0 32.6326 .01 .01
+1.15 0 0 32.4054 .01 .01
+1.16 0 0 32.1817 .01 .01
+1.17 0 0 31.9615 .01 .01
+1.18 0 0 31.7446 .01 .01
+1.19 0 0 31.5311 .01 .01
+1.2 0 0 31.3207 .01 .01
+1.21 0 0 31.1134 .01 .01
+1.22 0 0 30.9092 .01 .01
+1.23 0 0 30.708 .01 .01
+1.24 0 0 30.5098 .01 .01
+1.25 0 0 30.3143 .01 .01
+1.26 0 0 30.1217 .01 .01
+1.27 0 0 29.9318 .01 .01
+1.28 0 0 29.7446 .01 .01
+1.29 0 0 29.56 .01 .01
+1.3 0 0 29.3779 .01 .01
+1.31 0 0 29.1984 .01 .01
+1.32 0 0 29.0213 .01 .01
+1.33 0 0 28.8466 .01 .01
+1.34 0 0 28.6743 .01 .01
+1.35 0 0 28.5042 .01 .01
+1.36 0 0 28.3364 .01 .01
+1.37 0 0 28.1708 .01 .01
+1.38 0 0 28.0074 .01 .01
+1.39 0 0 27.8461 .01 .01
+1.4 0 0 27.6869 .01 .01
+1.41 0 0 27.5297 .01 .01
+1.42 0 0 27.3744 .01 .01
+1.43 0 0 27.2212 .01 .01
+1.44 0 0 27.0699 .01 .01
+1.45 0 0 26.9204 .01 .01
+1.46 0 0 26.7728 .01 .01
+1.47 0 0 26.627 .01 .01
+1.48 0 0 26.483 .01 .01
+1.49 0 0 26.3407 .01 .01
+1.5 0 0 26.2001 .01 .01
+1.51 0 0 26.0612 .01 .01
+1.52 0 0 25.9239 .01 .01
+1.53 0 0 25.7883 .01 .01
+1.54 0 0 25.6543 .01 .01
+1.55 0 0 25.5218 .01 .01
+1.56 0 0 25.3908 .01 .01
+1.57 0 0 25.2613 .01 .01
+1.58 0 0 25.1333 .01 .01
+1.59 0 0 25.0068 .01 .01
+1.6 0 0 24.8817 .01 .01
+1.61 0 0 24.758 .01 .01
+1.62 0 0 24.6356 .01 .01
+1.63 0 0 24.5147 .01 .01
+1.64 0 0 24.395 .01 .01
+1.65 0 0 24.2767 .01 .01
+1.66 0 0 24.1596 .01 .01
+1.67 0 0 24.0438 .01 .01
+1.68 0 0 23.9292 .01 .01
+1.69 0 0 23.8159 .01 .01
+1.7 0 0 23.7037 .01 .01
+1.71 0 0 23.5928 .01 .01
+1.72 0 0 23.483 .01 .01
+1.73 0 0 23.3743 .01 .01
+1.74 0 0 23.2668 .01 .01
+1.75 0 0 23.1604 .01 .01
+1.76 0 0 23.055 .01 .01
+1.77 0 0 22.9508 .01 .01
+1.78 0 0 22.8476 .01 .01
+1.79 0 0 22.7454 .01 .01
+1.8 0 0 22.6443 .01 .01
+1.81 0 0 22.5441 .01 .01
+1.82 0 0 22.445 .01 .01
+1.83 0 0 22.3468 .01 .01
+1.84 0 0 22.2496 .01 .01
+1.85 0 0 22.1533 .01 .01
+1.86 0 0 22.058 .01 .01
+1.87 0 0 21.9636 .01 .01
+1.88 0 0 21.87 .01 .01
+1.89 0 0 21.7774 .01 .01
+1.9 0 0 21.6857 .01 .01
+1.91 0 0 21.5948 .01 .01
+1.92 0 0 21.5048 .01 .01
+1.93 0 0 21.4156 .01 .01
+1.94 0 0 21.3272 .01 .01
+1.95 0 0 21.2397 .01 .01
+1.96 0 0 21.153 .01 .01
+1.97 0 0 21.067 .01 .01
+1.98 0 0 20.9819 .01 .01
+1.99 0 0 20.8975 .01 .01
+2 0 0 20.8138 .01 .01
+2.01 0 0 20.7309 .01 .01
+2.02 0 0 20.6488 .01 .01
+2.03 0 0 20.5674 .01 .01
+2.04 0 0 20.4867 .01 .01
+2.05 0 0 20.4067 .01 .01
+2.06 0 0 20.3274 .01 .01
+2.07 0 0 20.2488 .01 .01
+2.08 0 0 20.1709 .01 .01
+2.09 0 0 20.0937 .01 .01
+2.1 0 0 20.0171 .01 .01
+2.11 0 0 19.9411 .01 .01
+2.12 0 0 19.8659 .01 .01
+2.13 0 0 19.7912 .01 .01
+2.14 0 0 19.7172 .01 .01
+2.15 0 0 19.6438 .01 .01
+2.16 0 0 19.571 .01 .01
+2.17 0 0 19.4988 .01 .01
+2.18 0 0 19.4272 .01 .01
+2.19 0 0 19.3562 .01 .01
+2.2 0 0 19.2858 .01 .01
+2.21 0 0 19.216 .01 .01
+2.22 0 0 19.1467 .01 .01
+2.23 0 0 19.078 .01 .01
+2.24 0 0 19.0098 .01 .01
+2.25 0 0 18.9422 .01 .01
+2.26 0 0 18.8751 .01 .01
+2.27 0 0 18.8086 .01 .01
+2.28 0 0 18.7425 .01 .01
+2.29 0 0 18.677 .01 .01
+2.3 0 0 18.612 .01 .01
+2.31 0 0 18.5475 .01 .01
+2.32 0 0 18.4836 .01 .01
+2.33 0 0 18.4201 .01 .01
+2.34 0 0 18.3571 .01 .01
+2.35 0 0 18.2945 .01 .01
+2.36 0 0 18.2325 .01 .01
+2.37 0 0 18.1709 .01 .01
+2.38 0 0 18.1098 .01 .01
+2.39 0 0 18.0492 .01 .01
+2.4 0 0 17.989 .01 .01
+2.41 0 0 17.9293 .01 .01
+2.42 0 0 17.87 .01 .01
+2.43 0 0 17.8111 .01 .01
+2.44 0 0 17.7527 .01 .01
+2.45 0 0 17.6947 .01 .01
+2.46 0 0 17.6371 .01 .01
+2.47 0 0 17.58 .01 .01
+2.48 0 0 17.5233 .01 .01
+2.49 0 0 17.4669 .01 .01
+2.5 0 0 17.411 .01 .01
+2.51 0 0 17.3555 .01 .01
+2.52 0 0 17.3004 .01 .01
+2.53 0 0 17.2457 .01 .01
+2.54 0 0 17.1913 .01 .01
+2.55 0 0 17.1374 .01 .01
+2.56 0 0 17.0838 .01 .01
+2.57 0 0 17.0306 .01 .01
+2.58 0 0 16.9778 .01 .01
+2.59 0 0 16.9253 .01 .01
+2.6 0 0 16.8732 .01 .01
+2.61 0 0 16.8215 .01 .01
+2.62 0 0 16.7701 .01 .01
+2.63 0 0 16.719 .01 .01
+2.64 0 0 16.6684 .01 .01
+2.65 0 0 16.618 .01 .01
+2.66 0 0 16.568 .01 .01
+2.67 0 0 16.5184 .01 .01
+2.68 0 0 16.469 .01 .01
+2.69 0 0 16.42 .01 .01
+2.7 0 0 16.3714 .01 .01
+2.71 0 0 16.323 .01 .01
+2.72 0 0 16.275 .01 .01
+2.73 0 0 16.2273 .01 .01
+2.74 0 0 16.1799 .01 .01
+2.75 0 0 16.1328 .01 .01
+2.76 0 0 16.086 .01 .01
+2.77 0 0 16.0396 .01 .01
+2.78 0 0 15.9934 .01 .01
+2.79 0 0 15.9475 .01 .01
+2.8 0 0 15.9019 .01 .01
+2.81 0 0 15.8566 .01 .01
+2.82 0 0 15.8116 .01 .01
+2.83 0 0 15.7669 .01 .01
+2.84 0 0 15.7225 .01 .01
+2.85 0 0 15.6783 .01 .01
+2.86 0 0 15.6345 .01 .01
+2.87 0 0 15.5909 .01 .01
+2.88 0 0 15.5476 .01 .01
+2.89 0 0 15.5045 .01 .01
+2.9 0 0 15.4617 .01 .01
+2.91 0 0 15.4192 .01 .01
+2.92 0 0 15.3769 .01 .01
+2.93 0 0 15.3349 .01 .01
+2.94 0 0 15.2932 .01 .01
+2.95 0 0 15.2517 .01 .01
+2.96 0 0 15.2105 .01 .01
+2.97 0 0 15.1695 .01 .01
+2.98 0 0 15.1287 .01 .01
+2.99 0 0 15.0883 .01 .01
+3 0 0 15.048 .01 .01
+3.01 0 0 15.008 .01 .01
+3.02 0 0 14.9682 .01 .01
+3.03 0 0 14.9287 .01 .01
+3.04 0 0 14.8894 .01 .01
+3.05 0 0 14.8503 .01 .01
+3.06 0 0 14.8115 .01 .01
+3.07 0 0 14.7729 .01 .01
+3.08 0 0 14.7345 .01 .01
+3.09 0 0 14.6963 .01 .01
+3.1 0 0 14.6584 .01 .01
+3.11 0 0 14.6207 .01 .01
+3.12 0 0 14.5832 .01 .01
+3.13 0 0 14.5459 .01 .01
+3.14 0 0 14.5088 .01 .01
+3.15 0 0 14.472 .01 .01
+3.16 0 0 14.4353 .01 .01
+3.17 0 0 14.3989 .01 .01
+3.18 0 0 14.3626 .01 .01
+3.19 0 0 14.3266 .01 .01
+3.2 0 0 14.2908 .01 .01
+3.21 0 0 14.2552 .01 .01
+3.22 0 0 14.2197 .01 .01
+3.23 0 0 14.1845 .01 .01
+3.24 0 0 14.1495 .01 .01
+3.25 0 0 14.1146 .01 .01
+3.26 0 0 14.08 .01 .01
+3.27 0 0 14.0455 .01 .01
+3.28 0 0 14.0113 .01 .01
+3.29 0 0 13.9772 .01 .01
+3.3 0 0 13.9433 .01 .01
+3.31 0 0 13.9096 .01 .01
+3.32 0 0 13.876 .01 .01
+3.33 0 0 13.8427 .01 .01
+3.34 0 0 13.8095 .01 .01
+3.35 0 0 13.7765 .01 .01
+3.36 0 0 13.7437 .01 .01
+3.37 0 0 13.7111 .01 .01
+3.38 0 0 13.6786 .01 .01
+3.39 0 0 13.6463 .01 .01
+3.4 0 0 13.6142 .01 .01
+3.41 0 0 13.5823 .01 .01
+3.42 0 0 13.5505 .01 .01
+3.43 0 0 13.5189 .01 .01
+3.44 0 0 13.4874 .01 .01
+3.45 0 0 13.4561 .01 .01
+3.46 0 0 13.425 .01 .01
+3.47 0 0 13.3941 .01 .01
+3.48 0 0 13.3633 .01 .01
+3.49 0 0 13.3326 .01 .01
+3.5 0 0 13.3021 .01 .01
+3.51 0 0 13.2718 .01 .01
+3.52 0 0 13.2416 .01 .01
+3.53 0 0 13.2116 .01 .01
+3.54 0 0 13.1818 .01 .01
+3.55 0 0 13.152 .01 .01
+3.56 0 0 13.1225 .01 .01
+3.57 0 0 13.0931 .01 .01
+3.58 0 0 13.0638 .01 .01
+3.59 0 0 13.0347 .01 .01
+3.6 0 0 13.0057 .01 .01
+3.61 0 0 12.9769 .01 .01
+3.62 0 0 12.9482 .01 .01
+3.63 0 0 12.9196 .01 .01
+3.64 0 0 12.8912 .01 .01
+3.65 0 0 12.863 .01 .01
+3.66 0 0 12.8349 .01 .01
+3.67 0 0 12.8069 .01 .01
+3.68 0 0 12.779 .01 .01
+3.69 0 0 12.7513 .01 .01
+3.7 0 0 12.7237 .01 .01
+3.71 0 0 12.6963 .01 .01
+3.72 0 0 12.669 .01 .01
+3.73 0 0 12.6418 .01 .01
+3.74 0 0 12.6148 .01 .01
+3.75 0 0 12.5878 .01 .01
+3.76 0 0 12.561 .01 .01
+3.77 0 0 12.5344 .01 .01
+3.78 0 0 12.5078 .01 .01
+3.79 0 0 12.4814 .01 .01
+3.8 0 0 12.4552 .01 .01
+3.81 0 0 12.429 .01 .01
+3.82 0 0 12.403 .01 .01
+3.83 0 0 12.377 .01 .01
+3.84 0 0 12.3513 .01 .01
+3.85 0 0 12.3256 .01 .01
+3.86 0 0 12.3 .01 .01
+3.87 0 0 12.2746 .01 .01
+3.88 0 0 12.2493 .01 .01
+3.89 0 0 12.2241 .01 .01
+3.9 0 0 12.199 .01 .01
+3.91 0 0 12.174 .01 .01
+3.92 0 0 12.1492 .01 .01
+3.93 0 0 12.1244 .01 .01
+3.94 0 0 12.0998 .01 .01
+3.95 0 0 12.0753 .01 .01
+3.96 0 0 12.0509 .01 .01
+3.97 0 0 12.0266 .01 .01
+3.98 0 0 12.0024 .01 .01
+3.99 0 0 11.9784 .01 .01
+4 0 0 11.9544 .01 .01
+4.01 0 0 11.9306 .01 .01
+4.02 0 0 11.9068 .01 .01
+4.03 0 0 11.8832 .01 .01
+4.04 0 0 11.8596 .01 .01
+4.05 0 0 11.8362 .01 .01
+4.06 0 0 11.8129 .01 .01
+4.07 0 0 11.7896 .01 .01
+4.08 0 0 11.7665 .01 .01
+4.09 0 0 11.7435 .01 .01
+4.1 0 0 11.7206 .01 .01
+4.11 0 0 11.6978 .01 .01
+4.12 0 0 11.675 .01 .01
+4.13 0 0 11.6524 .01 .01
+4.14 0 0 11.6299 .01 .01
+4.15 0 0 11.6075 .01 .01
+4.16 0 0 11.5851 .01 .01
+4.17 0 0 11.5629 .01 .01
+4.18 0 0 11.5408 .01 .01
+4.19 0 0 11.5187 .01 .01
+4.2 0 0 11.4968 .01 .01
+4.21 0 0 11.4749 .01 .01
+4.22 0 0 11.4532 .01 .01
+4.23 0 0 11.4315 .01 .01
+4.24 0 0 11.4099 .01 .01
+4.25 0 0 11.3885 .01 .01
+4.26 0 0 11.3671 .01 .01
+4.27 0 0 11.3458 .01 .01
+4.28 0 0 11.3246 .01 .01
+4.29 0 0 11.3034 .01 .01
+4.3 0 0 11.2824 .01 .01
+4.31 0 0 11.2614 .01 .01
+4.32 0 0 11.2406 .01 .01
+4.33 0 0 11.2198 .01 .01
+4.34 0 0 11.1991 .01 .01
+4.35 0 0 11.1785 .01 .01
+4.36 0 0 11.158 .01 .01
+4.37 0 0 11.1376 .01 .01
+4.38 0 0 11.1172 .01 .01
+4.39 0 0 11.097 .01 .01
+4.4 0 0 11.0768 .01 .01
+4.41 0 0 11.0567 .01 .01
+4.42 0 0 11.0367 .01 .01
+4.43 0 0 11.0167 .01 .01
+4.44 0 0 10.9969 .01 .01
+4.45 0 0 10.9771 .01 .01
+4.46 0 0 10.9574 .01 .01
+4.47 0 0 10.9378 .01 .01
+4.48 0 0 10.9183 .01 .01
+4.49 0 0 10.8988 .01 .01
+4.5 0 0 10.8794 .01 .01
+4.51 0 0 10.8601 .01 .01
+4.52 0 0 10.8409 .01 .01
+4.53 0 0 10.8217 .01 .01
+4.54 0 0 10.8027 .01 .01
+4.55 0 0 10.7837 .01 .01
+4.56 0 0 10.7648 .01 .01
+4.57 0 0 10.7459 .01 .01
+4.58 0 0 10.7271 .01 .01
+4.59 0 0 10.7084 .01 .01
+4.6 0 0 10.6898 .01 .01
+4.61 0 0 10.6712 .01 .01
+4.62 0 0 10.6528 .01 .01
+4.63 0 0 10.6344 .01 .01
+4.64 0 0 10.616 .01 .01
+4.65 0 0 10.5977 .01 .01
+4.66 0 0 10.5796 .01 .01
+4.67 0 0 10.5614 .01 .01
+4.68 0 0 10.5434 .01 .01
+4.69 0 0 10.5254 .01 .01
+4.7 0 0 10.5075 .01 .01
+4.71 0 0 10.4896 .01 .01
+4.72 0 0 10.4718 .01 .01
+4.73 0 0 10.4541 .01 .01
+4.74 0 0 10.4365 .01 .01
+4.75 0 0 10.4189 .01 .01
+4.76 0 0 10.4014 .01 .01
+4.77 0 0 10.3839 .01 .01
+4.78 0 0 10.3665 .01 .01
+4.79 0 0 10.3492 .01 .01
+4.8 0 0 10.332 .01 .01
+4.81 0 0 10.3148 .01 .01
+4.82 0 0 10.2977 .01 .01
+4.83 0 0 10.2806 .01 .01
+4.84 0 0 10.2636 .01 .01
+4.85 0 0 10.2467 .01 .01
+4.86 0 0 10.2298 .01 .01
+4.87 0 0 10.213 .01 .01
+4.88 0 0 10.1962 .01 .01
+4.89 0 0 10.1796 .01 .01
+4.9 0 0 10.1629 .01 .01
+4.91 0 0 10.1464 .01 .01
+4.92 0 0 10.1299 .01 .01
+4.93 0 0 10.1134 .01 .01
+4.94 0 0 10.097 .01 .01
+4.95 0 0 10.0807 .01 .01
+4.96 0 0 10.0645 .01 .01
+4.97 0 0 10.0483 .01 .01
+4.98 0 0 10.0321 .01 .01
+4.99 0 0 10.016 .01 .01
+5 0 0 10 .01 .01
+5.01 0 0 9.97007 .01 .01
+5.02 0 0 9.9403 .01 .01
+5.03 0 0 9.91067 .01 .01
+5.04 0 0 9.88119 .01 .01
+5.05 0 0 9.85185 .01 .01
+5.06 0 0 9.82266 .01 .01
+5.07 0 0 9.79362 .01 .01
+5.08 0 0 9.76471 .01 .01
+5.09 0 0 9.73595 .01 .01
+5.1 0 0 9.70733 .01 .01
+5.11 0 0 9.67885 .01 .01
+5.12 0 0 9.65051 .01 .01
+5.13 0 0 9.6223 .01 .01
+5.14 0 0 9.59423 .01 .01
+5.15 0 0 9.5663 .01 .01
+5.16 0 0 9.53851 .01 .01
+5.17 0 0 9.51085 .01 .01
+5.18 0 0 9.48332 .01 .01
+5.19 0 0 9.45592 .01 .01
+5.2 0 0 9.42866 .01 .01
+5.21 0 0 9.40153 .01 .01
+5.22 0 0 9.37452 .01 .01
+5.23 0 0 9.34765 .01 .01
+5.24 0 0 9.3209 .01 .01
+5.25 0 0 9.29429 .01 .01
+5.26 0 0 9.26779 .01 .01
+5.27 0 0 9.24143 .01 .01
+5.28 0 0 9.21519 .01 .01
+5.29 0 0 9.18907 .01 .01
+5.3 0 0 9.16307 .01 .01
+5.31 0 0 9.1372 .01 .01
+5.32 0 0 9.11145 .01 .01
+5.33 0 0 9.08582 .01 .01
+5.34 0 0 9.06031 .01 .01
+5.35 0 0 9.03492 .01 .01
+5.36 0 0 9.00965 .01 .01
+5.37 0 0 8.98449 .01 .01
+5.38 0 0 8.95946 .01 .01
+5.39 0 0 8.93453 .01 .01
+5.4 0 0 8.90973 .01 .01
+5.41 0 0 8.88503 .01 .01
+5.42 0 0 8.86046 .01 .01
+5.43 0 0 8.83599 .01 .01
+5.44 0 0 8.81164 .01 .01
+5.45 0 0 8.7874 .01 .01
+5.46 0 0 8.76327 .01 .01
+5.47 0 0 8.73925 .01 .01
+5.48 0 0 8.71534 .01 .01
+5.49 0 0 8.69154 .01 .01
+5.5 0 0 8.66784 .01 .01
+5.51 0 0 8.64426 .01 .01
+5.52 0 0 8.62078 .01 .01
+5.53 0 0 8.5974 .01 .01
+5.54 0 0 8.57414 .01 .01
+5.55 0 0 8.55097 .01 .01
+5.56 0 0 8.52791 .01 .01
+5.57 0 0 8.50496 .01 .01
+5.58 0 0 8.48211 .01 .01
+5.59 0 0 8.45936 .01 .01
+5.6 0 0 8.43671 .01 .01
+5.61 0 0 8.41416 .01 .01
+5.62 0 0 8.39171 .01 .01
+5.63 0 0 8.36936 .01 .01
+5.64 0 0 8.34711 .01 .01
+5.65 0 0 8.32496 .01 .01
+5.66 0 0 8.30291 .01 .01
+5.67 0 0 8.28095 .01 .01
+5.68 0 0 8.2591 .01 .01
+5.69 0 0 8.23733 .01 .01
+5.7 0 0 8.21567 .01 .01
+5.71 0 0 8.19409 .01 .01
+5.72 0 0 8.17261 .01 .01
+5.73 0 0 8.15123 .01 .01
+5.74 0 0 8.12994 .01 .01
+5.75 0 0 8.10874 .01 .01
+5.76 0 0 8.08763 .01 .01
+5.77 0 0 8.06661 .01 .01
+5.78 0 0 8.04569 .01 .01
+5.79 0 0 8.02485 .01 .01
+5.8 0 0 8.00411 .01 .01
+5.81 0 0 7.98345 .01 .01
+5.82 0 0 7.96289 .01 .01
+5.83 0 0 7.94241 .01 .01
+5.84 0 0 7.92202 .01 .01
+5.85 0 0 7.90171 .01 .01
+5.86 0 0 7.88149 .01 .01
+5.87 0 0 7.86136 .01 .01
+5.88 0 0 7.84132 .01 .01
+5.89 0 0 7.82136 .01 .01
+5.9 0 0 7.80148 .01 .01
+5.91 0 0 7.78169 .01 .01
+5.92 0 0 7.76198 .01 .01
+5.93 0 0 7.74235 .01 .01
+5.94 0 0 7.72281 .01 .01
+5.95 0 0 7.70335 .01 .01
+5.96 0 0 7.68397 .01 .01
+5.97 0 0 7.66467 .01 .01
+5.98 0 0 7.64545 .01 .01
+5.99 0 0 7.62632 .01 .01
+6 0 0 7.60726 .01 .01
+6.01 0 0 7.58828 .01 .01
+6.02 0 0 7.56938 .01 .01
+6.03 0 0 7.55056 .01 .01
+6.04 0 0 7.53181 .01 .01
+6.05 0 0 7.51315 .01 .01
+6.06 0 0 7.49456 .01 .01
+6.07 0 0 7.47605 .01 .01
+6.08 0 0 7.45761 .01 .01
+6.09 0 0 7.43925 .01 .01
+6.1 0 0 7.42096 .01 .01
+6.11 0 0 7.40275 .01 .01
+6.12 0 0 7.38462 .01 .01
+6.13 0 0 7.36655 .01 .01
+6.14 0 0 7.34856 .01 .01
+6.15 0 0 7.33065 .01 .01
+6.16 0 0 7.3128 .01 .01
+6.17 0 0 7.29503 .01 .01
+6.18 0 0 7.27733 .01 .01
+6.19 0 0 7.25971 .01 .01
+6.2 0 0 7.24215 .01 .01
+6.21 0 0 7.22466 .01 .01
+6.22 0 0 7.20725 .01 .01
+6.23 0 0 7.1899 .01 .01
+6.24 0 0 7.17262 .01 .01
+6.25 0 0 7.15542 .01 .01
+6.26 0 0 7.13828 .01 .01
+6.27 0 0 7.12121 .01 .01
+6.28 0 0 7.10421 .01 .01
+6.29 0 0 7.08727 .01 .01
+6.3 0 0 7.0704 .01 .01
+6.31 0 0 7.0536 .01 .01
+6.32 0 0 7.03687 .01 .01
+6.33 0 0 7.0202 .01 .01
+6.34 0 0 7.0036 .01 .01
+6.35 0 0 6.98706 .01 .01
+6.36 0 0 6.97059 .01 .01
+6.37 0 0 6.95418 .01 .01
+6.38 0 0 6.93784 .01 .01
+6.39 0 0 6.92156 .01 .01
+6.4 0 0 6.90534 .01 .01
+6.41 0 0 6.88919 .01 .01
+6.42 0 0 6.8731 .01 .01
+6.43 0 0 6.85707 .01 .01
+6.44 0 0 6.8411 .01 .01
+6.45 0 0 6.8252 .01 .01
+6.46 0 0 6.80936 .01 .01
+6.47 0 0 6.79358 .01 .01
+6.48 0 0 6.77786 .01 .01
+6.49 0 0 6.7622 .01 .01
+6.5 0 0 6.7466 .01 .01
+6.51 0 0 6.73106 .01 .01
+6.52 0 0 6.71558 .01 .01
+6.53 0 0 6.70016 .01 .01
+6.54 0 0 6.6848 .01 .01
+6.55 0 0 6.6695 .01 .01
+6.56 0 0 6.65425 .01 .01
+6.57 0 0 6.63907 .01 .01
+6.58 0 0 6.62394 .01 .01
+6.59 0 0 6.60887 .01 .01
+6.6 0 0 6.59385 .01 .01
+6.61 0 0 6.57889 .01 .01
+6.62 0 0 6.56399 .01 .01
+6.63 0 0 6.54915 .01 .01
+6.64 0 0 6.53436 .01 .01
+6.65 0 0 6.51962 .01 .01
+6.66 0 0 6.50495 .01 .01
+6.67 0 0 6.49032 .01 .01
+6.68 0 0 6.47575 .01 .01
+6.69 0 0 6.46124 .01 .01
+6.7 0 0 6.44678 .01 .01
+6.71 0 0 6.43237 .01 .01
+6.72 0 0 6.41802 .01 .01
+6.73 0 0 6.40372 .01 .01
+6.74 0 0 6.38947 .01 .01
+6.75 0 0 6.37528 .01 .01
+6.76 0 0 6.36114 .01 .01
+6.77 0 0 6.34705 .01 .01
+6.78 0 0 6.33301 .01 .01
+6.79 0 0 6.31903 .01 .01
+6.8 0 0 6.3051 .01 .01
+6.81 0 0 6.29121 .01 .01
+6.82 0 0 6.27738 .01 .01
+6.83 0 0 6.2636 .01 .01
+6.84 0 0 6.24987 .01 .01
+6.85 0 0 6.23619 .01 .01
+6.86 0 0 6.22256 .01 .01
+6.87 0 0 6.20897 .01 .01
+6.88 0 0 6.19544 .01 .01
+6.89 0 0 6.18196 .01 .01
+6.9 0 0 6.16853 .01 .01
+6.91 0 0 6.15514 .01 .01
+6.92 0 0 6.1418 .01 .01
+6.93 0 0 6.12851 .01 .01
+6.94 0 0 6.11527 .01 .01
+6.95 0 0 6.10208 .01 .01
+6.96 0 0 6.08893 .01 .01
+6.97 0 0 6.07583 .01 .01
+6.98 0 0 6.06278 .01 .01
+6.99 0 0 6.04978 .01 .01
+7 0 0 6.03682 .01 .01
+7.01 0 0 6.0239 .01 .01
+7.02 0 0 6.01104 .01 .01
+7.03 0 0 5.99821 .01 .01
+7.04 0 0 5.98544 .01 .01
+7.05 0 0 5.97271 .01 .01
+7.06 0 0 5.96002 .01 .01
+7.07 0 0 5.94738 .01 .01
+7.08 0 0 5.93479 .01 .01
+7.09 0 0 5.92224 .01 .01
+7.1 0 0 5.90973 .01 .01
+7.11 0 0 5.89726 .01 .01
+7.12 0 0 5.88484 .01 .01
+7.13 0 0 5.87247 .01 .01
+7.14 0 0 5.86014 .01 .01
+7.15 0 0 5.84785 .01 .01
+7.16 0 0 5.8356 .01 .01
+7.17 0 0 5.8234 .01 .01
+7.18 0 0 5.81123 .01 .01
+7.19 0 0 5.79911 .01 .01
+7.2 0 0 5.78704 .01 .01
+7.21 0 0 5.775 .01 .01
+7.22 0 0 5.76301 .01 .01
+7.23 0 0 5.75106 .01 .01
+7.24 0 0 5.73914 .01 .01
+7.25 0 0 5.72727 .01 .01
+7.26 0 0 5.71545 .01 .01
+7.27 0 0 5.70366 .01 .01
+7.28 0 0 5.69191 .01 .01
+7.29 0 0 5.6802 .01 .01
+7.3 0 0 5.66853 .01 .01
+7.31 0 0 5.65691 .01 .01
+7.32 0 0 5.64532 .01 .01
+7.33 0 0 5.63377 .01 .01
+7.34 0 0 5.62226 .01 .01
+7.35 0 0 5.61079 .01 .01
+7.36 0 0 5.59936 .01 .01
+7.37 0 0 5.58797 .01 .01
+7.38 0 0 5.57661 .01 .01
+7.39 0 0 5.5653 .01 .01
+7.4 0 0 5.55402 .01 .01
+7.41 0 0 5.54278 .01 .01
+7.42 0 0 5.53158 .01 .01
+7.43 0 0 5.52042 .01 .01
+7.44 0 0 5.50929 .01 .01
+7.45 0 0 5.4982 .01 .01
+7.46 0 0 5.48715 .01 .01
+7.47 0 0 5.47613 .01 .01
+7.48 0 0 5.46516 .01 .01
+7.49 0 0 5.45422 .01 .01
+7.5 0 0 5.44331 .01 .01
+7.51 0 0 5.43244 .01 .01
+7.52 0 0 5.42161 .01 .01
+7.53 0 0 5.41081 .01 .01
+7.54 0 0 5.40005 .01 .01
+7.55 0 0 5.38933 .01 .01
+7.56 0 0 5.37864 .01 .01
+7.57 0 0 5.36798 .01 .01
+7.58 0 0 5.35736 .01 .01
+7.59 0 0 5.34678 .01 .01
+7.6 0 0 5.33623 .01 .01
+7.61 0 0 5.32572 .01 .01
+7.62 0 0 5.31524 .01 .01
+7.63 0 0 5.30479 .01 .01
+7.64 0 0 5.29438 .01 .01
+7.65 0 0 5.284 .01 .01
+7.66 0 0 5.27366 .01 .01
+7.67 0 0 5.26335 .01 .01
+7.68 0 0 5.25307 .01 .01
+7.69 0 0 5.24283 .01 .01
+7.7 0 0 5.23262 .01 .01
+7.71 0 0 5.22244 .01 .01
+7.72 0 0 5.2123 .01 .01
+7.73 0 0 5.20218 .01 .01
+7.74 0 0 5.19211 .01 .01
+7.75 0 0 5.18206 .01 .01
+7.76 0 0 5.17205 .01 .01
+7.77 0 0 5.16207 .01 .01
+7.78 0 0 5.15212 .01 .01
+7.79 0 0 5.1422 .01 .01
+7.8 0 0 5.13231 .01 .01
+7.81 0 0 5.12246 .01 .01
+7.82 0 0 5.11264 .01 .01
+7.83 0 0 5.10284 .01 .01
+7.84 0 0 5.09308 .01 .01
+7.85 0 0 5.08336 .01 .01
+7.86 0 0 5.07366 .01 .01
+7.87 0 0 5.06399 .01 .01
+7.88 0 0 5.05435 .01 .01
+7.89 0 0 5.04475 .01 .01
+7.9 0 0 5.03517 .01 .01
+7.91 0 0 5.02563 .01 .01
+7.92 0 0 5.01611 .01 .01
+7.93 0 0 5.00663 .01 .01
+7.94 0 0 4.99717 .01 .01
+7.95 0 0 4.98775 .01 .01
+7.96 0 0 4.97835 .01 .01
+7.97 0 0 4.96898 .01 .01
+7.98 0 0 4.95965 .01 .01
+7.99 0 0 4.95034 .01 .01
+8 0 0 4.94106 .01 .01
+8.01 0 0 4.93181 .01 .01
+8.02 0 0 4.92259 .01 .01
+8.03 0 0 4.9134 .01 .01
+8.04 0 0 4.90423 .01 .01
+8.05 0 0 4.8951 .01 .01
+8.06 0 0 4.88599 .01 .01
+8.07 0 0 4.87691 .01 .01
+8.08 0 0 4.86786 .01 .01
+8.09 0 0 4.85884 .01 .01
+8.1 0 0 4.84984 .01 .01
+8.11 0 0 4.84087 .01 .01
+8.12 0 0 4.83193 .01 .01
+8.13 0 0 4.82302 .01 .01
+8.14 0 0 4.81414 .01 .01
+8.15 0 0 4.80528 .01 .01
+8.16 0 0 4.79645 .01 .01
+8.17 0 0 4.78764 .01 .01
+8.18 0 0 4.77887 .01 .01
+8.19 0 0 4.77012 .01 .01
+8.2 0 0 4.7614 .01 .01
+8.21 0 0 4.7527 .01 .01
+8.22 0 0 4.74403 .01 .01
+8.23 0 0 4.73538 .01 .01
+8.24 0 0 4.72677 .01 .01
+8.25 0 0 4.71818 .01 .01
+8.26 0 0 4.70961 .01 .01
+8.27 0 0 4.70107 .01 .01
+8.28 0 0 4.69256 .01 .01
+8.29 0 0 4.68407 .01 .01
+8.3 0 0 4.67561 .01 .01
+8.31 0 0 4.66717 .01 .01
+8.32 0 0 4.65876 .01 .01
+8.33 0 0 4.65037 .01 .01
+8.34 0 0 4.64201 .01 .01
+8.35 0 0 4.63367 .01 .01
+8.36 0 0 4.62536 .01 .01
+8.37 0 0 4.61707 .01 .01
+8.38 0 0 4.60881 .01 .01
+8.39 0 0 4.60057 .01 .01
+8.4 0 0 4.59236 .01 .01
+8.41 0 0 4.58417 .01 .01
+8.42 0 0 4.57601 .01 .01
+8.43 0 0 4.56787 .01 .01
+8.44 0 0 4.55975 .01 .01
+8.45 0 0 4.55166 .01 .01
+8.46 0 0 4.54359 .01 .01
+8.47 0 0 4.53555 .01 .01
+8.48 0 0 4.52753 .01 .01
+8.49 0 0 4.51953 .01 .01
+8.5 0 0 4.51156 .01 .01
+8.51 0 0 4.50361 .01 .01
+8.52 0 0 4.49568 .01 .01
+8.53 0 0 4.48778 .01 .01
+8.54 0 0 4.4799 .01 .01
+8.55 0 0 4.47204 .01 .01
+8.56 0 0 4.46421 .01 .01
+8.57 0 0 4.4564 .01 .01
+8.58 0 0 4.44861 .01 .01
+8.59 0 0 4.44084 .01 .01
+8.6 0 0 4.4331 .01 .01
+8.61 0 0 4.42538 .01 .01
+8.62 0 0 4.41768 .01 .01
+8.63 0 0 4.41 .01 .01
+8.64 0 0 4.40235 .01 .01
+8.65 0 0 4.39472 .01 .01
+8.66 0 0 4.38711 .01 .01
+8.67 0 0 4.37952 .01 .01
+8.68 0 0 4.37195 .01 .01
+8.69 0 0 4.36441 .01 .01
+8.7 0 0 4.35689 .01 .01
+8.71 0 0 4.34938 .01 .01
+8.72 0 0 4.3419 .01 .01
+8.73 0 0 4.33445 .01 .01
+8.74 0 0 4.32701 .01 .01
+8.75 0 0 4.31959 .01 .01
+8.76 0 0 4.3122 .01 .01
+8.77 0 0 4.30483 .01 .01
+8.78 0 0 4.29747 .01 .01
+8.79 0 0 4.29014 .01 .01
+8.8 0 0 4.28283 .01 .01
+8.81 0 0 4.27554 .01 .01
+8.82 0 0 4.26827 .01 .01
+8.83 0 0 4.26102 .01 .01
+8.84 0 0 4.2538 .01 .01
+8.85 0 0 4.24659 .01 .01
+8.86 0 0 4.2394 .01 .01
+8.87 0 0 4.23223 .01 .01
+8.88 0 0 4.22509 .01 .01
+8.89 0 0 4.21796 .01 .01
+8.9 0 0 4.21085 .01 .01
+8.91 0 0 4.20377 .01 .01
+8.92 0 0 4.1967 .01 .01
+8.93 0 0 4.18965 .01 .01
+8.94 0 0 4.18262 .01 .01
+8.95 0 0 4.17562 .01 .01
+8.96 0 0 4.16863 .01 .01
+8.97 0 0 4.16166 .01 .01
+8.98 0 0 4.15471 .01 .01
+8.99 0 0 4.14778 .01 .01
+9 0 0 4.14087 .01 .01
+9.01 0 0 4.13397 .01 .01
+9.02 0 0 4.1271 .01 .01
+9.03 0 0 4.12025 .01 .01
+9.04 0 0 4.11341 .01 .01
+9.05 0 0 4.1066 .01 .01
+9.06 0 0 4.0998 .01 .01
+9.07 0 0 4.09302 .01 .01
+9.08 0 0 4.08626 .01 .01
+9.09 0 0 4.07952 .01 .01
+9.1 0 0 4.0728 .01 .01
+9.11 0 0 4.06609 .01 .01
+9.12 0 0 4.05941 .01 .01
+9.13 0 0 4.05274 .01 .01
+9.14 0 0 4.04609 .01 .01
+9.15 0 0 4.03946 .01 .01
+9.16 0 0 4.03285 .01 .01
+9.17 0 0 4.02625 .01 .01
+9.18 0 0 4.01968 .01 .01
+9.19 0 0 4.01312 .01 .01
+9.2 0 0 4.00657 .01 .01
+9.21 0 0 4.00005 .01 .01
+9.22 0 0 3.99355 .01 .01
+9.23 0 0 3.98706 .01 .01
+9.24 0 0 3.98059 .01 .01
+9.25 0 0 3.97413 .01 .01
+9.26 0 0 3.9677 .01 .01
+9.27 0 0 3.96128 .01 .01
+9.28 0 0 3.95488 .01 .01
+9.29 0 0 3.94849 .01 .01
+9.3 0 0 3.94213 .01 .01
+9.31 0 0 3.93578 .01 .01
+9.32 0 0 3.92944 .01 .01
+9.33 0 0 3.92313 .01 .01
+9.34 0 0 3.91683 .01 .01
+9.35 0 0 3.91055 .01 .01
+9.36 0 0 3.90428 .01 .01
+9.37 0 0 3.89803 .01 .01
+9.38 0 0 3.8918 .01 .01
+9.39 0 0 3.88559 .01 .01
+9.4 0 0 3.87939 .01 .01
+9.41 0 0 3.87321 .01 .01
+9.42 0 0 3.86704 .01 .01
+9.43 0 0 3.86089 .01 .01
+9.44 0 0 3.85476 .01 .01
+9.45 0 0 3.84864 .01 .01
+9.46 0 0 3.84254 .01 .01
+9.47 0 0 3.83645 .01 .01
+9.48 0 0 3.83039 .01 .01
+9.49 0 0 3.82433 .01 .01
+9.5 0 0 3.8183 .01 .01
+9.51 0 0 3.81228 .01 .01
+9.52 0 0 3.80627 .01 .01
+9.53 0 0 3.80028 .01 .01
+9.54 0 0 3.79431 .01 .01
+9.55 0 0 3.78835 .01 .01
+9.56 0 0 3.78241 .01 .01
+9.57 0 0 3.77648 .01 .01
+9.58 0 0 3.77057 .01 .01
+9.59 0 0 3.76467 .01 .01
+9.6 0 0 3.75879 .01 .01
+9.61 0 0 3.75293 .01 .01
+9.62 0 0 3.74708 .01 .01
+9.63 0 0 3.74124 .01 .01
+9.64 0 0 3.73542 .01 .01
+9.65 0 0 3.72962 .01 .01
+9.66 0 0 3.72383 .01 .01
+9.67 0 0 3.71805 .01 .01
+9.68 0 0 3.71229 .01 .01
+9.69 0 0 3.70655 .01 .01
+9.7 0 0 3.70082 .01 .01
+9.71 0 0 3.6951 .01 .01
+9.72 0 0 3.6894 .01 .01
+9.73 0 0 3.68371 .01 .01
+9.74 0 0 3.67804 .01 .01
+9.75 0 0 3.67238 .01 .01
+9.76 0 0 3.66674 .01 .01
+9.77 0 0 3.66111 .01 .01
+9.78 0 0 3.6555 .01 .01
+9.79 0 0 3.6499 .01 .01
+9.8 0 0 3.64431 .01 .01
+9.81 0 0 3.63874 .01 .01
+9.82 0 0 3.63319 .01 .01
+9.83 0 0 3.62764 .01 .01
+9.84 0 0 3.62212 .01 .01
+9.85 0 0 3.6166 .01 .01
+9.86 0 0 3.6111 .01 .01
+9.87 0 0 3.60561 .01 .01
+9.88 0 0 3.60014 .01 .01
+9.89 0 0 3.59468 .01 .01
+9.9 0 0 3.58924 .01 .01
+9.91 0 0 3.58381 .01 .01
+9.92 0 0 3.57839 .01 .01
+9.93 0 0 3.57298 .01 .01
+9.94 0 0 3.56759 .01 .01
+9.95 0 0 3.56222 .01 .01
+9.96 0 0 3.55685 .01 .01
+9.97 0 0 3.5515 .01 .01
+9.98 0 0 3.54617 .01 .01
+9.99 0 0 3.54084 .01 .01
+10 0 0 3.53553 .01 .01
diff --git a/samples/gauss.dat b/samples/gauss.dat
new file mode 100644
index 0000000..4130e1b
--- /dev/null
+++ b/samples/gauss.dat
@@ -0,0 +1,901 @@
+1 0 0 0.338027 .01 .01
+1.01 0 0 0.341041 .01 .01
+1.02 0 0 0.344074 .01 .01
+1.03 0 0 0.347127 .01 .01
+1.04 0 0 0.350199 .01 .01
+1.05 0 0 0.353291 .01 .01
+1.06 0 0 0.356402 .01 .01
+1.07 0 0 0.359532 .01 .01
+1.08 0 0 0.362681 .01 .01
+1.09 0 0 0.36585 .01 .01
+1.1 0 0 0.369039 .01 .01
+1.11 0 0 0.372247 .01 .01
+1.12 0 0 0.375475 .01 .01
+1.13 0 0 0.378722 .01 .01
+1.14 0 0 0.381989 .01 .01
+1.15 0 0 0.385275 .01 .01
+1.16 0 0 0.388581 .01 .01
+1.17 0 0 0.391907 .01 .01
+1.18 0 0 0.395252 .01 .01
+1.19 0 0 0.398618 .01 .01
+1.2 0 0 0.402002 .01 .01
+1.21 0 0 0.405407 .01 .01
+1.22 0 0 0.408831 .01 .01
+1.23 0 0 0.412275 .01 .01
+1.24 0 0 0.415739 .01 .01
+1.25 0 0 0.419223 .01 .01
+1.26 0 0 0.422726 .01 .01
+1.27 0 0 0.426249 .01 .01
+1.28 0 0 0.429792 .01 .01
+1.29 0 0 0.433355 .01 .01
+1.3 0 0 0.436938 .01 .01
+1.31 0 0 0.440541 .01 .01
+1.32 0 0 0.444163 .01 .01
+1.33 0 0 0.447805 .01 .01
+1.34 0 0 0.451467 .01 .01
+1.35 0 0 0.455149 .01 .01
+1.36 0 0 0.458851 .01 .01
+1.37 0 0 0.462572 .01 .01
+1.38 0 0 0.466313 .01 .01
+1.39 0 0 0.470075 .01 .01
+1.4 0 0 0.473856 .01 .01
+1.41 0 0 0.477656 .01 .01
+1.42 0 0 0.481477 .01 .01
+1.43 0 0 0.485317 .01 .01
+1.44 0 0 0.489177 .01 .01
+1.45 0 0 0.493057 .01 .01
+1.46 0 0 0.496956 .01 .01
+1.47 0 0 0.500876 .01 .01
+1.48 0 0 0.504815 .01 .01
+1.49 0 0 0.508773 .01 .01
+1.5 0 0 0.512752 .01 .01
+1.51 0 0 0.516749 .01 .01
+1.52 0 0 0.520767 .01 .01
+1.53 0 0 0.524804 .01 .01
+1.54 0 0 0.52886 .01 .01
+1.55 0 0 0.532937 .01 .01
+1.56 0 0 0.537032 .01 .01
+1.57 0 0 0.541147 .01 .01
+1.58 0 0 0.545282 .01 .01
+1.59 0 0 0.549435 .01 .01
+1.6 0 0 0.553609 .01 .01
+1.61 0 0 0.557801 .01 .01
+1.62 0 0 0.562013 .01 .01
+1.63 0 0 0.566244 .01 .01
+1.64 0 0 0.570494 .01 .01
+1.65 0 0 0.574763 .01 .01
+1.66 0 0 0.579051 .01 .01
+1.67 0 0 0.583359 .01 .01
+1.68 0 0 0.587685 .01 .01
+1.69 0 0 0.59203 .01 .01
+1.7 0 0 0.596395 .01 .01
+1.71 0 0 0.600778 .01 .01
+1.72 0 0 0.605179 .01 .01
+1.73 0 0 0.6096 .01 .01
+1.74 0 0 0.614039 .01 .01
+1.75 0 0 0.618496 .01 .01
+1.76 0 0 0.622973 .01 .01
+1.77 0 0 0.627467 .01 .01
+1.78 0 0 0.63198 .01 .01
+1.79 0 0 0.636511 .01 .01
+1.8 0 0 0.641061 .01 .01
+1.81 0 0 0.645629 .01 .01
+1.82 0 0 0.650215 .01 .01
+1.83 0 0 0.654818 .01 .01
+1.84 0 0 0.65944 .01 .01
+1.85 0 0 0.66408 .01 .01
+1.86 0 0 0.668737 .01 .01
+1.87 0 0 0.673412 .01 .01
+1.88 0 0 0.678105 .01 .01
+1.89 0 0 0.682815 .01 .01
+1.9 0 0 0.687543 .01 .01
+1.91 0 0 0.692288 .01 .01
+1.92 0 0 0.697051 .01 .01
+1.93 0 0 0.70183 .01 .01
+1.94 0 0 0.706627 .01 .01
+1.95 0 0 0.71144 .01 .01
+1.96 0 0 0.716271 .01 .01
+1.97 0 0 0.721118 .01 .01
+1.98 0 0 0.725982 .01 .01
+1.99 0 0 0.730862 .01 .01
+2 0 0 0.735759 .01 .01
+2.01 0 0 0.740672 .01 .01
+2.02 0 0 0.745602 .01 .01
+2.03 0 0 0.750547 .01 .01
+2.04 0 0 0.755509 .01 .01
+2.05 0 0 0.760486 .01 .01
+2.06 0 0 0.76548 .01 .01
+2.07 0 0 0.770488 .01 .01
+2.08 0 0 0.775513 .01 .01
+2.09 0 0 0.780553 .01 .01
+2.1 0 0 0.785608 .01 .01
+2.11 0 0 0.790678 .01 .01
+2.12 0 0 0.795764 .01 .01
+2.13 0 0 0.800864 .01 .01
+2.14 0 0 0.805979 .01 .01
+2.15 0 0 0.811109 .01 .01
+2.16 0 0 0.816253 .01 .01
+2.17 0 0 0.821412 .01 .01
+2.18 0 0 0.826585 .01 .01
+2.19 0 0 0.831772 .01 .01
+2.2 0 0 0.836973 .01 .01
+2.21 0 0 0.842187 .01 .01
+2.22 0 0 0.847416 .01 .01
+2.23 0 0 0.852658 .01 .01
+2.24 0 0 0.857913 .01 .01
+2.25 0 0 0.863181 .01 .01
+2.26 0 0 0.868463 .01 .01
+2.27 0 0 0.873757 .01 .01
+2.28 0 0 0.879064 .01 .01
+2.29 0 0 0.884384 .01 .01
+2.3 0 0 0.889716 .01 .01
+2.31 0 0 0.895061 .01 .01
+2.32 0 0 0.900417 .01 .01
+2.33 0 0 0.905785 .01 .01
+2.34 0 0 0.911166 .01 .01
+2.35 0 0 0.916557 .01 .01
+2.36 0 0 0.921961 .01 .01
+2.37 0 0 0.927375 .01 .01
+2.38 0 0 0.9328 .01 .01
+2.39 0 0 0.938237 .01 .01
+2.4 0 0 0.943684 .01 .01
+2.41 0 0 0.949142 .01 .01
+2.42 0 0 0.95461 .01 .01
+2.43 0 0 0.960088 .01 .01
+2.44 0 0 0.965576 .01 .01
+2.45 0 0 0.971074 .01 .01
+2.46 0 0 0.976581 .01 .01
+2.47 0 0 0.982098 .01 .01
+2.48 0 0 0.987624 .01 .01
+2.49 0 0 0.99316 .01 .01
+2.5 0 0 0.998704 .01 .01
+2.51 0 0 1.00426 .01 .01
+2.52 0 0 1.00982 .01 .01
+2.53 0 0 1.01539 .01 .01
+2.54 0 0 1.02096 .01 .01
+2.55 0 0 1.02655 .01 .01
+2.56 0 0 1.03214 .01 .01
+2.57 0 0 1.03774 .01 .01
+2.58 0 0 1.04335 .01 .01
+2.59 0 0 1.04896 .01 .01
+2.6 0 0 1.05458 .01 .01
+2.61 0 0 1.06021 .01 .01
+2.62 0 0 1.06585 .01 .01
+2.63 0 0 1.07149 .01 .01
+2.64 0 0 1.07713 .01 .01
+2.65 0 0 1.08278 .01 .01
+2.66 0 0 1.08844 .01 .01
+2.67 0 0 1.0941 .01 .01
+2.68 0 0 1.09977 .01 .01
+2.69 0 0 1.10544 .01 .01
+2.7 0 0 1.11112 .01 .01
+2.71 0 0 1.1168 .01 .01
+2.72 0 0 1.12249 .01 .01
+2.73 0 0 1.12818 .01 .01
+2.74 0 0 1.13387 .01 .01
+2.75 0 0 1.13957 .01 .01
+2.76 0 0 1.14527 .01 .01
+2.77 0 0 1.15097 .01 .01
+2.78 0 0 1.15667 .01 .01
+2.79 0 0 1.16238 .01 .01
+2.8 0 0 1.16809 .01 .01
+2.81 0 0 1.1738 .01 .01
+2.82 0 0 1.17951 .01 .01
+2.83 0 0 1.18523 .01 .01
+2.84 0 0 1.19095 .01 .01
+2.85 0 0 1.19666 .01 .01
+2.86 0 0 1.20238 .01 .01
+2.87 0 0 1.2081 .01 .01
+2.88 0 0 1.21382 .01 .01
+2.89 0 0 1.21953 .01 .01
+2.9 0 0 1.22525 .01 .01
+2.91 0 0 1.23097 .01 .01
+2.92 0 0 1.23669 .01 .01
+2.93 0 0 1.2424 .01 .01
+2.94 0 0 1.24812 .01 .01
+2.95 0 0 1.25383 .01 .01
+2.96 0 0 1.25954 .01 .01
+2.97 0 0 1.26525 .01 .01
+2.98 0 0 1.27096 .01 .01
+2.99 0 0 1.27666 .01 .01
+3 0 0 1.28236 .01 .01
+3.01 0 0 1.28806 .01 .01
+3.02 0 0 1.29375 .01 .01
+3.03 0 0 1.29944 .01 .01
+3.04 0 0 1.30513 .01 .01
+3.05 0 0 1.31081 .01 .01
+3.06 0 0 1.31649 .01 .01
+3.07 0 0 1.32216 .01 .01
+3.08 0 0 1.32783 .01 .01
+3.09 0 0 1.33349 .01 .01
+3.1 0 0 1.33915 .01 .01
+3.11 0 0 1.3448 .01 .01
+3.12 0 0 1.35045 .01 .01
+3.13 0 0 1.35609 .01 .01
+3.14 0 0 1.36172 .01 .01
+3.15 0 0 1.36734 .01 .01
+3.16 0 0 1.37296 .01 .01
+3.17 0 0 1.37857 .01 .01
+3.18 0 0 1.38417 .01 .01
+3.19 0 0 1.38977 .01 .01
+3.2 0 0 1.39535 .01 .01
+3.21 0 0 1.40093 .01 .01
+3.22 0 0 1.4065 .01 .01
+3.23 0 0 1.41206 .01 .01
+3.24 0 0 1.41761 .01 .01
+3.25 0 0 1.42315 .01 .01
+3.26 0 0 1.42867 .01 .01
+3.27 0 0 1.43419 .01 .01
+3.28 0 0 1.4397 .01 .01
+3.29 0 0 1.4452 .01 .01
+3.3 0 0 1.45069 .01 .01
+3.31 0 0 1.45616 .01 .01
+3.32 0 0 1.46162 .01 .01
+3.33 0 0 1.46707 .01 .01
+3.34 0 0 1.47251 .01 .01
+3.35 0 0 1.47794 .01 .01
+3.36 0 0 1.48335 .01 .01
+3.37 0 0 1.48875 .01 .01
+3.38 0 0 1.49413 .01 .01
+3.39 0 0 1.49951 .01 .01
+3.4 0 0 1.50486 .01 .01
+3.41 0 0 1.51021 .01 .01
+3.42 0 0 1.51554 .01 .01
+3.43 0 0 1.52085 .01 .01
+3.44 0 0 1.52615 .01 .01
+3.45 0 0 1.53143 .01 .01
+3.46 0 0 1.5367 .01 .01
+3.47 0 0 1.54195 .01 .01
+3.48 0 0 1.54718 .01 .01
+3.49 0 0 1.5524 .01 .01
+3.5 0 0 1.5576 .01 .01
+3.51 0 0 1.56278 .01 .01
+3.52 0 0 1.56795 .01 .01
+3.53 0 0 1.5731 .01 .01
+3.54 0 0 1.57823 .01 .01
+3.55 0 0 1.58334 .01 .01
+3.56 0 0 1.58843 .01 .01
+3.57 0 0 1.59351 .01 .01
+3.58 0 0 1.59856 .01 .01
+3.59 0 0 1.60359 .01 .01
+3.6 0 0 1.60861 .01 .01
+3.61 0 0 1.6136 .01 .01
+3.62 0 0 1.61858 .01 .01
+3.63 0 0 1.62353 .01 .01
+3.64 0 0 1.62846 .01 .01
+3.65 0 0 1.63337 .01 .01
+3.66 0 0 1.63826 .01 .01
+3.67 0 0 1.64313 .01 .01
+3.68 0 0 1.64797 .01 .01
+3.69 0 0 1.6528 .01 .01
+3.7 0 0 1.6576 .01 .01
+3.71 0 0 1.66237 .01 .01
+3.72 0 0 1.66713 .01 .01
+3.73 0 0 1.67186 .01 .01
+3.74 0 0 1.67657 .01 .01
+3.75 0 0 1.68125 .01 .01
+3.76 0 0 1.68591 .01 .01
+3.77 0 0 1.69054 .01 .01
+3.78 0 0 1.69515 .01 .01
+3.79 0 0 1.69973 .01 .01
+3.8 0 0 1.70429 .01 .01
+3.81 0 0 1.70882 .01 .01
+3.82 0 0 1.71333 .01 .01
+3.83 0 0 1.7178 .01 .01
+3.84 0 0 1.72226 .01 .01
+3.85 0 0 1.72668 .01 .01
+3.86 0 0 1.73108 .01 .01
+3.87 0 0 1.73545 .01 .01
+3.88 0 0 1.7398 .01 .01
+3.89 0 0 1.74411 .01 .01
+3.9 0 0 1.7484 .01 .01
+3.91 0 0 1.75266 .01 .01
+3.92 0 0 1.75689 .01 .01
+3.93 0 0 1.7611 .01 .01
+3.94 0 0 1.76527 .01 .01
+3.95 0 0 1.76941 .01 .01
+3.96 0 0 1.77353 .01 .01
+3.97 0 0 1.77761 .01 .01
+3.98 0 0 1.78166 .01 .01
+3.99 0 0 1.78569 .01 .01
+4 0 0 1.78968 .01 .01
+4.01 0 0 1.79364 .01 .01
+4.02 0 0 1.79757 .01 .01
+4.03 0 0 1.80147 .01 .01
+4.04 0 0 1.80534 .01 .01
+4.05 0 0 1.80917 .01 .01
+4.06 0 0 1.81298 .01 .01
+4.07 0 0 1.81675 .01 .01
+4.08 0 0 1.82048 .01 .01
+4.09 0 0 1.82419 .01 .01
+4.1 0 0 1.82786 .01 .01
+4.11 0 0 1.8315 .01 .01
+4.12 0 0 1.83511 .01 .01
+4.13 0 0 1.83868 .01 .01
+4.14 0 0 1.84222 .01 .01
+4.15 0 0 1.84572 .01 .01
+4.16 0 0 1.84919 .01 .01
+4.17 0 0 1.85262 .01 .01
+4.18 0 0 1.85602 .01 .01
+4.19 0 0 1.85939 .01 .01
+4.2 0 0 1.86272 .01 .01
+4.21 0 0 1.86601 .01 .01
+4.22 0 0 1.86927 .01 .01
+4.23 0 0 1.87249 .01 .01
+4.24 0 0 1.87568 .01 .01
+4.25 0 0 1.87883 .01 .01
+4.26 0 0 1.88194 .01 .01
+4.27 0 0 1.88502 .01 .01
+4.28 0 0 1.88805 .01 .01
+4.29 0 0 1.89106 .01 .01
+4.3 0 0 1.89402 .01 .01
+4.31 0 0 1.89695 .01 .01
+4.32 0 0 1.89984 .01 .01
+4.33 0 0 1.90269 .01 .01
+4.34 0 0 1.90551 .01 .01
+4.35 0 0 1.90828 .01 .01
+4.36 0 0 1.91102 .01 .01
+4.37 0 0 1.91372 .01 .01
+4.38 0 0 1.91638 .01 .01
+4.39 0 0 1.919 .01 .01
+4.4 0 0 1.92158 .01 .01
+4.41 0 0 1.92412 .01 .01
+4.42 0 0 1.92662 .01 .01
+4.43 0 0 1.92909 .01 .01
+4.44 0 0 1.93151 .01 .01
+4.45 0 0 1.93389 .01 .01
+4.46 0 0 1.93624 .01 .01
+4.47 0 0 1.93854 .01 .01
+4.48 0 0 1.9408 .01 .01
+4.49 0 0 1.94303 .01 .01
+4.5 0 0 1.94521 .01 .01
+4.51 0 0 1.94735 .01 .01
+4.52 0 0 1.94945 .01 .01
+4.53 0 0 1.95151 .01 .01
+4.54 0 0 1.95353 .01 .01
+4.55 0 0 1.9555 .01 .01
+4.56 0 0 1.95744 .01 .01
+4.57 0 0 1.95933 .01 .01
+4.58 0 0 1.96118 .01 .01
+4.59 0 0 1.96299 .01 .01
+4.6 0 0 1.96476 .01 .01
+4.61 0 0 1.96648 .01 .01
+4.62 0 0 1.96817 .01 .01
+4.63 0 0 1.96981 .01 .01
+4.64 0 0 1.97141 .01 .01
+4.65 0 0 1.97296 .01 .01
+4.66 0 0 1.97448 .01 .01
+4.67 0 0 1.97595 .01 .01
+4.68 0 0 1.97737 .01 .01
+4.69 0 0 1.97876 .01 .01
+4.7 0 0 1.9801 .01 .01
+4.71 0 0 1.9814 .01 .01
+4.72 0 0 1.98265 .01 .01
+4.73 0 0 1.98387 .01 .01
+4.74 0 0 1.98503 .01 .01
+4.75 0 0 1.98616 .01 .01
+4.76 0 0 1.98724 .01 .01
+4.77 0 0 1.98828 .01 .01
+4.78 0 0 1.98927 .01 .01
+4.79 0 0 1.99022 .01 .01
+4.8 0 0 1.99113 .01 .01
+4.81 0 0 1.99199 .01 .01
+4.82 0 0 1.99281 .01 .01
+4.83 0 0 1.99359 .01 .01
+4.84 0 0 1.99432 .01 .01
+4.85 0 0 1.99501 .01 .01
+4.86 0 0 1.99565 .01 .01
+4.87 0 0 1.99625 .01 .01
+4.88 0 0 1.9968 .01 .01
+4.89 0 0 1.99731 .01 .01
+4.9 0 0 1.99778 .01 .01
+4.91 0 0 1.9982 .01 .01
+4.92 0 0 1.99858 .01 .01
+4.93 0 0 1.99891 .01 .01
+4.94 0 0 1.9992 .01 .01
+4.95 0 0 1.99944 .01 .01
+4.96 0 0 1.99964 .01 .01
+4.97 0 0 1.9998 .01 .01
+4.98 0 0 1.99991 .01 .01
+4.99 0 0 1.99998 .01 .01
+5 0 0 2 .01 .01
+5.01 0 0 1.99998 .01 .01
+5.02 0 0 1.99991 .01 .01
+5.03 0 0 1.9998 .01 .01
+5.04 0 0 1.99964 .01 .01
+5.05 0 0 1.99944 .01 .01
+5.06 0 0 1.9992 .01 .01
+5.07 0 0 1.99891 .01 .01
+5.08 0 0 1.99858 .01 .01
+5.09 0 0 1.9982 .01 .01
+5.1 0 0 1.99778 .01 .01
+5.11 0 0 1.99731 .01 .01
+5.12 0 0 1.9968 .01 .01
+5.13 0 0 1.99625 .01 .01
+5.14 0 0 1.99565 .01 .01
+5.15 0 0 1.99501 .01 .01
+5.16 0 0 1.99432 .01 .01
+5.17 0 0 1.99359 .01 .01
+5.18 0 0 1.99281 .01 .01
+5.19 0 0 1.99199 .01 .01
+5.2 0 0 1.99113 .01 .01
+5.21 0 0 1.99022 .01 .01
+5.22 0 0 1.98927 .01 .01
+5.23 0 0 1.98828 .01 .01
+5.24 0 0 1.98724 .01 .01
+5.25 0 0 1.98616 .01 .01
+5.26 0 0 1.98503 .01 .01
+5.27 0 0 1.98387 .01 .01
+5.28 0 0 1.98265 .01 .01
+5.29 0 0 1.9814 .01 .01
+5.3 0 0 1.9801 .01 .01
+5.31 0 0 1.97876 .01 .01
+5.32 0 0 1.97737 .01 .01
+5.33 0 0 1.97595 .01 .01
+5.34 0 0 1.97448 .01 .01
+5.35 0 0 1.97296 .01 .01
+5.36 0 0 1.97141 .01 .01
+5.37 0 0 1.96981 .01 .01
+5.38 0 0 1.96817 .01 .01
+5.39 0 0 1.96648 .01 .01
+5.4 0 0 1.96476 .01 .01
+5.41 0 0 1.96299 .01 .01
+5.42 0 0 1.96118 .01 .01
+5.43 0 0 1.95933 .01 .01
+5.44 0 0 1.95744 .01 .01
+5.45 0 0 1.9555 .01 .01
+5.46 0 0 1.95353 .01 .01
+5.47 0 0 1.95151 .01 .01
+5.48 0 0 1.94945 .01 .01
+5.49 0 0 1.94735 .01 .01
+5.5 0 0 1.94521 .01 .01
+5.51 0 0 1.94303 .01 .01
+5.52 0 0 1.9408 .01 .01
+5.53 0 0 1.93854 .01 .01
+5.54 0 0 1.93624 .01 .01
+5.55 0 0 1.93389 .01 .01
+5.56 0 0 1.93151 .01 .01
+5.57 0 0 1.92909 .01 .01
+5.58 0 0 1.92662 .01 .01
+5.59 0 0 1.92412 .01 .01
+5.6 0 0 1.92158 .01 .01
+5.61 0 0 1.919 .01 .01
+5.62 0 0 1.91638 .01 .01
+5.63 0 0 1.91372 .01 .01
+5.64 0 0 1.91102 .01 .01
+5.65 0 0 1.90828 .01 .01
+5.66 0 0 1.90551 .01 .01
+5.67 0 0 1.90269 .01 .01
+5.68 0 0 1.89984 .01 .01
+5.69 0 0 1.89695 .01 .01
+5.7 0 0 1.89402 .01 .01
+5.71 0 0 1.89106 .01 .01
+5.72 0 0 1.88805 .01 .01
+5.73 0 0 1.88502 .01 .01
+5.74 0 0 1.88194 .01 .01
+5.75 0 0 1.87883 .01 .01
+5.76 0 0 1.87568 .01 .01
+5.77 0 0 1.87249 .01 .01
+5.78 0 0 1.86927 .01 .01
+5.79 0 0 1.86601 .01 .01
+5.8 0 0 1.86272 .01 .01
+5.81 0 0 1.85939 .01 .01
+5.82 0 0 1.85602 .01 .01
+5.83 0 0 1.85262 .01 .01
+5.84 0 0 1.84919 .01 .01
+5.85 0 0 1.84572 .01 .01
+5.86 0 0 1.84222 .01 .01
+5.87 0 0 1.83868 .01 .01
+5.88 0 0 1.83511 .01 .01
+5.89 0 0 1.8315 .01 .01
+5.9 0 0 1.82786 .01 .01
+5.91 0 0 1.82419 .01 .01
+5.92 0 0 1.82048 .01 .01
+5.93 0 0 1.81675 .01 .01
+5.94 0 0 1.81298 .01 .01
+5.95 0 0 1.80917 .01 .01
+5.96 0 0 1.80534 .01 .01
+5.97 0 0 1.80147 .01 .01
+5.98 0 0 1.79757 .01 .01
+5.99 0 0 1.79364 .01 .01
+6 0 0 1.78968 .01 .01
+6.01 0 0 1.78569 .01 .01
+6.02 0 0 1.78166 .01 .01
+6.03 0 0 1.77761 .01 .01
+6.04 0 0 1.77353 .01 .01
+6.05 0 0 1.76941 .01 .01
+6.06 0 0 1.76527 .01 .01
+6.07 0 0 1.7611 .01 .01
+6.08 0 0 1.75689 .01 .01
+6.09 0 0 1.75266 .01 .01
+6.1 0 0 1.7484 .01 .01
+6.11 0 0 1.74411 .01 .01
+6.12 0 0 1.7398 .01 .01
+6.13 0 0 1.73545 .01 .01
+6.14 0 0 1.73108 .01 .01
+6.15 0 0 1.72668 .01 .01
+6.16 0 0 1.72226 .01 .01
+6.17 0 0 1.7178 .01 .01
+6.18 0 0 1.71333 .01 .01
+6.19 0 0 1.70882 .01 .01
+6.2 0 0 1.70429 .01 .01
+6.21 0 0 1.69973 .01 .01
+6.22 0 0 1.69515 .01 .01
+6.23 0 0 1.69054 .01 .01
+6.24 0 0 1.68591 .01 .01
+6.25 0 0 1.68125 .01 .01
+6.26 0 0 1.67657 .01 .01
+6.27 0 0 1.67186 .01 .01
+6.28 0 0 1.66713 .01 .01
+6.29 0 0 1.66237 .01 .01
+6.3 0 0 1.6576 .01 .01
+6.31 0 0 1.6528 .01 .01
+6.32 0 0 1.64797 .01 .01
+6.33 0 0 1.64313 .01 .01
+6.34 0 0 1.63826 .01 .01
+6.35 0 0 1.63337 .01 .01
+6.36 0 0 1.62846 .01 .01
+6.37 0 0 1.62353 .01 .01
+6.38 0 0 1.61858 .01 .01
+6.39 0 0 1.6136 .01 .01
+6.4 0 0 1.60861 .01 .01
+6.41 0 0 1.60359 .01 .01
+6.42 0 0 1.59856 .01 .01
+6.43 0 0 1.59351 .01 .01
+6.44 0 0 1.58843 .01 .01
+6.45 0 0 1.58334 .01 .01
+6.46 0 0 1.57823 .01 .01
+6.47 0 0 1.5731 .01 .01
+6.48 0 0 1.56795 .01 .01
+6.49 0 0 1.56278 .01 .01
+6.5 0 0 1.5576 .01 .01
+6.51 0 0 1.5524 .01 .01
+6.52 0 0 1.54718 .01 .01
+6.53 0 0 1.54195 .01 .01
+6.54 0 0 1.5367 .01 .01
+6.55 0 0 1.53143 .01 .01
+6.56 0 0 1.52615 .01 .01
+6.57 0 0 1.52085 .01 .01
+6.58 0 0 1.51554 .01 .01
+6.59 0 0 1.51021 .01 .01
+6.6 0 0 1.50486 .01 .01
+6.61 0 0 1.49951 .01 .01
+6.62 0 0 1.49413 .01 .01
+6.63 0 0 1.48875 .01 .01
+6.64 0 0 1.48335 .01 .01
+6.65 0 0 1.47794 .01 .01
+6.66 0 0 1.47251 .01 .01
+6.67 0 0 1.46707 .01 .01
+6.68 0 0 1.46162 .01 .01
+6.69 0 0 1.45616 .01 .01
+6.7 0 0 1.45069 .01 .01
+6.71 0 0 1.4452 .01 .01
+6.72 0 0 1.4397 .01 .01
+6.73 0 0 1.43419 .01 .01
+6.74 0 0 1.42867 .01 .01
+6.75 0 0 1.42315 .01 .01
+6.76 0 0 1.41761 .01 .01
+6.77 0 0 1.41206 .01 .01
+6.78 0 0 1.4065 .01 .01
+6.79 0 0 1.40093 .01 .01
+6.8 0 0 1.39535 .01 .01
+6.81 0 0 1.38977 .01 .01
+6.82 0 0 1.38417 .01 .01
+6.83 0 0 1.37857 .01 .01
+6.84 0 0 1.37296 .01 .01
+6.85 0 0 1.36734 .01 .01
+6.86 0 0 1.36172 .01 .01
+6.87 0 0 1.35609 .01 .01
+6.88 0 0 1.35045 .01 .01
+6.89 0 0 1.3448 .01 .01
+6.9 0 0 1.33915 .01 .01
+6.91 0 0 1.33349 .01 .01
+6.92 0 0 1.32783 .01 .01
+6.93 0 0 1.32216 .01 .01
+6.94 0 0 1.31649 .01 .01
+6.95 0 0 1.31081 .01 .01
+6.96 0 0 1.30513 .01 .01
+6.97 0 0 1.29944 .01 .01
+6.98 0 0 1.29375 .01 .01
+6.99 0 0 1.28806 .01 .01
+7 0 0 1.28236 .01 .01
+7.01 0 0 1.27666 .01 .01
+7.02 0 0 1.27096 .01 .01
+7.03 0 0 1.26525 .01 .01
+7.04 0 0 1.25954 .01 .01
+7.05 0 0 1.25383 .01 .01
+7.06 0 0 1.24812 .01 .01
+7.07 0 0 1.2424 .01 .01
+7.08 0 0 1.23669 .01 .01
+7.09 0 0 1.23097 .01 .01
+7.1 0 0 1.22525 .01 .01
+7.11 0 0 1.21953 .01 .01
+7.12 0 0 1.21382 .01 .01
+7.13 0 0 1.2081 .01 .01
+7.14 0 0 1.20238 .01 .01
+7.15 0 0 1.19666 .01 .01
+7.16 0 0 1.19095 .01 .01
+7.17 0 0 1.18523 .01 .01
+7.18 0 0 1.17951 .01 .01
+7.19 0 0 1.1738 .01 .01
+7.2 0 0 1.16809 .01 .01
+7.21 0 0 1.16238 .01 .01
+7.22 0 0 1.15667 .01 .01
+7.23 0 0 1.15097 .01 .01
+7.24 0 0 1.14527 .01 .01
+7.25 0 0 1.13957 .01 .01
+7.26 0 0 1.13387 .01 .01
+7.27 0 0 1.12818 .01 .01
+7.28 0 0 1.12249 .01 .01
+7.29 0 0 1.1168 .01 .01
+7.3 0 0 1.11112 .01 .01
+7.31 0 0 1.10544 .01 .01
+7.32 0 0 1.09977 .01 .01
+7.33 0 0 1.0941 .01 .01
+7.34 0 0 1.08844 .01 .01
+7.35 0 0 1.08278 .01 .01
+7.36 0 0 1.07713 .01 .01
+7.37 0 0 1.07149 .01 .01
+7.38 0 0 1.06585 .01 .01
+7.39 0 0 1.06021 .01 .01
+7.4 0 0 1.05458 .01 .01
+7.41 0 0 1.04896 .01 .01
+7.42 0 0 1.04335 .01 .01
+7.43 0 0 1.03774 .01 .01
+7.44 0 0 1.03214 .01 .01
+7.45 0 0 1.02655 .01 .01
+7.46 0 0 1.02096 .01 .01
+7.47 0 0 1.01539 .01 .01
+7.48 0 0 1.00982 .01 .01
+7.49 0 0 1.00426 .01 .01
+7.5 0 0 0.998704 .01 .01
+7.51 0 0 0.99316 .01 .01
+7.52 0 0 0.987624 .01 .01
+7.53 0 0 0.982098 .01 .01
+7.54 0 0 0.976581 .01 .01
+7.55 0 0 0.971074 .01 .01
+7.56 0 0 0.965576 .01 .01
+7.57 0 0 0.960088 .01 .01
+7.58 0 0 0.95461 .01 .01
+7.59 0 0 0.949142 .01 .01
+7.6 0 0 0.943684 .01 .01
+7.61 0 0 0.938237 .01 .01
+7.62 0 0 0.9328 .01 .01
+7.63 0 0 0.927375 .01 .01
+7.64 0 0 0.921961 .01 .01
+7.65 0 0 0.916557 .01 .01
+7.66 0 0 0.911166 .01 .01
+7.67 0 0 0.905785 .01 .01
+7.68 0 0 0.900417 .01 .01
+7.69 0 0 0.895061 .01 .01
+7.7 0 0 0.889716 .01 .01
+7.71 0 0 0.884384 .01 .01
+7.72 0 0 0.879064 .01 .01
+7.73 0 0 0.873757 .01 .01
+7.74 0 0 0.868463 .01 .01
+7.75 0 0 0.863181 .01 .01
+7.76 0 0 0.857913 .01 .01
+7.77 0 0 0.852658 .01 .01
+7.78 0 0 0.847416 .01 .01
+7.79 0 0 0.842187 .01 .01
+7.8 0 0 0.836973 .01 .01
+7.81 0 0 0.831772 .01 .01
+7.82 0 0 0.826585 .01 .01
+7.83 0 0 0.821412 .01 .01
+7.84 0 0 0.816253 .01 .01
+7.85 0 0 0.811109 .01 .01
+7.86 0 0 0.805979 .01 .01
+7.87 0 0 0.800864 .01 .01
+7.88 0 0 0.795764 .01 .01
+7.89 0 0 0.790678 .01 .01
+7.9 0 0 0.785608 .01 .01
+7.91 0 0 0.780553 .01 .01
+7.92 0 0 0.775513 .01 .01
+7.93 0 0 0.770488 .01 .01
+7.94 0 0 0.76548 .01 .01
+7.95 0 0 0.760486 .01 .01
+7.96 0 0 0.755509 .01 .01
+7.97 0 0 0.750547 .01 .01
+7.98 0 0 0.745602 .01 .01
+7.99 0 0 0.740672 .01 .01
+8 0 0 0.735759 .01 .01
+8.01 0 0 0.730862 .01 .01
+8.02 0 0 0.725982 .01 .01
+8.03 0 0 0.721118 .01 .01
+8.04 0 0 0.716271 .01 .01
+8.05 0 0 0.71144 .01 .01
+8.06 0 0 0.706627 .01 .01
+8.07 0 0 0.70183 .01 .01
+8.08 0 0 0.697051 .01 .01
+8.09 0 0 0.692288 .01 .01
+8.1 0 0 0.687543 .01 .01
+8.11 0 0 0.682815 .01 .01
+8.12 0 0 0.678105 .01 .01
+8.13 0 0 0.673412 .01 .01
+8.14 0 0 0.668737 .01 .01
+8.15 0 0 0.66408 .01 .01
+8.16 0 0 0.65944 .01 .01
+8.17 0 0 0.654818 .01 .01
+8.18 0 0 0.650215 .01 .01
+8.19 0 0 0.645629 .01 .01
+8.2 0 0 0.641061 .01 .01
+8.21 0 0 0.636511 .01 .01
+8.22 0 0 0.63198 .01 .01
+8.23 0 0 0.627467 .01 .01
+8.24 0 0 0.622973 .01 .01
+8.25 0 0 0.618496 .01 .01
+8.26 0 0 0.614039 .01 .01
+8.27 0 0 0.6096 .01 .01
+8.28 0 0 0.605179 .01 .01
+8.29 0 0 0.600778 .01 .01
+8.3 0 0 0.596395 .01 .01
+8.31 0 0 0.59203 .01 .01
+8.32 0 0 0.587685 .01 .01
+8.33 0 0 0.583359 .01 .01
+8.34 0 0 0.579051 .01 .01
+8.35 0 0 0.574763 .01 .01
+8.36 0 0 0.570494 .01 .01
+8.37 0 0 0.566244 .01 .01
+8.38 0 0 0.562013 .01 .01
+8.39 0 0 0.557801 .01 .01
+8.4 0 0 0.553609 .01 .01
+8.41 0 0 0.549435 .01 .01
+8.42 0 0 0.545282 .01 .01
+8.43 0 0 0.541147 .01 .01
+8.44 0 0 0.537032 .01 .01
+8.45 0 0 0.532937 .01 .01
+8.46 0 0 0.52886 .01 .01
+8.47 0 0 0.524804 .01 .01
+8.48 0 0 0.520767 .01 .01
+8.49 0 0 0.516749 .01 .01
+8.5 0 0 0.512752 .01 .01
+8.51 0 0 0.508773 .01 .01
+8.52 0 0 0.504815 .01 .01
+8.53 0 0 0.500876 .01 .01
+8.54 0 0 0.496956 .01 .01
+8.55 0 0 0.493057 .01 .01
+8.56 0 0 0.489177 .01 .01
+8.57 0 0 0.485317 .01 .01
+8.58 0 0 0.481477 .01 .01
+8.59 0 0 0.477656 .01 .01
+8.6 0 0 0.473856 .01 .01
+8.61 0 0 0.470075 .01 .01
+8.62 0 0 0.466313 .01 .01
+8.63 0 0 0.462572 .01 .01
+8.64 0 0 0.458851 .01 .01
+8.65 0 0 0.455149 .01 .01
+8.66 0 0 0.451467 .01 .01
+8.67 0 0 0.447805 .01 .01
+8.68 0 0 0.444163 .01 .01
+8.69 0 0 0.440541 .01 .01
+8.7 0 0 0.436938 .01 .01
+8.71 0 0 0.433355 .01 .01
+8.72 0 0 0.429792 .01 .01
+8.73 0 0 0.426249 .01 .01
+8.74 0 0 0.422726 .01 .01
+8.75 0 0 0.419223 .01 .01
+8.76 0 0 0.415739 .01 .01
+8.77 0 0 0.412275 .01 .01
+8.78 0 0 0.408831 .01 .01
+8.79 0 0 0.405407 .01 .01
+8.8 0 0 0.402002 .01 .01
+8.81 0 0 0.398618 .01 .01
+8.82 0 0 0.395252 .01 .01
+8.83 0 0 0.391907 .01 .01
+8.84 0 0 0.388581 .01 .01
+8.85 0 0 0.385275 .01 .01
+8.86 0 0 0.381989 .01 .01
+8.87 0 0 0.378722 .01 .01
+8.88 0 0 0.375475 .01 .01
+8.89 0 0 0.372247 .01 .01
+8.9 0 0 0.369039 .01 .01
+8.91 0 0 0.36585 .01 .01
+8.92 0 0 0.362681 .01 .01
+8.93 0 0 0.359532 .01 .01
+8.94 0 0 0.356402 .01 .01
+8.95 0 0 0.353291 .01 .01
+8.96 0 0 0.350199 .01 .01
+8.97 0 0 0.347127 .01 .01
+8.98 0 0 0.344074 .01 .01
+8.99 0 0 0.341041 .01 .01
+9 0 0 0.338027 .01 .01
+9.01 0 0 0.335032 .01 .01
+9.02 0 0 0.332056 .01 .01
+9.03 0 0 0.329099 .01 .01
+9.04 0 0 0.326161 .01 .01
+9.05 0 0 0.323242 .01 .01
+9.06 0 0 0.320343 .01 .01
+9.07 0 0 0.317462 .01 .01
+9.08 0 0 0.3146 .01 .01
+9.09 0 0 0.311757 .01 .01
+9.1 0 0 0.308933 .01 .01
+9.11 0 0 0.306128 .01 .01
+9.12 0 0 0.303341 .01 .01
+9.13 0 0 0.300573 .01 .01
+9.14 0 0 0.297824 .01 .01
+9.15 0 0 0.295093 .01 .01
+9.16 0 0 0.292381 .01 .01
+9.17 0 0 0.289687 .01 .01
+9.18 0 0 0.287012 .01 .01
+9.19 0 0 0.284355 .01 .01
+9.2 0 0 0.281717 .01 .01
+9.21 0 0 0.279097 .01 .01
+9.22 0 0 0.276495 .01 .01
+9.23 0 0 0.273911 .01 .01
+9.24 0 0 0.271345 .01 .01
+9.25 0 0 0.268797 .01 .01
+9.26 0 0 0.266268 .01 .01
+9.27 0 0 0.263756 .01 .01
+9.28 0 0 0.261262 .01 .01
+9.29 0 0 0.258786 .01 .01
+9.3 0 0 0.256328 .01 .01
+9.31 0 0 0.253888 .01 .01
+9.32 0 0 0.251465 .01 .01
+9.33 0 0 0.249059 .01 .01
+9.34 0 0 0.246672 .01 .01
+9.35 0 0 0.244301 .01 .01
+9.36 0 0 0.241948 .01 .01
+9.37 0 0 0.239613 .01 .01
+9.38 0 0 0.237295 .01 .01
+9.39 0 0 0.234994 .01 .01
+9.4 0 0 0.23271 .01 .01
+9.41 0 0 0.230443 .01 .01
+9.42 0 0 0.228193 .01 .01
+9.43 0 0 0.22596 .01 .01
+9.44 0 0 0.223744 .01 .01
+9.45 0 0 0.221545 .01 .01
+9.46 0 0 0.219362 .01 .01
+9.47 0 0 0.217196 .01 .01
+9.48 0 0 0.215047 .01 .01
+9.49 0 0 0.212915 .01 .01
+9.5 0 0 0.210798 .01 .01
+9.51 0 0 0.208699 .01 .01
+9.52 0 0 0.206615 .01 .01
+9.53 0 0 0.204548 .01 .01
+9.54 0 0 0.202497 .01 .01
+9.55 0 0 0.200462 .01 .01
+9.56 0 0 0.198443 .01 .01
+9.57 0 0 0.19644 .01 .01
+9.58 0 0 0.194453 .01 .01
+9.59 0 0 0.192482 .01 .01
+9.6 0 0 0.190527 .01 .01
+9.61 0 0 0.188587 .01 .01
+9.62 0 0 0.186663 .01 .01
+9.63 0 0 0.184754 .01 .01
+9.64 0 0 0.182861 .01 .01
+9.65 0 0 0.180983 .01 .01
+9.66 0 0 0.17912 .01 .01
+9.67 0 0 0.177273 .01 .01
+9.68 0 0 0.175441 .01 .01
+9.69 0 0 0.173624 .01 .01
+9.7 0 0 0.171822 .01 .01
+9.71 0 0 0.170035 .01 .01
+9.72 0 0 0.168262 .01 .01
+9.73 0 0 0.166505 .01 .01
+9.74 0 0 0.164762 .01 .01
+9.75 0 0 0.163034 .01 .01
+9.76 0 0 0.16132 .01 .01
+9.77 0 0 0.159621 .01 .01
+9.78 0 0 0.157936 .01 .01
+9.79 0 0 0.156266 .01 .01
+9.8 0 0 0.154609 .01 .01
+9.81 0 0 0.152967 .01 .01
+9.82 0 0 0.151339 .01 .01
+9.83 0 0 0.149725 .01 .01
+9.84 0 0 0.148125 .01 .01
+9.85 0 0 0.146539 .01 .01
+9.86 0 0 0.144966 .01 .01
+9.87 0 0 0.143408 .01 .01
+9.88 0 0 0.141862 .01 .01
+9.89 0 0 0.140331 .01 .01
+9.9 0 0 0.138813 .01 .01
+9.91 0 0 0.137308 .01 .01
+9.92 0 0 0.135816 .01 .01
+9.93 0 0 0.134338 .01 .01
+9.94 0 0 0.132873 .01 .01
+9.95 0 0 0.131421 .01 .01
+9.96 0 0 0.129981 .01 .01
+9.97 0 0 0.128555 .01 .01
+9.98 0 0 0.127142 .01 .01
+9.99 0 0 0.125741 .01 .01
+10 0 0 0.124353 .01 .01
diff --git a/samples/linear.dat b/samples/linear.dat
new file mode 100644
index 0000000..03849b6
--- /dev/null
+++ b/samples/linear.dat
@@ -0,0 +1,4 @@
+0 0 0 4 1 1
+1 0 0 7 1 1
+2 0 0 10 1 1
+3 0 0 13 1 1
diff --git a/samples/powerlaw.dat b/samples/powerlaw.dat
new file mode 100644
index 0000000..ef67d32
--- /dev/null
+++ b/samples/powerlaw.dat
@@ -0,0 +1,901 @@
+1 0 0 5 .01 .01
+1.01 0 0 4.94557 .01 .01
+1.02 0 0 4.89226 .01 .01
+1.03 0 0 4.84004 .01 .01
+1.04 0 0 4.78887 .01 .01
+1.05 0 0 4.73873 .01 .01
+1.06 0 0 4.68958 .01 .01
+1.07 0 0 4.64139 .01 .01
+1.08 0 0 4.59414 .01 .01
+1.09 0 0 4.54779 .01 .01
+1.1 0 0 4.50234 .01 .01
+1.11 0 0 4.45774 .01 .01
+1.12 0 0 4.41398 .01 .01
+1.13 0 0 4.37103 .01 .01
+1.14 0 0 4.32887 .01 .01
+1.15 0 0 4.28748 .01 .01
+1.16 0 0 4.24684 .01 .01
+1.17 0 0 4.20693 .01 .01
+1.18 0 0 4.16773 .01 .01
+1.19 0 0 4.12922 .01 .01
+1.2 0 0 4.09139 .01 .01
+1.21 0 0 4.05421 .01 .01
+1.22 0 0 4.01767 .01 .01
+1.23 0 0 3.98175 .01 .01
+1.24 0 0 3.94645 .01 .01
+1.25 0 0 3.91173 .01 .01
+1.26 0 0 3.87759 .01 .01
+1.27 0 0 3.84402 .01 .01
+1.28 0 0 3.811 .01 .01
+1.29 0 0 3.77852 .01 .01
+1.3 0 0 3.74656 .01 .01
+1.31 0 0 3.71511 .01 .01
+1.32 0 0 3.68416 .01 .01
+1.33 0 0 3.6537 .01 .01
+1.34 0 0 3.62372 .01 .01
+1.35 0 0 3.59421 .01 .01
+1.36 0 0 3.56515 .01 .01
+1.37 0 0 3.53653 .01 .01
+1.38 0 0 3.50835 .01 .01
+1.39 0 0 3.4806 .01 .01
+1.4 0 0 3.45326 .01 .01
+1.41 0 0 3.42633 .01 .01
+1.42 0 0 3.3998 .01 .01
+1.43 0 0 3.37365 .01 .01
+1.44 0 0 3.34789 .01 .01
+1.45 0 0 3.3225 .01 .01
+1.46 0 0 3.29748 .01 .01
+1.47 0 0 3.27281 .01 .01
+1.48 0 0 3.24849 .01 .01
+1.49 0 0 3.22452 .01 .01
+1.5 0 0 3.20088 .01 .01
+1.51 0 0 3.17757 .01 .01
+1.52 0 0 3.15458 .01 .01
+1.53 0 0 3.13191 .01 .01
+1.54 0 0 3.10955 .01 .01
+1.55 0 0 3.08749 .01 .01
+1.56 0 0 3.06572 .01 .01
+1.57 0 0 3.04425 .01 .01
+1.58 0 0 3.02306 .01 .01
+1.59 0 0 3.00216 .01 .01
+1.6 0 0 2.98152 .01 .01
+1.61 0 0 2.96116 .01 .01
+1.62 0 0 2.94106 .01 .01
+1.63 0 0 2.92122 .01 .01
+1.64 0 0 2.90163 .01 .01
+1.65 0 0 2.88229 .01 .01
+1.66 0 0 2.8632 .01 .01
+1.67 0 0 2.84434 .01 .01
+1.68 0 0 2.82572 .01 .01
+1.69 0 0 2.80734 .01 .01
+1.7 0 0 2.78918 .01 .01
+1.71 0 0 2.77124 .01 .01
+1.72 0 0 2.75352 .01 .01
+1.73 0 0 2.73602 .01 .01
+1.74 0 0 2.71873 .01 .01
+1.75 0 0 2.70164 .01 .01
+1.76 0 0 2.68476 .01 .01
+1.77 0 0 2.66808 .01 .01
+1.78 0 0 2.6516 .01 .01
+1.79 0 0 2.63531 .01 .01
+1.8 0 0 2.61921 .01 .01
+1.81 0 0 2.6033 .01 .01
+1.82 0 0 2.58757 .01 .01
+1.83 0 0 2.57202 .01 .01
+1.84 0 0 2.55664 .01 .01
+1.85 0 0 2.54145 .01 .01
+1.86 0 0 2.52642 .01 .01
+1.87 0 0 2.51156 .01 .01
+1.88 0 0 2.49687 .01 .01
+1.89 0 0 2.48234 .01 .01
+1.9 0 0 2.46798 .01 .01
+1.91 0 0 2.45377 .01 .01
+1.92 0 0 2.43971 .01 .01
+1.93 0 0 2.42581 .01 .01
+1.94 0 0 2.41206 .01 .01
+1.95 0 0 2.39846 .01 .01
+1.96 0 0 2.385 .01 .01
+1.97 0 0 2.37169 .01 .01
+1.98 0 0 2.35851 .01 .01
+1.99 0 0 2.34548 .01 .01
+2 0 0 2.33258 .01 .01
+2.01 0 0 2.31982 .01 .01
+2.02 0 0 2.30719 .01 .01
+2.03 0 0 2.29469 .01 .01
+2.04 0 0 2.28232 .01 .01
+2.05 0 0 2.27008 .01 .01
+2.06 0 0 2.25796 .01 .01
+2.07 0 0 2.24596 .01 .01
+2.08 0 0 2.23409 .01 .01
+2.09 0 0 2.22233 .01 .01
+2.1 0 0 2.21069 .01 .01
+2.11 0 0 2.19917 .01 .01
+2.12 0 0 2.18776 .01 .01
+2.13 0 0 2.17647 .01 .01
+2.14 0 0 2.16528 .01 .01
+2.15 0 0 2.15421 .01 .01
+2.16 0 0 2.14324 .01 .01
+2.17 0 0 2.13238 .01 .01
+2.18 0 0 2.12162 .01 .01
+2.19 0 0 2.11097 .01 .01
+2.2 0 0 2.10041 .01 .01
+2.21 0 0 2.08996 .01 .01
+2.22 0 0 2.07961 .01 .01
+2.23 0 0 2.06935 .01 .01
+2.24 0 0 2.05919 .01 .01
+2.25 0 0 2.04913 .01 .01
+2.26 0 0 2.03916 .01 .01
+2.27 0 0 2.02928 .01 .01
+2.28 0 0 2.01949 .01 .01
+2.29 0 0 2.00979 .01 .01
+2.3 0 0 2.00018 .01 .01
+2.31 0 0 1.99066 .01 .01
+2.32 0 0 1.98122 .01 .01
+2.33 0 0 1.97187 .01 .01
+2.34 0 0 1.9626 .01 .01
+2.35 0 0 1.95342 .01 .01
+2.36 0 0 1.94432 .01 .01
+2.37 0 0 1.93529 .01 .01
+2.38 0 0 1.92635 .01 .01
+2.39 0 0 1.91749 .01 .01
+2.4 0 0 1.9087 .01 .01
+2.41 0 0 1.89999 .01 .01
+2.42 0 0 1.89136 .01 .01
+2.43 0 0 1.8828 .01 .01
+2.44 0 0 1.87431 .01 .01
+2.45 0 0 1.8659 .01 .01
+2.46 0 0 1.85755 .01 .01
+2.47 0 0 1.84928 .01 .01
+2.48 0 0 1.84108 .01 .01
+2.49 0 0 1.83295 .01 .01
+2.5 0 0 1.82489 .01 .01
+2.51 0 0 1.81689 .01 .01
+2.52 0 0 1.80896 .01 .01
+2.53 0 0 1.8011 .01 .01
+2.54 0 0 1.7933 .01 .01
+2.55 0 0 1.78557 .01 .01
+2.56 0 0 1.77789 .01 .01
+2.57 0 0 1.77029 .01 .01
+2.58 0 0 1.76274 .01 .01
+2.59 0 0 1.75526 .01 .01
+2.6 0 0 1.74783 .01 .01
+2.61 0 0 1.74047 .01 .01
+2.62 0 0 1.73316 .01 .01
+2.63 0 0 1.72591 .01 .01
+2.64 0 0 1.71872 .01 .01
+2.65 0 0 1.71159 .01 .01
+2.66 0 0 1.70451 .01 .01
+2.67 0 0 1.69749 .01 .01
+2.68 0 0 1.69053 .01 .01
+2.69 0 0 1.68361 .01 .01
+2.7 0 0 1.67676 .01 .01
+2.71 0 0 1.66995 .01 .01
+2.72 0 0 1.6632 .01 .01
+2.73 0 0 1.6565 .01 .01
+2.74 0 0 1.64985 .01 .01
+2.75 0 0 1.64325 .01 .01
+2.76 0 0 1.6367 .01 .01
+2.77 0 0 1.63021 .01 .01
+2.78 0 0 1.62376 .01 .01
+2.79 0 0 1.61736 .01 .01
+2.8 0 0 1.611 .01 .01
+2.81 0 0 1.6047 .01 .01
+2.82 0 0 1.59844 .01 .01
+2.83 0 0 1.59223 .01 .01
+2.84 0 0 1.58606 .01 .01
+2.85 0 0 1.57994 .01 .01
+2.86 0 0 1.57386 .01 .01
+2.87 0 0 1.56783 .01 .01
+2.88 0 0 1.56185 .01 .01
+2.89 0 0 1.5559 .01 .01
+2.9 0 0 1.55 .01 .01
+2.91 0 0 1.54414 .01 .01
+2.92 0 0 1.53833 .01 .01
+2.93 0 0 1.53255 .01 .01
+2.94 0 0 1.52682 .01 .01
+2.95 0 0 1.52113 .01 .01
+2.96 0 0 1.51548 .01 .01
+2.97 0 0 1.50986 .01 .01
+2.98 0 0 1.50429 .01 .01
+2.99 0 0 1.49876 .01 .01
+3 0 0 1.49326 .01 .01
+3.01 0 0 1.48781 .01 .01
+3.02 0 0 1.48239 .01 .01
+3.03 0 0 1.47701 .01 .01
+3.04 0 0 1.47167 .01 .01
+3.05 0 0 1.46636 .01 .01
+3.06 0 0 1.46109 .01 .01
+3.07 0 0 1.45585 .01 .01
+3.08 0 0 1.45066 .01 .01
+3.09 0 0 1.44549 .01 .01
+3.1 0 0 1.44036 .01 .01
+3.11 0 0 1.43527 .01 .01
+3.12 0 0 1.43021 .01 .01
+3.13 0 0 1.42518 .01 .01
+3.14 0 0 1.42019 .01 .01
+3.15 0 0 1.41523 .01 .01
+3.16 0 0 1.41031 .01 .01
+3.17 0 0 1.40542 .01 .01
+3.18 0 0 1.40056 .01 .01
+3.19 0 0 1.39573 .01 .01
+3.2 0 0 1.39093 .01 .01
+3.21 0 0 1.38616 .01 .01
+3.22 0 0 1.38143 .01 .01
+3.23 0 0 1.37673 .01 .01
+3.24 0 0 1.37205 .01 .01
+3.25 0 0 1.36741 .01 .01
+3.26 0 0 1.3628 .01 .01
+3.27 0 0 1.35821 .01 .01
+3.28 0 0 1.35366 .01 .01
+3.29 0 0 1.34913 .01 .01
+3.3 0 0 1.34464 .01 .01
+3.31 0 0 1.34017 .01 .01
+3.32 0 0 1.33573 .01 .01
+3.33 0 0 1.33132 .01 .01
+3.34 0 0 1.32693 .01 .01
+3.35 0 0 1.32258 .01 .01
+3.36 0 0 1.31825 .01 .01
+3.37 0 0 1.31394 .01 .01
+3.38 0 0 1.30967 .01 .01
+3.39 0 0 1.30542 .01 .01
+3.4 0 0 1.3012 .01 .01
+3.41 0 0 1.297 .01 .01
+3.42 0 0 1.29283 .01 .01
+3.43 0 0 1.28868 .01 .01
+3.44 0 0 1.28456 .01 .01
+3.45 0 0 1.28047 .01 .01
+3.46 0 0 1.2764 .01 .01
+3.47 0 0 1.27235 .01 .01
+3.48 0 0 1.26833 .01 .01
+3.49 0 0 1.26433 .01 .01
+3.5 0 0 1.26036 .01 .01
+3.51 0 0 1.25641 .01 .01
+3.52 0 0 1.25249 .01 .01
+3.53 0 0 1.24858 .01 .01
+3.54 0 0 1.2447 .01 .01
+3.55 0 0 1.24085 .01 .01
+3.56 0 0 1.23702 .01 .01
+3.57 0 0 1.2332 .01 .01
+3.58 0 0 1.22942 .01 .01
+3.59 0 0 1.22565 .01 .01
+3.6 0 0 1.2219 .01 .01
+3.61 0 0 1.21818 .01 .01
+3.62 0 0 1.21448 .01 .01
+3.63 0 0 1.2108 .01 .01
+3.64 0 0 1.20714 .01 .01
+3.65 0 0 1.2035 .01 .01
+3.66 0 0 1.19989 .01 .01
+3.67 0 0 1.19629 .01 .01
+3.68 0 0 1.19272 .01 .01
+3.69 0 0 1.18916 .01 .01
+3.7 0 0 1.18563 .01 .01
+3.71 0 0 1.18211 .01 .01
+3.72 0 0 1.17862 .01 .01
+3.73 0 0 1.17514 .01 .01
+3.74 0 0 1.17169 .01 .01
+3.75 0 0 1.16825 .01 .01
+3.76 0 0 1.16483 .01 .01
+3.77 0 0 1.16143 .01 .01
+3.78 0 0 1.15805 .01 .01
+3.79 0 0 1.15469 .01 .01
+3.8 0 0 1.15135 .01 .01
+3.81 0 0 1.14803 .01 .01
+3.82 0 0 1.14472 .01 .01
+3.83 0 0 1.14144 .01 .01
+3.84 0 0 1.13817 .01 .01
+3.85 0 0 1.13491 .01 .01
+3.86 0 0 1.13168 .01 .01
+3.87 0 0 1.12846 .01 .01
+3.88 0 0 1.12527 .01 .01
+3.89 0 0 1.12208 .01 .01
+3.9 0 0 1.11892 .01 .01
+3.91 0 0 1.11577 .01 .01
+3.92 0 0 1.11264 .01 .01
+3.93 0 0 1.10953 .01 .01
+3.94 0 0 1.10643 .01 .01
+3.95 0 0 1.10335 .01 .01
+3.96 0 0 1.10029 .01 .01
+3.97 0 0 1.09724 .01 .01
+3.98 0 0 1.0942 .01 .01
+3.99 0 0 1.09119 .01 .01
+4 0 0 1.08819 .01 .01
+4.01 0 0 1.0852 .01 .01
+4.02 0 0 1.08223 .01 .01
+4.03 0 0 1.07928 .01 .01
+4.04 0 0 1.07634 .01 .01
+4.05 0 0 1.07342 .01 .01
+4.06 0 0 1.07051 .01 .01
+4.07 0 0 1.06762 .01 .01
+4.08 0 0 1.06474 .01 .01
+4.09 0 0 1.06188 .01 .01
+4.1 0 0 1.05903 .01 .01
+4.11 0 0 1.05619 .01 .01
+4.12 0 0 1.05338 .01 .01
+4.13 0 0 1.05057 .01 .01
+4.14 0 0 1.04778 .01 .01
+4.15 0 0 1.045 .01 .01
+4.16 0 0 1.04224 .01 .01
+4.17 0 0 1.03949 .01 .01
+4.18 0 0 1.03675 .01 .01
+4.19 0 0 1.03403 .01 .01
+4.2 0 0 1.03133 .01 .01
+4.21 0 0 1.02863 .01 .01
+4.22 0 0 1.02595 .01 .01
+4.23 0 0 1.02328 .01 .01
+4.24 0 0 1.02063 .01 .01
+4.25 0 0 1.01799 .01 .01
+4.26 0 0 1.01536 .01 .01
+4.27 0 0 1.01274 .01 .01
+4.28 0 0 1.01014 .01 .01
+4.29 0 0 1.00755 .01 .01
+4.3 0 0 1.00497 .01 .01
+4.31 0 0 1.00241 .01 .01
+4.32 0 0 0.999857 .01 .01
+4.33 0 0 0.997317 .01 .01
+4.34 0 0 0.99479 .01 .01
+4.35 0 0 0.992274 .01 .01
+4.36 0 0 0.989771 .01 .01
+4.37 0 0 0.98728 .01 .01
+4.38 0 0 0.984801 .01 .01
+4.39 0 0 0.982334 .01 .01
+4.4 0 0 0.979878 .01 .01
+4.41 0 0 0.977434 .01 .01
+4.42 0 0 0.975002 .01 .01
+4.43 0 0 0.972581 .01 .01
+4.44 0 0 0.970172 .01 .01
+4.45 0 0 0.967774 .01 .01
+4.46 0 0 0.965387 .01 .01
+4.47 0 0 0.963012 .01 .01
+4.48 0 0 0.960648 .01 .01
+4.49 0 0 0.958295 .01 .01
+4.5 0 0 0.955952 .01 .01
+4.51 0 0 0.953621 .01 .01
+4.52 0 0 0.951301 .01 .01
+4.53 0 0 0.948991 .01 .01
+4.54 0 0 0.946692 .01 .01
+4.55 0 0 0.944403 .01 .01
+4.56 0 0 0.942125 .01 .01
+4.57 0 0 0.939858 .01 .01
+4.58 0 0 0.937601 .01 .01
+4.59 0 0 0.935354 .01 .01
+4.6 0 0 0.933118 .01 .01
+4.61 0 0 0.930891 .01 .01
+4.62 0 0 0.928675 .01 .01
+4.63 0 0 0.926469 .01 .01
+4.64 0 0 0.924273 .01 .01
+4.65 0 0 0.922087 .01 .01
+4.66 0 0 0.91991 .01 .01
+4.67 0 0 0.917744 .01 .01
+4.68 0 0 0.915587 .01 .01
+4.69 0 0 0.91344 .01 .01
+4.7 0 0 0.911302 .01 .01
+4.71 0 0 0.909174 .01 .01
+4.72 0 0 0.907055 .01 .01
+4.73 0 0 0.904946 .01 .01
+4.74 0 0 0.902846 .01 .01
+4.75 0 0 0.900756 .01 .01
+4.76 0 0 0.898674 .01 .01
+4.77 0 0 0.896602 .01 .01
+4.78 0 0 0.894539 .01 .01
+4.79 0 0 0.892485 .01 .01
+4.8 0 0 0.89044 .01 .01
+4.81 0 0 0.888404 .01 .01
+4.82 0 0 0.886377 .01 .01
+4.83 0 0 0.884358 .01 .01
+4.84 0 0 0.882348 .01 .01
+4.85 0 0 0.880347 .01 .01
+4.86 0 0 0.878355 .01 .01
+4.87 0 0 0.876371 .01 .01
+4.88 0 0 0.874396 .01 .01
+4.89 0 0 0.872429 .01 .01
+4.9 0 0 0.870471 .01 .01
+4.91 0 0 0.868521 .01 .01
+4.92 0 0 0.866579 .01 .01
+4.93 0 0 0.864646 .01 .01
+4.94 0 0 0.862721 .01 .01
+4.95 0 0 0.860804 .01 .01
+4.96 0 0 0.858895 .01 .01
+4.97 0 0 0.856994 .01 .01
+4.98 0 0 0.855102 .01 .01
+4.99 0 0 0.853217 .01 .01
+5 0 0 0.85134 .01 .01
+5.01 0 0 0.849471 .01 .01
+5.02 0 0 0.84761 .01 .01
+5.03 0 0 0.845756 .01 .01
+5.04 0 0 0.843911 .01 .01
+5.05 0 0 0.842073 .01 .01
+5.06 0 0 0.840242 .01 .01
+5.07 0 0 0.838419 .01 .01
+5.08 0 0 0.836604 .01 .01
+5.09 0 0 0.834796 .01 .01
+5.1 0 0 0.832996 .01 .01
+5.11 0 0 0.831203 .01 .01
+5.12 0 0 0.829417 .01 .01
+5.13 0 0 0.827639 .01 .01
+5.14 0 0 0.825868 .01 .01
+5.15 0 0 0.824104 .01 .01
+5.16 0 0 0.822347 .01 .01
+5.17 0 0 0.820598 .01 .01
+5.18 0 0 0.818855 .01 .01
+5.19 0 0 0.81712 .01 .01
+5.2 0 0 0.815392 .01 .01
+5.21 0 0 0.81367 .01 .01
+5.22 0 0 0.811956 .01 .01
+5.23 0 0 0.810248 .01 .01
+5.24 0 0 0.808548 .01 .01
+5.25 0 0 0.806854 .01 .01
+5.26 0 0 0.805166 .01 .01
+5.27 0 0 0.803486 .01 .01
+5.28 0 0 0.801812 .01 .01
+5.29 0 0 0.800145 .01 .01
+5.3 0 0 0.798485 .01 .01
+5.31 0 0 0.796831 .01 .01
+5.32 0 0 0.795183 .01 .01
+5.33 0 0 0.793542 .01 .01
+5.34 0 0 0.791908 .01 .01
+5.35 0 0 0.79028 .01 .01
+5.36 0 0 0.788658 .01 .01
+5.37 0 0 0.787043 .01 .01
+5.38 0 0 0.785434 .01 .01
+5.39 0 0 0.783831 .01 .01
+5.4 0 0 0.782234 .01 .01
+5.41 0 0 0.780644 .01 .01
+5.42 0 0 0.77906 .01 .01
+5.43 0 0 0.777482 .01 .01
+5.44 0 0 0.77591 .01 .01
+5.45 0 0 0.774344 .01 .01
+5.46 0 0 0.772784 .01 .01
+5.47 0 0 0.77123 .01 .01
+5.48 0 0 0.769682 .01 .01
+5.49 0 0 0.76814 .01 .01
+5.5 0 0 0.766604 .01 .01
+5.51 0 0 0.765074 .01 .01
+5.52 0 0 0.763549 .01 .01
+5.53 0 0 0.762031 .01 .01
+5.54 0 0 0.760518 .01 .01
+5.55 0 0 0.75901 .01 .01
+5.56 0 0 0.757509 .01 .01
+5.57 0 0 0.756013 .01 .01
+5.58 0 0 0.754523 .01 .01
+5.59 0 0 0.753038 .01 .01
+5.6 0 0 0.751559 .01 .01
+5.61 0 0 0.750086 .01 .01
+5.62 0 0 0.748618 .01 .01
+5.63 0 0 0.747155 .01 .01
+5.64 0 0 0.745698 .01 .01
+5.65 0 0 0.744246 .01 .01
+5.66 0 0 0.7428 .01 .01
+5.67 0 0 0.741359 .01 .01
+5.68 0 0 0.739924 .01 .01
+5.69 0 0 0.738493 .01 .01
+5.7 0 0 0.737068 .01 .01
+5.71 0 0 0.735648 .01 .01
+5.72 0 0 0.734234 .01 .01
+5.73 0 0 0.732824 .01 .01
+5.74 0 0 0.73142 .01 .01
+5.75 0 0 0.730021 .01 .01
+5.76 0 0 0.728627 .01 .01
+5.77 0 0 0.727238 .01 .01
+5.78 0 0 0.725854 .01 .01
+5.79 0 0 0.724475 .01 .01
+5.8 0 0 0.723101 .01 .01
+5.81 0 0 0.721732 .01 .01
+5.82 0 0 0.720369 .01 .01
+5.83 0 0 0.719009 .01 .01
+5.84 0 0 0.717655 .01 .01
+5.85 0 0 0.716306 .01 .01
+5.86 0 0 0.714961 .01 .01
+5.87 0 0 0.713622 .01 .01
+5.88 0 0 0.712287 .01 .01
+5.89 0 0 0.710957 .01 .01
+5.9 0 0 0.709631 .01 .01
+5.91 0 0 0.708311 .01 .01
+5.92 0 0 0.706995 .01 .01
+5.93 0 0 0.705683 .01 .01
+5.94 0 0 0.704377 .01 .01
+5.95 0 0 0.703074 .01 .01
+5.96 0 0 0.701777 .01 .01
+5.97 0 0 0.700484 .01 .01
+5.98 0 0 0.699196 .01 .01
+5.99 0 0 0.697912 .01 .01
+6 0 0 0.696632 .01 .01
+6.01 0 0 0.695357 .01 .01
+6.02 0 0 0.694087 .01 .01
+6.03 0 0 0.692821 .01 .01
+6.04 0 0 0.691559 .01 .01
+6.05 0 0 0.690302 .01 .01
+6.06 0 0 0.689049 .01 .01
+6.07 0 0 0.6878 .01 .01
+6.08 0 0 0.686556 .01 .01
+6.09 0 0 0.685316 .01 .01
+6.1 0 0 0.68408 .01 .01
+6.11 0 0 0.682849 .01 .01
+6.12 0 0 0.681622 .01 .01
+6.13 0 0 0.680399 .01 .01
+6.14 0 0 0.67918 .01 .01
+6.15 0 0 0.677965 .01 .01
+6.16 0 0 0.676755 .01 .01
+6.17 0 0 0.675548 .01 .01
+6.18 0 0 0.674346 .01 .01
+6.19 0 0 0.673148 .01 .01
+6.2 0 0 0.671953 .01 .01
+6.21 0 0 0.670763 .01 .01
+6.22 0 0 0.669577 .01 .01
+6.23 0 0 0.668395 .01 .01
+6.24 0 0 0.667217 .01 .01
+6.25 0 0 0.666043 .01 .01
+6.26 0 0 0.664872 .01 .01
+6.27 0 0 0.663706 .01 .01
+6.28 0 0 0.662543 .01 .01
+6.29 0 0 0.661385 .01 .01
+6.3 0 0 0.66023 .01 .01
+6.31 0 0 0.659079 .01 .01
+6.32 0 0 0.657932 .01 .01
+6.33 0 0 0.656789 .01 .01
+6.34 0 0 0.65565 .01 .01
+6.35 0 0 0.654514 .01 .01
+6.36 0 0 0.653382 .01 .01
+6.37 0 0 0.652254 .01 .01
+6.38 0 0 0.651129 .01 .01
+6.39 0 0 0.650009 .01 .01
+6.4 0 0 0.648891 .01 .01
+6.41 0 0 0.647778 .01 .01
+6.42 0 0 0.646668 .01 .01
+6.43 0 0 0.645562 .01 .01
+6.44 0 0 0.644459 .01 .01
+6.45 0 0 0.64336 .01 .01
+6.46 0 0 0.642265 .01 .01
+6.47 0 0 0.641173 .01 .01
+6.48 0 0 0.640085 .01 .01
+6.49 0 0 0.639 .01 .01
+6.5 0 0 0.637919 .01 .01
+6.51 0 0 0.636841 .01 .01
+6.52 0 0 0.635767 .01 .01
+6.53 0 0 0.634696 .01 .01
+6.54 0 0 0.633628 .01 .01
+6.55 0 0 0.632564 .01 .01
+6.56 0 0 0.631504 .01 .01
+6.57 0 0 0.630446 .01 .01
+6.58 0 0 0.629392 .01 .01
+6.59 0 0 0.628342 .01 .01
+6.6 0 0 0.627295 .01 .01
+6.61 0 0 0.626251 .01 .01
+6.62 0 0 0.62521 .01 .01
+6.63 0 0 0.624173 .01 .01
+6.64 0 0 0.623139 .01 .01
+6.65 0 0 0.622109 .01 .01
+6.66 0 0 0.621081 .01 .01
+6.67 0 0 0.620057 .01 .01
+6.68 0 0 0.619036 .01 .01
+6.69 0 0 0.618018 .01 .01
+6.7 0 0 0.617004 .01 .01
+6.71 0 0 0.615992 .01 .01
+6.72 0 0 0.614984 .01 .01
+6.73 0 0 0.613979 .01 .01
+6.74 0 0 0.612977 .01 .01
+6.75 0 0 0.611978 .01 .01
+6.76 0 0 0.610982 .01 .01
+6.77 0 0 0.60999 .01 .01
+6.78 0 0 0.609 .01 .01
+6.79 0 0 0.608014 .01 .01
+6.8 0 0 0.60703 .01 .01
+6.81 0 0 0.60605 .01 .01
+6.82 0 0 0.605072 .01 .01
+6.83 0 0 0.604098 .01 .01
+6.84 0 0 0.603126 .01 .01
+6.85 0 0 0.602158 .01 .01
+6.86 0 0 0.601192 .01 .01
+6.87 0 0 0.60023 .01 .01
+6.88 0 0 0.59927 .01 .01
+6.89 0 0 0.598314 .01 .01
+6.9 0 0 0.59736 .01 .01
+6.91 0 0 0.596409 .01 .01
+6.92 0 0 0.595461 .01 .01
+6.93 0 0 0.594516 .01 .01
+6.94 0 0 0.593574 .01 .01
+6.95 0 0 0.592634 .01 .01
+6.96 0 0 0.591698 .01 .01
+6.97 0 0 0.590764 .01 .01
+6.98 0 0 0.589833 .01 .01
+6.99 0 0 0.588905 .01 .01
+7 0 0 0.587979 .01 .01
+7.01 0 0 0.587057 .01 .01
+7.02 0 0 0.586137 .01 .01
+7.03 0 0 0.58522 .01 .01
+7.04 0 0 0.584306 .01 .01
+7.05 0 0 0.583394 .01 .01
+7.06 0 0 0.582485 .01 .01
+7.07 0 0 0.581579 .01 .01
+7.08 0 0 0.580675 .01 .01
+7.09 0 0 0.579775 .01 .01
+7.1 0 0 0.578876 .01 .01
+7.11 0 0 0.577981 .01 .01
+7.12 0 0 0.577088 .01 .01
+7.13 0 0 0.576198 .01 .01
+7.14 0 0 0.57531 .01 .01
+7.15 0 0 0.574425 .01 .01
+7.16 0 0 0.573543 .01 .01
+7.17 0 0 0.572663 .01 .01
+7.18 0 0 0.571785 .01 .01
+7.19 0 0 0.570911 .01 .01
+7.2 0 0 0.570039 .01 .01
+7.21 0 0 0.569169 .01 .01
+7.22 0 0 0.568302 .01 .01
+7.23 0 0 0.567437 .01 .01
+7.24 0 0 0.566575 .01 .01
+7.25 0 0 0.565716 .01 .01
+7.26 0 0 0.564859 .01 .01
+7.27 0 0 0.564004 .01 .01
+7.28 0 0 0.563152 .01 .01
+7.29 0 0 0.562302 .01 .01
+7.3 0 0 0.561455 .01 .01
+7.31 0 0 0.56061 .01 .01
+7.32 0 0 0.559768 .01 .01
+7.33 0 0 0.558928 .01 .01
+7.34 0 0 0.55809 .01 .01
+7.35 0 0 0.557255 .01 .01
+7.36 0 0 0.556422 .01 .01
+7.37 0 0 0.555592 .01 .01
+7.38 0 0 0.554764 .01 .01
+7.39 0 0 0.553938 .01 .01
+7.4 0 0 0.553115 .01 .01
+7.41 0 0 0.552294 .01 .01
+7.42 0 0 0.551475 .01 .01
+7.43 0 0 0.550658 .01 .01
+7.44 0 0 0.549844 .01 .01
+7.45 0 0 0.549033 .01 .01
+7.46 0 0 0.548223 .01 .01
+7.47 0 0 0.547416 .01 .01
+7.48 0 0 0.546611 .01 .01
+7.49 0 0 0.545808 .01 .01
+7.5 0 0 0.545008 .01 .01
+7.51 0 0 0.544209 .01 .01
+7.52 0 0 0.543413 .01 .01
+7.53 0 0 0.54262 .01 .01
+7.54 0 0 0.541828 .01 .01
+7.55 0 0 0.541039 .01 .01
+7.56 0 0 0.540252 .01 .01
+7.57 0 0 0.539467 .01 .01
+7.58 0 0 0.538684 .01 .01
+7.59 0 0 0.537903 .01 .01
+7.6 0 0 0.537125 .01 .01
+7.61 0 0 0.536348 .01 .01
+7.62 0 0 0.535574 .01 .01
+7.63 0 0 0.534802 .01 .01
+7.64 0 0 0.534032 .01 .01
+7.65 0 0 0.533264 .01 .01
+7.66 0 0 0.532498 .01 .01
+7.67 0 0 0.531735 .01 .01
+7.68 0 0 0.530973 .01 .01
+7.69 0 0 0.530214 .01 .01
+7.7 0 0 0.529456 .01 .01
+7.71 0 0 0.528701 .01 .01
+7.72 0 0 0.527948 .01 .01
+7.73 0 0 0.527197 .01 .01
+7.74 0 0 0.526447 .01 .01
+7.75 0 0 0.5257 .01 .01
+7.76 0 0 0.524955 .01 .01
+7.77 0 0 0.524212 .01 .01
+7.78 0 0 0.523471 .01 .01
+7.79 0 0 0.522732 .01 .01
+7.8 0 0 0.521995 .01 .01
+7.81 0 0 0.521259 .01 .01
+7.82 0 0 0.520526 .01 .01
+7.83 0 0 0.519795 .01 .01
+7.84 0 0 0.519066 .01 .01
+7.85 0 0 0.518338 .01 .01
+7.86 0 0 0.517613 .01 .01
+7.87 0 0 0.51689 .01 .01
+7.88 0 0 0.516168 .01 .01
+7.89 0 0 0.515449 .01 .01
+7.9 0 0 0.514731 .01 .01
+7.91 0 0 0.514015 .01 .01
+7.92 0 0 0.513301 .01 .01
+7.93 0 0 0.512589 .01 .01
+7.94 0 0 0.511879 .01 .01
+7.95 0 0 0.511171 .01 .01
+7.96 0 0 0.510465 .01 .01
+7.97 0 0 0.50976 .01 .01
+7.98 0 0 0.509057 .01 .01
+7.99 0 0 0.508357 .01 .01
+8 0 0 0.507658 .01 .01
+8.01 0 0 0.506961 .01 .01
+8.02 0 0 0.506265 .01 .01
+8.03 0 0 0.505572 .01 .01
+8.04 0 0 0.50488 .01 .01
+8.05 0 0 0.50419 .01 .01
+8.06 0 0 0.503502 .01 .01
+8.07 0 0 0.502816 .01 .01
+8.08 0 0 0.502132 .01 .01
+8.09 0 0 0.501449 .01 .01
+8.1 0 0 0.500768 .01 .01
+8.11 0 0 0.500089 .01 .01
+8.12 0 0 0.499411 .01 .01
+8.13 0 0 0.498736 .01 .01
+8.14 0 0 0.498062 .01 .01
+8.15 0 0 0.49739 .01 .01
+8.16 0 0 0.496719 .01 .01
+8.17 0 0 0.49605 .01 .01
+8.18 0 0 0.495383 .01 .01
+8.19 0 0 0.494718 .01 .01
+8.2 0 0 0.494054 .01 .01
+8.21 0 0 0.493392 .01 .01
+8.22 0 0 0.492732 .01 .01
+8.23 0 0 0.492074 .01 .01
+8.24 0 0 0.491417 .01 .01
+8.25 0 0 0.490762 .01 .01
+8.26 0 0 0.490108 .01 .01
+8.27 0 0 0.489456 .01 .01
+8.28 0 0 0.488806 .01 .01
+8.29 0 0 0.488158 .01 .01
+8.3 0 0 0.487511 .01 .01
+8.31 0 0 0.486865 .01 .01
+8.32 0 0 0.486222 .01 .01
+8.33 0 0 0.48558 .01 .01
+8.34 0 0 0.484939 .01 .01
+8.35 0 0 0.4843 .01 .01
+8.36 0 0 0.483663 .01 .01
+8.37 0 0 0.483028 .01 .01
+8.38 0 0 0.482394 .01 .01
+8.39 0 0 0.481761 .01 .01
+8.4 0 0 0.48113 .01 .01
+8.41 0 0 0.480501 .01 .01
+8.42 0 0 0.479873 .01 .01
+8.43 0 0 0.479247 .01 .01
+8.44 0 0 0.478623 .01 .01
+8.45 0 0 0.478 .01 .01
+8.46 0 0 0.477378 .01 .01
+8.47 0 0 0.476758 .01 .01
+8.48 0 0 0.47614 .01 .01
+8.49 0 0 0.475523 .01 .01
+8.5 0 0 0.474908 .01 .01
+8.51 0 0 0.474294 .01 .01
+8.52 0 0 0.473682 .01 .01
+8.53 0 0 0.473071 .01 .01
+8.54 0 0 0.472461 .01 .01
+8.55 0 0 0.471854 .01 .01
+8.56 0 0 0.471247 .01 .01
+8.57 0 0 0.470642 .01 .01
+8.58 0 0 0.470039 .01 .01
+8.59 0 0 0.469437 .01 .01
+8.6 0 0 0.468837 .01 .01
+8.61 0 0 0.468238 .01 .01
+8.62 0 0 0.46764 .01 .01
+8.63 0 0 0.467044 .01 .01
+8.64 0 0 0.46645 .01 .01
+8.65 0 0 0.465857 .01 .01
+8.66 0 0 0.465265 .01 .01
+8.67 0 0 0.464675 .01 .01
+8.68 0 0 0.464086 .01 .01
+8.69 0 0 0.463498 .01 .01
+8.7 0 0 0.462912 .01 .01
+8.71 0 0 0.462328 .01 .01
+8.72 0 0 0.461745 .01 .01
+8.73 0 0 0.461163 .01 .01
+8.74 0 0 0.460582 .01 .01
+8.75 0 0 0.460004 .01 .01
+8.76 0 0 0.459426 .01 .01
+8.77 0 0 0.45885 .01 .01
+8.78 0 0 0.458275 .01 .01
+8.79 0 0 0.457701 .01 .01
+8.8 0 0 0.457129 .01 .01
+8.81 0 0 0.456559 .01 .01
+8.82 0 0 0.455989 .01 .01
+8.83 0 0 0.455421 .01 .01
+8.84 0 0 0.454855 .01 .01
+8.85 0 0 0.454289 .01 .01
+8.86 0 0 0.453725 .01 .01
+8.87 0 0 0.453163 .01 .01
+8.88 0 0 0.452601 .01 .01
+8.89 0 0 0.452041 .01 .01
+8.9 0 0 0.451483 .01 .01
+8.91 0 0 0.450925 .01 .01
+8.92 0 0 0.450369 .01 .01
+8.93 0 0 0.449814 .01 .01
+8.94 0 0 0.449261 .01 .01
+8.95 0 0 0.448709 .01 .01
+8.96 0 0 0.448158 .01 .01
+8.97 0 0 0.447608 .01 .01
+8.98 0 0 0.44706 .01 .01
+8.99 0 0 0.446513 .01 .01
+9 0 0 0.445968 .01 .01
+9.01 0 0 0.445423 .01 .01
+9.02 0 0 0.44488 .01 .01
+9.03 0 0 0.444338 .01 .01
+9.04 0 0 0.443797 .01 .01
+9.05 0 0 0.443258 .01 .01
+9.06 0 0 0.44272 .01 .01
+9.07 0 0 0.442183 .01 .01
+9.08 0 0 0.441647 .01 .01
+9.09 0 0 0.441113 .01 .01
+9.1 0 0 0.44058 .01 .01
+9.11 0 0 0.440048 .01 .01
+9.12 0 0 0.439517 .01 .01
+9.13 0 0 0.438987 .01 .01
+9.14 0 0 0.438459 .01 .01
+9.15 0 0 0.437932 .01 .01
+9.16 0 0 0.437406 .01 .01
+9.17 0 0 0.436882 .01 .01
+9.18 0 0 0.436358 .01 .01
+9.19 0 0 0.435836 .01 .01
+9.2 0 0 0.435315 .01 .01
+9.21 0 0 0.434795 .01 .01
+9.22 0 0 0.434276 .01 .01
+9.23 0 0 0.433759 .01 .01
+9.24 0 0 0.433242 .01 .01
+9.25 0 0 0.432727 .01 .01
+9.26 0 0 0.432213 .01 .01
+9.27 0 0 0.4317 .01 .01
+9.28 0 0 0.431189 .01 .01
+9.29 0 0 0.430678 .01 .01
+9.3 0 0 0.430169 .01 .01
+9.31 0 0 0.42966 .01 .01
+9.32 0 0 0.429153 .01 .01
+9.33 0 0 0.428647 .01 .01
+9.34 0 0 0.428143 .01 .01
+9.35 0 0 0.427639 .01 .01
+9.36 0 0 0.427136 .01 .01
+9.37 0 0 0.426635 .01 .01
+9.38 0 0 0.426135 .01 .01
+9.39 0 0 0.425636 .01 .01
+9.4 0 0 0.425137 .01 .01
+9.41 0 0 0.424641 .01 .01
+9.42 0 0 0.424145 .01 .01
+9.43 0 0 0.42365 .01 .01
+9.44 0 0 0.423156 .01 .01
+9.45 0 0 0.422664 .01 .01
+9.46 0 0 0.422172 .01 .01
+9.47 0 0 0.421682 .01 .01
+9.48 0 0 0.421193 .01 .01
+9.49 0 0 0.420705 .01 .01
+9.5 0 0 0.420217 .01 .01
+9.51 0 0 0.419731 .01 .01
+9.52 0 0 0.419246 .01 .01
+9.53 0 0 0.418763 .01 .01
+9.54 0 0 0.41828 .01 .01
+9.55 0 0 0.417798 .01 .01
+9.56 0 0 0.417317 .01 .01
+9.57 0 0 0.416838 .01 .01
+9.58 0 0 0.416359 .01 .01
+9.59 0 0 0.415881 .01 .01
+9.6 0 0 0.415405 .01 .01
+9.61 0 0 0.414929 .01 .01
+9.62 0 0 0.414455 .01 .01
+9.63 0 0 0.413982 .01 .01
+9.64 0 0 0.413509 .01 .01
+9.65 0 0 0.413038 .01 .01
+9.66 0 0 0.412568 .01 .01
+9.67 0 0 0.412098 .01 .01
+9.68 0 0 0.41163 .01 .01
+9.69 0 0 0.411163 .01 .01
+9.7 0 0 0.410697 .01 .01
+9.71 0 0 0.410231 .01 .01
+9.72 0 0 0.409767 .01 .01
+9.73 0 0 0.409304 .01 .01
+9.74 0 0 0.408842 .01 .01
+9.75 0 0 0.40838 .01 .01
+9.76 0 0 0.40792 .01 .01
+9.77 0 0 0.407461 .01 .01
+9.78 0 0 0.407003 .01 .01
+9.79 0 0 0.406545 .01 .01
+9.8 0 0 0.406089 .01 .01
+9.81 0 0 0.405634 .01 .01
+9.82 0 0 0.405179 .01 .01
+9.83 0 0 0.404726 .01 .01
+9.84 0 0 0.404274 .01 .01
+9.85 0 0 0.403822 .01 .01
+9.86 0 0 0.403372 .01 .01
+9.87 0 0 0.402922 .01 .01
+9.88 0 0 0.402474 .01 .01
+9.89 0 0 0.402026 .01 .01
+9.9 0 0 0.401579 .01 .01
+9.91 0 0 0.401134 .01 .01
+9.92 0 0 0.400689 .01 .01
+9.93 0 0 0.400245 .01 .01
+9.94 0 0 0.399802 .01 .01
+9.95 0 0 0.39936 .01 .01
+9.96 0 0 0.398919 .01 .01
+9.97 0 0 0.398479 .01 .01
+9.98 0 0 0.39804 .01 .01
+9.99 0 0 0.397601 .01 .01
+10 0 0 0.397164 .01 .01
diff --git a/statistics/chisq.hpp b/statistics/chisq.hpp
new file mode 100644
index 0000000..15b3d33
--- /dev/null
+++ b/statistics/chisq.hpp
@@ -0,0 +1,163 @@
+#ifndef CHI_SQ_HPP
+#define CHI_SQ_HPP
+#include <core/fitter.hpp>
+#include <iostream>
+#include <vector>
+#include <cmath>
+using std::cerr;using std::endl;
+
+namespace opt_utilities
+{
+ template<typename Ty,typename Tx,typename Tp,typename Ts,typename Tstr>
+ class chisq
+ :public statistic<Ty,Tx,Tp,Ts,Tstr>
+ {
+ private:
+ bool verb;
+ int n;
+
+
+ statistic<Ty,Tx,Tp,Ts,Tstr>* do_clone()const
+ {
+ // return const_cast<statistic<Ty,Tx,Tp>*>(this);
+ return new chisq<Ty,Tx,Tp,Ts,Tstr>(*this);
+ }
+ public:
+ void verbose(bool v)
+ {
+ verb=v;
+ }
+ public:
+ chisq()
+ :verb(false)
+ {}
+
+
+
+ Ts do_eval(const Tp& p)
+ {
+ Ts result(0);
+ for(int i=(this->datas()).size()-1;i>=0;--i)
+ {
+ Ty chi=(this->datas().get_data(i).get_y()-eval_model(this->datas().get_data(i).get_x(),p))/this->datas().get_data(i).get_y_upper_err();
+ result+=chi*chi;
+
+ }
+ if(verb)
+ {
+ n++;
+ if(n%10==0)
+ {
+
+ cerr<<result<<"\t";
+ for(size_t i=0;i<get_size(p);++i)
+ {
+ cerr<<get_element(p,i)<<",";
+ }
+ cerr<<endl;
+ }
+
+ }
+
+ return result;
+ }
+ };
+
+#if 1
+
+ template<>
+ class chisq<double,double,std::vector<double>,double,std::string>
+ :public statistic<double,double,std::vector<double> ,double,std::string>
+ {
+ public:
+ typedef double Ty;
+ typedef double Tx;
+ typedef std::vector<double> Tp;
+ typedef double Ts;
+ typedef std::string Tstr;
+ private:
+ bool verb;
+ int n;
+
+ statistic<Ty,Tx,Tp,Ts,Tstr>* do_clone()const
+ {
+ // return const_cast<statistic<Ty,Tx,Tp>*>(this);
+ return new chisq<Ty,Tx,Tp,Ts,Tstr>(*this);
+ }
+
+
+ public:
+ void verbose(bool v)
+ {
+ verb=v;
+ }
+ public:
+ chisq()
+ :verb(false)
+ {}
+
+
+
+ Ty do_eval(const Tp& p)
+ {
+ Ty result(0);
+ for(int i=(this->datas()).size()-1;i>=0;--i)
+ {
+
+#ifdef HAVE_X_ERROR
+ Tx x1=this->datas().get_data(i).get_x()-this->datas().get_data(i).get_x_lower_err();
+ Tx x2=this->datas().get_data(i).get_x()+this->datas().get_data(i).get_x_upper_err();
+ Ty errx=(eval_model(x1,p)-eval_model(x2,p))/2;
+ //Ty errx=0;
+#else
+ Ty errx=0;
+#endif
+
+ Ty y_model=eval_model(this->datas().get_data(i).get_x(),p);
+ Ty y_obs=this->datas().get_data(i).get_y();
+ Ty y_err;
+
+ if(y_model>y_obs)
+ {
+ y_err=this->datas().get_data(i).get_y_upper_err();
+ }
+ else
+ {
+ y_err=this->datas().get_data(i).get_y_lower_err();
+ }
+
+ Ty chi=(y_obs-y_model)/std::sqrt(y_err*y_err+errx*errx);
+
+ // Ty chi=(this->datas().get_data(i).get_y()-eval_model(this->datas().get_data(i).get_x(),p));
+ // cerr<<chi<<"\n";
+ result+=chi*chi;
+ //std::cerr<<chi<<std::endl;
+ //cerr<<eval_model(this->datas()[i].x,p)<<endl;
+ //cerr<<this->datas()[i].y_upper_err<<endl;
+ // cerr<<this->datas()[i].x<<"\t"<<this->datas()[i].y<<"\t"<<eval_model(this->datas()[i].x,p)<<endl;
+ }
+ if(verb)
+ {
+ n++;
+ if(n%10==0)
+ {
+ cerr<<result<<"\t";
+ for(int i=0;i<(int)get_size(p);++i)
+ {
+ cerr<<get_element(p,i)<<",";
+ }
+ cerr<<endl;
+ }
+
+ }
+
+ return result;
+ }
+ };
+#endif
+}
+
+#endif
+//EOF
+
+
diff --git a/statistics/cstat.hpp b/statistics/cstat.hpp
new file mode 100644
index 0000000..b6b401d
--- /dev/null
+++ b/statistics/cstat.hpp
@@ -0,0 +1,66 @@
+#ifndef CSTAT_HPP
+#define CSTAT_HPP
+#include <core/fitter.hpp>
+#include <iostream>
+
+using std::cout;using std::endl;
+namespace opt_utilities
+{
+ template<typename Ty,typename Tx,typename Tp,typename Ts,typename Tstr>
+ class cstat_poisson
+ :public statistic<Ty,Tx,Tp,Ts,Tstr>
+ {
+ private:
+ bool verb;
+ int n;
+
+ Ty lnfrac(Ty y)const
+ {
+ return y*log(y)-y;
+ }
+
+ public:
+ void verbose(bool v)
+ {
+ verb=v;
+ }
+ public:
+
+ statistic<Ty,Tx,Tp,Ts,Tstr>* do_clone()const
+ {
+ // return const_cast<statistic<Ty,Tx,Tp>*>(this);
+ return new cstat_poisson<Ty,Tx,Tp,Ts,Tstr>(*this);
+ }
+
+ Ts do_eval(const Tp& p)
+ {
+ Ts result(0);
+ for(int i=(this->datas()).size()-1;i>=0;--i)
+ {
+ Ty model_y=eval_model(this->datas().get_data(i).get_x(),p);
+ result+=model_y-this->datas().get_data(i).get_y()*log(model_y)+lnfrac(this->datas().get_data(i).get_y());
+ }
+
+ if(verb)
+ {
+ n++;
+ if(n%10==0)
+ {
+ cout<<result/this->p_fitter->get_dof()<<"\t";
+ for(int i=0;i<get_size(p);++i)
+ {
+ cout<<get_element(p,i)<<",";
+ }
+ cout<<endl;
+ }
+
+ }
+ return result;
+ }
+ };
+}
+
+#endif
+//EOF
+
+
diff --git a/test.cc b/test.cc
new file mode 100644
index 0000000..a69186c
--- /dev/null
+++ b/test.cc
@@ -0,0 +1,142 @@
+#include <blitz/array.h>
+
+using namespace blitz;
+
+#include <core/opt_traits.hpp>
+
+namespace opt_utilities
+{
+ template <typename TX>
+ void set_element(blitz::Array<double,1>& x,size_t i,TX v)
+ {
+ x(i)=v;
+ }
+
+
+ inline const double& get_element(const blitz::Array<double,1>& x,size_t i)
+ {
+ return x(i);
+ }
+
+ inline size_t get_size(const Array<double,1>& x)
+ {
+ return x.extent(0);
+ }
+
+ inline void resize(Array<double,1>& x,size_t s)
+ {
+ x.resize(s);
+ }
+
+ inline Array<double,1>& opt_eq(Array<double,1>& lhs, const Array<double,1>& rhs)
+ {
+ lhs.resize(rhs.extent(0));
+ lhs=rhs.copy();
+ return lhs;
+ }
+
+ template <>
+ class value_type_trait<Array<double,1> >
+ {
+ public:
+ typedef double value_type;
+ };
+
+ template <>
+ class value_type_trait<const Array<double,1> >
+ {
+ public:
+ typedef double value_type;
+ };
+}
+
+#include <statistics/chisq.hpp>
+#include <core/optimizer.hpp>
+#include <core/default_data_set.hpp>
+#include <methods/powell/powell_method.hpp>
+#include <methods/gsl_simplex/gsl_simplex.hpp>
+#include <core/fitter.hpp>
+using namespace std;
+#include <fstream>
+#include <vector>
+#include <blitz/array.h>
+//#include "gmpxx.h"
+using namespace std;
+//using namespace opt_utilities;
+using namespace blitz;
+
+class foo
+ :public opt_utilities::func_obj<double,blitz::Array<double,1> >
+{
+ typedef blitz::Array<double,1> pT;
+ double do_eval(const pT& x)
+ {
+ return x(0)*x(0)+x(1)*x(1);
+ }
+
+ foo* do_clone()const
+ {
+ return new foo(*this);
+ }
+};
+
+class lin1d
+ :public opt_utilities::model<double,double,blitz::Array<double,1> >
+{
+private:
+ opt_utilities::model<double,double,Array<double,1> >* do_clone()const
+ {
+ return new lin1d(*this);
+ }
+public:
+ lin1d()
+ {
+ this->push_param_info(opt_utilities::param_info<Array<double,1> >("k",1));
+ this->push_param_info(opt_utilities::param_info<Array<double,1> >("b",0));
+ }
+
+public:
+ double do_eval(const double& x,const Array<double,1>& param)
+ {
+ return x*opt_utilities::get_element(param,(size_t)0)+opt_utilities::get_element(param,(size_t)1);
+ }
+
+private:
+ std::string do_to_string()const
+ {
+ return "linear model\n"
+ "y=k*x+b\n";
+ }
+};
+
+
+
+int main()
+{
+ opt_utilities::fitter<double,double,Array<double,1>,double> f;
+ //opt_utilities::optimizer<double,Array<double,1> > opt;
+ opt_utilities::powell_method<double,Array<double,1> > pm;
+ f.set_method(pm);
+
+ Array<double,1> a(2);
+ a=2,4;
+
+ opt_utilities::default_data_set<double,double> ds;
+
+ for(double x=0;x<10;x+=.1)
+ {
+ opt_utilities::data<double,double> d;
+ d.set_x(x);
+ d.set_x_lower_err(0);
+ d.set_x_upper_err(0);
+ d.set_y(x*3+4);
+ d.set_y_lower_err(.1);
+ d.set_y_upper_err(.1);
+ ds.push_back(d);
+ }
+ f.load_data(ds);
+ f.set_model(lin1d());
+ f.set_statistic(opt_utilities::chisq<double,double,blitz::Array<double,1>,double>());
+ cout<<f.fit();
+}
+
diff --git a/test1.cc b/test1.cc
new file mode 100644
index 0000000..0e456fd
--- /dev/null
+++ b/test1.cc
@@ -0,0 +1,149 @@
+#include "optimizer.hpp"
+#include "powell_method.hpp"
+#include "add_model.hpp"
+#include "lin1d.hpp"
+#include "poly1d.hpp"
+#include "data_loaders.hpp"
+#include "chisq.hpp"
+#include "freeze_param.hpp"
+#include "add_model.hpp"
+#include "mul_model.hpp"
+#include "pow_model.hpp"
+#include "gsl_simplex.hpp"
+#include "pl1d.hpp"
+using namespace std;
+#include "dl_model.hpp"
+#include <fstream>
+#include <vector>
+//#include "gmpxx.h"
+#include "strmodel1d.hpp"
+using namespace std;
+using namespace opt_utilities;
+
+class foo
+ :public func_obj<double,vector<double> >
+{
+public:
+ double do_eval(const vector<double>& p)
+ {
+ // cout<<"p0="<<p[0]<<endl;
+ return p[0]*p[0]+p[1]*p[1];
+ }
+
+ foo* do_clone()const
+ {
+ return new foo(*this);
+ }
+};
+
+
+double my_f (const gsl_vector *v, void *params)
+{
+ double x, y;
+ double *p = (double *)params;
+ // cout<<p[1]<<endl;
+ x = gsl_vector_get(v, 0);
+ y = gsl_vector_get(v, 1);
+
+ return x*x+y*y;
+}
+
+
+
+
+
+int main()
+{
+
+ optimizer<double,vector<double> > op;
+ powell_method<double,vector<double> > pw;
+ gsl_simplex<double,vector<double> > gs;
+
+ op.set_func_obj(foo());
+ op.set_opt_method(gs);
+ vector<double> p1(2);
+ p1[0]=1;
+ p1[1]=1;
+ op.set_start_point(p1);
+
+ vector<double> p=op.optimize();
+ cout<<p[0]<<"\t"<<p[1]<<endl;
+
+ return 0;
+
+
+
+ const gsl_multimin_fminimizer_type *T =
+ gsl_multimin_fminimizer_nmsimplex;
+ gsl_multimin_fminimizer *s = NULL;
+ gsl_vector *ss, *x;
+ gsl_multimin_function minex_func;
+
+ size_t iter = 0;
+ int status;
+ double size;
+
+ /* Starting point */
+ x = gsl_vector_alloc (2);
+ gsl_vector_set (x, 0, 5.0);
+ gsl_vector_set (x, 1, 7.0);
+
+ /* Set initial step sizes to 1 */
+ ss = gsl_vector_alloc (2);
+ gsl_vector_set_all (ss, 1.0);
+ foo f;
+ /* Initialize method and iterate */
+ minex_func.n = 2;
+ minex_func.f = &gsl_func_adapter<double,vector<double> >;
+ minex_func.params = (void *)&f;
+
+ s = gsl_multimin_fminimizer_alloc (T, 2);
+ gsl_multimin_fminimizer_set (s, &minex_func, x, ss);
+
+ do
+ {
+ iter++;
+ status = gsl_multimin_fminimizer_iterate(s);
+
+ if (status)
+ break;
+
+ size = gsl_multimin_fminimizer_size (s);
+ status = gsl_multimin_test_size (size, 1e-2);
+
+ if (status == GSL_SUCCESS)
+ {
+ printf ("converged to minimum at\n");
+ }
+
+ printf ("%5d %10.3e %10.3ef f() = %7.3f size = %.3f\n",
+ iter,
+ gsl_vector_get (s->x, 0),
+ gsl_vector_get (s->x, 1),
+ s->fval, size);
+ }
+ while (status == GSL_CONTINUE && iter < 100);
+
+ /*
+ foo f;
+ gsl_vector_set (x, 0, 0.0);
+ gsl_vector_set (x, 1, 0.0);
+ cout<<"fdsa ";
+ cout<<gsl_func_adapter<double,vector<double> >(x,(void*)&f)<<endl;;
+
+ */
+
+ gsl_vector_free(x);
+ gsl_vector_free(ss);
+ gsl_multimin_fminimizer_free (s);
+
+
+
+
+
+ return status;
+
+
+
+}
+
diff --git a/utilities/opt_types.hpp b/utilities/opt_types.hpp
new file mode 100644
index 0000000..ebe56c7
--- /dev/null
+++ b/utilities/opt_types.hpp
@@ -0,0 +1,29 @@
+#ifndef OPT_TYPES_HPP
+#define OPT_TYPES_HPP
+#include <core/fitter.hpp>
+#include <core/default_data_set.hpp>
+#include <methods/powell/powell_method.hpp>
+#include <statistics/chisq.hpp>
+#include <vector>
+
+namespace opt_utilities
+{
+ template <typename Ty,typename Tx,typename Tp,typename Ts,typename Tstr>
+ class opt_types
+ {
+ public:
+ typedef fitter<Ty,Tx,Tp,Ts,Tstr> fitter;
+ typedef chisq<Ty,Tx,Tp,Ts,Tstr> chisq;
+ typedef powell_method<Ty,Tp> powell_method;
+ typedef model<Ty,Tx,Tp,Tstr> model;
+ typedef default_data_set<Ty,Ty> data_set;
+ };
+
+ typedef opt_types<double,double,std::vector<double>,double,std::string> dopt;
+}
+
+
+
+
+#endif
+//EOF
diff --git a/version_ctrl.cc b/version_ctrl.cc
new file mode 100644
index 0000000..97781ad
--- /dev/null
+++ b/version_ctrl.cc
@@ -0,0 +1,18 @@
+#include <iostream>
+using namespace std;
+class cprt
+{
+public:
+ cprt()
+ {
+ cerr<<"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"<<endl;
+ cerr<<"% Flexible model fitting package %"<<endl;
+ cerr<<"% version 2.18 %"<<endl;
+ cerr<<"% by Gu Junhua 2007. %"<<endl;
+ cerr<<"% tompkins@sjtu.edu.cn %"<<endl;
+ cerr<<"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"<<endl;;
+
+ }
+
+ ~cprt(){}
+}_licence;