Strange, my gcc 7.5.0 so far did not complain here, even in a minimal example and even though it can be problematic when you have to rely on the exact values. Which gcc version do the buildbots use?
The problem boils down to that
double (binary64) cannot hold the maximal value of
long (int64), same for
float (binary32) and
What happens in the 32-bit case, analogous for the 64-bit case:
int i = std::numeric_limits<int>::max ();
float f = i;
// i = 2^31 - 1 = 2147483647
// = 0111 1111 1111 1111 1111 1111 1111 1111
// |---- fraction part of f (*) ---|
// (*) 23 bit and implicit one
Thus the value stored exceeds the precision of
f and is rounded up to the nearest floating-point number that is 2^31 = 2147483648.
Both cases are a little different
For the first error
oct-stream.cc (line 141) the question is, does the value stored in
double d exceed the maximum possible index size?
if (d > std::numeric_limits<octave_idx_type>::max ())
The question is correctly translated to C++.
flintmax() would put a too strict limit 2^53 on the permitted range 2^63-1, even though
d can never address the full range of possible indices. A general problem of using double for indexing
This warning can be maybe fixed with
// Note: +1.0 to avoid implicit rounding warning!
if (d >= (std::numeric_limits<octave_idx_type>::max () + 1.0))
that is making the implicit rounding explicit.
In the case of
xisint(T x) the question is, whether a conversion from “double” or “float” to “int” (int32) will succeed (not overflow). Only in case of “float” the warning is thrown, the “double” usages of the code are fine. Maybe a similar fix is fine too:
template <typename T>
static inline bool
xisint (T x)
// Note: max () + 1.0 to avoid implicit rounding warning!
return (octave::math::x_nint (x) == x
&& ((x >= 0 && x < (std::numeric_limits<int>::max () + 1.0))
|| (x <= 0 && x >= std::numeric_limits<int>::min ())));
I also relaxed the bounds by one. Previously, it was INT_MIN < x < INT_MAX, now I use the “<=” comparison (in the first case implicitly). To me it is not obvious why we have to go one stop inside the bounds to be correct here and the Octave BIST does not complain.
I would apply those changes only if it really helps omitting the correct compiler warnings.