From: Christian Bauer Date: Wed, 19 Jan 2000 22:46:56 +0000 (+0000) Subject: - implemented global class registry (for class basic and derived classes) X-Git-Tag: release_0-5-0~61 X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?a=commitdiff_plain;h=0a1b35cf1e59c9e3aae33de8febaa1c8f4bbe630;p=ginac.git - implemented global class registry (for class basic and derived classes) - 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 --- diff --git a/ginac/Makefile.am b/ginac/Makefile.am index 1d165809..1035e836 100644 --- a/ginac/Makefile.am +++ b/ginac/Makefile.am @@ -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 diff --git a/ginac/Makefile.in b/ginac/Makefile.in index bffdd528..12b11d08 100644 --- a/ginac/Makefile.in +++ b/ginac/Makefile.in @@ -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 \ diff --git a/ginac/add.cpp b/ginac/add.cpp index 8700ce6e..ab05def2 100644 --- a/ginac/add.cpp +++ b/ginac/add.cpp @@ -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 diff --git a/ginac/add.h b/ginac/add.h index d2d4d769..d4da3bea 100644 --- a/ginac/add.h +++ b/ginac/add.h @@ -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 index 00000000..dfc00cee --- /dev/null +++ b/ginac/archive.cpp @@ -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 +#include + +#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::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::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>(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>(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> 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::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::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::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::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::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::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::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::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::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::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 << ""; 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 index 00000000..a2db1666 --- /dev/null +++ b/ginac/archive.h @@ -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 + +#include +#include + +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 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 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 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 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__ diff --git a/ginac/basic.cpp b/ginac/basic.cpp index a8f2baa0..b632a6e3 100644 --- a/ginac/basic.cpp +++ b/ginac/basic.cpp @@ -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 ////////// diff --git a/ginac/basic.h b/ginac/basic.h index 242bd456..ecf120a1 100644 --- a/ginac/basic.h +++ b/ginac/basic.h @@ -33,6 +33,7 @@ #include #include #include +#include #ifndef NO_GINAC_NAMESPACE namespace GiNaC { @@ -43,6 +44,7 @@ class ex; class symbol; class lst; class numeric; +class archive_node; //typedef vector exvector; typedef vector exvector; // CINT does not like vector<...,default_alloc> @@ -53,6 +55,8 @@ typedef vector 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__ - diff --git a/ginac/constant.cpp b/ginac/constant.cpp index fa7adf24..1e9a4c15 100644 --- a/ginac/constant.cpp +++ b/ginac/constant.cpp @@ -26,12 +26,15 @@ #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 ////////// diff --git a/ginac/constant.h b/ginac/constant.h index 99cbe999..2e6ad5b0 100644 --- a/ginac/constant.h +++ b/ginac/constant.h @@ -38,6 +38,7 @@ typedef ex (*evalffunctype)(void); * number). */ class constant : public basic { + GINAC_DECLARE_REGISTERED_CLASS(constant, basic) // member functions diff --git a/ginac/container.pl b/ginac/container.pl index 5979038d..c9ff5e4f 100755 --- a/ginac/container.pl +++ b/ginac/container.pl @@ -139,6 +139,7 @@ typedef ${STLHEADER} ${STLT}; // CINT does not like ${STLHEADER class ${CONTAINER} : public basic { + GINAC_DECLARE_REGISTERED_CLASS(${CONTAINER}, basic) public: ${CONTAINER}(); @@ -276,12 +277,15 @@ $implementation=<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 ////////// diff --git a/ginac/diff.cpp b/ginac/diff.cpp index afbbedab..c3bd2395 100644 --- a/ginac/diff.cpp +++ b/ginac/diff.cpp @@ -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; } diff --git a/ginac/ex.h b/ginac/ex.h index 313bd6c7..21a4ea7c 100644 --- a/ginac/ex.h +++ b/ginac/ex.h @@ -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); } diff --git a/ginac/expairseq.cpp b/ginac/expairseq.cpp index 0e867c83..0d4a01c7 100644 --- a/ginac/expairseq.cpp +++ b/ginac/expairseq.cpp @@ -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 diff --git a/ginac/expairseq.h b/ginac/expairseq.h index 6203af3a..d9d7bf05 100644 --- a/ginac/expairseq.h +++ b/ginac/expairseq.h @@ -57,6 +57,8 @@ typedef vector 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 diff --git a/ginac/fail.cpp b/ginac/fail.cpp index 395b1189..9e8d8a6a 100644 --- a/ginac/fail.cpp +++ b/ginac/fail.cpp @@ -22,19 +22,22 @@ */ #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 ////////// diff --git a/ginac/fail.h b/ginac/fail.h index 4dce177f..aa207d4d 100644 --- a/ginac/fail.h +++ b/ginac/fail.h @@ -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: diff --git a/ginac/function.pl b/ginac/function.pl index f08990d9..e2b4374f 100755 --- a/ginac/function.pl +++ b/ginac/function.pl @@ -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=<::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 ////////// diff --git a/ginac/ginac.h b/ginac/ginac.h index 78a8f204..c91d06c4 100644 --- a/ginac/ginac.h +++ b/ginac/ginac.h @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -43,7 +44,7 @@ #include #include #include -#include +#include #include #include diff --git a/ginac/indexed.cpp b/ginac/indexed.cpp index acdd8b00..4eeb2db1 100644 --- a/ginac/indexed.cpp +++ b/ginac/indexed.cpp @@ -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 diff --git a/ginac/indexed.h b/ginac/indexed.h index 6121e020..ce416ff9 100644 --- a/ginac/indexed.h +++ b/ginac/indexed.h @@ -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 diff --git a/ginac/inifcns.cpp b/ginac/inifcns.cpp index a334bfcc..c99e3581 100644 --- a/ginac/inifcns.cpp +++ b/ginac/inifcns.cpp @@ -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); diff --git a/ginac/inifcns_gamma.cpp b/ginac/inifcns_gamma.cpp index cb8699e4..d20a27f2 100644 --- a/ginac/inifcns_gamma.cpp +++ b/ginac/inifcns_gamma.cpp @@ -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" diff --git a/ginac/matrix.cpp b/ginac/matrix.cpp index 156bc9f4..0ed64ef6 100644 --- a/ginac/matrix.cpp +++ b/ginac/matrix.cpp @@ -24,13 +24,16 @@ #include #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 ////////// diff --git a/ginac/matrix.h b/ginac/matrix.h index 1be80d77..3780122f 100644 --- a/ginac/matrix.h +++ b/ginac/matrix.h @@ -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 diff --git a/ginac/mul.cpp b/ginac/mul.cpp index c83acf02..b269836a 100644 --- a/ginac/mul.cpp +++ b/ginac/mul.cpp @@ -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 diff --git a/ginac/mul.h b/ginac/mul.h index 4917b011..8f8e1142 100644 --- a/ginac/mul.h +++ b/ginac/mul.h @@ -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; diff --git a/ginac/ncmul.cpp b/ginac/ncmul.cpp index d3a6883f..d7d97b95 100644 --- a/ginac/ncmul.cpp +++ b/ginac/ncmul.cpp @@ -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 diff --git a/ginac/ncmul.h b/ginac/ncmul.h index 2e229952..10477938 100644 --- a/ginac/ncmul.h +++ b/ginac/ncmul.h @@ -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); diff --git a/ginac/normal.cpp b/ginac/normal.cpp index 0ee26ad5..f0d9c1ab 100644 --- a/ginac/normal.cpp +++ b/ginac/normal.cpp @@ -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); } diff --git a/ginac/numeric.cpp b/ginac/numeric.cpp index c0a2051b..dd6a1ebc 100644 --- a/ginac/numeric.cpp +++ b/ginac/numeric.cpp @@ -26,10 +26,13 @@ #include #include +#include +#include //!! #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) diff --git a/ginac/numeric.h b/ginac/numeric.h index 73ca87f2..71cccb26 100644 --- a/ginac/numeric.h +++ b/ginac/numeric.h @@ -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); diff --git a/ginac/power.cpp b/ginac/power.cpp index 32b6cfa6..ccbf5281 100644 --- a/ginac/power.cpp +++ b/ginac/power.cpp @@ -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 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 diff --git a/ginac/power.h b/ginac/power.h index e721ab2e..4224c199 100644 --- a/ginac/power.h +++ b/ginac/power.h @@ -37,6 +37,8 @@ class add; * representing exponentiation. */ class power : public basic { + GINAC_DECLARE_REGISTERED_CLASS(power, basic) + friend class mul; // member functions diff --git a/ginac/series.cpp b/ginac/pseries.cpp similarity index 70% rename from ginac/series.cpp rename to ginac/pseries.cpp index 1671931f..ff39d24f 100644 --- a/ginac/series.cpp +++ b/ginac/pseries.cpp @@ -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. */ /* @@ -21,44 +21,48 @@ * 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(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 diff --git a/ginac/series.h b/ginac/pseries.h similarity index 72% rename from ginac/series.h rename to ginac/pseries.h index 5bf81435..8f041d38 100644 --- a/ginac/series.h +++ b/ginac/pseries.h @@ -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(*e.bp); + return static_cast(*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(*e.bp).convert_to_poly(true)); + return (static_cast(*e.bp).convert_to_poly(true)); } #ifndef NO_GINAC_NAMESPACE diff --git a/ginac/registrar.cpp b/ginac/registrar.cpp new file mode 100644 index 00000000..fc548302 --- /dev/null +++ b/ginac/registrar.cpp @@ -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 +#include + +#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 index 00000000..463328dd --- /dev/null +++ b/ginac/registrar.h @@ -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 + +#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__ diff --git a/ginac/relational.cpp b/ginac/relational.cpp index 5784c359..d854e47d 100644 --- a/ginac/relational.cpp +++ b/ginac/relational.cpp @@ -24,13 +24,16 @@ #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 ////////// diff --git a/ginac/relational.h b/ginac/relational.h index 25a05c4c..80d255e5 100644 --- a/ginac/relational.h +++ b/ginac/relational.h @@ -34,6 +34,7 @@ namespace GiNaC { * relation between them. */ class relational : public basic { + GINAC_DECLARE_REGISTERED_CLASS(relational, basic) // types public: diff --git a/ginac/symbol.cpp b/ginac/symbol.cpp index 2fa8907f..bf73ccfb 100644 --- a/ginac/symbol.cpp +++ b/ginac/symbol.cpp @@ -25,21 +25,24 @@ #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