From a629d98f0678a30e382283b3b7d4cd3abebaca20 Mon Sep 17 00:00:00 2001 From: Jens Vollinga Date: Wed, 9 Nov 2005 16:47:00 +0000 Subject: [PATCH] * Special power-simplification rules may now be defined for functions. * The function abs defines now such a special rule. [V.Kisil] --- ginac/function.pl | 63 ++++++++++++++++++++++++++++++++++++++++++++++- ginac/inifcns.cpp | 12 +++++++-- ginac/power.cpp | 4 +++ 3 files changed, 76 insertions(+), 3 deletions(-) diff --git a/ginac/function.pl b/ginac/function.pl index 7a2f6a9d..6f6c6e7e 100755 --- a/ginac/function.pl +++ b/ginac/function.pl @@ -83,6 +83,10 @@ $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 &','',''); @@ -99,6 +103,8 @@ $conjugate_func_interface=generate(' function_options & conjugate_func(conjug $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( @@ -149,6 +155,12 @@ $diff_switch_statement=generate( 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}: @@ -207,6 +219,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) @@ -272,6 +294,7 @@ typedef ex (* eval_funcp)(); typedef ex (* evalf_funcp)(); typedef ex (* conjugate_funcp)(); typedef ex (* derivative_funcp)(); +typedef ex (* power_funcp)(); typedef ex (* series_funcp)(); typedef void (* print_funcp)(); @@ -280,6 +303,7 @@ $typedef_eval_funcp $typedef_evalf_funcp $typedef_conjugate_funcp $typedef_derivative_funcp +$typedef_power_funcp $typedef_series_funcp $typedef_print_funcp // end of generated lines @@ -290,6 +314,7 @@ typedef ex (* eval_funcp_exvector)(const exvector &); typedef ex (* evalf_funcp_exvector)(const exvector &); typedef ex (* conjugate_funcp_exvector)(const exvector &); typedef ex (* derivative_funcp_exvector)(const exvector &, unsigned); +typedef ex (* power_funcp_exvector)(const exvector &, const ex &); typedef ex (* series_funcp_exvector)(const exvector &, const relational &, int, unsigned); typedef void (* print_funcp_exvector)(const exvector &, const print_context &); @@ -313,6 +338,7 @@ $eval_func_interface $evalf_func_interface $conjugate_func_interface $derivative_func_interface +$power_func_interface $series_func_interface $print_func_interface // end of generated lines @@ -320,6 +346,7 @@ $print_func_interface function_options & evalf_func(evalf_funcp_exvector ef); function_options & conjugate_func(conjugate_funcp_exvector d); function_options & derivative_func(derivative_funcp_exvector d); + function_options & power_func(power_funcp_exvector d); function_options & series_func(series_funcp_exvector s); template function_options & print_func(print_funcp_exvector p) @@ -341,6 +368,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); @@ -353,6 +381,7 @@ protected: evalf_funcp evalf_f; conjugate_funcp conjugate_f; derivative_funcp derivative_f; + power_funcp power_f; series_funcp series_f; std::vector print_dispatch_table; @@ -371,6 +400,7 @@ protected: bool evalf_use_exvector_args; bool conjugate_use_exvector_args; bool derivative_use_exvector_args; + bool power_use_exvector_args; bool series_use_exvector_args; bool print_use_exvector_args; @@ -441,6 +471,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); @@ -516,6 +547,7 @@ $implementation=<setflag(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; diff --git a/ginac/inifcns.cpp b/ginac/inifcns.cpp index 26ebd937..9a488fe9 100644 --- a/ginac/inifcns.cpp +++ b/ginac/inifcns.cpp @@ -107,13 +107,21 @@ static ex abs_conjugate(const ex & arg) return abs(arg); } +static ex abs_power(const ex & arg, const ex & exp) +{ + if (arg.is_equal(arg.conjugate()) && is_a(exp) && ex_to(exp).is_even()) + return power(arg, exp); + else + return power(abs(arg), exp).hold(); +} + REGISTER_FUNCTION(abs, eval_func(abs_eval). evalf_func(abs_evalf). print_func(abs_print_latex). print_func(abs_print_csrc_float). print_func(abs_print_csrc_float). - conjugate_func(abs_conjugate)); - + conjugate_func(abs_conjugate). + power_func(abs_power)); ////////// // Complex sign diff --git a/ginac/power.cpp b/ginac/power.cpp index 339b48c1..3dd0f48f 100644 --- a/ginac/power.cpp +++ b/ginac/power.cpp @@ -381,6 +381,10 @@ ex power::eval(int level) const if (ebasis.is_equal(_ex1)) return _ex1; + // power of a function calculated by separate rules defined for this function + if (is_exactly_a(ebasis)) + return ex_to(ebasis).power(eexponent); + if (exponent_is_numerical) { // ^(c1,c2) -> c1^c2 (c1, c2 numeric(), -- 2.44.0