* Implementation of sequences of expression pairs. */
/*
- * GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University Mainz, Germany
+ * GiNaC Copyright (C) 1999-2001 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 <algorithm>
#include <string>
#include <stdexcept>
-#include <cmath>
#include "expairseq.h"
#include "lst.h"
#error "FIXME: expair_needs_further_processing not yet implemented for hashtabs, sorry. A.F."
#endif // def EXPAIRSEQ_USE_HASHTAB
-GINAC_IMPLEMENT_REGISTERED_CLASS(expairseq, basic)
+GINAC_IMPLEMENT_REGISTERED_CLASS_NO_CTORS(expairseq, basic)
//////////
// helper classes
{
debugmsg("expairseq operator=",LOGLEVEL_ASSIGNMENT);
if (this != &other) {
- destroy(1);
+ destroy(true);
copy(other);
}
return *this;
for (unsigned i=0; i<hashtabsize; ++i) {
hashtab[i].clear();
for (epplist::const_iterator cit=other.hashtab[i].begin();
- cit!=other.hashtab[i].end(); ++cit) {
+ cit!=other.hashtab[i].end(); ++cit) {
hashtab[i].push_back(seq.begin()+((*cit)-osb));
}
}
}
/*
-expairseq::expairseq(const epvector & v, bool do_not_canonicalize) :
- inherited(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(const epvector & v, const ex & oc) :
- inherited(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, const ex & oc) :
- inherited(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);
while (i != iend) {
n.add_ex("rest", i->rest);
n.add_ex("coeff", i->coeff);
- i++;
+ ++i;
}
n.add_ex("overall_coeff", overall_coeff);
}
for (epplist::const_iterator it=hashtab[i].begin();
it!=hashtab[i].end(); ++it) {
os << *it-seq.begin() << " ";
- this_bin_fill++;
+ ++this_bin_fill;
}
os << std::endl;
cum_fill += this_bin_fill;
return this->hold();
}
- return (new expairseq(vp,overall_coeff))
- ->setflag(status_flags::dynallocated |
- status_flags::evaluated );
+ return (new expairseq(vp,overall_coeff))->setflag(status_flags::dynallocated | status_flags::evaluated);
}
ex expairseq::evalf(int level) const
}
void expairseq::printseq(std::ostream & os, char delim,
- unsigned this_precedence,
- unsigned upper_precedence) const
+ unsigned this_precedence,
+ unsigned upper_precedence) const
{
if (this_precedence<=upper_precedence) os << "(";
epvector::const_iterator it,it_last;
}
expair expairseq::combine_ex_with_coeff_to_pair(const ex & e,
- const ex & c) const
+ const ex & c) const
{
GINAC_ASSERT(is_ex_exactly_of_type(c,numeric));
}
expair expairseq::combine_pair_with_coeff_to_pair(const expair & p,
- const ex & c) const
+ const ex & c) const
{
GINAC_ASSERT(is_ex_exactly_of_type(p.coeff,numeric));
GINAC_ASSERT(is_ex_exactly_of_type(c,numeric));
GINAC_ASSERT(is_ex_exactly_of_type(c1,numeric));
GINAC_ASSERT(is_ex_exactly_of_type(c2,numeric));
overall_coeff = ex_to_numeric(overall_coeff).
- add_dyn(ex_to_numeric(c1).mul(ex_to_numeric(c2)));
+ add_dyn(ex_to_numeric(c1).mul(ex_to_numeric(c2)));
}
bool expairseq::can_make_flat(const expair & p) const
void expairseq::construct_from_2_ex(const ex & lh, const ex & rh)
{
if (lh.bp->tinfo()==tinfo()) {
- if (rh.bp->tinfo()==tinfo()) {
+ if (rh.bp->tinfo()==tinfo()) {
#ifdef 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 {
+ 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
- construct_from_2_expairseq(ex_to_expairseq(lh),
- ex_to_expairseq(rh));
+ construct_from_2_expairseq(ex_to_expairseq(lh),
+ ex_to_expairseq(rh));
#ifdef EXPAIRSEQ_USE_HASHTAB
- }
+ }
#endif // def EXPAIRSEQ_USE_HASHTAB
- return;
- } else {
+ return;
+ } else {
#ifdef 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 {
+ 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
- construct_from_expairseq_ex(ex_to_expairseq(lh),rh);
+ construct_from_expairseq_ex(ex_to_expairseq(lh), rh);
#ifdef EXPAIRSEQ_USE_HASHTAB
- }
+ }
#endif // def EXPAIRSEQ_USE_HASHTAB
- return;
- }
+ return;
+ }
} else if (rh.bp->tinfo()==tinfo()) {
#ifdef EXPAIRSEQ_USE_HASHTAB
unsigned totalsize=ex_to_expairseq(rh).seq.size()+1;
int cmpval=(*first1).rest.compare((*first2).rest);
if (cmpval==0) {
// combine terms
- const numeric & newcoeff=ex_to_numeric((*first1).coeff).
- add(ex_to_numeric((*first2).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));
if (expair_needs_further_processing(seq.end()-1)) {
int cmpval=(*first).rest.compare(p.rest);
if (cmpval==0) {
// combine terms
- const numeric & newcoeff=ex_to_numeric((*first).coeff).
- add(ex_to_numeric(p.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));
if (expair_needs_further_processing(seq.end()-1)) {
cit=v.begin();
while (cit!=citend) {
if (cit->bp->tinfo()==tinfo()) {
- nexpairseqs++;
+ ++nexpairseqs;
noperands+=ex_to_expairseq(*cit).seq.size();
}
++cit;
cit = v.begin();
while (cit!=citend) {
if (cit->rest.bp->tinfo()==tinfo()) {
- nexpairseqs++;
+ ++nexpairseqs;
noperands += ex_to_expairseq((*cit).rest).seq.size();
}
++cit;
if ((cit->rest.bp->tinfo()==tinfo())&&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));
+ ex_to_numeric((*cit).coeff));
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))));
+ ex_to_numeric((*cit_s).coeff).mul_dyn(ex_to_numeric((*cit).coeff))));
//seq.push_back(combine_pair_with_coeff_to_pair(*cit_s,
// (*cit).coeff));
++cit_s;
do {
last_numeric--;
} while (is_ex_exactly_of_type((*last_numeric).rest,numeric));
- last_numeric++;
+ ++last_numeric;
sort(last_numeric,seq.end(),expair_is_less());
}
}
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));
+ (*itin1).coeff = ex_to_numeric((*itin1).coeff).
+ add_dyn(ex_to_numeric((*itin2).coeff));
if (expair_needs_further_processing(itin1)) {
needs_further_processing = true;
}
unsigned hash=e.gethash();
unsigned hashindex;
if (is_a_numeric_hash(hash)) {
- hashindex=hashmask;
+ hashindex = hashmask;
} else {
- hashindex=hash & hashmask;
+ hashindex = hash & hashmask;
// last hashtab entry is reserved for numerics
- if (hashindex==hashmask) hashindex=0;
+ if (hashindex==hashmask) hashindex = 0;
}
GINAC_ASSERT(hashindex>=0);
GINAC_ASSERT((hashindex<hashtabsize)||(hashtabsize==0));
GINAC_ASSERT(new_hashtabsize<hashtabsize);
if (new_hashtabsize==0) {
hashtab.clear();
- hashtabsize=0;
+ hashtabsize = 0;
canonicalize();
return;
}
// shrink by a factor of 2
unsigned half_hashtabsize=hashtabsize/2;
- for (unsigned i=0; i<half_hashtabsize-1; ++i) {
+ for (unsigned i=0; i<half_hashtabsize-1; ++i)
hashtab[i].merge(hashtab[i+half_hashtabsize],epp_is_less());
- }
// special treatment for numeric hashes
hashtab[0].merge(hashtab[half_hashtabsize-1],epp_is_less());
- hashtab[half_hashtabsize-1]=hashtab[hashtabsize-1];
+ hashtab[half_hashtabsize-1] = hashtab[hashtabsize-1];
hashtab.resize(half_hashtabsize);
- hashtabsize=half_hashtabsize;
- hashmask=hashtabsize-1;
+ hashtabsize = half_hashtabsize;
+ hashmask = hashtabsize-1;
}
}
if (hashtabsize==0) return; // nothing to do
// calculate hashindex of element to be deleted
- unsigned hashindex=calc_hashindex((*element).rest);
+ unsigned hashindex = calc_hashindex((*element).rest);
// find it in hashtab and remove it
- epplist & eppl=hashtab[hashindex];
- epplist::iterator epplit=eppl.begin();
- bool erased=false;
+ epplist & eppl = hashtab[hashindex];
+ epplist::iterator epplit = eppl.begin();
+ bool erased = false;
while (epplit!=eppl.end()) {
if (*epplit == element) {
eppl.erase(epplit);
- erased=true;
+ erased = true;
break;
}
++epplit;
cout << "tried to erase " << element-seq.begin() << std::endl;
cout << "size " << seq.end()-seq.begin() << std::endl;
- unsigned hashindex=calc_hashindex((*element).rest);
- epplist & eppl=hashtab[hashindex];
+ unsigned hashindex = calc_hashindex((*element).rest);
+ epplist & eppl = hashtab[hashindex];
epplist::iterator epplit=eppl.begin();
bool erased=false;
while (epplit!=eppl.end()) {
if (*epplit == element) {
eppl.erase(epplit);
- erased=true;
+ erased = true;
break;
}
++epplit;
unsigned hashindex=calc_hashindex((*newpos).rest);
// find it in hashtab and modify it
- epplist & eppl=hashtab[hashindex];
+ epplist & eppl = hashtab[hashindex];
epplist::iterator epplit=eppl.begin();
while (epplit!=eppl.end()) {
if (*epplit == oldpos) {
void expairseq::sorted_insert(epplist & eppl, epp elem)
{
- epplist::iterator current=eppl.begin();
+ epplist::iterator current = eppl.begin();
while ((current!=eppl.end())&&((*(*current)).is_less(*elem))) {
++current;
}
}
void expairseq::build_hashtab_and_combine(epvector::iterator & first_numeric,
- epvector::iterator & last_non_zero,
- vector<bool> & touched,
- unsigned & number_of_zeroes)
+ epvector::iterator & last_non_zero,
+ vector<bool> & touched,
+ unsigned & number_of_zeroes)
{
epp current=seq.begin();
++current;
} else {
// epplit points to a matching expair, combine it with current
- (*(*epplit)).coeff=ex_to_numeric((*(*epplit)).coeff).
- add_dyn(ex_to_numeric((*current).coeff));
+ (*(*epplit)).coeff = ex_to_numeric((*(*epplit)).coeff).
+ add_dyn(ex_to_numeric((*current).coeff));
// move obsolete current expair to end by swapping with last_non_zero element
// if this was a numeric, it is swapped with the expair before first_numeric
}
void expairseq::drop_coeff_0_terms(epvector::iterator & first_numeric,
- epvector::iterator & last_non_zero,
- vector<bool> & touched,
- unsigned & number_of_zeroes)
+ 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
++number_of_zeroes;
if (first_numeric!=current) {
-
+
// 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()];
// combine same terms, drop term with coeff 0, move numerics to end
// calculate size of hashtab
- hashtabsize=calc_hashtabsize(seq.size());
+ hashtabsize = calc_hashtabsize(seq.size());
// hashtabsize is a power of 2
- hashmask=hashtabsize-1;
+ hashmask = hashtabsize-1;
// allocate hashtab
hashtab.clear();
touched.reserve(seq.size());
for (unsigned i=0; i<seq.size(); ++i) touched[i]=false;
- unsigned number_of_zeroes=0;
+ unsigned number_of_zeroes = 0;
GINAC_ASSERT(!has_coeff_0());
build_hashtab_and_combine(first_numeric,last_non_zero,touched,number_of_zeroes);
// double test makes it easier to set a breakpoint...
if (!is_ex_exactly_of_type((*it_last).rest,numeric)||
!is_ex_exactly_of_type((*it).rest,numeric)) {
- printpair(cout,*it_last,0);
- cout << ">";
- printpair(cout,*it,0);
- cout << "\n";
- cout << "pair1:" << std::endl;
- (*it_last).rest.printtree(cout);
- (*it_last).coeff.printtree(cout);
- cout << "pair2:" << std::endl;
- (*it).rest.printtree(cout);
- (*it).coeff.printtree(cout);
+ printpair(std::clog,*it_last,0);
+ std::clog << ">";
+ printpair(std::clog,*it,0);
+ std::clog << "\n";
+ std::clog << "pair1:" << std::endl;
+ (*it_last).rest.printtree(std::clog);
+ (*it_last).coeff.printtree(std::clog);
+ std::clog << "pair2:" << std::endl;
+ (*it).rest.printtree(std::clog);
+ (*it).coeff.printtree(std::clog);
return 0;
}
}
}
// copy first changed element
s->push_back(combine_ex_with_coeff_to_pair(expanded_ex,
- (*cit2).coeff));
+ (*cit2).coeff));
++cit2;
// copy rest
while (cit2!=last) {
s->push_back(combine_ex_with_coeff_to_pair((*cit2).rest.expand(options),
- (*cit2).coeff));
+ (*cit2).coeff));
++cit2;
}
return s;
}
// copy first changed element
s->push_back(combine_ex_with_coeff_to_pair(evaled_ex,
- (*cit2).coeff));
+ (*cit2).coeff));
++cit2;
// copy rest
while (cit2!=last) {
s->push_back(combine_ex_with_coeff_to_pair((*cit2).rest.eval(level),
- (*cit2).coeff));
+ (*cit2).coeff));
++cit2;
}
return s;
--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.evalf(level)));
+ (*it).coeff.evalf(level)));
}
return s;
}
--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),
- (*it).coeff));
+ (*it).coeff));
}
return s;
}
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));
+ (*it).coeff));
}
return s;
}
if (!are_ex_trivially_equal((*cit).rest,subsed_ex)) {
// something changed, copy seq, subs 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
}
// copy first changed element
s->push_back(combine_ex_with_coeff_to_pair(subsed_ex,
- (*cit2).coeff));
+ (*cit2).coeff));
++cit2;
// copy rest
while (cit2!=last) {
s->push_back(combine_ex_with_coeff_to_pair((*cit2).rest.subs(ls,lr),
- (*cit2).coeff));
+ (*cit2).coeff));
++cit2;
}
return s;
unsigned expairseq::hashtabfactor=1;
#endif // def EXPAIRSEQ_USE_HASHTAB
-//////////
-// global constants
-//////////
-
-const expairseq some_expairseq;
-const type_info & typeid_expairseq=typeid(some_expairseq);
-
#ifndef NO_NAMESPACE_GINAC
} // namespace GiNaC
#endif // ndef NO_NAMESPACE_GINAC