changeset 30859:df26decca96b stable

Tweak check for maximum possible increment of integer ranges (bug #62212). * ibinterp/octave-value/ov.cc (range_numel (T base, double increment, T limit)): Use condition that compensates the impact of floating point representation. * test/range.tst: Tag tests as fixed.
author Markus Mützel <markus.muetzel@gmx.de>
date Wed, 23 Mar 2022 18:27:53 +0100
parents 9b3b0dbb4eba
children fc045a84cb33 2f2e875d93fa
files libinterp/octave-value/ov.cc test/range.tst
diffstat 2 files changed, 8 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/octave-value/ov.cc	Wed Mar 23 15:35:36 2022 +0100
+++ b/libinterp/octave-value/ov.cc	Wed Mar 23 18:27:53 2022 +0100
@@ -3250,16 +3250,16 @@
 
     double abs_increment = std::abs (increment);
 
-    if (abs_increment > max_val)
+    // Technically, this condition should be `abs_increment > max_val`.
+    // But intmax('uint64') is not representable exactly as floating point
+    // number.  Instead, it "rounds" up by 1 to 2^64.  To account for
+    // this, use the following expression which works for all unsigned
+    // integer types.
+    if ((abs_increment-1.) >= max_val)
       return 1;
 
     UT unsigned_increment = range_increment<T> (increment);
 
-    // If the increment wasn't zero before but it is now, the cast to UT
-    // wrapped around. The range can only have one value.
-    if (unsigned_increment == 0)
-      return 1;
-
     return range_numel_aux (base, unsigned_increment, limit);
   }
 
--- a/test/range.tst	Wed Mar 23 15:35:36 2022 +0100
+++ b/test/range.tst	Wed Mar 23 18:27:53 2022 +0100
@@ -608,7 +608,7 @@
 %! endfor
 
 ## integer range with large double increments
-%!test <62212>  # ascending ranges
+%!test <*62212>  # ascending ranges
 %! types = {"int8", "int16", "int32", "int64"};
 %! for i_type = 1:numel (types)
 %!   assert (intmin (types{i_type}) : -double (intmin (types{i_type})) : intmax (types{i_type}), ...
@@ -621,7 +621,7 @@
 %!             [intmin(types{i_type}), intmax(types{i_type})-1]);
 %!   endif
 %! endfor
-%!test <62212>  # descending ranges
+%!test <*62212>  # descending ranges
 %! types = {"int8", "int16", "int32", "int64"};
 %! for i_type = 1:numel (types)
 %!   assert (intmax (types{i_type}) : double (intmin (types{i_type})) : intmin (types{i_type}), ...