GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
pt-mat.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2013 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 #include <iostream>
28 
29 #include "quit.h"
30 
31 #include "data.h"
32 #include "defun.h"
33 #include "error.h"
34 #include "oct-obj.h"
35 #include "pt-arg-list.h"
36 #include "pt-bp.h"
37 #include "pt-exp.h"
38 #include "pt-mat.h"
39 #include "pt-walk.h"
40 #include "utils.h"
41 #include "ov.h"
42 #include "variables.h"
43 
44 #include "ov-cx-mat.h"
45 #include "ov-flt-cx-mat.h"
46 #include "ov-re-sparse.h"
47 #include "ov-cx-sparse.h"
48 
49 // The character to fill with when creating string arrays.
50 char Vstring_fill_char = ' ';
51 
52 // General matrices. This list type is much more work to handle than
53 // constant matrices, but it allows us to construct matrices from
54 // other matrices, variables, and functions.
55 
56 // But first, some internal classes that make our job much easier.
57 
58 class
60 {
61 private:
62 
63  class
65  {
66  public:
67 
69  : count (1), dv (0, 0), all_str (false),
70  all_sq_str (false), all_dq_str (false),
71  some_str (false), all_real (false), all_cmplx (false),
72  all_mt (true), any_cell (false), any_sparse (false),
73  any_class (false), all_1x1 (false),
74  first_elem_is_struct (false), class_nm (), ok (false)
75  { }
76 
78  : count (1), dv (0, 0), all_str (false), all_sq_str (false),
79  some_str (false), all_real (false), all_cmplx (false),
80  all_mt (true), any_cell (false), any_sparse (false),
81  any_class (false), all_1x1 (! row.empty ()),
82  first_elem_is_struct (false), class_nm (), ok (false)
83  { init (row); }
84 
85  ~tm_row_const_rep (void) { }
86 
88 
90 
91  bool all_str;
92  bool all_sq_str;
93  bool all_dq_str;
94  bool some_str;
95  bool all_real;
96  bool all_cmplx;
97  bool all_mt;
98  bool any_cell;
99  bool any_sparse;
100  bool any_class;
101  bool all_1x1;
103 
104  std::string class_nm;
105 
106  bool ok;
107 
108  void do_init_element (const octave_value&, bool&);
109 
110  void init (const tree_argument_list&);
111 
112  void cellify (void);
113 
114  private:
115 
117 
118  tm_row_const_rep& operator = (const tm_row_const_rep&);
119 
120  };
121 
122 public:
123 
126 
128  : rep (0) { }
129 
131  : rep (new tm_row_const_rep (row)) { }
132 
134  : rep (x.rep)
135  {
136  if (rep)
137  rep->count++;
138  }
139 
140  tm_row_const& operator = (const tm_row_const& x)
141  {
142  if (this != &x && rep != x.rep)
143  {
144  if (rep && --rep->count == 0)
145  delete rep;
146 
147  rep = x.rep;
148 
149  if (rep)
150  rep->count++;
151  }
152 
153  return *this;
154  }
155 
156  ~tm_row_const (void)
157  {
158  if (rep && --rep->count == 0)
159  delete rep;
160  }
161 
162  octave_idx_type rows (void) { return rep->dv(0); }
163  octave_idx_type cols (void) { return rep->dv(1); }
164 
165  bool empty (void) const { return rep->empty (); }
166 
167  size_t length (void) const { return rep->length (); }
168 
169  dim_vector dims (void) { return rep->dv; }
170 
171  bool all_strings_p (void) const { return rep->all_str; }
172  bool all_sq_strings_p (void) const { return rep->all_sq_str; }
173  bool all_dq_strings_p (void) const { return rep->all_dq_str; }
174  bool some_strings_p (void) const { return rep->some_str; }
175  bool all_real_p (void) const { return rep->all_real; }
176  bool all_complex_p (void) const { return rep->all_cmplx; }
177  bool all_empty_p (void) const { return rep->all_mt; }
178  bool any_cell_p (void) const { return rep->any_cell; }
179  bool any_sparse_p (void) const { return rep->any_sparse; }
180  bool any_class_p (void) const { return rep->any_class; }
181  bool all_1x1_p (void) const { return rep->all_1x1; }
182  bool first_elem_struct_p (void) const { return rep->first_elem_is_struct; }
183 
184  std::string class_name (void) const { return rep->class_nm; }
185 
186  void cellify (void) { rep->cellify (); }
187 
188  operator bool () const { return (rep && rep->ok); }
189 
190  iterator begin (void) { return rep->begin (); }
191  const_iterator begin (void) const { return rep->begin (); }
192 
193  iterator end (void) { return rep->end (); }
194  const_iterator end (void) const { return rep->end (); }
195 
196 private:
197 
199 };
200 
201 std::string
202 get_concat_class (const std::string& c1, const std::string& c2)
203 {
204  std::string retval = octave_base_value::static_class_name ();
205 
206  if (c1 == c2)
207  retval = c1;
208  else if (c1.empty ())
209  retval = c2;
210  else if (c2.empty ())
211  retval = c1;
212  else if (c1 == "class" || c2 == "class")
213  retval = "class";
214  else
215  {
216  bool c1_is_int = (c1 == "int8" || c1 == "uint8"
217  || c1 == "int16" || c1 == "uint16"
218  || c1 == "int32" || c1 == "uint32"
219  || c1 == "int64" || c1 == "uint64");
220  bool c2_is_int = (c2 == "int8" || c2 == "uint8"
221  || c2 == "int16" || c2 == "uint16"
222  || c2 == "int32" || c2 == "uint32"
223  || c2 == "int64" || c2 == "uint64");
224 
225  bool c1_is_char = (c1 == "char");
226  bool c2_is_char = (c2 == "char");
227 
228  bool c1_is_double = (c1 == "double");
229  bool c2_is_double = (c2 == "double");
230 
231  bool c1_is_single = (c1 == "single");
232  bool c2_is_single = (c2 == "single");
233 
234  bool c1_is_logical = (c1 == "logical");
235  bool c2_is_logical = (c2 == "logical");
236 
237  bool c1_is_built_in_type
238  = (c1_is_int || c1_is_char || c1_is_double || c1_is_single
239  || c1_is_logical);
240 
241  bool c2_is_built_in_type
242  = (c2_is_int || c2_is_char || c2_is_double || c2_is_single
243  || c2_is_logical);
244 
245  // Order is important here...
246 
247  if (c1 == "struct" && c2 == c1)
248  retval = c1;
249  else if (c1 == "cell" || c2 == "cell")
250  retval = "cell";
251  else if (c1_is_char && c2_is_built_in_type)
252  retval = c1;
253  else if (c2_is_char && c1_is_built_in_type)
254  retval = c2;
255  else if (c1_is_int && c2_is_built_in_type)
256  retval = c1;
257  else if (c2_is_int && c1_is_built_in_type)
258  retval = c2;
259  else if (c1_is_single && c2_is_built_in_type)
260  retval = c1;
261  else if (c2_is_single && c1_is_built_in_type)
262  retval = c2;
263  else if (c1_is_double && c2_is_built_in_type)
264  retval = c1;
265  else if (c2_is_double && c1_is_built_in_type)
266  retval = c2;
267  else if (c1_is_logical && c2_is_logical)
268  retval = c1;
269  }
270 
271  return retval;
272 }
273 
274 static void
275 eval_error (const char *msg, const dim_vector& x, const dim_vector& y)
276 {
277  ::error ("%s (%s vs %s)", msg, x.str ().c_str (), y.str ().c_str ());
278 }
279 
280 void
282  bool& first_elem)
283 {
284  std::string this_elt_class_nm
285  = val.is_object () ? std::string ("class") : val.class_name ();
286 
287  class_nm = get_concat_class (class_nm, this_elt_class_nm);
288 
289  dim_vector this_elt_dv = val.dims ();
290 
291  if (! this_elt_dv.zero_by_zero ())
292  {
293  all_mt = false;
294 
295  if (first_elem)
296  {
297  if (val.is_map ())
298  first_elem_is_struct = true;
299 
300  first_elem = false;
301  }
302  }
303 
304  append (val);
305 
306  if (all_str && ! val.is_string ())
307  all_str = false;
308 
309  if (all_sq_str && ! val.is_sq_string ())
310  all_sq_str = false;
311 
312  if (all_dq_str && ! val.is_dq_string ())
313  all_dq_str = false;
314 
315  if (! some_str && val.is_string ())
316  some_str = true;
317 
318  if (all_real && ! val.is_real_type ())
319  all_real = false;
320 
321  if (all_cmplx && ! (val.is_complex_type () || val.is_real_type ()))
322  all_cmplx = false;
323 
324  if (!any_cell && val.is_cell ())
325  any_cell = true;
326 
327  if (!any_sparse && val.is_sparse_type ())
328  any_sparse = true;
329 
330  if (!any_class && val.is_object ())
331  any_class = true;
332 
333  // Special treatment of sparse matrices to avoid out-of-memory error
334  all_1x1 = all_1x1 && ! val.is_sparse_type () && val.numel () == 1;
335 }
336 
337 void
339 {
340  all_str = true;
341  all_sq_str = true;
342  all_dq_str = true;
343  all_real = true;
344  all_cmplx = true;
345  any_cell = false;
346  any_sparse = false;
347  any_class = false;
348 
349  bool first_elem = true;
350 
352  p != row.end ();
353  p++)
354  {
355  octave_quit ();
356 
357  tree_expression *elt = *p;
358 
359  octave_value tmp = elt->rvalue1 ();
360 
361  if (error_state || tmp.is_undefined ())
362  {
363  ok = ! error_state;
364  return;
365  }
366  else
367  {
368  if (tmp.is_cs_list ())
369  {
370  octave_value_list tlst = tmp.list_value ();
371 
372  for (octave_idx_type i = 0; i < tlst.length (); i++)
373  {
374  octave_quit ();
375 
376  do_init_element (tlst(i), first_elem);
377  }
378  }
379  else
380  do_init_element (tmp, first_elem);
381  }
382  }
383 
384  if (any_cell && ! any_class && ! first_elem_is_struct)
385  cellify ();
386 
387  first_elem = true;
388 
389  for (iterator p = begin (); p != end (); p++)
390  {
391  octave_quit ();
392 
393  octave_value val = *p;
394 
395  dim_vector this_elt_dv = val.dims ();
396 
397  if (! this_elt_dv.zero_by_zero ())
398  {
399  all_mt = false;
400 
401  if (first_elem)
402  {
403  first_elem = false;
404  dv = this_elt_dv;
405  }
406  else if ((! any_class) && (! dv.hvcat (this_elt_dv, 1)))
407  {
408  eval_error ("horizontal dimensions mismatch", dv, this_elt_dv);
409  break;
410  }
411  }
412  }
413 
414  ok = ! error_state;
415 }
416 
417 void
419 {
420  bool elt_changed = false;
421 
422  for (iterator p = begin (); p != end (); p++)
423  {
424  octave_quit ();
425 
426  if (! p->is_cell ())
427  {
428  elt_changed = true;
429 
430  *p = Cell (*p);
431  }
432  }
433 
434  if (elt_changed)
435  {
436  bool first_elem = true;
437 
438  for (iterator p = begin (); p != end (); p++)
439  {
440  octave_quit ();
441 
442  octave_value val = *p;
443 
444  dim_vector this_elt_dv = val.dims ();
445 
446  if (! this_elt_dv.zero_by_zero ())
447  {
448  if (first_elem)
449  {
450  first_elem = false;
451  dv = this_elt_dv;
452  }
453  else if (! dv.hvcat (this_elt_dv, 1))
454  {
455  eval_error ("horizontal dimensions mismatch",
456  dv, this_elt_dv);
457  break;
458  }
459  }
460  }
461  }
462 }
463 
464 class
466 {
467 public:
468 
469  tm_const (const tree_matrix& tm)
470  : dv (0, 0), all_str (false), all_sq_str (false), all_dq_str (false),
471  some_str (false), all_real (false), all_cmplx (false),
472  all_mt (true), any_cell (false), any_sparse (false),
473  any_class (false), class_nm (), ok (false)
474  { init (tm); }
475 
476  ~tm_const (void) { }
477 
478  octave_idx_type rows (void) const { return dv.elem (0); }
479  octave_idx_type cols (void) const { return dv.elem (1); }
480 
481  dim_vector dims (void) const { return dv; }
482 
483  bool all_strings_p (void) const { return all_str; }
484  bool all_sq_strings_p (void) const { return all_sq_str; }
485  bool all_dq_strings_p (void) const { return all_dq_str; }
486  bool some_strings_p (void) const { return some_str; }
487  bool all_real_p (void) const { return all_real; }
488  bool all_complex_p (void) const { return all_cmplx; }
489  bool all_empty_p (void) const { return all_mt; }
490  bool any_cell_p (void) const { return any_cell; }
491  bool any_sparse_p (void) const { return any_sparse; }
492  bool any_class_p (void) const { return any_class; }
493  bool all_1x1_p (void) const { return all_1x1; }
494 
495  std::string class_name (void) const { return class_nm; }
496 
497  operator bool () const { return ok; }
498 
499 private:
500 
502 
503  bool all_str;
506  bool some_str;
507  bool all_real;
508  bool all_cmplx;
509  bool all_mt;
510  bool any_cell;
512  bool any_class;
513  bool all_1x1;
514 
515  std::string class_nm;
516 
517  bool ok;
518 
519  tm_const (void);
520 
521  tm_const (const tm_const&);
522 
523  tm_const& operator = (const tm_const&);
524 
525  void init (const tree_matrix& tm);
526 };
527 
528 void
530 {
531  all_str = true;
532  all_sq_str = true;
533  all_dq_str = true;
534  all_real = true;
535  all_cmplx = true;
536  any_cell = false;
537  any_sparse = false;
538  any_class = false;
539  all_1x1 = ! tm.empty ();
540 
541  bool first_elem = true;
542  bool first_elem_is_struct = false;
543 
544  // Just eval and figure out if what we have is complex or all
545  // strings. We can't check columns until we know that this is a
546  // numeric matrix -- collections of strings can have elements of
547  // different lengths.
548 
549  for (tree_matrix::const_iterator p = tm.begin (); p != tm.end (); p++)
550  {
551  octave_quit ();
552 
553  tree_argument_list *elt = *p;
554 
555  tm_row_const tmp (*elt);
556 
557  if (first_elem)
558  {
559  first_elem_is_struct = tmp.first_elem_struct_p ();
560 
561  first_elem = false;
562  }
563 
564  if (tmp && ! tmp.empty ())
565  {
566  if (all_str && ! tmp.all_strings_p ())
567  all_str = false;
568 
569  if (all_sq_str && ! tmp.all_sq_strings_p ())
570  all_sq_str = false;
571 
572  if (all_dq_str && ! tmp.all_dq_strings_p ())
573  all_dq_str = false;
574 
575  if (! some_str && tmp.some_strings_p ())
576  some_str = true;
577 
578  if (all_real && ! tmp.all_real_p ())
579  all_real = false;
580 
581  if (all_cmplx && ! tmp.all_complex_p ())
582  all_cmplx = false;
583 
584  if (all_mt && ! tmp.all_empty_p ())
585  all_mt = false;
586 
587  if (!any_cell && tmp.any_cell_p ())
588  any_cell = true;
589 
590  if (!any_sparse && tmp.any_sparse_p ())
591  any_sparse = true;
592 
593  if (!any_class && tmp.any_class_p ())
594  any_class = true;
595 
596  all_1x1 = all_1x1 && tmp.all_1x1_p ();
597 
598  append (tmp);
599  }
600  else
601  break;
602  }
603 
604  if (! error_state)
605  {
606  if (any_cell && ! any_class && ! first_elem_is_struct)
607  {
608  for (iterator q = begin (); q != end (); q++)
609  {
610  octave_quit ();
611 
612  q->cellify ();
613  }
614  }
615 
616  first_elem = true;
617 
618  for (iterator q = begin (); q != end (); q++)
619  {
620  octave_quit ();
621 
622  tm_row_const elt = *q;
623 
624  octave_idx_type this_elt_nr = elt.rows ();
625  octave_idx_type this_elt_nc = elt.cols ();
626 
627  std::string this_elt_class_nm = elt.class_name ();
628  class_nm = get_concat_class (class_nm, this_elt_class_nm);
629 
630  dim_vector this_elt_dv = elt.dims ();
631 
632  all_mt = false;
633 
634  if (first_elem)
635  {
636  first_elem = false;
637 
638  dv = this_elt_dv;
639  }
640  else if (all_str && dv.length () == 2
641  && this_elt_dv.length () == 2)
642  {
643  // FIXME: this is Octave's specialty. Character matrices allow
644  // rows of unequal length.
645  if (this_elt_nc > cols ())
646  dv(1) = this_elt_nc;
647  dv(0) += this_elt_nr;
648  }
649  else if ((!any_class) && (!dv.hvcat (this_elt_dv, 0)))
650  {
651  eval_error ("vertical dimensions mismatch", dv, this_elt_dv);
652  return;
653  }
654  }
655  }
656 
657  ok = ! error_state;
658 }
659 
661 tree_matrix::rvalue (int nargout)
662 {
663  octave_value_list retval;
664 
665  if (nargout > 1)
666  error ("invalid number of output arguments for matrix list");
667  else
668  retval = rvalue1 (nargout);
669 
670  return retval;
671 }
672 
673 void
675 {
676  if (! (all_dq_strings_p || all_sq_strings_p))
677  warning_with_id ("Octave:mixed-string-concat",
678  "concatenation of different character string types may have unintended consequences");
679 }
680 
681 template<class TYPE, class T>
682 static void
684  tm_const& tmp)
685 {
686  octave_idx_type r = 0, c = 0;
687 
688  for (tm_const::iterator p = tmp.begin (); p != tmp.end (); p++)
689  {
690  tm_row_const row = *p;
691  // Skip empty arrays to allow looser rules.
692  if (row.dims ().any_zero ())
693  continue;
694 
695  for (tm_row_const::iterator q = row.begin ();
696  q != row.end ();
697  q++)
698  {
699  octave_quit ();
700 
701  TYPE ra = octave_value_extract<TYPE> (*q);
702 
703  // Skip empty arrays to allow looser rules.
704  if (! error_state)
705  {
706  if (! ra.is_empty ())
707  {
708  result.insert (ra, r, c);
709 
710  if (! error_state)
711  c += ra.columns ();
712  else
713  return;
714  }
715  }
716  else
717  return;
718  }
719 
720  r += row.rows ();
721  c = 0;
722  }
723 }
724 
725 template<class TYPE, class T>
726 static void
728  const dim_vector& dv,
729  tm_const& tmp)
730 {
731  if (dv.any_zero ())
732  {
733  result = Array<T> (dv);
734  return;
735  }
736 
737  if (tmp.length () == 1)
738  {
739  // If possible, forward the operation to liboctave.
740  // Single row.
741  tm_row_const& row = tmp.front ();
743  && row.all_1x1_p ())
744  {
745  // Optimize all scalars case.
746  result.clear (dv);
747  assert (static_cast<size_t> (result.numel ()) == row.length ());
748  octave_idx_type i = 0;
749  for (tm_row_const::iterator q = row.begin ();
750  q != row.end () && ! error_state; q++)
751  result(i++) = octave_value_extract<T> (*q);
752 
753  return;
754  }
755 
756  octave_idx_type ncols = row.length (), i = 0;
757  OCTAVE_LOCAL_BUFFER (Array<T>, array_list, ncols);
758 
759  for (tm_row_const::iterator q = row.begin ();
760  q != row.end () && ! error_state;
761  q++)
762  {
763  octave_quit ();
764 
765  array_list[i] = octave_value_extract<TYPE> (*q);
766  i++;
767  }
768 
769  if (! error_state)
770  result = Array<T>::cat (-2, ncols, array_list);
771  }
772  else
773  {
774  result = Array<T> (dv);
775  single_type_concat<TYPE> (result, tmp);
776  }
777 }
778 
779 template<class TYPE, class T>
780 static void
782  const dim_vector& dv,
783  tm_const& tmp)
784 {
785  if (dv.any_zero ())
786  {
787  result = Sparse<T> (dv);
788  return;
789  }
790 
791  // Sparse matrices require preallocation for efficient indexing; besides,
792  // only horizontal concatenation can be efficiently handled by indexing.
793  // So we just cat all rows through liboctave, then cat the final column.
794  octave_idx_type nrows = tmp.length (), j = 0;
795  OCTAVE_LOCAL_BUFFER (Sparse<T>, sparse_row_list, nrows);
796  for (tm_const::iterator p = tmp.begin (); p != tmp.end (); p++)
797  {
798  tm_row_const row = *p;
799  octave_idx_type ncols = row.length (), i = 0;
800  OCTAVE_LOCAL_BUFFER (Sparse<T>, sparse_list, ncols);
801 
802  for (tm_row_const::iterator q = row.begin ();
803  q != row.end () && ! error_state;
804  q++)
805  {
806  octave_quit ();
807 
808  sparse_list[i] = octave_value_extract<TYPE> (*q);
809  i++;
810  }
811 
812  Sparse<T> stmp = Sparse<T>::cat (-2, ncols, sparse_list);
813  sparse_row_list[j] = stmp;
814  j++;
815  }
816 
817  result = Sparse<T>::cat (-1, nrows, sparse_row_list);
818 }
819 
820 template<class MAP>
821 static void
823  const dim_vector& dv,
824  tm_const& tmp)
825 {
826  if (dv.any_zero ())
827  {
828  result = octave_map (dv);
829  return;
830  }
831 
832  octave_idx_type nrows = tmp.length (), j = 0;
833  OCTAVE_LOCAL_BUFFER (octave_map, map_row_list, nrows);
834  for (tm_const::iterator p = tmp.begin (); p != tmp.end (); p++)
835  {
836  tm_row_const row = *p;
837  octave_idx_type ncols = row.length (), i = 0;
838  OCTAVE_LOCAL_BUFFER (MAP, map_list, ncols);
839 
840  for (tm_row_const::iterator q = row.begin ();
841  q != row.end () && ! error_state;
842  q++)
843  {
844  octave_quit ();
845 
846  map_list[i] = octave_value_extract<MAP> (*q);
847  i++;
848  }
849 
850  octave_map mtmp = octave_map::cat (-2, ncols, map_list);
851  map_row_list[j] = mtmp;
852  j++;
853  }
854 
855  result = octave_map::cat (-1, nrows, map_row_list);
856 }
857 
858 template<class TYPE>
859 static octave_value
861  tm_const& tmp)
862 {
863  TYPE result;
864 
865  single_type_concat<TYPE> (result, dv, tmp);
866 
867  return result;
868 }
869 
870 template<>
873  tm_const& tmp)
874 {
875  octave_map result;
876 
877  if (tmp.all_1x1_p ())
878  single_type_concat<octave_scalar_map> (result, dv, tmp);
879  else
880  single_type_concat<octave_map> (result, dv, tmp);
881 
882  return result;
883 }
884 
885 static octave_value
887 {
888  octave_value retval;
889 
891 
892  octave_idx_type j = 0;
893  for (tm_const::iterator p = tmc.begin (); p != tmc.end (); p++)
894  {
895  octave_quit ();
896 
897  tm_row_const tmrc = *p;
898 
899  if (tmrc.length () == 1)
900  rows(j++) = *(tmrc.begin ());
901  else
902  {
903  octave_value_list row (tmrc.length (), octave_value ());
904 
905  octave_idx_type i = 0;
906  for (tm_row_const::iterator q = tmrc.begin (); q != tmrc.end (); q++)
907  row(i++) = *q;
908 
909  rows(j++) = do_class_concat (row, "horzcat", 1);
910  }
911  }
912 
913  if (! error_state)
914  {
915  if (rows.length () == 1)
916  retval = rows(0);
917  else
918  retval = do_class_concat (rows, "vertcat", 0);
919  }
920 
921  return retval;
922 }
923 
926 {
927  octave_value retval = Matrix ();
928 
929  bool all_sq_strings_p = false;
930  bool all_dq_strings_p = false;
931  bool all_empty_p = false;
932  bool all_real_p = false;
933  bool any_sparse_p = false;
934  bool any_class_p = false;
935  bool frc_str_conv = false;
936 
937  tm_const tmp (*this);
938 
939  if (tmp && ! tmp.empty ())
940  {
941  dim_vector dv = tmp.dims ();
942  all_sq_strings_p = tmp.all_sq_strings_p ();
943  all_dq_strings_p = tmp.all_dq_strings_p ();
944  all_empty_p = tmp.all_empty_p ();
945  all_real_p = tmp.all_real_p ();
946  any_sparse_p = tmp.any_sparse_p ();
947  any_class_p = tmp.any_class_p ();
948  frc_str_conv = tmp.some_strings_p ();
949 
950  // Try to speed up the common cases.
951 
952  std::string result_type = tmp.class_name ();
953 
954  if (any_class_p)
955  {
956  retval = do_class_concat (tmp);
957  }
958  else if (result_type == "double")
959  {
960  if (any_sparse_p)
961  {
962  if (all_real_p)
963  retval = do_single_type_concat<SparseMatrix> (dv, tmp);
964  else
965  retval = do_single_type_concat<SparseComplexMatrix> (dv, tmp);
966  }
967  else
968  {
969  if (all_real_p)
970  retval = do_single_type_concat<NDArray> (dv, tmp);
971  else
972  retval = do_single_type_concat<ComplexNDArray> (dv, tmp);
973  }
974  }
975  else if (result_type == "single")
976  {
977  if (all_real_p)
978  retval = do_single_type_concat<FloatNDArray> (dv, tmp);
979  else
980  retval = do_single_type_concat<FloatComplexNDArray> (dv, tmp);
981  }
982  else if (result_type == "char")
983  {
984  char type = all_dq_strings_p ? '"' : '\'';
985 
986  maybe_warn_string_concat (all_dq_strings_p, all_sq_strings_p);
987 
988  charNDArray result (dv, Vstring_fill_char);
989 
990  single_type_concat<charNDArray> (result, tmp);
991 
992  retval = octave_value (result, type);
993  }
994  else if (result_type == "logical")
995  {
996  if (any_sparse_p)
997  retval = do_single_type_concat<SparseBoolMatrix> (dv, tmp);
998  else
999  retval = do_single_type_concat<boolNDArray> (dv, tmp);
1000  }
1001  else if (result_type == "int8")
1002  retval = do_single_type_concat<int8NDArray> (dv, tmp);
1003  else if (result_type == "int16")
1004  retval = do_single_type_concat<int16NDArray> (dv, tmp);
1005  else if (result_type == "int32")
1006  retval = do_single_type_concat<int32NDArray> (dv, tmp);
1007  else if (result_type == "int64")
1008  retval = do_single_type_concat<int64NDArray> (dv, tmp);
1009  else if (result_type == "uint8")
1010  retval = do_single_type_concat<uint8NDArray> (dv, tmp);
1011  else if (result_type == "uint16")
1012  retval = do_single_type_concat<uint16NDArray> (dv, tmp);
1013  else if (result_type == "uint32")
1014  retval = do_single_type_concat<uint32NDArray> (dv, tmp);
1015  else if (result_type == "uint64")
1016  retval = do_single_type_concat<uint64NDArray> (dv, tmp);
1017  else if (result_type == "cell")
1018  retval = do_single_type_concat<Cell> (dv, tmp);
1019  else if (result_type == "struct")
1020  retval = do_single_type_concat<octave_map> (dv, tmp);
1021  else
1022  {
1023  // The line below might seem crazy, since we take a copy of
1024  // the first argument, resize it to be empty and then resize
1025  // it to be full. This is done since it means that there is
1026  // no recopying of data, as would happen if we used a single
1027  // resize. It should be noted that resize operation is also
1028  // significantly slower than the do_cat_op function, so it
1029  // makes sense to have an empty matrix and copy all data.
1030  //
1031  // We might also start with a empty octave_value using
1032  //
1033  // ctmp = octave_value_typeinfo::lookup_type
1034  // (tmp.begin() -> begin() -> type_name());
1035  //
1036  // and then directly resize. However, for some types there
1037  // might be some additional setup needed, and so this should
1038  // be avoided.
1039 
1040  octave_value ctmp;
1041 
1042  // Find the first non-empty object
1043 
1044  if (any_sparse_p)
1045  {
1046  // Start with sparse matrix to avoid issues memory issues
1047  // with things like [ones(1,4),sprandn(1e8,4,1e-4)]
1048  if (all_real_p)
1049  ctmp = octave_sparse_matrix ().resize (dv);
1050  else
1051  ctmp = octave_sparse_complex_matrix ().resize (dv);
1052  }
1053  else
1054  {
1055  for (tm_const::iterator p = tmp.begin (); p != tmp.end (); p++)
1056  {
1057  octave_quit ();
1058 
1059  tm_row_const row = *p;
1060 
1061  for (tm_row_const::iterator q = row.begin ();
1062  q != row.end (); q++)
1063  {
1064  octave_quit ();
1065 
1066  ctmp = *q;
1067 
1068  if (! ctmp.all_zero_dims ())
1069  goto found_non_empty;
1070  }
1071  }
1072 
1073  ctmp = (*(tmp.begin () -> begin ()));
1074 
1075  found_non_empty:
1076 
1077  if (! all_empty_p)
1078  ctmp = ctmp.resize (dim_vector (0,0)).resize (dv);
1079  }
1080 
1081  if (! error_state)
1082  {
1083  // Now, extract the values from the individual elements and
1084  // insert them in the result matrix.
1085 
1086  int dv_len = dv.length ();
1087  octave_idx_type ntmp = dv_len > 1 ? dv_len : 2;
1088  Array<octave_idx_type> ra_idx (dim_vector (ntmp, 1), 0);
1089 
1090  for (tm_const::iterator p = tmp.begin (); p != tmp.end (); p++)
1091  {
1092  octave_quit ();
1093 
1094  tm_row_const row = *p;
1095 
1096  for (tm_row_const::iterator q = row.begin ();
1097  q != row.end ();
1098  q++)
1099  {
1100  octave_quit ();
1101 
1102  octave_value elt = *q;
1103 
1104  if (elt.is_empty ())
1105  continue;
1106 
1107  ctmp = do_cat_op (ctmp, elt, ra_idx);
1108 
1109  if (error_state)
1110  goto done;
1111 
1112  ra_idx (1) += elt.columns ();
1113  }
1114 
1115  ra_idx (0) += row.rows ();
1116  ra_idx (1) = 0;
1117  }
1118 
1119  retval = ctmp;
1120 
1121  if (frc_str_conv && ! retval.is_string ())
1122  retval = retval.convert_to_str ();
1123  }
1124  }
1125  }
1126 
1127 done:
1128  return retval;
1129 }
1130 
1134 {
1135  tree_matrix *new_matrix = new tree_matrix (0, line (), column ());
1136 
1137  new_matrix->copy_base (*this, scope, context);
1138 
1139  return new_matrix;
1140 }
1141 
1142 void
1144 {
1145  tw.visit_matrix (*this);
1146 }
1147 
1148 /*
1149 ## test concatenation with all zero matrices
1150 %!assert ([ "" 65*ones(1,10) ], "AAAAAAAAAA");
1151 %!assert ([ 65*ones(1,10) "" ], "AAAAAAAAAA");
1152 
1153 %!test
1154 %! c = {"foo"; "bar"; "bazoloa"};
1155 %! assert ([c; "a"; "bc"; "def"], {"foo"; "bar"; "bazoloa"; "a"; "bc"; "def"});
1156 
1157 %!assert (class ([int64(1), int64(1)]), "int64")
1158 %!assert (class ([int64(1), int32(1)]), "int64")
1159 %!assert (class ([int64(1), int16(1)]), "int64")
1160 %!assert (class ([int64(1), int8(1)]), "int64")
1161 %!assert (class ([int64(1), uint64(1)]), "int64")
1162 %!assert (class ([int64(1), uint32(1)]), "int64")
1163 %!assert (class ([int64(1), uint16(1)]), "int64")
1164 %!assert (class ([int64(1), uint8(1)]), "int64")
1165 %!assert (class ([int64(1), single(1)]), "int64")
1166 %!assert (class ([int64(1), double(1)]), "int64")
1167 %!assert (class ([int64(1), cell(1)]), "cell")
1168 %!assert (class ([int64(1), true]), "int64")
1169 %!assert (class ([int64(1), "a"]), "char")
1170 
1171 %!assert (class ([int32(1), int64(1)]), "int32")
1172 %!assert (class ([int32(1), int32(1)]), "int32")
1173 %!assert (class ([int32(1), int16(1)]), "int32")
1174 %!assert (class ([int32(1), int8(1)]), "int32")
1175 %!assert (class ([int32(1), uint64(1)]), "int32")
1176 %!assert (class ([int32(1), uint32(1)]), "int32")
1177 %!assert (class ([int32(1), uint16(1)]), "int32")
1178 %!assert (class ([int32(1), uint8(1)]), "int32")
1179 %!assert (class ([int32(1), single(1)]), "int32")
1180 %!assert (class ([int32(1), double(1)]), "int32")
1181 %!assert (class ([int32(1), cell(1)]), "cell")
1182 %!assert (class ([int32(1), true]), "int32")
1183 %!assert (class ([int32(1), "a"]), "char")
1184 
1185 %!assert (class ([int16(1), int64(1)]), "int16")
1186 %!assert (class ([int16(1), int32(1)]), "int16")
1187 %!assert (class ([int16(1), int16(1)]), "int16")
1188 %!assert (class ([int16(1), int8(1)]), "int16")
1189 %!assert (class ([int16(1), uint64(1)]), "int16")
1190 %!assert (class ([int16(1), uint32(1)]), "int16")
1191 %!assert (class ([int16(1), uint16(1)]), "int16")
1192 %!assert (class ([int16(1), uint8(1)]), "int16")
1193 %!assert (class ([int16(1), single(1)]), "int16")
1194 %!assert (class ([int16(1), double(1)]), "int16")
1195 %!assert (class ([int16(1), cell(1)]), "cell")
1196 %!assert (class ([int16(1), true]), "int16")
1197 %!assert (class ([int16(1), "a"]), "char")
1198 
1199 %!assert (class ([int8(1), int64(1)]), "int8")
1200 %!assert (class ([int8(1), int32(1)]), "int8")
1201 %!assert (class ([int8(1), int16(1)]), "int8")
1202 %!assert (class ([int8(1), int8(1)]), "int8")
1203 %!assert (class ([int8(1), uint64(1)]), "int8")
1204 %!assert (class ([int8(1), uint32(1)]), "int8")
1205 %!assert (class ([int8(1), uint16(1)]), "int8")
1206 %!assert (class ([int8(1), uint8(1)]), "int8")
1207 %!assert (class ([int8(1), single(1)]), "int8")
1208 %!assert (class ([int8(1), double(1)]), "int8")
1209 %!assert (class ([int8(1), cell(1)]), "cell")
1210 %!assert (class ([int8(1), true]), "int8")
1211 %!assert (class ([int8(1), "a"]), "char")
1212 
1213 %!assert (class ([uint64(1), int64(1)]), "uint64")
1214 %!assert (class ([uint64(1), int32(1)]), "uint64")
1215 %!assert (class ([uint64(1), int16(1)]), "uint64")
1216 %!assert (class ([uint64(1), int8(1)]), "uint64")
1217 %!assert (class ([uint64(1), uint64(1)]), "uint64")
1218 %!assert (class ([uint64(1), uint32(1)]), "uint64")
1219 %!assert (class ([uint64(1), uint16(1)]), "uint64")
1220 %!assert (class ([uint64(1), uint8(1)]), "uint64")
1221 %!assert (class ([uint64(1), single(1)]), "uint64")
1222 %!assert (class ([uint64(1), double(1)]), "uint64")
1223 %!assert (class ([uint64(1), cell(1)]), "cell")
1224 %!assert (class ([uint64(1), true]), "uint64")
1225 %!assert (class ([uint64(1), "a"]), "char")
1226 
1227 %!assert (class ([uint32(1), int64(1)]), "uint32")
1228 %!assert (class ([uint32(1), int32(1)]), "uint32")
1229 %!assert (class ([uint32(1), int16(1)]), "uint32")
1230 %!assert (class ([uint32(1), int8(1)]), "uint32")
1231 %!assert (class ([uint32(1), uint64(1)]), "uint32")
1232 %!assert (class ([uint32(1), uint32(1)]), "uint32")
1233 %!assert (class ([uint32(1), uint16(1)]), "uint32")
1234 %!assert (class ([uint32(1), uint8(1)]), "uint32")
1235 %!assert (class ([uint32(1), single(1)]), "uint32")
1236 %!assert (class ([uint32(1), double(1)]), "uint32")
1237 %!assert (class ([uint32(1), cell(1)]), "cell")
1238 %!assert (class ([uint32(1), true]), "uint32")
1239 %!assert (class ([uint32(1), "a"]), "char")
1240 
1241 %!assert (class ([uint16(1), int64(1)]), "uint16")
1242 %!assert (class ([uint16(1), int32(1)]), "uint16")
1243 %!assert (class ([uint16(1), int16(1)]), "uint16")
1244 %!assert (class ([uint16(1), int8(1)]), "uint16")
1245 %!assert (class ([uint16(1), uint64(1)]), "uint16")
1246 %!assert (class ([uint16(1), uint32(1)]), "uint16")
1247 %!assert (class ([uint16(1), uint16(1)]), "uint16")
1248 %!assert (class ([uint16(1), uint8(1)]), "uint16")
1249 %!assert (class ([uint16(1), single(1)]), "uint16")
1250 %!assert (class ([uint16(1), double(1)]), "uint16")
1251 %!assert (class ([uint16(1), cell(1)]), "cell")
1252 %!assert (class ([uint16(1), true]), "uint16")
1253 %!assert (class ([uint16(1), "a"]), "char")
1254 
1255 %!assert (class ([uint8(1), int64(1)]), "uint8")
1256 %!assert (class ([uint8(1), int32(1)]), "uint8")
1257 %!assert (class ([uint8(1), int16(1)]), "uint8")
1258 %!assert (class ([uint8(1), int8(1)]), "uint8")
1259 %!assert (class ([uint8(1), uint64(1)]), "uint8")
1260 %!assert (class ([uint8(1), uint32(1)]), "uint8")
1261 %!assert (class ([uint8(1), uint16(1)]), "uint8")
1262 %!assert (class ([uint8(1), uint8(1)]), "uint8")
1263 %!assert (class ([uint8(1), single(1)]), "uint8")
1264 %!assert (class ([uint8(1), double(1)]), "uint8")
1265 %!assert (class ([uint8(1), cell(1)]), "cell")
1266 %!assert (class ([uint8(1), true]), "uint8")
1267 %!assert (class ([uint8(1), "a"]), "char")
1268 
1269 %!assert (class ([single(1), int64(1)]), "int64")
1270 %!assert (class ([single(1), int32(1)]), "int32")
1271 %!assert (class ([single(1), int16(1)]), "int16")
1272 %!assert (class ([single(1), int8(1)]), "int8")
1273 %!assert (class ([single(1), uint64(1)]), "uint64")
1274 %!assert (class ([single(1), uint32(1)]), "uint32")
1275 %!assert (class ([single(1), uint16(1)]), "uint16")
1276 %!assert (class ([single(1), uint8(1)]), "uint8")
1277 %!assert (class ([single(1), single(1)]), "single")
1278 %!assert (class ([single(1), double(1)]), "single")
1279 %!assert (class ([single(1), cell(1)]), "cell")
1280 %!assert (class ([single(1), true]), "single")
1281 %!assert (class ([single(1), "a"]), "char")
1282 
1283 %!assert (class ([double(1), int64(1)]), "int64")
1284 %!assert (class ([double(1), int32(1)]), "int32")
1285 %!assert (class ([double(1), int16(1)]), "int16")
1286 %!assert (class ([double(1), int8(1)]), "int8")
1287 %!assert (class ([double(1), uint64(1)]), "uint64")
1288 %!assert (class ([double(1), uint32(1)]), "uint32")
1289 %!assert (class ([double(1), uint16(1)]), "uint16")
1290 %!assert (class ([double(1), uint8(1)]), "uint8")
1291 %!assert (class ([double(1), single(1)]), "single")
1292 %!assert (class ([double(1), double(1)]), "double")
1293 %!assert (class ([double(1), cell(1)]), "cell")
1294 %!assert (class ([double(1), true]), "double")
1295 %!assert (class ([double(1), "a"]), "char")
1296 
1297 %!assert (class ([cell(1), int64(1)]), "cell")
1298 %!assert (class ([cell(1), int32(1)]), "cell")
1299 %!assert (class ([cell(1), int16(1)]), "cell")
1300 %!assert (class ([cell(1), int8(1)]), "cell")
1301 %!assert (class ([cell(1), uint64(1)]), "cell")
1302 %!assert (class ([cell(1), uint32(1)]), "cell")
1303 %!assert (class ([cell(1), uint16(1)]), "cell")
1304 %!assert (class ([cell(1), uint8(1)]), "cell")
1305 %!assert (class ([cell(1), single(1)]), "cell")
1306 %!assert (class ([cell(1), double(1)]), "cell")
1307 %!assert (class ([cell(1), cell(1)]), "cell")
1308 %!assert (class ([cell(1), true]), "cell")
1309 %!assert (class ([cell(1), "a"]), "cell")
1310 
1311 %!assert (class ([true, int64(1)]), "int64")
1312 %!assert (class ([true, int32(1)]), "int32")
1313 %!assert (class ([true, int16(1)]), "int16")
1314 %!assert (class ([true, int8(1)]), "int8")
1315 %!assert (class ([true, uint64(1)]), "uint64")
1316 %!assert (class ([true, uint32(1)]), "uint32")
1317 %!assert (class ([true, uint16(1)]), "uint16")
1318 %!assert (class ([true, uint8(1)]), "uint8")
1319 %!assert (class ([true, single(1)]), "single")
1320 %!assert (class ([true, double(1)]), "double")
1321 %!assert (class ([true, cell(1)]), "cell")
1322 %!assert (class ([true, true]), "logical")
1323 %!assert (class ([true, "a"]), "char")
1324 
1325 %!assert (class (["a", int64(1)]), "char")
1326 %!assert (class (["a", int32(1)]), "char")
1327 %!assert (class (["a", int16(1)]), "char")
1328 %!assert (class (["a", int8(1)]), "char")
1329 %!assert (class (["a", int64(1)]), "char")
1330 %!assert (class (["a", int32(1)]), "char")
1331 %!assert (class (["a", int16(1)]), "char")
1332 %!assert (class (["a", int8(1)]), "char")
1333 %!assert (class (["a", single(1)]), "char")
1334 %!assert (class (["a", double(1)]), "char")
1335 %!assert (class (["a", cell(1)]), "cell")
1336 %!assert (class (["a", true]), "char")
1337 %!assert (class (["a", "a"]), "char")
1338 
1339 %!assert (class ([cell(1), struct("foo", "bar")]), "cell")
1340 %!error [struct("foo", "bar"), cell(1)]
1341 
1342 %!assert ([,1], 1)
1343 %!assert ([1,], 1)
1344 %!assert ([,1,], 1)
1345 %!assert ([,1,;;], 1)
1346 %!assert ([,1,;,;], 1)
1347 
1348 %!assert ([1,1], ones (1, 2))
1349 %!assert ([,1,1], ones (1, 2))
1350 %!assert ([1,1,], ones (1, 2))
1351 %!assert ([,1,1,], ones (1, 2))
1352 %!assert ([,1,1,;;], ones (1, 2))
1353 %!assert ([,1,1,;,;], ones (1, 2))
1354 %!assert ([,;,1,1], ones (1, 2))
1355 
1356 %!assert ([1;1], ones (2, 1))
1357 %!assert ([1,;1], ones (2, 1))
1358 %!assert ([1,;,;1], ones (2, 1))
1359 
1360 %!error eval ("[,,]")
1361 %!error eval ("[,,;,]")
1362 %!error eval ("[,;,,;,]")
1363 
1364 %!assert (isnull ([,]))
1365 %!assert (isnull ([;]))
1366 %!assert (isnull ([;;]))
1367 %!assert (isnull ([;,;]))
1368 %!assert (isnull ([,;,;,]))
1369 */
1370 
1371 DEFUN (string_fill_char, args, nargout,
1372  "-*- texinfo -*-\n\
1373 @deftypefn {Built-in Function} {@var{val} =} string_fill_char ()\n\
1374 @deftypefnx {Built-in Function} {@var{old_val} =} string_fill_char (@var{new_val})\n\
1375 @deftypefnx {Built-in Function} {} string_fill_char (@var{new_val}, \"local\")\n\
1376 Query or set the internal variable used to pad all rows of a character\n\
1377 matrix to the same length. It must be a single character. The default\n\
1378 value is @qcode{\" \"} (a single space). For example:\n\
1379 \n\
1380 @example\n\
1381 @group\n\
1382 string_fill_char (\"X\");\n\
1383 [ \"these\"; \"are\"; \"strings\" ]\n\
1384  @result{} \"theseXX\"\n\
1385  \"areXXXX\"\n\
1386  \"strings\"\n\
1387 @end group\n\
1388 @end example\n\
1389 \n\
1390 When called from inside a function with the @qcode{\"local\"} option, the\n\
1391 variable is changed locally for the function and any subroutines it calls. \n\
1392 The original variable value is restored when exiting the function.\n\
1393 @end deftypefn")
1394 {
1395  return SET_INTERNAL_VARIABLE (string_fill_char);
1396 }
1397 
1398 /*
1399 ## string_fill_char() function call must be outside of %!test block
1400 ## due to the way a %!test block is wrapped inside a function
1401 %!shared orig_val, old_val
1402 %! orig_val = string_fill_char ();
1403 %! old_val = string_fill_char ("X");
1404 %!test
1405 %! assert (orig_val, old_val);
1406 %! assert (string_fill_char (), "X");
1407 %! assert (["these"; "are"; "strings"], ["theseXX"; "areXXXX"; "strings"]);
1408 %! string_fill_char (orig_val);
1409 %! assert (string_fill_char (), orig_val);
1410 
1411 %!error (string_fill_char (1, 2))
1412 */