-@node Structures, Adding classes, Symbolic functions, Extending GiNaC
-@c node-name, next, previous, up
-@section Structures
-
-If you are doing some very specialized things with GiNaC, or if you just
-need some more organized way to store data in your expressions instead of
-anonymous lists, you may want to implement your own algebraic classes.
-('algebraic class' means any class directly or indirectly derived from
-@code{basic} that can be used in GiNaC expressions).
-
-GiNaC offers two ways of accomplishing this: either by using the
-@code{structure<T>} template class, or by rolling your own class from
-scratch. This section will discuss the @code{structure<T>} template which
-is easier to use but more limited, while the implementation of custom
-GiNaC classes is the topic of the next section. However, you may want to
-read both sections because many common concepts and member functions are
-shared by both concepts, and it will also allow you to decide which approach
-is most suited to your needs.
-
-The @code{structure<T>} template, defined in the GiNaC header file
-@file{structure.h}, wraps a type that you supply (usually a C++ @code{struct}
-or @code{class}) into a GiNaC object that can be used in expressions.
-
-@subsection Example: scalar products
-
-Let's suppose that we need a way to handle some kind of abstract scalar
-product of the form @samp{<x|y>} in expressions. Objects of the scalar
-product class have to store their left and right operands, which can in turn
-be arbitrary expressions. Here is a possible way to represent such a
-product in a C++ @code{struct}:
-
-@example
-#include <iostream>
-using namespace std;
-
-#include <ginac/ginac.h>
-using namespace GiNaC;
-
-struct sprod_s @{
- ex left, right;
-
- sprod_s() @{@}
- sprod_s(ex l, ex r) : left(l), right(r) @{@}
-@};
-@end example
-
-The default constructor is required. Now, to make a GiNaC class out of this
-data structure, we need only one line:
-
-@example
-typedef structure<sprod_s> sprod;
-@end example
-
-That's it. This line constructs an algebraic class @code{sprod} which
-contains objects of type @code{sprod_s}. We can now use @code{sprod} in
-expressions like any other GiNaC class:
-
-@example
-...
- symbol a("a"), b("b");
- ex e = sprod(sprod_s(a, b));
-...
-@end example
-
-Note the difference between @code{sprod} which is the algebraic class, and
-@code{sprod_s} which is the unadorned C++ structure containing the @code{left}
-and @code{right} data members. As shown above, an @code{sprod} can be
-constructed from an @code{sprod_s} object.
-
-If you find the nested @code{sprod(sprod_s())} constructor too unwieldy,
-you could define a little wrapper function like this:
-
-@example
-inline ex make_sprod(ex left, ex right)
-@{
- return sprod(sprod_s(left, right));
-@}
-@end example
-
-The @code{sprod_s} object contained in @code{sprod} can be accessed with
-the GiNaC @code{ex_to<>()} function followed by the @code{->} operator or
-@code{get_struct()}:
-
-@example
-...
- cout << ex_to<sprod>(e)->left << endl;
- // -> a
- cout << ex_to<sprod>(e).get_struct().right << endl;
- // -> b
-...
-@end example
-
-You only have read access to the members of @code{sprod_s}.
-
-The type definition of @code{sprod} is enough to write your own algorithms
-that deal with scalar products, for example:
-
-@example
-ex swap_sprod(ex p)
-@{
- if (is_a<sprod>(p)) @{
- const sprod_s & sp = ex_to<sprod>(p).get_struct();
- return make_sprod(sp.right, sp.left);
- @} else
- return p;
-@}
-
-...
- f = swap_sprod(e);
- // f is now <b|a>
-...
-@end example
-
-@subsection Structure output
-
-While the @code{sprod} type is useable it still leaves something to be
-desired, most notably proper output:
-
-@example
-...
- cout << e << endl;
- // -> [structure object]
-...
-@end example
-
-By default, any structure types you define will be printed as
-@samp{[structure object]}. To override this, you can specialize the
-template's @code{print()} member function. The member functions of
-GiNaC classes are described in more detail in the next section, but
-it shouldn't be hard to figure out what's going on here:
-
-@example
-void sprod::print(const print_context & c, unsigned level) const
-@{
- // tree debug output handled by superclass
- if (is_a<print_tree>(c))
- inherited::print(c, level);
-
- // get the contained sprod_s object
- const sprod_s & sp = get_struct();
-
- // print_context::s is a reference to an ostream
- c.s << "<" << sp.left << "|" << sp.right << ">";
-@}
-@end example
-
-Now we can print expressions containing scalar products:
-
-@example
-...
- cout << e << endl;
- // -> <a|b>
- cout << swap_sprod(e) << endl;
- // -> <b|a>
-...
-@end example
-
-@subsection Comparing structures
-
-The @code{sprod} class defined so far still has one important drawback: all
-scalar products are treated as being equal because GiNaC doesn't know how to
-compare objects of type @code{sprod_s}. This can lead to some confusing
-and undesired behavior:
-
-@example
-...
- cout << make_sprod(a, b) - make_sprod(a*a, b*b) << endl;
- // -> 0
- cout << make_sprod(a, b) + make_sprod(a*a, b*b) << endl;
- // -> 2*<a|b> or 2*<a^2|b^2> (which one is undefined)
-...
-@end example
-
-To remedy this, we first need to define the operators @code{==} and @code{<}
-for objects of type @code{sprod_s}:
-
-@example
-inline bool operator==(const sprod_s & lhs, const sprod_s & rhs)
-@{
- return lhs.left.is_equal(rhs.left) && lhs.right.is_equal(rhs.right);
-@}
-
-inline bool operator<(const sprod_s & lhs, const sprod_s & rhs)
-@{
- return lhs.left.compare(rhs.left) < 0 ? true : lhs.right.compare(rhs.right) < 0;
-@}
-@end example
-
-The ordering established by the @code{<} operator doesn't have to make any
-algebraic sense, but it needs to be well defined. Note that we can't use
-expressions like @code{lhs.left == rhs.left} or @code{lhs.left < rhs.left}
-in the implementation of these operators because they would construct
-GiNaC @code{relational} objects which in the case of @code{<} do not
-establish a well defined ordering (for arbitrary expressions, GiNaC can't
-decide which one is algebraically 'less').
-
-Next, we need to change our definition of the @code{sprod} type to let
-GiNaC know that an ordering relation exists for the embedded objects:
-
-@example
-typedef structure<sprod_s, compare_std_less> sprod;
-@end example
-
-@code{sprod} objects then behave as expected:
-
-@example
-...
- cout << make_sprod(a, b) - make_sprod(a*a, b*b) << endl;
- // -> <a|b>-<a^2|b^2>
- cout << make_sprod(a, b) + make_sprod(a*a, b*b) << endl;
- // -> <a|b>+<a^2|b^2>
- cout << make_sprod(a, b) - make_sprod(a, b) << endl;
- // -> 0
- cout << make_sprod(a, b) + make_sprod(a, b) << endl;
- // -> 2*<a|b>
-...
-@end example
-
-The @code{compare_std_less} policy parameter tells GiNaC to use the
-@code{std::less} and @code{std::equal_to} functors to compare objects of
-type @code{sprod_s}. By default, these functors forward their work to the
-standard @code{<} and @code{==} operators, which we have overloaded.
-Alternatively, we could have specialized @code{std::less} and
-@code{std::equal_to} for class @code{sprod_s}.
-
-GiNaC provides two other comparison policies for @code{structure<T>}
-objects: the default @code{compare_all_equal}, and @code{compare_bitwise}
-which does a bit-wise comparison of the contained @code{T} objects.
-This should be used with extreme care because it only works reliably with
-built-in integral types, and it also compares any padding (filler bytes of
-undefined value) that the @code{T} class might have.
-
-@subsection Subexpressions
-
-Our scalar product class has two subexpressions: the left and right
-operands. It might be a good idea to make them accessible via the standard
-@code{nops()} and @code{op()} methods:
-
-@example
-size_t sprod::nops() const
-@{
- return 2;
-@}
-
-ex sprod::op(size_t i) const
-@{
- switch (i) @{
- case 0:
- return get_struct().left;
- case 1:
- return get_struct().right;
- default:
- throw std::range_error("sprod::op(): no such operand");
- @}
-@}
-@end example
-
-Implementing @code{nops()} and @code{op()} for container types such as
-@code{sprod} has two other nice side effects:
-
-@itemize @bullet
-@item
-@code{has()} works as expected
-@item
-GiNaC generates better hash keys for the objects (the default implementation
-of @code{calchash()} takes subexpressions into account)
-@end itemize
-
-@cindex @code{let_op()}
-There is a non-const variant of @code{op()} called @code{let_op()} that
-allows replacing subexpressions:
-
-@example
-ex & sprod::let_op(size_t i)
-@{
- // every non-const member function must call this
- ensure_if_modifiable();
-
- switch (i) @{
- case 0:
- return get_struct().left;
- case 1:
- return get_struct().right;
- default:
- throw std::range_error("sprod::let_op(): no such operand");
- @}
-@}
-@end example
-
-Once we have provided @code{let_op()} we also get @code{subs()} and
-@code{map()} for free. In fact, every container class that returns a non-null
-@code{nops()} value must either implement @code{let_op()} or provide custom
-implementations of @code{subs()} and @code{map()}.
-
-In turn, the availability of @code{map()} enables the recursive behavior of a
-couple of other default method implementations, in particular @code{evalf()},
-@code{evalm()}, @code{normal()}, @code{diff()} and @code{expand()}. Although
-we probably want to provide our own version of @code{expand()} for scalar
-products that turns expressions like @samp{<a+b|c>} into @samp{<a|c>+<b|c>}.
-This is left as an exercise for the reader.
-
-The @code{structure<T>} template defines many more member functions that
-you can override by specialization to customize the behavior of your
-structures. You are referred to the next section for a description of
-some of these (especially @code{eval()}). There is, however, one topic
-that shall be addressed here, as it demonstrates one peculiarity of the
-@code{structure<T>} template: archiving.
-
-@subsection Archiving structures
-
-If you don't know how the archiving of GiNaC objects is implemented, you
-should first read the next section and then come back here. You're back?
-Good.
-
-To implement archiving for structures it is not enough to provide
-specializations for the @code{archive()} member function and the
-unarchiving constructor (the @code{unarchive()} function has a default
-implementation). You also need to provide a unique name (as a string literal)
-for each structure type you define. This is because in GiNaC archives,
-the class of an object is stored as a string, the class name.
-
-By default, this class name (as returned by the @code{class_name()} member
-function) is @samp{structure} for all structure classes. This works as long
-as you have only defined one structure type, but if you use two or more you
-need to provide a different name for each by specializing the
-@code{get_class_name()} member function. Here is a sample implementation
-for enabling archiving of the scalar product type defined above:
-
-@example
-const char *sprod::get_class_name() @{ return "sprod"; @}
-
-void sprod::archive(archive_node & n) const
-@{
- inherited::archive(n);
- n.add_ex("left", get_struct().left);
- n.add_ex("right", get_struct().right);
-@}
-
-sprod::structure(const archive_node & n, lst & sym_lst) : inherited(n, sym_lst)
-@{
- n.find_ex("left", get_struct().left, sym_lst);
- n.find_ex("right", get_struct().right, sym_lst);
-@}
-@end example
-
-Note that the unarchiving constructor is @code{sprod::structure} and not
-@code{sprod::sprod}, and that we don't need to supply an
-@code{sprod::unarchive()} function.
-
-
-@node Adding classes, A Comparison With Other CAS, Structures, Extending GiNaC