X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Fmul.cpp;h=2b404877c9840aa53a071e712aa222e51680533a;hp=27add930cf56863ae7d635d3031e4dc2b1d7ea9f;hb=e100f94d92d574ea89a817eca8c58c5eb3418821;hpb=0c2f0f4c6d4118e817c5b9a14a9d0f3ada82e9fe diff --git a/ginac/mul.cpp b/ginac/mul.cpp index 27add930..2b404877 100644 --- a/ginac/mul.cpp +++ b/ginac/mul.cpp @@ -3,7 +3,7 @@ * Implementation of GiNaC's products of expressions. */ /* - * GiNaC Copyright (C) 1999-2011 Johannes Gutenberg University Mainz, Germany + * GiNaC Copyright (C) 1999-2015 Johannes Gutenberg University Mainz, Germany * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -283,10 +283,6 @@ bool mul::info(unsigned inf) const case info_flags::integer: case info_flags::crational: case info_flags::cinteger: - case info_flags::positive: - case info_flags::nonnegative: - case info_flags::posint: - case info_flags::nonnegint: case info_flags::even: case info_flags::crational_polynomial: case info_flags::rational_function: { @@ -309,39 +305,98 @@ bool mul::info(unsigned inf) const } return false; } + case info_flags::positive: case info_flags::negative: { - bool neg = false; + if ((inf==info_flags::positive) && (flags & status_flags::is_positive)) + return true; + else if ((inf==info_flags::negative) && (flags & status_flags::is_negative)) + return true; + if (flags & status_flags::purely_indefinite) + return false; + + bool pos = true; epvector::const_iterator i = seq.begin(), end = seq.end(); while (i != end) { const ex& factor = recombine_pair_to_ex(*i++); if (factor.info(info_flags::positive)) continue; else if (factor.info(info_flags::negative)) - neg = !neg; + pos = !pos; else return false; } if (overall_coeff.info(info_flags::negative)) - neg = !neg; - return neg; + pos = !pos; + setflag(pos ? status_flags::is_positive : status_flags::is_negative); + return (inf == info_flags::positive? pos : !pos); } + case info_flags::nonnegative: { + if (flags & status_flags::is_positive) + return true; + bool pos = true; + epvector::const_iterator i = seq.begin(), end = seq.end(); + while (i != end) { + const ex& factor = recombine_pair_to_ex(*i++); + if (factor.info(info_flags::nonnegative) || factor.info(info_flags::positive)) + continue; + else if (factor.info(info_flags::negative)) + pos = !pos; + else + return false; + } + return (overall_coeff.info(info_flags::negative)? !pos : pos); + } + case info_flags::posint: case info_flags::negint: { - bool neg = false; + bool pos = true; epvector::const_iterator i = seq.begin(), end = seq.end(); while (i != end) { const ex& factor = recombine_pair_to_ex(*i++); if (factor.info(info_flags::posint)) continue; else if (factor.info(info_flags::negint)) - neg = !neg; + pos = !pos; else return false; } if (overall_coeff.info(info_flags::negint)) - neg = !neg; + pos = !pos; else if (!overall_coeff.info(info_flags::posint)) return false; - return neg; + return (inf ==info_flags::posint? pos : !pos); + } + case info_flags::nonnegint: { + bool pos = true; + epvector::const_iterator i = seq.begin(), end = seq.end(); + while (i != end) { + const ex& factor = recombine_pair_to_ex(*i++); + if (factor.info(info_flags::nonnegint) || factor.info(info_flags::posint)) + continue; + else if (factor.info(info_flags::negint)) + pos = !pos; + else + return false; + } + if (overall_coeff.info(info_flags::negint)) + pos = !pos; + else if (!overall_coeff.info(info_flags::posint)) + return false; + return pos; + } + case info_flags::indefinite: { + if (flags & status_flags::purely_indefinite) + return true; + if (flags & (status_flags::is_positive | status_flags::is_negative)) + return false; + epvector::const_iterator i = seq.begin(), end = seq.end(); + while (i != end) { + const ex& term = recombine_pair_to_ex(*i); + if (term.info(info_flags::positive) || term.info(info_flags::negative)) + return false; + ++i; + } + setflag(status_flags::purely_indefinite); + return true; } } return inherited::info(inf); @@ -351,7 +406,7 @@ bool mul::is_polynomial(const ex & var) const { for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i) { if (!i->rest.is_polynomial(var) || - (i->rest.has(var) && !i->coeff.info(info_flags::integer))) { + (i->rest.has(var) && !i->coeff.info(info_flags::nonnegint))) { return false; } } @@ -448,24 +503,6 @@ ex mul::eval(int level) const setflag(status_flags::dynallocated); } -#ifdef DO_GINAC_ASSERT - epvector::const_iterator i = seq.begin(), end = seq.end(); - while (i != end) { - GINAC_ASSERT((!is_exactly_a(i->rest)) || - (!(ex_to(i->coeff).is_integer()))); - GINAC_ASSERT(!(i->is_canonical_numeric())); - if (is_exactly_a(recombine_pair_to_ex(*i))) - print(print_tree(std::cerr)); - GINAC_ASSERT(!is_exactly_a(recombine_pair_to_ex(*i))); - /* for paranoia */ - expair p = split_ex_to_pair(recombine_pair_to_ex(*i)); - GINAC_ASSERT(p.rest.is_equal(i->rest)); - GINAC_ASSERT(p.coeff.is_equal(i->coeff)); - /* end paranoia */ - ++i; - } -#endif // def DO_GINAC_ASSERT - if (flags & status_flags::evaluated) { GINAC_ASSERT(seq.size()>0); GINAC_ASSERT(seq.size()>1 || !overall_coeff.is_equal(_ex1)); @@ -500,7 +537,7 @@ ex mul::eval(int level) const )->setflag(status_flags::dynallocated | status_flags::evaluated); } else if ((seq_size >= 2) && (! (flags & status_flags::expanded))) { // Strip the content and the unit part from each term. Thus - // things like (-x+a)*(3*x-3*a) automagically turn into - 3*(x-a)2 + // things like (-x+a)*(3*x-3*a) automagically turn into - 3*(x-a)^2 epvector::const_iterator last = seq.end(); epvector::const_iterator i = seq.begin(); @@ -552,8 +589,7 @@ ex mul::eval(int level) const primitive->setflag(status_flags::dynallocated); primitive->clearflag(status_flags::hash_calculated); primitive->overall_coeff = ex_to(primitive->overall_coeff).div_dyn(c); - for (epvector::iterator ai = primitive->seq.begin(); - ai != primitive->seq.end(); ++ai) + for (epvector::iterator ai = primitive->seq.begin(); ai != primitive->seq.end(); ++ai) ai->coeff = ex_to(ai->coeff).div_dyn(c); s->push_back(expair(*primitive, _ex1)); @@ -728,7 +764,7 @@ bool tryfactsubs(const ex & origfactor, const ex & patternfactor, int & nummatch return true; } -/** Checks wheter e matches to the pattern pat and the (possibly to be updated) +/** Checks whether e matches to the pattern pat and the (possibly to be updated) * list of replacements repls. This matching is in the sense of algebraic * substitutions. Matching starts with pat.op(factor) of the pattern because * the factors before this one have already been matched. The (possibly @@ -737,8 +773,8 @@ bool tryfactsubs(const ex & origfactor, const ex & patternfactor, int & nummatch * is true for factors that have been matched by the current match. */ bool algebraic_match_mul_with_mul(const mul &e, const ex &pat, exmap& repls, - int factor, int &nummatches, const std::vector &subsed, - std::vector &matched) + int factor, int &nummatches, const std::vector &subsed, + std::vector &matched) { GINAC_ASSERT(subsed.size() == e.nops()); GINAC_ASSERT(matched.size() == e.nops()); @@ -769,7 +805,7 @@ bool algebraic_match_mul_with_mul(const mul &e, const ex &pat, exmap& repls, bool mul::has(const ex & pattern, unsigned options) const { - if(!(options&has_options::algebraic)) + if(!(options & has_options::algebraic)) return basic::has(pattern,options); if(is_a(pattern)) { exmap repls; @@ -936,7 +972,7 @@ unsigned mul::return_type() const // all factors checked return all_commutative ? return_types::commutative : return_types::noncommutative; } - + return_type_t mul::return_type_tinfo() const { if (seq.empty()) @@ -972,7 +1008,7 @@ expair mul::split_ex_to_pair(const ex & e) const } return expair(e,_ex1); } - + expair mul::combine_ex_with_coeff_to_pair(const ex & e, const ex & c) const { @@ -985,7 +1021,7 @@ expair mul::combine_ex_with_coeff_to_pair(const ex & e, return split_ex_to_pair(power(e,c)); } - + expair mul::combine_pair_with_coeff_to_pair(const expair & p, const ex & c) const { @@ -998,7 +1034,7 @@ expair mul::combine_pair_with_coeff_to_pair(const expair & p, return split_ex_to_pair(power(recombine_pair_to_ex(p),c)); } - + ex mul::recombine_pair_to_ex(const expair & p) const { if (ex_to(p.coeff).is_equal(*_num1_p)) @@ -1010,22 +1046,22 @@ ex mul::recombine_pair_to_ex(const expair & p) const bool mul::expair_needs_further_processing(epp it) { if (is_exactly_a(it->rest) && - ex_to(it->coeff).is_integer()) { + ex_to(it->coeff).is_integer()) { // combined pair is product with integer power -> expand it *it = split_ex_to_pair(recombine_pair_to_ex(*it)); return true; } if (is_exactly_a(it->rest)) { + if (it->coeff.is_equal(_ex1)) { + // pair has coeff 1 and must be moved to the end + return true; + } expair ep = split_ex_to_pair(recombine_pair_to_ex(*it)); if (!ep.is_equal(*it)) { // combined pair is a numeric power which can be simplified *it = ep; return true; } - if (it->coeff.is_equal(_ex1)) { - // combined pair has coeff 1 and must be moved to the end - return true; - } } return false; } @@ -1257,7 +1293,7 @@ ex mul::expand(unsigned options) const /** Member-wise expand the expairs representing this sequence. This must be * overridden from expairseq::expandchildren() and done iteratively in order - * to allow for early cancallations and thus safe memory. + * to allow for early cancellations and thus safe memory. * * @see mul::expand() * @return pointer to epvector containing expanded representation or zero