948. ratio arithmetic tweak

Section: 23.16.4 [ratio.arithmetic] Status: C++11 Submitter: Howard Hinnant Opened: 2008-12-26 Last modified: 2016-02-10

Priority: Not Prioritized

View all other issues in [ratio.arithmetic].

View all issues with C++11 status.

Discussion:

N2800, 23.16.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> 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;
};

[ Post Summit: ]

Recommend Tentatively Ready.

Proposed resolution:

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

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