
Tested the time taken to run through all the Boost.Math Bessel function tests, with type double, real_concept (a simple wrapper around double from Boost.Math's test suite) and mp_number<float_backend<double> > (a trivial mp_number backend that wraps a floating point type):
Time for double = 0.0157549 seconds Time for real_concept = 0.0166421 seconds Time for float_backend<double> = 0.0408635 seconds Time for float_backend<double> - no expression templates = 0.0253047 seconds
Out of curiosity, what compiler/options? I know from similar experiments that it can play a huge role, and only with the highest optimizations (profile feedback and all) were the performances the same. In other cases the abstraction penalty never disappeared.
It's VC++ 10 with /Ox. As you can see the abstraction penalty for real_concept (which is about as simple a wrapper as you can get) just about but not quite disappears, but is still there for the more complex mp_number.
Seems like there may be some small opportunity for optimization of the comparison operators as well (i.e. not evaluating in terms of a compare() function).
Is this related? http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51938
Yes, though I confess I wasn't expecting compiler to make the optimisation you suggest - I'm very impressed that clang can!!
By the way, compare is required to return int, but sometimes it would be more convenient if I could use long (for the same reason you picked int and not an enum {-1,0,1}). Or even double. Do you do anything with the result of compare that works better because it is an int? I might even want to use a proxy.
Good point - I think the result of my_backend::compare can be any integer or enum type - it must be comparable with a literal zero (for the comparison ops), and convertible to int (for mp_number::compare). But I think it would be a legitimate optimization for the return type to be the same type as a limb in the internal representation. Cheers, John.