Boost logo

Boost :

From: George A. Heintzelman (georgeh_at_[hidden])
Date: 2001-08-30 13:25:11


> On Thursday 30 August 2001 18:52, George Heintzelman wrote:
> > [...] when operating on units with different base systems, the
> > compiler looks up the conversion constants and hopefully can reduce the
> > conversion to a single multiplication at compile time, invisible to the
> > user.
>
> Mmm... after thinking about it some more, I would prefer
> the system *not* to do any automatic conversions and require
> unit_cast<>() or somesuch. Runtime cost is runtime cost,
> and it better be visible to the user. Especially because there's
> no guarantee it will be reduced down to a *single* multiplication.
> Most compilers will not do floating-point calculations at compile
> time, even with constants.

Interesting point. I agree that this could mask some runtime cost from
the user, but I'm not sure that's a terrible thing -- after all, so
does vector::insert, and probably more egregiously than here. OTOH, a
more serious concern for me is ambiguity. Given an expression x*y where
x is in inches and y is in centimeters, what is the base units of the
result? I don't know and can't guess, so I agree that for binary
operations, a unit_cast of some nature is required.

I would like to enable y = x with y in centimeters and x in inches,
however. If it is not going to be regularly optimized down to a single
multiplication, though, these kinds of conversions get stickier,
especially with higher-dimensionality (= more multiplications) units
involved.

So, I tested this code (which would look very similar to what a
compiler would need to do for an implicit conversion between inches and
centimeters) with the two compilers readily available to me: g++-2.95
and Sun CC 6u1, both on a Solaris 2.8 machine:

#include <iostream>

int main() {
  const double x = 0.0254;
  const double y = 0.01;

  double inches;
  std::cin >> inches;

  std::cout << inches*(x/y) << std::endl;
}

g++ (-O3 optimization) successfully hoisted the floating-point division
x/y out into a predefined constant, and removed all reference to the
space for x and y proper. CC (-xO3 optimization), on the other hand,
did not manage to optimize that out, instead carrying out the division
at runtime, although it allocated x and y in a global space rather than
on the stack (not really a relevant optimization here, but nice to
know).

The same results were obtained when x and y were taken out and
implemented as inline functions instead (both compilers generated
isomorphic code to their versions with the const double variables, as
far as I could tell, though I'm not an assembler expert).

When the parentheses around (x/y) were removed, g++ did *not* optimize
out the multiplication -- correctly, I believe, as IEEE
multiplication/division are not associative, unlike the pure
mathematical form. So we would have to take care that all floating
point arithmetic with constants was carried out before applying it to
the user's variable, if at all possible, to enable this optimization.
That is probably also necessary to avoid unnecessary overflows, anyway.

In sum, g++ gets full marks and Sun CC fails the test. I would be
interested in knowing how well other compilers manage with this little
test, but the fact that g++ successfully optimized it is encouraging;
it certainly isn't beyond expecting compilers to do.

George Heintzelman
georgeh_at_[hidden]


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk