changeset 32228:355b4434b45d

VM: Fix problem with trivial ranges (patch #10362). * libinterp/octave-value/ov-range.cc, libinterp/octave-value/ov-range.h (ov_range<double>::could_be_trivial_range): Check that double precision values can be represented as `int` data type. * test/compile/bytecode.tst, test/compile/bytecode_for.m: Add tests with more for-loop expressions.
author Petter T. <petter.vilhelm@gmail.com>
date Thu, 15 Jun 2023 16:03:54 +0200
parents 1ce9acf56351
children 9fddcbde0329
files libinterp/octave-value/ov-range.cc libinterp/octave-value/ov-range.h test/compile/bytecode.tst test/compile/bytecode_for.m
diffstat 4 files changed, 58 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/octave-value/ov-range.cc	Thu Aug 03 18:54:41 2023 +0200
+++ b/libinterp/octave-value/ov-range.cc	Thu Jun 15 16:03:54 2023 +0200
@@ -995,11 +995,38 @@
   if (n <= 1)
     return false;
 
-  double f = m_range.final_value ();
-  if (f > std::numeric_limits<int>::max()
-      || f < std::numeric_limits<int>::min())
+  if (m_range.final_value () > std::numeric_limits<int>::max() ||
+      m_range.final_value () < std::numeric_limits<int>::min())
+    return false;
+  if (m_range.increment () > std::numeric_limits<int>::max() ||
+      m_range.increment () < std::numeric_limits<int>::min())
+    return false;
+  if (m_range.base () > std::numeric_limits<int>::max() ||
+      m_range.base () < std::numeric_limits<int>::min())
+    return false;
+  if (m_range.limit () > std::numeric_limits<int>::max() ||
+      m_range.limit () < std::numeric_limits<int>::min())
+    return false;
+
+  if (std::isnan (m_range.final_value ()))
     return false;
-  if (std::isnan (f))
+  if (std::isnan (m_range.increment ()))
+    return false;
+  if (std::isnan (m_range.base ()))
+    return false;
+  if (std::isnan (m_range.limit ()))
+    return false;
+
+  if (static_cast<int> (m_range.final_value ()) != m_range.final_value ())
+    return false;
+  if (static_cast<int> (m_range.increment ()) != m_range.increment ())
+    return false;
+  if (static_cast<int> (m_range.base ()) != m_range.base ())
+    return false;
+  if (static_cast<int> (m_range.limit ()) != m_range.limit ())
+    return false;
+
+  if (m_range.reverse ())
     return false;
 
   return true;
--- a/libinterp/octave-value/ov-range.h	Thu Aug 03 18:54:41 2023 +0200
+++ b/libinterp/octave-value/ov-range.h	Thu Jun 15 16:03:54 2023 +0200
@@ -56,7 +56,7 @@
 {
 public:
 
-  octave_trivial_range (octave_idx_type numel, double base, double incr)
+  octave_trivial_range (octave_idx_type numel, int base, int incr)
       : m_numel (numel), m_base (base), m_increment(incr) { }
 
   octave_trivial_range () {};
--- a/test/compile/bytecode.tst	Thu Aug 03 18:54:41 2023 +0200
+++ b/test/compile/bytecode.tst	Thu Jun 15 16:03:54 2023 +0200
@@ -87,7 +87,7 @@
 %!test
 %! __enable_vm_eval__ (0, "local");
 %! clear all
-%! key = "1 2 3 4 4 1 3 5 5 4 3 2 1 1 1 4 2 2 16 4 3 3 256 3 2 1  double 1 3 size 2 size 1 2 4 size 2 size 1  double q size 1 size 1 w size 1 size 1 e size 1 size 1 char single single 5 1 11 2 12 key:a val:1 1val:1 key:b val:1 3val:2 4val:2 2key:c val:string ";
+%! key = "1 2 3 4 4 1 3 5 5 1 4 4 4 3 2 1 1 0.200 0.300 0.400 0.400 0.300 0.200 0.100 0.000 0.000 NaN NaN NaN 1 4 2 2 16 4 3 3 256 3 2 1  double 1 3 size 2 size 1 2 4 size 2 size 1  double q size 1 size 1 w size 1 size 1 e size 1 size 1 char single single 5 1 11 2 12 key:a val:1 1val:1 key:b val:1 3val:2 4val:2 2key:c val:string ";
 %!
 %! __compile bytecode_for clear;
 %! bytecode_for ();
--- a/test/compile/bytecode_for.m	Thu Aug 03 18:54:41 2023 +0200
+++ b/test/compile/bytecode_for.m	Thu Jun 15 16:03:54 2023 +0200
@@ -11,11 +11,36 @@
   end
   __printf_assert__ ("%d ", i);
 
+  for i = 1:3:5
+    __printf_assert__ ("%d ", i);
+  end
+  __printf_assert__ ("%d ", i);
+
   for i = 4:-1:1
     __printf_assert__ ("%d ", i);
   end
   __printf_assert__ ("%d ", i);
 
+  for i = 0.2:0.1:0.4
+    __printf_assert__ ("%3.3f ", i);
+  end
+  __printf_assert__ ("%3.3f ", i);
+
+  for i = 0.3:-0.1:0
+    __printf_assert__ ("%3.3f ", i);
+  end
+  __printf_assert__ ("%3.3f ", i);
+
+  for i = 0:NaN:2
+    __printf_assert__ ("%3.3f ", i);
+  end
+  for i = 0:1:NaN
+    __printf_assert__ ("%3.3f ", i);
+  end
+  for i = NaN:1:2
+    __printf_assert__ ("%3.3f ", i);
+  end
+
   for j = 1:4
     break
   end