| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
5.1.2 Accessing subexpressions
Many GiNaC classes, like add, mul, lst, and
function, act as containers for subexpressions. For example, the
subexpressions of a sum (an add object) are the individual terms,
and the subexpressions of a function are the function's arguments.
GiNaC provides several ways of accessing subexpressions. The first way is to use the two methods
size_t ex::nops(); ex ex::op(size_t i); |
nops() determines the number of subexpressions (operands) contained
in the expression, while op(i) returns the i-th
(0..nops()-1) subexpression. In the case of a power object,
op(0) will return the basis and op(1) the exponent. For
indexed objects, op(0) is the base expression and op(i),
i>0 are the indices.
The second way to access subexpressions is via the STL-style random-access
iterator class const_iterator and the methods
const_iterator ex::begin(); const_iterator ex::end(); |
begin() returns an iterator referring to the first subexpression;
end() returns an iterator which is one-past the last subexpression.
If the expression has no subexpressions, then begin() == end(). These
iterators can also be used in conjunction with non-modifying STL algorithms.
Here is an example that (non-recursively) prints the subexpressions of a given expression in three different ways:
{
ex e = ...
// with nops()/op()
for (size_t i = 0; i != e.nops(); ++i)
cout << e.op(i) << endl;
// with iterators
for (const_iterator i = e.begin(); i != e.end(); ++i)
cout << *i << endl;
// with iterators and STL copy()
std::copy(e.begin(), e.end(), std::ostream_iterator<ex>(cout, "\n"));
}
|
op()/nops() and const_iterator only access an
expression's immediate children. GiNaC provides two additional iterator
classes, const_preorder_iterator and const_postorder_iterator,
that iterate over all objects in an expression tree, in preorder or postorder,
respectively. They are STL-style forward iterators, and are created with the
methods
const_preorder_iterator ex::preorder_begin(); const_preorder_iterator ex::preorder_end(); const_postorder_iterator ex::postorder_begin(); const_postorder_iterator ex::postorder_end(); |
The following example illustrates the differences between
const_iterator, const_preorder_iterator, and
const_postorder_iterator:
{
symbol A("A"), B("B"), C("C");
ex e = lst(lst(A, B), C);
std::copy(e.begin(), e.end(),
std::ostream_iterator<ex>(cout, "\n"));
// {A,B}
// C
std::copy(e.preorder_begin(), e.preorder_end(),
std::ostream_iterator<ex>(cout, "\n"));
// {{A,B},C}
// {A,B}
// A
// B
// C
std::copy(e.postorder_begin(), e.postorder_end(),
std::ostream_iterator<ex>(cout, "\n"));
// A
// B
// {A,B}
// C
// {{A,B},C}
}
|
Finally, the left-hand side and right-hand side expressions of objects of
class relational (and only of these) can also be accessed with the
methods
ex ex::lhs(); ex ex::rhs(); |
| [ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
