
Thanks for doing this Darren. A few comments below... On Jun 18, 2008, at 11:48 PM, Darren Garvey wrote:
I thought this bit looked simple enough to have a go at, so I took a shot at it and am attaching the results (tested with gcc 4.2.3 on Ubuntu). My conclusion is that the (relevant bit of) text is as clear as it needs to be - since I could follow it - except for one point:
When it says: """ num shall have the value sign(N)*sign(D)*abs(N)/gcd.
den shall have the value abs(D)/gcd.
"""
... are sign() and abs() supposed to be runtime functions? I implemented them as meta-functions - I'm sure these are in boost somewhere, I just don't know where. Maybe compilers are generally clever enough, or the standard guarantees those functions will be evaluated at compile time? I'm never sure where the line is drawn on this one...
They have to execute at compile time. Whether or not the C++0X constexpr feature can be brought to bear here I really don't know. In my example implementation they were simply "__"-prefixed meta functions.
The attached code is quite straightforward and basically does what the text says it should (I hope), but no more. The main limitation is that it uses static_gcd<> from Boost.Math. That meta-function is parametrised with `unsigned long` instead of `intmax_t` which limits how big the allowed numbers can be. I tried without luck to change the relevant header but I suppose it's not really relevant to this experiment.
This is a show-stopper. One of the basic features of ratio is that you can throw any integral value at it, and it will either hand back the right answer or refuse to compile. Some worrisome results: typedef boost::utility::ratio<1, 0x8000000000000000LL> R9; std::cout << R9::num << '/' << R9::den << '\n'; -1/-9223372036854775808 This paragraph:
A diagnostic shall be emitted if ratio is instantiated with D == 0, or if the absolute value of N or D can not be represented. [Note: These rules ensure that infinite ratios are avoided and that for any negative input, there exists a representable value of its absolute value which is positive. In a two's complement representation, this excludes the most negative value. -- end note]
was intended to cause the above example to fail to compile because abs(0x8000000000000000) < 0. Once we have an intmax_t-based gcd, the ratio arithmetic and less-than comparison will need more work to detect overflow and subsequently refuse to compile:
For each of the class templates in this clause, each template parameter shall refer to a ratio. If the implementation is unable to form the indicatedratio due to overflow, a diagnostic shall be issued.
...
If R1::num * R2::den < R2::num * R1::den, ratio_less derives from true_type, else derives from false_type. Implementations are permitted to use more complex algorithms to compute the above relationship to avoid overflow. If the implementation is not able to avoid overflow, a diagnostic shall be emitted.
In general, N2615 is sprinkled liberally with "diagnostic required". Errors which can be detected at compile time are actively sought out. -Howard