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