changeset 28638:98192ec1621f

replace Range with range<double> * __magick_read__.cc, cellfun.cc, data.cc, ls-mat4.cc, max.cc, pr-output.cc, pr-output.h, rand.cc, tril.cc, xpow.cc, xpow.h, ov-base.cc, ov-base.h, ov-range.cc, ov-range.h, ov.cc, ov.h, jit-typeinfo.cc, jit-typeinfo.h, pt-eval.cc, pt-jit.cc, idx-vector.cc, idx-vector.h: Replace all uses of Range with range<double>. * Range.h: Deprecated Range constructors.
author John W. Eaton <jwe@octave.org>
date Thu, 06 Aug 2020 16:28:30 -0400
parents fb37f50d5ba8
children 7ebe185e3818
files libinterp/corefcn/__magick_read__.cc libinterp/corefcn/cellfun.cc libinterp/corefcn/data.cc libinterp/corefcn/ls-mat4.cc libinterp/corefcn/max.cc libinterp/corefcn/pr-output.cc libinterp/corefcn/pr-output.h libinterp/corefcn/rand.cc libinterp/corefcn/tril.cc libinterp/corefcn/xpow.cc libinterp/corefcn/xpow.h libinterp/octave-value/ov-base.cc libinterp/octave-value/ov-base.h libinterp/octave-value/ov-range.cc libinterp/octave-value/ov-range.h libinterp/octave-value/ov.cc libinterp/octave-value/ov.h libinterp/parse-tree/jit-typeinfo.cc libinterp/parse-tree/jit-typeinfo.h libinterp/parse-tree/pt-eval.cc libinterp/parse-tree/pt-jit.cc liboctave/array/Range.h liboctave/array/idx-vector.cc liboctave/array/idx-vector.h
diffstat 24 files changed, 219 insertions(+), 150 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/__magick_read__.cc	Thu Aug 06 15:36:30 2020 -0400
+++ b/libinterp/corefcn/__magick_read__.cc	Thu Aug 06 16:28:30 2020 -0400
@@ -141,17 +141,17 @@
 // width 1.  In those cases, the type will come as scalar instead of range
 // since that's the behavior of the colon operator (1:1:1 will be a scalar,
 // not a range).
-static Range
+static octave::range<double>
 get_region_range (const octave_value& region)
 {
-  Range output;
+  octave::range<double> output;
 
   if (region.is_range ())
     output = region.range_value ();
   else if (region.is_scalar_type ())
     {
       double value = region.scalar_value ();
-      output = Range (value, value);
+      output = octave::range<double> (value, value);
     }
   else if (region.is_matrix_type ())
     {
@@ -159,7 +159,7 @@
       double base = array(0);
       double limit = array(array.numel () - 1);
       double incr = array(1) - base;
-      output = Range (base, limit, incr);
+      output = octave::range<double> (base, incr, limit);
     }
   else
     error ("__magick_read__: unknown datatype for Region option");
@@ -181,8 +181,8 @@
 
     // Subtract 1 to account for 0 indexing.
 
-    const Range rows = get_region_range (pixel_region (0));
-    const Range cols = get_region_range (pixel_region (1));
+    const octave::range<double> rows = get_region_range (pixel_region (0));
+    const octave::range<double> cols = get_region_range (pixel_region (1));
 
     m_row_start = rows.base () - 1;
     m_col_start = cols.base () - 1;
--- a/libinterp/corefcn/cellfun.cc	Thu Aug 06 15:36:30 2020 -0400
+++ b/libinterp/corefcn/cellfun.cc	Thu Aug 06 16:28:30 2020 -0400
@@ -2419,7 +2419,7 @@
       octave_value_list idx (ndims, octave_value::magic_colon_t);
       for (octave_idx_type i = 0; i < n; i++)
         {
-          idx(dim) = Range (lb(i), ub(i));
+          idx(dim) = octave::range<double> (lb(i), ub(i));
           retcell.xelem (i) = x.index_op (idx);
         }
     }
--- a/libinterp/corefcn/data.cc	Thu Aug 06 15:36:30 2020 -0400
+++ b/libinterp/corefcn/data.cc	Thu Aug 06 16:28:30 2020 -0400
@@ -4023,7 +4023,13 @@
     case oct_data_conv::dt_double:
       {
         if (dims.ndims () == 2 && dims(0) == 1)
-          retval = Range (static_cast<double> (val), 0.0, dims(1));
+          {
+            // FIXME: If this optimization provides a significant
+            // benefit, then maybe there should be a special storage
+            // type for constant value arrays.
+            double dval = static_cast<double> (val);
+            retval = octave::range<double>::make_constant (dval, dims(1));
+          }
         else
           retval = NDArray (dims, val);
       }
@@ -4095,7 +4101,10 @@
 
     case oct_data_conv::dt_double:
       if (dims.ndims () == 2 && dims(0) == 1 && octave::math::isfinite (val))
-        retval = Range (val, 0.0, dims(1));  // Packed form
+        // FIXME: If this optimization provides a significant benefit,
+        // then maybe there should be a special storage type for
+        // constant value arrays.
+        retval = octave::range<double>::make_constant (val, dims(1));
       else
         retval = NDArray (dims, val);
       break;
@@ -4161,7 +4170,10 @@
 
     case oct_data_conv::dt_double:
       if (dims.ndims () == 2 && dims(0) == 1 && octave::math::isfinite (val))
-        retval = Range (val, 0.0, dims(1));  // Packed form
+        // FIXME: If this optimization provides a significant benefit,
+        // then maybe there should be a special storage type for
+        // constant value arrays.
+        retval = octave::range<double>::make_constant (val, dims(1));
       else
         retval = NDArray (dims, val);
       break;
@@ -7220,7 +7232,7 @@
 
       if (vals.is_range ())
         {
-          Range r = vals.range_value ();
+          octave::range<double> r = vals.range_value ();
           if (r.increment () == 0)
             vals = r.base ();
         }
--- a/libinterp/corefcn/ls-mat4.cc	Thu Aug 06 15:36:30 2020 -0400
+++ b/libinterp/corefcn/ls-mat4.cc	Thu Aug 06 16:28:30 2020 -0400
@@ -465,7 +465,7 @@
     }
   else if (tc.is_range ())
     {
-      Range r = tc.range_value ();
+      octave::range<double> r = tc.range_value ();
       double base = r.base ();
       double inc = r.increment ();
       octave_idx_type nel = r.numel ();
--- a/libinterp/corefcn/max.cc	Thu Aug 06 15:36:30 2020 -0400
+++ b/libinterp/corefcn/max.cc	Thu Aug 06 16:28:30 2020 -0400
@@ -269,7 +269,7 @@
           {
             if (arg.is_range () && (dim == -1 || dim == 1))
               {
-                Range range = arg.range_value ();
+                octave::range<double> range = arg.range_value ();
                 if (range.numel () < 1)
                   {
                     retval(0) = arg;
--- a/libinterp/corefcn/pr-output.cc	Thu Aug 06 15:36:30 2020 -0400
+++ b/libinterp/corefcn/pr-output.cc	Thu Aug 06 16:28:30 2020 -0400
@@ -1319,7 +1319,7 @@
 
 template <>
 float_display_format
-make_format (const Range& r)
+make_format (const octave::range<double>& r)
 {
   if (free_format)
     return float_display_format ();
@@ -2488,7 +2488,7 @@
 }
 
 void
-octave_print_internal (std::ostream& os, const Range& r,
+octave_print_internal (std::ostream& os, const octave::range<double>& r,
                        bool pr_as_read_syntax, int extra_indent)
 {
   double base = r.base ();
--- a/libinterp/corefcn/pr-output.h	Thu Aug 06 15:36:30 2020 -0400
+++ b/libinterp/corefcn/pr-output.h	Thu Aug 06 16:28:30 2020 -0400
@@ -48,7 +48,6 @@
 class FloatDiagMatrix;
 class NDArray;
 class FloatNDArray;
-class Range;
 class boolMatrix;
 class boolNDArray;
 class charMatrix;
@@ -57,6 +56,11 @@
 class Cell;
 class octave_value;
 
+namespace octave
+{
+  template <typename T> class range;
+}
+
 template <typename T> class intNDArray;
 
 template <typename T>
@@ -91,7 +95,7 @@
 
 template <>
 float_display_format
-make_format (const Range& r);
+make_format (const octave::range<double>& r);
 
 template <>
 float_display_format
@@ -309,7 +313,7 @@
                        int extra_indent = 0);
 
 extern OCTINTERP_API void
-octave_print_internal (std::ostream& os, const Range& r,
+octave_print_internal (std::ostream& os, const octave::range<double>& r,
                        bool pr_as_read_syntax = false,
                        int extra_indent = 0);
 
--- a/libinterp/corefcn/rand.cc	Thu Aug 06 15:36:30 2020 -0400
+++ b/libinterp/corefcn/rand.cc	Thu Aug 06 16:28:30 2020 -0400
@@ -181,7 +181,7 @@
           }
         else if (tmp.is_range ())
           {
-            Range r = tmp.range_value ();
+            octave::range<double> r = tmp.range_value ();
 
             if (! r.all_elements_are_ints ())
               error ("%s: all elements of range must be integers", fcn);
--- a/libinterp/corefcn/tril.cc	Thu Aug 06 15:36:30 2020 -0400
+++ b/libinterp/corefcn/tril.cc	Thu Aug 06 16:28:30 2020 -0400
@@ -286,7 +286,7 @@
         octave_value_list ov_idx;
         std::list<octave_value_list> idx_tmp;
         ov_idx(1) = static_cast<double> (nc+1);
-        ov_idx(0) = Range (1, nr);
+        ov_idx(0) = octave::range<double> (1, nr);
         idx_tmp.push_back (ov_idx);
         ov_idx(1) = static_cast<double> (nc);
         tmp = tmp.resize (dim_vector (0,0));
@@ -301,7 +301,7 @@
               {
                 octave_idx_type nr_limit = (1 > j - k ? 1 : j - k);
                 ov_idx(1) = static_cast<double> (j);
-                ov_idx(0) = Range (nr_limit, nr);
+                ov_idx(0) = octave::range<double> (nr_limit, nr);
                 std::list<octave_value_list> idx;
                 idx.push_back (ov_idx);
 
@@ -316,7 +316,7 @@
               {
                 octave_idx_type nr_limit = (nr < j - k ? nr : j - k);
                 ov_idx(1) = static_cast<double> (j);
-                ov_idx(0) = Range (1, nr_limit);
+                ov_idx(0) = octave::range<double> (1, nr_limit);
                 std::list<octave_value_list> idx;
                 idx.push_back (ov_idx);
 
--- a/libinterp/corefcn/xpow.cc	Thu Aug 06 15:36:30 2020 -0400
+++ b/libinterp/corefcn/xpow.cc	Thu Aug 06 16:28:30 2020 -0400
@@ -711,7 +711,7 @@
 }
 
 octave_value
-elem_xpow (double a, const Range& r)
+elem_xpow (double a, const octave::range<double>& r)
 {
   octave_value retval;
 
@@ -742,7 +742,10 @@
       retval = result;
     }
   else
-    retval = elem_xpow (a, r.matrix_value ());
+    {
+      Matrix tmp = r.array_value ();
+      retval = elem_xpow (a, tmp);
+    }
 
   return retval;
 }
@@ -939,7 +942,7 @@
 }
 
 octave_value
-elem_xpow (const Complex& a, const Range& r)
+elem_xpow (const Complex& a, const octave::range<double>& r)
 {
   octave_value retval;
 
@@ -971,7 +974,10 @@
       retval = result;
     }
   else
-    retval = elem_xpow (a, r.matrix_value ());
+    {
+      Matrix tmp = r.array_value ();
+      retval = elem_xpow (a, tmp);
+    }
 
   return retval;
 }
--- a/libinterp/corefcn/xpow.h	Thu Aug 06 15:36:30 2020 -0400
+++ b/libinterp/corefcn/xpow.h	Thu Aug 06 16:28:30 2020 -0400
@@ -75,7 +75,7 @@
 
 extern OCTINTERP_API octave_value elem_xpow (double a, const Matrix& b);
 extern OCTINTERP_API octave_value elem_xpow (double a, const ComplexMatrix& b);
-extern OCTINTERP_API octave_value elem_xpow (double a, const Range& r);
+extern OCTINTERP_API octave_value elem_xpow (double a, const octave::range<double>& r);
 
 extern OCTINTERP_API octave_value elem_xpow (const Matrix& a, double b);
 extern OCTINTERP_API octave_value elem_xpow (const Matrix& a, const Matrix& b);
@@ -86,7 +86,7 @@
 extern OCTINTERP_API octave_value elem_xpow (const Complex& a, const Matrix& b);
 extern OCTINTERP_API octave_value elem_xpow (const Complex& a,
                                              const ComplexMatrix& b);
-extern OCTINTERP_API octave_value elem_xpow (const Complex& a, const Range& r);
+extern OCTINTERP_API octave_value elem_xpow (const Complex& a, const octave::range<double>& r);
 
 extern OCTINTERP_API octave_value elem_xpow (const ComplexMatrix& a, double b);
 extern OCTINTERP_API octave_value elem_xpow (const ComplexMatrix& a,
--- a/libinterp/octave-value/ov-base.cc	Thu Aug 06 15:36:30 2020 -0400
+++ b/libinterp/octave-value/ov-base.cc	Thu Aug 06 16:28:30 2020 -0400
@@ -811,7 +811,7 @@
   err_wrong_type_arg ("octave_base_value::cellstr_value()", type_name ());
 }
 
-Range
+octave::range<double>
 octave_base_value::range_value (void) const
 {
   err_wrong_type_arg ("octave_base_value::range_value()", type_name ());
--- a/libinterp/octave-value/ov-base.h	Thu Aug 06 15:36:30 2020 -0400
+++ b/libinterp/octave-value/ov-base.h	Thu Aug 06 16:28:30 2020 -0400
@@ -609,7 +609,7 @@
 
   virtual Array<std::string> cellstr_value (void) const;
 
-  virtual Range range_value (void) const;
+  virtual octave::range<double> range_value (void) const;
 
   virtual octave_map map_value (void) const;
 
--- a/libinterp/octave-value/ov-range.cc	Thu Aug 06 15:36:30 2020 -0400
+++ b/libinterp/octave-value/ov-range.cc	Thu Aug 06 16:28:30 2020 -0400
@@ -85,7 +85,7 @@
 {
   octave_base_value *retval = nullptr;
 
-  switch (m_range.numel ())
+  switch (numel ())
     {
     case 1:
       retval = new octave_scalar (m_range.base ());
@@ -96,7 +96,7 @@
       break;
 
     case -2:
-      retval = new octave_matrix (m_range.matrix_value ());
+      retval = new octave_matrix (matrix_value ());
       break;
 
     default:
@@ -146,7 +146,7 @@
         {
           idx_vector i = idx(0).index_vector ();
 
-          if (i.is_scalar () && i(0) < m_range.numel ())
+          if (i.is_scalar () && i(0) < numel ())
             retval = m_range.elem (i(0));
           else
             retval = m_range.index (i);
@@ -163,7 +163,7 @@
     }
   else
     {
-      octave_value tmp (new octave_matrix (m_range.matrix_value ()));
+      octave_value tmp (new octave_matrix (matrix_value ()));
 
       return tmp.index_op (idx, resize_ok);
     }
@@ -191,7 +191,7 @@
 double
 octave_range::double_value (bool) const
 {
-  octave_idx_type nel = m_range.numel ();
+  octave_idx_type nel = numel ();
 
   if (nel == 0)
     err_invalid_conversion ("range", "real scalar");
@@ -205,7 +205,7 @@
 float
 octave_range::float_value (bool) const
 {
-  octave_idx_type nel = m_range.numel ();
+  octave_idx_type nel = numel ();
 
   if (nel == 0)
     err_invalid_conversion ("range", "real scalar");
@@ -219,7 +219,7 @@
 charNDArray
 octave_range::char_array_value (bool) const
 {
-  const Matrix matrix = m_range.matrix_value ();
+  const Matrix matrix = matrix_value ();
   charNDArray retval (dims ());
 
   octave_idx_type nel = numel ();
@@ -235,7 +235,7 @@
 {
   // FIXME: this is a potential waste of memory.
 
-  Matrix m = m_range.matrix_value ();
+  Matrix m = matrix_value ();
 
   return m.all (dim);
 }
@@ -245,7 +245,7 @@
 {
   // FIXME: this is a potential waste of memory.
 
-  Matrix m = m_range.matrix_value ();
+  Matrix m = matrix_value ();
 
   return m.any (dim);
 }
@@ -255,14 +255,14 @@
 {
   return
     (k == 0
-       ? octave_value (DiagMatrix (DiagArray2<double> (m_range.matrix_value ())))
+       ? octave_value (DiagMatrix (DiagArray2<double> (matrix_value ())))
        : octave_value (m_range.diag (k)));
 }
 
 octave_value
 octave_range::diag (octave_idx_type m, octave_idx_type n) const
 {
-  Matrix mat = m_range.matrix_value ();
+  Matrix mat = matrix_value ();
 
   return mat.diag (m, n);
 }
@@ -279,7 +279,7 @@
       if (dims ().numel () > 1)
         warn_array_as_logical (dims ());
 
-      Range r = range_value ();
+      octave::range<double> r = range_value ();
       double base = r.base ();
       double limit = r.limit ();
 
@@ -290,13 +290,13 @@
         {
           /*
           // This tells us whether one element is 0, if arithmetic is exact.
-          double steps_to_zero = base / r.inc ();
+          double steps_to_zero = base / r.increment ();
 
           retval = (steps_to_zero != floor (steps_to_zero));
           */
 
           // FIXME: this is a waste of memory.
-          Matrix m ((m_range.matrix_value ().all ()).all ());
+          Matrix m ((matrix_value ().all ()).all ());
 
           retval = ! m.isempty () && m(0, 0) != 0.0;
         }
@@ -308,7 +308,7 @@
 Complex
 octave_range::complex_value (bool) const
 {
-  octave_idx_type nel = m_range.numel ();
+  octave_idx_type nel = numel ();
 
   if (nel == 0)
     err_invalid_conversion ("range", "complex scalar");
@@ -326,7 +326,7 @@
 
   FloatComplex retval (tmp, tmp);
 
-  octave_idx_type nel = m_range.numel ();
+  octave_idx_type nel = numel ();
 
   if (nel == 0)
     err_invalid_conversion ("range", "complex scalar");
@@ -342,7 +342,7 @@
 boolNDArray
 octave_range::bool_array_value (bool warn) const
 {
-  Matrix m = m_range.matrix_value ();
+  Matrix m = matrix_value ();
 
   if (m.any_element_is_nan ())
     octave::err_nan_to_logical_conversion ();
@@ -366,7 +366,7 @@
 octave_value
 octave_range::convert_to_str_internal (bool pad, bool force, char type) const
 {
-  octave_value tmp (m_range.matrix_value ());
+  octave_value tmp (matrix_value ());
   return tmp.convert_to_str (pad, force, type);
 }
 
@@ -379,55 +379,55 @@
 octave_value
 octave_range::as_single (void) const
 {
-  return FloatMatrix (m_range.matrix_value ());
+  return FloatMatrix (matrix_value ());
 }
 
 octave_value
 octave_range::as_int8 (void) const
 {
-  return int8NDArray (m_range.matrix_value ());
+  return int8NDArray (matrix_value ());
 }
 
 octave_value
 octave_range::as_int16 (void) const
 {
-  return int16NDArray (m_range.matrix_value ());
+  return int16NDArray (matrix_value ());
 }
 
 octave_value
 octave_range::as_int32 (void) const
 {
-  return int32NDArray (m_range.matrix_value ());
+  return int32NDArray (matrix_value ());
 }
 
 octave_value
 octave_range::as_int64 (void) const
 {
-  return int64NDArray (m_range.matrix_value ());
+  return int64NDArray (matrix_value ());
 }
 
 octave_value
 octave_range::as_uint8 (void) const
 {
-  return uint8NDArray (m_range.matrix_value ());
+  return uint8NDArray (matrix_value ());
 }
 
 octave_value
 octave_range::as_uint16 (void) const
 {
-  return uint16NDArray (m_range.matrix_value ());
+  return uint16NDArray (matrix_value ());
 }
 
 octave_value
 octave_range::as_uint32 (void) const
 {
-  return uint32NDArray (m_range.matrix_value ());
+  return uint32NDArray (matrix_value ());
 }
 
 octave_value
 octave_range::as_uint64 (void) const
 {
-  return uint64NDArray (m_range.matrix_value ());
+  return uint64NDArray (matrix_value ());
 }
 
 void
@@ -449,7 +449,7 @@
 {
   bool retval = false;
 
-  octave_idx_type n = m_range.numel ();
+  octave_idx_type n = numel ();
 
   indent (os);
 
@@ -471,7 +471,7 @@
 void
 octave_range::short_disp (std::ostream& os) const
 {
-  octave_idx_type len = m_range.numel ();
+  octave_idx_type len = numel ();
 
   if (len == 0)
     os << "[]";
@@ -524,7 +524,7 @@
 bool
 octave_range::save_ascii (std::ostream& os)
 {
-  Range r = range_value ();
+  octave::range<double> r = range_value ();
   double base = r.base ();
   double limit = r.limit ();
   double inc = r.increment ();
@@ -561,9 +561,12 @@
     error ("load: failed to load range constant");
 
   if (inc != 0)
-    m_range = Range (base, limit, inc);
+    m_range = octave::range<double> (base, limit, inc);
   else
-    m_range = Range (base, inc, static_cast<octave_idx_type> (limit));
+    {
+      octave_idx_type numel = static_cast<octave_idx_type> (limit);
+      m_range = octave::range<double>::make_constant (base, numel);
+    }
 
   return true;
 }
@@ -573,7 +576,7 @@
 {
   char tmp = LS_DOUBLE;
   os.write (reinterpret_cast<char *> (&tmp), 1);
-  Range r = range_value ();
+  octave::range<double> r = range_value ();
   double bas = r.base ();
   double lim = r.limit ();
   double inc = r.increment ();
@@ -608,9 +611,12 @@
   if (swap)
     swap_bytes<8> (&inc);
   if (inc != 0)
-    m_range = Range (bas, lim, inc);
+    m_range = octave::range<double> (bas, lim, inc);
   else
-    m_range = Range (bas, inc, static_cast<octave_idx_type> (lim));
+    {
+      octave_idx_type numel = static_cast<octave_idx_type> (lim);
+      m_range = octave::range<double>::make_constant (bas, numel);
+    }
 
   return true;
 }
@@ -671,7 +677,7 @@
       return false;
     }
 
-  Range r = range_value ();
+  octave::range<double> r = range_value ();
   double range_vals[3];
   range_vals[0] = r.base ();
   range_vals[1] = (r.increment () != 0 ? r.limit () : r.numel ());
@@ -742,17 +748,16 @@
       >= 0)
     {
       retval = true;
-      octave_idx_type nel;
-      if (hdf5_get_scalar_attr (data_hid, H5T_NATIVE_IDX,
-                                "OCTAVE_RANGE_NELEM", &nel))
-        m_range = Range (rangevals[0], rangevals[2], nel);
+
+      // Don't use OCTAVE_RANGE_NELEM attribute, just reconstruct the range.
+
+      if (rangevals[2] != 0)
+        m_range = octave::range<double> (rangevals[0], rangevals[1],
+                                         rangevals[2]);
       else
         {
-          if (rangevals[2] != 0)
-            m_range = Range (rangevals[0], rangevals[1], rangevals[2]);
-          else
-            m_range = Range (rangevals[0], rangevals[2],
-                           static_cast<octave_idx_type> (rangevals[1]));
+          octave_idx_type numel = static_cast<octave_idx_type> (rangevals[1]);
+          m_range = octave::range<double>::make_constant (rangevals[0], numel);
         }
     }
 
@@ -792,6 +797,5 @@
 octave_value
 octave_range::fast_elem_extract (octave_idx_type n) const
 {
-  return (n < m_range.numel ()
-          ? octave_value (m_range.elem (n)) : octave_value ());
+  return (n < numel () ? octave_value (m_range.elem (n)) : octave_value ());
 }
--- a/libinterp/octave-value/ov-range.h	Thu Aug 06 15:36:30 2020 -0400
+++ b/libinterp/octave-value/ov-range.h	Thu Aug 06 16:28:30 2020 -0400
@@ -58,17 +58,26 @@
   octave_range (void)
     : octave_base_value (), m_range (), m_idx_cache () { }
 
-  octave_range (double base, double limit, double inc)
-    : octave_base_value (), m_range (base, limit, inc), m_idx_cache ()
+  octave_range (const octave::range<double>& r)
+    : octave_base_value (), m_range (r), m_idx_cache ()
   {
-    if (m_range.numel () < 0)
+    if (numel () < 0 && numel () != -2)
+      error ("invalid range");
+  }
+
+  octave_range (double base, double limit, double increment)
+    : octave_base_value (), m_range (base, limit, increment), m_idx_cache ()
+  {
+    if (numel () < 0)
       error ("invalid range");
   }
 
   octave_range (const Range& r)
-    : octave_base_value (), m_range (r), m_idx_cache ()
+    : octave_base_value (),
+      m_range (r.base (), r.increment (), r.limit (), r.numel ()),
+      m_idx_cache ()
   {
-    if (m_range.numel () < 0 && m_range.numel () != -2)
+    if (numel () < 0 && numel () != -2)
       error ("invalid range");
   }
 
@@ -78,7 +87,9 @@
   { }
 
   octave_range (const Range& r, const idx_vector& cache)
-    : octave_base_value (), m_range (r), m_idx_cache ()
+    : octave_base_value (),
+      m_range (r.base (), r.increment (), r.limit (), r.numel ()),
+      m_idx_cache ()
   {
     set_idx_cache (cache);
   }
@@ -115,10 +126,12 @@
 
   dim_vector dims (void) const
   {
-    octave_idx_type n = m_range.numel ();
+    octave_idx_type n = numel ();
     return dim_vector (n > 0, n);
   }
 
+  octave_idx_type numel (void) const { return m_range.numel (); }
+
   octave_idx_type nnz (void) const { return m_range.nnz (); }
 
   octave_value resize (const dim_vector& dv, bool fill = false) const;
@@ -133,7 +146,7 @@
 
   octave_value squeeze (void) const { return m_range; }
 
-  octave_value full_value (void) const { return m_range.matrix_value (); }
+  octave_value full_value (void) const { return matrix_value (); }
 
   bool is_defined (void) const { return true; }
 
@@ -150,11 +163,17 @@
   octave_value diag (octave_idx_type m, octave_idx_type n) const;
 
   octave_value sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const
-  { return m_range.sort (dim, mode); }
+  {
+    Matrix tmp = matrix_value ();
+    return tmp.sort (dim, mode);
+  }
 
   octave_value sort (Array<octave_idx_type>& sidx, octave_idx_type dim = 0,
                      sortmode mode = ASCENDING) const
-  { return m_range.sort (sidx, dim, mode); }
+  {
+    Matrix tmp = matrix_value ();
+    return tmp.sort (sidx, dim, mode);
+  }
 
   sortmode issorted (sortmode mode = UNSORTED) const
   { return m_range.issorted (mode); }
@@ -188,16 +207,16 @@
   { return float_value (frc_str_conv); }
 
   Matrix matrix_value (bool = false) const
-  { return m_range.matrix_value (); }
+  { return m_range.array_value (); }
 
   FloatMatrix float_matrix_value (bool = false) const
-  { return m_range.matrix_value (); }
+  { return matrix_value (); }
 
   NDArray array_value (bool = false) const
-  { return m_range.matrix_value (); }
+  { return matrix_value (); }
 
   FloatNDArray float_array_value (bool = false) const
-  { return FloatMatrix (m_range.matrix_value ()); }
+  { return FloatMatrix (matrix_value ()); }
 
   charNDArray char_array_value (bool = false) const;
 
@@ -230,7 +249,7 @@
   uint64_array_value (void) const { return uint64NDArray (array_value ()); }
 
   SparseMatrix sparse_matrix_value (bool = false) const
-  { return SparseMatrix (m_range.matrix_value ()); }
+  { return SparseMatrix (matrix_value ()); }
 
   SparseComplexMatrix sparse_complex_matrix_value (bool = false) const
   { return SparseComplexMatrix (sparse_matrix_value ()); }
@@ -242,18 +261,18 @@
   boolNDArray bool_array_value (bool warn = false) const;
 
   ComplexMatrix complex_matrix_value (bool = false) const
-  { return ComplexMatrix (m_range.matrix_value ()); }
+  { return ComplexMatrix (matrix_value ()); }
 
   FloatComplexMatrix float_complex_matrix_value (bool = false) const
-  { return FloatComplexMatrix (m_range.matrix_value ()); }
+  { return FloatComplexMatrix (matrix_value ()); }
 
   ComplexNDArray complex_array_value (bool = false) const
-  { return ComplexMatrix (m_range.matrix_value ()); }
+  { return ComplexMatrix (matrix_value ()); }
 
   FloatComplexNDArray float_complex_array_value (bool = false) const
-  { return FloatComplexMatrix (m_range.matrix_value ()); }
+  { return FloatComplexMatrix (matrix_value ()); }
 
-  Range range_value (void) const { return m_range; }
+  octave::range<double> range_value (void) const { return m_range; }
 
   octave_value convert_to_str_internal (bool pad, bool force, char type) const;
 
@@ -318,7 +337,7 @@
 
 private:
 
-  Range m_range;
+  octave::range<double> m_range;
 
   idx_vector set_idx_cache (const idx_vector& idx) const
   {
--- a/libinterp/octave-value/ov.cc	Thu Aug 06 15:36:30 2020 -0400
+++ b/libinterp/octave-value/ov.cc	Thu Aug 06 16:28:30 2020 -0400
@@ -1008,7 +1008,7 @@
   : rep ()
 {
   double scalar;
-  Range range;
+  octave::range<double> range;
   NDArray array;
   boolNDArray mask;
   idx_vector::idx_class_type idx_class;
@@ -1088,6 +1088,14 @@
   maybe_mutate ();
 }
 
+octave_value::octave_value (const octave::range<double>& r, bool force_range)
+  : rep (force_range || ! Vdisable_range
+         ? dynamic_cast<octave_base_value *> (new octave_range (r))
+         : dynamic_cast<octave_base_value *> (new octave_matrix (r.array_value ())))
+{
+  maybe_mutate ();
+}
+
 octave_value::octave_value (const octave_map& m)
   : rep (new octave_struct (m))
 {
@@ -2088,7 +2096,7 @@
 XVALUE_EXTRACTOR (Cell, xcell_value, cell_value)
 XVALUE_EXTRACTOR (Array<std::string>, xcellstr_value, cellstr_value)
 
-XVALUE_EXTRACTOR (Range, xrange_value, range_value)
+XVALUE_EXTRACTOR (octave::range<double>, xrange_value, range_value)
 
 XVALUE_EXTRACTOR (octave_map, xmap_value, map_value)
 XVALUE_EXTRACTOR (octave_scalar_map, xscalar_map_value, scalar_map_value)
@@ -2857,21 +2865,22 @@
   make_range (const octave_value& base, const octave_value& increment,
               const octave_value& limit, bool for_cmd_expr)
   {
+    // FIXME: ultimately we will eliminate these casts and create range
+    // objects that properly correspond to the type T instead of always
+    // returning range<double>.
+
     if (base.isempty () || increment.isempty () || limit.isempty ())
-      return octave_value (Range (), for_cmd_expr);
-
-    T b = octave_value_extract<T> (base);
-    T i = octave_value_extract<T> (increment);
-    T l = octave_value_extract<T> (limit);
-
-    // FIXME: ultimately, we will eliminate these casts and create range
-    // objects that properly correspond to the type T.
-
-    double db = static_cast<double> (b);
-    double di = static_cast<double> (i);
-    double dl = static_cast<double> (l);
-
-    return octave_value (Range (db, dl, di), for_cmd_expr);
+      return octave_value (octave::range<double> (), for_cmd_expr);
+
+    T base_val = octave_value_extract<T> (base);
+    T increment_val = octave_value_extract<T> (increment);
+    T limit_val = octave_value_extract<T> (limit);
+
+    octave::range<double> r (static_cast<double> (base_val),
+                             static_cast<double> (increment_val),
+                             static_cast<double> (limit_val));
+
+    return octave_value (r, for_cmd_expr);
   }
 
   template <>
@@ -2881,25 +2890,25 @@
   {
     octave_value retval;
 
+    bool dq_str = (base.is_dq_string () || increment.is_dq_string ()
+                   || limit.is_dq_string ());
+
+    char type = dq_str ? '"' : '\'';
+
     if (base.isempty () || increment.isempty () || limit.isempty ())
-      retval = octave_value (Range (), for_cmd_expr);
+      retval = octave_value ("", type);
     else
       {
         Matrix mtx_base = base.matrix_value (true);
         Matrix mtx_increment = increment.matrix_value (true);
         Matrix mtx_limit = limit.matrix_value (true);
 
-        double b = mtx_base(0);
-        double i = mtx_increment(0);
-        double l = mtx_limit(0);
-
-        retval = octave_value (Range (b, l, i), for_cmd_expr);
+        range<double> tmp (mtx_base(0), mtx_increment(0), mtx_limit(0));
+
+        retval = octave_value (tmp, for_cmd_expr);
       }
 
-    bool dq_str = (base.is_dq_string () || increment.is_dq_string ()
-                   || limit.is_dq_string ());
-
-    return retval.convert_to_str (false, true, dq_str ? '"' : '\'');
+    return retval.convert_to_str (false, true, type);
   }
 
   octave_value
--- a/libinterp/octave-value/ov.h	Thu Aug 06 15:36:30 2020 -0400
+++ b/libinterp/octave-value/ov.h	Thu Aug 06 16:28:30 2020 -0400
@@ -273,8 +273,11 @@
                 bool zero_based = false, bool cache_index = false);
   octave_value (const Array<std::string>& cellstr);
   octave_value (const idx_vector& idx, bool lazy = true);
+  OCTAVE_DEPRECATED (7, "use 'octave_value (range<double>&)' instead")
   octave_value (double base, double limit, double inc);
+  OCTAVE_DEPRECATED (7, "use 'octave_value (range<double>&)' instead")
   octave_value (const Range& r, bool force_range = false);
+  octave_value (const octave::range<double>& r, bool force_range = false);
   octave_value (const octave_map& m);
   octave_value (const octave_scalar_map& m);
   octave_value (const std::map<std::string, octave_value>&);
@@ -937,7 +940,7 @@
   Array<std::string> cellstr_value (void) const
   { return rep->cellstr_value (); }
 
-  Range range_value (void) const
+  octave::range<double> range_value (void) const
   { return rep->range_value (); }
 
   octave_map map_value (void) const;
@@ -1149,7 +1152,7 @@
 
   Array<std::string> xcellstr_value (const char *fmt, ...) const;
 
-  Range xrange_value (const char *fmt, ...) const;
+  octave::range<double> xrange_value (const char *fmt, ...) const;
 
   octave_map xmap_value (const char *fmt, ...) const;
 
--- a/libinterp/parse-tree/jit-typeinfo.cc	Thu Aug 06 15:36:30 2020 -0400
+++ b/libinterp/parse-tree/jit-typeinfo.cc	Thu Aug 06 16:28:30 2020 -0400
@@ -116,7 +116,7 @@
   extern "C" octave_idx_type
   octave_jit_compute_nelem (double base, double limit, double inc)
   {
-    Range rng = Range (base, limit, inc);
+    range<double> rng (base, inc, limit);
     return rng.numel ();
   }
 
@@ -167,7 +167,7 @@
   extern "C" octave_base_value *
   octave_jit_cast_any_range (jit_range *rng)
   {
-    Range temp (*rng);
+    range<double> temp (*rng);
     octave_value ret (temp);
     octave_base_value *rep = ret.internal_rep ();
     rep->grab ();
@@ -480,7 +480,7 @@
   bool
   jit_range::all_elements_are_ints () const
   {
-    Range r (*this);
+    range<double> r (*this);
     return r.all_elements_are_ints ();
   }
 
--- a/libinterp/parse-tree/jit-typeinfo.h	Thu Aug 06 15:36:30 2020 -0400
+++ b/libinterp/parse-tree/jit-typeinfo.h	Thu Aug 06 16:28:30 2020 -0400
@@ -52,14 +52,14 @@
   struct
   jit_range
   {
-    jit_range (const Range& from)
+    jit_range (const range<double>& from)
       : m_base (from.base ()), m_limit (from.limit ()), m_inc (from.inc ()),
         m_nelem (from.numel ())
     { }
 
-    operator Range () const
+    operator range<double> () const
     {
-      return Range (m_base, m_limit, m_inc);
+      return range<double> (m_base, m_inc, m_limit);
     }
 
     bool all_elements_are_ints (void) const;
--- a/libinterp/parse-tree/pt-eval.cc	Thu Aug 06 15:36:30 2020 -0400
+++ b/libinterp/parse-tree/pt-eval.cc	Thu Aug 06 16:28:30 2020 -0400
@@ -2529,7 +2529,7 @@
 
     if (rhs.is_range ())
       {
-        Range rng = rhs.range_value ();
+        octave::range<double> rng = rhs.range_value ();
 
         octave_idx_type steps = rng.numel ();
 
--- a/libinterp/parse-tree/pt-jit.cc	Thu Aug 06 15:36:30 2020 -0400
+++ b/libinterp/parse-tree/pt-jit.cc	Thu Aug 06 16:28:30 2020 -0400
@@ -715,7 +715,7 @@
       }
     else if (ty == jit_typeinfo::get_range ())
       {
-        Range rv = v.range_value ();
+        range<double> rv = v.range_value ();
         m_result = m_factory.create<jit_const_range> (rv);
       }
     else if (ty == jit_typeinfo::get_complex ())
@@ -2314,7 +2314,7 @@
   {
     if (bounds.is_range ())
       {
-        Range rng = bounds.range_value ();
+        range<double> rng = bounds.range_value ();
         return rng.numel ();
       }
 
--- a/liboctave/array/Range.h	Thu Aug 06 15:36:30 2020 -0400
+++ b/liboctave/array/Range.h	Thu Aug 06 16:28:30 2020 -0400
@@ -355,6 +355,7 @@
 {
 public:
 
+  OCTAVE_DEPRECATED (7, "use the 'octave::range<double>' class instead")
   Range (void)
     : m_base (0), m_limit (0), m_inc (0), m_numel (0)
   { }
@@ -364,6 +365,7 @@
   // that mimics the behavior of the other Range class constructors that
   // reset limit to the computed final value.
 
+  OCTAVE_DEPRECATED (7, "use the 'octave::range<double>' class instead")
   Range (const octave::range<double>& r)
     : m_base (r.base ()), m_limit (r.final_value ()), m_inc (r.increment ()),
       m_numel (r.numel ())
@@ -375,6 +377,7 @@
 
   ~Range (void) = default;
 
+  OCTAVE_DEPRECATED (7, "use the 'octave::range<double>' class instead")
   Range (double b, double l)
     : m_base (b), m_limit (l), m_inc (1), m_numel (numel_internal ())
   {
@@ -382,6 +385,7 @@
       m_limit = limit_internal ();
   }
 
+  OCTAVE_DEPRECATED (7, "use the 'octave::range<double>' class instead")
   Range (double b, double l, double i)
     : m_base (b), m_limit (l), m_inc (i), m_numel (numel_internal ())
   {
@@ -395,6 +399,7 @@
   // For operators' usage (to preserve element count) and to create
   // constant row vectors (obsolete usage).
 
+  OCTAVE_DEPRECATED (7, "use the 'octave::range<double>' class instead")
   Range (double b, double i, octave_idx_type n)
     : m_base (b), m_limit (b + (n-1) * i), m_inc (i), m_numel (n)
   {
--- a/liboctave/array/idx-vector.cc	Thu Aug 06 15:36:30 2020 -0400
+++ b/liboctave/array/idx-vector.cc	Thu Aug 06 16:28:30 2020 -0400
@@ -132,7 +132,7 @@
     octave::err_invalid_index (start + (len-1)*step);
 }
 
-idx_vector::idx_range_rep::idx_range_rep (const Range& r)
+idx_vector::idx_range_rep::idx_range_rep (const octave::range<double>& r)
   : idx_base_rep (), start (0), len (r.numel ()), step (1)
 {
   if (len < 0)
@@ -207,11 +207,11 @@
   return os;
 }
 
-Range
+octave::range<double>
 idx_vector::idx_range_rep::unconvert (void) const
 {
-  return Range (static_cast<double> (start+1),
-                static_cast<double> (step), len);
+  return octave::range<double>::make_n_element_range
+    (static_cast<double> (start+1), static_cast<double> (step), len);
 }
 
 Array<octave_idx_type>
@@ -1226,7 +1226,7 @@
 }
 
 void idx_vector::unconvert (idx_class_type& iclass,
-                            double& scalar, Range& range,
+                            double& scalar, octave::range<double>& range,
                             Array<double>& array, Array<bool>& mask) const
 {
   iclass = idx_class ();
--- a/liboctave/array/idx-vector.h	Thu Aug 06 15:36:30 2020 -0400
+++ b/liboctave/array/idx-vector.h	Thu Aug 06 16:28:30 2020 -0400
@@ -41,14 +41,21 @@
 
 template <typename T> class Array;
 template <typename T> class Sparse;
-class Range;
+
+namespace octave
+{
+  template <typename T> class range;
+}
 
 // Design rationale:
-// idx_vector is a reference-counting, polymorphic pointer, that can contain
-// 4 types of index objects: a magic colon, a range, a scalar, or an index vector.
-// Polymorphic methods for single element access are provided, as well as
-// templates implementing "early dispatch", i.e., hoisting the checks for index
-// type out of loops.
+//
+// idx_vector is a reference-counting, polymorphic pointer, that can
+// contain 4 types of index objects: a magic colon, a range, a scalar,
+// or an index vector.
+//
+// Polymorphic methods for single element access are provided, as well
+// as templates implementing "early dispatch", i.e., hoisting the checks
+// for index type out of loops.
 
 class
 OCTAVE_API
@@ -173,7 +180,7 @@
     idx_range_rep (octave_idx_type _start, octave_idx_type _limit,
                    octave_idx_type _step);
 
-    idx_range_rep (const Range&);
+    idx_range_rep (const octave::range<double>&);
 
     // No copying!
 
@@ -212,7 +219,7 @@
 
     std::ostream& print (std::ostream& os) const;
 
-    Range unconvert (void) const;
+    octave::range<double> unconvert (void) const;
 
     Array<octave_idx_type> as_array (void);
 
@@ -525,7 +532,7 @@
 
   idx_vector (const Array<bool>& nda);
 
-  idx_vector (const Range& r)
+  idx_vector (const octave::range<double>& r)
     : rep (new idx_range_rep (r))
   { chkerr (); }
 
@@ -1013,7 +1020,7 @@
 
   // Unconverts the index to a scalar, Range, double array or a mask.
   void unconvert (idx_class_type& iclass,
-                  double& scalar, Range& range,
+                  double& scalar, octave::range<double>& range,
                   Array<double>& array, Array<bool>& mask) const;
 
   Array<octave_idx_type> as_array (void) const;