3 * Implementation of GiNaC's products 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
31 #ifndef NO_GINAC_NAMESPACE
33 #endif // ndef NO_GINAC_NAMESPACE
36 // default constructor, destructor, copy constructor assignment operator and helpers
43 debugmsg("mul default constructor",LOGLEVEL_CONSTRUCT);
44 tinfo_key = TINFO_mul;
49 debugmsg("mul destructor",LOGLEVEL_DESTRUCT);
53 mul::mul(mul const & other)
55 debugmsg("mul copy constructor",LOGLEVEL_CONSTRUCT);
59 mul const & mul::operator=(mul const & other)
61 debugmsg("mul operator=",LOGLEVEL_ASSIGNMENT);
71 void mul::copy(mul const & other)
73 expairseq::copy(other);
76 void mul::destroy(bool call_parent)
78 if (call_parent) expairseq::destroy(call_parent);
87 mul::mul(ex const & lh, ex const & rh)
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());
96 mul::mul(exvector const & v)
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());
106 mul::mul(epvector const & v, bool do_not_canonicalize)
108 debugmsg("mul constructor from epvector,bool",LOGLEVEL_CONSTRUCT);
109 tinfo_key = TINFO_mul;
110 if (do_not_canonicalize) {
112 #ifdef EXPAIRSEQ_USE_HASHTAB
113 combine_same_terms(); // to build hashtab
114 #endif // def EXPAIRSEQ_USE_HASHTAB
116 construct_from_epvector(v);
118 GINAC_ASSERT(is_canonical());
122 mul::mul(epvector const & v)
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());
131 mul::mul(epvector const & v, ex const & oc)
133 debugmsg("mul constructor from epvector,ex",LOGLEVEL_CONSTRUCT);
134 tinfo_key = TINFO_mul;
136 construct_from_epvector(v);
137 GINAC_ASSERT(is_canonical());
140 mul::mul(epvector * vp, ex const & oc)
142 debugmsg("mul constructor from epvector *,ex",LOGLEVEL_CONSTRUCT);
143 tinfo_key = TINFO_mul;
146 construct_from_epvector(*vp);
148 GINAC_ASSERT(is_canonical());
151 mul::mul(ex const & lh, ex const & mh, ex const & rh)
153 debugmsg("mul constructor from ex,ex,ex",LOGLEVEL_CONSTRUCT);
154 tinfo_key = TINFO_mul;
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());
166 // functions overriding virtual functions from bases classes
171 basic * mul::duplicate() const
173 debugmsg("mul duplicate",LOGLEVEL_ASSIGNMENT);
174 return new mul(*this);
177 bool mul::info(unsigned inf) const
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)))
187 return expairseq::info(inf);
191 typedef vector<int> intvector;
193 int mul::degree(symbol const & s) const
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();
202 int mul::ldegree(symbol const & s) const
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();
211 ex mul::coeff(symbol const & s, int const n) const
214 coeffseq.reserve(seq.size()+1);
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));
224 coeffseq.push_back(overall_coeff);
225 return (new mul(coeffseq))->setflag(status_flags::dynallocated);
228 epvector::const_iterator it=seq.begin();
230 while (it!=seq.end()) {
231 ex t=recombine_pair_to_ex(*it);
234 coeffseq.push_back(c);
237 coeffseq.push_back(t);
242 coeffseq.push_back(overall_coeff);
243 return (new mul(coeffseq))->setflag(status_flags::dynallocated);
250 ex mul::eval(int level) const
252 // simplifications: *(...,x,(c1,1),(c2,1)) -> *(...,x,(c1*c2,1)) (c1, c2 numeric(), move pairs to end first)
253 // *(...,x,1) -> *(...,x)
255 // *(+(x,y,...),(c,1)) -> *(+(*(x,c),*(y,c),...)) (c numeric())
259 debugmsg("mul eval",LOGLEVEL_MEMBER_FUNCTION);
261 if ((level==1)&&(flags & status_flags::evaluated)) {
262 #ifdef DO_GINAC_ASSERT
263 for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
264 GINAC_ASSERT((!is_ex_exactly_of_type((*cit).rest,mul))||
265 (!(ex_to_numeric((*cit).coeff).is_integer())));
268 // test if all numerics were moved to the end and
269 // all numerics with coeff 1 to the very end
271 epvector::const_iterator cit=seq.end();
272 bool all_coeff_1=true;
273 bool all_numeric=true;
276 if (is_ex_exactly_of_type((*cit).rest,numeric)) {
277 GINAC_ASSERT(all_numeric);
278 if ((*cit).coeff.is_equal(exONE())) {
279 GINAC_ASSERT(all_coeff_1);
286 } while (cit!=seq.begin());
288 #endif // def DO_GINAC_ASSERT
293 epvector::iterator it1,it2;
294 bool seq_copied=false;
296 epvector * evaled_seqp=evalchildren(level);
297 if (evaled_seqp!=0) {
298 // do more evaluation later
299 return (new mul(evaled_seqp))->setflag(status_flags::dynallocated);
302 // combine pairs with coeff 1 (all numerics should be at end, assert below)
304 // count number of pairs with coeff 1
305 unsigned num_coeff_1=0;
306 bool still_numeric=true;
307 epvector::const_iterator cit=seq.end();
312 if (is_ex_exactly_of_type((*cit).rest,numeric)) {
313 if ((*cit).coeff.is_equal(exONE())) {
319 } while ((cit!=seq.begin())&&still_numeric);
326 #ifdef DO_GINAC_ASSERT
327 for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
328 GINAC_ASSERT((!is_ex_exactly_of_type((*cit).rest,mul))||
329 (!(ex_to_numeric((*cit).coeff).is_integer())));
332 // test if all numerics were moved to the end and
333 // all numerics with coeff 1 to the very end
335 epvector::const_iterator cit=seq.end();
336 bool all_coeff_1=true;
337 bool all_numeric=true;
340 if (is_ex_exactly_of_type((*cit).rest,numeric)) {
341 GINAC_ASSERT(all_numeric);
342 if ((*cit).coeff.is_equal(exONE())) {
343 GINAC_ASSERT(all_coeff_1);
350 } while (cit!=seq.begin());
352 #endif // def DO_GINAC_ASSERT
354 if (flags & status_flags::evaluated) {
358 expair const & last_expair=*(seq.end()-1);
359 expair const & next_to_last_expair=*(seq.end()-2);
360 int seq_size = seq.size();
362 // *(...,x,(c1,1),(c2,1)) -> *(...,x,(c1*c2,1)) (c1, c2 numeric())
363 if ((!seq_copied) && (seq_size>=2) &&
364 is_ex_exactly_of_type(last_expair.rest,numeric) &&
365 ex_to_numeric(last_expair.coeff).is_equal(numONE()) &&
366 is_ex_exactly_of_type(next_to_last_expair.rest,numeric) &&
367 ex_to_numeric(next_to_last_expair.coeff).is_equal(numONE()) ) {
373 while (seq_copied && (newseq.size()>=2) &&
374 is_ex_exactly_of_type((*it1).rest,numeric) &&
375 ex_to_numeric((*it1).coeff).is_equal(numONE()) &&
376 is_ex_exactly_of_type((*it2).rest,numeric) &&
377 ex_to_numeric((*it2).coeff).is_equal(numONE()) ) {
378 *it1=expair(ex_to_numeric((*it1).rest).mul_dyn(ex_to_numeric((*it2).rest)),exONE());
384 // *(...,x,1) -> *(...,x)
385 if ((!seq_copied) && (seq_size>=1) &&
386 (is_ex_exactly_of_type(last_expair.rest,numeric)) &&
387 (ex_to_numeric(last_expair.rest).compare(numONE())==0)) {
392 if (seq_copied && (newseq.size()>=1) &&
393 (is_ex_exactly_of_type((*it2).rest,numeric)) &&
394 (ex_to_numeric((*it2).rest).compare(numONE())==0)) {
400 if ((!seq_copied) && (seq_size>=1) &&
401 (is_ex_exactly_of_type(last_expair.rest,numeric)) &&
402 (ex_to_numeric(last_expair.rest).is_zero())) {
405 if (seq_copied && (newseq.size()>=1) &&
406 (is_ex_exactly_of_type((*it2).rest,numeric)) &&
407 (ex_to_numeric((*it2).rest).is_zero())) {
411 // *(+(x,y,...),c) -> +(*(x,c),*(y,c),...) (c numeric(), no powers of +())
412 if ((!seq_copied) && (seq_size==2) &&
413 is_ex_exactly_of_type(next_to_last_expair.rest,add) &&
414 is_ex_exactly_of_type(last_expair.rest,numeric) &&
415 ex_to_numeric(last_expair.coeff).is_equal(numONE()) &&
416 (ex_to_numeric(next_to_last_expair.coeff).compare(numONE())==0)) {
417 add const & addref=ex_to_add(next_to_last_expair.rest);
419 distrseq.reserve(addref.seq.size());
420 for (epvector::const_iterator cit=addref.seq.begin(); cit!=addref.seq.end(); ++cit) {
421 distrseq.push_back(addref.combine_pair_with_coeff_to_pair(*cit,
424 // special treatment for the last element if it is numeric (to
425 // avoid terms like (2/3)*(3/2)) is no longer necessary, this
426 // is handled in add::combine_pair_with_coeff_to_pair()
427 return (new add(distrseq,1))->setflag(status_flags::dynallocated |
428 status_flags::evaluated );
430 if (seq_copied && (newseq.size()==2) &&
431 is_ex_exactly_of_type(newseq[0].rest,add) &&
432 is_ex_exactly_of_type(newseq[1].rest,numeric) &&
433 ex_to_numeric(newseq[1].coeff).is_equal(numONE()) &&
434 (ex_to_numeric(newseq[0].coeff).compare(numONE())==0)) {
435 add const & addref=ex_to_add(newseq[0].rest);
437 distrseq.reserve(addref.seq.size());
438 for (epvector::const_iterator cit=addref.seq.begin(); cit!=addref.seq.end(); ++cit) {
439 distrseq.push_back(addref.combine_pair_with_coeff_to_pair(*cit,
442 // special treatment for the last element if it is numeric (to
443 // avoid terms like (2/3)*(3/2)) is no longer necessary, this
444 // is handled in add::combine_pair_with_coeff_to_pair()
445 return (new add(distrseq,1))->setflag(status_flags::dynallocated |
446 status_flags::evaluated );
450 if ((!seq_copied) && (seq_size==0)) {
452 } else if (seq_copied && (newseq.size()==0)) {
457 if ((!seq_copied) && (seq_size==1)) {
458 return recombine_pair_to_ex(*(seq.begin()));
459 } else if (seq_copied && (newseq.size()==1)) {
460 return recombine_pair_to_ex(*(newseq.begin()));
463 if (!seq_copied) return this->hold();
465 return (new mul(newseq,1))->setflag(status_flags::dynallocated |
466 status_flags::evaluated );
470 ex mul::eval(int level) const
472 // simplifications *(...,x;0) -> 0
473 // *(+(x,y,...);c) -> *(+(*(x,c),*(y,c),...)) (c numeric())
477 debugmsg("mul eval",LOGLEVEL_MEMBER_FUNCTION);
479 epvector * evaled_seqp=evalchildren(level);
480 if (evaled_seqp!=0) {
481 // do more evaluation later
482 return (new mul(evaled_seqp,overall_coeff))->
483 setflag(status_flags::dynallocated);
486 #ifdef DO_GINAC_ASSERT
487 for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
488 GINAC_ASSERT((!is_ex_exactly_of_type((*cit).rest,mul))||
489 (!(ex_to_numeric((*cit).coeff).is_integer())));
490 GINAC_ASSERT(!((*cit).is_numeric_with_coeff_1()));
491 if (is_ex_exactly_of_type(recombine_pair_to_ex(*cit),numeric)) {
494 GINAC_ASSERT(!is_ex_exactly_of_type(recombine_pair_to_ex(*cit),numeric));
496 expair p=split_ex_to_pair(recombine_pair_to_ex(*cit));
497 GINAC_ASSERT(p.rest.is_equal((*cit).rest));
498 GINAC_ASSERT(p.coeff.is_equal((*cit).coeff));
501 #endif // def DO_GINAC_ASSERT
503 if (flags & status_flags::evaluated) {
504 GINAC_ASSERT(seq.size()>0);
505 GINAC_ASSERT((seq.size()>1)||!overall_coeff.is_equal(exONE()));
509 int seq_size=seq.size();
510 if (overall_coeff.is_equal(exZERO())) {
513 } else if (seq_size==0) {
515 return overall_coeff;
516 } else if ((seq_size==1)&&overall_coeff.is_equal(exONE())) {
518 return recombine_pair_to_ex(*(seq.begin()));
519 } else if ((seq_size==1) &&
520 is_ex_exactly_of_type((*seq.begin()).rest,add) &&
521 ex_to_numeric((*seq.begin()).coeff).is_equal(numONE())) {
522 // *(+(x,y,...);c) -> +(*(x,c),*(y,c),...) (c numeric(), no powers of +())
523 add const & addref=ex_to_add((*seq.begin()).rest);
525 distrseq.reserve(addref.seq.size());
526 for (epvector::const_iterator cit=addref.seq.begin(); cit!=addref.seq.end(); ++cit) {
527 distrseq.push_back(addref.combine_pair_with_coeff_to_pair(*cit,
530 return (new add(distrseq,
531 ex_to_numeric(addref.overall_coeff).
532 mul_dyn(ex_to_numeric(overall_coeff))))
533 ->setflag(status_flags::dynallocated |
534 status_flags::evaluated );
540 ex mul::eval(int level) const
542 // simplifications: *(...,x,c1,c2) -> *(...,x,c1*c2) (c1, c2 numeric())
543 // *(...,(c1,c2)) -> (...,(c1^c2,1)) (normalize)
544 // *(...,x,1) -> +(...,x)
546 // *(+(x,y,...),c) -> *(+(*(x,c),*(y,c),...)) (c numeric())
550 debugmsg("mul eval",LOGLEVEL_MEMBER_FUNCTION);
553 epvector::iterator it1,it2;
555 // *(...,x,c1,c2) -> *(...,x,c1*c2) (c1, c2 numeric())
558 while ((newseq.size()>=2)&&is_exactly_of_type(*(*it1).rest.bp,numeric)&&
559 is_exactly_of_type(*(*it2).rest.bp,numeric)) {
560 *it1=expair(ex_to_numeric((*it1).rest).power(ex_to_numeric((*it1).coeff))
561 .mul(ex_to_numeric((*it2).rest).power(ex_to_numeric((*it2).coeff))),exONE());
567 if ((newseq.size()>=1)&&is_exactly_of_type(*(*it2).rest.bp,numeric)) {
568 // *(...,(c1,c2)) -> (...,(c1^c2,1)) (normalize)
569 *it2=expair(ex_to_numeric((*it2).rest).power(ex_to_numeric((*it2).coeff)),exONE());
570 // *(...,x,1) -> *(...,x)
571 if (static_cast<numeric &>(*(*it2).rest.bp).compare(numONE())==0) {
578 if ((newseq.size()>=1)&&is_exactly_of_type(*(*it2).rest.bp,numeric)) {
579 if (static_cast<numeric &>(*(*it2).rest.bp).is_zero()==0) {
584 // *(+(x,y,...),c) -> +(*(x,c),*(y,c),...) (c numeric(), no powers of +())
585 if ((newseq.size()==2)&&is_ex_exactly_of_type(newseq[0].rest,add)&&
586 is_ex_exactly_of_type(newseq[1].rest,numeric)&&
587 (ex_to_numeric(newseq[0].coeff).compare(numONE())==0)) {
588 add const & addref=ex_to_add(newseq[0].rest);
589 numeric const & numref=ex_to_numeric(newseq[1].rest);
591 distrseq.reserve(addref.seq.size());
592 for (epvector::const_iterator cit=addref.seq.begin(); cit!=addref.seq.end(); ++cit) {
593 distrseq.push_back(expair((*cit).rest,ex_to_numeric((*cit).coeff).mul(numref)));
595 return (new add(distrseq,1))->setflag(status_flags::dynallocated |
596 status_flags::evaluated );
599 if (newseq.size()==0) {
602 } else if (newseq.size()==1) {
604 return recombine_pair_to_ex(*newseq.begin());
607 return (new mul(newseq,1))->setflag(status_flags::dynallocated |
608 status_flags::evaluated );
612 exvector mul::get_indices(void) const
614 // return union of indices of factors
616 for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
617 exvector subiv=(*cit).rest.get_indices();
618 iv.reserve(iv.size()+subiv.size());
619 for (exvector::const_iterator cit2=subiv.begin(); cit2!=subiv.end(); ++cit2) {
626 ex mul::simplify_ncmul(exvector const & v) const
628 throw(std::logic_error("mul::simplify_ncmul() should never have been called!"));
633 int mul::compare_same_type(basic const & other) const
635 return expairseq::compare_same_type(other);
638 bool mul::is_equal_same_type(basic const & other) const
640 return expairseq::is_equal_same_type(other);
643 unsigned mul::return_type(void) const
646 // mul without factors: should not happen, but commutes
647 return return_types::commutative;
650 bool all_commutative=1;
652 epvector::const_iterator cit_noncommutative_element; // point to first found nc element
654 for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
655 rt=(*cit).rest.return_type();
656 if (rt==return_types::noncommutative_composite) return rt; // one ncc -> mul also ncc
657 if ((rt==return_types::noncommutative)&&(all_commutative)) {
658 // first nc element found, remember position
659 cit_noncommutative_element=cit;
662 if ((rt==return_types::noncommutative)&&(!all_commutative)) {
663 // another nc element found, compare type_infos
664 if ((*cit_noncommutative_element).rest.return_type_tinfo()!=(*cit).rest.return_type_tinfo()) {
665 // diffent types -> mul is ncc
666 return return_types::noncommutative_composite;
670 // all factors checked
671 return all_commutative ? return_types::commutative : return_types::noncommutative;
674 unsigned mul::return_type_tinfo(void) const
677 // mul without factors: should not happen
680 // return type_info of first noncommutative element
681 for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
682 if ((*cit).rest.return_type()==return_types::noncommutative) {
683 return (*cit).rest.return_type_tinfo();
686 // no noncommutative element found, should not happen
690 ex mul::thisexpairseq(epvector const & v, ex const & oc) const
692 return (new mul(v,oc))->setflag(status_flags::dynallocated);
695 ex mul::thisexpairseq(epvector * vp, ex const & oc) const
697 return (new mul(vp,oc))->setflag(status_flags::dynallocated);
700 expair mul::split_ex_to_pair(ex const & e) const
702 if (is_ex_exactly_of_type(e,power)) {
703 power const & powerref=ex_to_power(e);
704 if (is_ex_exactly_of_type(powerref.exponent,numeric)) {
705 return expair(powerref.basis,powerref.exponent);
708 return expair(e,exONE());
711 expair mul::combine_ex_with_coeff_to_pair(ex const & e,
714 // to avoid duplication of power simplification rules,
715 // we create a temporary power object
716 // otherwise it would be hard to correctly simplify
717 // expression like (4^(1/3))^(3/2)
718 if (are_ex_trivially_equal(c,exONE())) {
719 return split_ex_to_pair(e);
721 return split_ex_to_pair(power(e,c));
724 expair mul::combine_pair_with_coeff_to_pair(expair const & p,
727 // to avoid duplication of power simplification rules,
728 // we create a temporary power object
729 // otherwise it would be hard to correctly simplify
730 // expression like (4^(1/3))^(3/2)
731 if (are_ex_trivially_equal(c,exONE())) {
734 return split_ex_to_pair(power(recombine_pair_to_ex(p),c));
737 ex mul::recombine_pair_to_ex(expair const & p) const
739 // if (p.coeff.compare(exONE())==0) {
740 // if (are_ex_trivially_equal(p.coeff,exONE())) {
741 if (ex_to_numeric(p.coeff).is_equal(numONE())) {
744 return power(p.rest,p.coeff);
748 bool mul::expair_needs_further_processing(epp it)
750 if (is_ex_exactly_of_type((*it).rest,mul) &&
751 ex_to_numeric((*it).coeff).is_integer()) {
752 // combined pair is product with integer power -> expand it
753 *it=split_ex_to_pair(recombine_pair_to_ex(*it));
756 if (is_ex_exactly_of_type((*it).rest,numeric)) {
757 expair ep=split_ex_to_pair(recombine_pair_to_ex(*it));
758 if (!ep.is_equal(*it)) {
759 // combined pair is a numeric power which can be simplified
763 if (ex_to_numeric((*it).coeff).is_equal(numONE())) {
764 // combined pair has coeff 1 and must be moved to the end
771 ex mul::default_overall_coeff(void) const
776 void mul::combine_overall_coeff(ex const & c)
778 GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric));
779 GINAC_ASSERT(is_ex_exactly_of_type(c,numeric));
780 overall_coeff = ex_to_numeric(overall_coeff).mul_dyn(ex_to_numeric(c));
783 void mul::combine_overall_coeff(ex const & c1, ex const & c2)
785 GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric));
786 GINAC_ASSERT(is_ex_exactly_of_type(c1,numeric));
787 GINAC_ASSERT(is_ex_exactly_of_type(c2,numeric));
788 overall_coeff = ex_to_numeric(overall_coeff).
789 mul_dyn(ex_to_numeric(c1).power(ex_to_numeric(c2)));
792 bool mul::can_make_flat(expair const & p) const
794 GINAC_ASSERT(is_ex_exactly_of_type(p.coeff,numeric));
795 // this assertion will probably fail somewhere
796 // it would require a more careful make_flat, obeying the power laws
797 // probably should return true only if p.coeff is integer
798 return ex_to_numeric(p.coeff).is_equal(numONE());
801 ex mul::expand(unsigned options) const
803 exvector sub_expanded_seq;
804 intvector positions_of_adds;
805 intvector number_of_add_operands;
807 epvector * expanded_seqp=expandchildren(options);
809 epvector const & expanded_seq = expanded_seqp==0 ? seq : *expanded_seqp;
811 positions_of_adds.resize(expanded_seq.size());
812 number_of_add_operands.resize(expanded_seq.size());
814 int number_of_adds=0;
815 int number_of_expanded_terms=1;
817 unsigned current_position=0;
818 epvector::const_iterator last=expanded_seq.end();
819 for (epvector::const_iterator cit=expanded_seq.begin(); cit!=last; ++cit) {
820 if (is_ex_exactly_of_type((*cit).rest,add)&&
821 (ex_to_numeric((*cit).coeff).is_equal(numONE()))) {
822 positions_of_adds[number_of_adds]=current_position;
823 add const & expanded_addref=ex_to_add((*cit).rest);
824 int addref_nops=expanded_addref.nops();
825 number_of_add_operands[number_of_adds]=addref_nops;
826 number_of_expanded_terms *= addref_nops;
832 if (number_of_adds==0) {
833 if (expanded_seqp==0) {
834 return this->setflag(status_flags::expanded);
836 return (new mul(expanded_seqp,overall_coeff))->
837 setflag(status_flags::dynallocated ||
838 status_flags::expanded);
842 distrseq.reserve(number_of_expanded_terms);
845 k.resize(number_of_adds);
848 for (l=0; l<number_of_adds; l++) {
855 for (l=0; l<number_of_adds; l++) {
856 add const & addref=ex_to_add(expanded_seq[positions_of_adds[l]].rest);
857 GINAC_ASSERT(term[positions_of_adds[l]].coeff.compare(exONE())==0);
858 term[positions_of_adds[l]]=split_ex_to_pair(addref.op(k[l]));
861 cout << "mul::expand() term begin" << endl;
862 for (epvector::const_iterator cit=term.begin(); cit!=term.end(); ++cit) {
863 cout << "rest" << endl;
864 (*cit).rest.printtree(cout);
865 cout << "coeff" << endl;
866 (*cit).coeff.printtree(cout);
868 cout << "mul::expand() term end" << endl;
870 distrseq.push_back((new mul(term,overall_coeff))->
871 setflag(status_flags::dynallocated |
872 status_flags::expanded));
876 while ((l>=0)&&((++k[l])>=number_of_add_operands[l])) {
883 if (expanded_seqp!=0) {
884 delete expanded_seqp;
887 cout << "mul::expand() distrseq begin" << endl;
888 for (exvector::const_iterator cit=distrseq.begin(); cit!=distrseq.end(); ++cit) {
889 (*cit).printtree(cout);
891 cout << "mul::expand() distrseq end" << endl;
894 return (new add(distrseq))->setflag(status_flags::dynallocated |
895 status_flags::expanded);
899 ex mul::expand(unsigned options) const
901 exvector sub_expanded_seq;
902 intvector positions_of_adds;
903 intvector number_of_add_operands;
905 sub_expanded_seq.resize(seq.size());
906 positions_of_adds.resize(seq.size());
907 number_of_add_operands.reserve(seq.size());
909 int number_of_adds=0;
910 int number_of_expanded_terms=1;
911 for (unsigned current_position=0; current_position<seq.size(); current_position++) {
912 ex const & expanded_ex=recombine_pair_to_ex(seq[current_position]).expand(options);
913 if (is_ex_exactly_of_type(expanded_ex,add)) {
914 positions_of_adds[number_of_adds]=current_position;
915 add const & expanded_addref=ex_to_add(expanded_ex);
916 number_of_add_operands[number_of_adds]=expanded_addref.seq.size();
917 number_of_expanded_terms *= expanded_addref.seq.size();
920 sub_expanded_seq.push_back(expanded_ex);
924 distrseq.reserve(number_of_expanded_terms);
927 k.resize(number_of_adds);
930 for (l=0; l<number_of_adds; l++) {
936 term=sub_expanded_seq;
937 for (l=0; l<number_of_adds; l++) {
938 add const & addref=ex_to_add(sub_expanded_seq[positions_of_adds[l]]);
939 term[positions_of_adds[l]]=addref.recombine_pair_to_ex(addref.seq[k[l]]);
941 distrseq.push_back((new mul(term))->setflag(status_flags::dynallocated |
942 status_flags::expanded));
946 while ((l>=0)&&((++k[l])>=number_of_add_operands[l])) {
953 return (new add(distrseq))->setflag(status_flags::dynallocated |
954 status_flags::expanded);
959 // new virtual functions which can be overridden by derived classes
965 // non-virtual functions in this class
968 epvector * mul::expandchildren(unsigned options) const
970 epvector::const_iterator last=seq.end();
971 epvector::const_iterator cit=seq.begin();
973 ex const & factor=recombine_pair_to_ex(*cit);
974 ex const & expanded_factor=factor.expand(options);
975 if (!are_ex_trivially_equal(factor,expanded_factor)) {
977 // something changed, copy seq, eval and return it
978 epvector *s=new epvector;
979 s->reserve(seq.size());
981 // copy parts of seq which are known not to have changed
982 epvector::const_iterator cit2=seq.begin();
987 // copy first changed element
988 s->push_back(split_ex_to_pair(expanded_factor));
992 s->push_back(split_ex_to_pair(recombine_pair_to_ex(*cit2).expand(options)));
1000 return 0; // nothing has changed
1004 // static member variables
1009 unsigned mul::precedence=50;
1017 type_info const & typeid_mul=typeid(some_mul);
1019 #ifndef NO_GINAC_NAMESPACE
1020 } // namespace GiNaC
1021 #endif // ndef NO_GINAC_NAMESPACE