Functions can define a custom expand() now.
authorVladimir V. Kisil <kisilv@maths.leeds.ac.uk>
Mon, 7 Oct 2013 05:04:30 +0000 (08:04 +0300)
committerAlexei Sheplyakov <Alexei.Sheplyakov@gmail.com>
Wed, 16 Oct 2013 05:20:29 +0000 (08:20 +0300)
Signed-off-by: Vladimir V. Kisil <kisilv@maths.leeds.ac.uk>
ginac/function.cppy
ginac/function.hppy
ginac/function.py
ginac/version.h

index fb83cdc..2a9080c 100644 (file)
@@ -78,8 +78,8 @@ void function_options::initialize()
 {
        set_name("unnamed_function", "\\\\mbox{unnamed}");
        nparams = 0;
-       eval_f = evalf_f = real_part_f = imag_part_f = conjugate_f = derivative_f
-               = power_f = series_f = 0;
+       eval_f = evalf_f = real_part_f = imag_part_f = conjugate_f = expand_f
+               = derivative_f = power_f = series_f = 0;
        evalf_params_first = true;
        use_return_type = false;
        eval_use_exvector_args = false;
@@ -87,6 +87,7 @@ void function_options::initialize()
        conjugate_use_exvector_args = false;
        real_part_use_exvector_args = false;
        imag_part_use_exvector_args = false;
+       expand_use_exvector_args = false;
        derivative_use_exvector_args = false;
        power_use_exvector_args = false;
        series_use_exvector_args = false;
@@ -360,15 +361,6 @@ next_context:
        }
 }
 
-ex function::expand(unsigned options) const
-{
-       // Only expand arguments when asked to do so
-       if (options & expand_options::expand_function_args)
-               return inherited::expand(options);
-       else
-               return (options == 0) ? setflag(status_flags::expanded) : *this;
-}
-
 ex function::eval(int level) const
 {
        if (level>1) {
@@ -756,6 +748,34 @@ ex function::power(const ex & power_param) const // power of function
        throw(std::logic_error("function::power(): no power function defined"));
 }
 
+ex function::expand(unsigned options) const
+{
+       GINAC_ASSERT(serial<registered_functions().size());
+       const function_options &opt = registered_functions()[serial];
+
+       // No expand defined? Then return the same function with expanded arguments (if required)
+       if (opt.expand_f == NULL) {
+               // Only expand arguments when asked to do so
+               if (options & expand_options::expand_function_args)
+                       return inherited::expand(options);
+               else
+                       return (options == 0) ? setflag(status_flags::expanded) : *this;
+       }
+
+       current_serial = serial;
+       if (opt.expand_use_exvector_args)
+               return ((expand_funcp_exvector)(opt.expand_f))(seq,  options);
+       switch (opt.nparams) {
+               // the following lines have been generated for max. @maxargs@ parameters
++++ for N in range(1, maxargs + 1):
+               case @N@:
+                       return ((expand_funcp_@N@)(opt.expand_f))(@seq('seq[%(n)d]', N, 0)@, options);
+---
+               // end of generated lines
+       }
+       throw(std::logic_error("function::expand(): no expand of function defined"));
+}
+
 std::vector<function_options> & function::registered_functions()
 {
        static std::vector<function_options> rf = std::vector<function_options>();
index e7ec83e..fa17813 100644 (file)
@@ -57,6 +57,7 @@ typedef ex (* evalf_funcp)();
 typedef ex (* conjugate_funcp)();
 typedef ex (* real_part_funcp)();
 typedef ex (* imag_part_funcp)();
+typedef ex (* expand_funcp)();
 typedef ex (* derivative_funcp)();
 typedef ex (* power_funcp)();
 typedef ex (* series_funcp)();
@@ -69,6 +70,7 @@ typedef ex (* evalf_funcp_@N@)( @args@ );
 typedef ex (* conjugate_funcp_@N@)( @args@ );
 typedef ex (* real_part_funcp_@N@)( @args@ );
 typedef ex (* imag_part_funcp_@N@)( @args@ );
+typedef ex (* expand_funcp_@N@)( @args@, unsigned );
 typedef ex (* derivative_funcp_@N@)( @args@, unsigned );
 typedef ex (* power_funcp_@N@)( @args@, const ex & );
 typedef ex (* series_funcp_@N@)( @args@, const relational &, int, unsigned );
@@ -81,6 +83,7 @@ typedef void (* print_funcp_@N@)( @args@, const print_context & );
 +++ for fp in "eval evalf conjugate real_part imag_part".split():
 typedef ex (* @fp@_funcp_exvector)(const exvector &);
 ---
+typedef ex (* expand_funcp_exvector)(const exvector &, unsigned);
 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);
@@ -151,6 +154,7 @@ protected:
        conjugate_funcp conjugate_f;
        real_part_funcp real_part_f;
        imag_part_funcp imag_part_f;
+       expand_funcp expand_f;
        derivative_funcp derivative_f;
        power_funcp power_f;
        series_funcp series_f;
@@ -172,6 +176,7 @@ protected:
        bool conjugate_use_exvector_args;
        bool real_part_use_exvector_args;
        bool imag_part_use_exvector_args;
+       bool expand_use_exvector_args;
        bool derivative_use_exvector_args;
        bool power_use_exvector_args;
        bool series_use_exvector_args;
index 6ceb254..0ecb918 100755 (executable)
@@ -2,7 +2,7 @@
 # encoding: utf-8
 
 maxargs = 14
-methods = "eval evalf conjugate real_part imag_part derivative power series print".split()
+methods = "eval evalf conjugate real_part imag_part expand derivative power series print".split()
 
 import sys, os, optparse
 sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'scripts'))
index 7ce9d5c..61d5c18 100644 (file)
@@ -49,9 +49,9 @@
 // increasing. This doesn't matter, though: there is not incurred cost
 // for numbers that are omitted, except for shrinking the available space
 // of leftover numbers. Not something we need to worry about yet. ;-)
-#define GINAC_LT_CURRENT  3
+#define GINAC_LT_CURRENT  4
 #define GINAC_LT_REVISION 0
-#define GINAC_LT_AGE      1
+#define GINAC_LT_AGE      2
 
 /*
  * GiNaC archive file version information.