- // simplifications: +(...,x,c1,c2) -> +(...,x,c1+c2) (c1, c2 numeric())
- // +(...,(c1,c2)) -> (...,(c1*c2,1)) (normalize)
- // +(...,x,0) -> +(...,x)
- // +(x) -> x
- // +() -> 0
-
- debugmsg("add eval",LOGLEVEL_MEMBER_FUNCTION);
-
- if ((level==1)&&(flags & status_flags::evaluated)) {
-#ifdef DOASSERT
- for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
- ASSERT(!is_ex_exactly_of_type((*cit).rest,add));
- ASSERT(!(is_ex_exactly_of_type((*cit).rest,numeric)&&
- (ex_to_numeric((*cit).coeff).compare(numONE())!=0)));
- }
-#endif // def DOASSERT
- return *this;
- }
-
- epvector newseq;
- epvector::iterator it1,it2;
- bool seq_copied=false;
-
- epvector * evaled_seqp=evalchildren(level);
- if (evaled_seqp!=0) {
- // do more evaluation later
- return (new add(evaled_seqp))->setflag(status_flags::dynallocated);
- }
-
-#ifdef DOASSERT
- for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
- ASSERT(!is_ex_exactly_of_type((*cit).rest,add));
- ASSERT(!(is_ex_exactly_of_type((*cit).rest,numeric)&&
- (ex_to_numeric((*cit).coeff).compare(numONE())!=0)));
- }
-#endif // def DOASSERT
-
- if (flags & status_flags::evaluated) {
- return *this;
- }
-
- expair const & last_expair=*(seq.end()-1);
- expair const & next_to_last_expair=*(seq.end()-2);
- int seq_size = seq.size();
-
- // +(...,x,c1,c2) -> +(...,x,c1+c2) (c1, c2 numeric())
- if ((!seq_copied)&&(seq_size>=2)&&
- is_ex_exactly_of_type(last_expair.rest,numeric)&&
- is_ex_exactly_of_type(next_to_last_expair.rest,numeric)) {
- newseq=seq;
- seq_copied=true;
- it2=newseq.end()-1;
- it1=it2-1;
- }
- while (seq_copied&&(newseq.size()>=2)&&
- is_ex_exactly_of_type((*it1).rest,numeric)&&
- is_ex_exactly_of_type((*it2).rest,numeric)) {
- *it1=expair(ex_to_numeric((*it1).rest).mul(ex_to_numeric((*it1).coeff))
- .add_dyn(ex_to_numeric((*it2).rest).mul(ex_to_numeric((*it2).coeff))),exONE());
- newseq.pop_back();
- it2=newseq.end()-1;
- it1=it2-1;
- }
-
- // +(...,(c1,c2)) -> (...,(c1*c2,1)) (normalize)
- if ((!seq_copied)&&(seq_size>=1)&&
- (is_ex_exactly_of_type(last_expair.rest,numeric))&&
- (ex_to_numeric(last_expair.coeff).compare(numONE())!=0)) {
- newseq=seq;
- seq_copied=true;
- it2=newseq.end()-1;
- }
- if (seq_copied&&(newseq.size()>=1)&&
- (is_ex_exactly_of_type((*it2).rest,numeric))&&
- (ex_to_numeric((*it2).coeff).compare(numONE())!=0)) {
- *it2=expair(ex_to_numeric((*it2).rest).mul_dyn(ex_to_numeric((*it2).coeff)),exONE());
- }
-
- // +(...,x,0) -> +(...,x)
- if ((!seq_copied)&&(seq_size>=1)&&
- (is_ex_exactly_of_type(last_expair.rest,numeric))&&
- (ex_to_numeric(last_expair.rest).is_zero())) {
- newseq=seq;
- seq_copied=true;
- it2=newseq.end()-1;
- }
- if (seq_copied&&(newseq.size()>=1)&&
- (is_ex_exactly_of_type((*it2).rest,numeric))&&
- (ex_to_numeric((*it2).rest).is_zero())) {
- newseq.pop_back();
- }
-
- // +() -> 0
- if ((!seq_copied)&&(seq_size==0)) {
- return exZERO();
- } else if (seq_copied&&(newseq.size()==0)) {
- return exZERO();
- }
-
- // +(x) -> x
- if ((!seq_copied)&&(seq_size==1)) {
- return recombine_pair_to_ex(*(seq.begin()));
- } else if (seq_copied&&(newseq.size()==1)) {
- return recombine_pair_to_ex(*(newseq.begin()));
- }
-
- if (!seq_copied) return this->hold();
-
- return (new add(newseq,1))->setflag(status_flags::dynallocated |
- status_flags::evaluated );
-}
-*/
-
+ switch (inf) {
+ case info_flags::polynomial:
+ case info_flags::integer_polynomial:
+ case info_flags::cinteger_polynomial:
+ case info_flags::rational_polynomial:
+ case info_flags::crational_polynomial:
+ case info_flags::rational_function: {
+ epvector::const_iterator i = seq.begin(), end = seq.end();
+ while (i != end) {
+ if (!(recombine_pair_to_ex(*i).info(inf)))
+ return false;
+ ++i;
+ }
+ return overall_coeff.info(inf);
+ }
+ case info_flags::algebraic: {
+ epvector::const_iterator i = seq.begin(), end = seq.end();
+ while (i != end) {
+ if ((recombine_pair_to_ex(*i).info(inf)))
+ return true;
+ ++i;
+ }
+ return false;
+ }
+ }
+ return inherited::info(inf);
+}
+
+int add::degree(const ex & s) const
+{
+ int deg = std::numeric_limits<int>::min();
+ if (!overall_coeff.is_zero())
+ deg = 0;
+
+ // Find maximum of degrees of individual terms
+ epvector::const_iterator i = seq.begin(), end = seq.end();
+ while (i != end) {
+ int cur_deg = i->rest.degree(s);
+ if (cur_deg > deg)
+ deg = cur_deg;
+ ++i;
+ }
+ return deg;
+}
+
+int add::ldegree(const ex & s) const
+{
+ int deg = std::numeric_limits<int>::max();
+ if (!overall_coeff.is_zero())
+ deg = 0;
+
+ // Find minimum of degrees of individual terms
+ epvector::const_iterator i = seq.begin(), end = seq.end();
+ while (i != end) {
+ int cur_deg = i->rest.ldegree(s);
+ if (cur_deg < deg)
+ deg = cur_deg;
+ ++i;
+ }
+ return deg;
+}
+
+ex add::coeff(const ex & s, int n) const
+{
+ std::auto_ptr<epvector> coeffseq(new epvector);
+ std::auto_ptr<epvector> coeffseq_cliff(new epvector);
+ char rl = clifford_max_label(s);
+ bool do_clifford = (rl != -1);
+ bool nonscalar = false;
+
+ // Calculate sum of coefficients in each term
+ epvector::const_iterator i = seq.begin(), end = seq.end();
+ while (i != end) {
+ ex restcoeff = i->rest.coeff(s, n);
+ if (!restcoeff.is_zero()) {
+ if (do_clifford) {
+ if (clifford_max_label(restcoeff) == -1) {
+ coeffseq_cliff->push_back(combine_ex_with_coeff_to_pair(ncmul(restcoeff, dirac_ONE(rl)), i->coeff));
+ } else {
+ coeffseq_cliff->push_back(combine_ex_with_coeff_to_pair(restcoeff, i->coeff));
+ nonscalar = true;
+ }
+ }
+ coeffseq->push_back(combine_ex_with_coeff_to_pair(restcoeff, i->coeff));
+ }
+ ++i;
+ }
+
+ return (new add(nonscalar ? coeffseq_cliff : coeffseq,
+ n==0 ? overall_coeff : _ex0))->setflag(status_flags::dynallocated);
+}
+
+/** Perform automatic term rewriting rules in this class. In the following
+ * x stands for a symbolic variables of type ex and c stands for such
+ * an expression that contain a plain number.
+ * - +(;c) -> c
+ * - +(x;0) -> x
+ *
+ * @param level cut-off in recursive evaluation */