- implemented global class registry (for class basic and derived classes)
authorChristian Bauer <Christian.Bauer@uni-mainz.de>
Wed, 19 Jan 2000 22:46:56 +0000 (22:46 +0000)
committerChristian Bauer <Christian.Bauer@uni-mainz.de>
Wed, 19 Jan 2000 22:46:56 +0000 (22:46 +0000)
- implemented archiving of expressions (except for class idx, and all classes
  derived from idx and indexed)
- added series() wrapper function
- class series renamed to pseries to avoid name clashes with global series()
  wrapper function, ex::series(), and basic::series()
- corrected the series expansion of single symbols with respect to the order
  term
- calling subs() on a series didn't work

43 files changed:
ginac/Makefile.am
ginac/Makefile.in
ginac/add.cpp
ginac/add.h
ginac/archive.cpp [new file with mode: 0644]
ginac/archive.h [new file with mode: 0644]
ginac/basic.cpp
ginac/basic.h
ginac/constant.cpp
ginac/constant.h
ginac/container.pl
ginac/diff.cpp
ginac/ex.h
ginac/expairseq.cpp
ginac/expairseq.h
ginac/fail.cpp
ginac/fail.h
ginac/function.pl
ginac/ginac.h
ginac/indexed.cpp
ginac/indexed.h
ginac/inifcns.cpp
ginac/inifcns_gamma.cpp
ginac/matrix.cpp
ginac/matrix.h
ginac/mul.cpp
ginac/mul.h
ginac/ncmul.cpp
ginac/ncmul.h
ginac/normal.cpp
ginac/numeric.cpp
ginac/numeric.h
ginac/power.cpp
ginac/power.h
ginac/pseries.cpp [moved from ginac/series.cpp with 70% similarity]
ginac/pseries.h [moved from ginac/series.h with 72% similarity]
ginac/registrar.cpp [new file with mode: 0644]
ginac/registrar.h [new file with mode: 0644]
ginac/relational.cpp
ginac/relational.h
ginac/symbol.cpp
ginac/symbol.h
ginac/tinfos.h

index 1d16580..1035e83 100644 (file)
@@ -1,21 +1,23 @@
 ## Process this file with automake to produce Makefile.in
 
 lib_LTLIBRARIES = libginac.la
-libginac_la_SOURCES = add.cpp basic.cpp constant.cpp diff.cpp ex.cpp \
-  expairseq.cpp exprseq.cpp fail.cpp function.cpp inifcns.cpp \
+libginac_la_SOURCES = add.cpp archive.cpp basic.cpp constant.cpp diff.cpp \
+  ex.cpp expairseq.cpp exprseq.cpp fail.cpp function.cpp inifcns.cpp \
   inifcns_trans.cpp inifcns_zeta.cpp inifcns_gamma.cpp matrix.cpp mul.cpp \
-  normal.cpp numeric.cpp operators.cpp power.cpp relational.cpp symbol.cpp \
-  utils.cpp series.cpp ncmul.cpp clifford.cpp structure.cpp color.cpp \
-  indexed.cpp idx.cpp isospin.cpp exprseq_suppl.cpp lst.cpp lst_suppl.cpp \
-  simp_lor.cpp coloridx.cpp lorentzidx.cpp lortensor.cpp debugmsg.h utils.h 
+  normal.cpp numeric.cpp operators.cpp power.cpp registrar.cpp relational.cpp \
+  symbol.cpp pseries.cpp utils.cpp ncmul.cpp clifford.cpp structure.cpp \
+  color.cpp indexed.cpp idx.cpp isospin.cpp exprseq_suppl.cpp lst.cpp \
+  lst_suppl.cpp simp_lor.cpp coloridx.cpp lorentzidx.cpp lortensor.cpp \
+  debugmsg.h utils.h 
 libginac_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
   -release $(LT_RELEASE)
 ginacincludedir = $(includedir)/ginac
-ginacinclude_HEADERS = ginac.h add.h basic.h clifford.h color.h coloridx.h \
-  constant.h ex.h expair.h expairseq.h exprseq.h fail.h flags.h function.h \
-  idx.h indexed.h inifcns.h isospin.h lorentzidx.h lst.h matrix.h mul.h \
-  ncmul.h normal.h numeric.h operators.h power.h relational.h series.h \
-  simp_lor.h structure.h symbol.h lortensor.h tinfos.h assertion.h
+ginacinclude_HEADERS = ginac.h add.h archive.h basic.h clifford.h color.h \
+  coloridx.h constant.h ex.h expair.h expairseq.h exprseq.h fail.h flags.h \
+  function.h idx.h indexed.h inifcns.h isospin.h lorentzidx.h lst.h matrix.h \
+  mul.h ncmul.h normal.h numeric.h operators.h power.h registrar.h \
+  relational.h pseries.h simp_lor.h structure.h symbol.h lortensor.h tinfos.h \
+  assertion.h
 EXTRA_DIST = container.pl function.pl structure.pl
 
 # Files which are generated by perl scripts
index bffdd52..12b11d0 100644 (file)
@@ -59,6 +59,8 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 host_alias = @host_alias@
 host_triplet = @host@
+ARCHIVE_AGE = @ARCHIVE_AGE@
+ARCHIVE_VERSION = @ARCHIVE_VERSION@
 AS = @AS@
 CC = @CC@
 CXX = @CXX@
@@ -98,12 +100,12 @@ VERSION = @VERSION@
 YACC = @YACC@
 
 lib_LTLIBRARIES = libginac.la
-libginac_la_SOURCES = add.cpp basic.cpp constant.cpp diff.cpp ex.cpp   expairseq.cpp exprseq.cpp fail.cpp function.cpp inifcns.cpp   inifcns_trans.cpp inifcns_zeta.cpp inifcns_gamma.cpp matrix.cpp mul.cpp   normal.cpp numeric.cpp operators.cpp power.cpp relational.cpp symbol.cpp   utils.cpp series.cpp ncmul.cpp clifford.cpp structure.cpp color.cpp   indexed.cpp idx.cpp isospin.cpp exprseq_suppl.cpp lst.cpp lst_suppl.cpp   simp_lor.cpp coloridx.cpp lorentzidx.cpp lortensor.cpp debugmsg.h utils.h 
+libginac_la_SOURCES = add.cpp archive.cpp basic.cpp constant.cpp diff.cpp   ex.cpp expairseq.cpp exprseq.cpp fail.cpp function.cpp inifcns.cpp   inifcns_trans.cpp inifcns_zeta.cpp inifcns_gamma.cpp matrix.cpp mul.cpp   normal.cpp numeric.cpp operators.cpp power.cpp registrar.cpp relational.cpp   symbol.cpp pseries.cpp utils.cpp ncmul.cpp clifford.cpp structure.cpp   color.cpp indexed.cpp idx.cpp isospin.cpp exprseq_suppl.cpp lst.cpp   lst_suppl.cpp simp_lor.cpp coloridx.cpp lorentzidx.cpp lortensor.cpp   debugmsg.h utils.h 
 
 libginac_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)   -release $(LT_RELEASE)
 
 ginacincludedir = $(includedir)/ginac
-ginacinclude_HEADERS = ginac.h add.h basic.h clifford.h color.h coloridx.h   constant.h ex.h expair.h expairseq.h exprseq.h fail.h flags.h function.h   idx.h indexed.h inifcns.h isospin.h lorentzidx.h lst.h matrix.h mul.h   ncmul.h normal.h numeric.h operators.h power.h relational.h series.h   simp_lor.h structure.h symbol.h lortensor.h tinfos.h assertion.h
+ginacinclude_HEADERS = ginac.h add.h archive.h basic.h clifford.h color.h   coloridx.h constant.h ex.h expair.h expairseq.h exprseq.h fail.h flags.h   function.h idx.h indexed.h inifcns.h isospin.h lorentzidx.h lst.h matrix.h   mul.h ncmul.h normal.h numeric.h operators.h power.h registrar.h   relational.h pseries.h simp_lor.h structure.h symbol.h lortensor.h tinfos.h   assertion.h
 
 EXTRA_DIST = container.pl function.pl structure.pl
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
@@ -117,13 +119,13 @@ CPPFLAGS = @CPPFLAGS@
 LDFLAGS = @LDFLAGS@
 LIBS = @LIBS@
 libginac_la_LIBADD = 
-libginac_la_OBJECTS =  add.lo basic.lo constant.lo diff.lo ex.lo \
-expairseq.lo exprseq.lo fail.lo function.lo inifcns.lo inifcns_trans.lo \
-inifcns_zeta.lo inifcns_gamma.lo matrix.lo mul.lo normal.lo numeric.lo \
-operators.lo power.lo relational.lo symbol.lo utils.lo series.lo \
-ncmul.lo clifford.lo structure.lo color.lo indexed.lo idx.lo isospin.lo \
-exprseq_suppl.lo lst.lo lst_suppl.lo simp_lor.lo coloridx.lo \
-lorentzidx.lo lortensor.lo
+libginac_la_OBJECTS =  add.lo archive.lo basic.lo constant.lo diff.lo \
+ex.lo expairseq.lo exprseq.lo fail.lo function.lo inifcns.lo \
+inifcns_trans.lo inifcns_zeta.lo inifcns_gamma.lo matrix.lo mul.lo \
+normal.lo numeric.lo operators.lo power.lo registrar.lo relational.lo \
+symbol.lo pseries.lo utils.lo ncmul.lo clifford.lo structure.lo \
+color.lo indexed.lo idx.lo isospin.lo exprseq_suppl.lo lst.lo \
+lst_suppl.lo simp_lor.lo coloridx.lo lorentzidx.lo lortensor.lo
 CXXFLAGS = @CXXFLAGS@
 CXXCOMPILE = $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
 LTCXXCOMPILE = $(LIBTOOL) --mode=compile $(CXX) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
@@ -143,16 +145,16 @@ DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
 
 TAR = tar
 GZIP_ENV = --best
-DEP_FILES =  .deps/add.P .deps/basic.P .deps/clifford.P .deps/color.P \
-.deps/coloridx.P .deps/constant.P .deps/diff.P .deps/ex.P \
+DEP_FILES =  .deps/add.P .deps/archive.P .deps/basic.P .deps/clifford.P \
+.deps/color.P .deps/coloridx.P .deps/constant.P .deps/diff.P .deps/ex.P \
 .deps/expairseq.P .deps/exprseq.P .deps/exprseq_suppl.P .deps/fail.P \
 .deps/function.P .deps/idx.P .deps/indexed.P .deps/inifcns.P \
 .deps/inifcns_gamma.P .deps/inifcns_trans.P .deps/inifcns_zeta.P \
 .deps/isospin.P .deps/lorentzidx.P .deps/lortensor.P .deps/lst.P \
 .deps/lst_suppl.P .deps/matrix.P .deps/mul.P .deps/ncmul.P \
 .deps/normal.P .deps/numeric.P .deps/operators.P .deps/power.P \
-.deps/relational.P .deps/series.P .deps/simp_lor.P .deps/structure.P \
-.deps/symbol.P .deps/utils.P
+.deps/pseries.P .deps/registrar.P .deps/relational.P .deps/simp_lor.P \
+.deps/structure.P .deps/symbol.P .deps/utils.P
 SOURCES = $(libginac_la_SOURCES)
 OBJECTS = $(libginac_la_OBJECTS)
 
@@ -288,7 +290,7 @@ distdir: $(DISTFILES)
        @for file in $(DISTFILES); do \
          d=$(srcdir); \
          if test -d $$d/$$file; then \
-           cp -pr $$d/$$file $(distdir)/$$file; \
+           cp -pr $$/$$file $(distdir)/$$file; \
          else \
            test -f $(distdir)/$$file \
            || ln $$d/$$file $(distdir)/$$file 2> /dev/null \
index 8700ce6..ab05def 100644 (file)
@@ -25,6 +25,7 @@
 
 #include "add.h"
 #include "mul.h"
+#include "archive.h"
 #include "debugmsg.h"
 #include "utils.h"
 
@@ -32,6 +33,8 @@
 namespace GiNaC {
 #endif // ndef NO_GINAC_NAMESPACE
 
+GINAC_IMPLEMENT_REGISTERED_CLASS(add, expairseq)
+
 //////////
 // default constructor, destructor, copy constructor assignment operator and helpers
 //////////
@@ -70,12 +73,12 @@ add const & add::operator=(add const & other)
 
 void add::copy(add const & other)
 {
-    expairseq::copy(other);
+    inherited::copy(other);
 }
 
 void add::destroy(bool call_parent)
 {
-    if (call_parent) expairseq::destroy(call_parent);
+    if (call_parent) inherited::destroy(call_parent);
 }
 
 //////////
@@ -148,6 +151,28 @@ add::add(epvector * vp, ex const & oc)
     GINAC_ASSERT(is_canonical());
 }
 
+//////////
+// archiving
+//////////
+
+/** Construct object from archive_node. */
+add::add(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
+{
+    debugmsg("add constructor from archive_node", LOGLEVEL_CONSTRUCT);
+}
+
+/** Unarchive the object. */
+ex add::unarchive(const archive_node &n, const lst &sym_lst)
+{
+    return (new add(n, sym_lst))->setflag(status_flags::dynallocated);
+}
+
+/** Archive the object. */
+void add::archive(archive_node &n) const
+{
+    inherited::archive(n);
+}
+
 //////////
 // functions overriding virtual functions from bases classes
 //////////
@@ -317,7 +342,7 @@ bool add::info(unsigned inf) const
         }
         return overall_coeff.info(inf);
     } else {
-        return expairseq::info(inf);
+        return inherited::info(inf);
     }
 }
 
@@ -421,7 +446,7 @@ exvector add::get_indices(void) const
 ex add::simplify_ncmul(exvector const & v) const
 {
     if (seq.size()==0) {
-        return expairseq::simplify_ncmul(v);
+        return inherited::simplify_ncmul(v);
     }
     return (*seq.begin()).rest.simplify_ncmul(v);
 }    
@@ -430,12 +455,12 @@ ex add::simplify_ncmul(exvector const & v) const
 
 int add::compare_same_type(basic const & other) const
 {
-    return expairseq::compare_same_type(other);
+    return inherited::compare_same_type(other);
 }
 
 bool add::is_equal_same_type(basic const & other) const
 {
-    return expairseq::is_equal_same_type(other);
+    return inherited::is_equal_same_type(other);
 }
 
 unsigned add::return_type(void) const
index d2d4d76..d4da3be 100644 (file)
@@ -32,6 +32,8 @@ namespace GiNaC {
 /** Sum of expressions. */
 class add : public expairseq
 {
+    GINAC_DECLARE_REGISTERED_CLASS(add, expairseq)
+
     friend class mul;
     friend class ncmul;
     friend class power;
diff --git a/ginac/archive.cpp b/ginac/archive.cpp
new file mode 100644 (file)
index 0000000..dfc00ce
--- /dev/null
@@ -0,0 +1,582 @@
+/** @file archive.cpp
+ *
+ *  Archiving of GiNaC expressions. */
+
+/*
+ *  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 <iostream>
+#include <stdexcept>
+
+#include "archive.h"
+#include "registrar.h"
+#include "ex.h"
+#include "config.h"
+#include "utils.h"
+
+#ifndef NO_GINAC_NAMESPACE
+namespace GiNaC {
+#endif // ndef NO_GINAC_NAMESPACE
+
+
+/** Archive an expression.
+ *  @param ex  the expression to be archived
+ *  @param name  name under which the expression is stored */
+void archive::archive_ex(const ex &e, const char *name)
+{
+       // Create root node (which recursively archives the whole expression tree)
+       // and add it to the archive
+       archive_node_id id = add_node(archive_node(*this, e));
+
+       // Add root node ID to list of archived expressions
+       archived_ex ae = archived_ex(atomize(name), id);
+       exprs.push_back(ae);
+}
+
+
+/** Add archive_node to archive if the corresponding expression is
+ *  not already archived.
+ *  @return ID of archived node */
+archive_node_id archive::add_node(const archive_node &n)
+{
+       // Search for node in nodes vector
+       vector<archive_node>::const_iterator i = nodes.begin(), iend = nodes.end();
+       archive_node_id id = 0;
+       while (i != iend) {
+               if (i->has_same_ex_as(n))
+                       return id;
+               i++; id++;
+       }
+
+       // Not found, add archive_node to nodes vector
+       nodes.push_back(n);
+       return id;
+}
+
+
+/** Retrieve archive_node by ID. */
+archive_node &archive::get_node(archive_node_id id)
+{
+       if (id >= nodes.size())
+               throw (std::range_error("archive::get_node(): archive node ID out of range"));
+
+       return nodes[id];
+}
+
+
+/** Retrieve expression from archive by name.
+ *  @param sym_lst  list of pre-defined symbols */
+ex archive::unarchive_ex(const lst &sym_lst, const char *name) const
+{
+       // Find root node
+       string name_string = name;
+       archive_atom id = atomize(name_string);
+       vector<archived_ex>::const_iterator i = exprs.begin(), iend = exprs.end();
+       while (i != iend) {
+               if (i->name == id)
+                       goto found;
+               i++;
+       }
+       throw (std::logic_error("expression with name '" + name_string + "' not found in archive"));
+
+found:
+       // Recursively unarchive all nodes, starting at the root node
+       return nodes[i->root].unarchive(sym_lst);
+}
+
+/** Retrieve expression from archive by index.
+ *  @param sym_lst  list of pre-defined symbols */
+ex archive::unarchive_ex(const lst &sym_lst, unsigned int index) const
+{
+       if (index >= exprs.size())
+               throw (std::range_error("index of archived expression out of range"));
+
+       // Recursively unarchive all nodes, starting at the root node
+       return nodes[exprs[index].root].unarchive(sym_lst);
+}
+
+/** Retrieve expression and its name from archive by index.
+ *  @param sym_lst  list of pre-defined symbols */
+ex archive::unarchive_ex(const lst &sym_lst, string &name, unsigned int index) const
+{
+       if (index >= exprs.size())
+               throw (std::range_error("index of archived expression out of range"));
+
+       // Return expression name
+       name = unatomize(exprs[index].name);
+
+       // Recursively unarchive all nodes, starting at the root node
+       return nodes[exprs[index].root].unarchive(sym_lst);
+}
+
+
+/** Return number of archived expressions. */
+unsigned int archive::num_expressions(void) const
+{
+       return exprs.size();
+}
+
+
+/*
+ *  Archive file format
+ *
+ *   - 4 bytes signature 'GARC'
+ *   - unsigned version number
+ *   - unsigned number of atoms
+ *      - atom strings (each zero-terminated)
+ *   - unsigned number of expressions
+ *      - unsigned name atom
+ *      - unsigned root node ID
+ *   - unsigned number of nodes
+ *      - unsigned number of properties
+ *        - unsigned type (PTYPE_*)
+ *        - unsigned name atom
+ *        - unsigned property value
+ *
+ *  Unsigned quantities are stored in a compressed format:
+ *   - numbers in the range 0x00..0x7f are stored verbatim (1 byte)
+ *   - numbers larger than 0x7f are stored in 7-bit packets (1 byte per
+ *     packet), starting with the LSBs; all bytes except the last one have
+ *     their upper bit set
+ *
+ *  Examples:
+ *   0x00           =   0x00
+ *    ..                 ..
+ *   0x7f           =   0x7f
+ *   0x80 0x01      =   0x80
+ *    ..   ..            ..
+ *   0xff 0x01      =   0xff
+ *   0x80 0x02      =  0x100
+ *    ..   ..            ..
+ *   0xff 0x02      =  0x17f
+ *   0x80 0x03      =  0x180
+ *    ..   ..            ..
+ *   0xff 0x7f      = 0x3fff
+ *   0x80 0x80 0x01 = 0x4000
+ *    ..   ..   ..       ..
+ */
+
+/** Write unsigned integer quantity to stream. */
+static void write_unsigned(ostream &os, unsigned int val)
+{
+       while (val > 0x80) {
+               os.put((val & 0x7f) | 0x80);
+               val >>= 7;
+       }
+       os.put(val);
+}
+
+/** Read unsigned integer quantity from stream. */
+static unsigned int read_unsigned(istream &is)
+{
+       unsigned char b;
+       unsigned int ret = 0;
+       unsigned int shift = 0;
+       do {
+               is.get(b);
+               ret |= (b & 0x7f) << shift;
+               shift += 7;
+       } while (b & 0x80);
+       return ret;
+}
+
+/** Write archive_node to binary data stream. */
+ostream &operator<<(ostream &os, const archive_node &n)
+{
+       // Write properties
+       unsigned int num_props = n.props.size();
+       write_unsigned(os, num_props);
+       for (unsigned int i=0; i<num_props; i++) {
+               write_unsigned(os, n.props[i].type);
+               write_unsigned(os, n.props[i].name);
+               write_unsigned(os, n.props[i].value);
+       }
+}
+
+/** Write archive to binary data stream. */
+ostream &operator<<(ostream &os, const archive &ar)
+{
+       // Write header
+       os.put('G');    // Signature
+       os.put('A');
+       os.put('R');
+       os.put('C');
+       write_unsigned(os, ARCHIVE_VERSION);
+
+       // Write atoms
+       unsigned int num_atoms = ar.atoms.size();
+       write_unsigned(os, num_atoms);
+       for (unsigned int i=0; i<num_atoms; i++)
+               os << ar.atoms[i] << ends;
+
+       // Write expressions
+       unsigned int num_exprs = ar.exprs.size();
+       write_unsigned(os, num_exprs);
+       for (unsigned int i=0; i<num_exprs; i++) {
+               write_unsigned(os, ar.exprs[i].name);
+               write_unsigned(os, ar.exprs[i].root);
+       }
+
+       // Write nodes
+       unsigned int num_nodes = ar.nodes.size();
+       write_unsigned(os, num_nodes);
+       for (unsigned int i=0; i<num_nodes; i++)
+               os << ar.nodes[i];
+}
+
+/** Read archive_node from binary data stream. */
+istream &operator>>(istream &is, archive_node &n)
+{
+       // Read properties
+       unsigned int num_props = read_unsigned(is);
+       n.props.resize(num_props);
+       for (unsigned int i=0; i<num_props; i++) {
+               n.props[i].type = (archive_node::property_type)read_unsigned(is);
+               n.props[i].name = read_unsigned(is);
+               n.props[i].value = read_unsigned(is);
+       }
+}
+
+/** Read archive from binary data stream. */
+istream &operator>>(istream &is, archive &ar)
+{
+       // Read header
+       char c1, c2, c3, c4;
+       is.get(c1); is.get(c2); is.get(c3); is.get(c4);
+       if (c1 != 'G' || c2 != 'A' || c3 != 'R' || c4 != 'C')
+               throw (std::runtime_error("not a GiNaC archive (signature not found)"));
+       unsigned int version = read_unsigned(is);
+       if (version > ARCHIVE_VERSION || version < ARCHIVE_VERSION - ARCHIVE_AGE)
+               throw (std::runtime_error("archive version " + ToString(version) + " cannot be read by this GiNaC library (which supports versions " + ToString(ARCHIVE_VERSION-ARCHIVE_AGE) + " thru " + ToString(ARCHIVE_VERSION)));
+
+       // Read atoms
+       unsigned int num_atoms = read_unsigned(is);
+       ar.atoms.resize(num_atoms);
+       for (unsigned int i=0; i<num_atoms; i++)
+               getline(is, ar.atoms[i], '\0');
+
+       // Read expressions
+       unsigned int num_exprs = read_unsigned(is);
+       ar.exprs.resize(num_exprs);
+       for (unsigned int i=0; i<num_exprs; i++) {
+               archive_atom name = read_unsigned(is);
+               archive_node_id root = read_unsigned(is);
+               ar.exprs[i] = archive::archived_ex(name, root);
+       }
+
+       // Read nodes
+       unsigned int num_nodes = read_unsigned(is);
+       ar.nodes.resize(num_nodes, ar);
+       for (unsigned int i=0; i<num_nodes; i++)
+               is >> ar.nodes[i];
+}
+
+
+/** Atomize a string (i.e. convert it into an ID number that uniquely
+ *  represents the string). */
+archive_atom archive::atomize(const string &s) const
+{
+       // Search for string in atoms vector
+       vector<string>::const_iterator i = atoms.begin(), iend = atoms.end();
+       archive_atom id = 0;
+       while (i != iend) {
+               if (*i == s)
+                       return id;
+               i++; id++;
+       }
+
+       // Not found, add to atoms vector
+       atoms.push_back(s);
+       return id;
+}
+
+/** Unatomize a string (i.e. convert the ID number back to the string). */
+const string &archive::unatomize(archive_atom id) const
+{
+       if (id >= atoms.size())
+               throw (std::range_error("archive::unatomizee(): atom ID out of range"));
+
+       return atoms[id];
+}
+
+
+/** Copy constructor of archive_node. */
+archive_node::archive_node(const archive_node &other)
+       : a(other.a), props(other.props), has_expression(other.has_expression), e(other.e)
+{
+}
+
+
+/** Assignment operator of archive_node. */
+const archive_node &archive_node::operator=(const archive_node &other)
+{
+       if (this != &other) {
+               a = other.a;
+               props = other.props;
+               has_expression = other.has_expression;
+               e = other.e;
+       }
+       return *this;
+}
+
+
+/** Recursively construct archive node from expression. */
+archive_node::archive_node(archive &ar, const ex &expr)
+       : a(ar), has_expression(true), e(expr)
+{
+       expr.bp->archive(*this);
+}
+
+
+/** Check if the archive_node stores the same expression as another
+ *  archive_node.
+ *  @return "true" if expressions are the same */
+bool archive_node::has_same_ex_as(const archive_node &other) const
+{
+       if (!has_expression || !other.has_expression)
+               return false;
+       return e.bp == other.e.bp;
+}
+
+
+/** Add property of type "bool" to node. */
+void archive_node::add_bool(const string &name, bool value)
+{
+       props.push_back(property(a.atomize(name), PTYPE_BOOL, value));
+}
+
+/** Add property of type "unsigned int" to node. */
+void archive_node::add_unsigned(const string &name, unsigned int value)
+{
+       props.push_back(property(a.atomize(name), PTYPE_UNSIGNED, value));
+}
+
+/** Add property of type "string" to node. */
+void archive_node::add_string(const string &name, const string &value)
+{
+       props.push_back(property(a.atomize(name), PTYPE_STRING, a.atomize(value)));
+}
+
+/** Add property of type "ex" to node. */
+void archive_node::add_ex(const string &name, const ex &value)
+{
+       // Recursively create an archive_node and add its ID to the properties of this node
+       archive_node_id id = a.add_node(archive_node(a, value));
+       props.push_back(property(a.atomize(name), PTYPE_NODE, id));
+}
+
+
+/** Retrieve property of type "bool" from node.
+ *  @return "true" if property was found, "false" otherwise */
+bool archive_node::find_bool(const string &name, bool &ret) const
+{
+       archive_atom name_atom = a.atomize(name);
+       vector<property>::const_iterator i = props.begin(), iend = props.end();
+       while (i != iend) {
+               if (i->type == PTYPE_BOOL && i->name == name_atom) {
+                       ret = i->value;
+                       return true;
+               }
+               i++;
+       }
+       return false;
+}
+
+/** Retrieve property of type "unsigned" from node.
+ *  @return "true" if property was found, "false" otherwise */
+bool archive_node::find_unsigned(const string &name, unsigned int &ret) const
+{
+       archive_atom name_atom = a.atomize(name);
+       vector<property>::const_iterator i = props.begin(), iend = props.end();
+       while (i != iend) {
+               if (i->type == PTYPE_UNSIGNED && i->name == name_atom) {
+                       ret = i->value;
+                       return true;
+               }
+               i++;
+       }
+       return false;
+}
+
+/** Retrieve property of type "string" from node.
+ *  @return "true" if property was found, "false" otherwise */
+bool archive_node::find_string(const string &name, string &ret) const
+{
+       archive_atom name_atom = a.atomize(name);
+       vector<property>::const_iterator i = props.begin(), iend = props.end();
+       while (i != iend) {
+               if (i->type == PTYPE_STRING && i->name == name_atom) {
+                       ret = a.unatomize(i->value);
+                       return true;
+               }
+               i++;
+       }
+       return false;
+}
+
+/** Retrieve property of type "ex" from node.
+ *  @return "true" if property was found, "false" otherwise */
+bool archive_node::find_ex(const string &name, ex &ret, const lst &sym_lst, unsigned int index) const
+{
+       archive_atom name_atom = a.atomize(name);
+       vector<property>::const_iterator i = props.begin(), iend = props.end();
+       unsigned int found_index = 0;
+       while (i != iend) {
+               if (i->type == PTYPE_NODE && i->name == name_atom) {
+                       if (found_index == index)
+                               goto found;
+                       found_index++;
+               }
+               i++;
+       }
+       return false;
+
+found:
+       ret = a.get_node(i->value).unarchive(sym_lst);
+       return true;
+}
+
+
+/** Convert archive node to GiNaC expression. */
+ex archive_node::unarchive(const lst &sym_lst) const
+{
+       // Already unarchived? Then return cached unarchived expression.
+       if (has_expression)
+               return e;
+
+       // Find instantiation function for class specified in node
+       string class_name;
+       if (!find_string("class", class_name))
+               throw (std::runtime_error("archive node contains no class name"));
+       unarch_func f = find_unarch_func(class_name);
+
+       // Call instantiation function
+       e = f(*this, sym_lst);
+       has_expression = true;
+       return e;
+}
+
+
+/** Assignment operator of property. */
+const archive_node::property &archive_node::property::operator=(const property &other)
+{
+       if (this != &other) {
+               type = other.type;
+               name = other.name;
+               value = other.value;
+       }
+       return *this;
+}
+
+
+/** Clear all archived expressions. */
+void archive::clear(void)
+{
+       atoms.clear();
+       exprs.clear();
+       nodes.clear();
+}
+
+
+/** Delete cached unarchived expressions in all archive_nodes (mainly for debugging). */
+void archive::forget(void)
+{
+       vector<archive_node>::iterator i = nodes.begin(), iend = nodes.end();
+       while (i != iend) {
+               i->forget();
+               i++;
+       }
+}
+
+/** Delete cached unarchived expressions from node (for debugging). */
+void archive_node::forget(void)
+{
+       has_expression = false;
+       e = 0;
+}
+
+
+/** Dump archive to stream (for debugging). */
+void archive::dump(ostream &os) const
+{
+       // Dump atoms
+       os << "Atoms:\n";
+       {
+               vector<string>::const_iterator i = atoms.begin(), iend = atoms.end();
+               archive_atom id = 0;
+               while (i != iend) {
+                       os << " " << id << " " << *i << endl;
+                       i++; id++;
+               }
+       }
+       os << endl;
+
+       // Dump expressions
+       os << "Expressions:\n";
+       {
+               vector<archived_ex>::const_iterator i = exprs.begin(), iend = exprs.end();
+               unsigned int index = 0;
+               while (i != iend) {
+                       os << " " << index << " \"" << unatomize(i->name) << "\" root node " << i->root << endl;
+                       i++; index++;
+               }
+       }
+       os << endl;
+
+       // Dump nodes
+       os << "Nodes:\n";
+       {
+               vector<archive_node>::const_iterator i = nodes.begin(), iend = nodes.end();
+               archive_node_id id = 0;
+               while (i != iend) {
+                       os << " " << id << " ";
+                       i->dump(os);
+                       i++; id++;
+               }
+       }
+}
+
+/** Dump archive_node to stream (for debugging). */
+void archive_node::dump(ostream &os) const
+{
+       // Dump cached unarchived expression
+       if (has_expression)
+               os << "(basic * " << e.bp << " = " << e << ")\n";
+       else
+               os << "(no expression)\n";
+
+       // Dump properties
+       vector<property>::const_iterator i = props.begin(), iend = props.end();
+       while (i != iend) {
+               os << "  ";
+               switch (i->type) {
+                       case PTYPE_BOOL: os << "bool"; break;
+                       case PTYPE_UNSIGNED: os << "unsigned"; break;
+                       case PTYPE_STRING: os << "string"; break;
+                       case PTYPE_NODE: os << "node"; break;
+                       default: os << "<unknown>"; break;
+               }
+               os << " \"" << a.unatomize(i->name) << "\" " << i->value << endl;
+               i++;
+       }
+}
+
+
+#ifndef NO_GINAC_NAMESPACE
+} // namespace GiNaC
+#endif // ndef NO_GINAC_NAMESPACE
diff --git a/ginac/archive.h b/ginac/archive.h
new file mode 100644 (file)
index 0000000..a2db166
--- /dev/null
@@ -0,0 +1,189 @@
+/** @file archive.h
+ *
+ *  Archiving of GiNaC expressions. */
+
+/*
+ *  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
+ */
+
+#ifndef __GINAC_ARCHIVE_H__
+#define __GINAC_ARCHIVE_H__
+
+#include <ginac/ex.h>
+
+#include <string>
+#include <vector>
+
+class ostream;
+class istream;
+
+#ifndef NO_GINAC_NAMESPACE
+namespace GiNaC {
+#endif // ndef NO_GINAC_NAMESPACE
+
+class lst;
+class archive;
+
+
+/** Numerical ID value to refer to an archive_node. */
+typedef unsigned int archive_node_id;
+
+/** Numerical ID value to refer to a string. */
+typedef unsigned int archive_atom;
+
+
+/** This class stores all properties needed to record/retrieve the state
+ *  of one object of class basic (or a derived class). Each property is
+ *  addressed by its name and data type. */
+class archive_node
+{
+       friend ostream &operator<<(ostream &os, const archive_node &ar);
+       friend istream &operator>>(istream &is, archive_node &ar);
+
+public:
+       archive_node(archive &ar) : a(ar), has_expression(false) {}
+       archive_node(archive &ar, const ex &expr);
+       ~archive_node() {}
+
+       archive_node(const archive_node &other);
+       const archive_node &operator=(const archive_node &other);
+
+       bool has_same_ex_as(const archive_node &other) const;
+
+       void add_bool(const string &name, bool value);
+       void add_unsigned(const string &name, unsigned int value);
+       void add_string(const string &name, const string &value);
+       void add_ex(const string &name, const ex &value);
+
+       bool find_bool(const string &name, bool &ret) const;
+       bool find_unsigned(const string &name, unsigned int &ret) const;
+       bool find_string(const string &name, string &ret) const;
+       bool find_ex(const string &name, ex &ret, const lst &sym_lst, unsigned int index = 0) const;
+
+       ex unarchive(const lst &sym_lst) const;
+
+       void forget(void);
+       void dump(ostream &os) const;
+
+private:
+       /** Property data types */
+       enum property_type {
+               PTYPE_BOOL,
+               PTYPE_UNSIGNED,
+               PTYPE_STRING,
+               PTYPE_NODE
+       };
+
+       /** Archived property (data type, name and associated data) */
+       struct property {
+               property() {}
+               property(archive_atom n, property_type t, unsigned int v) : type(t), name(n), value(v) {}
+               ~property() {}
+
+               property(const property &other) : type(other.type), name(other.name), value(other.value) {}
+               const property &operator=(const property &other);
+
+               property_type type;     /**< Data type of property. */
+               archive_atom name;      /**< Name of property. */
+               unsigned int value;     /**< Stored value. */
+       };
+
+       /** Reference to the archive to which this node belongs. */
+       archive &a;
+
+       /** Vector of stored properties. */
+       vector<property> props;
+
+       /** Flag indicating whether a cached unarchived representation of this node exists. */
+       mutable bool has_expression;
+
+       /** The cached unarchived representation of this node (if any). */
+       mutable ex e;
+};
+
+
+/** This class holds archived versions of GiNaC expressions (class ex).
+ *  An archive can be constructed from an expression and then written to
+ *  a stream; or it can be read from a stream and then unarchived, yielding
+ *  back the expression. Archives can hold multiple expressions which can
+ *  be referred to by name or index number. The main component of the
+ *  archive class is a vector of archive_nodes which each store one object
+ *  of class basic (or a derived class). */
+class archive
+{
+       friend ostream &operator<<(ostream &os, const archive &ar);
+       friend istream &operator>>(istream &is, archive &ar);
+
+public:
+       archive() {}
+       ~archive() {}
+
+       /** Construct archive from expression using the default name "ex". */
+       archive(const ex &e) {archive_ex(e, "ex");}
+
+       /** Construct archive from expression using the specified name. */
+       archive(const ex &e, const char *n) {archive_ex(e, n);}
+
+       archive_node_id add_node(const archive_node &n);
+       archive_node &get_node(archive_node_id id);
+
+       void archive_ex(const ex &e, const char *name);
+       ex unarchive_ex(const lst &sym_lst, const char *name) const;
+       ex unarchive_ex(const lst &sym_lst, unsigned int index = 0) const;
+       ex unarchive_ex(const lst &sym_lst, string &name, unsigned int index = 0) const;
+       unsigned int num_expressions(void) const;
+
+       void clear(void);
+
+       void forget(void);
+       void dump(ostream &os) const;
+
+private:
+       /** Vector of archived nodes. */
+       vector<archive_node> nodes;
+
+       /** Archived expression descriptor. */
+       struct archived_ex {
+               archived_ex() {}
+               archived_ex(archive_atom n, archive_node_id node) : name(n), root(node) {}
+
+               archive_atom name;              /**< Name of expression. */
+               archive_node_id root;   /**< ID of root node. */
+       };
+
+       /** Vector of archived expression descriptors. */
+       vector<archived_ex> exprs;
+
+public:
+       archive_atom atomize(const string &s) const;
+       const string &unatomize(archive_atom id) const;
+
+private:
+       /** Vector of atomized strings (using a vector allows faster unarchiving). */
+       mutable vector<string> atoms;
+};
+
+
+ostream &operator<<(ostream &os, const archive &ar);
+istream &operator>>(istream &is, archive &ar);
+
+
+#ifndef NO_GINAC_NAMESPACE
+} // namespace GiNaC
+#endif // ndef NO_GINAC_NAMESPACE
+
+#endif // ndef __GINAC_ARCHIVE_H__
index a8f2baa..b632a6e 100644 (file)
@@ -31,6 +31,7 @@
 #include "symbol.h"
 #include "lst.h"
 #include "ncmul.h"
+#include "archive.h"
 #include "utils.h"
 #include "debugmsg.h"
 
@@ -38,6 +39,8 @@
 namespace GiNaC {
 #endif // ndef NO_GINAC_NAMESPACE
 
+GINAC_IMPLEMENT_REGISTERED_CLASS(basic, void)
+
 //////////
 // default constructor, destructor, copy constructor assignment operator and helpers
 //////////
@@ -47,27 +50,27 @@ namespace GiNaC {
 #ifndef INLINE_BASIC_CONSTRUCTORS
 basic::basic() : flags(0), refcount(0), tinfo_key(TINFO_BASIC)
 {
-    debugmsg("basic default constructor",LOGLEVEL_CONSTRUCT);
+    debugmsg("basic default constructor", LOGLEVEL_CONSTRUCT);
     // nothing to do
 }
 
 basic::~basic() 
 {
-    debugmsg("basic destructor",LOGLEVEL_DESTRUCT);
+    debugmsg("basic destructor", LOGLEVEL_DESTRUCT);
     destroy(0);
     GINAC_ASSERT((!(flags & status_flags::dynallocated))||(refcount==0));
 }
 
 basic::basic(basic const & other) : flags(0), refcount(0), tinfo_key(TINFO_BASIC)
 {
-    debugmsg("basic copy constructor",LOGLEVEL_CONSTRUCT);
+    debugmsg("basic copy constructor", LOGLEVEL_CONSTRUCT);
     copy(other);
 }
 #endif
 
 basic const & basic::operator=(basic const & other)
 {
-    debugmsg("basic operator=",LOGLEVEL_ASSIGNMENT);
+    debugmsg("basic operator=", LOGLEVEL_ASSIGNMENT);
     if (this != &other) {
         destroy(1);
         copy(other);
@@ -93,11 +96,40 @@ void basic::copy(basic const & other)
 #ifndef INLINE_BASIC_CONSTRUCTORS
 basic::basic(unsigned ti) : flags(0), refcount(0), tinfo_key(ti)
 {
-    debugmsg("basic constructor with tinfo_key",LOGLEVEL_CONSTRUCT);
+    debugmsg("basic constructor with tinfo_key", LOGLEVEL_CONSTRUCT);
     // nothing to do
 }
 #endif
 
+//////////
+// archiving
+//////////
+
+/** Construct object from archive_node. */
+basic::basic(const archive_node &n, const lst &sym_lst) : flags(0), refcount(0)
+{
+    debugmsg("basic constructor from archive_node", LOGLEVEL_CONSTRUCT);
+
+    // Reconstruct tinfo_key from class name
+    string class_name;
+    if (n.find_string("class", class_name))
+        tinfo_key = find_tinfo_key(class_name);
+    else
+        throw (std::runtime_error("archive node contains no class name"));
+}
+
+/** Unarchive the object. */
+ex basic::unarchive(const archive_node &n, const lst &sym_lst)
+{
+    return (new basic(n, sym_lst))->setflag(status_flags::dynallocated);
+}
+
+/** Archive the object. */
+void basic::archive(archive_node &n) const
+{
+    n.add_string("class", class_name());
+}
+
 //////////
 // functions overriding virtual functions from bases classes
 //////////
index 242bd45..ecf120a 100644 (file)
@@ -33,6 +33,7 @@
 #include <ginac/flags.h>
 #include <ginac/tinfos.h>
 #include <ginac/assertion.h>
+#include <ginac/registrar.h>
 
 #ifndef NO_GINAC_NAMESPACE
 namespace GiNaC {
@@ -43,6 +44,7 @@ class ex;
 class symbol;
 class lst;
 class numeric;
+class archive_node;
 
 //typedef vector<ex> exvector;
 typedef vector<ex,malloc_alloc> exvector; // CINT does not like vector<...,default_alloc>
@@ -53,6 +55,8 @@ typedef vector<ex,malloc_alloc> exvector; // CINT does not like vector<...,defau
  *  It is responsible for the reference counting. */
 class basic
 {
+    GINAC_DECLARE_REGISTERED_CLASS(basic, void)
+
     friend class ex;
 
 // member functions
@@ -221,4 +225,3 @@ extern int max_recursion_level;
 #endif // ndef NO_GINAC_NAMESPACE
 
 #endif // ndef __GINAC_BASIC_H__
-
index fa7adf2..1e9a4c1 100644 (file)
 #include "constant.h"
 #include "numeric.h"
 #include "ex.h"
+#include "archive.h"
 #include "debugmsg.h"
 
 #ifndef NO_GINAC_NAMESPACE
 namespace GiNaC {
 #endif // ndef NO_GINAC_NAMESPACE
 
+GINAC_IMPLEMENT_REGISTERED_CLASS(constant, basic)
+
 //////////
 // default constructor, destructor, copy constructor assignment operator and helpers
 //////////
@@ -101,6 +104,42 @@ constant::constant(string const & initname, numeric const & initnumber) :
     debugmsg("constant constructor from string, numeric",LOGLEVEL_CONSTRUCT);
 }
 
+//////////
+// archiving
+//////////
+
+/** Construct object from archive_node. */
+constant::constant(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
+{
+    debugmsg("constant constructor from archive_node", LOGLEVEL_CONSTRUCT);
+}
+
+/** Unarchive the object. */
+ex constant::unarchive(const archive_node &n, const lst &sym_lst)
+{
+    // Find constant by name (!! this is bad: 'twould be better if there
+    // was a list of all global constants that we could search)
+    string s;
+    if (n.find_string("name", s)) {
+        if (s == Pi.name)
+            return Pi;
+        else if (s == Catalan.name)
+            return Catalan;
+        else if (s == EulerGamma.name)
+            return EulerGamma;
+        else
+            throw (std::runtime_error("unknown constant '" + s + "' in archive"));
+    } else
+        throw (std::runtime_error("unnamed constant in archive"));
+}
+
+/** Archive the object. */
+void constant::archive(archive_node &n) const
+{
+    inherited::archive(n);
+    n.add_string("name", name);
+}
+
 //////////
 // functions overriding virtual functions from bases classes
 //////////
index 99cbe99..2e6ad5b 100644 (file)
@@ -38,6 +38,7 @@ typedef ex (*evalffunctype)(void);
  *  number). */
 class constant : public basic
 {
+    GINAC_DECLARE_REGISTERED_CLASS(constant, basic)
 
 // member functions
 
index 5979038..c9ff5e4 100755 (executable)
@@ -139,6 +139,7 @@ typedef ${STLHEADER}<ex,malloc_alloc> ${STLT}; // CINT does not like ${STLHEADER
 
 class ${CONTAINER} : public basic
 {
+    GINAC_DECLARE_REGISTERED_CLASS(${CONTAINER}, basic)
 
 public:
     ${CONTAINER}();
@@ -276,12 +277,15 @@ $implementation=<<END_OF_IMPLEMENTATION;
 
 #include "${CONTAINER}.h"
 #include "ex.h"
+#include "archive.h"
 #include "debugmsg.h"
 
 #ifndef NO_GINAC_NAMESPACE
 namespace GiNaC {
 #endif // ndef NO_GINAC_NAMESPACE
 
+GINAC_IMPLEMENT_REGISTERED_CLASS(${CONTAINER}, basic)
+
 ${RESERVE_IMPLEMENTATION}
 
 //////////
@@ -321,14 +325,14 @@ ${CONTAINER} const & ${CONTAINER}::operator=(${CONTAINER} const & other)
 
 void ${CONTAINER}::copy(${CONTAINER} const & other)
 {
-    basic::copy(other);
+    inherited::copy(other);
     seq=other.seq;
 }
 
 void ${CONTAINER}::destroy(bool call_parent)
 {
     seq.clear();
-    if (call_parent) basic::destroy(call_parent);
+    if (call_parent) inherited::destroy(call_parent);
 }
 
 //////////
@@ -497,6 +501,40 @@ ${CONTAINER}::${CONTAINER}(ex const & e1, ex const & e2, ex const & e3,
     seq.push_back(e10);
 }
 
+//////////
+// archiving
+//////////
+
+/** Construct object from archive_node. */
+${CONTAINER}::${CONTAINER}(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
+{
+    debugmsg("${CONTAINER} constructor from archive_node", LOGLEVEL_CONSTRUCT);
+    for (unsigned int i=0; true; i++) {
+        ex e;
+        if (n.find_ex("seq", e, sym_lst, i))
+            seq.push_back(e);
+        else
+            break;
+    }
+}
+
+/** Unarchive the object. */
+ex ${CONTAINER}::unarchive(const archive_node &n, const lst &sym_lst)
+{
+    return (new ${CONTAINER}(n, sym_lst))->setflag(status_flags::dynallocated);
+}
+
+/** Archive the object. */
+void ${CONTAINER}::archive(archive_node &n) const
+{
+    inherited::archive(n);
+    ${STLT}::const_iterator i = seq.begin(), iend = seq.end();
+    while (i != iend) {
+        n.add_ex("seq", *i);
+        i++;
+    }
+}
+
 //////////
 // functions overriding virtual functions from bases classes
 //////////
index afbbeda..c3bd239 100644 (file)
@@ -34,7 +34,7 @@
 #include "numeric.h"
 #include "power.h"
 #include "relational.h"
-#include "series.h"
+#include "pseries.h"
 #include "symbol.h"
 #include "utils.h"
 
@@ -200,9 +200,9 @@ ex function::diff(symbol const & s) const
 }
 
 
-/** Implementation of ex::diff() for a power-series. It treats the series as a polynomial.
+/** Implementation of ex::diff() for a power series. It treats the series as a polynomial.
  *  @see ex::diff */
-ex series::diff(symbol const & s) const
+ex pseries::diff(symbol const & s) const
 {
     if (s == var) {
         epvector new_seq;
@@ -219,7 +219,7 @@ ex series::diff(symbol const & s) const
             }
             it++;
         }
-        return series(var, point, new_seq);
+        return pseries(var, point, new_seq);
     } else {
         return *this;
     }
index 313bd6c..21a4ea7 100644 (file)
@@ -308,6 +308,9 @@ inline ex evalf(ex const & thisex, int level = 0)
 inline ex diff(ex const & thisex, symbol const & s, unsigned nth = 1)
 { return thisex.diff(s, nth); }
 
+inline ex series(ex const & thisex, symbol const & s, ex const & point, int order = 6)
+{ return thisex.series(s, point, order); }
+
 inline ex subs(ex const & thisex, ex const & e)
 { return thisex.subs(e); }
 
index 0e867c8..0d4a01c 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "expairseq.h"
 #include "lst.h"
+#include "archive.h"
 #include "debugmsg.h"
 #include "utils.h"
 
@@ -38,6 +39,8 @@ namespace GiNaC {
 #error "FIXME: expair_needs_further_processing not yet implemented for hashtabs, sorry. A.F."
 #endif // def EXPAIRSEQ_USE_HASHTAB
 
+GINAC_IMPLEMENT_REGISTERED_CLASS(expairseq, basic)
+
 //////////
 // helper classes
 //////////
@@ -77,7 +80,7 @@ expairseq const & expairseq::operator=(expairseq const & other)
 
 void expairseq::copy(expairseq const & other)
 {
-    basic::copy(other);
+    inherited::copy(other);
     seq=other.seq;
     overall_coeff=other.overall_coeff;
 #ifdef EXPAIRSEQ_USE_HASHTAB
@@ -104,14 +107,14 @@ void expairseq::copy(expairseq const & other)
 // other constructors
 //////////
 
-expairseq::expairseq(ex const & lh, ex const & rh) : basic(TINFO_expairseq)
+expairseq::expairseq(ex const & lh, ex const & rh) : inherited(TINFO_expairseq)
 {
     debugmsg("expairseq constructor from ex,ex",LOGLEVEL_CONSTRUCT);
     construct_from_2_ex(lh,rh);
     GINAC_ASSERT(is_canonical());
 }
 
-expairseq::expairseq(exvector const & v) : basic(TINFO_expairseq)
+expairseq::expairseq(exvector const & v) : inherited(TINFO_expairseq)
 {
     debugmsg("expairseq constructor from exvector",LOGLEVEL_CONSTRUCT);
     construct_from_exvector(v);
@@ -120,7 +123,7 @@ expairseq::expairseq(exvector const & v) : basic(TINFO_expairseq)
 
 /*
 expairseq::expairseq(epvector const & v, bool do_not_canonicalize) :
-    basic(TINFO_expairseq)
+    inherited(TINFO_expairseq)
 {
     debugmsg("expairseq constructor from epvector",LOGLEVEL_CONSTRUCT);
     if (do_not_canonicalize) {
@@ -136,7 +139,7 @@ expairseq::expairseq(epvector const & v, bool do_not_canonicalize) :
 */
 
 expairseq::expairseq(epvector const & v, ex const & oc) :
-    basic(TINFO_expairseq), overall_coeff(oc)
+    inherited(TINFO_expairseq), overall_coeff(oc)
 {
     debugmsg("expairseq constructor from epvector,ex",LOGLEVEL_CONSTRUCT);
     construct_from_epvector(v);
@@ -144,7 +147,7 @@ expairseq::expairseq(epvector const & v, ex const & oc) :
 }
 
 expairseq::expairseq(epvector * vp, ex const & oc) :
-    basic(TINFO_expairseq), overall_coeff(oc)
+    inherited(TINFO_expairseq), overall_coeff(oc)
 {
     debugmsg("expairseq constructor from epvector *,ex",LOGLEVEL_CONSTRUCT);
     GINAC_ASSERT(vp!=0);
@@ -153,6 +156,47 @@ expairseq::expairseq(epvector * vp, ex const & oc) :
     GINAC_ASSERT(is_canonical());
 }
 
+//////////
+// archiving
+//////////
+
+/** Construct object from archive_node. */
+expairseq::expairseq(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
+#ifdef EXPAIRSEQ_USE_HASHTAB
+    , hashtabsize(0)
+#endif
+{
+    debugmsg("expairseq constructor from archive_node", LOGLEVEL_CONSTRUCT);
+    for (unsigned int i=0; true; i++) {
+        ex rest;
+        ex coeff;
+        if (n.find_ex("rest", rest, sym_lst, i) && n.find_ex("coeff", coeff, sym_lst, i))
+            seq.push_back(expair(rest, coeff));
+        else
+            break;
+    }
+    n.find_ex("overall_coeff", overall_coeff, sym_lst);
+}
+
+/** Unarchive the object. */
+ex expairseq::unarchive(const archive_node &n, const lst &sym_lst)
+{
+    return (new expairseq(n, sym_lst))->setflag(status_flags::dynallocated);
+}
+
+/** Archive the object. */
+void expairseq::archive(archive_node &n) const
+{
+    inherited::archive(n);
+    epvector::const_iterator i = seq.begin(), iend = seq.end();
+    while (i != iend) {
+        n.add_ex("rest", i->rest);
+        n.add_ex("coeff", i->coeff);
+        i++;
+    }
+    n.add_ex("overall_coeff", overall_coeff);
+}
+
 //////////
 // functions overriding virtual functions from bases classes
 //////////
@@ -265,7 +309,7 @@ void expairseq::printtree(ostream & os, unsigned indent) const
 
 bool expairseq::info(unsigned inf) const
 {
-    return basic::info(inf);
+    return inherited::info(inf);
 }
 
 unsigned expairseq::nops() const
index 6203af3..d9d7bf0 100644 (file)
@@ -57,6 +57,8 @@ typedef vector<epplist> epplistvector;
  *  the same way.) */
 class expairseq : public basic
 {
+    GINAC_DECLARE_REGISTERED_CLASS(expairseq, basic)
+
 // member functions
 
     // default constructor, destructor, copy constructor assignment operator and helpers
index 395b118..9e8d8a6 100644 (file)
  */
 
 #include "fail.h"
+#include "archive.h"
 #include "debugmsg.h"
 
 #ifndef NO_GINAC_NAMESPACE
 namespace GiNaC {
 #endif // ndef NO_GINAC_NAMESPACE
 
+GINAC_IMPLEMENT_REGISTERED_CLASS(fail, basic)
+
 //////////
 // default constructor, destructor, copy constructor assignment operator and helpers
 //////////
 
 // public
 
-fail::fail() : basic(TINFO_fail)
+fail::fail() : inherited(TINFO_fail)
 {
     debugmsg("fail default constructor",LOGLEVEL_CONSTRUCT);
 }
@@ -65,12 +68,12 @@ fail const & fail::operator=(fail const & other)
 
 void fail::copy(fail const & other)
 {
-    basic::copy(other);
+    inherited::copy(other);
 }
 
 void fail::destroy(bool call_parent)
 {
-    if (call_parent) basic::destroy(call_parent);
+    if (call_parent) inherited::destroy(call_parent);
 }
 
 
@@ -80,6 +83,28 @@ void fail::destroy(bool call_parent)
 
 // none
 
+//////////
+// archiving
+//////////
+
+/** Construct object from archive_node. */
+fail::fail(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
+{
+    debugmsg("fail constructor from archive_node", LOGLEVEL_CONSTRUCT);
+}
+
+/** Unarchive the object. */
+ex fail::unarchive(const archive_node &n, const lst &sym_lst)
+{
+    return (new fail(n, sym_lst))->setflag(status_flags::dynallocated);
+}
+
+/** Archive the object. */
+void fail::archive(archive_node &n) const
+{
+    inherited::archive(n);
+}
+
 //////////
 // functions overriding virtual functions from bases classes
 //////////
index 4dce177..aa207d4 100644 (file)
@@ -32,7 +32,7 @@ namespace GiNaC {
 
 class fail : public basic
 {
-// member functions
+    GINAC_DECLARE_REGISTERED_CLASS(fail, basic)
 
     // default constructor, destructor, copy constructor assignment operator and helpers
 public:
index f08990d..e2b4374 100755 (executable)
@@ -259,6 +259,8 @@ struct registered_function_info {
     and user defined functions */
 class function : public exprseq
 {
+    GINAC_DECLARE_REGISTERED_CLASS(function, exprseq)
+
     // CINT has a linking problem
     friend void ginsh_get_ginac_functions(void);
 
@@ -382,6 +384,7 @@ $implementation=<<END_OF_IMPLEMENTATION;
 
 #include "function.h"
 #include "ex.h"
+#include "archive.h"
 #include "utils.h"
 #include "debugmsg.h"
 
@@ -389,6 +392,8 @@ $implementation=<<END_OF_IMPLEMENTATION;
 namespace GiNaC {
 #endif // ndef NO_GINAC_NAMESPACE
 
+GINAC_IMPLEMENT_REGISTERED_CLASS(function, exprseq)
+
 //////////
 // default constructor, destructor, copy constructor assignment operator and helpers
 //////////
@@ -472,6 +477,46 @@ function::function(unsigned ser, exvector * vp)
     tinfo_key = TINFO_function;
 }
 
+//////////
+// archiving
+//////////
+
+/** Construct object from archive_node. */
+function::function(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
+{
+    debugmsg("function constructor from archive_node", LOGLEVEL_CONSTRUCT);
+
+    // Find serial number by function name
+    string s;
+    if (n.find_string("name", s)) {
+        unsigned int ser = 0;
+        vector<registered_function_info>::const_iterator i = registered_functions().begin(), iend = registered_functions().end();
+        while (i != iend) {
+            if (s == i->name) {
+                serial = ser;
+                return;
+            }
+            i++; ser++;
+        }
+        throw (std::runtime_error("unknown function '" + s + "' in archive"));
+    } else
+        throw (std::runtime_error("unnamed function in archive"));
+}
+
+/** Unarchive the object. */
+ex function::unarchive(const archive_node &n, const lst &sym_lst)
+{
+    return (new function(n, sym_lst))->setflag(status_flags::dynallocated);
+}
+
+/** Archive the object. */
+void function::archive(archive_node &n) const
+{
+    inherited::archive(n);
+    GINAC_ASSERT(serial < registered_functions().size());
+    n.add_string("name", registered_functions()[serial].name);
+}
+
 //////////
 // functions overriding virtual functions from bases classes
 //////////
index 78a8f20..c91d06c 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <ginac/ex.h>
 #include <ginac/normal.h>
+#include <ginac/archive.h>
 
 #include <ginac/constant.h>
 #include <ginac/fail.h>
@@ -43,7 +44,7 @@
 #include <ginac/expairseq.h>
 #include <ginac/add.h>
 #include <ginac/mul.h>
-#include <ginac/series.h>
+#include <ginac/pseries.h>
 
 #include <ginac/exprseq.h>
 #include <ginac/function.h>
index acdd8b0..4eeb2db 100644 (file)
@@ -31,6 +31,8 @@
 namespace GiNaC {
 #endif // ndef NO_GINAC_NAMESPACE
 
+GINAC_IMPLEMENT_REGISTERED_CLASS(indexed, exprseq)
+
 //////////
 // default constructor, destructor, copy constructor assignment operator and helpers
 //////////
@@ -69,13 +71,13 @@ indexed const & indexed::operator=(indexed const & other)
 
 void indexed::copy(indexed const & other)
 {
-    exprseq::copy(other);
+    inherited::copy(other);
 }
 
 void indexed::destroy(bool call_parent)
 {
     if (call_parent) {
-        exprseq::destroy(call_parent);
+        inherited::destroy(call_parent);
     }
 }
 
@@ -85,14 +87,14 @@ void indexed::destroy(bool call_parent)
 
 // public
 
-indexed::indexed(ex const & i1) : exprseq(i1)
+indexed::indexed(ex const & i1) : inherited(i1)
 {
     debugmsg("indexed constructor from ex",LOGLEVEL_CONSTRUCT);
     tinfo_key=TINFO_indexed;
     GINAC_ASSERT(all_of_type_idx());
 }
 
-indexed::indexed(ex const & i1, ex const & i2) : exprseq(i1,i2)
+indexed::indexed(ex const & i1, ex const & i2) : inherited(i1,i2)
 {
     debugmsg("indexed constructor from ex,ex",LOGLEVEL_CONSTRUCT);
     tinfo_key=TINFO_indexed;
@@ -100,7 +102,7 @@ indexed::indexed(ex const & i1, ex const & i2) : exprseq(i1,i2)
 }
 
 indexed::indexed(ex const & i1, ex const & i2, ex const & i3)
-    : exprseq(i1,i2,i3)
+    : inherited(i1,i2,i3)
 {
     debugmsg("indexed constructor from ex,ex,ex",LOGLEVEL_CONSTRUCT);
     tinfo_key=TINFO_indexed;
@@ -108,27 +110,49 @@ indexed::indexed(ex const & i1, ex const & i2, ex const & i3)
 }
 
 indexed::indexed(ex const & i1, ex const & i2, ex const & i3, ex const & i4)
-    : exprseq(i1,i2,i3,i4)
+    : inherited(i1,i2,i3,i4)
 {
     debugmsg("indexed constructor from ex,ex,ex,ex",LOGLEVEL_CONSTRUCT);
     tinfo_key=TINFO_indexed;
     GINAC_ASSERT(all_of_type_idx());
 }
 
-indexed::indexed(exvector const & iv) : exprseq(iv)
+indexed::indexed(exvector const & iv) : inherited(iv)
 {
     debugmsg("indexed constructor from exvector",LOGLEVEL_CONSTRUCT);
     tinfo_key=TINFO_indexed;
     GINAC_ASSERT(all_of_type_idx());
 }
 
-indexed::indexed(exvector * ivp) : exprseq(ivp)
+indexed::indexed(exvector * ivp) : inherited(ivp)
 {
     debugmsg("indexed constructor from exvector *",LOGLEVEL_CONSTRUCT);
     tinfo_key=TINFO_indexed;
     GINAC_ASSERT(all_of_type_idx());
 }
 
+//////////
+// archiving
+//////////
+
+/** Construct object from archive_node. */
+indexed::indexed(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
+{
+    debugmsg("indexed constructor from archive_node", LOGLEVEL_CONSTRUCT);
+}
+
+/** Unarchive the object. */
+ex indexed::unarchive(const archive_node &n, const lst &sym_lst)
+{
+    return (new indexed(n, sym_lst))->setflag(status_flags::dynallocated);
+}
+
+/** Archive the object. */
+void indexed::archive(archive_node &n) const
+{
+    inherited::archive(n);
+}
+
 //////////
 // functions overriding virtual functions from bases classes
 //////////
@@ -175,7 +199,7 @@ bool indexed::info(unsigned inf) const
 {
     if (inf==info_flags::indexed) return true;
     if (inf==info_flags::has_indices) return seq.size()!=0;
-    return exprseq::info(inf);
+    return inherited::info(inf);
 }
 
 exvector indexed::get_indices(void) const
@@ -199,13 +223,13 @@ exvector indexed::get_indices(void) const
 int indexed::compare_same_type(basic const & other) const
 {
     GINAC_ASSERT(is_of_type(other,indexed));
-    return exprseq::compare_same_type(other);
+    return inherited::compare_same_type(other);
 }
 
 bool indexed::is_equal_same_type(basic const & other) const
 {
     GINAC_ASSERT(is_of_type(other,indexed));
-    return exprseq::is_equal_same_type(other);
+    return inherited::is_equal_same_type(other);
 }
 
 unsigned indexed::return_type(void) const
index 6121e02..ce416ff 100644 (file)
@@ -33,6 +33,8 @@ namespace GiNaC {
 /** Base class for non-commutative indexed objects */
 class indexed : public exprseq
 {
+    GINAC_DECLARE_REGISTERED_CLASS(indexed, exprseq)
+
 // member functions
 
     // default constructor, destructor, copy constructor assignment operator and helpers
index a334bfc..c99e358 100644 (file)
@@ -33,7 +33,7 @@
 #include "numeric.h"
 #include "power.h"
 #include "relational.h"
-#include "series.h"
+#include "pseries.h"
 #include "symbol.h"
 #include "utils.h"
 
@@ -157,10 +157,10 @@ static ex Order_eval(ex const & x)
 
 static ex Order_series(ex const & x, symbol const & s, ex const & point, int order)
 {
-       // Just wrap the function into a series object
+       // Just wrap the function into a pseries object
        epvector new_seq;
        new_seq.push_back(expair(Order(_ex1()), numeric(min(x.ldegree(s), order))));
-       return series(s, point, new_seq);
+       return pseries(s, point, new_seq);
 }
 
 REGISTER_FUNCTION(Order, Order_eval, NULL, NULL, Order_series);
index cb8699e..d20a27f 100644 (file)
@@ -27,7 +27,7 @@
 #include "inifcns.h"
 #include "ex.h"
 #include "constant.h"
-#include "series.h"
+#include "pseries.h"
 #include "numeric.h"
 #include "power.h"
 #include "relational.h"
index 156bc9f..0ed64ef 100644 (file)
 #include <stdexcept>
 
 #include "matrix.h"
-#include "debugmsg.h"
+#include "archive.h"
 #include "utils.h"
+#include "debugmsg.h"
 
 #ifndef NO_GINAC_NAMESPACE
 namespace GiNaC {
 #endif // ndef NO_GINAC_NAMESPACE
 
+GINAC_IMPLEMENT_REGISTERED_CLASS(matrix, basic)
+
 //////////
 // default constructor, destructor, copy constructor, assignment operator
 // and helpers:
@@ -40,7 +43,7 @@ namespace GiNaC {
 
 /** Default ctor.  Initializes to 1 x 1-dimensional zero-matrix. */
 matrix::matrix()
-    : basic(TINFO_matrix), row(1), col(1)
+    : inherited(TINFO_matrix), row(1), col(1)
 {
     debugmsg("matrix default constructor",LOGLEVEL_CONSTRUCT);
     m.push_back(_ex0());
@@ -71,7 +74,7 @@ matrix const & matrix::operator=(matrix const & other)
 
 void matrix::copy(matrix const & other)
 {
-    basic::copy(other);
+    inherited::copy(other);
     row=other.row;
     col=other.col;
     m=other.m;  // use STL's vector copying
@@ -79,7 +82,7 @@ void matrix::copy(matrix const & other)
 
 void matrix::destroy(bool call_parent)
 {
-    if (call_parent) basic::destroy(call_parent);
+    if (call_parent) inherited::destroy(call_parent);
 }
 
 //////////
@@ -93,7 +96,7 @@ void matrix::destroy(bool call_parent)
  *  @param r number of rows
  *  @param c number of cols */
 matrix::matrix(unsigned r, unsigned c)
-    : basic(TINFO_matrix), row(r), col(c)
+    : inherited(TINFO_matrix), row(r), col(c)
 {
     debugmsg("matrix constructor from unsigned,unsigned",LOGLEVEL_CONSTRUCT);
     m.resize(r*c, _ex0());
@@ -103,11 +106,50 @@ matrix::matrix(unsigned r, unsigned c)
 
 /** Ctor from representation, for internal use only. */
 matrix::matrix(unsigned r, unsigned c, exvector const & m2)
-    : basic(TINFO_matrix), row(r), col(c), m(m2)
+    : inherited(TINFO_matrix), row(r), col(c), m(m2)
 {
     debugmsg("matrix constructor from unsigned,unsigned,exvector",LOGLEVEL_CONSTRUCT);
 }
 
+//////////
+// archiving
+//////////
+
+/** Construct object from archive_node. */
+matrix::matrix(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
+{
+    debugmsg("matrix constructor from archive_node", LOGLEVEL_CONSTRUCT);
+    if (!(n.find_unsigned("row", row)) || !(n.find_unsigned("col", col)))
+        throw (std::runtime_error("unknown matrix dimensions in archive"));
+    m.reserve(row * col);
+    for (unsigned int i=0; true; i++) {
+        ex e;
+        if (n.find_ex("m", e, sym_lst, i))
+            m.push_back(e);
+        else
+            break;
+    }
+}
+
+/** Unarchive the object. */
+ex matrix::unarchive(const archive_node &n, const lst &sym_lst)
+{
+    return (new matrix(n, sym_lst))->setflag(status_flags::dynallocated);
+}
+
+/** Archive the object. */
+void matrix::archive(archive_node &n) const
+{
+    inherited::archive(n);
+    n.add_unsigned("row", row);
+    n.add_unsigned("col", col);
+    exvector::const_iterator i = m.begin(), iend = m.end();
+    while (i != iend) {
+        n.add_ex("m", *i);
+        i++;
+    }
+}
+
 //////////
 // functions overriding virtual functions from bases classes
 //////////
index 1be80d7..3780122 100644 (file)
@@ -34,10 +34,13 @@ namespace GiNaC {
 /** Symbolic matrices. */
 class matrix : public basic
 {
+    GINAC_DECLARE_REGISTERED_CLASS(matrix, basic)
+
 // friends
     friend ex determinant_numeric(const matrix & m);
     friend ex determinant_symbolic_perm(const matrix & m);
     friend ex determinant_symbolic_minor(const matrix & m);
+
 // member functions
 
     // default constructor, destructor, copy constructor, assignment operator
index c83acf0..b269836 100644 (file)
@@ -26,6 +26,7 @@
 #include "mul.h"
 #include "add.h"
 #include "power.h"
+#include "archive.h"
 #include "debugmsg.h"
 #include "utils.h"
 
@@ -33,6 +34,8 @@
 namespace GiNaC {
 #endif // ndef NO_GINAC_NAMESPACE
 
+GINAC_IMPLEMENT_REGISTERED_CLASS(mul, expairseq)
+
 //////////
 // default constructor, destructor, copy constructor assignment operator and helpers
 //////////
@@ -71,12 +74,12 @@ mul const & mul::operator=(mul const & other)
 
 void mul::copy(mul const & other)
 {
-    expairseq::copy(other);
+    inherited::copy(other);
 }
 
 void mul::destroy(bool call_parent)
 {
-    if (call_parent) expairseq::destroy(call_parent);
+    if (call_parent) inherited::destroy(call_parent);
 }
 
 //////////
@@ -163,6 +166,28 @@ mul::mul(ex const & lh, ex const & mh, ex const & rh)
     GINAC_ASSERT(is_canonical());
 }
 
+//////////
+// archiving
+//////////
+
+/** Construct object from archive_node. */
+mul::mul(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
+{
+    debugmsg("mul constructor from archive_node", LOGLEVEL_CONSTRUCT);
+}
+
+/** Unarchive the object. */
+ex mul::unarchive(const archive_node &n, const lst &sym_lst)
+{
+    return (new mul(n, sym_lst))->setflag(status_flags::dynallocated);
+}
+
+/** Archive the object. */
+void mul::archive(archive_node &n) const
+{
+    inherited::archive(n);
+}
+
 //////////
 // functions overriding virtual functions from bases classes
 //////////
@@ -285,7 +310,7 @@ bool mul::info(unsigned inf) const
         }
         return overall_coeff.info(inf);
     } else {
-        return expairseq::info(inf);
+        return inherited::info(inf);
     }
 }
 
@@ -439,12 +464,12 @@ ex mul::simplify_ncmul(exvector const & v) const
 
 int mul::compare_same_type(basic const & other) const
 {
-    return expairseq::compare_same_type(other);
+    return inherited::compare_same_type(other);
 }
 
 bool mul::is_equal_same_type(basic const & other) const
 {
-    return expairseq::is_equal_same_type(other);
+    return inherited::is_equal_same_type(other);
 }
 
 unsigned mul::return_type(void) const
index 4917b01..8f8e114 100644 (file)
@@ -32,6 +32,8 @@ namespace GiNaC {
 /** Product of expressions. */
 class mul : public expairseq
 {
+    GINAC_DECLARE_REGISTERED_CLASS(mul, expairseq)
+
     friend class add;
     friend class ncmul;
     friend class power;
index d3a6883..d7d97b9 100644 (file)
@@ -28,6 +28,7 @@
 #include "ex.h"
 #include "add.h"
 #include "mul.h"
+#include "archive.h"
 #include "debugmsg.h"
 #include "utils.h"
 
@@ -35,6 +36,8 @@
 namespace GiNaC {
 #endif // ndef NO_GINAC_NAMESPACE
 
+GINAC_IMPLEMENT_REGISTERED_CLASS(ncmul, exprseq)
+
 //////////
 // default constructor, destructor, copy constructor assignment operator and helpers
 //////////
@@ -73,12 +76,12 @@ ncmul const & ncmul::operator=(ncmul const & other)
 
 void ncmul::copy(ncmul const & other)
 {
-    exprseq::copy(other);
+    inherited::copy(other);
 }
 
 void ncmul::destroy(bool call_parent)
 {
-    if (call_parent) exprseq::destroy(call_parent);
+    if (call_parent) inherited::destroy(call_parent);
 }
 
 //////////
@@ -88,28 +91,28 @@ void ncmul::destroy(bool call_parent)
 // public
 
 ncmul::ncmul(ex const & lh, ex const & rh) :
-    exprseq(lh,rh)
+    inherited(lh,rh)
 {
     debugmsg("ncmul constructor from ex,ex",LOGLEVEL_CONSTRUCT);
     tinfo_key = TINFO_ncmul;
 }
 
 ncmul::ncmul(ex const & f1, ex const & f2, ex const & f3) :
-    exprseq(f1,f2,f3)
+    inherited(f1,f2,f3)
 {
     debugmsg("ncmul constructor from 3 ex",LOGLEVEL_CONSTRUCT);
     tinfo_key = TINFO_ncmul;
 }
 
 ncmul::ncmul(ex const & f1, ex const & f2, ex const & f3,
-      ex const & f4) : exprseq(f1,f2,f3,f4)
+      ex const & f4) : inherited(f1,f2,f3,f4)
 {
     debugmsg("ncmul constructor from 4 ex",LOGLEVEL_CONSTRUCT);
     tinfo_key = TINFO_ncmul;
 }
 
 ncmul::ncmul(ex const & f1, ex const & f2, ex const & f3,
-      ex const & f4, ex const & f5) : exprseq(f1,f2,f3,f4,f5)
+      ex const & f4, ex const & f5) : inherited(f1,f2,f3,f4,f5)
 {
     debugmsg("ncmul constructor from 5 ex",LOGLEVEL_CONSTRUCT);
     tinfo_key = TINFO_ncmul;
@@ -117,23 +120,46 @@ ncmul::ncmul(ex const & f1, ex const & f2, ex const & f3,
 
 ncmul::ncmul(ex const & f1, ex const & f2, ex const & f3,
       ex const & f4, ex const & f5, ex const & f6) :
-    exprseq(f1,f2,f3,f4,f5,f6)
+    inherited(f1,f2,f3,f4,f5,f6)
 {
     debugmsg("ncmul constructor from 6 ex",LOGLEVEL_CONSTRUCT);
     tinfo_key = TINFO_ncmul;
 }
 
-ncmul::ncmul(exvector const & v, bool discardable) : exprseq(v,discardable)
+ncmul::ncmul(exvector const & v, bool discardable) : inherited(v,discardable)
 {
     debugmsg("ncmul constructor from exvector,bool",LOGLEVEL_CONSTRUCT);
     tinfo_key = TINFO_ncmul;
 }
 
-ncmul::ncmul(exvector * vp) : exprseq(vp)
+ncmul::ncmul(exvector * vp) : inherited(vp)
 {
     debugmsg("ncmul constructor from exvector *",LOGLEVEL_CONSTRUCT);
     tinfo_key = TINFO_ncmul;
 }
+
+//////////
+// archiving
+//////////
+
+/** Construct object from archive_node. */
+ncmul::ncmul(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
+{
+    debugmsg("ncmul constructor from archive_node", LOGLEVEL_CONSTRUCT);
+}
+
+/** Unarchive the object. */
+ex ncmul::unarchive(const archive_node &n, const lst &sym_lst)
+{
+    return (new ncmul(n, sym_lst))->setflag(status_flags::dynallocated);
+}
+
+/** Archive the object. */
+void ncmul::archive(archive_node &n) const
+{
+    inherited::archive(n);
+}
+
     
 //////////
 // functions overriding virtual functions from bases classes
@@ -514,7 +540,7 @@ ex ncmul::thisexprseq(exvector * vp) const
 
 int ncmul::compare_same_type(basic const & other) const
 {
-    return exprseq::compare_same_type(other);
+    return inherited::compare_same_type(other);
 }
 
 unsigned ncmul::return_type(void) const
index 2e22995..1047793 100644 (file)
@@ -32,6 +32,8 @@ namespace GiNaC {
 /** Non-commutative product of expressions. */
 class ncmul : public exprseq
 {
+    GINAC_DECLARE_REGISTERED_CLASS(ncmul, exprseq)
+
     friend class power;
     friend ex nonsimplified_ncmul(exvector const & v);
     friend ex simplified_ncmul(exvector const & v);
index 0ee26ad..f0d9c1a 100644 (file)
@@ -43,7 +43,7 @@
 #include "numeric.h"
 #include "power.h"
 #include "relational.h"
-#include "series.h"
+#include "pseries.h"
 #include "symbol.h"
 #include "utils.h"
 
@@ -1460,10 +1460,10 @@ ex power::normal(lst &sym_lst, lst &repl_lst, int level) const
 }
 
 
-/** Implementation of ex::normal() for series. It normalizes each coefficient and
+/** Implementation of ex::normal() for pseries. It normalizes each coefficient and
  *  replaces the series by a temporary symbol.
  *  @see ex::normal */
-ex series::normal(lst &sym_lst, lst &repl_lst, int level) const
+ex pseries::normal(lst &sym_lst, lst &repl_lst, int level) const
 {
     epvector new_seq;
     new_seq.reserve(seq.size());
@@ -1474,7 +1474,7 @@ ex series::normal(lst &sym_lst, lst &repl_lst, int level) const
         it++;
     }
 
-    ex n = series(var, point, new_seq);
+    ex n = pseries(var, point, new_seq);
     return replace_with_symbol(n, sym_lst, repl_lst);
 }
 
index c0a2051..dd6a1eb 100644 (file)
 
 #include <vector>
 #include <stdexcept>
+#include <string>
+#include <strstream>   //!!
 
 #include "numeric.h"
 #include "ex.h"
 #include "config.h"
+#include "archive.h"
 #include "debugmsg.h"
 #include "utils.h"
 
@@ -48,6 +51,8 @@ namespace GiNaC {
 // linker has no problems finding text symbols for numerator or denominator
 //#define SANE_LINKER
 
+GINAC_IMPLEMENT_REGISTERED_CLASS(numeric, basic)
+
 //////////
 // default constructor, destructor, copy constructor assignment
 // operator and helpers
@@ -110,7 +115,7 @@ void numeric::destroy(bool call_parent)
 
 numeric::numeric(int i) : basic(TINFO_numeric)
 {
-    debugmsg("const numericructor from int",LOGLEVEL_CONSTRUCT);
+    debugmsg("numeric constructor from int",LOGLEVEL_CONSTRUCT);
     // Not the whole int-range is available if we don't cast to long
     // first. This is due to the behaviour of the cl_I-ctor, which
     // emphasizes efficiency:
@@ -122,7 +127,7 @@ numeric::numeric(int i) : basic(TINFO_numeric)
 
 numeric::numeric(unsigned int i) : basic(TINFO_numeric)
 {
-    debugmsg("const numericructor from uint",LOGLEVEL_CONSTRUCT);
+    debugmsg("numeric constructor from uint",LOGLEVEL_CONSTRUCT);
     // Not the whole uint-range is available if we don't cast to ulong
     // first. This is due to the behaviour of the cl_I-ctor, which
     // emphasizes efficiency:
@@ -134,7 +139,7 @@ numeric::numeric(unsigned int i) : basic(TINFO_numeric)
 
 numeric::numeric(long i) : basic(TINFO_numeric)
 {
-    debugmsg("const numericructor from long",LOGLEVEL_CONSTRUCT);
+    debugmsg("numeric constructor from long",LOGLEVEL_CONSTRUCT);
     value = new cl_I(i);
     calchash();
     setflag(status_flags::evaluated|
@@ -143,7 +148,7 @@ numeric::numeric(long i) : basic(TINFO_numeric)
 
 numeric::numeric(unsigned long i) : basic(TINFO_numeric)
 {
-    debugmsg("const numericructor from ulong",LOGLEVEL_CONSTRUCT);
+    debugmsg("numeric constructor from ulong",LOGLEVEL_CONSTRUCT);
     value = new cl_I(i);
     calchash();
     setflag(status_flags::evaluated|
@@ -155,7 +160,7 @@ numeric::numeric(unsigned long i) : basic(TINFO_numeric)
  *  @exception overflow_error (division by zero) */
 numeric::numeric(long numer, long denom) : basic(TINFO_numeric)
 {
-    debugmsg("const numericructor from long/long",LOGLEVEL_CONSTRUCT);
+    debugmsg("numeric constructor from long/long",LOGLEVEL_CONSTRUCT);
     if (!denom)
         throw (std::overflow_error("division by zero"));
     value = new cl_I(numer);
@@ -167,7 +172,7 @@ numeric::numeric(long numer, long denom) : basic(TINFO_numeric)
 
 numeric::numeric(double d) : basic(TINFO_numeric)
 {
-    debugmsg("const numericructor from double",LOGLEVEL_CONSTRUCT);
+    debugmsg("numeric constructor from double",LOGLEVEL_CONSTRUCT);
     // We really want to explicitly use the type cl_LF instead of the
     // more general cl_F, since that would give us a cl_DF only which
     // will not be promoted to cl_LF if overflow occurs:
@@ -180,7 +185,7 @@ numeric::numeric(double d) : basic(TINFO_numeric)
 
 numeric::numeric(char const *s) : basic(TINFO_numeric)
 {   // MISSING: treatment of complex and ints and rationals.
-    debugmsg("const numericructor from string",LOGLEVEL_CONSTRUCT);
+    debugmsg("numeric constructor from string",LOGLEVEL_CONSTRUCT);
     if (strchr(s, '.'))
         value = new cl_LF(s);
     else
@@ -194,13 +199,67 @@ numeric::numeric(char const *s) : basic(TINFO_numeric)
  *  only. */
 numeric::numeric(cl_N const & z) : basic(TINFO_numeric)
 {
-    debugmsg("const numericructor from cl_N", LOGLEVEL_CONSTRUCT);
+    debugmsg("numeric constructor from cl_N", LOGLEVEL_CONSTRUCT);
     value = new cl_N(z);
     calchash();
     setflag(status_flags::evaluated|
             status_flags::hash_calculated);
 }
 
+//////////
+// archiving
+//////////
+
+/** Construct object from archive_node. */
+numeric::numeric(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
+{
+    debugmsg("numeric constructor from archive_node", LOGLEVEL_CONSTRUCT);
+    value = new cl_N;
+#if 0  //!!
+    // This is how it should be implemented but we have no istringstream here...
+    string str;
+    if (n.find_string("number", str)) {
+        istringstream s(str);
+        s >> *value;
+    }
+#else
+    // Workaround for the above: read from strstream
+    string str;
+    if (n.find_string("number", str)) {
+        istrstream f(str.c_str(), str.size() + 1);
+        f >> *value;
+    }
+#endif
+    calchash();
+    setflag(status_flags::evaluated|
+            status_flags::hash_calculated);
+}
+
+/** Unarchive the object. */
+ex numeric::unarchive(const archive_node &n, const lst &sym_lst)
+{
+    return (new numeric(n, sym_lst))->setflag(status_flags::dynallocated);
+}
+
+/** Archive the object. */
+void numeric::archive(archive_node &n) const
+{
+    inherited::archive(n);
+#if 0  //!!
+    // This is how it should be implemented but we have no ostringstream here...
+    ostringstream s;
+    s << *value;
+    n.add_string("number", s.str());
+#else
+    // Workaround for the above: write to strstream
+    char buf[1024];
+    ostrstream f(buf, 1024);
+    f << *value << ends;
+    string str(buf);
+    n.add_string("number", str);
+#endif
+}
+
 //////////
 // functions overriding virtual functions from bases classes
 //////////
@@ -1370,7 +1429,7 @@ _numeric_digits::_numeric_digits()
 {
     assert(!too_late);
     too_late = true;
-    cl_default_float_format = cl_float_format(17); 
+    cl_default_float_format = cl_float_format(17);
 }
 
 _numeric_digits& _numeric_digits::operator=(long prec)
index 73ca87f..71cccb2 100644 (file)
@@ -63,6 +63,8 @@ private:
  *  hierarchy. Objects of this type may directly be created by the user.*/
 class numeric : public basic
 {
+    GINAC_DECLARE_REGISTERED_CLASS(numeric, basic)
+
 // friends
     friend numeric exp(const numeric & x);
     friend numeric log(const numeric & x);
index 32b6cfa..ccbf528 100644 (file)
@@ -31,6 +31,7 @@
 #include "numeric.h"
 #include "relational.h"
 #include "symbol.h"
+#include "archive.h"
 #include "debugmsg.h"
 #include "utils.h"
 
@@ -38,6 +39,8 @@
 namespace GiNaC {
 #endif // ndef NO_GINAC_NAMESPACE
 
+GINAC_IMPLEMENT_REGISTERED_CLASS(power, basic)
+
 typedef vector<int> intvector;
 
 //////////
@@ -77,14 +80,14 @@ power const & power::operator=(power const & other)
 
 void power::copy(power const & other)
 {
-    basic::copy(other);
+    inherited::copy(other);
     basis=other.basis;
     exponent=other.exponent;
 }
 
 void power::destroy(bool call_parent)
 {
-    if (call_parent) basic::destroy(call_parent);
+    if (call_parent) inherited::destroy(call_parent);
 }
 
 //////////
@@ -105,6 +108,32 @@ power::power(ex const & lh, numeric const & rh) : basic(TINFO_power), basis(lh),
     GINAC_ASSERT(basis.return_type()==return_types::commutative);
 }
 
+//////////
+// archiving
+//////////
+
+/** Construct object from archive_node. */
+power::power(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
+{
+    debugmsg("power constructor from archive_node", LOGLEVEL_CONSTRUCT);
+    n.find_ex("basis", basis, sym_lst);
+    n.find_ex("exponent", exponent, sym_lst);
+}
+
+/** Unarchive the object. */
+ex power::unarchive(const archive_node &n, const lst &sym_lst)
+{
+    return (new power(n, sym_lst))->setflag(status_flags::dynallocated);
+}
+
+/** Archive the object. */
+void power::archive(archive_node &n) const
+{
+    inherited::archive(n);
+    n.add_ex("basis", basis);
+    n.add_ex("exponent", exponent);
+}
+
 //////////
 // functions overriding virtual functions from bases classes
 //////////
@@ -229,7 +258,7 @@ bool power::info(unsigned inf) const
     } else if (inf==info_flags::rational_function) {
         return exponent.info(info_flags::integer);
     } else {
-        return basic::info(inf);
+        return inherited::info(inf);
     }
 }
 
@@ -480,7 +509,7 @@ ex power::subs(lst const & ls, lst const & lr) const
 
 ex power::simplify_ncmul(exvector const & v) const
 {
-    return basic::simplify_ncmul(v);
+    return inherited::simplify_ncmul(v);
 }
 
 // protected
index e721ab2..4224c19 100644 (file)
@@ -37,6 +37,8 @@ class add;
  *  representing exponentiation. */
 class power : public basic
 {
+    GINAC_DECLARE_REGISTERED_CLASS(power, basic)
+
     friend class mul;
 
 // member functions
similarity index 70%
rename from ginac/series.cpp
rename to ginac/pseries.cpp
index 1671931..ff39d24 100644 (file)
@@ -1,6 +1,6 @@
-/** @file series.cpp
+/** @file pseries.cpp
  *
- *  Implementation of class for extended truncated power-series and
+ *  Implementation of class for extended truncated power series and
  *  methods for series expansion. */
 
 /*
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include "series.h"
+#include "pseries.h"
 #include "add.h"
 #include "inifcns.h"
+#include "lst.h"
 #include "mul.h"
 #include "power.h"
 #include "relational.h"
 #include "symbol.h"
-#include "debugmsg.h"
+#include "archive.h"
 #include "utils.h"
+#include "debugmsg.h"
 
 #ifndef NO_GINAC_NAMESPACE
 namespace GiNaC {
 #endif // ndef NO_GINAC_NAMESPACE
 
+GINAC_IMPLEMENT_REGISTERED_CLASS(pseries, basic)
+
 /*
  *  Default constructor, destructor, copy constructor, assignment operator and helpers
  */
 
-series::series() : basic(TINFO_series)
+pseries::pseries() : basic(TINFO_pseries)
 {
-    debugmsg("series default constructor", LOGLEVEL_CONSTRUCT);
+    debugmsg("pseries default constructor", LOGLEVEL_CONSTRUCT);
 }
 
-series::~series()
+pseries::~pseries()
 {
-    debugmsg("series destructor", LOGLEVEL_DESTRUCT);
+    debugmsg("pseries destructor", LOGLEVEL_DESTRUCT);
     destroy(false);
 }
 
-series::series(series const &other)
+pseries::pseries(pseries const &other)
 {
-    debugmsg("series copy constructor", LOGLEVEL_CONSTRUCT);
+    debugmsg("pseries copy constructor", LOGLEVEL_CONSTRUCT);
     copy(other);
 }
 
-series const &series::operator=(series const & other)
+pseries const &pseries::operator=(pseries const & other)
 {
-    debugmsg("series operator=", LOGLEVEL_ASSIGNMENT);
+    debugmsg("pseries operator=", LOGLEVEL_ASSIGNMENT);
     if (this != &other) {
         destroy(true);
         copy(other);
@@ -66,7 +70,7 @@ series const &series::operator=(series const & other)
     return *this;
 }
 
-void series::copy(series const &other)
+void pseries::copy(pseries const &other)
 {
     inherited::copy(other);
     seq = other.seq;
@@ -74,7 +78,7 @@ void series::copy(series const &other)
     point = other.point;
 }
 
-void series::destroy(bool call_parent)
+void pseries::destroy(bool call_parent)
 {
     if (call_parent)
         inherited::destroy(call_parent);
@@ -85,7 +89,7 @@ void series::destroy(bool call_parent)
  *  Other constructors
  */
 
-/** Construct series from a vector of coefficients and powers.
+/** Construct pseries from a vector of coefficients and powers.
  *  expair.rest holds the coefficient, expair.coeff holds the power.
  *  The powers must be integers (positive or negative) and in ascending order;
  *  the last coefficient can be Order(_ex1()) to represent a truncated,
@@ -94,43 +98,83 @@ void series::destroy(bool call_parent)
  *  @param var_  series variable (must hold a symbol)
  *  @param point_  expansion point
  *  @param ops_  vector of {coefficient, power} pairs (coefficient must not be zero)
- *  @return newly constructed series */
-series::series(ex const &var_, ex const &point_, epvector const &ops_)
-    : basic(TINFO_series), seq(ops_), var(var_), point(point_)
+ *  @return newly constructed pseries */
+pseries::pseries(ex const &var_, ex const &point_, epvector const &ops_)
+    : basic(TINFO_pseries), seq(ops_), var(var_), point(point_)
 {
-    debugmsg("series constructor from ex,ex,epvector", LOGLEVEL_CONSTRUCT);
+    debugmsg("pseries constructor from ex,ex,epvector", LOGLEVEL_CONSTRUCT);
     GINAC_ASSERT(is_ex_exactly_of_type(var_, symbol));
 }
 
 
+/*
+ *  Archiving
+ */
+
+/** Construct object from archive_node. */
+pseries::pseries(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
+{
+    debugmsg("pseries constructor from archive_node", LOGLEVEL_CONSTRUCT);
+    for (unsigned int i=0; true; i++) {
+        ex rest;
+        ex coeff;
+        if (n.find_ex("coeff", rest, sym_lst, i) && n.find_ex("power", coeff, sym_lst, i))
+            seq.push_back(expair(rest, coeff));
+        else
+            break;
+    }
+    n.find_ex("var", var, sym_lst);
+    n.find_ex("point", point, sym_lst);
+}
+
+/** Unarchive the object. */
+ex pseries::unarchive(const archive_node &n, const lst &sym_lst)
+{
+    return (new pseries(n, sym_lst))->setflag(status_flags::dynallocated);
+}
+
+/** Archive the object. */
+void pseries::archive(archive_node &n) const
+{
+    inherited::archive(n);
+    epvector::const_iterator i = seq.begin(), iend = seq.end();
+    while (i != iend) {
+        n.add_ex("coeff", i->rest);
+        n.add_ex("power", i->coeff);
+        i++;
+    }
+    n.add_ex("var", var);
+    n.add_ex("point", point);
+}
+
+
 /*
  *  Functions overriding virtual functions from base classes
  */
 
-basic *series::duplicate() const
+basic *pseries::duplicate() const
 {
-    debugmsg("series duplicate", LOGLEVEL_DUPLICATE);
-    return new series(*this);
+    debugmsg("pseries duplicate", LOGLEVEL_DUPLICATE);
+    return new pseries(*this);
 }
 
-void series::print(ostream &os, unsigned upper_precedence) const
+void pseries::print(ostream &os, unsigned upper_precedence) const
 {
        debugmsg("symbol print", LOGLEVEL_PRINT);
        convert_to_poly().print(os, upper_precedence);
 }
 
-void series::printraw(ostream &os) const
+void pseries::printraw(ostream &os) const
 {
        debugmsg("symbol printraw", LOGLEVEL_PRINT);
-       os << "series(" << var << ";" << point << ";";
+       os << "pseries(" << var << ";" << point << ";";
        for (epvector::const_iterator i=seq.begin(); i!=seq.end(); i++) {
                os << "(" << (*i).rest << "," << (*i).coeff << "),";
        }
        os << ")";
 }
 
-// Highest degree of variable
-int series::degree(symbol const &s) const
+int pseries::degree(symbol const &s) const
 {
     if (var.is_equal(s)) {
         // Return last exponent
@@ -153,8 +197,7 @@ int series::degree(symbol const &s) const
     }
 }
 
-// Lowest degree of variable
-int series::ldegree(symbol const &s) const
+int pseries::ldegree(symbol const &s) const
 {
     if (var.is_equal(s)) {
         // Return first exponent
@@ -177,8 +220,7 @@ int series::ldegree(symbol const &s) const
     }
 }
 
-// Coefficient of variable
-ex series::coeff(symbol const &s, int const n) const
+ex pseries::coeff(symbol const &s, int const n) const
 {
     if (var.is_equal(s)) {
         epvector::const_iterator it = seq.begin(), itend = seq.end();
@@ -195,7 +237,7 @@ ex series::coeff(symbol const &s, int const n) const
         return convert_to_poly().coeff(s, n);
 }
 
-ex series::eval(int level) const
+ex pseries::eval(int level) const
 {
     if (level == 1)
         return this->hold();
@@ -208,23 +250,44 @@ ex series::eval(int level) const
         new_seq.push_back(expair(it->rest.eval(level-1), it->coeff));
         it++;
     }
-    return (new series(var, point, new_seq))->setflag(status_flags::dynallocated | status_flags::evaluated);
+    return (new pseries(var, point, new_seq))->setflag(status_flags::dynallocated | status_flags::evaluated);
 }
 
 /** Evaluate numerically.  The order term is dropped. */
-ex series::evalf(int level) const
+ex pseries::evalf(int level) const
 {
     return convert_to_poly().evalf(level);
 }
 
+ex pseries::subs(lst const & ls, lst const & lr) const
+{
+       // If expansion variable is being substituted, convert the series to a
+       // polynomial and do the substitution there because the result might
+       // no longer be a power series
+       if (ls.has(var))
+               return convert_to_poly(true).subs(ls, lr);
+
+       // Otherwise construct a new series with substituted coefficients and
+       // expansion point
+       epvector new_seq;
+       new_seq.reserve(seq.size());
+       epvector::const_iterator it = seq.begin(), itend = seq.end();
+       while (it != itend) {
+               new_seq.push_back(expair(it->rest.subs(ls, lr), it->coeff));
+               it++;
+       }
+    return (new pseries(var, point.subs(ls, lr), new_seq))->setflag(status_flags::dynallocated);
+}
+
+
 /*
- *  Construct expression (polynomial) out of series
+ *  Construct ordinary polynomial out of series
  */
 
-/** Convert a series object to an ordinary polynomial.
+/** Convert a pseries object to an ordinary polynomial.
  *
  *  @param no_order flag: discard higher order terms */
-ex series::convert_to_poly(bool no_order) const
+ex pseries::convert_to_poly(bool no_order) const
 {
     ex e;
     epvector::const_iterator it = seq.begin(), itend = seq.end();
@@ -262,7 +325,7 @@ ex basic::series(symbol const & s, ex const & point, int order) const
         deriv = deriv.diff(s).expand();
         if (deriv.is_zero()) {
             // Series terminates
-            return series::series(s, point, seq);
+            return pseries(s, point, seq);
         }
         coeff = fac.inverse() * deriv.subs(s == point);
         if (!coeff.is_zero())
@@ -273,23 +336,41 @@ ex basic::series(symbol const & s, ex const & point, int order) const
     deriv = deriv.diff(s);
     if (!deriv.is_zero())
         seq.push_back(expair(Order(_ex1()), numeric(n)));
-    return series::series(s, point, seq);
+    return pseries(s, point, seq);
 }
 
 
-/** Add one series object to another, producing a series object that represents
+/** Implementation of ex::series() for symbols.
+ *  @see ex::series */
+ex symbol::series(symbol const & s, ex const & point, int order) const
+{
+       epvector seq;
+       if (is_equal(s)) {
+               if (order > 0 && !point.is_zero())
+                       seq.push_back(expair(point, _ex0()));
+               if (order > 1)
+                       seq.push_back(expair(_ex1(), _ex1()));
+               else
+                       seq.push_back(expair(Order(_ex1()), numeric(order)));
+       } else
+               seq.push_back(expair(*this, _ex0()));
+       return pseries(s, point, seq);
+}
+
+
+/** Add one series object to another, producing a pseries object that represents
  *  the sum.
  *
- *  @param other  series object to add with
- *  @return the sum as a series */
-ex series::add_series(const series &other) const
+ *  @param other  pseries object to add with
+ *  @return the sum as a pseries */
+ex pseries::add_series(const pseries &other) const
 {
     // Adding two series with different variables or expansion points
     // results in an empty (constant) series 
     if (!is_compatible_to(other)) {
         epvector nul;
         nul.push_back(expair(Order(_ex1()), _ex0()));
-        return series(var, point, nul);
+        return pseries(var, point, nul);
     }
     
     // Series addition
@@ -347,79 +428,45 @@ ex series::add_series(const series &other) const
             }
         }
     }
-    return series(var, point, new_seq);
+    return pseries(var, point, new_seq);
 }
 
 
 /** Implementation of ex::series() for sums. This performs series addition when
- *  adding series objects.
+ *  adding pseries objects.
  *  @see ex::series */
-/*
-ex add::series(symbol const & s, ex const & point, int order) const
-{
-    ex acc; // Series accumulator
-
-    // Get first term
-    epvector::const_iterator it = seq.begin();
-    epvector::const_iterator itend = seq.end();
-    if (it != itend) {
-        if (is_ex_exactly_of_type(it->rest, series))
-            acc = it->rest;
-        else
-            acc = it->rest.series(s, point, order);
-        if (!it->coeff.is_equal(_ex1()))
-            acc = ex_to_series(acc).mul_const(ex_to_numeric(it->coeff));
-        it++;
-    }
-
-    // Add remaining terms
-    for (; it!=itend; it++) {
-        ex op;
-        if (is_ex_exactly_of_type(it->rest, series))
-            op = it->rest;
-        else
-            op = it->rest.series(s, point, order);
-        if (!it->coeff.is_equal(_ex1()))
-            op = ex_to_series(op).mul_const(ex_to_numeric(it->coeff));
-
-        // Series addition
-        acc = ex_to_series(acc).add_series(ex_to_series(op));
-    }
-    return acc;
-}
-*/
 ex add::series(symbol const & s, ex const & point, int order) const
 {
     ex acc; // Series accumulator
     
     // Get first term from overall_coeff
-    acc = overall_coeff.series(s,point,order);
-    
+    acc = overall_coeff.series(s, point, order);
+
     // Add remaining terms
     epvector::const_iterator it = seq.begin();
     epvector::const_iterator itend = seq.end();
     for (; it!=itend; it++) {
         ex op;
-        if (is_ex_exactly_of_type(it->rest, series))
+        if (is_ex_exactly_of_type(it->rest, pseries))
             op = it->rest;
         else
             op = it->rest.series(s, point, order);
         if (!it->coeff.is_equal(_ex1()))
-            op = ex_to_series(op).mul_const(ex_to_numeric(it->coeff));
+            op = ex_to_pseries(op).mul_const(ex_to_numeric(it->coeff));
         
         // Series addition
-        acc = ex_to_series(acc).add_series(ex_to_series(op));
+        acc = ex_to_pseries(acc).add_series(ex_to_pseries(op));
     }
     return acc;
 }
 
 
-/** Multiply a series object with a numeric constant, producing a series object
+/** Multiply a pseries object with a numeric constant, producing a pseries object
  *  that represents the product.
  *
  *  @param other  constant to multiply with
- *  @return the product as a series */
-ex series::mul_const(const numeric &other) const
+ *  @return the product as a pseries */
+ex pseries::mul_const(const numeric &other) const
 {
     epvector new_seq;
     new_seq.reserve(seq.size());
@@ -432,23 +479,23 @@ ex series::mul_const(const numeric &other) const
             new_seq.push_back(*it);
         it++;
     }
-    return series(var, point, new_seq);
+    return pseries(var, point, new_seq);
 }
 
 
-/** Multiply one series object to another, producing a series object that
+/** Multiply one pseries object to another, producing a pseries object that
  *  represents the product.
  *
- *  @param other  series object to multiply with
- *  @return the product as a series */
-ex series::mul_series(const series &other) const
+ *  @param other  pseries object to multiply with
+ *  @return the product as a pseries */
+ex pseries::mul_series(const pseries &other) const
 {
     // Multiplying two series with different variables or expansion points
     // results in an empty (constant) series 
     if (!is_compatible_to(other)) {
         epvector nul;
         nul.push_back(expair(Order(_ex1()), _ex0()));
-        return series(var, point, nul);
+        return pseries(var, point, nul);
     }
 
     // Series multiplication
@@ -486,48 +533,10 @@ ex series::mul_series(const series &other) const
     }
     if (higher_order_c < INT_MAX)
         new_seq.push_back(expair(Order(_ex1()), numeric(higher_order_c)));
-    return series::series(var, point, new_seq);
+    return pseries(var, point, new_seq);
 }
 
 
-/*
-ex mul::series(symbol const & s, ex const & point, int order) const
-{
-    ex acc; // Series accumulator
-
-    // Get first term
-    epvector::const_iterator it = seq.begin();
-    epvector::const_iterator itend = seq.end();
-    if (it != itend) {
-        if (is_ex_exactly_of_type(it->rest, series))
-            acc = it->rest;
-        else
-            acc = it->rest.series(s, point, order);
-        if (!it->coeff.is_equal(_ex1()))
-            acc = ex_to_series(acc).power_const(ex_to_numeric(it->coeff), order);
-        it++;
-    }
-
-    // Multiply with remaining terms
-    for (; it!=itend; it++) {
-        ex op = it->rest;
-        if (op.info(info_flags::numeric)) {
-            // series * const (special case, faster)
-            ex f = power(op, it->coeff);
-            acc = ex_to_series(acc).mul_const(ex_to_numeric(f));
-            continue;
-        } else if (!is_ex_exactly_of_type(op, series))
-            op = op.series(s, point, order);
-        if (!it->coeff.is_equal(_ex1()))
-            op = ex_to_series(op).power_const(ex_to_numeric(it->coeff), order);
-
-        // Series multiplication
-        acc = ex_to_series(acc).mul_series(ex_to_series(op));
-    }
-    return acc;
-}
-*/
-
 /** Implementation of ex::series() for product. This performs series
  *  multiplication when multiplying series.
  *  @see ex::series */
@@ -546,15 +555,15 @@ ex mul::series(symbol const & s, ex const & point, int order) const
         if (op.info(info_flags::numeric)) {
             // series * const (special case, faster)
             ex f = power(op, it->coeff);
-            acc = ex_to_series(acc).mul_const(ex_to_numeric(f));
+            acc = ex_to_pseries(acc).mul_const(ex_to_numeric(f));
             continue;
-        } else if (!is_ex_exactly_of_type(op, series))
+        } else if (!is_ex_exactly_of_type(op, pseries))
             op = op.series(s, point, order);
         if (!it->coeff.is_equal(_ex1()))
-            op = ex_to_series(op).power_const(ex_to_numeric(it->coeff), order);
+            op = ex_to_pseries(op).power_const(ex_to_numeric(it->coeff), order);
 
         // Series multiplication
-        acc = ex_to_series(acc).mul_series(ex_to_series(op));
+        acc = ex_to_pseries(acc).mul_series(ex_to_pseries(op));
     }
     return acc;
 }
@@ -564,7 +573,7 @@ ex mul::series(symbol const & s, ex const & point, int order) const
  *
  *  @param p  power to compute
  *  @param deg  truncation order of series calculation */
-ex series::power_const(const numeric &p, int deg) const
+ex pseries::power_const(const numeric &p, int deg) const
 {
     int i;
     const symbol *s = static_cast<symbol *>(var.bp);
@@ -604,7 +613,7 @@ ex series::power_const(const numeric &p, int deg) const
     }
     if (!higher_order && !all_sums_zero)
         new_seq.push_back(expair(Order(_ex1()), numeric(deg) + p * ldeg));
-    return series::series(var, point, new_seq);
+    return pseries(var, point, new_seq);
 }
 
 
@@ -614,7 +623,7 @@ ex series::power_const(const numeric &p, int deg) const
 ex power::series(symbol const & s, ex const & point, int order) const
 {
     ex e;
-    if (!is_ex_exactly_of_type(basis, series)) {
+    if (!is_ex_exactly_of_type(basis, pseries)) {
         // Basis is not a series, may there be a singulary?
         if (!exponent.info(info_flags::negint))
             return basic::series(s, point, order);
@@ -631,19 +640,19 @@ ex power::series(symbol const & s, ex const & point, int order) const
     }
     
     // Power e
-    return ex_to_series(e).power_const(ex_to_numeric(exponent), order);
+    return ex_to_pseries(e).power_const(ex_to_numeric(exponent), order);
 }
 
 
 /** Compute the truncated series expansion of an expression.
- *  This function returns an expression containing an object of class series to
+ *  This function returns an expression containing an object of class pseries to
  *  represent the series. If the series does not terminate within the given
  *  truncation order, the last term of the series will be an order term.
  *
  *  @param s  expansion variable
  *  @param point  expansion point
  *  @param order  truncation order of series calculations
- *  @return an expression holding a series object */
+ *  @return an expression holding a pseries object */
 ex ex::series(symbol const &s, ex const &point, int order) const
 {
     GINAC_ASSERT(bp!=0);
@@ -652,8 +661,8 @@ ex ex::series(symbol const &s, ex const &point, int order) const
 
 
 // Global constants
-const series some_series;
-type_info const & typeid_series = typeid(some_series);
+const pseries some_pseries;
+type_info const & typeid_pseries = typeid(some_pseries);
 
 #ifndef NO_GINAC_NAMESPACE
 } // namespace GiNaC
similarity index 72%
rename from ginac/series.h
rename to ginac/pseries.h
index 5bf8143..8f041d3 100644 (file)
@@ -1,4 +1,4 @@
-/** @file series.h
+/** @file pseries.h
  *
  *  Interface to class for extended truncated power series. */
 
@@ -34,23 +34,23 @@ namespace GiNaC {
  *  integer powers). It consists of expression coefficients (only non-zero
  *  coefficients are stored), an expansion variable and an expansion point.
  *  Other classes must provide members to convert into this type. */
-class series : public basic
+class pseries : public basic
 {
-    typedef basic inherited;
+    GINAC_DECLARE_REGISTERED_CLASS(pseries, basic)
 
     // default constructor, destructor, copy constructor, assignment operator and helpers
 public:
-    series();
-    ~series();
-    series(series const &other);
-    series const &operator=(series const &other);
+    pseries();
+    ~pseries();
+    pseries(pseries const &other);
+    pseries const &operator=(pseries const &other);
 protected:
-    void copy(series const &other);
+    void copy(pseries const &other);
     void destroy(bool call_parent);
 
     // other constructors
 public:
-    series(ex const &var_, ex const &point_, epvector const &ops_);
+    pseries(ex const &var_, ex const &point_, epvector const &ops_);
 
     // functions overriding virtual functions from base classes
 public:
@@ -62,17 +62,18 @@ public:
     ex coeff(symbol const &s, int const n=1) const;
     ex eval(int level=0) const;
     ex evalf(int level=0) const;
-    ex diff(symbol const & s) const;
     ex normal(lst &sym_lst, lst &repl_lst, int level=0) const;
+    ex diff(symbol const & s) const;
+    ex subs(lst const & ls, lst const & lr) const;
 
     // non-virtual functions in this class
 public:
     ex convert_to_poly(bool no_order = false) const;
-    bool is_compatible_to(const series &other) const {return var.compare(other.var) == 0 && point.compare(other.point) == 0;}
+    bool is_compatible_to(const pseries &other) const {return var.compare(other.var) == 0 && point.compare(other.point) == 0;}
     bool is_zero(void) const {return seq.size() == 0;}
-    ex add_series(const series &other) const;
+    ex add_series(const pseries &other) const;
     ex mul_const(const numeric &other) const;
-    ex mul_series(const series &other) const;
+    ex mul_series(const pseries &other) const;
     ex power_const(const numeric &p, int deg) const;
 
 protected:
@@ -87,32 +88,32 @@ protected:
 };
 
 // global constants
-extern const series some_series;
-extern type_info const & typeid_series;
+extern const pseries some_pseries;
+extern type_info const & typeid_pseries;
 
-/** Return a reference to the series object embedded in an expression.
- *  The result is undefined if the expression does not contain a series
+/** Return a reference to the pseries object embedded in an expression.
+ *  The result is undefined if the expression does not contain a pseries
  *  object at its top level.
  *
  *  @param e expression
- *  @return reference to series object
+ *  @return reference to pseries object
  *  @see is_ex_of_type */
-inline const series &ex_to_series(const ex &e)
+inline const pseries &ex_to_pseries(const ex &e)
 {
-       return static_cast<const series &>(*e.bp);
+       return static_cast<const pseries &>(*e.bp);
 }
 
-/** Convert the series object embedded in an expression to an ordinary
+/** Convert the pseries object embedded in an expression to an ordinary
  *  polynomial in the expansion variable. The result is undefined if the
- *  expression does not contain a series object at its top level.
+ *  expression does not contain a pseries object at its top level.
  *
  *  @param e expression
  *  @return polynomial expression
  *  @see is_ex_of_type
- *  @see series::convert_to_poly */
+ *  @see pseries::convert_to_poly */
 inline ex series_to_poly(const ex &e)
 {
-       return (static_cast<const series &>(*e.bp).convert_to_poly(true));
+       return (static_cast<const pseries &>(*e.bp).convert_to_poly(true));
 }
 
 #ifndef NO_GINAC_NAMESPACE
diff --git a/ginac/registrar.cpp b/ginac/registrar.cpp
new file mode 100644 (file)
index 0000000..fc54830
--- /dev/null
@@ -0,0 +1,61 @@
+/** @file registrar.cpp
+ *
+ *  GiNaC's class registrar (for class basic and all classes derived from it). */
+
+/*
+ *  GiNaC Copyright (C) 1999-2000 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 <string>
+#include <stdexcept>
+
+#include "registrar.h"
+
+#ifndef NO_GINAC_NAMESPACE
+namespace GiNaC {
+#endif // ndef NO_GINAC_NAMESPACE
+
+registered_class_info *first_registered_class = NULL;
+
+/** Find registered_class_info strucure by class name. */
+static inline registered_class_info *find_registered_class_info(const string &class_name)
+{
+       registered_class_info *p = first_registered_class;
+       while (p) {
+               if (class_name == p->name)
+                       return p;
+               p = p->next;
+       }
+       throw (std::runtime_error("class '" + class_name + "' not registered"));
+}
+
+unsigned int find_tinfo_key(const string &class_name)
+{
+       registered_class_info *p = find_registered_class_info(class_name);
+       return p->tinfo_key;
+}
+
+unarch_func find_unarch_func(const string &class_name)
+{
+       registered_class_info *p = find_registered_class_info(class_name);
+       return p->unarchive;
+}
+
+
+#ifndef NO_GINAC_NAMESPACE
+} // namespace GiNaC
+#endif // ndef NO_GINAC_NAMESPACE
diff --git a/ginac/registrar.h b/ginac/registrar.h
new file mode 100644 (file)
index 0000000..463328d
--- /dev/null
@@ -0,0 +1,97 @@
+/** @file registrar.h
+ *
+ *  GiNaC's class registrar (for class basic and all classes derived from it). */
+
+/*
+ *  GiNaC Copyright (C) 1999-2000 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_REGISTRAR_H__
+#define __GINAC_REGISTRAR_H__
+
+#include <string>
+
+#ifndef NO_GINAC_NAMESPACE
+namespace GiNaC {
+#endif // ndef NO_GINAC_NAMESPACE
+
+class registered_class_info;
+class ex;
+class archive_node;
+class lst;
+
+
+/** Unarchiving function (static member function of every GiNaC class). */
+typedef ex (*unarch_func)(const archive_node &n, const lst &sym_lst);
+
+
+/** Head of list of all registered_class_info structures. */
+extern registered_class_info *first_registered_class;
+
+
+/** This structure stores information about a registered GiNaC class. */
+struct registered_class_info {
+    registered_class_info(const char *n, const char *s, unsigned int k, unarch_func f)
+        : name(n), super(s), tinfo_key(k), unarchive(f)
+    {
+        // Add structure to list
+        next = first_registered_class;
+        first_registered_class = this;
+    }
+
+    registered_class_info *next;       /**< Pointer to next registered_class_info in list. */
+    const char *name;                          /**< Class name. */
+    const char *super;                         /**< Name of superclass. */
+    unsigned int tinfo_key;                    /**< TINFO_* key. */
+    unarch_func unarchive;                     /**< Pointer to unarchiving function. */
+};
+
+
+/** Macro for inclusion in the declaration of each registered class. */
+#define GINAC_DECLARE_REGISTERED_CLASS(classname, supername) \
+public: \
+    typedef supername inherited; \
+\
+       /** This structure stores information about the class. */ \
+    static registered_class_info reg_info; \
+\
+       /** Return pointer to class name. */ \
+    virtual const char *class_name(void) const; \
+\
+    classname(const archive_node &n, const lst &sym_lst); \
+    virtual void archive(archive_node &n) const; \
+    static ex unarchive(const archive_node &n, const lst &sym_lst); \
+private:
+
+/** Macro for inclusion in the implementation of each registered class. */
+#define GINAC_IMPLEMENT_REGISTERED_CLASS(classname, supername) \
+    registered_class_info classname::reg_info(#classname, #supername, TINFO_##classname, &classname::unarchive); \
+    const char *classname::class_name(void) const {return reg_info.name;}
+
+
+/** Find TINFO_* key by class name. */
+extern unsigned int find_tinfo_key(const string &class_name);
+
+/** Find unarchiving function by class name. */
+extern unarch_func find_unarch_func(const string &class_name);
+
+
+#ifndef NO_GINAC_NAMESPACE
+} // namespace GiNaC
+#endif // ndef NO_GINAC_NAMESPACE
+
+#endif // ndef __GINAC_REGISTRAR_H__
index 5784c35..d854e47 100644 (file)
 
 #include "relational.h"
 #include "numeric.h"
-#include "debugmsg.h"
+#include "archive.h"
 #include "utils.h"
+#include "debugmsg.h"
 
 #ifndef NO_GINAC_NAMESPACE
 namespace GiNaC {
 #endif // ndef NO_GINAC_NAMESPACE
 
+GINAC_IMPLEMENT_REGISTERED_CLASS(relational, basic)
+
 //////////
 // default constructor, destructor, copy constructor assignment operator and helpers
 //////////
@@ -93,6 +96,37 @@ relational::relational(ex const & lhs, ex const & rhs, operators oper) : basic(T
     o=oper;
 }
 
+//////////
+// archiving
+//////////
+
+/** Construct object from archive_node. */
+relational::relational(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
+{
+    debugmsg("relational constructor from archive_node", LOGLEVEL_CONSTRUCT);
+    unsigned int opi;
+    if (!(n.find_unsigned("op", opi)))
+        throw (std::runtime_error("unknown relational operator in archive"));
+    o = (operators)opi;
+    n.find_ex("lh", lh, sym_lst);
+    n.find_ex("rh", rh, sym_lst);
+}
+
+/** Unarchive the object. */
+ex relational::unarchive(const archive_node &n, const lst &sym_lst)
+{
+    return (new relational(n, sym_lst))->setflag(status_flags::dynallocated);
+}
+
+/** Archive the object. */
+void relational::archive(archive_node &n) const
+{
+    inherited::archive(n);
+    n.add_ex("lh", lh);
+    n.add_ex("rh", rh);
+    n.add_unsigned("op", o);
+}
+
 //////////
 // functions overriding virtual functions from bases classes
 //////////
index 25a05c4..80d255e 100644 (file)
@@ -34,6 +34,7 @@ namespace GiNaC {
  *  relation between them. */
 class relational : public basic
 {
+    GINAC_DECLARE_REGISTERED_CLASS(relational, basic)
 
 // types
 public:
index 2fa8907..bf73ccf 100644 (file)
 
 #include "symbol.h"
 #include "lst.h"
-#include "utils.h"
 #include "idx.h"
+#include "archive.h"
 #include "debugmsg.h"
+#include "utils.h"
 
 #ifndef NO_GINAC_NAMESPACE
 namespace GiNaC {
 #endif // ndef NO_GINAC_NAMESPACE
 
+GINAC_IMPLEMENT_REGISTERED_CLASS(symbol, basic)
+
 //////////
 // default constructor, destructor, copy constructor assignment operator and helpers
 //////////
 
-symbol::symbol() : basic(TINFO_symbol)
+symbol::symbol() : inherited(TINFO_symbol)
 {
-    debugmsg("symbol default constructor",LOGLEVEL_CONSTRUCT);
+    debugmsg("symbol default constructor", LOGLEVEL_CONSTRUCT);
     serial=next_serial++;
     name=autoname_prefix()+ToString(serial);
     asexinfop=new assigned_ex_info;
@@ -48,19 +51,19 @@ symbol::symbol() : basic(TINFO_symbol)
 
 symbol::~symbol()
 {
-    debugmsg("symbol destructor",LOGLEVEL_DESTRUCT);
+    debugmsg("symbol destructor", LOGLEVEL_DESTRUCT);
     destroy(0);
 }
 
 symbol::symbol(symbol const & other)
 {
-    debugmsg("symbol copy constructor",LOGLEVEL_CONSTRUCT);
+    debugmsg("symbol copy constructor", LOGLEVEL_CONSTRUCT);
     copy(other);
 }
 
 void symbol::copy(symbol const & other)
 {
-    basic::copy(other);
+    inherited::copy(other);
     name=other.name;
     serial=other.serial;
     asexinfop=other.asexinfop;
@@ -73,7 +76,7 @@ void symbol::destroy(bool call_parent)
         delete asexinfop;
     }
     if (call_parent) {
-        basic::destroy(call_parent);
+        inherited::destroy(call_parent);
     }
 }
 
@@ -89,24 +92,59 @@ void symbol::destroy(bool call_parent)
 
 // public
 
-symbol::symbol(string const & initname) : basic(TINFO_symbol)
+symbol::symbol(string const & initname) : inherited(TINFO_symbol)
 {
-    debugmsg("symbol constructor from string",LOGLEVEL_CONSTRUCT);
+    debugmsg("symbol constructor from string", LOGLEVEL_CONSTRUCT);
     name=initname;
     serial=next_serial++;
     asexinfop=new assigned_ex_info;
     setflag(status_flags::evaluated);
 }
 
+//////////
+// archiving
+//////////
+
+/** Construct object from archive_node. */
+symbol::symbol(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
+{
+    debugmsg("symbol constructor from archive_node", LOGLEVEL_CONSTRUCT);
+    serial = next_serial++;
+    if (!(n.find_string("name", name)))
+        name = autoname_prefix() + ToString(serial);
+    asexinfop = new assigned_ex_info;
+    setflag(status_flags::evaluated);
+}
+
+/** Unarchive the object. */
+ex symbol::unarchive(const archive_node &n, const lst &sym_lst)
+{
+    ex s = (new symbol(n, sym_lst))->setflag(status_flags::dynallocated);
+
+    // If symbol is in sym_lst, return the existing symbol
+    for (int i=0; i<sym_lst.nops(); i++) {
+        if (is_ex_of_type(sym_lst.op(i), symbol) && (ex_to_symbol(sym_lst.op(i)).name == ex_to_symbol(s).name))
+            return sym_lst.op(i);
+    }
+    return s;
+}
+
+/** Archive the object. */
+void symbol::archive(archive_node &n) const
+{
+    inherited::archive(n);
+    n.add_string("name", name);
+}
+
 //////////
 // functions overriding virtual functions from bases classes
 //////////
 
 // public
 
-basic * symbol::duplicate() const
+basic *symbol::duplicate() const
 {
-    debugmsg("symbol duplicate",LOGLEVEL_DUPLICATE);
+    debugmsg("symbol duplicate", LOGLEVEL_DUPLICATE);
     return new symbol(*this);
 }
 
@@ -149,7 +187,7 @@ bool symbol::info(unsigned inf) const
         inf==info_flags::rational_function) {
         return true;
     } else {
-        return basic::info(inf);
+        return inherited::info(inf);
     }
 }
 
index 7ed972a..d633a47 100644 (file)
@@ -39,7 +39,10 @@ namespace GiNaC {
  *  first place. */
 class symbol : public basic
 {
+    GINAC_DECLARE_REGISTERED_CLASS(symbol, basic)
+
 // types
+
     /** Symbols as keys to expressions. */
     class assigned_ex_info {
     public:
@@ -79,6 +82,7 @@ public:
     ex coeff(symbol const & s, int const n = 1) const;
     ex eval(int level = 0) const;
     ex diff(symbol const & s) const;
+    ex series(symbol const & s, ex const & point, int order) const;
     ex normal(lst &sym_lst, lst &repl_lst, int level=0) const;
     ex subs(lst const & ls, lst const & lr) const;
 protected:
index 93d46c8..b60ce4b 100644 (file)
@@ -52,7 +52,7 @@ const unsigned TINFO_fail         = 0x00080001U;
 
 const unsigned TINFO_numeric      = 0x00090001U;
 
-const unsigned TINFO_series       = 0x000a0001U;
+const unsigned TINFO_pseries      = 0x000a0001U;
 
 const unsigned TINFO_indexed      = 0x000b0001U;
 const unsigned TINFO_algebra      = 0x000b1001U;