GNU Octave  8.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
pt-tm-const.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1996-2023 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 "oct-locbuf.h"
31 #include "quit.h"
32 
33 #include "data.h"
34 #include "defun.h"
35 #include "error.h"
36 #include "errwarn.h"
37 #include "oct-map.h"
38 #include "ovl.h"
39 #include "pt-arg-list.h"
40 #include "pt-bp.h"
41 #include "pt-eval.h"
42 #include "pt-exp.h"
43 #include "pt-mat.h"
44 #include "pt-tm-const.h"
45 #include "utils.h"
46 #include "ov.h"
47 #include "variables.h"
48 
49 #include "ov-cx-mat.h"
50 #include "ov-flt-cx-mat.h"
51 #include "ov-re-sparse.h"
52 #include "ov-cx-sparse.h"
53 
54 OCTAVE_NORETURN static
55 void
56 eval_error (const char *msg, const dim_vector& x, const dim_vector& y)
57 {
58  error ("%s (%s vs %s)", msg, x.str ().c_str (), y.str ().c_str ());
59 }
60 
62 
63 void tm_row_const::cellify (void)
64 {
65  bool elt_changed = false;
66 
67  for (auto& elt : m_values)
68  {
69  octave_quit ();
70 
71  if (! elt.iscell ())
72  {
73  elt_changed = true;
74 
75  if (elt.isempty ())
76  elt = Cell ();
77  else
78  elt = Cell (elt);
79  }
80  }
81 
82  if (! elt_changed)
83  return;
84 
85  bool first_elem = true;
86 
87  for (const auto& val : m_values)
88  {
89  octave_quit ();
90 
91  dim_vector this_elt_dv = val.dims ();
92 
93  if (! this_elt_dv.zero_by_zero ())
94  {
95  if (first_elem)
96  {
97  first_elem = false;
98  m_dv = this_elt_dv;
99  }
100  else if (! m_dv.hvcat (this_elt_dv, 1))
101  eval_error ("horizontal dimensions mismatch", m_dv, this_elt_dv);
102  }
103  }
104 }
105 
106 void tm_row_const::init_element (const octave_value& val, bool& first_elem)
107 {
108  std::string this_elt_class_name
109  = val.isobject () ? "class" : val.class_name ();
110 
111  m_class_name = get_concat_class (m_class_name, this_elt_class_name);
112 
113  dim_vector this_elt_dv = val.dims ();
114 
115  if (! this_elt_dv.zero_by_zero ())
116  {
117  m_all_empty = false;
118 
119  if (first_elem)
120  {
121  if (val.isstruct ())
122  m_first_elem_is_struct = true;
123 
124  first_elem = false;
125  }
126  }
127  else if (val.iscell ())
128  first_elem = false;
129 
130  m_values.push_back (val);
131 
132  if (m_all_strings && ! val.is_string ())
133  m_all_strings = false;
134 
135  if (m_all_sq_strings && ! val.is_sq_string ())
136  m_all_sq_strings = false;
137 
138  if (m_all_dq_strings && ! val.is_dq_string ())
139  m_all_dq_strings = false;
140 
141  if (! m_some_strings && val.is_string ())
142  m_some_strings = true;
143 
144  if (m_all_real && ! val.isreal ())
145  m_all_real = false;
146 
147  if (m_all_complex && ! (val.iscomplex () || val.isreal ()))
148  m_all_complex = false;
149 
150  if (! m_any_cell && val.iscell ())
151  m_any_cell = true;
152 
153  if (! m_any_sparse && val.issparse ())
154  m_any_sparse = true;
155 
156  if (! m_any_class && val.isobject ())
157  m_any_class = true;
158 
159  // Special treatment of sparse matrices to avoid out-of-memory error
160  m_all_1x1 = m_all_1x1 && ! val.issparse () && val.numel () == 1;
161 }
162 
164 {
165  bool first_elem = true;
166 
167  for (auto *elt : row)
168  {
169  octave_quit ();
170 
171  octave_value tmp = elt->evaluate (tw);
172 
173  if (tmp.is_undefined ())
174  error ("undefined element in matrix list");
175 
176  if (tmp.is_cs_list ())
177  {
178  octave_value_list tlst = tmp.list_value ();
179 
180  for (octave_idx_type i = 0; i < tlst.length (); i++)
181  {
182  octave_quit ();
183 
184  init_element (tlst(i), first_elem);
185  }
186  }
187  else
188  init_element (tmp, first_elem);
189  }
190 
192  cellify ();
193 
194  first_elem = true;
195 
196  for (const auto& val : m_values)
197  {
198  octave_quit ();
199 
200  dim_vector this_elt_dv = val.dims ();
201 
202  if (! this_elt_dv.zero_by_zero ())
203  {
204  m_all_empty = false;
205 
206  if (first_elem)
207  {
208  first_elem = false;
209  m_dv = this_elt_dv;
210  }
211  else if ((! m_any_class) && (! m_dv.hvcat (this_elt_dv, 1)))
212  eval_error ("horizontal dimensions mismatch", m_dv, this_elt_dv);
213  }
214  }
215 }
216 
217 octave_value tm_const::concat (char string_fill_char) const
218 {
219  if (m_tm_rows.empty ())
220  return Matrix ();
221 
222  // Try to speed up the common cases.
223 
224  std::string result_type = m_class_name;
225 
226  if (m_any_class)
227  return class_concat ();
228  else if (result_type == "double")
229  {
230  if (m_any_sparse)
231  {
232  if (m_all_real)
233  return sparse_array_concat<SparseMatrix> ();
234  else
235  return sparse_array_concat<SparseComplexMatrix> ();
236  }
237  else
238  {
239  if (m_all_real)
240  return array_concat<NDArray> ();
241  else
242  return array_concat<ComplexNDArray> ();
243  }
244  }
245  else if (result_type == "single")
246  {
247  if (m_all_real)
248  return array_concat<FloatNDArray> ();
249  else
250  return array_concat<FloatComplexNDArray> ();
251  }
252  else if (result_type == "char")
253  {
254  if (! m_all_strings)
255  warn_implicit_conversion ("Octave:num-to-str",
256  "numeric", result_type);
257  else
259 
260  return char_array_concat (string_fill_char);
261  }
262  else if (result_type == "logical")
263  {
264  if (m_any_sparse)
265  return sparse_array_concat<SparseBoolMatrix> ();
266  else
267  return array_concat<boolNDArray> ();
268  }
269  else if (result_type == "int8")
270  return array_concat<int8NDArray> ();
271  else if (result_type == "int16")
272  return array_concat<int16NDArray> ();
273  else if (result_type == "int32")
274  return array_concat<int32NDArray> ();
275  else if (result_type == "int64")
276  return array_concat<int64NDArray> ();
277  else if (result_type == "uint8")
278  return array_concat<uint8NDArray> ();
279  else if (result_type == "uint16")
280  return array_concat<uint16NDArray> ();
281  else if (result_type == "uint32")
282  return array_concat<uint32NDArray> ();
283  else if (result_type == "uint64")
284  return array_concat<uint64NDArray> ();
285  else if (result_type == "cell")
286  return array_concat<Cell> ();
287  else if (result_type == "struct")
288  {
289  if (m_all_1x1)
290  return map_concat<octave_scalar_map> ();
291  else
292  return map_concat<octave_map> ();
293  }
294  else
295  return generic_concat ();
296 }
297 
298 void tm_const::init (const tree_matrix& tm)
299 {
300  bool first_elem = true;
301  bool first_elem_is_struct = false;
302 
303  // Just eval and figure out if what we have is complex or all strings.
304  // We can't check columns until we know that this is a numeric matrix --
305  // collections of strings can have elements of different lengths.
306 
307  for (const auto *elt : tm)
308  {
309  octave_quit ();
310 
311  tm_row_const row (*elt, m_evaluator);
312 
313  if (first_elem)
314  {
315  first_elem_is_struct = row.first_elem_struct_p ();
316 
317  first_elem = false;
318  }
319 
320  if (row.empty ())
321  continue;
322 
323  if (m_all_strings && ! row.all_strings_p ())
324  m_all_strings = false;
325 
326  if (m_all_sq_strings && ! row.all_sq_strings_p ())
327  m_all_sq_strings = false;
328 
329  if (m_all_dq_strings && ! row.all_dq_strings_p ())
330  m_all_dq_strings = false;
331 
332  if (! m_some_strings && row.some_strings_p ())
333  m_some_strings = true;
334 
335  if (m_all_real && ! row.all_real_p ())
336  m_all_real = false;
337 
338  if (m_all_complex && ! row.all_complex_p ())
339  m_all_complex = false;
340 
341  if (m_all_empty && ! row.all_empty_p ())
342  m_all_empty = false;
343 
344  if (! m_any_cell && row.any_cell_p ())
345  m_any_cell = true;
346 
347  if (! m_any_sparse && row.any_sparse_p ())
348  m_any_sparse = true;
349 
350  if (! m_any_class && row.any_class_p ())
351  m_any_class = true;
352 
353  m_all_1x1 = m_all_1x1 && row.all_1x1_p ();
354 
355  m_tm_rows.push_back (row);
356  }
357 
358  if (m_any_cell && ! m_any_class && ! first_elem_is_struct)
359  {
360  for (auto& elt : m_tm_rows)
361  {
362  octave_quit ();
363 
364  elt.cellify ();
365  }
366  }
367 
368  first_elem = true;
369 
370  for (const auto& elt : m_tm_rows)
371  {
372  octave_quit ();
373 
374  octave_idx_type this_elt_nr = elt.rows ();
375  octave_idx_type this_elt_nc = elt.cols ();
376 
377  std::string this_elt_class_name = elt.class_name ();
378  m_class_name = get_concat_class (m_class_name, this_elt_class_name);
379 
380  dim_vector this_elt_dv = elt.dims ();
381 
382  m_all_empty = false;
383 
384  if (first_elem)
385  {
386  first_elem = false;
387 
388  m_dv = this_elt_dv;
389  }
390  else if (m_all_strings && m_dv.ndims () == 2
391  && this_elt_dv.ndims () == 2)
392  {
393  // This is Octave's specialty.
394  // Character matrices support rows of unequal length.
395  if (m_dv.any_zero ())
396  {
397  // Empty existing element (bug #52542).
398  // Replace empty element with non-empty one.
399  m_dv = this_elt_dv;
400  }
401  else
402  {
403  if (this_elt_nc > cols ())
404  m_dv(1) = this_elt_nc;
405  m_dv(0) += this_elt_nr;
406  }
407  }
408  else if ((! m_any_class) && (! m_dv.hvcat (this_elt_dv, 0)))
409  eval_error ("vertical dimensions mismatch", m_dv, this_elt_dv);
410  }
411 }
412 
413 octave_value tm_const::char_array_concat (char string_fill_char) const
414 {
415  char type = (m_all_dq_strings ? '"' : '\'');
416 
417  charNDArray result (m_dv, string_fill_char);
418 
419  array_concat_internal<charNDArray> (result);
420 
421  return octave_value (result, type);
422 }
423 
425 {
426  octave_value retval;
427 
429 
430  octave_idx_type j = 0;
431  for (const auto& tmrc : m_tm_rows)
432  {
433  octave_quit ();
434 
435  if (tmrc.length () == 1)
436  rows(j++) = *(tmrc.begin ());
437  else
438  {
439  octave_value_list row (tmrc.length (), octave_value ());
440 
441  octave_idx_type i = 0;
442  for (const auto& elt : tmrc)
443  row(i++) = elt;
444 
445  rows(j++) = do_class_concat (row, "horzcat", 1);
446  }
447  }
448 
449  if (rows.length () == 1)
450  retval = rows(0);
451  else
452  retval = do_class_concat (rows, "vertcat", 0);
453 
454  return retval;
455 }
456 
458 {
459  // The line below might seem crazy, since we take a copy of the
460  // first argument, resize it to be empty and then resize it to be
461  // full. This is done since it means that there is no recopying of
462  // data, as would happen if we used a single resize. It should be
463  // noted that resize operation is also significantly slower than the
464  // cat_op function, so it makes sense to have an empty matrix and
465  // copy all data.
466  //
467  // We might also start with a empty octave_value using
468  //
469  // ctmp = type_info::lookup_type (tmp.begin() -> begin() -> type_name());
470  //
471  // and then directly resize. However, for some types there might be
472  // some additional setup needed, and so this should be avoided.
473 
474  octave_value ctmp;
475 
476  // Find the first non-empty object
477 
478  if (m_any_sparse)
479  {
480  // Start with sparse matrix to avoid issues memory issues with
481  // things like [ones(1,4),sprandn(1e8,4,1e-4)]
482 
483  if (m_all_real)
484  ctmp = octave_sparse_matrix ().resize (m_dv);
485  else
487  }
488  else
489  {
490  for (const auto& row : m_tm_rows)
491  {
492  octave_quit ();
493 
494  for (const auto& elt : row)
495  {
496  octave_quit ();
497 
498  ctmp = elt;
499 
500  if (! ctmp.all_zero_dims ())
501  goto found_non_empty;
502  }
503  }
504 
505  ctmp = (*(m_tm_rows.begin () -> begin ()));
506 
507  found_non_empty:
508 
509  if (! m_all_empty)
510  ctmp = ctmp.resize (dim_vector (0, 0)).resize (m_dv);
511  }
512 
513  // Now, extract the values from the individual elements and insert
514  // them in the result matrix.
515 
517 
518  type_info& ti = interp.get_type_info ();
519 
520  int dv_len = m_dv.ndims ();
521  octave_idx_type ntmp = (dv_len > 1 ? dv_len : 2);
523 
524  for (const auto& row : m_tm_rows)
525  {
526  octave_quit ();
527 
528  for (const auto& elt : row)
529  {
530  octave_quit ();
531 
532  if (elt.isempty ())
533  continue;
534 
535  ctmp = cat_op (ti, ctmp, elt, ra_idx);
536 
537  ra_idx (1) += elt.columns ();
538  }
539 
540  ra_idx (0) += row.rows ();
541  ra_idx (1) = 0;
542  }
543 
544  octave_value retval = ctmp;
545 
546  // If some elements are strings, force the result to be a string.
547 
548  if (m_some_strings && ! retval.is_string ())
549  retval = retval.convert_to_str ();
550 
551  return retval;
552 }
553 
554 // The result is passed as a parameter to this function so that the
555 // char_array_concat function can create the array externally.
556 // Otherwise, we would need a specialization of this function for
557 // character arrays just to handle string_fill_char.
558 
559 template <typename TYPE>
560 void tm_const::array_concat_internal (TYPE& result) const
561 {
562  octave_idx_type r = 0;
563  octave_idx_type c = 0;
564 
565  for (const auto& row : m_tm_rows)
566  {
567  // Skip empty arrays to allow looser rules.
568  if (row.dims ().any_zero ())
569  continue;
570 
571  for (const auto& elt : row)
572  {
573  octave_quit ();
574 
575  TYPE ra = octave_value_extract<TYPE> (elt);
576 
577  // Skip empty arrays to allow looser rules.
578 
579  if (! ra.isempty ())
580  {
581  result.insert (ra, r, c);
582 
583  c += ra.columns ();
584  }
585  }
586 
587  r += row.rows ();
588  c = 0;
589  }
590 }
591 
592 template <typename TYPE>
593 TYPE tm_const::array_concat (void) const
594 {
595  typedef typename TYPE::element_type ELT_T;
596 
597  if (m_dv.any_zero ())
598  return TYPE (m_dv);
599 
600  if (m_tm_rows.size () == 1)
601  {
602  // If possible, forward the operation to liboctave.
603  // Single row.
604  const tm_row_const& row = m_tm_rows.front ();
607  && row.all_1x1_p ())
608  {
609  // Optimize all scalars case.
610  TYPE result (m_dv);
611  panic_unless (static_cast<std::size_t> (result.numel ())
612  == row.length ());
613  octave_idx_type i = 0;
614  for (const auto& elt : row)
615  result(i++) = octave_value_extract<ELT_T> (elt);
616 
617  return result;
618  }
619 
620  octave_idx_type ncols = row.length ();
621  octave_idx_type i = 0;
622  OCTAVE_LOCAL_BUFFER (TYPE, array_list, ncols);
623 
624  for (const auto& elt : row)
625  {
626  octave_quit ();
627 
628  array_list[i++] = octave_value_extract<TYPE> (elt);
629  }
630 
631  return TYPE::cat (-2, ncols, array_list);
632  }
633  else
634  {
635  TYPE result (m_dv);
636  array_concat_internal<TYPE> (result);
637  return result;
638  }
639 }
640 
641 template <typename TYPE>
643 {
644  if (m_dv.any_zero ())
645  return TYPE (m_dv);
646 
647  // Sparse matrices require preallocation for efficient indexing; besides,
648  // only horizontal concatenation can be efficiently handled by indexing.
649  // So we just cat all rows through liboctave, then cat the final column.
650  octave_idx_type nrows = m_tm_rows.size ();
651  octave_idx_type j = 0;
652  OCTAVE_LOCAL_BUFFER (TYPE, sparse_row_list, nrows);
653  for (const auto& row : m_tm_rows)
654  {
655  octave_idx_type ncols = row.length ();
656  octave_idx_type i = 0;
657  OCTAVE_LOCAL_BUFFER (TYPE, sparse_list, ncols);
658 
659  for (auto& elt : row)
660  {
661  octave_quit ();
662 
663  sparse_list[i] = octave_value_extract<TYPE> (elt);
664  i++;
665  }
666 
667  TYPE stmp = TYPE::cat (-2, ncols, sparse_list);
668  sparse_row_list[j] = stmp;
669  j++;
670  }
671 
672  return TYPE::cat (-1, nrows, sparse_row_list);
673 }
674 
675 template <typename MAP>
677 {
678  if (m_dv.any_zero ())
679  return octave_map (m_dv);
680 
681  octave_idx_type nrows = m_tm_rows.size ();
682  octave_idx_type j = 0;
683  OCTAVE_LOCAL_BUFFER (octave_map, map_row_list, nrows);
684  for (const auto& row : m_tm_rows)
685  {
686  octave_idx_type ncols = row.length ();
687  octave_idx_type i = 0;
688  OCTAVE_LOCAL_BUFFER (MAP, map_list, ncols);
689 
690  for (auto& elt : row)
691  {
692  octave_quit ();
693 
694  map_list[i] = octave_value_extract<MAP> (elt);
695  i++;
696  }
697 
698  octave_map mtmp = octave_map::cat (-2, ncols, map_list);
699  map_row_list[j] = mtmp;
700  j++;
701  }
702 
703  return octave_map::cat (-1, nrows, map_row_list);
704 }
705 
707 
708 /*
709 ## test concatenation with all zero matrices
710 %!assert ([ "" 65*ones(1,10) ], "AAAAAAAAAA")
711 %!assert ([ 65*ones(1,10) "" ], "AAAAAAAAAA")
712 
713 %!test
714 %! c = {"foo"; "bar"; "bazoloa"};
715 %! assert ([c; "a"; "bc"; "def"], {"foo"; "bar"; "bazoloa"; "a"; "bc"; "def"});
716 
717 %!assert (class ([int64(1), int64(1)]), "int64")
718 %!assert (class ([int64(1), int32(1)]), "int64")
719 %!assert (class ([int64(1), int16(1)]), "int64")
720 %!assert (class ([int64(1), int8(1)]), "int64")
721 %!assert (class ([int64(1), uint64(1)]), "int64")
722 %!assert (class ([int64(1), uint32(1)]), "int64")
723 %!assert (class ([int64(1), uint16(1)]), "int64")
724 %!assert (class ([int64(1), uint8(1)]), "int64")
725 %!assert (class ([int64(1), single(1)]), "int64")
726 %!assert (class ([int64(1), double(1)]), "int64")
727 %!assert (class ([int64(1), cell(1)]), "cell")
728 %!assert (class ([int64(1), true]), "int64")
729 %!assert (class ([int64(1), "a"]), "char")
730 
731 %!assert (class ([int32(1), int64(1)]), "int32")
732 %!assert (class ([int32(1), int32(1)]), "int32")
733 %!assert (class ([int32(1), int16(1)]), "int32")
734 %!assert (class ([int32(1), int8(1)]), "int32")
735 %!assert (class ([int32(1), uint64(1)]), "int32")
736 %!assert (class ([int32(1), uint32(1)]), "int32")
737 %!assert (class ([int32(1), uint16(1)]), "int32")
738 %!assert (class ([int32(1), uint8(1)]), "int32")
739 %!assert (class ([int32(1), single(1)]), "int32")
740 %!assert (class ([int32(1), double(1)]), "int32")
741 %!assert (class ([int32(1), cell(1)]), "cell")
742 %!assert (class ([int32(1), true]), "int32")
743 %!assert (class ([int32(1), "a"]), "char")
744 
745 %!assert (class ([int16(1), int64(1)]), "int16")
746 %!assert (class ([int16(1), int32(1)]), "int16")
747 %!assert (class ([int16(1), int16(1)]), "int16")
748 %!assert (class ([int16(1), int8(1)]), "int16")
749 %!assert (class ([int16(1), uint64(1)]), "int16")
750 %!assert (class ([int16(1), uint32(1)]), "int16")
751 %!assert (class ([int16(1), uint16(1)]), "int16")
752 %!assert (class ([int16(1), uint8(1)]), "int16")
753 %!assert (class ([int16(1), single(1)]), "int16")
754 %!assert (class ([int16(1), double(1)]), "int16")
755 %!assert (class ([int16(1), cell(1)]), "cell")
756 %!assert (class ([int16(1), true]), "int16")
757 %!assert (class ([int16(1), "a"]), "char")
758 
759 %!assert (class ([int8(1), int64(1)]), "int8")
760 %!assert (class ([int8(1), int32(1)]), "int8")
761 %!assert (class ([int8(1), int16(1)]), "int8")
762 %!assert (class ([int8(1), int8(1)]), "int8")
763 %!assert (class ([int8(1), uint64(1)]), "int8")
764 %!assert (class ([int8(1), uint32(1)]), "int8")
765 %!assert (class ([int8(1), uint16(1)]), "int8")
766 %!assert (class ([int8(1), uint8(1)]), "int8")
767 %!assert (class ([int8(1), single(1)]), "int8")
768 %!assert (class ([int8(1), double(1)]), "int8")
769 %!assert (class ([int8(1), cell(1)]), "cell")
770 %!assert (class ([int8(1), true]), "int8")
771 %!assert (class ([int8(1), "a"]), "char")
772 
773 %!assert (class ([uint64(1), int64(1)]), "uint64")
774 %!assert (class ([uint64(1), int32(1)]), "uint64")
775 %!assert (class ([uint64(1), int16(1)]), "uint64")
776 %!assert (class ([uint64(1), int8(1)]), "uint64")
777 %!assert (class ([uint64(1), uint64(1)]), "uint64")
778 %!assert (class ([uint64(1), uint32(1)]), "uint64")
779 %!assert (class ([uint64(1), uint16(1)]), "uint64")
780 %!assert (class ([uint64(1), uint8(1)]), "uint64")
781 %!assert (class ([uint64(1), single(1)]), "uint64")
782 %!assert (class ([uint64(1), double(1)]), "uint64")
783 %!assert (class ([uint64(1), cell(1)]), "cell")
784 %!assert (class ([uint64(1), true]), "uint64")
785 %!assert (class ([uint64(1), "a"]), "char")
786 
787 %!assert (class ([uint32(1), int64(1)]), "uint32")
788 %!assert (class ([uint32(1), int32(1)]), "uint32")
789 %!assert (class ([uint32(1), int16(1)]), "uint32")
790 %!assert (class ([uint32(1), int8(1)]), "uint32")
791 %!assert (class ([uint32(1), uint64(1)]), "uint32")
792 %!assert (class ([uint32(1), uint32(1)]), "uint32")
793 %!assert (class ([uint32(1), uint16(1)]), "uint32")
794 %!assert (class ([uint32(1), uint8(1)]), "uint32")
795 %!assert (class ([uint32(1), single(1)]), "uint32")
796 %!assert (class ([uint32(1), double(1)]), "uint32")
797 %!assert (class ([uint32(1), cell(1)]), "cell")
798 %!assert (class ([uint32(1), true]), "uint32")
799 %!assert (class ([uint32(1), "a"]), "char")
800 
801 %!assert (class ([uint16(1), int64(1)]), "uint16")
802 %!assert (class ([uint16(1), int32(1)]), "uint16")
803 %!assert (class ([uint16(1), int16(1)]), "uint16")
804 %!assert (class ([uint16(1), int8(1)]), "uint16")
805 %!assert (class ([uint16(1), uint64(1)]), "uint16")
806 %!assert (class ([uint16(1), uint32(1)]), "uint16")
807 %!assert (class ([uint16(1), uint16(1)]), "uint16")
808 %!assert (class ([uint16(1), uint8(1)]), "uint16")
809 %!assert (class ([uint16(1), single(1)]), "uint16")
810 %!assert (class ([uint16(1), double(1)]), "uint16")
811 %!assert (class ([uint16(1), cell(1)]), "cell")
812 %!assert (class ([uint16(1), true]), "uint16")
813 %!assert (class ([uint16(1), "a"]), "char")
814 
815 %!assert (class ([uint8(1), int64(1)]), "uint8")
816 %!assert (class ([uint8(1), int32(1)]), "uint8")
817 %!assert (class ([uint8(1), int16(1)]), "uint8")
818 %!assert (class ([uint8(1), int8(1)]), "uint8")
819 %!assert (class ([uint8(1), uint64(1)]), "uint8")
820 %!assert (class ([uint8(1), uint32(1)]), "uint8")
821 %!assert (class ([uint8(1), uint16(1)]), "uint8")
822 %!assert (class ([uint8(1), uint8(1)]), "uint8")
823 %!assert (class ([uint8(1), single(1)]), "uint8")
824 %!assert (class ([uint8(1), double(1)]), "uint8")
825 %!assert (class ([uint8(1), cell(1)]), "cell")
826 %!assert (class ([uint8(1), true]), "uint8")
827 %!assert (class ([uint8(1), "a"]), "char")
828 
829 %!assert (class ([single(1), int64(1)]), "int64")
830 %!assert (class ([single(1), int32(1)]), "int32")
831 %!assert (class ([single(1), int16(1)]), "int16")
832 %!assert (class ([single(1), int8(1)]), "int8")
833 %!assert (class ([single(1), uint64(1)]), "uint64")
834 %!assert (class ([single(1), uint32(1)]), "uint32")
835 %!assert (class ([single(1), uint16(1)]), "uint16")
836 %!assert (class ([single(1), uint8(1)]), "uint8")
837 %!assert (class ([single(1), single(1)]), "single")
838 %!assert (class ([single(1), double(1)]), "single")
839 %!assert (class ([single(1), cell(1)]), "cell")
840 %!assert (class ([single(1), true]), "single")
841 %!assert (class ([single(1), "a"]), "char")
842 
843 %!assert (class ([double(1), int64(1)]), "int64")
844 %!assert (class ([double(1), int32(1)]), "int32")
845 %!assert (class ([double(1), int16(1)]), "int16")
846 %!assert (class ([double(1), int8(1)]), "int8")
847 %!assert (class ([double(1), uint64(1)]), "uint64")
848 %!assert (class ([double(1), uint32(1)]), "uint32")
849 %!assert (class ([double(1), uint16(1)]), "uint16")
850 %!assert (class ([double(1), uint8(1)]), "uint8")
851 %!assert (class ([double(1), single(1)]), "single")
852 %!assert (class ([double(1), double(1)]), "double")
853 %!assert (class ([double(1), cell(1)]), "cell")
854 %!assert (class ([double(1), true]), "double")
855 %!assert (class ([double(1), "a"]), "char")
856 
857 %!assert (class ([cell(1), int64(1)]), "cell")
858 %!assert (class ([cell(1), int32(1)]), "cell")
859 %!assert (class ([cell(1), int16(1)]), "cell")
860 %!assert (class ([cell(1), int8(1)]), "cell")
861 %!assert (class ([cell(1), uint64(1)]), "cell")
862 %!assert (class ([cell(1), uint32(1)]), "cell")
863 %!assert (class ([cell(1), uint16(1)]), "cell")
864 %!assert (class ([cell(1), uint8(1)]), "cell")
865 %!assert (class ([cell(1), single(1)]), "cell")
866 %!assert (class ([cell(1), double(1)]), "cell")
867 %!assert (class ([cell(1), cell(1)]), "cell")
868 %!assert (class ([cell(1), true]), "cell")
869 %!assert (class ([cell(1), "a"]), "cell")
870 
871 %!assert (class ([true, int64(1)]), "int64")
872 %!assert (class ([true, int32(1)]), "int32")
873 %!assert (class ([true, int16(1)]), "int16")
874 %!assert (class ([true, int8(1)]), "int8")
875 %!assert (class ([true, uint64(1)]), "uint64")
876 %!assert (class ([true, uint32(1)]), "uint32")
877 %!assert (class ([true, uint16(1)]), "uint16")
878 %!assert (class ([true, uint8(1)]), "uint8")
879 %!assert (class ([true, single(1)]), "single")
880 %!assert (class ([true, double(1)]), "double")
881 %!assert (class ([true, cell(1)]), "cell")
882 %!assert (class ([true, true]), "logical")
883 %!assert (class ([true, "a"]), "char")
884 
885 %!assert (class (["a", int64(1)]), "char")
886 %!assert (class (["a", int32(1)]), "char")
887 %!assert (class (["a", int16(1)]), "char")
888 %!assert (class (["a", int8(1)]), "char")
889 %!assert (class (["a", int64(1)]), "char")
890 %!assert (class (["a", int32(1)]), "char")
891 %!assert (class (["a", int16(1)]), "char")
892 %!assert (class (["a", int8(1)]), "char")
893 %!assert (class (["a", single(1)]), "char")
894 %!assert (class (["a", double(1)]), "char")
895 %!assert (class (["a", cell(1)]), "cell")
896 %!assert (class (["a", true]), "char")
897 %!assert (class (["a", "a"]), "char")
898 
899 %!assert (class ([cell(1), struct("foo", "bar")]), "cell")
900 %!error [struct("foo", "bar"), cell(1)]
901 
902 %!test <*39041> assert (class ([cell(0), struct()]), "cell")
903 %!test <51086> assert (class ([struct(), cell(0)]), "struct")
904 
905 %!assert ([,1], 1)
906 %!assert ([1,], 1)
907 %!assert ([,1,], 1)
908 %!assert ([,1,;;], 1)
909 %!assert ([,1,;,;], 1)
910 
911 %!assert ([1,1], ones (1, 2))
912 %!assert ([,1,1], ones (1, 2))
913 %!assert ([1,1,], ones (1, 2))
914 %!assert ([,1,1,], ones (1, 2))
915 %!assert ([,1,1,;;], ones (1, 2))
916 %!assert ([,1,1,;,;], ones (1, 2))
917 %!assert ([,;,1,1], ones (1, 2))
918 
919 %!assert ([1;1], ones (2, 1))
920 %!assert ([1,;1], ones (2, 1))
921 %!assert ([1,;,;1], ones (2, 1))
922 
923 %!error eval ("[,,]")
924 %!error eval ("[,,;,]")
925 %!error eval ("[,;,,;,]")
926 
927 %!assert (isnull ([,]))
928 %!assert (isnull ([;]))
929 %!assert (isnull ([;;]))
930 %!assert (isnull ([;,;]))
931 %!assert (isnull ([,;,;,]))
932 
933 ## Undefined elements.
934 %!function my_undef ()
935 %!endfunction
936 %!
937 %!shared es
938 %! es = struct ("a", {});
939 %!
940 %!assert <*58695> ([1; es.a; 3], [1; 3])
941 %!test <*58695>
942 %! fail ("undefined element in matrix list", "[1; my_undef(), 3]");
943 %!
944 %!assert <*58695> ([es.a; es.a; 3], 3)
945 %!test <*58695>
946 %! fail ("undefined element in matrix list", "[my_undef(); my_undef(); 3]")
947 */
OCTAVE_END_NAMESPACE(octave)
Definition: Cell.h:43
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:94
OCTAVE_API std::string str(char sep='x') const
Definition: dim-vector.cc:68
bool zero_by_zero(void) const
Definition: dim-vector.h:311
OCTAVE_API bool hvcat(const dim_vector &dvb, int dim)
This corresponds to [,] (horzcat, dim = 0) and [;] (vertcat, dim = 1).
Definition: dim-vector.cc:201
octave_idx_type ndims(void) const
Number of dimensions.
Definition: dim-vector.h:257
bool any_zero(void) const
Definition: dim-vector.h:316
type_info & get_type_info(void)
Definition: interpreter.h:293
OCTINTERP_API octave_value resize(const dim_vector &dv, bool=false) const
octave_idx_type columns(void) const
Definition: ov-base.h:363
octave_idx_type rows(void) const
Definition: ov-base.h:356
static octave_map cat(int dim, octave_idx_type n, const octave_scalar_map *map_list)
Definition: oct-map.cc:688
octave_idx_type length(void) const
Definition: ovl.h:113
bool iscell(void) const
Definition: ov.h:649
bool isreal(void) const
Definition: ov.h:783
bool issparse(void) const
Definition: ov.h:798
OCTINTERP_API octave_value_list list_value(void) const
octave_idx_type numel(void) const
Definition: ov.h:604
bool is_dq_string(void) const
Definition: ov.h:688
bool is_cs_list(void) const
Definition: ov.h:715
bool is_string(void) const
Definition: ov.h:682
std::string class_name(void) const
Definition: ov.h:1454
bool isstruct(void) const
Definition: ov.h:694
bool all_zero_dims(void) const
Definition: ov.h:598
octave_value convert_to_str(bool pad=false, bool force=false, char type='\'') const
Definition: ov.h:1414
bool isobject(void) const
Definition: ov.h:709
bool is_sq_string(void) const
Definition: ov.h:685
bool is_undefined(void) const
Definition: ov.h:640
octave_value resize(const dim_vector &dv, bool fill=false) const
Definition: ov.h:625
bool iscomplex(void) const
Definition: ov.h:786
dim_vector dims(void) const
Definition: ov.h:586
octave_value concat(char string_fill_char) const
Definition: pt-tm-const.cc:217
void init(const tree_matrix &tm)
Definition: pt-tm-const.cc:298
octave_value char_array_concat(char string_fill_char) const
Definition: pt-tm-const.cc:413
void array_concat_internal(TYPE &result) const
Definition: pt-tm-const.cc:560
octave_map map_concat(void) const
Definition: pt-tm-const.cc:676
tree_evaluator & m_evaluator
Definition: pt-tm-const.h:214
std::list< tm_row_const > m_tm_rows
Definition: pt-tm-const.h:220
TYPE sparse_array_concat(void) const
Definition: pt-tm-const.cc:642
octave_value class_concat(void) const
Definition: pt-tm-const.cc:424
TYPE array_concat(void) const
Definition: pt-tm-const.cc:593
octave_value generic_concat(void) const
Definition: pt-tm-const.cc:457
octave_idx_type rows(void) const
Definition: pt-tm-const.h:82
bool all_complex_p(void) const
Definition: pt-tm-const.h:90
bool m_any_class
Definition: pt-tm-const.h:133
bool m_all_1x1
Definition: pt-tm-const.h:136
octave_idx_type cols(void) const
Definition: pt-tm-const.h:83
bool all_empty_p(void) const
Definition: pt-tm-const.h:91
bool m_all_complex
Definition: pt-tm-const.h:121
bool m_first_elem_is_struct
Definition: pt-tm-const.h:139
bool m_all_real
Definition: pt-tm-const.h:118
bool first_elem_struct_p(void) const
Definition: pt-tm-const.h:96
dim_vector m_dv
Definition: pt-tm-const.h:103
bool m_some_strings
Definition: pt-tm-const.h:115
bool m_any_sparse
Definition: pt-tm-const.h:130
bool m_any_cell
Definition: pt-tm-const.h:127
bool any_cell_p(void) const
Definition: pt-tm-const.h:92
bool m_all_empty
Definition: pt-tm-const.h:124
bool all_1x1_p(void) const
Definition: pt-tm-const.h:95
std::string m_class_name
Definition: pt-tm-const.h:142
bool all_strings_p(void) const
Definition: pt-tm-const.h:85
bool any_class_p(void) const
Definition: pt-tm-const.h:94
bool all_dq_strings_p(void) const
Definition: pt-tm-const.h:87
bool m_all_dq_strings
Definition: pt-tm-const.h:112
bool m_all_sq_strings
Definition: pt-tm-const.h:109
bool all_real_p(void) const
Definition: pt-tm-const.h:89
bool any_sparse_p(void) const
Definition: pt-tm-const.h:93
bool all_sq_strings_p(void) const
Definition: pt-tm-const.h:86
bool some_strings_p(void) const
Definition: pt-tm-const.h:88
bool m_all_strings
Definition: pt-tm-const.h:106
std::size_t length(void) const
Definition: pt-tm-const.h:174
bool empty(void) const
Definition: pt-tm-const.h:172
void init(const tree_argument_list &, tree_evaluator &tw)
Definition: pt-tm-const.cc:163
void cellify(void)
Definition: pt-tm-const.cc:63
std::list< octave_value > m_values
Definition: pt-tm-const.h:180
void init_element(const octave_value &, bool &)
Definition: pt-tm-const.cc:106
interpreter & get_interpreter(void)
Definition: pt-eval.h:427
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
octave_value do_class_concat(const octave_value_list &ovl, const std::string &cattype, int dim)
Definition: data.cc:1740
void error(const char *fmt,...)
Definition: error.cc:979
void panic_unless(bool cond)
Definition: error.h:526
void warn_implicit_conversion(const char *id, const char *from, const char *to)
Definition: errwarn.cc:344
F77_RET_T const F77_DBLE * x
class OCTAVE_API Matrix
Definition: mx-fwd.h:31
T * r
Definition: mx-inlines.cc:773
#define OCTAVE_LOCAL_BUFFER(T, buf, size)
Definition: oct-locbuf.h:44
const octave_base_value const Array< octave_idx_type > & ra_idx
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))
OCTINTERP_API octave_value cat_op(type_info &ti, const octave_value &a, const octave_value &b, const Array< octave_idx_type > &ra_idx)
void maybe_warn_string_concat(bool all_dq_strings_p, bool all_sq_strings_p)
Definition: pt-mat.cc:127
std::string get_concat_class(const std::string &c1, const std::string &c2)
Definition: pt-mat.cc:56
static OCTAVE_NORETURN void eval_error(const char *msg, const dim_vector &x, const dim_vector &y)
Definition: pt-tm-const.cc:56