@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
@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.
@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()}
@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()}
@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()}
@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()}
@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
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
{
}
// 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;
return *this;
}
+bool constant::is_polynomial(const ex & var) const
+{
+ return true;
+}
+
// protected
/** Implementation of ex::diff() for a constant always returns 0.
// 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;
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
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); }
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); }
#include "expairseq.h"
#include "lst.h"
+#include "add.h"
#include "mul.h"
#include "power.h"
#include "relational.h"
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
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;
return false;
}
+bool numeric::is_polynomial(const ex & var) const
+{
+ return true;
+}
+
int numeric::degree(const ex & s) const
{
return 0;
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;
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)))
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;
}
}
+bool symbol::is_polynomial(const ex & var) const
+{
+ return true;
+}
+
// protected
/** Implementation of ex::diff() for single differentiation of a symbol.
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;