changeset 24770:39186eac5a05

preparing for a brave new future, use templates in some pr-output functions * pr-output.h, pr-output.cc, pr-flt-fmt.h (class pr_engineering_float, class pr_formatted_float, class pr_rational_float): Define as templates. Adapt all uses. (union equiv, engineering_exponent, num_digits, rational_approx, pr_any_float, pr_float, pr_imag_float, pr_complex, pr_scale_header): Define as templates. Use 1 and 0 instead of 1.0 and 0.0 to avoid creating double constants unnecessrily.
author John W. Eaton <jwe@octave.org>
date Fri, 16 Feb 2018 02:46:21 -0500
parents e574b957b01b
children d277debe9c2f
files libinterp/corefcn/pr-flt-fmt.h libinterp/corefcn/pr-output.cc libinterp/corefcn/pr-output.h
diffstat 3 files changed, 152 insertions(+), 122 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/pr-flt-fmt.h	Fri Feb 16 00:42:39 2018 -0500
+++ b/libinterp/corefcn/pr-flt-fmt.h	Fri Feb 16 02:46:21 2018 -0500
@@ -28,8 +28,13 @@
 #include <iomanip>
 #include <iosfwd>
 
+template <typename T>
 class pr_engineering_float;
+
+template <typename T>
 class pr_formatted_float;
+
+template <typename T>
 class pr_rational_float;
 
 extern int output_max_field_width (void);
@@ -105,14 +110,17 @@
     return *this;
   }
 
+  template <typename T>
   friend std::ostream&
-  operator << (std::ostream& os, const pr_engineering_float& pef);
+  operator << (std::ostream& os, const pr_engineering_float<T>& pef);
 
+  template <typename T>
   friend std::ostream&
-  operator << (std::ostream& os, const pr_formatted_float& pff);
+  operator << (std::ostream& os, const pr_formatted_float<T>& pff);
 
+  template <typename T>
   friend std::ostream&
-  operator << (std::ostream& os, const pr_rational_float& prf);
+  operator << (std::ostream& os, const pr_rational_float<T>& prf);
 
   // Field width.  Zero means as wide as necessary.
   int fw;
--- a/libinterp/corefcn/pr-output.cc	Fri Feb 16 00:42:39 2018 -0500
+++ b/libinterp/corefcn/pr-output.cc	Fri Feb 16 02:46:21 2018 -0500
@@ -134,20 +134,21 @@
   // the sign of the remainder is implementation-defined".
 }
 
+template <typename T>
 static int
-engineering_exponent (double x)
+engineering_exponent (T x)
 {
   int ex = 0;
 
   if (x != 0)
     {
-      double absval = (x < 0.0 ? -x : x);
+      T absval = (x < 0 ? -x : x);
       int logabsval = static_cast<int> (std::floor (log10 (absval)));
 
       // Avoid using modulo function with negative arguments for
       // portability.  See extended comment at calc_scale_exp
 
-      if (logabsval < 0.0)
+      if (logabsval < 0)
         ex = logabsval - 2 + ((-logabsval + 2) % 3);
       else
         ex = logabsval - (logabsval % 3);
@@ -156,28 +157,32 @@
   return ex;
 }
 
+template <typename T>
 static int
-num_digits (const double& x)
+num_digits (T x)
 {
   return 1 + (print_eng
               ? engineering_exponent (x)
               : static_cast<int> (std::floor (log10 (x))));
 }
 
+template <typename T>
 int
-pr_engineering_float::exponent (void) const
+pr_engineering_float<T>::exponent (void) const
 {
   return engineering_exponent (m_val);
 }
 
-double
-pr_engineering_float::mantissa (void) const
+template <typename T>
+T
+pr_engineering_float<T>::mantissa (void) const
 {
-  return m_val / std::pow (10.0, exponent ());
+  return m_val / std::pow (static_cast<T> (10), exponent ());
 }
 
+template <typename T>
 std::ostream&
-operator << (std::ostream& os, const pr_engineering_float& pef)
+operator << (std::ostream& os, const pr_engineering_float<T>& pef)
 {
   octave::preserve_stream_state stream_state (os);
 
@@ -208,8 +213,9 @@
   return os;
 }
 
+template <typename T>
 std::ostream&
-operator << (std::ostream& os, const pr_formatted_float& pff)
+operator << (std::ostream& os, const pr_formatted_float<T>& pff)
 {
   octave::preserve_stream_state stream_state (os);
 
@@ -229,8 +235,9 @@
   return os;
 }
 
+template <typename T>
 static inline std::string
-rational_approx (double val, int len)
+rational_approx (T val, int len)
 {
   std::string s;
 
@@ -252,11 +259,11 @@
     }
   else
     {
-      double lastn = 1.;
-      double lastd = 0.;
-      double n = octave::math::round (val);
-      double d = 1.;
-      double frac = val - n;
+      T lastn = 1;
+      T lastd = 0;
+      T n = octave::math::round (val);
+      T d = 1;
+      T frac = val - n;
       int m = 0;
 
       std::ostringstream buf2;
@@ -264,15 +271,15 @@
       buf2 << std::setprecision (0) << static_cast<int> (n);
       s = buf2.str ();
 
-      while (1)
+      while (true)
         {
-          double flip = 1. / frac;
-          double step = octave::math::round (flip);
-          double nextn = n;
-          double nextd = d;
+          T flip = 1 / frac;
+          T step = octave::math::round (flip);
+          T nextn = n;
+          T nextd = d;
 
           // Have we converged to 1/intmax ?
-          if (std::abs (flip) > static_cast<double> (std::numeric_limits<int>::max ()))
+          if (std::abs (flip) > static_cast<T> (std::numeric_limits<int>::max ()))
             {
               lastn = n;
               lastd = d;
@@ -307,7 +314,7 @@
           s = buf.str ();
         }
 
-      if (lastd < 0.)
+      if (lastd < 0)
         {
           // Move sign to the top
           lastd = - lastd;
@@ -337,8 +344,9 @@
 %! assert (err, 0, 4 * eps);
 */
 
+template <typename T>
 std::ostream&
-operator << (std::ostream& os, const pr_rational_float& prf)
+operator << (std::ostream& os, const pr_rational_float<T>& prf)
 {
   octave::preserve_stream_state stream_state (os);
 
@@ -385,7 +393,7 @@
       }
 
   if (all_inf_or_nan)
-    result = 0.0;
+    result = 0;
 
   return result;
 }
@@ -414,7 +422,7 @@
       }
 
   if (all_inf_or_nan)
-    result = 0.0;
+    result = 0;
 
   return result;
 }
@@ -526,9 +534,9 @@
 
   bool int_only = (! inf_or_nan && octave::math::x_nint (d) == d);
 
-  double d_abs = (d < 0.0 ? -d : d);
-
-  int digits = (inf_or_nan || d_abs == 0.0) ? 0 : num_digits (d_abs);
+  double d_abs = (d < 0 ? -d : d);
+
+  int digits = (inf_or_nan || d_abs == 0) ? 0 : num_digits (d_abs);
 
   return make_real_format (digits, inf_or_nan, int_only, fw);
 }
@@ -673,12 +681,12 @@
   double max_abs = pr_max_internal (m_abs);
   double min_abs = pr_min_internal (m_abs);
 
-  int x_max = (max_abs == 0.0 ? 0 : num_digits (max_abs));
-
-  int x_min = (min_abs == 0.0 ? 0 : num_digits (min_abs));
-
-  scale = (x_max == 0 || int_or_inf_or_nan)
-          ? 1.0 : std::pow (10.0, calc_scale_exp (x_max - 1));
+  int x_max = (max_abs == 0 ? 0 : num_digits (max_abs));
+
+  int x_min = (min_abs == 0 ? 0 : num_digits (min_abs));
+
+  scale = ((x_max == 0 || int_or_inf_or_nan)
+           ? 1 : std::pow (10.0, calc_scale_exp (x_max - 1)));
 
   return make_real_matrix_format (x_max, x_min, inf_or_nan,
                                   int_or_inf_or_nan, fw);
@@ -850,14 +858,14 @@
   bool int_only = (octave::math::x_nint (rp) == rp
                    && octave::math::x_nint (ip) == ip);
 
-  double r_abs = (rp < 0.0 ? -rp : rp);
-  double i_abs = (ip < 0.0 ? -ip : ip);
+  double r_abs = (rp < 0 ? -rp : rp);
+  double i_abs = (ip < 0 ? -ip : ip);
 
   int r_x = (! octave::math::isfinite (rp)
-             || r_abs == 0.0) ? 0 : num_digits (r_abs);
+             || r_abs == 0) ? 0 : num_digits (r_abs);
 
   int i_x = (! octave::math::isfinite (ip)
-             || i_abs == 0.0) ? 0 : num_digits (i_abs);
+             || i_abs == 0) ? 0 : num_digits (i_abs);
 
   int x_max, x_min;
 
@@ -1064,19 +1072,19 @@
   double i_max_abs = pr_max_internal (i_m_abs);
   double i_min_abs = pr_min_internal (i_m_abs);
 
-  int r_x_max = (r_max_abs == 0.0 ? 0 : num_digits (r_max_abs));
-
-  int r_x_min = (r_min_abs == 0.0 ? 0 : num_digits (r_min_abs));
-
-  int i_x_max = (i_max_abs == 0.0 ? 0 : num_digits (i_max_abs));
-
-  int i_x_min = (i_min_abs == 0.0 ? 0 : num_digits (i_min_abs));
+  int r_x_max = (r_max_abs == 0 ? 0 : num_digits (r_max_abs));
+
+  int r_x_min = (r_min_abs == 0 ? 0 : num_digits (r_min_abs));
+
+  int i_x_max = (i_max_abs == 0 ? 0 : num_digits (i_max_abs));
+
+  int i_x_min = (i_min_abs == 0 ? 0 : num_digits (i_min_abs));
 
   int x_max = (r_x_max > i_x_max ? r_x_max : i_x_max);
   int x_min = (r_x_min > i_x_min ? r_x_min : i_x_min);
 
-  scale = (x_max == 0 || int_or_inf_or_nan)
-          ? 1.0 : std::pow (10.0, calc_scale_exp (x_max - 1));
+  scale = ((x_max == 0 || int_or_inf_or_nan)
+           ? 1 : std::pow (10.0, calc_scale_exp (x_max - 1)));
 
   return make_complex_matrix_format (x_max, x_min, r_x_max, r_x_min,
                                      inf_or_nan, int_or_inf_or_nan,
@@ -1214,23 +1222,24 @@
 
   bool all_ints = r.all_elements_are_ints ();
 
-  double max_abs = (r_max < 0.0 ? -r_max : r_max);
-  double min_abs = (r_min < 0.0 ? -r_min : r_min);
-
-  int x_max = (max_abs == 0.0 ? 0 : num_digits (max_abs));
-
-  int x_min = (min_abs == 0.0 ? 0 : num_digits (min_abs));
-
-  scale = (x_max == 0 || all_ints)
-          ? 1.0 : std::pow (10.0, calc_scale_exp (x_max - 1));
+  double max_abs = (r_max < 0 ? -r_max : r_max);
+  double min_abs = (r_min < 0 ? -r_min : r_min);
+
+  int x_max = (max_abs == 0 ? 0 : num_digits (max_abs));
+
+  int x_min = (min_abs == 0 ? 0 : num_digits (min_abs));
+
+  scale = ((x_max == 0 || all_ints)
+           ? 1 : std::pow (10.0, calc_scale_exp (x_max - 1)));
 
   return make_range_format (x_max, x_min, all_ints, fw);
 }
 
+template <typename T>
 union equiv
 {
-  double d;
-  unsigned char i[sizeof (double)];
+  T val;
+  unsigned char i[sizeof (T)];
 };
 
 #define PRINT_CHAR_BITS(os, c)                  \
@@ -1269,8 +1278,9 @@
     }                                           \
   while (0)
 
+template <typename T>
 static void
-pr_any_float (std::ostream& os, const float_format& fmt, double d, int fw = 0)
+pr_any_float (std::ostream& os, const float_format& fmt, T val, int fw = 0)
 {
   // Unless explicitly asked for, always print in big-endian format
   // for hex and bit formats.
@@ -1282,8 +1292,8 @@
     {
       octave::preserve_stream_state stream_state (os);
 
-      equiv tmp;
-      tmp.d = d;
+      equiv<T> tmp;
+      tmp.val = val;
 
       // Unless explicitly asked for, always print in big-endian format.
 
@@ -1300,43 +1310,43 @@
       if (hex_format > 1
           || flt_fmt == octave::mach_info::flt_fmt_ieee_big_endian)
         {
-          for (size_t i = 0; i < sizeof (double); i++)
+          for (size_t i = 0; i < sizeof (T); i++)
             os << std::setw (2) << static_cast<int> (tmp.i[i]);
         }
       else
         {
-          for (int i = sizeof (double) - 1; i >= 0; i--)
+          for (int i = sizeof (T) - 1; i >= 0; i--)
             os << std::setw (2) << static_cast<int> (tmp.i[i]);
         }
     }
   else if (bit_format)
     {
-      equiv tmp;
-      tmp.d = d;
+      equiv<T> tmp;
+      tmp.val = val;
 
       octave::mach_info::float_format flt_fmt =
         octave::mach_info::native_float_format ();
 
       if (flt_fmt == octave::mach_info::flt_fmt_ieee_big_endian)
         {
-          for (size_t i = 0; i < sizeof (double); i++)
+          for (size_t i = 0; i < sizeof (T); i++)
             PRINT_CHAR_BITS (os, tmp.i[i]);
         }
       else
         {
           if (bit_format > 1)
             {
-              for (size_t i = 0; i < sizeof (double); i++)
+              for (size_t i = 0; i < sizeof (T); i++)
                 PRINT_CHAR_BITS_SWAPPED (os, tmp.i[i]);
             }
           else
             {
-              for (int i = sizeof (double) - 1; i >= 0; i--)
+              for (int i = sizeof (T) - 1; i >= 0; i--)
                 PRINT_CHAR_BITS (os, tmp.i[i]);
             }
         }
     }
-  else if (octave::math::isna (d))
+  else if (octave::math::isna (val))
     {
       octave::preserve_stream_state stream_state (os);
 
@@ -1346,13 +1356,13 @@
         os << "NA";
     }
   else if (rat_format)
-    os << pr_rational_float (fmt, d);
-  else if (octave::math::isinf (d))
+    os << pr_rational_float<T> (fmt, val);
+  else if (octave::math::isinf (val))
     {
       octave::preserve_stream_state stream_state (os);
 
       const char *s;
-      if (d < 0.0)
+      if (val < 0)
         s = "-Inf";
       else
         s = "Inf";
@@ -1362,7 +1372,7 @@
       else
         os << s;
     }
-  else if (octave::math::isnan (d))
+  else if (octave::math::isnan (val))
     {
       octave::preserve_stream_state stream_state (os);
 
@@ -1372,42 +1382,47 @@
         os << "NaN";
     }
   else if (print_eng)
-    os << pr_engineering_float (fmt, d);
+    os << pr_engineering_float<T> (fmt, val);
   else
-    os << pr_formatted_float (fmt, d);
+    os << pr_formatted_float<T> (fmt, val);
 }
 
+template <typename T>
 static inline void
-pr_float (std::ostream& os, const float_display_format& fmt, double d,
-          int fw = 0, double scale = 1.0)
+pr_float (std::ostream& os, const float_display_format& fmt, T val,
+          int fw = 0, T scale = 1)
 {
-  if (Vfixed_point_format && ! print_g && scale != 1.0)
-    d /= scale;
-
-  pr_any_float (os, fmt.real_format (), d, fw);
+  if (Vfixed_point_format && ! print_g && scale != 1)
+    val /= scale;
+
+  pr_any_float (os, fmt.real_format (), val, fw);
 }
 
+template <typename T>
 static inline void
 pr_imag_float (std::ostream& os, const float_display_format& fmt,
-               double d, int fw = 0)
+               T val, int fw = 0)
 {
-  pr_any_float (os, fmt.imag_format (), d, fw);
+  pr_any_float (os, fmt.imag_format (), val, fw);
 }
 
+template <typename T>
 static void
 pr_complex (std::ostream& os, const float_display_format& fmt,
-            const Complex& c, int r_fw = 0, int i_fw = 0, double scale = 1.0)
+            const std::complex<T>& cval, int r_fw = 0, int i_fw = 0,
+            T scale = 1)
 {
-  Complex tmp
-    = (Vfixed_point_format && ! print_g && scale != 1.0) ? c / scale : c;
-
-  double r = tmp.real ();
+  std::complex<T> tmp
+    = ((Vfixed_point_format && ! print_g && scale != 1)
+       ? cval / scale : cval);
+
+  T r = tmp.real ();
 
   pr_float (os, fmt, r, r_fw);
 
   if (! bank_format)
     {
-      double i = tmp.imag ();
+      T i = tmp.imag ();
       if (! (hex_format || bit_format) && lo_ieee_signbit (i))
         {
           os << " - ";
@@ -1466,10 +1481,11 @@
     }
 }
 
+template <typename T>
 static void
-pr_scale_header (std::ostream& os, double scale)
+pr_scale_header (std::ostream& os, T scale)
 {
-  if (Vfixed_point_format && ! print_g && scale != 1.0)
+  if (Vfixed_point_format && ! print_g && scale != 1)
     {
       octave::preserve_stream_state stream_state (os);
 
@@ -1630,7 +1646,7 @@
       {                                                                 \
         int new_digits                                                  \
           = static_cast<int>                                            \
-          (std::floor (log10 (double (abs (nda(i).value ()))) + 1.0));  \
+          (std::floor (log10 (double (abs (nda(i).value ()))) + 1));  \
                                                                         \
         if (new_digits > digits)                                        \
           digits = new_digits;                                          \
@@ -1693,7 +1709,7 @@
     bool isneg = false;                                                 \
     int digits                                                          \
       = static_cast<int>                                                \
-      (std::floor (log10 (double (abs (val.value ()))) + 1.0));         \
+      (std::floor (log10 (double (abs (val.value ()))) + 1));         \
                                                                         \
     isneg = (abs (val.value ()) != val.value ());                       \
                                                                         \
@@ -1796,7 +1812,7 @@
   else
     {
       int fw = 0;
-      double scale = 1.0;
+      double scale = 1;
       float_display_format fmt = make_format (m, fw, scale);
       int column_width = fw + 2;
       octave_idx_type total_width = nc * column_width;
@@ -1925,7 +1941,7 @@
   else
     {
       int fw;
-      double scale = 1.0;
+      double scale = 1;
       float_display_format fmt = make_format (Matrix (m.diag ()), fw, scale);
       int column_width = fw + 2;
       octave_idx_type total_width = nc * column_width;
@@ -2139,14 +2155,14 @@
   double rp = c.real ();
   double ip = c.imag ();
 
-  if (rp == 0.0)
+  if (rp == 0)
     {
-      if (ip == 0.0)
+      if (ip == 0)
         os << ' ';
       else
         os << 'i';
     }
-  else if (ip == 0.0)
+  else if (ip == 0)
     pr_plus_format (os, rp);
   else
     os << 'c';
@@ -2196,7 +2212,7 @@
   else
     {
       int r_fw, i_fw;
-      double scale = 1.0;
+      double scale = 1;
       float_display_format fmt = make_format (cm, r_fw, i_fw, scale);
       int column_width = i_fw + r_fw;
       column_width += (rat_format || bank_format || hex_format
@@ -2327,7 +2343,7 @@
   else
     {
       int r_fw, i_fw;
-      double scale = 1.0;
+      double scale = 1;
       float_display_format fmt
         = make_format (ComplexMatrix (cm.diag ()), r_fw, i_fw, scale);
       int column_width = i_fw + r_fw;
@@ -2407,7 +2423,7 @@
           int zero_fw;
           {
             std::ostringstream tmp_oss;
-            pr_complex (tmp_oss, fmt, Complex (0.0), r_fw, i_fw, scale);
+            pr_complex (tmp_oss, fmt, Complex (0), r_fw, i_fw, scale);
             zero_fw = tmp_oss.str ().length ();
           }
 
@@ -2658,7 +2674,7 @@
   else
     {
       int fw = 0;
-      double scale = 1.0;
+      double scale = 1;
       float_display_format fmt = make_format (r, fw, scale);
 
       if (pr_as_read_syntax)
@@ -2666,7 +2682,7 @@
           if (free_format)
             {
               os << base << " : ";
-              if (increment != 1.0)
+              if (increment != 1)
                 os << increment << " : ";
               os << limit;
             }
@@ -2674,7 +2690,7 @@
             {
               pr_float (os, fmt, base, fw);
               os << " : ";
-              if (increment != 1.0)
+              if (increment != 1)
                 {
                   pr_float (os, fmt, increment, fw);
                   os << " : ";
@@ -3210,7 +3226,7 @@
             {
               int new_digits
                 = static_cast<int>
-                  (std::floor (log10 (double (abs (nda(i).value ()))) + 1.0));
+                  (std::floor (log10 (double (abs (nda(i).value ()))) + 1));
 
               if (new_digits > digits)
                 digits = new_digits;
--- a/libinterp/corefcn/pr-output.h	Fri Feb 16 00:42:39 2018 -0500
+++ b/libinterp/corefcn/pr-output.h	Fri Feb 16 02:46:21 2018 -0500
@@ -519,6 +519,7 @@
 octave_print_internal (std::ostream& os, const octave_value& ov,
                        bool pr_as_read_syntax = false);
 
+template <typename T>
 class
 pr_engineering_float
 {
@@ -526,19 +527,20 @@
 
   const float_format m_ff;
 
-  double m_val;
+  T m_val;
 
   int exponent (void) const;
 
-  double mantissa (void) const;
+  T mantissa (void) const;
 
-  pr_engineering_float (const float_format& ff, double val)
+  pr_engineering_float (const float_format& ff, T val)
     : m_ff (ff), m_val (val) { }
 
-  pr_engineering_float (const float_display_format& fdf, double val)
+  pr_engineering_float (const float_display_format& fdf, T val)
     : m_ff (fdf.real_format ()), m_val (val) { }
 };
 
+template <typename T>
 class
 pr_formatted_float
 {
@@ -546,15 +548,16 @@
 
   const float_format m_ff;
 
-  double m_val;
+  T m_val;
 
-  pr_formatted_float (const float_format& ff, double val)
+  pr_formatted_float (const float_format& ff, T val)
     : m_ff (ff), m_val (val) { }
 
-  pr_formatted_float (const float_display_format& fdf, double val)
+  pr_formatted_float (const float_display_format& fdf, T val)
     : m_ff (fdf.real_format ()), m_val (val) { }
 };
 
+template <typename T>
 class
 pr_rational_float
 {
@@ -562,23 +565,26 @@
 
   const float_format m_ff;
 
-  double m_val;
+  T m_val;
 
-  pr_rational_float (const float_format& ff, double val)
+  pr_rational_float (const float_format& ff, T val)
     : m_ff (ff), m_val (val) { }
 
-  pr_rational_float (const float_display_format& fdf, double val)
+  pr_rational_float (const float_display_format& fdf, T val)
     : m_ff (fdf.real_format ()), m_val (val) { }
 };
 
+template <typename T>
 extern std::ostream&
-operator << (std::ostream& os, const pr_engineering_float& pef);
+operator << (std::ostream& os, const pr_engineering_float<T>& pef);
 
+template <typename T>
 extern std::ostream&
-operator << (std::ostream& os, const pr_formatted_float& pff);
+operator << (std::ostream& os, const pr_formatted_float<T>& pff);
 
+template <typename T>
 extern std::ostream&
-operator << (std::ostream& os, const pr_rational_float& prf);
+operator << (std::ostream& os, const pr_rational_float<T>& prf);
 
 // TRUE means that the dimensions of empty objects should be printed
 // like this: x = [](2x0).