3 * Implementation of GiNaC's sums of expressions. */
6 * GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #ifndef NO_GINAC_NAMESPACE
32 #endif // ndef NO_GINAC_NAMESPACE
35 // default constructor, destructor, copy constructor assignment operator and helpers
42 debugmsg("add default constructor",LOGLEVEL_CONSTRUCT);
43 tinfo_key = TINFO_add;
48 debugmsg("add destructor",LOGLEVEL_DESTRUCT);
52 add::add(add const & other)
54 debugmsg("add copy constructor",LOGLEVEL_CONSTRUCT);
58 add const & add::operator=(add const & other)
60 debugmsg("add operator=",LOGLEVEL_ASSIGNMENT);
70 void add::copy(add const & other)
72 expairseq::copy(other);
75 void add::destroy(bool call_parent)
77 if (call_parent) expairseq::destroy(call_parent);
86 add::add(ex const & lh, ex const & rh)
88 debugmsg("add constructor from ex,ex",LOGLEVEL_CONSTRUCT);
89 tinfo_key = TINFO_add;
90 overall_coeff=exZERO();
91 construct_from_2_ex(lh,rh);
92 GINAC_ASSERT(is_canonical());
95 add::add(exvector const & v)
97 debugmsg("add constructor from exvector",LOGLEVEL_CONSTRUCT);
98 tinfo_key = TINFO_add;
99 overall_coeff=exZERO();
100 construct_from_exvector(v);
101 GINAC_ASSERT(is_canonical());
105 add::add(epvector const & v, bool do_not_canonicalize)
107 debugmsg("add constructor from epvector,bool",LOGLEVEL_CONSTRUCT);
108 tinfo_key = TINFO_add;
109 if (do_not_canonicalize) {
111 #ifdef EXPAIRSEQ_USE_HASHTAB
112 combine_same_terms(); // to build hashtab
113 #endif // def EXPAIRSEQ_USE_HASHTAB
115 construct_from_epvector(v);
117 GINAC_ASSERT(is_canonical());
121 add::add(epvector const & v)
123 debugmsg("add constructor from epvector",LOGLEVEL_CONSTRUCT);
124 tinfo_key = TINFO_add;
125 overall_coeff=exZERO();
126 construct_from_epvector(v);
127 GINAC_ASSERT(is_canonical());
130 add::add(epvector const & v, ex const & oc)
132 debugmsg("add constructor from epvector,ex",LOGLEVEL_CONSTRUCT);
133 tinfo_key = TINFO_add;
135 construct_from_epvector(v);
136 GINAC_ASSERT(is_canonical());
139 add::add(epvector * vp, ex const & oc)
141 debugmsg("add constructor from epvector *,ex",LOGLEVEL_CONSTRUCT);
142 tinfo_key = TINFO_add;
145 construct_from_epvector(*vp);
147 GINAC_ASSERT(is_canonical());
151 // functions overriding virtual functions from bases classes
156 basic * add::duplicate() const
158 debugmsg("add duplicate",LOGLEVEL_DUPLICATE);
159 return new add(*this);
162 bool add::info(unsigned inf) const
165 if (inf==info_flags::polynomial || inf==info_flags::integer_polynomial || inf==info_flags::rational_polynomial || inf==info_flags::rational_function) {
166 for (epvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
167 if (!(recombine_pair_to_ex(*it).info(inf)))
172 return expairseq::info(inf);
176 int add::degree(symbol const & s) const
179 if (!overall_coeff.is_equal(exZERO())) {
183 for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
184 cur_deg=(*cit).rest.degree(s);
185 if (cur_deg>deg) deg=cur_deg;
190 int add::ldegree(symbol const & s) const
193 if (!overall_coeff.is_equal(exZERO())) {
197 for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
198 cur_deg=(*cit).rest.ldegree(s);
199 if (cur_deg<deg) deg=cur_deg;
204 ex add::coeff(symbol const & s, int const n) const
207 coeffseq.reserve(seq.size());
209 epvector::const_iterator it=seq.begin();
210 while (it!=seq.end()) {
211 coeffseq.push_back(combine_ex_with_coeff_to_pair((*it).rest.coeff(s,n),
216 return (new add(coeffseq,overall_coeff))->setflag(status_flags::dynallocated);
218 return (new add(coeffseq))->setflag(status_flags::dynallocated);
221 ex add::eval(int level) const
223 // simplifications: +(;c) -> c
226 debugmsg("add eval",LOGLEVEL_MEMBER_FUNCTION);
228 epvector * evaled_seqp=evalchildren(level);
229 if (evaled_seqp!=0) {
230 // do more evaluation later
231 return (new add(evaled_seqp,overall_coeff))->
232 setflag(status_flags::dynallocated);
235 #ifdef DO_GINAC_ASSERT
236 for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
237 GINAC_ASSERT(!is_ex_exactly_of_type((*cit).rest,add));
238 if (is_ex_exactly_of_type((*cit).rest,numeric)) {
241 GINAC_ASSERT(!is_ex_exactly_of_type((*cit).rest,numeric));
243 #endif // def DO_GINAC_ASSERT
245 if (flags & status_flags::evaluated) {
246 GINAC_ASSERT(seq.size()>0);
247 GINAC_ASSERT((seq.size()>1)||!overall_coeff.is_equal(exZERO()));
251 int seq_size=seq.size();
254 return overall_coeff;
255 } else if ((seq_size==1)&&overall_coeff.is_equal(exZERO())) {
257 return recombine_pair_to_ex(*(seq.begin()));
262 exvector add::get_indices(void) const
264 // FIXME: all terms in the sum should have the same indices (compatible
265 // tensors) however this is not checked, since there is no function yet
266 // which compares indices (idxvector can be unsorted)
270 return (seq.begin())->rest.get_indices();
273 ex add::simplify_ncmul(exvector const & v) const
276 return expairseq::simplify_ncmul(v);
278 return (*seq.begin()).rest.simplify_ncmul(v);
283 int add::compare_same_type(basic const & other) const
285 return expairseq::compare_same_type(other);
288 bool add::is_equal_same_type(basic const & other) const
290 return expairseq::is_equal_same_type(other);
293 unsigned add::return_type(void) const
296 return return_types::commutative;
298 return (*seq.begin()).rest.return_type();
301 unsigned add::return_type_tinfo(void) const
306 return (*seq.begin()).rest.return_type_tinfo();
309 ex add::thisexpairseq(epvector const & v, ex const & oc) const
311 return (new add(v,oc))->setflag(status_flags::dynallocated);
314 ex add::thisexpairseq(epvector * vp, ex const & oc) const
316 return (new add(vp,oc))->setflag(status_flags::dynallocated);
319 expair add::split_ex_to_pair(ex const & e) const
321 if (is_ex_exactly_of_type(e,mul)) {
322 mul const & mulref=ex_to_mul(e);
323 ex numfactor=mulref.overall_coeff;
324 // mul * mulcopyp=static_cast<mul *>(mulref.duplicate());
325 mul * mulcopyp=new mul(mulref);
326 mulcopyp->overall_coeff=exONE();
327 mulcopyp->clearflag(status_flags::evaluated);
328 mulcopyp->clearflag(status_flags::hash_calculated);
329 return expair(mulcopyp->setflag(status_flags::dynallocated),numfactor);
331 return expair(e,exONE());
334 expair add::combine_ex_with_coeff_to_pair(ex const & e,
337 GINAC_ASSERT(is_ex_exactly_of_type(c,numeric));
338 if (is_ex_exactly_of_type(e,mul)) {
339 mul const & mulref=ex_to_mul(e);
340 ex numfactor=mulref.overall_coeff;
341 //mul * mulcopyp=static_cast<mul *>(mulref.duplicate());
342 mul * mulcopyp=new mul(mulref);
343 mulcopyp->overall_coeff=exONE();
344 mulcopyp->clearflag(status_flags::evaluated);
345 mulcopyp->clearflag(status_flags::hash_calculated);
346 if (are_ex_trivially_equal(c,exONE())) {
347 return expair(mulcopyp->setflag(status_flags::dynallocated),numfactor);
348 } else if (are_ex_trivially_equal(numfactor,exONE())) {
349 return expair(mulcopyp->setflag(status_flags::dynallocated),c);
351 return expair(mulcopyp->setflag(status_flags::dynallocated),
352 ex_to_numeric(numfactor).mul_dyn(ex_to_numeric(c)));
353 } else if (is_ex_exactly_of_type(e,numeric)) {
354 if (are_ex_trivially_equal(c,exONE())) {
355 return expair(e,exONE());
357 return expair(ex_to_numeric(e).mul_dyn(ex_to_numeric(c)),exONE());
362 expair add::combine_pair_with_coeff_to_pair(expair const & p,
365 GINAC_ASSERT(is_ex_exactly_of_type(p.coeff,numeric));
366 GINAC_ASSERT(is_ex_exactly_of_type(c,numeric));
368 if (is_ex_exactly_of_type(p.rest,numeric)) {
369 GINAC_ASSERT(ex_to_numeric(p.coeff).is_equal(numONE())); // should be normalized
370 return expair(ex_to_numeric(p.rest).mul_dyn(ex_to_numeric(c)),exONE());
373 return expair(p.rest,ex_to_numeric(p.coeff).mul_dyn(ex_to_numeric(c)));
376 ex add::recombine_pair_to_ex(expair const & p) const
378 //if (p.coeff.compare(exONE())==0) {
379 //if (are_ex_trivially_equal(p.coeff,exONE())) {
380 if (ex_to_numeric(p.coeff).is_equal(numONE())) {
383 return p.rest*p.coeff;
387 ex add::expand(unsigned options) const
389 epvector * vp=expandchildren(options);
393 return (new add(vp,overall_coeff))->setflag(status_flags::expanded |
394 status_flags::dynallocated );
398 // new virtual functions which can be overridden by derived classes
404 // non-virtual functions in this class
410 // static member variables
415 unsigned add::precedence=40;
422 type_info const & typeid_add=typeid(some_add);
424 #ifndef NO_GINAC_NAMESPACE
426 #endif // ndef NO_GINAC_NAMESPACE