This file records noteworthy changes.
+0.8.1 (<date>)
+* degree(), ldegree(), coeff(), lcoeff(), tcoeff() and collect() can now
+ be used with constants and indexed expressions as well, so you can use
+ it to collect by powers of Pi or find the coefficient of gamma~0.
+ Limitations:
+ - it only works with symbols, constants and indexed expressions;
+ trying to find the coefficient of, e.g., "x^2" or "x+y" won't work
+ - it does not know about dummy index summations; the coefficient of
+ gamma~0 in p.mu*gamma~mu should be p.0 but is returned as 0
+ - using the functions on elements of noncommutative products might
+ return wrong or surprising results
+* Added preliminary (re)implementations of color and clifford classes.
+* simplify_indexed(): contraction of symmetric and antisymmetric tensors
+ is zero.
+* Some bugfixes (indexed objects, archive writing).
+
0.8.0 (24 March 2001)
* Complete revamp of indexed objects. Instead of multiple classes for
indexed things and their indices there is now only one "indexed" class
@code{collect()} accomplishes this task:
@example
-ex ex::collect(const symbol & s);
+ex ex::collect(const ex & s);
@end example
Note that the original polynomial needs to be in expanded form in order
methods
@example
-int ex::degree(const symbol & s);
-int ex::ldegree(const symbol & s);
+int ex::degree(const ex & s);
+int ex::ldegree(const ex & s);
@end example
which also work reliably on non-expanded input polynomials (they even work
a coefficient with a certain power from an expanded polynomial you use
@example
-ex ex::coeff(const symbol & s, int n);
+ex ex::coeff(const ex & s, int n);
@end example
You can also obtain the leading and trailing coefficients with the methods
@example
-ex ex::lcoeff(const symbol & s);
-ex ex::tcoeff(const symbol & s);
+ex ex::lcoeff(const ex & s);
+ex ex::tcoeff(const ex & s);
@end example
which are equivalent to @code{coeff(s, degree(s))} and @code{coeff(s, ldegree(s))},
return inherited::info(inf);
}
-int add::degree(const symbol & s) const
+int add::degree(const ex & s) const
{
int deg = INT_MIN;
if (!overall_coeff.is_equal(_ex0()))
return deg;
}
-int add::ldegree(const symbol & s) const
+int add::ldegree(const ex & s) const
{
int deg = INT_MAX;
if (!overall_coeff.is_equal(_ex0()))
return deg;
}
-ex add::coeff(const symbol & s, int n) const
+ex add::coeff(const ex & s, int n) const
{
epvector coeffseq;
coeffseq.reserve(seq.size());
void printraw(std::ostream & os) const;
void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence=0) const;
bool info(unsigned inf) const;
- int degree(const symbol & s) const;
- int ldegree(const symbol & s) const;
- ex coeff(const symbol & s, int n=1) 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 series(const relational & r, int order, unsigned options = 0) const;
ex normal(lst &sym_lst, lst &repl_lst, int level=0) const;
}
/** Return degree of highest power in symbol s. */
-int basic::degree(const symbol & s) const
+int basic::degree(const ex & s) const
{
return 0;
}
/** Return degree of lowest power in symbol s. */
-int basic::ldegree(const symbol & s) const
+int basic::ldegree(const ex & s) const
{
return 0;
}
/** Return coefficient of degree n in symbol s. */
-ex basic::coeff(const symbol & s, int n) const
+ex basic::coeff(const ex & s, int n) const
{
return n==0 ? *this : _ex0();
}
/** Sort expression in terms of powers of some symbol.
* @param s symbol to sort in. */
-ex basic::collect(const symbol & s) const
+ex basic::collect(const ex & s) const
{
ex x;
for (int n=this->ldegree(s); n<=this->degree(s); n++)
virtual ex operator[](const ex & index) const;
virtual ex operator[](int i) const;
virtual bool has(const ex & other) const;
- virtual int degree(const symbol & s) const;
- virtual int ldegree(const symbol & s) const;
- virtual ex coeff(const symbol & s, int n = 1) const;
- virtual ex collect(const symbol & s) 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;
+ virtual ex collect(const ex & s) const;
virtual ex eval(int level = 0) const;
virtual ex evalf(int level = 0) const;
virtual ex series(const relational & r, int order, unsigned options = 0) const;
os << name;
}
+int constant::degree(const ex & s) const
+{
+ return is_equal(*s.bp) ? 1 : 0;
+}
+
+int constant::ldegree(const ex & s) const
+{
+ return is_equal(*s.bp) ? 1 : 0;
+}
+
+ex constant::coeff(const ex & s, int n) const
+{
+ if (is_equal(*s.bp))
+ return n==1 ? _ex1() : _ex0();
+ else
+ return n==0 ? *this : _ex0();
+}
+
ex constant::evalf(int level) const
{
if (ef!=0) {
void printraw(std::ostream & os) const;
void printtree(std::ostream & os, unsigned indent) const;
void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence = 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;
return bp->has(other);
}
-int ex::degree(const symbol & s) const
+int ex::degree(const ex & s) const
{
GINAC_ASSERT(bp!=0);
return bp->degree(s);
}
-int ex::ldegree(const symbol & s) const
+int ex::ldegree(const ex & s) const
{
GINAC_ASSERT(bp!=0);
return bp->ldegree(s);
}
-ex ex::coeff(const symbol & s, int n) const
+ex ex::coeff(const ex & s, int n) const
{
GINAC_ASSERT(bp!=0);
return bp->coeff(s,n);
}
-ex ex::collect(const symbol & s) const
+ex ex::collect(const ex & s) const
{
GINAC_ASSERT(bp!=0);
return bp->collect(s);
unsigned nops() const;
ex expand(unsigned options=0) const;
bool has(const ex & other) const;
- int degree(const symbol & s) const;
- int ldegree(const symbol & s) const;
- ex coeff(const symbol & s, int n=1) const;
- ex lcoeff(const symbol & s) const { return coeff(s, degree(s)); }
- ex tcoeff(const symbol & s) const { return coeff(s, ldegree(s)); }
+ int degree(const ex & s) const;
+ int ldegree(const ex & s) const;
+ ex coeff(const ex & s, int n=1) const;
+ ex lcoeff(const ex & s) const { return coeff(s, degree(s)); }
+ ex tcoeff(const ex & s) const { return coeff(s, ldegree(s)); }
ex numer(void) const;
ex denom(void) const;
ex unit(const symbol &x) const;
ex to_rational(lst &repl_lst) const;
ex smod(const numeric &xi) const;
numeric max_coefficient(void) const;
- ex collect(const symbol & s) const;
+ ex collect(const ex & s) const;
ex eval(int level = 0) const;
ex evalf(int level = 0) const;
ex diff(const symbol & s, unsigned nth = 1) const;
inline bool has(const ex & thisex, const ex & other)
{ return thisex.has(other); }
-inline int degree(const ex & thisex, const symbol & s)
+inline int degree(const ex & thisex, const ex & s)
{ return thisex.degree(s); }
-inline int ldegree(const ex & thisex, const symbol & s)
+inline int ldegree(const ex & thisex, const ex & s)
{ return thisex.ldegree(s); }
-inline ex coeff(const ex & thisex, const symbol & s, int n=1)
+inline ex coeff(const ex & thisex, const ex & s, int n=1)
{ return thisex.coeff(s, n); }
inline ex numer(const ex & thisex)
inline ex to_rational(const ex & thisex, lst & repl_lst)
{ return thisex.to_rational(repl_lst); }
-inline ex collect(const ex & thisex, const symbol & s)
+inline ex collect(const ex & thisex, const ex & s)
{ return thisex.collect(s); }
inline ex eval(const ex & thisex, int level = 0)
return base.bp->eval_indexed(*this);
}
+int indexed::degree(const ex & s) const
+{
+ return is_equal(*s.bp) ? 1 : 0;
+}
+
+int indexed::ldegree(const ex & s) const
+{
+ return is_equal(*s.bp) ? 1 : 0;
+}
+
+ex indexed::coeff(const ex & s, int n) const
+{
+ if (is_equal(*s.bp))
+ return n==1 ? _ex1() : _ex0();
+ else
+ return n==0 ? ex(*this) : _ex0();
+}
+
ex indexed::thisexprseq(const exvector & v) const
{
return indexed(symmetry, v);
void print(std::ostream & os, unsigned upper_precedence=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 inherited::info(inf);
}
-int mul::degree(const symbol & s) const
+int mul::degree(const ex & s) const
{
int deg_sum = 0;
for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
return deg_sum;
}
-int mul::ldegree(const symbol & s) const
+int mul::ldegree(const ex & s) const
{
int deg_sum = 0;
for (epvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
return deg_sum;
}
-ex mul::coeff(const symbol & s, int n) const
+ex mul::coeff(const ex & s, int n) const
{
exvector coeffseq;
coeffseq.reserve(seq.size()+1);
void printraw(std::ostream & os) const;
void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence) const;
bool info(unsigned inf) const;
- int degree(const symbol & s) const;
- int ldegree(const symbol & s) const;
- ex coeff(const symbol & s, int n = 1) 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;
ex series(const relational & s, int order, unsigned options = 0) const;
status_flags::expanded);
}
-int ncmul::degree(const symbol & s) const
+int ncmul::degree(const ex & s) const
{
int deg_sum=0;
for (exvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
return deg_sum;
}
-int ncmul::ldegree(const symbol & s) const
+int ncmul::ldegree(const ex & s) const
{
int deg_sum=0;
for (exvector::const_iterator cit=seq.begin(); cit!=seq.end(); ++cit) {
return deg_sum;
}
-ex ncmul::coeff(const symbol & s, int n) const
+ex ncmul::coeff(const ex & s, int n) const
{
exvector coeffseq;
coeffseq.reserve(seq.size());
void printraw(std::ostream & os) const;
void printcsrc(std::ostream & os, unsigned type, unsigned upper_precedence = 0) const;
bool info(unsigned inf) const;
- int degree(const symbol & s) const;
- int ldegree(const symbol & s) const;
+ int degree(const ex & s) const;
+ int ldegree(const ex & s) const;
ex expand(unsigned options=0) const;
- ex coeff(const symbol & s, int n=1) const;
+ ex coeff(const ex & s, int n=1) const;
ex eval(int level=0) const;
ex subs(const lst & ls, const lst & lr) const;
exvector get_free_indices(void) const;
return i==0 ? basis : exponent;
}
-int power::degree(const symbol & s) const
+int power::degree(const ex & s) const
{
if (is_exactly_of_type(*exponent.bp,numeric)) {
- if ((*basis.bp).compare(s)==0) {
+ if (basis.is_equal(s)) {
if (ex_to_numeric(exponent).is_integer())
return ex_to_numeric(exponent).to_int();
else
return 0;
}
-int power::ldegree(const symbol & s) const
+int power::ldegree(const ex & s) const
{
if (is_exactly_of_type(*exponent.bp,numeric)) {
- if ((*basis.bp).compare(s)==0) {
+ if (basis.is_equal(s)) {
if (ex_to_numeric(exponent).is_integer())
return ex_to_numeric(exponent).to_int();
else
return 0;
}
-ex power::coeff(const symbol & s, int n) const
+ex power::coeff(const ex & s, int n) const
{
- if ((*basis.bp).compare(s)!=0) {
+ if (!basis.is_equal(s)) {
// basis not equal to s
if (n == 0)
return *this;
bool info(unsigned inf) const;
unsigned nops() const;
ex & let_op(int i);
- int degree(const symbol & s) const;
- int ldegree(const symbol & s) const;
- ex coeff(const symbol & s, int n = 1) 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;
ex series(const relational & s, int order, unsigned options = 0) const;
/** Return degree of highest power of the series. This is usually the exponent
* of the Order term. If s is not the expansion variable of the series, the
* series is examined termwise. */
-int pseries::degree(const symbol &s) const
+int pseries::degree(const ex &s) const
{
if (var.is_equal(s)) {
// Return last exponent
* series is examined termwise. If s is the expansion variable but the
* expansion point is not zero the series is not expanded to find the degree.
* I.e.: (1-x) + (1-x)^2 + Order((1-x)^3) has ldegree(x) 1, not 0. */
-int pseries::ldegree(const symbol &s) const
+int pseries::ldegree(const ex &s) const
{
if (var.is_equal(s)) {
// Return first exponent
* If s is not the expansion variable, an attempt is made to convert the
* series to a polynomial and return the corresponding coefficient from
* there. */
-ex pseries::coeff(const symbol &s, int n) const
+ex pseries::coeff(const ex &s, int n) const
{
if (var.is_equal(s)) {
if (seq.size() == 0)
}
/** Does nothing. */
-ex pseries::collect(const symbol &s) const
+ex pseries::collect(const ex &s) const
{
return *this;
}
numeric fac(1);
ex deriv = *this;
ex coeff = deriv.subs(r);
- const symbol *s = static_cast<symbol *>(r.lhs().bp);
+ const symbol &s = static_cast<symbol &>(*r.lhs().bp);
if (!coeff.is_zero())
seq.push_back(expair(coeff, numeric(0)));
int n;
for (n=1; n<order; ++n) {
fac = fac.mul(numeric(n));
- deriv = deriv.diff(*s).expand();
+ deriv = deriv.diff(s).expand();
if (deriv.is_zero()) {
// Series terminates
return pseries(r, seq);
}
// Higher-order terms, if present
- deriv = deriv.diff(*s);
+ deriv = deriv.diff(s);
if (!deriv.expand().is_zero())
seq.push_back(expair(Order(_ex1()), numeric(n)));
return pseries(r, seq);
epvector seq;
const ex point = r.rhs();
GINAC_ASSERT(is_ex_exactly_of_type(r.lhs(),symbol));
- const symbol *s = static_cast<symbol *>(r.lhs().bp);
+ ex s = r.lhs();
- if (this->is_equal(*s)) {
+ if (this->is_equal(*s.bp)) {
if (order > 0 && !point.is_zero())
seq.push_back(expair(point, _ex0()));
if (order > 1)
// Series multiplication
epvector new_seq;
- const symbol *s = static_cast<symbol *>(var.bp);
- int a_max = degree(*s);
- int b_max = other.degree(*s);
- int a_min = ldegree(*s);
- int b_min = other.ldegree(*s);
+ int a_max = degree(var);
+ int b_max = other.degree(var);
+ int a_min = ldegree(var);
+ int b_min = other.ldegree(var);
int cdeg_min = a_min + b_min;
int cdeg_max = a_max + b_max;
int higher_order_a = INT_MAX;
int higher_order_b = INT_MAX;
- if (is_order_function(coeff(*s, a_max)))
+ if (is_order_function(coeff(var, a_max)))
higher_order_a = a_max + b_min;
- if (is_order_function(other.coeff(*s, b_max)))
+ if (is_order_function(other.coeff(var, b_max)))
higher_order_b = b_max + a_min;
int higher_order_c = std::min(higher_order_a, higher_order_b);
if (cdeg_max >= higher_order_c)
ex co = _ex0();
// c(i)=a(0)b(i)+...+a(i)b(0)
for (int i=a_min; cdeg-i>=b_min; ++i) {
- ex a_coeff = coeff(*s, i);
- ex b_coeff = other.coeff(*s, cdeg-i);
+ ex a_coeff = coeff(var, i);
+ ex b_coeff = other.coeff(var, cdeg-i);
if (!is_order_function(a_coeff) && !is_order_function(b_coeff))
co += a_coeff * b_coeff;
}
}
if (higher_order_c < INT_MAX)
new_seq.push_back(expair(Order(_ex1()), numeric(higher_order_c)));
- return pseries(relational(var,point), new_seq);
+ return pseries(relational(var, point), new_seq);
}
return *this;
}
- const symbol *s = static_cast<symbol *>(var.bp);
- int ldeg = ldegree(*s);
+ int ldeg = ldegree(var);
// Compute coefficients of the powered series
exvector co;
co.reserve(deg);
- co.push_back(power(coeff(*s, ldeg), p));
+ co.push_back(power(coeff(var, ldeg), p));
bool all_sums_zero = true;
for (int i=1; i<deg; ++i) {
ex sum = _ex0();
for (int j=1; j<=i; ++j) {
- ex c = coeff(*s, j + ldeg);
+ ex c = coeff(var, j + ldeg);
if (is_order_function(c)) {
co.push_back(Order(_ex1()));
break;
}
if (!sum.is_zero())
all_sums_zero = false;
- co.push_back(sum / coeff(*s, ldeg) / numeric(i));
+ co.push_back(sum / coeff(var, ldeg) / numeric(i));
}
// Construct new series (of non-zero coefficients)
{
const ex p = r.rhs();
GINAC_ASSERT(is_ex_exactly_of_type(r.lhs(),symbol));
- const symbol *s = static_cast<symbol *>(r.lhs().bp);
+ const symbol &s = static_cast<symbol &>(*r.lhs().bp);
- if (var.is_equal(*s) && point.is_equal(p)) {
- if (order > degree(*s))
+ if (var.is_equal(s) && point.is_equal(p)) {
+ if (order > degree(s))
return *this;
else {
epvector new_seq;
unsigned nops(void) const;
ex op(int i) const;
ex &let_op(int i);
- int degree(const symbol &s) const;
- int ldegree(const symbol &s) const;
- ex coeff(const symbol &s, int n = 1) const;
- ex collect(const symbol &s) const;
+ int degree(const ex &s) const;
+ int ldegree(const ex &s) const;
+ ex coeff(const ex &s, int n = 1) const;
+ ex collect(const ex &s) const;
ex eval(int level=0) const;
ex evalf(int level=0) const;
ex series(const relational & r, int order, unsigned options = 0) const;
return false;
}
-int symbol::degree(const symbol & s) const
+int symbol::degree(const ex & s) const
{
- return compare_same_type(s)==0 ? 1 : 0;
+ return is_equal(*s.bp) ? 1 : 0;
}
-int symbol::ldegree(const symbol & s) const
+int symbol::ldegree(const ex & s) const
{
- return compare_same_type(s)==0 ? 1 : 0;
+ return is_equal(*s.bp) ? 1 : 0;
}
-ex symbol::coeff(const symbol & s, int n) const
+ex symbol::coeff(const ex & s, int n) const
{
- if (compare_same_type(s)==0)
+ if (is_equal(*s.bp))
return n==1 ? _ex1() : _ex0();
else
return n==0 ? *this : _ex0();
bool info(unsigned inf) const;
ex expand(unsigned options = 0) const;
bool has(const ex & other) const;
- int degree(const symbol & s) const;
- int ldegree(const symbol & s) const;
- ex coeff(const symbol & s, int n = 1) 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 series(const relational & s, int order, unsigned options = 0) const;
ex normal(lst &sym_lst, lst &repl_lst, int level = 0) const;
inline void unassign(symbol & symarg)
{ symarg.unassign(); }
-inline int degree(const symbol & a, const symbol & s)
+inline int degree(const symbol & a, const ex & s)
{ return a.degree(s); }
-inline int ldegree(const symbol & a, const symbol & s)
+inline int ldegree(const symbol & a, const ex & s)
{ return a.ldegree(s); }
} // namespace GiNaC