home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / octave-1.1.1p1-src.tgz / tar.out / fsf / octave / src / pr-output.cc < prev    next >
C/C++ Source or Header  |  1996-09-28  |  27KB  |  1,459 lines

  1. // pr-output.cc                                               -*- C++ -*-
  2. /*
  3.  
  4. Copyright (C) 1992, 1993, 1994, 1995 John W. Eaton
  5.  
  6. This file is part of Octave.
  7.  
  8. Octave is free software; you can redistribute it and/or modify it
  9. under the terms of the GNU General Public License as published by the
  10. Free Software Foundation; either version 2, or (at your option) any
  11. later version.
  12.  
  13. Octave is distributed in the hope that it will be useful, but WITHOUT
  14. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  16. for more details.
  17.  
  18. You should have received a copy of the GNU General Public License
  19. along with Octave; see the file COPYING.  If not, write to the Free
  20. Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  
  22. */
  23.  
  24. #ifdef HAVE_CONFIG_H
  25. #include "config.h"
  26. #endif
  27.  
  28. #include <iostream.h>
  29. #include <strstream.h>
  30. #include <string.h>
  31. #include <math.h>
  32. #include <float.h>
  33. #include <Complex.h>
  34.  
  35. #include "dMatrix.h"
  36. #include "CMatrix.h"
  37. #include "Range.h"
  38.  
  39. #include "tree-const.h"
  40. #include "variables.h"
  41. #include "user-prefs.h"
  42. #include "pr-output.h"
  43. #include "mappers.h"
  44. #include "pager.h"
  45. #include "help.h"
  46. #include "error.h"
  47. #include "utils.h"
  48. #include "defun.h"
  49.  
  50. // Current format string for real numbers and the real part of complex
  51. // numbers.
  52. static char *curr_real_fmt = 0;
  53.  
  54. // Current format string for the imaginary part of complex numbers.
  55. static char *curr_imag_fmt = 0;
  56.  
  57. // Nonzero means don\'t do any fancy formatting.
  58. static int free_format = 0;
  59.  
  60. // Nonzero means print plus sign for nonzero, blank for zero.
  61. static int plus_format = 0;
  62.  
  63. // Nonzero means always print like dollars and cents.
  64. static int bank_format = 0;
  65.  
  66. // Nonzero means use an e format.
  67. static int print_e = 0;
  68.  
  69. // Nonzero means print E instead of e for exponent field.
  70. static int print_big_e = 0;
  71.  
  72. static int
  73. any_element_is_negative (const Matrix& a)
  74. {
  75.   int nr = a.rows ();
  76.   int nc = a.columns ();
  77.   for (int j = 0; j < nc; j++)
  78.     for (int i = 0; i < nr; i++)
  79.       if (a.elem (i, j) < 0.0)
  80.     return 1;
  81.   return 0;
  82. }
  83.  
  84. static int
  85. any_element_is_inf_or_nan (const Matrix& a)
  86. {
  87.   int nr = a.rows ();
  88.   int nc = a.columns ();
  89.   for (int j = 0; j < nc; j++)
  90.     for (int i = 0; i < nr; i++)
  91.       {
  92.     double val = a.elem (i, j);
  93.     if (xisinf (val) || xisnan (val))
  94.       return 1;
  95.       }
  96.   return 0;
  97. }
  98.  
  99. static int
  100. any_element_is_inf_or_nan (const ComplexMatrix& a)
  101. {
  102.   int nr = a.rows ();
  103.   int nc = a.columns ();
  104.   for (int j = 0; j < nc; j++)
  105.     for (int i = 0; i < nr; i++)
  106.       {
  107.     Complex val = a.elem (i, j);
  108.     if (xisinf (val) || xisnan (val))
  109.       return 1;
  110.       }
  111.   return 0;
  112. }
  113.  
  114. static int
  115. all_elements_are_int_or_inf_or_nan (const Matrix& a)
  116. {
  117.   int nr = a.rows ();
  118.   int nc = a.columns ();
  119.   for (int j = 0; j < nc; j++)
  120.     for (int i = 0; i < nr; i++)
  121.       {
  122.     double val = a.elem (i, j);
  123.     if (xisnan (val) || D_NINT (val) == val)
  124.       continue;
  125.     else
  126.       return 0;
  127.       }
  128.   return 1;
  129. }
  130.  
  131. static Matrix
  132. abs (const Matrix& a)
  133. {
  134.   int nr = a.rows ();
  135.   int nc = a.columns ();
  136.   Matrix retval (nr, nc);
  137.   for (int j = 0; j < nc; j++)
  138.     for (int i = 0; i < nr; i++)
  139.       retval.elem (i, j) = fabs (a.elem (i, j));
  140.   return retval;
  141. }
  142.  
  143. static double
  144. pr_max_internal (const Matrix& m)
  145. {
  146.   int nr = m.rows ();
  147.   int nc = m.columns ();
  148.  
  149.   double result = DBL_MIN;
  150.  
  151.   for (int j = 0; j < nc; j++)
  152.     for (int i = 0; i < nr; i++)
  153.       {
  154.     double val = m.elem (i, j);
  155.     if (xisinf (val) || xisnan (val))
  156.       continue;
  157.  
  158.     if (val > result)
  159.       result = val;
  160.       }
  161.   return result;
  162. }
  163.  
  164. static double
  165. pr_min_internal (const Matrix& m)
  166. {
  167.   int nr = m.rows ();
  168.   int nc = m.columns ();
  169.  
  170.   double result = DBL_MAX;
  171.  
  172.   for (int j = 0; j < nc; j++)
  173.     for (int i = 0; i < nr; i++)
  174.       {
  175.     double val = m.elem (i, j);
  176.     if (xisinf (val) || xisnan (val))
  177.       continue;
  178.  
  179.     if (val < result)
  180.       result = val;
  181.       }
  182.   return result;
  183. }
  184.  
  185. static void
  186. set_format (double d, int& fw)
  187. {
  188.   curr_real_fmt = 0;
  189.   curr_imag_fmt = 0;
  190.  
  191.   if (free_format)
  192.     return;
  193.  
  194.   static char fmt_buf[128];
  195.  
  196.   int sign = (d < 0.0);
  197.  
  198.   int inf_or_nan = (xisinf (d) || xisnan (d));
  199.  
  200.   double d_abs = d < 0.0 ? -d : d;
  201.  
  202.   int digits = (inf_or_nan || d_abs == 0.0) ? 0
  203.     : (int) floor (log10 (d_abs) + 1.0);
  204.  
  205.   int prec = user_pref.output_precision;
  206.  
  207.   int ld, rd;
  208.  
  209.   if (bank_format)
  210.     {
  211.       fw = digits < 0 ? 4 : digits + 3;
  212.       if (inf_or_nan && fw < 3)
  213.     fw = 3;
  214.       fw += sign;
  215.       rd = 2;
  216.     }
  217.   else if (xisnan (d) || D_NINT (d) == d)
  218.     {
  219.       fw = digits;
  220.       if (inf_or_nan && fw < 3)
  221.     fw = 3;
  222.       fw += sign;
  223.       rd = 0;
  224.     }
  225.   else
  226.     {
  227.       if (digits > 0)
  228.     {
  229.       ld = digits;
  230.       rd = prec - digits;
  231.       digits++;
  232.     }
  233.       else
  234.     {
  235.       ld = 1;
  236.       rd = prec - digits;
  237.       digits = -digits + 1;
  238.     }
  239.  
  240.       fw = ld + 1 + rd;
  241.       if (inf_or_nan && fw < 3)
  242.     fw = 3;
  243.       fw += sign;
  244.     }
  245.  
  246.   if (! bank_format && (fw > user_pref.output_max_field_width || print_e))
  247.     {
  248.       int exp_field = 4;
  249.       if (digits > 100)
  250.     exp_field++;
  251.  
  252.       fw = 2 + prec + exp_field;
  253.       if (inf_or_nan && fw < 3)
  254.     fw = 3;
  255.       fw += sign;
  256.  
  257.       if (print_big_e)
  258.     sprintf (fmt_buf, "%%%d.%dE", fw, prec - 1);
  259.       else
  260.     sprintf (fmt_buf, "%%%d.%de", fw, prec - 1);
  261.     }
  262.   else
  263.     {
  264.       sprintf (fmt_buf, "%%%d.%df", fw, rd);
  265.     }
  266.  
  267.   curr_real_fmt = &fmt_buf[0];
  268. }
  269.  
  270. static inline void
  271. set_format (double d)
  272. {
  273.   int fw;
  274.   set_format (d, fw);
  275. }
  276.  
  277. static void
  278. set_format (const Matrix& m, int& fw)
  279. {
  280.   curr_real_fmt = 0;
  281.   curr_imag_fmt = 0;
  282.  
  283.   if (free_format)
  284.     return;
  285.  
  286.   static char fmt_buf[128];
  287.  
  288.   int sign = any_element_is_negative (m);
  289.  
  290.   int inf_or_nan = any_element_is_inf_or_nan (m);
  291.  
  292.   Matrix m_abs = abs (m);
  293.   double max_abs = pr_max_internal (m_abs);
  294.   double min_abs = pr_min_internal (m_abs);
  295.  
  296.   int x_max = max_abs == 0.0 ? 0 : (int) floor (log10 (max_abs) + 1.0);
  297.   int x_min = min_abs == 0.0 ? 0 : (int) floor (log10 (min_abs) + 1.0);
  298.  
  299.   int prec = user_pref.output_precision;
  300.  
  301.   int ld, rd;
  302.  
  303.   if (bank_format)
  304.     {
  305.       int digits = x_max > x_min ? x_max : x_min;
  306.       fw = digits <= 0 ? 4 : digits + 3;
  307.       if (inf_or_nan && fw < 3)
  308.     fw = 3;
  309.       fw += sign;
  310.       rd = 2;
  311.     }
  312.   else if (all_elements_are_int_or_inf_or_nan (m))
  313.     {
  314.       int digits = x_max > x_min ? x_max : x_min;
  315.       fw = digits <= 0 ? 1 : digits;
  316.       if (inf_or_nan && fw < 3)
  317.     fw = 3;
  318.       fw += sign;
  319.       rd = 0;
  320.     }
  321.   else
  322.     {
  323.       int ld_max, rd_max;
  324.       if (x_max > 0)
  325.     {
  326.       ld_max = x_max;
  327.       rd_max = prec - x_max;
  328.       x_max++;
  329.     }
  330.       else
  331.     {
  332.       ld_max = 1;
  333.       rd_max = prec - x_max;
  334.       x_max = -x_max + 1;
  335.     }
  336.  
  337.       int ld_min, rd_min;
  338.       if (x_min > 0)
  339.     {
  340.       ld_min = x_min;
  341.       rd_min = prec - x_min;
  342.       x_min++;
  343.     }
  344.       else
  345.     {
  346.       ld_min = 1;
  347.       rd_min = prec - x_min;
  348.       x_min = -x_min + 1;
  349.     }
  350.  
  351.       ld = ld_max > ld_min ? ld_max : ld_min;
  352.       rd = rd_max > rd_min ? rd_max : rd_min;
  353.  
  354.       fw = ld + 1 + rd;
  355.       if (inf_or_nan && fw < 3)
  356.     fw = 3;
  357.       fw += sign;
  358.     }
  359.  
  360.   if (! bank_format && (fw > user_pref.output_max_field_width || print_e))
  361.     {
  362.       int exp_field = 4;
  363.       if (x_max > 100 || x_min > 100)
  364.     exp_field++;
  365.  
  366.       fw = 2 + prec + exp_field;
  367.       if (inf_or_nan && fw < 3)
  368.     fw = 3;
  369.       fw += sign;
  370.  
  371.       if (print_big_e)
  372.     sprintf (fmt_buf, "%%%d.%dE", fw, prec - 1);
  373.       else
  374.     sprintf (fmt_buf, "%%%d.%de", fw, prec - 1);
  375.     }
  376.   else
  377.     {
  378.       sprintf (fmt_buf, "%%%d.%df", fw, rd);
  379.     }
  380.  
  381.   curr_real_fmt = &fmt_buf[0];
  382. }
  383.  
  384. static inline void
  385. set_format (const Matrix& m)
  386. {
  387.   int fw;
  388.   set_format (m, fw);
  389. }
  390.  
  391. static void
  392. set_format (const Complex& c, int& r_fw, int& i_fw)
  393. {
  394.   curr_real_fmt = 0;
  395.   curr_imag_fmt = 0;
  396.  
  397.   if (free_format)
  398.     return;
  399.  
  400.   static char r_fmt_buf[128];
  401.   static char i_fmt_buf[128];
  402.  
  403.   double rp = c.real ();
  404.   double ip = c.imag ();
  405.  
  406.   int sign = (rp < 0.0);
  407.  
  408.   int inf_or_nan = (xisinf (c) || xisnan (c));
  409.  
  410.   double r_abs = rp < 0.0 ? -rp : rp;
  411.   double i_abs = ip < 0.0 ? -ip : ip;
  412.  
  413.   int r_x = r_abs == 0.0 ? 0 : (int) floor (log10 (r_abs) + 1.0);
  414.   int i_x = i_abs == 0.0 ? 0 : (int) floor (log10 (i_abs) + 1.0);
  415.  
  416.   int x_max, x_min;
  417.  
  418.   if (r_x > i_x)
  419.     {
  420.       x_max = r_x;
  421.       x_min = i_x;
  422.     }
  423.   else
  424.     {
  425.       x_max = i_x;
  426.       x_min = r_x;
  427.     }
  428.  
  429.   int prec = user_pref.output_precision;
  430.  
  431.   int ld, rd;
  432.  
  433.   if (bank_format)
  434.     {
  435.       int digits = r_x;
  436.       i_fw = 0;
  437.       r_fw = digits <= 0 ? 4 : digits + 3;
  438.       if (inf_or_nan && r_fw < 3)
  439.     r_fw = 3;
  440.       r_fw += sign;
  441.       rd = 2;
  442.     }
  443.   else if (inf_or_nan || (D_NINT (rp) == rp && D_NINT (ip) == ip))
  444.     {
  445.       int digits = x_max > x_min ? x_max : x_min;
  446.       i_fw = r_fw = digits <= 0 ? 1 : digits;
  447.       if (inf_or_nan && i_fw < 3)
  448.     i_fw = r_fw = 3;
  449.       r_fw += sign;
  450.       rd = 0;
  451.     }
  452.   else
  453.     {
  454.       int ld_max, rd_max;
  455.       if (x_max > 0)
  456.     {
  457.       ld_max = x_max;
  458.       rd_max = prec - x_max;
  459.       x_max++;
  460.     }
  461.       else
  462.     {
  463.       ld_max = 1;
  464.       rd_max = prec - x_max;
  465.       x_max = -x_max + 1;
  466.     }
  467.  
  468.       int ld_min, rd_min;
  469.       if (x_min > 0)
  470.     {
  471.       ld_min = x_min;
  472.       rd_min = prec - x_min;
  473.       x_min++;
  474.     }
  475.       else
  476.     {
  477.       ld_min = 1;
  478.       rd_min = prec - x_min;
  479.       x_min = -x_min + 1;
  480.     }
  481.  
  482.       ld = ld_max > ld_min ? ld_max : ld_min;
  483.       rd = rd_max > rd_min ? rd_max : rd_min;
  484.  
  485.       i_fw = r_fw = ld + 1 + rd;
  486.       if (inf_or_nan && i_fw < 3)
  487.     i_fw = r_fw = 3;
  488.       r_fw += sign;
  489.     }
  490.  
  491.   if (! bank_format && (r_fw > user_pref.output_max_field_width || print_e))
  492.     {
  493.       int exp_field = 4;
  494.       if (x_max > 100 || x_min > 100)
  495.     exp_field++;
  496.  
  497.       i_fw = r_fw = 1 + prec + exp_field;
  498.       if (inf_or_nan && i_fw < 3)
  499.     i_fw = r_fw = 3;
  500.       r_fw += sign;
  501.  
  502.       if (print_big_e)
  503.     {
  504.       sprintf (r_fmt_buf, "%%%d.%dE", r_fw, prec - 1);
  505.       sprintf (i_fmt_buf, "%%%d.%dE", i_fw, prec - 1);
  506.     }
  507.       else
  508.     {
  509.       sprintf (r_fmt_buf, "%%%d.%de", r_fw, prec - 1);
  510.       sprintf (i_fmt_buf, "%%%d.%de", i_fw, prec - 1);
  511.     }
  512.     }
  513.   else
  514.     {
  515.       sprintf (r_fmt_buf, "%%%d.%df", r_fw, rd);
  516.       sprintf (i_fmt_buf, "%%%d.%df", i_fw, rd);
  517.     }
  518.  
  519.   curr_real_fmt = &r_fmt_buf[0];
  520.   curr_imag_fmt = &i_fmt_buf[0];
  521. }
  522.  
  523. static inline void
  524. set_format (const Complex& c)
  525. {
  526.   int r_fw, i_fw;
  527.   set_format (c, r_fw, i_fw);
  528. }
  529.  
  530. static void
  531. set_format (const ComplexMatrix& cm, int& r_fw, int& i_fw)
  532. {
  533.   curr_real_fmt = 0;
  534.   curr_imag_fmt = 0;
  535.  
  536.   if (free_format)
  537.     return;
  538.  
  539.   static char r_fmt_buf[128];
  540.   static char i_fmt_buf[128];
  541.  
  542.   Matrix rp = real (cm);
  543.   Matrix ip = imag (cm);
  544.  
  545.   int sign = any_element_is_negative (rp);
  546.  
  547.   int inf_or_nan = any_element_is_inf_or_nan (cm);
  548.  
  549.   Matrix r_m_abs = abs (rp);
  550.   double r_max_abs = pr_max_internal (r_m_abs);
  551.   double r_min_abs = pr_min_internal (r_m_abs);
  552.  
  553.   Matrix i_m_abs = abs (ip);
  554.   double i_max_abs = pr_max_internal (i_m_abs);
  555.   double i_min_abs = pr_min_internal (i_m_abs);
  556.  
  557.   int r_x_max = r_max_abs == 0.0 ? 0 : (int) floor (log10 (r_max_abs) + 1.0);
  558.   int r_x_min = r_min_abs == 0.0 ? 0 : (int) floor (log10 (r_min_abs) + 1.0);
  559.  
  560.   int i_x_max = i_max_abs == 0.0 ? 0 : (int) floor (log10 (i_max_abs) + 1.0);
  561.   int i_x_min = i_min_abs == 0.0 ? 0 : (int) floor (log10 (i_min_abs) + 1.0);
  562.  
  563.   int x_max = r_x_max > i_x_max ? r_x_max : i_x_max;
  564.   int x_min = r_x_min > i_x_min ? r_x_min : i_x_min;
  565.  
  566.   int prec = user_pref.output_precision;
  567.  
  568.   int ld, rd;
  569.  
  570.   if (bank_format)
  571.     {
  572.       int digits = r_x_max > r_x_min ? r_x_max : r_x_min;
  573.       i_fw = 0;
  574.       r_fw = digits <= 0 ? 4 : digits + 3;
  575.       if (inf_or_nan && i_fw < 3)
  576.     i_fw = r_fw = 3;
  577.       r_fw += sign;
  578.       rd = 2;
  579.     }
  580.   else if (all_elements_are_int_or_inf_or_nan (rp)
  581.        && all_elements_are_int_or_inf_or_nan (ip))
  582.     {
  583.       int digits = x_max > x_min ? x_max : x_min;
  584.       i_fw = r_fw = digits <= 0 ? 1 : digits;
  585.       if (inf_or_nan && i_fw < 3)
  586.     i_fw = r_fw = 3;
  587.       r_fw += sign;
  588.       rd = 0;
  589.     }
  590.   else
  591.     {
  592.       int ld_max, rd_max;
  593.       if (x_max > 0)
  594.     {
  595.       ld_max = x_max;
  596.       rd_max = prec - x_max;
  597.       x_max++;
  598.     }
  599.       else
  600.     {
  601.       ld_max = 1;
  602.       rd_max = prec - x_max;
  603.       x_max = -x_max + 1;
  604.     }
  605.  
  606.       int ld_min, rd_min;
  607.       if (x_min > 0)
  608.     {
  609.       ld_min = x_min;
  610.       rd_min = prec - x_min;
  611.       x_min++;
  612.     }
  613.       else
  614.     {
  615.       ld_min = 1;
  616.       rd_min = prec - x_min;
  617.       x_min = -x_min + 1;
  618.     }
  619.  
  620.       ld = ld_max > ld_min ? ld_max : ld_min;
  621.       rd = rd_max > rd_min ? rd_max : rd_min;
  622.  
  623.       i_fw = r_fw = ld + 1 + rd;
  624.       if (inf_or_nan && i_fw < 3)
  625.     i_fw = r_fw = 3;
  626.       r_fw += sign;
  627.     }
  628.  
  629.   if (! bank_format && (r_fw > user_pref.output_max_field_width || print_e))
  630.     {
  631.       int exp_field = 4;
  632.       if (x_max > 100 || x_min > 100)
  633.     exp_field++;
  634.  
  635.       i_fw = r_fw = 1 + prec + exp_field;
  636.       if (inf_or_nan && i_fw < 3)
  637.     i_fw = r_fw = 3;
  638.       r_fw += sign;
  639.  
  640.       if (print_big_e)
  641.     {
  642.       sprintf (r_fmt_buf, "%%%d.%dE", r_fw, prec - 1);
  643.       sprintf (i_fmt_buf, "%%%d.%dE", i_fw, prec - 1);
  644.     }
  645.       else
  646.     {
  647.       sprintf (r_fmt_buf, "%%%d.%de", r_fw, prec - 1);
  648.       sprintf (i_fmt_buf, "%%%d.%de", i_fw, prec - 1);
  649.     }
  650.     }
  651.   else
  652.     {
  653.       sprintf (r_fmt_buf, "%%%d.%df", r_fw, rd);
  654.       sprintf (i_fmt_buf, "%%%d.%df", i_fw, rd);
  655.     }
  656.  
  657.   curr_real_fmt = &r_fmt_buf[0];
  658.   curr_imag_fmt = &i_fmt_buf[0];
  659. }
  660.  
  661. static int
  662. all_elements_are_ints (const Range& r)
  663. {
  664. // If the base and increment are ints, the final value in the range
  665. // will also be an integer, even if the limit is not.
  666.  
  667.   double b = r.base ();
  668.   double i = r.inc ();
  669.  
  670.   return (! (xisnan (b) || xisnan (i))
  671.       && (double) NINT (b) == b && (double) NINT (i) == i);
  672. }
  673.  
  674. static inline void
  675. set_format (const ComplexMatrix& cm)
  676. {
  677.   int r_fw, i_fw;
  678.   set_format (cm, r_fw, i_fw);
  679. }
  680.  
  681. static void
  682. set_format (const Range& r, int& fw)
  683. {
  684.   curr_real_fmt = 0;
  685.   curr_imag_fmt = 0;
  686.  
  687.   if (free_format)
  688.     return;
  689.  
  690.   static char fmt_buf[128];
  691.  
  692.   double r_min = r.base ();
  693.   double r_max = r.limit ();
  694.  
  695.   if (r_max < r_min)
  696.     {
  697.       double tmp = r_max;
  698.       r_max = r_min;
  699.       r_min = tmp;
  700.     }
  701.  
  702.   int sign = (r_min < 0.0);
  703.  
  704.   double max_abs = r_max < 0.0 ? -r_max : r_max;
  705.   double min_abs = r_min < 0.0 ? -r_min : r_min;
  706.  
  707.   int x_max = max_abs == 0.0 ? 0 : (int) floor (log10 (max_abs) + 1.0);
  708.   int x_min = min_abs == 0.0 ? 0 : (int) floor (log10 (min_abs) + 1.0);
  709.  
  710.   int prec = user_pref.output_precision;
  711.  
  712.   int ld, rd;
  713.  
  714.   if (bank_format)
  715.     {
  716.       int digits = x_max > x_min ? x_max : x_min;
  717.       fw = sign + digits < 0 ? 4 : digits + 3;
  718.       rd = 2;
  719.     }
  720.   else if (all_elements_are_ints (r))
  721.     {
  722.       int digits = x_max > x_min ? x_max : x_min;
  723.       fw = sign + digits;
  724.       rd = 0;
  725.     }
  726.   else
  727.     {
  728.       int ld_max, rd_max;
  729.       if (x_max > 0)
  730.     {
  731.       ld_max = x_max;
  732.       rd_max = prec - x_max;
  733.       x_max++;
  734.     }
  735.       else
  736.     {
  737.       ld_max = 1;
  738.       rd_max = prec - x_max;
  739.       x_max = -x_max + 1;
  740.     }
  741.  
  742.       int ld_min, rd_min;
  743.       if (x_min > 0)
  744.     {
  745.       ld_min = x_min;
  746.       rd_min = prec - x_min;
  747.       x_min++;
  748.     }
  749.       else
  750.     {
  751.       ld_min = 1;
  752.       rd_min = prec - x_min;
  753.       x_min = -x_min + 1;
  754.     }
  755.  
  756.       ld = ld_max > ld_min ? ld_max : ld_min;
  757.       rd = rd_max > rd_min ? rd_max : rd_min;
  758.  
  759.       fw = sign + ld + 1 + rd;
  760.     }
  761.  
  762.   if (! bank_format && (fw > user_pref.output_max_field_width || print_e))
  763.     {
  764.       int exp_field = 4;
  765.       if (x_max > 100 || x_min > 100)
  766.     exp_field++;
  767.  
  768.       fw = sign + 2 + prec + exp_field;
  769.  
  770.       if (print_big_e)
  771.     sprintf (fmt_buf, "%%%d.%dE", fw, prec - 1);
  772.       else
  773.     sprintf (fmt_buf, "%%%d.%de", fw, prec - 1);
  774.     }
  775.   else
  776.     {
  777.       sprintf (fmt_buf, "%%%d.%df", fw, rd);
  778.     }
  779.  
  780.   curr_real_fmt = &fmt_buf[0];
  781. }
  782.  
  783. static inline void
  784. set_format (const Range& r)
  785. {
  786.   int fw;
  787.   set_format (r, fw);
  788. }
  789.  
  790. static inline void
  791. pr_any_float (const char *fmt, ostream& os, double d, int fw = 0)
  792. {
  793.   if (d == -0.0)
  794.     d = 0.0;
  795.  
  796.   if (fmt)
  797.     {
  798.       if (xisinf (d))
  799.     {
  800.       char *s;
  801.       if (d < 0.0)
  802.         s = "-Inf";
  803.       else
  804.         s = "Inf";
  805.  
  806.       if (fw > 0)
  807.         os.form ("%*s", fw, s);
  808.       else
  809.         os << s;
  810.     }
  811.       else if (xisnan (d))
  812.     {
  813.       if (fw > 0)
  814.         os.form ("%*s", fw, "NaN");
  815.       else
  816.         os << "NaN";
  817.     }
  818.       else
  819.     os.form (fmt, d);
  820.     }
  821.   else
  822.     os << d;
  823. }
  824.  
  825. static inline void
  826. pr_float (ostream& os, double d, int fw = 0)
  827. {
  828.   pr_any_float (curr_real_fmt, os, d, fw);
  829. }
  830.  
  831. static inline void
  832. pr_imag_float (ostream& os, double d, int fw = 0)
  833. {
  834.   pr_any_float (curr_imag_fmt, os, d, fw);
  835. }
  836.  
  837. static inline void
  838. pr_complex (ostream& os, const Complex& c, int r_fw = 0, int i_fw = 0)
  839. {
  840.   double r = c.real ();
  841.   pr_float (os, r, r_fw);
  842.   if (! bank_format)
  843.     {
  844.       double i = c.imag ();
  845.       if (i < 0)
  846.     {
  847.       os << " - ";
  848.       i = -i;
  849.       pr_imag_float (os, i, i_fw);
  850.     }
  851.       else
  852.     {
  853.       os << " + ";
  854.       pr_imag_float (os, i, i_fw);
  855.     }
  856.       os << "i";
  857.     }
  858. }
  859.  
  860. static void
  861. print_empty_matrix (ostream& os, int nr, int nc, int pr_as_read_syntax)
  862. {
  863.   assert (nr == 0 || nc == 0);
  864.  
  865.   if (pr_as_read_syntax)
  866.     {
  867.       if (nr == 0 && nc == 0)
  868.     os << "[]";
  869.       else
  870.     os << "zeros (" << nr << ", " << nc << ")";
  871.     }
  872.   else
  873.     {
  874.       os << "[]";
  875.       if (user_pref.print_empty_dimensions)
  876.     os << "(" << nr << "x" << nc << ")";
  877.       os << "\n";
  878.     }
  879. }
  880.  
  881. void
  882. octave_print_internal (ostream& os, double d, int pr_as_read_syntax)
  883. {
  884.   if (plus_format)
  885.     {
  886.       if (d == 0.0)
  887.     os << " ";
  888.       else
  889.     os << "+";
  890.     }
  891.   else
  892.     {
  893.       set_format (d);
  894.       if (free_format)
  895.     os << d;
  896.       else
  897.     pr_float (os, d);
  898.     }
  899.  
  900.   if (! pr_as_read_syntax)
  901.     os << "\n";
  902. }
  903.  
  904. void
  905. octave_print_internal (ostream& os, const Matrix& m, int pr_as_read_syntax)
  906. {
  907.   int nr = m.rows ();
  908.   int nc = m.columns ();
  909.  
  910.   if (nr == 0 || nc == 0)
  911.     print_empty_matrix (os, nr, nc, pr_as_read_syntax);
  912.   else if (plus_format && ! pr_as_read_syntax)
  913.     {
  914.       for (int i = 0; i < nr; i++)
  915.     {
  916.       for (int j = 0; j < nc; j++)
  917.         {
  918.           if (j == 0)
  919.         os << "  ";
  920.  
  921.           if (m.elem (i, j) == 0.0)
  922.         os << " ";
  923.           else
  924.         os << "+";
  925.         }
  926.       os << "\n";
  927.     }
  928.     }
  929.   else
  930.     {
  931.       int fw;
  932.       set_format (m, fw);
  933.       int column_width = fw + 2;
  934.       int total_width = nc * column_width;
  935.       int max_width = terminal_columns ();
  936.  
  937.       if (pr_as_read_syntax)
  938.     max_width -= 4;
  939.  
  940.       if (free_format)
  941.     {
  942.       if (pr_as_read_syntax)
  943.         os << "[\n";
  944.  
  945.       os << m;
  946.  
  947.       if (pr_as_read_syntax)
  948.         os << "]";
  949.  
  950.       return;
  951.     }
  952.  
  953.       int inc = nc;
  954.       if (total_width > max_width && user_pref.split_long_rows)
  955.     {
  956.       inc = max_width / column_width;
  957.       if (inc == 0)
  958.         inc++;
  959.     }
  960.  
  961.       if (pr_as_read_syntax)
  962.     {
  963.       for (int i = 0; i < nr; i++)
  964.         {
  965.           int col = 0;
  966.           while (col < nc)
  967.         {
  968.           int lim = col + inc < nc ? col + inc : nc;
  969.  
  970.           for (int j = col; j < lim; j++)
  971.             {
  972.               if (i == 0 && j == 0)
  973.             os << "[ ";
  974.               else
  975.             {
  976.               if (j > col && j < lim)
  977.                 os << ", ";
  978.               else
  979.                 os << "  ";
  980.             }
  981.  
  982.               pr_float (os, m.elem (i, j));
  983.             }
  984.  
  985.           col += inc;
  986.  
  987.           if (col >= nc)
  988.             {
  989.               if (i == nr - 1)
  990.             os << " ]";
  991.               else
  992.             os << ";\n";
  993.             }
  994.           else
  995.             os << " ...\n";
  996.         }
  997.         }
  998.     }
  999.       else
  1000.     {
  1001.       for (int col = 0; col < nc; col += inc)
  1002.         {
  1003.           int lim = col + inc < nc ? col + inc : nc;
  1004.  
  1005.           if (total_width > max_width && user_pref.split_long_rows)
  1006.         {
  1007.           if (col != 0)
  1008.             os << "\n";
  1009.  
  1010.           int num_cols = lim - col;
  1011.           if (num_cols == 1)
  1012.             os << " Column " << col + 1 << ":\n\n";
  1013.           else if (num_cols == 2)
  1014.             os << " Columns " << col + 1 << " and " << lim
  1015.               << ":\n\n";
  1016.           else
  1017.             os << " Columns " << col + 1 << " through " << lim
  1018.               << ":\n\n";
  1019.         }
  1020.  
  1021.           for (int i = 0; i < nr; i++)
  1022.         {
  1023.           for (int j = col; j < lim; j++)
  1024.             {
  1025.               os << "  ";
  1026.  
  1027.               pr_float (os, m.elem (i, j), fw);
  1028.             }
  1029.  
  1030.           os << "\n";
  1031.         }
  1032.         }
  1033.     }
  1034.     }
  1035. }
  1036.  
  1037. void
  1038. octave_print_internal (ostream& os, const Complex& c,
  1039.                int pr_as_read_syntax)
  1040. {
  1041.   if (plus_format)
  1042.     {
  1043.       if (c == 0.0)
  1044.     os << " ";
  1045.       else
  1046.     os << "+";
  1047.     }
  1048.   else
  1049.     {
  1050.       set_format (c);
  1051.       if (free_format)
  1052.     os << c;
  1053.       else
  1054.     pr_complex (os, c);
  1055.     }
  1056.  
  1057.   if (! pr_as_read_syntax)
  1058.     os << "\n";
  1059. }
  1060.  
  1061. void
  1062. octave_print_internal (ostream& os, const ComplexMatrix& cm,
  1063.                int pr_as_read_syntax)
  1064. {
  1065.   int nr = cm.rows ();
  1066.   int nc = cm.columns ();
  1067.  
  1068.   if (nr == 0 || nc == 0)
  1069.     print_empty_matrix (os, nr, nc, pr_as_read_syntax);
  1070.   else if (plus_format && ! pr_as_read_syntax)
  1071.     {
  1072.       for (int i = 0; i < nr; i++)
  1073.     {
  1074.       for (int j = 0; j < nc; j++)
  1075.         {
  1076.           if (j == 0)
  1077.         os << "  ";
  1078.  
  1079.           if (cm.elem (i, j) == 0.0)
  1080.         os << " ";
  1081.           else
  1082.         os << "+";
  1083.         }
  1084.       os << "\n";
  1085.     }
  1086.     }
  1087.   else
  1088.     {
  1089.       int r_fw, i_fw;
  1090.       set_format (cm, r_fw, i_fw);
  1091.       int column_width = i_fw + r_fw;
  1092.       column_width += bank_format ? 2 : 7;
  1093.       int total_width = nc * column_width;
  1094.       int max_width = terminal_columns ();
  1095.  
  1096.       if (pr_as_read_syntax)
  1097.     max_width -= 4;
  1098.  
  1099.       if (free_format)
  1100.     {
  1101.       if (pr_as_read_syntax)
  1102.         os << "[\n";
  1103.  
  1104.       os << cm;
  1105.  
  1106.       if (pr_as_read_syntax)
  1107.         os << "]";
  1108.  
  1109.       return;
  1110.     }
  1111.  
  1112.       int inc = nc;
  1113.       if (total_width > max_width && user_pref.split_long_rows)
  1114.     {
  1115.       inc = max_width / column_width;
  1116.       if (inc == 0)
  1117.         inc++;
  1118.     }
  1119.  
  1120.       if (pr_as_read_syntax)
  1121.     {
  1122.       for (int i = 0; i < nr; i++)
  1123.         {
  1124.           int col = 0;
  1125.           while (col < nc)
  1126.         {
  1127.           int lim = col + inc < nc ? col + inc : nc;
  1128.  
  1129.           for (int j = col; j < lim; j++)
  1130.             {
  1131.               if (i == 0 && j == 0)
  1132.             os << "[ ";
  1133.               else
  1134.             {
  1135.               if (j > col && j < lim)
  1136.                 os << ", ";
  1137.               else
  1138.                 os << "  ";
  1139.             }
  1140.  
  1141.               pr_complex (os, cm.elem (i, j));
  1142.             }
  1143.  
  1144.           col += inc;
  1145.  
  1146.           if (col >= nc)
  1147.             {
  1148.               if (i == nr - 1)
  1149.             os << " ]";
  1150.               else
  1151.             os << ";\n";
  1152.             }
  1153.           else
  1154.             os << " ...\n";
  1155.         }
  1156.         }
  1157.     }
  1158.       else
  1159.     {
  1160.       for (int col = 0; col < nc; col += inc)
  1161.         {
  1162.           int lim = col + inc < nc ? col + inc : nc;
  1163.  
  1164.           if (total_width > max_width && user_pref.split_long_rows)
  1165.         {
  1166.           if (col != 0)
  1167.             os << "\n";
  1168.  
  1169.           int num_cols = lim - col;
  1170.           if (num_cols == 1)
  1171.             os << " Column " << col + 1 << ":\n\n";
  1172.           else if (num_cols == 2)
  1173.             os << " Columns " << col + 1 << " and " << lim
  1174.               << ":\n\n";
  1175.           else
  1176.             os << " Columns " << col + 1 << " through " << lim
  1177.               << ":\n\n";
  1178.         }
  1179.  
  1180.           for (int i = 0; i < nr; i++)
  1181.         {
  1182.           for (int j = col; j < lim; j++)
  1183.             {
  1184.               os << "  ";
  1185.  
  1186.               pr_complex (os, cm.elem (i, j));
  1187.             }
  1188.           os << "\n";
  1189.         }
  1190.         }
  1191.     }
  1192.     }
  1193. }
  1194.  
  1195. void
  1196. octave_print_internal (ostream& os, const Range& r,
  1197.                int pr_as_read_syntax)
  1198. {
  1199.   double base = r.base ();
  1200.   double increment = r.inc ();
  1201.   double limit = r.limit ();
  1202.   int num_elem = r.nelem ();
  1203.  
  1204.   if (plus_format && ! pr_as_read_syntax)
  1205.     {
  1206.       os << "  ";
  1207.       for (int i = 0; i < num_elem; i++)
  1208.     {
  1209.       double val = base + i * increment;
  1210.       if (val == 0.0)
  1211.         os << " ";
  1212.       else
  1213.         os << "+";
  1214.     }
  1215.     }
  1216.   else
  1217.     {
  1218.       int fw;
  1219.       set_format (r, fw);
  1220.  
  1221.       if (pr_as_read_syntax)
  1222.     {
  1223.       
  1224.       if (free_format)
  1225.         {
  1226.           os << base << " : ";
  1227.           if (increment != 1.0)
  1228.         os << increment << " : ";
  1229.           os << limit;
  1230.         }
  1231.       else
  1232.         {
  1233.           pr_float (os, base, fw);
  1234.           os << " : ";
  1235.           if (increment != 1.0)
  1236.         {
  1237.           pr_float (os, increment, fw);
  1238.           os << " : ";
  1239.         }
  1240.           pr_float (os, limit, fw);
  1241.         }
  1242.     }
  1243.       else
  1244.     {
  1245.       int column_width = fw + 2;
  1246.       int total_width = num_elem * column_width;
  1247.       int max_width = terminal_columns ();
  1248.  
  1249.       if (free_format)
  1250.         {
  1251.           os << r;
  1252.           return;
  1253.         }
  1254.  
  1255.       int inc = num_elem;
  1256.       if (total_width > max_width && user_pref.split_long_rows)
  1257.         {
  1258.           inc = max_width / column_width;
  1259.           if (inc == 0)
  1260.         inc++;
  1261.         }
  1262.  
  1263.       int col = 0;
  1264.       while (col < num_elem)
  1265.         {
  1266.           int lim = col + inc < num_elem ? col + inc : num_elem;
  1267.  
  1268.           if (total_width > max_width && user_pref.split_long_rows)
  1269.         {
  1270.           if (col != 0)
  1271.             os << "\n";
  1272.  
  1273.           int num_cols = lim - col;
  1274.           if (num_cols == 1)
  1275.             os << " Column " << col + 1 << ":\n\n";
  1276.           else if (num_cols == 2)
  1277.             os << " Columns " << col + 1 << " and " << lim
  1278.               << ":\n\n";
  1279.           else
  1280.             os << " Columns " << col + 1 << " through " << lim
  1281.               << ":\n\n";
  1282.         }
  1283.  
  1284.           for (int i = col; i < lim; i++)
  1285.         {
  1286.           double val = base + i * increment;
  1287.           os << "  ";
  1288.           pr_float (os, val, fw);
  1289.         }
  1290.  
  1291.           os << "\n";
  1292.  
  1293.           col += inc;
  1294.         }
  1295.     }
  1296.     }
  1297. }
  1298.  
  1299. DEFUN ("disp", Fdisp, Sdisp, 1, 1,
  1300.   "disp (X): display value without name tag")
  1301. {
  1302.   Octave_object retval;
  1303.  
  1304.   int nargin = args.length ();
  1305.  
  1306.   if (nargin == 1)
  1307.     args(0).eval (1);
  1308.   else
  1309.     print_usage ("disp");
  1310.  
  1311.   return retval;
  1312. }
  1313.  
  1314. static void
  1315. init_format_state (void)
  1316. {
  1317.   free_format = 0;
  1318.   plus_format = 0;
  1319.   bank_format = 0;
  1320.   print_e = 0;
  1321.   print_big_e = 0;
  1322. }
  1323.  
  1324. static void
  1325. set_output_prec_and_fw (int prec, int fw)
  1326. {
  1327.   tree_constant *tmp = 0;
  1328.  
  1329.   tmp = new tree_constant ((double) prec);
  1330.   bind_builtin_variable ("output_precision", tmp);
  1331.  
  1332.   tmp = new tree_constant ((double) fw);
  1333.   bind_builtin_variable ("output_max_field_width", tmp);
  1334. }
  1335.  
  1336. void
  1337. set_format_style (int argc, char **argv)
  1338. {
  1339.   if (--argc > 0)
  1340.     {
  1341.       argv++;
  1342.       if (*argv[0])
  1343.     {
  1344.       if (strcmp (*argv, "short") == 0)
  1345.         {
  1346.           if (--argc > 0)
  1347.         {
  1348.           argv++;
  1349.           if (strcmp (*argv, "e") == 0)
  1350.             {
  1351.               init_format_state ();
  1352.               print_e = 1;
  1353.             }
  1354.           else if (strcmp (*argv, "E") == 0)
  1355.             {
  1356.               init_format_state ();
  1357.               print_e = 1;
  1358.               print_big_e = 1;
  1359.             }
  1360.           else
  1361.             {
  1362.               error ("format: unrecognized option `short %s'", *argv);
  1363.               return;
  1364.             }
  1365.         }
  1366.           else
  1367.         init_format_state ();
  1368.  
  1369.           set_output_prec_and_fw (3, 8);
  1370.         }
  1371.       else if (strcmp (*argv, "long") == 0)
  1372.         {
  1373.           if (--argc > 0)
  1374.         {
  1375.           argv++;
  1376.           if (strcmp (*argv, "e") == 0)
  1377.             {
  1378.               init_format_state ();
  1379.               print_e = 1;
  1380.             }
  1381.           else if (strcmp (*argv, "E") == 0)
  1382.             {
  1383.               init_format_state ();
  1384.               print_e = 1;
  1385.               print_big_e = 1;
  1386.             }
  1387.           else
  1388.             {
  1389.               error ("format: unrecognized option `long %s'", *argv);
  1390.               return;
  1391.             }
  1392.         }
  1393.           else
  1394.         init_format_state ();
  1395.  
  1396.           set_output_prec_and_fw (15, 24);
  1397.         }
  1398.       else if (strcmp (*argv, "hex") == 0)
  1399.         error ("format: format state `hex' not implemented yet");
  1400.       else if (strcmp (*argv, "+") == 0)
  1401.         {
  1402.           init_format_state ();
  1403.           plus_format = 1;
  1404.         }
  1405.       else if (strcmp (*argv, "bank") == 0)
  1406.         {
  1407.           init_format_state ();
  1408.           bank_format = 1;
  1409.         }
  1410.       else if (strcmp (*argv, "free") == 0)
  1411.         {
  1412.           init_format_state ();
  1413.           free_format = 1;
  1414.         }
  1415.       else if (strcmp (*argv, "none") == 0)
  1416.         {
  1417.           init_format_state ();
  1418.           free_format = 1;
  1419.         }
  1420.       else if (strcmp (*argv, "compact") == 0)
  1421.         error ("format: format state `compact' not implemented yet");
  1422.       else if (strcmp (*argv, "loose") == 0)
  1423.         error ("format: format state `loose' not implemented yet");
  1424.       else
  1425.         error ("format: unrecognized format state `%s'", *argv);
  1426.     }
  1427.       else
  1428.     usage ("format [format_state]");
  1429.     }
  1430.   else
  1431.     {
  1432.       init_format_state ();
  1433.       set_output_prec_and_fw (5, 10);
  1434.     }
  1435. }
  1436.  
  1437. DEFUN_TEXT ("format", Fformat, Sformat, -1, 1,
  1438.   "format [style]\n\
  1439. \n\
  1440. set output formatting style")
  1441. {
  1442.   Octave_object retval;
  1443.  
  1444.   DEFINE_ARGV("format");
  1445.  
  1446.   set_format_style (argc, argv);
  1447.  
  1448.   DELETE_ARGV;
  1449.  
  1450.   return retval;
  1451. }
  1452.  
  1453. /*
  1454. ;;; Local Variables: ***
  1455. ;;; mode: C++ ***
  1456. ;;; page-delimiter: "^/\\*" ***
  1457. ;;; End: ***
  1458. */
  1459.