manpagez: man pages & more
info ginac
Home | html | info | man
[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

6.4.3 Comparing structures

The 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 sprod_s. This can lead to some confusing and undesired behavior:

 
...
    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)
...

To remedy this, we first need to define the operators == and < for objects of type sprod_s:

 
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;
}

The ordering established by the < operator doesn't have to make any algebraic sense, but it needs to be well defined. Note that we can't use expressions like lhs.left == rhs.left or lhs.left < rhs.left in the implementation of these operators because they would construct GiNaC relational objects which in the case of < 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 sprod type to let GiNaC know that an ordering relation exists for the embedded objects:

 
typedef structure<sprod_s, compare_std_less> sprod;

sprod objects then behave as expected:

 
...
    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>
...

The compare_std_less policy parameter tells GiNaC to use the std::less and std::equal_to functors to compare objects of type sprod_s. By default, these functors forward their work to the standard < and == operators, which we have overloaded. Alternatively, we could have specialized std::less and std::equal_to for class sprod_s.

GiNaC provides two other comparison policies for structure<T> objects: the default compare_all_equal, and compare_bitwise which does a bit-wise comparison of the contained 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 T class might have.


[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]
© manpagez.com 2000-2024
Individual documents may contain additional copyright information.