changeset 30868:79edd49a5a97

maint: Merge stable to default.
author Markus Mützel <markus.muetzel@gmx.de>
date Mon, 28 Mar 2022 19:52:24 +0200
parents a8d61c30f41a (current diff) 014030798d5e (diff)
children b7826af05108
files libinterp/corefcn/oct-stream.cc libinterp/octave-value/ov-base.cc libinterp/octave-value/ov.cc liboctave/util/oct-string.cc
diffstat 7 files changed, 80 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/oct-stream.cc	Sat Mar 26 14:25:34 2022 -0700
+++ b/libinterp/corefcn/oct-stream.cc	Mon Mar 28 19:52:24 2022 +0200
@@ -141,7 +141,10 @@
           ::error ("%s: negative value invalid as size specification",
                    who.c_str ());
 
-        if (d > std::numeric_limits<octave_idx_type>::max ())
+        static const double out_of_range_top
+          = static_cast<double> (std::numeric_limits<octave_idx_type>::max ())
+            + 1.;
+        if (d >= out_of_range_top)
           ::error ("%s: dimension too large for Octave's index type",
                    who.c_str ());
 
--- a/libinterp/corefcn/xpow.cc	Sat Mar 26 14:25:34 2022 -0700
+++ b/libinterp/corefcn/xpow.cc	Mon Mar 28 19:52:24 2022 +0200
@@ -76,8 +76,18 @@
 xisint (T x)
 {
   return (octave::math::x_nint (x) == x
-          && ((x >= 0 && x < std::numeric_limits<int>::max ())
-              || (x <= 0 && x > std::numeric_limits<int>::min ())));
+          && x <= std::numeric_limits<int>::max ()
+          && x >= std::numeric_limits<int>::min ());
+}
+
+static inline bool
+xisint (float x)
+{
+  static const float out_of_range_top
+    = static_cast<float>(std::numeric_limits<int>::max ()) + 1.;
+  return (octave::math::x_nint (x) == x
+          && x < out_of_range_top
+          && x >= std::numeric_limits<int>::min ());
 }
 
 // Safer pow functions.
--- a/libinterp/octave-value/ov-base.cc	Sat Mar 26 14:25:34 2022 -0700
+++ b/libinterp/octave-value/ov-base.cc	Mon Mar 28 19:52:24 2022 +0200
@@ -474,11 +474,13 @@
         err_wrong_type_arg (ee, "octave_base_value::" #F "_value ()", type_name ()); \
       }                                                                 \
                                                                         \
+    static const double out_of_range_top                                \
+      = static_cast<double>(std::numeric_limits<T>::max ()) + 1.;       \
     if (require_int && octave::math::x_nint (d) != d)                   \
       error_with_cfn ("conversion of %g to " #T " value failed", d);    \
     else if (d < std::numeric_limits<T>::min ())                        \
       retval = std::numeric_limits<T>::min ();                          \
-    else if (d > std::numeric_limits<T>::max ())                        \
+    else if (d >= out_of_range_top)                                     \
       retval = std::numeric_limits<T>::max ();                          \
     else                                                                \
       retval = static_cast<T> (octave::math::fix (d));                  \
--- a/libinterp/octave-value/ov.cc	Sat Mar 26 14:25:34 2022 -0700
+++ b/libinterp/octave-value/ov.cc	Mon Mar 28 19:52:24 2022 +0200
@@ -3073,8 +3073,11 @@
 
     double dval = val.double_value ();
     double intpart;
-
-    if (dval > std::numeric_limits<typename T::val_type>::max ()
+    static const double out_of_range_top
+      = static_cast<double> (std::numeric_limits<typename T::val_type>::max ())
+        + 1.;
+
+    if (dval >= out_of_range_top
         || dval < std::numeric_limits<typename T::val_type>::min ()
         || std::modf (dval, &intpart) != 0.0)
       error ("colon operator %s invalid (not an integer or out of range for given integer type)", op_str);
@@ -3246,16 +3249,18 @@
         || (increment < 0 && base < limit))
       return 0;
 
-    static const UT max_val = std::numeric_limits<UT>::max ();
+    static const double out_of_range_top
+      = static_cast<double> (std::numeric_limits<UT>::max ()) + 1.;
 
     double abs_increment = std::abs (increment);
 
-    // Technically, this condition should be `abs_increment > max_val`.
+    // Technically, this condition should be
+    // `abs_increment > std::numeric_limits<UT>::max ()`.
     // But intmax('uint64') is not representable exactly as floating point
     // number.  Instead, it "rounds" up by 1 to 2^64.  To account for
     // this, use the following expression which works for all unsigned
     // integer types.
-    if ((abs_increment-1.) >= max_val)
+    if (abs_increment >= out_of_range_top)
       return 1;
 
     UT unsigned_increment = range_increment<T> (increment);
--- a/liboctave/numeric/lo-mappers.cc	Sat Mar 26 14:25:34 2022 -0700
+++ b/liboctave/numeric/lo-mappers.cc	Mon Mar 28 19:52:24 2022 +0200
@@ -183,7 +183,9 @@
     octave_idx_type
     nint_big (double x)
     {
-      if (x > std::numeric_limits<octave_idx_type>::max ())
+      static const double out_of_range_top
+        = static_cast<double>(std::numeric_limits<octave_idx_type>::max ())+1.;
+      if (x >= out_of_range_top)
         return std::numeric_limits<octave_idx_type>::max ();
       else if (x < std::numeric_limits<octave_idx_type>::min ())
         return std::numeric_limits<octave_idx_type>::min ();
@@ -195,7 +197,9 @@
     octave_idx_type
     nint_big (float x)
     {
-      if (x > std::numeric_limits<octave_idx_type>::max ())
+      static const float out_of_range_top
+        = static_cast<float>(std::numeric_limits<octave_idx_type>::max ())+1.;
+      if (x >= out_of_range_top)
         return std::numeric_limits<octave_idx_type>::max ();
       else if (x < std::numeric_limits<octave_idx_type>::min ())
         return std::numeric_limits<octave_idx_type>::min ();
@@ -218,7 +222,9 @@
     int
     nint (float x)
     {
-      if (x > std::numeric_limits<int>::max ())
+      static const float out_of_range_top
+        = static_cast<float>(std::numeric_limits<int>::max ()) + 1.;
+      if (x >= out_of_range_top)
         return std::numeric_limits<int>::max ();
       else if (x < std::numeric_limits<int>::min ())
         return std::numeric_limits<int>::min ();
--- a/liboctave/util/oct-inttypes.cc	Sat Mar 26 14:25:34 2022 -0700
+++ b/liboctave/util/oct-inttypes.cc	Mon Mar 28 19:52:24 2022 +0200
@@ -228,7 +228,11 @@
 bool
 octave_int_cmp_op::emulate_mop (uint64_t x, double y)
 {
-  static const double xxup = std::numeric_limits<uint64_t>::max ();
+  // The following cast changes the value to 2^64 (which is outside the range
+  // of `uint64_t`).  Take care to handle this correctly (e.g., don't cast back
+  // to `uint64_t`)!
+  static const double xxup
+    = static_cast<double> (std::numeric_limits<uint64_t>::max ());
   // This converts to the nearest double.  Unless there's an equality, the
   // result is clear.
   double xx = x;
@@ -248,8 +252,14 @@
 bool
 octave_int_cmp_op::emulate_mop (int64_t x, double y)
 {
-  static const double xxup = std::numeric_limits<int64_t>::max ();
-  static const double xxlo = std::numeric_limits<int64_t>::min ();
+  // The following cast changes the value to 2^63 (which is outside the range
+  // of `int64_t`).  Take care to handle this correctly (e.g., don't cast back
+  // to `int64_t`)!  The same applies to the lower limit on systems using one's
+  // complement.
+  static const double xxup
+    = static_cast<double> (std::numeric_limits<int64_t>::max ());
+  static const double xxlo
+    = static_cast<double> (std::numeric_limits<int64_t>::min ());
   // This converts to the nearest double.  Unless there's an equality, the
   // result is clear.
   double xx = x;
@@ -452,6 +462,8 @@
 OCTAVE_API octave_int64
 operator + (const octave_int64& x, const double& y)
 {
+  // The following cast changes the value to 2^63 (which is outside the range
+  // of `int64_t`).
   if (fabs (y) < static_cast<double> (octave_int64::max ()))
     return x + octave_int64 (y);
   else
@@ -487,7 +499,9 @@
 OCTAVE_API octave_uint64
 operator - (const double& x, const octave_uint64& y)
 {
-  if (x <= static_cast<double> (octave_uint64::max ()))
+  // The following cast changes the value to 2^64 (which is outside the range
+  // of `uint64_t`).
+  if (x < static_cast<double> (octave_uint64::max ()))
     return octave_uint64 (x) - y;
   else
     {
@@ -581,7 +595,10 @@
 OCTAVE_API octave_uint64
 operator * (const octave_uint64& x, const double& y)
 {
-  if (y >= 0 && y < octave_uint64::max () && y == octave::math::fix (y))
+  // The following cast changes the value to 2^64 (which is outside the range
+  // of `uint64_t`).
+  if (y >= 0 && y < static_cast<double> (octave_uint64::max ())
+      && y == octave::math::fix (y))
     return x * octave_uint64 (static_cast<uint64_t> (y));
   else if (y == 0.5)
     return x / octave_uint64 (static_cast<uint64_t> (2));
@@ -616,7 +633,10 @@
 OCTAVE_API octave_int64
 operator * (const octave_int64& x, const double& y)
 {
-  if (fabs (y) < octave_int64::max () && y == octave::math::fix (y))
+  // The following cast changes the value to 2^63 (which is outside the range
+  // of `int64_t`).
+  if (fabs (y) < static_cast<double> (octave_int64::max ())
+      && y == octave::math::fix (y))
     return x * octave_int64 (static_cast<int64_t> (y));
   else if (fabs (y) == 0.5)
     return x / octave_int64 (static_cast<uint64_t> (4*y));
@@ -666,7 +686,10 @@
 OCTAVE_API octave_uint64
 operator / (const octave_uint64& x, const double& y)
 {
-  if (y >= 0 && y < octave_uint64::max () && y == octave::math::fix (y))
+  // The following cast changes the value to 2^64 (which is outside the range
+  // of `uint64_t`).
+  if (y >= 0 && y < static_cast<double> (octave_uint64::max ())
+      && y == octave::math::fix (y))
     return x / octave_uint64 (y);
   else
     return x * (1.0/y);
@@ -676,7 +699,10 @@
 OCTAVE_API octave_int64
 operator / (const octave_int64& x, const double& y)
 {
-  if (fabs (y) < octave_int64::max () && y == octave::math::fix (y))
+  // The following cast changes the value to 2^63 (which is outside the range
+  // of `int64_t`).
+  if (fabs (y) < static_cast<double> (octave_int64::max ())
+      && y == octave::math::fix (y))
     return x / octave_int64 (y);
   else
     return x * (1.0/y);
--- a/liboctave/util/oct-string.cc	Sat Mar 26 14:25:34 2022 -0700
+++ b/liboctave/util/oct-string.cc	Mon Mar 28 19:52:24 2022 +0200
@@ -700,6 +700,10 @@
   if (len <= 0)
     len = 10;
 
+  static const T out_of_range_top
+    = static_cast<T>(std::numeric_limits<int>::max ()) + 1.;
+  static const T out_of_range_bottom
+    = static_cast<T>(std::numeric_limits<int>::min ()) - 1.;
   if (octave::math::isinf (val))
     {
       if (val > 0)
@@ -709,8 +713,7 @@
     }
   else if (octave::math::isnan (val))
     s = "0/0";
-  else if (val < std::numeric_limits<int>::min ()
-           || val > std::numeric_limits<int>::max ()
+  else if (val <= out_of_range_bottom || val >= out_of_range_top
            || octave::math::x_nint (val) == val)
     {
       std::ostringstream buf;
@@ -740,7 +743,7 @@
           T nextd = d;
 
           // Have we converged to 1/intmax ?
-          if (std::abs (flip) > static_cast<T> (std::numeric_limits<int>::max ()))
+          if (std::abs (flip) > out_of_range_top)
             {
               lastn = n;
               lastd = d;
@@ -771,8 +774,8 @@
                 break;
             }
 
-          if (std::abs (n) > std::numeric_limits<int>::max ()
-              || std::abs (d) > std::numeric_limits<int>::max ())
+          if (std::abs (n) >= out_of_range_top
+              || std::abs (d) >= out_of_range_top)
             break;
 
           s = buf.str ();