diff --git a/pub/lib/func.cpp b/pub/lib/func.cpp index e1dcea4f206af4074918541865f58e9ff372d5ae..81242db15046c9cbf91c6bb00a3d8badeb99df8f 100644 --- a/pub/lib/func.cpp +++ b/pub/lib/func.cpp @@ -316,36 +316,36 @@ double func_rotdiff( double w, double tau, double qb ) //* Coordinate concatenation //************************************************************************************************** -CCoord CFunc1::coord( CCoord *co1 ) const +CCoord CFunc::coord( CCoord *co1 ) const { CCoord co = *co1; - if (txt=="0-") { + if (tag=="0-") { co.name = "-" + co1->name; - } else if (txt=="ln") { + } else if (tag=="ln") { co.name = "ln " + co1->name; - } else if (txt=="lg") { + } else if (tag=="lg") { co.name = "lg " + co1->name; - } else if (txt=="sqrt") { + } else if (tag=="sqrt") { co.name = "sqrt (" + co1->name + ")"; co.unit = co1->unit=="" ? "" : "(" + co1->unit + ")^1/2"; } else { - co.name = txt + "(" + co1->name + ")"; + co.name = tag + "(" + co1->name + ")"; } return co; } -CCoord CFunc2::coord( class CCoord *co1, class CCoord *co2 ) const +CCoord CFunc::coord( class CCoord *co1, class CCoord *co2 ) const { CCoord co = *co1; - if ( txt=="+" || txt=="-" ) { + if ( tag=="+" || tag=="-" ) { if( co1->name==co2->name ){ if( co1->unit!=co2->unit ) throw "same coordinate name and different units" " in additive operation"; co = *co1; } else { - co.name = co1->name + txt + co2->name; + co.name = co1->name + tag + co2->name; if ( co1->unit=="" ) co.unit = ""; else if ( co2->unit!="" && co2->unit!=co1->unit) { @@ -355,34 +355,34 @@ CCoord CFunc2::coord( class CCoord *co1, class CCoord *co2 ) const } else co.unit = co1->unit; } - } else if ( txt=="*" || txt=="/" ) { - co.name = co1->name + txt + co2->name; + } else if ( tag=="*" || tag=="/" ) { + co.name = co1->name + tag + co2->name; if ( co1->unit!="" && co2->unit!="" ) - co.unit = co1->unit + txt + co2->unit; + co.unit = co1->unit + tag + co2->unit; else if( co1->unit!="" ) co.unit = co1->unit; else if( co2->unit!="" ) - co.unit = txt=="*" ? co2->unit : "1/(" + co2->unit + ")"; + co.unit = tag=="*" ? co2->unit : "1/(" + co2->unit + ")"; else co.unit = ""; - } else if ( txt=="^" ) { + } else if ( tag=="^" ) { if (co2->unit != "") { cout << "? exponent is not dimensionless\n"; } co.name = co1->name + "^" + co2->name; co.unit = co1->unit=="" ? "" : ( co1->unit + "^<val>" ); } else { - co.name = txt + "(" + co1->name + "," + co2->name + ")"; + co.name = tag + "(" + co1->name + "," + co2->name + ")"; co.unit = ""; } return co; } -CCoord CFunc3::coord( class CCoord *co1, class CCoord *co2, class CCoord *co3 ) +CCoord CFunc::coord( class CCoord *co1, class CCoord *co2, class CCoord *co3 ) const { CCoord co; - co.name = txt + "(" + co1->name + "," + co2->name + "," + co3->name + ")"; + co.name = tag + "(" + co1->name + "," + co2->name + "," + co3->name + ")"; co.unit = ""; return co; } @@ -393,14 +393,14 @@ CCoord CFunc3::coord( class CCoord *co1, class CCoord *co2, class CCoord *co3 ) //************************************************************************************************** namespace NFunctions { // internals: - map<const char*,const CFunc*> fmap; // unsorted hash, for expression evaluation - vector<const CFunc*> flist; // sorted array, for help text + map<string,CFunc*> FMap; // unsorted hash, for expression evaluation + vector<const CFunc*> FList; // sorted array, for help text } -const CFunc* NFunctions::find( string key ) +const CFunc* NFunctions::find( string tag ) { - auto pos = fmap.find(key); - return pos == fmap.end() ? NULL : pos->second; + auto pos = FMap.find(tag); + return pos == FMap.end() ? NULL : pos->second; } void NFunctions::display_functions() @@ -409,60 +409,64 @@ void NFunctions::display_functions() // first operators by precedence, then functions. cout << "Operators by precedence:\n"; - int prec = -1; - for( int i=0; i<flist.size(); ++i ){ + int precedence = -1; + for( int i=0; i<FList.size(); ++i ){ const CFunc *f; - f = flist[i]; - if( f->prec ) { // operators - if( f->prec!=prec ) + f = FList[i]; + if( f->precedence ) { // operators + if( f->precedence!=precedence ) cout << "\n "; - cout << " " << f->txt; + cout << " " << f->tag; } else { // functions - if( f->prec!=prec ) + if( f->precedence!=precedence ) cout << "\nBuilt-in functions:\n"; - cout << " " << f->txt << f->com << "\n"; + cout << " " << f->tag << f->explanation << "\n"; } - prec = f->prec; + precedence = f->precedence; } } -void register_fct_meta( const char* _name, int _narg, const char* _explanation, int _precedence ) +void register_fct_template( const char* _tag, + const char* _outtype, const char* _intypes, void* _f ) { - CFunc* f; - if ( _narg==1 ) - f = new CFunc1( _name, _explanation, _precedence ); - else if ( _narg==2 ) - f = new CFunc2( _name, _explanation, _precedence ); - else if ( _narg==3 ) - f = new CFunc3( _name, _explanation, _precedence ); - else - throw S("invalid _narg"); - - NFunctions::fmap.insert( make_pair( _name, f ) ); - NFunctions::flist.push_back( f ); + auto pos = NFunctions::FMap.find(_tag); + if( pos != NFunctions::FMap.end() ) + throw S("Cannot register fct_") + _outtype + "_" + _intypes + "_" + _tag + + ": no meta entry"; + const auto tf = new CTypedFunc( _outtype, _intypes, _f ); + pos->second->tyfulis.push_back( tf ); +} + +void register_fct_meta( const char* _tag, int _narg, const char* _explanation, int _precedence ) +{ + CFunc* f( new CFunc( _tag, _narg, _explanation, _precedence ) ); + NFunctions::FMap.insert( make_pair( _tag, f ) ); + NFunctions::FList.push_back( f ); } -void register_fct_i_i( const char* _name, func_i_i _f ) +void register_fct_i_i( const char* _tag, func_i_i _f ) { + register_fct_template( _tag, "i", "i", (void*)_f ); } -void register_fct_d_d( const char* _name, func_d_d _f ) +void register_fct_d_d( const char* _tag, func_d_d _f ) { + register_fct_template( _tag, "d", "d", (void*)_f ); } -void register_fct_e_e( const char* _name, func_e_e _f ) +void register_fct_e_e( const char* _tag, func_e_e _f ) { } -void register_fct_i_i_i( const char* _name, func_i_i_i _f ) +void register_fct_i_i_i( const char* _tag, func_i_i_i _f ) { } -void register_fct_d_d_d( const char* _name, func_d_d_d _f ) +void register_fct_d_d_d( const char* _tag, func_d_d_d _f ) { } -void register_fct_e_e_e( const char* _name, func_e_e_e _f ) +void register_fct_e_e_e( const char* _tag, func_e_e_e _f ) { } diff --git a/pub/lib/func.hpp b/pub/lib/func.hpp index fd441f9d8e64908a6a50147feb939aae2229d86d..c50b636a5776b054ea94315916fd1b3cb5640412 100644 --- a/pub/lib/func.hpp +++ b/pub/lib/func.hpp @@ -32,51 +32,31 @@ typedef void (*deri_f2) (double&,double&,double,double,double,double); typedef void (*deri_f3) (double&,double&, double,double,double,double,double,double); -//! A wrapper holding a function, its gradient, its name, and more. +//! A wrapper holding a function with given input and output types. + +class CTypedFunc { + public: + const string outtype; + const string intypes; + void* f; // the polymorphic function pointer + CTypedFunc( const char* _outtype, const char* _intypes, void* _f ) + : outtype(_outtype), intypes(_intypes), f(_f) {}; +}; + +//! A wrapper holding a function. class CFunc { public: - const char* name; + const string tag; int narg; const char* explanation; int precedence; - CFunc( const char* _name, int _narg, const char* _explanation="", int _precedence ) - : name(_name), narg(_narg), explanation(_explanation), precedence(_precedence) {}; - virtual ~CFunc() {}; // magic: makes dynamic_cast possible -}; - -//! Wrapping a function with 1 argument. - -class CFunc1 : public CFunc { - public: - func_f1 f1; - deri_f1 d1; - CFunc1( const char* _name, const char* _explanation="", int _precedence ) : - : CFunc( _name, 1, _explanation, _precedence ) {}; + vector<const CTypedFunc*> tyfulis; //! List of available typed function instances. + CFunc( const char* _tag, int _narg, const char* _explanation, int _precedence=0 ) + : tag(_tag), narg(_narg), explanation(_explanation), precedence(_precedence) {}; class CCoord coord( class CCoord *co ) const; -}; - -//! Wrapping a function with 2 arguments. - -class CFunc2 : public CFunc { - public: - func_f2 f2; - deri_f2 d2; - CFunc12( const char* _name, const char* _explanation="", int _precedence ) : - : CFunc( _name, 2, _explanation, _precedence ) {}; class CCoord coord( class CCoord *co1, class CCoord *co2 ) const; -}; - -//! Wrapping a function with 3 arguments. - -class CFunc3 : public CFunc { - public: - func_f3 f3; - deri_f3 d3; - CFunc3( const char* _name, const char* _explanation="", int _precedence ) : - : CFunc( _name, 3, _explanation, _precedence ) {}; - class CCoord coord( - class CCoord *co1, class CCoord *co2, class CCoord *co3 ) const; + class CCoord coord( class CCoord *co1, class CCoord *co2, class CCoord *co3 ) const; }; //! Collection of function wrappers CFunc diff --git a/pub/lib/node.cpp b/pub/lib/node.cpp index ac1dccb7ffd50d109eca469f77ed75be17421ab9..1fcbd511deede4bab01c7cf4314c8c6b35583525 100644 --- a/pub/lib/node.cpp +++ b/pub/lib/node.cpp @@ -255,20 +255,20 @@ void CNodeFun::npar_exec( int *np ) const void CNodeFun1::set_coord( CCoord& ret, int k ) const { CCoord r; arg[0]->set_coord( r, k ); - ret = (dynamic_cast<const CFunc1*>( fu ))->coord( &r ); + ret = fu->coord( &r ); } void CNodeFun2::set_coord( CCoord& ret, int k ) const { CCoord r[2]; arg[0]->set_coord( r[0], k ); arg[1]->set_coord( r[1], k ); - ret = (dynamic_cast<const CFunc2*>( fu ))->coord( r+0, r+1 ); + ret = fu->coord( r+0, r+1 ); } void CNodeFun3::set_coord( CCoord& ret, int k ) const { CCoord r[3]; arg[0]->set_coord( r[0], k ); arg[1]->set_coord( r[1], k ); arg[2]->set_coord( r[2], k ); - ret = (dynamic_cast<const CFunc3*>( fu ))->coord( r+0, r+1, r+2 ); + ret = fu->coord( r+0, r+1, r+2 ); } //! Returns string representation of this node.