* Implementation of sequences of expression pairs. */
/*
- * GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
+ * GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University Mainz, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include "expairseq.h"
#include "lst.h"
+#include "archive.h"
#include "debugmsg.h"
#include "utils.h"
-#ifndef NO_GINAC_NAMESPACE
+#ifndef NO_NAMESPACE_GINAC
namespace GiNaC {
-#endif // ndef NO_GINAC_NAMESPACE
+#endif // ndef NO_NAMESPACE_GINAC
#ifdef EXPAIRSEQ_USE_HASHTAB
#error "FIXME: expair_needs_further_processing not yet implemented for hashtabs, sorry. A.F."
#endif // def EXPAIRSEQ_USE_HASHTAB
+GINAC_IMPLEMENT_REGISTERED_CLASS(expairseq, basic)
+
//////////
// helper classes
//////////
class epp_is_less
{
public:
- bool operator()(epp const & lh, epp const & rh) const
+ bool operator()(const epp & lh, const epp & rh) const
{
return (*lh).is_less(*rh);
}
// public
-expairseq::expairseq(expairseq const & other)
+expairseq::expairseq(const expairseq & other)
{
debugmsg("expairseq copy constructor",LOGLEVEL_CONSTRUCT);
copy(other);
}
-expairseq const & expairseq::operator=(expairseq const & other)
+const expairseq & expairseq::operator=(const expairseq & other)
{
debugmsg("expairseq operator=",LOGLEVEL_ASSIGNMENT);
if (this != &other) {
// protected
-void expairseq::copy(expairseq const & other)
+void expairseq::copy(const expairseq & other)
{
- basic::copy(other);
+ inherited::copy(other);
seq=other.seq;
overall_coeff=other.overall_coeff;
#ifdef EXPAIRSEQ_USE_HASHTAB
// other constructors
//////////
-expairseq::expairseq(ex const & lh, ex const & rh) : basic(TINFO_expairseq)
+expairseq::expairseq(const ex & lh, const ex & rh) : inherited(TINFO_expairseq)
{
debugmsg("expairseq constructor from ex,ex",LOGLEVEL_CONSTRUCT);
construct_from_2_ex(lh,rh);
GINAC_ASSERT(is_canonical());
}
-expairseq::expairseq(exvector const & v) : basic(TINFO_expairseq)
+expairseq::expairseq(const exvector & v) : inherited(TINFO_expairseq)
{
debugmsg("expairseq constructor from exvector",LOGLEVEL_CONSTRUCT);
construct_from_exvector(v);
}
/*
-expairseq::expairseq(epvector const & v, bool do_not_canonicalize) :
- basic(TINFO_expairseq)
+expairseq::expairseq(const epvector & v, bool do_not_canonicalize) :
+ inherited(TINFO_expairseq)
{
debugmsg("expairseq constructor from epvector",LOGLEVEL_CONSTRUCT);
if (do_not_canonicalize) {
}
*/
-expairseq::expairseq(epvector const & v, ex const & oc) :
- basic(TINFO_expairseq), overall_coeff(oc)
+expairseq::expairseq(const epvector & v, const ex & oc) :
+ inherited(TINFO_expairseq), overall_coeff(oc)
{
debugmsg("expairseq constructor from epvector,ex",LOGLEVEL_CONSTRUCT);
construct_from_epvector(v);
GINAC_ASSERT(is_canonical());
}
-expairseq::expairseq(epvector * vp, ex const & oc) :
- basic(TINFO_expairseq), overall_coeff(oc)
+expairseq::expairseq(epvector * vp, const ex & oc) :
+ inherited(TINFO_expairseq), overall_coeff(oc)
{
debugmsg("expairseq constructor from epvector *,ex",LOGLEVEL_CONSTRUCT);
GINAC_ASSERT(vp!=0);
GINAC_ASSERT(is_canonical());
}
+//////////
+// archiving
+//////////
+
+/** Construct object from archive_node. */
+expairseq::expairseq(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
+#ifdef EXPAIRSEQ_USE_HASHTAB
+ , hashtabsize(0)
+#endif
+{
+ debugmsg("expairseq constructor from archive_node", LOGLEVEL_CONSTRUCT);
+ for (unsigned int i=0; true; i++) {
+ ex rest;
+ ex coeff;
+ if (n.find_ex("rest", rest, sym_lst, i) && n.find_ex("coeff", coeff, sym_lst, i))
+ seq.push_back(expair(rest, coeff));
+ else
+ break;
+ }
+ n.find_ex("overall_coeff", overall_coeff, sym_lst);
+}
+
+/** Unarchive the object. */
+ex expairseq::unarchive(const archive_node &n, const lst &sym_lst)
+{
+ return (new expairseq(n, sym_lst))->setflag(status_flags::dynallocated);
+}
+
+/** Archive the object. */
+void expairseq::archive(archive_node &n) const
+{
+ inherited::archive(n);
+ epvector::const_iterator i = seq.begin(), iend = seq.end();
+ while (i != iend) {
+ n.add_ex("rest", i->rest);
+ n.add_ex("coeff", i->coeff);
+ i++;
+ }
+ n.add_ex("overall_coeff", overall_coeff);
+}
+
//////////
// functions overriding virtual functions from bases classes
//////////
unsigned count[MAXCOUNT+1];
for (int i=0; i<MAXCOUNT+1; ++i) count[i]=0;
unsigned this_bin_fill;
- unsigned cum_fill_sq=0;
- unsigned cum_fill=0;
+ unsigned cum_fill_sq = 0;
+ unsigned cum_fill = 0;
for (unsigned i=0; i<hashtabsize; ++i) {
this_bin_fill=0;
if (hashtab[i].size()>0) {
++count[MAXCOUNT];
}
}
- unsigned fact=1;
- double cum_prob=0;
- double lambda=(1.0*seq.size())/hashtabsize;
+ 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);
+ double prob = pow(lambda,k)/fact*exp(-lambda);
cum_prob += prob;
os << string(indent+delta_indent,' ') << "bins with " << k << " entries: "
<< int(1000.0*count[k]/hashtabsize)/10.0 << "% (expected: "
bool expairseq::info(unsigned inf) const
{
- return basic::info(inf);
+ return inherited::info(inf);
}
-int expairseq::nops() const
+unsigned expairseq::nops() const
{
if (overall_coeff.is_equal(default_overall_coeff())) {
return seq.size();
return seq.size()+1;
}
-ex expairseq::op(int const i) const
+ex expairseq::op(int i) const
{
if (unsigned(i)<seq.size()) {
return recombine_pair_to_ex(seq[i]);
return overall_coeff;
}
-ex & expairseq::let_op(int const i)
+ex & expairseq::let_op(int i)
{
throw(std::logic_error("let_op not defined for expairseq and derived classes (add,mul,...)"));
}
ex expairseq::evalf(int level) const
{
- return thisexpairseq(evalfchildren(level),overall_coeff);
+ return thisexpairseq(evalfchildren(level),overall_coeff.evalf(level-1));
}
ex expairseq::normal(lst &sym_lst, lst &repl_lst, int level) const
{
- ex n=thisexpairseq(normalchildren(level),overall_coeff);
+ ex n = thisexpairseq(normalchildren(level),overall_coeff);
return n.bp->basic::normal(sym_lst,repl_lst,level);
}
-ex expairseq::subs(lst const & ls, lst const & lr) const
+ex expairseq::subs(const lst & ls, const lst & lr) const
{
epvector * vp=subschildren(ls,lr);
if (vp==0) {
// protected
-int expairseq::compare_same_type(basic const & other) const
+/** Implementation of ex::diff() for an expairseq. It differentiates all elements of the
+ * sequence.
+ * @see ex::diff */
+ex expairseq::derivative(const symbol & s) const
+{
+ return thisexpairseq(diffchildren(s),overall_coeff);
+}
+
+int expairseq::compare_same_type(const basic & other) const
{
GINAC_ASSERT(is_of_type(other, expairseq));
- expairseq const & o=static_cast<expairseq const &>(const_cast<basic &>(other));
+ const expairseq & o = static_cast<const expairseq &>(const_cast<basic &>(other));
int cmpval;
}
// compare overall_coeff
- cmpval=overall_coeff.compare(o.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
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();
- epvector::const_iterator last2=o.seq.end();
+ epvector::const_iterator cit1 = seq.begin();
+ epvector::const_iterator cit2 = o.seq.begin();
+ epvector::const_iterator last1 = seq.end();
+ epvector::const_iterator last2 = o.seq.end();
for (; (cit1!=last1)&&(cit2!=last2); ++cit1, ++cit2) {
- cmpval=(*cit1).compare(*cit2);
+ cmpval = (*cit1).compare(*cit2);
if (cmpval!=0) return cmpval;
}
for (unsigned i=0; i<hashtabsize; ++i) {
unsigned sz=hashtab[i].size();
if (sz>0) {
- epplist const & eppl1=hashtab[i];
- epplist const & eppl2=o.hashtab[i];
+ 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()) {
#endif // def EXPAIRSEQ_USE_HASHTAB
}
-bool expairseq::is_equal_same_type(basic const & other) const
+bool expairseq::is_equal_same_type(const basic & other) const
{
- expairseq const & o=dynamic_cast<expairseq const &>(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;
for (unsigned i=0; i<hashtabsize; ++i) {
unsigned sz=hashtab[i].size();
if (sz>0) {
- epplist const & eppl1=hashtab[i];
- epplist const & eppl2=o.hashtab[i];
+ 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()) {
ex expairseq::expand(unsigned options) const
{
- epvector * vp=expandchildren(options);
+ epvector * vp = expandchildren(options);
if (vp==0) {
return *this;
}
// protected
-ex expairseq::thisexpairseq(epvector const & v,ex const & oc) const
+ex expairseq::thisexpairseq(const epvector & v,const ex & oc) const
{
return expairseq(v,oc);
}
-ex expairseq::thisexpairseq(epvector * vp, ex const & oc) const
+ex expairseq::thisexpairseq(epvector * vp, const ex & oc) const
{
return expairseq(vp,oc);
}
-void expairseq::printpair(ostream & os, expair const & p, unsigned upper_precedence) const
+void expairseq::printpair(ostream & os, const expair & p, unsigned upper_precedence) const
{
os << "[[";
p.rest.bp->print(os,precedence);
if (this_precedence<=upper_precedence) os << ")";
}
-expair expairseq::split_ex_to_pair(ex const & e) const
+expair expairseq::split_ex_to_pair(const ex & e) const
{
- return expair(e,exONE());
+ return expair(e,_ex1());
}
-expair expairseq::combine_ex_with_coeff_to_pair(ex const & e,
- ex const & 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(expair const & p,
- ex const & 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(expair const & p) const
+ex expairseq::recombine_pair_to_ex(const expair & p) const
{
return lst(p.rest,p.coeff);
}
ex expairseq::default_overall_coeff(void) const
{
- return exZERO();
+ return _ex0();
}
-void expairseq::combine_overall_coeff(ex const & 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(ex const & c1, ex const & 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(expair const & 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(ex const & lh, ex const & rh)
+void expairseq::construct_from_2_ex_via_exvector(const ex & lh, const ex & rh)
{
exvector v;
v.reserve(2);
#endif // def EXPAIRSEQ_USE_HASHTAB
}
-void expairseq::construct_from_2_ex(ex const & lh, ex const & rh)
+void expairseq::construct_from_2_ex(const ex & lh, const ex & rh)
{
if (lh.bp->tinfo()==tinfo()) {
if (rh.bp->tinfo()==tinfo()) {
}
}
-void expairseq::construct_from_2_expairseq(expairseq const & s1,
- expairseq const & 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);
int cmpval=(*first1).rest.compare((*first2).rest);
if (cmpval==0) {
// combine terms
- numeric const & 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));
}
}
-void expairseq::construct_from_expairseq_ex(expairseq const & s,
- ex const & 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)) {
int cmpval=(*first).rest.compare(p.rest);
if (cmpval==0) {
// combine terms
- numeric const & 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));
}
}
-void expairseq::construct_from_exvector(exvector const & 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)
#endif // def EXPAIRSEQ_USE_HASHTAB
}
-void expairseq::construct_from_epvector(epvector const & 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)
#include <iostream>
-void expairseq::make_flat(exvector const & v)
+void expairseq::make_flat(const exvector & v)
{
exvector::const_iterator cit, citend = v.end();
cit=v.begin();
while (cit!=citend) {
if (cit->bp->tinfo()==tinfo()) {
- expairseq const & subseqref=ex_to_expairseq(*cit);
+ const expairseq & subseqref=ex_to_expairseq(*cit);
combine_overall_coeff(subseqref.overall_coeff);
epvector::const_iterator cit_s=subseqref.seq.begin();
while (cit_s!=subseqref.seq.end()) {
(*cit).printraw(cout);
}
cout << endl;
- cout.flush();
*/
}
-void expairseq::make_flat(epvector const & v)
+void expairseq::make_flat(const epvector & v)
{
epvector::const_iterator cit, citend = v.end();
// and their cumulative number of operands
int nexpairseqs=0;
int noperands=0;
- cit=v.begin();
+
+ cit = v.begin();
while (cit!=citend) {
if (cit->rest.bp->tinfo()==tinfo()) {
nexpairseqs++;
- noperands+=ex_to_expairseq((*cit).rest).seq.size();
+ noperands += ex_to_expairseq((*cit).rest).seq.size();
}
++cit;
}
seq.reserve(v.size()+noperands-nexpairseqs);
// copy elements and split off numerical part
- cit=v.begin();
+ cit = v.begin();
while (cit!=citend) {
if ((cit->rest.bp->tinfo()==tinfo())&&can_make_flat(*cit)) {
- expairseq const & subseqref=ex_to_expairseq((*cit).rest);
+ 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();
return size;
}
-unsigned expairseq::calc_hashindex(ex const & e) const
+unsigned expairseq::calc_hashindex(const ex & e) const
{
// calculate hashindex
unsigned hash=e.gethash();
if (!touched[i]) {
++current;
++i;
- } else if (!ex_to_numeric((*current).coeff).is_equal(numZERO())) {
+ } else if (!ex_to_numeric((*current).coeff).is_equal(_num0())) {
++current;
++i;
} else {
bool expairseq::has_coeff_0(void) const
{
for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
- if ((*cit).coeff.is_equal(exZERO())) {
+ if ((*cit).coeff.is_equal(_ex0())) {
return true;
}
}
if (hashtabsize>0) return 1; // not canoncalized
#endif // def EXPAIRSEQ_USE_HASHTAB
- epvector::const_iterator it=seq.begin();
- epvector::const_iterator it_last=it;
+ epvector::const_iterator it = seq.begin();
+ epvector::const_iterator it_last = it;
for (++it; it!=seq.end(); it_last=it, ++it) {
if (!((*it_last).is_less(*it)||(*it_last).is_equal(*it))) {
if (!is_ex_exactly_of_type((*it_last).rest,numeric)||
epvector * expairseq::expandchildren(unsigned options) const
{
- 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) {
- ex const & 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
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;
epvector::const_iterator last=seq.end();
epvector::const_iterator cit=seq.begin();
while (cit!=last) {
- ex const & 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;
+ epvector *s = new epvector;
s->reserve(seq.size());
// copy parts of seq which are known not to have changed
epvector expairseq::evalfchildren(int level) const
{
- epvector s;
- s.reserve(seq.size());
-
- if (level==1) {
+ 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.evalf(level),
- (*it).coeff));
+ (*it).coeff.evalf(level)));
}
return s;
}
epvector expairseq::normalchildren(int level) const
{
+ if (level==1)
+ return seq;
+
+ if (level == -max_recursion_level)
+ throw(std::runtime_error("max recursion level reached"));
+
epvector s;
s.reserve(seq.size());
- if (level==1) {
- return seq;
- }
- if (level == -max_recursion_level) {
- throw(std::runtime_error("max recursion level reached"));
- }
--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(symbol const & y) const
+epvector expairseq::diffchildren(const symbol & y) const
{
epvector s;
s.reserve(seq.size());
return s;
}
-epvector * expairseq::subschildren(lst const & ls, lst const & lr) const
+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
epvector::const_iterator last=seq.end();
epvector::const_iterator cit=seq.begin();
while (cit!=last) {
- ex const & 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
//////////
const expairseq some_expairseq;
-type_info const & typeid_expairseq=typeid(some_expairseq);
+const type_info & typeid_expairseq=typeid(some_expairseq);
-#ifndef NO_GINAC_NAMESPACE
+#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
-#endif // ndef NO_GINAC_NAMESPACE
+#endif // ndef NO_NAMESPACE_GINAC