GNU Octave 7.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-2022 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
54OCTAVE_NORETURN static
55void
56eval_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
61namespace 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 ())
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
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 assert (static_cast<std::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
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:291
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
bool empty(void) const
Definition: pt-tm-const.h:172
std::size_t length(void) const
Definition: pt-tm-const.h:174
OCTINTERP_API octave_value resize(const dim_vector &dv, bool=false) const
octave_idx_type columns(void) const
Definition: ov-base.h:355
octave_idx_type rows(void) const
Definition: ov-base.h:348
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: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:1451
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:1411
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
interpreter & get_interpreter(void)
Definition: pt-eval.h:414
octave_value do_class_concat(const octave_value_list &ovl, const std::string &cattype, int dim)
Definition: data.cc:1711
void error(const char *fmt,...)
Definition: error.cc:980
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
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()) ? '\'' :'"'))
OCTINTERP_API octave_value cat_op(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