pr-output.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1993-2012 John W. Eaton
00004 
00005 This file is part of Octave.
00006 
00007 Octave is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 Octave is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Octave; see the file COPYING.  If not, see
00019 <http://www.gnu.org/licenses/>.
00020 
00021 */
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026 
00027 #include <cfloat>
00028 #include <cstdio>
00029 #include <cstring>
00030 
00031 #include <iomanip>
00032 #include <iostream>
00033 #include <sstream>
00034 #include <string>
00035 
00036 #include "Array-util.h"
00037 #include "CMatrix.h"
00038 #include "Range.h"
00039 #include "cmd-edit.h"
00040 #include "dMatrix.h"
00041 #include "lo-mappers.h"
00042 #include "lo-math.h"
00043 #include "mach-info.h"
00044 #include "oct-cmplx.h"
00045 #include "quit.h"
00046 #include "str-vec.h"
00047 
00048 #include "Cell.h"
00049 #include "defun.h"
00050 #include "error.h"
00051 #include "gripes.h"
00052 #include "oct-obj.h"
00053 #include "oct-stream.h"
00054 #include "pager.h"
00055 #include "pr-output.h"
00056 #include "sysdep.h"
00057 #include "unwind-prot.h"
00058 #include "utils.h"
00059 #include "variables.h"
00060 
00061 // TRUE means use a scaled fixed point format for 'format long' and
00062 // 'format short'.
00063 static bool Vfixed_point_format = false;
00064 
00065 // The maximum field width for a number printed by the default output
00066 // routines.
00067 static int Voutput_max_field_width = 10;
00068 
00069 // The precision of the numbers printed by the default output
00070 // routines.
00071 static int Voutput_precision = 5;
00072 
00073 // TRUE means that the dimensions of empty objects should be printed
00074 // like this: x = [](2x0).
00075 bool Vprint_empty_dimensions = true;
00076 
00077 // TRUE means that the rows of big matrices should be split into
00078 // smaller slices that fit on the screen.
00079 static bool Vsplit_long_rows = true;
00080 
00081 // TRUE means don't do any fancy formatting.
00082 static bool free_format = false;
00083 
00084 // TRUE means print plus sign for nonzero, blank for zero.
00085 static bool plus_format = false;
00086 
00087 // First char for > 0, second for < 0, third for == 0.
00088 static std::string plus_format_chars = "+  ";
00089 
00090 // TRUE means always print in a rational approximation
00091 static bool rat_format = false;
00092 
00093 // Used to force the length of the rational approximation string for Frats
00094 static int rat_string_len = -1;
00095 
00096 // TRUE means always print like dollars and cents.
00097 static bool bank_format = false;
00098 
00099 // TRUE means print data in hexadecimal format.
00100 static int hex_format = 0;
00101 
00102 // TRUE means print data in binary-bit-pattern format.
00103 static int bit_format = 0;
00104 
00105 // TRUE means don't put newlines around the column number headers.
00106 bool Vcompact_format = false;
00107 
00108 // TRUE means use an e format.
00109 static bool print_e = false;
00110 
00111 // TRUE means use a g format.
00112 static bool print_g = false;
00113 
00114 // TRUE means print E instead of e for exponent field.
00115 static bool print_big_e = false;
00116 
00117 // TRUE means use an engineering format.
00118 static bool print_eng = false;
00119 
00120 class pr_engineering_float;
00121 class pr_formatted_float;
00122 class pr_rational_float;
00123 
00124 static int
00125 current_output_max_field_width (void)
00126 {
00127   return Voutput_max_field_width;
00128 }
00129 
00130 static int
00131 current_output_precision (void)
00132 {
00133   return Voutput_precision;
00134 }
00135 
00136 class
00137 float_format
00138 {
00139 public:
00140 
00141   float_format (int w = current_output_max_field_width (),
00142                 int p = current_output_precision (), int f = 0)
00143     : fw (w), ex (0), prec (p), fmt (f), up (0), sp (0) { }
00144 
00145   float_format (int w, int e, int p, int f)
00146     : fw (w), ex (e), prec (p), fmt (f), up (0), sp (0) { }
00147 
00148   float_format (const float_format& ff)
00149     : fw (ff.fw), ex (ff.ex), prec (ff.prec), fmt (ff.fmt), up (ff.up), sp (ff.sp) { }
00150 
00151   float_format& operator = (const float_format& ff)
00152     {
00153       if (&ff != this)
00154         {
00155           fw = ff.fw;
00156           ex = ff.ex;
00157           prec = ff.prec;
00158           fmt = ff.fmt;
00159           up = ff.up;
00160           sp = ff.sp;
00161         }
00162 
00163       return *this;
00164     }
00165 
00166   ~float_format (void) { }
00167 
00168   float_format& scientific (void) { fmt = std::ios::scientific; return *this; }
00169   float_format& fixed (void) { fmt = std::ios::fixed; return *this; }
00170   float_format& general (void) { fmt = 0; return *this; }
00171 
00172   float_format& uppercase (void) { up = std::ios::uppercase; return *this; }
00173   float_format& lowercase (void) { up = 0; return *this; }
00174 
00175   float_format& precision (int p) { prec = p; return *this; }
00176 
00177   float_format& width (int w) { fw = w; return *this; }
00178 
00179   float_format& trailing_zeros (bool tz = true)
00180     { sp = tz ? std::ios::showpoint : 0; return *this; }
00181 
00182   friend std::ostream& operator << (std::ostream& os,
00183                                     const pr_engineering_float& pef);
00184 
00185   friend std::ostream& operator << (std::ostream& os,
00186                                     const pr_formatted_float& pff);
00187 
00188   friend std::ostream& operator << (std::ostream& os,
00189                                     const pr_rational_float& prf);
00190 
00191 private:
00192 
00193   // Field width.  Zero means as wide as necessary.
00194   int fw;
00195 
00196   // Exponent Field width.  Zero means as wide as necessary.
00197   int ex;
00198 
00199   // Precision.
00200   int prec;
00201 
00202   // Format.
00203   int fmt;
00204 
00205   // E or e.
00206   int up;
00207 
00208   // Show trailing zeros.
00209   int sp;
00210 };
00211 
00212 static int
00213 calc_scale_exp (const int& x)
00214 {
00215   if (! print_eng)
00216     return x;
00217   else
00218     return x - 3*static_cast<int> (x/3);
00219   /* The expression above is equivalent to x - (x % 3).
00220    * According to the ISO specification for C++ the modulo operator is
00221    * compiler dependent if any of the arguments are negative.  Since this
00222    * function will need to work on negative arguments, and we want to avoid
00223    * portability issues, we re-implement the modulo function to the desired
00224    * behavior (truncation).  There may be a gnulib replacement.
00225    *
00226    * ISO/IEC 14882:2003 : Programming languages -- C++. 5.6.4: ISO, IEC. 2003 .
00227    * "the binary % operator yields the remainder from the division of the first
00228    * expression by the second. .... If both operands are nonnegative then the
00229    * remainder is nonnegative; if not, the sign of the remainder is
00230    * implementation-defined".  */
00231 }
00232 
00233 static int
00234 engineering_exponent (const double& x)
00235 {
00236   int ex = 0;
00237   if (x != 0)
00238     {
00239       double absval = (x < 0.0 ? -x : x);
00240       int logabsval = static_cast<int> (gnulib::floor (log10 (absval)));
00241       /* Avoid using modulo function with negative arguments for portability.
00242        * See extended comment at calc_scale_exp */
00243       if (logabsval < 0.0)
00244         ex = logabsval - 2 + ((-logabsval + 2) % 3);
00245       else
00246         ex = logabsval - (logabsval % 3);
00247     }
00248   return ex;
00249 }
00250 
00251 static int
00252 num_digits (const double& x)
00253 {
00254   return 1 + (print_eng
00255               ? engineering_exponent (x)
00256               : static_cast<int> (gnulib::floor (log10 (x))));
00257 }
00258 
00259 class
00260 pr_engineering_float
00261 {
00262 public:
00263 
00264   const float_format& f;
00265 
00266   double val;
00267 
00268   int exponent (void) const
00269   {
00270     return engineering_exponent (val);
00271   }
00272 
00273   double mantissa (void) const
00274   {
00275     return val / std::pow (10.0, exponent ());
00276   }
00277 
00278   pr_engineering_float (const float_format& f_arg, double val_arg)
00279     : f (f_arg), val (val_arg) { }
00280 };
00281 
00282 std::ostream&
00283 operator << (std::ostream& os, const pr_engineering_float& pef)
00284 {
00285   if (pef.f.fw >= 0)
00286     os << std::setw (pef.f.fw - pef.f.ex);
00287 
00288   if (pef.f.prec >= 0)
00289     os << std::setprecision (pef.f.prec);
00290 
00291   std::ios::fmtflags oflags =
00292     os.flags (static_cast<std::ios::fmtflags>
00293               (pef.f.fmt | pef.f.up | pef.f.sp));
00294 
00295   os << pef.mantissa ();
00296 
00297   int ex = pef.exponent ();
00298   if (ex < 0)
00299     {
00300       os << std::setw (0) << "e-";
00301       ex = -ex;
00302     }
00303   else
00304     os << std::setw (0) << "e+";
00305 
00306   os << std::setw (pef.f.ex - 2) << std::setfill('0') << ex
00307      << std::setfill(' ');
00308 
00309   os.flags (oflags);
00310 
00311   return os;
00312 }
00313 
00314 class
00315 pr_formatted_float
00316 {
00317 public:
00318 
00319   const float_format& f;
00320 
00321   double val;
00322 
00323   pr_formatted_float (const float_format& f_arg, double val_arg)
00324     : f (f_arg), val (val_arg) { }
00325 };
00326 
00327 std::ostream&
00328 operator << (std::ostream& os, const pr_formatted_float& pff)
00329 {
00330   if (pff.f.fw >= 0)
00331     os << std::setw (pff.f.fw);
00332 
00333   if (pff.f.prec >= 0)
00334     os << std::setprecision (pff.f.prec);
00335 
00336   std::ios::fmtflags oflags =
00337     os.flags (static_cast<std::ios::fmtflags>
00338               (pff.f.fmt | pff.f.up | pff.f.sp));
00339 
00340   os << pff.val;
00341 
00342   os.flags (oflags);
00343 
00344   return os;
00345 }
00346 
00347 static inline std::string
00348 rational_approx (double val, int len)
00349 {
00350   std::string s;
00351 
00352   if (len <= 0)
00353     len = 10;
00354 
00355   if (xisinf (val))
00356     s = "1/0";
00357   else if (xisnan (val))
00358     s = "0/0";
00359   else if (val < INT_MIN || val > INT_MAX || D_NINT (val) == val)
00360     {
00361       std::ostringstream buf;
00362       buf.flags (std::ios::fixed);
00363       buf << std::setprecision (0) << xround(val);
00364       s = buf.str ();
00365     }
00366   else
00367     {
00368       double lastn = 1.;
00369       double lastd = 0.;
00370       double n = xround (val);
00371       double d = 1.;
00372       double frac = val - n;
00373       int m = 0;
00374 
00375       std::ostringstream buf2;
00376       buf2.flags (std::ios::fixed);
00377       buf2 << std::setprecision (0) << static_cast<int>(n);
00378       s = buf2.str();
00379 
00380       while (1)
00381         {
00382           double flip = 1. / frac;
00383           double step = xround (flip);
00384           double nextn = n;
00385           double nextd = d;
00386 
00387           // Have we converged to 1/intmax ?
00388           if (m > 100 || fabs (frac) < 1 / static_cast<double>(INT_MAX))
00389             {
00390               lastn = n;
00391               lastd = d;
00392               break;
00393             }
00394 
00395           frac = flip - step;
00396           n = n * step + lastn;
00397           d = d * step + lastd;
00398           lastn = nextn;
00399           lastd = nextd;
00400 
00401           std::ostringstream buf;
00402           buf.flags (std::ios::fixed);
00403           buf << std::setprecision (0) << static_cast<int>(n)
00404               << "/" << static_cast<int>(d);
00405           m++;
00406 
00407           if (n < 0 && d < 0)
00408             {
00409               // Double negative, string can be two characters longer..
00410               if (buf.str().length() > static_cast<unsigned int>(len + 2) &&
00411                   m > 1)
00412                 break;
00413             }
00414           else if (buf.str().length() > static_cast<unsigned int>(len) &&
00415                    m > 1)
00416             break;
00417 
00418           s = buf.str();
00419         }
00420 
00421       if (lastd < 0.)
00422         {
00423           // Move sign to the top
00424           lastd = - lastd;
00425           lastn = - lastn;
00426           std::ostringstream buf;
00427           buf.flags (std::ios::fixed);
00428           buf << std::setprecision (0) << static_cast<int>(lastn)
00429                << "/" << static_cast<int>(lastd);
00430           s = buf.str();
00431         }
00432     }
00433 
00434   return s;
00435 }
00436 
00437 class
00438 pr_rational_float
00439 {
00440 public:
00441 
00442   const float_format& f;
00443 
00444   double val;
00445 
00446   pr_rational_float (const float_format& f_arg, double val_arg)
00447     : f (f_arg), val (val_arg) { }
00448 };
00449 
00450 std::ostream&
00451 operator << (std::ostream& os, const pr_rational_float& prf)
00452 {
00453   int fw = (rat_string_len > 0 ? rat_string_len : prf.f.fw);
00454   std::string s = rational_approx (prf.val, fw);
00455 
00456   if (fw >= 0)
00457     os << std::setw (fw);
00458 
00459   std::ios::fmtflags oflags =
00460     os.flags (static_cast<std::ios::fmtflags>
00461               (prf.f.fmt | prf.f.up | prf.f.sp));
00462 
00463   if (fw > 0 && s.length() > static_cast<unsigned int>(fw))
00464     os << "*";
00465   else
00466     os << s;
00467 
00468   os.flags (oflags);
00469 
00470   return os;
00471 }
00472 
00473 // Current format for real numbers and the real part of complex
00474 // numbers.
00475 static float_format *curr_real_fmt = 0;
00476 
00477 // Current format for the imaginary part of complex numbers.
00478 static float_format *curr_imag_fmt = 0;
00479 
00480 static double
00481 pr_max_internal (const Matrix& m)
00482 {
00483   octave_idx_type nr = m.rows ();
00484   octave_idx_type nc = m.columns ();
00485 
00486   double result = -DBL_MAX;
00487 
00488   bool all_inf_or_nan = true;
00489 
00490   for (octave_idx_type j = 0; j < nc; j++)
00491     for (octave_idx_type i = 0; i < nr; i++)
00492       {
00493         double val = m(i,j);
00494         if (xisinf (val) || xisnan (val))
00495           continue;
00496 
00497         all_inf_or_nan = false;
00498 
00499         if (val > result)
00500           result = val;
00501       }
00502 
00503   if (all_inf_or_nan)
00504     result = 0.0;
00505 
00506   return result;
00507 }
00508 
00509 static double
00510 pr_min_internal (const Matrix& m)
00511 {
00512   octave_idx_type nr = m.rows ();
00513   octave_idx_type nc = m.columns ();
00514 
00515   double result = DBL_MAX;
00516 
00517   bool all_inf_or_nan = true;
00518 
00519   for (octave_idx_type j = 0; j < nc; j++)
00520     for (octave_idx_type i = 0; i < nr; i++)
00521       {
00522         double val = m(i,j);
00523         if (xisinf (val) || xisnan (val))
00524           continue;
00525 
00526         all_inf_or_nan = false;
00527 
00528         if (val < result)
00529           result = val;
00530       }
00531 
00532   if (all_inf_or_nan)
00533     result = 0.0;
00534 
00535   return result;
00536 }
00537 
00538 // FIXME -- it would be nice to share more code among these
00539 // functions,..
00540 
00541 static void
00542 set_real_format (int digits, bool inf_or_nan, bool int_only, int &fw)
00543 {
00544   static float_format fmt;
00545 
00546   int prec = Voutput_precision;
00547 
00548   int ld, rd;
00549 
00550   if (rat_format)
00551     {
00552       fw = 0;
00553       rd = 0;
00554     }
00555   else if (bank_format)
00556     {
00557       fw = digits < 0 ? 4 : digits + 3;
00558       if (inf_or_nan && fw < 4)
00559         fw = 4;
00560       rd = 2;
00561     }
00562   else if (hex_format)
00563     {
00564       fw = 2 * sizeof (double);
00565       rd = 0;
00566     }
00567   else if (bit_format)
00568     {
00569       fw = 8 * sizeof (double);
00570       rd = 0;
00571     }
00572   else if (inf_or_nan || int_only)
00573     {
00574       fw = 1 + digits;
00575       if (inf_or_nan && fw < 4)
00576         fw = 4;
00577       rd = fw;
00578     }
00579   else
00580     {
00581       if (digits > 0)
00582         {
00583           ld = digits;
00584           rd = prec > digits ? prec - digits : prec;
00585           digits++;
00586         }
00587       else
00588         {
00589           ld = 1;
00590           rd = prec > digits ? prec - digits : prec;
00591           digits = -digits + 1;
00592         }
00593 
00594       fw = 1 + ld + 1 + rd;
00595       if (inf_or_nan && fw < 4)
00596         fw = 4;
00597     }
00598 
00599   if (! (rat_format || bank_format || hex_format || bit_format)
00600       && (fw > Voutput_max_field_width || print_e || print_g || print_eng))
00601     {
00602       if (print_g)
00603         fmt = float_format ();
00604       else
00605         {
00606           int ex = 4;
00607           if (digits > 100)
00608             ex++;
00609 
00610           if (print_eng)
00611             {
00612               fw = 4 + prec + ex;
00613               if (inf_or_nan && fw < 6)
00614                 fw = 6;
00615               fmt = float_format (fw, ex, prec - 1, std::ios::fixed);
00616             }
00617           else
00618             {
00619               fw = 2 + prec + ex;
00620               if (inf_or_nan && fw < 4)
00621                 fw = 4;
00622               fmt = float_format (fw, prec - 1, std::ios::scientific);
00623             }
00624         }
00625 
00626       if (print_big_e)
00627         fmt.uppercase ();
00628     }
00629   else if (! bank_format && (inf_or_nan || int_only))
00630     fmt = float_format (fw, rd);
00631   else
00632     fmt = float_format (fw, rd, std::ios::fixed);
00633 
00634   curr_real_fmt = &fmt;
00635 }
00636 
00637 static void
00638 set_format (double d, int& fw)
00639 {
00640   curr_real_fmt = 0;
00641   curr_imag_fmt = 0;
00642 
00643   if (free_format)
00644     return;
00645 
00646   bool inf_or_nan = (xisinf (d) || xisnan (d));
00647 
00648   bool int_only = (! inf_or_nan && D_NINT (d) == d);
00649 
00650   double d_abs = d < 0.0 ? -d : d;
00651 
00652   int digits = (inf_or_nan || d_abs == 0.0)
00653     ? 0 : num_digits (d_abs);
00654 
00655   set_real_format (digits, inf_or_nan, int_only, fw);
00656 }
00657 
00658 static inline void
00659 set_format (double d)
00660 {
00661   int fw;
00662   set_format (d, fw);
00663 }
00664 
00665 static void
00666 set_real_matrix_format (int x_max, int x_min, bool inf_or_nan,
00667                         int int_or_inf_or_nan, int& fw)
00668 {
00669   static float_format fmt;
00670 
00671   int prec = Voutput_precision;
00672 
00673   int ld, rd;
00674 
00675   if (rat_format)
00676     {
00677       fw = 9;
00678       rd = 0;
00679     }
00680   else if (bank_format)
00681     {
00682       int digits = x_max > x_min ? x_max : x_min;
00683       fw = digits <= 0 ? 4 : digits + 3;
00684       if (inf_or_nan && fw < 4)
00685         fw = 4;
00686       rd = 2;
00687     }
00688   else if (hex_format)
00689     {
00690       fw = 2 * sizeof (double);
00691       rd = 0;
00692     }
00693   else if (bit_format)
00694     {
00695       fw = 8 * sizeof (double);
00696       rd = 0;
00697     }
00698   else if (Vfixed_point_format && ! print_g)
00699     {
00700       rd = prec;
00701       fw = rd + 2;
00702       if (inf_or_nan && fw < 4)
00703         fw = 4;
00704     }
00705   else if (int_or_inf_or_nan)
00706     {
00707       int digits = x_max > x_min ? x_max : x_min;
00708       fw = digits <= 0 ? 2 : digits + 1;
00709       if (inf_or_nan && fw < 4)
00710         fw = 4;
00711       rd = fw;
00712     }
00713   else
00714     {
00715       int ld_max, rd_max;
00716       if (x_max > 0)
00717         {
00718           ld_max = x_max;
00719           rd_max = prec > x_max ? prec - x_max : prec;
00720           x_max++;
00721         }
00722       else
00723         {
00724           ld_max = 1;
00725           rd_max = prec > x_max ? prec - x_max : prec;
00726           x_max = -x_max + 1;
00727         }
00728 
00729       int ld_min, rd_min;
00730       if (x_min > 0)
00731         {
00732           ld_min = x_min;
00733           rd_min = prec > x_min ? prec - x_min : prec;
00734           x_min++;
00735         }
00736       else
00737         {
00738           ld_min = 1;
00739           rd_min = prec > x_min ? prec - x_min : prec;
00740           x_min = -x_min + 1;
00741         }
00742 
00743       ld = ld_max > ld_min ? ld_max : ld_min;
00744       rd = rd_max > rd_min ? rd_max : rd_min;
00745 
00746       fw = 1 + ld + 1 + rd;
00747       if (inf_or_nan && fw < 4)
00748         fw = 4;
00749     }
00750 
00751   if (! (rat_format || bank_format || hex_format || bit_format)
00752       && (print_e
00753           || print_eng || print_g
00754           || (! Vfixed_point_format && fw > Voutput_max_field_width)))
00755     {
00756       if (print_g)
00757         fmt = float_format ();
00758       else
00759         {
00760           int ex = 4;
00761           if (x_max > 100 || x_min > 100)
00762             ex++;
00763 
00764           if (print_eng)
00765             {
00766               fw = 4 + prec + ex;
00767               if (inf_or_nan && fw < 6)
00768                 fw = 6;
00769               fmt = float_format (fw, ex, prec - 1, std::ios::fixed);
00770             }
00771           else
00772             {
00773               fw = 2 + prec + ex;
00774               if (inf_or_nan && fw < 4)
00775                 fw = 4;
00776               fmt = float_format (fw, prec - 1, std::ios::scientific);
00777             }
00778         }
00779 
00780       if (print_big_e)
00781         fmt.uppercase ();
00782     }
00783   else if (! bank_format && int_or_inf_or_nan)
00784     fmt = float_format (fw, rd);
00785   else
00786     fmt = float_format (fw, rd, std::ios::fixed);
00787 
00788   curr_real_fmt = &fmt;
00789 }
00790 
00791 static void
00792 set_format (const Matrix& m, int& fw, double& scale)
00793 {
00794   curr_real_fmt = 0;
00795   curr_imag_fmt = 0;
00796 
00797   if (free_format)
00798     return;
00799 
00800   bool inf_or_nan = m.any_element_is_inf_or_nan ();
00801 
00802   bool int_or_inf_or_nan = m.all_elements_are_int_or_inf_or_nan ();
00803 
00804   Matrix m_abs = m.abs ();
00805   double max_abs = pr_max_internal (m_abs);
00806   double min_abs = pr_min_internal (m_abs);
00807 
00808   int x_max = max_abs == 0.0 ? 0 : num_digits (max_abs);
00809 
00810   int x_min = min_abs == 0.0 ? 0 : num_digits (min_abs);
00811 
00812   scale = (x_max == 0 || int_or_inf_or_nan) ? 1.0
00813     : std::pow (10.0, calc_scale_exp (x_max - 1));
00814 
00815   set_real_matrix_format (x_max, x_min, inf_or_nan, int_or_inf_or_nan, fw);
00816 }
00817 
00818 static inline void
00819 set_format (const Matrix& m)
00820 {
00821   int fw;
00822   double scale;
00823   set_format (m, fw, scale);
00824 }
00825 
00826 static void
00827 set_complex_format (int x_max, int x_min, int r_x, bool inf_or_nan,
00828                     int int_only, int& r_fw, int& i_fw)
00829 {
00830   static float_format r_fmt;
00831   static float_format i_fmt;
00832 
00833   int prec = Voutput_precision;
00834 
00835   int ld, rd;
00836 
00837   if (rat_format)
00838     {
00839       i_fw = 0;
00840       r_fw = 0;
00841       rd = 0;
00842     }
00843   else if (bank_format)
00844     {
00845       int digits = r_x;
00846       i_fw = 0;
00847       r_fw = digits <= 0 ? 4 : digits + 3;
00848       if (inf_or_nan && r_fw < 4)
00849         r_fw = 4;
00850       rd = 2;
00851     }
00852   else if (hex_format)
00853     {
00854       r_fw = 2 * sizeof (double);
00855       i_fw = 2 * sizeof (double);
00856       rd = 0;
00857     }
00858   else if (bit_format)
00859     {
00860       r_fw = 8 * sizeof (double);
00861       i_fw = 8 * sizeof (double);
00862       rd = 0;
00863     }
00864   else if (inf_or_nan || int_only)
00865     {
00866       int digits = x_max > x_min ? x_max : x_min;
00867       i_fw = digits <= 0 ? 1 : digits;
00868       r_fw = i_fw + 1;
00869       if (inf_or_nan && i_fw < 3)
00870         {
00871           i_fw = 3;
00872           r_fw = 4;
00873         }
00874       rd = r_fw;
00875     }
00876   else
00877     {
00878       int ld_max, rd_max;
00879       if (x_max > 0)
00880         {
00881           ld_max = x_max;
00882           rd_max = prec > x_max ? prec - x_max : prec;
00883           x_max++;
00884         }
00885       else
00886         {
00887           ld_max = 1;
00888           rd_max = prec > x_max ? prec - x_max : prec;
00889           x_max = -x_max + 1;
00890         }
00891 
00892       int ld_min, rd_min;
00893       if (x_min > 0)
00894         {
00895           ld_min = x_min;
00896           rd_min = prec > x_min ? prec - x_min : prec;
00897           x_min++;
00898         }
00899       else
00900         {
00901           ld_min = 1;
00902           rd_min = prec > x_min ? prec - x_min : prec;
00903           x_min = -x_min + 1;
00904         }
00905 
00906       ld = ld_max > ld_min ? ld_max : ld_min;
00907       rd = rd_max > rd_min ? rd_max : rd_min;
00908 
00909       i_fw = ld + 1 + rd;
00910       r_fw = i_fw + 1;
00911       if (inf_or_nan && i_fw < 3)
00912         {
00913           i_fw = 3;
00914           r_fw = 4;
00915         }
00916     }
00917 
00918   if (! (rat_format || bank_format || hex_format || bit_format)
00919       && (r_fw > Voutput_max_field_width || print_e || print_eng || print_g))
00920     {
00921       if (print_g)
00922         {
00923           r_fmt = float_format ();
00924           i_fmt = float_format ();
00925         }
00926       else
00927         {
00928           int ex = 4;
00929           if (x_max > 100 || x_min > 100)
00930             ex++;
00931 
00932           if (print_eng)
00933             {
00934               i_fw =  3 + prec + ex;
00935               r_fw = i_fw + 1;
00936               if (inf_or_nan && i_fw < 5)
00937                 {
00938                   i_fw = 5;
00939                   r_fw = 6;
00940                 }
00941               r_fmt = float_format (r_fw, ex, prec - 1, std::ios::fixed);
00942               i_fmt = float_format (i_fw, ex, prec - 1, std::ios::fixed);
00943             }
00944           else
00945             {
00946               i_fw = 1 + prec + ex;
00947               r_fw = i_fw + 1;
00948               if (inf_or_nan && i_fw < 3)
00949                 {
00950                   i_fw = 3;
00951                   r_fw = 4;
00952                 }
00953               r_fmt = float_format (r_fw, prec - 1, std::ios::scientific);
00954               i_fmt = float_format (i_fw, prec - 1, std::ios::scientific);
00955             }
00956         }
00957 
00958       if (print_big_e)
00959         {
00960           r_fmt.uppercase ();
00961           i_fmt.uppercase ();
00962         }
00963     }
00964   else if (! bank_format && (inf_or_nan || int_only))
00965     {
00966       r_fmt = float_format (r_fw, rd);
00967       i_fmt = float_format (i_fw, rd);
00968     }
00969   else
00970     {
00971       r_fmt = float_format (r_fw, rd, std::ios::fixed);
00972       i_fmt = float_format (i_fw, rd, std::ios::fixed);
00973     }
00974 
00975   curr_real_fmt = &r_fmt;
00976   curr_imag_fmt = &i_fmt;
00977 }
00978 
00979 static void
00980 set_format (const Complex& c, int& r_fw, int& i_fw)
00981 {
00982   curr_real_fmt = 0;
00983   curr_imag_fmt = 0;
00984 
00985   if (free_format)
00986     return;
00987 
00988   double rp = c.real ();
00989   double ip = c.imag ();
00990 
00991   bool inf_or_nan = (xisinf (c) || xisnan (c));
00992 
00993   bool int_only = (D_NINT (rp) == rp && D_NINT (ip) == ip);
00994 
00995   double r_abs = rp < 0.0 ? -rp : rp;
00996   double i_abs = ip < 0.0 ? -ip : ip;
00997 
00998   int r_x = (xisinf (rp) || xisnan (rp) || r_abs == 0.0)
00999     ? 0 : num_digits (r_abs);
01000 
01001   int i_x = (xisinf (ip) || xisnan (ip) || i_abs == 0.0)
01002     ? 0 : num_digits (i_abs);
01003 
01004   int x_max, x_min;
01005 
01006   if (r_x > i_x)
01007     {
01008       x_max = r_x;
01009       x_min = i_x;
01010     }
01011   else
01012     {
01013       x_max = i_x;
01014       x_min = r_x;
01015     }
01016 
01017   set_complex_format (x_max, x_min, r_x, inf_or_nan, int_only, r_fw, i_fw);
01018 }
01019 
01020 static inline void
01021 set_format (const Complex& c)
01022 {
01023   int r_fw, i_fw;
01024   set_format (c, r_fw, i_fw);
01025 }
01026 
01027 static void
01028 set_complex_matrix_format (int x_max, int x_min, int r_x_max,
01029                            int r_x_min, bool inf_or_nan,
01030                            int int_or_inf_or_nan, int& r_fw, int& i_fw)
01031 {
01032   static float_format r_fmt;
01033   static float_format i_fmt;
01034 
01035   int prec = Voutput_precision;
01036 
01037   int ld, rd;
01038 
01039   if (rat_format)
01040     {
01041       i_fw = 9;
01042       r_fw = 9;
01043       rd = 0;
01044     }
01045   else if (bank_format)
01046     {
01047       int digits = r_x_max > r_x_min ? r_x_max : r_x_min;
01048       i_fw = 0;
01049       r_fw = digits <= 0 ? 4 : digits + 3;
01050       if (inf_or_nan && r_fw < 4)
01051         r_fw = 4;
01052       rd = 2;
01053     }
01054   else if (hex_format)
01055     {
01056       r_fw = 2 * sizeof (double);
01057       i_fw = 2 * sizeof (double);
01058       rd = 0;
01059     }
01060   else if (bit_format)
01061     {
01062       r_fw = 8 * sizeof (double);
01063       i_fw = 8 * sizeof (double);
01064       rd = 0;
01065     }
01066   else if (Vfixed_point_format && ! print_g)
01067     {
01068       rd = prec;
01069       i_fw = rd + 1;
01070       r_fw = i_fw + 1;
01071       if (inf_or_nan && i_fw < 3)
01072         {
01073           i_fw = 3;
01074           r_fw = 4;
01075         }
01076     }
01077   else if (int_or_inf_or_nan)
01078     {
01079       int digits = x_max > x_min ? x_max : x_min;
01080       i_fw = digits <= 0 ? 1 : digits;
01081       r_fw = i_fw + 1;
01082       if (inf_or_nan && i_fw < 3)
01083         {
01084           i_fw = 3;
01085           r_fw = 4;
01086         }
01087       rd = r_fw;
01088     }
01089   else
01090     {
01091       int ld_max, rd_max;
01092       if (x_max > 0)
01093         {
01094           ld_max = x_max;
01095           rd_max = prec > x_max ? prec - x_max : prec;
01096           x_max++;
01097         }
01098       else
01099         {
01100           ld_max = 1;
01101           rd_max = prec > x_max ? prec - x_max : prec;
01102           x_max = -x_max + 1;
01103         }
01104 
01105       int ld_min, rd_min;
01106       if (x_min > 0)
01107         {
01108           ld_min = x_min;
01109           rd_min = prec > x_min ? prec - x_min : prec;
01110           x_min++;
01111         }
01112       else
01113         {
01114           ld_min = 1;
01115           rd_min = prec > x_min ? prec - x_min : prec;
01116           x_min = -x_min + 1;
01117         }
01118 
01119       ld = ld_max > ld_min ? ld_max : ld_min;
01120       rd = rd_max > rd_min ? rd_max : rd_min;
01121 
01122       i_fw = ld + 1 + rd;
01123       r_fw = i_fw + 1;
01124       if (inf_or_nan && i_fw < 3)
01125         {
01126           i_fw = 3;
01127           r_fw = 4;
01128         }
01129     }
01130 
01131   if (! (rat_format || bank_format || hex_format || bit_format)
01132       && (print_e
01133           || print_eng || print_g
01134           || (! Vfixed_point_format && r_fw > Voutput_max_field_width)))
01135     {
01136       if (print_g)
01137         {
01138           r_fmt = float_format ();
01139           i_fmt = float_format ();
01140         }
01141       else
01142         {
01143           int ex = 4;
01144           if (x_max > 100 || x_min > 100)
01145             ex++;
01146 
01147           if (print_eng)
01148             {
01149               i_fw = 3 + prec + ex;
01150               r_fw = i_fw + 1;
01151               if (inf_or_nan && i_fw < 5)
01152                 {
01153                   i_fw = 5;
01154                   r_fw = 6;
01155                 }
01156               r_fmt = float_format (r_fw, ex, prec - 1, std::ios::fixed);
01157               i_fmt = float_format (i_fw, ex, prec - 1, std::ios::fixed);
01158             }
01159           else
01160             {
01161               i_fw = 1 + prec + ex;
01162               r_fw = i_fw + 1;
01163               if (inf_or_nan && i_fw < 3)
01164                 {
01165                   i_fw = 3;
01166                   r_fw = 4;
01167                 }
01168               r_fmt = float_format (r_fw, prec - 1, std::ios::scientific);
01169               i_fmt = float_format (i_fw, prec - 1, std::ios::scientific);
01170             }
01171         }
01172 
01173       if (print_big_e)
01174         {
01175           r_fmt.uppercase ();
01176           i_fmt.uppercase ();
01177         }
01178     }
01179   else if (! bank_format && int_or_inf_or_nan)
01180     {
01181       r_fmt = float_format (r_fw, rd);
01182       i_fmt = float_format (i_fw, rd);
01183     }
01184   else
01185     {
01186       r_fmt = float_format (r_fw, rd, std::ios::fixed);
01187       i_fmt = float_format (i_fw, rd, std::ios::fixed);
01188     }
01189 
01190   curr_real_fmt = &r_fmt;
01191   curr_imag_fmt = &i_fmt;
01192 }
01193 
01194 static void
01195 set_format (const ComplexMatrix& cm, int& r_fw, int& i_fw, double& scale)
01196 {
01197   curr_real_fmt = 0;
01198   curr_imag_fmt = 0;
01199 
01200   if (free_format)
01201     return;
01202 
01203   Matrix rp = real (cm);
01204   Matrix ip = imag (cm);
01205 
01206   bool inf_or_nan = cm.any_element_is_inf_or_nan ();
01207 
01208   bool int_or_inf_or_nan = (rp.all_elements_are_int_or_inf_or_nan ()
01209                             && ip.all_elements_are_int_or_inf_or_nan ());
01210 
01211   Matrix r_m_abs = rp.abs ();
01212   double r_max_abs = pr_max_internal (r_m_abs);
01213   double r_min_abs = pr_min_internal (r_m_abs);
01214 
01215   Matrix i_m_abs = ip.abs ();
01216   double i_max_abs = pr_max_internal (i_m_abs);
01217   double i_min_abs = pr_min_internal (i_m_abs);
01218 
01219   int r_x_max = r_max_abs == 0.0 ? 0 : num_digits (r_max_abs);
01220 
01221   int r_x_min = r_min_abs == 0.0 ? 0 : num_digits (r_min_abs);
01222 
01223   int i_x_max = i_max_abs == 0.0 ? 0 : num_digits (i_max_abs);
01224 
01225   int i_x_min = i_min_abs == 0.0 ? 0 : num_digits (i_min_abs);
01226 
01227   int x_max = r_x_max > i_x_max ? r_x_max : i_x_max;
01228   int x_min = r_x_min > i_x_min ? r_x_min : i_x_min;
01229 
01230   scale = (x_max == 0 || int_or_inf_or_nan) ? 1.0
01231     : std::pow (10.0, calc_scale_exp (x_max - 1));
01232 
01233   set_complex_matrix_format (x_max, x_min, r_x_max, r_x_min, inf_or_nan,
01234                              int_or_inf_or_nan, r_fw, i_fw);
01235 }
01236 
01237 static inline void
01238 set_format (const ComplexMatrix& cm)
01239 {
01240   int r_fw, i_fw;
01241   double scale;
01242   set_format (cm, r_fw, i_fw, scale);
01243 }
01244 
01245 static void
01246 set_range_format (int x_max, int x_min, int all_ints, int& fw)
01247 {
01248   static float_format fmt;
01249 
01250   int prec = Voutput_precision;
01251 
01252   int ld, rd;
01253 
01254   if (rat_format)
01255     {
01256       fw = 9;
01257       rd = 0;
01258     }
01259   else if (bank_format)
01260     {
01261       int digits = x_max > x_min ? x_max : x_min;
01262       fw = digits < 0 ? 5 : digits + 4;
01263       rd = 2;
01264     }
01265   else if (hex_format)
01266     {
01267       fw = 2 * sizeof (double);
01268       rd = 0;
01269     }
01270   else if (bit_format)
01271     {
01272       fw = 8 * sizeof (double);
01273       rd = 0;
01274     }
01275   else if (all_ints)
01276     {
01277       int digits = x_max > x_min ? x_max : x_min;
01278       fw = digits + 1;
01279       rd = fw;
01280     }
01281   else if (Vfixed_point_format && ! print_g)
01282     {
01283       rd = prec;
01284       fw = rd + 3;
01285     }
01286   else
01287     {
01288       int ld_max, rd_max;
01289       if (x_max > 0)
01290         {
01291           ld_max = x_max;
01292           rd_max = prec > x_max ? prec - x_max : prec;
01293           x_max++;
01294         }
01295       else
01296         {
01297           ld_max = 1;
01298           rd_max = prec > x_max ? prec - x_max : prec;
01299           x_max = -x_max + 1;
01300         }
01301 
01302       int ld_min, rd_min;
01303       if (x_min > 0)
01304         {
01305           ld_min = x_min;
01306           rd_min = prec > x_min ? prec - x_min : prec;
01307           x_min++;
01308         }
01309       else
01310         {
01311           ld_min = 1;
01312           rd_min = prec > x_min ? prec - x_min : prec;
01313           x_min = -x_min + 1;
01314         }
01315 
01316       ld = ld_max > ld_min ? ld_max : ld_min;
01317       rd = rd_max > rd_min ? rd_max : rd_min;
01318 
01319       fw = ld + rd + 3;
01320     }
01321 
01322   if (! (rat_format || bank_format || hex_format || bit_format)
01323       && (print_e
01324           || print_eng || print_g
01325           || (! Vfixed_point_format && fw > Voutput_max_field_width)))
01326     {
01327       if (print_g)
01328         fmt = float_format ();
01329       else
01330         {
01331           int ex = 4;
01332           if (x_max > 100 || x_min > 100)
01333             ex++;
01334 
01335           if (print_eng)
01336             {
01337               fw = 5 + prec + ex;
01338               fmt = float_format (fw, ex, prec - 1, std::ios::fixed);
01339             }
01340           else
01341             {
01342               fw = 3 + prec + ex;
01343               fmt = float_format (fw, prec - 1, std::ios::scientific);
01344             }
01345         }
01346 
01347       if (print_big_e)
01348         fmt.uppercase ();
01349     }
01350   else if (! bank_format && all_ints)
01351     fmt = float_format (fw, rd);
01352   else
01353     fmt = float_format (fw, rd, std::ios::fixed);
01354 
01355   curr_real_fmt = &fmt;
01356 }
01357 
01358 static void
01359 set_format (const Range& r, int& fw, double& scale)
01360 {
01361   curr_real_fmt = 0;
01362   curr_imag_fmt = 0;
01363 
01364   if (free_format)
01365     return;
01366 
01367   double r_min = r.base ();
01368   double r_max = r.limit ();
01369 
01370   if (r_max < r_min)
01371     {
01372       double tmp = r_max;
01373       r_max = r_min;
01374       r_min = tmp;
01375     }
01376 
01377   bool all_ints = r.all_elements_are_ints ();
01378 
01379   double max_abs = r_max < 0.0 ? -r_max : r_max;
01380   double min_abs = r_min < 0.0 ? -r_min : r_min;
01381 
01382   int x_max = max_abs == 0.0 ? 0 : num_digits (max_abs);
01383 
01384   int x_min = min_abs == 0.0 ? 0 : num_digits (min_abs);
01385 
01386   scale = (x_max == 0 || all_ints) ? 1.0
01387     : std::pow (10.0, calc_scale_exp (x_max - 1));
01388 
01389   set_range_format (x_max, x_min, all_ints, fw);
01390 }
01391 
01392 static inline void
01393 set_format (const Range& r)
01394 {
01395   int fw;
01396   double scale;
01397   set_format (r, fw, scale);
01398 }
01399 
01400 union equiv
01401 {
01402   double d;
01403   unsigned char i[sizeof (double)];
01404 };
01405 
01406 #define PRINT_CHAR_BITS(os, c) \
01407   do \
01408     { \
01409       unsigned char ctmp = c; \
01410       char stmp[9]; \
01411       stmp[0] = (ctmp & 0x80) ? '1' : '0'; \
01412       stmp[1] = (ctmp & 0x40) ? '1' : '0'; \
01413       stmp[2] = (ctmp & 0x20) ? '1' : '0'; \
01414       stmp[3] = (ctmp & 0x10) ? '1' : '0'; \
01415       stmp[4] = (ctmp & 0x08) ? '1' : '0'; \
01416       stmp[5] = (ctmp & 0x04) ? '1' : '0'; \
01417       stmp[6] = (ctmp & 0x02) ? '1' : '0'; \
01418       stmp[7] = (ctmp & 0x01) ? '1' : '0'; \
01419       stmp[8] = '\0'; \
01420       os << stmp; \
01421     } \
01422   while (0)
01423 
01424 #define PRINT_CHAR_BITS_SWAPPED(os, c) \
01425   do \
01426     { \
01427       unsigned char ctmp = c; \
01428       char stmp[9]; \
01429       stmp[0] = (ctmp & 0x01) ? '1' : '0'; \
01430       stmp[1] = (ctmp & 0x02) ? '1' : '0'; \
01431       stmp[2] = (ctmp & 0x04) ? '1' : '0'; \
01432       stmp[3] = (ctmp & 0x08) ? '1' : '0'; \
01433       stmp[4] = (ctmp & 0x10) ? '1' : '0'; \
01434       stmp[5] = (ctmp & 0x20) ? '1' : '0'; \
01435       stmp[6] = (ctmp & 0x40) ? '1' : '0'; \
01436       stmp[7] = (ctmp & 0x80) ? '1' : '0'; \
01437       stmp[8] = '\0'; \
01438       os << stmp; \
01439     } \
01440   while (0)
01441 
01442 static void
01443 pr_any_float (const float_format *fmt, std::ostream& os, double d, int fw = 0)
01444 {
01445   if (fmt)
01446     {
01447       // Unless explicitly asked for, always print in big-endian
01448       // format for hex and bit formats.
01449       //
01450       //   {bit,hex}_format == 1: print big-endian
01451       //   {bit,hex}_format == 2: print native
01452 
01453       if (hex_format)
01454         {
01455           equiv tmp;
01456           tmp.d = d;
01457 
01458           // Unless explicitly asked for, always print in big-endian
01459           // format.
01460 
01461           // FIXME -- is it correct to swap bytes for VAX
01462           // formats and not for Cray?
01463 
01464           // FIXME -- will bad things happen if we are
01465           // interrupted before resetting the format flags and fill
01466           // character?
01467 
01468           oct_mach_info::float_format flt_fmt =
01469             oct_mach_info::native_float_format ();
01470 
01471           char ofill = os.fill ('0');
01472 
01473           std::ios::fmtflags oflags
01474             = os.flags (std::ios::right | std::ios::hex);
01475 
01476           if (hex_format > 1
01477               || flt_fmt == oct_mach_info::flt_fmt_ieee_big_endian
01478               || flt_fmt == oct_mach_info::flt_fmt_cray
01479               || flt_fmt == oct_mach_info::flt_fmt_unknown)
01480             {
01481               for (size_t i = 0; i < sizeof (double); i++)
01482                 os << std::setw (2) << static_cast<int> (tmp.i[i]);
01483             }
01484           else
01485             {
01486               for (int i = sizeof (double) - 1; i >= 0; i--)
01487                 os << std::setw (2) << static_cast<int> (tmp.i[i]);
01488             }
01489 
01490           os.fill (ofill);
01491           os.setf (oflags);
01492         }
01493       else if (bit_format)
01494         {
01495           equiv tmp;
01496           tmp.d = d;
01497 
01498           // FIXME -- is it correct to swap bytes for VAX
01499           // formats and not for Cray?
01500 
01501           oct_mach_info::float_format flt_fmt =
01502             oct_mach_info::native_float_format ();
01503 
01504           if (flt_fmt == oct_mach_info::flt_fmt_ieee_big_endian
01505               || flt_fmt == oct_mach_info::flt_fmt_cray
01506               || flt_fmt == oct_mach_info::flt_fmt_unknown)
01507             {
01508               for (size_t i = 0; i < sizeof (double); i++)
01509                 PRINT_CHAR_BITS (os, tmp.i[i]);
01510             }
01511           else
01512             {
01513               if (bit_format > 1)
01514                 {
01515                   for (size_t i = 0; i < sizeof (double); i++)
01516                     PRINT_CHAR_BITS_SWAPPED (os, tmp.i[i]);
01517                 }
01518               else
01519                 {
01520                   for (int i = sizeof (double) - 1; i >= 0; i--)
01521                     PRINT_CHAR_BITS (os, tmp.i[i]);
01522                 }
01523             }
01524         }
01525       else if (octave_is_NA (d))
01526         {
01527           if (fw > 0)
01528             os << std::setw (fw) << "NA";
01529           else
01530             os << "NA";
01531         }
01532       else if (rat_format)
01533         os << pr_rational_float (*fmt, d);
01534       else if (xisinf (d))
01535         {
01536           const char *s;
01537           if (d < 0.0)
01538             s = "-Inf";
01539           else
01540             s = "Inf";
01541 
01542           if (fw > 0)
01543             os << std::setw (fw) << s;
01544           else
01545             os << s;
01546         }
01547       else if (xisnan (d))
01548         {
01549           if (fw > 0)
01550             os << std::setw (fw) << "NaN";
01551           else
01552             os << "NaN";
01553         }
01554       else if (print_eng)
01555         os << pr_engineering_float (*fmt, d);
01556       else
01557         os << pr_formatted_float (*fmt, d);
01558     }
01559   else
01560     os << d;
01561 }
01562 
01563 static inline void
01564 pr_float (std::ostream& os, double d, int fw = 0, double scale = 1.0)
01565 {
01566   if (Vfixed_point_format && ! print_g && scale != 1.0)
01567     d /= scale;
01568 
01569   pr_any_float (curr_real_fmt, os, d, fw);
01570 }
01571 
01572 static inline void
01573 pr_imag_float (std::ostream& os, double d, int fw = 0)
01574 {
01575   pr_any_float (curr_imag_fmt, os, d, fw);
01576 }
01577 
01578 static void
01579 pr_complex (std::ostream& os, const Complex& c, int r_fw = 0,
01580             int i_fw = 0, double scale = 1.0)
01581 {
01582   Complex tmp
01583     = (Vfixed_point_format && ! print_g && scale != 1.0) ? c / scale : c;
01584 
01585   double r = tmp.real ();
01586 
01587   pr_float (os, r, r_fw);
01588 
01589   if (! bank_format)
01590     {
01591       double i = tmp.imag ();
01592       if (! (hex_format || bit_format) && lo_ieee_signbit (i))
01593         {
01594           os << " - ";
01595           i = -i;
01596           pr_imag_float (os, i, i_fw);
01597         }
01598       else
01599         {
01600           if (hex_format || bit_format)
01601             os << "  ";
01602           else
01603             os << " + ";
01604 
01605           pr_imag_float (os, i, i_fw);
01606         }
01607       os << "i";
01608     }
01609 }
01610 
01611 static void
01612 print_empty_matrix (std::ostream& os, octave_idx_type nr, octave_idx_type nc, bool pr_as_read_syntax)
01613 {
01614   assert (nr == 0 || nc == 0);
01615 
01616   if (pr_as_read_syntax)
01617     {
01618       if (nr == 0 && nc == 0)
01619         os << "[]";
01620       else
01621         os << "zeros (" << nr << ", " << nc << ")";
01622     }
01623   else
01624     {
01625       os << "[]";
01626 
01627       if (Vprint_empty_dimensions)
01628         os << "(" << nr << "x" << nc << ")";
01629     }
01630 }
01631 
01632 static void
01633 print_empty_nd_array (std::ostream& os, const dim_vector& dims,
01634                       bool pr_as_read_syntax)
01635 {
01636   assert (dims.any_zero ());
01637 
01638   if (pr_as_read_syntax)
01639     os << "zeros (" << dims.str (',') << ")";
01640   else
01641     {
01642       os << "[]";
01643 
01644       if (Vprint_empty_dimensions)
01645         os << "(" << dims.str () << ")";
01646     }
01647 }
01648 
01649 static void
01650 pr_scale_header (std::ostream& os, double scale)
01651 {
01652   if (Vfixed_point_format && ! print_g && scale != 1.0)
01653     {
01654       os << "  "
01655          << std::setw (8) << std::setprecision (1)
01656          << std::setiosflags (std::ios::scientific|std::ios::left)
01657          << scale
01658          << std::resetiosflags (std::ios::scientific|std::ios::left)
01659          << " *\n";
01660 
01661       if (! Vcompact_format)
01662         os << "\n";
01663     }
01664 }
01665 
01666 static void
01667 pr_col_num_header (std::ostream& os, octave_idx_type total_width, int max_width,
01668                    octave_idx_type lim, octave_idx_type col, int extra_indent)
01669 {
01670   if (total_width > max_width && Vsplit_long_rows)
01671     {
01672       if (col != 0)
01673         {
01674           if (Vcompact_format)
01675             os << "\n";
01676           else
01677             os << "\n\n";
01678         }
01679 
01680       octave_idx_type num_cols = lim - col;
01681 
01682       os << std::setw (extra_indent) << "";
01683 
01684       if (num_cols == 1)
01685         os << " Column " << col + 1 << ":\n";
01686       else if (num_cols == 2)
01687         os << " Columns " << col + 1 << " and " << lim << ":\n";
01688       else
01689         os << " Columns " << col + 1 << " through " << lim << ":\n";
01690 
01691       if (! Vcompact_format)
01692         os << "\n";
01693     }
01694 }
01695 
01696 template <class T>
01697 /* static */ inline void
01698 pr_plus_format (std::ostream& os, const T& val)
01699 {
01700   if (val > T (0))
01701     os << plus_format_chars[0];
01702   else if (val < T (0))
01703     os << plus_format_chars[1];
01704   else
01705     os << plus_format_chars[2];
01706 }
01707 
01708 void
01709 octave_print_internal (std::ostream& os, double d,
01710                        bool /* pr_as_read_syntax */)
01711 {
01712   if (plus_format)
01713     {
01714       pr_plus_format (os, d);
01715     }
01716   else
01717     {
01718       set_format (d);
01719       if (free_format)
01720         os << d;
01721       else
01722         pr_float (os, d);
01723     }
01724 }
01725 
01726 void
01727 octave_print_internal (std::ostream& os, const Matrix& m,
01728                        bool pr_as_read_syntax, int extra_indent)
01729 {
01730   octave_idx_type nr = m.rows ();
01731   octave_idx_type nc = m.columns ();
01732 
01733   if (nr == 0 || nc == 0)
01734     print_empty_matrix (os, nr, nc, pr_as_read_syntax);
01735   else if (plus_format && ! pr_as_read_syntax)
01736     {
01737       for (octave_idx_type i = 0; i < nr; i++)
01738         {
01739           for (octave_idx_type j = 0; j < nc; j++)
01740             {
01741               octave_quit ();
01742 
01743               pr_plus_format (os, m(i,j));
01744             }
01745 
01746           if (i < nr - 1)
01747             os << "\n";
01748         }
01749     }
01750   else
01751     {
01752       int fw;
01753       double scale = 1.0;
01754       set_format (m, fw, scale);
01755       int column_width = fw + 2;
01756       octave_idx_type total_width = nc * column_width;
01757       octave_idx_type max_width = command_editor::terminal_cols ();
01758 
01759       if (pr_as_read_syntax)
01760         max_width -= 4;
01761       else
01762         max_width -= extra_indent;
01763 
01764       if (max_width < 0)
01765         max_width = 0;
01766 
01767       if (free_format)
01768         {
01769           if (pr_as_read_syntax)
01770             os << "[\n";
01771 
01772           os << m;
01773 
01774           if (pr_as_read_syntax)
01775             os << "]";
01776 
01777           return;
01778         }
01779 
01780       octave_idx_type inc = nc;
01781       if (total_width > max_width && Vsplit_long_rows)
01782         {
01783           inc = max_width / column_width;
01784           if (inc == 0)
01785             inc++;
01786         }
01787 
01788       if (pr_as_read_syntax)
01789         {
01790           for (octave_idx_type i = 0; i < nr; i++)
01791             {
01792               octave_idx_type col = 0;
01793               while (col < nc)
01794                 {
01795                   octave_idx_type lim = col + inc < nc ? col + inc : nc;
01796 
01797                   for (octave_idx_type j = col; j < lim; j++)
01798                     {
01799                       octave_quit ();
01800 
01801                       if (i == 0 && j == 0)
01802                         os << "[ ";
01803                       else
01804                         {
01805                           if (j > col && j < lim)
01806                             os << ", ";
01807                           else
01808                             os << "  ";
01809                         }
01810 
01811                       pr_float (os, m(i,j));
01812                     }
01813 
01814                   col += inc;
01815 
01816                   if (col >= nc)
01817                     {
01818                       if (i == nr - 1)
01819                         os << " ]";
01820                       else
01821                         os << ";\n";
01822                     }
01823                   else
01824                     os << " ...\n";
01825                 }
01826             }
01827         }
01828       else
01829         {
01830           pr_scale_header (os, scale);
01831 
01832           for (octave_idx_type col = 0; col < nc; col += inc)
01833             {
01834               octave_idx_type lim = col + inc < nc ? col + inc : nc;
01835 
01836               pr_col_num_header (os, total_width, max_width, lim, col,
01837                                  extra_indent);
01838 
01839               for (octave_idx_type i = 0; i < nr; i++)
01840                 {
01841                   os << std::setw (extra_indent) << "";
01842 
01843                   for (octave_idx_type j = col; j < lim; j++)
01844                     {
01845                       octave_quit ();
01846 
01847                       os << "  ";
01848 
01849                       pr_float (os, m(i,j), fw, scale);
01850                     }
01851 
01852                   if (i < nr - 1)
01853                     os << "\n";
01854                 }
01855             }
01856         }
01857     }
01858 }
01859 
01860 void
01861 octave_print_internal (std::ostream& os, const DiagMatrix& m,
01862                        bool pr_as_read_syntax, int extra_indent)
01863 {
01864   octave_idx_type nr = m.rows ();
01865   octave_idx_type nc = m.columns ();
01866 
01867   if (nr == 0 || nc == 0)
01868     print_empty_matrix (os, nr, nc, pr_as_read_syntax);
01869   else if (plus_format && ! pr_as_read_syntax)
01870     {
01871       for (octave_idx_type i = 0; i < nr; i++)
01872         {
01873           for (octave_idx_type j = 0; j < nc; j++)
01874             {
01875               octave_quit ();
01876 
01877               pr_plus_format (os, m(i,j));
01878             }
01879 
01880           if (i < nr - 1)
01881             os << "\n";
01882         }
01883     }
01884   else
01885     {
01886       int fw;
01887       double scale = 1.0;
01888       set_format (Matrix (m.diag ()), fw, scale);
01889       int column_width = fw + 2;
01890       octave_idx_type total_width = nc * column_width;
01891       octave_idx_type max_width = command_editor::terminal_cols ();
01892 
01893       if (pr_as_read_syntax)
01894         max_width -= 4;
01895       else
01896         max_width -= extra_indent;
01897 
01898       if (max_width < 0)
01899         max_width = 0;
01900 
01901       if (free_format)
01902         {
01903           if (pr_as_read_syntax)
01904             os << "[\n";
01905 
01906           os << Matrix (m);
01907 
01908           if (pr_as_read_syntax)
01909             os << "]";
01910 
01911           return;
01912         }
01913 
01914       octave_idx_type inc = nc;
01915       if (total_width > max_width && Vsplit_long_rows)
01916         {
01917           inc = max_width / column_width;
01918           if (inc == 0)
01919             inc++;
01920         }
01921 
01922       if (pr_as_read_syntax)
01923         {
01924           os << "diag (";
01925 
01926           octave_idx_type col = 0;
01927           while (col < nc)
01928             {
01929               octave_idx_type lim = col + inc < nc ? col + inc : nc;
01930 
01931               for (octave_idx_type j = col; j < lim; j++)
01932                 {
01933                   octave_quit ();
01934 
01935                   if (j == 0)
01936                     os << "[ ";
01937                   else
01938                     {
01939                       if (j > col && j < lim)
01940                         os << ", ";
01941                       else
01942                         os << "  ";
01943                     }
01944 
01945                   pr_float (os, m(j,j));
01946                 }
01947 
01948               col += inc;
01949 
01950               if (col >= nc)
01951                   os << " ]";
01952               else
01953                 os << " ...\n";
01954             }
01955           os << ")";
01956         }
01957       else
01958         {
01959           os << "Diagonal Matrix\n";
01960           if (! Vcompact_format)
01961             os << "\n";
01962 
01963           pr_scale_header (os, scale);
01964 
01965           // kluge. Get the true width of a number.
01966           int zero_fw;
01967 
01968             {
01969               std::ostringstream tmp_oss;
01970               pr_float (tmp_oss, 0.0, fw, scale);
01971               zero_fw = tmp_oss.str ().length ();
01972             }
01973 
01974           for (octave_idx_type col = 0; col < nc; col += inc)
01975             {
01976               octave_idx_type lim = col + inc < nc ? col + inc : nc;
01977 
01978               pr_col_num_header (os, total_width, max_width, lim, col,
01979                                  extra_indent);
01980 
01981               for (octave_idx_type i = 0; i < nr; i++)
01982                 {
01983                   os << std::setw (extra_indent) << "";
01984 
01985                   for (octave_idx_type j = col; j < lim; j++)
01986                     {
01987                       octave_quit ();
01988 
01989                       os << "  ";
01990 
01991                       if (i == j)
01992                         pr_float (os, m(i,j), fw, scale);
01993                       else
01994                         os << std::setw (zero_fw) << '0';
01995 
01996                     }
01997 
01998                   if (i < nr - 1)
01999                     os << "\n";
02000                 }
02001             }
02002         }
02003     }
02004 }
02005 
02006 template <typename NDA_T, typename ELT_T, typename MAT_T>
02007 void print_nd_array(std::ostream& os, const NDA_T& nda,
02008                     bool pr_as_read_syntax)
02009 {
02010 
02011   if (nda.is_empty ())
02012     print_empty_nd_array (os, nda.dims (), pr_as_read_syntax);
02013   else
02014     {
02015 
02016       int ndims = nda.ndims ();
02017 
02018       dim_vector dims = nda.dims ();
02019 
02020       Array<octave_idx_type> ra_idx (dim_vector (ndims, 1), 0);
02021 
02022       octave_idx_type m = 1;
02023 
02024       for (int i = 2; i < ndims; i++)
02025         m *= dims(i);
02026 
02027       octave_idx_type nr = dims(0);
02028       octave_idx_type nc = dims(1);
02029 
02030       for (octave_idx_type i = 0; i < m; i++)
02031         {
02032           octave_quit ();
02033 
02034           std::string nm = "ans";
02035 
02036           if (m > 1)
02037             {
02038               nm += "(:,:,";
02039 
02040               std::ostringstream buf;
02041 
02042               for (int k = 2; k < ndims; k++)
02043                 {
02044                   buf << ra_idx(k) + 1;
02045 
02046                   if (k < ndims - 1)
02047                     buf << ",";
02048                   else
02049                     buf << ")";
02050                 }
02051 
02052               nm += buf.str ();
02053             }
02054 
02055           Array<idx_vector> idx (dim_vector (ndims, 1));
02056 
02057           idx(0) = idx_vector (':');
02058           idx(1) = idx_vector (':');
02059 
02060           for (int k = 2; k < ndims; k++)
02061             idx(k) = idx_vector (ra_idx(k));
02062 
02063           octave_value page
02064             = MAT_T (Array<ELT_T> (nda.index (idx), dim_vector (nr, nc)));
02065 
02066           if (i != m - 1)
02067             {
02068               page.print_with_name (os, nm);
02069             }
02070           else
02071             {
02072               page.print_name_tag (os, nm);
02073               page.print_raw (os);
02074             }
02075 
02076           if (i < m)
02077             NDA_T::increment_index (ra_idx, dims, 2);
02078         }
02079     }
02080 }
02081 
02082 void
02083 octave_print_internal (std::ostream& os, const NDArray& nda,
02084                        bool pr_as_read_syntax, int extra_indent)
02085 {
02086   switch (nda.ndims ())
02087     {
02088     case 1:
02089     case 2:
02090       octave_print_internal (os, nda.matrix_value (),
02091                              pr_as_read_syntax, extra_indent);
02092       break;
02093 
02094     default:
02095       print_nd_array <NDArray, double, Matrix> (os, nda, pr_as_read_syntax);
02096       break;
02097     }
02098 }
02099 
02100 template <>
02101 /* static */ inline void
02102 pr_plus_format<> (std::ostream& os, const Complex& c)
02103 {
02104   double rp = c.real ();
02105   double ip = c.imag ();
02106 
02107   if (rp == 0.0)
02108     {
02109       if (ip == 0.0)
02110         os << " ";
02111       else
02112         os << "i";
02113     }
02114   else if (ip == 0.0)
02115     pr_plus_format (os, rp);
02116   else
02117     os << "c";
02118 }
02119 
02120 void
02121 octave_print_internal (std::ostream& os, const Complex& c,
02122                        bool /* pr_as_read_syntax */)
02123 {
02124   if (plus_format)
02125     {
02126       pr_plus_format (os, c);
02127     }
02128   else
02129     {
02130       set_format (c);
02131       if (free_format)
02132         os << c;
02133       else
02134         pr_complex (os, c);
02135     }
02136 }
02137 
02138 void
02139 octave_print_internal (std::ostream& os, const ComplexMatrix& cm,
02140                        bool pr_as_read_syntax, int extra_indent)
02141 {
02142   octave_idx_type nr = cm.rows ();
02143   octave_idx_type nc = cm.columns ();
02144 
02145  if (nr == 0 || nc == 0)
02146     print_empty_matrix (os, nr, nc, pr_as_read_syntax);
02147   else if (plus_format && ! pr_as_read_syntax)
02148     {
02149       for (octave_idx_type i = 0; i < nr; i++)
02150         {
02151           for (octave_idx_type j = 0; j < nc; j++)
02152             {
02153               octave_quit ();
02154 
02155               pr_plus_format (os, cm(i,j));
02156             }
02157 
02158           if (i < nr - 1)
02159             os << "\n";
02160         }
02161     }
02162   else
02163     {
02164       int r_fw, i_fw;
02165       double scale = 1.0;
02166       set_format (cm, r_fw, i_fw, scale);
02167       int column_width = i_fw + r_fw;
02168       column_width += (rat_format || bank_format || hex_format
02169                        || bit_format) ? 2 : 7;
02170       octave_idx_type total_width = nc * column_width;
02171       octave_idx_type max_width = command_editor::terminal_cols ();
02172 
02173       if (pr_as_read_syntax)
02174         max_width -= 4;
02175       else
02176         max_width -= extra_indent;
02177 
02178       if (max_width < 0)
02179         max_width = 0;
02180 
02181       if (free_format)
02182         {
02183           if (pr_as_read_syntax)
02184             os << "[\n";
02185 
02186           os << cm;
02187 
02188           if (pr_as_read_syntax)
02189             os << "]";
02190 
02191           return;
02192         }
02193 
02194       octave_idx_type inc = nc;
02195       if (total_width > max_width && Vsplit_long_rows)
02196         {
02197           inc = max_width / column_width;
02198           if (inc == 0)
02199             inc++;
02200         }
02201 
02202       if (pr_as_read_syntax)
02203         {
02204           for (octave_idx_type i = 0; i < nr; i++)
02205             {
02206               octave_idx_type col = 0;
02207               while (col < nc)
02208                 {
02209                   octave_idx_type lim = col + inc < nc ? col + inc : nc;
02210 
02211                   for (octave_idx_type j = col; j < lim; j++)
02212                     {
02213                       octave_quit ();
02214 
02215                       if (i == 0 && j == 0)
02216                         os << "[ ";
02217                       else
02218                         {
02219                           if (j > col && j < lim)
02220                             os << ", ";
02221                           else
02222                             os << "  ";
02223                         }
02224 
02225                       pr_complex (os, cm(i,j));
02226                     }
02227 
02228                   col += inc;
02229 
02230                   if (col >= nc)
02231                     {
02232                       if (i == nr - 1)
02233                         os << " ]";
02234                       else
02235                         os << ";\n";
02236                     }
02237                   else
02238                     os << " ...\n";
02239                 }
02240             }
02241         }
02242       else
02243         {
02244           pr_scale_header (os, scale);
02245 
02246           for (octave_idx_type col = 0; col < nc; col += inc)
02247             {
02248               octave_idx_type lim = col + inc < nc ? col + inc : nc;
02249 
02250               pr_col_num_header (os, total_width, max_width, lim, col,
02251                                  extra_indent);
02252 
02253               for (octave_idx_type i = 0; i < nr; i++)
02254                 {
02255                   os << std::setw (extra_indent) << "";
02256 
02257                   for (octave_idx_type j = col; j < lim; j++)
02258                     {
02259                       octave_quit ();
02260 
02261                       os << "  ";
02262 
02263                       pr_complex (os, cm(i,j), r_fw, i_fw, scale);
02264                     }
02265 
02266                   if (i < nr - 1)
02267                     os << "\n";
02268                 }
02269             }
02270         }
02271     }
02272 }
02273 
02274 void
02275 octave_print_internal (std::ostream& os, const ComplexDiagMatrix& cm,
02276                        bool pr_as_read_syntax, int extra_indent)
02277 {
02278   octave_idx_type nr = cm.rows ();
02279   octave_idx_type nc = cm.columns ();
02280 
02281  if (nr == 0 || nc == 0)
02282     print_empty_matrix (os, nr, nc, pr_as_read_syntax);
02283   else if (plus_format && ! pr_as_read_syntax)
02284     {
02285       for (octave_idx_type i = 0; i < nr; i++)
02286         {
02287           for (octave_idx_type j = 0; j < nc; j++)
02288             {
02289               octave_quit ();
02290 
02291               pr_plus_format (os, cm(i,j));
02292             }
02293 
02294           if (i < nr - 1)
02295             os << "\n";
02296         }
02297     }
02298   else
02299     {
02300       int r_fw, i_fw;
02301       double scale = 1.0;
02302       set_format (ComplexMatrix (cm.diag ()), r_fw, i_fw, scale);
02303       int column_width = i_fw + r_fw;
02304       column_width += (rat_format || bank_format || hex_format
02305                        || bit_format) ? 2 : 7;
02306       octave_idx_type total_width = nc * column_width;
02307       octave_idx_type max_width = command_editor::terminal_cols ();
02308 
02309       if (pr_as_read_syntax)
02310         max_width -= 4;
02311       else
02312         max_width -= extra_indent;
02313 
02314       if (max_width < 0)
02315         max_width = 0;
02316 
02317       if (free_format)
02318         {
02319           if (pr_as_read_syntax)
02320             os << "[\n";
02321 
02322           os << ComplexMatrix (cm);
02323 
02324           if (pr_as_read_syntax)
02325             os << "]";
02326 
02327           return;
02328         }
02329 
02330       octave_idx_type inc = nc;
02331       if (total_width > max_width && Vsplit_long_rows)
02332         {
02333           inc = max_width / column_width;
02334           if (inc == 0)
02335             inc++;
02336         }
02337 
02338       if (pr_as_read_syntax)
02339         {
02340           os << "diag (";
02341 
02342           octave_idx_type col = 0;
02343           while (col < nc)
02344             {
02345               octave_idx_type lim = col + inc < nc ? col + inc : nc;
02346 
02347               for (octave_idx_type j = col; j < lim; j++)
02348                 {
02349                   octave_quit ();
02350 
02351                   if (j == 0)
02352                     os << "[ ";
02353                   else
02354                     {
02355                       if (j > col && j < lim)
02356                         os << ", ";
02357                       else
02358                         os << "  ";
02359                     }
02360 
02361                   pr_complex (os, cm(j,j));
02362                 }
02363 
02364               col += inc;
02365 
02366               if (col >= nc)
02367                   os << " ]";
02368               else
02369                 os << " ...\n";
02370             }
02371           os << ")";
02372         }
02373       else
02374         {
02375           os << "Diagonal Matrix\n";
02376           if (! Vcompact_format)
02377             os << "\n";
02378 
02379           pr_scale_header (os, scale);
02380 
02381           // kluge. Get the true width of a number.
02382           int zero_fw;
02383 
02384             {
02385               std::ostringstream tmp_oss;
02386               pr_complex (tmp_oss, Complex (0.0), r_fw, i_fw, scale);
02387               zero_fw = tmp_oss.str ().length ();
02388             }
02389 
02390           for (octave_idx_type col = 0; col < nc; col += inc)
02391             {
02392               octave_idx_type lim = col + inc < nc ? col + inc : nc;
02393 
02394               pr_col_num_header (os, total_width, max_width, lim, col,
02395                                  extra_indent);
02396 
02397               for (octave_idx_type i = 0; i < nr; i++)
02398                 {
02399                   os << std::setw (extra_indent) << "";
02400 
02401                   for (octave_idx_type j = col; j < lim; j++)
02402                     {
02403                       octave_quit ();
02404 
02405                       os << "  ";
02406 
02407                       if (i == j)
02408                         pr_complex (os, cm(i,j), r_fw, i_fw, scale);
02409                       else
02410                         os << std::setw (zero_fw) << '0';
02411                     }
02412 
02413                   if (i < nr - 1)
02414                     os << "\n";
02415                 }
02416             }
02417         }
02418     }
02419 }
02420 
02421 void
02422 octave_print_internal (std::ostream& os, const PermMatrix& m,
02423                        bool pr_as_read_syntax, int extra_indent)
02424 {
02425   octave_idx_type nr = m.rows ();
02426   octave_idx_type nc = m.columns ();
02427 
02428   if (nr == 0 || nc == 0)
02429     print_empty_matrix (os, nr, nc, pr_as_read_syntax);
02430   else if (plus_format && ! pr_as_read_syntax)
02431     {
02432       for (octave_idx_type i = 0; i < nr; i++)
02433         {
02434           for (octave_idx_type j = 0; j < nc; j++)
02435             {
02436               octave_quit ();
02437 
02438               pr_plus_format (os, m(i,j));
02439             }
02440 
02441           if (i < nr - 1)
02442             os << "\n";
02443         }
02444     }
02445   else
02446     {
02447       int fw = 2;
02448       int column_width = fw + 2;
02449       octave_idx_type total_width = nc * column_width;
02450       octave_idx_type max_width = command_editor::terminal_cols ();
02451 
02452       if (pr_as_read_syntax)
02453         max_width -= 4;
02454       else
02455         max_width -= extra_indent;
02456 
02457       if (max_width < 0)
02458         max_width = 0;
02459 
02460       if (free_format)
02461         {
02462           if (pr_as_read_syntax)
02463             os << "[\n";
02464 
02465           os << Matrix (m);
02466 
02467           if (pr_as_read_syntax)
02468             os << "]";
02469 
02470           return;
02471         }
02472 
02473       octave_idx_type inc = nc;
02474       if (total_width > max_width && Vsplit_long_rows)
02475         {
02476           inc = max_width / column_width;
02477           if (inc == 0)
02478             inc++;
02479         }
02480 
02481       if (pr_as_read_syntax)
02482         {
02483           Array<octave_idx_type> pvec = m.pvec ();
02484           bool colp = m.is_col_perm ();
02485 
02486           os << "eye (";
02487           if (colp) os << ":, ";
02488 
02489           octave_idx_type col = 0;
02490           while (col < nc)
02491             {
02492               octave_idx_type lim = col + inc < nc ? col + inc : nc;
02493 
02494               for (octave_idx_type j = col; j < lim; j++)
02495                 {
02496                   octave_quit ();
02497 
02498                   if (j == 0)
02499                     os << "[ ";
02500                   else
02501                     {
02502                       if (j > col && j < lim)
02503                         os << ", ";
02504                       else
02505                         os << "  ";
02506                     }
02507 
02508                   os << pvec (j);
02509                 }
02510 
02511               col += inc;
02512 
02513               if (col >= nc)
02514                   os << " ]";
02515               else
02516                 os << " ...\n";
02517             }
02518           if (! colp) os << ", :";
02519           os << ")";
02520         }
02521       else
02522         {
02523           os << "Permutation Matrix\n";
02524           if (! Vcompact_format)
02525             os << "\n";
02526 
02527           for (octave_idx_type col = 0; col < nc; col += inc)
02528             {
02529               octave_idx_type lim = col + inc < nc ? col + inc : nc;
02530 
02531               pr_col_num_header (os, total_width, max_width, lim, col,
02532                                  extra_indent);
02533 
02534               for (octave_idx_type i = 0; i < nr; i++)
02535                 {
02536                   os << std::setw (extra_indent) << "";
02537 
02538                   for (octave_idx_type j = col; j < lim; j++)
02539                     {
02540                       octave_quit ();
02541 
02542                       os << "  ";
02543 
02544                       os << std::setw (fw) << m(i,j);
02545                     }
02546 
02547                   if (i < nr - 1)
02548                     os << "\n";
02549                 }
02550             }
02551         }
02552     }
02553 }
02554 
02555 void
02556 octave_print_internal (std::ostream& os, const ComplexNDArray& nda,
02557                        bool pr_as_read_syntax, int extra_indent)
02558 {
02559   switch (nda.ndims ())
02560     {
02561     case 1:
02562     case 2:
02563       octave_print_internal (os, nda.matrix_value (),
02564                              pr_as_read_syntax, extra_indent);
02565       break;
02566 
02567     default:
02568       print_nd_array <ComplexNDArray, Complex,
02569                       ComplexMatrix> (os, nda, pr_as_read_syntax);
02570       break;
02571     }
02572 }
02573 
02574 void
02575 octave_print_internal (std::ostream& os, bool d, bool pr_as_read_syntax)
02576 {
02577   octave_print_internal (os, double (d), pr_as_read_syntax);
02578 }
02579 
02580 // FIXME -- write single precision versions of the printing functions.
02581 
02582 void
02583 octave_print_internal (std::ostream& os, float d, bool pr_as_read_syntax)
02584 {
02585   octave_print_internal (os, double (d), pr_as_read_syntax);
02586 }
02587 
02588 void
02589 octave_print_internal (std::ostream& os, const FloatMatrix& m,
02590                        bool pr_as_read_syntax, int extra_indent)
02591 {
02592   octave_print_internal (os, Matrix (m), pr_as_read_syntax, extra_indent);
02593 }
02594 
02595 void
02596 octave_print_internal (std::ostream& os, const FloatDiagMatrix& m,
02597                        bool pr_as_read_syntax, int extra_indent)
02598 {
02599   octave_print_internal (os, DiagMatrix (m), pr_as_read_syntax, extra_indent);
02600 }
02601 
02602 void
02603 octave_print_internal (std::ostream& os, const FloatNDArray& nda,
02604                        bool pr_as_read_syntax, int extra_indent)
02605 {
02606   octave_print_internal (os, NDArray (nda), pr_as_read_syntax, extra_indent);
02607 }
02608 
02609 void
02610 octave_print_internal (std::ostream& os, const FloatComplex& c,
02611                        bool pr_as_read_syntax)
02612 {
02613   octave_print_internal (os, Complex (c), pr_as_read_syntax);
02614 }
02615 
02616 void
02617 octave_print_internal (std::ostream& os, const FloatComplexMatrix& cm,
02618                        bool pr_as_read_syntax, int extra_indent)
02619 {
02620   octave_print_internal (os, ComplexMatrix (cm), pr_as_read_syntax, extra_indent);
02621 }
02622 
02623 void
02624 octave_print_internal (std::ostream& os, const FloatComplexDiagMatrix& cm,
02625                        bool pr_as_read_syntax, int extra_indent)
02626 {
02627   octave_print_internal (os, ComplexDiagMatrix (cm), pr_as_read_syntax, extra_indent);
02628 }
02629 
02630 void
02631 octave_print_internal (std::ostream& os, const FloatComplexNDArray& nda,
02632                        bool pr_as_read_syntax, int extra_indent)
02633 {
02634   octave_print_internal (os, ComplexNDArray (nda), pr_as_read_syntax, extra_indent);
02635 }
02636 
02637 void
02638 octave_print_internal (std::ostream& os, const Range& r,
02639                        bool pr_as_read_syntax, int extra_indent)
02640 {
02641   double base = r.base ();
02642   double increment = r.inc ();
02643   double limit = r.limit ();
02644   octave_idx_type num_elem = r.nelem ();
02645 
02646   if (plus_format && ! pr_as_read_syntax)
02647     {
02648       for (octave_idx_type i = 0; i < num_elem; i++)
02649         {
02650           octave_quit ();
02651 
02652           double val = base + i * increment;
02653 
02654           pr_plus_format (os, val);
02655         }
02656     }
02657   else
02658     {
02659       int fw = 0;
02660       double scale = 1.0;
02661       set_format (r, fw, scale);
02662 
02663       if (pr_as_read_syntax)
02664         {
02665           if (free_format)
02666             {
02667               os << base << " : ";
02668               if (increment != 1.0)
02669                 os << increment << " : ";
02670               os << limit;
02671             }
02672           else
02673             {
02674               pr_float (os, base, fw);
02675               os << " : ";
02676               if (increment != 1.0)
02677                 {
02678                   pr_float (os, increment, fw);
02679                   os << " : ";
02680                 }
02681               pr_float (os, limit, fw);
02682             }
02683         }
02684       else
02685         {
02686           int column_width = fw + 2;
02687           octave_idx_type total_width = num_elem * column_width;
02688           octave_idx_type max_width = command_editor::terminal_cols ();
02689 
02690           if (free_format)
02691             {
02692               os << r;
02693               return;
02694             }
02695 
02696           octave_idx_type inc = num_elem;
02697           if (total_width > max_width && Vsplit_long_rows)
02698             {
02699               inc = max_width / column_width;
02700               if (inc == 0)
02701                 inc++;
02702             }
02703 
02704           max_width -= extra_indent;
02705 
02706           if (max_width < 0)
02707             max_width = 0;
02708 
02709           pr_scale_header (os, scale);
02710 
02711           octave_idx_type col = 0;
02712           while (col < num_elem)
02713             {
02714               octave_idx_type lim = col + inc < num_elem ? col + inc : num_elem;
02715 
02716               pr_col_num_header (os, total_width, max_width, lim, col,
02717                                  extra_indent);
02718 
02719               os << std::setw (extra_indent) << "";
02720 
02721               for (octave_idx_type i = col; i < lim; i++)
02722                 {
02723                   octave_quit ();
02724 
02725                   double val = base + i * increment;
02726 
02727                   if (i == num_elem - 1)
02728                     {
02729                       // See the comments in Range::matrix_value.
02730 
02731                       if ((increment > 0 && val > limit)
02732                           || (increment < 0 && val < limit))
02733                         val = limit;
02734                     }
02735 
02736                   os << "  ";
02737 
02738                   pr_float (os, val, fw, scale);
02739                 }
02740 
02741               col += inc;
02742             }
02743         }
02744     }
02745 }
02746 
02747 void
02748 octave_print_internal (std::ostream& os, const boolMatrix& bm,
02749                        bool pr_as_read_syntax,
02750                        int extra_indent)
02751 {
02752   Matrix tmp (bm);
02753   octave_print_internal (os, tmp, pr_as_read_syntax, extra_indent);
02754 }
02755 
02756 void
02757 octave_print_internal (std::ostream& os, const boolNDArray& nda,
02758                        bool pr_as_read_syntax,
02759                        int extra_indent)
02760 {
02761   switch (nda.ndims ())
02762     {
02763     case 1:
02764     case 2:
02765       octave_print_internal (os, nda.matrix_value (),
02766                              pr_as_read_syntax, extra_indent);
02767       break;
02768 
02769     default:
02770       print_nd_array<boolNDArray, bool,
02771                      boolMatrix> (os, nda, pr_as_read_syntax);
02772       break;
02773     }
02774 }
02775 
02776 void
02777 octave_print_internal (std::ostream& os, const charMatrix& chm,
02778                        bool pr_as_read_syntax,
02779                        int /* extra_indent FIXME */,
02780                        bool pr_as_string)
02781 {
02782   if (pr_as_string)
02783     {
02784       octave_idx_type nstr = chm.rows ();
02785 
02786       if (pr_as_read_syntax && nstr > 1)
02787         os << "[ ";
02788 
02789       if (nstr != 0)
02790         {
02791           for (octave_idx_type i = 0; i < nstr; i++)
02792             {
02793               octave_quit ();
02794 
02795               std::string row = chm.row_as_string (i);
02796 
02797               if (pr_as_read_syntax)
02798                 {
02799                   os << "\"" << undo_string_escapes (row) << "\"";
02800 
02801                   if (i < nstr - 1)
02802                     os << "; ";
02803                 }
02804               else
02805                 {
02806                   os << row;
02807 
02808                   if (i < nstr - 1)
02809                     os << "\n";
02810                 }
02811             }
02812         }
02813 
02814       if (pr_as_read_syntax && nstr > 1)
02815         os << " ]";
02816     }
02817   else
02818     {
02819       os << "sorry, printing char matrices not implemented yet\n";
02820     }
02821 }
02822 
02823 void
02824 octave_print_internal (std::ostream& os, const charNDArray& nda,
02825                        bool pr_as_read_syntax, int extra_indent,
02826                        bool pr_as_string)
02827 {
02828   switch (nda.ndims ())
02829     {
02830     case 1:
02831     case 2:
02832       octave_print_internal (os, nda.matrix_value (),
02833                              pr_as_read_syntax, extra_indent, pr_as_string);
02834       break;
02835 
02836     default:
02837       print_nd_array <charNDArray, char,
02838                       charMatrix> (os, nda, pr_as_read_syntax);
02839       break;
02840     }
02841 }
02842 
02843 void
02844 octave_print_internal (std::ostream& os, const std::string& s,
02845                        bool pr_as_read_syntax, int extra_indent)
02846 {
02847   Array<std::string> nda (dim_vector (1, 1), s);
02848 
02849   octave_print_internal (os, nda, pr_as_read_syntax, extra_indent);
02850 }
02851 
02852 void
02853 octave_print_internal (std::ostream& os, const Array<std::string>& nda,
02854                        bool pr_as_read_syntax, int /* extra_indent */)
02855 {
02856   // FIXME -- this mostly duplicates the code in the print_nd_array<>
02857   // function. Can fix this with std::is_same from C++11.
02858 
02859   if (nda.is_empty ())
02860     print_empty_nd_array (os, nda.dims (), pr_as_read_syntax);
02861   else if (nda.length () == 1)
02862     {
02863       os << nda(0);
02864     }
02865   else
02866     {
02867       int ndims = nda.ndims ();
02868 
02869       dim_vector dims = nda.dims ();
02870 
02871       Array<octave_idx_type> ra_idx (dim_vector (ndims, 1), 0);
02872 
02873       octave_idx_type m = 1;
02874 
02875       for (int i = 2; i < ndims; i++)
02876         m *= dims(i);
02877 
02878       octave_idx_type nr = dims(0);
02879       octave_idx_type nc = dims(1);
02880 
02881       for (octave_idx_type i = 0; i < m; i++)
02882         {
02883           std::string nm = "ans";
02884 
02885           if (m > 1)
02886             {
02887               nm += "(:,:,";
02888 
02889               std::ostringstream buf;
02890 
02891               for (int k = 2; k < ndims; k++)
02892                 {
02893                   buf << ra_idx(k) + 1;
02894 
02895                   if (k < ndims - 1)
02896                     buf << ",";
02897                   else
02898                     buf << ")";
02899                 }
02900 
02901               nm += buf.str ();
02902             }
02903 
02904           Array<idx_vector> idx (dim_vector (ndims, 1));
02905 
02906           idx(0) = idx_vector (':');
02907           idx(1) = idx_vector (':');
02908 
02909           for (int k = 2; k < ndims; k++)
02910             idx(k) = idx_vector (ra_idx(k));
02911 
02912           Array<std::string> page (nda.index (idx), dim_vector (nr, nc));
02913 
02914           // FIXME -- need to do some more work to put these
02915           // in neatly aligned columns...
02916 
02917           octave_idx_type n_rows = page.rows ();
02918           octave_idx_type n_cols = page.cols ();
02919 
02920           os << nm << " =\n";
02921           if (! Vcompact_format)
02922             os << "\n";
02923 
02924           for (octave_idx_type ii = 0; ii < n_rows; ii++)
02925             {
02926               for (octave_idx_type jj = 0; jj < n_cols; jj++)
02927                 os << "  " << page(ii,jj);
02928 
02929               os << "\n";
02930             }
02931 
02932           if (i < m - 1)
02933             os << "\n";
02934 
02935           if (i < m)
02936             increment_index (ra_idx, dims, 2);
02937         }
02938     }
02939 }
02940 
02941 template <class T>
02942 class
02943 octave_print_conv
02944 {
02945 public:
02946   typedef T print_conv_type;
02947 };
02948 
02949 #define PRINT_CONV(T1, T2) \
02950   template <> \
02951   class \
02952   octave_print_conv<T1> \
02953   { \
02954   public: \
02955     typedef T2 print_conv_type; \
02956   }
02957 
02958 PRINT_CONV (octave_int8, octave_int16);
02959 PRINT_CONV (octave_uint8, octave_uint16);
02960 
02961 #undef PRINT_CONV
02962 
02963 template <class T>
02964 /* static */ inline void
02965 pr_int (std::ostream& os, const T& d, int fw = 0)
02966 {
02967   size_t sz = d.byte_size();
02968   const unsigned char * tmpi = d.iptr();
02969 
02970   // Unless explicitly asked for, always print in big-endian
02971   // format for hex and bit formats.
02972   //
02973   //   {bit,hex}_format == 1: print big-endian
02974   //   {bit,hex}_format == 2: print native
02975 
02976   if (hex_format)
02977     {
02978       char ofill = os.fill ('0');
02979 
02980       std::ios::fmtflags oflags
02981         = os.flags (std::ios::right | std::ios::hex);
02982 
02983       if (hex_format > 1 || oct_mach_info::words_big_endian ())
02984         {
02985           for (size_t i = 0; i < sz; i++)
02986             os << std::setw (2) << static_cast<int> (tmpi[i]);
02987         }
02988       else
02989         {
02990           for (int i = sz - 1; i >= 0; i--)
02991             os << std::setw (2) << static_cast<int> (tmpi[i]);
02992         }
02993 
02994       os.fill (ofill);
02995       os.setf (oflags);
02996     }
02997   else if (bit_format)
02998     {
02999       if (oct_mach_info::words_big_endian ())
03000         {
03001           for (size_t i = 0; i < sz; i++)
03002             PRINT_CHAR_BITS (os, tmpi[i]);
03003         }
03004       else
03005         {
03006           if (bit_format > 1)
03007             {
03008               for (size_t i = 0; i < sz; i++)
03009                 PRINT_CHAR_BITS_SWAPPED (os, tmpi[i]);
03010             }
03011           else
03012             {
03013               for (int i = sz - 1; i >= 0; i--)
03014                 PRINT_CHAR_BITS (os, tmpi[i]);
03015             }
03016         }
03017     }
03018   else
03019     {
03020       os << std::setw (fw)
03021          << typename octave_print_conv<T>::print_conv_type (d);
03022 
03023       if (bank_format)
03024         os << ".00";
03025     }
03026 }
03027 
03028 // FIXME -- all this mess with abs is an attempt to avoid seeing
03029 //
03030 //   warning: comparison of unsigned expression < 0 is always false
03031 //
03032 // from GCC.  Isn't there a better way
03033 
03034 template <class T>
03035 /* static */ inline T
03036 abs (T x)
03037 {
03038   return x < 0 ? -x : x;
03039 }
03040 
03041 #define INSTANTIATE_ABS(T) \
03042   template /* static */ T abs (T)
03043 
03044 INSTANTIATE_ABS(signed char);
03045 INSTANTIATE_ABS(short);
03046 INSTANTIATE_ABS(int);
03047 INSTANTIATE_ABS(long);
03048 INSTANTIATE_ABS(long long);
03049 
03050 #define SPECIALIZE_UABS(T) \
03051   template <> \
03052   /* static */ inline unsigned T \
03053   abs (unsigned T x) \
03054   { \
03055     return x; \
03056   }
03057 
03058 SPECIALIZE_UABS(char)
03059 SPECIALIZE_UABS(short)
03060 SPECIALIZE_UABS(int)
03061 SPECIALIZE_UABS(long)
03062 SPECIALIZE_UABS(long long)
03063 
03064 template void
03065 pr_int (std::ostream&, const octave_int8&, int);
03066 
03067 template void
03068 pr_int (std::ostream&, const octave_int16&, int);
03069 
03070 template void
03071 pr_int (std::ostream&, const octave_int32&, int);
03072 
03073 template void
03074 pr_int (std::ostream&, const octave_int64&, int);
03075 
03076 template void
03077 pr_int (std::ostream&, const octave_uint8&, int);
03078 
03079 template void
03080 pr_int (std::ostream&, const octave_uint16&, int);
03081 
03082 template void
03083 pr_int (std::ostream&, const octave_uint32&, int);
03084 
03085 template void
03086 pr_int (std::ostream&, const octave_uint64&, int);
03087 
03088 template <class T>
03089 void
03090 octave_print_internal_template (std::ostream& os, const octave_int<T>& val,
03091                                 bool)
03092 {
03093   if (plus_format)
03094     {
03095       pr_plus_format (os, val);
03096     }
03097   else
03098     {
03099       if (free_format)
03100         os << typename octave_print_conv<octave_int<T> >::print_conv_type (val);
03101       else
03102         pr_int (os, val);
03103     }
03104 }
03105 
03106 #define PRINT_INT_SCALAR_INTERNAL(TYPE) \
03107   OCTINTERP_API void \
03108   octave_print_internal (std::ostream& os, const octave_int<TYPE>& val, bool dummy) \
03109   { \
03110     octave_print_internal_template (os, val, dummy); \
03111   }
03112 
03113 PRINT_INT_SCALAR_INTERNAL (int8_t)
03114 PRINT_INT_SCALAR_INTERNAL (uint8_t)
03115 PRINT_INT_SCALAR_INTERNAL (int16_t)
03116 PRINT_INT_SCALAR_INTERNAL (uint16_t)
03117 PRINT_INT_SCALAR_INTERNAL (int32_t)
03118 PRINT_INT_SCALAR_INTERNAL (uint32_t)
03119 PRINT_INT_SCALAR_INTERNAL (int64_t)
03120 PRINT_INT_SCALAR_INTERNAL (uint64_t)
03121 
03122 template <class T>
03123 /* static */ inline void
03124 octave_print_internal_template (std::ostream& os, const intNDArray<T>& nda,
03125                                 bool pr_as_read_syntax, int extra_indent)
03126 {
03127   // FIXME -- this mostly duplicates the code in the print_nd_array<>
03128   // function. Can fix this with std::is_same from C++11.
03129 
03130   if (nda.is_empty ())
03131     print_empty_nd_array (os, nda.dims (), pr_as_read_syntax);
03132   else if (nda.length () == 1)
03133     octave_print_internal_template (os, nda(0), pr_as_read_syntax);
03134   else if (plus_format && ! pr_as_read_syntax)
03135     {
03136       int ndims = nda.ndims ();
03137 
03138       Array<octave_idx_type> ra_idx (dim_vector (ndims, 1), 0);
03139 
03140       dim_vector dims = nda.dims ();
03141 
03142       octave_idx_type m = 1;
03143 
03144       for (int i = 2; i < ndims; i++)
03145         m *= dims(i);
03146 
03147       octave_idx_type nr = dims(0);
03148       octave_idx_type nc = dims(1);
03149 
03150       for (octave_idx_type i = 0; i < m; i++)
03151         {
03152           if (m > 1)
03153             {
03154               std::string nm = "ans(:,:,";
03155 
03156               std::ostringstream buf;
03157 
03158               for (int k = 2; k < ndims; k++)
03159                 {
03160                   buf << ra_idx(k) + 1;
03161 
03162                   if (k < ndims - 1)
03163                     buf << ",";
03164                   else
03165                     buf << ")";
03166                 }
03167 
03168               nm += buf.str ();
03169 
03170               os << nm << " =\n";
03171               if (! Vcompact_format)
03172                 os << "\n";
03173             }
03174 
03175           Array<idx_vector> idx (dim_vector (ndims, 1));
03176 
03177           idx(0) = idx_vector (':');
03178           idx(1) = idx_vector (':');
03179 
03180           for (int k = 2; k < ndims; k++)
03181             idx(k) = idx_vector (ra_idx(k));
03182 
03183           Array<T> page (nda.index (idx), dim_vector (nr, nc));
03184 
03185           for (octave_idx_type ii = 0; ii < nr; ii++)
03186             {
03187               for (octave_idx_type jj = 0; jj < nc; jj++)
03188                 {
03189                   octave_quit ();
03190 
03191                   pr_plus_format (os, page(ii,jj));
03192                 }
03193 
03194               if ((ii < nr - 1) || (i < m -1))
03195                 os << "\n";
03196             }
03197 
03198           if (i < m - 1)
03199             {
03200               os << "\n";
03201               increment_index (ra_idx, dims, 2);
03202             }
03203         }
03204     }
03205   else
03206     {
03207       int ndims = nda.ndims ();
03208 
03209       dim_vector dims = nda.dims ();
03210 
03211       Array<octave_idx_type> ra_idx (dim_vector (ndims, 1), 0);
03212 
03213       octave_idx_type m = 1;
03214 
03215       for (int i = 2; i < ndims; i++)
03216         m *= dims(i);
03217 
03218       octave_idx_type nr = dims(0);
03219       octave_idx_type nc = dims(1);
03220 
03221       int fw = 0;
03222       if (hex_format)
03223         fw = 2 * nda(0).byte_size ();
03224       else if (bit_format)
03225         fw = nda(0).nbits ();
03226       else
03227         {
03228           bool isneg = false;
03229           int digits = 0;
03230 
03231           for (octave_idx_type i = 0; i < dims.numel (); i++)
03232             {
03233               int new_digits = static_cast<int>
03234                 (gnulib::floor (log10 (double (abs (nda(i).value ()))) + 1.0));
03235 
03236               if (new_digits > digits)
03237                 digits = new_digits;
03238 
03239               if (! isneg)
03240               isneg = (abs (nda(i).value ()) != nda(i).value ());
03241             }
03242 
03243           fw = digits + isneg;
03244         }
03245 
03246       int column_width = fw + (rat_format ?  0 : (bank_format ? 5 : 2));
03247       octave_idx_type total_width = nc * column_width;
03248       int max_width = command_editor::terminal_cols () - extra_indent;
03249       octave_idx_type inc = nc;
03250       if (total_width > max_width && Vsplit_long_rows)
03251         {
03252           inc = max_width / column_width;
03253           if (inc == 0)
03254             inc++;
03255         }
03256 
03257       for (octave_idx_type i = 0; i < m; i++)
03258         {
03259           if (m > 1)
03260             {
03261               std::string nm = "ans(:,:,";
03262 
03263               std::ostringstream buf;
03264 
03265               for (int k = 2; k < ndims; k++)
03266                 {
03267                   buf << ra_idx(k) + 1;
03268 
03269                   if (k < ndims - 1)
03270                     buf << ",";
03271                   else
03272                     buf << ")";
03273                 }
03274 
03275               nm += buf.str ();
03276 
03277               os << nm << " =\n";
03278               if (! Vcompact_format)
03279                 os << "\n";
03280             }
03281 
03282           Array<idx_vector> idx (dim_vector (ndims, 1));
03283 
03284           idx(0) = idx_vector (':');
03285           idx(1) = idx_vector (':');
03286 
03287           for (int k = 2; k < ndims; k++)
03288             idx(k) = idx_vector (ra_idx(k));
03289 
03290           Array<T> page (nda.index (idx), dim_vector (nr, nc));
03291 
03292           if (free_format)
03293             {
03294               if (pr_as_read_syntax)
03295                 os << "[\n";
03296 
03297               for (octave_idx_type ii = 0; ii < nr; ii++)
03298                 {
03299                   for (octave_idx_type jj = 0; jj < nc; jj++)
03300                     {
03301                       octave_quit ();
03302                       os << "  ";
03303                       os << typename octave_print_conv<T>::print_conv_type (page(ii,jj));
03304                     }
03305                   os << "\n";
03306                 }
03307 
03308               if (pr_as_read_syntax)
03309                 os << "]";
03310             }
03311           else
03312             {
03313               octave_idx_type n_rows = page.rows ();
03314               octave_idx_type n_cols = page.cols ();
03315 
03316               for (octave_idx_type col = 0; col < n_cols; col += inc)
03317                 {
03318                   octave_idx_type lim = col + inc < n_cols ? col + inc : n_cols;
03319 
03320                   pr_col_num_header (os, total_width, max_width, lim, col,
03321                                      extra_indent);
03322 
03323                   for (octave_idx_type ii = 0; ii < n_rows; ii++)
03324                     {
03325                       os << std::setw (extra_indent) << "";
03326 
03327                       for (octave_idx_type jj = col; jj < lim; jj++)
03328                         {
03329                           octave_quit ();
03330                           os << "  ";
03331                           pr_int (os, page(ii,jj), fw);
03332                         }
03333                       if ((ii < n_rows - 1) || (i < m -1))
03334                         os << "\n";
03335                     }
03336                 }
03337             }
03338 
03339           if (i < m - 1)
03340             {
03341               os << "\n";
03342               increment_index (ra_idx, dims, 2);
03343             }
03344         }
03345     }
03346 }
03347 
03348 #define PRINT_INT_ARRAY_INTERNAL(TYPE) \
03349   OCTINTERP_API void \
03350   octave_print_internal (std::ostream& os, const intNDArray<TYPE>& nda, \
03351                          bool pr_as_read_syntax, int extra_indent) \
03352   { \
03353     octave_print_internal_template (os, nda, pr_as_read_syntax, extra_indent); \
03354   }
03355 
03356 PRINT_INT_ARRAY_INTERNAL (octave_int8)
03357 PRINT_INT_ARRAY_INTERNAL (octave_uint8)
03358 PRINT_INT_ARRAY_INTERNAL (octave_int16)
03359 PRINT_INT_ARRAY_INTERNAL (octave_uint16)
03360 PRINT_INT_ARRAY_INTERNAL (octave_int32)
03361 PRINT_INT_ARRAY_INTERNAL (octave_uint32)
03362 PRINT_INT_ARRAY_INTERNAL (octave_int64)
03363 PRINT_INT_ARRAY_INTERNAL (octave_uint64)
03364 
03365 void
03366 octave_print_internal (std::ostream&, const Cell&, bool, int, bool)
03367 {
03368   panic_impossible ();
03369 }
03370 
03371 DEFUN (rats, args, nargout,
03372   "-*- texinfo -*-\n\
03373 @deftypefn {Built-in Function} {} rats (@var{x}, @var{len})\n\
03374 Convert @var{x} into a rational approximation represented as a string.\n\
03375 You can convert the string back into a matrix as follows:\n\
03376 \n\
03377 @example\n\
03378 @group\n\
03379    r = rats(hilb(4));\n\
03380    x = str2num(r)\n\
03381 @end group\n\
03382 @end example\n\
03383 \n\
03384 The optional second argument defines the maximum length of the string\n\
03385 representing the elements of @var{x}.  By default @var{len} is 9.\n\
03386 @seealso{format, rat}\n\
03387 @end deftypefn")
03388 {
03389   octave_value retval;
03390 
03391   int nargin = args.length ();
03392 
03393   if (nargin < 1 || nargin > 2 || nargout > 1)
03394     print_usage ();
03395   else
03396     {
03397       unwind_protect frame;
03398 
03399       frame.protect_var (rat_string_len);
03400 
03401       rat_string_len = 9;
03402 
03403       if (nargin == 2)
03404         rat_string_len = args(1).nint_value ();
03405 
03406       if (! error_state)
03407         {
03408           octave_value arg = args(0);
03409 
03410           if (arg.is_numeric_type ())
03411             {
03412               frame.protect_var (rat_format);
03413 
03414               rat_format = true;
03415 
03416               std::ostringstream buf;
03417               args(0).print (buf);
03418               std::string s = buf.str ();
03419 
03420               std::list<std::string> lst;
03421 
03422               size_t n = 0;
03423               size_t s_len = s.length ();
03424 
03425               while (n < s_len)
03426                 {
03427                   size_t m = s.find ('\n',  n);
03428 
03429                   if (m == std::string::npos)
03430                     {
03431                       lst.push_back (s.substr (n));
03432                       break;
03433                     }
03434                   else
03435                     {
03436                       lst.push_back (s.substr (n, m - n));
03437                       n = m + 1;
03438                     }
03439                 }
03440 
03441               retval = string_vector (lst);
03442             }
03443           else
03444             error ("rats: X must be numeric");
03445         }
03446     }
03447 
03448   return retval;
03449 }
03450 
03451 DEFUN (disp, args, nargout,
03452   "-*- texinfo -*-\n\
03453 @deftypefn {Built-in Function} {} disp (@var{x})\n\
03454 Display the value of @var{x}.  For example:\n\
03455 \n\
03456 @example\n\
03457 @group\n\
03458 disp (\"The value of pi is:\"), disp (pi)\n\
03459 \n\
03460      @print{} the value of pi is:\n\
03461      @print{} 3.1416\n\
03462 @end group\n\
03463 @end example\n\
03464 \n\
03465 @noindent\n\
03466 Note that the output from @code{disp} always ends with a newline.\n\
03467 \n\
03468 If an output value is requested, @code{disp} prints nothing and\n\
03469 returns the formatted output in a string.\n\
03470 @seealso{fdisp}\n\
03471 @end deftypefn")
03472 {
03473   octave_value_list retval;
03474 
03475   int nargin = args.length ();
03476 
03477   if (nargin == 1 && nargout < 2)
03478     {
03479       if (nargout == 0)
03480         args(0).print (octave_stdout);
03481       else
03482         {
03483           octave_value arg = args(0);
03484           std::ostringstream buf;
03485           arg.print (buf);
03486           retval = octave_value (buf.str (), arg.is_dq_string () ? '"' : '\'');
03487         }
03488     }
03489   else
03490     print_usage ();
03491 
03492   return retval;
03493 }
03494 
03495 DEFUN (fdisp, args, ,
03496   "-*- texinfo -*-\n\
03497 @deftypefn {Built-in Function} {} fdisp (@var{fid}, @var{x})\n\
03498 Display the value of @var{x} on the stream @var{fid}.  For example:\n\
03499 \n\
03500 @example\n\
03501 @group\n\
03502 fdisp (stdout, \"The value of pi is:\"), fdisp (stdout, pi)\n\
03503 \n\
03504      @print{} the value of pi is:\n\
03505      @print{} 3.1416\n\
03506 @end group\n\
03507 @end example\n\
03508 \n\
03509 @noindent\n\
03510 Note that the output from @code{fdisp} always ends with a newline.\n\
03511 @seealso{disp}\n\
03512 @end deftypefn")
03513 {
03514   octave_value_list retval;
03515 
03516   int nargin = args.length ();
03517 
03518   if (nargin == 2)
03519     {
03520       int fid = octave_stream_list::get_file_number (args (0));
03521 
03522       octave_stream os = octave_stream_list::lookup (fid, "fdisp");
03523 
03524       if (! error_state)
03525         {
03526           std::ostream *osp = os.output_stream ();
03527 
03528           if (osp)
03529             args(1).print (*osp);
03530           else
03531             error ("fdisp: stream FID not open for writing");
03532         }
03533     }
03534   else
03535     print_usage ();
03536 
03537   return retval;
03538 }
03539 
03540 /*
03541 %!test
03542 %! format short
03543 %! fd = tmpfile ();
03544 %! for r = [0, Inf -Inf, NaN]
03545 %!   for i = [0, Inf -Inf, NaN]
03546 %!     fdisp (fd, complex (r, i));
03547 %!   endfor
03548 %! endfor
03549 %! fclose (fd);
03550 
03551 %!test
03552 %! foo.real = pi * ones (3,20,3);
03553 %! foo.complex = pi * ones (3,20,3) + 1i;
03554 %! foo.char = repmat ("- Hello World -", [3, 20]);
03555 %! foo.cell = {foo.real, foo.complex, foo.char};
03556 %! fields = fieldnames (foo);
03557 %! for f = 1:numel(fields)
03558 %!   format loose
03559 %!   loose = disp (foo.(fields{f}));
03560 %!   format compact
03561 %!   compact = disp (foo.(fields{f}));
03562 %!   expected = strrep (loose, "\n\n", "\n");
03563 %!   assert (expected, compact)
03564 %! endfor
03565 */
03566 
03567 static void
03568 init_format_state (void)
03569 {
03570   free_format = false;
03571   plus_format = false;
03572   rat_format = false;
03573   bank_format = false;
03574   hex_format = 0;
03575   bit_format = 0;
03576   Vcompact_format = false;
03577   print_e = false;
03578   print_big_e = false;
03579   print_g = false;
03580   print_eng = false;
03581 }
03582 
03583 static void
03584 set_output_prec_and_fw (int prec, int fw)
03585 {
03586   Voutput_precision =  prec;
03587   Voutput_max_field_width = fw;
03588 }
03589 
03590 static void
03591 set_format_style (int argc, const string_vector& argv)
03592 {
03593   int idx = 1;
03594 
03595   if (--argc > 0)
03596     {
03597       std::string arg = argv[idx++];
03598 
03599       if (arg == "short")
03600         {
03601           if (--argc > 0)
03602             {
03603               arg = argv[idx++];
03604 
03605               if (arg == "e")
03606                 {
03607                   init_format_state ();
03608                   print_e = true;
03609                 }
03610               else if (arg == "E")
03611                 {
03612                   init_format_state ();
03613                   print_e = true;
03614                   print_big_e = true;
03615                 }
03616               else if (arg == "g")
03617                 {
03618                   init_format_state ();
03619                   print_g = true;
03620                 }
03621               else if (arg == "G")
03622                 {
03623                   init_format_state ();
03624                   print_g = true;
03625                   print_big_e = true;
03626                 }
03627               else if (arg == "eng")
03628                 {
03629                   init_format_state ();
03630                   print_eng = true;
03631                 }
03632               else
03633                 {
03634                   error ("format: unrecognized option 'short %s'",
03635                          arg.c_str ());
03636                   return;
03637                 }
03638             }
03639           else
03640             init_format_state ();
03641 
03642           set_output_prec_and_fw (5, 10);
03643         }
03644       else if (arg == "long")
03645         {
03646           if (--argc > 0)
03647             {
03648               arg = argv[idx++];
03649 
03650               if (arg == "e")
03651                 {
03652                   init_format_state ();
03653                   print_e = true;
03654                 }
03655               else if (arg == "E")
03656                 {
03657                   init_format_state ();
03658                   print_e = true;
03659                   print_big_e = true;
03660                 }
03661               else if (arg == "g")
03662                 {
03663                   init_format_state ();
03664                   print_g = true;
03665                 }
03666               else if (arg == "G")
03667                 {
03668                   init_format_state ();
03669                   print_g = true;
03670                   print_big_e = true;
03671                 }
03672               else if (arg == "eng")
03673                 {
03674                   init_format_state ();
03675                   print_eng = true;
03676                 }
03677               else
03678                 {
03679                   error ("format: unrecognized option 'long %s'",
03680                          arg.c_str ());
03681                   return;
03682                 }
03683             }
03684           else
03685             init_format_state ();
03686 
03687           set_output_prec_and_fw (15, 20);
03688         }
03689       else if (arg == "hex")
03690         {
03691           init_format_state ();
03692           hex_format = 1;
03693         }
03694       else if (arg == "native-hex")
03695         {
03696           init_format_state ();
03697           hex_format = 2;
03698         }
03699       else if (arg == "bit")
03700         {
03701           init_format_state ();
03702           bit_format = 1;
03703         }
03704       else if (arg == "native-bit")
03705         {
03706           init_format_state ();
03707           bit_format = 2;
03708         }
03709       else if (arg == "+" || arg == "plus")
03710         {
03711           if (--argc > 0)
03712             {
03713               arg = argv[idx++];
03714 
03715               if (arg.length () == 3)
03716                 plus_format_chars = arg;
03717               else
03718                 {
03719                   error ("format: invalid option for plus format");
03720                   return;
03721                 }
03722             }
03723           else
03724             plus_format_chars = "+  ";
03725 
03726           init_format_state ();
03727           plus_format = true;
03728         }
03729       else if (arg == "rat")
03730         {
03731           init_format_state ();
03732           rat_format = true;
03733         }
03734       else if (arg == "bank")
03735         {
03736           init_format_state ();
03737           bank_format = true;
03738         }
03739       else if (arg == "free")
03740         {
03741           init_format_state ();
03742           free_format = true;
03743         }
03744       else if (arg == "none")
03745         {
03746           init_format_state ();
03747           free_format = true;
03748         }
03749       else if (arg == "compact")
03750         {
03751           Vcompact_format = true;
03752         }
03753       else if (arg == "loose")
03754         {
03755           Vcompact_format = false;
03756         }
03757       else
03758         error ("format: unrecognized format state '%s'", arg.c_str ());
03759     }
03760   else
03761     {
03762       init_format_state ();
03763       set_output_prec_and_fw (5, 10);
03764     }
03765 }
03766 
03767 DEFUN (format, args, ,
03768   "-*- texinfo -*-\n\
03769 @deftypefn  {Command} {} format\n\
03770 @deftypefnx {Command} {} format options\n\
03771 Reset or specify the format of the output produced by @code{disp} and\n\
03772 Octave's normal echoing mechanism.  This command only affects the display\n\
03773 of numbers but not how they are stored or computed.  To change the internal\n\
03774 representation from the default double use one of the conversion functions\n\
03775 such as @code{single}, @code{uint8}, @code{int64}, etc.\n\
03776 \n\
03777 By default, Octave displays 5 significant digits in a human readable form\n\
03778 (option @samp{short} paired with @samp{loose} format for matrices).\n\
03779 If @code{format} is invoked without any options, this default format\n\
03780 is restored.\n\
03781 \n\
03782 Valid formats for floating point numbers are listed in the following\n\
03783 table.\n\
03784 \n\
03785 @table @code\n\
03786 @item short\n\
03787 Fixed point format with 5 significant figures in a field that is a maximum\n\
03788 of 10 characters wide.  (default).\n\
03789 \n\
03790 If Octave is unable to format a matrix so that columns line up on the\n\
03791 decimal point and all numbers fit within the maximum field width then\n\
03792 it switches to an exponential @samp{e} format.\n\
03793 \n\
03794 @item long\n\
03795 Fixed point format with 15 significant figures in a field that is a maximum\n\
03796 of 20 characters wide.\n\
03797 \n\
03798 As with the @samp{short} format, Octave will switch to an exponential\n\
03799 @samp{e} format if it is unable to format a matrix properly using the\n\
03800 current format.\n\
03801 \n\
03802 @item short e\n\
03803 @itemx long e\n\
03804 Exponential format.  The number to be represented is split between a mantissa\n\
03805 and an exponent (power of 10).  The mantissa has 5 significant digits in the\n\
03806 short format and 15 digits in the long format.\n\
03807 For example, with the @samp{short e} format, @code{pi} is displayed as\n\
03808 @code{3.1416e+00}.\n\
03809 \n\
03810 @item short E\n\
03811 @itemx long E\n\
03812 Identical to @samp{short e} or @samp{long e} but displays an uppercase\n\
03813 @samp{E} to indicate the exponent.\n\
03814 For example, with the @samp{long E} format, @code{pi} is displayed as\n\
03815 @code{3.14159265358979E+00}.\n\
03816 \n\
03817 @item short g\n\
03818 @itemx long g\n\
03819 Optimally choose between fixed point and exponential format based on\n\
03820 the magnitude of the number.\n\
03821 For example, with the @samp{short g} format,\n\
03822 @code{pi .^ [2; 4; 8; 16; 32]} is displayed as\n\
03823 \n\
03824 @example\n\
03825 @group\n\
03826 ans =\n\
03827 \n\
03828       9.8696\n\
03829       97.409\n\
03830       9488.5\n\
03831   9.0032e+07\n\
03832   8.1058e+15\n\
03833 @end group\n\
03834 @end example\n\
03835 \n\
03836 @item short eng\n\
03837 @itemx long eng\n\
03838 Identical to @samp{short e} or @samp{long e} but displays the value\n\
03839 using an engineering format, where the exponent is divisible by 3. For\n\
03840 example, with the @samp{short eng} format, @code{10 * pi} is displayed as\n\
03841 @code{31.4159e+00}.\n\
03842 \n\
03843 @item long G\n\
03844 @itemx short G\n\
03845 Identical to @samp{short g} or @samp{long g} but displays an uppercase\n\
03846 @samp{E} to indicate the exponent.\n\
03847 \n\
03848 @item free\n\
03849 @itemx none\n\
03850 Print output in free format, without trying to line up columns of\n\
03851 matrices on the decimal point.  This also causes complex numbers to be\n\
03852 formatted as numeric pairs like this @samp{(0.60419, 0.60709)} instead\n\
03853 of like this @samp{0.60419 + 0.60709i}.\n\
03854 @end table\n\
03855 \n\
03856 The following formats affect all numeric output (floating point and\n\
03857 integer types).\n\
03858 \n\
03859 @table @code\n\
03860 @item  +\n\
03861 @itemx + @var{chars}\n\
03862 @itemx plus\n\
03863 @itemx plus @var{chars}\n\
03864 Print a @samp{+} symbol for nonzero matrix elements and a space for zero\n\
03865 matrix elements.  This format can be very useful for examining the\n\
03866 structure of a large sparse matrix.\n\
03867 \n\
03868 The optional argument @var{chars} specifies a list of 3 characters to use\n\
03869 for printing values greater than zero, less than zero and equal to zero.\n\
03870 For example, with the @samp{+ \"+-.\"} format, @code{[1, 0, -1; -1, 0, 1]}\n\
03871 is displayed as\n\
03872 \n\
03873 @example\n\
03874 @group\n\
03875 ans =\n\
03876 \n\
03877 +.-\n\
03878 -.+\n\
03879 @end group\n\
03880 @end example\n\
03881 \n\
03882 @item bank\n\
03883 Print in a fixed format with two digits to the right of the decimal\n\
03884 point.\n\
03885 \n\
03886 @item native-hex\n\
03887 Print the hexadecimal representation of numbers as they are stored in\n\
03888 memory.  For example, on a workstation which stores 8 byte real values\n\
03889 in IEEE format with the least significant byte first, the value of\n\
03890 @code{pi} when printed in @code{native-hex} format is\n\
03891 @code{400921fb54442d18}.\n\
03892 \n\
03893 @item hex\n\
03894 The same as @code{native-hex}, but always print the most significant\n\
03895 byte first.\n\
03896 \n\
03897 @item native-bit\n\
03898 Print the bit representation of numbers as stored in memory.\n\
03899 For example, the value of @code{pi} is\n\
03900 \n\
03901 @example\n\
03902 @group\n\
03903 01000000000010010010000111111011\n\
03904 01010100010001000010110100011000\n\
03905 @end group\n\
03906 @end example\n\
03907 \n\
03908 (shown here in two 32 bit sections for typesetting purposes) when\n\
03909 printed in native-bit format on a workstation which stores 8 byte real values\n\
03910 in IEEE format with the least significant byte first.\n\
03911 \n\
03912 @item bit\n\
03913 The same as @code{native-bit}, but always print the most significant\n\
03914 bits first.\n\
03915 \n\
03916 @item rat\n\
03917 Print a rational approximation, i.e., values are approximated\n\
03918 as the ratio of small integers.\n\
03919 For example, with the @samp{rat} format,\n\
03920 @code{pi} is displayed as @code{355/113}.\n\
03921 @end table\n\
03922 \n\
03923 The following two options affect the display of all matrices.\n\
03924 \n\
03925 @table @code\n\
03926 @item compact\n\
03927 Remove blank lines around column number labels and between\n\
03928 matrices producing more compact output with more data per page.\n\
03929 \n\
03930 @item loose\n\
03931 Insert blank lines above and below column number labels and between matrices\n\
03932 to produce a more readable output with less data per page.  (default).\n\
03933 @end table\n\
03934 @seealso{fixed_point_format, output_max_field_width, output_precision, split_long_rows, rats}\n\
03935 @end deftypefn")
03936 {
03937   octave_value_list retval;
03938 
03939   int argc = args.length () + 1;
03940 
03941   string_vector argv = args.make_argv ("format");
03942 
03943   if (error_state)
03944     return retval;
03945 
03946   set_format_style (argc, argv);
03947 
03948   return retval;
03949 }
03950 
03951 DEFUN (fixed_point_format, args, nargout,
03952   "-*- texinfo -*-\n\
03953 @deftypefn  {Built-in Function} {@var{val} =} fixed_point_format ()\n\
03954 @deftypefnx {Built-in Function} {@var{old_val} =} fixed_point_format (@var{new_val})\n\
03955 @deftypefnx {Built-in Function} {} fixed_point_format (@var{new_val}, \"local\")\n\
03956 Query or set the internal variable that controls whether Octave will\n\
03957 use a scaled format to print matrix values such that the largest\n\
03958 element may be written with a single leading digit with the scaling\n\
03959 factor is printed on the first line of output.  For example:\n\
03960 \n\
03961 @example\n\
03962 @group\n\
03963 octave:1> logspace (1, 7, 5)'\n\
03964 ans =\n\
03965 \n\
03966   1.0e+07  *\n\
03967 \n\
03968   0.00000\n\
03969   0.00003\n\
03970   0.00100\n\
03971   0.03162\n\
03972   1.00000\n\
03973 @end group\n\
03974 @end example\n\
03975 \n\
03976 @noindent\n\
03977 Notice that first value appears to be zero when it is actually 1.  For\n\
03978 this reason, you should be careful when setting\n\
03979 @code{fixed_point_format} to a nonzero value.\n\
03980 \n\
03981 When called from inside a function with the \"local\" option, the variable is\n\
03982 changed locally for the function and any subroutines it calls.  The original\n\
03983 variable value is restored when exiting the function.\n\
03984 @seealso{format, output_max_field_width, output_precision}\n\
03985 @end deftypefn")
03986 {
03987   return SET_INTERNAL_VARIABLE (fixed_point_format);
03988 }
03989 
03990 DEFUN (print_empty_dimensions, args, nargout,
03991   "-*- texinfo -*-\n\
03992 @deftypefn  {Built-in Function} {@var{val} =} print_empty_dimensions ()\n\
03993 @deftypefnx {Built-in Function} {@var{old_val} =} print_empty_dimensions (@var{new_val})\n\
03994 @deftypefnx {Built-in Function} {} print_empty_dimensions (@var{new_val}, \"local\")\n\
03995 Query or set the internal variable that controls whether the\n\
03996 dimensions of empty matrices are printed along with the empty matrix\n\
03997 symbol, @samp{[]}.  For example, the expression\n\
03998 \n\
03999 @example\n\
04000 zeros (3, 0)\n\
04001 @end example\n\
04002 \n\
04003 @noindent\n\
04004 will print\n\
04005 \n\
04006 @example\n\
04007 ans = [](3x0)\n\
04008 @end example\n\
04009 \n\
04010 When called from inside a function with the \"local\" option, the variable is\n\
04011 changed locally for the function and any subroutines it calls.  The original\n\
04012 variable value is restored when exiting the function.\n\
04013 @seealso{format}\n\
04014 @end deftypefn")
04015 {
04016   return SET_INTERNAL_VARIABLE (print_empty_dimensions);
04017 }
04018 
04019 DEFUN (split_long_rows, args, nargout,
04020   "-*- texinfo -*-\n\
04021 @deftypefn  {Built-in Function} {@var{val} =} split_long_rows ()\n\
04022 @deftypefnx {Built-in Function} {@var{old_val} =} split_long_rows (@var{new_val})\n\
04023 @deftypefnx {Built-in Function} {} split_long_rows (@var{new_val}, \"local\")\n\
04024 Query or set the internal variable that controls whether rows of a matrix\n\
04025 may be split when displayed to a terminal window.  If the rows are split,\n\
04026 Octave will display the matrix in a series of smaller pieces, each of\n\
04027 which can fit within the limits of your terminal width and each set of\n\
04028 rows is labeled so that you can easily see which columns are currently\n\
04029 being displayed.  For example:\n\
04030 \n\
04031 @example\n\
04032 @group\n\
04033 octave:13> rand (2,10)\n\
04034 ans =\n\
04035 \n\
04036  Columns 1 through 6:\n\
04037 \n\
04038   0.75883  0.93290  0.40064  0.43818  0.94958  0.16467\n\
04039   0.75697  0.51942  0.40031  0.61784  0.92309  0.40201\n\
04040 \n\
04041  Columns 7 through 10:\n\
04042 \n\
04043   0.90174  0.11854  0.72313  0.73326\n\
04044   0.44672  0.94303  0.56564  0.82150\n\
04045 @end group\n\
04046 @end example\n\
04047 \n\
04048 When called from inside a function with the \"local\" option, the variable is\n\
04049 changed locally for the function and any subroutines it calls.  The original\n\
04050 variable value is restored when exiting the function.\n\
04051 @seealso{format}\n\
04052 @end deftypefn")
04053 {
04054   return SET_INTERNAL_VARIABLE (split_long_rows);
04055 }
04056 
04057 DEFUN (output_max_field_width, args, nargout,
04058   "-*- texinfo -*-\n\
04059 @deftypefn  {Built-in Function} {@var{val} =} output_max_field_width ()\n\
04060 @deftypefnx {Built-in Function} {@var{old_val} =} output_max_field_width (@var{new_val})\n\
04061 @deftypefnx {Built-in Function} {} output_max_field_width (@var{new_val}, \"local\")\n\
04062 Query or set the internal variable that specifies the maximum width\n\
04063 of a numeric output field.\n\
04064 \n\
04065 When called from inside a function with the \"local\" option, the variable is\n\
04066 changed locally for the function and any subroutines it calls.  The original\n\
04067 variable value is restored when exiting the function.\n\
04068 @seealso{format, fixed_point_format, output_precision}\n\
04069 @end deftypefn")
04070 {
04071   return SET_INTERNAL_VARIABLE_WITH_LIMITS (output_max_field_width, 0, INT_MAX);
04072 }
04073 
04074 DEFUN (output_precision, args, nargout,
04075   "-*- texinfo -*-\n\
04076 @deftypefn  {Built-in Function} {@var{val} =} output_precision ()\n\
04077 @deftypefnx {Built-in Function} {@var{old_val} =} output_precision (@var{new_val})\n\
04078 @deftypefnx {Built-in Function} {} output_precision (@var{new_val}, \"local\")\n\
04079 Query or set the internal variable that specifies the minimum number of\n\
04080 significant figures to display for numeric output.\n\
04081 \n\
04082 When called from inside a function with the \"local\" option, the variable is\n\
04083 changed locally for the function and any subroutines it calls.  The original\n\
04084 variable value is restored when exiting the function.\n\
04085 @seealso{format, fixed_point_format, output_max_field_width}\n\
04086 @end deftypefn")
04087 {
04088   return SET_INTERNAL_VARIABLE_WITH_LIMITS (output_precision, -1, INT_MAX);
04089 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines