GNU Octave 10.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
ov.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1996-2025 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 <cmath>
31
32#include <type_traits>
33
34#include "data-conv.h"
35#include "quit.h"
36#include "str-vec.h"
37
38#include "ovl.h"
39#include "oct-stream.h"
40#include "ov.h"
41#include "ov-base.h"
42#include "ov-bool.h"
43#include "ov-bool-mat.h"
44#include "ov-cell.h"
45#include "ov-scalar.h"
46#include "ov-float.h"
47#include "ov-re-mat.h"
48#include "ov-flt-re-mat.h"
49#include "ov-re-diag.h"
50#include "ov-flt-re-diag.h"
51#include "ov-legacy-range.h"
52#include "ov-perm.h"
53#include "ov-bool-sparse.h"
54#include "ov-cx-sparse.h"
55#include "ov-re-sparse.h"
56#include "ov-int8.h"
57#include "ov-int16.h"
58#include "ov-int32.h"
59#include "ov-int64.h"
60#include "ov-uint8.h"
61#include "ov-uint16.h"
62#include "ov-uint32.h"
63#include "ov-uint64.h"
64#include "ov-complex.h"
65#include "ov-flt-complex.h"
66#include "ov-cx-mat.h"
67#include "ov-flt-cx-mat.h"
68#include "ov-cx-diag.h"
69#include "ov-flt-cx-diag.h"
70#include "ov-ch-mat.h"
71#include "ov-str-mat.h"
72#include "ov-range.h"
73#include "ov-struct.h"
74#include "ov-class.h"
75#include "ov-classdef.h"
76#include "ov-oncleanup.h"
77#include "ov-cs-list.h"
78#include "ov-colon.h"
79#include "ov-builtin.h"
80#include "ov-dld-fcn.h"
81#include "ov-usr-fcn.h"
82#include "ov-fcn-handle.h"
83#include "ov-typeinfo.h"
84#include "ov-magic-int.h"
85#include "ov-null-mat.h"
86#include "ov-lazy-idx.h"
87#include "ov-java.h"
88
89#include "defun.h"
90#include "error.h"
91#include "errwarn.h"
92#include "interpreter-private.h"
93#include "pager.h"
94#include "parse.h"
95#include "pr-flt-fmt.h"
96#include "pr-output.h"
97#include "symtab.h"
98#include "utils.h"
99#include "variables.h"
100
101// We are likely to have a lot of octave_value objects to allocate, so
102// make the grow_size large.
103
104// If TRUE, create special space-optimized diagonal matrix objects.
105
106static bool Voptimize_diagonal_matrix = true;
107
108// If TRUE, create special space-optimized permutation matrix objects.
109
110static bool Voptimize_permutation_matrix = true;
111
112// If TRUE, create special space-optimized range objects.
113
114static bool Voptimize_range = true;
115
116// FIXME
117
118// Octave's value type.
119
122{
123 static octave_base_value nr;
124 return &nr;
125}
126
127std::string
129{
130 switch (op)
131 {
132 case op_not:
133 return "!";
134
135 case op_uplus:
136 return "+";
137
138 case op_uminus:
139 return "-";
140
141 case op_transpose:
142 return ".'";
143
144 case op_hermitian:
145 return "'";
146
147 case op_incr:
148 return "++";
149
150 case op_decr:
151 return "--";
152
153 default:
154 return "<unknown>";
155 }
156}
157
158std::string
160{
161 switch (op)
162 {
163 case op_not:
164 return "not";
165
166 case op_uplus:
167 return "uplus";
168
169 case op_uminus:
170 return "uminus";
171
172 case op_transpose:
173 return "transpose";
174
175 case op_hermitian:
176 return "ctranspose";
177
178 default:
179 return "<unknown>";
180 }
181}
182
183std::string
185{
186 switch (op)
187 {
188 case op_add:
189 return "+";
190
191 case op_sub:
192 return "-";
193
194 case op_mul:
195 return "*";
196
197 case op_div:
198 return "/";
199
200 case op_pow:
201 return "^";
202
203 case op_ldiv:
204 return R"(\)";
205
206 case op_lt:
207 return "<";
208
209 case op_le:
210 return "<=";
211
212 case op_eq:
213 return "==";
214
215 case op_ge:
216 return ">=";
217
218 case op_gt:
219 return ">";
220
221 case op_ne:
222 return "!=";
223
224 case op_el_mul:
225 return ".*";
226
227 case op_el_div:
228 return "./";
229
230 case op_el_pow:
231 return ".^";
232
233 case op_el_ldiv:
234 return R"(.\)";
235
236 case op_el_and:
237 return "&";
238
239 case op_el_or:
240 return "|";
241
242 case op_struct_ref:
243 return ".";
244
245 default:
246 return "<unknown>";
247 }
248}
249
250std::string
252{
253 switch (op)
254 {
255 case op_add:
256 return "plus";
257
258 case op_sub:
259 return "minus";
260
261 case op_mul:
262 return "mtimes";
263
264 case op_div:
265 return "mrdivide";
266
267 case op_pow:
268 return "mpower";
269
270 case op_ldiv:
271 return "mldivide";
272
273 case op_lt:
274 return "lt";
275
276 case op_le:
277 return "le";
278
279 case op_eq:
280 return "eq";
281
282 case op_ge:
283 return "ge";
284
285 case op_gt:
286 return "gt";
287
288 case op_ne:
289 return "ne";
290
291 case op_el_mul:
292 return "times";
293
294 case op_el_div:
295 return "rdivide";
296
297 case op_el_pow:
298 return "power";
299
300 case op_el_ldiv:
301 return "ldivide";
302
303 case op_el_and:
304 return "and";
305
306 case op_el_or:
307 return "or";
308
309 default:
310 return "<unknown>";
311 }
312}
313
314std::string
316{
317 switch (op)
318 {
319 case op_trans_mul:
320 return "transtimes";
321
322 case op_mul_trans:
323 return "timestrans";
324
325 case op_herm_mul:
326 return "hermtimes";
327
328 case op_mul_herm:
329 return "timesherm";
330
331 case op_trans_ldiv:
332 return "transldiv";
333
334 case op_herm_ldiv:
335 return "hermldiv";
336
337 case op_el_and_not:
338 return "andnot";
339
340 case op_el_or_not:
341 return "ornot";
342
343 case op_el_not_and:
344 return "notand";
345
346 case op_el_not_or:
347 return "notor";
348
349 default:
350 return "<unknown>";
351 }
352}
353
354std::string
356{
357 switch (op)
358 {
359 case op_asn_eq:
360 return "=";
361
362 case op_add_eq:
363 return "+=";
364
365 case op_sub_eq:
366 return "-=";
367
368 case op_mul_eq:
369 return "*=";
370
371 case op_div_eq:
372 return "/=";
373
374 case op_ldiv_eq:
375 return R"(\=)";
376
377 case op_pow_eq:
378 return "^=";
379
380 case op_el_mul_eq:
381 return ".*=";
382
383 case op_el_div_eq:
384 return "./=";
385
386 case op_el_ldiv_eq:
387 return R"(.\=)";
388
389 case op_el_pow_eq:
390 return ".^=";
391
392 case op_el_and_eq:
393 return "&=";
394
395 case op_el_or_eq:
396 return "|=";
397
398 default:
399 return "<unknown>";
400 }
401}
402
405{
406 switch (op)
407 {
408 case op_add_eq:
409 return op_add;
410
411 case op_sub_eq:
412 return op_sub;
413
414 case op_mul_eq:
415 return op_mul;
416
417 case op_div_eq:
418 return op_div;
419
420 case op_ldiv_eq:
421 return op_ldiv;
422
423 case op_pow_eq:
424 return op_pow;
425
426 case op_el_mul_eq:
427 return op_el_mul;
428
429 case op_el_div_eq:
430 return op_el_div;
431
432 case op_el_ldiv_eq:
433 return op_el_ldiv;
434
435 case op_el_pow_eq:
436 return op_el_pow;
437
438 case op_el_and_eq:
439 return op_el_and;
440
441 case op_el_or_eq:
442 return op_el_or;
443
444 default:
445 return unknown_binary_op;
446 }
447}
448
451{
452 switch (op)
453 {
454 case op_add:
455 return op_add_eq;
456
457 case op_sub:
458 return op_sub_eq;
459
460 case op_mul:
461 return op_mul_eq;
462
463 case op_div:
464 return op_div_eq;
465
466 case op_el_mul:
467 return op_el_mul_eq;
468
469 case op_el_div:
470 return op_el_div_eq;
471
472 case op_el_and:
473 return op_el_and_eq;
474
475 case op_el_or:
476 return op_el_or_eq;
477
478 default:
479 return unknown_assign_op;
480 }
481}
482
484 : m_rep (new octave_scalar (i))
485{ }
486
487octave_value::octave_value (unsigned short int i)
488 : m_rep (new octave_scalar (i))
489{ }
490
492 : m_rep (new octave_scalar (i))
493{ }
494
496 : m_rep (new octave_scalar (i))
497{ }
498
500 : m_rep (new octave_scalar (i))
501{ }
502
503octave_value::octave_value (unsigned long int i)
504 : m_rep (new octave_scalar (i))
505{ }
506
507#if defined (OCTAVE_HAVE_LONG_LONG_INT)
508octave_value::octave_value (long long int i)
509 : m_rep (new octave_scalar (i))
510{ }
511#endif
512
513#if defined (OCTAVE_HAVE_UNSIGNED_LONG_LONG_INT)
514octave_value::octave_value (unsigned long long int i)
515 : m_rep (new octave_scalar (i))
516{ }
517#endif
518
519octave_value::octave_value (octave::sys::time t)
520 : m_rep (new octave_scalar (t.double_value ()))
521{ }
522
524 : m_rep (new octave_scalar (d))
525{ }
526
528 : m_rep (new octave_float_scalar (d))
529{ }
530
531octave_value::octave_value (const Cell& c, bool is_csl)
532 : m_rep (is_csl
533 ? dynamic_cast<octave_base_value *> (new octave_cs_list (c))
534 : dynamic_cast<octave_base_value *> (new octave_cell (c)))
535{ }
536
538 : m_rep (is_csl
539 ? dynamic_cast<octave_base_value *> (new octave_cs_list (Cell (a)))
540 : dynamic_cast<octave_base_value *> (new octave_cell (Cell (a))))
541{ }
542
544 : m_rep (new octave_matrix (m, t))
545{
546 maybe_mutate ();
547}
548
550 : m_rep (new octave_float_matrix (m, t))
551{
552 maybe_mutate ();
553}
554
556 : m_rep (new octave_matrix (a))
557{
558 maybe_mutate ();
559}
560
562 : m_rep (new octave_float_matrix (a))
563{
564 maybe_mutate ();
565}
566
568 : m_rep (new octave_matrix (a))
569{
570 maybe_mutate ();
571}
572
574 : m_rep (new octave_float_matrix (a))
575{
576 maybe_mutate ();
577}
578
580 : m_rep (Voptimize_diagonal_matrix
581 ? dynamic_cast<octave_base_value *> (new octave_diag_matrix (d))
582 : dynamic_cast<octave_base_value *> (new octave_matrix (Matrix (d))))
583{
584 maybe_mutate ();
585}
586
588 : m_rep (Voptimize_diagonal_matrix
589 ? dynamic_cast<octave_base_value *> (new octave_float_diag_matrix (d))
590 : dynamic_cast<octave_base_value *> (new octave_float_matrix (FloatMatrix (d))))
591{
592 maybe_mutate ();
593}
594
596 : m_rep (Voptimize_diagonal_matrix
597 ? dynamic_cast<octave_base_value *> (new octave_complex_diag_matrix (d))
598 : dynamic_cast<octave_base_value *> (new octave_complex_matrix (ComplexMatrix (d))))
599{
600 maybe_mutate ();
601}
602
604 : m_rep (Voptimize_diagonal_matrix
607{
608 maybe_mutate ();
609}
610
612 : m_rep (Voptimize_diagonal_matrix
613 ? dynamic_cast<octave_base_value *> (new octave_diag_matrix (d))
614 : dynamic_cast<octave_base_value *> (new octave_matrix (Matrix (d))))
615{
616 maybe_mutate ();
617}
618
620 : m_rep (Voptimize_diagonal_matrix
621 ? dynamic_cast<octave_base_value *> (new octave_float_diag_matrix (d))
622 : dynamic_cast<octave_base_value *> (new octave_float_matrix (FloatMatrix (d))))
623{
624 maybe_mutate ();
625}
626
628 : m_rep (new octave_matrix (v))
629{
630 maybe_mutate ();
631}
632
634 : m_rep (new octave_float_matrix (v))
635{
636 maybe_mutate ();
637}
638
640 : m_rep (new octave_matrix (v))
641{
642 maybe_mutate ();
643}
644
646 : m_rep (new octave_float_matrix (v))
647{
648 maybe_mutate ();
649}
650
652 : m_rep (new octave_complex (C))
653{
654 maybe_mutate ();
655}
656
658 : m_rep (new octave_float_complex (C))
659{
660 maybe_mutate ();
661}
662
664 : m_rep (new octave_complex_matrix (m, t))
665{
666 maybe_mutate ();
667}
668
670 : m_rep (new octave_float_complex_matrix (m, t))
671{
672 maybe_mutate ();
673}
674
676 : m_rep (new octave_complex_matrix (a))
677{
678 maybe_mutate ();
679}
680
686
688 : m_rep (new octave_complex_matrix (a))
689{
690 maybe_mutate ();
691}
692
698
700 : m_rep (Voptimize_diagonal_matrix
701 ? dynamic_cast<octave_base_value *> (new octave_complex_diag_matrix (d))
702 : dynamic_cast<octave_base_value *> (new octave_complex_matrix (ComplexMatrix (d))))
703{
704 maybe_mutate ();
705}
706
708 : m_rep (Voptimize_diagonal_matrix
711{
712 maybe_mutate ();
713}
714
716 : m_rep (new octave_complex_matrix (v))
717{
718 maybe_mutate ();
719}
720
726
728 : m_rep (new octave_complex_matrix (v))
729{
730 maybe_mutate ();
731}
732
738
740 : m_rep (Voptimize_permutation_matrix
741 ? dynamic_cast<octave_base_value *> (new octave_perm_matrix (p))
742 : dynamic_cast<octave_base_value *> (new octave_matrix (Matrix (p))))
743{
744 maybe_mutate ();
745}
746
748 : m_rep (new octave_bool (b))
749{ }
750
752 : m_rep (new octave_bool_matrix (bm, t))
753{
754 maybe_mutate ();
755}
756
758 : m_rep (new octave_bool_matrix (bnda))
759{
760 maybe_mutate ();
761}
762
764 : m_rep (new octave_bool_matrix (bnda))
765{
766 maybe_mutate ();
767}
768
769octave_value::octave_value (char c, char type)
770 : m_rep (type == '"'
773{
774 maybe_mutate ();
775}
776
777octave_value::octave_value (const char *s, char type)
778 : m_rep (type == '"'
781{
782 maybe_mutate ();
783}
784
785octave_value::octave_value (const std::string& s, char type)
786 : m_rep (type == '"'
789{
790 maybe_mutate ();
791}
792
793octave_value::octave_value (const string_vector& s, char type)
794 : m_rep (type == '"'
797{
798 maybe_mutate ();
799}
800
802 : m_rep (type == '"'
803 ? new octave_char_matrix_dq_str (chm)
804 : new octave_char_matrix_sq_str (chm))
805{
806 maybe_mutate ();
807}
808
809octave_value::octave_value (const charNDArray& chm, char type)
810 : m_rep (type == '"'
811 ? new octave_char_matrix_dq_str (chm)
812 : new octave_char_matrix_sq_str (chm))
813{
814 maybe_mutate ();
815}
816
817octave_value::octave_value (const Array<char>& chm, char type)
818 : m_rep (type == '"'
819 ? new octave_char_matrix_dq_str (chm)
820 : new octave_char_matrix_sq_str (chm))
821{
822 maybe_mutate ();
823}
824
826 : m_rep (new octave_sparse_matrix (m, t))
827{
828 maybe_mutate ();
829}
830
832 : m_rep (new octave_sparse_matrix (m, t))
833{
834 maybe_mutate ();
835}
836
838 : m_rep (new octave_sparse_complex_matrix (m, t))
839{
840 maybe_mutate ();
841}
842
844 : m_rep (new octave_sparse_complex_matrix (m, t))
845{
846 maybe_mutate ();
847}
848
850 : m_rep (new octave_sparse_bool_matrix (bm, t))
851{
852 maybe_mutate ();
853}
854
856 : m_rep (new octave_sparse_bool_matrix (bm, t))
857{
858 maybe_mutate ();
859}
860
862 : m_rep (new octave_int8_scalar (i))
863{
864 maybe_mutate ();
865}
866
868 : m_rep (new octave_uint8_scalar (i))
869{
870 maybe_mutate ();
871}
872
874 : m_rep (new octave_int16_scalar (i))
875{
876 maybe_mutate ();
877}
878
880 : m_rep (new octave_uint16_scalar (i))
881{
882 maybe_mutate ();
883}
884
886 : m_rep (new octave_int32_scalar (i))
887{
888 maybe_mutate ();
889}
890
892 : m_rep (new octave_uint32_scalar (i))
893{
894 maybe_mutate ();
895}
896
898 : m_rep (new octave_int64_scalar (i))
899{
900 maybe_mutate ();
901}
902
904 : m_rep (new octave_uint64_scalar (i))
905{
906 maybe_mutate ();
907}
908
910 : m_rep (new octave_int8_matrix (inda))
911{
912 maybe_mutate ();
913}
914
916 : m_rep (new octave_int8_matrix (inda))
917{
918 maybe_mutate ();
919}
920
922 : m_rep (new octave_uint8_matrix (inda))
923{
924 maybe_mutate ();
925}
926
928 : m_rep (new octave_uint8_matrix (inda))
929{
930 maybe_mutate ();
931}
932
934 : m_rep (new octave_int16_matrix (inda))
935{
936 maybe_mutate ();
937}
938
940 : m_rep (new octave_int16_matrix (inda))
941{
942 maybe_mutate ();
943}
944
946 : m_rep (new octave_uint16_matrix (inda))
947{
948 maybe_mutate ();
949}
950
952 : m_rep (new octave_uint16_matrix (inda))
953{
954 maybe_mutate ();
955}
956
958 : m_rep (new octave_int32_matrix (inda))
959{
960 maybe_mutate ();
961}
962
964 : m_rep (new octave_int32_matrix (inda))
965{
966 maybe_mutate ();
967}
968
970 : m_rep (new octave_uint32_matrix (inda))
971{
972 maybe_mutate ();
973}
974
976 : m_rep (new octave_uint32_matrix (inda))
977{
978 maybe_mutate ();
979}
980
982 : m_rep (new octave_int64_matrix (inda))
983{
984 maybe_mutate ();
985}
986
988 : m_rep (new octave_int64_matrix (inda))
989{
990 maybe_mutate ();
991}
992
994 : m_rep (new octave_uint64_matrix (inda))
995{
996 maybe_mutate ();
997}
998
1000 : m_rep (new octave_uint64_matrix (inda))
1001{
1002 maybe_mutate ();
1003}
1004
1005octave_value::octave_value (const Array<octave_idx_type>& inda, bool zero_based,
1006 bool cache_index)
1007 : m_rep (new octave_matrix (inda, zero_based, cache_index))
1008{
1009 maybe_mutate ();
1010}
1011
1012octave_value::octave_value (const octave::idx_vector& idx, bool lazy)
1013 : m_rep ()
1014{
1015 double scalar;
1016 octave::range<double> range;
1017 NDArray array;
1018 boolNDArray mask;
1019 octave::idx_vector::idx_class_type idx_class;
1020
1021 if (lazy)
1022 {
1023 // Only make lazy indices out of ranges and index vectors.
1024 switch (idx.idx_class ())
1025 {
1026 case octave::idx_vector::class_range:
1027 case octave::idx_vector::class_vector:
1028 m_rep = new octave_lazy_index (idx);
1029 maybe_mutate ();
1030 return;
1031
1032 default:
1033 break;
1034 }
1035 }
1036
1037 idx.unconvert (idx_class, scalar, range, array, mask);
1038
1039 switch (idx_class)
1040 {
1041 case octave::idx_vector::class_colon:
1042 m_rep = new octave_magic_colon ();
1043 break;
1044
1045 case octave::idx_vector::class_range:
1046 m_rep = new octave_range (range, idx);
1047 break;
1048
1049 case octave::idx_vector::class_scalar:
1050 m_rep = new octave_scalar (scalar);
1051 break;
1052
1053 case octave::idx_vector::class_vector:
1054 m_rep = new octave_matrix (array, idx);
1055 break;
1056
1057 case octave::idx_vector::class_mask:
1058 m_rep = new octave_bool_matrix (mask, idx);
1059 break;
1060
1061 case octave::idx_vector::class_invalid:
1062 error ("unexpected: invalid index in conversion to octave_value - please report this bug");
1063 break;
1064
1065 // We should have handled all possible enum values above. Rely
1066 // on compiler diagnostics to warn if we haven't. For example,
1067 // GCC's -Wswitch option, enabled by -Wall, will provide a
1068 // warning.
1069 }
1070
1071 // FIXME: needed?
1072 maybe_mutate ();
1073}
1074
1076 : m_rep (new octave_cell (cellstr))
1077{
1078 maybe_mutate ();
1079}
1080
1081octave_value::octave_value (const octave::range<double>& r, bool force_range)
1082 : m_rep (force_range || Voptimize_range
1083 ? dynamic_cast<octave_base_value *> (new ov_range<double> (r))
1084 : dynamic_cast<octave_base_value *> (new octave_matrix (r.array_value ())))
1085{
1086 maybe_mutate ();
1087}
1088
1089// For now, enable only range<double>.
1090
1092 : m_rep (new octave_struct (m))
1093{
1094 maybe_mutate ();
1095}
1096
1098 : m_rep (new octave_scalar_struct (m))
1099{ }
1100
1101octave_value::octave_value (const std::map<std::string, octave_value>& m)
1102 : m_rep (new octave_scalar_struct (m))
1103{ }
1104
1105octave_value::octave_value (const octave_map& m, const std::string& id,
1106 const std::list<std::string>& plist)
1107 : m_rep (new octave_class (m, id, plist))
1108{
1109 maybe_mutate ();
1110}
1111
1112octave_value::octave_value (const octave_scalar_map& m, const std::string& id,
1113 const std::list<std::string>& plist)
1114 : m_rep (new octave_class (m, id, plist))
1115{ }
1116
1118 : m_rep (new octave_cs_list (l))
1119{ }
1120
1122 : m_rep (new octave_magic_colon ())
1123{ }
1124
1126octave_value::clone () const
1127{
1128 return m_rep->clone ();
1129}
1130
1131void
1132octave_value::break_closure_cycles (const std::shared_ptr<octave::stack_frame>& frame)
1133{
1134 if (is_function_handle ())
1135 {
1137
1138 if (fhdl->is_nested (frame) && ! fhdl->is_weak_nested ())
1139 *this = fhdl->make_weak_nested_handle ();
1140 else if (fhdl->is_anonymous () && ! fhdl->is_weak_anonymous ())
1141 *this = fhdl->make_weak_anonymous_handle ();
1142 }
1143 else
1144 {
1145 // FIXME: Is there a efficient way to avoid calling make_unique
1146 // if REP doesn't contain any nested function handles?
1147 //
1148 // Probably we should be asking REP to make a modified copy IFF it
1149 // is needed, then replace our REP with that if a copy is made,
1150 // otherwise we leave it alone.
1151
1152 make_unique ();
1153
1154 m_rep->break_closure_cycles (frame);
1155 }
1156}
1157
1158void
1160{
1162
1163 if (tmp && tmp != m_rep)
1164 {
1165 if (--m_rep->m_count == 0)
1166 delete m_rep;
1167
1168 m_rep = tmp;
1169 }
1170}
1171
1173
1174DEFUN (double, args, ,
1175 doc: /* -*- texinfo -*-
1176@deftypefn {} {@var{y} =} double (@var{x})
1177Convert @var{x} to double precision type.
1178@seealso{single}
1179@end deftypefn */)
1180{
1181 if (args.length () != 1)
1182 print_usage ();
1183
1184 return ovl (args(0).as_double ());
1185}
1186
1187/*
1188%!assert (class (double (single (1))), "double")
1189%!assert (class (double (single (1 + i))), "double")
1190%!assert (class (double (int8 (1))), "double")
1191%!assert (class (double (uint8 (1))), "double")
1192%!assert (class (double (int16 (1))), "double")
1193%!assert (class (double (uint16 (1))), "double")
1194%!assert (class (double (int32 (1))), "double")
1195%!assert (class (double (uint32 (1))), "double")
1196%!assert (class (double (int64 (1))), "double")
1197%!assert (class (double (uint64 (1))), "double")
1198%!assert (class (double (true)), "double")
1199%!assert (class (double ("A")), "double")
1200%!test
1201%! x = sparse (logical ([1 0; 0 1]));
1202%! y = double (x);
1203%! assert (class (x), "logical");
1204%! assert (class (y), "double");
1205%! assert (issparse (y));
1206%!test
1207%! x = diag (single ([1 3 2]));
1208%! y = double (x);
1209%! assert (class (x), "single");
1210%! assert (class (y), "double");
1211%!test
1212%! x = diag (single ([i 3 2]));
1213%! y = double (x);
1214%! assert (class (x), "single");
1215%! assert (class (y), "double");
1216*/
1217
1218DEFUN (single, args, ,
1219 doc: /* -*- texinfo -*-
1220@deftypefn {} {@var{y} =} single (@var{x})
1221Convert @var{x} to single precision type.
1222@seealso{double}
1223@end deftypefn */)
1224{
1225 if (args.length () != 1)
1226 print_usage ();
1227
1228 return args(0).as_single ();
1229
1230 return ovl ();
1231}
1232
1233/*
1234%!assert (class (single (1)), "single")
1235%!assert (class (single (1 + i)), "single")
1236%!assert (class (single (int8 (1))), "single")
1237%!assert (class (single (uint8 (1))), "single")
1238%!assert (class (single (int16 (1))), "single")
1239%!assert (class (single (uint16 (1))), "single")
1240%!assert (class (single (int32 (1))), "single")
1241%!assert (class (single (uint32 (1))), "single")
1242%!assert (class (single (int64 (1))), "single")
1243%!assert (class (single (uint64 (1))), "single")
1244%!assert (class (single (true)), "single")
1245%!assert (class (single ("A")), "single")
1246%!error single (sparse (1))
1247%!test
1248%! x = diag ([1 3 2]);
1249%! y = single (x);
1250%! assert (class (x), "double");
1251%! assert (class (y), "single");
1252%!test
1253%! x = diag ([i 3 2]);
1254%! y = single (x);
1255%! assert (class (x), "double");
1256%! assert (class (y), "single");
1257*/
1258
1259DEFUN (int8, args, ,
1260 doc: /* -*- texinfo -*-
1261@deftypefn {} {@var{y} =} int8 (@var{x})
1262Convert @var{x} to 8-bit integer type.
1263@seealso{uint8, int16, uint16, int32, uint32, int64, uint64}
1264@end deftypefn */)
1265{
1266 if (args.length () != 1)
1267 print_usage ();
1268
1269 return args(0).as_int8 ();
1270}
1271
1272/*
1273%!assert (class (int8 (1)), "int8")
1274%!assert (int8 (1.25), int8 (1))
1275%!assert (int8 (1.5), int8 (2))
1276%!assert (int8 (-1.5), int8 (-2))
1277%!assert (int8 (2^9), int8 (2^8-1))
1278%!assert (int8 (-2^9), int8 (-2^8))
1279*/
1280
1281DEFUN (int16, args, ,
1282 doc: /* -*- texinfo -*-
1283@deftypefn {} {@var{y} =} int16 (@var{x})
1284Convert @var{x} to 16-bit integer type.
1285@seealso{int8, uint8, uint16, int32, uint32, int64, uint64}
1286@end deftypefn */)
1287{
1288 if (args.length () != 1)
1289 print_usage ();
1290
1291 return args(0).as_int16 ();
1292}
1293
1294/*
1295%!assert (class (int16 (1)), "int16")
1296%!assert (int16 (1.25), int16 (1))
1297%!assert (int16 (1.5), int16 (2))
1298%!assert (int16 (-1.5), int16 (-2))
1299%!assert (int16 (2^17), int16 (2^16-1))
1300%!assert (int16 (-2^17), int16 (-2^16))
1301*/
1302
1303DEFUN (int32, args, ,
1304 doc: /* -*- texinfo -*-
1305@deftypefn {} {@var{y} =} int32 (@var{x})
1306Convert @var{x} to 32-bit integer type.
1307@seealso{int8, uint8, int16, uint16, uint32, int64, uint64}
1308@end deftypefn */)
1309{
1310 if (args.length () != 1)
1311 print_usage ();
1312
1313 return args(0).as_int32 ();
1314}
1315
1316/*
1317%!assert (class (int32 (1)), "int32")
1318%!assert (int32 (1.25), int32 (1))
1319%!assert (int32 (1.5), int32 (2))
1320%!assert (int32 (-1.5), int32 (-2))
1321%!assert (int32 (2^33), int32 (2^32-1))
1322%!assert (int32 (-2^33), int32 (-2^32))
1323*/
1324
1325DEFUN (int64, args, ,
1326 doc: /* -*- texinfo -*-
1327@deftypefn {} {@var{y} =} int64 (@var{x})
1328Convert @var{x} to 64-bit integer type.
1329@seealso{int8, uint8, int16, uint16, int32, uint32, uint64}
1330@end deftypefn */)
1331{
1332 if (args.length () != 1)
1333 print_usage ();
1334
1335 return args(0).as_int64 ();
1336}
1337
1338/*
1339%!assert (class (int64 (1)), "int64")
1340%!assert (int64 (1.25), int64 (1))
1341%!assert (int64 (1.5), int64 (2))
1342%!assert (int64 (-1.5), int64 (-2))
1343%!assert (int64 (2^65), int64 (2^64-1))
1344%!assert (int64 (-2^65), int64 (-2^64))
1345*/
1346
1347DEFUN (uint8, args, ,
1348 doc: /* -*- texinfo -*-
1349@deftypefn {} {@var{y} =} uint8 (@var{x})
1350Convert @var{x} to unsigned 8-bit integer type.
1351@seealso{int8, int16, uint16, int32, uint32, int64, uint64}
1352@end deftypefn */)
1353{
1354 if (args.length () != 1)
1355 print_usage ();
1356
1357 return args(0).as_uint8 ();
1358}
1359
1360/*
1361%!assert (class (uint8 (1)), "uint8")
1362%!assert (uint8 (1.25), uint8 (1))
1363%!assert (uint8 (1.5), uint8 (2))
1364%!assert (uint8 (-1.5), uint8 (0))
1365%!assert (uint8 (2^9), uint8 (2^8-1))
1366%!assert (uint8 (-2^9), uint8 (0))
1367*/
1368
1369DEFUN (uint16, args, ,
1370 doc: /* -*- texinfo -*-
1371@deftypefn {} {@var{y} =} uint16 (@var{x})
1372Convert @var{x} to unsigned 16-bit integer type.
1373@seealso{int8, uint8, int16, int32, uint32, int64, uint64}
1374@end deftypefn */)
1375{
1376 if (args.length () != 1)
1377 print_usage ();
1378
1379 return args(0).as_uint16 ();
1380}
1381
1382/*
1383%!assert (class (uint16 (1)), "uint16")
1384%!assert (uint16 (1.25), uint16 (1))
1385%!assert (uint16 (1.5), uint16 (2))
1386%!assert (uint16 (-1.5), uint16 (0))
1387%!assert (uint16 (2^17), uint16 (2^16-1))
1388%!assert (uint16 (-2^17), uint16 (0))
1389*/
1390
1391DEFUN (uint32, args, ,
1392 doc: /* -*- texinfo -*-
1393@deftypefn {} {@var{y} =} uint32 (@var{x})
1394Convert @var{x} to unsigned 32-bit integer type.
1395@seealso{int8, uint8, int16, uint16, int32, int64, uint64}
1396@end deftypefn */)
1397{
1398 if (args.length () != 1)
1399 print_usage ();
1400
1401 return args(0).as_uint32 ();
1402}
1403
1404/*
1405%!assert (class (uint32 (1)), "uint32")
1406%!assert (uint32 (1.25), uint32 (1))
1407%!assert (uint32 (1.5), uint32 (2))
1408%!assert (uint32 (-1.5), uint32 (0))
1409%!assert (uint32 (2^33), uint32 (2^32-1))
1410%!assert (uint32 (-2^33), uint32 (0))
1411*/
1412
1413DEFUN (uint64, args, ,
1414 doc: /* -*- texinfo -*-
1415@deftypefn {} {@var{y} =} uint64 (@var{x})
1416Convert @var{x} to unsigned 64-bit integer type.
1417@seealso{int8, uint8, int16, uint16, int32, uint32, int64}
1418@end deftypefn */)
1419{
1420 if (args.length () != 1)
1421 print_usage ();
1422
1423 return args(0).as_uint64 ();
1424}
1425
1426/*
1427%!assert (class (uint64 (1)), "uint64")
1428%!assert (uint64 (1.25), uint64 (1))
1429%!assert (uint64 (1.5), uint64 (2))
1430%!assert (uint64 (-1.5), uint64 (0))
1431%!assert (uint64 (2^65), uint64 (2^64-1))
1432%!assert (uint64 (-2^65), uint64 (0))
1433*/
1434
1435OCTAVE_END_NAMESPACE(octave)
1436
1438octave_value::single_subsref (const std::string& type,
1439 const octave_value_list& idx)
1440{
1441 std::list<octave_value_list> i;
1442
1443 i.push_back (idx);
1444
1445 return m_rep->subsref (type, i);
1446}
1447
1450simple_subsref (char type, octave_value_list& idx, int nargout)
1451{
1452 return m_rep->simple_subsref (type, idx, nargout);
1453}
1454
1456octave_value::subsref (const std::string& type,
1457 const std::list<octave_value_list>& idx, int nargout)
1458{
1459 return m_rep->subsref (type, idx, nargout);
1460}
1461
1463octave_value::next_subsref (const std::string& type,
1464 const std::list<octave_value_list>& idx,
1465 std::size_t skip)
1466{
1467 if (idx.size () > skip)
1468 {
1469 std::list<octave_value_list> new_idx (idx);
1470 for (std::size_t i = 0; i < skip; i++)
1471 new_idx.erase (new_idx.begin ());
1472 return subsref (type.substr (skip), new_idx);
1473 }
1474 else
1475 return *this;
1476}
1477
1479octave_value::next_subsref (int nargout, const std::string& type,
1480 const std::list<octave_value_list>& idx,
1481 std::size_t skip)
1482{
1483 if (idx.size () > skip)
1484 {
1485 std::list<octave_value_list> new_idx (idx);
1486 for (std::size_t i = 0; i < skip; i++)
1487 new_idx.erase (new_idx.begin ());
1488 return subsref (type.substr (skip), new_idx, nargout);
1489 }
1490 else
1491 return *this;
1492}
1493
1495octave_value::next_subsref (bool auto_add, const std::string& type,
1496 const std::list<octave_value_list>& idx,
1497 std::size_t skip)
1498{
1499 if (idx.size () > skip)
1500 {
1501 std::list<octave_value_list> new_idx (idx);
1502 for (std::size_t i = 0; i < skip; i++)
1503 new_idx.erase (new_idx.begin ());
1504 return subsref (type.substr (skip), new_idx, auto_add);
1505 }
1506 else
1507 return *this;
1508}
1509
1512 octave_idx_type num_indices) const
1513{
1514 dim_vector dv = dims ();
1515 int ndims = dv.ndims ();
1516
1517 if (num_indices < ndims)
1518 {
1519 for (int i = num_indices; i < ndims; i++)
1520 dv(num_indices-1) *= dv(i);
1521
1522 if (num_indices == 1)
1523 {
1524 ndims = 2;
1525 dv.resize (ndims);
1526 dv(1) = 1;
1527 }
1528 else
1529 {
1530 ndims = num_indices;
1531 dv.resize (ndims);
1532 }
1533 }
1534
1535 return (index_position < ndims ? dv(index_position) : 1);
1536}
1537
1539octave_value::subsasgn (const std::string& type,
1540 const std::list<octave_value_list>& idx,
1541 const octave_value& rhs)
1542{
1543 return m_rep->subsasgn (type, idx, rhs);
1544}
1545
1547octave_value::undef_subsasgn (const std::string& type,
1548 const std::list<octave_value_list>& idx,
1549 const octave_value& rhs)
1550{
1551 return m_rep->undef_subsasgn (type, idx, rhs);
1552}
1553
1555octave_value::assign (assign_op op, const std::string& type,
1556 const std::list<octave_value_list>& idx,
1557 const octave_value& rhs)
1558{
1559 make_unique ();
1560
1561 octave_value t_rhs = rhs;
1562
1563 if (op != op_asn_eq)
1564 {
1565 if (! is_defined ())
1566 error ("in computed assignment A(index) OP= X, A must be defined first");
1567
1568 octave_value t = subsref (type, idx);
1569
1570 binary_op binop = op_eq_to_binary_op (op);
1571
1572 t_rhs = octave::binary_op (binop, t, rhs);
1573 }
1574
1575 *this = subsasgn (type, idx, t_rhs);
1576
1577 return *this;
1578}
1579
1581octave_value::assign (assign_op op, const octave_value& rhs)
1582{
1583 if (op == op_asn_eq)
1584 // Regularize a null matrix if stored into a variable.
1586 else if (is_defined ())
1587 {
1588 octave::type_info::assign_op_fcn f = nullptr;
1589
1590 // Only attempt to operate in-place if this variable is unshared.
1591 if (m_rep->m_count == 1)
1592 {
1593 int tthis = this->type_id ();
1594 int trhs = rhs.type_id ();
1595
1596 octave::type_info& ti = octave::__get_type_info__ ();
1597
1598 f = ti.lookup_assign_op (op, tthis, trhs);
1599 }
1600
1601 if (f)
1602 {
1603 f (*m_rep, octave_value_list (), rhs.get_rep ());
1604 // Usually unnecessary, but may be needed (complex arrays).
1605 maybe_mutate ();
1606 }
1607 else
1608 {
1609
1610 binary_op binop = op_eq_to_binary_op (op);
1611
1612 octave_value t = octave::binary_op (binop, *this, rhs);
1613
1614 operator = (t);
1615 }
1616 }
1617 else
1618 error ("in computed assignment A OP= X, A must be defined first");
1619
1620 return *this;
1621}
1622
1623// FIXME: This is a bit of a kluge. We'd like to just use val.dims()
1624// and if val is an object, expect that dims will call size if it is
1625// overloaded by a user-defined method. But there are currently some
1626// unresolved const issues that prevent that solution from working.
1627
1628std::string
1630{
1631 octave_value tmp = *this;
1632
1633 Matrix sz = tmp.size ();
1634
1635 dim_vector dv = dim_vector::alloc (sz.numel ());
1636
1637 for (octave_idx_type i = 0; i < dv.ndims (); i++)
1638 dv(i) = sz(i);
1639
1640 return dv.str ();
1641}
1642
1644octave_value::length () const
1645{
1646 octave_idx_type retval = 0;
1647
1648 const dim_vector dv = dims ();
1649
1650 for (int i = 0; i < dv.ndims (); i++)
1651 {
1652 if (dv(i) == 0)
1653 {
1654 retval = 0;
1655 break;
1656 }
1657
1658 if (dv(i) > retval)
1659 retval = dv(i);
1660 }
1661
1662 return retval;
1663}
1664
1665bool
1666octave_value::is_equal (const octave_value& test) const
1667{
1668 bool retval = false;
1669
1670 // If there is no op_eq for these types, we can't compare values.
1671
1672 if (rows () == test.rows () && columns () == test.columns ())
1673 {
1674 octave_value tmp = octave::binary_op (octave_value::op_eq, *this, test);
1675
1676 // Empty array also means a match.
1677 if (tmp.is_defined ())
1678 {
1679 if (tmp.isempty ())
1680 retval = true;
1681 else
1682 {
1683 // Reshape into a vector and call all() explicitly,
1684 // to avoid Octave:array-as-logical warning.
1685 tmp = tmp.reshape (dim_vector (tmp.numel (), 1));
1686 retval = tmp.all ().is_true ();
1687 }
1688 }
1689 }
1690
1691 return retval;
1692}
1693
1694// Define the idx_type_value function here instead of in ov.h to avoid
1695// needing definitions for the SIZEOF_X macros in ov.h.
1696
1698octave_value::idx_type_value (bool req_int, bool frc_str_conv) const
1699{
1700#if defined (OCTAVE_ENABLE_64)
1701 return int64_value (req_int, frc_str_conv);
1702#else
1703 return int_value (req_int, frc_str_conv);
1704#endif
1705}
1706
1708octave_value::strict_idx_type_value (bool frc_str_conv) const
1709{
1710#if defined (OCTAVE_ENABLE_64)
1711 return int64_value (true, frc_str_conv);
1712#else
1713 return int_value (true, frc_str_conv);
1714#endif
1715}
1716
1717Cell
1719{
1720 return m_rep->cell_value ();
1721}
1722
1725{
1726 return m_rep->map_value ();
1727}
1728
1731{
1732 return m_rep->scalar_map_value ();
1733}
1734
1736octave_value::function_value (bool silent) const
1737{
1738 return m_rep->function_value (silent);
1739}
1740
1742octave_value::classdef_object_value (bool silent) const
1743{
1744 return m_rep->classdef_object_value (silent);
1745}
1746
1748octave_value::user_function_value (bool silent) const
1749{
1750 return m_rep->user_function_value (silent);
1751}
1752
1754octave_value::user_script_value (bool silent) const
1755{
1756 return m_rep->user_script_value (silent);
1757}
1758
1760octave_value::user_code_value (bool silent) const
1761{
1762 return m_rep->user_code_value (silent);
1763}
1764
1766octave_value::fcn_handle_value (bool silent) const
1767{
1768 return m_rep->fcn_handle_value (silent);
1769}
1770
1773{
1774 return m_rep->list_value ();
1775}
1776
1777static dim_vector
1778make_vector_dims (const dim_vector& dv, bool force_vector_conversion,
1779 const std::string& my_type, const std::string& wanted_type)
1780{
1781 dim_vector retval (dv);
1782 retval.chop_trailing_singletons ();
1783 octave_idx_type nel = dv.numel ();
1784
1785 if (retval.ndims () > 2 || (retval(0) != 1 && retval(1) != 1))
1786 {
1787 if (! force_vector_conversion)
1788 warn_implicit_conversion ("Octave:array-to-vector",
1789 my_type.c_str (), wanted_type.c_str ());
1790 retval = dim_vector (nel, 1);
1791 }
1792
1793 return retval;
1794}
1795
1797octave_value::column_vector_value (bool force_string_conv,
1798 bool frc_vec_conv) const
1799{
1800 return ColumnVector (vector_value (force_string_conv,
1801 frc_vec_conv));
1802}
1803
1805octave_value::complex_column_vector_value (bool force_string_conv,
1806 bool frc_vec_conv) const
1807{
1808 return ComplexColumnVector (complex_vector_value (force_string_conv,
1809 frc_vec_conv));
1810}
1811
1813octave_value::row_vector_value (bool force_string_conv,
1814 bool frc_vec_conv) const
1815{
1816 return RowVector (vector_value (force_string_conv,
1817 frc_vec_conv));
1818}
1819
1821octave_value::complex_row_vector_value (bool force_string_conv,
1822 bool frc_vec_conv) const
1823{
1824 return ComplexRowVector (complex_vector_value (force_string_conv,
1825 frc_vec_conv));
1826}
1827
1829octave_value::vector_value (bool force_string_conv,
1830 bool force_vector_conversion) const
1831{
1832 Array<double> retval = array_value (force_string_conv);
1833
1834 return retval.reshape (make_vector_dims (retval.dims (),
1835 force_vector_conversion,
1836 type_name (), "real vector"));
1837}
1838
1839template <typename T>
1840static Array<int>
1841convert_to_int_array (const Array<octave_int<T>>& A)
1842{
1843 Array<int> retval (A.dims ());
1844 octave_idx_type n = A.numel ();
1845
1846 for (octave_idx_type i = 0; i < n; i++)
1847 retval.xelem (i) = octave_int<int> (A.xelem (i));
1848
1849 return retval;
1850}
1851
1853octave_value::int_vector_value (bool require_int, bool force_string_conv,
1854 bool force_vector_conversion) const
1855{
1856 Array<int> retval;
1857
1858 if (isinteger ())
1859 {
1860 if (is_int32_type ())
1861 retval = convert_to_int_array (int32_array_value ());
1862 else if (is_int64_type ())
1863 retval = convert_to_int_array (int64_array_value ());
1864 else if (is_int16_type ())
1865 retval = convert_to_int_array (int16_array_value ());
1866 else if (is_int8_type ())
1867 retval = convert_to_int_array (int8_array_value ());
1868 else if (is_uint32_type ())
1869 retval = convert_to_int_array (uint32_array_value ());
1870 else if (is_uint64_type ())
1871 retval = convert_to_int_array (uint64_array_value ());
1872 else if (is_uint16_type ())
1873 retval = convert_to_int_array (uint16_array_value ());
1874 else if (is_uint8_type ())
1875 retval = convert_to_int_array (uint8_array_value ());
1876 else
1877 retval = array_value (force_string_conv);
1878 }
1879 else
1880 {
1881 const NDArray a = array_value (force_string_conv);
1882
1883 if (require_int)
1884 {
1885 retval.resize (a.dims ());
1886 for (octave_idx_type i = 0; i < a.numel (); i++)
1887 {
1888 double ai = a.elem (i);
1889 int v = static_cast<int> (ai);
1890 if (ai == v)
1891 retval.xelem (i) = v;
1892 else
1893 {
1894 error_with_cfn ("conversion of %g to int value failed", ai);
1895 break;
1896 }
1897 }
1898 }
1899 else
1900 retval = Array<int> (a);
1901 }
1902
1903 return retval.reshape (make_vector_dims (retval.dims (),
1904 force_vector_conversion,
1905 type_name (), "integer vector"));
1906}
1907
1908template <typename T>
1910convert_to_octave_idx_type_array (const Array<octave_int<T>>& A)
1911{
1912 Array<octave_idx_type> retval (A.dims ());
1913 octave_idx_type n = A.numel ();
1914
1915 for (octave_idx_type i = 0; i < n; i++)
1916 retval.xelem (i) = octave_int<octave_idx_type> (A.xelem (i));
1917
1918 return retval;
1919}
1920
1923 bool force_string_conv,
1924 bool force_vector_conversion) const
1925{
1927
1928 if (isinteger ())
1929 {
1930 if (is_int32_type ())
1931 retval = convert_to_octave_idx_type_array (int32_array_value ());
1932 else if (is_int64_type ())
1933 retval = convert_to_octave_idx_type_array (int64_array_value ());
1934 else if (is_int16_type ())
1935 retval = convert_to_octave_idx_type_array (int16_array_value ());
1936 else if (is_int8_type ())
1937 retval = convert_to_octave_idx_type_array (int8_array_value ());
1938 else if (is_uint32_type ())
1939 retval = convert_to_octave_idx_type_array (uint32_array_value ());
1940 else if (is_uint64_type ())
1941 retval = convert_to_octave_idx_type_array (uint64_array_value ());
1942 else if (is_uint16_type ())
1943 retval = convert_to_octave_idx_type_array (uint16_array_value ());
1944 else if (is_uint8_type ())
1945 retval = convert_to_octave_idx_type_array (uint8_array_value ());
1946 else
1947 retval = array_value (force_string_conv);
1948 }
1949 else
1950 {
1951 const NDArray a = array_value (force_string_conv);
1952
1953 if (require_int)
1954 {
1955 retval.resize (a.dims ());
1956 for (octave_idx_type i = 0; i < a.numel (); i++)
1957 {
1958 double ai = a.elem (i);
1959 octave_idx_type v = static_cast<octave_idx_type> (ai);
1960 if (ai == v)
1961 retval.xelem (i) = v;
1962 else
1963 {
1964 error_with_cfn ("conversion of %g to octave_idx_type value failed", ai);
1965 break;
1966 }
1967 }
1968 }
1969 else
1970 retval = Array<octave_idx_type> (a);
1971 }
1972
1973 return retval.reshape (make_vector_dims (retval.dims (),
1974 force_vector_conversion,
1975 type_name (), "integer vector"));
1976}
1977
1979octave_value::complex_vector_value (bool force_string_conv,
1980 bool force_vector_conversion) const
1981{
1982 Array<Complex> retval = complex_array_value (force_string_conv);
1983
1984 return retval.reshape (make_vector_dims (retval.dims (),
1985 force_vector_conversion,
1986 type_name (), "complex vector"));
1987}
1988
1990octave_value::float_column_vector_value (bool force_string_conv,
1991 bool frc_vec_conv) const
1992{
1993 return FloatColumnVector (float_vector_value (force_string_conv,
1994 frc_vec_conv));
1995}
1996
1999 bool frc_vec_conv) const
2000{
2001 return
2003 frc_vec_conv));
2004}
2005
2007octave_value::float_row_vector_value (bool force_string_conv,
2008 bool frc_vec_conv) const
2009{
2010 return FloatRowVector (float_vector_value (force_string_conv,
2011 frc_vec_conv));
2012}
2013
2015octave_value::float_complex_row_vector_value (bool force_string_conv,
2016 bool frc_vec_conv) const
2017{
2018 return FloatComplexRowVector (float_complex_vector_value (force_string_conv,
2019 frc_vec_conv));
2020}
2021
2023octave_value::float_vector_value (bool force_string_conv,
2024 bool force_vector_conversion) const
2025{
2026 Array<float> retval = float_array_value (force_string_conv);
2027
2028 return retval.reshape (make_vector_dims (retval.dims (),
2029 force_vector_conversion,
2030 type_name (), "real vector"));
2031}
2032
2034octave_value::float_complex_vector_value (bool force_string_conv,
2035 bool force_vector_conversion) const
2036{
2037 Array<FloatComplex> retval = float_complex_array_value (force_string_conv);
2038
2039 return retval.reshape (make_vector_dims (retval.dims (),
2040 force_vector_conversion,
2041 type_name (), "complex vector"));
2042}
2043
2044// NAME can't always be "x ## FCN" because some of the original
2045// value extraction functions perform implicit type conversions that we
2046// wish to avoid for these functions.
2047
2048#define XVALUE_EXTRACTOR(TYPE, NAME, FCN) \
2049 TYPE \
2050 octave_value::NAME (const char *fmt, ...) const \
2051 { \
2052 TYPE retval; \
2053 \
2054 try \
2055 { \
2056 retval = FCN (); \
2057 } \
2058 catch (octave::execution_exception& ee) \
2059 { \
2060 if (fmt) \
2061 { \
2062 va_list args; \
2063 va_start (args, fmt); \
2064 verror (ee, fmt, args); \
2065 va_end (args); \
2066 } \
2067 \
2068 throw ee; \
2069 } \
2070 \
2071 return retval; \
2072 }
2073
2074XVALUE_EXTRACTOR (short int, xshort_value, short_value)
2075
2076XVALUE_EXTRACTOR (unsigned short int, xushort_value, ushort_value)
2077
2078XVALUE_EXTRACTOR (int, xint_value, int_value)
2079
2080XVALUE_EXTRACTOR (unsigned int, xuint_value, uint_value)
2081
2082XVALUE_EXTRACTOR (int, xnint_value, nint_value)
2083
2084XVALUE_EXTRACTOR (long int, xlong_value, long_value)
2085
2086XVALUE_EXTRACTOR (unsigned long int, xulong_value, ulong_value)
2087
2088XVALUE_EXTRACTOR (int64_t, xint64_value, int64_value)
2089
2090XVALUE_EXTRACTOR (uint64_t, xuint64_value, uint64_value)
2091
2092XVALUE_EXTRACTOR (octave_idx_type, xidx_type_value, idx_type_value)
2093
2094XVALUE_EXTRACTOR (double, xdouble_value, double_value)
2095XVALUE_EXTRACTOR (float, xfloat_value, float_value)
2096
2097XVALUE_EXTRACTOR (double, xscalar_value, scalar_value)
2098XVALUE_EXTRACTOR (float, xfloat_scalar_value, float_scalar_value)
2099
2100XVALUE_EXTRACTOR (Matrix, xmatrix_value, matrix_value)
2101XVALUE_EXTRACTOR (FloatMatrix, xfloat_matrix_value, float_matrix_value)
2102
2103XVALUE_EXTRACTOR (NDArray, xarray_value, array_value)
2104XVALUE_EXTRACTOR (FloatNDArray, xfloat_array_value, float_array_value)
2105
2106XVALUE_EXTRACTOR (Complex, xcomplex_value, complex_value)
2107XVALUE_EXTRACTOR (FloatComplex, xfloat_complex_value, float_complex_value)
2108
2109XVALUE_EXTRACTOR (ComplexMatrix, xcomplex_matrix_value, complex_matrix_value)
2110XVALUE_EXTRACTOR (FloatComplexMatrix, xfloat_complex_matrix_value, float_complex_matrix_value)
2111
2112XVALUE_EXTRACTOR (ComplexNDArray, xcomplex_array_value, complex_array_value)
2113XVALUE_EXTRACTOR (FloatComplexNDArray, xfloat_complex_array_value, float_complex_array_value)
2114
2115XVALUE_EXTRACTOR (bool, xbool_value, bool_value)
2116XVALUE_EXTRACTOR (boolMatrix, xbool_matrix_value, bool_matrix_value)
2117XVALUE_EXTRACTOR (boolNDArray, xbool_array_value, bool_array_value)
2118
2119XVALUE_EXTRACTOR (charMatrix, xchar_matrix_value, char_matrix_value)
2120XVALUE_EXTRACTOR (charNDArray, xchar_array_value, char_array_value)
2121
2122XVALUE_EXTRACTOR (SparseMatrix, xsparse_matrix_value, sparse_matrix_value)
2123XVALUE_EXTRACTOR (SparseComplexMatrix, xsparse_complex_matrix_value, sparse_complex_matrix_value)
2124XVALUE_EXTRACTOR (SparseBoolMatrix, xsparse_bool_matrix_value, sparse_bool_matrix_value)
2125
2126XVALUE_EXTRACTOR (DiagMatrix, xdiag_matrix_value, diag_matrix_value)
2127XVALUE_EXTRACTOR (FloatDiagMatrix, xfloat_diag_matrix_value, float_diag_matrix_value)
2128XVALUE_EXTRACTOR (ComplexDiagMatrix, xcomplex_diag_matrix_value, complex_diag_matrix_value)
2129XVALUE_EXTRACTOR (FloatComplexDiagMatrix, xfloat_complex_diag_matrix_value, float_complex_diag_matrix_value)
2130
2131XVALUE_EXTRACTOR (PermMatrix, xperm_matrix_value, perm_matrix_value)
2132
2133XVALUE_EXTRACTOR (octave_int8, xint8_scalar_value, int8_scalar_value)
2134XVALUE_EXTRACTOR (octave_int16, xint16_scalar_value, int16_scalar_value)
2135XVALUE_EXTRACTOR (octave_int32, xint32_scalar_value, int32_scalar_value)
2136XVALUE_EXTRACTOR (octave_int64, xint64_scalar_value, int64_scalar_value)
2137
2138XVALUE_EXTRACTOR (octave_uint8, xuint8_scalar_value, uint8_scalar_value)
2139XVALUE_EXTRACTOR (octave_uint16, xuint16_scalar_value, uint16_scalar_value)
2140XVALUE_EXTRACTOR (octave_uint32, xuint32_scalar_value, uint32_scalar_value)
2141XVALUE_EXTRACTOR (octave_uint64, xuint64_scalar_value, uint64_scalar_value)
2142
2143XVALUE_EXTRACTOR (int8NDArray, xint8_array_value, int8_array_value)
2144XVALUE_EXTRACTOR (int16NDArray, xint16_array_value, int16_array_value)
2145XVALUE_EXTRACTOR (int32NDArray, xint32_array_value, int32_array_value)
2146XVALUE_EXTRACTOR (int64NDArray, xint64_array_value, int64_array_value)
2147
2148XVALUE_EXTRACTOR (uint8NDArray, xuint8_array_value, uint8_array_value)
2149XVALUE_EXTRACTOR (uint16NDArray, xuint16_array_value, uint16_array_value)
2150XVALUE_EXTRACTOR (uint32NDArray, xuint32_array_value, uint32_array_value)
2151XVALUE_EXTRACTOR (uint64NDArray, xuint64_array_value, uint64_array_value)
2152
2153XVALUE_EXTRACTOR (std::string, xstring_value, m_rep->xstring_value)
2154XVALUE_EXTRACTOR (string_vector, xstring_vector_value, string_vector_value)
2155
2156XVALUE_EXTRACTOR (Cell, xcell_value, cell_value)
2157XVALUE_EXTRACTOR (Array<std::string>, xcellstr_value, cellstr_value)
2158
2159XVALUE_EXTRACTOR (octave::range<double>, xrange_value, range_value)
2160
2161// For now, enable only ov_range<double>.
2162
2163XVALUE_EXTRACTOR (octave_map, xmap_value, map_value)
2164XVALUE_EXTRACTOR (octave_scalar_map, xscalar_map_value, scalar_map_value)
2165
2166XVALUE_EXTRACTOR (ColumnVector, xcolumn_vector_value, column_vector_value)
2167XVALUE_EXTRACTOR (ComplexColumnVector, xcomplex_column_vector_value, complex_column_vector_value)
2168
2169XVALUE_EXTRACTOR (RowVector, xrow_vector_value, row_vector_value)
2170XVALUE_EXTRACTOR (ComplexRowVector, xcomplex_row_vector_value, complex_row_vector_value)
2171
2172XVALUE_EXTRACTOR (FloatColumnVector, xfloat_column_vector_value, float_column_vector_value)
2173XVALUE_EXTRACTOR (FloatComplexColumnVector, xfloat_complex_column_vector_value, float_complex_column_vector_value)
2174
2175XVALUE_EXTRACTOR (FloatRowVector, xfloat_row_vector_value, float_row_vector_value)
2176XVALUE_EXTRACTOR (FloatComplexRowVector, xfloat_complex_row_vector_value, float_complex_row_vector_value)
2177
2178XVALUE_EXTRACTOR (Array<int>, xint_vector_value, int_vector_value)
2179XVALUE_EXTRACTOR (Array<octave_idx_type>, xoctave_idx_type_vector_value, octave_idx_type_vector_value)
2180
2181XVALUE_EXTRACTOR (Array<double>, xvector_value, vector_value)
2182XVALUE_EXTRACTOR (Array<Complex>, xcomplex_vector_value, complex_vector_value)
2183
2184XVALUE_EXTRACTOR (Array<float>, xfloat_vector_value, float_vector_value)
2185XVALUE_EXTRACTOR (Array<FloatComplex>, xfloat_complex_vector_value, float_complex_vector_value)
2186
2187XVALUE_EXTRACTOR (octave_function *, xfunction_value, function_value)
2188XVALUE_EXTRACTOR (octave_user_function *, xuser_function_value, user_function_value)
2189XVALUE_EXTRACTOR (octave_user_script *, xuser_script_value, user_script_value)
2190XVALUE_EXTRACTOR (octave_user_code *, xuser_code_value, user_code_value)
2191XVALUE_EXTRACTOR (octave_fcn_handle *, xfcn_handle_value, fcn_handle_value)
2192
2193XVALUE_EXTRACTOR (octave_value_list, xlist_value, list_value)
2194
2195// Make some stricter versions of XVALUE_EXTRACTOR,
2196// especially for parsing integer arguments that cannot be floating point.
2197// See bug #65538.
2198
2199XVALUE_EXTRACTOR (int, strict_int_value, strict_int_value)
2200
2201XVALUE_EXTRACTOR (bool, strict_bool_value, strict_bool_value)
2202
2203XVALUE_EXTRACTOR (octave_idx_type, strict_idx_type_value, strict_idx_type_value)
2204
2205#undef XVALUE_EXTRACTOR
2206
2207
2210{
2211 octave_value retval = *this;
2212 if (isnull ())
2213 retval = octave_value (m_rep->empty_clone ());
2214 else if (is_magic_int ())
2215 retval = octave_value (m_rep->double_value ());
2216 else if (is_range () && ! m_rep->is_storable ())
2217 error ("range with infinite number of elements cannot be stored");
2218 else
2219 retval.maybe_economize ();
2220
2221 return retval;
2222}
2223
2224void
2226{
2227 if (isnull ())
2228 {
2230 if (--m_rep->m_count == 0)
2231 delete m_rep;
2232 m_rep = rc;
2233 }
2234 else if (is_magic_int ())
2235 {
2237 if (--m_rep->m_count == 0)
2238 delete m_rep;
2239 m_rep = rc;
2240 }
2241 else if (is_range () && ! m_rep->is_storable ())
2242 error ("range with infinite number of elements cannot be stored");
2243 else
2244 maybe_economize ();
2245}
2246
2249{
2250 return m_rep->get_edit_display_format ();
2251}
2252
2253int
2254octave_value::write (octave::stream& os, int block_size,
2255 oct_data_conv::data_type output_type, int skip,
2256 octave::mach_info::float_format flt_fmt) const
2257{
2258 return m_rep->write (os, block_size, output_type, skip, flt_fmt);
2259}
2260
2261void
2262octave_value::print_info (std::ostream& os, const std::string& prefix) const
2263{
2264 os << prefix << "type_name: " << type_name () << "\n"
2265 << prefix << "m_count: " << get_count () << "\n"
2266 << prefix << "m_rep info: ";
2267
2268 m_rep->print_info (os, prefix + ' ');
2269}
2270
2271bool
2272octave_value::load_ascii (std::istream& is)
2273{
2274 bool status = m_rep->load_ascii (is);
2275
2276 // Force conversion of legacy objects.
2277 if (is_legacy_object ())
2278 maybe_mutate ();
2279
2280 return status;
2281}
2282bool
2283octave_value::load_binary (std::istream& is, bool swap,
2284 octave::mach_info::float_format fmt)
2285{
2286 bool status = m_rep->load_binary (is, swap, fmt);
2287
2288 // Force conversion of legacy objects.
2289 if (is_legacy_object ())
2290 maybe_mutate ();
2291
2292 return status;
2293}
2294
2295bool
2296octave_value::load_hdf5 (octave_hdf5_id loc_id, const char *name)
2297{
2298 bool status = m_rep->load_hdf5 (loc_id, name);
2299
2300 // Force conversion of legacy objects.
2301 if (is_legacy_object ())
2302 maybe_mutate ();
2303
2304 return status;
2305}
2306
2307const void *
2308octave_value::mex_get_data (mxClassID class_id, mxComplexity complexity) const
2309{
2310 // If class_id is set to mxUNKNOWN_CLASS, return data for any type.
2311 // Otherwise, require that REP matches the requested type and
2312 // complexity.
2313
2314 if (class_id != mxUNKNOWN_CLASS)
2315 {
2316 bool type_ok = false;
2317
2318 switch (class_id)
2319 {
2320 case mxDOUBLE_CLASS:
2321 type_ok = is_double_type ();
2322 break;
2323
2324 case mxSINGLE_CLASS:
2325 type_ok = is_single_type ();
2326 break;
2327
2328 case mxINT8_CLASS:
2329 type_ok = is_int8_type ();
2330 break;
2331
2332 case mxINT16_CLASS:
2333 type_ok = is_int16_type ();
2334 break;
2335
2336 case mxINT32_CLASS:
2337 type_ok = is_int32_type ();
2338 break;
2339
2340 case mxINT64_CLASS:
2341 type_ok = is_int64_type ();
2342 break;
2343
2344 case mxUINT8_CLASS:
2345 type_ok = is_uint8_type ();
2346 break;
2347
2348 case mxUINT16_CLASS:
2349 type_ok = is_uint16_type ();
2350 break;
2351
2352 case mxUINT32_CLASS:
2353 type_ok = is_uint32_type ();
2354 break;
2355
2356 case mxUINT64_CLASS:
2357 type_ok = is_uint64_type ();
2358 break;
2359
2360 default:
2361 // We only expect to see numeric types explicitly requested.
2362 error ("mex_get_data: unexpected type requested");
2363 }
2364
2365 if (! type_ok)
2366 error ("mex_get_data: type mismatch");
2367
2368 if (complexity == mxCOMPLEX && ! iscomplex ())
2369 error ("mex_get_data: objectis not complex as requested");
2370 }
2371
2372 return m_rep->mex_get_data ();
2373}
2374
2375OCTAVE_NORETURN static void
2376err_unary_op_conversion_failed (const std::string& op,
2377 const std::string& tn)
2378{
2379 error ("operator %s: type conversion for '%s' failed",
2380 op.c_str (), tn.c_str ());
2381}
2382
2383OCTAVE_NORETURN static void
2384err_unary_op (const std::string& on, const std::string& tn)
2385{
2386 error ("unary operator '%s' not implemented for '%s' operands",
2387 on.c_str (), tn.c_str ());
2388}
2389
2392{
2393 if (op == op_incr || op == op_decr)
2394 {
2395 // We want the error just here, because in the other branch this should
2396 // not happen, and if it did anyway (internal error), the message would
2397 // be confusing.
2398 if (is_undefined ())
2399 {
2400 std::string op_str = unary_op_as_string (op);
2401 error ("in x%s or %sx, x must be defined first",
2402 op_str.c_str (), op_str.c_str ());
2403 return *this;
2404 }
2405
2406 // Genuine.
2407 int t = type_id ();
2408
2409 octave::type_info& ti = octave::__get_type_info__ ();
2410
2411 octave::type_info::non_const_unary_op_fcn f
2412 = ti.lookup_non_const_unary_op (op, t);
2413
2414 if (f)
2415 {
2416 make_unique ();
2417
2418 f (*m_rep);
2419 }
2420 else
2421 {
2423
2424 if (! cf)
2425 err_unary_op (octave_value::unary_op_as_string (op), type_name ());
2426
2427 octave_base_value *tmp = cf (*m_rep);
2428
2429 if (! tmp)
2430 err_unary_op_conversion_failed
2432
2433 octave_base_value *old_rep = m_rep;
2434 m_rep = tmp;
2435
2436 t = type_id ();
2437
2438 f = ti.lookup_non_const_unary_op (op, t);
2439
2440 if (f)
2441 {
2442 f (*m_rep);
2443
2444 if (old_rep && --old_rep->m_count == 0)
2445 delete old_rep;
2446 }
2447 else
2448 {
2449 if (old_rep)
2450 {
2451 if (--m_rep->m_count == 0)
2452 delete m_rep;
2453
2454 m_rep = old_rep;
2455 }
2456
2457 err_unary_op (octave_value::unary_op_as_string (op),
2458 type_name ());
2459 }
2460 }
2461 }
2462 else
2463 {
2464 // Non-genuine.
2465 int t = type_id ();
2466
2467 octave::type_info::non_const_unary_op_fcn f = nullptr;
2468
2469 // Only attempt to operate in-place if this variable is unshared.
2470 if (m_rep->m_count == 1)
2471 {
2472 octave::type_info& ti = octave::__get_type_info__ ();
2473
2474 f = ti.lookup_non_const_unary_op (op, t);
2475 }
2476
2477 if (f)
2478 f (*m_rep);
2479 else
2480 *this = octave::unary_op (op, *this);
2481 }
2482
2483 return *this;
2484}
2485
2487octave_value::non_const_unary_op (unary_op op, const std::string& type,
2488 const std::list<octave_value_list>& idx)
2489{
2490 if (idx.empty ())
2491 non_const_unary_op (op);
2492 else
2493 {
2494 // FIXME: only do the following stuff if we can't find a
2495 // specific function to call to handle the op= operation for the
2496 // types we have.
2497
2498 assign_op assop = unary_op_to_assign_op (op);
2499
2500 assign (assop, type, idx, 1.0);
2501 }
2502
2503 return *this;
2504}
2505
2507octave_value::unary_op_to_assign_op (unary_op op)
2508{
2509 switch (op)
2510 {
2511 case op_incr:
2512 return op_add_eq;
2513
2514 case op_decr:
2515 return op_sub_eq;
2516
2517 default:
2518 {
2519 std::string on = unary_op_as_string (op);
2520 error ("operator %s: no assign operator found", on.c_str ());
2521 }
2522 }
2523}
2524
2526octave_value::op_eq_to_binary_op (assign_op op)
2527{
2528 switch (op)
2529 {
2530 case op_add_eq:
2531 return op_add;
2532
2533 case op_sub_eq:
2534 return op_sub;
2535
2536 case op_mul_eq:
2537 return op_mul;
2538
2539 case op_div_eq:
2540 return op_div;
2541
2542 case op_ldiv_eq:
2543 return op_ldiv;
2544
2545 case op_pow_eq:
2546 return op_pow;
2547
2548 case op_el_mul_eq:
2549 return op_el_mul;
2550
2551 case op_el_div_eq:
2552 return op_el_div;
2553
2554 case op_el_ldiv_eq:
2555 return op_el_ldiv;
2556
2557 case op_el_pow_eq:
2558 return op_el_pow;
2559
2560 case op_el_and_eq:
2561 return op_el_and;
2562
2563 case op_el_or_eq:
2564 return op_el_or;
2565
2566 default:
2567 {
2568 std::string on = assign_op_as_string (op);
2569 error ("operator %s: no binary operator found", on.c_str ());
2570 }
2571 }
2572}
2573
2575octave_value::empty_conv (const std::string& type, const octave_value& rhs)
2576{
2577 if (type.length () > 0)
2578 {
2579 switch (type[0])
2580 {
2581 case '(':
2582 if (type.length () > 1 && type[1] == '.')
2583 return octave_map ();
2584 else
2585 return octave_value (rhs.empty_clone ());
2586
2587 case '{':
2588 return Cell ();
2589
2590 case '.':
2591 return octave_scalar_map ();
2592
2593 default:
2594 error ("unexpected: index not '(', '{', or '.' in octave_value::empty_conv - please report this bug");
2595 }
2596 }
2597 else
2598 return octave_value (rhs.empty_clone ());
2599}
2600
2602
2603OCTAVE_NORETURN static void
2604err_binary_op (const std::string& on, const std::string& tn1,
2605 const std::string& tn2)
2606{
2607 error ("binary operator '%s' not implemented for '%s' by '%s' operations",
2608 on.c_str (), tn1.c_str (), tn2.c_str ());
2609}
2610
2611OCTAVE_NORETURN static void
2612err_binary_op_conv (const std::string& on)
2613{
2614 error ("type conversion failed for binary operator '%s'", on.c_str ());
2615}
2616
2619 const octave_value& v1, const octave_value& v2)
2620{
2621 octave_value retval;
2622
2623 int t1 = v1.type_id ();
2624 int t2 = v2.type_id ();
2625
2626 if (t1 == octave_class::static_type_id ()
2630 {
2632
2633 if (! f)
2634 err_binary_op (octave_value::binary_op_as_string (op),
2635 v1.class_name (), v2.class_name ());
2636
2637 retval = f (v1, v2);
2638 }
2639 else
2640 {
2641 // FIXME: we need to handle overloading operators for built-in
2642 // classes (double, char, int8, etc.)
2643
2645 = ti.lookup_binary_op (op, t1, t2);
2646
2647 if (f)
2648 retval = f (v1.get_rep (), v2.get_rep ());
2649 else
2650 {
2651 octave_value tv1;
2654
2655 octave_value tv2;
2658
2659 // Try biased (one-sided) conversions first.
2660 if (cf2.type_id () >= 0
2661 && ti.lookup_binary_op (op, t1, cf2.type_id ()))
2662 cf1 = nullptr;
2663 else if (cf1.type_id () >= 0
2664 && ti.lookup_binary_op (op, cf1.type_id (), t2))
2665 cf2 = nullptr;
2666
2667 if (cf1)
2668 {
2669 octave_base_value *tmp = cf1 (v1.get_rep ());
2670
2671 if (! tmp)
2672 err_binary_op_conv (octave_value::binary_op_as_string (op));
2673
2674 tv1 = octave_value (tmp);
2675 t1 = tv1.type_id ();
2676 }
2677 else
2678 tv1 = v1;
2679
2680 if (cf2)
2681 {
2682 octave_base_value *tmp = cf2 (v2.get_rep ());
2683
2684 if (! tmp)
2685 err_binary_op_conv (octave_value::binary_op_as_string (op));
2686
2687 tv2 = octave_value (tmp);
2688 t2 = tv2.type_id ();
2689 }
2690 else
2691 tv2 = v2;
2692
2693 if (cf1 || cf2)
2694 {
2695 retval = binary_op (op, tv1, tv2);
2696 }
2697 else
2698 {
2699 //demote double -> single and try again
2700 cf1 = tv1.numeric_demotion_function ();
2701
2702 cf2 = tv2.numeric_demotion_function ();
2703
2704 // Try biased (one-sided) conversions first.
2705 if (cf2.type_id () >= 0
2706 && ti.lookup_binary_op (op, t1, cf2.type_id ()))
2707 cf1 = nullptr;
2708 else if (cf1.type_id () >= 0
2709 && ti.lookup_binary_op (op, cf1.type_id (), t2))
2710 cf2 = nullptr;
2711
2712 if (cf1)
2713 {
2714 octave_base_value *tmp = cf1 (tv1.get_rep ());
2715
2716 if (! tmp)
2717 err_binary_op_conv (octave_value::binary_op_as_string (op));
2718
2719 tv1 = octave_value (tmp);
2720 t1 = tv1.type_id ();
2721 }
2722
2723 if (cf2)
2724 {
2725 octave_base_value *tmp = cf2 (tv2.get_rep ());
2726
2727 if (! tmp)
2728 err_binary_op_conv (octave_value::binary_op_as_string (op));
2729
2730 tv2 = octave_value (tmp);
2731 t2 = tv2.type_id ();
2732 }
2733
2734 if (! cf1 && ! cf2)
2735 err_binary_op (octave_value::binary_op_as_string (op),
2736 v1.type_name (), v2.type_name ());
2737
2738 f = ti.lookup_binary_op (op, t1, t2);
2739
2740 if (! f)
2741 err_binary_op (octave_value::binary_op_as_string (op),
2742 v1.type_name (), v2.type_name ());
2743
2744 retval = f (tv1.get_rep (), tv2.get_rep ());
2745 }
2746 }
2747 }
2748
2749 return retval;
2750}
2751
2754 const octave_value& v2)
2755{
2757
2758 return binary_op (ti, op, v1, v2);
2759}
2760
2761static octave_value
2762decompose_binary_op (type_info& ti, octave_value::compound_binary_op op,
2763 const octave_value& v1, const octave_value& v2)
2764{
2765 switch (op)
2766 {
2769 unary_op (octave_value::op_transpose, v1), v2);
2770
2772 return binary_op (ti, octave_value::op_mul,
2773 v1, unary_op (octave_value::op_transpose, v2));
2774
2776 return binary_op (ti, octave_value::op_mul,
2777 unary_op (octave_value::op_hermitian, v1), v2);
2778
2780 return binary_op (ti, octave_value::op_mul,
2781 v1, unary_op (octave_value::op_hermitian, v2));
2782
2784 return binary_op (ti, octave_value::op_ldiv,
2785 unary_op (octave_value::op_transpose, v1), v2);
2786
2788 return binary_op (ti, octave_value::op_ldiv,
2789 unary_op (octave_value::op_hermitian, v1), v2);
2790
2793 unary_op (octave_value::op_not, v1), v2);
2794
2797 unary_op (octave_value::op_not, v1), v2);
2798
2801 v1, unary_op (octave_value::op_not, v2));
2802
2805 v1, unary_op (octave_value::op_not, v2));
2806
2807 default:
2808 error ("invalid compound operator");
2809 }
2810}
2811
2814 const octave_value& v1, const octave_value& v2)
2815{
2816 octave_value retval;
2817
2818 int t1 = v1.type_id ();
2819 int t2 = v2.type_id ();
2820
2821 if (t1 == octave_class::static_type_id ()
2825 {
2827
2828 if (f)
2829 retval = f (v1, v2);
2830 else
2831 retval = decompose_binary_op (ti, op, v1, v2);
2832 }
2833 else
2834 {
2836
2837 if (f)
2838 retval = f (v1.get_rep (), v2.get_rep ());
2839 else
2840 retval = decompose_binary_op (ti, op, v1, v2);
2841 }
2842
2843 return retval;
2844}
2845
2848 const octave_value& v1, const octave_value& v2)
2849{
2851
2852 return binary_op (ti, op, v1, v2);
2853}
2854
2855OCTAVE_NORETURN static void
2856err_cat_op (const std::string& tn1, const std::string& tn2)
2857{
2858 error ("concatenation operator not implemented for '%s' by '%s' operations",
2859 tn1.c_str (), tn2.c_str ());
2860}
2861
2862OCTAVE_NORETURN static void
2863err_cat_op_conv ()
2864{
2865 error ("type conversion failed for concatenation operator");
2866}
2867
2869cat_op (type_info& ti, const octave_value& v1,
2871{
2872 octave_value retval;
2873
2874 // Can't rapid return for concatenation with an empty object here as
2875 // something like cat(1,[],single([]) must return the correct type.
2876
2877 int t1 = v1.type_id ();
2878 int t2 = v2.type_id ();
2879
2881
2882 if (f)
2883 retval = f (v1.get_rep (), v2.get_rep (), ra_idx);
2884 else
2885 {
2886 octave_value tv1;
2888
2889 octave_value tv2;
2891
2892 // Try biased (one-sided) conversions first.
2893 if (cf2.type_id () >= 0 && ti.lookup_cat_op (t1, cf2.type_id ()))
2894 cf1 = nullptr;
2895 else if (cf1.type_id () >= 0 && ti.lookup_cat_op (cf1.type_id (), t2))
2896 cf2 = nullptr;
2897
2898 if (cf1)
2899 {
2900 octave_base_value *tmp = cf1 (v1.get_rep ());
2901
2902 if (! tmp)
2903 err_cat_op_conv ();
2904
2905 tv1 = octave_value (tmp);
2906 t1 = tv1.type_id ();
2907 }
2908 else
2909 tv1 = v1;
2910
2911 if (cf2)
2912 {
2913 octave_base_value *tmp = cf2 (v2.get_rep ());
2914
2915 if (! tmp)
2916 err_cat_op_conv ();
2917
2918 tv2 = octave_value (tmp);
2919 t2 = tv2.type_id ();
2920 }
2921 else
2922 tv2 = v2;
2923
2924 if (! cf1 && ! cf2)
2925 err_cat_op (v1.type_name (), v2.type_name ());
2926
2927 retval = cat_op (ti, tv1, tv2, ra_idx);
2928 }
2929
2930 return retval;
2931}
2932
2934cat_op (const octave_value& v1, const octave_value& v2,
2936{
2938
2939 return cat_op (ti, v1, v2, ra_idx);
2940}
2941
2942// Unless the colon operator is used with a class or classdef object,
2943// then all arguments must be the same type or mixed with double
2944// values.
2945
2946static builtin_type_t
2947get_colon_op_type (builtin_type_t op1_type, builtin_type_t op2_type)
2948{
2949 if (op1_type == op2_type)
2950 return op1_type;
2951
2952 if (op1_type == btyp_double)
2953 return op2_type;
2954
2955 if (op2_type == btyp_double)
2956 return op1_type;
2957
2958 return btyp_unknown;
2959}
2960
2961static builtin_type_t
2962get_colon_op_type (const octave_value& base, const octave_value& increment,
2963 const octave_value& limit)
2964{
2965 builtin_type_t typ
2966 = get_colon_op_type (base.builtin_type (), increment.builtin_type ());
2967
2968 if (typ == btyp_unknown)
2969 return typ;
2970
2971 return get_colon_op_type (typ, limit.builtin_type ());
2972}
2973
2974// This check depends on the type of VAL either being the expected
2975// integer type or a double value.
2976
2977template <typename T>
2978static void
2979check_colon_operand (const octave_value& val, const char *op_str)
2980{
2981 if (! val.is_double_type ())
2982 return;
2983
2984 double dval = val.double_value ();
2985 double intpart;
2986 static constexpr double out_of_range_top
2987 = static_cast<double> (std::numeric_limits<typename T::val_type>::max ()) + 1.0;
2988
2989 if (dval >= out_of_range_top
2990 || dval < std::numeric_limits<typename T::val_type>::min ()
2991 || std::modf (dval, &intpart) != 0.0)
2992 error ("colon operator %s invalid (not an integer or out of range for given integer type)", op_str);
2993}
2994
2995// Return the difference between two unsigned integers as an unsigned
2996// integer of the same type.
2997
2998template <typename UT,
2999 typename std::enable_if<(std::is_integral<UT>::value
3000 && std::is_unsigned<UT>::value),
3001 bool>::type = true>
3002UT
3003integer_difference (UT a, UT b)
3004{
3005 return a > b ? a - b : b - a;
3006}
3007
3008// Return the difference between two signed integers as an unsigned
3009// integer corresponding to the signed type.
3010
3011template <typename ST,
3012 typename UT = typename std::make_unsigned<ST>::type,
3013 typename std::enable_if<(std::is_integral<ST>::value
3014 && std::is_signed<ST>::value),
3015 bool>::type = true>
3016UT
3017integer_difference (ST a, ST b)
3018{
3019 // Map to unsigned.
3020 // Idea from https://stackoverflow.com/questions/10589559
3021
3022 static const UT offset = UT (0) - static_cast<UT> (std::numeric_limits<ST>::min ());
3023
3024 UT au = static_cast<UT> (a) + offset;
3025 UT bu = static_cast<UT> (b) + offset;
3026
3027 return integer_difference (au, bu);
3028}
3029
3030// Number of elements in an integer range taking care to avoid
3031// overflow. Base and limit are of the same type. If they are
3032// unsigned, then increment is also of the same type. If they are
3033// signed, then the type of increment is the unsigned type
3034// corresponding to T. Assumes that the base and limit values are
3035// consistent with the sign of the original increment (not an empty
3036// range) so we can calculate numel with the absolute value of the
3037// increment and the absolute difference between the base and limit
3038// values.
3039
3040template <typename T,
3041 typename UT = typename std::make_unsigned<T>::type,
3042 typename std::enable_if<std::is_integral<T>::value,
3043 bool>::type = true>
3045range_numel_aux (T base, UT unsigned_increment, T limit)
3046{
3047 // Adding one to DIFF/INCREMENT may overflow, so check whether it is
3048 // out of range before adding.
3049
3050 UT nel_m1 = integer_difference (limit, base) / unsigned_increment;
3051
3052 // FIXME: fix error message.
3053 if (nel_m1 > std::numeric_limits<octave_idx_type>::max () - 1)
3054 error ("too many elements for range!");
3055
3056 return static_cast<octave_idx_type> (nel_m1) + 1;
3057}
3058
3059// Convert signed range increment to unsigned.
3060
3061template <typename ST,
3062 typename UT = typename std::make_unsigned<ST>::type,
3063 typename std::enable_if<(std::is_integral<ST>::value
3064 && std::is_signed<ST>::value),
3065 bool>::type = true>
3066UT
3067range_increment (ST increment)
3068{
3069 return (increment < 0
3070 ? UT (0) - static_cast<UT> (increment)
3071 : static_cast<UT> (increment));
3072}
3073
3074// "Convert" unsigned range increment to unsigned. A no-op, but
3075// needed to provide a consistent interface for other template
3076// functions.
3077
3078template <typename T,
3079 typename UT = typename std::make_unsigned<T>::type,
3080 typename std::enable_if<(std::is_integral<UT>::value
3081 && std::is_unsigned<UT>::value),
3082 bool>::type = true>
3083UT
3084range_increment (UT increment)
3085{
3086 return increment;
3087}
3088
3089// Convert double range increment to unsigned. Enable by return type.
3090
3091template <typename T,
3092 typename UT = typename std::make_unsigned<T>::type>
3093typename std::enable_if<(std::is_integral<UT>::value
3094 && std::is_unsigned<UT>::value), UT>::type
3095range_increment (double increment)
3096{
3097 double abs_increment = std::abs (increment);
3098
3099 return static_cast<UT> (abs_increment);
3100}
3101
3102// Number of elements in an integer range base:increment:limit. Base,
3103// increment, and limit are of the same signed type.
3104
3105template <typename ST,
3106 typename std::enable_if<(std::is_integral<ST>::value
3107 && std::is_signed<ST>::value),
3108 bool>::type = true>
3110range_numel (ST base, ST increment, ST limit)
3111{
3112 typedef typename std::make_unsigned<ST>::type UT;
3113
3114 if (increment == 0
3115 || (increment > 0 && base > limit)
3116 || (increment < 0 && base < limit))
3117 return 0;
3118
3119 UT unsigned_increment = range_increment<ST> (increment);
3120
3121 return range_numel_aux (base, unsigned_increment, limit);
3122}
3123
3124// Number of elements in an integer range base:increment:limit. Base,
3125// increment, and limit are unsigned and of the same type.
3126
3127template <typename UT,
3128 typename std::enable_if<(std::is_integral<UT>::value
3129 && std::is_unsigned<UT>::value),
3130 bool>::type = true>
3132range_numel (UT base, UT increment, UT limit)
3133{
3134 // Unsigned, INCREMENT is always >= 0.
3135 if (increment == 0 || base > limit)
3136 return 0;
3137
3138 return range_numel_aux (base, increment, limit);
3139}
3140
3141// Number of elements in an integer range base:increment:limit. Base
3142// and limit are of the same type and increment is a double value.
3143
3144template <typename T,
3145 typename UT = typename std::make_unsigned<T>::type,
3146 typename std::enable_if<std::is_integral<T>::value,
3147 bool>::type = true>
3149range_numel (T base, double increment, T limit)
3150{
3151 double intpart;
3152 if (math::isnan (increment) || std::modf (increment, &intpart) != 0.0)
3153 error ("colon operator increment invalid (not an integer)");
3154
3155 if (increment == 0
3156 || (increment > 0 && base > limit)
3157 || (increment < 0 && base < limit))
3158 return 0;
3159
3160 static constexpr double out_of_range_top
3161 = static_cast<double> (std::numeric_limits<UT>::max ()) + 1.0;
3162
3163 double abs_increment = std::abs (increment);
3164
3165 // Technically, this condition should be
3166 // `abs_increment > std::numeric_limits<UT>::max ()`.
3167 // But intmax('uint64') is not representable exactly as floating point
3168 // number. Instead, it "rounds" up by 1 to 2^64. To account for
3169 // this, use the following expression which works for all unsigned
3170 // integer types.
3171 if (abs_increment >= out_of_range_top)
3172 return 1;
3173
3174 UT unsigned_increment = range_increment<T> (increment);
3175
3176 return range_numel_aux (base, unsigned_increment, limit);
3177}
3178
3179// Make a range from integer values. Increment may be integer or double.
3180
3181template <typename T,
3182 typename IT,
3183 typename std::enable_if<(std::is_integral<T>::value
3184 && std::is_arithmetic<IT>::value),
3185 bool>::type = true>
3187make_int_range (T base, IT increment, T limit)
3188{
3189 octave_idx_type nel = range_numel (base, increment, limit);
3190
3191 // For now, we create arrays instead of range<T> for all types
3192 // except double.
3193
3194 Array<octave_int<T>> result (dim_vector (1, nel));
3195
3196 if (nel > 0)
3197 {
3198 typedef typename std::make_unsigned<T>::type UT;
3199
3200 UT unsigned_increment = range_increment<T> (increment);
3201
3202 T val = base;
3203 result.xelem (0) = val;
3204
3205 if (limit > base)
3206 {
3207 for (octave_idx_type i = 1; i < nel; i++)
3208 {
3209 val += unsigned_increment;
3210 result.xelem (i) = val;
3211 }
3212 }
3213 else
3214 {
3215 for (octave_idx_type i = 1; i < nel; i++)
3216 {
3217 val -= unsigned_increment;
3218 result.xelem (i) = val;
3219 }
3220 }
3221 }
3222
3223 return octave_value (result);
3224}
3225
3226// Make a range from floating point values.
3227
3228// FIXME: Try again to define memory efficient range classes for
3229// integer and floating point values? Maybe with the templates
3230// defined in this file we could do that in a reasonable way?
3231// Regardless of that, it might be good to provide special treatment
3232// of colon expressions in FOR loops so that we can eliminate the
3233// "is_for_cmd_expr / force_range" flag from the parser and the
3234// octave_value constructors for range objects.
3235
3236// NOTE: We define this function separately for float and double so
3237// that we can avoid having to instantiate ov_range<float>. We DO
3238// instantiate range<float> but only so we can take advantage of the
3239// range<T> class to generate the corresponding array of float values
3240// and not have to duplicate that code here.
3241
3242template <typename T,
3243 typename std::enable_if<std::is_same<T, double>::value,
3244 bool>::type = true>
3246make_float_range (T base, T increment, T limit, bool is_for_cmd_expr)
3247{
3248 if (math::isnan (base)
3249 || math::isnan (increment)
3250 || math::isnan (limit))
3251 return octave_value (numeric_limits<T>::NaN ());
3252
3253 if (increment == 0
3254 || (increment > 0 && base > limit)
3255 || (increment < 0 && base < limit))
3256 return octave_value (Array<T> (dim_vector (1, 0)));
3257
3258 // At this point, we know that the base and limit values are
3259 // consistent with the sign of the increment (not an empty range).
3260
3261 range<T> r (base, increment, limit);
3262
3263 if (! is_for_cmd_expr && ! r.is_storable ())
3264 error ("range with infinite number of elements cannot be stored");
3265
3266 return octave_value (r, is_for_cmd_expr);
3267}
3268
3269template <typename T,
3270 typename std::enable_if<std::is_same<T, float>::value,
3271 bool>::type = true>
3273make_float_range (T base, T increment, T limit, bool is_for_cmd_expr)
3274{
3275 if (math::isnan (base)
3276 || math::isnan (increment)
3277 || math::isnan (limit))
3278 return octave_value (numeric_limits<T>::NaN ());
3279
3280 if (increment == 0
3281 || (increment > 0 && base > limit)
3282 || (increment < 0 && base < limit))
3283 return octave_value (Array<T> (dim_vector (1, 0)));
3284
3285 // At this point, we know that the base and limit values are
3286 // consistent with the sign of the increment (not an empty range).
3287
3288 range<T> r (base, increment, limit);
3289
3290 if (! is_for_cmd_expr && ! r.is_storable ())
3291 error ("range with infinite number of elements cannot be stored");
3292
3293 return octave_value (r.array_value ());
3294}
3295
3296template <typename T,
3297 typename std::enable_if<(std::is_same<T, octave_int8>::value
3298 || std::is_same<T, octave_uint8>::value
3299 || std::is_same<T, octave_int16>::value
3300 || std::is_same<T, octave_uint16>::value
3301 || std::is_same<T, octave_int32>::value
3302 || std::is_same<T, octave_uint32>::value
3303 || std::is_same<T, octave_int64>::value
3304 || std::is_same<T, octave_uint64>::value),
3305 bool>::type = true>
3307make_int_range (const octave_value& base, const octave_value& increment,
3308 const octave_value& limit)
3309{
3310 if (base.isempty () || increment.isempty () || limit.isempty ())
3311 return octave_value (Array<T> (dim_vector (1, 0)));
3312
3313 check_colon_operand<T> (base, "lower bound");
3314 check_colon_operand<T> (limit, "upper bound");
3315
3316 typename T::val_type base_val = octave_value_extract<T> (base).value ();
3317 typename T::val_type limit_val = octave_value_extract<T> (limit).value ();
3318
3319 if (increment.is_double_type ())
3320 {
3321 double increment_val = increment.double_value ();
3322
3323 return make_int_range (base_val, increment_val, limit_val);
3324 }
3325
3326 check_colon_operand<T> (increment, "increment");
3327
3328 typename T::val_type increment_val
3329 = octave_value_extract<T> (increment).value ();
3330
3331 return make_int_range (base_val, increment_val, limit_val);
3332}
3333
3334template <typename T,
3335 typename std::enable_if<std::is_floating_point<T>::value,
3336 bool>::type = true>
3338make_float_range (const octave_value& base, const octave_value& increment,
3339 const octave_value& limit, bool is_for_cmd_expr)
3340{
3341 if (base.isempty () || increment.isempty () || limit.isempty ())
3342 return octave_value (Array<T> (dim_vector (1, 0)));
3343
3344 T base_val = octave_value_extract<T> (base);
3345 T increment_val = octave_value_extract<T> (increment);
3346 T limit_val = octave_value_extract<T> (limit);
3347
3348 return make_float_range (base_val, increment_val, limit_val,
3349 is_for_cmd_expr);
3350}
3351
3352
3354make_char_range (const octave_value& base, const octave_value& increment,
3355 const octave_value& limit)
3356{
3357 octave_value retval;
3358
3359 bool dq_str = (base.is_dq_string () || increment.is_dq_string ()
3360 || limit.is_dq_string ());
3361
3362 char type = dq_str ? '"' : '\'';
3363
3364 if (base.isempty () || increment.isempty () || limit.isempty ())
3365 retval = octave_value ("", type);
3366 else
3367 {
3368 Matrix mtx_base = base.matrix_value (true);
3369 Matrix mtx_increment = increment.matrix_value (true);
3370 Matrix mtx_limit = limit.matrix_value (true);
3371
3372 range<double> tmp (mtx_base(0), mtx_increment(0), mtx_limit(0));
3373
3374 retval = octave_value (tmp);
3375 }
3376
3377 return retval.convert_to_str (false, true, type);
3378}
3379
3381colon_op (const octave_value& base, const octave_value& increment_arg,
3382 const octave_value& limit, bool is_for_cmd_expr)
3383{
3384 if (base.isobject () || increment_arg.isobject () || limit.isobject ())
3385 {
3386 octave_value_list tmp1;
3387
3388 if (increment_arg.is_defined ())
3389 {
3390 tmp1(2) = limit;
3391 tmp1(1) = increment_arg;
3392 tmp1(0) = base;
3393 }
3394 else
3395 {
3396 tmp1(1) = limit;
3397 tmp1(0) = base;
3398 }
3399
3400 interpreter& interp = __get_interpreter__ ();
3401
3402 symbol_table& symtab = interp.get_symbol_table ();
3403
3404 octave_value fcn = symtab.find_function ("colon", tmp1);
3405
3406 if (fcn.is_defined ())
3407 {
3408 octave_value_list tmp2 = interp.feval (fcn, tmp1, 1);
3409
3410 return tmp2(0);
3411 }
3412 }
3413
3414 octave_value increment
3415 = increment_arg.is_defined () ? increment_arg : octave_value (1.0);
3416
3417 if (base.numel () > 1 || limit.numel () > 1 || increment.numel () > 1)
3418 warning_with_id ("Octave:colon-nonscalar-argument",
3419 "colon arguments should be scalars");
3420
3421 if (base.iscomplex () || limit.iscomplex () || increment.iscomplex ())
3422 warning_with_id ("Octave:colon-complex-argument",
3423 "imaginary part of complex colon arguments is ignored");
3424
3425 // FIXME: is there a better way to do this job, maybe using type traits?
3426
3427 builtin_type_t type_id = get_colon_op_type (base, increment, limit);
3428
3429 // For compatibility with Matlab, don't allow the range used in
3430 // a FOR loop expression to be converted to a Matrix.
3431
3432 // For now, these functions create arrays instead of range<T> for
3433 // all types except double.
3434
3435 switch (type_id)
3436 {
3437 case btyp_double:
3438 case btyp_complex:
3439 return make_float_range<double> (base, increment, limit, is_for_cmd_expr);
3440
3441 case btyp_float:
3442 case btyp_float_complex:
3443 return make_float_range<float> (base, increment, limit, is_for_cmd_expr);
3444
3445 case btyp_int8:
3446 return make_int_range<octave_int8> (base, increment, limit);
3447
3448 case btyp_int16:
3449 return make_int_range<octave_int16> (base, increment, limit);
3450
3451 case btyp_int32:
3452 return make_int_range<octave_int32> (base, increment, limit);
3453
3454 case btyp_int64:
3455 return make_int_range<octave_int64> (base, increment, limit);
3456
3457 case btyp_uint8:
3458 return make_int_range<octave_uint8> (base, increment, limit);
3459
3460 case btyp_uint16:
3461 return make_int_range<octave_uint16> (base, increment, limit);
3462
3463 case btyp_uint32:
3464 return make_int_range<octave_uint32> (base, increment, limit);
3465
3466 case btyp_uint64:
3467 return make_int_range<octave_uint64> (base, increment, limit);
3468
3469 case btyp_char:
3470 return make_char_range (base, increment, limit);
3471
3472 case btyp_unknown:
3473 error ("incompatible types found in range expression");
3474
3475 default:
3476 error ("invalid types found in range expression");
3477 }
3478
3479 return octave_value ();
3480}
3481
3482OCTAVE_NORETURN static void
3483err_unary_op_conv (const std::string& on)
3484{
3485 error ("type conversion failed for unary operator '%s'", on.c_str ());
3486}
3487
3490 const octave_value& v)
3491{
3492 octave_value retval;
3493
3494 int t = v.type_id ();
3495
3498 {
3500
3501 if (! f)
3502 err_unary_op (octave_value::unary_op_as_string (op), v.class_name ());
3503
3504 retval = f (v);
3505 }
3506 else
3507 {
3508 // FIXME: we need to handle overloading operators for built-in
3509 // classes (double, char, int8, etc.)
3510
3512
3513 if (f)
3514 retval = f (v.get_rep ());
3515 else
3516 {
3517 octave_value tv;
3520
3521 if (! cf)
3522 err_unary_op (octave_value::unary_op_as_string (op),
3523 v.type_name ());
3524
3525 octave_base_value *tmp = cf (v.get_rep ());
3526
3527 if (! tmp)
3528 err_unary_op_conv (octave_value::unary_op_as_string (op));
3529
3530 tv = octave_value (tmp);
3531 retval = unary_op (op, tv);
3532 }
3533 }
3534
3535 return retval;
3536}
3537
3540{
3542
3543 return unary_op (ti, op, v);
3544}
3545
3546OCTAVE_END_NAMESPACE(octave)
3547
3548void
3549install_types (octave::type_info& ti)
3550{
3559
3560 // Legacy range type, preserved to allow loading "constant" ranges
3561 // from data files.
3563
3565
3566 // For now, enable only ov_range<double>.
3567
3572 octave_int8_scalar::register_type (ti);
3573 octave_int16_scalar::register_type (ti);
3574 octave_int32_scalar::register_type (ti);
3575 octave_int64_scalar::register_type (ti);
3576 octave_uint8_scalar::register_type (ti);
3577 octave_uint16_scalar::register_type (ti);
3578 octave_uint32_scalar::register_type (ti);
3580 octave_int8_matrix::register_type (ti);
3581 octave_int16_matrix::register_type (ti);
3582 octave_int32_matrix::register_type (ti);
3583 octave_int64_matrix::register_type (ti);
3584 octave_uint8_matrix::register_type (ti);
3585 octave_uint16_matrix::register_type (ti);
3586 octave_uint32_matrix::register_type (ti);
3616}
3617
3619
3620DEFUN (sizeof, args, ,
3621 doc: /* -*- texinfo -*-
3622@deftypefn {} {@var{sz} =} sizeof (@var{val})
3623Return the size of @var{val} in bytes.
3624@seealso{whos}
3625@end deftypefn */)
3626{
3627 if (args.length () != 1)
3628 print_usage ();
3629
3630 return ovl (args(0).byte_size ());
3631}
3632
3633/*
3634%!assert (sizeof (uint64 (ones (3))), 72)
3635%!assert (sizeof (double (zeros (2,4))), 64)
3636%!assert (sizeof ({"foo", "bar", "baaz"}), 10)
3637*/
3638
3639static void
3640decode_subscripts (const char *name, const octave_value& arg,
3641 std::string& type_string,
3642 std::list<octave_value_list>& idx)
3643{
3644 const octave_map m = arg.xmap_value ("%s: second argument must be a structure with fields 'type' and 'subs'", name);
3645
3646 if (m.nfields () != 2 || ! m.contains ("type") || ! m.contains ("subs"))
3647 error ("%s: second argument must be a structure with fields 'type' and 'subs'",
3648 name);
3649
3650 octave_idx_type nel = m.numel ();
3651
3652 type_string = std::string (nel, '\0');
3653 idx = std::list<octave_value_list> ();
3654
3655 if (nel == 0)
3656 return;
3657
3658 const Cell type = m.contents ("type");
3659 const Cell subs = m.contents ("subs");
3660
3661 for (int k = 0; k < nel; k++)
3662 {
3663 std::string item = type(k).xstring_value ("%s: type(%d) must be a string", name, k+1);
3664
3665 if (item == "{}")
3666 type_string[k] = '{';
3667 else if (item == "()")
3668 type_string[k] = '(';
3669 else if (item == ".")
3670 type_string[k] = '.';
3671 else
3672 error ("%s: invalid indexing type '%s'", name, item.c_str ());
3673
3674 octave_value_list idx_item;
3675
3676 if (subs(k).is_string ())
3677 idx_item(0) = subs(k);
3678 else if (subs(k).iscell ())
3679 {
3680 Cell subs_cell = subs(k).cell_value ();
3681
3682 for (int n = 0; n < subs_cell.numel (); n++)
3683 {
3684 if (subs_cell(n).is_string ()
3685 && subs_cell(n).string_value () == ":")
3687 else
3688 idx_item(n) = subs_cell(n);
3689 }
3690 }
3691 else
3692 error ("%s: subs(%d) must be a string or cell array", name, k+1);
3693
3694 idx.push_back (idx_item);
3695 }
3696}
3697
3698DEFUN (subsref, args, nargout,
3699 doc: /* -*- texinfo -*-
3700@deftypefn {} {@var{newval} =} subsref (@var{val}, @var{idx})
3701Perform the subscripted element selection operation on @var{val} according
3702to the subscript specified by @var{idx}.
3703
3704The subscript @var{idx} must be a structure array with fields @samp{type}
3705and @samp{subs}. Valid values for @samp{type} are @qcode{"()"},
3706@qcode{"@{@}"}, and @qcode{"."}. The @samp{subs} field may be either
3707@qcode{":"} or a cell array of index values.
3708
3709The following example shows how to extract the first two columns of a matrix
3710
3711@example
3712@group
3713val = magic (3)
3714 @result{} val = [ 8 1 6
3715 3 5 7
3716 4 9 2 ]
3717idx.type = "()";
3718idx.subs = @{":", 1:2@};
3719subsref (val, idx)
3720 @result{} [ 8 1
3721 3 5
3722 4 9 ]
3723@end group
3724@end example
3725
3726@noindent
3727Note that this is the same as writing @code{val(:, 1:2)}.
3728
3729If @var{idx} is an empty structure array with fields @samp{type} and
3730@samp{subs}, return @var{val}.
3731
3732The keyword @code{end} cannot be used within @code{subsref} for indexing
3733assignments.
3734@seealso{subsasgn, substruct}
3735@end deftypefn */)
3736{
3737 if (args.length () != 2)
3738 print_usage ();
3739
3740 std::string type;
3741 std::list<octave_value_list> idx;
3742
3743 decode_subscripts ("subsref", args(1), type, idx);
3744
3745 octave_value arg0 = args(0);
3746
3747 if (type.empty ())
3748 return ovl (arg0);
3749 else
3750 return arg0.subsref (type, idx, nargout);
3751}
3752
3753DEFUN (subsasgn, args, ,
3754 doc: /* -*- texinfo -*-
3755@deftypefn {} {@var{newval} =} subsasgn (@var{val}, @var{idx}, @var{rhs})
3756Perform the subscripted assignment operation according to the subscript
3757specified by @var{idx}.
3758
3759The subscript @var{idx} must be a structure array with fields @samp{type}
3760and @samp{subs}. Valid values for @samp{type} are @qcode{"()"},
3761@qcode{"@{@}"}, and @qcode{"."}. The @samp{subs} field may be either
3762@qcode{":"} or a cell array of index values.
3763
3764The following example shows how to set the two first columns of a 3-by-3
3765matrix to zero.
3766
3767@example
3768@group
3769val = magic (3);
3770idx.type = "()";
3771idx.subs = @{":", 1:2@};
3772val = subsasgn (val, idx, 0)
3773 @result{} [ 0 0 6
3774 0 0 7
3775 0 0 2 ]
3776@end group
3777@end example
3778
3779Note that this is the same as writing @code{val(:, 1:2) = 0}.
3780
3781If @var{idx} is an empty structure array with fields @samp{type} and
3782@samp{subs}, return @var{rhs}.
3783
3784The keyword @code{end} cannot be used within @code{subsasgn} for indexing
3785assignments.
3786@seealso{subsref, substruct, optimize_subsasgn_calls}
3787@end deftypefn */)
3788{
3789 if (args.length () != 3)
3790 print_usage ();
3791
3792 std::string type;
3793 std::list<octave_value_list> idx;
3794
3795 decode_subscripts ("subsasgn", args(1), type, idx);
3796
3797 if (type.empty ())
3798 {
3799 // Regularize a null matrix if stored into a variable.
3800 return ovl (args(2).storable_value ());
3801 }
3802 else
3803 {
3804 octave_value arg0 = args(0);
3805 octave_value arg2 = args(2);
3806
3807 arg0.make_unique ();
3808
3809 bool arg2_null = arg2.is_zero_by_zero () && arg2.is_double_type ();
3810
3811 return ovl (arg0.subsasgn (type, idx, (arg2_null
3813 : arg2)));
3814 }
3815}
3816
3817/*
3818%!test
3819%! a = reshape ([1:25], 5,5);
3820%! idx1 = substruct ("()", {3, 3});
3821%! idx2 = substruct ("()", {2:2:5, 2:2:5});
3822%! idx3 = substruct ("()", {":", [1,5]});
3823%! idx4 = struct ("type", {}, "subs", {});
3824%! assert (subsref (a, idx1), 13);
3825%! assert (subsref (a, idx2), [7 17; 9 19]);
3826%! assert (subsref (a, idx3), [1:5; 21:25]');
3827%! assert (subsref (a, idx4), a);
3828%! a = subsasgn (a, idx1, 0);
3829%! a = subsasgn (a, idx2, 0);
3830%! a = subsasgn (a, idx3, 0);
3831%!# a = subsasgn (a, idx4, 0);
3832%! b = [0 6 11 16 0
3833%! 0 0 12 0 0
3834%! 0 8 0 18 0
3835%! 0 0 14 0 0
3836%! 0 10 15 20 0];
3837%! assert (a, b);
3838
3839%!test
3840%! x = 1:10;
3841%! assert (subsasgn (x, substruct ("()", {1}), zeros (0, 0)), 2:10);
3842
3843%!test
3844%! c = num2cell (reshape ([1:25],5,5));
3845%! idx1 = substruct ("{}", {3, 3});
3846%! idx2 = substruct ("()", {2:2:5, 2:2:5});
3847%! idx3 = substruct ("()", {":", [1,5]});
3848%! idx2p = substruct ("{}", {2:2:5, 2:2:5});
3849%! idx3p = substruct ("{}", {":", [1,5]});
3850%! idx4 = struct ("type", {}, "subs", {});
3851%! assert ({ subsref(c, idx1) }, {13});
3852%! assert ({ subsref(c, idx2p) }, {7 9 17 19});
3853%! assert ({ subsref(c, idx3p) }, num2cell ([1:5, 21:25]));
3854%! assert (subsref (c, idx4), c);
3855%! c = subsasgn (c, idx1, 0);
3856%! c = subsasgn (c, idx2, 0);
3857%! c = subsasgn (c, idx3, 0);
3858%!# c = subsasgn (c, idx4, 0);
3859%! d = {0 6 11 16 0
3860%! 0 0 12 0 0
3861%! 0 8 0 18 0
3862%! 0 0 14 0 0
3863%! 0 10 15 20 0};
3864%! assert (c, d);
3865
3866%!test
3867%! s.a = "ohai";
3868%! s.b = "dere";
3869%! s.c = 42;
3870%! idx1 = substruct (".", "a");
3871%! idx2 = substruct (".", "b");
3872%! idx3 = substruct (".", "c");
3873%! idx4 = struct ("type", {}, "subs", {});
3874%! assert (subsref (s, idx1), "ohai");
3875%! assert (subsref (s, idx2), "dere");
3876%! assert (subsref (s, idx3), 42);
3877%! assert (subsref (s, idx4), s);
3878%! s = subsasgn (s, idx1, "Hello");
3879%! s = subsasgn (s, idx2, "There");
3880%! s = subsasgn (s, idx3, 163);
3881%!# s = subsasgn (s, idx4, 163);
3882%! t.a = "Hello";
3883%! t.b = "There";
3884%! t.c = 163;
3885%! assert (s, t);
3886
3887// Overloaded subsref in classdef class
3888%!test
3889%! data.x = 1;
3890%! cm = containers.Map;
3891%! cm('foo') = data;
3892%! assert (cm('foo').x, 1);
3893*/
3894
3895DEFUN (is_sq_string, args, ,
3896 doc: /* -*- texinfo -*-
3897@deftypefn {} {@var{tf} =} is_sq_string (@var{x})
3898Return true if @var{x} is a single-quoted character string.
3899@seealso{is_dq_string, ischar}
3900@end deftypefn */)
3901{
3902 if (args.length () != 1)
3903 print_usage ();
3904
3905 return ovl (args(0).is_sq_string ());
3906}
3907
3908/*
3909%!assert (is_sq_string ('foo'), true)
3910%!assert (is_sq_string ("foo"), false)
3911%!assert (is_sq_string (1.0), false)
3912%!assert (is_sq_string ({2.0}), false)
3913
3914%!error is_sq_string ()
3915%!error is_sq_string ('foo', 2)
3916*/
3917
3918DEFUN (is_dq_string, args, ,
3919 doc: /* -*- texinfo -*-
3920@deftypefn {} {@var{tf} =} is_dq_string (@var{x})
3921Return true if @var{x} is a double-quoted character string.
3922@seealso{is_sq_string, ischar}
3923@end deftypefn */)
3924{
3925 if (args.length () != 1)
3926 print_usage ();
3927
3928 return ovl (args(0).is_dq_string ());
3929}
3930
3931/*
3932%!assert (is_dq_string ("foo"), true)
3933%!assert (is_dq_string ('foo'), false)
3934%!assert (is_dq_string (1.0), false)
3935%!assert (is_dq_string ({2.0}), false)
3936
3937%!error is_dq_string ()
3938%!error is_dq_string ("foo", 2)
3939*/
3940
3941DEFUN (optimize_permutation_matrix, args, nargout,
3942 doc: /* -*- texinfo -*-
3943@deftypefn {} {@var{val} =} optimize_permutation_matrix ()
3944@deftypefnx {} {@var{old_val} =} optimize_permutation_matrix (@var{new_val})
3945@deftypefnx {} {@var{old_val} =} optimize_permutation_matrix (@var{new_val}, "local")
3946Query or set whether a special space-efficient format is used for storing
3947permutation matrices.
3948
3949The default value is true. If this option is set to false, Octave will store
3950permutation matrices as full matrices.
3951
3952When called from inside a function with the @qcode{"local"} option, the setting
3953is changed locally for the function and any subroutines it calls. The original
3954setting is restored when exiting the function.
3955@seealso{optimize_range, optimize_diagonal_matrix}
3956@end deftypefn */)
3957{
3958 return set_internal_variable (Voptimize_permutation_matrix, args, nargout,
3959 "optimize_permutation_matrix");
3960}
3961
3962/*
3963%!function p = __test_dpm__ (dpm)
3964%! optimize_permutation_matrix (dpm, "local");
3965%! [~, ~, p] = lu ([1,2;3,4]);
3966%!endfunction
3967
3968%!assert (typeinfo (__test_dpm__ (true)), "permutation matrix")
3969%!assert (typeinfo (__test_dpm__ (false)), "matrix")
3970*/
3971
3972DEFUN (optimize_diagonal_matrix, args, nargout,
3973 doc: /* -*- texinfo -*-
3974@deftypefn {} {@var{val} =} optimize_diagonal_matrix ()
3975@deftypefnx {} {@var{old_val} =} optimize_diagonal_matrix (@var{new_val})
3976@deftypefnx {} {@var{old_val} =} optimize_diagonal_matrix (@var{new_val}, "local")
3977Query or set whether a special space-efficient format is used for storing
3978diagonal matrices.
3979
3980The default value is true. If this option is set to false, Octave will store
3981diagonal matrices as full matrices.
3982
3983When called from inside a function with the @qcode{"local"} option, the setting
3984is changed locally for the function and any subroutines it calls. The original
3985setting is restored when exiting the function.
3986@seealso{optimize_range, optimize_permutation_matrix}
3987@end deftypefn */)
3988{
3989 return set_internal_variable (Voptimize_diagonal_matrix, args, nargout,
3990 "optimize_diagonal_matrix");
3991}
3992
3993/*
3994%!function [x, xi, fx, fxi] = __test_ddm__ (ddm)
3995%! optimize_diagonal_matrix (ddm, "local");
3996%! x = eye (2);
3997%! xi = x*i;
3998%! fx = single (x);
3999%! fxi = single (xi);
4000%!endfunction
4001
4002%!shared x, xi, fx, fxi
4003%! [x, xi, fx, fxi] = __test_ddm__ (true);
4004%!assert (typeinfo (x), "diagonal matrix")
4005%!assert (typeinfo (xi), "complex diagonal matrix")
4006%!assert (typeinfo (fx), "float diagonal matrix")
4007%!assert (typeinfo (fxi), "float complex diagonal matrix")
4008
4009%!shared x, xi, fx, fxi
4010%! [x, xi, fx, fxi] = __test_ddm__ (false);
4011%!assert (typeinfo (x), "matrix")
4012%!assert (typeinfo (xi), "complex matrix")
4013%!assert (typeinfo (fx), "float matrix")
4014%!assert (typeinfo (fxi), "float complex matrix")
4015*/
4016
4017DEFUN (optimize_range, args, nargout,
4018 doc: /* -*- texinfo -*-
4019@deftypefn {} {@var{val} =} optimize_range ()
4020@deftypefnx {} {@var{old_val} =} optimize_range (@var{new_val})
4021@deftypefnx {} {@var{old_val} =} optimize_range (@var{new_val}, "local")
4022Query or set whether a special space-efficient format is used for storing
4023ranges.
4024
4025The default value is true. If this option is set to false, Octave will store
4026ranges as full matrices.
4027
4028When called from inside a function with the @qcode{"local"} option, the setting
4029is changed locally for the function and any subroutines it calls. The original
4030setting is restored when exiting the function.
4031@seealso{optimize_diagonal_matrix, optimize_permutation_matrix}
4032@end deftypefn */)
4033{
4034 return set_internal_variable (Voptimize_range, args, nargout,
4035 "optimize_range");
4036}
4037
4038/*
4039%!function r = __test_dr__ (dr)
4040%! optimize_range (dr, "local");
4041%! ## Constant folding will produce range for 1:13.
4042%! base = 1;
4043%! limit = 13;
4044%! r = base:limit;
4045%!endfunction
4046
4047%!assert (typeinfo (__test_dr__ (true)), "double_range")
4048%!assert (typeinfo (__test_dr__ (false)), "matrix")
4049*/
4050
4051OCTAVE_END_NAMESPACE(octave)
#define C(a, b)
Definition Faddeeva.cc:256
N Dimensional Array with copy-on-write semantics.
Definition Array.h:130
const dim_vector & dims() const
Return a const-reference so that dims ()(i) works efficiently.
Definition Array.h:507
T & xelem(octave_idx_type n)
Size of the specified dimension.
Definition Array.h:525
T & elem(octave_idx_type n)
Size of the specified dimension.
Definition Array.h:563
void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
Array< T, Alloc > reshape(octave_idx_type nr, octave_idx_type nc) const
Size of the specified dimension.
Definition Array.h:636
octave_idx_type numel() const
Number of elements in the array.
Definition Array.h:418
Definition Cell.h:41
Vector representing the dimensions (size) of an Array.
Definition dim-vector.h:90
std::string str(char sep='x') const
Definition dim-vector.cc:68
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
Definition dim-vector.h:331
void resize(int n, int fill_value=0)
Definition dim-vector.h:268
static dim_vector alloc(int n)
Definition dim-vector.h:198
octave_idx_type ndims() const
Number of dimensions.
Definition dim-vector.h:253
octave_value_list feval(const char *name, const octave_value_list &args=octave_value_list(), int nargout=0)
Evaluate an Octave function (built-in or interpreted) and return the list of result values.
symbol_table & get_symbol_table()
virtual bool load_hdf5(octave_hdf5_id loc_id, const char *name)
Definition ov-base.cc:1017
virtual octave_value subsref(const std::string &type, const std::list< octave_value_list > &idx)
Definition ov-base.cc:245
virtual octave_base_value * clone() const
Definition ov-base.h:288
virtual octave_user_script * user_script_value(bool silent=false)
Definition ov-base.cc:953
virtual octave_value_list simple_subsref(char type, octave_value_list &idx, int nargout)
Definition ov-base.cc:237
virtual octave_fcn_handle * fcn_handle_value(bool silent=false)
Definition ov-base.cc:971
virtual octave_classdef * classdef_object_value(bool silent=false)
Definition ov-base.cc:925
virtual float_display_format get_edit_display_format() const
Definition ov-base.cc:503
octave_base_value *(* type_conv_fcn)(const octave_base_value &)
Definition ov-base.h:257
virtual octave_base_value * try_narrowing_conversion()
Definition ov-base.h:332
static void register_type()
Definition ov-base.cc:101
octave::refcount< octave_idx_type > m_count
Definition ov-base.h:958
virtual type_conv_info numeric_conversion_function() const
Definition ov-base.h:303
virtual int type_id() const
Definition ov-base.h:977
virtual octave_value_list list_value() const
Definition ov-base.cc:980
virtual const void * mex_get_data() const
Definition ov-base.h:796
virtual bool load_ascii(std::istream &is)
Definition ov-base.cc:992
virtual bool load_binary(std::istream &is, bool swap, octave::mach_info::float_format fmt)
Definition ov-base.cc:1004
virtual octave_user_function * user_function_value(bool silent=false)
Definition ov-base.cc:944
virtual void print_info(std::ostream &os, const std::string &prefix) const
Definition ov-base.cc:509
virtual int write(octave::stream &os, int block_size, oct_data_conv::data_type output_type, int skip, octave::mach_info::float_format flt_fmt) const
Definition ov-base.cc:1023
virtual bool is_storable() const
Definition ov-base.h:425
virtual octave_map map_value() const
Definition ov-base.cc:877
virtual octave_value subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
Definition ov-base.cc:294
virtual octave_user_code * user_code_value(bool silent=false)
Definition ov-base.cc:962
virtual octave_scalar_map scalar_map_value() const
Definition ov-base.cc:883
virtual double double_value(bool=false) const
Definition ov-base.cc:579
virtual octave_value undef_subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
Definition ov-base.cc:360
virtual void break_closure_cycles(const std::shared_ptr< octave::stack_frame > &)
Definition ov-base.h:300
virtual std::string type_name() const
Definition ov-base.h:977
virtual std::string class_name() const
Definition ov-base.h:977
virtual octave_base_value * empty_clone() const
Definition ov-base.cc:118
virtual octave_function * function_value(bool silent=false)
Definition ov-base.cc:935
virtual Cell cell_value() const
Definition ov-base.cc:591
static void register_type()
static void register_type()
Definition ov-bool.cc:52
static void register_type()
Definition ov-builtin.cc:43
static void register_type()
Definition ov-cell.cc:64
static void register_type()
Definition ov-str-mat.cc:62
static void register_type()
Definition ov-str-mat.cc:60
static int static_type_id()
Definition ov-class.h:228
static int static_type_id()
static void register_type()
Definition ov-cx-diag.cc:39
static void register_type()
Definition ov-cx-mat.cc:67
static void register_type()
Definition ov-complex.cc:56
static void register_type()
Definition ov-cs-list.cc:39
static void register_type()
Definition ov-re-diag.cc:38
static void register_type()
Definition ov-dld-fcn.cc:44
bool is_nested() const
octave_value make_weak_anonymous_handle() const
bool is_anonymous() const
octave_value make_weak_nested_handle() const
static void register_type()
bool is_weak_anonymous() const
bool is_weak_nested() const
static void register_type()
static void register_type()
static void register_type()
Definition ov-float.cc:61
static void register_type()
static void register_type()
static void register_type()
Definition ov-colon.cc:38
static void register_type()
static void register_type()
octave_idx_type nfields() const
Definition oct-map.h:323
const Cell & contents(const_iterator p) const
Definition oct-map.h:310
octave_idx_type numel() const
Definition oct-map.h:368
bool contains(const std::string &name) const
Definition oct-map.h:329
static void register_type()
Definition ov-re-mat.cc:86
static void register_type()
static const octave_value instance
Definition ov-null-mat.h:50
static void register_type()
static void register_type()
static void register_type()
static void register_type()
Definition ov-perm.cc:482
static void register_type()
static void register_type()
Definition ov-scalar.cc:60
static void register_type()
static void register_type()
Definition ov-struct.cc:58
static void register_type()
Definition ov-range.cc:982
static void register_type()
Definition ov-uint64.cc:61
static void register_type()
Definition ov-uint64.cc:64
static void register_type()
bool is_function_handle() const
Definition ov.h:768
octave_value_list list_value() const
octave_value & operator=(const octave_value &a)
Definition ov.h:389
bool is_magic_int() const
Definition ov.h:676
const octave_base_value & get_rep() const
Definition ov.h:1374
static std::string unary_op_fcn_name(unary_op)
Definition ov.cc:159
bool is_undefined() const
Definition ov.h:595
bool is_uint32_type() const
Definition ov.h:724
bool isinteger() const
Definition ov.h:730
ComplexRowVector complex_row_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
std::string class_name() const
Definition ov.h:1362
octave_value subsref(const std::string &type, const std::list< octave_value_list > &idx)
Definition ov.h:476
octave_function * function_value(bool silent=false) const
int32NDArray int32_array_value() const
Definition ov.h:965
uint16NDArray uint16_array_value() const
Definition ov.h:974
static std::string binary_op_as_string(binary_op)
Definition ov.cc:184
octave_map xmap_value(const char *fmt,...) const
bool is_true() const
Definition ov.h:758
octave_classdef * classdef_object_value(bool silent=false) const
int16NDArray int16_array_value() const
Definition ov.h:962
void maybe_economize()
Definition ov.h:1304
Cell cell_value() const
int int_value(bool req_int=false, bool frc_str_conv=false) const
Definition ov.h:812
bool is_dq_string() const
Definition ov.h:643
@ op_hermitian
Definition ov.h:84
@ op_uminus
Definition ov.h:82
@ op_not
Definition ov.h:80
@ op_transpose
Definition ov.h:83
@ op_uplus
Definition ov.h:81
@ op_incr
Definition ov.h:85
@ op_decr
Definition ov.h:86
int8NDArray int8_array_value() const
Definition ov.h:959
std::string get_dims_str() const
int ndims() const
Definition ov.h:551
octave_value()
Definition ov.h:172
void make_unique()
Definition ov.h:352
octave_idx_type rows() const
Definition ov.h:545
int64_t int64_value(bool req_int=false, bool frc_str_conv=false) const
Definition ov.h:834
Array< float > float_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
octave_scalar_map scalar_map_value() const
octave_idx_type strict_idx_type_value(bool frc_str_conv=false) const
bool is_int8_type() const
Definition ov.h:706
octave_value_list simple_subsref(char type, octave_value_list &idx, int nargout)
bool load_binary(std::istream &is, bool swap, octave::mach_info::float_format fmt)
octave_user_script * user_script_value(bool silent=false) const
static std::string assign_op_as_string(assign_op)
Definition ov.cc:355
octave_value undef_subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
octave_idx_type idx_type_value(bool req_int=false, bool frc_str_conv=false) const
Matrix size()
Definition ov.h:462
octave_idx_type end_index(octave_idx_type index_position, octave_idx_type num_indices) const
static octave_value empty_conv(const std::string &type, const octave_value &rhs=octave_value())
static assign_op binary_op_to_assign_op(binary_op)
Definition ov.cc:450
int type_id() const
Definition ov.h:1358
compound_binary_op
Definition ov.h:117
@ op_herm_ldiv
Definition ov.h:124
@ op_el_not_or
Definition ov.h:126
@ op_el_not_and
Definition ov.h:125
@ op_el_and_not
Definition ov.h:127
@ op_mul_trans
Definition ov.h:120
@ op_mul_herm
Definition ov.h:122
@ op_trans_ldiv
Definition ov.h:123
@ op_el_or_not
Definition ov.h:128
@ op_herm_mul
Definition ov.h:121
@ op_trans_mul
Definition ov.h:119
FloatComplexRowVector float_complex_row_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
bool is_range() const
Definition ov.h:646
ComplexNDArray complex_array_value(bool frc_str_conv=false) const
Definition ov.h:884
octave_value next_subsref(const std::string &type, const std::list< octave_value_list > &idx, std::size_t skip=1)
Array< FloatComplex > float_complex_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
FloatRowVector float_row_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
bool is_single_type() const
Definition ov.h:698
bool is_defined() const
Definition ov.h:592
void make_storable_value()
bool isempty() const
Definition ov.h:601
FloatColumnVector float_column_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
bool is_legacy_object() const
Definition ov.h:598
void break_closure_cycles(const std::shared_ptr< octave::stack_frame > &)
bool is_equal(const octave_value &) const
@ op_pow_eq
Definition ov.h:141
@ op_asn_eq
Definition ov.h:135
@ op_add_eq
Definition ov.h:136
@ op_el_pow_eq
Definition ov.h:145
@ op_mul_eq
Definition ov.h:138
@ op_div_eq
Definition ov.h:139
@ op_el_and_eq
Definition ov.h:146
@ op_el_ldiv_eq
Definition ov.h:144
@ op_sub_eq
Definition ov.h:137
@ op_el_mul_eq
Definition ov.h:142
@ op_el_or_eq
Definition ov.h:147
@ unknown_assign_op
Definition ov.h:149
@ op_el_div_eq
Definition ov.h:143
@ op_ldiv_eq
Definition ov.h:140
octave_value storable_value() const
bool is_uint8_type() const
Definition ov.h:718
bool is_uint64_type() const
Definition ov.h:727
float_display_format get_edit_display_format() const
octave_base_value::type_conv_info numeric_demotion_function() const
Definition ov.h:426
bool is_zero_by_zero() const
Definition ov.h:556
bool is_uint16_type() const
Definition ov.h:721
uint64NDArray uint64_array_value() const
Definition ov.h:980
octave_value & non_const_unary_op(unary_op op)
static std::string unary_op_as_string(unary_op)
Definition ov.cc:128
bool load_hdf5(octave_hdf5_id loc_id, const char *name)
const void * mex_get_data(mxClassID class_id=mxUNKNOWN_CLASS, mxComplexity complexity=mxREAL) const
bool is_int16_type() const
Definition ov.h:709
octave_value reshape(const dim_vector &dv) const
Definition ov.h:571
void maybe_mutate()
FloatComplexColumnVector float_complex_column_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
octave_base_value::type_conv_info numeric_conversion_function() const
Definition ov.h:423
octave_idx_type numel() const
Definition ov.h:559
bool load_ascii(std::istream &is)
octave_map map_value() const
Array< int > int_vector_value(bool req_int=false, bool frc_str_conv=false, bool frc_vec_conv=false) const
bool isnull() const
Definition ov.h:679
Array< Complex > complex_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
magic_colon
Definition ov.h:170
@ magic_colon_t
Definition ov.h:170
octave_value & assign(assign_op op, const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
bool is_int64_type() const
Definition ov.h:715
void print_info(std::ostream &os, const std::string &prefix="") const
bool iscomplex() const
Definition ov.h:741
octave_base_value * clone() const
binary_op
Definition ov.h:92
@ op_ldiv
Definition ov.h:98
@ op_ne
Definition ov.h:104
@ unknown_binary_op
Definition ov.h:113
@ op_el_or
Definition ov.h:110
@ op_el_ldiv
Definition ov.h:108
@ op_pow
Definition ov.h:97
@ op_ge
Definition ov.h:102
@ op_div
Definition ov.h:96
@ op_el_pow
Definition ov.h:107
@ op_mul
Definition ov.h:95
@ op_add
Definition ov.h:93
@ op_sub
Definition ov.h:94
@ op_el_mul
Definition ov.h:105
@ op_le
Definition ov.h:100
@ op_struct_ref
Definition ov.h:111
@ op_lt
Definition ov.h:99
@ op_gt
Definition ov.h:103
@ op_eq
Definition ov.h:101
@ op_el_and
Definition ov.h:109
@ op_el_div
Definition ov.h:106
octave_value single_subsref(const std::string &type, const octave_value_list &idx)
octave_fcn_handle * fcn_handle_value(bool silent=false) const
ComplexColumnVector complex_column_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
int64NDArray int64_array_value() const
Definition ov.h:968
octave_idx_type get_count() const
Definition ov.h:421
NDArray array_value(bool frc_str_conv=false) const
Definition ov.h:865
Array< double > vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
static binary_op assign_op_to_binary_op(assign_op)
Definition ov.cc:404
int write(octave::stream &os, int block_size, oct_data_conv::data_type output_type, int skip, octave::mach_info::float_format flt_fmt) const
static std::string binary_op_fcn_name(binary_op)
Definition ov.cc:251
octave_idx_type length() const
bool is_double_type() const
Definition ov.h:695
bool is_int32_type() const
Definition ov.h:712
Array< octave_idx_type > octave_idx_type_vector_value(bool req_int=false, bool frc_str_conv=false, bool frc_vec_conv=false) const
octave_value convert_to_str(bool pad=false, bool force=false, char type='\'') const
Definition ov.h:1322
uint8NDArray uint8_array_value() const
Definition ov.h:971
octave_user_function * user_function_value(bool silent=false) const
std::string type_name() const
Definition ov.h:1360
octave_value all(int dim=0) const
Definition ov.h:684
octave_base_value * m_rep
The real representation.
Definition ov.h:1560
FloatComplexNDArray float_complex_array_value(bool frc_str_conv=false) const
Definition ov.h:888
ColumnVector column_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
static octave_base_value * nil_rep()
Definition ov.cc:121
FloatNDArray float_array_value(bool frc_str_conv=false) const
Definition ov.h:868
octave_user_code * user_code_value(bool silent=false) const
uint32NDArray uint32_array_value() const
Definition ov.h:977
RowVector row_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
octave_idx_type columns() const
Definition ov.h:547
Matrix matrix_value(bool frc_str_conv=false) const
Definition ov.h:859
builtin_type_t builtin_type() const
Definition ov.h:690
octave_base_value * empty_clone() const
Definition ov.h:337
double double_value(bool frc_str_conv=false) const
Definition ov.h:847
bool isobject() const
Definition ov.h:664
octave_value subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
dim_vector dims() const
Definition ov.h:541
static void register_type()
octave_value find_function(const std::string &name, const symbol_scope &search_scope=symbol_scope::invalid())
Definition symtab.cc:254
octave_value(* unary_op_fcn)(const octave_base_value &)
Definition ov-typeinfo.h:48
octave_value(* binary_op_fcn)(const octave_base_value &, const octave_base_value &)
Definition ov-typeinfo.h:56
octave_value(* binary_class_op_fcn)(const octave_value &, const octave_value &)
Definition ov-typeinfo.h:53
binary_class_op_fcn lookup_binary_class_op(octave_value::binary_op)
octave_value(* cat_op_fcn)(const octave_base_value &, const octave_base_value &, const Array< octave_idx_type > &ra_idx)
Definition ov-typeinfo.h:59
octave_value(* unary_class_op_fcn)(const octave_value &)
Definition ov-typeinfo.h:46
unary_class_op_fcn lookup_unary_class_op(octave_value::unary_op)
cat_op_fcn lookup_cat_op(int, int)
binary_op_fcn lookup_binary_op(octave_value::binary_op, int, int)
unary_op_fcn lookup_unary_op(octave_value::unary_op, int)
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void print_usage()
Definition defun-int.h:72
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition defun.h:56
void warning_with_id(const char *id, const char *fmt,...)
Definition error.cc:1093
void error_with_cfn(const char *fmt,...)
Definition error.cc:1033
void error(const char *fmt,...)
Definition error.cc:1003
void warn_implicit_conversion(const char *id, const char *from, const char *to)
Definition errwarn.cc:344
type_info & __get_type_info__()
interpreter & __get_interpreter__()
F77_RET_T const F77_INT F77_CMPLX * A
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
F77_RET_T const F77_DBLE const F77_DBLE * f
std::complex< double > Complex
Definition oct-cmplx.h:33
std::complex< float > FloatComplex
Definition oct-cmplx.h:34
int64_t octave_hdf5_id
@ IT
const octave_base_value const Array< octave_idx_type > & ra_idx
const octave_char_matrix & v2
builtin_type_t
Definition ov-base.h:83
@ btyp_float_complex
Definition ov-base.h:87
@ btyp_double
Definition ov-base.h:84
@ btyp_int32
Definition ov-base.h:90
@ btyp_float
Definition ov-base.h:85
@ btyp_uint16
Definition ov-base.h:93
@ btyp_int64
Definition ov-base.h:91
@ btyp_unknown
Definition ov-base.h:101
@ btyp_uint64
Definition ov-base.h:95
@ btyp_int16
Definition ov-base.h:89
@ btyp_uint32
Definition ov-base.h:94
@ btyp_char
Definition ov-base.h:97
@ btyp_uint8
Definition ov-base.h:92
@ btyp_int8
Definition ov-base.h:88
@ btyp_complex
Definition ov-base.h:86
octave_double_range octave_range
Definition ov-range.h:572
#define XVALUE_EXTRACTOR(TYPE, NAME, FCN)
octave_value colon_op(const octave_value &base, const octave_value &increment, const octave_value &limit, bool is_for_cmd_expr=false)
void install_types(octave::type_info &)
octave_value cat_op(type_info &ti, const octave_value &a, const octave_value &b, const Array< octave_idx_type > &ra_idx)
octave_value binary_op(type_info &ti, octave_value::binary_op op, const octave_value &a, const octave_value &b)
octave_value unary_op(type_info &ti, octave_value::unary_op op, const octave_value &a)
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition ovl.h:217
octave_value set_internal_variable(bool &var, const octave_value_list &args, int nargout, const char *nm)
Definition variables.cc:583