changeset 32626:395ab2ffb0c2

maint: Use constexpr where possible for performance. * libinterp/corefcn/__betainc__.cc, libinterp/corefcn/__expint__.cc, libinterp/corefcn/__gammainc__.cc, libinterp/corefcn/dlmread.cc, libinterp/corefcn/gl2ps-print.cc, libinterp/corefcn/graphics.cc, libinterp/corefcn/input.cc, libinterp/corefcn/oct-stream.cc, libinterp/corefcn/quadcc.cc, libinterp/corefcn/xpow.cc, libinterp/octave-value/ov-base-int.cc, libinterp/octave-value/ov-base.cc, libinterp/octave-value/ov.cc, libinterp/operators/op-mi.cc, liboctave/array/Array-base.cc, liboctave/array/Sparse.cc, liboctave/array/idx-vector.cc, liboctave/numeric/lo-mappers.cc, liboctave/util/oct-inttypes.cc, liboctave/util/oct-inttypes.h, liboctave/util/oct-string.cc: Use "static constexpr" rather than "static const" where possible so that compiler may move some optimizations into compile stage, rather than runtime initialization. Capitalize constant expression names.
author Rik <rik@octave.org>
date Wed, 20 Dec 2023 20:02:42 -0800
parents b60af3354ac3
children 3b151ee4e140
files libinterp/corefcn/__betainc__.cc libinterp/corefcn/__expint__.cc libinterp/corefcn/__gammainc__.cc libinterp/corefcn/dlmread.cc libinterp/corefcn/gl2ps-print.cc libinterp/corefcn/graphics.cc libinterp/corefcn/input.cc libinterp/corefcn/oct-stream.cc libinterp/corefcn/quadcc.cc libinterp/corefcn/xpow.cc libinterp/octave-value/ov-base-int.cc libinterp/octave-value/ov-base.cc libinterp/octave-value/ov.cc libinterp/operators/op-mi.cc liboctave/array/Array-base.cc liboctave/array/Sparse.cc liboctave/array/idx-vector.cc liboctave/numeric/lo-mappers.cc liboctave/util/oct-inttypes.cc liboctave/util/oct-inttypes.h liboctave/util/oct-string.cc
diffstat 21 files changed, 84 insertions(+), 84 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/__betainc__.cc	Wed Dec 20 18:24:41 2023 -0800
+++ b/libinterp/corefcn/__betainc__.cc	Wed Dec 20 20:02:42 2023 -0800
@@ -79,7 +79,7 @@
 
       // Initialize variables used in algorithm
       static const float tiny = math::exp2 (-50.0f);
-      static const float eps = std::numeric_limits<float>::epsilon ();
+      static constexpr float eps = std::numeric_limits<float>::epsilon ();
       float xj, x2, y, Cj, Dj, aj, bj, Deltaj, alpha_j, beta_j;
       int j, maxit;
       maxit = 200;
@@ -150,7 +150,7 @@
 
       // Initialize variables used in algorithm
       static const double tiny = math::exp2 (-100.0);
-      static const double eps = std::numeric_limits<double>::epsilon ();
+      static constexpr double eps = std::numeric_limits<double>::epsilon ();
       double xj, x2, y, Cj, Dj, aj, bj, Deltaj, alpha_j, beta_j;
       int j, maxit;
       maxit = 200;
--- a/libinterp/corefcn/__expint__.cc	Wed Dec 20 18:24:41 2023 -0800
+++ b/libinterp/corefcn/__expint__.cc	Wed Dec 20 20:02:42 2023 -0800
@@ -65,7 +65,7 @@
 
       // Initialize variables used in algorithm
       static const FloatComplex tiny = math::exp2 (-50.0f);
-      static const float eps = std::numeric_limits<float>::epsilon ();
+      static constexpr float eps = std::numeric_limits<float>::epsilon ();
       const FloatComplex cone (1.0, 0.0);
       const FloatComplex czero (0.0, 0.0);
       const int maxit = 100;
@@ -123,7 +123,7 @@
 
       // Initialize variables used in algorithm
       static const Complex tiny = math::exp2 (-100.0);
-      static const double eps = std::numeric_limits<double>::epsilon ();
+      static constexpr double eps = std::numeric_limits<double>::epsilon ();
       const Complex cone (1.0, 0.0);
       const Complex czero (0.0, 0.0);
       const int maxit = 200;
--- a/libinterp/corefcn/__gammainc__.cc	Wed Dec 20 18:24:41 2023 -0800
+++ b/libinterp/corefcn/__gammainc__.cc	Wed Dec 20 20:02:42 2023 -0800
@@ -71,7 +71,7 @@
 
       // Initialize variables used in algorithm
       static const float tiny = math::exp2 (-50.0f);
-      static const float eps = std::numeric_limits<float>::epsilon();
+      static constexpr float eps = std::numeric_limits<float>::epsilon();
       float y, Cj, Dj, bj, aj, Deltaj;
       int j, maxit;
       maxit = 200;
@@ -126,7 +126,7 @@
 
       // Initialize variables used in algorithm
       static const double tiny = math::exp2 (-100.0);
-      static const double eps = std::numeric_limits<double>::epsilon();
+      static constexpr double eps = std::numeric_limits<double>::epsilon();
       double y, Cj, Dj, bj, aj, Deltaj;
       int j, maxit;
       maxit = 200;
--- a/libinterp/corefcn/dlmread.cc	Wed Dec 20 18:24:41 2023 -0800
+++ b/libinterp/corefcn/dlmread.cc	Wed Dec 20 20:02:42 2023 -0800
@@ -47,10 +47,10 @@
 #include "ovl.h"
 #include "utils.h"
 
-static const octave_idx_type idx_max
+static constexpr octave_idx_type idx_max
   = std::numeric_limits<octave_idx_type>::max () - 1;
 
-static const double idx_max_dbl = double (idx_max);
+static constexpr double idx_max_dbl = double (idx_max);
 
 static bool
 read_cell_spec (std::istream& is, octave_idx_type& row, octave_idx_type& col)
--- a/libinterp/corefcn/gl2ps-print.cc	Wed Dec 20 18:24:41 2023 -0800
+++ b/libinterp/corefcn/gl2ps-print.cc	Wed Dec 20 20:02:42 2023 -0800
@@ -1522,10 +1522,10 @@
 
   OCTAVE_LOCAL_BUFFER (float, tmp_data, static_cast<size_t> (3)*w*h);
 
-  static const float maxval = std::numeric_limits<uint8_t>::max ();
+  static constexpr float MAXVAL = std::numeric_limits<uint8_t>::max ();
 
   for (int i = 0; i < 3*w*h; i++)
-    tmp_data[i] = data[i] / maxval;
+    tmp_data[i] = data[i] / MAXVAL;
 
   draw_pixels (w, h, tmp_data);
 }
@@ -1537,10 +1537,10 @@
 
   OCTAVE_LOCAL_BUFFER (float, tmp_data, static_cast<size_t> (3)*w*h);
 
-  static const float maxval = std::numeric_limits<uint16_t>::max ();
+  static constexpr float MAXVAL = std::numeric_limits<uint16_t>::max ();
 
   for (int i = 0; i < 3*w*h; i++)
-    tmp_data[i] = data[i] / maxval;
+    tmp_data[i] = data[i] / MAXVAL;
 
   draw_pixels (w, h, tmp_data);
 }
--- a/libinterp/corefcn/graphics.cc	Wed Dec 20 18:24:41 2023 -0800
+++ b/libinterp/corefcn/graphics.cc	Wed Dec 20 20:02:42 2023 -0800
@@ -7364,20 +7364,20 @@
 
   magform ((hi - lo) / ticint, a, b);
 
-  static const double sqrt_2 = sqrt (2.0);
-  static const double sqrt_10 = sqrt (10.0);
-  static const double sqrt_50 = sqrt (50.0);
-
-  if (a < sqrt_2)
+  static constexpr double SQRT_2 = sqrt (2.0);
+  static constexpr double SQRT_10 = sqrt (10.0);
+  static constexpr double SQRT_50 = sqrt (50.0);
+
+  if (a < SQRT_2)
     x = 1;
-  else if (a < sqrt_10)
+  else if (a < SQRT_10)
     x = 2;
-  else if (a < sqrt_50)
+  else if (a < SQRT_50)
     x = 5;
   else
     x = 10;
 
-  return x * std::pow (10., b);
+  return x * std::pow (10.0, b);
 }
 
 // Attempt to make "nice" limits from the actual max and min of the data.
--- a/libinterp/corefcn/input.cc	Wed Dec 20 18:24:41 2023 -0800
+++ b/libinterp/corefcn/input.cc	Wed Dec 20 20:02:42 2023 -0800
@@ -261,13 +261,13 @@
 is_completing_dirfns ()
 {
   static std::string dirfns_commands[] = {"cd", "isfile", "isfolder", "ls"};
-  static const std::size_t dirfns_commands_length = 4;
+  static const std::size_t DIRFNS_COMMANDS_LENGTH = 4;
 
   bool retval = false;
 
   std::string line = command_editor::get_line_buffer ();
 
-  for (std::size_t i = 0; i < dirfns_commands_length; i++)
+  for (std::size_t i = 0; i < DIRFNS_COMMANDS_LENGTH; i++)
     {
       int index = line.find (dirfns_commands[i] + ' ');
 
--- a/libinterp/corefcn/oct-stream.cc	Wed Dec 20 18:24:41 2023 -0800
+++ b/libinterp/corefcn/oct-stream.cc	Wed Dec 20 20:02:42 2023 -0800
@@ -142,9 +142,8 @@
         ::error ("%s: negative value invalid as size specification",
                  who.c_str ());
 
-      static const double out_of_range_top
-        = static_cast<double> (std::numeric_limits<octave_idx_type>::max ())
-          + 1.;
+      static constexpr double out_of_range_top
+        = static_cast<double> (std::numeric_limits<octave_idx_type>::max ()) + 1.0;
       if (d >= out_of_range_top)
         ::error ("%s: dimension too large for Octave's index type",
                  who.c_str ());
--- a/libinterp/corefcn/quadcc.cc	Wed Dec 20 18:24:41 2023 -0800
+++ b/libinterp/corefcn/quadcc.cc	Wed Dec 20 20:02:42 2023 -0800
@@ -61,7 +61,7 @@
 };
 
 // Define relative tolerance used when deciding to drop an interval.
-static const double DROP_RELTOL = std::numeric_limits<double>::epsilon () * 10;
+static constexpr double DROP_RELTOL = std::numeric_limits<double>::epsilon () * 10;
 
 // Some constants and matrices that we'll need.
 
--- a/libinterp/corefcn/xpow.cc	Wed Dec 20 18:24:41 2023 -0800
+++ b/libinterp/corefcn/xpow.cc	Wed Dec 20 20:02:42 2023 -0800
@@ -83,8 +83,9 @@
 static inline bool
 xisint (float x)
 {
-  static const float out_of_range_top
-    = static_cast<float> (std::numeric_limits<int>::max ()) + 1.;
+  static constexpr float out_of_range_top
+    = static_cast<float> (std::numeric_limits<int>::max ()) + 1.0;
+
   return (octave::math::x_nint (x) == x
           && x < out_of_range_top
           && x >= std::numeric_limits<int>::min ());
--- a/libinterp/octave-value/ov-base-int.cc	Wed Dec 20 18:24:41 2023 -0800
+++ b/libinterp/octave-value/ov-base-int.cc	Wed Dec 20 20:02:42 2023 -0800
@@ -177,8 +177,8 @@
 
       val_type ival = tmp.value ();
 
-      static const bool is_signed = std::numeric_limits<val_type>::is_signed;
-      static const bool can_be_larger_than_uchar_max
+      static constexpr bool is_signed = std::numeric_limits<val_type>::is_signed;
+      static constexpr bool can_be_larger_than_uchar_max
         = octave_base_int_helper_traits<val_type>::can_be_larger_than_uchar_max;
 
       if (octave_base_int_helper<val_type, is_signed,
@@ -578,8 +578,8 @@
 
   val_type ival = tmp.value ();
 
-  static const bool is_signed = std::numeric_limits<val_type>::is_signed;
-  static const bool can_be_larger_than_uchar_max
+  static constexpr bool is_signed = std::numeric_limits<val_type>::is_signed;
+  static constexpr bool can_be_larger_than_uchar_max
     = octave_base_int_helper_traits<val_type>::can_be_larger_than_uchar_max;
 
   if (octave_base_int_helper<val_type, is_signed,
--- a/libinterp/octave-value/ov-base.cc	Wed Dec 20 18:24:41 2023 -0800
+++ b/libinterp/octave-value/ov-base.cc	Wed Dec 20 20:02:42 2023 -0800
@@ -529,8 +529,8 @@
         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.;      \
+    static constexpr double out_of_range_top                            \
+      = static_cast<double> (std::numeric_limits<T>::max ()) + 1.0;     \
     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 ())                        \
--- a/libinterp/octave-value/ov.cc	Wed Dec 20 18:24:41 2023 -0800
+++ b/libinterp/octave-value/ov.cc	Wed Dec 20 20:02:42 2023 -0800
@@ -2957,9 +2957,8 @@
 
   double dval = val.double_value ();
   double intpart;
-  static const double out_of_range_top
-    = static_cast<double> (std::numeric_limits<typename T::val_type>::max ())
-      + 1.;
+  static constexpr double out_of_range_top
+    = static_cast<double> (std::numeric_limits<typename T::val_type>::max ()) + 1.0;
 
   if (dval >= out_of_range_top
       || dval < std::numeric_limits<typename T::val_type>::min ()
@@ -2994,8 +2993,7 @@
   // Map to unsigned.
   // Idea from https://stackoverflow.com/questions/10589559
 
-  static const UT offset
-    = UT (0) - static_cast<UT> (std::numeric_limits<ST>::min ());
+  static const UT offset = UT (0) - static_cast<UT> (std::numeric_limits<ST>::min ());
 
   UT au = static_cast<UT> (a) + offset;
   UT bu = static_cast<UT> (b) + offset;
@@ -3133,8 +3131,8 @@
       || (increment < 0 && base < limit))
     return 0;
 
-  static const double out_of_range_top
-    = static_cast<double> (std::numeric_limits<UT>::max ()) + 1.;
+  static constexpr double out_of_range_top
+    = static_cast<double> (std::numeric_limits<UT>::max ()) + 1.0;
 
   double abs_increment = std::abs (increment);
 
--- a/libinterp/operators/op-mi.cc	Wed Dec 20 18:24:41 2023 -0800
+++ b/libinterp/operators/op-mi.cc	Wed Dec 20 20:02:42 2023 -0800
@@ -67,10 +67,10 @@
 
   uint64_t ival = val.value ();
 
-  static const uint64_t max_val
+  static constexpr uint64_t max_val
     = static_cast<uint64_t> (std::numeric_limits<int64_t>::max ());
 
-  static const uint64_t max_val_p1 = max_val + 1;
+  static constexpr uint64_t max_val_p1 = max_val + 1;
 
   if (ival <= max_val)
     {
@@ -84,7 +84,7 @@
       // should return int8(-128) but converting directly to int8 and
       // negating will not return the correct result.
 
-      static const int64_t min_signed_ival
+      static constexpr int64_t min_signed_ival
         = std::numeric_limits<int64_t>::min ();
 
       return octave_value (new octave_magic_int (min_signed_ival));
--- a/liboctave/array/Array-base.cc	Wed Dec 20 18:24:41 2023 -0800
+++ b/liboctave/array/Array-base.cc	Wed Dec 20 20:02:42 2023 -0800
@@ -951,8 +951,8 @@
         }
       else
         {
-          static const octave_idx_type max_stack_chunk = 1024;
-          octave_idx_type nn = n + std::min (nx, max_stack_chunk);
+          static const octave_idx_type MAX_STACK_CHUNK = 1024;
+          octave_idx_type nn = n + std::min (nx, MAX_STACK_CHUNK);
           Array<T, Alloc> tmp (Array<T, Alloc> (dim_vector (nn, 1)), dv, 0, n);
           T *dest = tmp.fortran_vec ();
 
@@ -2196,11 +2196,11 @@
 
   // This determines the split ratio between the O(M*log2(N)) and O(M+N)
   // algorithms.
-  static const double ratio = 1.0;
+  static const double RATIO = 1.0;
   sortmode vmode = UNSORTED;
 
   // Attempt the O(M+N) algorithm if M is large enough.
-  if (nval > ratio * n / octave::math::log2 (n + 1.0))
+  if (nval > RATIO * n / octave::math::log2 (n + 1.0))
     {
       vmode = values.issorted ();
       // The table must not contain a NaN.
--- a/liboctave/array/Sparse.cc	Wed Dec 20 18:24:41 2023 -0800
+++ b/liboctave/array/Sparse.cc	Wed Dec 20 20:02:42 2023 -0800
@@ -150,9 +150,9 @@
   // Always preserve space for 1 element.
   nz = (nz > 0 ? nz : 1);
 
-  // Skip reallocation if we have less than 1/frac extra elements to discard.
-  static const int frac = 5;
-  if (nz > m_nzmax || nz < m_nzmax - m_nzmax/frac)
+  // Skip reallocation if we have less than 1/FRAC extra elements to discard.
+  static const int FRAC = 5;
+  if (nz > m_nzmax || nz < m_nzmax - m_nzmax/FRAC)
     {
       // Reallocate.
       octave_idx_type min_nzmax = std::min (nz, m_nzmax);
--- a/liboctave/array/idx-vector.cc	Wed Dec 20 18:24:41 2023 -0800
+++ b/liboctave/array/idx-vector.cc	Wed Dec 20 20:02:42 2023 -0800
@@ -761,7 +761,7 @@
   : m_rep (nullptr)
 {
   // Convert only if it means saving at least half the memory.
-  static const int factor = (2 * sizeof (octave_idx_type));
+  static constexpr int factor = (2 * sizeof (octave_idx_type));
   octave_idx_type nnz = bnda.nnz ();
   if (nnz <= bnda.numel () / factor)
     m_rep = new idx_vector_rep (bnda, nnz);
--- a/liboctave/numeric/lo-mappers.cc	Wed Dec 20 18:24:41 2023 -0800
+++ b/liboctave/numeric/lo-mappers.cc	Wed Dec 20 20:02:42 2023 -0800
@@ -187,29 +187,29 @@
 octave_idx_type
 nint_big (double x)
 {
-  static const double out_of_range_top
-    = static_cast<double> (std::numeric_limits<octave_idx_type>::max ())+1.;
+  static constexpr double out_of_range_top
+    = static_cast<double> (std::numeric_limits<octave_idx_type>::max ()) + 1.0;
+
   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 ();
   else
-    return static_cast<octave_idx_type> ((x > 0.0) ? (x + 0.5)
-                                         : (x - 0.5));
+    return static_cast<octave_idx_type> ((x > 0.0) ? (x + 0.5) : (x - 0.5));
 }
 
 octave_idx_type
 nint_big (float x)
 {
-  static const float out_of_range_top
-    = static_cast<float> (std::numeric_limits<octave_idx_type>::max ())+1.;
+  static constexpr float out_of_range_top
+    = static_cast<float> (std::numeric_limits<octave_idx_type>::max ()) + 1.0;
+
   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 ();
   else
-    return static_cast<octave_idx_type> ((x > 0.0f) ? (x + 0.5f)
-                                         : (x - 0.5f));
+    return static_cast<octave_idx_type> ((x > 0.0f) ? (x + 0.5f) : (x - 0.5f));
 }
 
 int
@@ -226,8 +226,9 @@
 int
 nint (float x)
 {
-  static const float out_of_range_top
-    = static_cast<float> (std::numeric_limits<int>::max ()) + 1.;
+  static constexpr float out_of_range_top
+    = static_cast<float> (std::numeric_limits<int>::max ()) + 1.0;
+
   if (x >= out_of_range_top)
     return std::numeric_limits<int>::max ();
   else if (x < std::numeric_limits<int>::min ())
--- a/liboctave/util/oct-inttypes.cc	Wed Dec 20 18:24:41 2023 -0800
+++ b/liboctave/util/oct-inttypes.cc	Wed Dec 20 20:02:42 2023 -0800
@@ -538,8 +538,8 @@
 OCTAVE_API octave_int64
 operator - (const double& x, const octave_int64& y)
 {
-  static const bool twosc = (std::numeric_limits<int64_t>::min ()
-                             < -std::numeric_limits<int64_t>::max ());
+  static constexpr bool twosc = (std::numeric_limits<int64_t>::min ()
+                                 < -std::numeric_limits<int64_t>::max ());
   // In case of symmetric integers (not two's complement), this will probably
   // be eliminated at compile time.
   if (twosc && y.value () == std::numeric_limits<int64_t>::min ())
--- a/liboctave/util/oct-inttypes.h	Wed Dec 20 18:24:41 2023 -0800
+++ b/liboctave/util/oct-inttypes.h	Wed Dec 20 20:02:42 2023 -0800
@@ -123,16 +123,16 @@
   class prom
   {
     // Promote to int?
-    static const bool s_pint = (sizeof (T1) < sizeof (int)
-                                && sizeof (T2) < sizeof (int));
+    static constexpr bool s_pint = (sizeof (T1) < sizeof (int)
+                                    && sizeof (T2) < sizeof (int));
 
-    static const bool s_t1sig = std::numeric_limits<T1>::is_signed;
-    static const bool s_t2sig = std::numeric_limits<T2>::is_signed;
+    static constexpr bool s_t1sig = std::numeric_limits<T1>::is_signed;
+    static constexpr bool s_t2sig = std::numeric_limits<T2>::is_signed;
 
-    static const bool s_psig
+    static constexpr bool s_psig
       = (s_pint || (sizeof (T2) > sizeof (T1) && s_t2sig) || s_t1sig);
 
-    static const int s_psize
+    static constexpr int s_psize
       = (s_pint
          ? sizeof (int)
          : (sizeof (T2) > sizeof (T1) ? sizeof (T2) : sizeof (T1)));
@@ -185,8 +185,8 @@
   {                                                     \
   public:                                               \
                                                         \
-    static const bool ltval = (0 OP 1);                 \
-    static const bool gtval = (1 OP 0);                 \
+    static constexpr bool ltval = (0 OP 1);             \
+    static constexpr bool gtval = (1 OP 0);             \
                                                         \
     template <typename T>                               \
     static bool op (T x, T y) { return x OP y; }        \
@@ -209,8 +209,8 @@
   {                                             \
   public:                                       \
                                                 \
-    static const bool ltval = VALUE;            \
-    static const bool gtval = VALUE;            \
+    static constexpr bool ltval = VALUE;        \
+    static constexpr bool gtval = VALUE;        \
                                                 \
     template <typename T>                       \
       static bool op (T, T) { return VALUE; }   \
@@ -357,16 +357,16 @@
     // An exhaustive test whether the max and/or min check can be
     // omitted.
 
-    static const bool t_is_signed = std::numeric_limits<T>::is_signed;
-    static const bool s_is_signed = std::numeric_limits<S>::is_signed;
+    static constexpr bool t_is_signed = std::numeric_limits<T>::is_signed;
+    static constexpr bool s_is_signed = std::numeric_limits<S>::is_signed;
 
-    static const int t_size = sizeof (T);
-    static const int s_size = sizeof (S);
+    static constexpr int t_size = sizeof (T);
+    static constexpr int s_size = sizeof (S);
 
-    static const bool omit_chk_min
+    static constexpr bool omit_chk_min
       = (! s_is_signed || (t_is_signed && t_size >= s_size));
 
-    static const bool omit_chk_max
+    static constexpr bool omit_chk_max
       = (t_size > s_size
          || (t_size == s_size && (! t_is_signed || s_is_signed)));
 
--- a/liboctave/util/oct-string.cc	Wed Dec 20 18:24:41 2023 -0800
+++ b/liboctave/util/oct-string.cc	Wed Dec 20 20:02:42 2023 -0800
@@ -917,10 +917,11 @@
   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.;
+  static constexpr T out_of_range_top
+    = static_cast<T> (std::numeric_limits<int>::max ()) + 1.0;
+  static constexpr T out_of_range_bottom
+    = static_cast<T> (std::numeric_limits<int>::min ()) - 1.0;
+
   if (octave::math::isinf (val))
     {
       if (val > 0)