# HG changeset patch # User John W. Eaton # Date 1647499973 14400 # Node ID 97504d2edcc70a6c649e0fc15510c132b3463a41 # Parent d874069706762a25b08555b39595bfefb22cef49# Parent 2989202f92f8059d26f757f940acfbb22efa28af maint: Merge stable to default. diff -r d87406970676 -r 97504d2edcc7 libinterp/octave-value/ov-base.cc --- a/libinterp/octave-value/ov-base.cc Wed Mar 16 18:45:11 2022 +0100 +++ b/libinterp/octave-value/ov-base.cc Thu Mar 17 02:52:53 2022 -0400 @@ -810,18 +810,22 @@ err_wrong_type_arg ("octave_base_value::cellstr_value()", type_name ()); } +octave::range +octave_base_value::range_value (void) const +{ + err_wrong_type_arg ("octave_base_value::range_value()", type_name ()); +} + +// For now, disable all but range. + +#if 0 + octave::range octave_base_value::float_range_value (void) const { err_wrong_type_arg ("octave_base_value::float_range_value()", type_name ()); } -octave::range -octave_base_value::range_value (void) const -{ - err_wrong_type_arg ("octave_base_value::range_value()", type_name ()); -} - octave::range octave_base_value::int8_range_value (void) const { @@ -870,6 +874,8 @@ err_wrong_type_arg ("octave_base_value::uint64_range_value()", type_name ()); } +#endif + octave_map octave_base_value::map_value (void) const { diff -r d87406970676 -r 97504d2edcc7 libinterp/octave-value/ov-base.h --- a/libinterp/octave-value/ov-base.h Wed Mar 16 18:45:11 2022 +0100 +++ b/libinterp/octave-value/ov-base.h Thu Mar 17 02:52:53 2022 -0400 @@ -630,9 +630,13 @@ virtual Array cellstr_value (void) const; - virtual octave::range float_range_value (void) const; + virtual octave::range range_value (void) const; + + // For now, disable all but range. - virtual octave::range range_value (void) const; +#if 0 + + virtual octave::range float_range_value (void) const; virtual octave::range int8_range_value (void) const; @@ -650,6 +654,8 @@ virtual octave::range uint64_range_value (void) const; +#endif + virtual octave_map map_value (void) const; virtual octave_scalar_map scalar_map_value (void) const; diff -r d87406970676 -r 97504d2edcc7 libinterp/octave-value/ov-range.cc --- a/libinterp/octave-value/ov-range.cc Wed Mar 16 18:45:11 2022 +0100 +++ b/libinterp/octave-value/ov-range.cc Thu Mar 17 02:52:53 2022 -0400 @@ -67,10 +67,14 @@ #if defined (HAVE_HDF5) template <> -octave_hdf5_id ov_range::hdf5_save_type = H5T_NATIVE_FLOAT; +octave_hdf5_id ov_range::hdf5_save_type = H5T_NATIVE_DOUBLE; + +// For now, disable all but ov_range. + +# if 0 template <> -octave_hdf5_id ov_range::hdf5_save_type = H5T_NATIVE_DOUBLE; +octave_hdf5_id ov_range::hdf5_save_type = H5T_NATIVE_FLOAT; template <> octave_hdf5_id ov_range::hdf5_save_type = H5T_NATIVE_INT8; @@ -96,15 +100,21 @@ template <> octave_hdf5_id ov_range::hdf5_save_type = H5T_NATIVE_UINT64; +# endif + #else template <> +octave_hdf5_id ov_range::hdf5_save_type = 0; + +// For now, disable all but ov_range. + +#if 0 + +template <> octave_hdf5_id ov_range::hdf5_save_type = 0; template <> -octave_hdf5_id ov_range::hdf5_save_type = 0; - -template <> octave_hdf5_id ov_range::hdf5_save_type = 0; template <> @@ -128,14 +138,20 @@ template <> octave_hdf5_id ov_range::hdf5_save_type = 0; +# endif + #endif +DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA (ov_range, + "range", "double"); + +// For now, disable all but ov_range. + +#if 0 + DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA (ov_range, "float_range", "single"); -DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA (ov_range, - "range", "double"); - DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA (ov_range, "int8_range", "int8"); @@ -160,6 +176,8 @@ DEFINE_TEMPLATE_OV_TYPEID_FUNCTIONS_AND_DATA (ov_range, "uint64_range", "uint64"); +#endif + template static octave_base_value * default_numeric_conversion_function (const octave_base_value& a) @@ -395,6 +413,17 @@ } template +octave::range +ov_range::range_value (void) const +{ + err_wrong_type_arg ("ov_range::range_value()", type_name ()); +} + +// For now, disable all but ov_range. + +#if 0 + +template octave::range ov_range::float_range_value (void) const { @@ -402,13 +431,6 @@ } template -octave::range -ov_range::range_value (void) const -{ - err_wrong_type_arg ("ov_range::range_value()", type_name ()); -} - -template octave::range ov_range::int8_range_value (void) const { @@ -464,6 +486,8 @@ err_wrong_type_arg ("ov_range::uint64_range_value ()", type_name ()); } +#endif + template octave_value ov_range::convert_to_str_internal (bool pad, bool force, char type) const @@ -691,6 +715,10 @@ // specialize for saving with "reverse" flag +// For now, disable all but ov_range. + +#if 0 + template <> bool ov_range::save_ascii (std::ostream& os) @@ -719,6 +747,8 @@ return xsave_ascii (os, m_range, true); } +#endif + template bool xload_ascii (std::istream& is, octave::range& r, const bool with_reverse) @@ -756,6 +786,10 @@ // specialize for loading with "reverse" flag +// For now, disable all but ov_range. + +#if 0 + template <> bool ov_range::load_ascii (std::istream& is) @@ -784,6 +818,8 @@ return xload_ascii (is, m_range, true); } +#endif + /* %!test %! a = b = 1:4; @@ -844,6 +880,10 @@ return xsave_binary (os, save_as_floats, m_range, false); } +// For now, disable all but ov_range. + +#if 0 + template <> bool ov_range::save_binary (std::ostream& os, bool save_as_floats) @@ -872,6 +912,8 @@ return xsave_binary (os, save_as_floats, m_range, true); } +#endif + template bool xload_binary (std::istream& is, bool swap, @@ -923,6 +965,10 @@ return xload_binary (is, swap, fmt, m_range, false); } +// For now, disable all but ov_range. + +#if 0 + template <> bool ov_range::load_binary (std::istream& is, bool swap, @@ -955,6 +1001,8 @@ return xload_binary (is, swap, fmt, m_range, true); } +#endif + /* %!test %! a = b = 1:4; @@ -1102,6 +1150,10 @@ #endif } +// For now, disable all but ov_range. + +#if 0 + template <> bool ov_range::save_hdf5 (octave_hdf5_id loc_id, const char *name, @@ -1178,6 +1230,8 @@ #endif } +#endif + #if defined (HAVE_HDF5) template @@ -1261,6 +1315,10 @@ #endif } +// For now, disable all but ov_range. + +#if 0 + template <> bool ov_range::load_hdf5 (octave_hdf5_id loc_id, const char *name) @@ -1325,6 +1383,8 @@ #endif } +#endif + /* %!testif HAVE_HDF5 %! a = b = 1:4; @@ -1384,15 +1444,19 @@ // Specializations. template <> -octave::range -ov_range::float_range_value (void) const +octave::range +ov_range::range_value (void) const { return m_range; } +// For now, disable all but ov_range. + +#if 0 + template <> -octave::range -ov_range::range_value (void) const +octave::range +ov_range::float_range_value (void) const { return m_range; } @@ -1453,6 +1517,8 @@ return m_range; } +#endif + template <> octave::idx_vector ov_range::index_vector (bool require_integers) const diff -r d87406970676 -r 97504d2edcc7 libinterp/octave-value/ov-range.h --- a/libinterp/octave-value/ov-range.h Wed Mar 16 18:45:11 2022 +0100 +++ b/libinterp/octave-value/ov-range.h Thu Mar 17 02:52:53 2022 -0400 @@ -32,6 +32,7 @@ #include #include +#include #include "Array-fwd.h" #include "Range.h" @@ -50,7 +51,8 @@ class octave_value_list; -// Range values. +// For now, we only need ov_range but we don't attempt to +// enforce that restriction. template class @@ -384,9 +386,13 @@ return raw_array_value (); } - OCTINTERP_API octave::range float_range_value (void) const; + OCTINTERP_API octave::range range_value (void) const; + +// For now, disable all but ov_range. - OCTINTERP_API octave::range range_value (void) const; +#if 0 + + OCTINTERP_API octave::range float_range_value (void) const; OCTINTERP_API octave::range int8_range_value (void) const; @@ -404,6 +410,8 @@ OCTINTERP_API octave::range uint64_range_value (void) const; +#endif + OCTINTERP_API octave_value convert_to_str_internal (bool pad, bool force, char type) const; @@ -494,8 +502,13 @@ DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA }; +DECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS (ov_range, double) + +// For now, disable all but ov_range. + +#if 0 + DECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS (ov_range, float) -DECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS (ov_range, double) DECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS (ov_range, octave_int8) DECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS (ov_range, octave_int16) DECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS (ov_range, octave_int32) @@ -505,17 +518,23 @@ DECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS (ov_range, octave_uint32) DECLARE_TEMPLATE_OV_TYPEID_SPECIALIZATIONS (ov_range, octave_uint64) +#endif + // Specializations. template <> +OCTINTERP_API octave::range +ov_range::range_value (void) const; + +// For now, disable all but ov_range. + +#if 0 + +template <> OCTINTERP_API octave::range ov_range::float_range_value (void) const; template <> -OCTINTERP_API octave::range -ov_range::range_value (void) const; - -template <> OCTINTERP_API octave::range ov_range::int8_range_value (void) const; @@ -547,6 +566,8 @@ OCTINTERP_API octave::range ov_range::uint64_range_value (void) const; +#endif + // The following specializations are here to preserve previous Range // performance until solutions can be generalized for other types. @@ -576,8 +597,13 @@ ov_range::print_raw (std::ostream& os, bool pr_as_read_syntax) const; +typedef ov_range octave_double_range; + +// For now, disable all but ov_range. + +#if 0 + typedef ov_range octave_float_range; -typedef ov_range octave_double_range; typedef ov_range octave_int8_range; typedef ov_range octave_int16_range; @@ -589,6 +615,8 @@ typedef ov_range octave_uint32_range; typedef ov_range octave_uint64_range; +#endif + typedef octave_double_range octave_range; #endif diff -r d87406970676 -r 97504d2edcc7 libinterp/octave-value/ov.cc --- a/libinterp/octave-value/ov.cc Wed Mar 16 18:45:11 2022 +0100 +++ b/libinterp/octave-value/ov.cc Thu Mar 17 02:52:53 2022 -0400 @@ -29,6 +29,8 @@ #include +#include + #include "data-conv.h" #include "quit.h" #include "str-vec.h" @@ -1091,23 +1093,18 @@ return dynamic_cast (new octave_matrix (r.matrix_value ())); } -octave_value::octave_value (const octave::range& r, char type, - bool /*force_range*/) -#if 0 - : m_rep (force_range || optimize_range - ? dynamic_cast (new octave_char_range (r, type)) - : dynamic_cast (type == '"' - ? new octave_char_matrix_dq_str (r.array_value ()) - : new octave_char_matrix_sq_str (r.array_value ()))) -#else - : m_rep (type == '"' - ? new octave_char_matrix_dq_str (r.array_value ()) - : new octave_char_matrix_sq_str (r.array_value ())) -#endif +octave_value::octave_value (const octave::range& r, bool force_range) + : m_rep (force_range || Voptimize_range + ? dynamic_cast (new ov_range (r)) + : dynamic_cast (new octave_matrix (r.array_value ()))) { maybe_mutate (); } +// For now, disable all but range. + +#if 0 + octave_value::octave_value (const octave::range& r, bool force_range) : m_rep (force_range || Voptimize_range ? dynamic_cast (new ov_range (r)) @@ -1116,14 +1113,6 @@ maybe_mutate (); } -octave_value::octave_value (const octave::range& r, bool force_range) - : m_rep (force_range || Voptimize_range - ? dynamic_cast (new ov_range (r)) - : dynamic_cast (new octave_matrix (r.array_value ()))) -{ - maybe_mutate (); -} - octave_value::octave_value (const octave::range& r, bool force_range) : m_rep (force_range || Voptimize_range @@ -1196,6 +1185,25 @@ maybe_mutate (); } +octave_value::octave_value (const octave::range& r, char type, + bool /*force_range*/) +#if 0 + : m_rep (force_range || optimize_range + ? dynamic_cast (new octave_char_range (r, type)) + : dynamic_cast (type == '"' + ? new octave_char_matrix_dq_str (r.array_value ()) + : new octave_char_matrix_sq_str (r.array_value ()))) +#else + : m_rep (type == '"' + ? new octave_char_matrix_dq_str (r.array_value ()) + : new octave_char_matrix_sq_str (r.array_value ())) +#endif +{ + maybe_mutate (); +} + +#endif + octave_value::octave_value (const octave_map& m) : m_rep (new octave_struct (m)) { @@ -2227,8 +2235,13 @@ XVALUE_EXTRACTOR (Cell, xcell_value, cell_value) XVALUE_EXTRACTOR (Array, xcellstr_value, cellstr_value) +XVALUE_EXTRACTOR (octave::range, xrange_value, range_value) + +// For now, disable all but ov_range. + +#if 0 + XVALUE_EXTRACTOR (octave::range, xfloat_range_value, float_range_value) -XVALUE_EXTRACTOR (octave::range, xrange_value, range_value) XVALUE_EXTRACTOR (octave::range, xint8_range_value, int8_range_value) XVALUE_EXTRACTOR (octave::range, xint16_range_value, int16_range_value) XVALUE_EXTRACTOR (octave::range, xint32_range_value, int32_range_value) @@ -2238,6 +2251,8 @@ XVALUE_EXTRACTOR (octave::range, xuint32_range_value, uint32_range_value) XVALUE_EXTRACTOR (octave::range, xuint64_range_value, uint64_range_value) +#endif + XVALUE_EXTRACTOR (octave_map, xmap_value, map_value) XVALUE_EXTRACTOR (octave_scalar_map, xscalar_map_value, scalar_map_value) @@ -3022,76 +3037,302 @@ error ("colon operator %s invalid (not an integer or out of range for given integer type)", op_str); } -// Templated version used for various integer types (int8, uint16, ...) - template + // Return the difference between two unsigned integers as an unsigned + // integer of the same type. + + template ::value + && std::is_unsigned::value), + bool>::type = true> + UT + integer_difference (UT a, UT b) + { + return a > b ? a - b : b - a; + } + + // Return the difference between two signed integers as an unsigned + // integer corresponding to the signed type. + + template ::type, + typename std::enable_if<(std::is_integral::value + && std::is_signed::value), + bool>::type = true> + UT + integer_difference (ST a, ST b) + { + // Map to unsigned. + // Idea from https://stackoverflow.com/questions/10589559 + + static const UT offset + = UT (0) - static_cast (std::numeric_limits::min ()); + + UT au = static_cast (a) + offset; + UT bu = static_cast (b) + offset; + + return integer_difference (au, bu); + } + + // Number of elements in an integer range taking care to avoid + // overflow. Base and limit are of the same type. If they are + // unsigned, then increment is also of the same type. If they are + // signed, then the type of increment is the unsigned type + // corresponding to T. Assumes that the base and limit values are + // consistent with the sign of the original increment (not an empty + // range) so we can calculate numel with the absolute value of the + // increment and the absolute difference between the base and limit + // values. + + template ::type, + typename std::enable_if::value, + bool>::type = true> + octave_idx_type + range_numel_aux (T base, UT unsigned_increment, T limit) + { + // Adding one to DIFF/INCREMENT may overflow, so check whether it is + // out of range before adding. + + UT nel_m1 = integer_difference (limit, base) / unsigned_increment; + + // FIXME: fix error message. + if (nel_m1 > std::numeric_limits::max () - 1) + error ("too many elements for range!"); + + return static_cast (nel_m1) + 1; + } + + // Number of elements in an integer range base:increment:limit. Base, + // increment, and limit are of the same signed type. + + template ::value + && std::is_signed::value), + bool>::type = true> + octave_idx_type + range_numel (ST base, ST increment, ST limit) + { + typedef typename std::make_unsigned::type UT; + + if (increment == 0 + || (increment > 0 && base > limit) + || (increment < 0 && base < limit)) + return 0; + + UT unsigned_increment = (increment < 0 + ? UT (0) - static_cast (increment) + : static_cast (increment)); + + return range_numel_aux (base, unsigned_increment, limit); + } + + // Number of elements in an integer range base:increment:limit. Base, + // increment, and limit are unsigned and of the same type. + + template ::value + && std::is_unsigned::value), + bool>::type = true> + octave_idx_type + range_numel (UT base, UT increment, UT limit) + { + // Unsigned, INCREMENT is always >= 0. + if (increment == 0 || base > limit) + return 0; + + return range_numel_aux (base, increment, limit); + } + + // Number of elements in an integer range base:increment:limit. Base + // and limit are of the same type and increment is a double value. + + template ::type, + typename std::enable_if::value, + bool>::type = true> + octave_idx_type + range_numel (T base, double increment, T limit) + { + double intpart; + if (math::isnan (increment) || std::modf (increment, &intpart) != 0.0) + error ("colon operator increment invalid (not an integer)"); + + if (increment == 0 + || (increment > 0 && base > limit) + || (increment < 0 && base < limit)) + return 0; + + static const UT max_val = std::numeric_limits::max (); + + double abs_increment = std::abs (increment); + + if (abs_increment > max_val) + return 1; + + return range_numel_aux (base, static_cast (abs_increment), limit); + } + + // Make a range from integer values. Increment may be integer or double. + + template ::value + && std::is_arithmetic::value), + bool>::type = true> octave_value - make_range (const octave_value& base, const octave_value& increment, - const octave_value& limit, bool for_cmd_expr) + make_int_range (T base, IT increment, T limit) + { + octave_idx_type nel = range_numel (base, increment, limit); + + // For now, we create arrays instead of range for all types + // except double. + + Array> result (dim_vector (1, nel)); + + if (nel > 0) + { + T val = base; + result.xelem (0) = val; + for (octave_idx_type i = 1; i < nel; i++) + { + val += increment; + result.xelem (i) = val; + } + } + + return octave_value (result); + } + + // Make a range from floating point values. + + // FIXME: Try again to define memory efficient range classes for + // integer and floating point values? Maybe with the templates + // defined in this file we could do that in a reasonable way? + // Regardless of that, it might be good to provide special treatment + // of colon expressions in FOR loops so that we can eliminate the + // "is_for_cmd_expr / force_rage" flag from the parser and the + // octave_value constructors for range objects. + + // NOTE: We define this function separately for float and double so + // that we can avoid having to instantiate ov_range. We DO + // instantiate range but only so we can take advantage of the + // range class to generate the corresponding array of float values + // and not have to duplicate that code here. + + template ::value, + bool>::type = true> + octave_value + make_float_range (T base, T increment, T limit, bool is_for_cmd_expr) + { + if (math::isnan (base) + || math::isnan (increment) + || math::isnan (limit)) + return octave_value (numeric_limits::NaN ()); + + if (increment == 0 + || (increment > 0 && base > limit) + || (increment < 0 && base < limit)) + return octave_value (Array (dim_vector (1, 0))); + + // At this point, we know that the base and limit values are + // consistent with the sign of the increment (not an empty range). + + range r (base, increment, limit); + + if (! is_for_cmd_expr && ! r.is_storable ()) + error ("range with infinite number of elements cannot be stored"); + + return octave_value (r, is_for_cmd_expr); + } + + template ::value, + bool>::type = true> + octave_value + make_float_range (T base, T increment, T limit, bool is_for_cmd_expr) + { + if (math::isnan (base) + || math::isnan (increment) + || math::isnan (limit)) + return octave_value (numeric_limits::NaN ()); + + if (increment == 0 + || (increment > 0 && base > limit) + || (increment < 0 && base < limit)) + return octave_value (Array (dim_vector (1, 0))); + + // At this point, we know that the base and limit values are + // consistent with the sign of the increment (not an empty range). + + range r (base, increment, limit); + + if (! is_for_cmd_expr && ! r.is_storable ()) + error ("range with infinite number of elements cannot be stored"); + + return octave_value (r.array_value ()); + } + + template ::value + || std::is_same::value + || std::is_same::value + || std::is_same::value + || std::is_same::value + || std::is_same::value + || std::is_same::value + || std::is_same::value), + bool>::type = true> + octave_value + make_int_range (const octave_value& base, const octave_value& increment, + const octave_value& limit) { if (base.isempty () || increment.isempty () || limit.isempty ()) - return octave_value (range (), for_cmd_expr); - - bool reverse = (base.is_uint8_type () || base.is_uint16_type () - || base.is_uint32_type () || base.is_uint64_type () - || limit.is_uint8_type () || limit.is_uint16_type () - || limit.is_uint32_type () || limit.is_uint64_type ()) - && increment.scalar_value () < 0; - - octave_value inc = (reverse ? -increment : increment); + return octave_value (Array (dim_vector (1, 0))); check_colon_operand (base, "lower bound"); - check_colon_operand (inc, "increment"); check_colon_operand (limit, "upper bound"); + typename T::val_type base_val = octave_value_extract (base).value (); + typename T::val_type limit_val = octave_value_extract (limit).value (); + + if (increment.is_double_type ()) + { + double increment_val = increment.double_value (); + + return make_int_range (base_val, increment_val, limit_val); + } + + check_colon_operand (increment, "increment"); + + typename T::val_type increment_val + = octave_value_extract (increment).value (); + + return make_int_range (base_val, increment_val, limit_val); + } + + template ::value, + bool>::type = true> + octave_value + make_float_range (const octave_value& base, const octave_value& increment, + const octave_value& limit, bool is_for_cmd_expr) + { + if (base.isempty () || increment.isempty () || limit.isempty ()) + return octave_value (Array (dim_vector (1, 0))); + T base_val = octave_value_extract (base); - - T increment_val = octave_value_extract (inc); - + T increment_val = octave_value_extract (increment); T limit_val = octave_value_extract (limit); - range r (base_val, increment_val, limit_val, reverse); - - return octave_value (r, for_cmd_expr); + return make_float_range (base_val, increment_val, limit_val, + is_for_cmd_expr); } - template <> + octave_value - make_range (const octave_value& base, const octave_value& increment, - const octave_value& limit, bool for_cmd_expr) - { - if (base.isempty () || increment.isempty () || limit.isempty ()) - return octave_value (range (), for_cmd_expr); - - double base_val = base.double_value (); - double increment_val = increment.double_value (); - double limit_val = limit.double_value (); - - range r (base_val, increment_val, limit_val); - - return octave_value (r, for_cmd_expr); - } - - template <> - octave_value - make_range (const octave_value& base, const octave_value& increment, - const octave_value& limit, bool for_cmd_expr) - { - if (base.isempty () || increment.isempty () || limit.isempty ()) - return octave_value (range (), for_cmd_expr); - - float base_val = base.float_value (); - float increment_val = increment.float_value (); - float limit_val = limit.float_value (); - - range r (base_val, increment_val, limit_val); - - return octave_value (r, for_cmd_expr); - } - - template <> - octave_value - make_range (const octave_value& base, const octave_value& increment, - const octave_value& limit, bool for_cmd_expr) + make_char_range (const octave_value& base, const octave_value& increment, + const octave_value& limit) { octave_value retval; @@ -3110,7 +3351,7 @@ range tmp (mtx_base(0), mtx_increment(0), mtx_limit(0)); - retval = octave_value (tmp, for_cmd_expr); + retval = octave_value (tmp); } return retval.convert_to_str (false, true, type); @@ -3168,50 +3409,45 @@ // For compatibility with Matlab, don't allow the range used in // a FOR loop expression to be converted to a Matrix. + // For now, these functions create arrays instead of range for + // all types except double. + switch (type_id) { case btyp_double: case btyp_complex: - return make_range (base, increment, limit, is_for_cmd_expr); + return make_float_range (base, increment, limit, is_for_cmd_expr); case btyp_float: case btyp_float_complex: - return make_range (base, increment, limit, is_for_cmd_expr); + return make_float_range (base, increment, limit, is_for_cmd_expr); case btyp_int8: - return make_range (base, increment, limit, - is_for_cmd_expr); + return make_int_range (base, increment, limit); case btyp_int16: - return make_range (base, increment, limit, - is_for_cmd_expr); + return make_int_range (base, increment, limit); case btyp_int32: - return make_range (base, increment, limit, - is_for_cmd_expr); + return make_int_range (base, increment, limit); case btyp_int64: - return make_range (base, increment, limit, - is_for_cmd_expr); + return make_int_range (base, increment, limit); case btyp_uint8: - return make_range (base, increment, limit, - is_for_cmd_expr); + return make_int_range (base, increment, limit); case btyp_uint16: - return make_range (base, increment, limit, - is_for_cmd_expr); + return make_int_range (base, increment, limit); case btyp_uint32: - return make_range (base, increment, limit, - is_for_cmd_expr); + return make_int_range (base, increment, limit); case btyp_uint64: - return make_range (base, increment, limit, - is_for_cmd_expr); + return make_int_range (base, increment, limit); case btyp_char: - return make_range (base, increment, limit, is_for_cmd_expr); + return make_char_range (base, increment, limit); case btyp_unknown: error ("incompatible types found in range expression"); @@ -3300,8 +3536,13 @@ octave_diag_matrix::register_type (ti); octave_complex_matrix::register_type (ti); octave_complex_diag_matrix::register_type (ti); + ov_range::register_type (ti); + + // For now, disable all but ov_range. + +#if 0 + ov_range::register_type (ti); - ov_range::register_type (ti); ov_range::register_type (ti); ov_range::register_type (ti); ov_range::register_type (ti); @@ -3310,6 +3551,9 @@ ov_range::register_type (ti); ov_range::register_type (ti); ov_range::register_type (ti); + +#endif + octave_bool::register_type (ti); octave_bool_matrix::register_type (ti); octave_char_matrix_str::register_type (ti); diff -r d87406970676 -r 97504d2edcc7 libinterp/octave-value/ov.h --- a/libinterp/octave-value/ov.h Wed Mar 16 18:45:11 2022 +0100 +++ b/libinterp/octave-value/ov.h Thu Mar 17 02:52:53 2022 -0400 @@ -316,28 +316,44 @@ } #endif - OCTINTERP_API octave_value (const octave::range& r, char type, + OCTINTERP_API octave_value (const octave::range& r, bool force_range = false); + + // For now, disable all but range. + +#if 0 + OCTINTERP_API octave_value (const octave::range& r, bool force_range = false); - OCTINTERP_API octave_value (const octave::range& r, - bool force_range = false); + OCTINTERP_API octave_value (const octave::range& r, bool force_range = false); + OCTINTERP_API octave_value (const octave::range& r, bool force_range = false); + OCTINTERP_API octave_value (const octave::range& r, bool force_range = false); + OCTINTERP_API octave_value (const octave::range& r, bool force_range = false); + OCTINTERP_API octave_value (const octave::range& r, bool force_range = false); + OCTINTERP_API octave_value (const octave::range& r, bool force_range = false); + OCTINTERP_API octave_value (const octave::range& r, bool force_range = false); + OCTINTERP_API octave_value (const octave::range& r, bool force_range = false); + + OCTINTERP_API octave_value (const octave::range& r, char type, + bool force_range = false); +#endif + OCTINTERP_API octave_value (const octave_map& m); OCTINTERP_API octave_value (const octave_scalar_map& m); OCTINTERP_API octave_value (const std::map&); @@ -1008,12 +1024,16 @@ Array cellstr_value (void) const { return m_rep->cellstr_value (); } + octave::range range_value (void) const + { return m_rep->range_value (); } + + // For now, disable all but range. + +#if 0 + octave::range float_range_value (void) const { return m_rep->float_range_value (); } - octave::range range_value (void) const - { return m_rep->range_value (); } - octave::range int8_range_value (void) const { return m_rep->int8_range_value (); } @@ -1038,6 +1058,8 @@ octave::range uint64_range_value (void) const { return m_rep->uint64_range_value (); } +#endif + OCTINTERP_API octave_map map_value (void) const; OCTINTERP_API octave_scalar_map scalar_map_value (void) const; @@ -1269,12 +1291,16 @@ OCTINTERP_API Array xcellstr_value (const char *fmt, ...) const; + OCTINTERP_API octave::range + xrange_value (const char *fmt, ...) const; + + // For now, disable all but range. + +#if 0 + OCTINTERP_API octave::range xfloat_range_value (const char *fmt, ...) const; - OCTINTERP_API octave::range - xrange_value (const char *fmt, ...) const; - OCTINTERP_API octave::range xint8_range_value (const char *fmt, ...) const; @@ -1299,6 +1325,8 @@ OCTINTERP_API octave::range xuint64_range_value (const char *fmt, ...) const; +#endif + OCTINTERP_API octave_map xmap_value (const char *fmt, ...) const; OCTINTERP_API octave_scalar_map diff -r d87406970676 -r 97504d2edcc7 libinterp/parse-tree/pt-colon.h --- a/libinterp/parse-tree/pt-colon.h Wed Mar 16 18:45:11 2022 +0100 +++ b/libinterp/parse-tree/pt-colon.h Thu Mar 17 02:52:53 2022 -0400 @@ -89,6 +89,8 @@ tree_expression * dup (symbol_scope& scope) const; + bool is_colon_expression (void) const { return true; } + octave_value evaluate (tree_evaluator&, int nargout = 1); octave_value_list evaluate_n (tree_evaluator& tw, int nargout = 1) diff -r d87406970676 -r 97504d2edcc7 libinterp/parse-tree/pt-eval.cc --- a/libinterp/parse-tree/pt-eval.cc Wed Mar 16 18:45:11 2022 +0100 +++ b/libinterp/parse-tree/pt-eval.cc Thu Mar 17 02:52:53 2022 -0400 @@ -3095,6 +3095,9 @@ return; } + // For now, disable all but range. + +#if 0 if (rhs.is_int64_type ()) { execute_range_loop (rhs.int64_range_value (), line, ult, loop_body); @@ -3148,6 +3151,7 @@ execute_range_loop (rhs.float_range_value (), line, ult, loop_body); return; } +#endif } if (rhs.is_scalar_type ()) diff -r d87406970676 -r 97504d2edcc7 libinterp/parse-tree/pt-exp.h --- a/libinterp/parse-tree/pt-exp.h Wed Mar 16 18:45:11 2022 +0100 +++ b/libinterp/parse-tree/pt-exp.h Thu Mar 17 02:52:53 2022 -0400 @@ -81,6 +81,8 @@ virtual bool is_boolean_expression (void) const { return false; } + virtual bool is_colon_expression (void) const { return false; } + virtual bool lvalue_ok (void) const { return false; } virtual bool rvalue_ok (void) const { return false; } diff -r d87406970676 -r 97504d2edcc7 liboctave/array/Range.cc --- a/liboctave/array/Range.cc Wed Mar 16 18:45:11 2022 +0100 +++ b/liboctave/array/Range.cc Thu Mar 17 02:52:53 2022 -0400 @@ -328,6 +328,10 @@ xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel); } + // For now, only define for float and double. + +#if 0 + template <> void range::init (void) @@ -384,6 +388,8 @@ xinit (m_base, m_limit, m_increment, m_reverse, m_final, m_numel); } +#endif + template <> bool range::is_storable (void) const diff -r d87406970676 -r 97504d2edcc7 liboctave/array/Range.h --- a/liboctave/array/Range.h Wed Mar 16 18:45:11 2022 +0100 +++ b/liboctave/array/Range.h Thu Mar 17 02:52:53 2022 -0400 @@ -29,6 +29,7 @@ #include "octave-config.h" #include +#include #include "Array-fwd.h" #include "dMatrix.h" @@ -39,8 +40,13 @@ namespace octave { + // For now, only define for floating point types. However, we only + // need range as a temporary local variable in make_float_range + // in ov.cc. + template - class range + class + range::value>::type> { public: @@ -123,9 +129,26 @@ return range (base, increment, final_val, numel, reverse); } - range (const range&) = default; + range (const range& r) + : m_base (r.m_base), m_increment (r.m_increment), + m_limit (r.m_limit), m_final (r.m_final), + m_numel (r.m_numel), m_reverse (r.m_reverse) + { } - range& operator = (const range&) = default; + range& operator = (const range& r) + { + if (this != &r) + { + m_base = r.m_base; + m_increment = r.m_increment; + m_limit = r.m_limit; + m_final = r.m_final; + m_numel = r.m_numel; + m_reverse = r.m_reverse; + } + + return *this; + } ~range (void) = default; @@ -370,6 +393,13 @@ template <> OCTAVE_API void range::init (void); template <> OCTAVE_API void range::init (void); + + // For now, only define for floating point types. However, we only + // need range as a temporary local variable in make_float_range + // in ov.cc. + +#if 0 + template <> OCTAVE_API void range::init (void); template <> OCTAVE_API void range::init (void); template <> OCTAVE_API void range::init (void); @@ -379,6 +409,8 @@ template <> OCTAVE_API void range::init (void); template <> OCTAVE_API void range::init (void); +#endif + template <> OCTAVE_API bool range::is_storable (void) const; template <> OCTAVE_API bool range::is_storable (void) const; diff -r d87406970676 -r 97504d2edcc7 liboctave/array/range-fwd.h --- a/liboctave/array/range-fwd.h Wed Mar 16 18:45:11 2022 +0100 +++ b/liboctave/array/range-fwd.h Thu Mar 17 02:52:53 2022 -0400 @@ -30,7 +30,7 @@ namespace octave { - template class OCTAVE_API range; + template class OCTAVE_API range; } #endif diff -r d87406970676 -r 97504d2edcc7 test/range.tst --- a/test/range.tst Wed Mar 16 18:45:11 2022 +0100 +++ b/test/range.tst Thu Mar 17 02:52:53 2022 -0400 @@ -491,7 +491,7 @@ %!error (1.5:uint8(1):5) %!error (-1:uint8(1):5) %!error (uint8(1):1.5:5) -%!error (uint8(1):-256:5) +%!error (uint8(1):NaN:5) %!error (uint8(1):1:5.5) %!error (uint8(1):1:256) %!error (uint8(1):-1:-6)