X-Git-Url: https://ginac.de/ginac.git//ginac.git?a=blobdiff_plain;f=ginac%2Fmul.cpp;h=8eef91763736fe0a759a699a8d0d4670c7b99a84;hb=9d8d0f4924171b0acb7ec6a333897fe1ec545707;hp=ad7aa13e3d5e5568241398f18ab55788241e94ad;hpb=8397b7a8f4d9a8e6db0025813f125ee365b15e6a;p=ginac.git diff --git a/ginac/mul.cpp b/ginac/mul.cpp index ad7aa13e..8eef9176 100644 --- a/ginac/mul.cpp +++ b/ginac/mul.cpp @@ -3,7 +3,7 @@ * Implementation of GiNaC's products of expressions. */ /* - * 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 @@ -30,48 +30,25 @@ #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; } -mul::~mul() -{ - debugmsg("mul destructor",LOGLEVEL_DESTRUCT); - destroy(false); -} - -mul::mul(const mul & other) -{ - debugmsg("mul copy constructor",LOGLEVEL_CONSTRUCT); - copy(other); -} - -const mul & mul::operator=(const mul & other) -{ - debugmsg("mul operator=",LOGLEVEL_ASSIGNMENT); - if (this != &other) { - destroy(true); - copy(other); - } - return *this; -} - // protected +/** For use by copy ctor and assignment operator. */ void mul::copy(const mul & other) { inherited::copy(other); @@ -83,14 +60,14 @@ void mul::destroy(bool call_parent) } ////////// -// 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); @@ -99,7 +76,7 @@ mul::mul(const ex & lh, const ex & 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); @@ -108,7 +85,7 @@ mul::mul(const 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); @@ -117,7 +94,7 @@ mul::mul(const 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); @@ -126,7 +103,7 @@ mul::mul(const epvector & v, const ex & oc) 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; @@ -137,7 +114,7 @@ mul::mul(epvector * vp, const ex & 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); @@ -156,7 +133,7 @@ mul::mul(const ex & lh, const ex & mh, const ex & rh) /** 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. */ @@ -177,17 +154,11 @@ void mul::archive(archive_node &n) const // public -basic * mul::duplicate() const -{ - debugmsg("mul duplicate",LOGLEVEL_ASSIGNMENT); - return new mul(*this); -} - void mul::print(std::ostream & os, unsigned upper_precedence) const { 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 << '-'; @@ -304,8 +275,6 @@ bool mul::info(unsigned inf) const return inherited::info(inf); } -typedef std::vector intvector; - int mul::degree(const symbol & s) const { int deg_sum = 0; @@ -334,7 +303,7 @@ ex mul::coeff(const symbol & s, int n) const if (n==0) { // product of individual coeffs // if a non-zero power of s is found, the resulting product will be 0 - epvector::const_iterator it=seq.begin(); + epvector::const_iterator it = seq.begin(); while (it!=seq.end()) { coeffseq.push_back(recombine_pair_to_ex(*it).coeff(s,n)); ++it; @@ -342,15 +311,15 @@ ex mul::coeff(const symbol & s, int n) const coeffseq.push_back(overall_coeff); return (new mul(coeffseq))->setflag(status_flags::dynallocated); } - + epvector::const_iterator it=seq.begin(); - bool coeff_found=0; + bool coeff_found = 0; while (it!=seq.end()) { - ex t=recombine_pair_to_ex(*it); - ex c=t.coeff(s,n); + ex t = recombine_pair_to_ex(*it); + ex c = t.coeff(s,n); if (!c.is_zero()) { coeffseq.push_back(c); - coeff_found=1; + coeff_found = 1; } else { coeffseq.push_back(t); } @@ -370,54 +339,53 @@ ex mul::eval(int level) const // *(+(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) { @@ -450,20 +418,6 @@ ex mul::evalf(int level) const return mul(s,overall_coeff.evalf(level)); } -exvector mul::get_indices(void) const -{ - // return union of indices of factors - exvector iv; - 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) { - iv.push_back(*cit2); - } - } - return iv; -} - ex mul::simplify_ncmul(const exvector & v) const { throw(std::logic_error("mul::simplify_ncmul() should never have been called!")); @@ -504,11 +458,11 @@ unsigned mul::return_type(void) const // 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 @@ -531,15 +485,13 @@ unsigned mul::return_type(void) const 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; @@ -558,10 +510,9 @@ ex mul::thisexpairseq(epvector * vp, const ex & oc) const 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()); } @@ -605,14 +556,14 @@ bool mul::expair_needs_further_processing(epp it) 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())) { @@ -658,75 +609,66 @@ ex mul::expand(unsigned options) const return *this; exvector sub_expanded_seq; - intvector positions_of_adds; - intvector number_of_add_operands; epvector * expanded_seqp = expandchildren(options); const epvector & expanded_seq = expanded_seqp==0 ? seq : *expanded_seqp; - positions_of_adds.resize(expanded_seq.size()); - number_of_add_operands.resize(expanded_seq.size()); - int number_of_adds = 0; - int number_of_expanded_terms = 1; - - unsigned current_position = 0; + epvector non_adds; + non_adds.reserve(expanded_seq.size()); + epvector::const_iterator cit = expanded_seq.begin(); epvector::const_iterator last = expanded_seq.end(); - for (epvector::const_iterator cit = expanded_seq.begin(); cit!=last; ++cit) { + ex last_expanded = _ex1(); + while (cit!=last) { if (is_ex_exactly_of_type((*cit).rest,add) && ((*cit).coeff.is_equal(_ex1()))) { - positions_of_adds[number_of_adds] = current_position; - const add & expanded_addref = ex_to_add((*cit).rest); - unsigned addref_nops = expanded_addref.nops(); - number_of_add_operands[number_of_adds] = addref_nops; - number_of_expanded_terms *= addref_nops; ++number_of_adds; + if (is_ex_exactly_of_type(last_expanded,add)) { + // expand adds + const add & add1 = ex_to_add(last_expanded); + const add & add2 = ex_to_add((*cit).rest); + int n1 = add1.nops(); + int n2 = add2.nops(); + exvector distrseq; + distrseq.reserve(n1*n2); + for (int i1=0; i1setflag(status_flags::dynallocated | status_flags::expanded); + } else { + non_adds.push_back(split_ex_to_pair(last_expanded)); + last_expanded = (*cit).rest; + } + } else { + non_adds.push_back(*cit); } - ++current_position; - } - - if (number_of_adds==0) { - if (expanded_seqp==0) - return this->setflag(status_flags::expanded); - else - return ((new mul(expanded_seqp,overall_coeff))-> - setflag(status_flags::dynallocated | status_flags::expanded)); + ++cit; } - - exvector distrseq; - distrseq.reserve(number_of_expanded_terms); - - intvector k; - k.resize(number_of_adds, 0); - - for (;;) { - epvector term; - term = expanded_seq; - for (int l=0; l - setflag(status_flags::dynallocated | status_flags::expanded)); - - // increment k[] - int l = number_of_adds-1; - while ((l>=0) && ((++k[l])>=number_of_add_operands[l])) { - k[l] = 0; - --l; + if (expanded_seqp) + delete expanded_seqp; + + if (is_ex_exactly_of_type(last_expanded,add)) { + add const & finaladd = ex_to_add(last_expanded); + exvector distrseq; + int n = finaladd.nops(); + distrseq.reserve(n); + for (int i=0; isetflag(status_flags::dynallocated | status_flags::expanded)); } - if (l < 0) break; + return ((new add(distrseq))-> + setflag(status_flags::dynallocated | status_flags::expanded)); } - - if (expanded_seqp!=0) - delete expanded_seqp; - - return (new add(distrseq))->setflag(status_flags::dynallocated | - status_flags::expanded); + non_adds.push_back(split_ex_to_pair(last_expanded)); + return (new mul(non_adds,overall_coeff))-> + setflag(status_flags::dynallocated | status_flags::expanded); } + ////////// // new virtual functions which can be overridden by derived classes ////////// @@ -737,6 +679,14 @@ ex mul::expand(unsigned options) const // 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(); @@ -747,7 +697,7 @@ epvector * mul::expandchildren(unsigned options) const 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 @@ -771,7 +721,7 @@ epvector * mul::expandchildren(unsigned options) const return 0; // nothing has changed } - + ////////// // static member variables ////////// @@ -780,14 +730,4 @@ epvector * mul::expandchildren(unsigned options) const unsigned mul::precedence = 50; - -////////// -// global constants -////////// - -const mul some_mul; -const std::type_info & typeid_mul = typeid(some_mul); - -#ifndef NO_NAMESPACE_GINAC } // namespace GiNaC -#endif // ndef NO_NAMESPACE_GINAC