/[GiNaC]/ginac/add.cpp
ViewVC logotype

Contents of /ginac/add.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.15 - (hide annotations)
Mon Jan 24 19:09:46 2000 UTC (13 years, 3 months ago) by kreckel
Branch: MAIN
Changes since 1.14: +0 -39 lines
- killed old add::print

1 cbauer 1.1 /** @file add.cpp
2     *
3 cbauer 1.4 * Implementation of GiNaC's sums of expressions. */
4    
5     /*
6 kreckel 1.12 * GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University Mainz, Germany
7 cbauer 1.2 *
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.
12     *
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.
17     *
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
21     */
22 cbauer 1.1
23     #include <iostream>
24     #include <stdexcept>
25    
26 cbauer 1.3 #include "add.h"
27     #include "mul.h"
28 cbauer 1.13 #include "archive.h"
29 cbauer 1.5 #include "debugmsg.h"
30 kreckel 1.10 #include "utils.h"
31 cbauer 1.5
32 frink 1.7 #ifndef NO_GINAC_NAMESPACE
33 cbauer 1.5 namespace GiNaC {
34 frink 1.7 #endif // ndef NO_GINAC_NAMESPACE
35 cbauer 1.1
36 cbauer 1.13 GINAC_IMPLEMENT_REGISTERED_CLASS(add, expairseq)
37    
38 cbauer 1.1 //////////
39     // default constructor, destructor, copy constructor assignment operator and helpers
40     //////////
41    
42     // public
43    
44     add::add()
45     {
46     debugmsg("add default constructor",LOGLEVEL_CONSTRUCT);
47 cbauer 1.3 tinfo_key = TINFO_add;
48 cbauer 1.1 }
49    
50     add::~add()
51     {
52     debugmsg("add destructor",LOGLEVEL_DESTRUCT);
53     destroy(0);
54     }
55    
56 cbauer 1.14 add::add(const add & other)
57 cbauer 1.1 {
58     debugmsg("add copy constructor",LOGLEVEL_CONSTRUCT);
59     copy(other);
60     }
61    
62 cbauer 1.14 const add & add::operator=(const add & other)
63 cbauer 1.1 {
64     debugmsg("add operator=",LOGLEVEL_ASSIGNMENT);
65     if (this != &other) {
66     destroy(1);
67     copy(other);
68     }
69     return *this;
70     }
71    
72     // protected
73    
74 cbauer 1.14 void add::copy(const add & other)
75 cbauer 1.1 {
76 cbauer 1.13 inherited::copy(other);
77 cbauer 1.1 }
78    
79     void add::destroy(bool call_parent)
80     {
81 cbauer 1.13 if (call_parent) inherited::destroy(call_parent);
82 cbauer 1.1 }
83    
84     //////////
85     // other constructors
86     //////////
87    
88     // public
89    
90 cbauer 1.14 add::add(const ex & lh, const ex & rh)
91 cbauer 1.1 {
92     debugmsg("add constructor from ex,ex",LOGLEVEL_CONSTRUCT);
93 cbauer 1.3 tinfo_key = TINFO_add;
94 kreckel 1.10 overall_coeff=_ex0();
95 cbauer 1.1 construct_from_2_ex(lh,rh);
96 cbauer 1.6 GINAC_ASSERT(is_canonical());
97 cbauer 1.1 }
98    
99 cbauer 1.14 add::add(const exvector & v)
100 cbauer 1.1 {
101     debugmsg("add constructor from exvector",LOGLEVEL_CONSTRUCT);
102 cbauer 1.3 tinfo_key = TINFO_add;
103 kreckel 1.10 overall_coeff=_ex0();
104 cbauer 1.1 construct_from_exvector(v);
105 cbauer 1.6 GINAC_ASSERT(is_canonical());
106 cbauer 1.1 }
107    
108     /*
109 cbauer 1.14 add::add(const epvector & v, bool do_not_canonicalize)
110 cbauer 1.1 {
111     debugmsg("add constructor from epvector,bool",LOGLEVEL_CONSTRUCT);
112 cbauer 1.3 tinfo_key = TINFO_add;
113 cbauer 1.1 if (do_not_canonicalize) {
114     seq=v;
115     #ifdef EXPAIRSEQ_USE_HASHTAB
116     combine_same_terms(); // to build hashtab
117     #endif // def EXPAIRSEQ_USE_HASHTAB
118     } else {
119     construct_from_epvector(v);
120     }
121 cbauer 1.6 GINAC_ASSERT(is_canonical());
122 cbauer 1.1 }
123     */
124    
125 cbauer 1.14 add::add(const epvector & v)
126 cbauer 1.1 {
127     debugmsg("add constructor from epvector",LOGLEVEL_CONSTRUCT);
128 cbauer 1.3 tinfo_key = TINFO_add;
129 kreckel 1.10 overall_coeff=_ex0();
130 cbauer 1.1 construct_from_epvector(v);
131 cbauer 1.6 GINAC_ASSERT(is_canonical());
132 cbauer 1.1 }
133    
134 cbauer 1.14 add::add(const epvector & v, const ex & oc)
135 cbauer 1.1 {
136     debugmsg("add constructor from epvector,ex",LOGLEVEL_CONSTRUCT);
137 cbauer 1.3 tinfo_key = TINFO_add;
138 cbauer 1.1 overall_coeff=oc;
139     construct_from_epvector(v);
140 cbauer 1.6 GINAC_ASSERT(is_canonical());
141 cbauer 1.1 }
142    
143 cbauer 1.14 add::add(epvector * vp, const ex & oc)
144 cbauer 1.1 {
145     debugmsg("add constructor from epvector *,ex",LOGLEVEL_CONSTRUCT);
146 cbauer 1.3 tinfo_key = TINFO_add;
147 cbauer 1.6 GINAC_ASSERT(vp!=0);
148 cbauer 1.1 overall_coeff=oc;
149     construct_from_epvector(*vp);
150     delete vp;
151 cbauer 1.6 GINAC_ASSERT(is_canonical());
152 cbauer 1.1 }
153    
154     //////////
155 cbauer 1.13 // archiving
156     //////////
157    
158     /** Construct object from archive_node. */
159     add::add(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst)
160     {
161     debugmsg("add constructor from archive_node", LOGLEVEL_CONSTRUCT);
162     }
163    
164     /** Unarchive the object. */
165     ex add::unarchive(const archive_node &n, const lst &sym_lst)
166     {
167     return (new add(n, sym_lst))->setflag(status_flags::dynallocated);
168     }
169    
170     /** Archive the object. */
171     void add::archive(archive_node &n) const
172     {
173     inherited::archive(n);
174     }
175    
176     //////////
177 cbauer 1.1 // functions overriding virtual functions from bases classes
178     //////////
179    
180     // public
181    
182     basic * add::duplicate() const
183     {
184     debugmsg("add duplicate",LOGLEVEL_DUPLICATE);
185     return new add(*this);
186     }
187    
188 kreckel 1.11 void add::print(ostream & os, unsigned upper_precedence) const
189     {
190     debugmsg("add print",LOGLEVEL_PRINT);
191     if (precedence<=upper_precedence) os << "(";
192     numeric coeff;
193     bool first = true;
194     // first print the overall numeric coefficient, if present:
195     if (!overall_coeff.is_zero()) {
196     os << overall_coeff;
197     first = false;
198     }
199     // then proceed with the remaining factors:
200     for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
201     coeff = ex_to_numeric(cit->coeff);
202     if (!first) {
203     if (coeff.csgn()==-1) os << '-'; else os << '+';
204     } else {
205     if (coeff.csgn()==-1) os << '-';
206     first = false;
207     }
208     if (!coeff.is_equal(_num1()) &&
209     !coeff.is_equal(_num_1())) {
210     if (coeff.is_rational()) {
211     if (coeff.is_negative())
212     os << -coeff;
213     else
214     os << coeff;
215     } else {
216     if (coeff.csgn()==-1)
217     (-coeff).print(os, precedence);
218     else
219     coeff.print(os, precedence);
220     }
221     os << '*';
222     }
223     os << cit->rest;
224 kreckel 1.9 }
225     if (precedence<=upper_precedence) os << ")";
226     }
227    
228     void add::printraw(ostream & os) const
229     {
230     debugmsg("add printraw",LOGLEVEL_PRINT);
231    
232     os << "+(";
233     for (epvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
234     os << "(";
235     (*it).rest.bp->printraw(os);
236     os << ",";
237     (*it).coeff.bp->printraw(os);
238     os << "),";
239     }
240     os << ",hash=" << hashvalue << ",flags=" << flags;
241     os << ")";
242     }
243    
244     void add::printcsrc(ostream & os, unsigned type, unsigned upper_precedence) const
245     {
246     debugmsg("add print csrc", LOGLEVEL_PRINT);
247     if (precedence <= upper_precedence)
248     os << "(";
249    
250     // Print arguments, separated by "+"
251     epvector::const_iterator it = seq.begin();
252     epvector::const_iterator itend = seq.end();
253     while (it != itend) {
254    
255     // If the coefficient is -1, it is replaced by a single minus sign
256 kreckel 1.10 if (it->coeff.compare(_num1()) == 0) {
257 kreckel 1.9 it->rest.bp->printcsrc(os, type, precedence);
258 kreckel 1.10 } else if (it->coeff.compare(_num_1()) == 0) {
259 kreckel 1.9 os << "-";
260     it->rest.bp->printcsrc(os, type, precedence);
261 kreckel 1.10 } else if (ex_to_numeric(it->coeff).numer().compare(_num1()) == 0) {
262 kreckel 1.9 it->rest.bp->printcsrc(os, type, precedence);
263     os << "/";
264     ex_to_numeric(it->coeff).denom().printcsrc(os, type, precedence);
265 kreckel 1.10 } else if (ex_to_numeric(it->coeff).numer().compare(_num_1()) == 0) {
266 kreckel 1.9 os << "-";
267     it->rest.bp->printcsrc(os, type, precedence);
268     os << "/";
269     ex_to_numeric(it->coeff).denom().printcsrc(os, type, precedence);
270     } else {
271     it->coeff.bp->printcsrc(os, type, precedence);
272     os << "*";
273     it->rest.bp->printcsrc(os, type, precedence);
274     }
275    
276     // Separator is "+", except if the following expression would have a leading minus sign
277     it++;
278 kreckel 1.10 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)))
279 kreckel 1.9 os << "+";
280     }
281    
282 kreckel 1.10 if (!overall_coeff.is_equal(_ex0())) {
283 kreckel 1.9 if (overall_coeff.info(info_flags::positive)) os << '+';
284     overall_coeff.bp->printcsrc(os,type,precedence);
285     }
286    
287     if (precedence <= upper_precedence)
288     os << ")";
289     }
290    
291 cbauer 1.1 bool add::info(unsigned inf) const
292     {
293     // TODO: optimize
294 kreckel 1.9 if (inf==info_flags::polynomial ||
295     inf==info_flags::integer_polynomial ||
296     inf==info_flags::cinteger_polynomial ||
297     inf==info_flags::rational_polynomial ||
298     inf==info_flags::crational_polynomial ||
299     inf==info_flags::rational_function) {
300 cbauer 1.1 for (epvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
301     if (!(recombine_pair_to_ex(*it).info(inf)))
302     return false;
303     }
304 kreckel 1.9 return overall_coeff.info(inf);
305 cbauer 1.1 } else {
306 cbauer 1.13 return inherited::info(inf);
307 cbauer 1.1 }
308     }
309    
310 cbauer 1.14 int add::degree(const symbol & s) const
311 cbauer 1.1 {
312     int deg=INT_MIN;
313 kreckel 1.10 if (!overall_coeff.is_equal(_ex0())) {
314 cbauer 1.1 deg=0;
315     }
316     int cur_deg;
317     for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
318     cur_deg=(*cit).rest.degree(s);
319     if (cur_deg>deg) deg=cur_deg;
320     }
321     return deg;
322     }
323    
324 cbauer 1.14 int add::ldegree(const symbol & s) const
325 cbauer 1.1 {
326     int deg=INT_MAX;
327 kreckel 1.10 if (!overall_coeff.is_equal(_ex0())) {
328 cbauer 1.1 deg=0;
329     }
330     int cur_deg;
331     for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
332     cur_deg=(*cit).rest.ldegree(s);
333     if (cur_deg<deg) deg=cur_deg;
334     }
335     return deg;
336     }
337    
338 cbauer 1.14 ex add::coeff(const symbol & s, int n) const
339 cbauer 1.1 {
340     epvector coeffseq;
341     coeffseq.reserve(seq.size());
342    
343     epvector::const_iterator it=seq.begin();
344     while (it!=seq.end()) {
345     coeffseq.push_back(combine_ex_with_coeff_to_pair((*it).rest.coeff(s,n),
346     (*it).coeff));
347     ++it;
348     }
349     if (n==0) {
350     return (new add(coeffseq,overall_coeff))->setflag(status_flags::dynallocated);
351     }
352     return (new add(coeffseq))->setflag(status_flags::dynallocated);
353     }
354    
355     ex add::eval(int level) const
356     {
357     // simplifications: +(;c) -> c
358     // +(x;1) -> x
359    
360     debugmsg("add eval",LOGLEVEL_MEMBER_FUNCTION);
361    
362     epvector * evaled_seqp=evalchildren(level);
363     if (evaled_seqp!=0) {
364     // do more evaluation later
365     return (new add(evaled_seqp,overall_coeff))->
366     setflag(status_flags::dynallocated);
367     }
368    
369 cbauer 1.6 #ifdef DO_GINAC_ASSERT
370 cbauer 1.1 for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
371 cbauer 1.6 GINAC_ASSERT(!is_ex_exactly_of_type((*cit).rest,add));
372 cbauer 1.1 if (is_ex_exactly_of_type((*cit).rest,numeric)) {
373     dbgprint();
374     }
375 cbauer 1.6 GINAC_ASSERT(!is_ex_exactly_of_type((*cit).rest,numeric));
376 cbauer 1.1 }
377 cbauer 1.6 #endif // def DO_GINAC_ASSERT
378 cbauer 1.1
379     if (flags & status_flags::evaluated) {
380 cbauer 1.6 GINAC_ASSERT(seq.size()>0);
381 kreckel 1.10 GINAC_ASSERT((seq.size()>1)||!overall_coeff.is_equal(_ex0()));
382 cbauer 1.1 return *this;
383     }
384    
385     int seq_size=seq.size();
386     if (seq_size==0) {
387     // +(;c) -> c
388     return overall_coeff;
389 kreckel 1.10 } else if ((seq_size==1)&&overall_coeff.is_equal(_ex0())) {
390 cbauer 1.1 // +(x;0) -> x
391     return recombine_pair_to_ex(*(seq.begin()));
392     }
393     return this->hold();
394     }
395    
396     exvector add::get_indices(void) const
397     {
398 cbauer 1.5 // FIXME: all terms in the sum should have the same indices (compatible
399     // tensors) however this is not checked, since there is no function yet
400     // which compares indices (idxvector can be unsorted)
401 cbauer 1.1 if (seq.size()==0) {
402     return exvector();
403     }
404     return (seq.begin())->rest.get_indices();
405     }
406    
407 cbauer 1.14 ex add::simplify_ncmul(const exvector & v) const
408 cbauer 1.1 {
409     if (seq.size()==0) {
410 cbauer 1.13 return inherited::simplify_ncmul(v);
411 cbauer 1.1 }
412     return (*seq.begin()).rest.simplify_ncmul(v);
413     }
414    
415     // protected
416    
417 cbauer 1.14 int add::compare_same_type(const basic & other) const
418 cbauer 1.1 {
419 cbauer 1.13 return inherited::compare_same_type(other);
420 cbauer 1.1 }
421    
422 cbauer 1.14 bool add::is_equal_same_type(const basic & other) const
423 cbauer 1.1 {
424 cbauer 1.13 return inherited::is_equal_same_type(other);
425 cbauer 1.1 }
426    
427     unsigned add::return_type(void) const
428     {
429     if (seq.size()==0) {
430     return return_types::commutative;
431     }
432     return (*seq.begin()).rest.return_type();
433     }
434    
435     unsigned add::return_type_tinfo(void) const
436     {
437     if (seq.size()==0) {
438     return tinfo_key;
439     }
440     return (*seq.begin()).rest.return_type_tinfo();
441     }
442    
443 cbauer 1.14 ex add::thisexpairseq(const epvector & v, const ex & oc) const
444 cbauer 1.1 {
445     return (new add(v,oc))->setflag(status_flags::dynallocated);
446     }
447    
448 cbauer 1.14 ex add::thisexpairseq(epvector * vp, const ex & oc) const
449 cbauer 1.1 {
450     return (new add(vp,oc))->setflag(status_flags::dynallocated);
451     }
452    
453 cbauer 1.14 expair add::split_ex_to_pair(const ex & e) const
454 cbauer 1.1 {
455     if (is_ex_exactly_of_type(e,mul)) {
456 cbauer 1.14 const mul & mulref=ex_to_mul(e);
457 cbauer 1.1 ex numfactor=mulref.overall_coeff;
458     // mul * mulcopyp=static_cast<mul *>(mulref.duplicate());
459     mul * mulcopyp=new mul(mulref);
460 kreckel 1.10 mulcopyp->overall_coeff=_ex1();
461 cbauer 1.1 mulcopyp->clearflag(status_flags::evaluated);
462     mulcopyp->clearflag(status_flags::hash_calculated);
463     return expair(mulcopyp->setflag(status_flags::dynallocated),numfactor);
464     }
465 kreckel 1.10 return expair(e,_ex1());
466 cbauer 1.1 }
467    
468 cbauer 1.14 expair add::combine_ex_with_coeff_to_pair(const ex & e,
469     const ex & c) const
470 cbauer 1.1 {
471 cbauer 1.6 GINAC_ASSERT(is_ex_exactly_of_type(c,numeric));
472 cbauer 1.1 if (is_ex_exactly_of_type(e,mul)) {
473 cbauer 1.14 const mul & mulref=ex_to_mul(e);
474 cbauer 1.1 ex numfactor=mulref.overall_coeff;
475     //mul * mulcopyp=static_cast<mul *>(mulref.duplicate());
476     mul * mulcopyp=new mul(mulref);
477 kreckel 1.10 mulcopyp->overall_coeff=_ex1();
478 cbauer 1.1 mulcopyp->clearflag(status_flags::evaluated);
479     mulcopyp->clearflag(status_flags::hash_calculated);
480 kreckel 1.10 if (are_ex_trivially_equal(c,_ex1())) {
481 cbauer 1.1 return expair(mulcopyp->setflag(status_flags::dynallocated),numfactor);
482 kreckel 1.10 } else if (are_ex_trivially_equal(numfactor,_ex1())) {
483 cbauer 1.1 return expair(mulcopyp->setflag(status_flags::dynallocated),c);
484     }
485     return expair(mulcopyp->setflag(status_flags::dynallocated),
486     ex_to_numeric(numfactor).mul_dyn(ex_to_numeric(c)));
487     } else if (is_ex_exactly_of_type(e,numeric)) {
488 kreckel 1.10 if (are_ex_trivially_equal(c,_ex1())) {
489     return expair(e,_ex1());
490 cbauer 1.1 }
491 kreckel 1.10 return expair(ex_to_numeric(e).mul_dyn(ex_to_numeric(c)),_ex1());
492 cbauer 1.1 }
493     return expair(e,c);
494     }
495    
496 cbauer 1.14 expair add::combine_pair_with_coeff_to_pair(const expair & p,
497     const ex & c) const
498 cbauer 1.1 {
499 cbauer 1.6 GINAC_ASSERT(is_ex_exactly_of_type(p.coeff,numeric));
500     GINAC_ASSERT(is_ex_exactly_of_type(c,numeric));
501 cbauer 1.1
502     if (is_ex_exactly_of_type(p.rest,numeric)) {
503 kreckel 1.10 GINAC_ASSERT(ex_to_numeric(p.coeff).is_equal(_num1())); // should be normalized
504     return expair(ex_to_numeric(p.rest).mul_dyn(ex_to_numeric(c)),_ex1());
505 cbauer 1.1 }
506    
507     return expair(p.rest,ex_to_numeric(p.coeff).mul_dyn(ex_to_numeric(c)));
508     }
509    
510 cbauer 1.14 ex add::recombine_pair_to_ex(const expair & p) const
511 cbauer 1.1 {
512 kreckel 1.10 //if (p.coeff.compare(_ex1())==0) {
513     //if (are_ex_trivially_equal(p.coeff,_ex1())) {
514     if (ex_to_numeric(p.coeff).is_equal(_num1())) {
515 cbauer 1.1 return p.rest;
516     } else {
517     return p.rest*p.coeff;
518     }
519     }
520    
521     ex add::expand(unsigned options) const
522     {
523     epvector * vp=expandchildren(options);
524     if (vp==0) {
525     return *this;
526     }
527     return (new add(vp,overall_coeff))->setflag(status_flags::expanded |
528     status_flags::dynallocated );
529     }
530    
531     //////////
532     // new virtual functions which can be overridden by derived classes
533     //////////
534    
535     // none
536    
537     //////////
538     // non-virtual functions in this class
539     //////////
540    
541     // none
542    
543     //////////
544     // static member variables
545     //////////
546    
547     // protected
548    
549     unsigned add::precedence=40;
550    
551     //////////
552     // global constants
553     //////////
554    
555     const add some_add;
556 cbauer 1.14 const type_info & typeid_add=typeid(some_add);
557 cbauer 1.1
558 frink 1.7 #ifndef NO_GINAC_NAMESPACE
559 cbauer 1.5 } // namespace GiNaC
560 frink 1.7 #endif // ndef NO_GINAC_NAMESPACE

Christian Bauer">Christian Bauer
ViewVC Help
Powered by ViewVC 1.1.15