This file records noteworthy changes.
+1.0.5 (<date>)
+* (l)degree(s), coeff(s, n) and collect(s) were extended to accept expressions
+ of any class (except add/mul/ncmul/numeric) for "s". They should even work
+ if "s" is a "power" object, as long as the exponent is non-integer, but with
+ some limitations. For example, you can "collect(a*2^x+b*2^x, 2^x)" to get
+ "(a+b)*2^x", but "degree(2^(3*x), 2^x)" yields 0 instead of 3).
+
1.0.4 (24 January 2001)
* Speedup in expand().
* Faster Bernoulli numbers (Markus Nullmeier).
/** Return degree of highest power in object s. */
int basic::degree(const ex & s) const
{
- return 0;
+ return is_equal(ex_to<basic>(s)) ? 1 : 0;
}
/** Return degree of lowest power in object s. */
int basic::ldegree(const ex & s) const
{
- return 0;
+ return is_equal(ex_to<basic>(s)) ? 1 : 0;
}
/** Return coefficient of degree n in object s. */
ex basic::coeff(const ex & s, int n) const
{
- return n==0 ? *this : _ex0;
+ if (is_equal(ex_to<basic>(s)))
+ return n==1 ? _ex1 : _ex0;
+ else
+ return n==0 ? *this : _ex0;
}
/** Sort expanded expression in terms of powers of some object(s).
c.s << name;
}
-int constant::degree(const ex & s) const
-{
- return is_equal(ex_to<basic>(s)) ? 1 : 0;
-}
-
-int constant::ldegree(const ex & s) const
-{
- return is_equal(ex_to<basic>(s)) ? 1 : 0;
-}
-
-ex constant::coeff(const ex & s, int n) const
-{
- if (is_equal(ex_to<basic>(s)))
- return n==1 ? _ex1 : _ex0;
- else
- return n==0 ? *this : _ex0;
-}
-
ex constant::evalf(int level) const
{
if (ef!=0) {
// functions overriding virtual functions from base classes
public:
void print(const print_context & c, unsigned level = 0) const;
- int degree(const ex & s) const;
- int ldegree(const ex & s) const;
- ex coeff(const ex & s, int n = 1) const;
ex evalf(int level = 0) const;
protected:
ex derivative(const symbol & s) const;
public:
void print(const print_context & c, unsigned level = 0) const;
unsigned precedence(void) const {return 70;}
- int degree(const ex & s) const;
- int ldegree(const ex & s) const;
- ex coeff(const ex & s, int n = 1) const;
ex expand(unsigned options=0) const;
ex eval(int level=0) const;
ex evalf(int level=0) const;
return (options == 0) ? setflag(status_flags::expanded) : *this;
}
-int function::degree(const ex & s) const
-{
- return is_equal(ex_to<basic>(s)) ? 1 : 0;
-}
-
-int function::ldegree(const ex & s) const
-{
- return is_equal(ex_to<basic>(s)) ? 1 : 0;
-}
-
-ex function::coeff(const ex & s, int n) const
-{
- if (is_equal(ex_to<basic>(s)))
- return n==1 ? _ex1 : _ex0;
- else
- return n==0 ? ex(*this) : _ex0;
-}
-
ex function::eval(int level) const
{
GINAC_ASSERT(serial<registered_functions().size());
return ex_to<basic>(base).eval_indexed(*this);
}
-int indexed::degree(const ex & s) const
-{
- return is_equal(ex_to<basic>(s)) ? 1 : 0;
-}
-
-int indexed::ldegree(const ex & s) const
-{
- return is_equal(ex_to<basic>(s)) ? 1 : 0;
-}
-
-ex indexed::coeff(const ex & s, int n) const
-{
- if (is_equal(ex_to<basic>(s)))
- return n==1 ? _ex1 : _ex0;
- else
- return n==0 ? ex(*this) : _ex0;
-}
-
ex indexed::thisexprseq(const exvector & v) const
{
return indexed(ex_to<symmetry>(symtree), v);
void print(const print_context & c, unsigned level = 0) const;
bool info(unsigned inf) const;
ex eval(int level = 0) const;
- int degree(const ex & s) const;
- int ldegree(const ex & s) const;
- ex coeff(const ex & s, int n = 1) const;
exvector get_free_indices(void) const;
protected:
return false;
}
+int numeric::degree(const ex & s) const
+{
+ return 0;
+}
+
+int numeric::ldegree(const ex & s) const
+{
+ return 0;
+}
+
+ex numeric::coeff(const ex & s, int n) const
+{
+ return n==0 ? *this : _ex0;
+}
+
/** Disassemble real part and imaginary part to scan for the occurrence of a
* single number. Also handles the imaginary unit. It ignores the sign on
* both this and the argument, which may lead to what might appear as funny
void print(const print_context & c, unsigned level = 0) const;
unsigned precedence(void) const {return 30;}
bool info(unsigned inf) const;
+ int degree(const ex & s) const;
+ int ldegree(const ex & s) const;
+ ex coeff(const ex & s, int n = 1) const;
bool has(const ex &other) const;
ex eval(int level = 0) const;
ex evalf(int level = 0) const;
int power::degree(const ex & s) const
{
- if (is_ex_exactly_of_type(exponent, numeric) && ex_to<numeric>(exponent).is_integer()) {
+ if (is_equal(ex_to<basic>(s)))
+ return 1;
+ else if (is_ex_exactly_of_type(exponent, numeric) && ex_to<numeric>(exponent).is_integer()) {
if (basis.is_equal(s))
return ex_to<numeric>(exponent).to_int();
else
int power::ldegree(const ex & s) const
{
- if (is_ex_exactly_of_type(exponent, numeric) && ex_to<numeric>(exponent).is_integer()) {
+ if (is_equal(ex_to<basic>(s)))
+ return 1;
+ else if (is_ex_exactly_of_type(exponent, numeric) && ex_to<numeric>(exponent).is_integer()) {
if (basis.is_equal(s))
return ex_to<numeric>(exponent).to_int();
else
ex power::coeff(const ex & s, int n) const
{
- if (!basis.is_equal(s)) {
+ if (is_equal(ex_to<basic>(s)))
+ return n==1 ? _ex1 : _ex0;
+ else if (!basis.is_equal(s)) {
// basis not equal to s
if (n == 0)
return *this;
return inherited::info(inf);
}
-int symbol::degree(const ex & s) const
-{
- return is_equal(ex_to<basic>(s)) ? 1 : 0;
-}
-
-int symbol::ldegree(const ex & s) const
-{
- return is_equal(ex_to<basic>(s)) ? 1 : 0;
-}
-
-ex symbol::coeff(const ex & s, int n) const
-{
- if (is_equal(ex_to<basic>(s)))
- return n==1 ? _ex1 : _ex0;
- else
- return n==0 ? *this : _ex0;
-}
-
ex symbol::eval(int level) const
{
if (level == -max_recursion_level)
basic * duplicate() const;
void print(const print_context & c, unsigned level = 0) const;
bool info(unsigned inf) const;
- int degree(const ex & s) const;
- int ldegree(const ex & s) const;
- ex coeff(const ex & s, int n = 1) const;
ex eval(int level = 0) const;
ex evalf(int level = 0) const { return *this; } // overwrites basic::evalf() for performance reasons
ex series(const relational & s, int order, unsigned options = 0) const;