Title
ratio arithmetic tweak
Status
c++11
Section
[ratio.arithmetic]
Submitter
Howard Hinnant

Created on 2008-12-26.00:00:00 last changed 154 months ago

Messages

Date: 2010-10-21.18:28:33

Proposed resolution:

Add a paragraph prior to p1 in [ratio.arithmetic]:

Implementations may use other algorithms to compute the indicated ratios to avoid overflow. If overflow occurs, a diagnostic shall be issued.

Date: 2010-10-21.18:28:33

[ Post Summit: ]

Recommend Tentatively Ready.

Date: 2008-12-26.00:00:00

N2800, [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> where T1 has the value R1::num * R2::num and T2 has the value R1::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;
};
History
Date User Action Args
2011-08-23 20:07:26adminsetstatus: wp -> c++11
2010-10-21 18:28:33adminsetmessages: + msg4498
2010-10-21 18:28:33adminsetmessages: + msg4497
2008-12-26 00:00:00admincreate