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