From: Chris Dams Date: Mon, 27 Mar 2006 19:13:21 +0000 (+0000) Subject: Added .is_polynomial() method. X-Git-Tag: release_1-4-0~101 X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=commitdiff_plain;h=80ceed0c855ea06ff5acd9375ad2e0c5ca386373 Added .is_polynomial() method. --- diff --git a/doc/tutorial/ginac.texi b/doc/tutorial/ginac.texi index 23956d77..93b00e6f 100644 --- a/doc/tutorial/ginac.texi +++ b/doc/tutorial/ginac.texi @@ -905,7 +905,7 @@ int main() @node The Class Hierarchy, Symbols, Error handling, Basic Concepts @c node-name, next, previous, up -@section The Class Hierarchy +@section The class hierarchy GiNaC's class hierarchy consists of several classes representing mathematical objects, all of which (except for @code{ex} and some @@ -4172,7 +4172,7 @@ after @code{other}. @node Numerical Evaluation, Substituting Expressions, Information About Expressions, Methods and Functions @c node-name, next, previous, up -@section Numerical Evaluation +@section Numerical evaluation @cindex @code{evalf()} GiNaC keeps algebraic expressions, numbers and constants in their exact form. @@ -4612,7 +4612,7 @@ and not for locating @code{x+y} within @code{x+y+z}. @node Applying a Function on Subexpressions, Visitors and Tree Traversal, Pattern Matching and Advanced Substitutions, Methods and Functions @c node-name, next, previous, up -@section Applying a Function on Subexpressions +@section Applying a function on subexpressions @cindex tree traversal @cindex @code{map()} @@ -4757,7 +4757,7 @@ argument. You can not use functions like @samp{diff()}, @samp{op()}, @node Visitors and Tree Traversal, Polynomial Arithmetic, Applying a Function on Subexpressions, Methods and Functions @c node-name, next, previous, up -@section Visitors and Tree Traversal +@section Visitors and tree traversal @cindex tree traversal @cindex @code{visitor} (class) @cindex @code{accept()} @@ -4981,6 +4981,22 @@ lst gather_indices(const ex & e) @c node-name, next, previous, up @section Polynomial arithmetic +@subsection Testing whether an expression is a polynomial +@cindex @code{is_polynomial()} + +Testing whether an expression is a polynomial in one or more variables +can be done with the method +@example +bool ex::is_polynomial(const ex & vars) const; +@end example +In the case of more than +one variable, the variables are given as a list. + +@example +(x*y*sin(y)).is_polynomial(x) // Returns true. +(x*y*sin(y)).is_polynomial(lst(x,y)) // Returns false. +@end example + @subsection Expanding and collecting @cindex @code{expand()} @cindex @code{collect()} @@ -5987,7 +6003,7 @@ J.Vollinga, S.Weinzierl, hep-ph/0410259 @node Complex Conjugation, Solving Linear Systems of Equations, Multiple polylogarithms, Methods and Functions @c node-name, next, previous, up -@section Complex Conjugation +@section Complex conjugation @c @cindex @code{conjugate()} @@ -6021,7 +6037,7 @@ change this behavior, you have to supply a specialized conjugation method for yo @node Solving Linear Systems of Equations, Input/Output, Complex Conjugation, Methods and Functions @c node-name, next, previous, up -@section Solving Linear Systems of Equations +@section Solving linear systems of equations @cindex @code{lsolve()} The function @code{lsolve()} provides a convenient wrapper around some diff --git a/ginac/basic.cpp b/ginac/basic.cpp index f65e3f0c..a3c727be 100644 --- a/ginac/basic.cpp +++ b/ginac/basic.cpp @@ -325,6 +325,12 @@ ex basic::map(map_function & f) const return *this; } +/** Check whether this is a polynomial in the given variables. */ +bool basic::is_polynomial(const ex & var) const +{ + return !has(var) || is_equal(ex_to(var)); +} + /** Return degree of highest power in object s. */ int basic::degree(const ex & s) const { diff --git a/ginac/basic.h b/ginac/basic.h index fc825226..6b117cc9 100644 --- a/ginac/basic.h +++ b/ginac/basic.h @@ -180,6 +180,7 @@ public: } // degree/coeff + virtual bool is_polynomial(const ex & var) const; virtual int degree(const ex & s) const; virtual int ldegree(const ex & s) const; virtual ex coeff(const ex & s, int n = 1) const; diff --git a/ginac/constant.cpp b/ginac/constant.cpp index 86fb55b7..5cfecc96 100644 --- a/ginac/constant.cpp +++ b/ginac/constant.cpp @@ -146,6 +146,11 @@ ex constant::evalf(int level) const return *this; } +bool constant::is_polynomial(const ex & var) const +{ + return true; +} + // protected /** Implementation of ex::diff() for a constant always returns 0. diff --git a/ginac/constant.h b/ginac/constant.h index 331ad209..99226376 100644 --- a/ginac/constant.h +++ b/ginac/constant.h @@ -49,6 +49,7 @@ public: // functions overriding virtual functions from base classes public: ex evalf(int level = 0) const; + bool is_polynomial(const ex & var) const; protected: ex derivative(const symbol & s) const; bool is_equal_same_type(const basic & other) const; diff --git a/ginac/ex.cpp b/ginac/ex.cpp index a5ede054..f1835377 100644 --- a/ginac/ex.cpp +++ b/ginac/ex.cpp @@ -240,6 +240,20 @@ ex ex::rhs() const return bp->op(1); } +/** Check whether expression is a polynomial. */ +bool ex::is_polynomial(const ex & vars) const +{ + if (is_a(vars)) { + const lst & varlst = ex_to(vars); + for (lst::const_iterator i=varlst.begin(); i!=varlst.end(); ++i) + if (!bp->is_polynomial(*i)) + return false; + return true; + } + else + return bp->is_polynomial(vars); +} + // private /** Make this ex writable (if more than one ex handle the same basic) by diff --git a/ginac/ex.h b/ginac/ex.h index 697f3b4e..c23336ba 100644 --- a/ginac/ex.h +++ b/ginac/ex.h @@ -159,6 +159,7 @@ public: void traverse(visitor & v) const { traverse_preorder(v); } // degree/coeff + bool is_polynomial(const ex & vars) const; int degree(const ex & s) const { return bp->degree(s); } int ldegree(const ex & s) const { return bp->ldegree(s); } ex coeff(const ex & s, int n = 1) const { return bp->coeff(s, n); } @@ -690,6 +691,9 @@ inline bool has(const ex & thisex, const ex & pattern, unsigned options = 0) inline bool find(const ex & thisex, const ex & pattern, lst & found) { return thisex.find(pattern, found); } +inline bool is_polynomial(const ex & thisex, const ex & vars) +{ return thisex.is_polynomial(vars); } + inline int degree(const ex & thisex, const ex & s) { return thisex.degree(s); } diff --git a/ginac/expairseq.cpp b/ginac/expairseq.cpp index 458b440d..5652d89c 100644 --- a/ginac/expairseq.cpp +++ b/ginac/expairseq.cpp @@ -27,6 +27,7 @@ #include "expairseq.h" #include "lst.h" +#include "add.h" #include "mul.h" #include "power.h" #include "relational.h" @@ -347,6 +348,17 @@ ex expairseq::conjugate() const return result; } +bool expairseq::is_polynomial(const ex & var) const +{ + if (!is_exactly_a(*this) && !is_exactly_a(*this)) + return basic::is_polynomial(var); + for (epvector::const_iterator i=seq.begin(); i!=seq.end(); ++i) { + if (!(i->rest).is_polynomial(var)) + return false; + } + return true; +} + bool expairseq::match(const ex & pattern, lst & repl_lst) const { // This differs from basic::match() because we want "a+b+c+d" to diff --git a/ginac/expairseq.h b/ginac/expairseq.h index acc2ce1e..4cfc0579 100644 --- a/ginac/expairseq.h +++ b/ginac/expairseq.h @@ -86,6 +86,7 @@ public: bool match(const ex & pattern, lst & repl_lst) const; ex subs(const exmap & m, unsigned options = 0) const; ex conjugate() const; + bool is_polynomial(const ex & var) const; protected: bool is_equal_same_type(const basic & other) const; unsigned return_type() const; diff --git a/ginac/numeric.cpp b/ginac/numeric.cpp index b8170e71..278741f1 100644 --- a/ginac/numeric.cpp +++ b/ginac/numeric.cpp @@ -603,6 +603,11 @@ bool numeric::info(unsigned inf) const return false; } +bool numeric::is_polynomial(const ex & var) const +{ + return true; +} + int numeric::degree(const ex & s) const { return 0; diff --git a/ginac/numeric.h b/ginac/numeric.h index f0e3362f..ff460638 100644 --- a/ginac/numeric.h +++ b/ginac/numeric.h @@ -105,6 +105,7 @@ public: public: unsigned precedence() const {return 30;} bool info(unsigned inf) const; + bool is_polynomial(const ex & var) const; int degree(const ex & s) const; int ldegree(const ex & s) const; ex coeff(const ex & s, int n = 1) const; diff --git a/ginac/power.cpp b/ginac/power.cpp index 6f6f178d..95a01ace 100644 --- a/ginac/power.cpp +++ b/ginac/power.cpp @@ -258,6 +258,15 @@ ex power::map(map_function & f) const return *this; } +bool power::is_polynomial(const ex & var) const +{ + if (exponent.has(var)) + return false; + if (!exponent.info(info_flags::nonnegint)) + return false; + return basis.is_polynomial(var); +} + int power::degree(const ex & s) const { if (is_equal(ex_to(s))) diff --git a/ginac/power.h b/ginac/power.h index 48ca5b5d..c7645247 100644 --- a/ginac/power.h +++ b/ginac/power.h @@ -54,6 +54,7 @@ public: size_t nops() const; ex op(size_t i) const; ex map(map_function & f) const; + bool is_polynomial(const ex & var) const; int degree(const ex & s) const; int ldegree(const ex & s) const; ex coeff(const ex & s, int n = 1) const; diff --git a/ginac/symbol.cpp b/ginac/symbol.cpp index 6b37ee12..10b38a8e 100644 --- a/ginac/symbol.cpp +++ b/ginac/symbol.cpp @@ -226,6 +226,11 @@ ex symbol::conjugate() const } } +bool symbol::is_polynomial(const ex & var) const +{ + return true; +} + // protected /** Implementation of ex::diff() for single differentiation of a symbol. diff --git a/ginac/symbol.h b/ginac/symbol.h index 3b187d61..b7c17a80 100644 --- a/ginac/symbol.h +++ b/ginac/symbol.h @@ -75,6 +75,7 @@ public: unsigned return_type() const { return ret_type; } tinfo_t return_type_tinfo() const { return ret_type_tinfo; } ex conjugate() const; + bool is_polynomial(const ex & var) const; protected: ex derivative(const symbol & s) const; bool is_equal_same_type(const basic & other) const;