]> www.ginac.de Git - ginac.git/blobdiff - ginac/diff.cpp
some changes to allow GiNaC to cooperate with cint:
[ginac.git] / ginac / diff.cpp
index b8ef4c5c71e8bd0120aa902645d9b5d20d728ecb..65ee609a27cc8d04a7c76c43a585dc473e397f00 100644 (file)
@@ -2,9 +2,44 @@
  *
  *  Implementation of symbolic differentiation in all of GiNaC's classes. */
 
+/*
+ *  GiNaC Copyright (C) 1999 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
 #include <stdexcept>
 
-#include "ginac.h"
+#include "basic.h"
+#include "ex.h"
+#include "add.h"
+#include "constant.h"
+#include "expairseq.h"
+#include "indexed.h"
+#include "inifcns.h"
+#include "mul.h"
+#include "ncmul.h"
+#include "numeric.h"
+#include "power.h"
+#include "relational.h"
+#include "series.h"
+#include "symbol.h"
+
+#ifndef NO_GINAC_NAMESPACE
+namespace GiNaC {
+#endif // ndef NO_GINAC_NAMESPACE
 
 /** Default implementation of ex::diff(). It prints and error message and returns a fail object.
  *  @see ex::diff */
@@ -142,17 +177,22 @@ ex power::diff(symbol const & s) const
 ex function::diff(symbol const & s) const
 {
     exvector new_seq;
-
-    if (serial == function_index_Order) {
-
+    
+    if (serial==function_index_Order) {
         // Order Term function only differentiates the argument
         return Order(seq[0].diff(s));
-
     } else {
-
         // Chain rule
+        ex arg_diff;
         for (unsigned i=0; i!=seq.size(); i++) {
-            new_seq.push_back(mul(pdiff(i), seq[i].diff(s)));
+            arg_diff = seq[i].diff(s);
+            // We apply the chain rule only when it makes sense.  This is not
+            // just for performance reasons but also to allow functions to
+            // throw when differentiated with respect to one of its arguments
+            // without running into trouble with our automatic full
+            // differentiation:
+            if (!arg_diff.is_zero())
+                new_seq.push_back(mul(pdiff(i), arg_diff));
         }
     }
     return add(new_seq);
@@ -167,7 +207,7 @@ ex series::diff(symbol const & s) const
         epvector new_seq;
         epvector::const_iterator it = seq.begin(), itend = seq.end();
         
-        //!! coeff might depend on var
+        // FIXME: coeff might depend on var
         while (it != itend) {
             if (is_order_function(it->rest)) {
                 new_seq.push_back(expair(it->rest, it->coeff - 1));
@@ -193,16 +233,20 @@ ex series::diff(symbol const & s) const
 
 ex ex::diff(symbol const & s, unsigned nth) const
 {
-    ASSERT(bp!=0);
+    GINAC_ASSERT(bp!=0);
 
-    if ( nth==0 ) {
+    if (nth==0) {
         return *this;
     }
 
     ex ndiff = bp->diff(s);
-    while ( nth>1 ) {
+    while (nth>1) {
         ndiff = ndiff.diff(s);
         --nth;
     }
     return ndiff;
 }
+
+#ifndef NO_GINAC_NAMESPACE
+} // namespace GiNaC
+#endif // ndef NO_GINAC_NAMESPACE