- replaced the Derivative() function by a more resonable fderivative class;
authorChristian Bauer <Christian.Bauer@uni-mainz.de>
Wed, 27 Jun 2001 00:32:01 +0000 (00:32 +0000)
committerChristian Bauer <Christian.Bauer@uni-mainz.de>
Wed, 27 Jun 2001 00:32:01 +0000 (00:32 +0000)
  to see it in action, try "series(abs(x),x==0,3)" and "series(abs(x),x==y,3)"
  in ginsh with previous GiNaC releases and with this one
- add::eval() throws an exception when the first term is non-commutative and
  the overall_coeff is non-zero
- small fixes to print_tree output of indexed objects
- ncmul::expand() now actually does expand something like "(dirac_gamma(mu)+1)
  *dirac_gamma(nu)" correctly (but the change to add::eval() should make this
  a "can't happen" case)
- moved ToString() to tostring.h (fewer header dependencies)
- ALL YOUR "BASES CLASSES" ARE BELONG TO US

54 files changed:
ginac/Makefile.am
ginac/add.cpp
ginac/add.h
ginac/archive.cpp
ginac/basic.cpp
ginac/basic.h
ginac/clifford.cpp
ginac/clifford.h
ginac/color.cpp
ginac/color.h
ginac/constant.cpp
ginac/constant.h
ginac/container.pl
ginac/ex.cpp
ginac/ex.h
ginac/expairseq.cpp
ginac/expairseq.h
ginac/fail.cpp
ginac/fail.h
ginac/fderivative.cpp [new file with mode: 0644]
ginac/fderivative.h [new file with mode: 0644]
ginac/function.pl
ginac/ginac.h
ginac/idx.cpp
ginac/idx.h
ginac/indexed.cpp
ginac/inifcns.cpp
ginac/inifcns.h
ginac/inifcns_trans.cpp
ginac/matrix.cpp
ginac/matrix.h
ginac/mul.cpp
ginac/mul.h
ginac/ncmul.cpp
ginac/ncmul.h
ginac/numeric.cpp
ginac/numeric.h
ginac/power.cpp
ginac/power.h
ginac/pseries.cpp
ginac/relational.cpp
ginac/relational.h
ginac/structure.cpp
ginac/structure.h
ginac/structure.pl
ginac/symbol.cpp
ginac/symbol.h
ginac/symmetry.cpp
ginac/tensor.cpp
ginac/tensor.h
ginac/tinfos.h
ginac/utils.cpp
ginac/utils.h
ginac/wildcard.cpp

index 913457c..fc759b1 100644 (file)
@@ -8,7 +8,7 @@ libginac_la_SOURCES = add.cpp archive.cpp basic.cpp constant.cpp ex.cpp \
   symbol.cpp pseries.cpp utils.cpp ncmul.cpp structure.cpp exprseq_suppl.cpp \
   lst.cpp lst_suppl.cpp input_parser.yy input_lexer.ll input_lexer.h \
   remember.h remember.cpp debugmsg.h utils.h idx.cpp indexed.cpp tensor.cpp \
-  color.cpp clifford.cpp wildcard.cpp symmetry.cpp
+  color.cpp clifford.cpp wildcard.cpp symmetry.cpp fderivative.cpp tostring.h
 libginac_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
   -release $(LT_RELEASE)
 ginacincludedir = $(includedir)/ginac
@@ -17,7 +17,7 @@ ginacinclude_HEADERS = ginac.h add.h archive.h basic.h constant.h ex.h \
   lst.h matrix.h mul.h ncmul.h normal.h numeric.h operators.h power.h \
   registrar.h relational.h pseries.h structure.h symbol.h tinfos.h assertion.h \
   version.h idx.h indexed.h tensor.h color.h clifford.h wildcard.h print.h \
-  symmetry.h
+  symmetry.h fderivative.h
 LFLAGS = -Pginac_yy -olex.yy.c
 YFLAGS = -p ginac_yy -d
 EXTRA_DIST = container.pl function.pl structure.pl input_parser.h version.h.in
index 7764d36..b681a4f 100644 (file)
@@ -107,7 +107,7 @@ add::add(epvector * vp, const ex & oc)
 DEFAULT_ARCHIVING(add)
 
 //////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
 //////////
 
 // public
@@ -339,12 +339,14 @@ ex add::eval(int level) const
        }
        
        int seq_size = seq.size();
-       if (seq_size==0) {
+       if (seq_size == 0) {
                // +(;c) -> c
                return overall_coeff;
-       } else if ((seq_size==1) && overall_coeff.is_zero()) {
+       } else if (seq_size == 1 && overall_coeff.is_zero()) {
                // +(x;0) -> x
                return recombine_pair_to_ex(*(seq.begin()));
+       } else if (!overall_coeff.is_zero() && seq[0].rest.return_type() != return_types::commutative) {
+               throw (std::logic_error("add::eval(): sum of non-commutative objects has non-zero numeric term"));
        }
        return this->hold();
 }
index c0dfca5..fe8d20b 100644 (file)
@@ -44,7 +44,7 @@ public:
        add(const epvector & v, const ex & oc);
        add(epvector * vp, const ex & oc);
        
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
        unsigned precedence(void) const {return 40;}
index c547916..c5c2613 100644 (file)
@@ -27,7 +27,7 @@
 #include "registrar.h"
 #include "ex.h"
 #include "config.h"
-#include "utils.h"
+#include "tostring.h"
 
 namespace GiNaC {
 
index f8839db..36ea641 100644 (file)
@@ -101,12 +101,6 @@ void basic::archive(archive_node &n) const
        n.add_string("class", class_name());
 }
 
-//////////
-// functions overriding virtual functions from bases classes
-//////////
-
-// none
-
 //////////
 // new virtual functions which can be overridden by derived classes
 //////////
index 56369b8..28568c5 100644 (file)
@@ -96,8 +96,6 @@ protected:
        {
                /* debugmsg("basic ctor with tinfo_key", LOGLEVEL_CONSTRUCT); */
        }
-       // functions overriding virtual functions from bases classes
-       // none
        
        // new virtual functions which can be overridden by derived classes
 public: // only const functions please (may break reference counting)
index cde94eb..8d8c2c6 100644 (file)
@@ -123,7 +123,7 @@ DEFAULT_ARCHIVING(diracgamma)
 DEFAULT_ARCHIVING(diracgamma5)
 
 //////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
 //////////
 
 int clifford::compare_same_type(const basic & other) const
index 7120a4b..0c8573a 100644 (file)
@@ -71,7 +71,7 @@ class diracone : public tensor
 {
        GINAC_DECLARE_REGISTERED_CLASS(diracone, tensor)
 
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
 };
@@ -82,7 +82,7 @@ class diracgamma : public tensor
 {
        GINAC_DECLARE_REGISTERED_CLASS(diracgamma, tensor)
 
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
        bool contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const;
@@ -95,7 +95,7 @@ class diracgamma5 : public tensor
 {
        GINAC_DECLARE_REGISTERED_CLASS(diracgamma5, tensor)
 
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
 };
index 3b54417..561f88b 100644 (file)
@@ -124,7 +124,7 @@ DEFAULT_ARCHIVING(su3f)
 DEFAULT_ARCHIVING(su3d)
 
 //////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
 //////////
 
 int color::compare_same_type(const basic & other) const
index ba62735..03b9d8d 100644 (file)
@@ -73,7 +73,7 @@ class su3one : public tensor
 {
        GINAC_DECLARE_REGISTERED_CLASS(su3one, tensor)
 
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
 };
@@ -83,7 +83,7 @@ class su3t : public tensor
 {
        GINAC_DECLARE_REGISTERED_CLASS(su3t, tensor)
 
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
        bool contract_with(exvector::iterator self, exvector::iterator other, exvector & v) const;
@@ -95,7 +95,7 @@ class su3f : public tensor
 {
        GINAC_DECLARE_REGISTERED_CLASS(su3f, tensor)
 
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
        ex eval_indexed(const basic & i) const;
@@ -107,7 +107,7 @@ class su3d : public tensor
 {
        GINAC_DECLARE_REGISTERED_CLASS(su3d, tensor)
 
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
        ex eval_indexed(const basic & i) const;
index 4ca9492..60c3be2 100644 (file)
@@ -131,7 +131,7 @@ void constant::archive(archive_node &n) const
 }
 
 //////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
 //////////
 
 // public
index 160b7ac..bdd8d69 100644 (file)
@@ -46,7 +46,7 @@ public:
        constant(const std::string & initname, evalffunctype efun = 0, const std::string & texname = std::string());
        constant(const std::string & initname, const numeric & initnumber, const std::string & texname = std::string());
        
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
        int degree(const ex & s) const;
index a0a4a7b..8374b9b 100755 (executable)
@@ -430,7 +430,7 @@ void ${CONTAINER}::archive(archive_node &n) const
 }
 
 //////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
 //////////
 
 // public
index de48a4f..b6b9685 100644 (file)
@@ -43,18 +43,6 @@ namespace GiNaC {
 
 // none (all inlined)
 
-//////////
-// functions overriding virtual functions from bases classes
-//////////
-
-// none
-
-//////////
-// new virtual functions which can be overridden by derived classes
-//////////
-
-// none
-
 //////////
 // non-virtual functions in this class
 //////////
index fcba458..88f4e2e 100644 (file)
@@ -70,12 +70,6 @@ public:
         *  symbols and other parser errors will throw an exception. */
        ex(const std::string &s, const ex &l);
        
-       // functions overriding virtual functions from bases classes
-       // none
-       
-       // new virtual functions which can be overridden by derived classes
-       // none
-
        // non-virtual functions in this class
 public:
        void swap(ex & other);
index 87b19e1..d796e4b 100644 (file)
@@ -177,7 +177,7 @@ void expairseq::archive(archive_node &n) const
 DEFAULT_UNARCHIVE(expairseq)
 
 //////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
 //////////
 
 // public
index 8d083c1..9fe72d5 100644 (file)
@@ -83,7 +83,7 @@ public:
        expairseq(const epvector & v, const ex & oc);
        expairseq(epvector * vp, const ex & oc); // vp will be deleted
        
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        basic * duplicate() const;
        void print(const print_context & c, unsigned level = 0) const;
index 4c3090f..d3ed59a 100644 (file)
@@ -44,7 +44,7 @@ DEFAULT_CTORS(fail)
 DEFAULT_ARCHIVING(fail)
 
 //////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
 //////////
 
 DEFAULT_COMPARE(fail)
index 2405092..3c51479 100644 (file)
@@ -32,7 +32,7 @@ class fail : public basic
 {
        GINAC_DECLARE_REGISTERED_CLASS(fail, basic)
        
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
 protected:
diff --git a/ginac/fderivative.cpp b/ginac/fderivative.cpp
new file mode 100644 (file)
index 0000000..319cae2
--- /dev/null
@@ -0,0 +1,229 @@
+/** @file fderivative.cpp
+ *
+ *  Implementation of abstract derivatives of functions. */
+
+/*
+ *  GiNaC Copyright (C) 1999-2001 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 "fderivative.h"
+#include "print.h"
+#include "archive.h"
+#include "debugmsg.h"
+#include "utils.h"
+
+namespace GiNaC {
+
+GINAC_IMPLEMENT_REGISTERED_CLASS(fderivative, function)
+
+//////////
+// default constructor, destructor, copy constructor assignment operator and helpers
+//////////
+
+fderivative::fderivative()
+{
+       debugmsg("fderivative default constructor", LOGLEVEL_CONSTRUCT);
+       tinfo_key = TINFO_fderivative;
+}
+
+void fderivative::copy(const fderivative & other)
+{
+       inherited::copy(other);
+       parameter_set = other.parameter_set;
+}
+
+DEFAULT_DESTROY(fderivative)
+
+//////////
+// other constructors
+//////////
+
+fderivative::fderivative(unsigned ser, unsigned param, const exvector & args) : function(ser, args)
+{
+       debugmsg("fderivative constructor from unsigned,unsigned,exvector", LOGLEVEL_CONSTRUCT);
+       parameter_set.insert(param);
+       tinfo_key = TINFO_fderivative;
+}
+
+fderivative::fderivative(unsigned ser, const paramset & params, const exvector & args) : function(ser, args), parameter_set(params)
+{
+       debugmsg("fderivative constructor from unsigned,paramset,exvector", LOGLEVEL_CONSTRUCT);
+       tinfo_key = TINFO_fderivative;
+}
+
+fderivative::fderivative(unsigned ser, const paramset & params, exvector * vp) : function(ser, vp), parameter_set(params)
+{
+       debugmsg("fderivative constructor from unsigned,paramset,exvector *", LOGLEVEL_CONSTRUCT);
+       tinfo_key = TINFO_fderivative;
+}
+
+//////////
+// archiving
+//////////
+
+fderivative::fderivative(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
+{
+       debugmsg("fderivative constructor from archive_node", LOGLEVEL_CONSTRUCT);
+       unsigned i = 0;
+       while (true) {
+               unsigned u;
+               if (n.find_unsigned("param", u, i))
+                       parameter_set.insert(u);
+               else
+                       break;
+               i++;
+       }
+}
+
+void fderivative::archive(archive_node &n) const
+{
+       inherited::archive(n);
+       paramset::const_iterator i = parameter_set.begin(), end = parameter_set.end();
+       while (i != end) {
+               n.add_unsigned("param", *i);
+               ++i;
+       }
+}
+
+DEFAULT_UNARCHIVE(fderivative)
+
+//////////
+// functions overriding virtual functions from base classes
+//////////
+
+void fderivative::print(const print_context & c, unsigned level) const
+{
+       debugmsg("fderivative print", LOGLEVEL_PRINT);
+
+       if (is_of_type(c, print_tree)) {
+
+               c.s << std::string(level, ' ') << class_name() << " "
+                   << registered_functions()[serial].name
+                   << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
+                   << ", nops=" << nops()
+                   << ", params=";
+               paramset::const_iterator i = parameter_set.begin(), end = parameter_set.end();
+               --end;
+               while (i != end)
+                       c.s << *i++ << ",";
+               c.s << *i << endl;
+               unsigned delta_indent = static_cast<const print_tree &>(c).delta_indent;
+               for (unsigned i=0; i<seq.size(); ++i)
+                       seq[i].print(c, level + delta_indent);
+               c.s << std::string(level + delta_indent, ' ') << "=====" << std::endl;
+
+       } else {
+
+               c.s << "D[";
+               paramset::const_iterator i = parameter_set.begin(), end = parameter_set.end();
+               --end;
+               while (i != end)
+                       c.s << *i++ << ",";
+               c.s << *i << "](" << registered_functions()[serial].name << ")";
+               printseq(c, '(', ',', ')', exprseq::precedence(), function::precedence());
+       }
+}
+
+ex fderivative::eval(int level) const
+{
+       if (level > 1) {
+               // first evaluate children, then we will end up here again
+               return fderivative(serial, parameter_set, evalchildren(level));
+       }
+
+       // No parameters specified? Then return the function itself
+       if (parameter_set.empty())
+               return function(serial, seq);
+
+       // If the function in question actually has a derivative, return it
+       if (registered_functions()[serial].has_derivative() && parameter_set.size() == 1)
+               return pderivative(*(parameter_set.begin()));
+
+       return this->hold();
+}
+
+/** Numeric evaluation falls back to evaluation of arguments.
+ *  @see basic::evalf */
+ex fderivative::evalf(int level) const
+{
+       return basic::evalf(level);
+}
+
+/** The series expansion of derivatives falls back to Taylor expansion.
+ *  @see basic::series */
+ex fderivative::series(const relational & r, int order, unsigned options) const
+{
+       return basic::series(r, order, options);
+}
+
+ex fderivative::thisexprseq(const exvector & v) const
+{
+       return fderivative(serial, parameter_set, v);
+}
+
+ex fderivative::thisexprseq(exvector * vp) const
+{
+       return fderivative(serial, parameter_set, vp);
+}
+
+/** Implementation of ex::diff() for derivatives. It applies the chain rule.
+ *  @see ex::diff */
+ex fderivative::derivative(const symbol & s) const
+{
+       ex result;
+       for (unsigned i=0; i!=seq.size(); i++) {
+               ex arg_diff = seq[i].diff(s);
+               if (!arg_diff.is_zero()) {
+                       paramset ps = parameter_set;
+                       ps.insert(i);
+                       result += arg_diff * fderivative(serial, ps, seq);
+               }
+       }
+       return result;
+}
+
+int fderivative::compare_same_type(const basic & other) const
+{
+       GINAC_ASSERT(is_of_type(other, fderivative));
+       const fderivative & o = static_cast<const fderivative &>(other);
+
+       if (parameter_set != o.parameter_set)
+               return parameter_set < o.parameter_set ? -1 : 1;
+       else
+               return inherited::compare_same_type(o);
+}
+
+bool fderivative::is_equal_same_type(const basic & other) const
+{
+       GINAC_ASSERT(is_of_type(other, fderivative));
+       const fderivative & o = static_cast<const fderivative &>(other);
+
+       if (parameter_set != o.parameter_set)
+               return false;
+       else
+               return inherited::is_equal_same_type(o);
+}
+
+bool fderivative::match_same_type(const basic & other) const
+{
+       GINAC_ASSERT(is_of_type(other, fderivative));
+       const fderivative & o = static_cast<const fderivative &>(other);
+
+       return parameter_set == o.parameter_set;
+}
+
+} // namespace GiNaC
diff --git a/ginac/fderivative.h b/ginac/fderivative.h
new file mode 100644 (file)
index 0000000..a0b0f51
--- /dev/null
@@ -0,0 +1,89 @@
+/** @file fderivative.h
+ *
+ *  Interface to abstract derivatives of functions. */
+
+/*
+ *  GiNaC Copyright (C) 1999-2001 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
+ */
+
+#ifndef __GINAC_FDERIVATIVE_H__
+#define __GINAC_FDERIVATIVE_H__
+
+#include <set>
+
+#include "function.h"
+
+namespace GiNaC {
+
+
+typedef std::multiset<unsigned> paramset;
+
+/** This class represents the (abstract) derivative of a symbolic function.
+ *  It is used to represent the derivatives of functions that do not have
+ *  a derivative or series expansion procedure defined. */
+class fderivative : public function
+{
+       GINAC_DECLARE_REGISTERED_CLASS(fderivative, function)
+
+       // other constructors
+public:
+       /** Construct derivative with respect to one parameter.
+        *
+        *  @param ser Serial number of function
+        *  @param param Number of parameter with respect to which to take the derivative
+        *  @param args Arguments of derivative function */
+       fderivative(unsigned ser, unsigned param, const exvector & args);
+
+       /** Construct derivative with respect to multiple parameters.
+        *
+        *  @param ser Serial number of function
+        *  @param params Set of numbers of parameters with respect to which to take the derivative
+        *  @param args Arguments of derivative function */
+       fderivative(unsigned ser, const paramset & params, const exvector & args);
+
+       // internal constructors
+       fderivative(unsigned ser, const paramset & params, exvector * vp); // vp will be deleted
+
+       // functions overriding virtual functions from base classes
+public:
+       void print(const print_context & c, unsigned level = 0) const;
+       ex eval(int level = 0) const;
+       ex evalf(int level = 0) const;
+       ex series(const relational & r, int order, unsigned options = 0) const;
+       ex thisexprseq(const exvector & v) const;
+       ex thisexprseq(exvector * vp) 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;
+
+       // member variables
+protected:
+       paramset parameter_set; /**< Set of parameter numbers with respect to which to take the derivative */
+};
+
+// utility functions
+
+/** Specialization of is_exactly_a<T>(obj) for derivatives. */
+template<> inline bool is_exactly_a<fderivative>(const basic & obj)
+{
+       return obj.tinfo()==TINFO_fderivative;
+}
+
+} // namespace GiNaC
+
+#endif // ndef __GINAC_DERIVATIVE_H__
index de7433e..f6923c0 100755 (executable)
@@ -158,7 +158,7 @@ END_OF_SERIES_FUNC_IMPLEMENTATION
 $interface=<<END_OF_INTERFACE;
 /** \@file function.h
  *
- *  Interface to abstract class function (new function concept). */
+ *  Interface to class of symbolic functions. */
 
 /*
  *  This file was generated automatically by function.pl.
@@ -240,6 +240,7 @@ $typedef_series_funcp
 class function_options
 {
        friend class function;
+       friend class fderivative;
 public:
        function_options();
        function_options(std::string const & n, std::string const & tn=std::string());
@@ -305,7 +306,6 @@ class function : public exprseq
        friend class remember_table_entry;
        // friend class remember_table_list;
        // friend class remember_table;
-       friend ex Derivative_eval(const ex &, const ex &);
 
 // member functions
 
@@ -319,7 +319,7 @@ $constructors_interface
        function(unsigned ser, const exvector & v, bool discardable = false);
        function(unsigned ser, exvector * vp); // vp will be deleted
 
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
        unsigned precedence(void) const {return 70;}
@@ -387,7 +387,7 @@ END_OF_INTERFACE
 $implementation=<<END_OF_IMPLEMENTATION;
 /** \@file function.cpp
  *
- *  Implementation of class function. */
+ *  Implementation of class of symbolic functions. */
 
 /*
  *  This file was generated automatically by function.pl.
@@ -416,12 +416,14 @@ $implementation=<<END_OF_IMPLEMENTATION;
 #include <list>
 
 #include "function.h"
+#include "fderivative.h"
 #include "ex.h"
 #include "lst.h"
 #include "symmetry.h"
 #include "print.h"
 #include "archive.h"
 #include "inifcns.h"
+#include "tostring.h"
 #include "utils.h"
 #include "debugmsg.h"
 #include "remember.h"
@@ -640,7 +642,7 @@ void function::archive(archive_node &n) const
 }
 
 //////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
 //////////
 
 // public
@@ -732,7 +734,7 @@ ex function::eval(int level) const
        // Canonicalize argument order according to the symmetry properties
        if (seq.size() > 1 && !(opt.symtree.is_zero())) {
                exvector v = seq;
-               GINAC_ASSERT(is_ex_exactly_of_type(opt.symtree, symmetry));
+               GINAC_ASSERT(is_of_type<symmetry>(opt.symtree));
                int sig = canonicalize(v.begin(), ex_to<symmetry>(opt.symtree));
                if (sig != INT_MAX) {
                        // Something has changed while sorting arguments, more evaluations later
@@ -846,25 +848,10 @@ ${series_switch_statement}
 ex function::derivative(const symbol & s) const
 {
        ex result;
-       
+
        if (serial == function_index_Order) {
                // Order Term function only differentiates the argument
                return Order(seq[0].diff(s));
-       } else if (serial == function_index_Derivative) {
-               // Inert derivative performs chain rule on the first argument only, and
-               // adds differentiation parameter to list (second argument)
-               GINAC_ASSERT(is_ex_exactly_of_type(seq[0], function));
-               GINAC_ASSERT(is_ex_exactly_of_type(seq[1], function));
-               ex fcn = seq[0];
-               ex arg_diff;
-               for (unsigned i=0; i!=fcn.nops(); i++) {
-                       arg_diff = fcn.op(i).diff(s);
-                       if (!arg_diff.is_zero()) {
-                               lst new_lst = ex_to<lst>(seq[1]);
-                               new_lst.append(i);
-                               result += arg_diff * Derivative(fcn, new_lst);
-                       }
-               }
        } else {
                // Chain rule
                ex arg_diff;
@@ -945,9 +932,10 @@ ex function::pderivative(unsigned diff_param) const // partial differentiation
 {
        GINAC_ASSERT(serial<registered_functions().size());
        
-       if (registered_functions()[serial].derivative_f==0) {
-               return Derivative(*this, lst(ex(diff_param)));
-       }
+       // No derivative defined? Then return abstract derivative object
+       if (registered_functions()[serial].derivative_f == NULL)
+               return fderivative(serial, diff_param, seq);
+
        switch (registered_functions()[serial].nparams) {
                // the following lines have been generated for max. ${maxargs} parameters
 ${diff_switch_statement}
index 3c0e9e8..d24a0de 100644 (file)
@@ -55,6 +55,7 @@
 #include "ncmul.h"
 
 #include "inifcns.h"
+#include "fderivative.h"
 #include "operators.h"
 
 #ifndef GINAC_BASE_ONLY
index bc56717..d704cbd 100644 (file)
@@ -152,7 +152,7 @@ DEFAULT_UNARCHIVE(varidx)
 DEFAULT_UNARCHIVE(spinidx)
 
 //////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
 //////////
 
 void idx::print(const print_context & c, unsigned level) const
index d98d4b1..c2ac972 100644 (file)
@@ -45,7 +45,7 @@ public:
         *  @return newly constructed index */
        explicit idx(const ex & v, const ex & dim);
 
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
        bool info(unsigned inf) const;
@@ -106,7 +106,7 @@ public:
         *  @return newly constructed index */
        varidx(const ex & v, const ex & dim, bool covariant = false);
 
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
        bool is_dummy_pair_same_type(const basic & other) const;
@@ -151,7 +151,7 @@ public:
         *  @return newly constructed index */
        spinidx(const ex & v, const ex & dim = 2, bool covariant = false, bool dotted = false);
 
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
        bool is_dummy_pair_same_type(const basic & other) const;
index a603ca2..c6a84e3 100644 (file)
@@ -187,7 +187,7 @@ void indexed::archive(archive_node &n) const
 DEFAULT_UNARCHIVE(indexed)
 
 //////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
 //////////
 
 void indexed::print(const print_context & c, unsigned level) const
@@ -201,7 +201,6 @@ void indexed::print(const print_context & c, unsigned level) const
                    << std::hex << ", hash=0x" << hashvalue << ", flags=0x" << flags << std::dec
                    << ", " << seq.size()-1 << " indices"
                    << ", symmetry=" << symtree << std::endl;
-               c.s << std::endl;
                unsigned delta_indent = static_cast<const print_tree &>(c).delta_indent;
                seq[0].print(c, level + delta_indent);
                printindices(c, level + delta_indent);
index 8c93b6f..f64597e 100644 (file)
@@ -409,44 +409,6 @@ REGISTER_FUNCTION(Order, eval_func(Order_eval).
                          series_func(Order_series).
                          latex_name("\\mathcal{O}"));
 
-//////////
-// Inert partial differentiation operator
-//////////
-
-ex Derivative_eval(const ex & f, const ex & l)
-{
-       if (!is_ex_of_type(f, function))
-               throw(std::invalid_argument("Derivative(): 1st argument must be a function"));
-       if (!is_ex_of_type(l, lst))
-               throw(std::invalid_argument("Derivative(): 2nd argument must be a list"));
-
-#if 0
-       // Perform differentiations if possible
-       const function &fcn = ex_to<function>(f);
-       if (fcn.registered_functions()[fcn.get_serial()].has_derivative() && l.nops() > 0) {
-
-               // The function actually seems to have a derivative, let's calculate it
-               ex d = fcn.pderivative(ex_to_numeric(l.op(0)).to_int());
-
-               // If this was the last differentiation, return the result
-               if (l.nops() == 1)
-                       return d;
-
-               // Otherwise recursively continue as long as the derivative is still
-               // a function
-               if (is_ex_of_type(d, function)) {
-                       lst l_copy = ex_to<lst>(l);
-                       l_copy.remove_first();
-                       return Derivative(d, l_copy);
-               }
-       }
-#endif
-       return Derivative(f, l).hold();
-}
-
-REGISTER_FUNCTION(Derivative, eval_func(Derivative_eval).
-                              latex_name("\\mathrm{D}"));
-
 //////////
 // Solve linear system
 //////////
index 8acc2bf..0defba9 100644 (file)
@@ -132,9 +132,6 @@ DECLARE_FUNCTION_2P(binomial)
 /** Order term function (for truncated power series). */
 DECLARE_FUNCTION_1P(Order)
 
-/** Inert partial differentiation operator. */
-DECLARE_FUNCTION_2P(Derivative)
-
 ex lsolve(const ex &eqns, const ex &symbols);
 
 /** Check whether a function is the Order (O(n)) function. */
index 229d3f7..150e342 100644 (file)
@@ -263,7 +263,7 @@ static ex sin_eval(const ex & x)
                        return sign*_ex1();
        }
        
-       if (is_ex_exactly_of_type(x, function)) {
+       if (is_exactly_a<function>(x)) {
                ex t = x.op(0);
                // sin(asin(x)) -> x
                if (is_ex_the_function(x, asin))
@@ -345,7 +345,7 @@ static ex cos_eval(const ex & x)
                        return sign*_ex0();
        }
        
-       if (is_ex_exactly_of_type(x, function)) {
+       if (is_exactly_a<function>(x)) {
                ex t = x.op(0);
                // cos(acos(x)) -> x
                if (is_ex_the_function(x, acos))
@@ -423,7 +423,7 @@ static ex tan_eval(const ex & x)
                        throw (pole_error("tan_eval(): simple pole",1));
        }
        
-       if (is_ex_exactly_of_type(x, function)) {
+       if (is_exactly_a<function>(x)) {
                ex t = x.op(0);
                // tan(atan(x)) -> x
                if (is_ex_the_function(x, atan))
@@ -736,7 +736,7 @@ static ex sinh_eval(const ex & x)
                ex_to<numeric>(x/Pi).real().is_zero())  // sinh(I*x) -> I*sin(x)
                return I*sin(x/I);
        
-       if (is_ex_exactly_of_type(x, function)) {
+       if (is_exactly_a<function>(x)) {
                ex t = x.op(0);
                // sinh(asinh(x)) -> x
                if (is_ex_the_function(x, asinh))
@@ -791,7 +791,7 @@ static ex cosh_eval(const ex & x)
                ex_to<numeric>(x/Pi).real().is_zero())  // cosh(I*x) -> cos(x)
                return cos(x/I);
        
-       if (is_ex_exactly_of_type(x, function)) {
+       if (is_exactly_a<function>(x)) {
                ex t = x.op(0);
                // cosh(acosh(x)) -> x
                if (is_ex_the_function(x, acosh))
@@ -846,7 +846,7 @@ static ex tanh_eval(const ex & x)
                ex_to<numeric>(x/Pi).real().is_zero())  // tanh(I*x) -> I*tan(x);
                return I*tan(x/I);
        
-       if (is_ex_exactly_of_type(x, function)) {
+       if (is_exactly_a<function>(x)) {
                ex t = x.op(0);
                // tanh(atanh(x)) -> x
                if (is_ex_the_function(x, atanh))
index 1f5e9af..15ebd9a 100644 (file)
@@ -141,7 +141,7 @@ void matrix::archive(archive_node &n) const
 DEFAULT_UNARCHIVE(matrix)
 
 //////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
 //////////
 
 // public
index 927c27c..5921374 100644 (file)
@@ -40,7 +40,7 @@ public:
        matrix(unsigned r, unsigned c, const exvector & m2);
        matrix(unsigned r, unsigned c, const lst & l);
        
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
        unsigned nops() const;
index 9bb753a..3cfb7ff 100644 (file)
@@ -122,7 +122,7 @@ mul::mul(const ex & lh, const ex & mh, const ex & rh)
 DEFAULT_ARCHIVING(mul)
 
 //////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
 //////////
 
 // public
index d24d37e..23e0e1f 100644 (file)
@@ -45,7 +45,7 @@ public:
        mul(epvector * vp, const ex & oc);
        mul(const ex & lh, const ex & mh, const ex & rh);
        
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
        unsigned precedence(void) const {return 50;}
index f7d1a41..bfc2acd 100644 (file)
@@ -109,7 +109,7 @@ ncmul::ncmul(exvector * vp) : inherited(vp)
 DEFAULT_ARCHIVING(ncmul)
        
 //////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
 //////////
 
 // public
@@ -140,7 +140,7 @@ void ncmul::print(const print_context & c, unsigned level) const
 
 bool ncmul::info(unsigned inf) const
 {
-       throw(std::logic_error("which flags have to be implemented in ncmul::info()?"));
+       return inherited::info(inf);
 }
 
 typedef std::vector<int> intvector;
@@ -151,12 +151,7 @@ ex ncmul::expand(unsigned options) const
        exvector expanded_seq = expandchildren(options);
        
        // Now, look for all the factors that are sums and remember their
-       // position and number of terms. One remark is in order here: we do not
-       // take into account the overall_coeff of the add objects. This is
-       // because in GiNaC, all terms of a sum must be of the same type, so
-       // a non-zero overall_coeff (which can only be numeric) would imply that
-       // the sum only has commutative terms. But then it would never appear
-       // as a factor of an ncmul.
+       // position and number of terms.
        intvector positions_of_adds(expanded_seq.size());
        intvector number_of_add_operands(expanded_seq.size());
 
@@ -166,12 +161,12 @@ ex ncmul::expand(unsigned options) const
        unsigned current_position = 0;
        exvector::const_iterator last = expanded_seq.end();
        for (exvector::const_iterator cit=expanded_seq.begin(); cit!=last; ++cit) {
-               if (is_ex_exactly_of_type(*cit, add)) {
+               if (is_exactly_a<add>(*cit)) {
                        positions_of_adds[number_of_adds] = current_position;
-                       const add & expanded_addref = ex_to<add>(*cit);
-                       number_of_add_operands[number_of_adds] = expanded_addref.seq.size();
-                       number_of_expanded_terms *= expanded_addref.seq.size();
-                       ++number_of_adds;
+                       unsigned num_ops = cit->nops();
+                       number_of_add_operands[number_of_adds] = num_ops;
+                       number_of_expanded_terms *= num_ops;
+                       number_of_adds++;
                }
                ++current_position;
        }
@@ -190,11 +185,8 @@ ex ncmul::expand(unsigned options) const
 
        while (true) {
                exvector term = expanded_seq;
-               for (int i=0; i<number_of_adds; i++) {
-                       GINAC_ASSERT(is_ex_exactly_of_type(expanded_seq[positions_of_adds[i]], add));
-                       const add & addref = ex_to<add>(expanded_seq[positions_of_adds[i]]);
-                       term[positions_of_adds[i]] = addref.recombine_pair_to_ex(addref.seq[k[i]]);
-               }
+               for (int i=0; i<number_of_adds; i++)
+                       term[positions_of_adds[i]] = expanded_seq[positions_of_adds[i]].op(k[i]);
                distrseq.push_back((new ncmul(term, true))->
                                    setflag(status_flags::dynallocated | (options == 0 ? status_flags::expanded : 0)));
 
index b0fbbee..67d381b 100644 (file)
@@ -51,7 +51,7 @@ public:
        ncmul(const exvector & v, bool discardable=false);
        ncmul(exvector * vp); // vp will be deleted
 
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
        unsigned precedence(void) const {return 50;}
index ffcdfbf..880e0a7 100644 (file)
@@ -336,7 +336,7 @@ void numeric::archive(archive_node &n) const
 DEFAULT_UNARCHIVE(numeric)
 
 //////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
 //////////
 
 /** Helper function to print a real number in a nicer way than is CLN's
index 251e573..09f1523 100644 (file)
@@ -80,7 +80,7 @@ public:
        numeric(double d);
        numeric(const char *);
        
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
        unsigned precedence(void) const {return 30;}
index 5daa841..2d4360d 100644 (file)
@@ -90,7 +90,7 @@ void power::archive(archive_node &n) const
 DEFAULT_UNARCHIVE(power)
 
 //////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
 //////////
 
 // public
index 952a72a..175fea0 100644 (file)
@@ -46,7 +46,7 @@ public:
        power(const ex & lh, const ex & rh) : inherited(TINFO_power), basis(lh), exponent(rh) {}
        template<typename T> power(const ex & lh, const T & rh) : inherited(TINFO_power), basis(lh), exponent(rh) {}
        
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
        unsigned precedence(void) const {return 60;}
index 0602ddd..4816d1f 100644 (file)
@@ -119,7 +119,7 @@ void pseries::archive(archive_node &n) const
 DEFAULT_UNARCHIVE(pseries)
 
 //////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
 //////////
 
 void pseries::print(const print_context & c, unsigned level) const
index 74ce1ac..c4e34dd 100644 (file)
@@ -92,7 +92,7 @@ void relational::archive(archive_node &n) const
 DEFAULT_UNARCHIVE(relational)
 
 //////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
 //////////
 
 // public
index fc559b5..40c799b 100644 (file)
@@ -49,7 +49,7 @@ public:
 public:
        relational(const ex & lhs, const ex & rhs, operators oper=equal);
        
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
        unsigned precedence(void) const {return 20;}
index 54dc1df..e1ea6d5 100644 (file)
@@ -45,7 +45,7 @@ DEFAULT_CTORS(structure)
 DEFAULT_ARCHIVING(structure)
 
 //////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
 //////////
 
 void structure::print(const print_context & c, unsigned level) const
index 62848b2..1f7eaea 100644 (file)
@@ -41,7 +41,7 @@ class structure : public basic
 {
        GINAC_DECLARE_REGISTERED_CLASS(structure, basic)
        
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level=0) const;
 protected:
index 8303dbe..f6b8a48 100755 (executable)
@@ -170,7 +170,7 @@ protected:
 public:
        ${STRUCTURE}(${constructor_arglist});
 
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        basic * duplicate() const;
        void print(const print_context & c, unsigned level = 0) const;
@@ -313,7 +313,7 @@ ${STRUCTURE}::${STRUCTURE}(${constructor_arglist})
 }
 
 //////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
 //////////
 
 // public
index ba0cccd..f5fd4a0 100644 (file)
@@ -28,6 +28,7 @@
 #include "print.h"
 #include "archive.h"
 #include "debugmsg.h"
+#include "tostring.h"
 #include "utils.h"
 
 namespace GiNaC {
@@ -137,7 +138,7 @@ void symbol::archive(archive_node &n) const
 }
 
 //////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
 //////////
 
 // public
@@ -242,16 +243,6 @@ bool symbol::is_equal_same_type(const basic & other) const
        return serial==o->serial;
 }
 
-unsigned symbol::return_type(void) const
-{
-       return return_types::commutative;
-}
-   
-unsigned symbol::return_type_tinfo(void) const
-{
-       return tinfo_key;
-}
-
 unsigned symbol::calchash(void) const
 {
        // this is where the schoolbook method
index 16c3193..2d9ec3b 100644 (file)
@@ -87,8 +87,6 @@ protected:
        ex derivative(const symbol & s) const;
        int compare_same_type(const basic & other) const;
        bool is_equal_same_type(const basic & other) const;
-       unsigned return_type(void) const;
-       unsigned return_type_tinfo(void) const;
        unsigned calchash(void) const;
        
        // non-virtual functions in this class
index dc2546f..1b81819 100644 (file)
@@ -135,7 +135,7 @@ void symmetry::archive(archive_node &n) const
 DEFAULT_UNARCHIVE(symmetry)
 
 //////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
 //////////
 
 int symmetry::compare_same_type(const basic & other) const
@@ -154,6 +154,8 @@ void symmetry::print(const print_context & c, unsigned level = 0) const
        if (children.empty()) {
                if (indices.size() > 0)
                        c.s << *(indices.begin());
+               else
+                       c.s << "none";
        } else {
                switch (type) {
                        case none: c.s << '!'; break;
index 1c8847a..65c8b59 100644 (file)
@@ -142,7 +142,7 @@ void tensepsilon::archive(archive_node &n) const
 }
 
 //////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
 //////////
 
 DEFAULT_COMPARE(tensor)
index 147ab44..d868355 100644 (file)
@@ -39,7 +39,7 @@ class tensor : public basic
 protected:
        tensor(unsigned ti);
 
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 protected:
        unsigned return_type(void) const { return return_types::noncommutative_composite; }
 };
@@ -51,7 +51,7 @@ class tensdelta : public tensor
 {
        GINAC_DECLARE_REGISTERED_CLASS(tensdelta, tensor)
 
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
        ex eval_indexed(const basic & i) const;
@@ -66,7 +66,7 @@ class tensmetric : public tensor
 {
        GINAC_DECLARE_REGISTERED_CLASS(tensmetric, tensor)
 
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
        ex eval_indexed(const basic & i) const;
@@ -86,7 +86,7 @@ public:
        /** Construct Lorentz metric tensor with given signature. */
        minkmetric(bool pos_sig);
 
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
        ex eval_indexed(const basic & i) const;
@@ -105,7 +105,7 @@ class spinmetric : public tensmetric
 {
        GINAC_DECLARE_REGISTERED_CLASS(spinmetric, tensmetric)
 
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
        ex eval_indexed(const basic & i) const;
@@ -124,7 +124,7 @@ class tensepsilon : public tensor
 public:
        tensepsilon(bool minkowski, bool pos_sig);
 
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
 public:
        void print(const print_context & c, unsigned level = 0) const;
        ex eval_indexed(const basic & i) const;
index 775cfc7..20e6d2b 100644 (file)
@@ -36,6 +36,7 @@ const unsigned TINFO_constant      = 0x00021001U;
 
 const unsigned TINFO_exprseq       = 0x00030001U;
 const unsigned TINFO_function      = 0x00031001U;
+const unsigned TINFO_fderivative   = 0x00032001U;
 const unsigned TINFO_ncmul         = 0x00031002U;
 
 const unsigned TINFO_lst           = 0x00040001U;
index 7acb3a9..75b0e84 100644 (file)
@@ -760,7 +760,7 @@ const ex & _ex120(void)
        // other ctors
        // none
 
-       // functions overriding virtual functions from bases classes
+       // functions overriding virtual functions from base classes
        // none
        
        // new virtual functions which can be overridden by derived classes
@@ -792,7 +792,7 @@ const ex & _ex120(void)
 // none
 
 //////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
 //////////
 
 // public
index 3e8e17c..001f64f 100644 (file)
 
 #include <string>
 #include <stdexcept>
-#if defined(HAVE_SSTREAM)
-#include <sstream>
-#elif defined(HAVE_STRSTREAM)
-#include <strstream>
-#else
-#error Need either sstream or strstream
-#endif
 #include "assertion.h"
 
 namespace GiNaC {
 
-// This should be obsoleted once <sstream> is widely deployed.
-template<class T>
-std::string ToString(const T & t)
-{
-#if defined(HAVE_SSTREAM)
-       std::ostringstream buf;
-       buf << t << std::ends;
-       return buf.str();
-#else
-       char buf[256];
-       std::ostrstream(buf,sizeof(buf)) << t << std::ends;
-       return buf;
-#endif
-}
-
 /** Exception class thrown by classes which provide their own series expansion
  *  to signal that ordinary Taylor expansion is safe. */
 class do_taylor {};
index 33ccb46..31d934a 100644 (file)
@@ -77,7 +77,7 @@ void wildcard::archive(archive_node &n) const
 DEFAULT_UNARCHIVE(wildcard)
 
 //////////
-// functions overriding virtual functions from bases classes
+// functions overriding virtual functions from base classes
 //////////
 
 int wildcard::compare_same_type(const basic & other) const