X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Fbasic.h;h=598058a5e8f02548bc475bd53fd01ac8a34c35cc;hp=d50c7ca34eb73d916e9f93fb2c38d3d28e0a71e6;hb=ed914545e01d60ecf2544e6141d6c5142c01327f;hpb=613ced9c74ce14644a926868bb02dec27af2321c diff --git a/ginac/basic.h b/ginac/basic.h index d50c7ca3..598058a5 100644 --- a/ginac/basic.h +++ b/ginac/basic.h @@ -3,7 +3,7 @@ * Interface to GiNaC's ABC. */ /* - * GiNaC Copyright (C) 1999-2003 Johannes Gutenberg University Mainz, Germany + * GiNaC Copyright (C) 1999-2016 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 @@ -17,40 +17,73 @@ * * 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 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef __GINAC_BASIC_H__ -#define __GINAC_BASIC_H__ - -#include // for size_t -#include -#include -// CINT needs to work properly with -#include +#ifndef GINAC_BASIC_H +#define GINAC_BASIC_H #include "flags.h" -#include "tinfos.h" +#include "ptr.h" #include "assertion.h" #include "registrar.h" +#include // for size_t +#include +#include +#include // for typeid +#include +#include + namespace GiNaC { class ex; -class ex_is_less; +struct ex_is_less; class symbol; class numeric; class relational; class archive_node; class print_context; -template class ptr; typedef std::vector exvector; +typedef std::set exset; typedef std::map exmap; +// Define this to enable some statistical output for comparisons and hashing +#undef GINAC_COMPARE_STATISTICS + +#ifdef GINAC_COMPARE_STATISTICS +class compare_statistics_t { +public: + compare_statistics_t() + : total_compares(0), nontrivial_compares(0), total_basic_compares(0), compare_same_hashvalue(0), compare_same_type(0), + total_is_equals(0), nontrivial_is_equals(0), total_basic_is_equals(0), is_equal_same_hashvalue(0), is_equal_same_type(0), + total_gethash(0), gethash_cached(0) {} + ~compare_statistics_t(); + + unsigned long total_compares; + unsigned long nontrivial_compares; + unsigned long total_basic_compares; + unsigned long compare_same_hashvalue; + unsigned long compare_same_type; + + unsigned long total_is_equals; + unsigned long nontrivial_is_equals; + unsigned long total_basic_is_equals; + unsigned long is_equal_same_hashvalue; + unsigned long is_equal_same_type; + + unsigned long total_gethash; + unsigned long gethash_cached; +}; + +extern compare_statistics_t compare_statistics; +#endif + /** Function object for map(). */ struct map_function { + virtual ~map_function() {} typedef const ex & argument_type; typedef ex result_type; virtual ex operator()(const ex & e) = 0; @@ -66,46 +99,46 @@ protected: }; -/** This class is the ABC (abstract base class) of GiNaC's class hierarchy. - * It is responsible for the reference counting. */ -class basic +/** This class is the ABC (abstract base class) of GiNaC's class hierarchy. */ +class basic : public refcounted { GINAC_DECLARE_REGISTERED_CLASS_NO_CTORS(basic, void) friend class ex; - friend class ptr; // default constructor, destructor, copy constructor and assignment operator protected: - basic() : tinfo_key(TINFO_basic), flags(0), refcount(0) {} + basic() : flags(0) {} public: /** basic destructor, virtual because class ex will delete objects of * derived classes via a basic*. */ virtual ~basic() { - GINAC_ASSERT((!(flags & status_flags::dynallocated))||(refcount==0)); + GINAC_ASSERT((!(flags & status_flags::dynallocated)) || (get_refcount() == 0)); } basic(const basic & other); const basic & operator=(const basic & other); protected: - /** Constructor with specified tinfo_key (used by derived classes instead - * of the default constructor to avoid assigning tinfo_key twice). */ - basic(unsigned ti) : tinfo_key(ti), flags(0), refcount(0) {} - // new virtual functions which can be overridden by derived classes public: // only const functions please (may break reference counting) /** Create a clone of this object on the heap. One can think of this as * simulating a virtual copy constructor which is needed for instance by * the refcounted construction of an ex from a basic. */ - virtual basic * duplicate() const { return new basic(*this); } + virtual basic * duplicate() const + { + basic * bp = new basic(*this); + bp->setflag(status_flags::dynallocated); + return bp; + } // evaluation - virtual ex eval(int level = 0) const; - virtual ex evalf(int level = 0) const; + virtual ex eval() const; + virtual ex evalf() const; virtual ex evalm() const; + virtual ex eval_integ() const; protected: virtual ex eval_ncmul(const exvector & v) const; public: @@ -130,8 +163,8 @@ public: virtual ex & operator[](size_t i); // pattern matching - virtual bool has(const ex & other) const; - virtual bool match(const ex & pattern, lst & repl_lst) const; + virtual bool has(const ex & other, unsigned options = 0) const; + virtual bool match(const ex & pattern, exmap & repls) const; protected: virtual bool match_same_type(const basic & other) const; public: @@ -150,6 +183,7 @@ public: } // degree/coeff + virtual bool is_polynomial(const ex & var) const; virtual int degree(const ex & s) const; virtual int ldegree(const ex & s) const; virtual ex coeff(const ex & s, int n = 1) const; @@ -165,9 +199,9 @@ public: virtual ex series(const relational & r, int order, unsigned options = 0) const; // rational functions - virtual ex normal(exmap & repl, exmap & rev_lookup, int level = 0) const; - virtual ex to_rational(lst &repl_lst) const; - virtual ex to_polynomial(lst &repl_lst) const; + virtual ex normal(exmap & repl, exmap & rev_lookup) const; + virtual ex to_rational(exmap & repl) const; + virtual ex to_polynomial(exmap & repl) const; // polynomial algorithms virtual numeric integer_content() const; @@ -182,9 +216,15 @@ public: // noncommutativity virtual unsigned return_type() const; - virtual unsigned return_type_tinfo() const; + virtual return_type_t return_type_tinfo() const; -protected: // functions that should be called from class ex only + // functions for complex expressions + virtual ex conjugate() const; + virtual ex real_part() const; + virtual ex imag_part() const; + + // functions that should be called from class ex only +protected: virtual int compare_same_type(const basic & other) const; virtual bool is_equal_same_type(const basic & other) const; @@ -205,13 +245,43 @@ public: void print_dispatch(const registered_class_info & ri, const print_context & c, unsigned level) const; + /** Save (serialize) the object into archive node. + * + * Losely speaking, this method turns an expression into a byte + * stream (which can be saved and restored later on, or sent via + * network, etc.) + */ + virtual void archive(archive_node& n) const; + /** Load (deserialize) the object from an archive node. + * + * @note This method is essentially a constructor. However, + * constructors can't be virtual. So, if unarchiving routines + * are implemented as constructors one would need to define such + * a constructor in every class, even if all it does is simply + * calling constructor of a superclass. + */ + virtual void read_archive(const archive_node& n, lst& syms); // no const + ex subs_one_level(const exmap & m, unsigned options) const; ex diff(const symbol & s, unsigned nth = 1) const; int compare(const basic & other) const; bool is_equal(const basic & other) const; const basic & hold() const; - unsigned gethash() const { if (flags & status_flags::hash_calculated) return hashvalue; else return calchash(); } - unsigned tinfo() const {return tinfo_key;} + + unsigned gethash() const + { +#ifdef GINAC_COMPARE_STATISTICS + compare_statistics.total_gethash++; +#endif + if (flags & status_flags::hash_calculated) { +#ifdef GINAC_COMPARE_STATISTICS + compare_statistics.gethash_cached++; +#endif + return hashvalue; + } else { + return calchash(); + } + } /** Set some status_flags. */ const basic & setflag(unsigned f) const {flags |= f; return *this;} @@ -228,14 +298,10 @@ protected: // member variables protected: - unsigned tinfo_key; ///< typeinfo mutable unsigned flags; ///< of type status_flags mutable unsigned hashvalue; ///< hash value -private: - size_t refcount; ///< reference counter, managed by ptr }; - // global variables extern int max_recursion_level; @@ -247,18 +313,41 @@ extern int max_recursion_level; template inline bool is_a(const basic &obj) { - return dynamic_cast(&obj) != 0; + return dynamic_cast(&obj) != nullptr; } -/** Check if obj is a T, not including base classes. This one is just an - * inefficient default. It should in all time-critical cases be overridden - * by template specializations that use the TINFO_* constants directly. */ +/** Check if obj is a T, not including base classes. */ template -inline bool is_exactly_a(const basic &obj) +inline bool is_exactly_a(const basic & obj) +{ + return typeid(T) == typeid(obj); +} + +/** Constructs a new (class basic or derived) B object on the heap. + * + * This function picks the object's ctor based on the given argument types. + * + * This helps the constructor of ex from basic (or a derived class B) because + * then the constructor doesn't have to duplicate the object onto the heap. + * See ex::construct_from_basic(const basic &) for more information. + */ +template +inline B & dynallocate(Args &&... args) +{ + return const_cast(static_cast((new B(std::forward(args)...))->setflag(status_flags::dynallocated))); +} +/** Constructs a new (class basic or derived) B object on the heap. + * + * This function is needed for GiNaC classes which have public ctors from + * initializer lists of expressions (which are not a type and not captured + * by the variadic template version). + */ +template +inline B & dynallocate(std::initializer_list il) { - return obj.tinfo() == T::get_class_info_static().options.get_id(); + return const_cast(static_cast((new B(il))->setflag(status_flags::dynallocated))); } } // namespace GiNaC -#endif // ndef __GINAC_BASIC_H__ +#endif // ndef GINAC_BASIC_H