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()}
@item @code{varidx} @tab Index with variance
@item @code{spinidx} @tab Index with variance and dot (used in Weyl-van-der-Waerden spinor formalism)
@item @code{wildcard} @tab Wildcard for pattern matching
+@item @code{structure} @tab Template for user-defined classes
@end multitable
@end cartouche
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
expressions via the @code{.subs()} method:
@example
-ex ex::subs(const ex & e);
-ex ex::subs(const lst & syms, const lst & repls);
+ex ex::subs(const ex & e, unsigned options = 0);
+ex ex::subs(const lst & syms, const lst & repls, unsigned options = 0);
@end example
In the first form, @code{subs()} accepts a relational of the form
contain the same number of elements). Using this form, you would write
@code{subs(lst(x, y), lst(y, x))} to exchange @samp{x} and @samp{y}.
+The optional last argument to @code{subs()} is a combination of
+@code{subs_options} flags. There are two options available:
+@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::algebraic} enables
+algebraic substitutions in products and powers.
+@ref{Pattern Matching and Advanced Substitutions}, for more information
+about patterns and algebraic substitutions.
+
@code{subs()} performs syntactic substitution of any complete algebraic
object; it does not try to match sub-expressions as is demonstrated by the
following example:
@end example
@subsection Algebraic substitutions
-The @code{subs()} method has an extra, optional, argument. This argument can
-be used to pass one of the @code{subs_options} to it. The only option that is
-currently available is the @code{subs_algebraic} option which affects
-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 in your pattern and in the expression that you
-want the substitution to occur in, it can be substituted as many times as
-possible, without getting negative powers.
+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
+in your pattern and in the expression that you want the substitution to occur
+in, it can be substituted as many times as possible, without getting negative
+powers.
An example clarifies it all (hopefully):
@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
To bring an expression into expanded form, its method
@example
-ex ex::expand();
+ex ex::expand(unsigned options = 0);
@end example
may be called. In our example above, this corresponds to @math{4*x*y +