3 * Implementation of GiNaC's products of expressions. */
11 // default constructor, destructor, copy constructor assignment operator and helpers
18 debugmsg("mul default constructor",LOGLEVEL_CONSTRUCT);
19 tinfo_key = TINFO_MUL;
24 debugmsg("mul destructor",LOGLEVEL_DESTRUCT);
28 mul::mul(mul const & other)
30 debugmsg("mul copy constructor",LOGLEVEL_CONSTRUCT);
34 mul const & mul::operator=(mul const & other)
36 debugmsg("mul operator=",LOGLEVEL_ASSIGNMENT);
46 void mul::copy(mul const & other)
48 expairseq::copy(other);
51 void mul::destroy(bool call_parent)
53 if (call_parent) expairseq::destroy(call_parent);
62 mul::mul(ex const & lh, ex const & rh)
64 debugmsg("mul constructor from ex,ex",LOGLEVEL_CONSTRUCT);
65 tinfo_key = TINFO_MUL;
66 overall_coeff=exONE();
67 construct_from_2_ex(lh,rh);
68 ASSERT(is_canonical());
71 mul::mul(exvector const & v)
73 debugmsg("mul constructor from exvector",LOGLEVEL_CONSTRUCT);
74 tinfo_key = TINFO_MUL;
75 overall_coeff=exONE();
76 construct_from_exvector(v);
77 ASSERT(is_canonical());
81 mul::mul(epvector const & v, bool do_not_canonicalize)
83 debugmsg("mul constructor from epvector,bool",LOGLEVEL_CONSTRUCT);
84 tinfo_key = TINFO_MUL;
85 if (do_not_canonicalize) {
87 #ifdef EXPAIRSEQ_USE_HASHTAB
88 combine_same_terms(); // to build hashtab
89 #endif // def EXPAIRSEQ_USE_HASHTAB
91 construct_from_epvector(v);
93 ASSERT(is_canonical());
97 mul::mul(epvector const & v)
99 debugmsg("mul constructor from epvector",LOGLEVEL_CONSTRUCT);
100 tinfo_key = TINFO_MUL;
101 overall_coeff=exONE();
102 construct_from_epvector(v);
103 ASSERT(is_canonical());
106 mul::mul(epvector const & v, ex const & oc)
108 debugmsg("mul constructor from epvector,ex",LOGLEVEL_CONSTRUCT);
109 tinfo_key = TINFO_MUL;
111 construct_from_epvector(v);
112 ASSERT(is_canonical());
115 mul::mul(epvector * vp, ex const & oc)
117 debugmsg("mul constructor from epvector *,ex",LOGLEVEL_CONSTRUCT);
118 tinfo_key = TINFO_MUL;
121 construct_from_epvector(*vp);
123 ASSERT(is_canonical());
126 mul::mul(ex const & lh, ex const & mh, ex const & rh)
128 debugmsg("mul constructor from ex,ex,ex",LOGLEVEL_CONSTRUCT);
129 tinfo_key = TINFO_MUL;
132 factors.push_back(lh);
133 factors.push_back(mh);
134 factors.push_back(rh);
135 overall_coeff=exONE();
136 construct_from_exvector(factors);
137 ASSERT(is_canonical());
141 // functions overriding virtual functions from bases classes
146 basic * mul::duplicate() const
148 debugmsg("mul duplicate",LOGLEVEL_ASSIGNMENT);
149 return new mul(*this);
152 bool mul::info(unsigned inf) const
155 if (inf==info_flags::polynomial || inf==info_flags::integer_polynomial || inf==info_flags::rational_polynomial || inf==info_flags::rational_function) {
156 for (epvector::const_iterator it=seq.begin(); it!=seq.end(); ++it) {
157 if (!(recombine_pair_to_ex(*it).info(inf)))
162 return expairseq::info(inf);
166 typedef vector<int> intvector;
168 int mul::degree(symbol const & s) const
171 for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
172 deg_sum+=(*cit).rest.degree(s) * ex_to_numeric((*cit).coeff).to_int();
177 int mul::ldegree(symbol const & s) const
180 for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
181 deg_sum+=(*cit).rest.ldegree(s) * ex_to_numeric((*cit).coeff).to_int();
186 ex mul::coeff(symbol const & s, int const n) const
189 coeffseq.reserve(seq.size()+1);
192 // product of individual coeffs
193 // if a non-zero power of s is found, the resulting product will be 0
194 epvector::const_iterator it=seq.begin();
195 while (it!=seq.end()) {
196 coeffseq.push_back(recombine_pair_to_ex(*it).coeff(s,n));
199 coeffseq.push_back(overall_coeff);
200 return (new mul(coeffseq))->setflag(status_flags::dynallocated);
203 epvector::const_iterator it=seq.begin();
205 while (it!=seq.end()) {
206 ex t=recombine_pair_to_ex(*it);
209 coeffseq.push_back(c);
212 coeffseq.push_back(t);
217 coeffseq.push_back(overall_coeff);
218 return (new mul(coeffseq))->setflag(status_flags::dynallocated);
225 ex mul::eval(int level) const
227 // simplifications: *(...,x,(c1,1),(c2,1)) -> *(...,x,(c1*c2,1)) (c1, c2 numeric(), move pairs to end first)
228 // *(...,x,1) -> *(...,x)
230 // *(+(x,y,...),(c,1)) -> *(+(*(x,c),*(y,c),...)) (c numeric())
234 debugmsg("mul eval",LOGLEVEL_MEMBER_FUNCTION);
236 if ((level==1)&&(flags & status_flags::evaluated)) {
238 for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
239 ASSERT((!is_ex_exactly_of_type((*cit).rest,mul))||
240 (!(ex_to_numeric((*cit).coeff).is_integer())));
243 // test if all numerics were moved to the end and
244 // all numerics with coeff 1 to the very end
246 epvector::const_iterator cit=seq.end();
247 bool all_coeff_1=true;
248 bool all_numeric=true;
251 if (is_ex_exactly_of_type((*cit).rest,numeric)) {
253 if ((*cit).coeff.is_equal(exONE())) {
261 } while (cit!=seq.begin());
263 #endif // def DOASSERT
268 epvector::iterator it1,it2;
269 bool seq_copied=false;
271 epvector * evaled_seqp=evalchildren(level);
272 if (evaled_seqp!=0) {
273 // do more evaluation later
274 return (new mul(evaled_seqp))->setflag(status_flags::dynallocated);
277 // combine pairs with coeff 1 (all numerics should be at end, assert below)
279 // count number of pairs with coeff 1
280 unsigned num_coeff_1=0;
281 bool still_numeric=true;
282 epvector::const_iterator cit=seq.end();
287 if (is_ex_exactly_of_type((*cit).rest,numeric)) {
288 if ((*cit).coeff.is_equal(exONE())) {
294 } while ((cit!=seq.begin())&&still_numeric);
302 for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
303 ASSERT((!is_ex_exactly_of_type((*cit).rest,mul))||
304 (!(ex_to_numeric((*cit).coeff).is_integer())));
307 // test if all numerics were moved to the end and
308 // all numerics with coeff 1 to the very end
310 epvector::const_iterator cit=seq.end();
311 bool all_coeff_1=true;
312 bool all_numeric=true;
315 if (is_ex_exactly_of_type((*cit).rest,numeric)) {
317 if ((*cit).coeff.is_equal(exONE())) {
325 } while (cit!=seq.begin());
327 #endif // def DOASSERT
329 if (flags & status_flags::evaluated) {
333 expair const & last_expair=*(seq.end()-1);
334 expair const & next_to_last_expair=*(seq.end()-2);
335 int seq_size = seq.size();
337 // *(...,x,(c1,1),(c2,1)) -> *(...,x,(c1*c2,1)) (c1, c2 numeric())
338 if ((!seq_copied) && (seq_size>=2) &&
339 is_ex_exactly_of_type(last_expair.rest,numeric) &&
340 ex_to_numeric(last_expair.coeff).is_equal(numONE()) &&
341 is_ex_exactly_of_type(next_to_last_expair.rest,numeric) &&
342 ex_to_numeric(next_to_last_expair.coeff).is_equal(numONE()) ) {
348 while (seq_copied && (newseq.size()>=2) &&
349 is_ex_exactly_of_type((*it1).rest,numeric) &&
350 ex_to_numeric((*it1).coeff).is_equal(numONE()) &&
351 is_ex_exactly_of_type((*it2).rest,numeric) &&
352 ex_to_numeric((*it2).coeff).is_equal(numONE()) ) {
353 *it1=expair(ex_to_numeric((*it1).rest).mul_dyn(ex_to_numeric((*it2).rest)),exONE());
359 // *(...,x,1) -> *(...,x)
360 if ((!seq_copied) && (seq_size>=1) &&
361 (is_ex_exactly_of_type(last_expair.rest,numeric)) &&
362 (ex_to_numeric(last_expair.rest).compare(numONE())==0)) {
367 if (seq_copied && (newseq.size()>=1) &&
368 (is_ex_exactly_of_type((*it2).rest,numeric)) &&
369 (ex_to_numeric((*it2).rest).compare(numONE())==0)) {
375 if ((!seq_copied) && (seq_size>=1) &&
376 (is_ex_exactly_of_type(last_expair.rest,numeric)) &&
377 (ex_to_numeric(last_expair.rest).is_zero())) {
380 if (seq_copied && (newseq.size()>=1) &&
381 (is_ex_exactly_of_type((*it2).rest,numeric)) &&
382 (ex_to_numeric((*it2).rest).is_zero())) {
386 // *(+(x,y,...),c) -> +(*(x,c),*(y,c),...) (c numeric(), no powers of +())
387 if ((!seq_copied) && (seq_size==2) &&
388 is_ex_exactly_of_type(next_to_last_expair.rest,add) &&
389 is_ex_exactly_of_type(last_expair.rest,numeric) &&
390 ex_to_numeric(last_expair.coeff).is_equal(numONE()) &&
391 (ex_to_numeric(next_to_last_expair.coeff).compare(numONE())==0)) {
392 add const & addref=ex_to_add(next_to_last_expair.rest);
394 distrseq.reserve(addref.seq.size());
395 for (epvector::const_iterator cit=addref.seq.begin(); cit!=addref.seq.end(); ++cit) {
396 distrseq.push_back(addref.combine_pair_with_coeff_to_pair(*cit,
399 // special treatment for the last element if it is numeric (to
400 // avoid terms like (2/3)*(3/2)) is no longer necessary, this
401 // is handled in add::combine_pair_with_coeff_to_pair()
402 return (new add(distrseq,1))->setflag(status_flags::dynallocated |
403 status_flags::evaluated );
405 if (seq_copied && (newseq.size()==2) &&
406 is_ex_exactly_of_type(newseq[0].rest,add) &&
407 is_ex_exactly_of_type(newseq[1].rest,numeric) &&
408 ex_to_numeric(newseq[1].coeff).is_equal(numONE()) &&
409 (ex_to_numeric(newseq[0].coeff).compare(numONE())==0)) {
410 add const & addref=ex_to_add(newseq[0].rest);
412 distrseq.reserve(addref.seq.size());
413 for (epvector::const_iterator cit=addref.seq.begin(); cit!=addref.seq.end(); ++cit) {
414 distrseq.push_back(addref.combine_pair_with_coeff_to_pair(*cit,
417 // special treatment for the last element if it is numeric (to
418 // avoid terms like (2/3)*(3/2)) is no longer necessary, this
419 // is handled in add::combine_pair_with_coeff_to_pair()
420 return (new add(distrseq,1))->setflag(status_flags::dynallocated |
421 status_flags::evaluated );
425 if ((!seq_copied) && (seq_size==0)) {
427 } else if (seq_copied && (newseq.size()==0)) {
432 if ((!seq_copied) && (seq_size==1)) {
433 return recombine_pair_to_ex(*(seq.begin()));
434 } else if (seq_copied && (newseq.size()==1)) {
435 return recombine_pair_to_ex(*(newseq.begin()));
438 if (!seq_copied) return this->hold();
440 return (new mul(newseq,1))->setflag(status_flags::dynallocated |
441 status_flags::evaluated );
445 ex mul::eval(int level) const
447 // simplifications *(...,x;0) -> 0
448 // *(+(x,y,...);c) -> *(+(*(x,c),*(y,c),...)) (c numeric())
452 debugmsg("mul eval",LOGLEVEL_MEMBER_FUNCTION);
454 epvector * evaled_seqp=evalchildren(level);
455 if (evaled_seqp!=0) {
456 // do more evaluation later
457 return (new mul(evaled_seqp,overall_coeff))->
458 setflag(status_flags::dynallocated);
462 for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
463 ASSERT((!is_ex_exactly_of_type((*cit).rest,mul))||
464 (!(ex_to_numeric((*cit).coeff).is_integer())));
465 ASSERT(!((*cit).is_numeric_with_coeff_1()));
466 if (is_ex_exactly_of_type(recombine_pair_to_ex(*cit),numeric)) {
469 ASSERT(!is_ex_exactly_of_type(recombine_pair_to_ex(*cit),numeric));
471 expair p=split_ex_to_pair(recombine_pair_to_ex(*cit));
472 ASSERT(p.rest.is_equal((*cit).rest));
473 ASSERT(p.coeff.is_equal((*cit).coeff));
476 #endif // def DOASSERT
478 if (flags & status_flags::evaluated) {
479 ASSERT(seq.size()>0);
480 ASSERT((seq.size()>1)||!overall_coeff.is_equal(exONE()));
484 int seq_size=seq.size();
485 if (overall_coeff.is_equal(exZERO())) {
488 } else if (seq_size==0) {
490 return overall_coeff;
491 } else if ((seq_size==1)&&overall_coeff.is_equal(exONE())) {
493 return recombine_pair_to_ex(*(seq.begin()));
494 } else if ((seq_size==1) &&
495 is_ex_exactly_of_type((*seq.begin()).rest,add) &&
496 ex_to_numeric((*seq.begin()).coeff).is_equal(numONE())) {
497 // *(+(x,y,...);c) -> +(*(x,c),*(y,c),...) (c numeric(), no powers of +())
498 add const & addref=ex_to_add((*seq.begin()).rest);
500 distrseq.reserve(addref.seq.size());
501 for (epvector::const_iterator cit=addref.seq.begin(); cit!=addref.seq.end(); ++cit) {
502 distrseq.push_back(addref.combine_pair_with_coeff_to_pair(*cit,
505 return (new add(distrseq,
506 ex_to_numeric(addref.overall_coeff).
507 mul_dyn(ex_to_numeric(overall_coeff))))
508 ->setflag(status_flags::dynallocated |
509 status_flags::evaluated );
515 ex mul::eval(int level) const
517 // simplifications: *(...,x,c1,c2) -> *(...,x,c1*c2) (c1, c2 numeric())
518 // *(...,(c1,c2)) -> (...,(c1^c2,1)) (normalize)
519 // *(...,x,1) -> +(...,x)
521 // *(+(x,y,...),c) -> *(+(*(x,c),*(y,c),...)) (c numeric())
525 debugmsg("mul eval",LOGLEVEL_MEMBER_FUNCTION);
528 epvector::iterator it1,it2;
530 // *(...,x,c1,c2) -> *(...,x,c1*c2) (c1, c2 numeric())
533 while ((newseq.size()>=2)&&is_exactly_of_type(*(*it1).rest.bp,numeric)&&
534 is_exactly_of_type(*(*it2).rest.bp,numeric)) {
535 *it1=expair(ex_to_numeric((*it1).rest).power(ex_to_numeric((*it1).coeff))
536 .mul(ex_to_numeric((*it2).rest).power(ex_to_numeric((*it2).coeff))),exONE());
542 if ((newseq.size()>=1)&&is_exactly_of_type(*(*it2).rest.bp,numeric)) {
543 // *(...,(c1,c2)) -> (...,(c1^c2,1)) (normalize)
544 *it2=expair(ex_to_numeric((*it2).rest).power(ex_to_numeric((*it2).coeff)),exONE());
545 // *(...,x,1) -> *(...,x)
546 if (static_cast<numeric &>(*(*it2).rest.bp).compare(numONE())==0) {
553 if ((newseq.size()>=1)&&is_exactly_of_type(*(*it2).rest.bp,numeric)) {
554 if (static_cast<numeric &>(*(*it2).rest.bp).is_zero()==0) {
559 // *(+(x,y,...),c) -> +(*(x,c),*(y,c),...) (c numeric(), no powers of +())
560 if ((newseq.size()==2)&&is_ex_exactly_of_type(newseq[0].rest,add)&&
561 is_ex_exactly_of_type(newseq[1].rest,numeric)&&
562 (ex_to_numeric(newseq[0].coeff).compare(numONE())==0)) {
563 add const & addref=ex_to_add(newseq[0].rest);
564 numeric const & numref=ex_to_numeric(newseq[1].rest);
566 distrseq.reserve(addref.seq.size());
567 for (epvector::const_iterator cit=addref.seq.begin(); cit!=addref.seq.end(); ++cit) {
568 distrseq.push_back(expair((*cit).rest,ex_to_numeric((*cit).coeff).mul(numref)));
570 return (new add(distrseq,1))->setflag(status_flags::dynallocated |
571 status_flags::evaluated );
574 if (newseq.size()==0) {
577 } else if (newseq.size()==1) {
579 return recombine_pair_to_ex(*newseq.begin());
582 return (new mul(newseq,1))->setflag(status_flags::dynallocated |
583 status_flags::evaluated );
587 exvector mul::get_indices(void) const
589 // return union of indices of factors
591 for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
592 exvector subiv=(*cit).rest.get_indices();
593 iv.reserve(iv.size()+subiv.size());
594 for (exvector::const_iterator cit2=subiv.begin(); cit2!=subiv.end(); ++cit2) {
601 ex mul::simplify_ncmul(exvector const & v) const
603 throw(std::logic_error("mul::simplify_ncmul() should never have been called!"));
608 int mul::compare_same_type(basic const & other) const
610 return expairseq::compare_same_type(other);
613 bool mul::is_equal_same_type(basic const & other) const
615 return expairseq::is_equal_same_type(other);
618 unsigned mul::return_type(void) const
621 // mul without factors: should not happen, but commutes
622 return return_types::commutative;
625 bool all_commutative=1;
627 epvector::const_iterator cit_noncommutative_element; // point to first found nc element
629 for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
630 rt=(*cit).rest.return_type();
631 if (rt==return_types::noncommutative_composite) return rt; // one ncc -> mul also ncc
632 if ((rt==return_types::noncommutative)&&(all_commutative)) {
633 // first nc element found, remember position
634 cit_noncommutative_element=cit;
637 if ((rt==return_types::noncommutative)&&(!all_commutative)) {
638 // another nc element found, compare type_infos
639 if ((*cit_noncommutative_element).rest.return_type_tinfo()!=(*cit).rest.return_type_tinfo()) {
640 // diffent types -> mul is ncc
641 return return_types::noncommutative_composite;
645 // all factors checked
646 return all_commutative ? return_types::commutative : return_types::noncommutative;
649 unsigned mul::return_type_tinfo(void) const
652 // mul without factors: should not happen
655 // return type_info of first noncommutative element
656 for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
657 if ((*cit).rest.return_type()==return_types::noncommutative) {
658 return (*cit).rest.return_type_tinfo();
661 // no noncommutative element found, should not happen
665 ex mul::thisexpairseq(epvector const & v, ex const & oc) const
667 return (new mul(v,oc))->setflag(status_flags::dynallocated);
670 ex mul::thisexpairseq(epvector * vp, ex const & oc) const
672 return (new mul(vp,oc))->setflag(status_flags::dynallocated);
675 expair mul::split_ex_to_pair(ex const & e) const
677 if (is_ex_exactly_of_type(e,power)) {
678 power const & powerref=ex_to_power(e);
679 if (is_ex_exactly_of_type(powerref.exponent,numeric)) {
680 return expair(powerref.basis,powerref.exponent);
683 return expair(e,exONE());
686 expair mul::combine_ex_with_coeff_to_pair(ex const & e,
689 // to avoid duplication of power simplification rules,
690 // we create a temporary power object
691 // otherwise it would be hard to correctly simplify
692 // expression like (4^(1/3))^(3/2)
693 if (are_ex_trivially_equal(c,exONE())) {
694 return split_ex_to_pair(e);
696 return split_ex_to_pair(power(e,c));
699 expair mul::combine_pair_with_coeff_to_pair(expair const & p,
702 // to avoid duplication of power simplification rules,
703 // we create a temporary power object
704 // otherwise it would be hard to correctly simplify
705 // expression like (4^(1/3))^(3/2)
706 if (are_ex_trivially_equal(c,exONE())) {
709 return split_ex_to_pair(power(recombine_pair_to_ex(p),c));
712 ex mul::recombine_pair_to_ex(expair const & p) const
714 // if (p.coeff.compare(exONE())==0) {
715 // if (are_ex_trivially_equal(p.coeff,exONE())) {
716 if (ex_to_numeric(p.coeff).is_equal(numONE())) {
719 return power(p.rest,p.coeff);
723 bool mul::expair_needs_further_processing(epp it)
725 if (is_ex_exactly_of_type((*it).rest,mul) &&
726 ex_to_numeric((*it).coeff).is_integer()) {
727 // combined pair is product with integer power -> expand it
728 *it=split_ex_to_pair(recombine_pair_to_ex(*it));
731 if (is_ex_exactly_of_type((*it).rest,numeric)) {
732 expair ep=split_ex_to_pair(recombine_pair_to_ex(*it));
733 if (!ep.is_equal(*it)) {
734 // combined pair is a numeric power which can be simplified
738 if (ex_to_numeric((*it).coeff).is_equal(numONE())) {
739 // combined pair has coeff 1 and must be moved to the end
746 ex mul::default_overall_coeff(void) const
751 void mul::combine_overall_coeff(ex const & c)
753 ASSERT(is_ex_exactly_of_type(overall_coeff,numeric));
754 ASSERT(is_ex_exactly_of_type(c,numeric));
755 overall_coeff = ex_to_numeric(overall_coeff).mul_dyn(ex_to_numeric(c));
758 void mul::combine_overall_coeff(ex const & c1, ex const & c2)
760 ASSERT(is_ex_exactly_of_type(overall_coeff,numeric));
761 ASSERT(is_ex_exactly_of_type(c1,numeric));
762 ASSERT(is_ex_exactly_of_type(c2,numeric));
763 overall_coeff = ex_to_numeric(overall_coeff).
764 mul_dyn(ex_to_numeric(c1).power(ex_to_numeric(c2)));
767 bool mul::can_make_flat(expair const & p) const
769 ASSERT(is_ex_exactly_of_type(p.coeff,numeric));
770 // this assertion will probably fail somewhere
771 // it would require a more careful make_flat, obeying the power laws
772 // probably should return true only if p.coeff is integer
773 return ex_to_numeric(p.coeff).is_equal(numONE());
776 ex mul::expand(unsigned options) const
778 exvector sub_expanded_seq;
779 intvector positions_of_adds;
780 intvector number_of_add_operands;
782 epvector * expanded_seqp=expandchildren(options);
784 epvector const & expanded_seq = expanded_seqp==0 ? seq : *expanded_seqp;
786 positions_of_adds.resize(expanded_seq.size());
787 number_of_add_operands.resize(expanded_seq.size());
789 int number_of_adds=0;
790 int number_of_expanded_terms=1;
792 unsigned current_position=0;
793 epvector::const_iterator last=expanded_seq.end();
794 for (epvector::const_iterator cit=expanded_seq.begin(); cit!=last; ++cit) {
795 if (is_ex_exactly_of_type((*cit).rest,add)&&
796 (ex_to_numeric((*cit).coeff).is_equal(numONE()))) {
797 positions_of_adds[number_of_adds]=current_position;
798 add const & expanded_addref=ex_to_add((*cit).rest);
799 int addref_nops=expanded_addref.nops();
800 number_of_add_operands[number_of_adds]=addref_nops;
801 number_of_expanded_terms *= addref_nops;
807 if (number_of_adds==0) {
808 if (expanded_seqp==0) {
809 return this->setflag(status_flags::expanded);
811 return (new mul(expanded_seqp,overall_coeff))->
812 setflag(status_flags::dynallocated ||
813 status_flags::expanded);
817 distrseq.reserve(number_of_expanded_terms);
820 k.resize(number_of_adds);
823 for (l=0; l<number_of_adds; l++) {
830 for (l=0; l<number_of_adds; l++) {
831 add const & addref=ex_to_add(expanded_seq[positions_of_adds[l]].rest);
832 ASSERT(term[positions_of_adds[l]].coeff.compare(exONE())==0);
833 term[positions_of_adds[l]]=split_ex_to_pair(addref.op(k[l]));
836 cout << "mul::expand() term begin" << endl;
837 for (epvector::const_iterator cit=term.begin(); cit!=term.end(); ++cit) {
838 cout << "rest" << endl;
839 (*cit).rest.printtree(cout);
840 cout << "coeff" << endl;
841 (*cit).coeff.printtree(cout);
843 cout << "mul::expand() term end" << endl;
845 distrseq.push_back((new mul(term,overall_coeff))->
846 setflag(status_flags::dynallocated |
847 status_flags::expanded));
851 while ((l>=0)&&((++k[l])>=number_of_add_operands[l])) {
858 if (expanded_seqp!=0) {
859 delete expanded_seqp;
862 cout << "mul::expand() distrseq begin" << endl;
863 for (exvector::const_iterator cit=distrseq.begin(); cit!=distrseq.end(); ++cit) {
864 (*cit).printtree(cout);
866 cout << "mul::expand() distrseq end" << endl;
869 return (new add(distrseq))->setflag(status_flags::dynallocated |
870 status_flags::expanded);
874 ex mul::expand(unsigned options) const
876 exvector sub_expanded_seq;
877 intvector positions_of_adds;
878 intvector number_of_add_operands;
880 sub_expanded_seq.resize(seq.size());
881 positions_of_adds.resize(seq.size());
882 number_of_add_operands.reserve(seq.size());
884 int number_of_adds=0;
885 int number_of_expanded_terms=1;
886 for (unsigned current_position=0; current_position<seq.size(); current_position++) {
887 ex const & expanded_ex=recombine_pair_to_ex(seq[current_position]).expand(options);
888 if (is_ex_exactly_of_type(expanded_ex,add)) {
889 positions_of_adds[number_of_adds]=current_position;
890 add const & expanded_addref=ex_to_add(expanded_ex);
891 number_of_add_operands[number_of_adds]=expanded_addref.seq.size();
892 number_of_expanded_terms *= expanded_addref.seq.size();
895 sub_expanded_seq.push_back(expanded_ex);
899 distrseq.reserve(number_of_expanded_terms);
902 k.resize(number_of_adds);
905 for (l=0; l<number_of_adds; l++) {
911 term=sub_expanded_seq;
912 for (l=0; l<number_of_adds; l++) {
913 add const & addref=ex_to_add(sub_expanded_seq[positions_of_adds[l]]);
914 term[positions_of_adds[l]]=addref.recombine_pair_to_ex(addref.seq[k[l]]);
916 distrseq.push_back((new mul(term))->setflag(status_flags::dynallocated |
917 status_flags::expanded));
921 while ((l>=0)&&((++k[l])>=number_of_add_operands[l])) {
928 return (new add(distrseq))->setflag(status_flags::dynallocated |
929 status_flags::expanded);
934 // new virtual functions which can be overridden by derived classes
940 // non-virtual functions in this class
943 epvector * mul::expandchildren(unsigned options) const
945 epvector::const_iterator last=seq.end();
946 epvector::const_iterator cit=seq.begin();
948 ex const & factor=recombine_pair_to_ex(*cit);
949 ex const & expanded_factor=factor.expand(options);
950 if (!are_ex_trivially_equal(factor,expanded_factor)) {
952 // something changed, copy seq, eval and return it
953 epvector *s=new epvector;
954 s->reserve(seq.size());
956 // copy parts of seq which are known not to have changed
957 epvector::const_iterator cit2=seq.begin();
962 // copy first changed element
963 s->push_back(split_ex_to_pair(expanded_factor));
967 s->push_back(split_ex_to_pair(recombine_pair_to_ex(*cit2).expand(options)));
975 return 0; // nothing has changed
979 // static member variables
984 unsigned mul::precedence=50;
992 type_info const & typeid_mul=typeid(some_mul);