The general rule is that when you construct expressions, GiNaC automatically
creates them in canonical form, which might differ from the form you typed in
your program. This may create some awkward looking output (@samp{-y+x} instead
-of @samp{y-x}) but allows for more efficient operation and usually yields
+of @samp{x-y}) but allows for more efficient operation and usually yields
some immediate simplifications.
@cindex @code{eval()}
for checking whether one expression is equal to another, or equal to zero,
respectively.
-@strong{Warning:} You will also find an @code{ex::compare()} method in the
-GiNaC header files. This method is however only to be used internally by
-GiNaC to establish a canonical sort order for terms, and using it to compare
-expressions will give very surprising results.
+
+@subsection Ordering expressions
+@cindex @code{ex_is_less} (class)
+@cindex @code{ex_is_equal} (class)
+@cindex @code{compare()}
+
+Sometimes it is necessary to establish a mathematically well-defined ordering
+on a set of arbitrary expressions, for example to use expressions as keys
+in a @code{std::map<>} container, or to bring a vector of expressions into
+a canonical order (which is done internally by GiNaC for sums and products).
+
+The operators @code{<}, @code{>} etc. described in the last section cannot
+be used for this, as they don't implement an ordering relation in the
+mathematical sense. In particular, they are not guaranteed to be
+antisymmetric: if @samp{a} and @samp{b} are different expressions, and
+@code{a < b} yields @code{false}, then @code{b < a} doesn't necessarily
+yield @code{true}.
+
+By default, STL classes and algorithms use the @code{<} and @code{==}
+operators to compare objects, which are unsuitable for expressions, but GiNaC
+provides two functors that can be supplied as proper binary comparison
+predicates to the STL:
+
+@example
+class ex_is_less : public std::binary_function<ex, ex, bool> @{
+public:
+ bool operator()(const ex &lh, const ex &rh) const;
+@};
+
+class ex_is_equal : public std::binary_function<ex, ex, bool> @{
+public:
+ bool operator()(const ex &lh, const ex &rh) const;
+@};
+@end example
+
+For example, to define a @code{map} that maps expressions to strings you
+have to use
+
+@example
+std::map<ex, std::string, ex_is_less> myMap;
+@end example
+
+Omitting the @code{ex_is_less} template parameter will introduce spurious
+bugs because the map operates improperly.
+
+Other examples for the use of the functors:
+
+@example
+std::vector<ex> v;
+// fill vector
+...
+
+// sort vector
+std::sort(v.begin(), v.end(), ex_is_less());
+
+// count the number of expressions equal to '1'
+unsigned num_ones = std::count_if(v.begin(), v.end(),
+ std::bind2nd(ex_is_equal(), 1));
+@end example
+
+The implementation of @code{ex_is_less} uses the member function
+
+@example
+int ex::compare(const ex & other) const;
+@end example
+
+which returns @math{0} if @code{*this} and @code{other} are equal, @math{-1}
+if @code{*this} sorts before @code{other}, and @math{1} if @code{*this} sorts
+after @code{other}.
@node Substituting Expressions, Pattern Matching and Advanced Substitutions, Information About Expressions, Methods and Functions
The optional last argument to @code{subs()} is a combination of
@code{subs_options} flags. There are two options available:
-@code{subs_options::subs_no_pattern} disables pattern matching, which makes
+@code{subs_options::no_pattern} disables pattern matching, which makes
large @code{subs()} operations significantly faster if you are not using
-patterns. The second option, @code{subs_options::subs_algebraic} enables
+patterns. The second option, @code{subs_options::algebraic} enables
algebraic substitutions in products and powers.
@ref{Pattern Matching and Advanced Substitutions}, for more information
about patterns and algebraic substitutions.
@end example
@subsection Algebraic substitutions
-Supplying the @code{subs_options::subs_algebraic} option to @code{subs()}
+Supplying the @code{subs_options::algebraic} option to @code{subs()}
enables smarter, algebraic substitutions in products and powers. If you want
to substitute some factors of a product, you only need to list these factors
in your pattern. Furthermore, if an (integer) power of some expression occurs
@example
cout << (a*a*a*a+b*b*b*b+pow(x+y,4)).subs(wild()*wild()==pow(wild(),3),
- subs_options::subs_algebraic) << endl;
+ subs_options::algebraic) << endl;
// --> (y+x)^6+b^6+a^6
-cout << ((a+b+c)*(a+b+c)).subs(a+b==x,subs_options::subs_algebraic) << endl;
+cout << ((a+b+c)*(a+b+c)).subs(a+b==x,subs_options::algebraic) << endl;
// --> (c+b+a)^2
// Powers and products are smart, but addition is just the same.
-cout << ((a+b+c)*(a+b+c)).subs(a+b+wild()==x+wild(), subs_options::subs_algebraic)
+cout << ((a+b+c)*(a+b+c)).subs(a+b+wild()==x+wild(), subs_options::algebraic)
<< endl;
// --> (x+c)^2
// As I said: addition is just the same.
-cout << (pow(a,5)*pow(b,7)+2*b).subs(b*b*a==x,subs_options::subs_algebraic) << endl;
+cout << (pow(a,5)*pow(b,7)+2*b).subs(b*b*a==x,subs_options::algebraic) << endl;
// --> x^3*b*a^2+2*b
-cout << (pow(a,-5)*pow(b,-7)+2*b).subs(1/(b*b*a)==x,subs_options::subs_algebraic)
+cout << (pow(a,-5)*pow(b,-7)+2*b).subs(1/(b*b*a)==x,subs_options::algebraic)
<< endl;
// --> 2*b+x^3*b^(-1)*a^(-2)
-cout << (4*x*x*x-2*x*x+5*x-1).subs(x==a,subs_options::subs_algebraic) << endl;
+cout << (4*x*x*x-2*x*x+5*x-1).subs(x==a,subs_options::algebraic) << endl;
// --> -1-2*a^2+4*a^3+5*a
cout << (4*x*x*x-2*x*x+5*x-1).subs(pow(x,wild())==pow(a,wild()),
- subs_options::subs_algebraic) << endl;
+ subs_options::algebraic) << endl;
// --> -1+5*x+4*x^3-2*x^2
// You should not really need this kind of patterns very often now.
// But perhaps this it's-not-a-bug-it's-a-feature (c/sh)ould still change.
cout << ex(sin(1+sin(x))).subs(sin(wild())==cos(wild()),
- subs_options::subs_algebraic) << endl;
+ subs_options::algebraic) << endl;
// --> cos(1+cos(x))
cout << expand((a*sin(x+y)*sin(x+y)+a*cos(x+y)*cos(x+y)+b)
.subs((pow(cos(wild()),2)==1-pow(sin(wild()),2)),
- subs_options::subs_algebraic)) << endl;
+ subs_options::algebraic)) << endl;
// --> b+a
@end example