#include "symbol.h"
#include "lst.h"
#include "ncmul.h"
-#include "idx.h"
-#include "indexed.h"
-#include "tensor.h"
-#include "function.h"
#include "archive.h"
#include "utils.h"
#include "debugmsg.h"
return false;
}
-/** Substitute a set of symbols by arbitrary expressions. The ex returned
+/** Substitute a set of objects by arbitrary expressions. The ex returned
* will already be evaluated. */
ex basic::subs(const lst & ls, const lst & lr) const
{
+ GINAC_ASSERT(ls.nops() == lr.nops());
+
+ for (unsigned i=0; i<ls.nops(); i++) {
+ if (is_equal(*ls.op(i).bp))
+ return lr.op(i);
+ }
+
return *this;
}
// public
-/** Substitute objects (symbols, indices, tensors, functions, indexed) in
- * expression and return the result as a new expression. There are two
- * valid types of replacement arguments: 1) a relational like object==ex
- * and 2) a list of relationals lst(object1==ex1,object2==ex2,...), which
- * is converted to subs(lst(object1,object2,...),lst(ex1,ex2,...)). */
+/** Substitute objects in an expression (syntactic substitution) and return
+ * the result as a new expression. There are two valid types of
+ * replacement arguments: 1) a relational like object==ex and 2) a list of
+ * relationals lst(object1==ex1,object2==ex2,...), which is converted to
+ * subs(lst(object1,object2,...),lst(ex1,ex2,...)). */
ex basic::subs(const ex & e) const
{
if (e.info(info_flags::relation_equal)) {
lst ls;
lst lr;
for (unsigned i=0; i<e.nops(); i++) {
- if (!e.op(i).info(info_flags::relation_equal)) {
+ ex r = e.op(i);
+ if (!r.info(info_flags::relation_equal)) {
throw(std::invalid_argument("basic::subs(ex): argument must be a list or equations"));
}
- ex s = e.op(i).op(0);
- ex r = e.op(i).op(1);
- if (!is_ex_of_type(s, symbol) && !is_ex_of_type(s, idx) &&
- !is_ex_of_type(s, tensor) && !is_ex_of_type(s, function) &&
- !is_ex_of_type(s, indexed)) {
- throw(std::invalid_argument("basic::subs(ex): lhs must be a symbol, idx, tensor, function or indexed"));
- }
- ls.append(s);
- lr.append(r);
+ ls.append(r.op(0));
+ lr.append(r.op(1));
}
- return subs(ls,lr);
+ return subs(ls, lr);
}
/** Compare objects to establish canonical ordering.
ex ${CONTAINER}::subs(const lst & ls, const lst & lr) const
{
${STLT} * vp=subschildren(ls,lr);
- if (vp==0) {
- return *this;
- }
+ if (vp==0)
+ return inherited::subs(ls, lr);
+
return this${CONTAINER}(vp);
}
{
epvector *vp = subschildren(ls,lr);
if (vp==0)
- return *this;
+ return inherited::subs(ls, lr);
return thisexpairseq(vp,overall_coeff);
}
ex evalf(int level=0) const;
unsigned calchash(void) const;
ex series(const relational & r, int order, unsigned options = 0) const;
- ex subs(const lst & ls, const lst & lr) const;
ex thisexprseq(const exvector & v) const;
ex thisexprseq(exvector * vp) const;
protected:
throw(std::logic_error("function::series(): invalid nparams"));
}
-ex function::subs(const lst & ls, const lst & lr) const
-{
- GINAC_ASSERT(ls.nops() == lr.nops());
-
- for (unsigned i=0; i<ls.nops(); i++) {
- if (is_ex_of_type(ls.op(i), function) &&
- compare_same_type(ex_to_function(ls.op(i)))==0)
- return lr.op(i);
- }
-
- return inherited::subs(ls, lr);
-}
-
// protected
return n==0 ? ex(*this) : _ex0();
}
-ex indexed::subs(const lst & ls, const lst & lr) const
-{
- GINAC_ASSERT(ls.nops() == lr.nops());
-
- for (unsigned i=0; i<ls.nops(); i++) {
- if (is_ex_of_type(ls.op(i), indexed) &&
- compare_same_type(ex_to_indexed(ls.op(i)))==0)
- return lr.op(i);
- }
-
- return inherited::subs(ls, lr);
-}
-
ex indexed::thisexprseq(const exvector & v) const
{
return indexed(symmetry, v);
int degree(const ex & s) const;
int ldegree(const ex & s) const;
ex coeff(const ex & s, int n = 1) const;
- ex subs(const lst & ls, const lst & lr) const;
exvector get_free_indices(void) const;
protected:
if (are_ex_trivially_equal(basis,subsed_basis)&&
are_ex_trivially_equal(exponent,subsed_exponent)) {
- return *this;
+ return inherited::subs(ls, lr);
}
return power(subsed_basis, subsed_exponent);
}
}
-ex symbol::subs(const lst & ls, const lst & lr) const
-{
- GINAC_ASSERT(ls.nops() == lr.nops());
-
- for (unsigned i=0; i<ls.nops(); i++) {
- if (is_ex_exactly_of_type(ls.op(i),symbol)) {
- if (compare_same_type(ex_to_symbol(ls.op(i)))==0)
- return lr.op(i);
- }
- }
- return *this;
-}
-
// protected
/** Implementation of ex::diff() for single differentiation of a symbol.
ex series(const relational & s, int order, unsigned options = 0) const;
ex normal(lst &sym_lst, lst &repl_lst, int level = 0) const;
ex to_rational(lst &repl_lst) const;
- ex subs(const lst & ls, const lst & lr) const;
protected:
ex derivative(const symbol & s) const;
int compare_same_type(const basic & other) const;
DEFAULT_PRINT(minkmetric, "eta")
DEFAULT_PRINT(tensepsilon, "eps")
-ex tensor::subs(const lst & ls, const lst & lr) const
-{
- GINAC_ASSERT(ls.nops() == lr.nops());
-
- for (unsigned i=0; i<ls.nops(); i++) {
- if (is_ex_of_type(ls.op(i), tensor) &&
- compare_same_type(ex_to_tensor(ls.op(i)))==0)
- return lr.op(i);
- }
- return *this;
-}
-
/** Automatic symbolic evaluation of an indexed delta tensor. */
ex tensdelta::eval_indexed(const basic & i) const
{
tensor(unsigned ti);
// functions overriding virtual functions from bases classes
-public:
- ex subs(const lst & ls, const lst & lr) const;
protected:
unsigned return_type(void) const { return return_types::noncommutative_composite; }
};