GNU Octave  6.2.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-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include "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 
61 namespace octave
62 {
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  {
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  // do_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 = do_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  assert (static_cast<size_t> (result.numel ()) == row.length ());
612  octave_idx_type i = 0;
613  for (const auto& elt : row)
614  result(i++) = octave_value_extract<ELT_T> (elt);
615 
616  return result;
617  }
618 
619  octave_idx_type ncols = row.length ();
620  octave_idx_type i = 0;
621  OCTAVE_LOCAL_BUFFER (TYPE, array_list, ncols);
622 
623  for (const auto& elt : row)
624  {
625  octave_quit ();
626 
627  array_list[i++] = octave_value_extract<TYPE> (elt);
628  }
629 
630  return TYPE::cat (-2, ncols, array_list);
631  }
632  else
633  {
634  TYPE result (m_dv);
635  array_concat_internal<TYPE> (result);
636  return result;
637  }
638  }
639 
640  template <typename TYPE>
642  {
643  if (m_dv.any_zero ())
644  return TYPE (m_dv);
645 
646  // Sparse matrices require preallocation for efficient indexing; besides,
647  // only horizontal concatenation can be efficiently handled by indexing.
648  // So we just cat all rows through liboctave, then cat the final column.
649  octave_idx_type nrows = m_tm_rows.size ();
650  octave_idx_type j = 0;
651  OCTAVE_LOCAL_BUFFER (TYPE, sparse_row_list, nrows);
652  for (const auto& row : m_tm_rows)
653  {
654  octave_idx_type ncols = row.length ();
655  octave_idx_type i = 0;
656  OCTAVE_LOCAL_BUFFER (TYPE, sparse_list, ncols);
657 
658  for (auto& elt : row)
659  {
660  octave_quit ();
661 
662  sparse_list[i] = octave_value_extract<TYPE> (elt);
663  i++;
664  }
665 
666  TYPE stmp = TYPE::cat (-2, ncols, sparse_list);
667  sparse_row_list[j] = stmp;
668  j++;
669  }
670 
671  return TYPE::cat (-1, nrows, sparse_row_list);
672  }
673 
674  template <typename MAP>
676  {
677  if (m_dv.any_zero ())
678  return octave_map (m_dv);
679 
680  octave_idx_type nrows = m_tm_rows.size ();
681  octave_idx_type j = 0;
682  OCTAVE_LOCAL_BUFFER (octave_map, map_row_list, nrows);
683  for (const auto& row : m_tm_rows)
684  {
685  octave_idx_type ncols = row.length ();
686  octave_idx_type i = 0;
687  OCTAVE_LOCAL_BUFFER (MAP, map_list, ncols);
688 
689  for (auto& elt : row)
690  {
691  octave_quit ();
692 
693  map_list[i] = octave_value_extract<MAP> (elt);
694  i++;
695  }
696 
697  octave_map mtmp = octave_map::cat (-2, ncols, map_list);
698  map_row_list[j] = mtmp;
699  j++;
700  }
701 
702  return octave_map::cat (-1, nrows, map_row_list);
703  }
704 }
705 
706 /*
707 ## test concatenation with all zero matrices
708 %!assert ([ "" 65*ones(1,10) ], "AAAAAAAAAA")
709 %!assert ([ 65*ones(1,10) "" ], "AAAAAAAAAA")
710 
711 %!test
712 %! c = {"foo"; "bar"; "bazoloa"};
713 %! assert ([c; "a"; "bc"; "def"], {"foo"; "bar"; "bazoloa"; "a"; "bc"; "def"});
714 
715 %!assert (class ([int64(1), int64(1)]), "int64")
716 %!assert (class ([int64(1), int32(1)]), "int64")
717 %!assert (class ([int64(1), int16(1)]), "int64")
718 %!assert (class ([int64(1), int8(1)]), "int64")
719 %!assert (class ([int64(1), uint64(1)]), "int64")
720 %!assert (class ([int64(1), uint32(1)]), "int64")
721 %!assert (class ([int64(1), uint16(1)]), "int64")
722 %!assert (class ([int64(1), uint8(1)]), "int64")
723 %!assert (class ([int64(1), single(1)]), "int64")
724 %!assert (class ([int64(1), double(1)]), "int64")
725 %!assert (class ([int64(1), cell(1)]), "cell")
726 %!assert (class ([int64(1), true]), "int64")
727 %!assert (class ([int64(1), "a"]), "char")
728 
729 %!assert (class ([int32(1), int64(1)]), "int32")
730 %!assert (class ([int32(1), int32(1)]), "int32")
731 %!assert (class ([int32(1), int16(1)]), "int32")
732 %!assert (class ([int32(1), int8(1)]), "int32")
733 %!assert (class ([int32(1), uint64(1)]), "int32")
734 %!assert (class ([int32(1), uint32(1)]), "int32")
735 %!assert (class ([int32(1), uint16(1)]), "int32")
736 %!assert (class ([int32(1), uint8(1)]), "int32")
737 %!assert (class ([int32(1), single(1)]), "int32")
738 %!assert (class ([int32(1), double(1)]), "int32")
739 %!assert (class ([int32(1), cell(1)]), "cell")
740 %!assert (class ([int32(1), true]), "int32")
741 %!assert (class ([int32(1), "a"]), "char")
742 
743 %!assert (class ([int16(1), int64(1)]), "int16")
744 %!assert (class ([int16(1), int32(1)]), "int16")
745 %!assert (class ([int16(1), int16(1)]), "int16")
746 %!assert (class ([int16(1), int8(1)]), "int16")
747 %!assert (class ([int16(1), uint64(1)]), "int16")
748 %!assert (class ([int16(1), uint32(1)]), "int16")
749 %!assert (class ([int16(1), uint16(1)]), "int16")
750 %!assert (class ([int16(1), uint8(1)]), "int16")
751 %!assert (class ([int16(1), single(1)]), "int16")
752 %!assert (class ([int16(1), double(1)]), "int16")
753 %!assert (class ([int16(1), cell(1)]), "cell")
754 %!assert (class ([int16(1), true]), "int16")
755 %!assert (class ([int16(1), "a"]), "char")
756 
757 %!assert (class ([int8(1), int64(1)]), "int8")
758 %!assert (class ([int8(1), int32(1)]), "int8")
759 %!assert (class ([int8(1), int16(1)]), "int8")
760 %!assert (class ([int8(1), int8(1)]), "int8")
761 %!assert (class ([int8(1), uint64(1)]), "int8")
762 %!assert (class ([int8(1), uint32(1)]), "int8")
763 %!assert (class ([int8(1), uint16(1)]), "int8")
764 %!assert (class ([int8(1), uint8(1)]), "int8")
765 %!assert (class ([int8(1), single(1)]), "int8")
766 %!assert (class ([int8(1), double(1)]), "int8")
767 %!assert (class ([int8(1), cell(1)]), "cell")
768 %!assert (class ([int8(1), true]), "int8")
769 %!assert (class ([int8(1), "a"]), "char")
770 
771 %!assert (class ([uint64(1), int64(1)]), "uint64")
772 %!assert (class ([uint64(1), int32(1)]), "uint64")
773 %!assert (class ([uint64(1), int16(1)]), "uint64")
774 %!assert (class ([uint64(1), int8(1)]), "uint64")
775 %!assert (class ([uint64(1), uint64(1)]), "uint64")
776 %!assert (class ([uint64(1), uint32(1)]), "uint64")
777 %!assert (class ([uint64(1), uint16(1)]), "uint64")
778 %!assert (class ([uint64(1), uint8(1)]), "uint64")
779 %!assert (class ([uint64(1), single(1)]), "uint64")
780 %!assert (class ([uint64(1), double(1)]), "uint64")
781 %!assert (class ([uint64(1), cell(1)]), "cell")
782 %!assert (class ([uint64(1), true]), "uint64")
783 %!assert (class ([uint64(1), "a"]), "char")
784 
785 %!assert (class ([uint32(1), int64(1)]), "uint32")
786 %!assert (class ([uint32(1), int32(1)]), "uint32")
787 %!assert (class ([uint32(1), int16(1)]), "uint32")
788 %!assert (class ([uint32(1), int8(1)]), "uint32")
789 %!assert (class ([uint32(1), uint64(1)]), "uint32")
790 %!assert (class ([uint32(1), uint32(1)]), "uint32")
791 %!assert (class ([uint32(1), uint16(1)]), "uint32")
792 %!assert (class ([uint32(1), uint8(1)]), "uint32")
793 %!assert (class ([uint32(1), single(1)]), "uint32")
794 %!assert (class ([uint32(1), double(1)]), "uint32")
795 %!assert (class ([uint32(1), cell(1)]), "cell")
796 %!assert (class ([uint32(1), true]), "uint32")
797 %!assert (class ([uint32(1), "a"]), "char")
798 
799 %!assert (class ([uint16(1), int64(1)]), "uint16")
800 %!assert (class ([uint16(1), int32(1)]), "uint16")
801 %!assert (class ([uint16(1), int16(1)]), "uint16")
802 %!assert (class ([uint16(1), int8(1)]), "uint16")
803 %!assert (class ([uint16(1), uint64(1)]), "uint16")
804 %!assert (class ([uint16(1), uint32(1)]), "uint16")
805 %!assert (class ([uint16(1), uint16(1)]), "uint16")
806 %!assert (class ([uint16(1), uint8(1)]), "uint16")
807 %!assert (class ([uint16(1), single(1)]), "uint16")
808 %!assert (class ([uint16(1), double(1)]), "uint16")
809 %!assert (class ([uint16(1), cell(1)]), "cell")
810 %!assert (class ([uint16(1), true]), "uint16")
811 %!assert (class ([uint16(1), "a"]), "char")
812 
813 %!assert (class ([uint8(1), int64(1)]), "uint8")
814 %!assert (class ([uint8(1), int32(1)]), "uint8")
815 %!assert (class ([uint8(1), int16(1)]), "uint8")
816 %!assert (class ([uint8(1), int8(1)]), "uint8")
817 %!assert (class ([uint8(1), uint64(1)]), "uint8")
818 %!assert (class ([uint8(1), uint32(1)]), "uint8")
819 %!assert (class ([uint8(1), uint16(1)]), "uint8")
820 %!assert (class ([uint8(1), uint8(1)]), "uint8")
821 %!assert (class ([uint8(1), single(1)]), "uint8")
822 %!assert (class ([uint8(1), double(1)]), "uint8")
823 %!assert (class ([uint8(1), cell(1)]), "cell")
824 %!assert (class ([uint8(1), true]), "uint8")
825 %!assert (class ([uint8(1), "a"]), "char")
826 
827 %!assert (class ([single(1), int64(1)]), "int64")
828 %!assert (class ([single(1), int32(1)]), "int32")
829 %!assert (class ([single(1), int16(1)]), "int16")
830 %!assert (class ([single(1), int8(1)]), "int8")
831 %!assert (class ([single(1), uint64(1)]), "uint64")
832 %!assert (class ([single(1), uint32(1)]), "uint32")
833 %!assert (class ([single(1), uint16(1)]), "uint16")
834 %!assert (class ([single(1), uint8(1)]), "uint8")
835 %!assert (class ([single(1), single(1)]), "single")
836 %!assert (class ([single(1), double(1)]), "single")
837 %!assert (class ([single(1), cell(1)]), "cell")
838 %!assert (class ([single(1), true]), "single")
839 %!assert (class ([single(1), "a"]), "char")
840 
841 %!assert (class ([double(1), int64(1)]), "int64")
842 %!assert (class ([double(1), int32(1)]), "int32")
843 %!assert (class ([double(1), int16(1)]), "int16")
844 %!assert (class ([double(1), int8(1)]), "int8")
845 %!assert (class ([double(1), uint64(1)]), "uint64")
846 %!assert (class ([double(1), uint32(1)]), "uint32")
847 %!assert (class ([double(1), uint16(1)]), "uint16")
848 %!assert (class ([double(1), uint8(1)]), "uint8")
849 %!assert (class ([double(1), single(1)]), "single")
850 %!assert (class ([double(1), double(1)]), "double")
851 %!assert (class ([double(1), cell(1)]), "cell")
852 %!assert (class ([double(1), true]), "double")
853 %!assert (class ([double(1), "a"]), "char")
854 
855 %!assert (class ([cell(1), int64(1)]), "cell")
856 %!assert (class ([cell(1), int32(1)]), "cell")
857 %!assert (class ([cell(1), int16(1)]), "cell")
858 %!assert (class ([cell(1), int8(1)]), "cell")
859 %!assert (class ([cell(1), uint64(1)]), "cell")
860 %!assert (class ([cell(1), uint32(1)]), "cell")
861 %!assert (class ([cell(1), uint16(1)]), "cell")
862 %!assert (class ([cell(1), uint8(1)]), "cell")
863 %!assert (class ([cell(1), single(1)]), "cell")
864 %!assert (class ([cell(1), double(1)]), "cell")
865 %!assert (class ([cell(1), cell(1)]), "cell")
866 %!assert (class ([cell(1), true]), "cell")
867 %!assert (class ([cell(1), "a"]), "cell")
868 
869 %!assert (class ([true, int64(1)]), "int64")
870 %!assert (class ([true, int32(1)]), "int32")
871 %!assert (class ([true, int16(1)]), "int16")
872 %!assert (class ([true, int8(1)]), "int8")
873 %!assert (class ([true, uint64(1)]), "uint64")
874 %!assert (class ([true, uint32(1)]), "uint32")
875 %!assert (class ([true, uint16(1)]), "uint16")
876 %!assert (class ([true, uint8(1)]), "uint8")
877 %!assert (class ([true, single(1)]), "single")
878 %!assert (class ([true, double(1)]), "double")
879 %!assert (class ([true, cell(1)]), "cell")
880 %!assert (class ([true, true]), "logical")
881 %!assert (class ([true, "a"]), "char")
882 
883 %!assert (class (["a", int64(1)]), "char")
884 %!assert (class (["a", int32(1)]), "char")
885 %!assert (class (["a", int16(1)]), "char")
886 %!assert (class (["a", int8(1)]), "char")
887 %!assert (class (["a", int64(1)]), "char")
888 %!assert (class (["a", int32(1)]), "char")
889 %!assert (class (["a", int16(1)]), "char")
890 %!assert (class (["a", int8(1)]), "char")
891 %!assert (class (["a", single(1)]), "char")
892 %!assert (class (["a", double(1)]), "char")
893 %!assert (class (["a", cell(1)]), "cell")
894 %!assert (class (["a", true]), "char")
895 %!assert (class (["a", "a"]), "char")
896 
897 %!assert (class ([cell(1), struct("foo", "bar")]), "cell")
898 %!error [struct("foo", "bar"), cell(1)]
899 
900 %!test <*39041> assert (class ([cell(0), struct()]), "cell")
901 %!test <51086> assert (class ([struct(), cell(0)]), "struct")
902 
903 %!assert ([,1], 1)
904 %!assert ([1,], 1)
905 %!assert ([,1,], 1)
906 %!assert ([,1,;;], 1)
907 %!assert ([,1,;,;], 1)
908 
909 %!assert ([1,1], ones (1, 2))
910 %!assert ([,1,1], ones (1, 2))
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 
917 %!assert ([1;1], ones (2, 1))
918 %!assert ([1,;1], ones (2, 1))
919 %!assert ([1,;,;1], ones (2, 1))
920 
921 %!error eval ("[,,]")
922 %!error eval ("[,,;,]")
923 %!error eval ("[,;,,;,]")
924 
925 %!assert (isnull ([,]))
926 %!assert (isnull ([;]))
927 %!assert (isnull ([;;]))
928 %!assert (isnull ([;,;]))
929 %!assert (isnull ([,;,;,]))
930 
931 ## Undefined elements.
932 %!function my_undef ()
933 %!endfunction
934 %!
935 %!shared es
936 %! es = struct ("a", {});
937 %!
938 %!assert <*58695> ([1; es.a; 3], [1; 3])
939 %!test <*58695>
940 %! fail ("undefined element in matrix list", "[1; my_undef(), 3]");
941 %!
942 %!assert <*58695> ([es.a; es.a; 3], 3)
943 %!test <*58695>
944 %! fail ("undefined element in matrix list", "[my_undef(); my_undef(); 3]")
945 */
Definition: Cell.h:43
Definition: dMatrix.h:42
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:95
std::string str(char sep='x') const
Definition: dim-vector.cc:85
bool zero_by_zero(void) const
Definition: dim-vector.h:377
bool hvcat(const dim_vector &dvb, int dim)
This corresponds to [,] (horzcat, dim = 0) and [;] (vertcat, dim = 1).
Definition: dim-vector.cc:220
octave_idx_type ndims(void) const
Number of dimensions.
Definition: dim-vector.h:334
bool any_zero(void) const
Definition: dim-vector.h:382
type_info & get_type_info(void)
Definition: interpreter.h:253
void array_concat_internal(TYPE &result) const
Definition: pt-tm-const.cc:560
octave_value char_array_concat(char string_fill_char) const
Definition: pt-tm-const.cc:413
tree_evaluator & m_evaluator
Definition: pt-tm-const.h:214
octave_map map_concat(void) const
Definition: pt-tm-const.cc:675
std::list< tm_row_const > m_tm_rows
Definition: pt-tm-const.h:220
TYPE array_concat(void) const
Definition: pt-tm-const.cc:593
octave_value generic_concat(void) const
Definition: pt-tm-const.cc:457
void init(const tree_matrix &tm)
Definition: pt-tm-const.cc:298
octave_value class_concat(void) const
Definition: pt-tm-const.cc:424
octave_value concat(char string_fill_char) const
Definition: pt-tm-const.cc:217
TYPE sparse_array_concat(void) const
Definition: pt-tm-const.cc:641
std::string m_class_name
Definition: pt-tm-const.h:142
dim_vector m_dv
Definition: pt-tm-const.h:103
bool all_sq_strings_p(void) const
Definition: pt-tm-const.h:86
bool m_first_elem_is_struct
Definition: pt-tm-const.h:139
bool first_elem_struct_p(void) const
Definition: pt-tm-const.h:96
bool some_strings_p(void) const
Definition: pt-tm-const.h:88
bool any_cell_p(void) const
Definition: pt-tm-const.h:92
bool all_empty_p(void) const
Definition: pt-tm-const.h:91
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
octave_idx_type rows(void) const
Definition: pt-tm-const.h:82
bool any_sparse_p(void) const
Definition: pt-tm-const.h:93
bool all_1x1_p(void) const
Definition: pt-tm-const.h:95
bool all_real_p(void) const
Definition: pt-tm-const.h:89
octave_idx_type cols(void) const
Definition: pt-tm-const.h:83
bool all_strings_p(void) const
Definition: pt-tm-const.h:85
bool all_complex_p(void) const
Definition: pt-tm-const.h:90
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
void init(const tree_argument_list &, tree_evaluator &tw)
Definition: pt-tm-const.cc:163
size_t length(void) const
Definition: pt-tm-const.h:174
bool empty(void) const
Definition: pt-tm-const.h:172
interpreter & get_interpreter(void)
Definition: pt-eval.h:370
octave_value resize(const dim_vector &dv, bool=false) const
octave_idx_type columns(void) const
Definition: ov-base.h:325
octave_idx_type rows(void) const
Definition: ov-base.h:318
static octave_map cat(int dim, octave_idx_type n, const octave_scalar_map *map_list)
Definition: oct-map.cc:690
octave_idx_type length(void) const
Definition: ovl.h:113
bool iscell(void) const
Definition: ov.h:560
bool isreal(void) const
Definition: ov.h:691
bool issparse(void) const
Definition: ov.h:706
octave_idx_type numel(void) const
Definition: ov.h:518
bool is_dq_string(void) const
Definition: ov.h:599
bool is_cs_list(void) const
Definition: ov.h:626
bool is_string(void) const
Definition: ov.h:593
std::string class_name(void) const
Definition: ov.h:1256
bool isstruct(void) const
Definition: ov.h:605
bool all_zero_dims(void) const
Definition: ov.h:512
octave_value_list list_value(void) const
bool isobject(void) const
Definition: ov.h:620
bool is_sq_string(void) const
Definition: ov.h:596
bool is_undefined(void) const
Definition: ov.h:554
octave_value resize(const dim_vector &dv, bool fill=false) const
Definition: ov.h:539
bool iscomplex(void) const
Definition: ov.h:694
dim_vector dims(void) const
Definition: ov.h:500
octave_value do_class_concat(const octave_value_list &ovl, std::string cattype, int dim)
Definition: data.cc:1696
void error(const char *fmt,...)
Definition: error.cc:968
void warn_implicit_conversion(const char *id, const char *from, const char *to)
Definition: errwarn.cc:344
F77_RET_T const F77_DBLE * x
T * r
Definition: mx-inlines.cc:773
std::string get_concat_class(const std::string &c1, const std::string &c2)
Definition: pt-mat.cc:56
void maybe_warn_string_concat(bool all_dq_strings_p, bool all_sq_strings_p)
Definition: pt-mat.cc:127
#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()) ? '\'' :'"'))
octave_value::octave_value(const Array< char > &chm, char type) return retval
Definition: ov.cc:811
OCTINTERP_API octave_value do_cat_op(octave::type_info &ti, const octave_value &a, const octave_value &b, const Array< octave_idx_type > &ra_idx)
static OCTAVE_NORETURN void eval_error(const char *msg, const dim_vector &x, const dim_vector &y)
Definition: pt-tm-const.cc:56