X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Ffunction.pl;h=6c70d2dd52137b26a6cb7b361e786dcc063379e8;hp=1f944f1a4f9c74a07dc13bb815c34f1dec61a65f;hb=def26469ff96228c66e877bb5594e7d9a24b638f;hpb=6d7bf9ee5a7ce05cb3a23dae664e781d7325d7b8 diff --git a/ginac/function.pl b/ginac/function.pl old mode 100755 new mode 100644 index 1f944f1a..6c70d2dd --- a/ginac/function.pl +++ b/ginac/function.pl @@ -1,4 +1,24 @@ -$maxargs=13; +# This perl script automatically generates function.h and function.cpp + +# function.pl options: \$maxargs=${maxargs} +# +# GiNaC Copyright (C) 1999-2008 Johannes Gutenberg University Mainz, Germany +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +$maxargs=14; sub generate_seq { my ($seq_template,$n)=@_; @@ -40,6 +60,7 @@ $declare_function_macro = generate( <<'END_OF_DECLARE_FUNCTION_MACRO','typename T${N}','const T${N} & p${N}','GiNaC::ex(p${N})'); #define DECLARE_FUNCTION_${N}P(NAME) \\ class NAME##_SERIAL { public: static unsigned serial; }; \\ +const unsigned NAME##_NPARAMS = ${N}; \\ template<${SEQ1}> const GiNaC::function NAME(${SEQ2}) { \\ return GiNaC::function(NAME##_SERIAL::serial, ${SEQ3}); \\ } @@ -54,10 +75,26 @@ $typedef_evalf_funcp=generate( 'typedef ex (* evalf_funcp_${N})(${SEQ1});'."\n", 'const ex &','',''); +$typedef_conjugate_funcp=generate( +'typedef ex (* conjugate_funcp_${N})(${SEQ1});'."\n", +'const ex &','',''); + +$typedef_real_part_funcp=generate( +'typedef ex (* real_part_funcp_${N})(${SEQ1});'."\n", +'const ex &','',''); + +$typedef_imag_part_funcp=generate( +'typedef ex (* imag_part_funcp_${N})(${SEQ1});'."\n", +'const ex &','',''); + $typedef_derivative_funcp=generate( 'typedef ex (* derivative_funcp_${N})(${SEQ1}, unsigned);'."\n", 'const ex &','',''); +$typedef_power_funcp=generate( +'typedef ex (* power_funcp_${N})(${SEQ1}, const ex &);'."\n", +'const ex &','',''); + $typedef_series_funcp=generate( 'typedef ex (* series_funcp_${N})(${SEQ1}, const relational &, int, unsigned);'."\n", 'const ex &','',''); @@ -70,8 +107,16 @@ $eval_func_interface=generate(' function_options & eval_func(eval_funcp_${N} $evalf_func_interface=generate(' function_options & evalf_func(evalf_funcp_${N} ef);'."\n",'','',''); +$conjugate_func_interface=generate(' function_options & conjugate_func(conjugate_funcp_${N} d);'."\n",'','',''); + +$real_part_func_interface=generate(' function_options & real_part_func(real_part_funcp_${N} d);'."\n",'','',''); + +$imag_part_func_interface=generate(' function_options & imag_part_func(imag_part_funcp_${N} d);'."\n",'','',''); + $derivative_func_interface=generate(' function_options & derivative_func(derivative_funcp_${N} d);'."\n",'','',''); +$power_func_interface=generate(' function_options & power_func(power_funcp_${N} d);'."\n",'','',''); + $series_func_interface=generate(' function_options & series_func(series_funcp_${N} s);'."\n",'','',''); $print_func_interface=generate( @@ -93,7 +138,6 @@ $constructors_implementation=generate( function::function(unsigned ser, ${SEQ1}) : exprseq(${SEQ2}), serial(ser) { - tinfo_key = TINFO_function; } END_OF_CONSTRUCTORS_IMPLEMENTATION @@ -110,12 +154,36 @@ $evalf_switch_statement=generate( return ((evalf_funcp_${N})(opt.evalf_f))(${SEQ1}); END_OF_EVALF_SWITCH_STATEMENT +$conjugate_switch_statement=generate( + <<'END_OF_DIFF_SWITCH_STATEMENT','seq[${N}-1]','',''); + case ${N}: + return ((conjugate_funcp_${N})(opt.conjugate_f))(${SEQ1}); +END_OF_DIFF_SWITCH_STATEMENT + +$real_part_switch_statement=generate( + <<'END_OF_DIFF_SWITCH_STATEMENT','seq[${N}-1]','',''); + case ${N}: + return ((real_part_funcp_${N})(opt.real_part_f))(${SEQ1}); +END_OF_DIFF_SWITCH_STATEMENT + +$imag_part_switch_statement=generate( + <<'END_OF_DIFF_SWITCH_STATEMENT','seq[${N}-1]','',''); + case ${N}: + return ((imag_part_funcp_${N})(opt.imag_part_f))(${SEQ1}); +END_OF_DIFF_SWITCH_STATEMENT + $diff_switch_statement=generate( <<'END_OF_DIFF_SWITCH_STATEMENT','seq[${N}-1]','',''); case ${N}: return ((derivative_funcp_${N})(opt.derivative_f))(${SEQ1},diff_param); END_OF_DIFF_SWITCH_STATEMENT +$power_switch_statement=generate( + <<'END_OF_POWER_SWITCH_STATEMENT','seq[${N}-1]','',''); + case ${N}: + return ((power_funcp_${N})(opt.power_f))(${SEQ1},power_param); +END_OF_POWER_SWITCH_STATEMENT + $series_switch_statement=generate( <<'END_OF_SERIES_SWITCH_STATEMENT','seq[${N}-1]','',''); case ${N}: @@ -154,6 +222,36 @@ function_options & function_options::evalf_func(evalf_funcp_${N} ef) } END_OF_EVALF_FUNC_IMPLEMENTATION +$conjugate_func_implementation=generate( + <<'END_OF_CONJUGATE_FUNC_IMPLEMENTATION','','',''); +function_options & function_options::conjugate_func(conjugate_funcp_${N} c) +{ + test_and_set_nparams(${N}); + conjugate_f = conjugate_funcp(c); + return *this; +} +END_OF_CONJUGATE_FUNC_IMPLEMENTATION + +$real_part_func_implementation=generate( + <<'END_OF_REAL_PART_FUNC_IMPLEMENTATION','','',''); +function_options & function_options::real_part_func(real_part_funcp_${N} c) +{ + test_and_set_nparams(${N}); + real_part_f = real_part_funcp(c); + return *this; +} +END_OF_REAL_PART_FUNC_IMPLEMENTATION + +$imag_part_func_implementation=generate( + <<'END_OF_IMAG_PART_FUNC_IMPLEMENTATION','','',''); +function_options & function_options::imag_part_func(imag_part_funcp_${N} c) +{ + test_and_set_nparams(${N}); + imag_part_f = imag_part_funcp(c); + return *this; +} +END_OF_IMAG_PART_FUNC_IMPLEMENTATION + $derivative_func_implementation=generate( <<'END_OF_DERIVATIVE_FUNC_IMPLEMENTATION','','',''); function_options & function_options::derivative_func(derivative_funcp_${N} d) @@ -164,6 +262,16 @@ function_options & function_options::derivative_func(derivative_funcp_${N} d) } END_OF_DERIVATIVE_FUNC_IMPLEMENTATION +$power_func_implementation=generate( + <<'END_OF_POWER_FUNC_IMPLEMENTATION','','',''); +function_options & function_options::power_func(power_funcp_${N} d) +{ + test_and_set_nparams(${N}); + power_f = power_funcp(d); + return *this; +} +END_OF_POWER_FUNC_IMPLEMENTATION + $series_func_implementation=generate( <<'END_OF_SERIES_FUNC_IMPLEMENTATION','','',''); function_options & function_options::series_func(series_funcp_${N} s) @@ -184,7 +292,7 @@ $interface=< function_options & print_func(print_funcp_exvector p) @@ -278,7 +409,7 @@ $print_func_interface return *this; } - function_options & set_return_type(unsigned rt, unsigned rtt=0); + function_options & set_return_type(unsigned rt, const return_type_t* rtt = 0); function_options & do_not_evalf_params(); function_options & remember(unsigned size, unsigned assoc_size=0, unsigned strategy=remember_strategies::delete_never); @@ -290,6 +421,7 @@ $print_func_interface protected: bool has_derivative() const { return derivative_f != NULL; } + bool has_power() const { return power_f != NULL; } void test_and_set_nparams(unsigned n); void set_print_func(unsigned id, print_funcp f); @@ -300,7 +432,11 @@ protected: eval_funcp eval_f; evalf_funcp evalf_f; + conjugate_funcp conjugate_f; + real_part_funcp real_part_f; + imag_part_funcp imag_part_f; derivative_funcp derivative_f; + power_funcp power_f; series_funcp series_f; std::vector print_dispatch_table; @@ -308,7 +444,7 @@ protected: bool use_return_type; unsigned return_type; - unsigned return_type_tinfo; + return_type_t return_type_tinfo; bool use_remember; unsigned remember_size; @@ -317,7 +453,11 @@ protected: bool eval_use_exvector_args; bool evalf_use_exvector_args; + bool conjugate_use_exvector_args; + bool real_part_use_exvector_args; + bool imag_part_use_exvector_args; bool derivative_use_exvector_args; + bool power_use_exvector_args; bool series_use_exvector_args; bool print_use_exvector_args; @@ -366,16 +506,20 @@ public: ex expand(unsigned options=0) const; ex eval(int level=0) const; ex evalf(int level=0) const; + ex eval_ncmul(const exvector & v) const; unsigned calchash() const; ex series(const relational & r, int order, unsigned options = 0) const; ex thiscontainer(const exvector & v) const; ex thiscontainer(std::auto_ptr vp) const; + ex conjugate() const; + ex real_part() const; + ex imag_part() const; protected: ex derivative(const symbol & s) const; bool is_equal_same_type(const basic & other) const; bool match_same_type(const basic & other) const; unsigned return_type() const; - unsigned return_type_tinfo() const; + return_type_t return_type_tinfo() const; // new virtual functions which can be overridden by derived classes // none @@ -387,6 +531,7 @@ protected: bool lookup_remember_table(ex & result) const; void store_remember_table(ex const & result) const; public: + ex power(const ex & exp) const; static unsigned register_new(function_options const & opt); static unsigned current_serial; static unsigned find_function(const std::string &name, unsigned nparams); @@ -401,12 +546,6 @@ protected: // utility functions/macros -/** Specialization of is_exactly_a(obj) for objects of type function. */ -template<> inline bool is_exactly_a(const basic & obj) -{ - return obj.tinfo()==TINFO_function; -} - template inline bool is_the_function(const ex & x) { @@ -433,7 +572,7 @@ $implementation=< #include #include #include +#include #include "function.h" #include "operators.h" @@ -462,6 +602,7 @@ $implementation=<(); return *this; } @@ -628,7 +813,6 @@ GINAC_IMPLEMENT_REGISTERED_CLASS(function, exprseq) function::function() : serial(0) { - tinfo_key = TINFO_function; } ////////// @@ -639,7 +823,6 @@ function::function() : serial(0) function::function(unsigned ser) : serial(ser) { - tinfo_key = TINFO_function; } // the following lines have been generated for max. ${maxargs} parameters @@ -648,7 +831,6 @@ $constructors_implementation function::function(unsigned ser, const exprseq & es) : exprseq(es), serial(ser) { - tinfo_key = TINFO_function; // Force re-evaluation even if the exprseq was already evaluated // (the exprseq copy constructor copies the flags) @@ -658,13 +840,11 @@ function::function(unsigned ser, const exprseq & es) : exprseq(es), serial(ser) function::function(unsigned ser, const exvector & v, bool discardable) : exprseq(v,discardable), serial(ser) { - tinfo_key = TINFO_function; } function::function(unsigned ser, std::auto_ptr vp) : exprseq(vp), serial(ser) { - tinfo_key = TINFO_function; } ////////// @@ -802,7 +982,7 @@ ex function::eval(int level) const exvector v = seq; GINAC_ASSERT(is_a(opt.symtree)); int sig = canonicalize(v.begin(), ex_to(opt.symtree)); - if (sig != INT_MAX) { + if (sig != std::numeric_limits::max()) { // Something has changed while sorting arguments, more evaluations later if (sig == 0) return _ex0; @@ -871,9 +1051,20 @@ ${evalf_switch_statement} throw(std::logic_error("function::evalf(): invalid nparams")); } +/** + * This method is defined to be in line with behaviour of function::return_type() + */ +ex function::eval_ncmul(const exvector & v) const +{ + // If this function is called then the list of arguments is non-empty + // and the first argument is non-commutative, see function::return_type() + return seq.begin()->eval_ncmul(v); +} + unsigned function::calchash() const { - unsigned v = golden_ratio_hash(golden_ratio_hash(tinfo()) ^ serial); + const void* this_tinfo = (const void*)typeid(*this).name(); + unsigned v = golden_ratio_hash(golden_ratio_hash((p_int)this_tinfo) ^ serial); for (size_t i=0; iop(i).gethash(); @@ -924,6 +1115,68 @@ ${series_switch_statement} throw(std::logic_error("function::series(): invalid nparams")); } +/** Implementation of ex::conjugate for functions. */ +ex function::conjugate() const +{ + GINAC_ASSERT(serial(); else return seq.begin()->return_type_tinfo(); } @@ -1052,10 +1305,31 @@ ${diff_switch_statement} throw(std::logic_error("function::pderivative(): no diff function defined")); } +ex function::power(const ex & power_param) const // power of function +{ + GINAC_ASSERT(serialsetflag(status_flags::dynallocated | + status_flags::evaluated); + + current_serial = serial; + if (opt.power_use_exvector_args) + return ((power_funcp_exvector)(opt.power_f))(seq, power_param); + switch (opt.nparams) { + // the following lines have been generated for max. ${maxargs} parameters +${power_switch_statement} + // end of generated lines + } + throw(std::logic_error("function::power(): no power function defined")); +} + std::vector & function::registered_functions() { - static std::vector * rf = new std::vector; - return *rf; + static std::vector rf = std::vector(); + return rf; } bool function::lookup_remember_table(ex & result) const