// This file is part of fityk program. Copyright (C) Marcin Wojdyr // Licence: GNU General Public License version 2 // $Id: func.h 424 2008-04-15 11:08:42Z wojdyr $ #ifndef FITYK__FUNC__H__ #define FITYK__FUNC__H__ #include <map> #include "mgr.h" #include "var.h" class Ftk; class Function : public VariableUser { public: struct Multi { int p; int n; fp mult; Multi(int n_, Variable::ParMult const& pm) : p(pm.p), n(n_), mult(pm.mult) {} }; std::string const type_formula; //eg. Gaussian(a,b,c) = a*(...) std::string const type_name; std::vector<std::string> const type_var_names; std::string const type_rhs; int const nv; /// number of variables Function(Ftk const* F_, std::string const &name_, std::vector<std::string> const &vars, std::string const &formula_); static Function* factory(Ftk const* F, std::string const &name_, std::string const &type_name, std::vector<std::string> const &vars); static std::vector<std::string> get_all_types(); static std::string get_formula(int n); static std::string get_formula(std::string const& type); static int is_builtin(int n); static std::string get_typename_from_formula(std::string const &formula) {return strip_string(std::string(formula, 0, formula.find_first_of("(")));} static std::string get_rhs_from_formula(std::string const &formula) { return strip_string(std::string(formula, formula.rfind('=')+1)); } static std::vector<std::string> get_varnames_from_formula(std::string const& formula); static std::vector<std::string> get_defvalues_from_formula(std::string const& formula); /// calculate value at x[i] and _add_ the result to y[i] (for each i) virtual void calculate_value(std::vector<fp> const &x, std::vector<fp> &y) const = 0; virtual void calculate_value_deriv(std::vector<fp> const &x, std::vector<fp> &y, std::vector<fp> &dy_da, bool in_dx=false) const = 0; void do_precomputations(std::vector<Variable*> const &variables); virtual void more_precomputations() {} void erased_parameter(int k); fp calculate_value(fp x) const; ///wrapper around array version /// calculate function value assuming function parameters has given values virtual void calculate_values_with_params(std::vector<fp> const& x, std::vector<fp>& y, std::vector<fp> const& alt_vv) const; virtual bool get_nonzero_range(fp/*level*/, fp&/*left*/, fp&/*right*/) const { return false; } void get_nonzero_idx_range(std::vector<fp> const &x, int &first, int &last) const; virtual bool has_center() const { return center_idx != -1; } virtual fp center() const { return center_idx==-1 ? 0. : vv[center_idx]; } virtual bool has_height() const { return false; } virtual fp height() const { return 0; } virtual bool has_fwhm() const { return false; } virtual fp fwhm() const { return 0; } virtual bool has_area() const { return false; } virtual fp area() const { return 0; } bool has_iwidth() const { return this->has_area() && this->has_height(); } fp iwidth() const { fp h=this->height(); return h ? this->area()/h : 0.; } virtual std::vector<std::string> get_other_prop_names() const { return std::vector<std::string>(); } /// has function other properties (e.g. like Lorentzian-FWHM of Voigt) bool has_other_props() const { return !get_other_prop_names().empty(); } /// check if has "other" property named `name' defined bool has_other_prop(std::string const& name); /// get other property, first check with has_other_prop virtual fp other_prop(std::string const&) const { return 0; } /// return ready-to-display string with all other properties std::string other_props_str() const; fp get_var_value(int n) const { assert(n>=0 && n<size(vv)); return vv[n]; } std::vector<fp> get_var_values() const { return vv; } std::string get_info(std::vector<Variable*> const &variables, std::vector<fp> const ¶meters, bool extended=false) const; std::string get_basic_assignment() const; std::string get_current_assignment(std::vector<Variable*> const &variables, std::vector<fp> const ¶meters) const; bool has_outdated_type() const { return type_formula != Function::get_formula(type_name); } virtual std::string get_current_formula(std::string const& x = "x") const; int get_param_nr(std::string const& param) const; std::string get_param_varname(std::string const& param) const { return get_var_name(get_param_nr(param)); } fp get_param_value(std::string const& param) const; /// similar to get_param_value(), but doesn't throw exceptions and doesn't /// search for pseudo-parameters bool get_param_value_safe(std::string const& param, fp &value) const; fp numarea(fp x1, fp x2, int nsteps) const; fp find_x_with_value(fp x1, fp x2, fp val, int max_iter=1000) const; fp find_extremum(fp x1, fp x2, int max_iter=1000) const; virtual std::string get_bytecode() const { return "No bytecode"; } virtual void precomputations_for_alternative_vv() { this->more_precomputations(); } protected: Ftk const* F; int const center_idx; std::vector<fp> vv; /// current variable values std::vector<Multi> multi; /// find index of parameter named "center"; returns -1 if not found int find_center_in_typevars() const; private: static std::vector<fp> calc_val_xx, calc_val_yy; }; ////////////////////////////////////////////////////////////////////////// namespace UdfContainer { bool is_compounded(std::string const& formula); std::vector<OpTree*> make_op_trees(std::string const& formula); struct UDF { std::string name; std::string formula; //full definition bool is_compound; bool is_builtin; std::vector<OpTree*> op_trees; UDF(std::string const& formula_, bool is_builtin_=false) : name(Function::get_typename_from_formula(formula_)), formula(formula_), is_compound(is_compounded(formula_)), is_builtin(is_builtin_) { if (!is_compound) op_trees = make_op_trees(formula); } }; extern std::vector<UDF> udfs; void initialize_udfs(); /// checks partially the definition and puts formula into udfs void define(std::string const &formula); /// removes the definition from udfs void undefine(std::string const &type); inline UDF const* get_udf(size_t n) {return n < udfs.size() ? &udfs[n] : 0;} UDF const* get_udf(std::string const &type); inline bool is_defined(std::string const &type) { return get_udf(type); } inline std::vector<UDF> const& get_udfs() { return udfs; } void check_cpd_rhs_function(std::string const &fun, std::vector<std::string> const& lhs_vars); void check_fudf_rhs(std::string const& rhs, std::vector<std::string> const& lhs_vars); std::vector<std::string> get_cpd_rhs_components(std::string const &formula, bool full); void check_rhs(std::string const& rhs, std::vector<std::string> const& lhs_vars); } /// Function which definition is based on other function(s) class CompoundFunction: public Function { friend class Function; public: void more_precomputations(); void calculate_value(std::vector<fp> const &xx, std::vector<fp> &yy) const; void calculate_value_deriv(std::vector<fp> const &xx, std::vector<fp> &yy, std::vector<fp> &dy_da, bool in_dx=false) const; std::string get_current_formula(std::string const& x = "x") const; bool has_center() const; fp center() const { return vmgr.get_function(0)->center(); } bool has_height() const; fp height() const; bool has_fwhm() const; fp fwhm() const; bool has_area() const; fp area() const; bool get_nonzero_range(fp level, fp& left, fp& right) const; void precomputations_for_alternative_vv(); void set_var_idx(std::vector<Variable*> const& variables); private: VariableManager vmgr; CompoundFunction(Ftk const* F, std::string const &name, std::string const &type, std::vector<std::string> const &vars); CompoundFunction (const CompoundFunction&); //disable }; ////////////////////////////////////////////////////////////////////////// /// User Defined Function, formula taken from user input class CustomFunction: public Function { friend class Function; public: void more_precomputations(); void calculate_value(std::vector<fp> const &xx, std::vector<fp> &yy) const; void calculate_value_deriv(std::vector<fp> const &xx, std::vector<fp> &yy, std::vector<fp> &dy_da, bool in_dx=false) const; void set_var_idx(std::vector<Variable*> const& variables); std::string get_bytecode() const { return afo.get_vmcode_info(); } private: CustomFunction(Ftk const* F, std::string const &name, std::string const &type, std::vector<std::string> const &vars, std::vector<OpTree*> const& op_trees); CustomFunction(const CustomFunction&); //disable fp value; std::vector<fp> derivatives; AnyFormulaO afo; }; #endif