## 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
POST_UNINSTALL = :
host_alias = @host_alias@
host_triplet = @host@
+ARCHIVE_AGE = @ARCHIVE_AGE@
+ARCHIVE_VERSION = @ARCHIVE_VERSION@
AS = @AS@
CC = @CC@
CXX = @CXX@
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
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)
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)
@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 \
#include "add.h"
#include "mul.h"
+#include "archive.h"
#include "debugmsg.h"
#include "utils.h"
namespace GiNaC {
#endif // ndef NO_GINAC_NAMESPACE
+GINAC_IMPLEMENT_REGISTERED_CLASS(add, expairseq)
+
//////////
// default constructor, destructor, copy constructor assignment operator and helpers
//////////
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);
}
//////////
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
//////////
}
return overall_coeff.info(inf);
} else {
- return expairseq::info(inf);
+ return inherited::info(inf);
}
}
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);
}
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
/** Sum of expressions. */
class add : public expairseq
{
+ GINAC_DECLARE_REGISTERED_CLASS(add, expairseq)
+
friend class mul;
friend class ncmul;
friend class power;
--- /dev/null
+/** @file archive.cpp
+ *
+ * Archiving of GiNaC expressions. */
+
+/*
+ * GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <iostream>
+#include <stdexcept>
+
+#include "archive.h"
+#include "registrar.h"
+#include "ex.h"
+#include "config.h"
+#include "utils.h"
+
+#ifndef NO_GINAC_NAMESPACE
+namespace GiNaC {
+#endif // ndef NO_GINAC_NAMESPACE
+
+
+/** Archive an expression.
+ * @param ex the expression to be archived
+ * @param name name under which the expression is stored */
+void archive::archive_ex(const ex &e, const char *name)
+{
+ // Create root node (which recursively archives the whole expression tree)
+ // and add it to the archive
+ archive_node_id id = add_node(archive_node(*this, e));
+
+ // Add root node ID to list of archived expressions
+ archived_ex ae = archived_ex(atomize(name), id);
+ exprs.push_back(ae);
+}
+
+
+/** Add archive_node to archive if the corresponding expression is
+ * not already archived.
+ * @return ID of archived node */
+archive_node_id archive::add_node(const archive_node &n)
+{
+ // Search for node in nodes vector
+ vector<archive_node>::const_iterator i = nodes.begin(), iend = nodes.end();
+ archive_node_id id = 0;
+ while (i != iend) {
+ if (i->has_same_ex_as(n))
+ return id;
+ i++; id++;
+ }
+
+ // Not found, add archive_node to nodes vector
+ nodes.push_back(n);
+ return id;
+}
+
+
+/** Retrieve archive_node by ID. */
+archive_node &archive::get_node(archive_node_id id)
+{
+ if (id >= nodes.size())
+ throw (std::range_error("archive::get_node(): archive node ID out of range"));
+
+ return nodes[id];
+}
+
+
+/** Retrieve expression from archive by name.
+ * @param sym_lst list of pre-defined symbols */
+ex archive::unarchive_ex(const lst &sym_lst, const char *name) const
+{
+ // Find root node
+ string name_string = name;
+ archive_atom id = atomize(name_string);
+ vector<archived_ex>::const_iterator i = exprs.begin(), iend = exprs.end();
+ while (i != iend) {
+ if (i->name == id)
+ goto found;
+ i++;
+ }
+ throw (std::logic_error("expression with name '" + name_string + "' not found in archive"));
+
+found:
+ // Recursively unarchive all nodes, starting at the root node
+ return nodes[i->root].unarchive(sym_lst);
+}
+
+/** Retrieve expression from archive by index.
+ * @param sym_lst list of pre-defined symbols */
+ex archive::unarchive_ex(const lst &sym_lst, unsigned int index) const
+{
+ if (index >= exprs.size())
+ throw (std::range_error("index of archived expression out of range"));
+
+ // Recursively unarchive all nodes, starting at the root node
+ return nodes[exprs[index].root].unarchive(sym_lst);
+}
+
+/** Retrieve expression and its name from archive by index.
+ * @param sym_lst list of pre-defined symbols */
+ex archive::unarchive_ex(const lst &sym_lst, string &name, unsigned int index) const
+{
+ if (index >= exprs.size())
+ throw (std::range_error("index of archived expression out of range"));
+
+ // Return expression name
+ name = unatomize(exprs[index].name);
+
+ // Recursively unarchive all nodes, starting at the root node
+ return nodes[exprs[index].root].unarchive(sym_lst);
+}
+
+
+/** Return number of archived expressions. */
+unsigned int archive::num_expressions(void) const
+{
+ return exprs.size();
+}
+
+
+/*
+ * Archive file format
+ *
+ * - 4 bytes signature 'GARC'
+ * - unsigned version number
+ * - unsigned number of atoms
+ * - atom strings (each zero-terminated)
+ * - unsigned number of expressions
+ * - unsigned name atom
+ * - unsigned root node ID
+ * - unsigned number of nodes
+ * - unsigned number of properties
+ * - unsigned type (PTYPE_*)
+ * - unsigned name atom
+ * - unsigned property value
+ *
+ * Unsigned quantities are stored in a compressed format:
+ * - numbers in the range 0x00..0x7f are stored verbatim (1 byte)
+ * - numbers larger than 0x7f are stored in 7-bit packets (1 byte per
+ * packet), starting with the LSBs; all bytes except the last one have
+ * their upper bit set
+ *
+ * Examples:
+ * 0x00 = 0x00
+ * .. ..
+ * 0x7f = 0x7f
+ * 0x80 0x01 = 0x80
+ * .. .. ..
+ * 0xff 0x01 = 0xff
+ * 0x80 0x02 = 0x100
+ * .. .. ..
+ * 0xff 0x02 = 0x17f
+ * 0x80 0x03 = 0x180
+ * .. .. ..
+ * 0xff 0x7f = 0x3fff
+ * 0x80 0x80 0x01 = 0x4000
+ * .. .. .. ..
+ */
+
+/** Write unsigned integer quantity to stream. */
+static void write_unsigned(ostream &os, unsigned int val)
+{
+ while (val > 0x80) {
+ os.put((val & 0x7f) | 0x80);
+ val >>= 7;
+ }
+ os.put(val);
+}
+
+/** Read unsigned integer quantity from stream. */
+static unsigned int read_unsigned(istream &is)
+{
+ unsigned char b;
+ unsigned int ret = 0;
+ unsigned int shift = 0;
+ do {
+ is.get(b);
+ ret |= (b & 0x7f) << shift;
+ shift += 7;
+ } while (b & 0x80);
+ return ret;
+}
+
+/** Write archive_node to binary data stream. */
+ostream &operator<<(ostream &os, const archive_node &n)
+{
+ // Write properties
+ unsigned int num_props = n.props.size();
+ write_unsigned(os, num_props);
+ for (unsigned int i=0; i<num_props; i++) {
+ write_unsigned(os, n.props[i].type);
+ write_unsigned(os, n.props[i].name);
+ write_unsigned(os, n.props[i].value);
+ }
+}
+
+/** Write archive to binary data stream. */
+ostream &operator<<(ostream &os, const archive &ar)
+{
+ // Write header
+ os.put('G'); // Signature
+ os.put('A');
+ os.put('R');
+ os.put('C');
+ write_unsigned(os, ARCHIVE_VERSION);
+
+ // Write atoms
+ unsigned int num_atoms = ar.atoms.size();
+ write_unsigned(os, num_atoms);
+ for (unsigned int i=0; i<num_atoms; i++)
+ os << ar.atoms[i] << ends;
+
+ // Write expressions
+ unsigned int num_exprs = ar.exprs.size();
+ write_unsigned(os, num_exprs);
+ for (unsigned int i=0; i<num_exprs; i++) {
+ write_unsigned(os, ar.exprs[i].name);
+ write_unsigned(os, ar.exprs[i].root);
+ }
+
+ // Write nodes
+ unsigned int num_nodes = ar.nodes.size();
+ write_unsigned(os, num_nodes);
+ for (unsigned int i=0; i<num_nodes; i++)
+ os << ar.nodes[i];
+}
+
+/** Read archive_node from binary data stream. */
+istream &operator>>(istream &is, archive_node &n)
+{
+ // Read properties
+ unsigned int num_props = read_unsigned(is);
+ n.props.resize(num_props);
+ for (unsigned int i=0; i<num_props; i++) {
+ n.props[i].type = (archive_node::property_type)read_unsigned(is);
+ n.props[i].name = read_unsigned(is);
+ n.props[i].value = read_unsigned(is);
+ }
+}
+
+/** Read archive from binary data stream. */
+istream &operator>>(istream &is, archive &ar)
+{
+ // Read header
+ char c1, c2, c3, c4;
+ is.get(c1); is.get(c2); is.get(c3); is.get(c4);
+ if (c1 != 'G' || c2 != 'A' || c3 != 'R' || c4 != 'C')
+ throw (std::runtime_error("not a GiNaC archive (signature not found)"));
+ unsigned int version = read_unsigned(is);
+ if (version > ARCHIVE_VERSION || version < ARCHIVE_VERSION - ARCHIVE_AGE)
+ throw (std::runtime_error("archive version " + ToString(version) + " cannot be read by this GiNaC library (which supports versions " + ToString(ARCHIVE_VERSION-ARCHIVE_AGE) + " thru " + ToString(ARCHIVE_VERSION)));
+
+ // Read atoms
+ unsigned int num_atoms = read_unsigned(is);
+ ar.atoms.resize(num_atoms);
+ for (unsigned int i=0; i<num_atoms; i++)
+ getline(is, ar.atoms[i], '\0');
+
+ // Read expressions
+ unsigned int num_exprs = read_unsigned(is);
+ ar.exprs.resize(num_exprs);
+ for (unsigned int i=0; i<num_exprs; i++) {
+ archive_atom name = read_unsigned(is);
+ archive_node_id root = read_unsigned(is);
+ ar.exprs[i] = archive::archived_ex(name, root);
+ }
+
+ // Read nodes
+ unsigned int num_nodes = read_unsigned(is);
+ ar.nodes.resize(num_nodes, ar);
+ for (unsigned int i=0; i<num_nodes; i++)
+ is >> ar.nodes[i];
+}
+
+
+/** Atomize a string (i.e. convert it into an ID number that uniquely
+ * represents the string). */
+archive_atom archive::atomize(const string &s) const
+{
+ // Search for string in atoms vector
+ vector<string>::const_iterator i = atoms.begin(), iend = atoms.end();
+ archive_atom id = 0;
+ while (i != iend) {
+ if (*i == s)
+ return id;
+ i++; id++;
+ }
+
+ // Not found, add to atoms vector
+ atoms.push_back(s);
+ return id;
+}
+
+/** Unatomize a string (i.e. convert the ID number back to the string). */
+const string &archive::unatomize(archive_atom id) const
+{
+ if (id >= atoms.size())
+ throw (std::range_error("archive::unatomizee(): atom ID out of range"));
+
+ return atoms[id];
+}
+
+
+/** Copy constructor of archive_node. */
+archive_node::archive_node(const archive_node &other)
+ : a(other.a), props(other.props), has_expression(other.has_expression), e(other.e)
+{
+}
+
+
+/** Assignment operator of archive_node. */
+const archive_node &archive_node::operator=(const archive_node &other)
+{
+ if (this != &other) {
+ a = other.a;
+ props = other.props;
+ has_expression = other.has_expression;
+ e = other.e;
+ }
+ return *this;
+}
+
+
+/** Recursively construct archive node from expression. */
+archive_node::archive_node(archive &ar, const ex &expr)
+ : a(ar), has_expression(true), e(expr)
+{
+ expr.bp->archive(*this);
+}
+
+
+/** Check if the archive_node stores the same expression as another
+ * archive_node.
+ * @return "true" if expressions are the same */
+bool archive_node::has_same_ex_as(const archive_node &other) const
+{
+ if (!has_expression || !other.has_expression)
+ return false;
+ return e.bp == other.e.bp;
+}
+
+
+/** Add property of type "bool" to node. */
+void archive_node::add_bool(const string &name, bool value)
+{
+ props.push_back(property(a.atomize(name), PTYPE_BOOL, value));
+}
+
+/** Add property of type "unsigned int" to node. */
+void archive_node::add_unsigned(const string &name, unsigned int value)
+{
+ props.push_back(property(a.atomize(name), PTYPE_UNSIGNED, value));
+}
+
+/** Add property of type "string" to node. */
+void archive_node::add_string(const string &name, const string &value)
+{
+ props.push_back(property(a.atomize(name), PTYPE_STRING, a.atomize(value)));
+}
+
+/** Add property of type "ex" to node. */
+void archive_node::add_ex(const string &name, const ex &value)
+{
+ // Recursively create an archive_node and add its ID to the properties of this node
+ archive_node_id id = a.add_node(archive_node(a, value));
+ props.push_back(property(a.atomize(name), PTYPE_NODE, id));
+}
+
+
+/** Retrieve property of type "bool" from node.
+ * @return "true" if property was found, "false" otherwise */
+bool archive_node::find_bool(const string &name, bool &ret) const
+{
+ archive_atom name_atom = a.atomize(name);
+ vector<property>::const_iterator i = props.begin(), iend = props.end();
+ while (i != iend) {
+ if (i->type == PTYPE_BOOL && i->name == name_atom) {
+ ret = i->value;
+ return true;
+ }
+ i++;
+ }
+ return false;
+}
+
+/** Retrieve property of type "unsigned" from node.
+ * @return "true" if property was found, "false" otherwise */
+bool archive_node::find_unsigned(const string &name, unsigned int &ret) const
+{
+ archive_atom name_atom = a.atomize(name);
+ vector<property>::const_iterator i = props.begin(), iend = props.end();
+ while (i != iend) {
+ if (i->type == PTYPE_UNSIGNED && i->name == name_atom) {
+ ret = i->value;
+ return true;
+ }
+ i++;
+ }
+ return false;
+}
+
+/** Retrieve property of type "string" from node.
+ * @return "true" if property was found, "false" otherwise */
+bool archive_node::find_string(const string &name, string &ret) const
+{
+ archive_atom name_atom = a.atomize(name);
+ vector<property>::const_iterator i = props.begin(), iend = props.end();
+ while (i != iend) {
+ if (i->type == PTYPE_STRING && i->name == name_atom) {
+ ret = a.unatomize(i->value);
+ return true;
+ }
+ i++;
+ }
+ return false;
+}
+
+/** Retrieve property of type "ex" from node.
+ * @return "true" if property was found, "false" otherwise */
+bool archive_node::find_ex(const string &name, ex &ret, const lst &sym_lst, unsigned int index) const
+{
+ archive_atom name_atom = a.atomize(name);
+ vector<property>::const_iterator i = props.begin(), iend = props.end();
+ unsigned int found_index = 0;
+ while (i != iend) {
+ if (i->type == PTYPE_NODE && i->name == name_atom) {
+ if (found_index == index)
+ goto found;
+ found_index++;
+ }
+ i++;
+ }
+ return false;
+
+found:
+ ret = a.get_node(i->value).unarchive(sym_lst);
+ return true;
+}
+
+
+/** Convert archive node to GiNaC expression. */
+ex archive_node::unarchive(const lst &sym_lst) const
+{
+ // Already unarchived? Then return cached unarchived expression.
+ if (has_expression)
+ return e;
+
+ // Find instantiation function for class specified in node
+ string class_name;
+ if (!find_string("class", class_name))
+ throw (std::runtime_error("archive node contains no class name"));
+ unarch_func f = find_unarch_func(class_name);
+
+ // Call instantiation function
+ e = f(*this, sym_lst);
+ has_expression = true;
+ return e;
+}
+
+
+/** Assignment operator of property. */
+const archive_node::property &archive_node::property::operator=(const property &other)
+{
+ if (this != &other) {
+ type = other.type;
+ name = other.name;
+ value = other.value;
+ }
+ return *this;
+}
+
+
+/** Clear all archived expressions. */
+void archive::clear(void)
+{
+ atoms.clear();
+ exprs.clear();
+ nodes.clear();
+}
+
+
+/** Delete cached unarchived expressions in all archive_nodes (mainly for debugging). */
+void archive::forget(void)
+{
+ vector<archive_node>::iterator i = nodes.begin(), iend = nodes.end();
+ while (i != iend) {
+ i->forget();
+ i++;
+ }
+}
+
+/** Delete cached unarchived expressions from node (for debugging). */
+void archive_node::forget(void)
+{
+ has_expression = false;
+ e = 0;
+}
+
+
+/** Dump archive to stream (for debugging). */
+void archive::dump(ostream &os) const
+{
+ // Dump atoms
+ os << "Atoms:\n";
+ {
+ vector<string>::const_iterator i = atoms.begin(), iend = atoms.end();
+ archive_atom id = 0;
+ while (i != iend) {
+ os << " " << id << " " << *i << endl;
+ i++; id++;
+ }
+ }
+ os << endl;
+
+ // Dump expressions
+ os << "Expressions:\n";
+ {
+ vector<archived_ex>::const_iterator i = exprs.begin(), iend = exprs.end();
+ unsigned int index = 0;
+ while (i != iend) {
+ os << " " << index << " \"" << unatomize(i->name) << "\" root node " << i->root << endl;
+ i++; index++;
+ }
+ }
+ os << endl;
+
+ // Dump nodes
+ os << "Nodes:\n";
+ {
+ vector<archive_node>::const_iterator i = nodes.begin(), iend = nodes.end();
+ archive_node_id id = 0;
+ while (i != iend) {
+ os << " " << id << " ";
+ i->dump(os);
+ i++; id++;
+ }
+ }
+}
+
+/** Dump archive_node to stream (for debugging). */
+void archive_node::dump(ostream &os) const
+{
+ // Dump cached unarchived expression
+ if (has_expression)
+ os << "(basic * " << e.bp << " = " << e << ")\n";
+ else
+ os << "(no expression)\n";
+
+ // Dump properties
+ vector<property>::const_iterator i = props.begin(), iend = props.end();
+ while (i != iend) {
+ os << " ";
+ switch (i->type) {
+ case PTYPE_BOOL: os << "bool"; break;
+ case PTYPE_UNSIGNED: os << "unsigned"; break;
+ case PTYPE_STRING: os << "string"; break;
+ case PTYPE_NODE: os << "node"; break;
+ default: os << "<unknown>"; break;
+ }
+ os << " \"" << a.unatomize(i->name) << "\" " << i->value << endl;
+ i++;
+ }
+}
+
+
+#ifndef NO_GINAC_NAMESPACE
+} // namespace GiNaC
+#endif // ndef NO_GINAC_NAMESPACE
--- /dev/null
+/** @file archive.h
+ *
+ * Archiving of GiNaC expressions. */
+
+/*
+ * GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __GINAC_ARCHIVE_H__
+#define __GINAC_ARCHIVE_H__
+
+#include <ginac/ex.h>
+
+#include <string>
+#include <vector>
+
+class ostream;
+class istream;
+
+#ifndef NO_GINAC_NAMESPACE
+namespace GiNaC {
+#endif // ndef NO_GINAC_NAMESPACE
+
+class lst;
+class archive;
+
+
+/** Numerical ID value to refer to an archive_node. */
+typedef unsigned int archive_node_id;
+
+/** Numerical ID value to refer to a string. */
+typedef unsigned int archive_atom;
+
+
+/** This class stores all properties needed to record/retrieve the state
+ * of one object of class basic (or a derived class). Each property is
+ * addressed by its name and data type. */
+class archive_node
+{
+ friend ostream &operator<<(ostream &os, const archive_node &ar);
+ friend istream &operator>>(istream &is, archive_node &ar);
+
+public:
+ archive_node(archive &ar) : a(ar), has_expression(false) {}
+ archive_node(archive &ar, const ex &expr);
+ ~archive_node() {}
+
+ archive_node(const archive_node &other);
+ const archive_node &operator=(const archive_node &other);
+
+ bool has_same_ex_as(const archive_node &other) const;
+
+ void add_bool(const string &name, bool value);
+ void add_unsigned(const string &name, unsigned int value);
+ void add_string(const string &name, const string &value);
+ void add_ex(const string &name, const ex &value);
+
+ bool find_bool(const string &name, bool &ret) const;
+ bool find_unsigned(const string &name, unsigned int &ret) const;
+ bool find_string(const string &name, string &ret) const;
+ bool find_ex(const string &name, ex &ret, const lst &sym_lst, unsigned int index = 0) const;
+
+ ex unarchive(const lst &sym_lst) const;
+
+ void forget(void);
+ void dump(ostream &os) const;
+
+private:
+ /** Property data types */
+ enum property_type {
+ PTYPE_BOOL,
+ PTYPE_UNSIGNED,
+ PTYPE_STRING,
+ PTYPE_NODE
+ };
+
+ /** Archived property (data type, name and associated data) */
+ struct property {
+ property() {}
+ property(archive_atom n, property_type t, unsigned int v) : type(t), name(n), value(v) {}
+ ~property() {}
+
+ property(const property &other) : type(other.type), name(other.name), value(other.value) {}
+ const property &operator=(const property &other);
+
+ property_type type; /**< Data type of property. */
+ archive_atom name; /**< Name of property. */
+ unsigned int value; /**< Stored value. */
+ };
+
+ /** Reference to the archive to which this node belongs. */
+ archive &a;
+
+ /** Vector of stored properties. */
+ vector<property> props;
+
+ /** Flag indicating whether a cached unarchived representation of this node exists. */
+ mutable bool has_expression;
+
+ /** The cached unarchived representation of this node (if any). */
+ mutable ex e;
+};
+
+
+/** This class holds archived versions of GiNaC expressions (class ex).
+ * An archive can be constructed from an expression and then written to
+ * a stream; or it can be read from a stream and then unarchived, yielding
+ * back the expression. Archives can hold multiple expressions which can
+ * be referred to by name or index number. The main component of the
+ * archive class is a vector of archive_nodes which each store one object
+ * of class basic (or a derived class). */
+class archive
+{
+ friend ostream &operator<<(ostream &os, const archive &ar);
+ friend istream &operator>>(istream &is, archive &ar);
+
+public:
+ archive() {}
+ ~archive() {}
+
+ /** Construct archive from expression using the default name "ex". */
+ archive(const ex &e) {archive_ex(e, "ex");}
+
+ /** Construct archive from expression using the specified name. */
+ archive(const ex &e, const char *n) {archive_ex(e, n);}
+
+ archive_node_id add_node(const archive_node &n);
+ archive_node &get_node(archive_node_id id);
+
+ void archive_ex(const ex &e, const char *name);
+ ex unarchive_ex(const lst &sym_lst, const char *name) const;
+ ex unarchive_ex(const lst &sym_lst, unsigned int index = 0) const;
+ ex unarchive_ex(const lst &sym_lst, string &name, unsigned int index = 0) const;
+ unsigned int num_expressions(void) const;
+
+ void clear(void);
+
+ void forget(void);
+ void dump(ostream &os) const;
+
+private:
+ /** Vector of archived nodes. */
+ vector<archive_node> nodes;
+
+ /** Archived expression descriptor. */
+ struct archived_ex {
+ archived_ex() {}
+ archived_ex(archive_atom n, archive_node_id node) : name(n), root(node) {}
+
+ archive_atom name; /**< Name of expression. */
+ archive_node_id root; /**< ID of root node. */
+ };
+
+ /** Vector of archived expression descriptors. */
+ vector<archived_ex> exprs;
+
+public:
+ archive_atom atomize(const string &s) const;
+ const string &unatomize(archive_atom id) const;
+
+private:
+ /** Vector of atomized strings (using a vector allows faster unarchiving). */
+ mutable vector<string> atoms;
+};
+
+
+ostream &operator<<(ostream &os, const archive &ar);
+istream &operator>>(istream &is, archive &ar);
+
+
+#ifndef NO_GINAC_NAMESPACE
+} // namespace GiNaC
+#endif // ndef NO_GINAC_NAMESPACE
+
+#endif // ndef __GINAC_ARCHIVE_H__
#include "symbol.h"
#include "lst.h"
#include "ncmul.h"
+#include "archive.h"
#include "utils.h"
#include "debugmsg.h"
namespace GiNaC {
#endif // ndef NO_GINAC_NAMESPACE
+GINAC_IMPLEMENT_REGISTERED_CLASS(basic, void)
+
//////////
// default constructor, destructor, copy constructor assignment operator and helpers
//////////
#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);
#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
//////////
#include <ginac/flags.h>
#include <ginac/tinfos.h>
#include <ginac/assertion.h>
+#include <ginac/registrar.h>
#ifndef NO_GINAC_NAMESPACE
namespace GiNaC {
class symbol;
class lst;
class numeric;
+class archive_node;
//typedef vector<ex> exvector;
typedef vector<ex,malloc_alloc> exvector; // CINT does not like vector<...,default_alloc>
* It is responsible for the reference counting. */
class basic
{
+ GINAC_DECLARE_REGISTERED_CLASS(basic, void)
+
friend class ex;
// member functions
#endif // ndef NO_GINAC_NAMESPACE
#endif // ndef __GINAC_BASIC_H__
-
#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
//////////
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
//////////
* number). */
class constant : public basic
{
+ GINAC_DECLARE_REGISTERED_CLASS(constant, basic)
// member functions
class ${CONTAINER} : public basic
{
+ GINAC_DECLARE_REGISTERED_CLASS(${CONTAINER}, basic)
public:
${CONTAINER}();
#include "${CONTAINER}.h"
#include "ex.h"
+#include "archive.h"
#include "debugmsg.h"
#ifndef NO_GINAC_NAMESPACE
namespace GiNaC {
#endif // ndef NO_GINAC_NAMESPACE
+GINAC_IMPLEMENT_REGISTERED_CLASS(${CONTAINER}, basic)
+
${RESERVE_IMPLEMENTATION}
//////////
void ${CONTAINER}::copy(${CONTAINER} const & other)
{
- basic::copy(other);
+ inherited::copy(other);
seq=other.seq;
}
void ${CONTAINER}::destroy(bool call_parent)
{
seq.clear();
- if (call_parent) basic::destroy(call_parent);
+ if (call_parent) inherited::destroy(call_parent);
}
//////////
seq.push_back(e10);
}
+//////////
+// archiving
+//////////
+
+/** Construct object from archive_node. */
+${CONTAINER}::${CONTAINER}(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
+{
+ debugmsg("${CONTAINER} constructor from archive_node", LOGLEVEL_CONSTRUCT);
+ for (unsigned int i=0; true; i++) {
+ ex e;
+ if (n.find_ex("seq", e, sym_lst, i))
+ seq.push_back(e);
+ else
+ break;
+ }
+}
+
+/** Unarchive the object. */
+ex ${CONTAINER}::unarchive(const archive_node &n, const lst &sym_lst)
+{
+ return (new ${CONTAINER}(n, sym_lst))->setflag(status_flags::dynallocated);
+}
+
+/** Archive the object. */
+void ${CONTAINER}::archive(archive_node &n) const
+{
+ inherited::archive(n);
+ ${STLT}::const_iterator i = seq.begin(), iend = seq.end();
+ while (i != iend) {
+ n.add_ex("seq", *i);
+ i++;
+ }
+}
+
//////////
// functions overriding virtual functions from bases classes
//////////
#include "numeric.h"
#include "power.h"
#include "relational.h"
-#include "series.h"
+#include "pseries.h"
#include "symbol.h"
#include "utils.h"
}
-/** 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;
}
it++;
}
- return series(var, point, new_seq);
+ return pseries(var, point, new_seq);
} else {
return *this;
}
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); }
#include "expairseq.h"
#include "lst.h"
+#include "archive.h"
#include "debugmsg.h"
#include "utils.h"
#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
//////////
void expairseq::copy(expairseq const & other)
{
- basic::copy(other);
+ inherited::copy(other);
seq=other.seq;
overall_coeff=other.overall_coeff;
#ifdef EXPAIRSEQ_USE_HASHTAB
// 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);
/*
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) {
*/
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);
}
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);
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
//////////
bool expairseq::info(unsigned inf) const
{
- return basic::info(inf);
+ return inherited::info(inf);
}
unsigned expairseq::nops() const
* the same way.) */
class expairseq : public basic
{
+ GINAC_DECLARE_REGISTERED_CLASS(expairseq, basic)
+
// member functions
// default constructor, destructor, copy constructor assignment operator and helpers
*/
#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);
}
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);
}
// 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
//////////
class fail : public basic
{
-// member functions
+ GINAC_DECLARE_REGISTERED_CLASS(fail, basic)
// default constructor, destructor, copy constructor assignment operator and helpers
public:
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);
#include "function.h"
#include "ex.h"
+#include "archive.h"
#include "utils.h"
#include "debugmsg.h"
namespace GiNaC {
#endif // ndef NO_GINAC_NAMESPACE
+GINAC_IMPLEMENT_REGISTERED_CLASS(function, exprseq)
+
//////////
// default constructor, destructor, copy constructor assignment operator and helpers
//////////
tinfo_key = TINFO_function;
}
+//////////
+// archiving
+//////////
+
+/** Construct object from archive_node. */
+function::function(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
+{
+ debugmsg("function constructor from archive_node", LOGLEVEL_CONSTRUCT);
+
+ // Find serial number by function name
+ string s;
+ if (n.find_string("name", s)) {
+ unsigned int ser = 0;
+ vector<registered_function_info>::const_iterator i = registered_functions().begin(), iend = registered_functions().end();
+ while (i != iend) {
+ if (s == i->name) {
+ serial = ser;
+ return;
+ }
+ i++; ser++;
+ }
+ throw (std::runtime_error("unknown function '" + s + "' in archive"));
+ } else
+ throw (std::runtime_error("unnamed function in archive"));
+}
+
+/** Unarchive the object. */
+ex function::unarchive(const archive_node &n, const lst &sym_lst)
+{
+ return (new function(n, sym_lst))->setflag(status_flags::dynallocated);
+}
+
+/** Archive the object. */
+void function::archive(archive_node &n) const
+{
+ inherited::archive(n);
+ GINAC_ASSERT(serial < registered_functions().size());
+ n.add_string("name", registered_functions()[serial].name);
+}
+
//////////
// functions overriding virtual functions from bases classes
//////////
#include <ginac/ex.h>
#include <ginac/normal.h>
+#include <ginac/archive.h>
#include <ginac/constant.h>
#include <ginac/fail.h>
#include <ginac/expairseq.h>
#include <ginac/add.h>
#include <ginac/mul.h>
-#include <ginac/series.h>
+#include <ginac/pseries.h>
#include <ginac/exprseq.h>
#include <ginac/function.h>
namespace GiNaC {
#endif // ndef NO_GINAC_NAMESPACE
+GINAC_IMPLEMENT_REGISTERED_CLASS(indexed, exprseq)
+
//////////
// default constructor, destructor, copy constructor assignment operator and helpers
//////////
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);
}
}
// 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;
}
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;
}
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
//////////
{
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
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
/** 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
#include "numeric.h"
#include "power.h"
#include "relational.h"
-#include "series.h"
+#include "pseries.h"
#include "symbol.h"
#include "utils.h"
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);
#include "inifcns.h"
#include "ex.h"
#include "constant.h"
-#include "series.h"
+#include "pseries.h"
#include "numeric.h"
#include "power.h"
#include "relational.h"
#include <stdexcept>
#include "matrix.h"
-#include "debugmsg.h"
+#include "archive.h"
#include "utils.h"
+#include "debugmsg.h"
#ifndef NO_GINAC_NAMESPACE
namespace GiNaC {
#endif // ndef NO_GINAC_NAMESPACE
+GINAC_IMPLEMENT_REGISTERED_CLASS(matrix, basic)
+
//////////
// default constructor, destructor, copy constructor, assignment operator
// and helpers:
/** 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());
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
void matrix::destroy(bool call_parent)
{
- if (call_parent) basic::destroy(call_parent);
+ if (call_parent) inherited::destroy(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());
/** 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
//////////
/** 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
#include "mul.h"
#include "add.h"
#include "power.h"
+#include "archive.h"
#include "debugmsg.h"
#include "utils.h"
namespace GiNaC {
#endif // ndef NO_GINAC_NAMESPACE
+GINAC_IMPLEMENT_REGISTERED_CLASS(mul, expairseq)
+
//////////
// default constructor, destructor, copy constructor assignment operator and helpers
//////////
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);
}
//////////
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
//////////
}
return overall_coeff.info(inf);
} else {
- return expairseq::info(inf);
+ return inherited::info(inf);
}
}
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
/** Product of expressions. */
class mul : public expairseq
{
+ GINAC_DECLARE_REGISTERED_CLASS(mul, expairseq)
+
friend class add;
friend class ncmul;
friend class power;
#include "ex.h"
#include "add.h"
#include "mul.h"
+#include "archive.h"
#include "debugmsg.h"
#include "utils.h"
namespace GiNaC {
#endif // ndef NO_GINAC_NAMESPACE
+GINAC_IMPLEMENT_REGISTERED_CLASS(ncmul, exprseq)
+
//////////
// default constructor, destructor, copy constructor assignment operator and helpers
//////////
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);
}
//////////
// 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;
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
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
/** 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);
#include "numeric.h"
#include "power.h"
#include "relational.h"
-#include "series.h"
+#include "pseries.h"
#include "symbol.h"
#include "utils.h"
}
-/** 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());
it++;
}
- ex n = series(var, point, new_seq);
+ ex n = pseries(var, point, new_seq);
return replace_with_symbol(n, sym_lst, repl_lst);
}
#include <vector>
#include <stdexcept>
+#include <string>
+#include <strstream> //!!
#include "numeric.h"
#include "ex.h"
#include "config.h"
+#include "archive.h"
#include "debugmsg.h"
#include "utils.h"
// 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
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:
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:
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|
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|
* @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);
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:
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
* 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
//////////
{
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)
* 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);
#include "numeric.h"
#include "relational.h"
#include "symbol.h"
+#include "archive.h"
#include "debugmsg.h"
#include "utils.h"
namespace GiNaC {
#endif // ndef NO_GINAC_NAMESPACE
+GINAC_IMPLEMENT_REGISTERED_CLASS(power, basic)
+
typedef vector<int> intvector;
//////////
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);
}
//////////
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
//////////
} else if (inf==info_flags::rational_function) {
return exponent.info(info_flags::integer);
} else {
- return basic::info(inf);
+ return inherited::info(inf);
}
}
ex power::simplify_ncmul(exvector const & v) const
{
- return basic::simplify_ncmul(v);
+ return inherited::simplify_ncmul(v);
}
// protected
* representing exponentiation. */
class power : public basic
{
+ GINAC_DECLARE_REGISTERED_CLASS(power, basic)
+
friend class mul;
// member functions
-/** @file series.cpp
+/** @file pseries.cpp
*
- * Implementation of class for extended truncated power-series and
+ * Implementation of class for extended truncated power series and
* methods for series expansion. */
/*
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include "series.h"
+#include "pseries.h"
#include "add.h"
#include "inifcns.h"
+#include "lst.h"
#include "mul.h"
#include "power.h"
#include "relational.h"
#include "symbol.h"
-#include "debugmsg.h"
+#include "archive.h"
#include "utils.h"
+#include "debugmsg.h"
#ifndef NO_GINAC_NAMESPACE
namespace GiNaC {
#endif // ndef NO_GINAC_NAMESPACE
+GINAC_IMPLEMENT_REGISTERED_CLASS(pseries, basic)
+
/*
* Default constructor, destructor, copy constructor, assignment operator and helpers
*/
-series::series() : basic(TINFO_series)
+pseries::pseries() : basic(TINFO_pseries)
{
- debugmsg("series default constructor", LOGLEVEL_CONSTRUCT);
+ debugmsg("pseries default constructor", LOGLEVEL_CONSTRUCT);
}
-series::~series()
+pseries::~pseries()
{
- debugmsg("series destructor", LOGLEVEL_DESTRUCT);
+ debugmsg("pseries destructor", LOGLEVEL_DESTRUCT);
destroy(false);
}
-series::series(series const &other)
+pseries::pseries(pseries const &other)
{
- debugmsg("series copy constructor", LOGLEVEL_CONSTRUCT);
+ debugmsg("pseries copy constructor", LOGLEVEL_CONSTRUCT);
copy(other);
}
-series const &series::operator=(series const & other)
+pseries const &pseries::operator=(pseries const & other)
{
- debugmsg("series operator=", LOGLEVEL_ASSIGNMENT);
+ debugmsg("pseries operator=", LOGLEVEL_ASSIGNMENT);
if (this != &other) {
destroy(true);
copy(other);
return *this;
}
-void series::copy(series const &other)
+void pseries::copy(pseries const &other)
{
inherited::copy(other);
seq = other.seq;
point = other.point;
}
-void series::destroy(bool call_parent)
+void pseries::destroy(bool call_parent)
{
if (call_parent)
inherited::destroy(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,
* @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
}
}
-// 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
}
}
-// 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();
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();
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();
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())
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
}
}
}
- 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());
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
}
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 */
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;
}
*
* @param p power to compute
* @param deg truncation order of series calculation */
-ex series::power_const(const numeric &p, int deg) const
+ex pseries::power_const(const numeric &p, int deg) const
{
int i;
const symbol *s = static_cast<symbol *>(var.bp);
}
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);
}
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);
}
// 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);
// 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
-/** @file series.h
+/** @file pseries.h
*
* Interface to class for extended truncated power series. */
* 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:
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:
};
// global constants
-extern const series some_series;
-extern type_info const & typeid_series;
+extern const pseries some_pseries;
+extern type_info const & typeid_pseries;
-/** Return a reference to the series object embedded in an expression.
- * The result is undefined if the expression does not contain a series
+/** Return a reference to the pseries object embedded in an expression.
+ * The result is undefined if the expression does not contain a pseries
* object at its top level.
*
* @param e expression
- * @return reference to series object
+ * @return reference to pseries object
* @see is_ex_of_type */
-inline const series &ex_to_series(const ex &e)
+inline const pseries &ex_to_pseries(const ex &e)
{
- return static_cast<const series &>(*e.bp);
+ return static_cast<const pseries &>(*e.bp);
}
-/** Convert the series object embedded in an expression to an ordinary
+/** Convert the pseries object embedded in an expression to an ordinary
* polynomial in the expansion variable. The result is undefined if the
- * expression does not contain a series object at its top level.
+ * expression does not contain a pseries object at its top level.
*
* @param e expression
* @return polynomial expression
* @see is_ex_of_type
- * @see series::convert_to_poly */
+ * @see pseries::convert_to_poly */
inline ex series_to_poly(const ex &e)
{
- return (static_cast<const series &>(*e.bp).convert_to_poly(true));
+ return (static_cast<const pseries &>(*e.bp).convert_to_poly(true));
}
#ifndef NO_GINAC_NAMESPACE
--- /dev/null
+/** @file registrar.cpp
+ *
+ * GiNaC's class registrar (for class basic and all classes derived from it). */
+
+/*
+ * GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University Mainz, Germany
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <string>
+#include <stdexcept>
+
+#include "registrar.h"
+
+#ifndef NO_GINAC_NAMESPACE
+namespace GiNaC {
+#endif // ndef NO_GINAC_NAMESPACE
+
+registered_class_info *first_registered_class = NULL;
+
+/** Find registered_class_info strucure by class name. */
+static inline registered_class_info *find_registered_class_info(const string &class_name)
+{
+ registered_class_info *p = first_registered_class;
+ while (p) {
+ if (class_name == p->name)
+ return p;
+ p = p->next;
+ }
+ throw (std::runtime_error("class '" + class_name + "' not registered"));
+}
+
+unsigned int find_tinfo_key(const string &class_name)
+{
+ registered_class_info *p = find_registered_class_info(class_name);
+ return p->tinfo_key;
+}
+
+unarch_func find_unarch_func(const string &class_name)
+{
+ registered_class_info *p = find_registered_class_info(class_name);
+ return p->unarchive;
+}
+
+
+#ifndef NO_GINAC_NAMESPACE
+} // namespace GiNaC
+#endif // ndef NO_GINAC_NAMESPACE
--- /dev/null
+/** @file registrar.h
+ *
+ * GiNaC's class registrar (for class basic and all classes derived from it). */
+
+/*
+ * GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University Mainz, Germany
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __GINAC_REGISTRAR_H__
+#define __GINAC_REGISTRAR_H__
+
+#include <string>
+
+#ifndef NO_GINAC_NAMESPACE
+namespace GiNaC {
+#endif // ndef NO_GINAC_NAMESPACE
+
+class registered_class_info;
+class ex;
+class archive_node;
+class lst;
+
+
+/** Unarchiving function (static member function of every GiNaC class). */
+typedef ex (*unarch_func)(const archive_node &n, const lst &sym_lst);
+
+
+/** Head of list of all registered_class_info structures. */
+extern registered_class_info *first_registered_class;
+
+
+/** This structure stores information about a registered GiNaC class. */
+struct registered_class_info {
+ registered_class_info(const char *n, const char *s, unsigned int k, unarch_func f)
+ : name(n), super(s), tinfo_key(k), unarchive(f)
+ {
+ // Add structure to list
+ next = first_registered_class;
+ first_registered_class = this;
+ }
+
+ registered_class_info *next; /**< Pointer to next registered_class_info in list. */
+ const char *name; /**< Class name. */
+ const char *super; /**< Name of superclass. */
+ unsigned int tinfo_key; /**< TINFO_* key. */
+ unarch_func unarchive; /**< Pointer to unarchiving function. */
+};
+
+
+/** Macro for inclusion in the declaration of each registered class. */
+#define GINAC_DECLARE_REGISTERED_CLASS(classname, supername) \
+public: \
+ typedef supername inherited; \
+\
+ /** This structure stores information about the class. */ \
+ static registered_class_info reg_info; \
+\
+ /** Return pointer to class name. */ \
+ virtual const char *class_name(void) const; \
+\
+ classname(const archive_node &n, const lst &sym_lst); \
+ virtual void archive(archive_node &n) const; \
+ static ex unarchive(const archive_node &n, const lst &sym_lst); \
+private:
+
+/** Macro for inclusion in the implementation of each registered class. */
+#define GINAC_IMPLEMENT_REGISTERED_CLASS(classname, supername) \
+ registered_class_info classname::reg_info(#classname, #supername, TINFO_##classname, &classname::unarchive); \
+ const char *classname::class_name(void) const {return reg_info.name;}
+
+
+/** Find TINFO_* key by class name. */
+extern unsigned int find_tinfo_key(const string &class_name);
+
+/** Find unarchiving function by class name. */
+extern unarch_func find_unarch_func(const string &class_name);
+
+
+#ifndef NO_GINAC_NAMESPACE
+} // namespace GiNaC
+#endif // ndef NO_GINAC_NAMESPACE
+
+#endif // ndef __GINAC_REGISTRAR_H__
#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
//////////
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
//////////
* relation between them. */
class relational : public basic
{
+ GINAC_DECLARE_REGISTERED_CLASS(relational, basic)
// types
public:
#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;
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;
delete asexinfop;
}
if (call_parent) {
- basic::destroy(call_parent);
+ inherited::destroy(call_parent);
}
}
// public
-symbol::symbol(string const & initname) : basic(TINFO_symbol)
+symbol::symbol(string const & initname) : inherited(TINFO_symbol)
{
- debugmsg("symbol constructor from string",LOGLEVEL_CONSTRUCT);
+ debugmsg("symbol constructor from string", LOGLEVEL_CONSTRUCT);
name=initname;
serial=next_serial++;
asexinfop=new assigned_ex_info;
setflag(status_flags::evaluated);
}
+//////////
+// archiving
+//////////
+
+/** Construct object from archive_node. */
+symbol::symbol(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
+{
+ debugmsg("symbol constructor from archive_node", LOGLEVEL_CONSTRUCT);
+ serial = next_serial++;
+ if (!(n.find_string("name", name)))
+ name = autoname_prefix() + ToString(serial);
+ asexinfop = new assigned_ex_info;
+ setflag(status_flags::evaluated);
+}
+
+/** Unarchive the object. */
+ex symbol::unarchive(const archive_node &n, const lst &sym_lst)
+{
+ ex s = (new symbol(n, sym_lst))->setflag(status_flags::dynallocated);
+
+ // If symbol is in sym_lst, return the existing symbol
+ for (int i=0; i<sym_lst.nops(); i++) {
+ if (is_ex_of_type(sym_lst.op(i), symbol) && (ex_to_symbol(sym_lst.op(i)).name == ex_to_symbol(s).name))
+ return sym_lst.op(i);
+ }
+ return s;
+}
+
+/** Archive the object. */
+void symbol::archive(archive_node &n) const
+{
+ inherited::archive(n);
+ n.add_string("name", name);
+}
+
//////////
// functions overriding virtual functions from bases classes
//////////
// public
-basic * symbol::duplicate() const
+basic *symbol::duplicate() const
{
- debugmsg("symbol duplicate",LOGLEVEL_DUPLICATE);
+ debugmsg("symbol duplicate", LOGLEVEL_DUPLICATE);
return new symbol(*this);
}
inf==info_flags::rational_function) {
return true;
} else {
- return basic::info(inf);
+ return inherited::info(inf);
}
}
* first place. */
class symbol : public basic
{
+ GINAC_DECLARE_REGISTERED_CLASS(symbol, basic)
+
// types
+
/** Symbols as keys to expressions. */
class assigned_ex_info {
public:
ex coeff(symbol const & s, int const n = 1) const;
ex eval(int level = 0) const;
ex diff(symbol const & s) const;
+ ex series(symbol const & s, ex const & point, int order) const;
ex normal(lst &sym_lst, lst &repl_lst, int level=0) const;
ex subs(lst const & ls, lst const & lr) const;
protected:
const unsigned TINFO_numeric = 0x00090001U;
-const unsigned TINFO_series = 0x000a0001U;
+const unsigned TINFO_pseries = 0x000a0001U;
const unsigned TINFO_indexed = 0x000b0001U;
const unsigned TINFO_algebra = 0x000b1001U;