]> www.ginac.de Git - ginac.git/blob - ginac/mul.cpp
- changed behaviour of numeric::is_rational() and added numeric::is_cinteger()
[ginac.git] / ginac / mul.cpp
1 /** @file mul.cpp
2  *
3  *  Implementation of GiNaC's products of expressions. */
4
5 /*
6  *  GiNaC Copyright (C) 1999 Johannes Gutenberg University Mainz, Germany
7  *
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
23 #include <vector>
24 #include <stdexcept>
25
26 #include "mul.h"
27 #include "add.h"
28 #include "power.h"
29 #include "debugmsg.h"
30
31 #ifndef NO_GINAC_NAMESPACE
32 namespace GiNaC {
33 #endif // ndef NO_GINAC_NAMESPACE
34
35 //////////
36 // default constructor, destructor, copy constructor assignment operator and helpers
37 //////////
38
39 // public
40
41 mul::mul()
42 {
43     debugmsg("mul default constructor",LOGLEVEL_CONSTRUCT);
44     tinfo_key = TINFO_mul;
45 }
46
47 mul::~mul()
48 {
49     debugmsg("mul destructor",LOGLEVEL_DESTRUCT);
50     destroy(0);
51 }
52
53 mul::mul(mul const & other)
54 {
55     debugmsg("mul copy constructor",LOGLEVEL_CONSTRUCT);
56     copy(other);
57 }
58
59 mul const & mul::operator=(mul const & other)
60 {
61     debugmsg("mul operator=",LOGLEVEL_ASSIGNMENT);
62     if (this != &other) {
63         destroy(1);
64         copy(other);
65     }
66     return *this;
67 }
68
69 // protected
70
71 void mul::copy(mul const & other)
72 {
73     expairseq::copy(other);
74 }
75
76 void mul::destroy(bool call_parent)
77 {
78     if (call_parent) expairseq::destroy(call_parent);
79 }
80
81 //////////
82 // other constructors
83 //////////
84
85 // public
86
87 mul::mul(ex const & lh, ex const & rh)
88 {
89     debugmsg("mul constructor from ex,ex",LOGLEVEL_CONSTRUCT);
90     tinfo_key = TINFO_mul;
91     overall_coeff=exONE();
92     construct_from_2_ex(lh,rh);
93     GINAC_ASSERT(is_canonical());
94 }
95
96 mul::mul(exvector const & v)
97 {
98     debugmsg("mul constructor from exvector",LOGLEVEL_CONSTRUCT);
99     tinfo_key = TINFO_mul;
100     overall_coeff=exONE();
101     construct_from_exvector(v);
102     GINAC_ASSERT(is_canonical());
103 }
104
105 /*
106 mul::mul(epvector const & v, bool do_not_canonicalize)
107 {
108     debugmsg("mul constructor from epvector,bool",LOGLEVEL_CONSTRUCT);
109     tinfo_key = TINFO_mul;
110     if (do_not_canonicalize) {
111         seq=v;
112 #ifdef EXPAIRSEQ_USE_HASHTAB
113         combine_same_terms(); // to build hashtab
114 #endif // def EXPAIRSEQ_USE_HASHTAB
115     } else {
116         construct_from_epvector(v);
117     }
118     GINAC_ASSERT(is_canonical());
119 }
120 */
121
122 mul::mul(epvector const & v)
123 {
124     debugmsg("mul constructor from epvector",LOGLEVEL_CONSTRUCT);
125     tinfo_key = TINFO_mul;
126     overall_coeff=exONE();
127     construct_from_epvector(v);
128     GINAC_ASSERT(is_canonical());
129 }
130
131 mul::mul(epvector const & v, ex const & oc)
132 {
133     debugmsg("mul constructor from epvector,ex",LOGLEVEL_CONSTRUCT);
134     tinfo_key = TINFO_mul;
135     overall_coeff=oc;
136     construct_from_epvector(v);
137     GINAC_ASSERT(is_canonical());
138 }
139
140 mul::mul(epvector * vp, ex const & oc)
141 {
142     debugmsg("mul constructor from epvector *,ex",LOGLEVEL_CONSTRUCT);
143     tinfo_key = TINFO_mul;
144     GINAC_ASSERT(vp!=0);
145     overall_coeff=oc;
146     construct_from_epvector(*vp);
147     delete vp;
148     GINAC_ASSERT(is_canonical());
149 }
150
151 mul::mul(ex const & lh, ex const & mh, ex const & rh)
152 {
153     debugmsg("mul constructor from ex,ex,ex",LOGLEVEL_CONSTRUCT);
154     tinfo_key = TINFO_mul;
155     exvector factors;
156     factors.reserve(3);
157     factors.push_back(lh);
158     factors.push_back(mh);
159     factors.push_back(rh);
160     overall_coeff=exONE();
161     construct_from_exvector(factors);
162     GINAC_ASSERT(is_canonical());
163 }
164
165 //////////
166 // functions overriding virtual functions from bases classes
167 //////////
168
169 // public
170
171 basic * mul::duplicate() const
172 {
173     debugmsg("mul duplicate",LOGLEVEL_ASSIGNMENT);
174     return new mul(*this);
175 }
176
177 bool mul::info(unsigned inf) const
178 {
179     // TODO: optimize
180     if (inf==info_flags::polynomial || inf==info_flags::integer_polynomial || inf==info_flags::rational_polynomial || inf==info_flags::rational_function) {
181         for (epvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
182             if (!(recombine_pair_to_ex(*it).info(inf)))
183                 return false;
184         }
185         return true;
186     } else {
187         return expairseq::info(inf);
188     }
189 }
190
191 typedef vector<int> intvector;
192
193 int mul::degree(symbol const & s) const
194 {
195     int deg_sum=0;
196     for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
197         deg_sum+=(*cit).rest.degree(s) * ex_to_numeric((*cit).coeff).to_int();
198     }
199     return deg_sum;
200 }
201
202 int mul::ldegree(symbol const & s) const
203 {
204     int deg_sum=0;
205     for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
206         deg_sum+=(*cit).rest.ldegree(s) * ex_to_numeric((*cit).coeff).to_int();
207     }
208     return deg_sum;
209 }
210
211 ex mul::coeff(symbol const & s, int const n) const
212 {
213     exvector coeffseq;
214     coeffseq.reserve(seq.size()+1);
215     
216     if (n==0) {
217         // product of individual coeffs
218         // if a non-zero power of s is found, the resulting product will be 0
219         epvector::const_iterator it=seq.begin();
220         while (it!=seq.end()) {
221             coeffseq.push_back(recombine_pair_to_ex(*it).coeff(s,n));
222             ++it;
223         }
224         coeffseq.push_back(overall_coeff);
225         return (new mul(coeffseq))->setflag(status_flags::dynallocated);
226     }
227          
228     epvector::const_iterator it=seq.begin();
229     bool coeff_found=0;
230     while (it!=seq.end()) {
231         ex t=recombine_pair_to_ex(*it);
232         ex c=t.coeff(s,n);
233         if (!c.is_zero()) {
234             coeffseq.push_back(c);
235             coeff_found=1;
236         } else {
237             coeffseq.push_back(t);
238         }
239         ++it;
240     }
241     if (coeff_found) {
242         coeffseq.push_back(overall_coeff);
243         return (new mul(coeffseq))->setflag(status_flags::dynallocated);
244     }
245     
246     return exZERO();
247 }
248
249 ex mul::eval(int level) const
250 {
251     // simplifications  *(...,x;0) -> 0
252     //                  *(+(x,y,...);c) -> *(+(*(x,c),*(y,c),...)) (c numeric())
253     //                  *(x;1) -> x
254     //                  *(;c) -> c
255
256     debugmsg("mul eval",LOGLEVEL_MEMBER_FUNCTION);
257
258     epvector * evaled_seqp=evalchildren(level);
259     if (evaled_seqp!=0) {
260         // do more evaluation later
261         return (new mul(evaled_seqp,overall_coeff))->
262                    setflag(status_flags::dynallocated);
263     }
264
265 #ifdef DO_GINAC_ASSERT
266     for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
267         GINAC_ASSERT((!is_ex_exactly_of_type((*cit).rest,mul))||
268                (!(ex_to_numeric((*cit).coeff).is_integer())));
269         GINAC_ASSERT(!((*cit).is_numeric_with_coeff_1()));
270         if (is_ex_exactly_of_type(recombine_pair_to_ex(*cit),numeric)) {
271             printtree(cerr,0);
272         }
273         GINAC_ASSERT(!is_ex_exactly_of_type(recombine_pair_to_ex(*cit),numeric));
274         /* for paranoia */
275         expair p=split_ex_to_pair(recombine_pair_to_ex(*cit));
276         GINAC_ASSERT(p.rest.is_equal((*cit).rest));
277         GINAC_ASSERT(p.coeff.is_equal((*cit).coeff));
278         /* end paranoia */
279     }
280 #endif // def DO_GINAC_ASSERT
281
282     if (flags & status_flags::evaluated) {
283         GINAC_ASSERT(seq.size()>0);
284         GINAC_ASSERT((seq.size()>1)||!overall_coeff.is_equal(exONE()));
285         return *this;
286     }
287
288     int seq_size=seq.size();
289     if (overall_coeff.is_equal(exZERO())) {
290         // *(...,x;0) -> 0
291         return exZERO();
292     } else if (seq_size==0) {
293         // *(;c) -> c
294         return overall_coeff;
295     } else if ((seq_size==1)&&overall_coeff.is_equal(exONE())) {
296         // *(x;1) -> x
297         return recombine_pair_to_ex(*(seq.begin()));
298     } else if ((seq_size==1) &&
299                is_ex_exactly_of_type((*seq.begin()).rest,add) &&
300                ex_to_numeric((*seq.begin()).coeff).is_equal(numONE())) {
301         // *(+(x,y,...);c) -> +(*(x,c),*(y,c),...) (c numeric(), no powers of +())
302         add const & addref=ex_to_add((*seq.begin()).rest);
303         epvector distrseq;
304         distrseq.reserve(addref.seq.size());
305         for (epvector::const_iterator cit=addref.seq.begin(); cit!=addref.seq.end(); ++cit) {
306             distrseq.push_back(addref.combine_pair_with_coeff_to_pair(*cit,
307                                    overall_coeff));
308         }
309         return (new add(distrseq,
310                         ex_to_numeric(addref.overall_coeff).
311                         mul_dyn(ex_to_numeric(overall_coeff))))
312             ->setflag(status_flags::dynallocated  |
313                       status_flags::evaluated );
314     }
315     return this->hold();
316 }
317
318 exvector mul::get_indices(void) const
319 {
320     // return union of indices of factors
321     exvector iv;
322     for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
323         exvector subiv=(*cit).rest.get_indices();
324         iv.reserve(iv.size()+subiv.size());
325         for (exvector::const_iterator cit2=subiv.begin(); cit2!=subiv.end(); ++cit2) {
326             iv.push_back(*cit2);
327         }
328     }
329     return iv;
330 }
331
332 ex mul::simplify_ncmul(exvector const & v) const
333 {
334     throw(std::logic_error("mul::simplify_ncmul() should never have been called!"));
335 }
336
337 // protected
338
339 int mul::compare_same_type(basic const & other) const
340 {
341     return expairseq::compare_same_type(other);
342 }
343
344 bool mul::is_equal_same_type(basic const & other) const
345 {
346     return expairseq::is_equal_same_type(other);
347 }
348
349 unsigned mul::return_type(void) const
350 {
351     if (seq.size()==0) {
352         // mul without factors: should not happen, but commutes
353         return return_types::commutative;
354     }
355
356     bool all_commutative=1;
357     unsigned rt;
358     epvector::const_iterator cit_noncommutative_element; // point to first found nc element
359
360     for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
361         rt=(*cit).rest.return_type();
362         if (rt==return_types::noncommutative_composite) return rt; // one ncc -> mul also ncc
363         if ((rt==return_types::noncommutative)&&(all_commutative)) {
364             // first nc element found, remember position
365             cit_noncommutative_element=cit;
366             all_commutative=0;
367         }
368         if ((rt==return_types::noncommutative)&&(!all_commutative)) {
369                 // another nc element found, compare type_infos
370             if ((*cit_noncommutative_element).rest.return_type_tinfo()!=(*cit).rest.return_type_tinfo()) {
371                 // diffent types -> mul is ncc
372                 return return_types::noncommutative_composite;
373             }
374         }
375     }
376     // all factors checked
377     return all_commutative ? return_types::commutative : return_types::noncommutative;
378 }
379    
380 unsigned mul::return_type_tinfo(void) const
381 {
382     if (seq.size()==0) {
383         // mul without factors: should not happen
384         return tinfo_key;
385     }
386     // return type_info of first noncommutative element
387     for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
388         if ((*cit).rest.return_type()==return_types::noncommutative) {
389             return (*cit).rest.return_type_tinfo();
390         }
391     }
392     // no noncommutative element found, should not happen
393     return tinfo_key;
394 }
395
396 ex mul::thisexpairseq(epvector const & v, ex const & oc) const
397 {
398     return (new mul(v,oc))->setflag(status_flags::dynallocated);
399 }
400
401 ex mul::thisexpairseq(epvector * vp, ex const & oc) const
402 {
403     return (new mul(vp,oc))->setflag(status_flags::dynallocated);
404 }
405
406 expair mul::split_ex_to_pair(ex const & e) const
407 {
408     if (is_ex_exactly_of_type(e,power)) {
409         power const & powerref=ex_to_power(e);
410         if (is_ex_exactly_of_type(powerref.exponent,numeric)) {
411             return expair(powerref.basis,powerref.exponent);
412         }
413     }
414     return expair(e,exONE());
415 }
416     
417 expair mul::combine_ex_with_coeff_to_pair(ex const & e,
418                                           ex const & c) const
419 {
420     // to avoid duplication of power simplification rules,
421     // we create a temporary power object
422     // otherwise it would be hard to correctly simplify
423     // expression like (4^(1/3))^(3/2)
424     if (are_ex_trivially_equal(c,exONE())) {
425         return split_ex_to_pair(e);
426     }
427     return split_ex_to_pair(power(e,c));
428 }
429     
430 expair mul::combine_pair_with_coeff_to_pair(expair const & p,
431                                             ex const & c) const
432 {
433     // to avoid duplication of power simplification rules,
434     // we create a temporary power object
435     // otherwise it would be hard to correctly simplify
436     // expression like (4^(1/3))^(3/2)
437     if (are_ex_trivially_equal(c,exONE())) {
438         return p;
439     }
440     return split_ex_to_pair(power(recombine_pair_to_ex(p),c));
441 }
442     
443 ex mul::recombine_pair_to_ex(expair const & p) const
444 {
445     // if (p.coeff.compare(exONE())==0) {
446     // if (are_ex_trivially_equal(p.coeff,exONE())) {
447     if (ex_to_numeric(p.coeff).is_equal(numONE())) {
448         return p.rest;
449     } else {
450         return power(p.rest,p.coeff);
451     }
452 }
453
454 bool mul::expair_needs_further_processing(epp it)
455 {
456     if (is_ex_exactly_of_type((*it).rest,mul) &&
457         ex_to_numeric((*it).coeff).is_integer()) {
458         // combined pair is product with integer power -> expand it
459         *it=split_ex_to_pair(recombine_pair_to_ex(*it));
460         return true;
461     }
462     if (is_ex_exactly_of_type((*it).rest,numeric)) {
463         expair ep=split_ex_to_pair(recombine_pair_to_ex(*it));
464         if (!ep.is_equal(*it)) {
465             // combined pair is a numeric power which can be simplified
466             *it=ep;
467             return true;
468         }
469         if (ex_to_numeric((*it).coeff).is_equal(numONE())) {
470             // combined pair has coeff 1 and must be moved to the end
471             return true;
472         }
473     }
474     return false;
475 }       
476
477 ex mul::default_overall_coeff(void) const
478 {
479     return exONE();
480 }
481
482 void mul::combine_overall_coeff(ex const & c)
483 {
484     GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric));
485     GINAC_ASSERT(is_ex_exactly_of_type(c,numeric));
486     overall_coeff = ex_to_numeric(overall_coeff).mul_dyn(ex_to_numeric(c));
487 }
488
489 void mul::combine_overall_coeff(ex const & c1, ex const & c2)
490 {
491     GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric));
492     GINAC_ASSERT(is_ex_exactly_of_type(c1,numeric));
493     GINAC_ASSERT(is_ex_exactly_of_type(c2,numeric));
494     overall_coeff = ex_to_numeric(overall_coeff).
495                         mul_dyn(ex_to_numeric(c1).power(ex_to_numeric(c2)));
496 }
497
498 bool mul::can_make_flat(expair const & p) const
499 {
500     GINAC_ASSERT(is_ex_exactly_of_type(p.coeff,numeric));
501     // this assertion will probably fail somewhere
502     // it would require a more careful make_flat, obeying the power laws
503     // probably should return true only if p.coeff is integer
504     return ex_to_numeric(p.coeff).is_equal(numONE());
505 }
506
507 ex mul::expand(unsigned options) const
508 {
509     exvector sub_expanded_seq;
510     intvector positions_of_adds;
511     intvector number_of_add_operands;
512
513     epvector * expanded_seqp=expandchildren(options);
514
515     epvector const & expanded_seq = expanded_seqp==0 ? seq : *expanded_seqp;
516
517     positions_of_adds.resize(expanded_seq.size());
518     number_of_add_operands.resize(expanded_seq.size());
519
520     int number_of_adds=0;
521     int number_of_expanded_terms=1;
522
523     unsigned current_position=0;
524     epvector::const_iterator last=expanded_seq.end();
525     for (epvector::const_iterator cit=expanded_seq.begin(); cit!=last; ++cit) {
526         if (is_ex_exactly_of_type((*cit).rest,add)&&
527             (ex_to_numeric((*cit).coeff).is_equal(numONE()))) {
528             positions_of_adds[number_of_adds]=current_position;
529             add const & expanded_addref=ex_to_add((*cit).rest);
530             int addref_nops=expanded_addref.nops();
531             number_of_add_operands[number_of_adds]=addref_nops;
532             number_of_expanded_terms *= addref_nops;
533             number_of_adds++;
534         }
535         current_position++;
536     }
537
538     if (number_of_adds==0) {
539         if (expanded_seqp==0) {
540             return this->setflag(status_flags::expanded);
541         }
542         return (new mul(expanded_seqp,overall_coeff))->
543                      setflag(status_flags::dynallocated ||
544                              status_flags::expanded);
545     }
546
547     exvector distrseq;
548     distrseq.reserve(number_of_expanded_terms);
549
550     intvector k;
551     k.resize(number_of_adds);
552     
553     int l;
554     for (l=0; l<number_of_adds; l++) {
555         k[l]=0;
556     }
557
558     while (1) {
559         epvector term;
560         term=expanded_seq;
561         for (l=0; l<number_of_adds; l++) {
562             add const & addref=ex_to_add(expanded_seq[positions_of_adds[l]].rest);
563             GINAC_ASSERT(term[positions_of_adds[l]].coeff.compare(exONE())==0);
564             term[positions_of_adds[l]]=split_ex_to_pair(addref.op(k[l]));
565         }
566         /*
567         cout << "mul::expand() term begin" << endl;
568         for (epvector::const_iterator cit=term.begin(); cit!=term.end(); ++cit) {
569             cout << "rest" << endl;
570             (*cit).rest.printtree(cout);
571             cout << "coeff" << endl;
572             (*cit).coeff.printtree(cout);
573         }
574         cout << "mul::expand() term end" << endl;
575         */
576         distrseq.push_back((new mul(term,overall_coeff))->
577                                 setflag(status_flags::dynallocated |
578                                         status_flags::expanded));
579
580         // increment k[]
581         l=number_of_adds-1;
582         while ((l>=0)&&((++k[l])>=number_of_add_operands[l])) {
583             k[l]=0;    
584             l--;
585         }
586         if (l<0) break;
587     }
588
589     if (expanded_seqp!=0) {
590         delete expanded_seqp;
591     }
592     /*
593     cout << "mul::expand() distrseq begin" << endl;
594     for (exvector::const_iterator cit=distrseq.begin(); cit!=distrseq.end(); ++cit) {
595         (*cit).printtree(cout);
596     }
597     cout << "mul::expand() distrseq end" << endl;
598     */
599
600     return (new add(distrseq))->setflag(status_flags::dynallocated |
601                                         status_flags::expanded);
602 }
603
604 //////////
605 // new virtual functions which can be overridden by derived classes
606 //////////
607
608 // none
609
610 //////////
611 // non-virtual functions in this class
612 //////////
613
614 epvector * mul::expandchildren(unsigned options) const
615 {
616     epvector::const_iterator last=seq.end();
617     epvector::const_iterator cit=seq.begin();
618     while (cit!=last) {
619         ex const & factor=recombine_pair_to_ex(*cit);
620         ex const & expanded_factor=factor.expand(options);
621         if (!are_ex_trivially_equal(factor,expanded_factor)) {
622
623             // something changed, copy seq, eval and return it
624             epvector *s=new epvector;
625             s->reserve(seq.size());
626
627             // copy parts of seq which are known not to have changed
628             epvector::const_iterator cit2=seq.begin();
629             while (cit2!=cit) {
630                 s->push_back(*cit2);
631                 ++cit2;
632             }
633             // copy first changed element
634             s->push_back(split_ex_to_pair(expanded_factor));
635             ++cit2;
636             // copy rest
637             while (cit2!=last) {
638                 s->push_back(split_ex_to_pair(recombine_pair_to_ex(*cit2).expand(options)));
639                 ++cit2;
640             }
641             return s;
642         }
643         ++cit;
644     }
645     
646     return 0; // nothing has changed
647 }
648    
649 //////////
650 // static member variables
651 //////////
652
653 // protected
654
655 unsigned mul::precedence=50;
656
657
658 //////////
659 // global constants
660 //////////
661
662 const mul some_mul;
663 type_info const & typeid_mul=typeid(some_mul);
664
665 #ifndef NO_GINAC_NAMESPACE
666 } // namespace GiNaC
667 #endif // ndef NO_GINAC_NAMESPACE