Mercurial > octave
changeset 30840:3c9e19cd8896
maint: Merge stable to default.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Thu, 17 Mar 2022 13:41:19 -0400 |
parents | ecde6a40fb72 (current diff) 1a4a3ba925c8 (diff) |
children | 022fd8234356 |
files | libinterp/octave-value/ov.cc |
diffstat | 1 files changed, 67 insertions(+), 8 deletions(-) [+] |
line wrap: on
line diff
--- a/libinterp/octave-value/ov.cc Thu Mar 17 16:43:27 2022 +0100 +++ b/libinterp/octave-value/ov.cc Thu Mar 17 13:41:19 2022 -0400 @@ -3102,6 +3102,49 @@ return static_cast<octave_idx_type> (nel_m1) + 1; } + // Convert signed range increment to unsigned. + + template <typename ST, + typename UT = typename std::make_unsigned<ST>::type, + typename std::enable_if<(std::is_integral<ST>::value + && std::is_signed<ST>::value), + bool>::type = true> + UT + range_increment (ST increment) + { + return (increment < 0 + ? UT (0) - static_cast<UT> (increment) + : static_cast<UT> (increment)); + } + + // "Convert" unsigned range increment to unsigned. A no-op, but + // needed to provide a consistent interface for other template + // functions. + + template <typename T, + typename UT = typename std::make_unsigned<T>::type, + typename std::enable_if<(std::is_integral<UT>::value + && std::is_unsigned<UT>::value), + bool>::type = true> + UT + range_increment (UT increment) + { + return increment; + } + + // Convert double range increment to unsigned. Enable by return type. + + template <typename T, + typename UT = typename std::make_unsigned<T>::type> + typename std::enable_if<(std::is_integral<UT>::value + && std::is_unsigned<UT>::value), UT>::type + range_increment (double increment) + { + double abs_increment = std::abs (increment); + + return static_cast<UT> (abs_increment); + } + // Number of elements in an integer range base:increment:limit. Base, // increment, and limit are of the same signed type. @@ -3119,9 +3162,7 @@ || (increment < 0 && base < limit)) return 0; - UT unsigned_increment = (increment < 0 - ? UT (0) - static_cast<UT> (increment) - : static_cast<UT> (increment)); + UT unsigned_increment = range_increment<ST> (increment); return range_numel_aux (base, unsigned_increment, limit); } @@ -3169,7 +3210,9 @@ if (abs_increment > max_val) return 1; - return range_numel_aux (base, static_cast<UT> (abs_increment), limit); + UT unsigned_increment = range_increment<T> (increment); + + return range_numel_aux (base, unsigned_increment, limit); } // Make a range from integer values. Increment may be integer or double. @@ -3191,12 +3234,28 @@ if (nel > 0) { + typedef typename std::make_unsigned<T>::type UT; + + UT unsigned_increment = range_increment<T> (increment); + T val = base; result.xelem (0) = val; - for (octave_idx_type i = 1; i < nel; i++) + + if (limit > base) { - val += increment; - result.xelem (i) = val; + for (octave_idx_type i = 1; i < nel; i++) + { + val += unsigned_increment; + result.xelem (i) = val; + } + } + else + { + for (octave_idx_type i = 1; i < nel; i++) + { + val -= unsigned_increment; + result.xelem (i) = val; + } } } @@ -3210,7 +3269,7 @@ // 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 + // "is_for_cmd_expr / force_range" flag from the parser and the // octave_value constructors for range objects. // NOTE: We define this function separately for float and double so