Comparison: when operator<() is better than opCmp()

Giuseppe Bilotta giuseppe.bilotta at gmail.com
Fri Sep 7 14:46:11 PDT 2007


Hello all,

I'm quite a newbie at D programming, although I have some
programming experience in languages such as C, C++, Ruby.

I've been initially attracted to D by its native support for the
'real' floating point type with the proper native support for nans
and infinities, and I've been thinking about doing some serious
scientific computing stuff in it.

As it happens, my university career has brought me to the field of
'reliable computing', and things such as interval analysis and
affine arithmetic. So I've decided to try my bones at programming
in D by implementing some reliable computing classes (intervals,
affine expressions, and other forms which are the fruit of my
research).

Now, while writing the initial structure of the interval class,
I've come across an interesting consideration: there are some
cases where having to implement comparison operators as the single
opCmp() method is (considerably) less efficient than having to do
it by having to implement the operators <(), <=() >(), >=() as
done in C++.

Let me explain. The class interval is basically a simple wrapper
for a pair of real numbers lo, hi such that lo <= hi; lo is the
lower bound of the interval, and hi is the upper bound.

Now, when comparing such an interval with, say, a real number, the
comparsions would be implemented in C++ as follows:

operator<(double val) { return hi < val ; }
operator<=(double val) { return hi <= val ; }
operator>(double val) { return lo > val ; }
operator>=(double val) { return lo >= val ; }

so that each comparison is actually very fast (a single
comparsion); we can inline it for maximum effect. By contrast, in
D we have

        real opCmp(in real val)
        {
                if (lo >= val)
                        return lo-val ;
                if (hi <= val)
                        return hi-val ;
                return real.nan ;
        }

whose result will be compared with 0 to determine the outcome.
This means that in the best case we have to do two comparisons and
a subtraction, and in the worst case three comparisons and a
subtraction. The subtractions can be eliminated by doing some
extra comparisons (i.e. checking for equality separately from
inequality in the two comparisons).

It is therefore quite obvious that the opCmp() way of doing things
is considerably more inefficient than the C++ way of overloading
each comparison separately: it involves less coding, but results
in slower code.

On the other hand, there are other cases in which opCmp() is more
efficient than implementing the comparison operators one by one.

So what I was wondering was if it was possible to have the
possibility to overload the single comparison operators in D,
while still keeping opCmp(). The way I see it, overloading would
work in a way similar to the way opAdd/opAdd_r work.

Let's say we have opGreater(), opLess(), opGreaterEqual(),
opLessEqual() in addition to opCmp(). When the expression a op b is
encountered, we check for the existence of a.opfunc(b), then of
b.opfunc_reverse(a), then for a.opCmp(b), and finally for
b.opCmp(a) (the result of which is negated before comparison with
0).

This way, the classes implementing opCmp() would still work as
they are, but efficient opfunc() implementations could be written
when necessary.

How does the idea sound?

-- 
Giuseppe "Oblomov" Bilotta



More information about the Digitalmars-d mailing list