diff liboctave/array/Range.cc @ 28592:e70c859c4bff

allow infinite limits on for loop ranges (bug #45143) * ov.cc (octave_value::octave_value (const Range&, bool)): If force_range is false, throw error if range is not OK. * Range.h, Range.cc (Range::ok): New function. (Range::numel_internal): Return one less than the maximum possible octave_idx_type value if infinite range is detected. (Range::init): Don't set m_limit if limit is infinite. (Range::Range (double, double)): Likewise. (Range::Range (double, double, double)): Likewise. (Range::Range (double, double, octave_idx_type): Trust supplied value of numel. * for.tst: New tests. * pt-eval.cc (tree_evaluator::visit_simple_for_command): Warn if range limit is infinite.
author John W. Eaton <jwe@octave.org>
date Fri, 24 Jul 2020 01:01:35 -0400
parents 455fe4a6f22c
children 83172e1c77f2
line wrap: on
line diff
--- a/liboctave/array/Range.cc	Tue Jul 21 17:05:15 2020 -0400
+++ b/liboctave/array/Range.cc	Fri Jul 24 01:01:35 2020 -0400
@@ -527,9 +527,16 @@
 {
   octave_idx_type retval = -1;
 
-  if (m_inc == 0
-      || (m_limit > m_base && m_inc < 0)
-      || (m_limit < m_base && m_inc > 0))
+  if (! octave::math::isfinite (m_base) || ! octave::math::isfinite (m_inc)
+      || octave::math::isnan (m_limit))
+    retval = -2;
+  else if (octave::math::isinf (m_limit)
+           && ((m_inc > 0 && m_limit > 0)
+               || (m_inc < 0 && m_limit < 0)))
+    retval = std::numeric_limits<octave_idx_type>::max () - 1;
+  else if (m_inc == 0
+           || (m_limit > m_base && m_inc < 0)
+           || (m_limit < m_base && m_inc > 0))
     {
       retval = 0;
     }
@@ -539,8 +546,8 @@
 
       double tmp = tfloor ((m_limit - m_base + m_inc) / m_inc, ct);
 
-      octave_idx_type n_elt = (tmp > 0.0 ? static_cast<octave_idx_type> (tmp)
-                                         : 0);
+      octave_idx_type n_elt = (tmp > 0.0
+                               ? static_cast<octave_idx_type> (tmp) : 0);
 
       // If the final element that we would compute for the range is equal to
       // the limit of the range, or is an adjacent floating point number,
@@ -559,8 +566,8 @@
             n_elt++;
         }
 
-      retval = (n_elt < std::numeric_limits<octave_idx_type>::max () - 1)
-               ? n_elt : -1;
+      retval = ((n_elt < std::numeric_limits<octave_idx_type>::max ())
+                ? n_elt : -1);
     }
 
   return retval;
@@ -569,12 +576,7 @@
 double
 Range::limit_internal (void) const
 {
-  double new_limit;
-
-  if (m_inc > 0)
-    new_limit = max ();
-  else
-    new_limit = min ();
+  double new_limit = m_inc > 0 ? max () : min ();
 
   // If result must be an integer then force the new_limit to be one.
   if (all_elements_are_ints ())
@@ -587,5 +589,7 @@
 Range::init (void)
 {
   m_numel = numel_internal ();
-  m_limit = limit_internal ();
+
+  if (! octave::math::isinf (m_limit))
+    m_limit = limit_internal ();
 }