# HG changeset patch # User John W. Eaton # Date 1517458911 21600 # Node ID 56f889d66b7c8c23bbad2a341061dac74744d98d # Parent 03546fb2490ffbcdc73515ef56a9433d4a816bcb move float_format container to setparate file * pr-flt-fmt.h, pr-flt-fmt.cc: New files, extracted from pr-output.h and pr-output.cc. (float_display_format): New class. * libinterp/corefcn/module.mk: Update. diff -r 03546fb2490f -r 56f889d66b7c libinterp/corefcn/module.mk --- a/libinterp/corefcn/module.mk Thu Feb 01 12:50:17 2018 -0800 +++ b/libinterp/corefcn/module.mk Wed Jan 31 22:21:51 2018 -0600 @@ -76,6 +76,7 @@ %reldir%/octave-default-image.h \ %reldir%/octave-link.h \ %reldir%/pager.h \ + %reldir%/pr-flt-fmt.h \ %reldir%/pr-output.h \ %reldir%/procstream.h \ %reldir%/sighandlers.h \ @@ -212,6 +213,7 @@ %reldir%/ordschur.cc \ %reldir%/pager.cc \ %reldir%/pinv.cc \ + %reldir%/pr-flt-fmt.cc \ %reldir%/pr-output.cc \ %reldir%/procstream.cc \ %reldir%/psi.cc \ diff -r 03546fb2490f -r 56f889d66b7c libinterp/corefcn/pr-flt-fmt.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/corefcn/pr-flt-fmt.cc Wed Jan 31 22:21:51 2018 -0600 @@ -0,0 +1,93 @@ +/* + +Copyright (C) 1993-2017 John W. Eaton + +This file is part of Octave. + +Octave is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Octave is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +. + +*/ + +#if defined (HAVE_CONFIG_H) +# include "config.h" +#endif + +#include "defun.h" +#include "error.h" +#include "pr-flt-fmt.h" +#include "variables.h" + +// The maximum field width for a number printed by the default output +// routines. +static int Voutput_max_field_width = 10; + +// The precision of the numbers printed by the default output +// routines. +static int Voutput_precision = 5; + +int +output_max_field_width (void) +{ + return Voutput_max_field_width; +} + +int +output_precision (void) +{ + return Voutput_precision; +} + +void +set_output_prec_and_fw (int prec, int fw) +{ + Voutput_precision = prec; + Voutput_max_field_width = fw; +} + +DEFUN (output_max_field_width, args, nargout, + doc: /* -*- texinfo -*- +@deftypefn {} {@var{val} =} output_max_field_width () +@deftypefnx {} {@var{old_val} =} output_max_field_width (@var{new_val}) +@deftypefnx {} {} output_max_field_width (@var{new_val}, "local") +Query or set the internal variable that specifies the maximum width +of a numeric output field. + +When called from inside a function with the @qcode{"local"} option, the +variable is changed locally for the function and any subroutines it calls. +The original variable value is restored when exiting the function. +@seealso{format, fixed_point_format, output_precision} +@end deftypefn */) +{ + return SET_INTERNAL_VARIABLE_WITH_LIMITS (output_max_field_width, 0, + std::numeric_limits::max ()); +} + +DEFUN (output_precision, args, nargout, + doc: /* -*- texinfo -*- +@deftypefn {} {@var{val} =} output_precision () +@deftypefnx {} {@var{old_val} =} output_precision (@var{new_val}) +@deftypefnx {} {} output_precision (@var{new_val}, "local") +Query or set the internal variable that specifies the minimum number of +significant figures to display for numeric output. + +When called from inside a function with the @qcode{"local"} option, the +variable is changed locally for the function and any subroutines it calls. +The original variable value is restored when exiting the function. +@seealso{format, fixed_point_format, output_max_field_width} +@end deftypefn */) +{ + return SET_INTERNAL_VARIABLE_WITH_LIMITS (output_precision, -1, + std::numeric_limits::max ()); +} diff -r 03546fb2490f -r 56f889d66b7c libinterp/corefcn/pr-flt-fmt.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libinterp/corefcn/pr-flt-fmt.h Wed Jan 31 22:21:51 2018 -0600 @@ -0,0 +1,165 @@ +/* + +Copyright (C) 1993-2017 John W. Eaton + +This file is part of Octave. + +Octave is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Octave is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +. + +*/ + +#if ! defined (octave_pr_flt_fmt_h) +#define octave_pr_flt_fmt_h 1 + +#include "octave-config.h" + +#include +#include + +class pr_engineering_float; +class pr_formatted_float; +class pr_rational_float; + +extern int output_max_field_width (void); + +extern int output_precision (void); + +extern void set_output_prec_and_fw (int prec, int fw); + +class +float_format +{ +public: + + float_format (int w = output_max_field_width (), + int p = output_precision (), int f = 0) + : fw (w), ex (0), prec (p), fmt (f), up (0), sp (0) { } + + float_format (int w, int e, int p, int f) + : fw (w), ex (e), prec (p), fmt (f), up (0), sp (0) { } + + float_format (const float_format& ff) = default; + + float_format& operator = (const float_format& ff) = default; + + ~float_format (void) = default; + + float_format& scientific (void) + { + fmt = std::ios::scientific; + return *this; + } + + float_format& fixed (void) + { + fmt = std::ios::fixed; + return *this; + } + + float_format& general (void) + { + fmt = 0; + return *this; + } + + float_format& uppercase (void) + { + up = std::ios::uppercase; + return *this; + } + + float_format& lowercase (void) + { + up = 0; + return *this; + } + + float_format& precision (int p) + { + prec = p; + return *this; + } + + float_format& width (int w) + { + fw = w; + return *this; + } + + float_format& trailing_zeros (bool tz = true) + + { + sp = (tz ? std::ios::showpoint : 0); + return *this; + } + + friend std::ostream& + operator << (std::ostream& os, const pr_engineering_float& pef); + + friend std::ostream& + operator << (std::ostream& os, const pr_formatted_float& pff); + + friend std::ostream& + operator << (std::ostream& os, const pr_rational_float& prf); + + // Field width. Zero means as wide as necessary. + int fw; + + // Exponent Field width. Zero means as wide as necessary. + int ex; + + // Precision. + int prec; + + // Format. + int fmt; + + // E or e. + int up; + + // Show trailing zeros. + int sp; +}; + +class +float_display_format +{ +public: + + float_display_format (void) = default; + + explicit float_display_format (const float_format& real_fmt, + const float_format& imag_fmt = float_format ()) + : m_real_fmt (real_fmt), m_imag_fmt (imag_fmt) + { } + + float_display_format (const float_display_format&) = default; + + float_display_format& operator = (const float_display_format&) = default; + + ~float_display_format (void) = default; + + float_format real_format (void) const { return m_real_fmt; } + + float_format imag_format (void) const { return m_imag_fmt; } + +private: + + float_format m_real_fmt; + + float_format m_imag_fmt; +}; + +#endif diff -r 03546fb2490f -r 56f889d66b7c libinterp/corefcn/pr-output.cc --- a/libinterp/corefcn/pr-output.cc Thu Feb 01 12:50:17 2018 -0800 +++ b/libinterp/corefcn/pr-output.cc Wed Jan 31 22:21:51 2018 -0600 @@ -52,6 +52,7 @@ #include "octave-preserve-stream-state.h" #include "pager.h" #include "parse.h" +#include "pr-flt-fmt.h" #include "pr-output.h" #include "sysdep.h" #include "unwind-prot.h" @@ -62,14 +63,6 @@ // 'format short'. static bool Vfixed_point_format = false; -// The maximum field width for a number printed by the default output -// routines. -static int Voutput_max_field_width = 10; - -// The precision of the numbers printed by the default output -// routines. -static int Voutput_precision = 5; - // TRUE means that the dimensions of empty objects should be printed // like this: x = [](2x0). bool Vprint_empty_dimensions = true; @@ -117,99 +110,6 @@ // TRUE means use an engineering format. static bool print_eng = false; -class pr_engineering_float; -class pr_formatted_float; -class pr_rational_float; - -static int -current_output_max_field_width (void) -{ - return Voutput_max_field_width; -} - -static int -current_output_precision (void) -{ - return Voutput_precision; -} - -class -float_format -{ -public: - - float_format (int w = current_output_max_field_width (), - int p = current_output_precision (), int f = 0) - : fw (w), ex (0), prec (p), fmt (f), up (0), sp (0) { } - - float_format (int w, int e, int p, int f) - : fw (w), ex (e), prec (p), fmt (f), up (0), sp (0) { } - - float_format (const float_format& ff) - : fw (ff.fw), ex (ff.ex), prec (ff.prec), fmt (ff.fmt), up (ff.up), - sp (ff.sp) { } - - float_format& operator = (const float_format& ff) - { - if (&ff != this) - { - fw = ff.fw; - ex = ff.ex; - prec = ff.prec; - fmt = ff.fmt; - up = ff.up; - sp = ff.sp; - } - - return *this; - } - - ~float_format (void) = default; - - float_format& scientific (void) { fmt = std::ios::scientific; return *this; } - float_format& fixed (void) { fmt = std::ios::fixed; return *this; } - float_format& general (void) { fmt = 0; return *this; } - - float_format& uppercase (void) { up = std::ios::uppercase; return *this; } - float_format& lowercase (void) { up = 0; return *this; } - - float_format& precision (int p) { prec = p; return *this; } - - float_format& width (int w) { fw = w; return *this; } - - float_format& trailing_zeros (bool tz = true) - { sp = (tz ? std::ios::showpoint : 0); return *this; } - - friend std::ostream& operator << (std::ostream& os, - const pr_engineering_float& pef); - - friend std::ostream& operator << (std::ostream& os, - const pr_formatted_float& pff); - - friend std::ostream& operator << (std::ostream& os, - const pr_rational_float& prf); - -private: - - // Field width. Zero means as wide as necessary. - int fw; - - // Exponent Field width. Zero means as wide as necessary. - int ex; - - // Precision. - int prec; - - // Format. - int fmt; - - // E or e. - int up; - - // Show trailing zeros. - int sp; -}; - static int calc_scale_exp (const int& x) { @@ -235,20 +135,24 @@ } static int -engineering_exponent (const double& x) +engineering_exponent (double x) { int ex = 0; + if (x != 0) { double absval = (x < 0.0 ? -x : x); int logabsval = static_cast (std::floor (log10 (absval))); + // Avoid using modulo function with negative arguments for // portability. See extended comment at calc_scale_exp + if (logabsval < 0.0) ex = logabsval - 2 + ((-logabsval + 2) % 3); else ex = logabsval - (logabsval % 3); } + return ex; } @@ -260,42 +164,33 @@ : static_cast (std::floor (log10 (x)))); } -class -pr_engineering_float +int +pr_engineering_float::exponent (void) const { -public: - - const float_format& f; - - double val; - - int exponent (void) const - { - return engineering_exponent (val); - } - - double mantissa (void) const - { - return val / std::pow (10.0, exponent ()); - } - - pr_engineering_float (const float_format& f_arg, double val_arg) - : f (f_arg), val (val_arg) { } -}; + return engineering_exponent (m_val); +} + +double +pr_engineering_float::mantissa (void) const +{ + return m_val / std::pow (10.0, exponent ()); +} std::ostream& operator << (std::ostream& os, const pr_engineering_float& pef) { octave::preserve_stream_state stream_state (os); - if (pef.f.fw >= 0) - os << std::setw (pef.f.fw - pef.f.ex); - - if (pef.f.prec >= 0) - os << std::setprecision (pef.f.prec); + float_format real_fmt = pef.m_ff; + + if (real_fmt.fw >= 0) + os << std::setw (real_fmt.fw - real_fmt.ex); + + if (real_fmt.prec >= 0) + os << std::setprecision (real_fmt.prec); os.flags (static_cast - (pef.f.fmt | pef.f.up | pef.f.sp)); + (real_fmt.fmt | real_fmt.up | real_fmt.sp)); os << pef.mantissa (); @@ -308,39 +203,28 @@ else os << std::setw (0) << "e+"; - os << std::setw (pef.f.ex - 2) << std::setfill ('0') << ex; + os << std::setw (real_fmt.ex - 2) << std::setfill ('0') << ex; return os; } -class -pr_formatted_float -{ -public: - - const float_format& f; - - double val; - - pr_formatted_float (const float_format& f_arg, double val_arg) - : f (f_arg), val (val_arg) { } -}; - std::ostream& operator << (std::ostream& os, const pr_formatted_float& pff) { octave::preserve_stream_state stream_state (os); - if (pff.f.fw >= 0) - os << std::setw (pff.f.fw); - - if (pff.f.prec >= 0) - os << std::setprecision (pff.f.prec); + float_format real_fmt = pff.m_ff; + + if (real_fmt.fw >= 0) + os << std::setw (real_fmt.fw); + + if (real_fmt.prec >= 0) + os << std::setprecision (real_fmt.prec); os.flags (static_cast - (pff.f.fmt | pff.f.up | pff.f.sp)); - - os << pff.val; + (real_fmt.fmt | real_fmt.up | real_fmt.sp)); + + os << pff.m_val; return os; } @@ -377,7 +261,7 @@ std::ostringstream buf2; buf2.flags (std::ios::fixed); - buf2 << std::setprecision (0) << static_cast(n); + buf2 << std::setprecision (0) << static_cast (n); s = buf2.str (); while (1) @@ -403,17 +287,17 @@ std::ostringstream buf; buf.flags (std::ios::fixed); - buf << std::setprecision (0) << static_cast(n) - << '/' << static_cast(d); + buf << std::setprecision (0) << static_cast (n) + << '/' << static_cast (d); m++; if (n < 0 && d < 0) { // Double negative, string can be two characters longer.. - if (buf.str ().length () > static_cast(len + 2)) + if (buf.str ().length () > static_cast (len + 2)) break; } - else if (buf.str ().length () > static_cast(len)) + else if (buf.str ().length () > static_cast (len)) break; if (std::abs (n) > std::numeric_limits::max () @@ -430,8 +314,8 @@ lastn = - lastn; std::ostringstream buf; buf.flags (std::ios::fixed); - buf << std::setprecision (0) << static_cast(lastn) - << '/' << static_cast(lastd); + buf << std::setprecision (0) << static_cast (lastn) + << '/' << static_cast (lastd); s = buf.str (); } } @@ -453,34 +337,23 @@ %! assert (err, 0, 4 * eps); */ -class -pr_rational_float -{ -public: - - const float_format& f; - - double val; - - pr_rational_float (const float_format& f_arg, double val_arg) - : f (f_arg), val (val_arg) { } -}; - std::ostream& operator << (std::ostream& os, const pr_rational_float& prf) { octave::preserve_stream_state stream_state (os); - int fw = (rat_string_len > 0 ? rat_string_len : prf.f.fw); - std::string s = rational_approx (prf.val, fw); + float_format real_fmt = prf.m_ff; + + int fw = (rat_string_len > 0 ? rat_string_len : real_fmt.fw); + std::string s = rational_approx (prf.m_val, fw); if (fw >= 0) os << std::setw (fw); os.flags (static_cast - (prf.f.fmt | prf.f.up | prf.f.sp)); - - if (fw > 0 && s.length () > static_cast(fw)) + (real_fmt.fmt | real_fmt.up | real_fmt.sp)); + + if (fw > 0 && s.length () > static_cast (fw)) os << '*'; else os << s; @@ -488,12 +361,8 @@ return os; } -// Current format for real numbers and the real part of complex -// numbers. -static float_format *curr_real_fmt = nullptr; - -// Current format for the imaginary part of complex numbers. -static float_format *curr_imag_fmt = nullptr; +// Current format for floating point numbers. +static float_display_format curr_float_display_fmt; static double pr_max_internal (const Matrix& m) @@ -555,12 +424,12 @@ // FIXME: it would be nice to share more code among these functions,.. -static void -set_real_format (int digits, bool inf_or_nan, bool int_only, int& fw) +static float_display_format +make_real_format (int digits, bool inf_or_nan, bool int_only, int& fw) { - static float_format fmt; - - int prec = Voutput_precision; + float_format fmt; + + int prec = output_precision (); int ld, rd; @@ -612,7 +481,7 @@ } if (! (rat_format || bank_format || hex_format || bit_format) - && (fw > Voutput_max_field_width || print_e || print_g || print_eng)) + && (fw > output_max_field_width () || print_e || print_g || print_eng)) { if (print_g) fmt = float_format (); @@ -647,17 +516,14 @@ else fmt = float_format (fw, rd, std::ios::fixed); - curr_real_fmt = &fmt; + return float_display_format (fmt); } -static void -set_format (double d, int& fw) +float_display_format +make_format (double d, int& fw) { - curr_real_fmt = nullptr; - curr_imag_fmt = nullptr; - if (free_format) - return; + return float_display_format (); bool inf_or_nan = (octave::math::isinf (d) || octave::math::isnan (d)); @@ -667,7 +533,13 @@ int digits = (inf_or_nan || d_abs == 0.0) ? 0 : num_digits (d_abs); - set_real_format (digits, inf_or_nan, int_only, fw); + return make_real_format (digits, inf_or_nan, int_only, fw); +} + +static void +set_format (double d, int& fw) +{ + curr_float_display_fmt = make_format (d, fw); } static inline void @@ -677,13 +549,13 @@ set_format (d, fw); } -static void -set_real_matrix_format (int x_max, int x_min, bool inf_or_nan, - int int_or_inf_or_nan, int& fw) +static float_display_format +make_real_matrix_format (int x_max, int x_min, bool inf_or_nan, + int int_or_inf_or_nan, int& fw) { - static float_format fmt; - - int prec = Voutput_precision; + float_format fmt; + + int prec = output_precision (); int ld, rd; @@ -766,7 +638,7 @@ if (! (rat_format || bank_format || hex_format || bit_format) && (print_e || print_eng || print_g - || (! Vfixed_point_format && fw > Voutput_max_field_width))) + || (! Vfixed_point_format && fw > output_max_field_width ()))) { if (print_g) fmt = float_format (); @@ -800,17 +672,14 @@ else fmt = float_format (fw, rd, std::ios::fixed); - curr_real_fmt = &fmt; + return float_display_format (fmt); } -static void -set_format (const Matrix& m, int& fw, double& scale) +float_display_format +make_format (const Matrix& m, int& fw, double& scale) { - curr_real_fmt = nullptr; - curr_imag_fmt = nullptr; - if (free_format) - return; + return float_display_format (); bool inf_or_nan = m.any_element_is_inf_or_nan (); @@ -827,17 +696,24 @@ scale = (x_max == 0 || int_or_inf_or_nan) ? 1.0 : std::pow (10.0, calc_scale_exp (x_max - 1)); - set_real_matrix_format (x_max, x_min, inf_or_nan, int_or_inf_or_nan, fw); + return make_real_matrix_format (x_max, x_min, inf_or_nan, + int_or_inf_or_nan, fw); } static void -set_complex_format (int x_max, int x_min, int r_x, bool inf_or_nan, - int int_only, int& r_fw, int& i_fw) +set_format (const Matrix& m, int& fw, double& scale) { - static float_format r_fmt; - static float_format i_fmt; - - int prec = Voutput_precision; + curr_float_display_fmt = make_format (m, fw, scale); +} + +static float_display_format +make_complex_format (int x_max, int x_min, int r_x, bool inf_or_nan, + int int_only, int& r_fw, int& i_fw) +{ + float_format r_fmt; + float_format i_fmt; + + int prec = output_precision (); int ld, rd; @@ -923,7 +799,7 @@ } if (! (rat_format || bank_format || hex_format || bit_format) - && (r_fw > Voutput_max_field_width || print_e || print_eng || print_g)) + && (r_fw > output_max_field_width () || print_e || print_eng || print_g)) { if (print_g) { @@ -979,18 +855,14 @@ i_fmt = float_format (i_fw, rd, std::ios::fixed); } - curr_real_fmt = &r_fmt; - curr_imag_fmt = &i_fmt; + return float_display_format (r_fmt, i_fmt); } -static void -set_format (const Complex& c, int& r_fw, int& i_fw) +float_display_format +make_format (const Complex& c, int& r_fw, int& i_fw) { - curr_real_fmt = nullptr; - curr_imag_fmt = nullptr; - if (free_format) - return; + return float_display_format (); double rp = c.real (); double ip = c.imag (); @@ -1022,7 +894,17 @@ x_min = r_x; } - set_complex_format (x_max, x_min, r_x, inf_or_nan, int_only, r_fw, i_fw); + return make_complex_format (x_max, x_min, r_x, inf_or_nan, int_only, + r_fw, i_fw); +} + +static void +set_format (const Complex& c, int& r_fw, int& i_fw) +{ + if (free_format) + curr_float_display_fmt = float_display_format (); + else + curr_float_display_fmt = make_format (c, r_fw, i_fw); } static inline void @@ -1032,15 +914,15 @@ set_format (c, r_fw, i_fw); } -static void -set_complex_matrix_format (int x_max, int x_min, int r_x_max, - int r_x_min, bool inf_or_nan, - int int_or_inf_or_nan, int& r_fw, int& i_fw) +static float_display_format +make_complex_matrix_format (int x_max, int x_min, int r_x_max, + int r_x_min, bool inf_or_nan, + int int_or_inf_or_nan, int& r_fw, int& i_fw) { - static float_format r_fmt; - static float_format i_fmt; - - int prec = Voutput_precision; + float_format r_fmt; + float_format i_fmt; + + int prec = output_precision (); int ld, rd; @@ -1139,7 +1021,7 @@ if (! (rat_format || bank_format || hex_format || bit_format) && (print_e || print_eng || print_g - || (! Vfixed_point_format && r_fw > Voutput_max_field_width))) + || (! Vfixed_point_format && r_fw > output_max_field_width ()))) { if (print_g) { @@ -1195,18 +1077,14 @@ i_fmt = float_format (i_fw, rd, std::ios::fixed); } - curr_real_fmt = &r_fmt; - curr_imag_fmt = &i_fmt; + return float_display_format (r_fmt, i_fmt); } -static void -set_format (const ComplexMatrix& cm, int& r_fw, int& i_fw, double& scale) +float_display_format +make_format (const ComplexMatrix& cm, int& r_fw, int& i_fw, double& scale) { - curr_real_fmt = nullptr; - curr_imag_fmt = nullptr; - if (free_format) - return; + return float_display_format (); Matrix rp = real (cm); Matrix ip = imag (cm); @@ -1238,16 +1116,26 @@ scale = (x_max == 0 || int_or_inf_or_nan) ? 1.0 : std::pow (10.0, calc_scale_exp (x_max - 1)); - set_complex_matrix_format (x_max, x_min, r_x_max, r_x_min, inf_or_nan, - int_or_inf_or_nan, r_fw, i_fw); + return make_complex_matrix_format (x_max, x_min, r_x_max, r_x_min, + inf_or_nan, int_or_inf_or_nan, + r_fw, i_fw); } static void -set_range_format (int x_max, int x_min, int all_ints, int& fw) +set_format (const ComplexMatrix& cm, int& r_fw, int& i_fw, double& scale) { - static float_format fmt; - - int prec = Voutput_precision; + if (free_format) + curr_float_display_fmt = float_display_format (); + else + curr_float_display_fmt = make_format (cm, r_fw, i_fw, scale); +} + +static float_display_format +make_range_format (int x_max, int x_min, int all_ints, int& fw) +{ + float_format fmt; + + int prec = output_precision (); int ld, rd; @@ -1322,7 +1210,7 @@ if (! (rat_format || bank_format || hex_format || bit_format) && (print_e || print_eng || print_g - || (! Vfixed_point_format && fw > Voutput_max_field_width))) + || (! Vfixed_point_format && fw > output_max_field_width ()))) { if (print_g) fmt = float_format (); @@ -1352,17 +1240,14 @@ else fmt = float_format (fw, rd, std::ios::fixed); - curr_real_fmt = &fmt; + return float_display_format (fmt); } -static void -set_format (const Range& r, int& fw, double& scale) +float_display_format +make_format (const Range& r, int& fw, double& scale) { - curr_real_fmt = nullptr; - curr_imag_fmt = nullptr; - if (free_format) - return; + return float_display_format (); double r_min = r.base (); double r_max = r.limit (); @@ -1386,7 +1271,13 @@ scale = (x_max == 0 || all_ints) ? 1.0 : std::pow (10.0, calc_scale_exp (x_max - 1)); - set_range_format (x_max, x_min, all_ints, fw); + return make_range_format (x_max, x_min, all_ints, fw); +} + +static void +set_format (const Range& r, int& fw, double& scale) +{ + curr_float_display_fmt = make_format (r, fw, scale); } union equiv @@ -1432,116 +1323,111 @@ while (0) static void -pr_any_float (const float_format *fmt, std::ostream& os, double d, int fw = 0) +pr_any_float (const float_format& fmt, std::ostream& os, double d, int fw = 0) { - if (fmt) + // Unless explicitly asked for, always print in big-endian format + // for hex and bit formats. + // + // {bit,hex}_format == 1: print big-endian + // {bit,hex}_format == 2: print native + + if (hex_format) { - // Unless explicitly asked for, always print in big-endian format - // for hex and bit formats. - // - // {bit,hex}_format == 1: print big-endian - // {bit,hex}_format == 2: print native - - if (hex_format) + octave::preserve_stream_state stream_state (os); + + equiv tmp; + tmp.d = d; + + // Unless explicitly asked for, always print in big-endian format. + + // FIXME: will bad things happen if we are + // interrupted before resetting the format flags and fill + // character? + + octave::mach_info::float_format flt_fmt = + octave::mach_info::native_float_format (); + + os.fill ('0'); + os.flags (std::ios::right | std::ios::hex); + + if (hex_format > 1 + || flt_fmt == octave::mach_info::flt_fmt_ieee_big_endian) { - octave::preserve_stream_state stream_state (os); - - equiv tmp; - tmp.d = d; - - // Unless explicitly asked for, always print in big-endian format. - - // FIXME: will bad things happen if we are - // interrupted before resetting the format flags and fill - // character? - - octave::mach_info::float_format flt_fmt = - octave::mach_info::native_float_format (); - - os.fill ('0'); - os.flags (std::ios::right | std::ios::hex); - - if (hex_format > 1 - || flt_fmt == octave::mach_info::flt_fmt_ieee_big_endian) + for (size_t i = 0; i < sizeof (double); i++) + os << std::setw (2) << static_cast (tmp.i[i]); + } + else + { + for (int i = sizeof (double) - 1; i >= 0; i--) + os << std::setw (2) << static_cast (tmp.i[i]); + } + } + else if (bit_format) + { + equiv tmp; + tmp.d = d; + + octave::mach_info::float_format flt_fmt = + octave::mach_info::native_float_format (); + + if (flt_fmt == octave::mach_info::flt_fmt_ieee_big_endian) + { + for (size_t i = 0; i < sizeof (double); i++) + PRINT_CHAR_BITS (os, tmp.i[i]); + } + else + { + if (bit_format > 1) { for (size_t i = 0; i < sizeof (double); i++) - os << std::setw (2) << static_cast (tmp.i[i]); + PRINT_CHAR_BITS_SWAPPED (os, tmp.i[i]); } else { for (int i = sizeof (double) - 1; i >= 0; i--) - os << std::setw (2) << static_cast (tmp.i[i]); - } - } - else if (bit_format) - { - equiv tmp; - tmp.d = d; - - octave::mach_info::float_format flt_fmt = - octave::mach_info::native_float_format (); - - if (flt_fmt == octave::mach_info::flt_fmt_ieee_big_endian) - { - for (size_t i = 0; i < sizeof (double); i++) PRINT_CHAR_BITS (os, tmp.i[i]); } - else - { - if (bit_format > 1) - { - for (size_t i = 0; i < sizeof (double); i++) - PRINT_CHAR_BITS_SWAPPED (os, tmp.i[i]); - } - else - { - for (int i = sizeof (double) - 1; i >= 0; i--) - PRINT_CHAR_BITS (os, tmp.i[i]); - } - } } - else if (octave::math::isna (d)) - { - octave::preserve_stream_state stream_state (os); - - if (fw > 0) - os << std::setw (fw) << "NA"; - else - os << "NA"; - } - else if (rat_format) - os << pr_rational_float (*fmt, d); - else if (octave::math::isinf (d)) - { - octave::preserve_stream_state stream_state (os); - - const char *s; - if (d < 0.0) - s = "-Inf"; - else - s = "Inf"; - - if (fw > 0) - os << std::setw (fw) << s; - else - os << s; - } - else if (octave::math::isnan (d)) - { - octave::preserve_stream_state stream_state (os); - - if (fw > 0) - os << std::setw (fw) << "NaN"; - else - os << "NaN"; - } - else if (print_eng) - os << pr_engineering_float (*fmt, d); + } + else if (octave::math::isna (d)) + { + octave::preserve_stream_state stream_state (os); + + if (fw > 0) + os << std::setw (fw) << "NA"; + else + os << "NA"; + } + else if (rat_format) + os << pr_rational_float (fmt, d); + else if (octave::math::isinf (d)) + { + octave::preserve_stream_state stream_state (os); + + const char *s; + if (d < 0.0) + s = "-Inf"; else - os << pr_formatted_float (*fmt, d); + s = "Inf"; + + if (fw > 0) + os << std::setw (fw) << s; + else + os << s; } + else if (octave::math::isnan (d)) + { + octave::preserve_stream_state stream_state (os); + + if (fw > 0) + os << std::setw (fw) << "NaN"; + else + os << "NaN"; + } + else if (print_eng) + os << pr_engineering_float (fmt, d); else - os << d; + os << pr_formatted_float (fmt, d); } static inline void @@ -1550,13 +1436,13 @@ if (Vfixed_point_format && ! print_g && scale != 1.0) d /= scale; - pr_any_float (curr_real_fmt, os, d, fw); + pr_any_float (curr_float_display_fmt.real_format (), os, d, fw); } static inline void pr_imag_float (std::ostream& os, double d, int fw = 0) { - pr_any_float (curr_imag_fmt, os, d, fw); + pr_any_float (curr_float_display_fmt.imag_format (), os, d, fw); } static void @@ -3683,13 +3569,6 @@ print_eng = false; } -static void -set_output_prec_and_fw (int prec, int fw) -{ - Voutput_precision = prec; - Voutput_max_field_width = fw; -} - static std::string format_string ("short"); static void @@ -4254,39 +4133,3 @@ { return SET_INTERNAL_VARIABLE (split_long_rows); } - -DEFUN (output_max_field_width, args, nargout, - doc: /* -*- texinfo -*- -@deftypefn {} {@var{val} =} output_max_field_width () -@deftypefnx {} {@var{old_val} =} output_max_field_width (@var{new_val}) -@deftypefnx {} {} output_max_field_width (@var{new_val}, "local") -Query or set the internal variable that specifies the maximum width -of a numeric output field. - -When called from inside a function with the @qcode{"local"} option, the -variable is changed locally for the function and any subroutines it calls. -The original variable value is restored when exiting the function. -@seealso{format, fixed_point_format, output_precision} -@end deftypefn */) -{ - return SET_INTERNAL_VARIABLE_WITH_LIMITS (output_max_field_width, 0, - std::numeric_limits::max ()); -} - -DEFUN (output_precision, args, nargout, - doc: /* -*- texinfo -*- -@deftypefn {} {@var{val} =} output_precision () -@deftypefnx {} {@var{old_val} =} output_precision (@var{new_val}) -@deftypefnx {} {} output_precision (@var{new_val}, "local") -Query or set the internal variable that specifies the minimum number of -significant figures to display for numeric output. - -When called from inside a function with the @qcode{"local"} option, the -variable is changed locally for the function and any subroutines it calls. -The original variable value is restored when exiting the function. -@seealso{format, fixed_point_format, output_max_field_width} -@end deftypefn */) -{ - return SET_INTERNAL_VARIABLE_WITH_LIMITS (output_precision, -1, - std::numeric_limits::max ()); -} diff -r 03546fb2490f -r 56f889d66b7c libinterp/corefcn/pr-output.h --- a/libinterp/corefcn/pr-output.h Thu Feb 01 12:50:17 2018 -0800 +++ b/libinterp/corefcn/pr-output.h Wed Jan 31 22:21:51 2018 -0600 @@ -30,6 +30,8 @@ #include "oct-cmplx.h" #include "oct-inttypes-fwd.h" +#include "pr-flt-fmt.h" + template class Array; class ComplexMatrix; class FloatComplexMatrix; @@ -262,6 +264,82 @@ octave_print_internal (std::ostream& os, const octave_value& ov, bool pr_as_read_syntax = false); +extern float_display_format +make_format (double d, int& fw); + +extern float_display_format +make_format (const Matrix& m, int& fw, double& scale); + +extern float_display_format +make_format (const Complex& c, int& r_fw, int& i_fw); + +extern float_display_format +make_format (const ComplexMatrix& cm, int& r_fw, int& i_fw, double& scale); + +extern float_display_format +make_format (const Range& r, int& fw, double& scale); + +class +pr_engineering_float +{ +public: + + const float_format m_ff; + + double m_val; + + int exponent (void) const; + + double mantissa (void) const; + + pr_engineering_float (const float_format& ff, double val) + : m_ff (ff), m_val (val) { } + + pr_engineering_float (const float_display_format& fdf, double val) + : m_ff (fdf.real_format ()), m_val (val) { } +}; + +class +pr_formatted_float +{ +public: + + const float_format m_ff; + + double m_val; + + pr_formatted_float (const float_format& ff, double val) + : m_ff (ff), m_val (val) { } + + pr_formatted_float (const float_display_format& fdf, double val) + : m_ff (fdf.real_format ()), m_val (val) { } +}; + +class +pr_rational_float +{ +public: + + const float_format m_ff; + + double m_val; + + pr_rational_float (const float_format& ff, double val) + : m_ff (ff), m_val (val) { } + + pr_rational_float (const float_display_format& fdf, double val) + : m_ff (fdf.real_format ()), m_val (val) { } +}; + +extern std::ostream& +operator << (std::ostream& os, const pr_engineering_float& pef); + +extern std::ostream& +operator << (std::ostream& os, const pr_formatted_float& pff); + +extern std::ostream& +operator << (std::ostream& os, const pr_rational_float& prf); + // TRUE means that the dimensions of empty objects should be printed // like this: x = [](2x0). extern bool Vprint_empty_dimensions;