#include "debugmsg.h"
#include "utils.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
GINAC_IMPLEMENT_REGISTERED_CLASS(add, expairseq)
// protected
+/** For use by copy ctor and assignment operator. */
void add::copy(const add & other)
{
inherited::copy(other);
GINAC_ASSERT(is_canonical());
}
-/*
-add::add(const epvector & v, bool do_not_canonicalize)
-{
- debugmsg("add constructor from epvector,bool",LOGLEVEL_CONSTRUCT);
- tinfo_key = TINFO_add;
- if (do_not_canonicalize) {
- seq=v;
-#ifdef EXPAIRSEQ_USE_HASHTAB
- combine_same_terms(); // to build hashtab
-#endif // def EXPAIRSEQ_USE_HASHTAB
- } else {
- construct_from_epvector(v);
- }
- GINAC_ASSERT(is_canonical());
-}
-*/
-
add::add(const epvector & v)
{
debugmsg("add constructor from epvector",LOGLEVEL_CONSTRUCT);
debugmsg("add print csrc", LOGLEVEL_PRINT);
if (precedence <= upper_precedence)
os << "(";
-
+
// Print arguments, separated by "+"
epvector::const_iterator it = seq.begin();
epvector::const_iterator itend = seq.end();
while (it != itend) {
-
+
// If the coefficient is -1, it is replaced by a single minus sign
if (it->coeff.compare(_num1()) == 0) {
it->rest.bp->printcsrc(os, type, precedence);
os << "*";
it->rest.bp->printcsrc(os, type, precedence);
}
-
+
// Separator is "+", except if the following expression would have a leading minus sign
it++;
if (it != itend && !(it->coeff.compare(_num0()) < 0 || (it->coeff.compare(_num1()) == 0 && is_ex_exactly_of_type(it->rest, numeric) && it->rest.compare(_num0()) < 0)))
os << "+";
}
- if (!overall_coeff.is_equal(_ex0())) {
+ if (!overall_coeff.is_zero()) {
if (overall_coeff.info(info_flags::positive)) os << '+';
overall_coeff.bp->printcsrc(os,type,precedence);
}
int add::degree(const symbol & s) const
{
int deg = INT_MIN;
- if (!overall_coeff.is_equal(_ex0())) {
+ if (!overall_coeff.is_equal(_ex0()))
deg = 0;
- }
+
int cur_deg;
for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
- cur_deg=(*cit).rest.degree(s);
- if (cur_deg>deg) deg=cur_deg;
+ cur_deg = (*cit).rest.degree(s);
+ if (cur_deg>deg)
+ deg = cur_deg;
}
return deg;
}
int add::ldegree(const symbol & s) const
{
int deg = INT_MAX;
- if (!overall_coeff.is_equal(_ex0())) {
+ if (!overall_coeff.is_equal(_ex0()))
deg = 0;
- }
+
int cur_deg;
for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
cur_deg = (*cit).rest.ldegree(s);
{
// simplifications: +(;c) -> c
// +(x;1) -> x
-
+
debugmsg("add eval",LOGLEVEL_MEMBER_FUNCTION);
-
- epvector * evaled_seqp=evalchildren(level);
+
+ epvector * evaled_seqp = evalchildren(level);
if (evaled_seqp!=0) {
// do more evaluation later
return (new add(evaled_seqp,overall_coeff))->
#ifdef DO_GINAC_ASSERT
for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
GINAC_ASSERT(!is_ex_exactly_of_type((*cit).rest,add));
- if (is_ex_exactly_of_type((*cit).rest,numeric)) {
+ if (is_ex_exactly_of_type((*cit).rest,numeric))
dbgprint();
- }
GINAC_ASSERT(!is_ex_exactly_of_type((*cit).rest,numeric));
}
#endif // def DO_GINAC_ASSERT
if (flags & status_flags::evaluated) {
GINAC_ASSERT(seq.size()>0);
- GINAC_ASSERT((seq.size()>1)||!overall_coeff.is_equal(_ex0()));
+ GINAC_ASSERT(seq.size()>1 || !overall_coeff.is_zero());
return *this;
}
- int seq_size=seq.size();
+ int seq_size = seq.size();
if (seq_size==0) {
// +(;c) -> c
return overall_coeff;
- } else if ((seq_size==1)&&overall_coeff.is_equal(_ex0())) {
+ } else if ((seq_size==1) && overall_coeff.is_equal(_ex0())) {
// +(x;0) -> x
return recombine_pair_to_ex(*(seq.begin()));
}
expair add::split_ex_to_pair(const ex & e) const
{
if (is_ex_exactly_of_type(e,mul)) {
- const mul & mulref = ex_to_mul(e);
+ const mul &mulref = ex_to_mul(e);
ex numfactor = mulref.overall_coeff;
- // mul * mulcopyp = static_cast<mul *>(mulref.duplicate());
- mul * mulcopyp = new mul(mulref);
+ mul *mulcopyp = new mul(mulref);
mulcopyp->overall_coeff = _ex1();
mulcopyp->clearflag(status_flags::evaluated);
mulcopyp->clearflag(status_flags::hash_calculated);
- return expair(mulcopyp->setflag(status_flags::dynallocated),numfactor);
+ mulcopyp->setflag(status_flags::dynallocated);
+ return expair(*mulcopyp,numfactor);
}
return expair(e,_ex1());
}
mulcopyp->clearflag(status_flags::evaluated);
mulcopyp->clearflag(status_flags::hash_calculated);
mulcopyp->setflag(status_flags::dynallocated);
- if (are_ex_trivially_equal(c, _ex1())) {
+ if (are_ex_trivially_equal(c, _ex1()))
return expair(*mulcopyp, numfactor);
- } else if (are_ex_trivially_equal(numfactor, _ex1())) {
+ else if (are_ex_trivially_equal(numfactor, _ex1()))
return expair(*mulcopyp, c);
- }
- return expair(*mulcopyp, ex_to_numeric(numfactor).mul_dyn(ex_to_numeric(c)));
+ else
+ return expair(*mulcopyp, ex_to_numeric(numfactor).mul_dyn(ex_to_numeric(c)));
} else if (is_ex_exactly_of_type(e, numeric)) {
if (are_ex_trivially_equal(c, _ex1()))
return expair(e, _ex1());
}
return expair(e, c);
}
-
+
expair add::combine_pair_with_coeff_to_pair(const expair & p,
const ex & c) const
{
return *this;
epvector * vp = expandchildren(options);
- if (vp==0)
+ if (vp==0) {
+ // the terms have not changed, so it is safe to declare this expanded
+ setflag(status_flags::expanded);
return *this;
+ }
return (new add(vp,overall_coeff))->setflag(status_flags::expanded | status_flags::dynallocated);
}
unsigned add::precedence = 40;
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#include "expairseq.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
/** Sum of expressions. */
class add : public expairseq
{
GINAC_DECLARE_REGISTERED_CLASS(add, expairseq)
-
+
friend class mul;
friend class ncmul;
friend class power;
-
+
// other constructors
public:
add(const ex & lh, const ex & rh);
add(const exvector & v);
add(const epvector & v);
- //add(const epvector & v, bool do_not_canonicalize=0);
add(const epvector & v, const ex & oc);
add(epvector * vp, const ex & oc);
-
+
// functions overriding virtual functions from bases classes
public:
void print(std::ostream & os, unsigned upper_precedence=0) const;
ex thisexpairseq(epvector * vp, const ex & oc) const;
expair split_ex_to_pair(const ex & e) const;
expair combine_ex_with_coeff_to_pair(const ex & e,
- const ex & c) const;
+ const ex & c) const;
expair combine_pair_with_coeff_to_pair(const expair & p,
- const ex & c) const;
+ const ex & c) const;
ex recombine_pair_to_ex(const expair & p) const;
ex expand(unsigned options=0) const;
return static_cast<const add &>(*e.bp);
}
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#endif // ndef __GINAC_ADD_H__
#include "config.h"
#include "utils.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
/** Archive an expression.
}
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#include <vector>
#include <iostream>
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
class lst;
class archive;
std::istream &operator>>(std::istream &is, archive &ar);
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#endif // ndef __GINAC_ARCHIVE_H__
#ifndef __GINAC_ASSERTION_H__
#define __GINAC_ASSERTION_H__
-extern "C" {
-#include <assert.h>
-}
+#include <cassert>
#if !defined(GINAC_ASSERT)
#if defined(DO_GINAC_ASSERT)
+/** Assertion macro for checking invariances. */
#define GINAC_ASSERT(X) assert(X)
#else
+/** Assertion macro for checking invariances. */
#define GINAC_ASSERT(X) ((void)0)
#endif
#endif
#include "utils.h"
#include "debugmsg.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
GINAC_IMPLEMENT_REGISTERED_CLASS_NO_CTORS(basic, void)
//////////
-// default constructor, destructor, copy constructor assignment operator and helpers
+// default ctor, dtor, copy ctor assignment operator and helpers
//////////
// public
-#ifndef INLINE_BASIC_CONSTRUCTORS
-basic::basic() : flags(0), refcount(0), tinfo_key(TINFO_BASIC)
+basic::basic(const basic & other) : tinfo_key(TINFO_basic), flags(0), refcount(0)
{
- debugmsg("basic default constructor", LOGLEVEL_CONSTRUCT);
- // nothing to do
-}
-
-basic::~basic()
-{
- debugmsg("basic destructor", LOGLEVEL_DESTRUCT);
- destroy(false);
- GINAC_ASSERT((!(flags & status_flags::dynallocated))||(refcount==0));
-}
-
-basic::basic(const basic & other) : flags(0), refcount(0), tinfo_key(TINFO_BASIC)
-{
- debugmsg("basic copy constructor", LOGLEVEL_CONSTRUCT);
+ debugmsg("basic copy ctor", LOGLEVEL_CONSTRUCT);
copy(other);
}
-#endif
const basic & basic::operator=(const basic & other)
{
// protected
-// none (all inlined)
+// none (all conditionally inlined)
//////////
-// other constructors
+// other ctors
//////////
-#ifndef INLINE_BASIC_CONSTRUCTORS
-basic::basic(unsigned ti) : flags(0), refcount(0), tinfo_key(ti)
-{
- debugmsg("basic constructor with tinfo_key", LOGLEVEL_CONSTRUCT);
- // nothing to do
-}
-#endif
+// none (all conditionally inlined)
//////////
// 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);
+ debugmsg("basic ctor from archive_node", LOGLEVEL_CONSTRUCT);
// Reconstruct tinfo_key from class name
std::string class_name;
// public
-/** Output to stream formatted to be useful as ginsh input. */
+/** Output to ostream formatted as parsable (as in ginsh) input.
+ * Generally, superfluous parenthesis should be avoided as far as possible. */
void basic::print(std::ostream & os, unsigned upper_precedence) const
{
debugmsg("basic print",LOGLEVEL_PRINT);
os << "[basic object]";
}
-/** Output to stream in ugly raw format, so brave developers can have a look
+/** Output to ostream in ugly raw format, so brave developers can have a look
* at the underlying structure. */
void basic::printraw(std::ostream & os) const
{
os << "[basic object]";
}
-/** Output to stream formatted in tree- (indented-) form, so developers can
+/** Output to ostream formatted in tree- (indented-) form, so developers can
* have a look at the underlying structure. */
void basic::printtree(std::ostream & os, unsigned indent) const
{
}
}
-/** Output to stream formatted as C-source.
+/** Output to ostream formatted as C-source.
*
* @param os a stream for output
* @param type variable type (one of the csrc_types)
/** Little wrapper arount print to be called within a debugger.
* This is needed because you cannot call foo.print(cout) from within the
- * debugger because it might not know what cout is. This method can be invoked
- * with no argument and it will simply print to stdout.
+ * debugger because it might not know what cout is. This method can be
+ * invoked with no argument and it will simply print to stdout.
*
* @see basic::print*/
void basic::dbgprint(void) const
{
- print(std::cerr);
+ this->print(std::cerr);
std::cerr << std::endl;
}
* @see basic::printtree */
void basic::dbgprinttree(void) const
{
- printtree(std::cerr,0);
+ this->printtree(std::cerr,0);
}
+/** Create a new copy of this 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. */
basic * basic::duplicate() const
{
debugmsg("basic duplicate",LOGLEVEL_DUPLICATE);
* @see class info_flags */
bool basic::info(unsigned inf) const
{
- return false; // all possible properties are false for basic objects
+ // all possible properties are false for basic objects
+ return false;
}
/** Number of operands/members. */
}
/** Search ocurrences. An object 'has' an expression if it is the expression
- * itself or one of the children 'has' it. */
+ * itself or one of the children 'has' it. As a consequence (according to
+ * the definition of children) given e=x+y+z, e.has(x) is true but e.has(x+y)
+ * is false. */
bool basic::has(const ex & other) const
{
GINAC_ASSERT(other.bp!=0);
if (is_equal(*other.bp)) return true;
if (nops()>0) {
- for (unsigned i=0; i<nops(); i++) {
- if (op(i).has(other)) return true;
- }
+ for (unsigned i=0; i<nops(); i++)
+ if (op(i).has(other))
+ return true;
}
+
return false;
}
ex basic::collect(const symbol & s) const
{
ex x;
- int ldeg = this->ldegree(s);
- int deg = this->degree(s);
- for (int n=ldeg; n<=deg; n++) {
+ for (int n=this->ldegree(s); n<=this->degree(s); n++)
x += this->coeff(s,n)*power(s,n);
- }
+
return x;
}
-/* Perform automatic symbolic evaluations on expression. */
+/** Perform automatic non-interruptive symbolic evaluation on expression. */
ex basic::eval(int level) const
{
// There is nothing to do for basic objects:
return *this;
}
-/* Substitute a set of symbols. */
+/** Substitute a set of symbols by arbitrary expressions. The ex returned
+ * will already be evaluated. */
ex basic::subs(const lst & ls, const lst & lr) const
{
return *this;
throw(std::logic_error("differentiation not supported by this type"));
}
-/** Returns order relation between two objects of same type. Needs to be
- * implemented by each class. */
+/** Returns order relation between two objects of same type. This needs to be
+ * implemented by each class. It may never return anything else than 0,
+ * signalling equality, or +1 and -1 signalling inequality and determining
+ * the canonical ordering. */
int basic::compare_same_type(const basic & other) const
{
return compare_pointers(this, &other);
/** Returns true if two objects of same type are equal. Normally needs
* not be reimplemented as long as it wasn't overwritten by some parent
- * class, since it just calls complare_same_type(). */
+ * class, since it just calls compare_same_type(). The reason why this
+ * function exists is that sometimes it is easier to determine equality
+ * than an order relation and then it can be overridden. */
bool basic::is_equal_same_type(const basic & other) const
{
- return compare_same_type(other)==0;
+ return this->compare_same_type(other)==0;
}
unsigned basic::return_type(void) const
return tinfo();
}
+/** Compute the hash value of an object and if it makes sense to store it in
+ * the objects status_flags, do so. The method inherited from class basic
+ * computes a hash value based on the type and hash values of possible
+ * members. For this reason it is well suited for container classes but
+ * atomic classes should override this implementation because otherwise they
+ * would all end up with the same hashvalue. */
unsigned basic::calchash(void) const
{
- unsigned v=golden_ratio_hash(tinfo());
+ unsigned v = golden_ratio_hash(tinfo());
for (unsigned i=0; i<nops(); i++) {
- v=rotate_left_31(v);
+ v = rotate_left_31(v);
v ^= (const_cast<basic *>(this))->op(i).gethash();
}
-
- v = v & 0x7FFFFFFFU;
+
+ // mask out numeric hashes:
+ v &= 0x7FFFFFFFU;
// store calculated hash value only if object is already evaluated
if (flags & status_flags::evaluated) {
setflag(status_flags::hash_calculated);
- hashvalue=v;
+ hashvalue = v;
}
return v;
return subs(ls,lr);
}
-/** Compare objects to establish canonical order.
+/** Compare objects to establish canonical ordering.
* All compare functions return: -1 for *this less than other, 0 equal,
* 1 greater. */
int basic::compare(const basic & other) const
{
unsigned hash_this = gethash();
unsigned hash_other = other.gethash();
-
+
if (hash_this<hash_other) return -1;
if (hash_this>hash_other) return 1;
-
+
unsigned typeid_this = tinfo();
unsigned typeid_other = other.tinfo();
-
+
if (typeid_this<typeid_other) {
- /*
- cout << "hash collision, different types: "
- << *this << " and " << other << endl;
- this->printraw(cout);
- cout << " and ";
- other.printraw(cout);
- cout << endl;
- */
+// std::cout << "hash collision, different types: "
+// << *this << " and " << other << std::endl;
+// this->printraw(std::cout);
+// std::cout << " and ";
+// other.printraw(std::cout);
+// std::cout << std::endl;
return -1;
}
if (typeid_this>typeid_other) {
- /*
- cout << "hash collision, different types: "
- << *this << " and " << other << endl;
- this->printraw(cout);
- cout << " and ";
- other.printraw(cout);
- cout << endl;
- */
+// std::cout << "hash collision, different types: "
+// << *this << " and " << other << std::endl;
+// this->printraw(std::cout);
+// std::cout << " and ";
+// other.printraw(std::cout);
+// std::cout << std::endl;
return 1;
}
-
+
GINAC_ASSERT(typeid(*this)==typeid(other));
-
- int cmpval=compare_same_type(other);
- if ((cmpval!=0)&&(hash_this<0x80000000U)) {
- /*
- cout << "hash collision, same type: "
- << *this << " and " << other << endl;
- this->printraw(cout);
- cout << " and ";
- other.printraw(cout);
- cout << endl;
- */
+
+ int cmpval = compare_same_type(other);
+ if ((cmpval!=0) && (hash_this<0x80000000U)) {
+// std::cout << "hash collision, same type: "
+// << *this << " and " << other << std::endl;
+// this->printraw(std::cout);
+// std::cout << " and ";
+// other.printraw(std::cout);
+// std::cout << std::endl;
}
return cmpval;
}
-/** Test for equality. */
+/** Test for equality.
+ * This is only a quick test, meaning objects should be in the same domain.
+ * You might have to .expand(), .normal() objects first, depending on the
+ * domain of your computation, to get a more reliable answer.
+ *
+ * @see is_equal_same_type */
bool basic::is_equal(const basic & other) const
{
- unsigned hash_this = gethash();
- unsigned hash_other = other.gethash();
-
- if (hash_this!=hash_other) return false;
-
- unsigned typeid_this = tinfo();
- unsigned typeid_other = other.tinfo();
-
- if (typeid_this!=typeid_other) return false;
-
+ if (this->gethash()!=other.gethash())
+ return false;
+ if (this->tinfo()!=other.tinfo())
+ return false;
+
GINAC_ASSERT(typeid(*this)==typeid(other));
-
- return is_equal_same_type(other);
+
+ return this->is_equal_same_type(other);
}
// protected
/** Stop further evaluation.
+ *
* @see basic::eval */
const basic & basic::hold(void) const
{
- return setflag(status_flags::evaluated);
+ return this->setflag(status_flags::evaluated);
}
+/** Ensure the object may be modified without hurting others, throws if this
+ * is not the case. */
void basic::ensure_if_modifiable(void) const
{
- if (refcount>1)
+ if (this->refcount>1)
throw(std::runtime_error("cannot modify multiply referenced object"));
}
// global variables
//////////
-int max_recursion_level=1024;
+int max_recursion_level = 1024;
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#include "tinfos.h"
#include "assertion.h"
#include "registrar.h"
+/*#include "debugmsg.h"*/
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
-class basic;
class ex;
class symbol;
class lst;
// Cint doesn't like vector<..,default_alloc> but malloc_alloc is
// unstandardized and not supported by newer GCCs.
#if defined(__GNUC__) && ((__GNUC__ == 2) && (__GNUC_MINOR__ < 97))
-typedef std::vector<ex,malloc_alloc> exvector;
+ typedef std::vector<ex,malloc_alloc> exvector;
#else
-typedef std::vector<ex> exvector;
+ typedef std::vector<ex> exvector;
#endif
-#define INLINE_BASIC_CONSTRUCTORS
-
/** This class is the ABC (abstract base class) of GiNaC's class hierarchy.
* It is responsible for the reference counting. */
class basic
{
GINAC_DECLARE_REGISTERED_CLASS_NO_CTORS(basic, void)
-
+
friend class ex;
-
+
// member functions
-
- // default constructor, destructor, copy constructor assignment operator and helpers
+
+ // default ctor, dtor, copy ctor assignment operator and helpers
public:
- basic()
-#ifdef INLINE_BASIC_CONSTRUCTORS
- : tinfo_key(TINFO_basic), flags(0), refcount(0)
+ basic() : tinfo_key(TINFO_basic), flags(0), refcount(0)
{
+ /* debugmsg("basic default ctor", LOGLEVEL_CONSTRUCT); */
}
-#else
-;
-#endif // def INLINE_BASIC_CONSTRUCTORS
-
+ /** basic dtor, virtual because class ex will delete objects via ptr. */
virtual ~basic()
-#ifdef INLINE_BASIC_CONSTRUCTORS
{
- destroy(0);
+ /* debugmsg("basic dtor", LOGLEVEL_DESTRUCT); */
+ destroy(false);
GINAC_ASSERT((!(flags & status_flags::dynallocated))||(refcount==0));
}
-#else
-;
-#endif // def INLINE_BASIC_CONSTRUCTORS
-
- basic(const basic & other)
-#ifdef INLINE_BASIC_CONSTRUCTORS
- {
- copy(other);
- }
-#else
-;
-#endif // def INLINE_BASIC_CONSTRUCTORS
-
+ basic(const basic & other);
const basic & operator=(const basic & other);
-
protected:
+ /** For use by copy ctor and assignment operator. */
void copy(const basic & other)
{
flags = other.flags & ~status_flags::dynallocated;
hashvalue = other.hashvalue;
tinfo_key = other.tinfo_key;
}
- void destroy(bool call_parent) {}
-
- // other constructors
- basic(unsigned ti)
-#ifdef INLINE_BASIC_CONSTRUCTORS
- : tinfo_key(ti), flags(0), refcount(0)
+ /** For use by dtor and assignment operator. */
+ virtual void destroy(bool call_parent) { }
+
+ // other ctors
+ /** ctor with specified tinfo_key */
+ basic(unsigned ti) : tinfo_key(ti), flags(0), refcount(0)
{
+ /* debugmsg("basic ctor with tinfo_key", LOGLEVEL_CONSTRUCT); */
}
-#else
-;
-#endif // def INLINE_BASIC_CONSTRUCTORS
-
// functions overriding virtual functions from bases classes
// none
virtual unsigned return_type(void) const;
virtual unsigned return_type_tinfo(void) const;
virtual unsigned calchash(void) const;
- virtual ex expand(unsigned options=0) const;
-
+ virtual ex expand(unsigned options = 0) const;
+
// non-virtual functions in this class
public:
ex subs(const ex & e) const;
int compare(const basic & other) const;
bool is_equal(const basic & other) const;
const basic & hold(void) const;
- unsigned gethash(void) const {if (flags & status_flags::hash_calculated) return hashvalue; else return calchash();}
+ unsigned gethash(void) const { if (flags & status_flags::hash_calculated) return hashvalue; else return calchash(); }
unsigned tinfo(void) const {return tinfo_key;}
+ /** Set some status_flags. */
const basic & setflag(unsigned f) const {flags |= f; return *this;}
+ /** Clear some status_flags. */
const basic & clearflag(unsigned f) const {flags &= ~f; return *this;}
protected:
void ensure_if_modifiable(void) const;
-
+
// member variables
protected:
- unsigned tinfo_key;
- mutable unsigned flags;
- mutable unsigned hashvalue;
- static unsigned precedence;
- static unsigned delta_indent;
+ unsigned tinfo_key; ///< typeinfo
+ mutable unsigned flags; ///< of type status_flags
+ mutable unsigned hashvalue; ///< hash value
+ static unsigned precedence; ///< precedence for printing parens
+ static unsigned delta_indent; ///< precedence for printtree
private:
- unsigned refcount;
+ unsigned refcount; ///< Number of reference counts
};
// global variables
// convenience macros
-#ifndef NO_NAMESPACE_GINAC
-
/** Check if OBJ is a TYPE, including base classes. */
#define is_of_type(OBJ,TYPE) \
(dynamic_cast<const TYPE *>(&OBJ)!=0)
#define is_ex_exactly_of_type(OBJ,TYPE) \
((*(OBJ).bp).tinfo()==GiNaC::TINFO_##TYPE)
-#else // ndef NO_NAMESPACE_GINAC
-
-#define is_of_type(OBJ,TYPE) \
- (dynamic_cast<const TYPE *>(&OBJ)!=0)
-
-#define is_exactly_of_type(OBJ,TYPE) \
- ((OBJ).tinfo()==TINFO_##TYPE)
-
-#define is_ex_of_type(OBJ,TYPE) \
- (dynamic_cast<const TYPE *>((OBJ).bp)!=0)
-
-#define is_ex_exactly_of_type(OBJ,TYPE) \
- ((*(OBJ).bp).tinfo()==TINFO_##TYPE)
-
-#endif // ndef NO_NAMESPACE_GINAC
-
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#endif // ndef __GINAC_BASIC_H__
#include "utils.h"
#include "debugmsg.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
GINAC_IMPLEMENT_REGISTERED_CLASS(clifford, lortensor)
return clifford("gamma", mu);
}
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#include <string>
#include "lortensor.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
/** This class holds an object representing an element of the Clifford
clifford clifford_gamma(const ex & mu);
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#endif // ndef __GINAC_CLIFFORD_H__
#include "debugmsg.h"
#include "utils.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
GINAC_IMPLEMENT_REGISTERED_CLASS(color, indexed)
return sum;
}
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#include "indexed.h"
#include "ex.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
const unsigned MAX_REPRESENTATION_LABELS = 4;
const unsigned COLOR_EIGHT = 8; // N*N-1
ex brute_force_sum_color_indices(const ex & e);
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#endif // ndef __GINAC_COLOR_H__
#include "utils.h"
#include "debugmsg.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
GINAC_IMPLEMENT_REGISTERED_CLASS(coloridx, idx)
return inherited::compare_same_type(other);
}
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#include "idx.h"
#include "ex.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
/** Class of indices for color algebra objects, to tell them apart from
return static_cast<const coloridx &>(*e.bp);
}
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#endif // ndef __GINAC_COLORIDX_H__
#include "ex.h"
#include "archive.h"
#include "debugmsg.h"
+#include "utils.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
GINAC_IMPLEMENT_REGISTERED_CLASS(constant, basic)
//////////
-// default constructor, destructor, copy constructor assignment operator and helpers
+// default ctor, dtor, copy ctor assignment operator and helpers
//////////
// public
constant::constant() : basic(TINFO_constant), name(""), ef(0), number(0), serial(next_serial++)
{
- debugmsg("constant default constructor",LOGLEVEL_CONSTRUCT);
+ debugmsg("constant default ctor",LOGLEVEL_CONSTRUCT);
}
// protected
+/** For use by copy ctor and assignment operator. */
void constant::copy(const constant & other)
{
- basic::copy(other);
- name=other.name;
- serial=other.serial;
- ef=other.ef;
- if (other.number != 0) {
+ inherited::copy(other);
+ name = other.name;
+ serial = other.serial;
+ ef = other.ef;
+ if (other.number != 0)
number = new numeric(*other.number);
- } else {
+ else
number = 0;
- }
}
void constant::destroy(bool call_parent)
{
delete number;
if (call_parent)
- basic::destroy(call_parent);
+ inherited::destroy(call_parent);
}
//////////
-// other constructors
+// other ctors
//////////
// public
constant::constant(const std::string & initname, evalffunctype efun)
: basic(TINFO_constant), name(initname), ef(efun), number(0), serial(next_serial++)
{
- debugmsg("constant constructor from string, function",LOGLEVEL_CONSTRUCT);
+ debugmsg("constant ctor from string, function",LOGLEVEL_CONSTRUCT);
+ setflag(status_flags::evaluated);
}
constant::constant(const std::string & initname, const numeric & initnumber)
: basic(TINFO_constant), name(initname), ef(0), number(new numeric(initnumber)), serial(next_serial++)
{
- debugmsg("constant constructor from string, numeric",LOGLEVEL_CONSTRUCT);
+ debugmsg("constant ctor from string, numeric",LOGLEVEL_CONSTRUCT);
+ setflag(status_flags::evaluated);
}
//////////
/** 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);
+ debugmsg("constant ctor from archive_node", LOGLEVEL_CONSTRUCT);
}
/** Unarchive the object. */
if (ef!=0) {
return ef();
} else if (number != 0) {
- return *number;
+ return number->evalf();
}
return *this;
}
return serial==o->serial;
}
+unsigned constant::calchash(void) const
+{
+ hashvalue = golden_ratio_hash(tinfo() ^ serial);
+ // mask out numeric hashes:
+ hashvalue &= 0x7FFFFFFFU;
+
+ setflag(status_flags::hash_calculated);
+
+ return hashvalue;
+}
+
//////////
// new virtual functions which can be overridden by derived classes
//////////
// static member variables
//////////
-unsigned constant::next_serial=0;
+unsigned constant::next_serial = 0;
//////////
// global constants
/** Catalan's constant. (0.91597...) Diverts straight into CLN for evalf(). */
const constant Catalan("Catalan", CatalanEvalf);
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#include <string>
#include "basic.h"
+#include "ex.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
typedef ex (*evalffunctype)(void);
class constant : public basic
{
GINAC_DECLARE_REGISTERED_CLASS(constant, basic)
-
+
// member functions
-
- // other constructors
+
+ // other ctors
public:
- constant(const std::string & initname, evalffunctype efun=0);
+ constant(const std::string & initname, evalffunctype efun = 0);
constant(const std::string & initname, const numeric & initnumber);
-
+
// functions overriding virtual functions from bases classes
public:
- void print(std::ostream & os, unsigned upper_precedence=0) const;
+ void print(std::ostream & os, unsigned upper_precedence = 0) const;
void printraw(std::ostream & os) const;
void printtree(std::ostream & os, unsigned indent) const;
- void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence=0) const;
- ex evalf(int level=0) const;
+ void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence = 0) const;
+ ex evalf(int level = 0) const;
protected:
ex derivative(const symbol & s) const;
bool is_equal_same_type(const basic & other) const;
+ unsigned calchash(void) const;
// new virtual functions which can be overridden by derived classes
// none
-
+
// non-virtual functions in this class
// none
-
+
// member variables
-
+
private:
- std::string name;
+ std::string name; ///< printname of this constant
evalffunctype ef;
- numeric * number;
- unsigned serial; //! unique serial number for comparision
+ numeric *number; ///< numerical value this constant evalf()s to
+ unsigned serial; ///< unique serial number for comparison
static unsigned next_serial;
};
extern const constant Catalan;
extern const constant Euler;
-#ifndef NO_NAMESPACE_GINAC
+// utility functions
+inline const constant &ex_to_constant(const ex &e)
+{
+ return static_cast<const constant &>(*e.bp);
+}
+
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#endif // ndef __GINAC_CONSTANT_H__
<<'END_OF_CONSTRUCTORS_IMPLEMENTATION','const ex & param${N}',', ',' seq.push_back(param${N});',"\n");
${CONTAINER}::${CONTAINER}(${SEQ1}) : basic(TINFO_${CONTAINER})
{
- debugmsg(\"${CONTAINER} constructor from ${N}*ex\",LOGLEVEL_CONSTRUCT);
+ debugmsg(\"${CONTAINER} ctor from ${N}*ex\",LOGLEVEL_CONSTRUCT);
RESERVE(seq,${N});
${SEQ2}
}
#include "basic.h"
#include "ex.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
// Cint does not like ${STLHEADER}<..,default_alloc> but malloc_alloc is
return static_cast<${CONTAINER} &>(*e.bp);
}
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#endif // ndef __GINAC_${CONTAINER_UC}_H__
#include "archive.h"
#include "debugmsg.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
GINAC_IMPLEMENT_REGISTERED_CLASS(${CONTAINER}, basic)
${RESERVE_IMPLEMENTATION}
//////////
-// default constructor, destructor, copy constructor assignment operator and helpers
+// default ctor, dtor, copy ctor assignment operator and helpers
//////////
// public
${CONTAINER}::${CONTAINER}() : basic(TINFO_${CONTAINER})
{
- debugmsg("${CONTAINER} default constructor",LOGLEVEL_CONSTRUCT);
+ debugmsg("${CONTAINER} default ctor",LOGLEVEL_CONSTRUCT);
}
// protected
}
//////////
-// other constructors
+// other ctors
//////////
// public
${CONTAINER}::${CONTAINER}(${STLT} const & s, bool discardable) : basic(TINFO_${CONTAINER})
{
- debugmsg("${CONTAINER} constructor from ${STLT}", LOGLEVEL_CONSTRUCT);
+ debugmsg("${CONTAINER} ctor from ${STLT}", LOGLEVEL_CONSTRUCT);
if (discardable) {
seq.swap(const_cast<${STLT} &>(s));
} else {
${CONTAINER}::${CONTAINER}(${STLT} * vp) : basic(TINFO_${CONTAINER})
{
- debugmsg("${CONTAINER} constructor from ${STLT} *",LOGLEVEL_CONSTRUCT);
+ debugmsg("${CONTAINER} ctor from ${STLT} *",LOGLEVEL_CONSTRUCT);
GINAC_ASSERT(vp!=0);
seq.swap(*vp);
delete vp;
/** 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);
+ debugmsg("${CONTAINER} ctor from archive_node", LOGLEVEL_CONSTRUCT);
for (unsigned int i=0; true; i++) {
ex e;
if (n.find_ex("seq", e, sym_lst, i))
// protected
-unsigned ${CONTAINER}::precedence=10;
+unsigned ${CONTAINER}::precedence = 10;
//////////
// global constants
const ${CONTAINER} some_${CONTAINER};
const std::type_info & typeid_${CONTAINER} = typeid(some_${CONTAINER});
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
END_OF_IMPLEMENTATION
// #define LOGMASK (LOGLEVEL_PRINT | LOGLEVEL_ASSIGNMENT | LOGLEVEL_OPERATOR | LOGLEVEL_DUPLICATE | LOGLEVEL_OPERATOR | LOGLEVEL_MEMBER_FUNCTION | LOGLEVEL_NONMEMBER_FUNCTION)
#ifdef VERBOSE
-#define debugmsg(msg, loglevel) if ((loglevel) & ~LOGMASK) std::clog << (msg) << endl;
+#define debugmsg(msg, loglevel) if ((loglevel) & ~LOGMASK) std::clog << (msg) << std::endl;
#else
#define debugmsg(msg, loglevel)
#endif // def VERBOSE
#include <iostream>
#include <stdexcept>
-#include "ex.h"
+#if defined(VERBOSE)
+# define GINAC_CONDITIONAL_INLINE
+# include "ex.h"
+# undef GINAC_CONDITIONAL_INLINE
+#else
+# include "ex.h"
+#endif
+
#include "add.h"
#include "mul.h"
#include "ncmul.h"
#include "debugmsg.h"
#include "utils.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
//////////
-// default constructor, destructor, copy constructor assignment operator and helpers
+// other ctors
//////////
-// public
-
-#ifndef INLINE_EX_CONSTRUCTORS
-
-ex::ex() : bp(_ex0().bp)
-{
- debugmsg("ex default constructor",LOGLEVEL_CONSTRUCT);
- GINAC_ASSERT(_ex0().bp!=0);
- GINAC_ASSERT(_ex0().bp->flags & status_flags::dynallocated);
- GINAC_ASSERT(bp!=0);
- ++bp->refcount;
-}
-
-ex::~ex()
-{
- debugmsg("ex destructor",LOGLEVEL_DESTRUCT);
- GINAC_ASSERT(bp!=0);
- GINAC_ASSERT(bp->flags & status_flags::dynallocated);
- if (--bp->refcount == 0) {
- delete bp;
- }
-}
-
-ex::ex(const ex & other) : bp(other.bp)
-{
- debugmsg("ex copy constructor",LOGLEVEL_CONSTRUCT);
- GINAC_ASSERT(bp!=0);
- GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
- ++bp->refcount;
-}
-
-const ex & ex::operator=(const ex & other)
-{
- debugmsg("ex operator=",LOGLEVEL_ASSIGNMENT);
- GINAC_ASSERT(bp!=0);
- GINAC_ASSERT(bp->flags & status_flags::dynallocated);
- GINAC_ASSERT(other.bp!=0);
- GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
- ++other.bp->refcount;
- basic * tmpbp = other.bp;
- if (--bp->refcount==0)
- delete bp;
- bp = tmpbp;
- return *this;
-}
-
-#endif // ndef INLINE_EX_CONSTRUCTORS
-
-//////////
-// other constructors
-//////////
-
-// public
-
-#ifndef INLINE_EX_CONSTRUCTORS
-
-ex::ex(const basic & other)
-{
- debugmsg("ex constructor from basic",LOGLEVEL_CONSTRUCT);
- construct_from_basic(other);
-}
-
-ex::ex(int i)
-{
- debugmsg("ex constructor from int",LOGLEVEL_CONSTRUCT);
- construct_from_int(i);
-}
-
-ex::ex(unsigned int i)
-{
- debugmsg("ex constructor from unsigned int",LOGLEVEL_CONSTRUCT);
- construct_from_uint(i);
-}
-
-ex::ex(long i)
-{
- debugmsg("ex constructor from long",LOGLEVEL_CONSTRUCT);
- construct_from_long(i);
-}
-
-ex::ex(unsigned long i)
-{
- debugmsg("ex constructor from unsigned long",LOGLEVEL_CONSTRUCT);
- construct_from_ulong(i);
-}
-
-ex::ex(double const d)
-{
- debugmsg("ex constructor from double",LOGLEVEL_CONSTRUCT);
- construct_from_double(d);
-}
-
-ex::ex(const std::string &s, const ex &l)
-{
- debugmsg("ex constructor from string,lst",LOGLEVEL_CONSTRUCT);
- construct_from_string_and_lst(s, l);
-}
-
-#endif // ndef INLINE_EX_CONSTRUCTORS
+// none (all inlined)
//////////
// functions overriding virtual functions from bases classes
// public
-/** Swap the contents of two expressions. */
+/** Efficiently swap the contents of two expressions. */
void ex::swap(ex & other)
{
debugmsg("ex swap",LOGLEVEL_MEMBER_FUNCTION);
GINAC_ASSERT(other.bp!=0);
GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
- basic * tmpbp=bp;
- bp=other.bp;
- other.bp=tmpbp;
+ basic * tmpbp = bp;
+ bp = other.bp;
+ other.bp = tmpbp;
}
/** Output formatted to be useful as ginsh input. */
bp->print(os,upper_precedence);
}
+/** Unreadable output with detailed type information. */
void ex::printraw(std::ostream & os) const
{
debugmsg("ex printraw",LOGLEVEL_PRINT);
os << ")";
}
+/** Very detailed and unreadable output with type information and all this. */
void ex::printtree(std::ostream & os, unsigned indent) const
{
debugmsg("ex printtree",LOGLEVEL_PRINT);
return (*static_cast<relational *>(bp)).rhs();
}
-#ifndef INLINE_EX_CONSTRUCTORS
-int ex::compare(const ex & other) const
-{
- GINAC_ASSERT(bp!=0);
- GINAC_ASSERT(other.bp!=0);
- if (bp==other.bp) {
- // special case: both expression point to same basic, trivially equal
- return 0;
- }
- return bp->compare(*other.bp);
-}
-#endif // ndef INLINE_EX_CONSTRUCTORS
-
-#ifndef INLINE_EX_CONSTRUCTORS
-bool ex::is_equal(const ex & other) const
-{
- GINAC_ASSERT(bp!=0);
- GINAC_ASSERT(other.bp!=0);
- // if both expression point to same basic they are trivially equal
- if (bp==other.bp)
- return true;
-
- return bp->is_equal(*other.bp);
-}
-#endif // ndef INLINE_EX_CONSTRUCTORS
-
unsigned ex::return_type(void) const
{
GINAC_ASSERT(bp!=0);
// private
+/** Make this ex writable (if more than one ex handle the same basic) by
+ * unlinking the object and creating an unshared copy of it. */
void ex::makewriteable()
{
debugmsg("ex makewriteable",LOGLEVEL_MEMBER_FUNCTION);
GINAC_ASSERT(bp->refcount==1);
}
+/** Ctor from basic implementation.
+ * @see ex::ex(const basic &) */
void ex::construct_from_basic(const basic & other)
{
if ((other.flags & status_flags::evaluated)==0) {
- // cf. copy constructor
+ // cf. copy ctor
const ex & tmpex = other.eval(1); // evaluate only one (top) level
bp = tmpex.bp;
GINAC_ASSERT(bp!=0);
GINAC_ASSERT(bp->flags & status_flags::dynallocated);
++bp->refcount;
- if ((other.flags & status_flags::dynallocated)&&(other.refcount==0)) {
+ if ((other.flags & status_flags::dynallocated)&&(other.refcount==0))
delete &const_cast<basic &>(other);
- }
} else {
if (other.flags & status_flags::dynallocated) {
- // it's on the heap, so just copy bp:
+ // ok, it is already on the heap, so just copy bp:
bp = &const_cast<basic &>(other);
} else {
// create a duplicate on the heap:
// none
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#ifndef __GINAC_EX_H__
#define __GINAC_EX_H__
-#include <iostream>
#include "basic.h"
#include "operators.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
-
-class ex;
-class symbol;
-class lst;
// Sorry, this is the only constant to pollute the global scope, the other ones
// are defined in utils.h and not visible from outside.
-extern const ex & _ex0(void); // single ex(numeric(0))
+class ex;
+extern const ex & _ex0(void); ///< single ex(numeric(0))
-#define INLINE_EX_CONSTRUCTORS
+class symbol;
+class lst;
/** Lightweight wrapper for GiNaC's symbolic objects. Basically all it does is
* to hold a pointer to the other objects, manage the reference counting and
class ex
{
friend class basic;
-
+
// member functions
-
- // default constructor, destructor, copy constructor assignment operator and helpers
+
+ // default ctor, dtor, copy ctor assignment operator and helpers
public:
- ex()
-#ifdef INLINE_EX_CONSTRUCTORS
- : bp(_ex0().bp)
- {
- GINAC_ASSERT(_ex0().bp!=0);
- GINAC_ASSERT(_ex0().bp->flags & status_flags::dynallocated);
- GINAC_ASSERT(bp!=0);
- ++bp->refcount;
-#ifdef OBSCURE_CINT_HACK
- update_last_created_or_assigned_bp();
-#endif // def OBSCURE_CINT_HACK
- }
-#else
-;
-#endif // def INLINE_EX_CONSTRUCTORS
-
- ~ex()
-#ifdef INLINE_EX_CONSTRUCTORS
- {
- GINAC_ASSERT(bp!=0);
- GINAC_ASSERT(bp->flags & status_flags::dynallocated);
- if (--bp->refcount == 0) {
- delete bp;
- }
- }
-#else
-;
-#endif // def INLINE_EX_CONSTRUCTORS
-
- ex(const ex & other)
-#ifdef INLINE_EX_CONSTRUCTORS
- : bp(other.bp)
- {
- GINAC_ASSERT(bp!=0);
- GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
- ++bp->refcount;
-#ifdef OBSCURE_CINT_HACK
- update_last_created_or_assigned_bp();
-#endif // def OBSCURE_CINT_HACK
- }
-#else
-;
-#endif // def INLINE_EX_CONSTRUCTORS
-
- const ex & operator=(const ex & other)
-#ifdef INLINE_EX_CONSTRUCTORS
- {
- GINAC_ASSERT(bp!=0);
- GINAC_ASSERT(bp->flags & status_flags::dynallocated);
- GINAC_ASSERT(other.bp!=0);
- GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
- ++other.bp->refcount;
- basic * tmpbp=other.bp;
- if (--bp->refcount==0) {
- delete bp;
- }
- bp=tmpbp;
-#ifdef OBSCURE_CINT_HACK
- update_last_created_or_assigned_bp();
-#endif // def OBSCURE_CINT_HACK
- return *this;
- }
-#else
-;
-#endif // def INLINE_EX_CONSTRUCTORS
-
-
- // other constructors
+ ex();
+ ~ex();
+ ex(const ex & other);
+ const ex & operator=(const ex & other);
+ // other ctors
public:
- ex(const basic & other)
-#ifdef INLINE_EX_CONSTRUCTORS
- {
- construct_from_basic(other);
-#ifdef OBSCURE_CINT_HACK
- update_last_created_or_assigned_bp();
-#endif // def OBSCURE_CINT_HACK
- }
-#else
-;
-#endif // def INLINE_EX_CONSTRUCTORS
-
- ex(int i)
-#ifdef INLINE_EX_CONSTRUCTORS
- {
- construct_from_int(i);
-#ifdef OBSCURE_CINT_HACK
- update_last_created_or_assigned_bp();
-#endif // def OBSCURE_CINT_HACK
- }
-#else
-;
-#endif // def INLINE_EX_CONSTRUCTORS
-
- ex(unsigned int i)
-#ifdef INLINE_EX_CONSTRUCTORS
- {
- construct_from_uint(i);
-#ifdef OBSCURE_CINT_HACK
- update_last_created_or_assigned_bp();
-#endif // def OBSCURE_CINT_HACK
- }
-#else
-;
-#endif // def INLINE_EX_CONSTRUCTORS
-
- ex(long i)
-#ifdef INLINE_EX_CONSTRUCTORS
- {
- construct_from_long(i);
-#ifdef OBSCURE_CINT_HACK
- update_last_created_or_assigned_bp();
-#endif // def OBSCURE_CINT_HACK
- }
-#else
-;
-#endif // def INLINE_EX_CONSTRUCTORS
-
- ex(unsigned long i)
-#ifdef INLINE_EX_CONSTRUCTORS
- {
- construct_from_ulong(i);
-#ifdef OBSCURE_CINT_HACK
- update_last_created_or_assigned_bp();
-#endif // def OBSCURE_CINT_HACK
- }
-#else
-;
-#endif // def INLINE_EX_CONSTRUCTORS
-
- ex(double const d)
-#ifdef INLINE_EX_CONSTRUCTORS
- {
- construct_from_double(d);
-#ifdef OBSCURE_CINT_HACK
- update_last_created_or_assigned_bp();
-#endif // def OBSCURE_CINT_HACK
- }
-#else
-;
-#endif // def INLINE_EX_CONSTRUCTORS
-
+ ex(const basic & other);
+ ex(int i);
+ ex(unsigned int i);
+ ex(long i);
+ ex(unsigned long i);
+ ex(double const d);
/** Construct ex from string and a list of symbols. The input grammar is
* similar to the GiNaC output format. All symbols to be used in the
* expression must be specified in a lst in the second argument. Undefined
* symbols and other parser errors will throw an exception. */
- ex(const std::string &s, const ex &l)
-#ifdef INLINE_EX_CONSTRUCTORS
- {
- construct_from_string_and_lst(s, l);
-#ifdef OBSCURE_CINT_HACK
- update_last_created_or_assigned_bp();
-#endif // def OBSCURE_CINT_HACK
- }
-#else
-;
-#endif // def INLINE_EX_CONSTRUCTORS
-
+ ex(const std::string &s, const ex &l);
// functions overriding virtual functions from bases classes
// none
ex & let_op(int i);
ex lhs(void) const;
ex rhs(void) const;
- int compare(const ex & other) const
-#ifdef INLINE_EX_CONSTRUCTORS
- {
- GINAC_ASSERT(bp!=0);
- GINAC_ASSERT(other.bp!=0);
- if (bp==other.bp) {
- // special case: both expression point to same basic, trivially equal
- return 0;
- }
- return bp->compare(*other.bp);
- }
-#else
-;
-#endif // def INLINE_EX_CONSTRUCTORS
- bool is_equal(const ex & other) const
-#ifdef INLINE_EX_CONSTRUCTORS
- {
- GINAC_ASSERT(bp!=0);
- GINAC_ASSERT(other.bp!=0);
- if (bp==other.bp) {
- // special case: both expression point to same basic, trivially equal
- return true;
- }
- return bp->is_equal(*other.bp);
- }
-#else
-;
-#endif // def INLINE_EX_CONSTRUCTORS
- bool is_zero(void) const {return compare(_ex0())==0;};
-
+ int compare(const ex & other) const;
+ bool is_equal(const ex & other) const;
+ bool is_zero(void) const { return is_equal(_ex0()); }
+
unsigned return_type(void) const;
unsigned return_type_tinfo(void) const;
unsigned gethash(void) const;
-
+
ex exadd(const ex & rh) const;
ex exmul(const ex & rh) const;
ex exncmul(const ex & rh) const;
delete last_created_or_assigned_bp;
}
}
- last_created_or_assigned_bp=bp;
+ last_created_or_assigned_bp = bp;
++last_created_or_assigned_bp->refcount;
- last_created_or_assigned_exp=(long)(void *)(this);
+ last_created_or_assigned_exp = (long)(void *)(this);
}
#endif // def OBSCURE_CINT_HACK
// member variables
public:
- basic *bp;
+ basic *bp; ///< pointer to basic object managed by this
#ifdef OBSCURE_CINT_HACK
static basic * last_created_or_assigned_bp;
static basic * dummy_bp;
#endif // def OBSCURE_CINT_HACK
};
+
+// performance-critical inlined method implementations
+
+inline
+ex::ex() : bp(_ex0().bp)
+{
+ /*debugmsg("ex default ctor",LOGLEVEL_CONSTRUCT);*/
+ GINAC_ASSERT(_ex0().bp!=0);
+ GINAC_ASSERT(_ex0().bp->flags & status_flags::dynallocated);
+ GINAC_ASSERT(bp!=0);
+ ++bp->refcount;
+#ifdef OBSCURE_CINT_HACK
+ update_last_created_or_assigned_bp();
+#endif // def OBSCURE_CINT_HACK
+}
+
+inline
+ex::~ex()
+{
+ /*debugmsg("ex dtor",LOGLEVEL_DESTRUCT);*/
+ GINAC_ASSERT(bp!=0);
+ GINAC_ASSERT(bp->flags & status_flags::dynallocated);
+ if (--bp->refcount == 0)
+ delete bp;
+}
+
+inline
+ex::ex(const ex & other) : bp(other.bp)
+{
+ /*debugmsg("ex copy ctor",LOGLEVEL_CONSTRUCT);*/
+ GINAC_ASSERT(bp!=0);
+ GINAC_ASSERT((bp->flags) & status_flags::dynallocated);
+ ++bp->refcount;
+#ifdef OBSCURE_CINT_HACK
+ update_last_created_or_assigned_bp();
+#endif // def OBSCURE_CINT_HACK
+}
+
+inline
+const ex & ex::operator=(const ex & other)
+{
+ /*debugmsg("ex operator=",LOGLEVEL_ASSIGNMENT);*/
+ GINAC_ASSERT(bp!=0);
+ GINAC_ASSERT(bp->flags & status_flags::dynallocated);
+ GINAC_ASSERT(other.bp!=0);
+ GINAC_ASSERT(other.bp->flags & status_flags::dynallocated);
+ if (--bp->refcount==0)
+ delete bp;
+ ++other.bp->refcount;
+ bp = other.bp;
+#ifdef OBSCURE_CINT_HACK
+ update_last_created_or_assigned_bp();
+#endif // def OBSCURE_CINT_HACK
+ return *this;
+}
+
+inline
+ex::ex(const basic & other)
+{
+ /*debugmsg("ex ctor from basic",LOGLEVEL_CONSTRUCT);*/
+ construct_from_basic(other);
+#ifdef OBSCURE_CINT_HACK
+ update_last_created_or_assigned_bp();
+#endif // def OBSCURE_CINT_HACK
+}
+
+inline
+ex::ex(int i)
+{
+ /*debugmsg("ex ctor from int",LOGLEVEL_CONSTRUCT);*/
+ construct_from_int(i);
+#ifdef OBSCURE_CINT_HACK
+ update_last_created_or_assigned_bp();
+#endif // def OBSCURE_CINT_HACK
+}
+
+inline
+ex::ex(unsigned int i)
+{
+ /*debugmsg("ex ctor from unsigned int",LOGLEVEL_CONSTRUCT);*/
+ construct_from_uint(i);
+#ifdef OBSCURE_CINT_HACK
+ update_last_created_or_assigned_bp();
+#endif // def OBSCURE_CINT_HACK
+}
+
+inline
+ex::ex(long i)
+{
+ /*debugmsg("ex ctor from long",LOGLEVEL_CONSTRUCT);*/
+ construct_from_long(i);
+#ifdef OBSCURE_CINT_HACK
+ update_last_created_or_assigned_bp();
+#endif // def OBSCURE_CINT_HACK
+}
+
+inline
+ex::ex(unsigned long i)
+{
+ /*debugmsg("ex ctor from unsigned long",LOGLEVEL_CONSTRUCT);*/
+ construct_from_ulong(i);
+#ifdef OBSCURE_CINT_HACK
+ update_last_created_or_assigned_bp();
+#endif // def OBSCURE_CINT_HACK
+}
+
+inline
+ex::ex(double const d)
+{
+ /*debugmsg("ex ctor from double",LOGLEVEL_CONSTRUCT);*/
+ construct_from_double(d);
+#ifdef OBSCURE_CINT_HACK
+ update_last_created_or_assigned_bp();
+#endif // def OBSCURE_CINT_HACK
+}
+
+inline
+ex::ex(const std::string &s, const ex &l)
+{
+ /*debugmsg("ex ctor from string,lst",LOGLEVEL_CONSTRUCT);*/
+ construct_from_string_and_lst(s, l);
+#ifdef OBSCURE_CINT_HACK
+ update_last_created_or_assigned_bp();
+#endif // def OBSCURE_CINT_HACK
+}
+
+inline
+int ex::compare(const ex & other) const
+{
+ GINAC_ASSERT(bp!=0);
+ GINAC_ASSERT(other.bp!=0);
+ if (bp==other.bp) // trivial case: both expressions point to same basic
+ return 0;
+ return bp->compare(*other.bp);
+}
+
+inline
+bool ex::is_equal(const ex & other) const
+{
+ GINAC_ASSERT(bp!=0);
+ GINAC_ASSERT(other.bp!=0);
+ if (bp==other.bp) // trivial case: both expressions point to same basic
+ return true;
+ return bp->is_equal(*other.bp);
+}
+
+
// utility functions
inline bool are_ex_trivially_equal(const ex &e1, const ex &e2)
{
inline void swap(ex & e1, ex & e2)
{ e1.swap(e2); }
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#endif // ndef __GINAC_EX_H__
-
#include "ex.h"
#include "numeric.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
/** A pair of expressions.
- * This similar to, but slightly extended STL's pair<> but we need to account
- * for methods like .compare() */
+ * This is similar to STL's pair<>. It is slightly extended since we need to
+ * account for methods like .compare(). Also, since this is meant for use by
+ * class expairseq it must satisfy the invariance that the member coeff must
+ * be of type numeric. */
class expair
{
public:
- expair() {}
- ~expair() {}
-
+ expair() : rest(0), coeff(1) { }
+ ~expair() { }
expair(const expair & other) : rest(other.rest), coeff(other.coeff)
{
GINAC_ASSERT(is_ex_exactly_of_type(coeff,numeric));
}
-
const expair & operator=(const expair & other)
{
if (this != &other) {
- rest=other.rest;
- coeff=other.coeff;
+ rest = other.rest;
+ coeff = other.coeff;
}
return *this;
}
-
+
+ /** Construct an expair from two ex. */
expair(const ex & r, const ex & c) : rest(r), coeff(c)
{
GINAC_ASSERT(is_ex_exactly_of_type(coeff,numeric));
}
- bool is_numeric_with_coeff_1(void) const
- {
- GINAC_ASSERT(is_ex_exactly_of_type(coeff,numeric));
- return is_ex_exactly_of_type(rest,numeric)
- && (coeff.is_equal(ex(1)));
- }
-
+ /** Member-wise check for canonical ordering equality. */
bool is_equal(const expair & other) const
{
return (rest.is_equal(other.rest) && coeff.is_equal(other.coeff));
}
-
+
+ /** Member-wise check for canonical ordering lessness. */
bool is_less(const expair & other) const
{
- return (rest.compare(other.rest)<0)
- || (!(other.rest.compare(rest)<0) && (coeff.compare(other.coeff)<0));
+ int restcmp = rest.compare(other.rest);
+ return ((restcmp<0) ||
+ (!(restcmp>0) && (coeff.compare(other.coeff)<0)));
}
-
+
+ /** Member-wise check for canonical ordering. */
int compare(const expair & other) const
{
- int cmpval=rest.compare(other.rest);
- if (cmpval!=0) return cmpval;
- cmpval=coeff.compare(other.coeff);
- return cmpval;
- }
-
- bool is_less_old2(const expair & other) const
- {
- /*
- bool this_numeric_with_coeff_1=is_numeric_with_coeff_1();
- bool other_numeric_with_coeff_1=other.is_numeric_with_coeff_1();
- if (this_numeric_with_coeff_1) {
- if (other_numeric_with_coeff_1) {
- // both have coeff 1: compare rests
- return rest.compare(other.rest)<0;
- }
- // only this has coeff 1: >
- return false;
- } else if (other_numeric_with_coeff_1) {
- // only other has coeff 1: <
- return true;
- }
- return (rest.compare(other.rest)<0)
- || (!(other.rest.compare(rest)<0) && (coeff.compare(other.coeff)<0));
- */
- if (is_ex_exactly_of_type(rest,numeric) &&
- is_ex_exactly_of_type(other.rest,numeric)) {
- if (coeff.is_equal(ex(1))) {
- if ((other.coeff).is_equal(ex(1))) {
- // both have coeff 1: compare rests
- return rest.compare(other.rest)<0;
- }
- // only this has coeff 1: >
- return false;
- } else if ((other.coeff).is_equal(ex(1))) {
- // only other has coeff 1: <
- return true;
- }
- // neither has coeff 1: usual compare
- }
- return (rest.compare(other.rest)<0)
- || (!(other.rest.compare(rest)<0) && (coeff.compare(other.coeff)<0));
+ int restcmp = rest.compare(other.rest);
+ if (restcmp!=0)
+ return restcmp;
+ else
+ return coeff.compare(other.coeff);
}
-
- int compare_old2(const expair & other) const
- {
- if (is_ex_exactly_of_type(rest,numeric) &&
- is_ex_exactly_of_type(other.rest,numeric)) {
- if ((coeff).is_equal(ex(1))) {
- if ((other.coeff).is_equal(ex(1))) {
- // both have coeff 1: compare rests
- return rest.compare(other.rest);
- }
- // only this has coeff 1: >
- return 1;
- } else if ((other.coeff).is_equal(ex(1))) {
- // only other has coeff 1: <
- return -1;
- }
- // neither has coeff 1: usual compare
- }
- /*
- bool this_numeric_with_coeff_1=is_numeric_with_coeff_1();
- bool other_numeric_with_coeff_1=other.is_numeric_with_coeff_1();
- if (this_numeric_with_coeff_1) {
- if (other_numeric_with_coeff_1) {
- // both have coeff 1: compare rests
- return rest.compare(other.rest);
- }
- // only this has coeff 1: >
- return 1;
- } else if (other_numeric_with_coeff_1) {
- // only other has coeff 1: <
- return -1;
- // neither has coeff 1: usual compare
- }
- */
- int cmpval=rest.compare(other.rest);
- if (cmpval!=0) return cmpval;
- return coeff.compare(other.coeff);
- }
-
- bool is_less_old(const expair & other) const
- {
- return (rest.compare(other.rest)<0)
- || (!(other.rest.compare(rest)<0) && (coeff.compare(other.coeff)<0));
- }
- int compare_old(const expair & other) const
- {
- int cmpval=rest.compare(other.rest);
- if (cmpval!=0) return cmpval;
- cmpval=coeff.compare(other.coeff);
- return cmpval;
- }
-
+
+ /** Output to ostream in ugly raw format. */
void printraw(std::ostream & os) const
{
os << "expair(";
coeff.printraw(os);
os << ")";
}
-
- ex rest;
- ex coeff;
-};
-
-class expair_is_less
-{
-public:
- bool operator()(const expair & lh, const expair & rh) const
+
+ /** True if this is of the form (numeric,ex(1)). */
+ bool is_canonical_numeric(void) const
{
- return lh.is_less(rh);
+ GINAC_ASSERT(is_ex_exactly_of_type(coeff,numeric));
+ return (is_ex_exactly_of_type(rest,numeric) &&
+ (coeff.is_equal(1)));
}
+
+ ex rest; ///< first member of pair, an arbitrary expression
+ ex coeff; ///< second member of pair, must be numeric
};
-class expair_is_less_old
+/** Function object for insertion into third argument of STL's sort() etc. */
+class expair_is_less
{
public:
- bool operator()(const expair & lh, const expair & rh) const
+ bool operator()(const expair &lh, const expair &rh) const
{
- return lh.is_less_old(rh);
+ return lh.is_less(rh);
}
};
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#endif // ndef __GINAC_EXPAIR_H__
#include "debugmsg.h"
#include "utils.h"
-#ifndef NO_NAMESPACE_GINAC
-namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
+#if EXPAIRSEQ_USE_HASHTAB
+#include <cmath>
+#endif // EXPAIRSEQ_USE_HASHTAB
-#ifdef EXPAIRSEQ_USE_HASHTAB
-#error "FIXME: expair_needs_further_processing not yet implemented for hashtabs, sorry. A.F."
-#endif // def EXPAIRSEQ_USE_HASHTAB
+namespace GiNaC {
GINAC_IMPLEMENT_REGISTERED_CLASS_NO_CTORS(expairseq, basic)
class epp_is_less
{
public:
- bool operator()(const epp & lh, const epp & rh) const
+ bool operator()(const epp &lh, const epp &rh) const
{
return (*lh).is_less(*rh);
}
};
//////////
-// default constructor, destructor, copy constructor assignment operator and helpers
+// default ctor, dtor, copy ctor assignment operator and helpers
//////////
// public
-expairseq::expairseq(const expairseq & other)
+expairseq::expairseq(const expairseq &other)
{
- debugmsg("expairseq copy constructor",LOGLEVEL_CONSTRUCT);
+ debugmsg("expairseq copy ctor",LOGLEVEL_CONSTRUCT);
copy(other);
}
-const expairseq & expairseq::operator=(const expairseq & other)
+const expairseq &expairseq::operator=(const expairseq &other)
{
debugmsg("expairseq operator=",LOGLEVEL_ASSIGNMENT);
if (this != &other) {
// protected
-void expairseq::copy(const expairseq & other)
+/** For use by copy ctor and assignment operator. */
+void expairseq::copy(const expairseq &other)
{
inherited::copy(other);
- seq=other.seq;
- overall_coeff=other.overall_coeff;
-#ifdef EXPAIRSEQ_USE_HASHTAB
+ seq = other.seq;
+ overall_coeff = other.overall_coeff;
+#if EXPAIRSEQ_USE_HASHTAB
// copy hashtab
- hashtabsize=other.hashtabsize;
+ hashtabsize = other.hashtabsize;
if (hashtabsize!=0) {
- hashmask=other.hashmask;
+ hashmask = other.hashmask;
hashtab.resize(hashtabsize);
- epvector::const_iterator osb=other.seq.begin();
+ epvector::const_iterator osb = other.seq.begin();
for (unsigned i=0; i<hashtabsize; ++i) {
hashtab[i].clear();
for (epplist::const_iterator cit=other.hashtab[i].begin();
} else {
hashtab.clear();
}
-#endif // def EXPAIRSEQ_USE_HASHTAB
+#endif // EXPAIRSEQ_USE_HASHTAB
+}
+
+void expairseq::destroy(bool call_parent)
+{
+ if (call_parent)
+ basic::destroy(call_parent);
}
//////////
-// other constructors
+// other ctors
//////////
-expairseq::expairseq(const ex & lh, const ex & rh) : inherited(TINFO_expairseq)
+expairseq::expairseq(const ex &lh, const ex &rh) : inherited(TINFO_expairseq)
{
- debugmsg("expairseq constructor from ex,ex",LOGLEVEL_CONSTRUCT);
+ debugmsg("expairseq ctor from ex,ex",LOGLEVEL_CONSTRUCT);
construct_from_2_ex(lh,rh);
GINAC_ASSERT(is_canonical());
}
-expairseq::expairseq(const exvector & v) : inherited(TINFO_expairseq)
+expairseq::expairseq(const exvector &v) : inherited(TINFO_expairseq)
{
- debugmsg("expairseq constructor from exvector",LOGLEVEL_CONSTRUCT);
+ debugmsg("expairseq ctor from exvector",LOGLEVEL_CONSTRUCT);
construct_from_exvector(v);
GINAC_ASSERT(is_canonical());
}
-/*
-expairseq::expairseq(const epvector & v, bool do_not_canonicalize)
- : inherited(TINFO_expairseq)
-{
- debugmsg("expairseq constructor from epvector",LOGLEVEL_CONSTRUCT);
- if (do_not_canonicalize) {
- seq=v;
-#ifdef EXPAIRSEQ_USE_HASHTAB
- combine_same_terms(); // to build hashtab
-#endif // def EXPAIRSEQ_USE_HASHTAB
- } else {
- construct_from_epvector(v);
- }
- GINAC_ASSERT(is_canonical());
-}
-*/
-
-expairseq::expairseq(const epvector & v, const ex & oc)
+expairseq::expairseq(const epvector &v, const ex &oc)
: inherited(TINFO_expairseq), overall_coeff(oc)
{
- debugmsg("expairseq constructor from epvector,ex",LOGLEVEL_CONSTRUCT);
+ debugmsg("expairseq ctor from epvector,ex",LOGLEVEL_CONSTRUCT);
construct_from_epvector(v);
GINAC_ASSERT(is_canonical());
}
-expairseq::expairseq(epvector * vp, const ex & oc)
+expairseq::expairseq(epvector *vp, const ex &oc)
: inherited(TINFO_expairseq), overall_coeff(oc)
{
- debugmsg("expairseq constructor from epvector *,ex",LOGLEVEL_CONSTRUCT);
+ debugmsg("expairseq ctor from epvector *,ex",LOGLEVEL_CONSTRUCT);
GINAC_ASSERT(vp!=0);
construct_from_epvector(*vp);
delete vp;
/** Construct object from archive_node. */
expairseq::expairseq(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
-#ifdef EXPAIRSEQ_USE_HASHTAB
+#if EXPAIRSEQ_USE_HASHTAB
, hashtabsize(0)
#endif
{
- debugmsg("expairseq constructor from archive_node", LOGLEVEL_CONSTRUCT);
+ debugmsg("expairseq ctor from archive_node", LOGLEVEL_CONSTRUCT);
for (unsigned int i=0; true; i++) {
ex rest;
ex coeff;
// public
-basic * expairseq::duplicate() const
+basic *expairseq::duplicate() const
{
debugmsg("expairseq duplicate",LOGLEVEL_DUPLICATE);
return new expairseq(*this);
}
-void expairseq::print(std::ostream & os, unsigned upper_precedence) const
+void expairseq::print(std::ostream &os, unsigned upper_precedence) const
{
debugmsg("expairseq print",LOGLEVEL_PRINT);
os << "[[";
os << "]]";
}
-void expairseq::printraw(std::ostream & os) const
+void expairseq::printraw(std::ostream &os) const
{
debugmsg("expairseq printraw",LOGLEVEL_PRINT);
-
+
os << "expairseq(";
for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
os << "(";
os << ")";
}
-void expairseq::printtree(std::ostream & os, unsigned indent) const
+void expairseq::printtree(std::ostream &os, unsigned indent) const
{
debugmsg("expairseq printtree",LOGLEVEL_PRINT);
for (unsigned i=0; i<seq.size(); ++i) {
seq[i].rest.printtree(os,indent+delta_indent);
seq[i].coeff.printtree(os,indent+delta_indent);
- if (i!=seq.size()-1) {
+ if (i!=seq.size()-1)
os << std::string(indent+delta_indent,' ') << "-----" << std::endl;
- }
}
if (!overall_coeff.is_equal(default_overall_coeff())) {
os << std::string(indent+delta_indent,' ') << "-----" << std::endl;
overall_coeff.printtree(os,indent+delta_indent);
}
os << std::string(indent+delta_indent,' ') << "=====" << std::endl;
-#ifdef EXPAIRSEQ_USE_HASHTAB
+#if EXPAIRSEQ_USE_HASHTAB
os << std::string(indent+delta_indent,' ')
<< "hashtab size " << hashtabsize << std::endl;
if (hashtabsize==0) return;
#define MAXCOUNT 5
unsigned count[MAXCOUNT+1];
- for (int i=0; i<MAXCOUNT+1; ++i) count[i]=0;
+ for (int i=0; i<MAXCOUNT+1; ++i)
+ count[i] = 0;
unsigned this_bin_fill;
unsigned cum_fill_sq = 0;
unsigned cum_fill = 0;
for (unsigned i=0; i<hashtabsize; ++i) {
- this_bin_fill=0;
+ this_bin_fill = 0;
if (hashtab[i].size()>0) {
os << std::string(indent+delta_indent,' ')
<< "bin " << i << " with entries ";
for (epplist::const_iterator it=hashtab[i].begin();
- it!=hashtab[i].end(); ++it) {
+ it!=hashtab[i].end(); ++it) {
os << *it-seq.begin() << " ";
++this_bin_fill;
}
cum_fill += this_bin_fill;
cum_fill_sq += this_bin_fill*this_bin_fill;
}
- if (this_bin_fill<MAXCOUNT) {
+ if (this_bin_fill<MAXCOUNT)
++count[this_bin_fill];
- } else {
+ else
++count[MAXCOUNT];
- }
}
unsigned fact = 1;
double cum_prob = 0;
double lambda = (1.0*seq.size())/hashtabsize;
for (int k=0; k<MAXCOUNT; ++k) {
- if (k>0) fact *= k;
- double prob = pow(lambda,k)/fact*exp(-lambda);
+ if (k>0)
+ fact *= k;
+ double prob = std::pow(lambda,k)/fact * std::exp(-lambda);
cum_prob += prob;
os << std::string(indent+delta_indent,' ') << "bins with " << k << " entries: "
<< int(1000.0*count[k]/hashtabsize)/10.0 << "% (expected: "
os << std::string(indent+delta_indent,' ') << "average fill: "
<< (1.0*cum_fill)/hashtabsize
<< " (should be equal to " << (1.0*seq.size())/hashtabsize << ")" << std::endl;
-#endif // def EXPAIRSEQ_USE_HASHTAB
+#endif // EXPAIRSEQ_USE_HASHTAB
}
bool expairseq::info(unsigned inf) const
unsigned expairseq::nops() const
{
- if (overall_coeff.is_equal(default_overall_coeff())) {
+ if (overall_coeff.is_equal(default_overall_coeff()))
return seq.size();
- }
- return seq.size()+1;
+ else
+ return seq.size()+1;
}
ex expairseq::op(int i) const
{
- if (unsigned(i)<seq.size()) {
+ if (unsigned(i)<seq.size())
return recombine_pair_to_ex(seq[i]);
- }
GINAC_ASSERT(!overall_coeff.is_equal(default_overall_coeff()));
return overall_coeff;
}
-ex & expairseq::let_op(int i)
+ex &expairseq::let_op(int i)
{
throw(std::logic_error("let_op not defined for expairseq and derived classes (add,mul,...)"));
}
ex expairseq::eval(int level) const
{
- if ((level==1)&&(flags & status_flags::evaluated)) {
+ if ((level==1) && (flags &status_flags::evaluated))
return *this;
- }
-
- epvector * vp=evalchildren(level);
- if (vp==0) {
+
+ epvector *vp = evalchildren(level);
+ if (vp==0)
return this->hold();
- }
-
+
return (new expairseq(vp,overall_coeff))->setflag(status_flags::dynallocated | status_flags::evaluated);
}
return n.bp->basic::normal(sym_lst,repl_lst,level);
}
-ex expairseq::subs(const lst & ls, const lst & lr) const
+ex expairseq::subs(const lst &ls, const lst &lr) const
{
- epvector * vp=subschildren(ls,lr);
- if (vp==0) {
+ epvector *vp = subschildren(ls,lr);
+ if (vp==0)
return *this;
- }
+
return thisexpairseq(vp,overall_coeff);
}
// protected
-/** Implementation of ex::diff() for an expairseq. It differentiates all elements of the
- * sequence.
+/** Implementation of ex::diff() for an expairseq.
+ * It differentiates all elements of the sequence.
* @see ex::diff */
-ex expairseq::derivative(const symbol & s) const
+ex expairseq::derivative(const symbol &s) const
{
return thisexpairseq(diffchildren(s),overall_coeff);
}
-int expairseq::compare_same_type(const basic & other) const
+int expairseq::compare_same_type(const basic &other) const
{
GINAC_ASSERT(is_of_type(other, expairseq));
- const expairseq & o = static_cast<const expairseq &>(const_cast<basic &>(other));
-
+ const expairseq &o = static_cast<const expairseq &>(const_cast<basic &>(other));
+
int cmpval;
// compare number of elements
- if (seq.size() != o.seq.size()) {
+ if (seq.size() != o.seq.size())
return (seq.size()<o.seq.size()) ? -1 : 1;
- }
-
+
// compare overall_coeff
cmpval = overall_coeff.compare(o.overall_coeff);
- if (cmpval!=0) return cmpval;
-
- //if (seq.size()==0) return 0; // empty expairseq's are equal
-
-#ifdef EXPAIRSEQ_USE_HASHTAB
+ if (cmpval!=0)
+ return cmpval;
+
+#if EXPAIRSEQ_USE_HASHTAB
GINAC_ASSERT(hashtabsize==o.hashtabsize);
if (hashtabsize==0) {
-#endif // def EXPAIRSEQ_USE_HASHTAB
+#endif // EXPAIRSEQ_USE_HASHTAB
epvector::const_iterator cit1 = seq.begin();
epvector::const_iterator cit2 = o.seq.begin();
epvector::const_iterator last1 = seq.end();
cmpval = (*cit1).compare(*cit2);
if (cmpval!=0) return cmpval;
}
-
+
GINAC_ASSERT(cit1==last1);
GINAC_ASSERT(cit2==last2);
return 0;
-#ifdef EXPAIRSEQ_USE_HASHTAB
+#if EXPAIRSEQ_USE_HASHTAB
}
-
+
// compare number of elements in each hashtab entry
for (unsigned i=0; i<hashtabsize; ++i) {
unsigned cursize=hashtab[i].size();
- if (cursize != o.hashtab[i].size()) {
+ if (cursize != o.hashtab[i].size())
return (cursize < o.hashtab[i].size()) ? -1 : 1;
- }
}
// compare individual (sorted) hashtab entries
for (unsigned i=0; i<hashtabsize; ++i) {
- unsigned sz=hashtab[i].size();
+ unsigned sz = hashtab[i].size();
if (sz>0) {
- const epplist & eppl1=hashtab[i];
- const epplist & eppl2=o.hashtab[i];
- epplist::const_iterator it1=eppl1.begin();
- epplist::const_iterator it2=eppl2.begin();
+ const epplist &eppl1 = hashtab[i];
+ const epplist &eppl2 = o.hashtab[i];
+ epplist::const_iterator it1 = eppl1.begin();
+ epplist::const_iterator it2 = eppl2.begin();
while (it1!=eppl1.end()) {
- cmpval=(*(*it1)).compare(*(*it2));
- if (cmpval!=0) return cmpval;
+ cmpval = (*(*it1)).compare(*(*it2));
+ if (cmpval!=0)
+ return cmpval;
++it1;
++it2;
}
}
return 0; // equal
-#endif // def EXPAIRSEQ_USE_HASHTAB
+#endif // EXPAIRSEQ_USE_HASHTAB
}
-bool expairseq::is_equal_same_type(const basic & other) const
+bool expairseq::is_equal_same_type(const basic &other) const
{
- const expairseq & o=dynamic_cast<const expairseq &>(const_cast<basic &>(other));
-
+ const expairseq &o = dynamic_cast<const expairseq &>(const_cast<basic &>(other));
+
// compare number of elements
- if (seq.size() != o.seq.size()) return false;
-
+ if (seq.size()!=o.seq.size())
+ return false;
+
// compare overall_coeff
- if (!overall_coeff.is_equal(o.overall_coeff)) return false;
-
-#ifdef EXPAIRSEQ_USE_HASHTAB
+ if (!overall_coeff.is_equal(o.overall_coeff))
+ return false;
+
+#if EXPAIRSEQ_USE_HASHTAB
// compare number of elements in each hashtab entry
if (hashtabsize!=o.hashtabsize) {
- cout << "this:" << std::endl;
- printtree(cout,0);
- cout << "other:" << std::endl;
- other.printtree(cout,0);
+ std::cout << "this:" << std::endl;
+ printtree(std::cout,0);
+ std::cout << "other:" << std::endl;
+ other.printtree(std::cout,0);
}
GINAC_ASSERT(hashtabsize==o.hashtabsize);
if (hashtabsize==0) {
-#endif // def EXPAIRSEQ_USE_HASHTAB
- epvector::const_iterator cit1=seq.begin();
- epvector::const_iterator cit2=o.seq.begin();
- epvector::const_iterator last1=seq.end();
+#endif // EXPAIRSEQ_USE_HASHTAB
+ epvector::const_iterator cit1 = seq.begin();
+ epvector::const_iterator cit2 = o.seq.begin();
+ epvector::const_iterator last1 = seq.end();
while (cit1!=last1) {
if (!(*cit1).is_equal(*cit2)) return false;
}
return true;
-#ifdef EXPAIRSEQ_USE_HASHTAB
+#if EXPAIRSEQ_USE_HASHTAB
}
-
+
for (unsigned i=0; i<hashtabsize; ++i) {
- if (hashtab[i].size() != o.hashtab[i].size()) return false;
+ if (hashtab[i].size() != o.hashtab[i].size())
+ return false;
}
// compare individual sorted hashtab entries
for (unsigned i=0; i<hashtabsize; ++i) {
- unsigned sz=hashtab[i].size();
+ unsigned sz = hashtab[i].size();
if (sz>0) {
- const epplist & eppl1=hashtab[i];
- const epplist & eppl2=o.hashtab[i];
- epplist::const_iterator it1=eppl1.begin();
- epplist::const_iterator it2=eppl2.begin();
+ const epplist &eppl1 = hashtab[i];
+ const epplist &eppl2 = o.hashtab[i];
+ epplist::const_iterator it1 = eppl1.begin();
+ epplist::const_iterator it2 = eppl2.begin();
while (it1!=eppl1.end()) {
if (!(*(*it1)).is_equal(*(*it2))) return false;
++it1;
}
}
}
-
+
return true;
-#endif // def EXPAIRSEQ_USE_HASHTAB
+#endif // EXPAIRSEQ_USE_HASHTAB
}
unsigned expairseq::return_type(void) const
unsigned expairseq::calchash(void) const
{
- unsigned v=golden_ratio_hash(tinfo());
- epvector::const_iterator last=seq.end();
- for (epvector::const_iterator cit=seq.begin(); cit!=last; ++cit) {
-#ifndef EXPAIRSEQ_USE_HASHTAB
- v=rotate_left_31(v); // rotation would spoil commutativity
-#endif // ndef EXPAIRSEQ_USE_HASHTAB
- v ^= (*cit).rest.gethash();
+ unsigned v = golden_ratio_hash(tinfo());
+ for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
+#if !EXPAIRSEQ_USE_HASHTAB
+ v = rotate_left_31(v); // rotation would spoil commutativity
+#endif // EXPAIRSEQ_USE_HASHTAB
+ v ^= cit->rest.gethash();
+#if !EXPAIRSEQ_USE_HASHTAB
+ v = rotate_left_31(v);
+ v ^= cit->coeff.gethash();
+#endif // EXPAIRSEQ_USE_HASHTAB
}
-
+
v ^= overall_coeff.gethash();
- v=v & 0x7FFFFFFFU;
+ v &= 0x7FFFFFFFU;
// store calculated hash value only if object is already evaluated
- if (flags & status_flags::evaluated) {
+ if (flags &status_flags::evaluated) {
setflag(status_flags::hash_calculated);
- hashvalue=v;
+ hashvalue = v;
}
-
+
return v;
}
ex expairseq::expand(unsigned options) const
{
- epvector * vp = expandchildren(options);
+ epvector *vp = expandchildren(options);
if (vp==0) {
+ // the terms have not changed, so it is safe to declare this expanded
+ setflag(status_flags::expanded);
return *this;
}
+
return thisexpairseq(vp,overall_coeff);
}
// protected
-ex expairseq::thisexpairseq(const epvector & v, const ex & oc) const
+/** Create an object of this type.
+ * This method works similar to a constructor. It is useful because expairseq
+ * has (at least) two possible different semantics but we want to inherit
+ * methods thus avoiding code duplication. Sometimes a method in expairseq
+ * has to create a new one of the same semantics, which cannot be done by a
+ * ctor because the name (add, mul,...) is unknown on the expaiseq level. In
+ * order for this trick to work a derived class must of course override this
+ * definition. */
+ex expairseq::thisexpairseq(const epvector &v, const ex &oc) const
{
return expairseq(v,oc);
}
-ex expairseq::thisexpairseq(epvector * vp, const ex & oc) const
+ex expairseq::thisexpairseq(epvector *vp, const ex &oc) const
{
return expairseq(vp,oc);
}
-void expairseq::printpair(std::ostream & os, const expair & p, unsigned upper_precedence) const
+void expairseq::printpair(std::ostream &os, const expair &p, unsigned upper_precedence) const
{
os << "[[";
p.rest.bp->print(os,precedence);
os << "]]";
}
-void expairseq::printseq(std::ostream & os, char delim,
+void expairseq::printseq(std::ostream &os, char delim,
unsigned this_precedence,
unsigned upper_precedence) const
{
- if (this_precedence<=upper_precedence) os << "(";
+ if (this_precedence<=upper_precedence)
+ os << "(";
epvector::const_iterator it,it_last;
it_last=seq.end();
--it_last;
os << delim;
}
printpair(os,*it,this_precedence);
- if (!overall_coeff.is_equal(default_overall_coeff())) {
+ if (!overall_coeff.is_equal(default_overall_coeff()))
os << delim << overall_coeff;
- }
- if (this_precedence<=upper_precedence) os << ")";
-}
-expair expairseq::split_ex_to_pair(const ex & e) const
+ if (this_precedence<=upper_precedence)
+ os << ")";
+}
+
+
+/** Form an expair from an ex, using the corresponding semantics.
+ * @see expairseq::recombine_pair_to_ex() */
+expair expairseq::split_ex_to_pair(const ex &e) const
{
return expair(e,_ex1());
}
-expair expairseq::combine_ex_with_coeff_to_pair(const ex & e,
- const ex & c) const
+
+expair expairseq::combine_ex_with_coeff_to_pair(const ex &e,
+ const ex &c) const
{
GINAC_ASSERT(is_ex_exactly_of_type(c,numeric));
-
+
return expair(e,c);
}
-expair expairseq::combine_pair_with_coeff_to_pair(const expair & p,
- const ex & c) const
+
+expair expairseq::combine_pair_with_coeff_to_pair(const expair &p,
+ const ex &c) const
{
GINAC_ASSERT(is_ex_exactly_of_type(p.coeff,numeric));
GINAC_ASSERT(is_ex_exactly_of_type(c,numeric));
return expair(p.rest,ex_to_numeric(p.coeff).mul_dyn(ex_to_numeric(c)));
}
-ex expairseq::recombine_pair_to_ex(const expair & p) const
+
+/** Form an ex out of an expair, using the corresponding semantics.
+ * @see expairseq::split_ex_to_pair() */
+ex expairseq::recombine_pair_to_ex(const expair &p) const
{
return lst(p.rest,p.coeff);
}
bool expairseq::expair_needs_further_processing(epp it)
{
+#if EXPAIRSEQ_USE_HASHTAB
+ //# error "FIXME: expair_needs_further_processing not yet implemented for hashtabs, sorry. A.F."
+#endif // EXPAIRSEQ_USE_HASHTAB
return false;
}
return _ex0();
}
-void expairseq::combine_overall_coeff(const ex & c)
+void expairseq::combine_overall_coeff(const ex &c)
{
GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric));
GINAC_ASSERT(is_ex_exactly_of_type(c,numeric));
overall_coeff = ex_to_numeric(overall_coeff).add_dyn(ex_to_numeric(c));
}
-void expairseq::combine_overall_coeff(const ex & c1, const ex & c2)
+void expairseq::combine_overall_coeff(const ex &c1, const ex &c2)
{
GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric));
GINAC_ASSERT(is_ex_exactly_of_type(c1,numeric));
add_dyn(ex_to_numeric(c1).mul(ex_to_numeric(c2)));
}
-bool expairseq::can_make_flat(const expair & p) const
+bool expairseq::can_make_flat(const expair &p) const
{
return true;
}
-
+
//////////
// non-virtual functions in this class
//////////
-void expairseq::construct_from_2_ex_via_exvector(const ex & lh, const ex & rh)
+void expairseq::construct_from_2_ex_via_exvector(const ex &lh, const ex &rh)
{
exvector v;
v.reserve(2);
v.push_back(lh);
v.push_back(rh);
construct_from_exvector(v);
-#ifdef EXPAIRSEQ_USE_HASHTAB
+#if EXPAIRSEQ_USE_HASHTAB
GINAC_ASSERT((hashtabsize==0)||(hashtabsize>=minhashtabsize));
GINAC_ASSERT(hashtabsize==calc_hashtabsize(seq.size()));
-#endif // def EXPAIRSEQ_USE_HASHTAB
+#endif // EXPAIRSEQ_USE_HASHTAB
}
-void expairseq::construct_from_2_ex(const ex & lh, const ex & rh)
+void expairseq::construct_from_2_ex(const ex &lh, const ex &rh)
{
if (lh.bp->tinfo()==tinfo()) {
if (rh.bp->tinfo()==tinfo()) {
-#ifdef EXPAIRSEQ_USE_HASHTAB
+#if EXPAIRSEQ_USE_HASHTAB
unsigned totalsize = ex_to_expairseq(lh).seq.size() +
ex_to_expairseq(rh).seq.size();
if (calc_hashtabsize(totalsize)!=0) {
construct_from_2_ex_via_exvector(lh,rh);
} else {
-#endif // def EXPAIRSEQ_USE_HASHTAB
+#endif // EXPAIRSEQ_USE_HASHTAB
construct_from_2_expairseq(ex_to_expairseq(lh),
ex_to_expairseq(rh));
-#ifdef EXPAIRSEQ_USE_HASHTAB
+#if EXPAIRSEQ_USE_HASHTAB
}
-#endif // def EXPAIRSEQ_USE_HASHTAB
+#endif // EXPAIRSEQ_USE_HASHTAB
return;
} else {
-#ifdef EXPAIRSEQ_USE_HASHTAB
- unsigned totalsize=ex_to_expairseq(lh).seq.size()+1;
- if (calc_hashtabsize(totalsize) != 0) {
+#if EXPAIRSEQ_USE_HASHTAB
+ unsigned totalsize = ex_to_expairseq(lh).seq.size()+1;
+ if (calc_hashtabsize(totalsize)!=0) {
construct_from_2_ex_via_exvector(lh, rh);
} else {
-#endif // def EXPAIRSEQ_USE_HASHTAB
+#endif // EXPAIRSEQ_USE_HASHTAB
construct_from_expairseq_ex(ex_to_expairseq(lh), rh);
-#ifdef EXPAIRSEQ_USE_HASHTAB
+#if EXPAIRSEQ_USE_HASHTAB
}
-#endif // def EXPAIRSEQ_USE_HASHTAB
+#endif // EXPAIRSEQ_USE_HASHTAB
return;
}
} else if (rh.bp->tinfo()==tinfo()) {
-#ifdef EXPAIRSEQ_USE_HASHTAB
+#if EXPAIRSEQ_USE_HASHTAB
unsigned totalsize=ex_to_expairseq(rh).seq.size()+1;
if (calc_hashtabsize(totalsize)!=0) {
construct_from_2_ex_via_exvector(lh,rh);
} else {
-#endif // def EXPAIRSEQ_USE_HASHTAB
+#endif // EXPAIRSEQ_USE_HASHTAB
construct_from_expairseq_ex(ex_to_expairseq(rh),lh);
-#ifdef EXPAIRSEQ_USE_HASHTAB
+#if EXPAIRSEQ_USE_HASHTAB
}
-#endif // def EXPAIRSEQ_USE_HASHTAB
+#endif // EXPAIRSEQ_USE_HASHTAB
return;
}
-
-#ifdef EXPAIRSEQ_USE_HASHTAB
+
+#if EXPAIRSEQ_USE_HASHTAB
if (calc_hashtabsize(2)!=0) {
construct_from_2_ex_via_exvector(lh,rh);
return;
}
- hashtabsize=0;
-#endif // def EXPAIRSEQ_USE_HASHTAB
+ hashtabsize = 0;
+#endif // EXPAIRSEQ_USE_HASHTAB
if (is_ex_exactly_of_type(lh,numeric)) {
if (is_ex_exactly_of_type(rh,numeric)) {
combine_overall_coeff(rh);
seq.push_back(split_ex_to_pair(lh));
} else {
- expair p1=split_ex_to_pair(lh);
- expair p2=split_ex_to_pair(rh);
-
- int cmpval=p1.rest.compare(p2.rest);
+ expair p1 = split_ex_to_pair(lh);
+ expair p2 = split_ex_to_pair(rh);
+
+ int cmpval = p1.rest.compare(p2.rest);
if (cmpval==0) {
p1.coeff=ex_to_numeric(p1.coeff).add_dyn(ex_to_numeric(p2.coeff));
if (!ex_to_numeric(p1.coeff).is_zero()) {
}
}
-void expairseq::construct_from_2_expairseq(const expairseq & s1,
- const expairseq & s2)
+void expairseq::construct_from_2_expairseq(const expairseq &s1,
+ const expairseq &s2)
{
combine_overall_coeff(s1.overall_coeff);
combine_overall_coeff(s2.overall_coeff);
- epvector::const_iterator first1=s1.seq.begin();
- epvector::const_iterator last1=s1.seq.end();
- epvector::const_iterator first2=s2.seq.begin();
- epvector::const_iterator last2=s2.seq.end();
+ epvector::const_iterator first1 = s1.seq.begin();
+ epvector::const_iterator last1 = s1.seq.end();
+ epvector::const_iterator first2 = s2.seq.begin();
+ epvector::const_iterator last2 = s2.seq.end();
seq.reserve(s1.seq.size()+s2.seq.size());
bool needs_further_processing=false;
while (first1!=last1 && first2!=last2) {
- int cmpval=(*first1).rest.compare((*first2).rest);
+ int cmpval = (*first1).rest.compare((*first2).rest);
if (cmpval==0) {
// combine terms
- const numeric & newcoeff = ex_to_numeric((*first1).coeff).
+ const numeric &newcoeff = ex_to_numeric((*first1).coeff).
add(ex_to_numeric((*first2).coeff));
if (!newcoeff.is_zero()) {
seq.push_back(expair((*first1).rest,newcoeff));
seq.push_back(*first2);
++first2;
}
-
+
if (needs_further_processing) {
- epvector v=seq;
+ epvector v = seq;
seq.clear();
construct_from_epvector(v);
}
}
-void expairseq::construct_from_expairseq_ex(const expairseq & s,
- const ex & e)
+void expairseq::construct_from_expairseq_ex(const expairseq &s,
+ const ex &e)
{
combine_overall_coeff(s.overall_coeff);
if (is_ex_exactly_of_type(e,numeric)) {
combine_overall_coeff(e);
- seq=s.seq;
+ seq = s.seq;
return;
}
-
- epvector::const_iterator first=s.seq.begin();
- epvector::const_iterator last=s.seq.end();
- expair p=split_ex_to_pair(e);
-
+
+ epvector::const_iterator first = s.seq.begin();
+ epvector::const_iterator last = s.seq.end();
+ expair p = split_ex_to_pair(e);
+
seq.reserve(s.seq.size()+1);
- bool p_pushed=0;
-
+ bool p_pushed = false;
+
bool needs_further_processing=false;
-
+
// merge p into s.seq
while (first!=last) {
int cmpval=(*first).rest.compare(p.rest);
if (cmpval==0) {
// combine terms
- const numeric & newcoeff = ex_to_numeric((*first).coeff).
+ const numeric &newcoeff = ex_to_numeric((*first).coeff).
add(ex_to_numeric(p.coeff));
if (!newcoeff.is_zero()) {
seq.push_back(expair((*first).rest,newcoeff));
}
}
++first;
- p_pushed=1;
+ p_pushed = true;
break;
} else if (cmpval<0) {
seq.push_back(*first);
++first;
} else {
seq.push_back(p);
- p_pushed=1;
+ p_pushed = true;
break;
}
}
-
+
if (p_pushed) {
// while loop exited because p was pushed, now push rest of s.seq
while (first!=last) {
}
if (needs_further_processing) {
- epvector v=seq;
+ epvector v = seq;
seq.clear();
construct_from_epvector(v);
}
}
-void expairseq::construct_from_exvector(const exvector & v)
+void expairseq::construct_from_exvector(const exvector &v)
{
// simplifications: +(a,+(b,c),d) -> +(a,b,c,d) (associativity)
// +(d,b,c,a) -> +(a,b,c,d) (canonicalization)
// (same for (+,*) -> (*,^)
make_flat(v);
-#ifdef EXPAIRSEQ_USE_HASHTAB
+#if EXPAIRSEQ_USE_HASHTAB
combine_same_terms();
#else
canonicalize();
combine_same_terms_sorted_seq();
-#endif // def EXPAIRSEQ_USE_HASHTAB
+#endif // EXPAIRSEQ_USE_HASHTAB
+ return;
}
-void expairseq::construct_from_epvector(const epvector & v)
+void expairseq::construct_from_epvector(const epvector &v)
{
// simplifications: +(a,+(b,c),d) -> +(a,b,c,d) (associativity)
// +(d,b,c,a) -> +(a,b,c,d) (canonicalization)
// (same for (+,*) -> (*,^)
make_flat(v);
-#ifdef EXPAIRSEQ_USE_HASHTAB
+#if EXPAIRSEQ_USE_HASHTAB
combine_same_terms();
#else
canonicalize();
combine_same_terms_sorted_seq();
-#endif // def EXPAIRSEQ_USE_HASHTAB
+#endif // EXPAIRSEQ_USE_HASHTAB
+ return;
}
-void expairseq::make_flat(const exvector & v)
+/** Combine this expairseq with argument exvector.
+ * It cares for associativity as well as for special handling of numerics. */
+void expairseq::make_flat(const exvector &v)
{
- exvector::const_iterator cit, citend = v.end();
-
+ exvector::const_iterator cit;
+
// count number of operands which are of same expairseq derived type
// and their cumulative number of operands
- int nexpairseqs=0;
- int noperands=0;
- cit=v.begin();
- while (cit!=citend) {
- if (cit->bp->tinfo()==tinfo()) {
+ int nexpairseqs = 0;
+ int noperands = 0;
+
+ cit = v.begin();
+ while (cit!=v.end()) {
+ if (cit->bp->tinfo()==this->tinfo()) {
++nexpairseqs;
- noperands+=ex_to_expairseq(*cit).seq.size();
+ noperands += ex_to_expairseq(*cit).seq.size();
}
++cit;
}
-
+
// reserve seq and coeffseq which will hold all operands
seq.reserve(v.size()+noperands-nexpairseqs);
-
+
// copy elements and split off numerical part
- cit=v.begin();
- while (cit!=citend) {
- if (cit->bp->tinfo()==tinfo()) {
- const expairseq & subseqref=ex_to_expairseq(*cit);
+ cit = v.begin();
+ while (cit!=v.end()) {
+ if (cit->bp->tinfo()==this->tinfo()) {
+ const expairseq &subseqref = ex_to_expairseq(*cit);
combine_overall_coeff(subseqref.overall_coeff);
- epvector::const_iterator cit_s=subseqref.seq.begin();
+ epvector::const_iterator cit_s = subseqref.seq.begin();
while (cit_s!=subseqref.seq.end()) {
seq.push_back(*cit_s);
++cit_s;
}
} else {
- if (is_ex_exactly_of_type(*cit,numeric)) {
+ if (is_ex_exactly_of_type(*cit,numeric))
combine_overall_coeff(*cit);
- } else {
+ else
seq.push_back(split_ex_to_pair(*cit));
- }
}
++cit;
}
-
- /*
- cout << "after make flat" << std::endl;
- for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
- (*cit).printraw(cout);
- }
- cout << std::endl;
- */
+
+ return;
}
-void expairseq::make_flat(const epvector & v)
+/** Combine this expairseq with argument epvector.
+ * It cares for associativity as well as for special handling of numerics. */
+void expairseq::make_flat(const epvector &v)
{
- epvector::const_iterator cit, citend = v.end();
-
+ epvector::const_iterator cit;
+
// count number of operands which are of same expairseq derived type
// and their cumulative number of operands
- int nexpairseqs=0;
- int noperands=0;
-
+ int nexpairseqs = 0;
+ int noperands = 0;
+
cit = v.begin();
- while (cit!=citend) {
- if (cit->rest.bp->tinfo()==tinfo()) {
+ while (cit!=v.end()) {
+ if (cit->rest.bp->tinfo()==this->tinfo()) {
++nexpairseqs;
noperands += ex_to_expairseq((*cit).rest).seq.size();
}
++cit;
}
-
+
// reserve seq and coeffseq which will hold all operands
seq.reserve(v.size()+noperands-nexpairseqs);
-
+
// copy elements and split off numerical part
cit = v.begin();
- while (cit!=citend) {
- if ((cit->rest.bp->tinfo()==tinfo())&&can_make_flat(*cit)) {
- const expairseq & subseqref=ex_to_expairseq((*cit).rest);
+ while (cit!=v.end()) {
+ if (cit->rest.bp->tinfo()==this->tinfo() &&
+ this->can_make_flat(*cit)) {
+ const expairseq &subseqref = ex_to_expairseq((*cit).rest);
combine_overall_coeff(ex_to_numeric(subseqref.overall_coeff),
ex_to_numeric((*cit).coeff));
- epvector::const_iterator cit_s=subseqref.seq.begin();
+ epvector::const_iterator cit_s = subseqref.seq.begin();
while (cit_s!=subseqref.seq.end()) {
seq.push_back(expair((*cit_s).rest,
ex_to_numeric((*cit_s).coeff).mul_dyn(ex_to_numeric((*cit).coeff))));
++cit_s;
}
} else {
- if ((*cit).is_numeric_with_coeff_1()) {
- combine_overall_coeff((*cit).rest);
- //if (is_ex_exactly_of_type((*cit).rest,numeric)) {
- // combine_overall_coeff(recombine_pair_to_ex(*cit));
- } else {
+ if (cit->is_canonical_numeric())
+ combine_overall_coeff(cit->rest);
+ else
seq.push_back(*cit);
- }
}
++cit;
}
+ return;
}
-epvector * expairseq::bubblesort(epvector::iterator itbegin, epvector::iterator itend)
-{
- unsigned n=itend-itbegin;
-
- epvector * sp=new epvector;
- sp->reserve(n);
-
- epvector::iterator last=itend-1;
- for (epvector::iterator it1=itbegin; it1!=last; ++it1) {
- for (epvector::iterator it2=it1+1; it2!=itend; ++it2) {
- if ((*it2).rest.compare((*it1).rest)<0) {
- iter_swap(it1,it2);
- }
- }
- sp->push_back(*it1);
- }
- sp->push_back(*last);
- return sp;
-}
-
-epvector * expairseq::mergesort(epvector::iterator itbegin, epvector::iterator itend)
-{
- unsigned n=itend-itbegin;
- /*
- if (n==1) {
- epvector * sp=new epvector;
- sp->push_back(*itbegin);
- return sp;
- }
- */
- if (n<16) return bubblesort(itbegin, itend);
- unsigned m=n/2;
-
- epvector * s1p=mergesort(itbegin, itbegin+m);
- epvector * s2p=mergesort(itbegin+m, itend);
-
- epvector * sp=new epvector;
- sp->reserve(s1p->size()+s2p->size());
-
- epvector::iterator first1=s1p->begin();
- epvector::iterator last1=s1p->end();
-
- epvector::iterator first2=s2p->begin();
- epvector::iterator last2=s2p->end();
-
- while (first1 != last1 && first2 != last2) {
- if ((*first1).rest.compare((*first2).rest)<0) {
- sp->push_back(*first1);
- ++first1;
- } else {
- sp->push_back(*first2);
- ++first2;
- }
- }
-
- if (first1 != last1) {
- while (first1 != last1) {
- sp->push_back(*first1);
- ++first1;
- }
- } else {
- while (first2 != last2) {
- sp->push_back(*first2);
- ++first2;
- }
- }
-
- delete s1p;
- delete s2p;
-
- return sp;
-}
-
+/** Brings this expairseq into a sorted (canonical) form. */
void expairseq::canonicalize(void)
{
// canonicalize
sort(seq.begin(),seq.end(),expair_is_less());
- /*
- sort(seq.begin(),seq.end(),expair_is_less_old());
- if (seq.size()>1) {
- if (is_ex_exactly_of_type((*(seq.begin())).rest,numeric)) {
- sort(seq.begin(),seq.end(),expair_is_less());
- } else {
- epvector::iterator last_numeric=seq.end();
- do {
- last_numeric--;
- } while (is_ex_exactly_of_type((*last_numeric).rest,numeric));
- ++last_numeric;
- sort(last_numeric,seq.end(),expair_is_less());
- }
- }
- */
-
- /*
- epvector * sorted_seqp=mergesort(seq.begin(),seq.end());
- epvector::iterator last=sorted_seqp->end();
- epvector::iterator it2=seq.begin();
- for (epvector::iterator it1=sorted_seqp->begin(); it1!=last; ++it1, ++it2) {
- iter_swap(it1,it2);
- }
- delete sorted_seqp;
- */
-
- /*
- cout << "after canonicalize" << std::endl;
- for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
- (*cit).printraw(cout);
- }
- cout << std::endl;
- cout.flush();
- */
+ return;
}
+
+/** Compact a presorted expairseq by combining all matching expairs to one
+ * each. On an add object, this is responsible for 2*x+3*x+y -> 5*x+y, for
+ * instance. */
void expairseq::combine_same_terms_sorted_seq(void)
{
- bool needs_further_processing=false;
+ bool needs_further_processing = false;
- // combine same terms, drop term with coeff 0
if (seq.size()>1) {
- epvector::iterator itin1=seq.begin();
- epvector::iterator itin2=itin1+1;
- epvector::iterator itout=itin1;
- epvector::iterator last=seq.end();
- // must_copy will be set to true the first time some combination is possible
- // from then on the sequence has changed and must be compacted
- bool must_copy=false;
+ epvector::iterator itin1 = seq.begin();
+ epvector::iterator itin2 = itin1+1;
+ epvector::iterator itout = itin1;
+ epvector::iterator last = seq.end();
+ // must_copy will be set to true the first time some combination is
+ // possible from then on the sequence has changed and must be compacted
+ bool must_copy = false;
while (itin2!=last) {
if ((*itin1).rest.compare((*itin2).rest)==0) {
(*itin1).coeff = ex_to_numeric((*itin1).coeff).
add_dyn(ex_to_numeric((*itin2).coeff));
- if (expair_needs_further_processing(itin1)) {
+ if (expair_needs_further_processing(itin1))
needs_further_processing = true;
- }
- must_copy=true;
+ must_copy = true;
} else {
if (!ex_to_numeric((*itin1).coeff).is_zero()) {
- if (must_copy) {
- *itout=*itin1;
- }
+ if (must_copy)
+ *itout = *itin1;
++itout;
}
- itin1=itin2;
+ itin1 = itin2;
}
++itin2;
}
if (!ex_to_numeric((*itin1).coeff).is_zero()) {
- if (must_copy) {
- *itout=*itin1;
- }
+ if (must_copy)
+ *itout = *itin1;
++itout;
}
- if (itout!=last) {
+ if (itout!=last)
seq.erase(itout,last);
- }
}
-
- /*
- cout << "after combine" << std::endl;
- for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
- (*cit).printraw(cout);
- }
- cout << std::endl;
- cout.flush();
- */
if (needs_further_processing) {
- epvector v=seq;
+ epvector v = seq;
seq.clear();
construct_from_epvector(v);
}
+ return;
}
-#ifdef EXPAIRSEQ_USE_HASHTAB
+#if EXPAIRSEQ_USE_HASHTAB
unsigned expairseq::calc_hashtabsize(unsigned sz) const
{
unsigned size;
unsigned nearest_power_of_2 = 1 << log2(sz);
- // if (nearest_power_of_2 < maxhashtabsize/hashtabfactor) {
- // size=nearest_power_of_2*hashtabfactor;
- size=nearest_power_of_2/hashtabfactor;
- if (size<minhashtabsize) return 0;
+ // if (nearest_power_of_2 < maxhashtabsize/hashtabfactor) {
+ // size = nearest_power_of_2*hashtabfactor;
+ size = nearest_power_of_2/hashtabfactor;
+ if (size<minhashtabsize)
+ return 0;
GINAC_ASSERT(hashtabsize<=0x8000000U); // really max size due to 31 bit hashing
// hashtabsize must be a power of 2
GINAC_ASSERT((1U << log2(size))==size);
return size;
}
-unsigned expairseq::calc_hashindex(const ex & e) const
+unsigned expairseq::calc_hashindex(const ex &e) const
{
// calculate hashindex
- unsigned hash=e.gethash();
+ unsigned hash = e.gethash();
unsigned hashindex;
if (is_a_numeric_hash(hash)) {
hashindex = hashmask;
} else {
- hashindex = hash & hashmask;
+ hashindex = hash &hashmask;
// last hashtab entry is reserved for numerics
if (hashindex==hashmask) hashindex = 0;
}
}
// shrink by a factor of 2
- unsigned half_hashtabsize=hashtabsize/2;
+ unsigned half_hashtabsize = hashtabsize/2;
for (unsigned i=0; i<half_hashtabsize-1; ++i)
hashtab[i].merge(hashtab[i+half_hashtabsize],epp_is_less());
// special treatment for numeric hashes
void expairseq::remove_hashtab_entry(epvector::const_iterator element)
{
- if (hashtabsize==0) return; // nothing to do
+ if (hashtabsize==0)
+ return; // nothing to do
// calculate hashindex of element to be deleted
unsigned hashindex = calc_hashindex((*element).rest);
// find it in hashtab and remove it
- epplist & eppl = hashtab[hashindex];
+ epplist &eppl = hashtab[hashindex];
epplist::iterator epplit = eppl.begin();
bool erased = false;
while (epplit!=eppl.end()) {
cout << "size " << seq.end()-seq.begin() << std::endl;
unsigned hashindex = calc_hashindex((*element).rest);
- epplist & eppl = hashtab[hashindex];
+ epplist &eppl = hashtab[hashindex];
epplist::iterator epplit=eppl.begin();
bool erased=false;
while (epplit!=eppl.end()) {
}
void expairseq::move_hashtab_entry(epvector::const_iterator oldpos,
- epvector::iterator newpos)
+ epvector::iterator newpos)
{
GINAC_ASSERT(hashtabsize!=0);
unsigned hashindex=calc_hashindex((*newpos).rest);
// find it in hashtab and modify it
- epplist & eppl = hashtab[hashindex];
- epplist::iterator epplit=eppl.begin();
+ epplist &eppl = hashtab[hashindex];
+ epplist::iterator epplit = eppl.begin();
while (epplit!=eppl.end()) {
if (*epplit == oldpos) {
- *epplit=newpos;
+ *epplit = newpos;
break;
}
++epplit;
GINAC_ASSERT(epplit!=eppl.end());
}
-void expairseq::sorted_insert(epplist & eppl, epp elem)
+void expairseq::sorted_insert(epplist &eppl, epp elem)
{
epplist::iterator current = eppl.begin();
while ((current!=eppl.end())&&((*(*current)).is_less(*elem))) {
eppl.insert(current,elem);
}
-void expairseq::build_hashtab_and_combine(epvector::iterator & first_numeric,
- epvector::iterator & last_non_zero,
- vector<bool> & touched,
- unsigned & number_of_zeroes)
+void expairseq::build_hashtab_and_combine(epvector::iterator &first_numeric,
+ epvector::iterator &last_non_zero,
+ vector<bool> &touched,
+ unsigned &number_of_zeroes)
{
epp current=seq.begin();
iter_swap(current,first_numeric);
} else {
// calculate hashindex
- unsigned currenthashindex=calc_hashindex((*current).rest);
+ unsigned currenthashindex = calc_hashindex((*current).rest);
// test if there is already a matching expair in the hashtab-list
- epplist & eppl=hashtab[currenthashindex];
- epplist::iterator epplit=eppl.begin();
+ epplist &eppl=hashtab[currenthashindex];
+ epplist::iterator epplit = eppl.begin();
while (epplit!=eppl.end()) {
- if ((*current).rest.is_equal((*(*epplit)).rest)) break;
+ if ((*current).rest.is_equal((*(*epplit)).rest))
+ break;
++epplit;
}
if (epplit==eppl.end()) {
}
}
}
-}
+}
-void expairseq::drop_coeff_0_terms(epvector::iterator & first_numeric,
- epvector::iterator & last_non_zero,
- vector<bool> & touched,
- unsigned & number_of_zeroes)
+void expairseq::drop_coeff_0_terms(epvector::iterator &first_numeric,
+ epvector::iterator &last_non_zero,
+ vector<bool> &touched,
+ unsigned &number_of_zeroes)
{
// move terms with coeff 0 to end and remove them from hashtab
// check only those elements which have been touched
- epp current=seq.begin();
- unsigned i=0;
+ epp current = seq.begin();
+ unsigned i = 0;
while (current!=first_numeric) {
if (!touched[i]) {
++current;
++i;
- } else if (!ex_to_numeric((*current).coeff).is_equal(_num0())) {
+ } else if (!ex_to_numeric((*current).coeff).is_zero()) {
++current;
++i;
} else {
remove_hashtab_entry(current);
-
+
// move element to the end, unless it is already at the end
if (current!=last_non_zero) {
iter_swap(current,last_non_zero);
if (numeric_swapped) iter_swap(first_numeric,current);
epvector::iterator changed_entry;
- if (numeric_swapped) {
- changed_entry=first_numeric;
- } else {
- changed_entry=last_non_zero;
- }
-
+ if (numeric_swapped)
+ changed_entry = first_numeric;
+ else
+ changed_entry = last_non_zero;
+
--last_non_zero;
++number_of_zeroes;
// change entry in hashtab which referred to first_numeric or last_non_zero to current
move_hashtab_entry(changed_entry,current);
- touched[current-seq.begin()]=touched[changed_entry-seq.begin()];
+ touched[current-seq.begin()] = touched[changed_entry-seq.begin()];
}
} else {
--first_numeric;
bool expairseq::has_coeff_0(void) const
{
for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
- if ((*cit).coeff.is_equal(_ex0())) {
+ if ((*cit).coeff.is_zero())
return true;
- }
}
return false;
}
epvector::const_iterator last_non_zero)
{
if (first_numeric==seq.end()) return; // no numerics
-
- epvector::iterator current=first_numeric;
- epvector::const_iterator last=last_non_zero+1;
+
+ epvector::iterator current = first_numeric;
+ epvector::const_iterator last = last_non_zero+1;
while (current!=last) {
sorted_insert(hashtab[hashmask],current);
++current;
// calculate size of hashtab
hashtabsize = calc_hashtabsize(seq.size());
-
+
// hashtabsize is a power of 2
hashmask = hashtabsize-1;
-
+
// allocate hashtab
hashtab.clear();
hashtab.resize(hashtabsize);
-
+
if (hashtabsize==0) {
canonicalize();
combine_same_terms_sorted_seq();
GINAC_ASSERT(!has_coeff_0());
return;
}
-
+
// iterate through seq, move numerics to end,
// fill hashtab and combine same terms
- epvector::iterator first_numeric=seq.end();
- epvector::iterator last_non_zero=seq.end()-1;
-
+ epvector::iterator first_numeric = seq.end();
+ epvector::iterator last_non_zero = seq.end()-1;
+
vector<bool> touched;
touched.reserve(seq.size());
for (unsigned i=0; i<seq.size(); ++i) touched[i]=false;
-
+
unsigned number_of_zeroes = 0;
-
+
GINAC_ASSERT(!has_coeff_0());
build_hashtab_and_combine(first_numeric,last_non_zero,touched,number_of_zeroes);
/*
cout << "end in combine after drop" << std::endl;
*/
}
-
+
add_numerics_to_hashtab(first_numeric,last_non_zero);
-
+
// pop zero elements
for (unsigned i=0; i<number_of_zeroes; ++i) {
seq.pop_back();
}
-
+
// shrink hashtabsize to calculated value
GINAC_ASSERT(!has_coeff_0());
-
+
shrink_hashtab();
-
+
GINAC_ASSERT(!has_coeff_0());
}
-#endif // def EXPAIRSEQ_USE_HASHTAB
+#endif // EXPAIRSEQ_USE_HASHTAB
+/** Check if this expairseq is in sorted (canonical) form. Useful mainly for
+ * debugging or in assertions since being sorted is an invariance. */
bool expairseq::is_canonical() const
{
- if (seq.size()<=1) return 1;
-
-#ifdef EXPAIRSEQ_USE_HASHTAB
+ if (seq.size()<=1)
+ return 1;
+
+#if EXPAIRSEQ_USE_HASHTAB
if (hashtabsize>0) return 1; // not canoncalized
-#endif // def EXPAIRSEQ_USE_HASHTAB
+#endif // EXPAIRSEQ_USE_HASHTAB
epvector::const_iterator it = seq.begin();
epvector::const_iterator it_last = it;
return 1;
}
+
+/** Member-wise expand the expairs in this sequence.
+ *
+ * @see expairseq::expand()
+ * @return pointer to epvector containing expanded pairs or zero pointer,
+ * if no members were changed. */
epvector * expairseq::expandchildren(unsigned options) const
{
epvector::const_iterator last = seq.end();
epvector::const_iterator cit = seq.begin();
while (cit!=last) {
- const ex & expanded_ex=(*cit).rest.expand(options);
+ const ex &expanded_ex = (*cit).rest.expand(options);
if (!are_ex_trivially_equal((*cit).rest,expanded_ex)) {
-
+
// something changed, copy seq, eval and return it
- epvector *s=new epvector;
+ epvector *s = new epvector;
s->reserve(seq.size());
-
+
// copy parts of seq which are known not to have changed
epvector::const_iterator cit2 = seq.begin();
while (cit2!=cit) {
++cit;
}
- return 0; // nothing has changed
+ return 0; // signalling nothing has changed
}
-
+
+
+/** Member-wise evaluate the expairs in this sequence.
+ *
+ * @see expairseq::eval()
+ * @return pointer to epvector containing evaluated pairs or zero pointer,
+ * if no members were changed. */
epvector * expairseq::evalchildren(int level) const
{
// returns a NULL pointer if nothing had to be evaluated
// returns a pointer to a newly created epvector otherwise
// (which has to be deleted somewhere else)
- if (level==1) {
+ if (level==1)
return 0;
- }
- if (level == -max_recursion_level) {
+
+ if (level == -max_recursion_level)
throw(std::runtime_error("max recursion level reached"));
- }
-
+
--level;
epvector::const_iterator last=seq.end();
epvector::const_iterator cit=seq.begin();
while (cit!=last) {
- const ex & evaled_ex=(*cit).rest.eval(level);
+ const ex &evaled_ex = (*cit).rest.eval(level);
if (!are_ex_trivially_equal((*cit).rest,evaled_ex)) {
-
+
// something changed, copy seq, eval and return it
epvector *s = new epvector;
s->reserve(seq.size());
-
+
// copy parts of seq which are known not to have changed
epvector::const_iterator cit2=seq.begin();
while (cit2!=cit) {
++cit;
}
- return 0; // nothing has changed
+ return 0; // signalling nothing has changed
}
+
+/** Member-wise evaluate numerically all expairs in this sequence.
+ *
+ * @see expairseq::evalf()
+ * @return epvector with all entries evaluated numerically. */
epvector expairseq::evalfchildren(int level) const
{
if (level==1)
return seq;
-
+
if (level==-max_recursion_level)
throw(std::runtime_error("max recursion level reached"));
return s;
}
+
+/** Member-wise normalize all expairs in this sequence.
+ *
+ * @see expairseq::normal()
+ * @return epvector with all entries normalized. */
epvector expairseq::normalchildren(int level) const
{
if (level==1)
return seq;
- if (level == -max_recursion_level)
+ if (level==-max_recursion_level)
throw(std::runtime_error("max recursion level reached"));
-
+
epvector s;
s.reserve(seq.size());
-
+
--level;
for (epvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
s.push_back(combine_ex_with_coeff_to_pair((*it).rest.normal(level),
return s;
}
-epvector expairseq::diffchildren(const symbol & y) const
+
+/** Member-wise differentiate all expairs in this sequence.
+ *
+ * @see expairseq::diff()
+ * @return epvector with all entries differentiated. */
+epvector expairseq::diffchildren(const symbol &y) const
{
epvector s;
s.reserve(seq.size());
-
+
for (epvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
s.push_back(combine_ex_with_coeff_to_pair((*it).rest.diff(y),
(*it).coeff));
return s;
}
-epvector * expairseq::subschildren(const lst & ls, const lst & lr) const
+
+/** Member-wise substitute in this sequence.
+ *
+ * @see expairseq::subs()
+ * @return pointer to epvector containing pairs after application of subs or zero
+ * pointer, if no members were changed. */
+epvector * expairseq::subschildren(const lst &ls, const lst &lr) const
{
// returns a NULL pointer if nothing had to be substituted
// returns a pointer to a newly created epvector otherwise
// (which has to be deleted somewhere else)
GINAC_ASSERT(ls.nops()==lr.nops());
- epvector::const_iterator last=seq.end();
- epvector::const_iterator cit=seq.begin();
+ epvector::const_iterator last = seq.end();
+ epvector::const_iterator cit = seq.begin();
while (cit!=last) {
- const ex & subsed_ex=(*cit).rest.subs(ls,lr);
+ const ex &subsed_ex=(*cit).rest.subs(ls,lr);
if (!are_ex_trivially_equal((*cit).rest,subsed_ex)) {
// something changed, copy seq, subs and return it
s->reserve(seq.size());
// copy parts of seq which are known not to have changed
- epvector::const_iterator cit2=seq.begin();
+ epvector::const_iterator cit2 = seq.begin();
while (cit2!=cit) {
s->push_back(*cit2);
++cit2;
++cit;
}
- return 0; // nothing has changed
+ return 0; // signalling nothing has changed
}
//////////
// protected
-unsigned expairseq::precedence=10;
+unsigned expairseq::precedence = 10;
-#ifdef EXPAIRSEQ_USE_HASHTAB
-unsigned expairseq::maxhashtabsize=0x4000000U;
-unsigned expairseq::minhashtabsize=0x1000U;
-unsigned expairseq::hashtabfactor=1;
-#endif // def EXPAIRSEQ_USE_HASHTAB
+#if EXPAIRSEQ_USE_HASHTAB
+unsigned expairseq::maxhashtabsize = 0x4000000U;
+unsigned expairseq::minhashtabsize = 0x1000U;
+unsigned expairseq::hashtabfactor = 1;
+#endif // EXPAIRSEQ_USE_HASHTAB
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#include <vector>
#include <list>
-
// CINT needs <algorithm> to work properly with <vector> and <list>
#include <algorithm>
#include "expair.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
-
-//#define EXPAIRSEQ_USE_HASHTAB
-
-typedef std::vector<expair> epvector;
-typedef epvector::iterator epviter;
-
-inline void iter_swap(epvector::iterator it1, epvector::iterator it2)
-{
- (*it1).rest.swap((*it2).rest);
- (*it1).coeff.swap((*it2).coeff);
-}
-typedef epvector::iterator epp;
-typedef std::list<epp> epplist;
-typedef std::vector<epplist> epplistvector;
+/** Using hash tables can potentially enhance the asymptotic behaviour of
+ * combining n terms into one large sum (or n terms into one large product)
+ * from O(n*log(n)) to about O(n). There are, however, several drawbacks.
+ * The constant in front of O(n) is quite large, when copying such an object
+ * one also has to copy the has table, comparison is quite expensive because
+ * there is no ordering any more, it doesn't help at all when combining two
+ * expairseqs because due to the presorted nature the behaviour would be
+ * O(n) anyways, the code is quite messy, etc, etc. The code is here as
+ * an example for following generations to tinker with. */
+#define EXPAIRSEQ_USE_HASHTAB 0
+
+typedef std::vector<expair> epvector; ///< expair-vector
+typedef epvector::iterator epviter; ///< expair-vector iterator
+typedef epvector::iterator epp; ///< expair-vector pointer
+typedef std::list<epp> epplist; ///< list of expair-vector pointers
+typedef std::vector<epplist> epplistvector; ///< vector of epplist
/** A sequence of class expair.
* This is used for time-critical classes like sums and products of terms
* since handling a list of coeff and rest is much faster than handling a
- * list of products or powers, respectively. (Incidentally, Maple does it
- * the same way.) */
+ * list of products or powers, respectively. (Not incidentally, Maple does it
+ * the same way, maybe others too.) The semantics is (at least) twofold:
+ * one for addition and one for multiplication and several methods have to
+ * be overridden by derived classes to reflect the change in semantics.
+ * However, most functionality turns out to be shared between addition and
+ * multiplication, which is the reason why there is this base class. */
class expairseq : public basic
{
GINAC_DECLARE_REGISTERED_CLASS_NO_CTORS(expairseq, basic)
// member functions
- // default constructor, destructor, copy constructor assignment operator and helpers
+ // default ctor, dtor, copy ctor assignment operator and helpers
public:
expairseq() : basic(TINFO_expairseq)
-#ifdef EXPAIRSEQ_USE_HASHTAB
+#if EXPAIRSEQ_USE_HASHTAB
, hashtabsize(0)
-#endif // def EXPAIRSEQ_USE_HASHTAB
- {
- }
- ~expairseq()
- {
- destroy(0);
- }
+#endif // EXPAIRSEQ_USE_HASHTAB
+ { }
+ ~expairseq() { destroy(false); }
expairseq(const expairseq & other);
const expairseq & operator=(const expairseq & other);
protected:
void copy(const expairseq & other);
- void destroy(bool call_parent)
- {
- if (call_parent) basic::destroy(call_parent);
- };
-
- // other constructors
+ void destroy(bool call_parent);
+ // other ctors
public:
expairseq(const ex & lh, const ex & rh);
expairseq(const exvector & v);
expairseq(const epvector & v, const ex & oc);
expairseq(epvector * vp, const ex & oc); // vp will be deleted
-
+
// functions overriding virtual functions from bases classes
public:
basic * duplicate() const;
unsigned return_type(void) const;
unsigned calchash(void) const;
ex expand(unsigned options=0) const;
-
+
// new virtual functions which can be overridden by derived classes
protected:
virtual ex thisexpairseq(const epvector & v, const ex & oc) const;
void construct_from_epvector(const epvector & v);
void make_flat(const exvector & v);
void make_flat(const epvector & v);
- epvector * bubblesort(epvector::iterator itbegin, epvector::iterator itend);
- epvector * mergesort(epvector::iterator itbegin, epvector::iterator itend);
void canonicalize(void);
void combine_same_terms_sorted_seq(void);
-#ifdef EXPAIRSEQ_USE_HASHTAB
+#if EXPAIRSEQ_USE_HASHTAB
void combine_same_terms(void);
unsigned calc_hashtabsize(unsigned sz) const;
unsigned calc_hashindex(const ex & e) const;
bool has_coeff_0(void) const;
void add_numerics_to_hashtab(epvector::iterator first_numeric,
epvector::const_iterator last_non_zero);
-#endif // def EXPAIRSEQ_USE_HASHTAB
+#endif // EXPAIRSEQ_USE_HASHTAB
bool is_canonical() const;
epvector * expandchildren(unsigned options) const;
epvector * evalchildren(int level) const;
epvector seq;
ex overall_coeff;
static unsigned precedence;
-#ifdef EXPAIRSEQ_USE_HASHTAB
+#if EXPAIRSEQ_USE_HASHTAB
epplistvector hashtab;
unsigned hashtabsize;
unsigned hashmask;
static unsigned maxhashtabsize;
static unsigned minhashtabsize;
static unsigned hashtabfactor;
-#endif // def EXPAIRSEQ_USE_HASHTAB
+#endif // EXPAIRSEQ_USE_HASHTAB
};
// utility functions
return static_cast<const expairseq &>(*e.bp);
}
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#endif // ndef __GINAC_EXPAIRSEQ_H__
/** @file exprseq_suppl.cpp
*
- * Supplement to exprseq.cpp, contains the parts which were
- * not automatically generated. */
+ * Supplement to exprseq.cpp, contains the parts which were not automatically
+ * generated. */
/*
* GiNaC Copyright (C) 1999-2001 Johannes Gutenberg University Mainz, Germany
#include "exprseq.h"
#include "ex.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
bool exprseq::info(unsigned inf) const
{
{
GINAC_ASSERT(i>=0);
GINAC_ASSERT(i<nops());
-
+
return seq[i];
}
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#include "archive.h"
#include "debugmsg.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
GINAC_IMPLEMENT_REGISTERED_CLASS(fail, basic)
//////////
-// default constructor, destructor, copy constructor assignment operator and helpers
+// default ctor, dtor, copy ctor assignment operator and helpers
//////////
// public
fail::fail() : inherited(TINFO_fail)
{
- debugmsg("fail default constructor",LOGLEVEL_CONSTRUCT);
+ debugmsg("fail default ctor",LOGLEVEL_CONSTRUCT);
}
// protected
/** 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);
+ debugmsg("fail ctor from archive_node", LOGLEVEL_CONSTRUCT);
}
/** Unarchive the object. */
return 0;
}
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#include "basic.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
class fail : public basic
{
GINAC_DECLARE_REGISTERED_CLASS(fail, basic)
-
- // other constructors
+
+ // other ctors
// none
-
+
// functions overriding virtual functions from bases classes
public:
void print(std::ostream & os, unsigned upper_precedence=0) const;
// new virtual functions which can be overridden by derived classes
// none
-
+
// non-virtual functions in this class
// none
-
+
// member variables
// none
};
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#endif // ndef __GINAC_FAIL_H__
#ifndef __GINAC_FLAGS_H__
#define __GINAC_FLAGS_H__
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
class expand_options {
public:
class determinant_algo {
public:
enum {
- automatic, //! Let the system choose
- gauss, //! Gauss elimiation
- divfree, //! Division-free elimination
- laplace, //! Laplace (or minor) elimination
- bareiss //! Bareiss fraction-free elimination
+ automatic, ///< Let the system choose
+ gauss, ///< Gauss elimiation
+ divfree, ///< Division-free elimination
+ laplace, ///< Laplace (or minor) elimination
+ bareiss ///< Bareiss fraction-free elimination
};
};
class solve_algo {
public:
enum {
- automatic, //! Let the system choose
- gauss, //! Gauss elimiation
- divfree, //! Division-free elimination
- bareiss //! Bareiss fraction-free elimination
+ automatic, ///< Let the system choose
+ gauss, ///< Gauss elimiation
+ divfree, ///< Division-free elimination
+ bareiss ///< Bareiss fraction-free elimination
};
};
-/** Flags to store information about the stato of an object. */
+/** Flags to store information about the state of an object.
+ * @see basic::flags */
class status_flags {
public:
enum {
- dynallocated = 0x0001, //! Heap-allocated (i.e. created by new)
- evaluated = 0x0002, //! .eval() has already done its job
- expanded = 0x0004, //! .expand() has already done its job
- hash_calculated = 0x0008 //! .calchash() has already done its job
+ dynallocated = 0x0001, ///< Heap-allocated (i.e. created by new if we want to be clever and bypass the stack)
+ evaluated = 0x0002, ///< .eval() has already done its job
+ expanded = 0x0004, ///< .expand() has already done its job
+ hash_calculated = 0x0008 ///< .calchash() has already done its job
};
};
class remember_strategies {
public:
enum {
- delete_never, //! Let table grow undefinitely, not recommmended, but currently default
- delete_lru, //! Least recently used
- delete_lfu, //! Least frequently used
- delete_cyclic //! First (oldest) one in list
+ delete_never, ///< Let table grow undefinitely
+ delete_lru, ///< Least recently used
+ delete_lfu, ///< Least frequently used
+ delete_cyclic ///< First (oldest) one in list
};
};
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#endif // ndef __GINAC_FLAGS_H__
return generate_from_to($template,$seq_template1,$seq_template2,1,$maxargs);
}
-$declare_function_macro_namespace = <<'END_OF_DECLARE_FUNCTION_1_AND_2P_MACRO_NAMESPACE';
+$declare_function_macro = <<'END_OF_DECLARE_FUNCTION_1_AND_2P_MACRO';
#define DECLARE_FUNCTION_1P(NAME) \
extern const unsigned function_index_##NAME; \
inline GiNaC::function NAME(const GiNaC::ex & p1) { \
return GiNaC::function(function_index_##NAME, p1, p2); \
}
-END_OF_DECLARE_FUNCTION_1_AND_2P_MACRO_NAMESPACE
+END_OF_DECLARE_FUNCTION_1_AND_2P_MACRO
-$declare_function_macro_namespace .= generate_from_to(
- <<'END_OF_DECLARE_FUNCTION_MACRO_NAMESPACE','const GiNaC::ex & p${N}','p${N}',3,$maxargs);
+$declare_function_macro .= generate_from_to(
+ <<'END_OF_DECLARE_FUNCTION_MACRO','const GiNaC::ex & p${N}','p${N}',3,$maxargs);
#define DECLARE_FUNCTION_${N}P(NAME) \\
extern const unsigned function_index_##NAME; \\
inline GiNaC::function NAME(${SEQ1}) { \\
return GiNaC::function(function_index_##NAME, ${SEQ2}); \\
}
-END_OF_DECLARE_FUNCTION_MACRO_NAMESPACE
-
-$declare_function_macro_no_namespace = <<'END_OF_DECLARE_FUNCTION_1_AND_2P_MACRO_NO_NAMESPACE';
-#define DECLARE_FUNCTION_1P(NAME) \
-extern const unsigned function_index_##NAME; \
-inline function NAME(const ex & p1) { \
- return function(function_index_##NAME, p1); \
-}
-#define DECLARE_FUNCTION_2P(NAME) \
-extern const unsigned function_index_##NAME; \
-inline function NAME(const ex & p1, const ex & p2) { \
- return function(function_index_##NAME, p1, p2); \
-}
-
-END_OF_DECLARE_FUNCTION_1_AND_2P_MACRO_NO_NAMESPACE
-
-$declare_function_macro_no_namespace .= generate_from_to(
- <<'END_OF_DECLARE_FUNCTION_MACRO_NO_NAMESPACE','const ex & p${N}','p${N}',3,$maxargs);
-#define DECLARE_FUNCTION_${N}P(NAME) \\
-extern const unsigned function_index_##NAME; \\
-inline function NAME(${SEQ1}) { \\
- return function(function_index_##NAME, ${SEQ2}); \\
-}
-
-END_OF_DECLARE_FUNCTION_MACRO_NO_NAMESPACE
+END_OF_DECLARE_FUNCTION_MACRO
$typedef_eval_funcp=generate(
'typedef ex (* eval_funcp_${N})(${SEQ1});'."\n",
function::function(unsigned ser, ${SEQ1})
: exprseq(${SEQ2}), serial(ser)
{
- debugmsg(\"function constructor from unsigned,${N}*ex\",LOGLEVEL_CONSTRUCT);
+ debugmsg(\"function ctor from unsigned,${N}*ex\",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_function;
}
END_OF_CONSTRUCTORS_IMPLEMENTATION
#include "exprseq.h"
-#ifndef NO_NAMESPACE_GINAC
-
-// the following lines have been generated for max. ${maxargs} parameters
-$declare_function_macro_namespace
-// end of generated lines
-
-#else // ndef NO_NAMESPACE_GINAC
-
// the following lines have been generated for max. ${maxargs} parameters
-$declare_function_macro_no_namespace
+$declare_function_macro
// end of generated lines
-#endif // ndef NO_NAMESPACE_GINAC
-
-#ifndef NO_NAMESPACE_GINAC
-
#define REGISTER_FUNCTION(NAME,OPT) \\
const unsigned function_index_##NAME= \\
GiNaC::function::register_new(GiNaC::function_options(#NAME).OPT);
derivative_func(D). \\
series_func(S));
-#else // ndef NO_NAMESPACE_GINAC
-
-#define REGISTER_FUNCTION(NAME,OPT) \\
-const unsigned function_index_##NAME= \\
- function::register_new(function_options(#NAME).OPT);
-
-#define REGISTER_FUNCTION_OLD(NAME,E,EF,D,S) \\
-const unsigned function_index_##NAME= \\
- function::register_new(function_options(#NAME). \\
- eval_func(E). \\
- evalf_func(EF). \\
- derivative_func(D). \\
- series_func(S));
-
-#endif // ndef NO_NAMESPACE_GINAC
-
#define BEGIN_TYPECHECK \\
bool automatic_typecheck=true;
automatic_typecheck=false; \\
} else
-#ifndef NO_NAMESPACE_GINAC
-
#define TYPECHECK_INTEGER(VAR) \\
if (!(VAR).info(GiNaC::info_flags::integer)) { \\
automatic_typecheck=false; \\
} else
-#else // ndef NO_NAMESPACE_GINAC
-
-#define TYPECHECK_INTEGER(VAR) \\
-if (!(VAR).info(info_flags::integer)) { \\
- automatic_typecheck=false; \\
-} else
-
-#endif // ndef NO_NAMESPACE_GINAC
-
#define END_TYPECHECK(RV) \\
{} \\
if (!automatic_typecheck) { \\
return RV.hold(); \\
}
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
class function;
// member functions
- // other constructors
+ // other ctors
public:
function(unsigned ser);
// the following lines have been generated for max. ${maxargs} parameters
ex expand(unsigned options=0) const;
ex eval(int level=0) const;
ex evalf(int level=0) const;
+ unsigned calchash(void) const;
ex series(const relational & r, int order, unsigned options = 0) const;
ex thisexprseq(const exvector & v) const;
ex thisexprseq(exvector * vp) const;
return static_cast<const function &>(*e.bp);
}
-#ifndef NO_NAMESPACE_GINAC
-
#define is_ex_the_function(OBJ, FUNCNAME) \\
(is_ex_exactly_of_type(OBJ, function) && static_cast<GiNaC::function *>(OBJ.bp)->getserial() == function_index_##FUNCNAME)
-#else // ndef NO_NAMESPACE_GINAC
-
-#define is_ex_the_function(OBJ, FUNCNAME) \\
- (is_ex_exactly_of_type(OBJ, function) && static_cast<function *>(OBJ.bp)->getserial() == function_index_##FUNCNAME)
-
-#endif // ndef NO_NAMESPACE_GINAC
-
// global constants
extern const function some_function;
extern const std::type_info & typeid_function;
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#endif // ndef __GINAC_FUNCTION_H__
#include "debugmsg.h"
#include "remember.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
//////////
// helper class function_options
GINAC_IMPLEMENT_REGISTERED_CLASS(function, exprseq)
//////////
-// default constructor, destructor, copy constructor assignment operator and helpers
+// default ctor, dtor, copy ctor assignment operator and helpers
//////////
// public
function::function() : serial(0)
{
- debugmsg("function default constructor",LOGLEVEL_CONSTRUCT);
+ debugmsg("function default ctor",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_function;
}
}
//////////
-// other constructors
+// other ctors
//////////
// public
function::function(unsigned ser) : serial(ser)
{
- debugmsg("function constructor from unsigned",LOGLEVEL_CONSTRUCT);
+ debugmsg("function ctor from unsigned",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_function;
}
function::function(unsigned ser, const exprseq & es) : exprseq(es), serial(ser)
{
- debugmsg("function constructor from unsigned,exprseq",LOGLEVEL_CONSTRUCT);
+ debugmsg("function ctor from unsigned,exprseq",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_function;
}
function::function(unsigned ser, const exvector & v, bool discardable)
: exprseq(v,discardable), serial(ser)
{
- debugmsg("function constructor from string,exvector,bool",LOGLEVEL_CONSTRUCT);
+ debugmsg("function ctor from string,exvector,bool",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_function;
}
function::function(unsigned ser, exvector * vp)
: exprseq(vp), serial(ser)
{
- debugmsg("function constructor from unsigned,exvector *",LOGLEVEL_CONSTRUCT);
+ debugmsg("function ctor from unsigned,exvector *",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_function;
}
/** 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);
+ debugmsg("function ctor from archive_node", LOGLEVEL_CONSTRUCT);
// Find serial number by function name
std::string s;
throw(std::logic_error("function::evalf(): invalid nparams"));
}
+unsigned function::calchash(void) const
+{
+ unsigned v = golden_ratio_hash(golden_ratio_hash(tinfo()) ^ serial);
+ for (unsigned i=0; i<nops(); i++) {
+ v = rotate_left_31(v);
+ v ^= this->op(i).gethash();
+ }
+ v &= 0x7FFFFFFFU;
+ if (flags & status_flags::evaluated) {
+ setflag(status_flags::hash_calculated);
+ hashvalue = v;
+ }
+ return v;
+}
+
ex function::thisexprseq(const exvector & v) const
{
return function(serial,v);
const function some_function;
const std::type_info & typeid_function=typeid(some_function);
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
END_OF_IMPLEMENTATION
#include "utils.h"
#include "debugmsg.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
GINAC_IMPLEMENT_REGISTERED_CLASS(idx, basic)
return res;
}
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#include "basic.h"
#include "ex.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
/** This class holds one index of an indexed object. Indices can be symbolic
ex subs_indices(const ex & e, const exvector & idxv_contra, const exvector & idxv_co);
unsigned count_index(const ex & e, const ex & i);
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#endif // ndef __GINAC_IDX_H__
#include "idx.h"
#include "debugmsg.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
GINAC_IMPLEMENT_REGISTERED_CLASS(indexed, exprseq)
return true;
}
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#include <string>
#include "exprseq.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
/** Base class for objects with indices. */
return static_cast<const indexed &>(*e.bp);
}
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#endif // ndef __GINAC_INDEXED_H__
#include "symbol.h"
#include "utils.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
//////////
// absolute value
unsigned force_include_tgamma = function_index_tgamma;
unsigned force_include_zeta1 = function_index_zeta1;
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#include "function.h"
#include "ex.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
/** Absolute value. */
DECLARE_FUNCTION_1P(abs)
return is_ex_the_function(e, Order);
}
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#endif // ndef __GINAC_INIFCNS_H__
#include "symbol.h"
#include "utils.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
//////////
// Logarithm of Gamma function
overloaded(2));
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#include "pseries.h"
#include "utils.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
//////////
// exponential function
series_func(atanh_series));
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#include "symbol.h"
#include "utils.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
//////////
// Riemann's Zeta-function
derivative_func(zeta2_deriv).
overloaded(2));
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
extern char ginac_yytext[];
#endif
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
class ex;
/** Get error message from the parser. */
extern std::string get_parser_error(void);
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#endif // ndef __GINAC_INPUT_LEXER_H__
#include "utils.h"
#include "debugmsg.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
GINAC_IMPLEMENT_REGISTERED_CLASS(isospin, indexed)
// private
-unsigned isospin::next_serial=0;
+unsigned isospin::next_serial = 0;
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#include <string>
#include "indexed.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
/** Base class for isospin object */
class isospin : public indexed
return static_cast<const isospin &>(*e.bp);
}
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#endif // ndef __GINAC_ISOSPIN_H__
#include "utils.h"
#include "debugmsg.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
GINAC_IMPLEMENT_REGISTERED_CLASS(lorentzidx, idx)
return *d;
}
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#include <vector>
#include "idx.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
/** Class of indices for Lorentz tensors, to tell them apart from other
ex Dim(void);
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#endif // ndef __GINAC_LORENTZIDX_H__
#include "utils.h"
#include "config.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
GINAC_IMPLEMENT_REGISTERED_CLASS(lortensor, indexed)
ex simplify_lortensor(const ex & e)
{
// all simplification is done on expanded objects
- ex e_expanded=e.expand();
+ ex e_expanded = e.expand();
// simplification of sum=sum of simplifications
if (is_ex_exactly_of_type(e_expanded,add)) {
return e_expanded;
}
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#include "indexed.h"
#include "lorentzidx.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
/** This class holds an object carrying Lorentz indices (of class
friend lortensor lortensor_delta(const ex & mu, const ex & nu);
friend lortensor lortensor_epsilon(const ex & mu, const ex & nu,
const ex & rho, const ex & sigma);
- friend lortensor lortensor_vector(const string & n, const ex & mu);
- friend lortensor lortensor_symbolic(const string & name, const exvector & iv);
+ friend lortensor lortensor_vector(const std::string & n, const ex & mu);
+ friend lortensor lortensor_symbolic(const std::string & name, const exvector & iv);
friend ex simplify_lortensor_mul(const ex & m);
friend ex simplify_lortensor(const ex & e);
lortensor lortensor_delta(const ex & mu, const ex & nu);
lortensor lortensor_epsilon(const ex & mu, const ex & nu,
const ex & rho, const ex & sigma);
-lortensor lortensor_vector(const string & n, const ex & mu);
-lortensor lortensor_symbolic(const string & name, const exvector & iv);
+lortensor lortensor_vector(const std::string & n, const ex & mu);
+lortensor lortensor_symbolic(const std::string & name, const exvector & iv);
ex simplify_lortensor_mul(const ex & m);
ex simplify_lortensor(const ex & e);
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#endif // ndef __GINAC_LORTENSOR_H__
/** @file lst_suppl.cpp
*
- * Supplement to lst.cpp, contains the parts which were
- * not automatically generated. */
+ * Supplement to lst.cpp, contains the parts which were not automatically
+ * generated. */
/*
* GiNaC Copyright (C) 1999-2001 Johannes Gutenberg University Mainz, Germany
#include "lst.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
bool lst::info(unsigned inf) const
{
return basic::info(inf);
}
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#include "symbol.h"
#include "normal.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
GINAC_IMPLEMENT_REGISTERED_CLASS(matrix, basic)
//////////
-// default constructor, destructor, copy constructor, assignment operator
-// and helpers:
+// default ctor, dtor, copy ctor, assignment operator and helpers:
//////////
// public
/** Default ctor. Initializes to 1 x 1-dimensional zero-matrix. */
matrix::matrix() : inherited(TINFO_matrix), row(1), col(1)
{
- debugmsg("matrix default constructor",LOGLEVEL_CONSTRUCT);
+ debugmsg("matrix default ctor",LOGLEVEL_CONSTRUCT);
m.push_back(_ex0());
}
// protected
+/** For use by copy ctor and assignment operator. */
void matrix::copy(const matrix & other)
{
inherited::copy(other);
}
//////////
-// other constructors
+// other ctors
//////////
// public
matrix::matrix(unsigned r, unsigned c)
: inherited(TINFO_matrix), row(r), col(c)
{
- debugmsg("matrix constructor from unsigned,unsigned",LOGLEVEL_CONSTRUCT);
+ debugmsg("matrix ctor from unsigned,unsigned",LOGLEVEL_CONSTRUCT);
m.resize(r*c, _ex0());
}
matrix::matrix(unsigned r, unsigned c, const exvector & m2)
: inherited(TINFO_matrix), row(r), col(c), m(m2)
{
- debugmsg("matrix constructor from unsigned,unsigned,exvector",LOGLEVEL_CONSTRUCT);
+ debugmsg("matrix ctor from unsigned,unsigned,exvector",LOGLEVEL_CONSTRUCT);
}
//////////
/** 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);
+ debugmsg("matrix ctor 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);
return m;
}
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#include "basic.h"
#include "ex.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
/** Symbolic matrices. */
class matrix : public basic
{
GINAC_DECLARE_REGISTERED_CLASS(matrix, basic)
-
- // other constructors
+
+ // other ctors
public:
matrix(unsigned r, unsigned c);
matrix(unsigned r, unsigned c, const exvector & m2);
-
+
// functions overriding virtual functions from bases classes
public:
void print(std::ostream & os, unsigned upper_precedence=0) const;
// non-virtual functions in this class
public:
- unsigned rows(void) const //! Get number of rows.
+ unsigned rows(void) const /// Get number of rows.
{ return row; }
- unsigned cols(void) const //! Get number of columns.
+ unsigned cols(void) const /// Get number of columns.
{ return col; }
matrix add(const matrix & other) const;
matrix sub(const matrix & other) const;
// member variables
protected:
- unsigned row; /**< number of rows */
- unsigned col; /**< number of columns */
- exvector m; /**< representation (cols indexed first) */
+ unsigned row; ///< number of rows
+ unsigned col; ///< number of columns
+ exvector m; ///< representation (cols indexed first)
static unsigned precedence;
};
extern ex lst_to_matrix(const ex &l);
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#endif // ndef __GINAC_MATRIX_H__
#include "debugmsg.h"
#include "utils.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
GINAC_IMPLEMENT_REGISTERED_CLASS(mul, expairseq)
//////////
-// default constructor, destructor, copy constructor assignment operator and helpers
+// default ctor, dctor, copy ctor assignment operator and helpers
//////////
// public
mul::mul()
{
- debugmsg("mul default constructor",LOGLEVEL_CONSTRUCT);
+ debugmsg("mul default ctor",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_mul;
}
// protected
+/** For use by copy ctor and assignment operator. */
void mul::copy(const mul & other)
{
inherited::copy(other);
}
//////////
-// other constructors
+// other ctors
//////////
// public
mul::mul(const ex & lh, const ex & rh)
{
- debugmsg("mul constructor from ex,ex",LOGLEVEL_CONSTRUCT);
+ debugmsg("mul ctor from ex,ex",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_mul;
overall_coeff = _ex1();
construct_from_2_ex(lh,rh);
mul::mul(const exvector & v)
{
- debugmsg("mul constructor from exvector",LOGLEVEL_CONSTRUCT);
+ debugmsg("mul ctor from exvector",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_mul;
overall_coeff = _ex1();
construct_from_exvector(v);
mul::mul(const epvector & v)
{
- debugmsg("mul constructor from epvector",LOGLEVEL_CONSTRUCT);
+ debugmsg("mul ctor from epvector",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_mul;
overall_coeff = _ex1();
construct_from_epvector(v);
mul::mul(const epvector & v, const ex & oc)
{
- debugmsg("mul constructor from epvector,ex",LOGLEVEL_CONSTRUCT);
+ debugmsg("mul ctor from epvector,ex",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_mul;
overall_coeff = oc;
construct_from_epvector(v);
mul::mul(epvector * vp, const ex & oc)
{
- debugmsg("mul constructor from epvector *,ex",LOGLEVEL_CONSTRUCT);
+ debugmsg("mul ctor from epvector *,ex",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_mul;
GINAC_ASSERT(vp!=0);
overall_coeff = oc;
mul::mul(const ex & lh, const ex & mh, const ex & rh)
{
- debugmsg("mul constructor from ex,ex,ex",LOGLEVEL_CONSTRUCT);
+ debugmsg("mul ctor from ex,ex,ex",LOGLEVEL_CONSTRUCT);
tinfo_key = TINFO_mul;
exvector factors;
factors.reserve(3);
/** 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);
+ debugmsg("mul ctor from archive_node", LOGLEVEL_CONSTRUCT);
}
/** Unarchive the object. */
{
debugmsg("mul print",LOGLEVEL_PRINT);
if (precedence<=upper_precedence) os << "(";
- bool first=true;
+ bool first = true;
// first print the overall numeric coefficient:
numeric coeff = ex_to_numeric(overall_coeff);
if (coeff.csgn()==-1) os << '-';
return inherited::info(inf);
}
-typedef std::vector<int> intvector;
-
int mul::degree(const symbol & s) const
{
int deg_sum = 0;
// *(+(x,y,...);c) -> *(+(*(x,c),*(y,c),...)) (c numeric())
// *(x;1) -> x
// *(;c) -> c
-
+
debugmsg("mul eval",LOGLEVEL_MEMBER_FUNCTION);
-
- epvector * evaled_seqp=evalchildren(level);
+
+ epvector * evaled_seqp = evalchildren(level);
if (evaled_seqp!=0) {
// do more evaluation later
return (new mul(evaled_seqp,overall_coeff))->
- setflag(status_flags::dynallocated);
+ setflag(status_flags::dynallocated);
}
-
+
#ifdef DO_GINAC_ASSERT
for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
- GINAC_ASSERT((!is_ex_exactly_of_type((*cit).rest,mul))||
- (!(ex_to_numeric((*cit).coeff).is_integer())));
- GINAC_ASSERT(!((*cit).is_numeric_with_coeff_1()));
- if (is_ex_exactly_of_type(recombine_pair_to_ex(*cit),numeric)) {
- printtree(cerr,0);
- }
+ GINAC_ASSERT((!is_ex_exactly_of_type((*cit).rest,mul)) ||
+ (!(ex_to_numeric((*cit).coeff).is_integer())));
+ GINAC_ASSERT(!(cit->is_canonical_numeric()));
+ if (is_ex_exactly_of_type(recombine_pair_to_ex(*cit),numeric))
+ printtree(std::cerr,0);
GINAC_ASSERT(!is_ex_exactly_of_type(recombine_pair_to_ex(*cit),numeric));
/* for paranoia */
- expair p=split_ex_to_pair(recombine_pair_to_ex(*cit));
+ expair p = split_ex_to_pair(recombine_pair_to_ex(*cit));
GINAC_ASSERT(p.rest.is_equal((*cit).rest));
GINAC_ASSERT(p.coeff.is_equal((*cit).coeff));
/* end paranoia */
}
#endif // def DO_GINAC_ASSERT
-
+
if (flags & status_flags::evaluated) {
GINAC_ASSERT(seq.size()>0);
- GINAC_ASSERT((seq.size()>1)||!overall_coeff.is_equal(_ex1()));
+ GINAC_ASSERT(seq.size()>1 || !overall_coeff.is_equal(_ex1()));
return *this;
}
-
- int seq_size=seq.size();
+
+ int seq_size = seq.size();
if (overall_coeff.is_equal(_ex0())) {
// *(...,x;0) -> 0
return _ex0();
} else if (seq_size==0) {
// *(;c) -> c
return overall_coeff;
- } else if ((seq_size==1)&&overall_coeff.is_equal(_ex1())) {
+ } else if (seq_size==1 && overall_coeff.is_equal(_ex1())) {
// *(x;1) -> x
return recombine_pair_to_ex(*(seq.begin()));
} else if ((seq_size==1) &&
is_ex_exactly_of_type((*seq.begin()).rest,add) &&
ex_to_numeric((*seq.begin()).coeff).is_equal(_num1())) {
// *(+(x,y,...);c) -> +(*(x,c),*(y,c),...) (c numeric(), no powers of +())
- const add & addref=ex_to_add((*seq.begin()).rest);
+ const add & addref = ex_to_add((*seq.begin()).rest);
epvector distrseq;
distrseq.reserve(addref.seq.size());
for (epvector::const_iterator cit=addref.seq.begin(); cit!=addref.seq.end(); ++cit) {
for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
exvector subiv=(*cit).rest.get_indices();
iv.reserve(iv.size()+subiv.size());
- for (exvector::const_iterator cit2=subiv.begin(); cit2!=subiv.end(); ++cit2) {
+ for (exvector::const_iterator cit2=subiv.begin(); cit2!=subiv.end(); ++cit2)
iv.push_back(*cit2);
- }
}
return iv;
}
// mul without factors: should not happen, but commutes
return return_types::commutative;
}
-
+
bool all_commutative = 1;
unsigned rt;
epvector::const_iterator cit_noncommutative_element; // point to first found nc element
-
+
for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
rt=(*cit).rest.return_type();
if (rt==return_types::noncommutative_composite) return rt; // one ncc -> mul also ncc
unsigned mul::return_type_tinfo(void) const
{
- if (seq.size()==0) {
- // mul without factors: should not happen
- return tinfo_key;
- }
+ if (seq.size()==0)
+ return tinfo_key; // mul without factors: should not happen
+
// return type_info of first noncommutative element
for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
- if ((*cit).rest.return_type()==return_types::noncommutative) {
+ if ((*cit).rest.return_type()==return_types::noncommutative)
return (*cit).rest.return_type_tinfo();
- }
}
// no noncommutative element found, should not happen
return tinfo_key;
expair mul::split_ex_to_pair(const ex & e) const
{
if (is_ex_exactly_of_type(e,power)) {
- const power & powerref=ex_to_power(e);
- if (is_ex_exactly_of_type(powerref.exponent,numeric)) {
+ const power & powerref = ex_to_power(e);
+ if (is_ex_exactly_of_type(powerref.exponent,numeric))
return expair(powerref.basis,powerref.exponent);
- }
}
return expair(e,_ex1());
}
if (is_ex_exactly_of_type((*it).rest,mul) &&
ex_to_numeric((*it).coeff).is_integer()) {
// combined pair is product with integer power -> expand it
- *it=split_ex_to_pair(recombine_pair_to_ex(*it));
+ *it = split_ex_to_pair(recombine_pair_to_ex(*it));
return true;
}
if (is_ex_exactly_of_type((*it).rest,numeric)) {
expair ep=split_ex_to_pair(recombine_pair_to_ex(*it));
if (!ep.is_equal(*it)) {
// combined pair is a numeric power which can be simplified
- *it=ep;
+ *it = ep;
return true;
}
if (ex_to_numeric((*it).coeff).is_equal(_num1())) {
return *this;
exvector sub_expanded_seq;
- intvector positions_of_adds;
epvector * expanded_seqp = expandchildren(options);
non_adds.reserve(expanded_seq.size());
epvector::const_iterator cit = expanded_seq.begin();
epvector::const_iterator last = expanded_seq.end();
- ex last_expanded=_ex1();
+ ex last_expanded = _ex1();
while (cit!=last) {
if (is_ex_exactly_of_type((*cit).rest,add) &&
((*cit).coeff.is_equal(_ex1()))) {
// non-virtual functions in this class
//////////
+
+/** Member-wise expand the expairs representing this sequence. This must be
+ * overridden from expairseq::expandchildren() and done iteratively in order
+ * to allow for early cancallations and thus safe memory.
+ *
+ * @see mul::expand()
+ * @return pointer to epvector containing expanded representation or zero
+ * pointer, if sequence is unchanged. */
epvector * mul::expandchildren(unsigned options) const
{
epvector::const_iterator last = seq.end();
if (!are_ex_trivially_equal(factor,expanded_factor)) {
// something changed, copy seq, eval and return it
- epvector *s=new epvector;
+ epvector *s = new epvector;
s->reserve(seq.size());
// copy parts of seq which are known not to have changed
return 0; // nothing has changed
}
-
+
//////////
// static member variables
//////////
unsigned mul::precedence = 50;
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#include "expairseq.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
/** Product of expressions. */
class mul : public expairseq
{
GINAC_DECLARE_REGISTERED_CLASS(mul, expairseq)
-
+
friend class add;
friend class ncmul;
friend class power;
-
- // other constructors
+
+ // other ctors
public:
mul(const ex & lh, const ex & rh);
mul(const exvector & v);
mul(const epvector & v, const ex & oc);
mul(epvector * vp, const ex & oc);
mul(const ex & lh, const ex & mh, const ex & rh);
-
+
// functions overriding virtual functions from bases classes
public:
void print(std::ostream & os, unsigned upper_precedence) const;
// new virtual functions which can be overridden by derived classes
// none
-
+
// non-virtual functions in this class
protected:
epvector * expandchildren(unsigned options) const;
-
+
// member variables
-
+
protected:
static unsigned precedence;
};
return static_cast<const mul &>(*e.bp);
}
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#endif // ndef __GINAC_MUL_H__
#include "debugmsg.h"
#include "utils.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
GINAC_IMPLEMENT_REGISTERED_CLASS(ncmul, exprseq)
// protected
-unsigned ncmul::precedence=50;
+unsigned ncmul::precedence = 50;
//////////
// friend functions
status_flags::evaluated);
}
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#include "exprseq.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
/** Non-commutative product of expressions. */
class ncmul : public exprseq
return static_cast <const ncmul &>(*e.bp);
}
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#endif // ndef __GINAC_NCMUL_H__
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <stdexcept>
#include <algorithm>
#include <map>
#include "symbol.h"
#include "utils.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
// If comparing expressions (ex::compare()) is fast, you can set this to 1.
// Some routines like quo(), rem() and gcd() will then return a quick answer
typedef std::pair<ex, bool> exbool;
struct ex2_less {
- bool operator() (const ex2 p, const ex2 q) const
+ bool operator() (const ex2 &p, const ex2 &q) const
{
- return p.first.compare(q.first) < 0 || (!(q.first.compare(p.first) < 0) && p.second.compare(q.second) < 0);
+ int cmp = p.first.compare(q.first);
+ return ((cmp<0) || (!(cmp>0) && p.second.compare(q.second)<0));
}
};
return bp->max_coefficient();
}
+/** Implementation ex::max_coefficient().
+ * @see heur_gcd */
numeric basic::max_coefficient(void) const
{
return _num1();
ex numeric::smod(const numeric &xi) const
{
-#ifndef NO_NAMESPACE_GINAC
return GiNaC::smod(*this, xi);
-#else // ndef NO_NAMESPACE_GINAC
- return ::smod(*this, xi);
-#endif // ndef NO_NAMESPACE_GINAC
}
ex add::smod(const numeric &xi) const
epvector::const_iterator itend = seq.end();
while (it != itend) {
GINAC_ASSERT(!is_ex_exactly_of_type(it->rest,numeric));
-#ifndef NO_NAMESPACE_GINAC
numeric coeff = GiNaC::smod(ex_to_numeric(it->coeff), xi);
-#else // ndef NO_NAMESPACE_GINAC
- numeric coeff = ::smod(ex_to_numeric(it->coeff), xi);
-#endif // ndef NO_NAMESPACE_GINAC
if (!coeff.is_zero())
newseq.push_back(expair(it->rest, coeff));
it++;
}
GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric));
-#ifndef NO_NAMESPACE_GINAC
numeric coeff = GiNaC::smod(ex_to_numeric(overall_coeff), xi);
-#else // ndef NO_NAMESPACE_GINAC
- numeric coeff = ::smod(ex_to_numeric(overall_coeff), xi);
-#endif // ndef NO_NAMESPACE_GINAC
return (new add(newseq,coeff))->setflag(status_flags::dynallocated);
}
#endif // def DO_GINAC_ASSERT
mul * mulcopyp=new mul(*this);
GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric));
-#ifndef NO_NAMESPACE_GINAC
mulcopyp->overall_coeff = GiNaC::smod(ex_to_numeric(overall_coeff),xi);
-#else // ndef NO_NAMESPACE_GINAC
- mulcopyp->overall_coeff = ::smod(ex_to_numeric(overall_coeff),xi);
-#endif // ndef NO_NAMESPACE_GINAC
mulcopyp->clearflag(status_flags::evaluated);
mulcopyp->clearflag(status_flags::hash_calculated);
return mulcopyp->setflag(status_flags::dynallocated);
}
-/** Implementation of ex::normal() for pseries. It normalizes each coefficient and
- * replaces the series by a temporary symbol.
+/** Implementation of ex::normal() for pseries. It normalizes each coefficient
+ * and replaces the series by a temporary symbol.
* @see ex::normal */
ex pseries::normal(lst &sym_lst, lst &repl_lst, int level) const
{
}
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#ifndef __GINAC_NORMAL_H__
#define __GINAC_NORMAL_H__
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
class ex;
class symbol;
// Square-free factorization of a polynomial a(x)
extern ex sqrfree(const ex &a, const symbol &x);
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#endif // ndef __GINAC_NORMAL_H__
#include <cln/complex_ring.h>
#include <cln/numtheory.h>
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
GINAC_IMPLEMENT_REGISTERED_CLASS(numeric, basic)
//////////
-// default constructor, destructor, copy constructor assignment
+// default ctor, dtor, copy ctor assignment
// operator and helpers
//////////
/** default ctor. Numerically it initializes to an integer zero. */
numeric::numeric() : basic(TINFO_numeric)
{
- debugmsg("numeric default constructor", LOGLEVEL_CONSTRUCT);
+ debugmsg("numeric default ctor", LOGLEVEL_CONSTRUCT);
value = cln::cl_I(0);
- calchash();
- setflag(status_flags::evaluated |
- status_flags::expanded |
- status_flags::hash_calculated);
+ setflag(status_flags::evaluated | status_flags::expanded);
}
// protected
-void numeric::copy(const numeric & other)
+/** For use by copy ctor and assignment operator. */
+void numeric::copy(const numeric &other)
{
- basic::copy(other);
+ inherited::copy(other);
value = other.value;
}
void numeric::destroy(bool call_parent)
{
- if (call_parent) basic::destroy(call_parent);
+ if (call_parent) inherited::destroy(call_parent);
}
//////////
-// other constructors
+// other ctors
//////////
// public
numeric::numeric(int i) : basic(TINFO_numeric)
{
- debugmsg("numeric constructor from int",LOGLEVEL_CONSTRUCT);
+ debugmsg("numeric ctor 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. However, if the integer is small enough,
value = cln::cl_I(i);
else
value = cln::cl_I((long) i);
- calchash();
- setflag(status_flags::evaluated |
- status_flags::expanded |
- status_flags::hash_calculated);
+ setflag(status_flags::evaluated | status_flags::expanded);
}
numeric::numeric(unsigned int i) : basic(TINFO_numeric)
{
- debugmsg("numeric constructor from uint",LOGLEVEL_CONSTRUCT);
+ debugmsg("numeric ctor 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. However, if the integer is small enough,
value = cln::cl_I(i);
else
value = cln::cl_I((unsigned long) i);
- calchash();
- setflag(status_flags::evaluated |
- status_flags::expanded |
- status_flags::hash_calculated);
+ setflag(status_flags::evaluated | status_flags::expanded);
}
numeric::numeric(long i) : basic(TINFO_numeric)
{
- debugmsg("numeric constructor from long",LOGLEVEL_CONSTRUCT);
+ debugmsg("numeric ctor from long",LOGLEVEL_CONSTRUCT);
value = cln::cl_I(i);
- calchash();
- setflag(status_flags::evaluated |
- status_flags::expanded |
- status_flags::hash_calculated);
+ setflag(status_flags::evaluated | status_flags::expanded);
}
numeric::numeric(unsigned long i) : basic(TINFO_numeric)
{
- debugmsg("numeric constructor from ulong",LOGLEVEL_CONSTRUCT);
+ debugmsg("numeric ctor from ulong",LOGLEVEL_CONSTRUCT);
value = cln::cl_I(i);
- calchash();
- setflag(status_flags::evaluated |
- status_flags::expanded |
- status_flags::hash_calculated);
+ setflag(status_flags::evaluated | status_flags::expanded);
}
/** Ctor for rational numerics a/b.
* @exception overflow_error (division by zero) */
numeric::numeric(long numer, long denom) : basic(TINFO_numeric)
{
- debugmsg("numeric constructor from long/long",LOGLEVEL_CONSTRUCT);
+ debugmsg("numeric ctor from long/long",LOGLEVEL_CONSTRUCT);
if (!denom)
throw std::overflow_error("division by zero");
value = cln::cl_I(numer) / cln::cl_I(denom);
- calchash();
- setflag(status_flags::evaluated |
- status_flags::expanded |
- status_flags::hash_calculated);
+ setflag(status_flags::evaluated | status_flags::expanded);
}
numeric::numeric(double d) : basic(TINFO_numeric)
{
- debugmsg("numeric constructor from double",LOGLEVEL_CONSTRUCT);
+ debugmsg("numeric ctor 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:
value = cln::cl_float(d, cln::default_float_format);
- calchash();
- setflag(status_flags::evaluated |
- status_flags::expanded |
- status_flags::hash_calculated);
+ setflag(status_flags::evaluated | status_flags::expanded);
}
+
/** ctor from C-style string. It also accepts complex numbers in GiNaC
* notation like "2+5*I". */
numeric::numeric(const char *s) : basic(TINFO_numeric)
{
- debugmsg("numeric constructor from string",LOGLEVEL_CONSTRUCT);
+ debugmsg("numeric ctor from string",LOGLEVEL_CONSTRUCT);
cln::cl_N ctorval = 0;
// parse complex numbers (functional but not completely safe, unfortunately
// std::string does not understand regexpese):
}
} while(delim != std::string::npos);
value = ctorval;
- calchash();
- setflag(status_flags::evaluated |
- status_flags::expanded |
- status_flags::hash_calculated);
+ setflag(status_flags::evaluated | status_flags::expanded);
}
+
/** Ctor from CLN types. This is for the initiated user or internal use
* only. */
-numeric::numeric(const cln::cl_N & z) : basic(TINFO_numeric)
+numeric::numeric(const cln::cl_N &z) : basic(TINFO_numeric)
{
- debugmsg("numeric constructor from cl_N", LOGLEVEL_CONSTRUCT);
+ debugmsg("numeric ctor from cl_N", LOGLEVEL_CONSTRUCT);
value = z;
- calchash();
- setflag(status_flags::evaluated |
- status_flags::expanded |
- status_flags::hash_calculated);
+ setflag(status_flags::evaluated | status_flags::expanded);
}
//////////
/** 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);
+ debugmsg("numeric ctor from archive_node", LOGLEVEL_CONSTRUCT);
cln::cl_N ctorval = 0;
// Read number as string
}
}
value = ctorval;
- calchash();
- setflag(status_flags::evaluated |
- status_flags::expanded |
- status_flags::hash_calculated);
+ setflag(status_flags::evaluated | status_flags::expanded);
}
/** Unarchive the object. */
* want to visibly distinguish from cl_LF.
*
* @see numeric::print() */
-static void print_real_number(std::ostream & os, const cln::cl_R & num)
+static void print_real_number(std::ostream &os, const cln::cl_R &num)
{
cln::cl_print_flags ourflags;
if (cln::instanceof(num, cln::cl_RA_ring)) {
* with the other routines and produces something compatible to ginsh input.
*
* @see print_real_number() */
-void numeric::print(std::ostream & os, unsigned upper_precedence) const
+void numeric::print(std::ostream &os, unsigned upper_precedence) const
{
debugmsg("numeric print", LOGLEVEL_PRINT);
cln::cl_R r = cln::realpart(cln::the<cln::cl_N>(value));
}
-void numeric::printraw(std::ostream & os) const
+void numeric::printraw(std::ostream &os) const
{
// The method printraw doesn't do much, it simply uses CLN's operator<<()
// for output, which is ugly but reliable. e.g: 2+2i
}
-void numeric::printtree(std::ostream & os, unsigned indent) const
+void numeric::printtree(std::ostream &os, unsigned indent) const
{
debugmsg("numeric printtree", LOGLEVEL_PRINT);
os << std::string(indent,' ') << cln::the<cln::cl_N>(value)
}
-void numeric::printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const
+void numeric::printcsrc(std::ostream &os, unsigned type, unsigned upper_precedence) const
{
debugmsg("numeric print csrc", LOGLEVEL_PRINT);
std::ios::fmtflags oldflags = os.flags();
* results: (2+I).has(-2) -> true. But this is consistent, since we also
* would like to have (-2+I).has(2) -> true and we want to think about the
* sign as a multiplicative factor. */
-bool numeric::has(const ex & other) const
+bool numeric::has(const ex &other) const
{
if (!is_exactly_of_type(*other.bp, numeric))
return false;
- const numeric & o = static_cast<numeric &>(const_cast<basic &>(*other.bp));
+ const numeric &o = static_cast<numeric &>(const_cast<basic &>(*other.bp));
if (this->is_equal(o) || this->is_equal(-o))
return true;
if (o.imag().is_zero()) // e.g. scan for 3 in -3*I
{
// level can safely be discarded for numeric objects.
return numeric(cln::cl_float(1.0, cln::default_float_format) *
- (cln::the<cln::cl_N>(value)));
+ (cln::the<cln::cl_N>(value)));
}
// protected
-/** Implementation of ex::diff() for a numeric. It always returns 0.
- *
- * @see ex::diff */
-ex numeric::derivative(const symbol & s) const
-{
- return _ex0();
-}
-
-
-int numeric::compare_same_type(const basic & other) const
+int numeric::compare_same_type(const basic &other) const
{
GINAC_ASSERT(is_exactly_of_type(other, numeric));
- const numeric & o = static_cast<numeric &>(const_cast<basic &>(other));
+ const numeric &o = static_cast<numeric &>(const_cast<basic &>(other));
return this->compare(o);
}
-bool numeric::is_equal_same_type(const basic & other) const
+bool numeric::is_equal_same_type(const basic &other) const
{
GINAC_ASSERT(is_exactly_of_type(other,numeric));
const numeric *o = static_cast<const numeric *>(&other);
// Use CLN's hashcode. Warning: It depends only on the number's value, not
// its type or precision (i.e. a true equivalence relation on numbers). As
// a consequence, 3 and 3.0 share the same hashvalue.
+ setflag(status_flags::hash_calculated);
return (hashvalue = cln::equal_hashcode(cln::the<cln::cl_N>(value)) | 0x80000000U);
}
// public
/** Numerical addition method. Adds argument to *this and returns result as
- * a new numeric object. */
-const numeric numeric::add(const numeric & other) const
+ * a numeric object. */
+const numeric numeric::add(const numeric &other) const
{
// Efficiency shortcut: trap the neutral element by pointer.
static const numeric * _num0p = &_num0();
/** Numerical subtraction method. Subtracts argument from *this and returns
- * result as a new numeric object. */
-const numeric numeric::sub(const numeric & other) const
+ * result as a numeric object. */
+const numeric numeric::sub(const numeric &other) const
{
return numeric(cln::the<cln::cl_N>(value)-cln::the<cln::cl_N>(other.value));
}
/** Numerical multiplication method. Multiplies *this and argument and returns
- * result as a new numeric object. */
-const numeric numeric::mul(const numeric & other) const
+ * result as a numeric object. */
+const numeric numeric::mul(const numeric &other) const
{
// Efficiency shortcut: trap the neutral element by pointer.
static const numeric * _num1p = &_num1();
/** Numerical division method. Divides *this by argument and returns result as
- * a new numeric object.
+ * a numeric object.
*
* @exception overflow_error (division by zero) */
-const numeric numeric::div(const numeric & other) const
+const numeric numeric::div(const numeric &other) const
{
if (cln::zerop(cln::the<cln::cl_N>(other.value)))
throw std::overflow_error("numeric::div(): division by zero");
}
-const numeric numeric::power(const numeric & other) const
+/** Numerical exponentiation. Raises *this to the power given as argument and
+ * returns result as a numeric object. */
+const numeric numeric::power(const numeric &other) const
{
// Efficiency shortcut: trap the neutral exponent by pointer.
static const numeric * _num1p = &_num1();
}
-const numeric & numeric::add_dyn(const numeric & other) const
+const numeric &numeric::add_dyn(const numeric &other) const
{
// Efficiency shortcut: trap the neutral element by pointer.
static const numeric * _num0p = &_num0();
}
-const numeric & numeric::sub_dyn(const numeric & other) const
+const numeric &numeric::sub_dyn(const numeric &other) const
{
return static_cast<const numeric &>((new numeric(cln::the<cln::cl_N>(value)-cln::the<cln::cl_N>(other.value)))->
setflag(status_flags::dynallocated));
}
-const numeric & numeric::mul_dyn(const numeric & other) const
+const numeric &numeric::mul_dyn(const numeric &other) const
{
// Efficiency shortcut: trap the neutral element by pointer.
static const numeric * _num1p = &_num1();
}
-const numeric & numeric::div_dyn(const numeric & other) const
+const numeric &numeric::div_dyn(const numeric &other) const
{
if (cln::zerop(cln::the<cln::cl_N>(other.value)))
throw std::overflow_error("division by zero");
}
-const numeric & numeric::power_dyn(const numeric & other) const
+const numeric &numeric::power_dyn(const numeric &other) const
{
// Efficiency shortcut: trap the neutral exponent by pointer.
static const numeric * _num1p=&_num1();
}
-const numeric & numeric::operator=(int i)
+const numeric &numeric::operator=(int i)
{
return operator=(numeric(i));
}
-const numeric & numeric::operator=(unsigned int i)
+const numeric &numeric::operator=(unsigned int i)
{
return operator=(numeric(i));
}
-const numeric & numeric::operator=(long i)
+const numeric &numeric::operator=(long i)
{
return operator=(numeric(i));
}
-const numeric & numeric::operator=(unsigned long i)
+const numeric &numeric::operator=(unsigned long i)
{
return operator=(numeric(i));
}
-const numeric & numeric::operator=(double d)
+const numeric &numeric::operator=(double d)
{
return operator=(numeric(d));
}
-const numeric & numeric::operator=(const char * s)
+const numeric &numeric::operator=(const char * s)
{
return operator=(numeric(s));
}
* csgn(x)==0 for x==0, csgn(x)==1 for Re(x)>0 or Re(x)=0 and Im(x)>0,
* csgn(x)==-1 for Re(x)<0 or Re(x)=0 and Im(x)<0.
*
- * @see numeric::compare(const numeric & other) */
+ * @see numeric::compare(const numeric &other) */
int numeric::csgn(void) const
{
if (cln::zerop(cln::the<cln::cl_N>(value)))
*
* @return csgn(*this-other)
* @see numeric::csgn(void) */
-int numeric::compare(const numeric & other) const
+int numeric::compare(const numeric &other) const
{
// Comparing two real numbers?
if (cln::instanceof(value, cln::cl_R_ring) &&
}
-bool numeric::is_equal(const numeric & other) const
+bool numeric::is_equal(const numeric &other) const
{
return cln::equal(cln::the<cln::cl_N>(value),cln::the<cln::cl_N>(other.value));
}
}
-bool numeric::operator==(const numeric & other) const
+bool numeric::operator==(const numeric &other) const
{
return equal(cln::the<cln::cl_N>(value), cln::the<cln::cl_N>(other.value));
}
-bool numeric::operator!=(const numeric & other) const
+bool numeric::operator!=(const numeric &other) const
{
return !equal(cln::the<cln::cl_N>(value), cln::the<cln::cl_N>(other.value));
}
/** Numerical comparison: less.
*
* @exception invalid_argument (complex inequality) */
-bool numeric::operator<(const numeric & other) const
+bool numeric::operator<(const numeric &other) const
{
if (this->is_real() && other.is_real())
return (cln::the<cln::cl_R>(value) < cln::the<cln::cl_R>(other.value));
/** Numerical comparison: less or equal.
*
* @exception invalid_argument (complex inequality) */
-bool numeric::operator<=(const numeric & other) const
+bool numeric::operator<=(const numeric &other) const
{
if (this->is_real() && other.is_real())
return (cln::the<cln::cl_R>(value) <= cln::the<cln::cl_R>(other.value));
/** Numerical comparison: greater.
*
* @exception invalid_argument (complex inequality) */
-bool numeric::operator>(const numeric & other) const
+bool numeric::operator>(const numeric &other) const
{
if (this->is_real() && other.is_real())
return (cln::the<cln::cl_R>(value) > cln::the<cln::cl_R>(other.value));
/** Numerical comparison: greater or equal.
*
* @exception invalid_argument (complex inequality) */
-bool numeric::operator>=(const numeric & other) const
+bool numeric::operator>=(const numeric &other) const
{
if (this->is_real() && other.is_real())
return (cln::the<cln::cl_R>(value) >= cln::the<cln::cl_R>(other.value));
//////////
/** Imaginary unit. This is not a constant but a numeric since we are
- * natively handing complex numbers anyways. */
+ * natively handing complex numbers anyways, so in each expression containing
+ * an I it is automatically eval'ed away anyhow. */
const numeric I = numeric(cln::complex(cln::cl_I(0),cln::cl_I(1)));
/** Exponential function.
*
* @return arbitrary precision numerical exp(x). */
-const numeric exp(const numeric & x)
+const numeric exp(const numeric &x)
{
return cln::exp(x.to_cl_N());
}
* @param z complex number
* @return arbitrary precision numerical log(x).
* @exception pole_error("log(): logarithmic pole",0) */
-const numeric log(const numeric & z)
+const numeric log(const numeric &z)
{
if (z.is_zero())
throw pole_error("log(): logarithmic pole",0);
/** Numeric sine (trigonometric function).
*
* @return arbitrary precision numerical sin(x). */
-const numeric sin(const numeric & x)
+const numeric sin(const numeric &x)
{
return cln::sin(x.to_cl_N());
}
/** Numeric cosine (trigonometric function).
*
* @return arbitrary precision numerical cos(x). */
-const numeric cos(const numeric & x)
+const numeric cos(const numeric &x)
{
return cln::cos(x.to_cl_N());
}
/** Numeric tangent (trigonometric function).
*
* @return arbitrary precision numerical tan(x). */
-const numeric tan(const numeric & x)
+const numeric tan(const numeric &x)
{
return cln::tan(x.to_cl_N());
}
/** Numeric inverse sine (trigonometric function).
*
* @return arbitrary precision numerical asin(x). */
-const numeric asin(const numeric & x)
+const numeric asin(const numeric &x)
{
return cln::asin(x.to_cl_N());
}
/** Numeric inverse cosine (trigonometric function).
*
* @return arbitrary precision numerical acos(x). */
-const numeric acos(const numeric & x)
+const numeric acos(const numeric &x)
{
return cln::acos(x.to_cl_N());
}
* @param z complex number
* @return atan(z)
* @exception pole_error("atan(): logarithmic pole",0) */
-const numeric atan(const numeric & x)
+const numeric atan(const numeric &x)
{
if (!x.is_real() &&
x.real().is_zero() &&
* @param x real number
* @param y real number
* @return atan(y/x) */
-const numeric atan(const numeric & y, const numeric & x)
+const numeric atan(const numeric &y, const numeric &x)
{
if (x.is_real() && y.is_real())
return cln::atan(cln::the<cln::cl_R>(x.to_cl_N()),
/** Numeric hyperbolic sine (trigonometric function).
*
* @return arbitrary precision numerical sinh(x). */
-const numeric sinh(const numeric & x)
+const numeric sinh(const numeric &x)
{
return cln::sinh(x.to_cl_N());
}
/** Numeric hyperbolic cosine (trigonometric function).
*
* @return arbitrary precision numerical cosh(x). */
-const numeric cosh(const numeric & x)
+const numeric cosh(const numeric &x)
{
return cln::cosh(x.to_cl_N());
}
/** Numeric hyperbolic tangent (trigonometric function).
*
* @return arbitrary precision numerical tanh(x). */
-const numeric tanh(const numeric & x)
+const numeric tanh(const numeric &x)
{
return cln::tanh(x.to_cl_N());
}
/** Numeric inverse hyperbolic sine (trigonometric function).
*
* @return arbitrary precision numerical asinh(x). */
-const numeric asinh(const numeric & x)
+const numeric asinh(const numeric &x)
{
return cln::asinh(x.to_cl_N());
}
/** Numeric inverse hyperbolic cosine (trigonometric function).
*
* @return arbitrary precision numerical acosh(x). */
-const numeric acosh(const numeric & x)
+const numeric acosh(const numeric &x)
{
return cln::acosh(x.to_cl_N());
}
/** Numeric inverse hyperbolic tangent (trigonometric function).
*
* @return arbitrary precision numerical atanh(x). */
-const numeric atanh(const numeric & x)
+const numeric atanh(const numeric &x)
{
return cln::atanh(x.to_cl_N());
}
-/*static cln::cl_N Li2_series(const ::cl_N & x,
- const ::float_format_t & prec)
+/*static cln::cl_N Li2_series(const ::cl_N &x,
+ const ::float_format_t &prec)
{
// Note: argument must be in the unit circle
// This is very inefficient unless we have fast floating point Bernoulli
/** Numeric evaluation of Dilogarithm within circle of convergence (unit
* circle) using a power series. */
-static cln::cl_N Li2_series(const cln::cl_N & x,
- const cln::float_format_t & prec)
+static cln::cl_N Li2_series(const cln::cl_N &x,
+ const cln::float_format_t &prec)
{
// Note: argument must be in the unit circle
cln::cl_N aug, acc;
}
/** Folds Li2's argument inside a small rectangle to enhance convergence. */
-static cln::cl_N Li2_projection(const cln::cl_N & x,
- const cln::float_format_t & prec)
+static cln::cl_N Li2_projection(const cln::cl_N &x,
+ const cln::float_format_t &prec)
{
const cln::cl_R re = cln::realpart(x);
const cln::cl_R im = cln::imagpart(x);
* continuous with quadrant IV.
*
* @return arbitrary precision numerical Li2(x). */
-const numeric Li2(const numeric & x)
+const numeric Li2(const numeric &x)
{
if (x.is_zero())
return _num0();
/** Numeric evaluation of Riemann's Zeta function. Currently works only for
* integer arguments. */
-const numeric zeta(const numeric & x)
+const numeric zeta(const numeric &x)
{
// A dirty hack to allow for things like zeta(3.0), since CLN currently
// only knows about integer arguments and zeta(3).evalf() automatically
return cln::zeta(aux);
}
std::clog << "zeta(" << x
- << "): Does anybody know good way to calculate this numerically?"
+ << "): Does anybody know a good way to calculate this numerically?"
<< std::endl;
return numeric(0);
}
/** The Gamma function.
* This is only a stub! */
-const numeric lgamma(const numeric & x)
+const numeric lgamma(const numeric &x)
{
std::clog << "lgamma(" << x
- << "): Does anybody know good way to calculate this numerically?"
+ << "): Does anybody know a good way to calculate this numerically?"
<< std::endl;
return numeric(0);
}
-const numeric tgamma(const numeric & x)
+const numeric tgamma(const numeric &x)
{
std::clog << "tgamma(" << x
- << "): Does anybody know good way to calculate this numerically?"
+ << "): Does anybody know a good way to calculate this numerically?"
<< std::endl;
return numeric(0);
}
/** The psi function (aka polygamma function).
* This is only a stub! */
-const numeric psi(const numeric & x)
+const numeric psi(const numeric &x)
{
std::clog << "psi(" << x
- << "): Does anybody know good way to calculate this numerically?"
+ << "): Does anybody know a good way to calculate this numerically?"
<< std::endl;
return numeric(0);
}
/** The psi functions (aka polygamma functions).
* This is only a stub! */
-const numeric psi(const numeric & n, const numeric & x)
+const numeric psi(const numeric &n, const numeric &x)
{
std::clog << "psi(" << n << "," << x
- << "): Does anybody know good way to calculate this numerically?"
+ << "): Does anybody know a good way to calculate this numerically?"
<< std::endl;
return numeric(0);
}
*
* @param n integer argument >= 0
* @exception range_error (argument must be integer >= 0) */
-const numeric factorial(const numeric & n)
+const numeric factorial(const numeric &n)
{
if (!n.is_nonneg_integer())
throw std::range_error("numeric::factorial(): argument must be integer >= 0");
* @param n integer argument >= -1
* @return n!! == n * (n-2) * (n-4) * ... * ({1|2}) with 0!! == (-1)!! == 1
* @exception range_error (argument must be integer >= -1) */
-const numeric doublefactorial(const numeric & n)
+const numeric doublefactorial(const numeric &n)
{
- if (n == numeric(-1))
+ if (n.is_equal(_num_1()))
return _num1();
if (!n.is_nonneg_integer())
* integer n and k and positive n this is the number of ways of choosing k
* objects from n distinct objects. If n is negative, the formula
* binomial(n,k) == (-1)^k*binomial(k-n-1,k) is used to compute the result. */
-const numeric binomial(const numeric & n, const numeric & k)
+const numeric binomial(const numeric &n, const numeric &k)
{
if (n.is_integer() && k.is_integer()) {
if (n.is_nonneg_integer()) {
*
* @return the nth Bernoulli number (a rational number).
* @exception range_error (argument must be integer >= 0) */
-const numeric bernoulli(const numeric & nn)
+const numeric bernoulli(const numeric &nn)
{
if (!nn.is_integer() || nn.is_negative())
throw std::range_error("numeric::bernoulli(): argument must be integer >= 0");
* @param n an integer
* @return the nth Fibonacci number F(n) (an integer number)
* @exception range_error (argument must be an integer) */
-const numeric fibonacci(const numeric & n)
+const numeric fibonacci(const numeric &n)
{
if (!n.is_integer())
throw std::range_error("numeric::fibonacci(): argument must be integer");
*
* @return a mod b in the range [0,abs(b)-1] with sign of b if both are
* integer, 0 otherwise. */
-const numeric mod(const numeric & a, const numeric & b)
+const numeric mod(const numeric &a, const numeric &b)
{
if (a.is_integer() && b.is_integer())
return cln::mod(cln::the<cln::cl_I>(a.to_cl_N()),
* Equivalent to Maple's mods.
*
* @return a mod b in the range [-iquo(abs(m)-1,2), iquo(abs(m),2)]. */
-const numeric smod(const numeric & a, const numeric & b)
+const numeric smod(const numeric &a, const numeric &b)
{
if (a.is_integer() && b.is_integer()) {
const cln::cl_I b2 = cln::ceiling1(cln::the<cln::cl_I>(b.to_cl_N()) >> 1) - 1;
* sign of a or is zero.
*
* @return remainder of a/b if both are integer, 0 otherwise. */
-const numeric irem(const numeric & a, const numeric & b)
+const numeric irem(const numeric &a, const numeric &b)
{
if (a.is_integer() && b.is_integer())
return cln::rem(cln::the<cln::cl_I>(a.to_cl_N()),
*
* @return remainder of a/b and quotient stored in q if both are integer,
* 0 otherwise. */
-const numeric irem(const numeric & a, const numeric & b, numeric & q)
+const numeric irem(const numeric &a, const numeric &b, numeric &q)
{
if (a.is_integer() && b.is_integer()) {
const cln::cl_I_div_t rem_quo = cln::truncate2(cln::the<cln::cl_I>(a.to_cl_N()),
* Equivalent to Maple's iquo as far as sign conventions are concerned.
*
* @return truncated quotient of a/b if both are integer, 0 otherwise. */
-const numeric iquo(const numeric & a, const numeric & b)
+const numeric iquo(const numeric &a, const numeric &b)
{
if (a.is_integer() && b.is_integer())
return truncate1(cln::the<cln::cl_I>(a.to_cl_N()),
*
* @return truncated quotient of a/b and remainder stored in r if both are
* integer, 0 otherwise. */
-const numeric iquo(const numeric & a, const numeric & b, numeric & r)
+const numeric iquo(const numeric &a, const numeric &b, numeric &r)
{
if (a.is_integer() && b.is_integer()) {
const cln::cl_I_div_t rem_quo = cln::truncate2(cln::the<cln::cl_I>(a.to_cl_N()),
*
* @return The GCD of two numbers if both are integer, a numerical 1
* if they are not. */
-const numeric gcd(const numeric & a, const numeric & b)
+const numeric gcd(const numeric &a, const numeric &b)
{
if (a.is_integer() && b.is_integer())
return cln::gcd(cln::the<cln::cl_I>(a.to_cl_N()),
*
* @return The LCM of two numbers if both are integer, the product of those
* two numbers if they are not. */
-const numeric lcm(const numeric & a, const numeric & b)
+const numeric lcm(const numeric &a, const numeric &b)
{
if (a.is_integer() && b.is_integer())
return cln::lcm(cln::the<cln::cl_I>(a.to_cl_N()),
* @return square root of z. Branch cut along negative real axis, the negative
* real axis itself where imag(z)==0 and real(z)<0 belongs to the upper part
* where imag(z)>0. */
-const numeric sqrt(const numeric & z)
+const numeric sqrt(const numeric &z)
{
return cln::sqrt(z.to_cl_N());
}
/** Integer numeric square root. */
-const numeric isqrt(const numeric & x)
+const numeric isqrt(const numeric &x)
{
if (x.is_integer()) {
cln::cl_I root;
}
+/** _numeric_digits default ctor, checking for singleton invariance. */
_numeric_digits::_numeric_digits()
: digits(17)
{
// It initializes to 17 digits, because in CLN float_format(17) turns out
// to be 61 (<64) while float_format(18)=65. The reason is we want to
// have a cl_LF instead of cl_SF, cl_FF or cl_DF.
- assert(!too_late);
+ if (too_late)
+ throw(std::runtime_error("I told you not to do instantiate me!"));
too_late = true;
cln::default_float_format = cln::float_format(17);
}
/** Append global Digits object to ostream. */
-void _numeric_digits::print(std::ostream & os) const
+void _numeric_digits::print(std::ostream &os) const
{
debugmsg("_numeric_digits print", LOGLEVEL_PRINT);
os << digits;
}
-std::ostream& operator<<(std::ostream& os, const _numeric_digits & e)
+std::ostream& operator<<(std::ostream &os, const _numeric_digits &e)
{
e.print(os);
return os;
* assignment from C++ unsigned ints and evaluated like any built-in type. */
_numeric_digits Digits;
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#include <cln/complex_class.h>
#endif
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
#define HASHVALUE_NUMERIC 0x80000001U
-/** This class is used to instantiate a global object Digits which
- * behaves just like Maple's Digits. We need an object rather than a
- * dumber basic type since as a side-effect we let it change
+/** This class is used to instantiate a global singleton object Digits
+ * which behaves just like Maple's Digits. We need an object rather
+ * than a dumber basic type since as a side-effect we let it change
* cl_default_float_format when it gets changed. The only other
* meaningful thing to do with it is converting it to an unsigned,
* for temprary storing its value e.g. The user must not create an
_numeric_digits();
_numeric_digits& operator=(long prec);
operator long();
- void print(std::ostream & os) const;
+ void print(std::ostream &os) const;
// member variables
private:
- long digits;
- static bool too_late;
+ long digits; ///< Number of decimal digits
+ static bool too_late; ///< Already one object present
};
/** This class is a wrapper around CLN-numbers within the GiNaC class
class numeric : public basic
{
GINAC_DECLARE_REGISTERED_CLASS(numeric, basic)
-
+
// member functions
-
- // other constructors
+
+ // other ctors
public:
explicit numeric(int i);
explicit numeric(unsigned int i);
// functions overriding virtual functions from bases classes
public:
- void print(std::ostream & os, unsigned precedence=0) const;
- void printraw(std::ostream & os) const;
- void printtree(std::ostream & os, unsigned indent) const;
- void printcsrc(std::ostream & os, unsigned type, unsigned precedence=0) const;
+ void print(std::ostream &os, unsigned precedence = 0) const;
+ void printraw(std::ostream &os) const;
+ void printtree(std::ostream &os, unsigned indent) const;
+ void printcsrc(std::ostream &os, unsigned type, unsigned precedence=0) const;
bool info(unsigned inf) const;
- bool has(const ex & other) const;
+ bool has(const ex &other) const;
ex eval(int level = 0) const;
ex evalf(int level = 0) const;
- ex normal(lst &sym_lst, lst &repl_lst, int level=0) const;
+ ex normal(lst &sym_lst, lst &repl_lst, int level = 0) const;
ex to_rational(lst &repl_lst) const;
numeric integer_content(void) const;
ex smod(const numeric &xi) const;
numeric max_coefficient(void) const;
protected:
- ex derivative(const symbol & s) const;
- bool is_equal_same_type(const basic & other) const;
+ /** Implementation of ex::diff for a numeric always returns 0.
+ * @see ex::diff */
+ ex derivative(const symbol &s) const { return _ex0(); }
+ bool is_equal_same_type(const basic &other) const;
unsigned calchash(void) const;
-
+
// new virtual functions which can be overridden by derived classes
// (none)
-
+
// non-virtual functions in this class
public:
- const numeric add(const numeric & other) const;
- const numeric sub(const numeric & other) const;
- const numeric mul(const numeric & other) const;
- const numeric div(const numeric & other) const;
- const numeric power(const numeric & other) const;
- const numeric & add_dyn(const numeric & other) const;
- const numeric & sub_dyn(const numeric & other) const;
- const numeric & mul_dyn(const numeric & other) const;
- const numeric & div_dyn(const numeric & other) const;
- const numeric & power_dyn(const numeric & other) const;
+ const numeric add(const numeric &other) const;
+ const numeric sub(const numeric &other) const;
+ const numeric mul(const numeric &other) const;
+ const numeric div(const numeric &other) const;
+ const numeric power(const numeric &other) const;
+ const numeric & add_dyn(const numeric &other) const;
+ const numeric & sub_dyn(const numeric &other) const;
+ const numeric & mul_dyn(const numeric &other) const;
+ const numeric & div_dyn(const numeric &other) const;
+ const numeric & power_dyn(const numeric &other) const;
const numeric & operator=(int i);
const numeric & operator=(unsigned int i);
const numeric & operator=(long i);
const numeric & operator=(unsigned long i);
const numeric & operator=(double d);
- const numeric & operator=(const char * s);
+ const numeric & operator=(const char *s);
const numeric inverse(void) const;
int csgn(void) const;
- int compare(const numeric & other) const;
- bool is_equal(const numeric & other) const;
+ int compare(const numeric &other) const;
+ bool is_equal(const numeric &other) const;
bool is_zero(void) const;
bool is_positive(void) const;
bool is_negative(void) const;
bool is_real(void) const;
bool is_cinteger(void) const;
bool is_crational(void) const;
- bool operator==(const numeric & other) const;
- bool operator!=(const numeric & other) const;
- bool operator<(const numeric & other) const;
- bool operator<=(const numeric & other) const;
- bool operator>(const numeric & other) const;
- bool operator>=(const numeric & other) const;
+ bool operator==(const numeric &other) const;
+ bool operator!=(const numeric &other) const;
+ bool operator<(const numeric &other) const;
+ bool operator<=(const numeric &other) const;
+ bool operator>(const numeric &other) const;
+ bool operator>=(const numeric &other) const;
int to_int(void) const;
long to_long(void) const;
double to_double(void) const;
const numeric denom(void) const;
int int_length(void) const;
// converting routines for interfacing with CLN:
- numeric(const cln::cl_N & z);
+ numeric(const cln::cl_N &z);
// member variables
extern const numeric I;
extern _numeric_digits Digits;
-//#define is_a_numeric_hash(x) ((x)==HASHVALUE_NUMERIC)
-// may have to be changed to ((x)>=0x80000000U)
-
-// has been changed
-//#define is_a_numeric_hash(x) ((x)&0x80000000U)
+// deprecated macro, for internal use only
+#define is_a_numeric_hash(x) ((x)&0x80000000U)
// global functions
-const numeric exp(const numeric & x);
-const numeric log(const numeric & x);
-const numeric sin(const numeric & x);
-const numeric cos(const numeric & x);
-const numeric tan(const numeric & x);
-const numeric asin(const numeric & x);
-const numeric acos(const numeric & x);
-const numeric atan(const numeric & x);
-const numeric atan(const numeric & y, const numeric & x);
-const numeric sinh(const numeric & x);
-const numeric cosh(const numeric & x);
-const numeric tanh(const numeric & x);
-const numeric asinh(const numeric & x);
-const numeric acosh(const numeric & x);
-const numeric atanh(const numeric & x);
-const numeric Li2(const numeric & x);
-const numeric zeta(const numeric & x);
-const numeric lgamma(const numeric & x);
-const numeric tgamma(const numeric & x);
-const numeric psi(const numeric & x);
-const numeric psi(const numeric & n, const numeric & x);
-const numeric factorial(const numeric & n);
-const numeric doublefactorial(const numeric & n);
-const numeric binomial(const numeric & n, const numeric & k);
-const numeric bernoulli(const numeric & n);
-const numeric fibonacci(const numeric & n);
-const numeric abs(const numeric & x);
-const numeric isqrt(const numeric & x);
-const numeric sqrt(const numeric & x);
-const numeric abs(const numeric & x);
-const numeric mod(const numeric & a, const numeric & b);
-const numeric smod(const numeric & a, const numeric & b);
-const numeric irem(const numeric & a, const numeric & b);
-const numeric irem(const numeric & a, const numeric & b, numeric & q);
-const numeric iquo(const numeric & a, const numeric & b);
-const numeric iquo(const numeric & a, const numeric & b, numeric & r);
-const numeric gcd(const numeric & a, const numeric & b);
-const numeric lcm(const numeric & a, const numeric & b);
+const numeric exp(const numeric &x);
+const numeric log(const numeric &x);
+const numeric sin(const numeric &x);
+const numeric cos(const numeric &x);
+const numeric tan(const numeric &x);
+const numeric asin(const numeric &x);
+const numeric acos(const numeric &x);
+const numeric atan(const numeric &x);
+const numeric atan(const numeric &y, const numeric &x);
+const numeric sinh(const numeric &x);
+const numeric cosh(const numeric &x);
+const numeric tanh(const numeric &x);
+const numeric asinh(const numeric &x);
+const numeric acosh(const numeric &x);
+const numeric atanh(const numeric &x);
+const numeric Li2(const numeric &x);
+const numeric zeta(const numeric &x);
+const numeric lgamma(const numeric &x);
+const numeric tgamma(const numeric &x);
+const numeric psi(const numeric &x);
+const numeric psi(const numeric &n, const numeric &x);
+const numeric factorial(const numeric &n);
+const numeric doublefactorial(const numeric &n);
+const numeric binomial(const numeric &n, const numeric &k);
+const numeric bernoulli(const numeric &n);
+const numeric fibonacci(const numeric &n);
+const numeric abs(const numeric &x);
+const numeric isqrt(const numeric &x);
+const numeric sqrt(const numeric &x);
+const numeric abs(const numeric &x);
+const numeric mod(const numeric &a, const numeric &b);
+const numeric smod(const numeric &a, const numeric &b);
+const numeric irem(const numeric &a, const numeric &b);
+const numeric irem(const numeric &a, const numeric &b, numeric &q);
+const numeric iquo(const numeric &a, const numeric &b);
+const numeric iquo(const numeric &a, const numeric &b, numeric &r);
+const numeric gcd(const numeric &a, const numeric &b);
+const numeric lcm(const numeric &a, const numeric &b);
// wrapper functions around member functions
-inline const numeric pow(const numeric & x, const numeric & y)
+inline const numeric pow(const numeric &x, const numeric &y)
{ return x.power(y); }
-inline const numeric inverse(const numeric & x)
+inline const numeric inverse(const numeric &x)
{ return x.inverse(); }
-inline int csgn(const numeric & x)
+inline int csgn(const numeric &x)
{ return x.csgn(); }
-inline bool is_zero(const numeric & x)
+inline bool is_zero(const numeric &x)
{ return x.is_zero(); }
-inline bool is_positive(const numeric & x)
+inline bool is_positive(const numeric &x)
{ return x.is_positive(); }
-inline bool is_integer(const numeric & x)
+inline bool is_integer(const numeric &x)
{ return x.is_integer(); }
-inline bool is_pos_integer(const numeric & x)
+inline bool is_pos_integer(const numeric &x)
{ return x.is_pos_integer(); }
-inline bool is_nonneg_integer(const numeric & x)
+inline bool is_nonneg_integer(const numeric &x)
{ return x.is_nonneg_integer(); }
-inline bool is_even(const numeric & x)
+inline bool is_even(const numeric &x)
{ return x.is_even(); }
-inline bool is_odd(const numeric & x)
+inline bool is_odd(const numeric &x)
{ return x.is_odd(); }
-inline bool is_prime(const numeric & x)
+inline bool is_prime(const numeric &x)
{ return x.is_prime(); }
-inline bool is_rational(const numeric & x)
+inline bool is_rational(const numeric &x)
{ return x.is_rational(); }
-inline bool is_real(const numeric & x)
+inline bool is_real(const numeric &x)
{ return x.is_real(); }
-inline bool is_cinteger(const numeric & x)
+inline bool is_cinteger(const numeric &x)
{ return x.is_cinteger(); }
-inline bool is_crational(const numeric & x)
+inline bool is_crational(const numeric &x)
{ return x.is_crational(); }
-inline int to_int(const numeric & x)
+inline int to_int(const numeric &x)
{ return x.to_int(); }
-inline long to_long(const numeric & x)
+inline long to_long(const numeric &x)
{ return x.to_long(); }
-inline double to_double(const numeric & x)
+inline double to_double(const numeric &x)
{ return x.to_double(); }
-inline const numeric real(const numeric & x)
+inline const numeric real(const numeric &x)
{ return x.real(); }
-inline const numeric imag(const numeric & x)
+inline const numeric imag(const numeric &x)
{ return x.imag(); }
-inline const numeric numer(const numeric & x)
+inline const numeric numer(const numeric &x)
{ return x.numer(); }
-inline const numeric denom(const numeric & x)
+inline const numeric denom(const numeric &x)
{ return x.denom(); }
// numeric evaluation functions for class constant objects:
return static_cast<const numeric &>(*e.bp);
}
-
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#ifdef __MAKECINT__
#pragma link off defined_in cln/number.h;
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <iostream>
-#include <stdexcept>
-
#include "operators.h"
-#include "basic.h"
-#include "ex.h"
#include "numeric.h"
#include "power.h"
#include "relational.h"
#include "debugmsg.h"
#include "utils.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
// binary arithmetic operators ex with ex
const ex & operator+=(ex & lh, const ex & rh)
{
debugmsg("operator+=(ex,ex)",LOGLEVEL_OPERATOR);
- return (lh=lh+rh);
+ return (lh=lh.exadd(rh));
}
const ex & operator-=(ex & lh, const ex & rh)
{
debugmsg("operator-=(ex,ex)",LOGLEVEL_OPERATOR);
- return (lh=lh-rh);
+ return (lh=lh.exadd(rh.exmul(_ex_1())));
}
const ex & operator*=(ex & lh, const ex & rh)
{
debugmsg("operator*=(ex,ex)",LOGLEVEL_OPERATOR);
- return (lh=lh*rh);
+ return (lh=lh.exmul(rh));
}
const ex & operator/=(ex & lh, const ex & rh)
{
debugmsg("operator/=(ex,ex)",LOGLEVEL_OPERATOR);
- return (lh=lh/rh);
+ return (lh=lh.exmul(power(rh,_ex_1())));
}
const ex & operator%=(ex & lh, const ex & rh)
numeric operator-(const numeric & lh)
{
debugmsg("operator-(numeric)",LOGLEVEL_OPERATOR);
- return _num_1()*lh;
+ return _num_1().mul(lh);
}
/** Numeric prefix increment. Adds 1 and returns incremented number. */
numeric& operator++(numeric & rh)
{
debugmsg("operator++(numeric)",LOGLEVEL_OPERATOR);
- rh = rh+_num1();
+ rh = rh.add(_num1());
return rh;
}
numeric& operator--(numeric & rh)
{
debugmsg("operator--(numeric)",LOGLEVEL_OPERATOR);
- rh = rh-_num1();
+ rh = rh.add(_num_1());
return rh;
}
numeric operator++(numeric & lh, int)
{
debugmsg("operator++(numeric,int)",LOGLEVEL_OPERATOR);
- numeric tmp = lh;
- lh = lh+_num1();
+ numeric tmp(lh);
+ lh = lh.add(_num1());
return tmp;
}
numeric operator--(numeric & lh, int)
{
debugmsg("operator--(numeric,int)",LOGLEVEL_OPERATOR);
- numeric tmp = lh;
- lh = lh-_num1();
+ numeric tmp(lh);
+ lh = lh.add(_num_1());
return tmp;
}
throw (std::logic_error("expression input from streams not implemented"));
}
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#include <iostream>
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
class ex;
class numeric;
std::ostream & operator<<(std::ostream & os, const ex & e);
std::istream & operator>>(std::istream & is, ex & e);
-#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_NAMESPACE_GINAC
#endif // ndef __GINAC_OPERATORS_H__
#include "debugmsg.h"
#include "utils.h"
-#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_NAMESPACE_GINAC
GINAC_IMPLEMENT_REGISTERED_CLASS(power, basic)
typedef std::vector<int> intvector;
//////////
-// default constructor, destructor, copy constructor assignment operator and helpers
+// default ctor, dtor, copy ctor assignment operator and helpers
//////////
// public
power::power() : basic(TINFO_power)
{
- debugmsg("power default constructor",LOGLEVEL_CONSTRUCT);
+ debugmsg("power default ctor",LOGLEVEL_CONSTRUCT);
}
// protected
void power::copy(const power & other)
{
inherited::copy(other);
- basis=other.basis;
- exponent=other.exponent;
+ basis = other.basis;
+ exponent = other.exponent;
}
void power::destroy(bool call_parent)
}
//////////
-// other constructors
+// other ctors
//////////
// public
power::power(const ex & lh, const ex & rh) : basic(TINFO_power), basis(lh), exponent(rh)
{
- debugmsg("power constructor from ex,ex",LOGLEVEL_CONSTRUCT);
+ debugmsg("power ctor from ex,ex",LOGLEVEL_CONSTRUCT);
GINAC_ASSERT(basis.return_type()==return_types::commutative);
}
power::power(const ex & lh, const numeric & rh) : basic(TINFO_power), basis(lh), exponent(rh)
{
- debugmsg("power constructor from ex,numeric",LOGLEVEL_CONSTRUCT);
+ debugmsg("power ctor from ex,numeric",LOGLEVEL_CONSTRUCT);
GINAC_ASSERT(basis.return_type()==return_types::commutative);
}
/** 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);
+ debugmsg("power ctor from archive_node", LOGLEVEL_CONSTRUCT);
n.find_ex("basis", basis, sym_lst);
n.find_ex("exponent", exponent, sym_lst);
}
static void print_sym_pow(std::ostream & os, unsigned type, const symbol &x, int exp)
{
- // Optimal output of integer powers of symbols to aid compiler CSE
+ // Optimal output of integer powers of symbols to aid compiler CSE.
+ // C.f. ISO/IEC 14882:1998, section 1.9 [intro execution], paragraph 15
+ // to learn why such a hack is really necessary.
if (exp == 1) {
x.printcsrc(os, type, 0);
} else if (exp == 2) {
}
// ^(x,0) -> 1 (0^0 also handled here)
- if (eexponent.is_zero())
+ if (eexponent.is_zero()) {
if (ebasis.is_zero())
throw (std::domain_error("power::eval(): pow(0,0) is undefined"));
else
return _ex1();
+ }
// ^(x,1) -> x
if (eexponent.is_equal(_ex1()))
// except if c1,c2 are rational, but c1^c2 is not)
bool basis_is_crational = num_basis->is_crational();
bool exponent_is_crational = num_exponent->is_crational();
- numeric res = (*num_basis).power(*num_exponent);
+ numeric res = num_basis->power(*num_exponent);
if ((!basis_is_crational || !exponent_is_crational)
|| res.is_crational()) {
else {
epvector res;
res.push_back(expair(ebasis,r.div(m)));
- return (new mul(res,ex(num_basis->power(q))))->setflag(status_flags::dynallocated | status_flags::evaluated);
+ return (new mul(res,ex(num_basis->power_dyn(q))))->setflag(status_flags::dynallocated | status_flags::evaluated);
}
}
}
if (is_ex_exactly_of_type(sub_exponent,numeric)) {
const numeric & num_sub_exponent = ex_to_numeric(sub_exponent);
GINAC_ASSERT(num_sub_exponent!=numeric(1));
- if (num_exponent->is_integer() || abs(num_sub_exponent)<1) {
+ if (num_exponent->is_integer() || abs(num_sub_exponent)<1)
return power(sub_basis,num_sub_exponent.mul(*num_exponent));
- }
}
}
// ^(*(...,x,c1),c2) -> ^(*(...,x;-1),c2)*(-c1)^c2 (c1, c2 numeric(), c1<0)
if (exponent_is_numerical && is_ex_exactly_of_type(ebasis,mul)) {
GINAC_ASSERT(!num_exponent->is_integer()); // should have been handled above
- const mul & mulref=ex_to_mul(ebasis);
+ const mul & mulref = ex_to_mul(ebasis);
if (!mulref.overall_coeff.is_equal(_ex1())) {
- const numeric & num_coeff=ex_to_numeric(mulref.overall_coeff);
+ const numeric & num_coeff