The most common class of objects a user deals with is the expression
ex, representing a mathematical object like a variable, number,
function, sum, product, etc... Expressions may be put together to form
new expressions, passed as arguments to functions, and so on. Here is a
little collection of valid expressions:
ex MyEx1 = 5; // simple number
ex MyEx2 = x + 2*y; // polynomial in x and y
ex MyEx3 = (x + 1)/(x - 1); // rational expression
ex MyEx4 = sin(x + 2*y) + 3*z + 41; // containing a function
ex MyEx5 = MyEx4 + 1; // similar to above
Expressions are handles to other more fundamental objects, that often
contain other expressions thus creating a tree of expressions
(See Internal structures, for particular examples). Most methods on
ex therefore run top-down through such an expression tree. For
example, the method has() scans recursively for occurrences of
something inside an expression. Thus, if you have declared MyEx4
as in the example above MyEx4.has(y) will find y inside
the argument of sin and hence return true.
The next sections will outline the general picture of GiNaC's class
hierarchy and describe the classes of objects that are handled by
ex.
GiNaC expressions (ex objects) have value semantics (they can be
assigned, reassigned and copied like integral types) but the operator
< doesn't provide a well-defined ordering on them. In STL-speak,
expressions are ‘Assignable’ but not ‘LessThanComparable’.
This implies that in order to use expressions in sorted containers such as
std::map<> and std::set<> you have to supply a suitable
comparison predicate. GiNaC provides such a predicate, called
ex_is_less. For example, a set of expressions should be defined
as std::set<ex, ex_is_less>.
Unsorted containers such as std::vector<> and std::list<>
don't pose a problem. A std::vector<ex> works as expected.
See Information about expressions, for more about comparing and ordering expressions.