4.9 Lists of expressions
The GiNaC class lst
serves for holding a list of arbitrary
expressions. They are not as ubiquitous as in many other computer algebra
packages, but are sometimes used to supply a variable number of arguments of
the same type to GiNaC methods such as subs()
and some matrix
constructors, so you should have a basic understanding of them.
Lists can be constructed by assigning a comma-separated sequence of
expressions:
| {
symbol x("x"), y("y");
lst l;
l = x, 2, y, x+y;
// now, l is a list holding the expressions 'x', '2', 'y', and 'x+y',
// in that order
...
|
There are also constructors that allow direct creation of lists of up to
16 expressions, which is often more convenient but slightly less efficient:
| ...
// This produces the same list 'l' as above:
// lst l(x, 2, y, x+y);
// lst l = lst(x, 2, y, x+y);
...
|
Use the nops()
method to determine the size (number of expressions) of
a list and the op()
method or the []
operator to access
individual elements:
| ...
cout << l.nops() << endl; // prints '4'
cout << l.op(2) << " " << l[0] << endl; // prints 'y x'
...
|
As with the standard list<T>
container, accessing random elements of a
lst
is generally an operation of order O(N). Faster read-only
sequential access to the elements of a list is possible with the
iterator types provided by the lst
class:
| typedef ... lst::const_iterator;
typedef ... lst::const_reverse_iterator;
lst::const_iterator lst::begin() const;
lst::const_iterator lst::end() const;
lst::const_reverse_iterator lst::rbegin() const;
lst::const_reverse_iterator lst::rend() const;
|
For example, to print the elements of a list individually you can use:
| ...
// O(N)
for (lst::const_iterator i = l.begin(); i != l.end(); ++i)
cout << *i << endl;
...
|
which is one order faster than
| ...
// O(N^2)
for (size_t i = 0; i < l.nops(); ++i)
cout << l.op(i) << endl;
...
|
These iterators also allow you to use some of the algorithms provided by
the C++ standard library:
| ...
// print the elements of the list (requires #include <iterator>)
std::copy(l.begin(), l.end(), ostream_iterator<ex>(cout, "\n"));
// sum up the elements of the list (requires #include <numeric>)
ex sum = std::accumulate(l.begin(), l.end(), ex(0));
cout << sum << endl; // prints '2+2*x+2*y'
...
|
lst
is one of the few GiNaC classes that allow in-place modifications
(the only other one is matrix
). You can modify single elements:
| ...
l[1] = 42; // l is now {x, 42, y, x+y}
l.let_op(1) = 7; // l is now {x, 7, y, x+y}
...
|
You can append or prepend an expression to a list with the append()
and prepend()
methods:
| ...
l.append(4*x); // l is now {x, 7, y, x+y, 4*x}
l.prepend(0); // l is now {0, x, 7, y, x+y, 4*x}
...
|
You can remove the first or last element of a list with remove_first()
and remove_last()
:
| ...
l.remove_first(); // l is now {x, 7, y, x+y, 4*x}
l.remove_last(); // l is now {x, 7, y, x+y}
...
|
You can remove all the elements of a list with remove_all()
:
| ...
l.remove_all(); // l is now empty
...
|
You can bring the elements of a list into a canonical order with sort()
:
| ...
lst l1, l2;
l1 = x, 2, y, x+y;
l2 = 2, x+y, x, y;
l1.sort();
l2.sort();
// l1 and l2 are now equal
...
|
Finally, you can remove all but the first element of consecutive groups of
elements with unique()
:
| ...
lst l3;
l3 = x, 2, 2, 2, y, x+y, y+x;
l3.unique(); // l3 is now {x, 2, y, x+y}
}
|