manpagez: man pages & more
info ginac
Home | html | info | man
[ < ] [ > ]   [ << ] [ 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] [ ? ]
© manpagez.com 2000-2024
Individual documents may contain additional copyright information.