Added .is_polynomial() method.
authorChris Dams <Chris.Dams@mi.infn.it>
Mon, 27 Mar 2006 19:13:21 +0000 (19:13 +0000)
committerChris Dams <Chris.Dams@mi.infn.it>
Mon, 27 Mar 2006 19:13:21 +0000 (19:13 +0000)
15 files changed:
doc/tutorial/ginac.texi
ginac/basic.cpp
ginac/basic.h
ginac/constant.cpp
ginac/constant.h
ginac/ex.cpp
ginac/ex.h
ginac/expairseq.cpp
ginac/expairseq.h
ginac/numeric.cpp
ginac/numeric.h
ginac/power.cpp
ginac/power.h
ginac/symbol.cpp
ginac/symbol.h

index 23956d7..93b00e6 100644 (file)
@@ -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
index f65e3f0..a3c727b 100644 (file)
@@ -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<basic>(var));
+}
+
 /** Return degree of highest power in object s. */
 int basic::degree(const ex & s) const
 {
index fc82522..6b117cc 100644 (file)
@@ -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;
index 86fb55b..5cfecc9 100644 (file)
@@ -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.
index 331ad20..9922637 100644 (file)
@@ -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;
index a5ede05..f183537 100644 (file)
@@ -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<lst>(vars)) {
+               const lst & varlst = ex_to<lst>(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 
index 697f3b4..c23336b 100644 (file)
@@ -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); }
 
index 458b440..5652d89 100644 (file)
@@ -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<add>(*this) && !is_exactly_a<mul>(*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
index acc2ce1..4cfc057 100644 (file)
@@ -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;
index b8170e7..278741f 100644 (file)
@@ -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;
index f0e3362..ff46063 100644 (file)
@@ -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;
index 6f6f178..95a01ac 100644 (file)
@@ -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<basic>(s)))
index 48ca5b5..c764524 100644 (file)
@@ -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;
index 6b37ee1..10b38a8 100644 (file)
@@ -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.
index 3b187d6..b7c17a8 100644 (file)
@@ -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;