changeset 10771:82d9efde7e96

pr-output.cc: Avoid use of % operator on negative operands to ensure compatability between C++ compilers.
author Rik <octave@nomad.inbox5.com>
date Wed, 07 Jul 2010 15:27:17 -0700
parents 84c35a483d1f
children 687586b99f9d
files src/ChangeLog src/pr-output.cc
diffstat 2 files changed, 69 insertions(+), 40 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,15 @@
+2010-07-07  Rik <octave@nomad.inbox5.com>
+
+	* pr-output.cc (calc_scale_exp): Avoid use of % operator on negative
+        operands for portability between C++ compilers.
+        (engineering_exponent): Avoid use of % operator.  Keep calculation of
+        exponent within pr_engineering_float class.  (encapsulation).
+        (num_digits): Rename from calc_digits.  Return true number of digits =
+        1 + calc_digits.
+        (calc_scale_exp): Rename from maybe_mod3 for readability.
+        (operator << (... pr_engineering_float pef): Use pef abbreviation for
+        pr_engineering_float.
+
 2010-07-07  David Bateman  <dbateman@free.fr>
 
 	* graphics.h.in (axes): Add hidden property __hold_all.
--- a/src/pr-output.cc
+++ b/src/pr-output.cc
@@ -184,13 +184,13 @@
     { sp = tz ? std::ios::showpoint : 0; return *this; }
 
   friend std::ostream& operator << (std::ostream& os,
-                                    const pr_engineering_float& pff);
+                                    const pr_engineering_float& pef);
 
   friend std::ostream& operator << (std::ostream& os,
                                     const pr_formatted_float& pff);
 
   friend std::ostream& operator << (std::ostream& os,
-                                    const pr_rational_float& pff);
+                                    const pr_rational_float& prf);
 
 private:
 
@@ -214,9 +214,24 @@
 };
 
 static int
-maybe_mod3 (const int& x)
+calc_scale_exp (const int& x)
 {
-  return print_eng ? x - (x % 3) : x;
+  if (! print_eng)
+    return x;
+  else
+    return x - 3*static_cast<int> (x/3);
+  /* The expression above is equivalent to x - (x % 3).
+   * According to the ISO specification for C++ the modulo operator is
+   * compiler dependent if any of the arguments are negative.  Since this
+   * function will need to work on negative arguments, and we want to avoid
+   * portability issues, we re-implement the modulo function to the desired
+   * behavior (truncation).  There may be a gnulib replacement.
+   *
+   * ISO/IEC 14882:2003 : Programming languages -- C++. 5.6.4: ISO, IEC. 2003 .
+   * "the binary % operator yields the remainder from the division of the first
+   * expression by the second. .... If both operands are nonnegative then the 
+   * remainder is nonnegative; if not, the sign of the remainder is 
+   * implementation-defined".  */
 }
 
 static int
@@ -227,19 +242,21 @@
     {
       double absval = (x < 0.0 ? -x : x);
       int logabsval = static_cast<int> (floor (log10 (absval)));
+      /* Avoid using modulo function with negative arguments for portability.
+       * See extended comment at calc_scale_exp */
       if (logabsval < 0.0)
-        ex = maybe_mod3 (logabsval - 2);  
+        ex = logabsval - 2 + ((-logabsval + 2) % 3);  
       else
-        ex = maybe_mod3 (logabsval);  
+        ex = logabsval - (logabsval % 3);
     }
   return ex;
 }
 
 static int
-calc_digits (const double& x)
+num_digits (const double& x)
 {
-  return print_eng ? engineering_exponent (x)
-    : static_cast<int> (floor (log10 (x)));
+  return 1 + (print_eng ? engineering_exponent (x)
+                        : static_cast<int> (floor (log10 (x))));
 }
 
 class
@@ -266,21 +283,21 @@
 };
 
 std::ostream&
-operator << (std::ostream& os, const pr_engineering_float& pff)
+operator << (std::ostream& os, const pr_engineering_float& pef)
 {
-  if (pff.f.fw >= 0)
-    os << std::setw (pff.f.fw - pff.f.ex);
-
-  if (pff.f.prec >= 0)
-    os << std::setprecision (pff.f.prec);
+  if (pef.f.fw >= 0)
+    os << std::setw (pef.f.fw - pef.f.ex);
+
+  if (pef.f.prec >= 0)
+    os << std::setprecision (pef.f.prec);
 
   std::ios::fmtflags oflags = 
     os.flags (static_cast<std::ios::fmtflags> 
-              (pff.f.fmt | pff.f.up | pff.f.sp));
-
-  os << pff.mantissa ();
-
-  int ex = pff.exponent ();
+              (pef.f.fmt | pef.f.up | pef.f.sp));
+
+  os << pef.mantissa ();
+
+  int ex = pef.exponent ();
   if (ex < 0)
     {
       os << std::setw (0) << "e-";
@@ -289,7 +306,7 @@
   else
     os << std::setw (0) << "e+";
 
-  os << std::setw (pff.f.ex - 2) << std::setfill('0') << ex 
+  os << std::setw (pef.f.ex - 2) << std::setfill('0') << ex 
      << std::setfill(' ');
 
   os.flags (oflags);
@@ -636,7 +653,7 @@
   double d_abs = d < 0.0 ? -d : d;
 
   int digits = (inf_or_nan || d_abs == 0.0)
-    ? 0 : (calc_digits (d_abs) + 1);
+    ? 0 : num_digits (d_abs);
 
   set_real_format (digits, inf_or_nan, int_only, fw);
 }
@@ -791,12 +808,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 : (calc_digits (max_abs) + 1);
-
-  int x_min = min_abs == 0.0 ? 0 : (calc_digits (min_abs) + 1);
+  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, maybe_mod3 (x_max - 1));
+    : std::pow (10.0, calc_scale_exp (x_max - 1));
 
   set_real_matrix_format (x_max, x_min, inf_or_nan, int_or_inf_or_nan, fw);
 }
@@ -982,10 +999,10 @@
   double i_abs = ip < 0.0 ? -ip : ip;
 
   int r_x = (xisinf (rp) || xisnan (rp) || r_abs == 0.0)
-    ? 0 : (calc_digits (r_abs) + 1);
+    ? 0 : num_digits (r_abs);
 
   int i_x = (xisinf (ip) || xisnan (ip) || i_abs == 0.0)
-    ? 0 : (calc_digits (i_abs) + 1);
+    ? 0 : num_digits (i_abs);
 
   int x_max, x_min;
 
@@ -1202,19 +1219,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 : (calc_digits (r_max_abs) + 1);
-
-  int r_x_min = r_min_abs == 0.0 ? 0 : (calc_digits (r_min_abs) + 1);
-
-  int i_x_max = i_max_abs == 0.0 ? 0 : (calc_digits (i_max_abs) + 1);
-
-  int i_x_min = i_min_abs == 0.0 ? 0 : (calc_digits (i_min_abs) + 1);
+  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 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, maybe_mod3 (x_max - 1));
+    : std::pow (10.0, calc_scale_exp (x_max - 1));
 
   set_complex_matrix_format (x_max, x_min, r_x_max, r_x_min, inf_or_nan,
                              int_or_inf_or_nan, r_fw, i_fw);
@@ -1365,12 +1382,12 @@
   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 : (calc_digits (max_abs) + 1);
-
-  int x_min = min_abs == 0.0 ? 0 : (calc_digits (min_abs) + 1);
+  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, maybe_mod3 (x_max - 1));
+    : std::pow (10.0, calc_scale_exp (x_max - 1));
 
   set_range_format (x_max, x_min, all_ints, fw);
 }