1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1993-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29
30 #include <cmath>
31
32 #include <iomanip>
33 #include <limits>
34 #include <list>
35 #include <sstream>
36 #include <string>
37
38 #include "Array-util.h"
39 #include "CMatrix.h"
40 #include "Range.h"
41 #include "cmd-edit.h"
42 #include "dMatrix.h"
43 #include "lo-mappers.h"
44 #include "mach-info.h"
45 #include "oct-cmplx.h"
46 #include "oct-string.h"
47 #include "quit.h"
48
49 #include "Cell.h"
50 #include "defun.h"
51 #include "error.h"
52 #include "errwarn.h"
53 #include "ovl.h"
54 #include "oct-stream.h"
55 #include "octave-preserve-stream-state.h"
56 #include "pager.h"
57 #include "parse.h"
58 #include "pr-flt-fmt.h"
59 #include "pr-output.h"
60 #include "sysdep.h"
61 #include "unwind-prot.h"
62 #include "utils.h"
63 #include "variables.h"
64
65 // TRUE means use a scaled fixed point format for 'format long' and
66 // 'format short'.
67 static bool Vfixed_point_format = false;
68
69 // TRUE means that the dimensions of empty objects should be printed
70 // like this: x = [](2x0).
71 bool Vprint_empty_dimensions = true;
72
73 // TRUE means that the rows of big matrices should be split into
74 // smaller slices that fit on the screen.
75 static bool Vsplit_long_rows = true;
76
77 // TRUE means don't do any fancy formatting.
78 static bool free_format = false;
79
80 // TRUE means print plus sign for nonzero, blank for zero.
81 static bool plus_format = false;
82
83 // First char for > 0, second for < 0, third for == 0.
84 static std::string plus_format_chars = "+- ";
85
86 // TRUE means always print in a rational approximation
87 static bool rat_format = false;
88
89 // Used to force the length of the rational approximation string for Frats
90 static int rat_string_len = -1;
91
92 // TRUE means always print like dollars and cents.
93 static bool bank_format = false;
94
95 // TRUE means print data in hexadecimal format.
96 static int hex_format = 0;
97
98 // TRUE means print data in binary-bit-pattern format.
99 static int bit_format = 0;
100
101 // TRUE means don't put newlines around the column number headers.
102 bool Vcompact_format = false;
103
104 // TRUE means use an e format.
105 static bool print_e = false;
106
107 // TRUE means use a g format.
108 static bool print_g = false;
109
110 // TRUE means print uppercase E in exponent field and A-F in hex format.
111 static bool uppercase_format = false;
112
113 // TRUE means use an engineering format.
114 static bool print_eng = false;
115
116 static int
calc_scale_exp(const int & x)117 calc_scale_exp (const int& x)
118 {
119 if (! print_eng)
120 return x;
121 else
122 return x - 3*static_cast<int> (x/3);
123
124 // The expression above is equivalent to x - (x % 3).
125
126 // According to the ISO specification for C++ the modulo operator is
127 // compiler dependent if any of the arguments are negative. Since
128 // this function will need to work on negative arguments, and we want
129 // to avoid portability issues, we re-implement the modulo function to
130 // the desired behavior (truncation). There may be a gnulib replacement.
131
132 // ISO/IEC 14882:2003 : Programming languages -- C++. 5.6.4: ISO,
133 // IEC. 2003 . "the binary % operator yields the remainder from the
134 // division of the first expression by the second. .... If both
135 // operands are nonnegative then the remainder is nonnegative; if not,
136 // the sign of the remainder is implementation-defined".
137 }
138
139 template <typename T>
140 static inline int
engineering_exponent(T x)141 engineering_exponent (T x)
142 {
143 int ex = 0;
144
145 if (x != 0)
146 {
147 T absval = (x < 0 ? -x : x);
148 int logabsval = static_cast<int> (std::floor (log10 (absval)));
149
150 // Avoid using modulo function with negative arguments for
151 // portability. See extended comment at calc_scale_exp
152
153 if (logabsval < 0)
154 ex = logabsval - 2 + ((-logabsval + 2) % 3);
155 else
156 ex = logabsval - (logabsval % 3);
157 }
158
159 return ex;
160 }
161
162 template <typename T>
163 static inline int
num_digits(T x)164 num_digits (T x)
165 {
166 return 1 + (print_eng
167 ? engineering_exponent (x)
168 : static_cast<int> (std::floor (log10 (x))));
169 }
170
171 template <typename T>
172 int
exponent(void) const173 pr_engineering_float<T>::exponent (void) const
174 {
175 return engineering_exponent (m_val);
176 }
177
178 template <typename T>
179 T
mantissa(void) const180 pr_engineering_float<T>::mantissa (void) const
181 {
182 return m_val / std::pow (static_cast<T> (10), exponent ());
183 }
184
185 template <typename T>
186 std::ostream&
operator <<(std::ostream & os,const pr_engineering_float<T> & pef)187 operator << (std::ostream& os, const pr_engineering_float<T>& pef)
188 {
189 octave::preserve_stream_state stream_state (os);
190
191 float_format real_fmt = pef.m_ff;
192
193 if (real_fmt.width () >= 0)
194 os << std::setw (real_fmt.width () - real_fmt.exponent_width ());
195
196 if (real_fmt.precision () >= 0)
197 os << std::setprecision (real_fmt.precision ());
198
199 os.flags (real_fmt.format_flags ());
200
201 os << pef.mantissa ();
202
203 int ex = pef.exponent ();
204 if (ex < 0)
205 {
206 if (uppercase_format)
207 os << std::setw (0) << "E-";
208 else
209 os << std::setw (0) << "e-";
210 ex = -ex;
211 }
212 else
213 {
214 if (uppercase_format)
215 os << std::setw (0) << "E+";
216 else
217 os << std::setw (0) << "e+";
218 }
219
220 os << std::setw (real_fmt.exponent_width () - 2)
221 << std::setfill ('0') << ex;
222
223 return os;
224 }
225
226 template <typename T>
227 std::ostream&
operator <<(std::ostream & os,const pr_formatted_float<T> & pff)228 operator << (std::ostream& os, const pr_formatted_float<T>& pff)
229 {
230 octave::preserve_stream_state stream_state (os);
231
232 float_format real_fmt = pff.m_ff;
233
234 if (real_fmt.width () >= 0)
235 os << std::setw (real_fmt.width ());
236
237 if (real_fmt.precision () >= 0)
238 os << std::setprecision (real_fmt.precision ());
239
240 os.flags (real_fmt.format_flags ());
241
242 os << pff.m_val;
243
244 return os;
245 }
246
247 template <typename T>
248 std::ostream&
operator <<(std::ostream & os,const pr_rational_float<T> & prf)249 operator << (std::ostream& os, const pr_rational_float<T>& prf)
250 {
251 octave::preserve_stream_state stream_state (os);
252
253 float_format real_fmt = prf.m_ff;
254 bool have_neg_sign = prf.m_val < 0;
255
256 int fw = (rat_string_len > 0 ? rat_string_len : real_fmt.width ());
257 std::string s;
258
259 if (have_neg_sign)
260 s = rational_approx (prf.m_val, fw);
261 else
262 s = rational_approx (prf.m_val, fw-1);
263
264 if (fw >= 0)
265 os << std::setw (fw);
266
267 os.flags (real_fmt.format_flags ());
268
269 if (s == "0")
270 s = '*';
271 else if (fw > 0)
272 {
273 if (s.find ('/') != std::string::npos)
274 {
275 if (s.length () > (static_cast<unsigned int> (fw)))
276 s = '*';
277 }
278 else
279 {
280 if (have_neg_sign)
281 {
282 if (s.length () > (static_cast<unsigned int> (fw) - 2))
283 s = '*';
284 }
285 else
286 {
287 if (s.length () > (static_cast<unsigned int> (fw) - 3))
288 s = '*';
289 }
290 }
291 }
292
293 os << s;
294
295 return os;
296 }
297
298 template <typename T>
299 static inline T
pr_max_internal(const MArray<T> & m)300 pr_max_internal (const MArray<T>& m)
301 {
302 // We expect a 2-d array.
303 assert (m.ndims () == 2);
304
305 octave_idx_type nr = m.rows ();
306 octave_idx_type nc = m.columns ();
307
308 T result = std::numeric_limits<T>::lowest ();
309
310 bool all_inf_or_nan = true;
311
312 for (octave_idx_type j = 0; j < nc; j++)
313 for (octave_idx_type i = 0; i < nr; i++)
314 {
315 T val = m(i,j);
316 if (! octave::math::isfinite (val))
317 continue;
318
319 all_inf_or_nan = false;
320
321 if (val > result)
322 result = val;
323 }
324
325 if (all_inf_or_nan)
326 result = 0;
327
328 return result;
329 }
330
331 template <typename T>
332 static inline T
pr_min_internal(const MArray<T> & m)333 pr_min_internal (const MArray<T>& m)
334 {
335 octave_idx_type nr = m.rows ();
336 octave_idx_type nc = m.columns ();
337
338 T result = std::numeric_limits<T>::max ();
339
340 bool all_inf_or_nan = true;
341
342 for (octave_idx_type j = 0; j < nc; j++)
343 for (octave_idx_type i = 0; i < nr; i++)
344 {
345 T val = m(i,j);
346 if (! octave::math::isfinite (val))
347 continue;
348
349 all_inf_or_nan = false;
350
351 if (val < result)
352 result = val;
353 }
354
355 if (all_inf_or_nan)
356 result = 0;
357
358 return result;
359 }
360
361 template <typename>
362 struct pr_output_traits
363 {
364 static const int digits10;
365 static const int max_field_width;
366 };
367
368 template <>
369 struct pr_output_traits<double>
370 {
371 static const int digits10;
372 static const int max_field_width;
373 };
374
375 const int pr_output_traits<double>::digits10 = 16;
376 const int pr_output_traits<double>::max_field_width = 21;
377
378 template <>
379 struct pr_output_traits<float>
380 {
381 static const int digits10;
382 static const int max_field_width;
383 };
384
385 const int pr_output_traits<float>::digits10 = 8;
386 const int pr_output_traits<float>::max_field_width = 13;
387
388 // FIXME: it would be nice to share more code among these functions,..
389
390 // Works for double and float.
391
392 template <typename T>
393 static inline float_display_format
make_real_format(int digits,bool inf_or_nan,bool int_only)394 make_real_format (int digits, bool inf_or_nan, bool int_only)
395 {
396 float_format fmt;
397
398 int prec = std::min (output_precision (), pr_output_traits<T>::digits10);
399
400 int fw = 0, ld = 0, rd = 0;
401
402 if (rat_format)
403 {
404 fw = 0;
405 rd = 0;
406 }
407 else if (bank_format)
408 {
409 fw = (digits < 0 ? 4 : digits + 3);
410 if (inf_or_nan)
411 fw = 3;
412 rd = 2;
413 }
414 else if (hex_format)
415 {
416 fw = 2 * sizeof (T);
417 rd = 0;
418 }
419 else if (bit_format)
420 {
421 fw = 8 * sizeof (T);
422 rd = 0;
423 }
424 else if (inf_or_nan)
425 {
426 fw = 3;
427 }
428 else if (int_only)
429 {
430 fw = digits;
431 ld = digits;
432 rd = 0;
433 }
434 else
435 {
436 if (digits > 0)
437 {
438 ld = digits;
439 rd = (prec > digits ? prec - digits : prec);
440 }
441 else if (digits < 0)
442 {
443 ld = 1;
444 rd = (prec > digits ? prec - digits : prec);
445 }
446 else
447 {
448 ld = 1;
449 rd = (prec > digits ? prec - 1 : prec);
450 }
451
452 fw = ld + 1 + rd;
453 }
454
455 if (! (rat_format || bank_format || hex_format || bit_format)
456 && (print_e || print_g || print_eng
457 || ld + rd > pr_output_traits<T>::digits10
458 || fw > pr_output_traits<T>::max_field_width
459 || ld + rd > (1.5 * prec)))
460 {
461 if (print_g)
462 fmt = float_format (prec, prec);
463 else
464 {
465 // e+ddd
466 int ex = 5;
467
468 if (print_eng)
469 {
470 // -ddd.
471 fw = 1 + prec + ex;
472 if (inf_or_nan)
473 {
474 fw = 3;
475 ex = 0;
476 }
477 fmt = float_format (fw, ex, prec - 1, std::ios::fixed);
478 }
479 else
480 {
481 // -d.
482 fw = prec + ex;
483 if (inf_or_nan)
484 {
485 fw = 3;
486 ex = 0;
487 }
488 fmt = float_format (fw, ex, prec - 1, std::ios::scientific);
489 }
490 }
491 }
492 else if (! bank_format && (inf_or_nan || int_only))
493 fmt = float_format (fw, ld);
494 else
495 fmt = float_format (fw, rd, std::ios::fixed);
496
497 if (uppercase_format)
498 fmt.uppercase ();
499
500 return float_display_format (fmt);
501 }
502
503 // Works for double and float.
504
505 template <typename T>
506 float_display_format
make_scalar_format(const T & val)507 make_scalar_format (const T& val)
508 {
509 if (free_format)
510 return float_display_format ();
511
512 bool inf_or_nan = (octave::math::isinf (val) || octave::math::isnan (val));
513
514 bool int_only = (! inf_or_nan && octave::math::x_nint (val) == val);
515
516 T val_abs = (val < 0 ? -val : val);
517
518 int digits = (inf_or_nan || val_abs == 0) ? 0 : num_digits (val_abs);
519
520 return make_real_format<T> (digits, inf_or_nan, int_only);
521 }
522
523 template <>
524 float_display_format
make_format(const double & d)525 make_format (const double& d)
526 {
527 return make_scalar_format (d);
528 }
529
530 template <>
531 float_display_format
make_format(const float & f)532 make_format (const float& f)
533 {
534 return make_scalar_format (f);
535 }
536
537 template <typename T>
538 static inline float_display_format
make_real_matrix_format(int x_max,int x_min,bool inf_or_nan,int int_or_inf_or_nan)539 make_real_matrix_format (int x_max, int x_min, bool inf_or_nan,
540 int int_or_inf_or_nan)
541 {
542 T scale = ((x_max == 0 || int_or_inf_or_nan)
543 ? 1 : std::pow (10.0, calc_scale_exp (x_max - 1)));
544
545 float_format fmt;
546
547 int prec = std::min (output_precision (), pr_output_traits<T>::digits10);
548
549 int fw = 0, ld = 0, rd = 0;
550
551 if (rat_format)
552 {
553 fw = 9;
554 rd = 0;
555 }
556 else if (bank_format)
557 {
558 int digits = (x_max > x_min ? x_max : x_min);
559 fw = (digits <= 0 ? 5 : digits + 4);
560 rd = 2;
561 }
562 else if (hex_format)
563 {
564 fw = 2 * sizeof (T);
565 rd = 0;
566 }
567 else if (bit_format)
568 {
569 fw = 8 * sizeof (T);
570 rd = 0;
571 }
572 else if (Vfixed_point_format && ! print_g)
573 {
574 rd = prec - 1;
575 fw = rd + 3;
576 if (inf_or_nan && fw < 4)
577 fw = 4;
578 }
579 else if (int_or_inf_or_nan)
580 {
581 int digits = (x_max > x_min ? x_max : x_min);
582 fw = (digits <= 0 ? 2 : digits + 1);
583 if (inf_or_nan && fw < 4)
584 fw = 4;
585 rd = fw;
586 }
587 else
588 {
589 int ld_max, rd_max;
590 if (x_max > 0)
591 {
592 ld_max = x_max;
593 rd_max = (prec > x_max ? prec - x_max : prec);
594 x_max++;
595 }
596 else if (x_max < 0)
597 {
598 ld_max = 1;
599 rd_max = (prec > x_max ? prec - x_max : prec);
600 x_max = -x_max + 1;
601 }
602 else
603 {
604 ld_max = 1;
605 rd_max = (prec > 1 ? prec - 1 : prec);
606 x_max = 1;
607 }
608
609 int ld_min, rd_min;
610 if (x_min > 0)
611 {
612 ld_min = x_min;
613 rd_min = (prec > x_min ? prec - x_min : prec);
614 x_min++;
615 }
616 else if (x_min < 0)
617 {
618 ld_min = 1;
619 rd_min = (prec > x_min ? prec - x_min : prec);
620 x_min = -x_min + 1;
621 }
622 else
623 {
624 ld_min = 1;
625 rd_min = (prec > 1 ? prec - 1 : prec);
626 x_min = 1;
627 }
628
629 ld = (ld_max > ld_min ? ld_max : ld_min);
630 rd = (rd_max > rd_min ? rd_max : rd_min);
631
632 fw = 1 + ld + 1 + rd;
633 if (inf_or_nan && fw < 4)
634 fw = 4;
635 }
636
637 if (! (rat_format || bank_format || hex_format || bit_format)
638 && (print_e || print_eng || print_g
639 || (! Vfixed_point_format
640 && (ld + rd > pr_output_traits<T>::digits10
641 || fw > pr_output_traits<T>::max_field_width
642 || ld + rd > (1.5 * prec)))))
643 {
644 if (print_g)
645 fmt = float_format (prec+6, prec);
646 else
647 {
648 int ex = 4;
649 if (x_max > 100 || x_min > 100)
650 ex++;
651
652 if (print_eng)
653 {
654 fw = 4 + prec + ex;
655 if (inf_or_nan && fw < 6)
656 fw = 6;
657 fmt = float_format (fw, ex, prec - 1, std::ios::fixed);
658 }
659 else
660 {
661 fw = 2 + prec + ex;
662 if (inf_or_nan && fw < 4)
663 fw = 4;
664 fmt = float_format (fw, prec - 1, std::ios::scientific);
665 }
666 }
667 }
668 else if (! bank_format && int_or_inf_or_nan)
669 fmt = float_format (fw, rd);
670 else
671 fmt = float_format (fw, rd, std::ios::fixed);
672
673 if (uppercase_format)
674 fmt.uppercase ();
675
676 return float_display_format (scale, fmt);
677 }
678
679 template <typename MT>
680 static inline float_display_format
make_matrix_format(const MT & m)681 make_matrix_format (const MT& m)
682 {
683 assert (m.ndims () == 2);
684
685 if (free_format)
686 return float_display_format ();
687
688 bool inf_or_nan = m.any_element_is_inf_or_nan ();
689
690 bool int_or_inf_or_nan = m.all_elements_are_int_or_inf_or_nan ();
691
692 MT m_abs = m.abs ();
693
694 typedef typename MT::element_type ELT_T;
695
696 ELT_T max_abs = pr_max_internal (m_abs);
697 ELT_T min_abs = pr_min_internal (m_abs);
698
699 int x_max = (max_abs == 0 ? 0 : num_digits (max_abs));
700
701 int x_min = (min_abs == 0 ? 0 : num_digits (min_abs));
702
703 return make_real_matrix_format<ELT_T> (x_max, x_min, inf_or_nan,
704 int_or_inf_or_nan);
705 }
706
707 template <>
708 float_display_format
make_format(const Matrix & m)709 make_format (const Matrix& m)
710 {
711 return make_matrix_format (m);
712 }
713
714 template <>
715 float_display_format
make_format(const FloatMatrix & m)716 make_format (const FloatMatrix& m)
717 {
718 return make_matrix_format (m);
719 }
720
721 template <typename T>
722 static inline float_display_format
make_complex_format(int x_max,int x_min,int r_x,bool inf_or_nan,int int_only)723 make_complex_format (int x_max, int x_min, int r_x,
724 bool inf_or_nan, int int_only)
725 {
726 float_format r_fmt;
727 float_format i_fmt;
728
729 int prec = std::min (output_precision (), pr_output_traits<T>::digits10);
730
731 int i_fw = 0, r_fw = 0, ld = 0, rd = 0;
732
733 if (rat_format)
734 {
735 i_fw = 0;
736 r_fw = 0;
737 rd = 0;
738 }
739 else if (bank_format)
740 {
741 int digits = r_x;
742 i_fw = 0;
743 r_fw = (digits <= 0 ? 5 : digits + 4);
744 rd = 2;
745 }
746 else if (hex_format)
747 {
748 r_fw = 2 * sizeof (T);
749 i_fw = 2 * sizeof (T);
750 rd = 0;
751 }
752 else if (bit_format)
753 {
754 r_fw = 8 * sizeof (T);
755 i_fw = 8 * sizeof (T);
756 rd = 0;
757 }
758 else if (inf_or_nan || int_only)
759 {
760 int digits = (x_max > x_min ? x_max : x_min);
761 i_fw = (digits <= 0 ? 1 : digits);
762 r_fw = i_fw + 1;
763 if (inf_or_nan && i_fw < 3)
764 {
765 i_fw = 3;
766 r_fw = 4;
767 }
768
769 if (int_only)
770 {
771 ld = digits;
772 rd = 0;
773 }
774 }
775 else
776 {
777 int ld_max, rd_max;
778 if (x_max > 0)
779 {
780 ld_max = x_max;
781 rd_max = (prec > x_max ? prec - x_max : prec);
782 x_max++;
783 }
784 else if (x_max < 0)
785 {
786 ld_max = 1;
787 rd_max = (prec > x_max ? prec - x_max : prec);
788 x_max = -x_max + 1;
789 }
790 else
791 {
792 ld_max = 1;
793 rd_max = (prec > 1 ? prec - 1 : prec);
794 x_max = 1;
795 }
796
797 int ld_min, rd_min;
798 if (x_min > 0)
799 {
800 ld_min = x_min;
801 rd_min = (prec > x_min ? prec - x_min : prec);
802 x_min++;
803 }
804 else if (x_min < 0)
805 {
806 ld_min = 1;
807 rd_min = (prec > x_min ? prec - x_min : prec);
808 x_min = -x_min + 1;
809 }
810 else
811 {
812 ld_min = 1;
813 rd_min = (prec > 1 ? prec - 1 : prec);
814 x_min = 1;
815 }
816
817 ld = (ld_max > ld_min ? ld_max : ld_min);
818 rd = (rd_max > rd_min ? rd_max : rd_min);
819
820 i_fw = ld + 1 + rd;
821 r_fw = i_fw + 1;
822 }
823
824 if (! (rat_format || bank_format || hex_format || bit_format)
825 && (print_e || print_eng || print_g
826 || ld + rd > pr_output_traits<T>::digits10
827 || r_fw > pr_output_traits<T>::max_field_width
828 || i_fw > pr_output_traits<T>::max_field_width
829 || ld + rd > (1.5 * prec)))
830 {
831 if (print_g)
832 {
833 int width = prec + 6;
834 r_fmt = float_format (width, prec);
835 i_fmt = float_format (width, prec);
836 }
837 else
838 {
839 int ex = 4;
840 if (x_max > 100 || x_min > 100)
841 ex++;
842
843 if (print_eng)
844 {
845 i_fw = 3 + prec + ex;
846 r_fw = i_fw + 1;
847 if (inf_or_nan && i_fw < 5)
848 {
849 i_fw = 5;
850 r_fw = 6;
851 }
852 r_fmt = float_format (r_fw, ex, prec - 1, std::ios::fixed);
853 i_fmt = float_format (i_fw, ex, prec - 1, std::ios::fixed);
854 }
855 else
856 {
857 i_fw = 1 + prec + ex;
858 r_fw = i_fw + 1;
859 if (inf_or_nan && i_fw < 3)
860 {
861 i_fw = 3;
862 r_fw = 4;
863 }
864 r_fmt = float_format (r_fw, prec - 1, std::ios::scientific);
865 i_fmt = float_format (i_fw, prec - 1, std::ios::scientific);
866 }
867 }
868
869 if (uppercase_format)
870 {
871 r_fmt.uppercase ();
872 i_fmt.uppercase ();
873 }
874 }
875 else if (! bank_format && (inf_or_nan || int_only))
876 {
877 r_fmt = float_format (r_fw, ld);
878 i_fmt = float_format (i_fw, ld);
879 }
880 else
881 {
882 r_fmt = float_format (r_fw, rd, std::ios::fixed);
883 i_fmt = float_format (i_fw, rd, std::ios::fixed);
884 }
885
886 return float_display_format (r_fmt, i_fmt);
887 }
888
889 template <typename T>
890 float_display_format
make_complex_scalar_format(const std::complex<T> & c)891 make_complex_scalar_format (const std::complex<T>& c)
892 {
893 if (free_format)
894 return float_display_format ();
895
896 T rp = c.real ();
897 T ip = c.imag ();
898
899 bool inf_or_nan = (octave::math::isinf (c) || octave::math::isnan (c));
900
901 bool int_only = (octave::math::x_nint (rp) == rp
902 && octave::math::x_nint (ip) == ip);
903
904 T r_abs = (rp < 0 ? -rp : rp);
905 T i_abs = (ip < 0 ? -ip : ip);
906
907 int r_x = (! octave::math::isfinite (rp)
908 || r_abs == 0) ? 0 : num_digits (r_abs);
909
910 int i_x = (! octave::math::isfinite (ip)
911 || i_abs == 0) ? 0 : num_digits (i_abs);
912
913 int x_max, x_min;
914
915 if (r_x > i_x)
916 {
917 x_max = r_x;
918 x_min = i_x;
919 }
920 else
921 {
922 x_max = i_x;
923 x_min = r_x;
924 }
925
926 return make_complex_format<T> (x_max, x_min, r_x, inf_or_nan, int_only);
927 }
928
929 template <>
930 float_display_format
make_format(const std::complex<double> & c)931 make_format (const std::complex<double>& c)
932 {
933 return make_complex_scalar_format (c);
934 }
935
936 template <>
937 float_display_format
make_format(const std::complex<float> & fc)938 make_format (const std::complex<float>& fc)
939 {
940 return make_complex_scalar_format (fc);
941 }
942
943 template <typename T>
944 static inline 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)945 make_complex_matrix_format (int x_max, int x_min, int r_x_max,
946 int r_x_min, bool inf_or_nan,
947 int int_or_inf_or_nan)
948 {
949 T scale = ((x_max == 0 || int_or_inf_or_nan)
950 ? 1 : std::pow (10.0, calc_scale_exp (x_max - 1)));
951
952 float_format r_fmt;
953 float_format i_fmt;
954
955 int prec = std::min (output_precision (), pr_output_traits<T>::digits10);
956
957 int i_fw = 0, r_fw = 0, ld = 0, rd = 0;
958
959 if (rat_format)
960 {
961 i_fw = 9;
962 r_fw = 9;
963 rd = 0;
964 }
965 else if (bank_format)
966 {
967 int digits = (r_x_max > r_x_min ? r_x_max : r_x_min);
968 i_fw = 0;
969 r_fw = (digits <= 0 ? 5 : digits + 4);
970 rd = 2;
971 }
972 else if (hex_format)
973 {
974 r_fw = 2 * sizeof (T);
975 i_fw = 2 * sizeof (T);
976 rd = 0;
977 }
978 else if (bit_format)
979 {
980 r_fw = 8 * sizeof (T);
981 i_fw = 8 * sizeof (T);
982 rd = 0;
983 }
984 else if (Vfixed_point_format && ! print_g)
985 {
986 rd = prec - 1;
987 i_fw = rd + 1;
988 r_fw = i_fw + 2;
989 if (inf_or_nan && i_fw < 3)
990 {
991 i_fw = 3;
992 r_fw = 4;
993 }
994 }
995 else if (int_or_inf_or_nan)
996 {
997 int digits = (x_max > x_min ? x_max : x_min);
998 i_fw = (digits <= 0 ? 1 : digits);
999 r_fw = i_fw + 1;
1000 if (inf_or_nan && i_fw < 3)
1001 {
1002 i_fw = 3;
1003 r_fw = 4;
1004 }
1005 rd = r_fw;
1006 }
1007 else
1008 {
1009 int ld_max, rd_max;
1010 if (x_max > 0)
1011 {
1012 ld_max = x_max;
1013 rd_max = (prec > x_max ? prec - x_max : prec);
1014 x_max++;
1015 }
1016 else if (x_max < 0)
1017 {
1018 ld_max = 1;
1019 rd_max = (prec > x_max ? prec - x_max : prec);
1020 x_max = -x_max + 1;
1021 }
1022 else
1023 {
1024 ld_max = 1;
1025 rd_max = (prec > 1 ? prec - 1 : prec);
1026 x_max = 1;
1027 }
1028
1029 int ld_min, rd_min;
1030 if (x_min > 0)
1031 {
1032 ld_min = x_min;
1033 rd_min = (prec > x_min ? prec - x_min : prec);
1034 x_min++;
1035 }
1036 else if (x_min < 0)
1037 {
1038 ld_min = 1;
1039 rd_min = (prec > x_min ? prec - x_min : prec);
1040 x_min = -x_min + 1;
1041 }
1042 else
1043 {
1044 ld_min = 1;
1045 rd_min = (prec > 1 ? prec - 1 : prec);
1046 x_min = 1;
1047 }
1048
1049 ld = (ld_max > ld_min ? ld_max : ld_min);
1050 rd = (rd_max > rd_min ? rd_max : rd_min);
1051
1052 i_fw = ld + 1 + rd;
1053 r_fw = i_fw + 1;
1054 if (inf_or_nan && i_fw < 3)
1055 {
1056 i_fw = 3;
1057 r_fw = 4;
1058 }
1059 }
1060
1061 if (! (rat_format || bank_format || hex_format || bit_format)
1062 && (print_e || print_eng || print_g
1063 || (! Vfixed_point_format
1064 && (ld + rd > pr_output_traits<T>::digits10
1065 || r_fw > pr_output_traits<T>::max_field_width
1066 || i_fw > pr_output_traits<T>::max_field_width
1067 || ld + rd > (1.5 * prec)))))
1068 {
1069 if (print_g)
1070 {
1071 int width = prec + 6;
1072 r_fmt = float_format (width, prec);
1073 i_fmt = float_format (width, prec);
1074 }
1075 else
1076 {
1077 int ex = 4;
1078 if (x_max > 100 || x_min > 100)
1079 ex++;
1080
1081 if (print_eng)
1082 {
1083 i_fw = 3 + prec + ex;
1084 r_fw = i_fw + 1;
1085 if (inf_or_nan && i_fw < 5)
1086 {
1087 i_fw = 5;
1088 r_fw = 6;
1089 }
1090 r_fmt = float_format (r_fw, ex, prec - 1, std::ios::fixed);
1091 i_fmt = float_format (i_fw, ex, prec - 1, std::ios::fixed);
1092 }
1093 else
1094 {
1095 i_fw = 1 + prec + ex;
1096 r_fw = i_fw + 1;
1097 if (inf_or_nan && i_fw < 3)
1098 {
1099 i_fw = 3;
1100 r_fw = 4;
1101 }
1102 r_fmt = float_format (r_fw, prec - 1, std::ios::scientific);
1103 i_fmt = float_format (i_fw, prec - 1, std::ios::scientific);
1104 }
1105 }
1106
1107 if (uppercase_format)
1108 {
1109 r_fmt.uppercase ();
1110 i_fmt.uppercase ();
1111 }
1112 }
1113 else if (! bank_format && int_or_inf_or_nan)
1114 {
1115 r_fmt = float_format (r_fw, rd);
1116 i_fmt = float_format (i_fw, rd);
1117 }
1118 else
1119 {
1120 r_fmt = float_format (r_fw, rd, std::ios::fixed);
1121 i_fmt = float_format (i_fw, rd, std::ios::fixed);
1122 }
1123
1124 return float_display_format (scale, r_fmt, i_fmt);
1125 }
1126
1127 template <typename CMT>
1128 static inline float_display_format
make_complex_matrix_format(const CMT & cm)1129 make_complex_matrix_format (const CMT& cm)
1130 {
1131 if (free_format)
1132 return float_display_format ();
1133
1134 typedef typename CMT::real_matrix_type RMT;
1135 typedef typename CMT::real_elt_type ELT_T;
1136
1137 RMT rp = real (cm);
1138 RMT ip = imag (cm);
1139
1140 bool inf_or_nan = cm.any_element_is_inf_or_nan ();
1141
1142 bool int_or_inf_or_nan = (rp.all_elements_are_int_or_inf_or_nan ()
1143 && ip.all_elements_are_int_or_inf_or_nan ());
1144
1145 RMT r_m_abs = rp.abs ();
1146 ELT_T r_max_abs = pr_max_internal (r_m_abs);
1147 ELT_T r_min_abs = pr_min_internal (r_m_abs);
1148
1149 RMT i_m_abs = ip.abs ();
1150 ELT_T i_max_abs = pr_max_internal (i_m_abs);
1151 ELT_T i_min_abs = pr_min_internal (i_m_abs);
1152
1153 int r_x_max = (r_max_abs == 0 ? 0 : num_digits (r_max_abs));
1154
1155 int r_x_min = (r_min_abs == 0 ? 0 : num_digits (r_min_abs));
1156
1157 int i_x_max = (i_max_abs == 0 ? 0 : num_digits (i_max_abs));
1158
1159 int i_x_min = (i_min_abs == 0 ? 0 : num_digits (i_min_abs));
1160
1161 int x_max = (r_x_max > i_x_max ? r_x_max : i_x_max);
1162 int x_min = (r_x_min > i_x_min ? r_x_min : i_x_min);
1163
1164 return make_complex_matrix_format<ELT_T> (x_max, x_min, r_x_max, r_x_min,
1165 inf_or_nan, int_or_inf_or_nan);
1166 }
1167
1168 template <>
1169 float_display_format
make_format(const ComplexMatrix & cm)1170 make_format (const ComplexMatrix& cm)
1171 {
1172 return make_complex_matrix_format (cm);
1173 }
1174
1175 template <>
1176 float_display_format
make_format(const FloatComplexMatrix & cm)1177 make_format (const FloatComplexMatrix& cm)
1178 {
1179 return make_complex_matrix_format (cm);
1180 }
1181
1182 template <>
1183 float_display_format
make_format(const boolNDArray &)1184 make_format (const boolNDArray&)
1185 {
1186 return float_display_format (float_format (1, 1));
1187 }
1188
1189 template <typename T>
1190 static inline float_display_format
make_range_format(int x_max,int x_min,int all_ints)1191 make_range_format (int x_max, int x_min, int all_ints)
1192 {
1193 double scale = ((x_max == 0 || all_ints)
1194 ? 1 : std::pow (10.0, calc_scale_exp (x_max - 1)));
1195
1196 float_format fmt;
1197
1198 int prec = std::min (output_precision (), pr_output_traits<T>::digits10);
1199
1200 int fw = 0, ld = 0, rd = 0;
1201
1202 if (rat_format)
1203 {
1204 fw = 9;
1205 rd = 0;
1206 }
1207 else if (bank_format)
1208 {
1209 int digits = (x_max > x_min ? x_max : x_min);
1210 fw = (digits < 0 ? 5 : digits + 4);
1211 rd = 2;
1212 }
1213 else if (hex_format)
1214 {
1215 fw = 2 * sizeof (T);
1216 rd = 0;
1217 }
1218 else if (bit_format)
1219 {
1220 fw = 8 * sizeof (T);
1221 rd = 0;
1222 }
1223 else if (all_ints)
1224 {
1225 int digits = (x_max > x_min ? x_max : x_min);
1226 fw = digits + 1;
1227 rd = fw;
1228 }
1229 else if (Vfixed_point_format && ! print_g)
1230 {
1231 rd = prec - 1;
1232 fw = rd + 3;
1233 }
1234 else
1235 {
1236 int ld_max, rd_max;
1237 if (x_max > 0)
1238 {
1239 ld_max = x_max;
1240 rd_max = (prec > x_max ? prec - x_max : prec);
1241 x_max++;
1242 }
1243 else if (x_max < 0)
1244 {
1245 ld_max = 1;
1246 rd_max = (prec > x_max ? prec - x_max : prec);
1247 x_max = -x_max + 1;
1248 }
1249 else
1250 {
1251 ld_max = 1;
1252 rd_max = (prec > 1 ? prec - 1 : prec);
1253 x_max = 1;
1254 }
1255
1256 int ld_min, rd_min;
1257 if (x_min > 0)
1258 {
1259 ld_min = x_min;
1260 rd_min = (prec > x_min ? prec - x_min : prec);
1261 x_min++;
1262 }
1263 else if (x_min < 0)
1264 {
1265 ld_min = 1;
1266 rd_min = (prec > x_min ? prec - x_min : prec);
1267 x_min = -x_min + 1;
1268 }
1269 else
1270 {
1271 ld_min = 1;
1272 rd_min = (prec > 1 ? prec - 1 : prec);
1273 x_min = 1;
1274 }
1275
1276 ld = (ld_max > ld_min ? ld_max : ld_min);
1277 rd = (rd_max > rd_min ? rd_max : rd_min);
1278
1279 fw = ld + rd + 3;
1280 }
1281
1282 if (! (rat_format || bank_format || hex_format || bit_format)
1283 && (print_e || print_eng || print_g
1284 || (! Vfixed_point_format
1285 && (ld + rd > pr_output_traits<T>::digits10
1286 || fw > pr_output_traits<T>::max_field_width
1287 || ld + rd > (1.5 * prec)))))
1288 {
1289 if (print_g)
1290 fmt = float_format (prec+6, prec);
1291 else
1292 {
1293 int ex = 4;
1294 if (x_max > 100 || x_min > 100)
1295 ex++;
1296
1297 if (print_eng)
1298 {
1299 fw = 5 + prec + ex;
1300 fmt = float_format (fw, ex, prec - 1, std::ios::fixed);
1301 }
1302 else
1303 {
1304 fw = 3 + prec + ex;
1305 fmt = float_format (fw, prec - 1, std::ios::scientific);
1306 }
1307 }
1308 }
1309 else if (! bank_format && all_ints)
1310 fmt = float_format (fw, rd);
1311 else
1312 fmt = float_format (fw, rd, std::ios::fixed);
1313
1314 if (uppercase_format)
1315 fmt.uppercase ();
1316
1317 return float_display_format (scale, fmt);
1318 }
1319
1320 template <>
1321 float_display_format
make_format(const Range & r)1322 make_format (const Range& r)
1323 {
1324 if (free_format)
1325 return float_display_format ();
1326
1327 double r_min = r.base ();
1328 double r_max = r.limit ();
1329
1330 if (r_max < r_min)
1331 {
1332 double tmp = r_max;
1333 r_max = r_min;
1334 r_min = tmp;
1335 }
1336
1337 bool all_ints = r.all_elements_are_ints ();
1338
1339 double max_abs = (r_max < 0 ? -r_max : r_max);
1340 double min_abs = (r_min < 0 ? -r_min : r_min);
1341
1342 int x_max = (max_abs == 0 ? 0 : num_digits (max_abs));
1343
1344 int x_min = (min_abs == 0 ? 0 : num_digits (min_abs));
1345
1346 return make_range_format<double> (x_max, x_min, all_ints);
1347 }
1348
1349 template <typename T>
1350 union equiv
1351 {
1352 T val;
1353 unsigned char i[sizeof (T)];
1354 };
1355
1356 #define PRINT_CHAR_BITS(os, c) \
1357 do \
1358 { \
1359 unsigned char ctmp = c; \
1360 char stmp[9]; \
1361 stmp[0] = (ctmp & 0x80) ? '1' : '0'; \
1362 stmp[1] = (ctmp & 0x40) ? '1' : '0'; \
1363 stmp[2] = (ctmp & 0x20) ? '1' : '0'; \
1364 stmp[3] = (ctmp & 0x10) ? '1' : '0'; \
1365 stmp[4] = (ctmp & 0x08) ? '1' : '0'; \
1366 stmp[5] = (ctmp & 0x04) ? '1' : '0'; \
1367 stmp[6] = (ctmp & 0x02) ? '1' : '0'; \
1368 stmp[7] = (ctmp & 0x01) ? '1' : '0'; \
1369 stmp[8] = '\0'; \
1370 os << stmp; \
1371 } \
1372 while (0)
1373
1374 #define PRINT_CHAR_BITS_SWAPPED(os, c) \
1375 do \
1376 { \
1377 unsigned char ctmp = c; \
1378 char stmp[9]; \
1379 stmp[0] = (ctmp & 0x01) ? '1' : '0'; \
1380 stmp[1] = (ctmp & 0x02) ? '1' : '0'; \
1381 stmp[2] = (ctmp & 0x04) ? '1' : '0'; \
1382 stmp[3] = (ctmp & 0x08) ? '1' : '0'; \
1383 stmp[4] = (ctmp & 0x10) ? '1' : '0'; \
1384 stmp[5] = (ctmp & 0x20) ? '1' : '0'; \
1385 stmp[6] = (ctmp & 0x40) ? '1' : '0'; \
1386 stmp[7] = (ctmp & 0x80) ? '1' : '0'; \
1387 stmp[8] = '\0'; \
1388 os << stmp; \
1389 } \
1390 while (0)
1391
1392 template <typename T>
1393 static inline void
pr_any_float(std::ostream & os,const float_format & fmt,T val)1394 pr_any_float (std::ostream& os, const float_format& fmt, T val)
1395 {
1396 // Unless explicitly asked for, always print in big-endian format
1397 // for hex and bit formats.
1398 //
1399 // {bit,hex}_format == 1: print big-endian
1400 // {bit,hex}_format == 2: print native
1401
1402 int fw = fmt.width ();
1403
1404 if (hex_format)
1405 {
1406 octave::preserve_stream_state stream_state (os);
1407
1408 equiv<T> tmp;
1409 tmp.val = val;
1410
1411 // Unless explicitly asked for, always print in big-endian format.
1412
1413 // FIXME: Will bad things happen if we are interrupted before resetting
1414 // the format flags and fill character?
1415
1416 octave::mach_info::float_format flt_fmt
1417 = octave::mach_info::native_float_format ();
1418
1419 os.fill ('0');
1420 if (uppercase_format)
1421 os.flags (std::ios::right | std::ios::hex | std::ios::uppercase);
1422 else
1423 os.flags (std::ios::right | std::ios::hex);
1424
1425 if (hex_format > 1
1426 || flt_fmt == octave::mach_info::flt_fmt_ieee_big_endian)
1427 {
1428 for (std::size_t i = 0; i < sizeof (T); i++)
1429 os << std::setw (2) << static_cast<int> (tmp.i[i]);
1430 }
1431 else
1432 {
1433 for (int i = sizeof (T) - 1; i >= 0; i--)
1434 os << std::setw (2) << static_cast<int> (tmp.i[i]);
1435 }
1436 }
1437 else if (bit_format)
1438 {
1439 equiv<T> tmp;
1440 tmp.val = val;
1441
1442 octave::mach_info::float_format flt_fmt
1443 = octave::mach_info::native_float_format ();
1444
1445 if (flt_fmt == octave::mach_info::flt_fmt_ieee_big_endian)
1446 {
1447 for (std::size_t i = 0; i < sizeof (T); i++)
1448 PRINT_CHAR_BITS (os, tmp.i[i]);
1449 }
1450 else
1451 {
1452 if (bit_format > 1)
1453 {
1454 for (std::size_t i = 0; i < sizeof (T); i++)
1455 PRINT_CHAR_BITS_SWAPPED (os, tmp.i[i]);
1456 }
1457 else
1458 {
1459 for (int i = sizeof (T) - 1; i >= 0; i--)
1460 PRINT_CHAR_BITS (os, tmp.i[i]);
1461 }
1462 }
1463 }
1464 else if (val == 0)
1465 {
1466 octave::preserve_stream_state stream_state (os);
1467
1468 if (fw > 0)
1469 os << std::setw (fw) << "0";
1470 else
1471 os << "0";
1472 }
1473 else if (octave::math::isna (val))
1474 {
1475 octave::preserve_stream_state stream_state (os);
1476
1477 if (fw > 0)
1478 os << std::setw (fw) << "NA";
1479 else
1480 os << "NA";
1481 }
1482 else if (rat_format)
1483 os << pr_rational_float<T> (fmt, val);
1484 else if (octave::math::isinf (val))
1485 {
1486 octave::preserve_stream_state stream_state (os);
1487
1488 const char *s;
1489 if (val < 0)
1490 s = "-Inf";
1491 else
1492 s = "Inf";
1493
1494 if (fw > 0)
1495 os << std::setw (fw) << s;
1496 else
1497 os << s;
1498 }
1499 else if (octave::math::isnan (val))
1500 {
1501 octave::preserve_stream_state stream_state (os);
1502
1503 if (fw > 0)
1504 os << std::setw (fw) << "NaN";
1505 else
1506 os << "NaN";
1507 }
1508 else if (print_eng)
1509 os << pr_engineering_float<T> (fmt, val);
1510 else
1511 os << pr_formatted_float<T> (fmt, val);
1512 }
1513
1514 template <typename T>
1515 static inline void
pr_float(std::ostream & os,const float_display_format & fmt,T val)1516 pr_float (std::ostream& os, const float_display_format& fmt, T val)
1517 {
1518 double scale = fmt.scale_factor ();
1519
1520 if (Vfixed_point_format && ! (print_g || print_e) && scale != 1)
1521 val /= scale;
1522
1523 pr_any_float (os, fmt.real_format (), val);
1524 }
1525
1526 template <typename T>
1527 static inline void
pr_imag_float(std::ostream & os,const float_display_format & fmt,T val)1528 pr_imag_float (std::ostream& os, const float_display_format& fmt, T val)
1529 {
1530 double scale = fmt.scale_factor ();
1531
1532 if (Vfixed_point_format && ! (print_g || print_e) && scale != 1)
1533 val /= scale;
1534
1535 pr_any_float (os, fmt.imag_format (), val);
1536 }
1537
1538 template <typename T>
1539 static inline void
pr_float(std::ostream & os,const float_display_format & fmt,const std::complex<T> & cval)1540 pr_float (std::ostream& os, const float_display_format& fmt,
1541 const std::complex<T>& cval)
1542 {
1543 T r = cval.real ();
1544
1545 pr_float (os, fmt, r);
1546
1547 if (! bank_format)
1548 {
1549 T i = cval.imag ();
1550 if (! (hex_format || bit_format) && lo_ieee_signbit (i))
1551 {
1552 os << " - ";
1553 i = -i;
1554 pr_imag_float (os, fmt, i);
1555 }
1556 else
1557 {
1558 if (hex_format || bit_format)
1559 os << " ";
1560 else
1561 os << " + ";
1562
1563 pr_imag_float (os, fmt, i);
1564 }
1565 os << 'i';
1566 }
1567 }
1568
1569 static inline void
print_empty_matrix(std::ostream & os,octave_idx_type nr,octave_idx_type nc,bool pr_as_read_syntax)1570 print_empty_matrix (std::ostream& os, octave_idx_type nr, octave_idx_type nc,
1571 bool pr_as_read_syntax)
1572 {
1573 assert (nr == 0 || nc == 0);
1574
1575 if (pr_as_read_syntax)
1576 {
1577 if (nr == 0 && nc == 0)
1578 os << "[]";
1579 else
1580 os << "zeros (" << nr << ", " << nc << ')';
1581 }
1582 else
1583 {
1584 os << "[]";
1585
1586 if (Vprint_empty_dimensions)
1587 os << '(' << nr << 'x' << nc << ')';
1588 }
1589 }
1590
1591 static inline void
print_empty_nd_array(std::ostream & os,const dim_vector & dims,bool pr_as_read_syntax)1592 print_empty_nd_array (std::ostream& os, const dim_vector& dims,
1593 bool pr_as_read_syntax)
1594 {
1595 assert (dims.any_zero ());
1596
1597 if (pr_as_read_syntax)
1598 os << "zeros (" << dims.str (',') << ')';
1599 else
1600 {
1601 os << "[]";
1602
1603 if (Vprint_empty_dimensions)
1604 os << '(' << dims.str () << ')';
1605 }
1606 }
1607
1608 static inline void
pr_scale_header(std::ostream & os,double scale)1609 pr_scale_header (std::ostream& os, double scale)
1610 {
1611 if (Vfixed_point_format && ! (print_g || print_e) && scale != 1)
1612 {
1613 octave::preserve_stream_state stream_state (os);
1614
1615 os << " "
1616 << std::setw (8) << std::setprecision (1)
1617 << std::setiosflags (std::ios::scientific | std::ios::left)
1618 << scale
1619 << "*\n";
1620
1621 if (! Vcompact_format)
1622 os << "\n";
1623 }
1624 }
1625
1626 static inline void
pr_col_num_header(std::ostream & os,octave_idx_type total_width,int max_width,octave_idx_type lim,octave_idx_type col,int extra_indent)1627 pr_col_num_header (std::ostream& os, octave_idx_type total_width, int max_width,
1628 octave_idx_type lim, octave_idx_type col, int extra_indent)
1629 {
1630 if (total_width > max_width && Vsplit_long_rows)
1631 {
1632 octave::preserve_stream_state stream_state (os);
1633
1634 if (col != 0)
1635 {
1636 if (Vcompact_format)
1637 os << "\n";
1638 else
1639 os << "\n\n";
1640 }
1641
1642 octave_idx_type num_cols = lim - col;
1643
1644 os << std::setw (extra_indent) << "";
1645
1646 if (num_cols == 1)
1647 os << " Column " << col + 1 << ":\n";
1648 else if (num_cols == 2)
1649 os << " Columns " << col + 1 << " and " << lim << ":\n";
1650 else
1651 os << " Columns " << col + 1 << " through " << lim << ":\n";
1652
1653 if (! Vcompact_format)
1654 os << "\n";
1655 }
1656 }
1657
1658 template <typename T>
1659 static inline void
pr_plus_format(std::ostream & os,const T & val)1660 pr_plus_format (std::ostream& os, const T& val)
1661 {
1662 if (val > T (0))
1663 os << plus_format_chars[0];
1664 else if (val < T (0))
1665 os << plus_format_chars[1];
1666 else
1667 os << plus_format_chars[2];
1668 }
1669
1670 // FIXME: all this mess with abs is an attempt to avoid seeing
1671 //
1672 // warning: comparison of unsigned expression < 0 is always false
1673 //
1674 // from GCC. Isn't there a better way?
1675
1676 template <typename T>
1677 static inline T
abs(T x)1678 abs (T x)
1679 {
1680 return x < 0 ? -x : x;
1681 }
1682
1683 #define INSTANTIATE_ABS(T) \
1684 template T abs (T)
1685
1686 INSTANTIATE_ABS(int8_t);
1687 INSTANTIATE_ABS(int16_t);
1688 INSTANTIATE_ABS(int32_t);
1689 INSTANTIATE_ABS(int64_t);
1690
1691 #define SPECIALIZE_UABS(T) \
1692 template <> \
1693 inline T \
1694 abs (T x) \
1695 { \
1696 return x; \
1697 }
1698
1699 SPECIALIZE_UABS(uint8_t)
SPECIALIZE_UABS(uint16_t)1700 SPECIALIZE_UABS(uint16_t)
1701 SPECIALIZE_UABS(uint32_t)
1702 SPECIALIZE_UABS(uint64_t)
1703
1704 #define MAKE_INT_MATRIX_FORMAT(TYPE) \
1705 template <> \
1706 float_display_format \
1707 make_format (const intNDArray<TYPE>& nda) \
1708 { \
1709 bool isneg = false; \
1710 int digits = 0; \
1711 \
1712 for (octave_idx_type i = 0; i < nda.numel (); i++) \
1713 { \
1714 int new_digits \
1715 = static_cast<int> \
1716 (std::floor (log10 (double (abs (nda(i).value ()))) + 1)); \
1717 \
1718 if (new_digits > digits) \
1719 digits = new_digits; \
1720 \
1721 if (! isneg) \
1722 isneg = (abs (nda(i).value ()) != nda(i).value ()); \
1723 } \
1724 \
1725 return float_display_format (float_format (digits + isneg, 0, 0)); \
1726 }
1727
1728 MAKE_INT_MATRIX_FORMAT (octave_int8)
1729 MAKE_INT_MATRIX_FORMAT (octave_uint8)
1730 MAKE_INT_MATRIX_FORMAT (octave_int16)
1731 MAKE_INT_MATRIX_FORMAT (octave_uint16)
1732 MAKE_INT_MATRIX_FORMAT (octave_int32)
1733 MAKE_INT_MATRIX_FORMAT (octave_uint32)
1734 MAKE_INT_MATRIX_FORMAT (octave_int64)
1735 MAKE_INT_MATRIX_FORMAT (octave_uint64)
1736
1737 #define MAKE_INT_SCALAR_FORMAT(TYPE) \
1738 template <> \
1739 float_display_format \
1740 make_format (const octave_int<TYPE>& val) \
1741 { \
1742 bool isneg = false; \
1743 int digits \
1744 = static_cast<int> \
1745 (std::floor (log10 (double (abs (val.value ()))) + 1)); \
1746 \
1747 isneg = (abs (val.value ()) != val.value ()); \
1748 \
1749 return float_display_format (float_format (digits + isneg, 0, 0)); \
1750 }
1751
1752 MAKE_INT_SCALAR_FORMAT (int8_t)
1753 MAKE_INT_SCALAR_FORMAT (uint8_t)
1754 MAKE_INT_SCALAR_FORMAT (int16_t)
1755 MAKE_INT_SCALAR_FORMAT (uint16_t)
1756 MAKE_INT_SCALAR_FORMAT (int32_t)
1757 MAKE_INT_SCALAR_FORMAT (uint32_t)
1758 MAKE_INT_SCALAR_FORMAT (int64_t)
1759 MAKE_INT_SCALAR_FORMAT (uint64_t)
1760
1761 void
1762 octave_print_internal (std::ostream& os, const float_display_format& fmt,
1763 bool d, bool pr_as_read_syntax)
1764 {
1765 octave_print_internal (os, fmt, octave_uint8 (d), pr_as_read_syntax);
1766 }
1767
1768 void
octave_print_internal(std::ostream & os,bool d,bool pr_as_read_syntax)1769 octave_print_internal (std::ostream& os, bool d, bool pr_as_read_syntax)
1770 {
1771 octave_print_internal (os, octave_uint8 (d), pr_as_read_syntax);
1772 }
1773
1774 void
octave_print_internal(std::ostream &,const float_display_format &,char,bool)1775 octave_print_internal (std::ostream&, const float_display_format&,
1776 char, bool)
1777 {
1778 panic_impossible ();
1779 }
1780
1781 void
octave_print_internal(std::ostream & os,const float_display_format & fmt,double d,bool pr_as_read_syntax)1782 octave_print_internal (std::ostream& os, const float_display_format& fmt,
1783 double d, bool pr_as_read_syntax)
1784 {
1785 if (pr_as_read_syntax)
1786 os << d;
1787 else if (plus_format)
1788 pr_plus_format (os, d);
1789 else
1790 {
1791 if (free_format)
1792 os << d;
1793 else
1794 pr_float (os, fmt, d);
1795 }
1796 }
1797
1798 void
octave_print_internal(std::ostream & os,const float_display_format & fmt,float d,bool pr_as_read_syntax)1799 octave_print_internal (std::ostream& os, const float_display_format& fmt,
1800 float d, bool pr_as_read_syntax)
1801 {
1802 if (pr_as_read_syntax)
1803 os << d;
1804 else if (plus_format)
1805 pr_plus_format (os, d);
1806 else
1807 {
1808 if (free_format)
1809 os << d;
1810 else
1811 pr_float (os, fmt, d);
1812 }
1813 }
1814
1815 template <typename MT>
1816 static inline void
octave_print_free(std::ostream & os,const MT & m,bool pr_as_read_syntax)1817 octave_print_free (std::ostream& os, const MT& m, bool pr_as_read_syntax)
1818 {
1819 octave_idx_type nr = m.rows ();
1820 octave_idx_type nc = m.columns ();
1821
1822 if (pr_as_read_syntax)
1823 os << "[\n";
1824
1825 for (octave_idx_type i = 0; i < nr; i++)
1826 {
1827 for (octave_idx_type j = 0; j < nc; j++)
1828 os << ' ' << m.elem(i,j);
1829
1830 if (i < nr - 1)
1831 os << "\n";
1832 }
1833
1834 if (pr_as_read_syntax)
1835 os << ']';
1836 }
1837
1838 template <typename MT>
1839 static inline void
pr_plus_format_matrix(std::ostream & os,const MT & m)1840 pr_plus_format_matrix (std::ostream& os, const MT& m)
1841 {
1842 octave_idx_type nr = m.rows ();
1843 octave_idx_type nc = m.columns ();
1844
1845 for (octave_idx_type i = 0; i < nr; i++)
1846 {
1847 for (octave_idx_type j = 0; j < nc; j++)
1848 {
1849 octave_quit ();
1850
1851 pr_plus_format (os, m(i,j));
1852 }
1853
1854 if (i < nr - 1)
1855 os << "\n";
1856 }
1857 }
1858
1859 static inline int
get_column_width(const float_display_format & fmt)1860 get_column_width (const float_display_format& fmt)
1861 {
1862 int r_fw = fmt.real_format().width ();
1863 int i_fw = fmt.imag_format().width ();
1864
1865 int retval = r_fw + i_fw + 2;
1866
1867 if (i_fw && ! (rat_format || bank_format || hex_format || bit_format))
1868 retval += 5;
1869
1870 return retval;
1871 }
1872
1873 template <typename MT>
1874 static void
octave_print_matrix_internal(std::ostream & os,const MT & m,bool pr_as_read_syntax,int extra_indent)1875 octave_print_matrix_internal (std::ostream& os, const MT& m,
1876 bool pr_as_read_syntax, int extra_indent)
1877 {
1878 octave_idx_type nr = m.rows ();
1879 octave_idx_type nc = m.columns ();
1880
1881 if (nr == 0 || nc == 0)
1882 print_empty_matrix (os, nr, nc, pr_as_read_syntax);
1883 else if (plus_format && ! pr_as_read_syntax)
1884 pr_plus_format_matrix (os, m);
1885 else
1886 {
1887 float_display_format fmt = make_format (m);
1888 int column_width = get_column_width (fmt);
1889 octave_idx_type total_width = nc * column_width;
1890 octave_idx_type max_width = octave::command_editor::terminal_cols ();
1891
1892 if (pr_as_read_syntax)
1893 max_width -= 4;
1894 else
1895 max_width -= extra_indent;
1896
1897 if (max_width < 0)
1898 max_width = 0;
1899
1900 if (free_format)
1901 {
1902 octave_print_free (os, m, pr_as_read_syntax);
1903 return;
1904 }
1905
1906 octave_idx_type inc = nc;
1907 if (total_width > max_width && Vsplit_long_rows)
1908 {
1909 inc = max_width / column_width;
1910 if (inc == 0)
1911 inc++;
1912 }
1913
1914 if (pr_as_read_syntax)
1915 {
1916 for (octave_idx_type i = 0; i < nr; i++)
1917 {
1918 octave_idx_type col = 0;
1919 while (col < nc)
1920 {
1921 octave_idx_type lim = (col + inc < nc ? col + inc : nc);
1922
1923 for (octave_idx_type j = col; j < lim; j++)
1924 {
1925 octave_quit ();
1926
1927 if (i == 0 && j == 0)
1928 os << "[ ";
1929 else
1930 {
1931 if (j > col)
1932 os << ", ";
1933 else
1934 os << " ";
1935 }
1936
1937 pr_float (os, fmt, m(i,j));
1938 }
1939
1940 col += inc;
1941
1942 if (col >= nc)
1943 {
1944 if (i == nr - 1)
1945 os << " ]";
1946 else
1947 os << ";\n";
1948 }
1949 else
1950 os << " ...\n";
1951 }
1952 }
1953 }
1954 else
1955 {
1956 octave::preserve_stream_state stream_state (os);
1957
1958 pr_scale_header (os, fmt.scale_factor ());
1959
1960 for (octave_idx_type col = 0; col < nc; col += inc)
1961 {
1962 octave_idx_type lim = (col + inc < nc ? col + inc : nc);
1963
1964 pr_col_num_header (os, total_width, max_width, lim, col,
1965 extra_indent);
1966
1967 for (octave_idx_type i = 0; i < nr; i++)
1968 {
1969 os << std::setw (extra_indent) << "";
1970
1971 for (octave_idx_type j = col; j < lim; j++)
1972 {
1973 octave_quit ();
1974
1975 os << " ";
1976
1977 pr_float (os, fmt, m(i,j));
1978 }
1979
1980 if (i < nr - 1)
1981 os << "\n";
1982 }
1983 }
1984 }
1985 }
1986 }
1987
1988 template <typename DMT>
1989 static void
octave_print_diag_matrix_internal(std::ostream & os,const DMT & m,bool pr_as_read_syntax,int extra_indent)1990 octave_print_diag_matrix_internal (std::ostream& os, const DMT& m,
1991 bool pr_as_read_syntax, int extra_indent)
1992 {
1993 octave_idx_type nr = m.rows ();
1994 octave_idx_type nc = m.columns ();
1995
1996 if (nr == 0 || nc == 0)
1997 print_empty_matrix (os, nr, nc, pr_as_read_syntax);
1998 else if (plus_format && ! pr_as_read_syntax)
1999 pr_plus_format_matrix (os, m);
2000 else
2001 {
2002 float_display_format fmt
2003 = make_format (typename DMT::full_matrix_type (m.diag ()));
2004 int column_width = get_column_width (fmt);
2005 octave_idx_type total_width = nc * column_width;
2006 octave_idx_type max_width = octave::command_editor::terminal_cols ();
2007
2008 if (pr_as_read_syntax)
2009 max_width -= 4;
2010 else
2011 max_width -= extra_indent;
2012
2013 if (max_width < 0)
2014 max_width = 0;
2015
2016 if (free_format)
2017 {
2018 octave_print_free (os, m, pr_as_read_syntax);
2019 return;
2020 }
2021
2022 octave_idx_type inc = nc;
2023 if (total_width > max_width && Vsplit_long_rows)
2024 {
2025 inc = max_width / column_width;
2026 if (inc == 0)
2027 inc++;
2028 }
2029
2030 if (pr_as_read_syntax)
2031 {
2032 os << "diag (";
2033
2034 octave_idx_type col = 0;
2035 while (col < nc)
2036 {
2037 octave_idx_type lim = (col + inc < nc ? col + inc : nc);
2038
2039 for (octave_idx_type j = col; j < lim; j++)
2040 {
2041 octave_quit ();
2042
2043 if (j == 0)
2044 os << "[ ";
2045 else
2046 {
2047 if (j > col)
2048 os << ", ";
2049 else
2050 os << " ";
2051 }
2052
2053 pr_float (os, fmt, m(j,j));
2054 }
2055
2056 col += inc;
2057
2058 if (col >= nc)
2059 os << " ]";
2060 else
2061 os << " ...\n";
2062 }
2063 os << ')';
2064 }
2065 else
2066 {
2067 octave::preserve_stream_state stream_state (os);
2068
2069 os << "Diagonal Matrix\n";
2070 if (! Vcompact_format)
2071 os << "\n";
2072
2073 pr_scale_header (os, fmt.scale_factor ());
2074
2075 // kluge. Get the true width of a number.
2076 int zero_fw;
2077 {
2078 std::ostringstream tmp_oss;
2079 typename DMT::element_type zero = 0;
2080 pr_float (tmp_oss, fmt, zero);
2081 zero_fw = tmp_oss.str ().length ();
2082 }
2083
2084 for (octave_idx_type col = 0; col < nc; col += inc)
2085 {
2086 octave_idx_type lim = (col + inc < nc ? col + inc : nc);
2087
2088 pr_col_num_header (os, total_width, max_width, lim, col,
2089 extra_indent);
2090
2091 for (octave_idx_type i = 0; i < nr; i++)
2092 {
2093 os << std::setw (extra_indent) << "";
2094
2095 for (octave_idx_type j = col; j < lim; j++)
2096 {
2097 octave_quit ();
2098
2099 os << " ";
2100
2101 if (i == j)
2102 pr_float (os, fmt, m(i,j));
2103 else
2104 os << std::setw (zero_fw) << '0';
2105 }
2106
2107 if (i < nr - 1)
2108 os << "\n";
2109 }
2110 }
2111 }
2112 }
2113 }
2114
2115 template <typename NDA_T, typename ELT_T, typename MAT_T>
print_nd_array(std::ostream & os,const NDA_T & nda,bool pr_as_read_syntax)2116 void print_nd_array (std::ostream& os, const NDA_T& nda,
2117 bool pr_as_read_syntax)
2118 {
2119
2120 if (nda.isempty ())
2121 print_empty_nd_array (os, nda.dims (), pr_as_read_syntax);
2122 else
2123 {
2124
2125 int ndims = nda.ndims ();
2126
2127 dim_vector dims = nda.dims ();
2128
2129 Array<octave_idx_type> ra_idx (dim_vector (ndims, 1), 0);
2130
2131 octave_idx_type m = 1;
2132
2133 for (int i = 2; i < ndims; i++)
2134 m *= dims(i);
2135
2136 octave_idx_type nr = dims(0);
2137 octave_idx_type nc = dims(1);
2138
2139 for (octave_idx_type i = 0; i < m; i++)
2140 {
2141 octave_quit ();
2142
2143 std::string nm = "ans";
2144
2145 if (m > 1)
2146 {
2147 nm += "(:,:,";
2148
2149 std::ostringstream buf;
2150
2151 for (int k = 2; k < ndims; k++)
2152 {
2153 buf << ra_idx(k) + 1;
2154
2155 if (k < ndims - 1)
2156 buf << ',';
2157 else
2158 buf << ')';
2159 }
2160
2161 nm += buf.str ();
2162 }
2163
2164 Array<idx_vector> idx (dim_vector (ndims, 1));
2165
2166 idx(0) = idx_vector (':');
2167 idx(1) = idx_vector (':');
2168
2169 for (int k = 2; k < ndims; k++)
2170 idx(k) = idx_vector (ra_idx(k));
2171
2172 octave_value page
2173 = MAT_T (Array<ELT_T> (nda.index (idx), dim_vector (nr, nc)));
2174
2175 if (i != m - 1)
2176 {
2177 page.print_with_name (os, nm);
2178 }
2179 else
2180 {
2181 page.print_name_tag (os, nm);
2182 page.print_raw (os);
2183 }
2184
2185 NDA_T::increment_index (ra_idx, dims, 2);
2186 }
2187 }
2188 }
2189
2190 void
octave_print_internal(std::ostream & os,const NDArray & nda,bool pr_as_read_syntax,int extra_indent)2191 octave_print_internal (std::ostream& os, const NDArray& nda,
2192 bool pr_as_read_syntax, int extra_indent)
2193 {
2194 switch (nda.ndims ())
2195 {
2196 case 1:
2197 case 2:
2198 octave_print_internal (os, Matrix (nda),
2199 pr_as_read_syntax, extra_indent);
2200 break;
2201
2202 default:
2203 print_nd_array <NDArray, double, Matrix> (os, nda, pr_as_read_syntax);
2204 break;
2205 }
2206 }
2207
2208 void
octave_print_internal(std::ostream & os,const FloatNDArray & nda,bool pr_as_read_syntax,int extra_indent)2209 octave_print_internal (std::ostream& os, const FloatNDArray& nda,
2210 bool pr_as_read_syntax, int extra_indent)
2211 {
2212 switch (nda.ndims ())
2213 {
2214 case 1:
2215 case 2:
2216 octave_print_internal (os, FloatMatrix (nda),
2217 pr_as_read_syntax, extra_indent);
2218 break;
2219
2220 default:
2221 print_nd_array <FloatNDArray, float, FloatMatrix> (os, nda, pr_as_read_syntax);
2222 break;
2223 }
2224 }
2225
2226 template <typename T>
2227 static inline void
pr_plus_format(std::ostream & os,const std::complex<T> & c)2228 pr_plus_format (std::ostream& os, const std::complex<T>& c)
2229 {
2230 T rp = c.real ();
2231 T ip = c.imag ();
2232
2233 if (rp == 0)
2234 {
2235 if (ip == 0)
2236 os << ' ';
2237 else
2238 os << 'i';
2239 }
2240 else if (ip == 0)
2241 pr_plus_format (os, rp);
2242 else
2243 os << 'c';
2244 }
2245
2246 extern void
octave_print_internal(std::ostream & os,const float_display_format & fmt,const Complex & c,bool pr_as_read_syntax)2247 octave_print_internal (std::ostream& os, const float_display_format& fmt,
2248 const Complex& c, bool pr_as_read_syntax)
2249 {
2250 if (pr_as_read_syntax)
2251 os << c;
2252 else if (plus_format)
2253 pr_plus_format (os, c);
2254 else
2255 {
2256 if (free_format)
2257 os << c;
2258 else
2259 pr_float (os, fmt, c);
2260 }
2261 }
2262
2263 void
octave_print_internal(std::ostream & os,const float_display_format & fmt,const FloatComplex & c,bool pr_as_read_syntax)2264 octave_print_internal (std::ostream& os, const float_display_format& fmt,
2265 const FloatComplex& c, bool pr_as_read_syntax)
2266 {
2267 if (pr_as_read_syntax)
2268 os << c;
2269 else if (plus_format)
2270 pr_plus_format (os, c);
2271 else
2272 {
2273 if (free_format)
2274 os << c;
2275 else
2276 pr_float (os, fmt, c);
2277 }
2278 }
2279
2280 void
octave_print_internal(std::ostream & os,const PermMatrix & m,bool pr_as_read_syntax,int extra_indent)2281 octave_print_internal (std::ostream& os, const PermMatrix& m,
2282 bool pr_as_read_syntax, int extra_indent)
2283 {
2284 octave_idx_type nr = m.rows ();
2285 octave_idx_type nc = m.columns ();
2286
2287 if (nr == 0 || nc == 0)
2288 print_empty_matrix (os, nr, nc, pr_as_read_syntax);
2289 else if (plus_format && ! pr_as_read_syntax)
2290 pr_plus_format_matrix (os, m);
2291 else
2292 {
2293 int fw = 2;
2294 int column_width = fw + 2;
2295 octave_idx_type total_width = nc * column_width;
2296 octave_idx_type max_width = octave::command_editor::terminal_cols ();
2297
2298 if (pr_as_read_syntax)
2299 max_width -= 4;
2300 else
2301 max_width -= extra_indent;
2302
2303 if (max_width < 0)
2304 max_width = 0;
2305
2306 if (free_format)
2307 {
2308 octave_print_free (os, m, pr_as_read_syntax);
2309 return;
2310 }
2311
2312 octave_idx_type inc = nc;
2313 if (total_width > max_width && Vsplit_long_rows)
2314 {
2315 inc = max_width / column_width;
2316 if (inc == 0)
2317 inc++;
2318 }
2319
2320 if (pr_as_read_syntax)
2321 {
2322 Array<octave_idx_type> pvec = m.col_perm_vec ();
2323
2324 os << "eye (";
2325 os << ":, ";
2326
2327 octave_idx_type col = 0;
2328 while (col < nc)
2329 {
2330 octave_idx_type lim = (col + inc < nc ? col + inc : nc);
2331
2332 for (octave_idx_type j = col; j < lim; j++)
2333 {
2334 octave_quit ();
2335
2336 if (j == 0)
2337 os << "[ ";
2338 else
2339 {
2340 if (j > col)
2341 os << ", ";
2342 else
2343 os << " ";
2344 }
2345
2346 os << pvec (j);
2347 }
2348
2349 col += inc;
2350
2351 if (col >= nc)
2352 os << " ]";
2353 else
2354 os << " ...\n";
2355 }
2356 os << ')';
2357 }
2358 else
2359 {
2360 octave::preserve_stream_state stream_state (os);
2361
2362 os << "Permutation Matrix\n";
2363 if (! Vcompact_format)
2364 os << "\n";
2365
2366 for (octave_idx_type col = 0; col < nc; col += inc)
2367 {
2368 octave_idx_type lim = (col + inc < nc ? col + inc : nc);
2369
2370 pr_col_num_header (os, total_width, max_width, lim, col,
2371 extra_indent);
2372
2373 for (octave_idx_type i = 0; i < nr; i++)
2374 {
2375 os << std::setw (extra_indent) << "";
2376
2377 for (octave_idx_type j = col; j < lim; j++)
2378 {
2379 octave_quit ();
2380
2381 os << " ";
2382
2383 os << std::setw (fw) << m(i,j);
2384 }
2385
2386 if (i < nr - 1)
2387 os << "\n";
2388 }
2389 }
2390 }
2391 }
2392 }
2393
2394 void
octave_print_internal(std::ostream & os,const ComplexNDArray & nda,bool pr_as_read_syntax,int extra_indent)2395 octave_print_internal (std::ostream& os, const ComplexNDArray& nda,
2396 bool pr_as_read_syntax, int extra_indent)
2397 {
2398 switch (nda.ndims ())
2399 {
2400 case 1:
2401 case 2:
2402 octave_print_internal (os, ComplexMatrix (nda),
2403 pr_as_read_syntax, extra_indent);
2404 break;
2405
2406 default:
2407 print_nd_array <ComplexNDArray, Complex, ComplexMatrix>
2408 (os, nda, pr_as_read_syntax);
2409 break;
2410 }
2411 }
2412
2413 void
octave_print_internal(std::ostream & os,const FloatComplexNDArray & nda,bool pr_as_read_syntax,int extra_indent)2414 octave_print_internal (std::ostream& os, const FloatComplexNDArray& nda,
2415 bool pr_as_read_syntax, int extra_indent)
2416 {
2417 switch (nda.ndims ())
2418 {
2419 case 1:
2420 case 2:
2421 octave_print_internal (os, FloatComplexMatrix (nda),
2422 pr_as_read_syntax, extra_indent);
2423 break;
2424
2425 default:
2426 print_nd_array <FloatComplexNDArray, FloatComplex, FloatComplexMatrix>
2427 (os, nda, pr_as_read_syntax);
2428 break;
2429 }
2430 }
2431
2432 // FIXME: write single precision versions of the printing functions.
2433
2434 void
octave_print_internal(std::ostream & os,const Matrix & m,bool pr_as_read_syntax,int extra_indent)2435 octave_print_internal (std::ostream& os, const Matrix& m,
2436 bool pr_as_read_syntax, int extra_indent)
2437 {
2438 octave_print_matrix_internal (os, m, pr_as_read_syntax, extra_indent);
2439 }
2440
2441 void
octave_print_internal(std::ostream & os,const FloatMatrix & m,bool pr_as_read_syntax,int extra_indent)2442 octave_print_internal (std::ostream& os, const FloatMatrix& m,
2443 bool pr_as_read_syntax, int extra_indent)
2444 {
2445 octave_print_matrix_internal (os, m, pr_as_read_syntax, extra_indent);
2446 }
2447
2448 void
octave_print_internal(std::ostream & os,const DiagMatrix & m,bool pr_as_read_syntax,int extra_indent)2449 octave_print_internal (std::ostream& os, const DiagMatrix& m,
2450 bool pr_as_read_syntax, int extra_indent)
2451 {
2452 octave_print_diag_matrix_internal (os, m, pr_as_read_syntax, extra_indent);
2453 }
2454
2455 void
octave_print_internal(std::ostream & os,const FloatDiagMatrix & m,bool pr_as_read_syntax,int extra_indent)2456 octave_print_internal (std::ostream& os, const FloatDiagMatrix& m,
2457 bool pr_as_read_syntax, int extra_indent)
2458 {
2459 octave_print_diag_matrix_internal (os, m, pr_as_read_syntax, extra_indent);
2460 }
2461
2462 void
octave_print_internal(std::ostream & os,const ComplexMatrix & cm,bool pr_as_read_syntax,int extra_indent)2463 octave_print_internal (std::ostream& os, const ComplexMatrix& cm,
2464 bool pr_as_read_syntax, int extra_indent)
2465 {
2466 octave_print_matrix_internal (os, cm, pr_as_read_syntax, extra_indent);
2467 }
2468
2469 void
octave_print_internal(std::ostream & os,const FloatComplexMatrix & cm,bool pr_as_read_syntax,int extra_indent)2470 octave_print_internal (std::ostream& os, const FloatComplexMatrix& cm,
2471 bool pr_as_read_syntax, int extra_indent)
2472 {
2473 octave_print_matrix_internal (os, cm, pr_as_read_syntax, extra_indent);
2474 }
2475
2476 void
octave_print_internal(std::ostream & os,const ComplexDiagMatrix & cm,bool pr_as_read_syntax,int extra_indent)2477 octave_print_internal (std::ostream& os, const ComplexDiagMatrix& cm,
2478 bool pr_as_read_syntax, int extra_indent)
2479 {
2480 octave_print_diag_matrix_internal (os, cm, pr_as_read_syntax, extra_indent);
2481 }
2482
2483 void
octave_print_internal(std::ostream & os,const FloatComplexDiagMatrix & cm,bool pr_as_read_syntax,int extra_indent)2484 octave_print_internal (std::ostream& os, const FloatComplexDiagMatrix& cm,
2485 bool pr_as_read_syntax, int extra_indent)
2486 {
2487 octave_print_diag_matrix_internal (os, cm, pr_as_read_syntax, extra_indent);
2488 }
2489
2490 void
octave_print_internal(std::ostream & os,const Range & r,bool pr_as_read_syntax,int extra_indent)2491 octave_print_internal (std::ostream& os, const Range& r,
2492 bool pr_as_read_syntax, int extra_indent)
2493 {
2494 double base = r.base ();
2495 double increment = r.inc ();
2496 double limit = r.limit ();
2497 octave_idx_type num_elem = r.numel ();
2498
2499 if (plus_format && ! pr_as_read_syntax)
2500 pr_plus_format_matrix (os, r);
2501 else
2502 {
2503 float_display_format fmt = make_format (r);
2504
2505 if (pr_as_read_syntax)
2506 {
2507 if (free_format)
2508 {
2509 os << base << " : ";
2510 if (increment != 1)
2511 os << increment << " : ";
2512 os << limit;
2513 }
2514 else
2515 {
2516 pr_float (os, fmt, base);
2517 os << " : ";
2518 if (increment != 1)
2519 {
2520 pr_float (os, fmt, increment);
2521 os << " : ";
2522 }
2523 pr_float (os, fmt, limit);
2524 }
2525 }
2526 else
2527 {
2528 octave::preserve_stream_state stream_state (os);
2529
2530 int column_width = get_column_width (fmt);
2531 octave_idx_type total_width = num_elem * column_width;
2532 octave_idx_type max_width = octave::command_editor::terminal_cols ();
2533
2534 if (free_format)
2535 {
2536 os << ' ';
2537 for (octave_idx_type i = 0; i < num_elem; i++)
2538 os << ' ' << r.elem(i);
2539 return;
2540 }
2541
2542 octave_idx_type inc = num_elem;
2543 if (total_width > max_width && Vsplit_long_rows)
2544 {
2545 inc = max_width / column_width;
2546 if (inc == 0)
2547 inc++;
2548 }
2549
2550 max_width -= extra_indent;
2551
2552 if (max_width < 0)
2553 max_width = 0;
2554
2555 pr_scale_header (os, fmt.scale_factor ());
2556
2557 octave_idx_type col = 0;
2558 while (col < num_elem)
2559 {
2560 octave_idx_type lim = (col + inc < num_elem ? col + inc : num_elem);
2561
2562 pr_col_num_header (os, total_width, max_width, lim, col,
2563 extra_indent);
2564
2565 os << std::setw (extra_indent) << "";
2566
2567 for (octave_idx_type i = col; i < lim; i++)
2568 {
2569 octave_quit ();
2570
2571 double val;
2572 if (i == 0)
2573 val = base;
2574 else
2575 val = base + i * increment;
2576
2577 if (i == num_elem - 1)
2578 {
2579 // See the comments in Range::matrix_value.
2580 if ((increment > 0 && val >= limit)
2581 || (increment < 0 && val <= limit))
2582 val = limit;
2583 }
2584
2585 os << " ";
2586
2587 pr_float (os, fmt, val);
2588 }
2589
2590 col += inc;
2591 }
2592 }
2593 }
2594 }
2595
2596 void
octave_print_internal(std::ostream & os,const boolMatrix & bm,bool pr_as_read_syntax,int extra_indent)2597 octave_print_internal (std::ostream& os, const boolMatrix& bm,
2598 bool pr_as_read_syntax,
2599 int extra_indent)
2600 {
2601 uint8NDArray tmp (bm);
2602 octave_print_internal (os, tmp, pr_as_read_syntax, extra_indent);
2603 }
2604
2605 void
octave_print_internal(std::ostream & os,const boolNDArray & nda,bool pr_as_read_syntax,int extra_indent)2606 octave_print_internal (std::ostream& os, const boolNDArray& nda,
2607 bool pr_as_read_syntax,
2608 int extra_indent)
2609 {
2610 switch (nda.ndims ())
2611 {
2612 case 1:
2613 case 2:
2614 octave_print_internal (os, boolMatrix (nda),
2615 pr_as_read_syntax, extra_indent);
2616 break;
2617
2618 default:
2619 print_nd_array<boolNDArray, bool,
2620 boolMatrix> (os, nda, pr_as_read_syntax);
2621 break;
2622 }
2623 }
2624
2625 void
octave_print_internal(std::ostream & os,const charMatrix & chm,bool pr_as_read_syntax,int,bool pr_as_string)2626 octave_print_internal (std::ostream& os, const charMatrix& chm,
2627 bool pr_as_read_syntax,
2628 int /* FIXME: extra_indent */,
2629 bool pr_as_string)
2630 {
2631 if (pr_as_string)
2632 {
2633 octave_idx_type nstr = chm.rows ();
2634
2635 if (pr_as_read_syntax && nstr > 1)
2636 os << "[ ";
2637
2638 if (nstr != 0)
2639 {
2640 for (octave_idx_type i = 0; i < nstr; i++)
2641 {
2642 octave_quit ();
2643
2644 std::string row = chm.row_as_string (i);
2645
2646 if (pr_as_read_syntax)
2647 {
2648 os << '"' << octave::undo_string_escapes (row) << '"';
2649
2650 if (i < nstr - 1)
2651 os << "; ";
2652 }
2653 else
2654 {
2655 os << row;
2656
2657 if (i < nstr - 1)
2658 os << "\n";
2659 }
2660 }
2661 }
2662
2663 if (pr_as_read_syntax && nstr > 1)
2664 os << " ]";
2665 }
2666 else
2667 {
2668 os << "sorry, printing char matrices not implemented yet\n";
2669 }
2670 }
2671
2672 void
octave_print_internal(std::ostream & os,const charNDArray & nda,bool pr_as_read_syntax,int extra_indent,bool pr_as_string)2673 octave_print_internal (std::ostream& os, const charNDArray& nda,
2674 bool pr_as_read_syntax, int extra_indent,
2675 bool pr_as_string)
2676 {
2677 switch (nda.ndims ())
2678 {
2679 case 1:
2680 case 2:
2681 octave_print_internal (os, charMatrix (nda),
2682 pr_as_read_syntax, extra_indent, pr_as_string);
2683 break;
2684
2685 default:
2686 print_nd_array <charNDArray, char, charMatrix> (os, nda,
2687 pr_as_read_syntax);
2688 break;
2689 }
2690 }
2691
2692 void
octave_print_internal(std::ostream & os,const std::string & s,bool pr_as_read_syntax,int extra_indent)2693 octave_print_internal (std::ostream& os, const std::string& s,
2694 bool pr_as_read_syntax, int extra_indent)
2695 {
2696 Array<std::string> nda (dim_vector (1, 1), s);
2697
2698 octave_print_internal (os, nda, pr_as_read_syntax, extra_indent);
2699 }
2700
2701 void
octave_print_internal(std::ostream & os,const Array<std::string> & nda,bool pr_as_read_syntax,int)2702 octave_print_internal (std::ostream& os, const Array<std::string>& nda,
2703 bool pr_as_read_syntax, int /* extra_indent */)
2704 {
2705 // FIXME: this mostly duplicates the code in the print_nd_array<>
2706 // function. Can fix this with std::is_same from C++11.
2707
2708 if (nda.isempty ())
2709 print_empty_nd_array (os, nda.dims (), pr_as_read_syntax);
2710 else if (nda.numel () == 1)
2711 {
2712 os << nda(0);
2713 }
2714 else
2715 {
2716 int ndims = nda.ndims ();
2717
2718 dim_vector dims = nda.dims ();
2719
2720 Array<octave_idx_type> ra_idx (dim_vector (ndims, 1), 0);
2721
2722 octave_idx_type m = 1;
2723
2724 for (int i = 2; i < ndims; i++)
2725 m *= dims(i);
2726
2727 octave_idx_type nr = dims(0);
2728 octave_idx_type nc = dims(1);
2729
2730 for (octave_idx_type i = 0; i < m; i++)
2731 {
2732 std::string nm = "ans";
2733
2734 if (m > 1)
2735 {
2736 nm += "(:,:,";
2737
2738 std::ostringstream buf;
2739
2740 for (int k = 2; k < ndims; k++)
2741 {
2742 buf << ra_idx(k) + 1;
2743
2744 if (k < ndims - 1)
2745 buf << ',';
2746 else
2747 buf << ')';
2748 }
2749
2750 nm += buf.str ();
2751 }
2752
2753 Array<idx_vector> idx (dim_vector (ndims, 1));
2754
2755 idx(0) = idx_vector (':');
2756 idx(1) = idx_vector (':');
2757
2758 for (int k = 2; k < ndims; k++)
2759 idx(k) = idx_vector (ra_idx(k));
2760
2761 Array<std::string> page (nda.index (idx), dim_vector (nr, nc));
2762
2763 // FIXME: need to do some more work to put these
2764 // in neatly aligned columns...
2765
2766 octave_idx_type n_rows = page.rows ();
2767 octave_idx_type n_cols = page.cols ();
2768
2769 os << nm << " =\n";
2770 if (! Vcompact_format)
2771 os << "\n";
2772
2773 for (octave_idx_type ii = 0; ii < n_rows; ii++)
2774 {
2775 for (octave_idx_type jj = 0; jj < n_cols; jj++)
2776 os << " " << page(ii,jj);
2777
2778 os << "\n";
2779 }
2780
2781 if (i < m - 1)
2782 os << "\n";
2783
2784 increment_index (ra_idx, dims, 2);
2785 }
2786 }
2787 }
2788
2789 template <typename T>
2790 class
2791 octave_print_conv
2792 {
2793 public:
2794 typedef T print_conv_type;
2795 };
2796
2797 #define PRINT_CONV(T1, T2) \
2798 template <> \
2799 class \
2800 octave_print_conv<T1> \
2801 { \
2802 public: \
2803 typedef T2 print_conv_type; \
2804 }
2805
2806 PRINT_CONV (octave_int8, octave_int16);
2807 PRINT_CONV (octave_uint8, octave_uint16);
2808
2809 #undef PRINT_CONV
2810
2811 template <typename T>
2812 static inline void
pr_int(std::ostream & os,const T & d,int fw=0)2813 pr_int (std::ostream& os, const T& d, int fw = 0)
2814 {
2815 std::size_t sz = d.byte_size ();
2816 const unsigned char *tmpi = d.iptr ();
2817
2818 // Unless explicitly asked for, always print in big-endian
2819 // format for hex and bit formats.
2820 //
2821 // {bit,hex}_format == 1: print big-endian
2822 // {bit,hex}_format == 2: print native
2823
2824 if (hex_format)
2825 {
2826 octave::preserve_stream_state stream_state (os);
2827
2828 os.fill ('0');
2829 if (uppercase_format)
2830 os.flags (std::ios::right | std::ios::hex | std::ios::uppercase);
2831 else
2832 os.flags (std::ios::right | std::ios::hex);
2833
2834 if (hex_format > 1 || octave::mach_info::words_big_endian ())
2835 {
2836 for (std::size_t i = 0; i < sz; i++)
2837 os << std::setw (2) << static_cast<int> (tmpi[i]);
2838 }
2839 else
2840 {
2841 for (int i = sz - 1; i >= 0; i--)
2842 os << std::setw (2) << static_cast<int> (tmpi[i]);
2843 }
2844 }
2845 else if (bit_format)
2846 {
2847 if (octave::mach_info::words_big_endian ())
2848 {
2849 for (std::size_t i = 0; i < sz; i++)
2850 PRINT_CHAR_BITS (os, tmpi[i]);
2851 }
2852 else
2853 {
2854 if (bit_format > 1)
2855 {
2856 for (std::size_t i = 0; i < sz; i++)
2857 PRINT_CHAR_BITS_SWAPPED (os, tmpi[i]);
2858 }
2859 else
2860 {
2861 for (int i = sz - 1; i >= 0; i--)
2862 PRINT_CHAR_BITS (os, tmpi[i]);
2863 }
2864 }
2865 }
2866 else
2867 {
2868 octave::preserve_stream_state stream_state (os);
2869
2870 os << std::setw (fw)
2871 << typename octave_print_conv<T>::print_conv_type (d);
2872
2873 if (bank_format)
2874 os << ".00";
2875 }
2876 }
2877
2878 template void
2879 pr_int (std::ostream&, const octave_int8&, int);
2880
2881 template void
2882 pr_int (std::ostream&, const octave_int16&, int);
2883
2884 template void
2885 pr_int (std::ostream&, const octave_int32&, int);
2886
2887 template void
2888 pr_int (std::ostream&, const octave_int64&, int);
2889
2890 template void
2891 pr_int (std::ostream&, const octave_uint8&, int);
2892
2893 template void
2894 pr_int (std::ostream&, const octave_uint16&, int);
2895
2896 template void
2897 pr_int (std::ostream&, const octave_uint32&, int);
2898
2899 template void
2900 pr_int (std::ostream&, const octave_uint64&, int);
2901
2902 template <typename T>
2903 void
octave_print_internal_template(std::ostream & os,const float_display_format & fmt,const octave_int<T> & val,bool)2904 octave_print_internal_template (std::ostream& os,
2905 const float_display_format& fmt,
2906 const octave_int<T>& val, bool)
2907 {
2908 if (plus_format)
2909 pr_plus_format (os, val);
2910 else
2911 {
2912 if (free_format)
2913 os << typename octave_print_conv<octave_int<T>>::print_conv_type (val);
2914 else
2915 {
2916 float_format r_fmt = fmt.real_format ();
2917
2918 pr_int (os, val, r_fmt.width ());
2919 }
2920 }
2921 }
2922
2923 #define PRINT_INT_SCALAR_INTERNAL(TYPE) \
2924 OCTINTERP_API void \
2925 octave_print_internal (std::ostream& os, \
2926 const float_display_format& fmt, \
2927 const octave_int<TYPE>& val, bool dummy) \
2928 { \
2929 octave_print_internal_template (os, fmt, val, dummy); \
2930 }
2931
2932 PRINT_INT_SCALAR_INTERNAL (int8_t)
PRINT_INT_SCALAR_INTERNAL(uint8_t)2933 PRINT_INT_SCALAR_INTERNAL (uint8_t)
2934 PRINT_INT_SCALAR_INTERNAL (int16_t)
2935 PRINT_INT_SCALAR_INTERNAL (uint16_t)
2936 PRINT_INT_SCALAR_INTERNAL (int32_t)
2937 PRINT_INT_SCALAR_INTERNAL (uint32_t)
2938 PRINT_INT_SCALAR_INTERNAL (int64_t)
2939 PRINT_INT_SCALAR_INTERNAL (uint64_t)
2940
2941 template <typename T>
2942 static inline void
2943 octave_print_internal_template (std::ostream& os, const intNDArray<T>& nda,
2944 bool pr_as_read_syntax, int extra_indent)
2945 {
2946 // FIXME: this mostly duplicates the code in the print_nd_array<>
2947 // function. Can fix this with std::is_same from C++11.
2948
2949 if (nda.isempty ())
2950 print_empty_nd_array (os, nda.dims (), pr_as_read_syntax);
2951 else if (nda.numel () == 1)
2952 octave_print_internal_template (os, float_display_format (), nda(0),
2953 pr_as_read_syntax);
2954 else if (plus_format && ! pr_as_read_syntax)
2955 {
2956 int ndims = nda.ndims ();
2957
2958 Array<octave_idx_type> ra_idx (dim_vector (ndims, 1), 0);
2959
2960 dim_vector dims = nda.dims ();
2961
2962 octave_idx_type m = 1;
2963
2964 for (int i = 2; i < ndims; i++)
2965 m *= dims(i);
2966
2967 octave_idx_type nr = dims(0);
2968 octave_idx_type nc = dims(1);
2969
2970 for (octave_idx_type i = 0; i < m; i++)
2971 {
2972 if (m > 1)
2973 {
2974 std::string nm = "ans(:,:,";
2975
2976 std::ostringstream buf;
2977
2978 for (int k = 2; k < ndims; k++)
2979 {
2980 buf << ra_idx(k) + 1;
2981
2982 if (k < ndims - 1)
2983 buf << ',';
2984 else
2985 buf << ')';
2986 }
2987
2988 nm += buf.str ();
2989
2990 os << nm << " =\n";
2991 if (! Vcompact_format)
2992 os << "\n";
2993 }
2994
2995 Array<idx_vector> idx (dim_vector (ndims, 1));
2996
2997 idx(0) = idx_vector (':');
2998 idx(1) = idx_vector (':');
2999
3000 for (int k = 2; k < ndims; k++)
3001 idx(k) = idx_vector (ra_idx(k));
3002
3003 Array<T> page (nda.index (idx), dim_vector (nr, nc));
3004
3005 for (octave_idx_type ii = 0; ii < nr; ii++)
3006 {
3007 for (octave_idx_type jj = 0; jj < nc; jj++)
3008 {
3009 octave_quit ();
3010
3011 pr_plus_format (os, page(ii,jj));
3012 }
3013
3014 if ((ii < nr - 1) || (i < m -1))
3015 os << "\n";
3016 }
3017
3018 if (i < m - 1)
3019 {
3020 os << "\n";
3021 increment_index (ra_idx, dims, 2);
3022 }
3023 }
3024 }
3025 else
3026 {
3027 int ndims = nda.ndims ();
3028
3029 dim_vector dims = nda.dims ();
3030
3031 Array<octave_idx_type> ra_idx (dim_vector (ndims, 1), 0);
3032
3033 octave_idx_type m = 1;
3034
3035 for (int i = 2; i < ndims; i++)
3036 m *= dims(i);
3037
3038 octave_idx_type nr = dims(0);
3039 octave_idx_type nc = dims(1);
3040
3041 int fw = 0;
3042 if (hex_format)
3043 fw = 2 * nda(0).byte_size ();
3044 else if (bit_format)
3045 fw = nda(0).nbits ();
3046 else
3047 {
3048 bool isneg = false;
3049 int digits = 0;
3050
3051 for (octave_idx_type i = 0; i < dims.numel (); i++)
3052 {
3053 int new_digits
3054 = static_cast<int>
3055 (std::floor (log10 (double (abs (nda(i).value ()))) + 1));
3056
3057 if (new_digits > digits)
3058 digits = new_digits;
3059
3060 if (! isneg)
3061 isneg = (abs (nda(i).value ()) != nda(i).value ());
3062 }
3063
3064 fw = digits + isneg;
3065 }
3066
3067 int column_width = fw + (rat_format ? 0 : (bank_format ? 5 : 2));
3068 octave_idx_type total_width = nc * column_width;
3069 int max_width = octave::command_editor::terminal_cols () - extra_indent;
3070 octave_idx_type inc = nc;
3071 if (total_width > max_width && Vsplit_long_rows)
3072 {
3073 inc = max_width / column_width;
3074 if (inc == 0)
3075 inc++;
3076 }
3077
3078 for (octave_idx_type i = 0; i < m; i++)
3079 {
3080 if (m > 1)
3081 {
3082 std::string nm = "ans(:,:,";
3083
3084 std::ostringstream buf;
3085
3086 for (int k = 2; k < ndims; k++)
3087 {
3088 buf << ra_idx(k) + 1;
3089
3090 if (k < ndims - 1)
3091 buf << ',';
3092 else
3093 buf << ')';
3094 }
3095
3096 nm += buf.str ();
3097
3098 os << nm << " =\n";
3099 if (! Vcompact_format)
3100 os << "\n";
3101 }
3102
3103 Array<idx_vector> idx (dim_vector (ndims, 1));
3104
3105 idx(0) = idx_vector (':');
3106 idx(1) = idx_vector (':');
3107
3108 for (int k = 2; k < ndims; k++)
3109 idx(k) = idx_vector (ra_idx(k));
3110
3111 Array<T> page (nda.index (idx), dim_vector (nr, nc));
3112
3113 if (free_format)
3114 {
3115 if (pr_as_read_syntax)
3116 os << "[\n";
3117
3118 for (octave_idx_type ii = 0; ii < nr; ii++)
3119 {
3120 for (octave_idx_type jj = 0; jj < nc; jj++)
3121 {
3122 octave_quit ();
3123 os << " ";
3124 os << typename octave_print_conv<T>::print_conv_type (page(ii,jj));
3125 }
3126 os << "\n";
3127 }
3128
3129 if (pr_as_read_syntax)
3130 os << ']';
3131 }
3132 else
3133 {
3134 octave::preserve_stream_state stream_state (os);
3135
3136 octave_idx_type n_rows = page.rows ();
3137 octave_idx_type n_cols = page.cols ();
3138
3139 for (octave_idx_type col = 0; col < n_cols; col += inc)
3140 {
3141 octave_idx_type lim = (col + inc < n_cols ? col + inc
3142 : n_cols);
3143
3144 pr_col_num_header (os, total_width, max_width, lim, col,
3145 extra_indent);
3146
3147 for (octave_idx_type ii = 0; ii < n_rows; ii++)
3148 {
3149 os << std::setw (extra_indent) << "";
3150
3151 for (octave_idx_type jj = col; jj < lim; jj++)
3152 {
3153 octave_quit ();
3154 os << " ";
3155 pr_int (os, page(ii,jj), fw);
3156 }
3157 if ((ii < n_rows - 1) || (i < m -1))
3158 os << "\n";
3159 }
3160 }
3161 }
3162
3163 if (i < m - 1)
3164 {
3165 os << "\n";
3166 increment_index (ra_idx, dims, 2);
3167 }
3168 }
3169 }
3170 }
3171
3172 #define PRINT_INT_ARRAY_INTERNAL(TYPE) \
3173 OCTINTERP_API void \
3174 octave_print_internal (std::ostream& os, const intNDArray<TYPE>& nda, \
3175 bool pr_as_read_syntax, int extra_indent) \
3176 { \
3177 octave_print_internal_template (os, nda, pr_as_read_syntax, extra_indent); \
3178 }
3179
3180 PRINT_INT_ARRAY_INTERNAL (octave_int8)
PRINT_INT_ARRAY_INTERNAL(octave_uint8)3181 PRINT_INT_ARRAY_INTERNAL (octave_uint8)
3182 PRINT_INT_ARRAY_INTERNAL (octave_int16)
3183 PRINT_INT_ARRAY_INTERNAL (octave_uint16)
3184 PRINT_INT_ARRAY_INTERNAL (octave_int32)
3185 PRINT_INT_ARRAY_INTERNAL (octave_uint32)
3186 PRINT_INT_ARRAY_INTERNAL (octave_int64)
3187 PRINT_INT_ARRAY_INTERNAL (octave_uint64)
3188
3189 void
3190 octave_print_internal (std::ostream&, const Cell&, bool, int, bool)
3191 {
3192 panic_impossible ();
3193 }
3194
3195 void
octave_print_internal(std::ostream &,const octave_value &,bool)3196 octave_print_internal (std::ostream&, const octave_value&, bool)
3197 {
3198 panic_impossible ();
3199 }
3200
3201 DEFUN (rats, args, ,
3202 doc: /* -*- texinfo -*-
3203 @deftypefn {} {@var{s} =} rats (@var{x})
3204 @deftypefnx {} {@var{s} =} rats (@var{x}, @var{len})
3205 Convert @var{x} into a rational approximation represented as a string.
3206
3207 A rational approximation to a floating point number is a simple fraction
3208 with numerator @var{N} and denominator @var{D} such that
3209 @code{@var{x} = @var{N}/@var{D}}.
3210
3211 The optional second argument defines the maximum length of the string
3212 representing the elements of @var{x}. By default, @var{len} is 9.
3213
3214 If the length of the smallest possible rational approximation exceeds
3215 @var{len}, an asterisk (*) padded with spaces will be returned instead.
3216
3217 Example conversion from matrix to string, and back again.
3218
3219 @example
3220 @group
3221 r = rats (hilb (4));
3222 x = str2num (r)
3223 @end group
3224 @end example
3225
3226 @seealso{rat, format}
3227 @end deftypefn */)
3228 {
3229 int nargin = args.length ();
3230
3231 if (nargin < 1 || nargin > 2)
3232 print_usage ();
3233
3234 octave_value arg = args(0);
3235
3236 if (! arg.isnumeric ())
3237 error ("rats: X must be numeric");
3238
3239 if (arg.isempty ())
3240 return ovl (octave_value (""));
3241
3242 // Convert to N-D arrays to 2-D arrays for Matlab compatibility
3243 if (arg.ndims () > 2)
3244 {
3245 dim_vector dv (arg.rows (), arg.numel () / arg.rows ());
3246 arg = arg.reshape (dv);
3247 }
3248
3249 octave::unwind_protect frame;
3250
3251 frame.protect_var (rat_string_len);
3252
3253 rat_string_len = 9;
3254 if (nargin == 2)
3255 rat_string_len = args(1).nint_value ();
3256
3257 frame.protect_var (rat_format);
3258
3259 rat_format = true;
3260
3261 std::ostringstream buf;
3262 arg.print (buf);
3263 std::string s = buf.str ();
3264
3265 std::list<std::string> lst;
3266
3267 std::size_t n = 0;
3268 std::size_t s_len = s.length ();
3269
3270 while (n < s_len)
3271 {
3272 std::size_t m = s.find ('\n', n);
3273
3274 if (m == std::string::npos)
3275 {
3276 lst.push_back (s.substr (n));
3277 break;
3278 }
3279 else
3280 {
3281 lst.push_back (s.substr (n, m - n));
3282 n = m + 1;
3283 }
3284 }
3285
3286 return ovl (string_vector (lst));
3287 }
3288
3289 /*
3290 %!test <*56941>
3291 %! [old_fmt, old_spacing] = format ();
3292 %! unwind_protect
3293 %! format short;
3294 %! assert (rats (-2.0005, 10), "-4001/2000");
3295 %! assert (strtrim (rats (2.0005, 30)), "4001/2000");
3296 %! assert (pi - str2num (rats (pi, 30)), 0, 4 * eps);
3297 %! assert (e - str2num (rats (e, 30)), 0, 4 * eps);
3298 %! unwind_protect_cleanup
3299 %! format (old_fmt);
3300 %! format (old_spacing);
3301 %! end_unwind_protect
3302
3303 %!test <*57003>
3304 %! x = ones (2,1,3);
3305 %! s = rats (x,4);
3306 %! assert (ndims (s) == 2);
3307 %! assert (rows (s) == 2);
3308 %! assert (columns (s) == 3 * 6);
3309
3310 %!assert <*57004> (rats ([]), '')
3311
3312 %!xtest <57704>
3313 %! [old_fmt, old_spacing] = format ();
3314 %! unwind_protect
3315 %! format short;
3316 %! assert (rats (2.0005, 9), "4001/2000");
3317 %! assert (rats (123, 2), " *");
3318 %! unwind_protect_cleanup
3319 %! format (old_fmt);
3320 %! format (old_spacing);
3321 %! end_unwind_protect
3322
3323 */
3324
3325 DEFUN (disp, args, nargout,
3326 classes: cell char double function_handle int8 int16 int32 int64 logical single struct uint8 uint16 uint32 uint64
3327 doc: /* -*- texinfo -*-
3328 @deftypefn {} {} disp (@var{x})
3329 @deftypefnx {} {@var{str} =} disp (@var{x})
3330 Display the value of @var{x}.
3331
3332 For example:
3333
3334 @example
3335 @group
3336 disp ("The value of pi is:"), disp (pi)
3337
3338 @print{} the value of pi is:
3339 @print{} 3.1416
3340 @end group
3341 @end example
3342
3343 @noindent
3344 Note that the output from @code{disp} always ends with a newline.
3345
3346 If an output value is requested, @code{disp} prints nothing and returns the
3347 formatted output in a string.
3348 @seealso{fdisp}
3349 @end deftypefn */)
3350 {
3351 if (args.length () != 1)
3352 print_usage ();
3353
3354 octave_value_list retval;
3355
3356 octave_value arg = args(0);
3357
3358 if (nargout == 0)
3359 arg.print (octave_stdout);
3360 else
3361 {
3362 std::ostringstream buf;
3363 arg.print (buf);
3364 retval = (octave_value (buf.str (), arg.is_dq_string () ? '"' : '\''));
3365 }
3366
3367 return retval;
3368 }
3369
3370 DEFMETHOD (fdisp, interp, args, ,
3371 classes: cell char double function_handle int8 int16 int32 int64 logical single struct uint8 uint16 uint32 uint64
3372 doc: /* -*- texinfo -*-
3373 @deftypefn {} {} fdisp (@var{fid}, @var{x})
3374 Display the value of @var{x} on the stream @var{fid}.
3375
3376 For example:
3377
3378 @example
3379 @group
3380 fdisp (stdout, "The value of pi is:"), fdisp (stdout, pi)
3381
3382 @print{} the value of pi is:
3383 @print{} 3.1416
3384 @end group
3385 @end example
3386
3387 @noindent
3388 Note that the output from @code{fdisp} always ends with a newline.
3389 @seealso{disp}
3390 @end deftypefn */)
3391 {
3392 if (args.length () != 2)
3393 print_usage ();
3394
3395 octave::stream_list& streams = interp.get_stream_list ();
3396
3397 int fid = streams.get_file_number (args(0));
3398
3399 octave::stream os = streams.lookup (fid, "fdisp");
3400
3401 std::ostream *osp = os.output_stream ();
3402
3403 octave_value arg = args(1);
3404
3405 if (osp)
3406 arg.print (*osp);
3407 else
3408 error ("fdisp: stream FID not open for writing");
3409
3410 return ovl ();
3411 }
3412
3413 /*
3414 ## FIXME: This test writes values to a file, but then never checks them.
3415 %!test
3416 %! [old_fmt, old_spacing] = format ();
3417 %! unwind_protect
3418 %! format short
3419 %! fd = tmpfile ();
3420 %! for r = [0, Inf -Inf, NaN]
3421 %! for i = [0, Inf -Inf, NaN]
3422 %! fdisp (fd, complex (r, i));
3423 %! endfor
3424 %! endfor
3425 %! fclose (fd);
3426 %! unwind_protect_cleanup
3427 %! format (old_fmt);
3428 %! format (old_spacing);
3429 %! end_unwind_protect
3430
3431 %!test
3432 %! [old_fmt, old_spacing] = format ();
3433 %! unwind_protect
3434 %! foo.real = pi * ones (3,20,3);
3435 %! foo.complex = pi * ones (3,20,3) + 1i;
3436 %! foo.char = repmat ("- Hello World -", [3, 20]);
3437 %! foo.cell = {foo.real, foo.complex, foo.char};
3438 %! fields = fieldnames (foo);
3439 %! for f = 1:numel (fields)
3440 %! format loose;
3441 %! loose = disp (foo.(fields{f}));
3442 %! format compact;
3443 %! compact = disp (foo.(fields{f}));
3444 %! expected = strrep (loose, "\n\n", "\n");
3445 %! assert (expected, compact);
3446 %! endfor
3447 %! unwind_protect_cleanup
3448 %! format (old_fmt);
3449 %! format (old_spacing);
3450 %! end_unwind_protect
3451 */
3452
3453 DEFUN (display, args, ,
3454 classes: cell char double function_handle int8 int16 int32 int64 logical single struct uint8 uint16 uint32 uint64
3455 doc: /* -*- texinfo -*-
3456 @deftypefn {} {} display (@var{obj})
3457 Display the contents of the object @var{obj} prepended by its name.
3458
3459 The Octave interpreter calls the @code{display} function whenever it needs
3460 to present a class on-screen. Typically, this would be a statement which
3461 does not end in a semicolon to suppress output. For example:
3462
3463 @example
3464 myclass (@dots{})
3465 @end example
3466
3467 Or:
3468
3469 @example
3470 myobj = myclass (@dots{})
3471 @end example
3472
3473 In general, user-defined classes should overload the @code{disp} method to
3474 avoid the default output:
3475
3476 @example
3477 @group
3478 myobj = myclass (@dots{})
3479 @result{} myobj =
3480
3481 <class myclass>
3482 @end group
3483 @end example
3484
3485 When overloading the @code{display} method instead, one has to take care
3486 of properly displaying the object's name. This can be done by using the
3487 @code{inputname} function.
3488
3489 @seealso{disp, class, subsref, subsasgn}
3490 @end deftypefn */)
3491 {
3492 int nargin = args.length ();
3493
3494 // Matlab apparently accepts two arguments with the second set to the
3495 // inputname of the first. This is undocumented, but we'll use it.
3496 // However, we never call display methods for classes with more than
3497 // one argument.
3498
3499 if (nargin < 1 || nargin > 2)
3500 print_usage ();
3501
3502 std::string name;
3503
3504 if (nargin == 2)
3505 name = args(1).xstring_value ("NAME must be a string");
3506 else
3507 {
3508 string_vector names = args.name_tags ();
3509 name = names(0);
3510 }
3511
3512 // We are here because there is no overloaded display method for this
3513 // object type.
3514
3515 octave_value value = args(0);
3516
3517 // If print_name_tag displays a newline, then also print one after
3518 // disp is done.
3519
3520 bool print_newlines = false;
3521 if (octave::valid_identifier (name))
3522 print_newlines = value.print_name_tag (octave_stdout, name);
3523
3524 // Use feval so that dispatch will also work for disp.
3525
3526 octave::feval ("disp", ovl (value));
3527
3528 if (print_newlines)
3529 octave_stdout << std::endl;
3530
3531 return ovl ();
3532 }
3533
3534 /*
3535 %!test
3536 %! [old_fmt, old_spacing] = format ();
3537 %! unwind_protect
3538 %! format short;
3539 %! str = evalc ("x = 1.1; display (x)");
3540 %! assert (str, "x = 1.1000\n");
3541 %! unwind_protect_cleanup
3542 %! format (old_fmt);
3543 %! format (old_spacing);
3544 %! end_unwind_protect
3545
3546 %!test
3547 %! [old_fmt, old_spacing] = format ();
3548 %! unwind_protect
3549 %! format short;
3550 %! str = evalc ("display (1.1)");
3551 %! assert (str, "1.1000\n");
3552 %! unwind_protect_cleanup
3553 %! format (old_fmt);
3554 %! format (old_spacing);
3555 %! end_unwind_protect
3556
3557 ## Test input validation
3558 %!error display ()
3559 %!error display (1,2)
3560 */
3561
3562 static inline void
init_format_state(void)3563 init_format_state (void)
3564 {
3565 free_format = false;
3566 plus_format = false;
3567 rat_format = false;
3568 bank_format = false;
3569 hex_format = 0;
3570 bit_format = 0;
3571 print_e = false;
3572 print_g = false;
3573 print_eng = false;
3574 }
3575
3576 static std::string format_string ("short");
3577
3578 static inline void
set_format_style(int argc,const string_vector & argv)3579 set_format_style (int argc, const string_vector& argv)
3580 {
3581 if (--argc == 0)
3582 {
3583 // Special case of no options, reset to default values
3584 init_format_state ();
3585 set_output_prec (5);
3586 format_string = "short";
3587 Vcompact_format = false;
3588 uppercase_format = false;
3589 return;
3590 }
3591
3592 int idx = 1;
3593 std::string format;
3594
3595 octave::unwind_protect frame;
3596
3597 frame.protect_var (bank_format);
3598 frame.protect_var (bit_format);
3599 frame.protect_var (free_format);
3600 frame.protect_var (hex_format);
3601 frame.protect_var (plus_format);
3602 frame.protect_var (plus_format_chars);
3603 frame.protect_var (rat_format);
3604 frame.protect_var (print_e);
3605 frame.protect_var (print_eng);
3606 frame.protect_var (print_g);
3607 frame.protect_var (format_string);
3608 frame.protect_var (Vcompact_format);
3609 frame.protect_var (uppercase_format);
3610 int prec = output_precision ();
3611 frame.add ([prec] (void) { set_output_prec (prec); });
3612
3613 format = format_string; // Initialize with existing value
3614 while (argc-- > 0)
3615 {
3616 std::string arg = argv[idx++];
3617 std::transform (arg.begin (), arg.end (), arg.begin (), tolower);
3618
3619 if (arg == "short")
3620 {
3621 format = arg;
3622 init_format_state ();
3623 if (argc > 0)
3624 {
3625 arg = argv[idx];
3626 if (arg == "e")
3627 {
3628 print_e = true;
3629 format.append (arg);
3630 argc--; idx++;
3631 }
3632 else if (arg == "g")
3633 {
3634 init_format_state ();
3635 print_g = true;
3636 format.append (arg);
3637 argc--; idx++;
3638 }
3639 else if (arg == "eng")
3640 {
3641 init_format_state ();
3642 print_eng = true;
3643 format.append (arg);
3644 argc--; idx++;
3645 }
3646 }
3647 set_output_prec (5);
3648 }
3649 else if (arg == "shorte")
3650 {
3651 format = arg;
3652 init_format_state ();
3653 print_e = true;
3654 set_output_prec (5);
3655 }
3656 else if (arg == "shortg")
3657 {
3658 format = arg;
3659 init_format_state ();
3660 print_g = true;
3661 set_output_prec (5);
3662 }
3663 else if (arg == "shorteng")
3664 {
3665 format = arg;
3666 init_format_state ();
3667 print_eng = true;
3668 set_output_prec (5);
3669 }
3670 else if (arg == "long")
3671 {
3672 format = arg;
3673 init_format_state ();
3674 if (argc > 0)
3675 {
3676 arg = argv[idx];
3677
3678 if (arg == "e")
3679 {
3680 print_e = true;
3681 format.append (arg);
3682 argc--; idx++;
3683 }
3684 else if (arg == "g")
3685 {
3686 print_g = true;
3687 format.append (arg);
3688 argc--; idx++;
3689 }
3690 else if (arg == "eng")
3691 {
3692 print_eng = true;
3693 format.append (arg);
3694 argc--; idx++;
3695 }
3696 }
3697 set_output_prec (16);
3698 }
3699 else if (arg == "longe")
3700 {
3701 format = arg;
3702 init_format_state ();
3703 print_e = true;
3704 set_output_prec (16);
3705 }
3706 else if (arg == "longg")
3707 {
3708 format = arg;
3709 init_format_state ();
3710 print_g = true;
3711 set_output_prec (16);
3712 }
3713 else if (arg == "longeng")
3714 {
3715 format = arg;
3716 init_format_state ();
3717 print_eng = true;
3718 set_output_prec (16);
3719 }
3720 else if (arg == "hex")
3721 {
3722 format = arg;
3723 init_format_state ();
3724 hex_format = 1;
3725 }
3726 else if (arg == "native-hex")
3727 {
3728 format = arg;
3729 init_format_state ();
3730 hex_format = 2;
3731 }
3732 else if (arg == "bit")
3733 {
3734 format = arg;
3735 init_format_state ();
3736 bit_format = 1;
3737 }
3738 else if (arg == "native-bit")
3739 {
3740 format = arg;
3741 init_format_state ();
3742 bit_format = 2;
3743 }
3744 else if (arg == "+" || arg == "plus")
3745 {
3746 format = arg;
3747 init_format_state ();
3748 plus_format = true;
3749 if (argc > 0)
3750 {
3751 arg = argv[idx];
3752
3753 if (arg.length () == 3)
3754 {
3755 plus_format_chars = arg;
3756 format.append (arg);
3757 argc--; idx++;
3758 }
3759 else
3760 plus_format_chars = "+- ";
3761 }
3762 else
3763 plus_format_chars = "+- ";
3764 }
3765 else if (arg == "rat")
3766 {
3767 format = arg;
3768 init_format_state ();
3769 rat_format = true;
3770 }
3771 else if (arg == "bank")
3772 {
3773 format = arg;
3774 init_format_state ();
3775 bank_format = true;
3776 }
3777 else if (arg == "free")
3778 {
3779 format = arg;
3780 init_format_state ();
3781 free_format = true;
3782 }
3783 else if (arg == "none")
3784 {
3785 format = arg;
3786 init_format_state ();
3787 free_format = true;
3788 }
3789 else if (arg == "compact")
3790 Vcompact_format = true;
3791 else if (arg == "loose")
3792 Vcompact_format = false;
3793 else if (arg == "lowercase")
3794 uppercase_format = false;
3795 else if (arg == "uppercase")
3796 uppercase_format = true;
3797 else
3798 error ("format: unrecognized format state '%s'", arg.c_str ());
3799 }
3800
3801 format_string = format;
3802
3803 // If successful, discard unwind state information
3804 frame.discard ();
3805 }
3806
3807 DEFUN (format, args, nargout,
3808 doc: /* -*- texinfo -*-
3809 @deftypefn {} {} format
3810 @deftypefnx {} {} format options
3811 @deftypefnx {} {[@var{format}, @var{formatspacing}, @var{uppercase}] =} format
3812 Reset or specify the format of the output produced by @code{disp} and Octave's
3813 normal echoing mechanism.
3814
3815 This command only affects the display of numbers, but not how they are stored
3816 or computed. To change the internal representation from the default double use
3817 one of the conversion functions such as @code{single}, @code{uint8},
3818 @code{int64}, etc.
3819
3820 By default, Octave displays 5 significant digits in a human readable form
3821 (option @samp{short}, option @samp{lowercase}, and option @samp{loose} format
3822 for matrices). If @code{format} is invoked without any options, this default
3823 format is restored.
3824
3825 Valid format options for floating point numbers are listed in the following
3826 table.
3827
3828 @table @code
3829 @item short
3830 Fixed point format with 5 significant figures (default).
3831
3832 @item long
3833 Fixed point format with 16 significant figures.
3834
3835 As with the @samp{short} format, Octave will switch to an exponential @samp{e}
3836 format if it is unable to format a matrix properly using the current format.
3837
3838 @item short e
3839 @itemx long e
3840 Exponential format. The number to be represented is split between a mantissa
3841 and an exponent (power of 10). The mantissa has 5 significant digits in the
3842 short format. In the long format, double values are displayed with 16
3843 significant digits and single values are displayed with 8. For example,
3844 with the @samp{short e} format, @code{pi} is displayed as @code{3.1416e+00}.
3845
3846 @item short g
3847 @itemx long g
3848 Optimally choose between fixed point and exponential format based on the
3849 magnitude of the number. For example, with the @samp{short g} format,
3850 @code{pi .^ [2; 4; 8; 16; 32]} is displayed as
3851
3852 @example
3853 @group
3854 ans =
3855
3856 9.8696
3857 97.409
3858 9488.5
3859 9.0032e+07
3860 8.1058e+15
3861 @end group
3862 @end example
3863
3864 @item short eng
3865 @itemx long eng
3866 Identical to @samp{short e} or @samp{long e} but displays the value using an
3867 engineering format, where the exponent is divisible by 3. For example, with
3868 the @samp{short eng} format, @code{10 * pi} is displayed as @code{31.416e+00}.
3869
3870 @item free
3871 @itemx none
3872 Print output in free format, without trying to line up columns of matrices on
3873 the decimal point. This is a raw format equivalent to the C++ code
3874 @code{std::cout << @var{variable}}. In general, the result is a presentation
3875 with 6 significant digits where unnecessary precision (such as trailing zeros
3876 for integers) is suppressed. Complex numbers are formatted as numeric pairs
3877 like this @samp{(0.60419, 0.60709)} instead of like this
3878 @samp{0.60419 + 0.60709i}.
3879 @end table
3880
3881 The following formats affect all numeric output (floating point and integer
3882 types).
3883
3884 @table @asis
3885 @item @qcode{"+"}
3886 @itemx @qcode{"+"} @qcode{"@var{chars}"}
3887 @itemx @code{plus}
3888 @itemx @code{plus @var{chars}}
3889 Print a @samp{+} symbol for matrix elements greater than zero, a @samp{-}
3890 symbol for elements less than zero, and a space for zero matrix elements. This
3891 format can be useful for examining the sparsity structure of a large matrix.
3892 For very large matrices the function @code{spy} which plots the sparsity
3893 pattern will be clearer.
3894
3895 The optional argument @var{chars} specifies a list of 3 characters to use for
3896 printing values greater than zero, less than zero, and equal to zero. For
3897 example, with the format @qcode{"+" "+-."}, the matrix
3898 @code{[1, 0, -1; -1, 0, 1]} is displayed as
3899
3900 @example
3901 @group
3902 ans =
3903
3904 +.-
3905 -.+
3906 @end group
3907 @end example
3908
3909 @item bank
3910 Print variable in a format appropriate for a currency (fixed format with two
3911 digits to the right of the decimal point). Only the real part of a variable is
3912 displayed, as the imaginary part makes no sense for a currency.
3913
3914 @item native-hex
3915 Print the hexadecimal representation of numbers as they are stored in memory.
3916 For example, on a workstation which stores 8 byte real values in IEEE format
3917 with the least significant byte first, the value of @code{pi} when printed in
3918 @code{native-hex} format is @code{400921fb54442d18}.
3919
3920 @item hex
3921 The same as @code{native-hex}, but always print the most significant byte
3922 first.
3923
3924 @item native-bit
3925 Print the bit representation of numbers as stored in memory. For example, the
3926 value of @code{pi} is
3927
3928 @example
3929 @group
3930 01000000000010010010000111111011
3931 01010100010001000010110100011000
3932 @end group
3933 @end example
3934
3935 (shown here in two 32 bit sections for typesetting purposes) when printed in
3936 native-bit format on a workstation which stores 8 byte real values in IEEE
3937 format with the least significant byte first.
3938
3939 @item bit
3940 The same as @code{native-bit}, but always print the most significant bits
3941 first.
3942
3943 @item rat
3944 Print a rational approximation, i.e., values are approximated as the ratio of
3945 small integers. For example, with the @samp{rat} format, @code{pi} is
3946 displayed as @code{355/113}.
3947 @end table
3948
3949 The following two options affect the display of scientific and hex notations.
3950
3951 @table @code
3952 @item lowercase (default)
3953 Use a lowercase @samp{e} for the exponent character in scientific notation and
3954 lowercase @samp{a-f} for the hex digits representing 10-15.
3955
3956 @item uppercase
3957 Use an uppercase @samp{E} for the exponent character in scientific notation and
3958 uppercase @samp{A-F} for the hex digits representing 10-15.
3959 @end table
3960
3961 The following two options affect the display of all matrices.
3962
3963 @table @code
3964 @item compact
3965 Remove blank lines around column number labels and between matrices producing
3966 more compact output with more data per page.
3967
3968 @item loose (default)
3969 Insert blank lines above and below column number labels and between matrices to
3970 produce a more readable output with less data per page.
3971 @end table
3972
3973 If @code{format} is called with multiple competing options, the rightmost one
3974 is used. In case of an error the format remains unchanged.
3975
3976 If called with one to three output arguments, and no inputs, return the current
3977 format, format spacing, and uppercase preference.
3978
3979 @seealso{fixed_point_format, output_precision, split_long_rows, print_empty_dimensions, rats}
3980 @end deftypefn */)
3981 {
3982 octave_value_list retval (std::min (nargout, 2));
3983
3984 int nargin = args.length ();
3985
3986 if (nargout == 0)
3987 {
3988 int argc = nargin + 1;
3989
3990 string_vector argv = args.make_argv ("format");
3991
3992 set_format_style (argc, argv);
3993 }
3994 else
3995 {
3996 if (nargin > 0)
3997 warning ("format: cannot query and set format at the same time, ignoring set operation");
3998
3999 if (nargout >= 3)
4000 retval(2) = (uppercase_format ? "uppercase" : "lowercase");
4001
4002 if (nargout >= 2)
4003 retval(1) = (Vcompact_format ? "compact" : "loose");
4004
4005 retval(0) = format_string;
4006 }
4007
4008 return retval;
4009 }
4010
4011 /*
4012 %!test
4013 %! [old_fmt, old_spacing, old_uppercase] = format ();
4014 %! unwind_protect
4015 %! ## Test one of the formats
4016 %! format long e;
4017 %! format uppercase;
4018 %! str = disp (pi);
4019 %! assert (str, "3.141592653589793E+00\n");
4020 %! str = disp (single (pi));
4021 %! assert (str, "3.1415927E+00\n");
4022 %! new_fmt = format ();
4023 %! assert (new_fmt, "longe");
4024 %! ## Test resetting format
4025 %! format compact;
4026 %! [~, new_spacing] = format ();
4027 %! assert (new_spacing, "compact");
4028 %! format;
4029 %! [new_fmt, new_spacing, new_case] = format ();
4030 %! assert (new_fmt, "short");
4031 %! assert (new_spacing, "loose");
4032 %! assert (new_case, "lowercase");
4033 %! unwind_protect_cleanup
4034 %! format (old_fmt);
4035 %! format (old_spacing);
4036 %! format (old_uppercase);
4037 %! end_unwind_protect
4038
4039 %!test <*53427>
4040 %! [old_fmt, old_spacing] = format ();
4041 %! unwind_protect
4042 %! format; # reset format to short and loose
4043 %! format compact; # set compact format
4044 %! format long; # set long format
4045 %! [fmt, spacing] = format ();
4046 %! assert (fmt, "long");
4047 %! assert (spacing, "compact");
4048 %! unwind_protect_cleanup
4049 %! format (old_fmt);
4050 %! format (old_spacing);
4051 %! end_unwind_protect
4052
4053 ## Test input validation
4054 %!test
4055 %! fail ("fmt = format ('long')", "warning", "cannot query and set format");
4056
4057 */
4058
4059 DEFUN (fixed_point_format, args, nargout,
4060 doc: /* -*- texinfo -*-
4061 @deftypefn {} {@var{val} =} fixed_point_format ()
4062 @deftypefnx {} {@var{old_val} =} fixed_point_format (@var{new_val})
4063 @deftypefnx {} {} fixed_point_format (@var{new_val}, "local")
4064 Query or set the internal variable that controls whether Octave will
4065 use a scaled format to print matrix values.
4066
4067 The scaled format prints a scaling factor on the first line of output chosen
4068 such that the largest matrix element can be written with a single leading
4069 digit. For example:
4070
4071 @example
4072 @group
4073 fixed_point_format (true)
4074 logspace (1, 7, 5)'
4075 ans =
4076
4077 1.0e+07 *
4078
4079 0.00000
4080 0.00003
4081 0.00100
4082 0.03162
4083 1.00000
4084 @end group
4085 @end example
4086
4087 @noindent
4088 Notice that the first value appears to be 0 when it is actually 1. Because
4089 of the possibility for confusion you should be careful about enabling
4090 @code{fixed_point_format}.
4091
4092 When called from inside a function with the @qcode{"local"} option, the
4093 variable is changed locally for the function and any subroutines it calls.
4094 The original variable value is restored when exiting the function.
4095 @seealso{format, output_precision}
4096 @end deftypefn */)
4097 {
4098 return SET_INTERNAL_VARIABLE (fixed_point_format);
4099 }
4100
4101 DEFUN (print_empty_dimensions, args, nargout,
4102 doc: /* -*- texinfo -*-
4103 @deftypefn {} {@var{val} =} print_empty_dimensions ()
4104 @deftypefnx {} {@var{old_val} =} print_empty_dimensions (@var{new_val})
4105 @deftypefnx {} {} print_empty_dimensions (@var{new_val}, "local")
4106 Query or set the internal variable that controls whether the dimensions of
4107 empty matrices are printed along with the empty matrix symbol, @samp{[]}.
4108
4109 For example, the expression
4110
4111 @example
4112 zeros (3, 0)
4113 @end example
4114
4115 @noindent
4116 will print
4117
4118 @example
4119 ans = [](3x0)
4120 @end example
4121
4122 When called from inside a function with the @qcode{"local"} option, the
4123 variable is changed locally for the function and any subroutines it calls.
4124 The original variable value is restored when exiting the function.
4125 @seealso{format}
4126 @end deftypefn */)
4127 {
4128 return SET_INTERNAL_VARIABLE (print_empty_dimensions);
4129 }
4130
4131 DEFUN (split_long_rows, args, nargout,
4132 doc: /* -*- texinfo -*-
4133 @deftypefn {} {@var{val} =} split_long_rows ()
4134 @deftypefnx {} {@var{old_val} =} split_long_rows (@var{new_val})
4135 @deftypefnx {} {} split_long_rows (@var{new_val}, "local")
4136 Query or set the internal variable that controls whether rows of a matrix
4137 may be split when displayed to a terminal window.
4138
4139 If the rows are split, Octave will display the matrix in a series of smaller
4140 pieces, each of which can fit within the limits of your terminal width and
4141 each set of rows is labeled so that you can easily see which columns are
4142 currently being displayed. For example:
4143
4144 @example
4145 @group
4146 octave:13> rand (2,10)
4147 ans =
4148
4149 Columns 1 through 6:
4150
4151 0.75883 0.93290 0.40064 0.43818 0.94958 0.16467
4152 0.75697 0.51942 0.40031 0.61784 0.92309 0.40201
4153
4154 Columns 7 through 10:
4155
4156 0.90174 0.11854 0.72313 0.73326
4157 0.44672 0.94303 0.56564 0.82150
4158 @end group
4159 @end example
4160
4161 When called from inside a function with the @qcode{"local"} option, the
4162 variable is changed locally for the function and any subroutines it calls.
4163 The original variable value is restored when exiting the function.
4164 @seealso{format}
4165 @end deftypefn */)
4166 {
4167 return SET_INTERNAL_VARIABLE (split_long_rows);
4168 }
4169