- fixed bug in normal(): normal(x^a) became (x^(-a))^(-1)
authorChristian Bauer <Christian.Bauer@uni-mainz.de>
Mon, 20 Mar 2000 15:17:44 +0000 (15:17 +0000)
committerChristian Bauer <Christian.Bauer@uni-mainz.de>
Mon, 20 Mar 2000 15:17:44 +0000 (15:17 +0000)
- first shot at inert Diff() and Derivative() functions; still buggy!

ginac/function.pl
ginac/inifcns.cpp
ginac/inifcns.h
ginac/normal.cpp
ginsh/ginsh_parser.yy

index 4a218bbe84952dbeb7f77affbc0285a1062aee08..988206e9265ebfb231c607b1d75eb3bd4a321525 100755 (executable)
@@ -508,7 +508,11 @@ protected:
     unsigned serial;
 };
 
-// utility macros
+// utility functions/macros
+inline const function &ex_to_function(const ex &e)
+{
+    return static_cast<const function &>(*e.bp);
+}
 
 #ifndef NO_NAMESPACE_GINAC
 
@@ -1041,7 +1045,7 @@ ex function::pderivative(unsigned diff_param) const // partial differentiation
     GINAC_ASSERT(serial<registered_functions().size());
     
     if (registered_functions()[serial].derivative_f==0) {
-        throw(std::logic_error(string("function::pderivative(") + registered_functions()[serial].name + "): no diff function defined"));
+        return Derivative(*this, diff_param);
     }
     switch (registered_functions()[serial].nparams) {
         // the following lines have been generated for max. ${maxargs} parameters
index 55da24d052de66e3559a5469a87f57b8b0883d56..e9e2cad1421b0bbcbccd985d487f61994d58d62a 100644 (file)
@@ -166,9 +166,50 @@ static ex Order_series(const ex & x, const symbol & s, const ex & point, int ord
        return pseries(s, point, new_seq);
 }
 
+// Differentiation is handled in function::derivative because of its special requirements
+
 REGISTER_FUNCTION(Order, eval_func(Order_eval).
                          series_func(Order_series));
 
+//////////
+// Inert differentiation
+//////////
+
+static ex Diff_eval(const ex & f, const ex & x)
+{
+       return Diff(f, x).hold();
+}
+
+static ex Diff_deriv(const ex & f, const ex & x, unsigned deriv_param)
+{
+       GINAC_ASSERT(deriv_param == 0 || deriv_param == 1);
+       if (deriv_param == 1)
+               return Diff(Diff(f, x), x);
+       else
+               return _ex0();
+}
+
+REGISTER_FUNCTION(Diff, eval_func(Diff_eval).
+                        derivative_func(Diff_deriv));
+
+//////////
+// Inert partial differentiation operator
+//////////
+
+static ex Derivative_eval(const ex & f, const ex & n)
+{
+       if (is_ex_exactly_of_type(n, numeric) && ex_to_numeric(n).is_nonneg_integer()) {
+               unsigned i = ex_to_numeric(n).to_int();
+               if (is_ex_exactly_of_type(f, function)) {
+                       if (i < f.nops() && is_ex_exactly_of_type(f.op(i), symbol))
+                               return Diff(f, f.op(i));
+               }
+       }
+       return Derivative(f, n).hold();
+}
+
+REGISTER_FUNCTION(Derivative, eval_func(Derivative_eval));
+
 //////////
 // Solve linear system
 //////////
index 603edb3ec1854383f5cded07cbaf5d956d3828d7..176f67943ccbfecdb9af7fb7ba4f035aae790196 100644 (file)
@@ -123,6 +123,12 @@ DECLARE_FUNCTION_2P(binomial)
 /** Order term function (for truncated power series). */
 DECLARE_FUNCTION_1P(Order)
 
+/** Inert differentiation. */
+DECLARE_FUNCTION_2P(Diff)
+
+/** Inert partial differentiation operator. */
+DECLARE_FUNCTION_2P(Derivative)
+
 ex lsolve(const ex &eqns, const ex &symbols);
 
 ex ncpower(const ex &basis, unsigned exponent);
index a5ebeb8b691ee4b6d95355fff45a17d68d87a414..d23b2289d520aa535bd0dd6fb43b6e43080536a7 100644 (file)
@@ -1574,19 +1574,20 @@ ex power::normal(lst &sym_lst, lst &repl_lst, int level) const
                        // (a/b)^n -> {a^n, b^n}
                        return (new lst(power(n.op(0), exponent), power(n.op(1), exponent)))->setflag(status_flags::dynallocated);
 
-               } else if (exponent.info(info_flags::negint)) {
+               } else if (exponent.info(info_flags::negative)) {
 
                        // (a/b)^-n -> {b^n, a^n}
                        return (new lst(power(n.op(1), -exponent), power(n.op(0), -exponent)))->setflag(status_flags::dynallocated);
                }
 
        } else {
+
                if (exponent.info(info_flags::positive)) {
 
-                       // (a/b)^z -> {sym((a/b)^z), 1}
+                       // (a/b)^x -> {sym((a/b)^x), 1}
                        return (new lst(replace_with_symbol(power(n.op(0) / n.op(1), exponent), sym_lst, repl_lst), _ex1()))->setflag(status_flags::dynallocated);
 
-               } else {
+               } else if (exponent.info(info_flags::negative)) {
 
                        if (n.op(1).is_equal(_ex1())) {
 
@@ -1595,9 +1596,14 @@ ex power::normal(lst &sym_lst, lst &repl_lst, int level) const
 
                        } else {
 
-                               // (a/b)^-x -> {(b/a)^x, 1}
+                               // (a/b)^-x -> {sym((b/a)^x), 1}
                                return (new lst(replace_with_symbol(power(n.op(1) / n.op(0), -exponent), sym_lst, repl_lst), _ex1()))->setflag(status_flags::dynallocated);
                        }
+
+               } else {        // exponent not numeric
+
+                       // (a/b)^x -> {sym((a/b)^x, 1}
+                       return (new lst(replace_with_symbol(power(n.op(0) / n.op(1), exponent), sym_lst, repl_lst), _ex1()))->setflag(status_flags::dynallocated);
                }
     }
 }
index fdb9bffa634fd1c6cad39ae3b12eae061473b9e3..6697d6f020ce0cfc4285ec72361488a1b26b7db0 100644 (file)
@@ -151,7 +151,6 @@ line        : ';'
                cout << "You should have received a copy of the GNU General Public License along with\n";
                cout << "this program. If not, write to the Free Software Foundation, 675 Mass Ave,\n";
                cout << "Cambridge, MA 02139, USA.\n";
-
        }
        | T_XYZZY               {cout << "Nothing happens.\n";}
        | T_INVENTORY           {cout << "You're not carrying anything.\n";}