Boost logo

Boost :

From: Moore, Paul (paul.moore_at_[hidden])
Date: 2001-10-10 04:29:30

From: "David Abrahams" <david.abrahams_at_[hidden]>
> From: "Daryle Walker" <darylew_at_[hidden]>
> > Since I don't use Windows (or an IBM-style PC), it's
> > very hard for me to play "guess the MSVC6 fix." However,
> > I want to support all the platforms that the rational
> > and pool libraries did, since I'm trying to replace the
> > specialty GCD/LCM routines they had. So if someone could
> > provide a fix that's close to my style, that's OK.
> If you are replacing functionality that used to work with
> this platform, I would not feel right about incorporating
> the change until there was a fix in place. Somebody did
> the work to make sure the appropriate workarounds were in
> place. Undoing that work would not only be bad for users;
> it would display disrespect for the original author. I
> would be very reluctant to follow that course.

Speaking as the author of the rational library, I guess should express my
view here.

My key design goals when developng the rational library were (1) simplicity,
(2) MSVC compatibility, and (3) compatibility with some (hypothetical)
"unlimited integer" type.

By "simplicity" I'm trying to capture the general concept that rational
numbers (at a naive level) aren't complicated, so the implementation
shouldn't be, either. Users should be able to look at the implementation,
and understand it. Compile-time template games, and masses of #ifdef special
casing, work against this goal.

My reason for MSVC compatibility is simple. That is the compiler I use, so
I'm not going to write a library I can't use. If MSVC (version 6)
compatibility goes, someone else will have to take over responsibility for
the library.

The unlimited integer compatibility requirement is to ensure that it *is*
possible to use rationals to avoid strange rounding and boundary case
issues. This isn't possible with limited-precision integers. But as I don't
have the time or expertise to write a good long-integer class, I just make
sure it's *possible* to do so.

Given all of the above, I have some serious reservations about using the GCD
library in rational.hpp. First of all, if there is a MSVC compatibility
problem, I definitely won't be using it. Sorry, but that's absolute.
Secondly, all the talk I've seen of Euclidean rings and the like, is
worrying. Goal (1) "simplicity" means that rational.hpp will stay resolutely
targeted at integers - not rings, or any other mathematical construct. (I'm
a mathematician by training, so I do know the terms, btw - I'm just glossing
over details here to avoid obscuring the point). I worry that if the GCD
library is stated as supporting rings or whatever, there will be a knock-on
tendency to ask for rational to support them as well. And I don't want to
spend my time rejecting such requests (and explaining my reasons each time).

So, ultimately, I don't have a problem with *having* a GCD library. However,
it's not clear to me that the library has the same design goals as the
rational library, and that clash of goals could cause an issue with *using*
it in rational.hpp.

BTW, I should point out that I haven't looked at the GCD library
implementation. I haven't had the time. I've done my best to follow the
discussions, but it's hard to do so, as the list traffic has been pretty
high (mostly on the thread library, which I've not been following) and in
digest mode it's almost impossible to pick out specific threads :-(

I'd appreciate comments, but it may be worth copying them to me directly as
well as to the list, as I may otherwise miss them...


PS Stop press: I just looked at the library. First impression - bloody hell,
that's complicated! Why is this better than the gcd implementation in

In more detail (looking only at gcd_integer - I simply don't follow the
rest!) the requirements on the integer type are very different to my
version. Mine needs (informally) operator%, assignability, operator+=,
operator< against (literal) 0, and while(m) to work. Yours needs
constructibility from a literal 0 (via static_cast), unary operator+ and
operator-, < and != comparisons vs zero, operator%= operator+, as well as
the strange trick at the end of using a+b (which, btw, is the *only*
dependency on operator+) to avoid testing for zero. (How can you be sure
that adding zero is cheaper than a zero test?)

I worked hard to reduce requirements on integers - both in terms of what is
implemented, and what is fast - because people requested it for long-integer
type compatibility. I'm not happy about having to revisit that.

OK, your GCD handles negative numbers - mine doesn't need to (as rational
has always normalised to positive before calling it). There may be a cost to
this generality, which can't be avoided. (But I assume this is where the
comments from others about unary + came in - I agree with them, you
shouldn't force the requirement on unary +, just so the code "looks pretty".
If you worry about looks, I'd recommend "if (a < zero) a = -a" ...

No, I'm afraid that unless a more detailed read of the class (which I'll try
to do at some stage!) changes my mind, I don't want to use this GCD in place
of the one in rational.hpp.

And yes, I know I should have done this earlier. All I can say is that I'm
sorry - I simply don't have much free time at the moment.


Boost list run by bdawes at, gregod at, cpdaniel at, john at