This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++11 status.
ratio
arithmetic tweakSection: 21.4.4 [ratio.arithmetic] Status: C++11 Submitter: Howard Hinnant Opened: 2008-12-26 Last modified: 2016-01-28
Priority: Not Prioritized
View all other issues in [ratio.arithmetic].
View all issues with C++11 status.
Discussion:
N2800, 21.4.4 [ratio.arithmetic] lacks a paragraph from the proposal N2661:
ratio arithmetic [ratio.arithmetic]
... If the implementation is unable to form the indicated
ratio
due to overflow, a diagnostic shall be issued.
The lack of a diagnostic on compile-time overflow is a significant lack of functionality. This paragraph could be put back into the WP simply editorially. However in forming this issue I realized that we can do better than that. This paragraph should also allow alternative formulations which go to extra lengths to avoid overflow when possible. I.e. we should not mandate overflow when the implementation can avoid it.
For example:
template <class R1, class R2> struct ratio_multiply { typedef see below} type;The nested typedef type shall be a synonym for
ratio<T1, T2>
whereT1
has the valueR1::num * R2::num
andT2
has the valueR1::den * R2::den
.
Consider the case where intmax_t
is a 64 bit 2's complement signed integer,
and we have:
typedef std::ratio<0x7FFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFF0> R1; typedef std::ratio<8, 7> R2; typedef std::ratio_multiply<R1, R2>::type RT;
According to the present formulation the implementaiton will multiply
0x7FFFFFFFFFFFFFFF * 8
which will result in an overflow and subsequently
require a diagnostic.
However if the implementation is first allowed to divde 0x7FFFFFFFFFFFFFFF
by 7
obtaining 0x1249249249249249 / 1
and divide
8
by 0x7FFFFFFFFFFFFFF0
obtaining 1 / 0x0FFFFFFFFFFFFFFE
,
then the exact result can then be computed without overflow:
[0x7FFFFFFFFFFFFFFF/0x7FFFFFFFFFFFFFF0] * [8/7] = [0x1249249249249249/0x0FFFFFFFFFFFFFFE]
Example implmentation which accomplishes this:
template <class R1, class R2> struct ratio_multiply { private: typedef ratio<R1::num, R2::den> _R3; typedef ratio<R2::num, R1::den> _R4; public: typedef ratio<__ll_mul<_R3::num, _R4::num>::value, __ll_mul<_R3::den, _R4::den>::value> type; };
[ Post Summit: ]
Recommend Tentatively Ready.
Proposed resolution:
Add a paragraph prior to p1 in 21.4.4 [ratio.arithmetic]:
Implementations may use other algorithms to compute the indicated ratios to avoid overflow. If overflow occurs, a diagnostic shall be issued.