GNU Octave 7.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
ov.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1996-2022 The Octave Project Developers
4//
5// See the file COPYRIGHT.md in the top-level directory of this
6// distribution or <https://octave.org/copyright/>.
7//
8// This file is part of Octave.
9//
10// Octave is free software: you can redistribute it and/or modify it
11// under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// Octave is distributed in the hope that it will be useful, but
16// WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with Octave; see the file COPYING. If not, see
22// <https://www.gnu.org/licenses/>.
23//
24////////////////////////////////////////////////////////////////////////
25
26#if defined (HAVE_CONFIG_H)
27# include "config.h"
28#endif
29
30#include <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
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
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
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
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
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
607{
608 maybe_mutate ();
609}
610
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
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
682 : m_rep (new octave_float_complex_matrix (a))
683{
684 maybe_mutate ();
685}
686
688 : m_rep (new octave_complex_matrix (a))
689{
690 maybe_mutate ();
691}
692
694 : m_rep (new octave_float_complex_matrix (a))
695{
696 maybe_mutate ();
697}
698
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
711{
712 maybe_mutate ();
713}
714
716 : m_rep (new octave_complex_matrix (v))
717{
718 maybe_mutate ();
719}
720
722 : m_rep (new octave_float_complex_matrix (v))
723{
724 maybe_mutate ();
725}
726
728 : m_rep (new octave_complex_matrix (v))
729{
730 maybe_mutate ();
731}
732
734 : m_rep (new octave_float_complex_matrix (v))
735{
736 maybe_mutate ();
737}
738
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;
1020
1021 if (lazy)
1022 {
1023 // Only make lazy indices out of ranges and index vectors.
1024 switch (idx.idx_class ())
1025 {
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 {
1042 m_rep = new octave_magic_colon ();
1043 break;
1044
1046 m_rep = new octave_range (range, idx);
1047 break;
1048
1050 m_rep = new octave_scalar (scalar);
1051 break;
1052
1054 m_rep = new octave_matrix (array, idx);
1055 break;
1056
1058 m_rep = new octave_bool_matrix (mask, idx);
1059 break;
1060
1061 default:
1063 break;
1064 }
1065
1066 // FIXME: needed?
1067 maybe_mutate ();
1068}
1069
1071 : m_rep (new octave_cell (cellstr))
1072{
1073 maybe_mutate ();
1074}
1075
1076// Remove when public constructor that uses this function is removed.
1078octave_value::make_range_rep_deprecated (double base, double inc, double limit)
1079{
1080#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
1081# pragma GCC diagnostic push
1082# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1083#endif
1084
1085 return dynamic_cast<octave_base_value *>
1086 (new octave_legacy_range (Range (base, inc, limit)));
1087
1088#if defined (HAVE_PRAGMA_GCC_DIAGNOSTIC)
1089# pragma GCC diagnostic pop
1090#endif
1091}
1092
1093// Remove when public constructor that uses this function is removed.
1095octave_value::make_range_rep_deprecated (const Range& r, bool force_range)
1096{
1097 if (! force_range && ! r.ok ())
1098 error ("invalid range");
1099
1100 if ((force_range || Voptimize_range))
1101 return dynamic_cast<octave_base_value *> (new octave_legacy_range (r));
1102 else
1103 return dynamic_cast<octave_base_value *> (new octave_matrix (r.matrix_value ()));
1104}
1105
1106octave_value::octave_value (const octave::range<double>& r, bool force_range)
1107 : m_rep (force_range || Voptimize_range
1108 ? dynamic_cast<octave_base_value *> (new ov_range<double> (r))
1109 : dynamic_cast<octave_base_value *> (new octave_matrix (r.array_value ())))
1110{
1111 maybe_mutate ();
1112}
1113
1114// For now, disable all but range<double>.
1115
1116#if 0
1117
1118octave_value::octave_value (const octave::range<float>& r, bool force_range)
1119 : m_rep (force_range || Voptimize_range
1120 ? dynamic_cast<octave_base_value *> (new ov_range<float> (r))
1121 : dynamic_cast<octave_base_value *> (new octave_float_matrix (r.array_value ())))
1122{
1123 maybe_mutate ();
1124}
1125
1126octave_value::octave_value (const octave::range<octave_int8>& r,
1127 bool force_range)
1128 : m_rep (force_range || Voptimize_range
1129 ? dynamic_cast<octave_base_value *> (new ov_range<octave_int8> (r))
1130 : dynamic_cast<octave_base_value *> (new octave_int8_matrix (r.array_value ())))
1131{
1132 maybe_mutate ();
1133}
1134
1135octave_value::octave_value (const octave::range<octave_int16>& r,
1136 bool force_range)
1137 : m_rep (force_range || Voptimize_range
1138 ? dynamic_cast<octave_base_value *> (new ov_range<octave_int16> (r))
1139 : dynamic_cast<octave_base_value *> (new octave_int16_matrix (r.array_value ())))
1140{
1141 maybe_mutate ();
1142}
1143
1144octave_value::octave_value (const octave::range<octave_int32>& r,
1145 bool force_range)
1146 : m_rep (force_range || Voptimize_range
1147 ? dynamic_cast<octave_base_value *> (new ov_range<octave_int32> (r))
1148 : dynamic_cast<octave_base_value *> (new octave_int32_matrix (r.array_value ())))
1149{
1150 maybe_mutate ();
1151}
1152
1153octave_value::octave_value (const octave::range<octave_int64>& r,
1154 bool force_range)
1155 : m_rep (force_range || Voptimize_range
1156 ? dynamic_cast<octave_base_value *> (new ov_range<octave_int64> (r))
1157 : dynamic_cast<octave_base_value *> (new octave_int64_matrix (r.array_value ())))
1158{
1159 maybe_mutate ();
1160}
1161
1162octave_value::octave_value (const octave::range<octave_uint8>& r,
1163 bool force_range)
1164 : m_rep (force_range || Voptimize_range
1165 ? dynamic_cast<octave_base_value *> (new ov_range<octave_uint8> (r))
1166 : dynamic_cast<octave_base_value *> (new octave_uint8_matrix (r.array_value ())))
1167{
1168 maybe_mutate ();
1169}
1170
1171octave_value::octave_value (const octave::range<octave_uint16>& r,
1172 bool force_range)
1173 : m_rep (force_range || Voptimize_range
1174 ? dynamic_cast<octave_base_value *> (new ov_range<octave_uint16> (r))
1175 : dynamic_cast<octave_base_value *> (new octave_uint16_matrix (r.array_value ())))
1176{
1177 maybe_mutate ();
1178}
1179
1180octave_value::octave_value (const octave::range<octave_uint32>& r,
1181 bool force_range)
1182 : m_rep (force_range || Voptimize_range
1183 ? dynamic_cast<octave_base_value *> (new ov_range<octave_uint32> (r))
1184 : dynamic_cast<octave_base_value *> (new octave_uint32_matrix (r.array_value ())))
1185{
1186 maybe_mutate ();
1187}
1188
1189octave_value::octave_value (const octave::range<octave_uint64>& r,
1190 bool force_range)
1191 : m_rep (force_range || Voptimize_range
1192 ? dynamic_cast<octave_base_value *> (new ov_range<octave_uint64> (r))
1193 : dynamic_cast<octave_base_value *> (new octave_uint64_matrix (r.array_value ())))
1194{
1195 maybe_mutate ();
1196}
1197
1198octave_value::octave_value (const octave::range<char>& r, char type,
1199 bool /*force_range*/)
1200#if 0
1201 : m_rep (force_range || optimize_range
1202 ? dynamic_cast<octave_base_value *> (new octave_char_range (r, type))
1203 : dynamic_cast<octave_base_value *> (type == '"'
1204 ? new octave_char_matrix_dq_str (r.array_value ())
1205 : new octave_char_matrix_sq_str (r.array_value ())))
1206#else
1207 : m_rep (type == '"'
1208 ? new octave_char_matrix_dq_str (r.array_value ())
1209 : new octave_char_matrix_sq_str (r.array_value ()))
1210#endif
1211{
1212 maybe_mutate ();
1213}
1214
1215#endif
1216
1218 : m_rep (new octave_struct (m))
1219{
1220 maybe_mutate ();
1221}
1222
1224 : m_rep (new octave_scalar_struct (m))
1225{ }
1226
1227octave_value::octave_value (const std::map<std::string, octave_value>& m)
1228 : m_rep (new octave_scalar_struct (m))
1229{ }
1230
1231octave_value::octave_value (const octave_map& m, const std::string& id,
1232 const std::list<std::string>& plist)
1233 : m_rep (new octave_class (m, id, plist))
1234{
1235 maybe_mutate ();
1236}
1237
1238octave_value::octave_value (const octave_scalar_map& m, const std::string& id,
1239 const std::list<std::string>& plist)
1240 : m_rep (new octave_class (m, id, plist))
1241{ }
1242
1244 : m_rep (new octave_cs_list (l))
1245{ }
1246
1248 : m_rep (new octave_magic_colon ())
1249{ }
1250
1251octave_value::octave_value (octave_base_value *new_rep, bool borrow)
1252 : m_rep (new_rep)
1253{
1254 if (borrow)
1255 m_rep->count++;
1256}
1257
1259octave_value::clone (void) const
1260{
1261 return m_rep->clone ();
1262}
1263
1264void
1265octave_value::break_closure_cycles (const std::shared_ptr<octave::stack_frame>& frame)
1266{
1267 if (is_function_handle ())
1268 {
1270
1271 if (fhdl->is_nested (frame) && ! fhdl->is_weak_nested ())
1272 *this = fhdl->make_weak_nested_handle ();
1273 else if (fhdl->is_anonymous () && ! fhdl->is_weak_anonymous ())
1274 *this = fhdl->make_weak_anonymous_handle ();
1275 }
1276 else
1277 {
1278 // FIXME: Is there a efficient way to avoid calling make_unique
1279 // if REP doesn't contain any nested function handles?
1280 //
1281 // Probably we should be asking REP to make a modified copy IFF it
1282 // is needed, then replace our REP with that if a copy is made,
1283 // otherwise we leave it alone.
1284
1285 make_unique ();
1286
1287 m_rep->break_closure_cycles (frame);
1288 }
1289}
1290
1291void
1293{
1295
1296 if (tmp && tmp != m_rep)
1297 {
1298 if (--m_rep->count == 0)
1299 delete m_rep;
1300
1301 m_rep = tmp;
1302 }
1303}
1304
1305OCTAVE_NAMESPACE_BEGIN
1306
1307DEFUN (double, args, ,
1308 doc: /* -*- texinfo -*-
1309@deftypefn {} {} double (@var{x})
1310Convert @var{x} to double precision type.
1311@seealso{single}
1312@end deftypefn */)
1313{
1314 if (args.length () != 1)
1315 print_usage ();
1316
1317 return ovl (args(0).as_double ());
1318}
1319
1320/*
1321%!assert (class (double (single (1))), "double")
1322%!assert (class (double (single (1 + i))), "double")
1323%!assert (class (double (int8 (1))), "double")
1324%!assert (class (double (uint8 (1))), "double")
1325%!assert (class (double (int16 (1))), "double")
1326%!assert (class (double (uint16 (1))), "double")
1327%!assert (class (double (int32 (1))), "double")
1328%!assert (class (double (uint32 (1))), "double")
1329%!assert (class (double (int64 (1))), "double")
1330%!assert (class (double (uint64 (1))), "double")
1331%!assert (class (double (true)), "double")
1332%!assert (class (double ("A")), "double")
1333%!test
1334%! x = sparse (logical ([1 0; 0 1]));
1335%! y = double (x);
1336%! assert (class (x), "logical");
1337%! assert (class (y), "double");
1338%! assert (issparse (y));
1339%!test
1340%! x = diag (single ([1 3 2]));
1341%! y = double (x);
1342%! assert (class (x), "single");
1343%! assert (class (y), "double");
1344%!test
1345%! x = diag (single ([i 3 2]));
1346%! y = double (x);
1347%! assert (class (x), "single");
1348%! assert (class (y), "double");
1349*/
1350
1351DEFUN (single, args, ,
1352 doc: /* -*- texinfo -*-
1353@deftypefn {} {} single (@var{x})
1354Convert @var{x} to single precision type.
1355@seealso{double}
1356@end deftypefn */)
1357{
1358 if (args.length () != 1)
1359 print_usage ();
1360
1361 return args(0).as_single ();
1362
1363 return ovl ();
1364}
1365
1366/*
1367%!assert (class (single (1)), "single")
1368%!assert (class (single (1 + i)), "single")
1369%!assert (class (single (int8 (1))), "single")
1370%!assert (class (single (uint8 (1))), "single")
1371%!assert (class (single (int16 (1))), "single")
1372%!assert (class (single (uint16 (1))), "single")
1373%!assert (class (single (int32 (1))), "single")
1374%!assert (class (single (uint32 (1))), "single")
1375%!assert (class (single (int64 (1))), "single")
1376%!assert (class (single (uint64 (1))), "single")
1377%!assert (class (single (true)), "single")
1378%!assert (class (single ("A")), "single")
1379%!error single (sparse (1))
1380%!test
1381%! x = diag ([1 3 2]);
1382%! y = single (x);
1383%! assert (class (x), "double");
1384%! assert (class (y), "single");
1385%!test
1386%! x = diag ([i 3 2]);
1387%! y = single (x);
1388%! assert (class (x), "double");
1389%! assert (class (y), "single");
1390*/
1391
1392DEFUN (int8, args, ,
1393 doc: /* -*- texinfo -*-
1394@deftypefn {} {} int8 (@var{x})
1395Convert @var{x} to 8-bit integer type.
1396@seealso{uint8, int16, uint16, int32, uint32, int64, uint64}
1397@end deftypefn */)
1398{
1399 if (args.length () != 1)
1400 print_usage ();
1401
1402 return args(0).as_int8 ();
1403}
1404
1405/*
1406%!assert (class (int8 (1)), "int8")
1407%!assert (int8 (1.25), int8 (1))
1408%!assert (int8 (1.5), int8 (2))
1409%!assert (int8 (-1.5), int8 (-2))
1410%!assert (int8 (2^9), int8 (2^8-1))
1411%!assert (int8 (-2^9), int8 (-2^8))
1412*/
1413
1414DEFUN (int16, args, ,
1415 doc: /* -*- texinfo -*-
1416@deftypefn {} {} int16 (@var{x})
1417Convert @var{x} to 16-bit integer type.
1418@seealso{int8, uint8, uint16, int32, uint32, int64, uint64}
1419@end deftypefn */)
1420{
1421 if (args.length () != 1)
1422 print_usage ();
1423
1424 return args(0).as_int16 ();
1425}
1426
1427/*
1428%!assert (class (int16 (1)), "int16")
1429%!assert (int16 (1.25), int16 (1))
1430%!assert (int16 (1.5), int16 (2))
1431%!assert (int16 (-1.5), int16 (-2))
1432%!assert (int16 (2^17), int16 (2^16-1))
1433%!assert (int16 (-2^17), int16 (-2^16))
1434*/
1435
1436DEFUN (int32, args, ,
1437 doc: /* -*- texinfo -*-
1438@deftypefn {} {} int32 (@var{x})
1439Convert @var{x} to 32-bit integer type.
1440@seealso{int8, uint8, int16, uint16, uint32, int64, uint64}
1441@end deftypefn */)
1442{
1443 if (args.length () != 1)
1444 print_usage ();
1445
1446 return args(0).as_int32 ();
1447}
1448
1449/*
1450%!assert (class (int32 (1)), "int32")
1451%!assert (int32 (1.25), int32 (1))
1452%!assert (int32 (1.5), int32 (2))
1453%!assert (int32 (-1.5), int32 (-2))
1454%!assert (int32 (2^33), int32 (2^32-1))
1455%!assert (int32 (-2^33), int32 (-2^32))
1456*/
1457
1458DEFUN (int64, args, ,
1459 doc: /* -*- texinfo -*-
1460@deftypefn {} {} int64 (@var{x})
1461Convert @var{x} to 64-bit integer type.
1462@seealso{int8, uint8, int16, uint16, int32, uint32, uint64}
1463@end deftypefn */)
1464{
1465 if (args.length () != 1)
1466 print_usage ();
1467
1468 return args(0).as_int64 ();
1469}
1470
1471/*
1472%!assert (class (int64 (1)), "int64")
1473%!assert (int64 (1.25), int64 (1))
1474%!assert (int64 (1.5), int64 (2))
1475%!assert (int64 (-1.5), int64 (-2))
1476%!assert (int64 (2^65), int64 (2^64-1))
1477%!assert (int64 (-2^65), int64 (-2^64))
1478*/
1479
1480DEFUN (uint8, args, ,
1481 doc: /* -*- texinfo -*-
1482@deftypefn {} {} uint8 (@var{x})
1483Convert @var{x} to unsigned 8-bit integer type.
1484@seealso{int8, int16, uint16, int32, uint32, int64, uint64}
1485@end deftypefn */)
1486{
1487 if (args.length () != 1)
1488 print_usage ();
1489
1490 return args(0).as_uint8 ();
1491}
1492
1493/*
1494%!assert (class (uint8 (1)), "uint8")
1495%!assert (uint8 (1.25), uint8 (1))
1496%!assert (uint8 (1.5), uint8 (2))
1497%!assert (uint8 (-1.5), uint8 (0))
1498%!assert (uint8 (2^9), uint8 (2^8-1))
1499%!assert (uint8 (-2^9), uint8 (0))
1500*/
1501
1502DEFUN (uint16, args, ,
1503 doc: /* -*- texinfo -*-
1504@deftypefn {} {} uint16 (@var{x})
1505Convert @var{x} to unsigned 16-bit integer type.
1506@seealso{int8, uint8, int16, int32, uint32, int64, uint64}
1507@end deftypefn */)
1508{
1509 if (args.length () != 1)
1510 print_usage ();
1511
1512 return args(0).as_uint16 ();
1513}
1514
1515/*
1516%!assert (class (uint16 (1)), "uint16")
1517%!assert (uint16 (1.25), uint16 (1))
1518%!assert (uint16 (1.5), uint16 (2))
1519%!assert (uint16 (-1.5), uint16 (0))
1520%!assert (uint16 (2^17), uint16 (2^16-1))
1521%!assert (uint16 (-2^17), uint16 (0))
1522*/
1523
1524DEFUN (uint32, args, ,
1525 doc: /* -*- texinfo -*-
1526@deftypefn {} {} uint32 (@var{x})
1527Convert @var{x} to unsigned 32-bit integer type.
1528@seealso{int8, uint8, int16, uint16, int32, int64, uint64}
1529@end deftypefn */)
1530{
1531 if (args.length () != 1)
1532 print_usage ();
1533
1534 return args(0).as_uint32 ();
1535}
1536
1537/*
1538%!assert (class (uint32 (1)), "uint32")
1539%!assert (uint32 (1.25), uint32 (1))
1540%!assert (uint32 (1.5), uint32 (2))
1541%!assert (uint32 (-1.5), uint32 (0))
1542%!assert (uint32 (2^33), uint32 (2^32-1))
1543%!assert (uint32 (-2^33), uint32 (0))
1544*/
1545
1546DEFUN (uint64, args, ,
1547 doc: /* -*- texinfo -*-
1548@deftypefn {} {} uint64 (@var{x})
1549Convert @var{x} to unsigned 64-bit integer type.
1550@seealso{int8, uint8, int16, uint16, int32, uint32, int64}
1551@end deftypefn */)
1552{
1553 if (args.length () != 1)
1554 print_usage ();
1555
1556 return args(0).as_uint64 ();
1557}
1558
1559/*
1560%!assert (class (uint64 (1)), "uint64")
1561%!assert (uint64 (1.25), uint64 (1))
1562%!assert (uint64 (1.5), uint64 (2))
1563%!assert (uint64 (-1.5), uint64 (0))
1564%!assert (uint64 (2^65), uint64 (2^64-1))
1565%!assert (uint64 (-2^65), uint64 (0))
1566*/
1567
1568OCTAVE_NAMESPACE_END
1569
1571octave_value::single_subsref (const std::string& type,
1572 const octave_value_list& idx)
1573{
1574 std::list<octave_value_list> i;
1575
1576 i.push_back (idx);
1577
1578 return m_rep->subsref (type, i);
1579}
1580
1582octave_value::subsref (const std::string& type,
1583 const std::list<octave_value_list>& idx, int nargout)
1584{
1585 return m_rep->subsref (type, idx, nargout);
1586}
1587
1589octave_value::next_subsref (const std::string& type,
1590 const std::list<octave_value_list>& idx,
1591 std::size_t skip)
1592{
1593 if (idx.size () > skip)
1594 {
1595 std::list<octave_value_list> new_idx (idx);
1596 for (std::size_t i = 0; i < skip; i++)
1597 new_idx.erase (new_idx.begin ());
1598 return subsref (type.substr (skip), new_idx);
1599 }
1600 else
1601 return *this;
1602}
1603
1605octave_value::next_subsref (int nargout, const std::string& type,
1606 const std::list<octave_value_list>& idx,
1607 std::size_t skip)
1608{
1609 if (idx.size () > skip)
1610 {
1611 std::list<octave_value_list> new_idx (idx);
1612 for (std::size_t i = 0; i < skip; i++)
1613 new_idx.erase (new_idx.begin ());
1614 return subsref (type.substr (skip), new_idx, nargout);
1615 }
1616 else
1617 return *this;
1618}
1619
1621octave_value::next_subsref (bool auto_add, const std::string& type,
1622 const std::list<octave_value_list>& idx,
1623 std::size_t skip)
1624{
1625 if (idx.size () > skip)
1626 {
1627 std::list<octave_value_list> new_idx (idx);
1628 for (std::size_t i = 0; i < skip; i++)
1629 new_idx.erase (new_idx.begin ());
1630 return subsref (type.substr (skip), new_idx, auto_add);
1631 }
1632 else
1633 return *this;
1634}
1635
1637octave_value::subsasgn (const std::string& type,
1638 const std::list<octave_value_list>& idx,
1639 const octave_value& rhs)
1640{
1641 return m_rep->subsasgn (type, idx, rhs);
1642}
1643
1645octave_value::undef_subsasgn (const std::string& type,
1646 const std::list<octave_value_list>& idx,
1647 const octave_value& rhs)
1648{
1649 return m_rep->undef_subsasgn (type, idx, rhs);
1650}
1651
1653octave_value::assign (assign_op op, const std::string& type,
1654 const std::list<octave_value_list>& idx,
1655 const octave_value& rhs)
1656{
1657 make_unique ();
1658
1659 octave_value t_rhs = rhs;
1660
1661 if (op != op_asn_eq)
1662 {
1663 if (! is_defined ())
1664 error ("in computed assignment A(index) OP= X, A must be defined first");
1665
1666 octave_value t = subsref (type, idx);
1667
1668 binary_op binop = op_eq_to_binary_op (op);
1669
1670 t_rhs = octave::binary_op (binop, t, rhs);
1671 }
1672
1673 *this = subsasgn (type, idx, t_rhs);
1674
1675 return *this;
1676}
1677
1679octave_value::assign (assign_op op, const octave_value& rhs)
1680{
1681 if (op == op_asn_eq)
1682 // Regularize a null matrix if stored into a variable.
1684 else if (is_defined ())
1685 {
1687
1688 // Only attempt to operate in-place if this variable is unshared.
1689 if (m_rep->count == 1)
1690 {
1691 int tthis = this->type_id ();
1692 int trhs = rhs.type_id ();
1693
1694 octave::type_info& ti
1695 = octave::__get_type_info__ ("octave_value::assign");
1696
1697 f = ti.lookup_assign_op (op, tthis, trhs);
1698 }
1699
1700 if (f)
1701 {
1702 f (*m_rep, octave_value_list (), rhs.get_rep ());
1703 // Usually unnecessary, but may be needed (complex arrays).
1704 maybe_mutate ();
1705 }
1706 else
1707 {
1708
1709 binary_op binop = op_eq_to_binary_op (op);
1710
1711 octave_value t = octave::binary_op (binop, *this, rhs);
1712
1713 operator = (t);
1714 }
1715 }
1716 else
1717 error ("in computed assignment A OP= X, A must be defined first");
1718
1719 return *this;
1720}
1721
1722// FIXME: This is a bit of a kluge. We'd like to just use val.dims()
1723// and if val is an object, expect that dims will call size if it is
1724// overloaded by a user-defined method. But there are currently some
1725// unresolved const issues that prevent that solution from working.
1726
1727std::string
1728octave_value::get_dims_str (void) const
1729{
1730 octave_value tmp = *this;
1731
1732 Matrix sz = tmp.size ();
1733
1734 dim_vector dv = dim_vector::alloc (sz.numel ());
1735
1736 for (octave_idx_type i = 0; i < dv.ndims (); i++)
1737 dv(i) = sz(i);
1738
1739 return dv.str ();
1740}
1741
1743octave_value::length (void) const
1744{
1745 octave_idx_type retval = 0;
1746
1747 const dim_vector dv = dims ();
1748
1749 for (int i = 0; i < dv.ndims (); i++)
1750 {
1751 if (dv(i) == 0)
1752 {
1753 retval = 0;
1754 break;
1755 }
1756
1757 if (dv(i) > retval)
1758 retval = dv(i);
1759 }
1760
1761 return retval;
1762}
1763
1764bool
1765octave_value::is_equal (const octave_value& test) const
1766{
1767 bool retval = false;
1768
1769 // If there is no op_eq for these types, we can't compare values.
1770
1771 if (rows () == test.rows () && columns () == test.columns ())
1772 {
1774
1775 // Empty array also means a match.
1776 if (tmp.is_defined ())
1777 {
1778 if (tmp.isempty ())
1779 retval = true;
1780 else
1781 {
1782 // Reshape into a vector and call all() explicitly,
1783 // to avoid Octave:array-as-logical warning.
1784 tmp = tmp.reshape (dim_vector (tmp.numel (), 1));
1785 retval = tmp.all ().is_true ();
1786 }
1787 }
1788 }
1789
1790 return retval;
1791}
1792
1793// Define the idx_type_value function here instead of in ov.h to avoid
1794// needing definitions for the SIZEOF_X macros in ov.h.
1795
1797octave_value::idx_type_value (bool req_int, bool frc_str_conv) const
1798{
1799#if defined (OCTAVE_ENABLE_64)
1800 return int64_value (req_int, frc_str_conv);
1801#else
1802 return int_value (req_int, frc_str_conv);
1803#endif
1804}
1805
1806Cell
1807octave_value::cell_value (void) const
1808{
1809 return m_rep->cell_value ();
1810}
1811
1813octave_value::map_value (void) const
1814{
1815 return m_rep->map_value ();
1816}
1817
1820{
1821 return m_rep->scalar_map_value ();
1822}
1823
1825octave_value::function_value (bool silent) const
1826{
1827 return m_rep->function_value (silent);
1828}
1829
1831octave_value::classdef_object_value (bool silent) const
1832{
1833 return m_rep->classdef_object_value (silent);
1834}
1835
1837octave_value::user_function_value (bool silent) const
1838{
1839 return m_rep->user_function_value (silent);
1840}
1841
1843octave_value::user_script_value (bool silent) const
1844{
1845 return m_rep->user_script_value (silent);
1846}
1847
1849octave_value::user_code_value (bool silent) const
1850{
1851 return m_rep->user_code_value (silent);
1852}
1853
1855octave_value::fcn_handle_value (bool silent) const
1856{
1857 return m_rep->fcn_handle_value (silent);
1858}
1859
1861octave_value::list_value (void) const
1862{
1863 return m_rep->list_value ();
1864}
1865
1866static dim_vector
1867make_vector_dims (const dim_vector& dv, bool force_vector_conversion,
1868 const std::string& my_type, const std::string& wanted_type)
1869{
1870 dim_vector retval (dv);
1871 retval.chop_trailing_singletons ();
1872 octave_idx_type nel = dv.numel ();
1873
1874 if (retval.ndims () > 2 || (retval(0) != 1 && retval(1) != 1))
1875 {
1876 if (! force_vector_conversion)
1877 warn_implicit_conversion ("Octave:array-to-vector",
1878 my_type.c_str (), wanted_type.c_str ());
1879 retval = dim_vector (nel, 1);
1880 }
1881
1882 return retval;
1883}
1884
1886octave_value::column_vector_value (bool force_string_conv,
1887 bool frc_vec_conv) const
1888{
1889 return ColumnVector (vector_value (force_string_conv,
1890 frc_vec_conv));
1891}
1892
1894octave_value::complex_column_vector_value (bool force_string_conv,
1895 bool frc_vec_conv) const
1896{
1897 return ComplexColumnVector (complex_vector_value (force_string_conv,
1898 frc_vec_conv));
1899}
1900
1902octave_value::row_vector_value (bool force_string_conv,
1903 bool frc_vec_conv) const
1904{
1905 return RowVector (vector_value (force_string_conv,
1906 frc_vec_conv));
1907}
1908
1910octave_value::complex_row_vector_value (bool force_string_conv,
1911 bool frc_vec_conv) const
1912{
1913 return ComplexRowVector (complex_vector_value (force_string_conv,
1914 frc_vec_conv));
1915}
1916
1918octave_value::vector_value (bool force_string_conv,
1919 bool force_vector_conversion) const
1920{
1921 Array<double> retval = array_value (force_string_conv);
1922
1923 return retval.reshape (make_vector_dims (retval.dims (),
1924 force_vector_conversion,
1925 type_name (), "real vector"));
1926}
1927
1928template <typename T>
1929static Array<int>
1930convert_to_int_array (const Array<octave_int<T>>& A)
1931{
1932 Array<int> retval (A.dims ());
1933 octave_idx_type n = A.numel ();
1934
1935 for (octave_idx_type i = 0; i < n; i++)
1936 retval.xelem (i) = octave_int<int> (A.xelem (i));
1937
1938 return retval;
1939}
1940
1942octave_value::int_vector_value (bool require_int, bool force_string_conv,
1943 bool force_vector_conversion) const
1944{
1945 Array<int> retval;
1946
1947 if (isinteger ())
1948 {
1949 if (is_int32_type ())
1950 retval = convert_to_int_array (int32_array_value ());
1951 else if (is_int64_type ())
1952 retval = convert_to_int_array (int64_array_value ());
1953 else if (is_int16_type ())
1954 retval = convert_to_int_array (int16_array_value ());
1955 else if (is_int8_type ())
1956 retval = convert_to_int_array (int8_array_value ());
1957 else if (is_uint32_type ())
1958 retval = convert_to_int_array (uint32_array_value ());
1959 else if (is_uint64_type ())
1960 retval = convert_to_int_array (uint64_array_value ());
1961 else if (is_uint16_type ())
1962 retval = convert_to_int_array (uint16_array_value ());
1963 else if (is_uint8_type ())
1964 retval = convert_to_int_array (uint8_array_value ());
1965 else
1966 retval = array_value (force_string_conv);
1967 }
1968 else
1969 {
1970 const NDArray a = array_value (force_string_conv);
1971
1972 if (require_int)
1973 {
1974 retval.resize (a.dims ());
1975 for (octave_idx_type i = 0; i < a.numel (); i++)
1976 {
1977 double ai = a.elem (i);
1978 int v = static_cast<int> (ai);
1979 if (ai == v)
1980 retval.xelem (i) = v;
1981 else
1982 {
1983 error_with_cfn ("conversion of %g to int value failed", ai);
1984 break;
1985 }
1986 }
1987 }
1988 else
1989 retval = Array<int> (a);
1990 }
1991
1992 return retval.reshape (make_vector_dims (retval.dims (),
1993 force_vector_conversion,
1994 type_name (), "integer vector"));
1995}
1996
1997template <typename T>
1999convert_to_octave_idx_type_array (const Array<octave_int<T>>& A)
2000{
2001 Array<octave_idx_type> retval (A.dims ());
2002 octave_idx_type n = A.numel ();
2003
2004 for (octave_idx_type i = 0; i < n; i++)
2005 retval.xelem (i) = octave_int<octave_idx_type> (A.xelem (i));
2006
2007 return retval;
2008}
2009
2012 bool force_string_conv,
2013 bool force_vector_conversion) const
2014{
2016
2017 if (isinteger ())
2018 {
2019 if (is_int32_type ())
2020 retval = convert_to_octave_idx_type_array (int32_array_value ());
2021 else if (is_int64_type ())
2022 retval = convert_to_octave_idx_type_array (int64_array_value ());
2023 else if (is_int16_type ())
2024 retval = convert_to_octave_idx_type_array (int16_array_value ());
2025 else if (is_int8_type ())
2026 retval = convert_to_octave_idx_type_array (int8_array_value ());
2027 else if (is_uint32_type ())
2028 retval = convert_to_octave_idx_type_array (uint32_array_value ());
2029 else if (is_uint64_type ())
2030 retval = convert_to_octave_idx_type_array (uint64_array_value ());
2031 else if (is_uint16_type ())
2032 retval = convert_to_octave_idx_type_array (uint16_array_value ());
2033 else if (is_uint8_type ())
2034 retval = convert_to_octave_idx_type_array (uint8_array_value ());
2035 else
2036 retval = array_value (force_string_conv);
2037 }
2038 else
2039 {
2040 const NDArray a = array_value (force_string_conv);
2041
2042 if (require_int)
2043 {
2044 retval.resize (a.dims ());
2045 for (octave_idx_type i = 0; i < a.numel (); i++)
2046 {
2047 double ai = a.elem (i);
2048 octave_idx_type v = static_cast<octave_idx_type> (ai);
2049 if (ai == v)
2050 retval.xelem (i) = v;
2051 else
2052 {
2053 error_with_cfn ("conversion of %g to octave_idx_type value failed", ai);
2054 break;
2055 }
2056 }
2057 }
2058 else
2059 retval = Array<octave_idx_type> (a);
2060 }
2061
2062 return retval.reshape (make_vector_dims (retval.dims (),
2063 force_vector_conversion,
2064 type_name (), "integer vector"));
2065}
2066
2068octave_value::complex_vector_value (bool force_string_conv,
2069 bool force_vector_conversion) const
2070{
2071 Array<Complex> retval = complex_array_value (force_string_conv);
2072
2073 return retval.reshape (make_vector_dims (retval.dims (),
2074 force_vector_conversion,
2075 type_name (), "complex vector"));
2076}
2077
2079octave_value::float_column_vector_value (bool force_string_conv,
2080 bool frc_vec_conv) const
2081{
2082 return FloatColumnVector (float_vector_value (force_string_conv,
2083 frc_vec_conv));
2084}
2085
2088 bool frc_vec_conv) const
2089{
2090 return
2092 frc_vec_conv));
2093}
2094
2096octave_value::float_row_vector_value (bool force_string_conv,
2097 bool frc_vec_conv) const
2098{
2099 return FloatRowVector (float_vector_value (force_string_conv,
2100 frc_vec_conv));
2101}
2102
2104octave_value::float_complex_row_vector_value (bool force_string_conv,
2105 bool frc_vec_conv) const
2106{
2107 return FloatComplexRowVector (float_complex_vector_value (force_string_conv,
2108 frc_vec_conv));
2109}
2110
2112octave_value::float_vector_value (bool force_string_conv,
2113 bool force_vector_conversion) const
2114{
2115 Array<float> retval = float_array_value (force_string_conv);
2116
2117 return retval.reshape (make_vector_dims (retval.dims (),
2118 force_vector_conversion,
2119 type_name (), "real vector"));
2120}
2121
2123octave_value::float_complex_vector_value (bool force_string_conv,
2124 bool force_vector_conversion) const
2125{
2126 Array<FloatComplex> retval = float_complex_array_value (force_string_conv);
2127
2128 return retval.reshape (make_vector_dims (retval.dims (),
2129 force_vector_conversion,
2130 type_name (), "complex vector"));
2131}
2132
2133// NAME can't always be "x ## FCN" because some of the original
2134// value extraction functions perform implicit type conversions that we
2135// wish to avoid for these functions.
2136
2137#define XVALUE_EXTRACTOR(TYPE, NAME, FCN) \
2138 TYPE \
2139 octave_value::NAME (const char *fmt, ...) const \
2140 { \
2141 TYPE retval; \
2142 \
2143 try \
2144 { \
2145 retval = FCN (); \
2146 } \
2147 catch (octave::execution_exception& ee) \
2148 { \
2149 if (fmt) \
2150 { \
2151 va_list args; \
2152 va_start (args, fmt); \
2153 verror (ee, fmt, args); \
2154 va_end (args); \
2155 } \
2156 \
2157 throw ee; \
2158 } \
2159 \
2160 return retval; \
2161 }
2162
2163XVALUE_EXTRACTOR (short int, xshort_value, short_value)
2164
2165XVALUE_EXTRACTOR (unsigned short int, xushort_value, ushort_value)
2166
2167XVALUE_EXTRACTOR (int, xint_value, int_value)
2168
2169XVALUE_EXTRACTOR (unsigned int, xuint_value, uint_value)
2170
2171XVALUE_EXTRACTOR (int, xnint_value, nint_value)
2172
2173XVALUE_EXTRACTOR (long int, xlong_value, long_value)
2174
2175XVALUE_EXTRACTOR (unsigned long int, xulong_value, ulong_value)
2176
2177XVALUE_EXTRACTOR (int64_t, xint64_value, int64_value)
2178
2179XVALUE_EXTRACTOR (uint64_t, xuint64_value, uint64_value)
2180
2181XVALUE_EXTRACTOR (octave_idx_type, xidx_type_value, idx_type_value)
2182
2183XVALUE_EXTRACTOR (double, xdouble_value, double_value)
2184XVALUE_EXTRACTOR (float, xfloat_value, float_value)
2185
2186XVALUE_EXTRACTOR (double, xscalar_value, scalar_value)
2187XVALUE_EXTRACTOR (float, xfloat_scalar_value, float_scalar_value)
2188
2189XVALUE_EXTRACTOR (Matrix, xmatrix_value, matrix_value)
2190XVALUE_EXTRACTOR (FloatMatrix, xfloat_matrix_value, float_matrix_value)
2191
2192XVALUE_EXTRACTOR (NDArray, xarray_value, array_value)
2193XVALUE_EXTRACTOR (FloatNDArray, xfloat_array_value, float_array_value)
2194
2195XVALUE_EXTRACTOR (Complex, xcomplex_value, complex_value)
2196XVALUE_EXTRACTOR (FloatComplex, xfloat_complex_value, float_complex_value)
2197
2198XVALUE_EXTRACTOR (ComplexMatrix, xcomplex_matrix_value, complex_matrix_value)
2199XVALUE_EXTRACTOR (FloatComplexMatrix, xfloat_complex_matrix_value, float_complex_matrix_value)
2200
2201XVALUE_EXTRACTOR (ComplexNDArray, xcomplex_array_value, complex_array_value)
2202XVALUE_EXTRACTOR (FloatComplexNDArray, xfloat_complex_array_value, float_complex_array_value)
2203
2204XVALUE_EXTRACTOR (bool, xbool_value, bool_value)
2205XVALUE_EXTRACTOR (boolMatrix, xbool_matrix_value, bool_matrix_value)
2206XVALUE_EXTRACTOR (boolNDArray, xbool_array_value, bool_array_value)
2207
2208XVALUE_EXTRACTOR (charMatrix, xchar_matrix_value, char_matrix_value)
2209XVALUE_EXTRACTOR (charNDArray, xchar_array_value, char_array_value)
2210
2211XVALUE_EXTRACTOR (SparseMatrix, xsparse_matrix_value, sparse_matrix_value)
2212XVALUE_EXTRACTOR (SparseComplexMatrix, xsparse_complex_matrix_value, sparse_complex_matrix_value)
2213XVALUE_EXTRACTOR (SparseBoolMatrix, xsparse_bool_matrix_value, sparse_bool_matrix_value)
2214
2215XVALUE_EXTRACTOR (DiagMatrix, xdiag_matrix_value, diag_matrix_value)
2216XVALUE_EXTRACTOR (FloatDiagMatrix, xfloat_diag_matrix_value, float_diag_matrix_value)
2217XVALUE_EXTRACTOR (ComplexDiagMatrix, xcomplex_diag_matrix_value, complex_diag_matrix_value)
2218XVALUE_EXTRACTOR (FloatComplexDiagMatrix, xfloat_complex_diag_matrix_value, float_complex_diag_matrix_value)
2219
2220XVALUE_EXTRACTOR (PermMatrix, xperm_matrix_value, perm_matrix_value)
2221
2222XVALUE_EXTRACTOR (octave_int8, xint8_scalar_value, int8_scalar_value)
2223XVALUE_EXTRACTOR (octave_int16, xint16_scalar_value, int16_scalar_value)
2224XVALUE_EXTRACTOR (octave_int32, xint32_scalar_value, int32_scalar_value)
2225XVALUE_EXTRACTOR (octave_int64, xint64_scalar_value, int64_scalar_value)
2226
2227XVALUE_EXTRACTOR (octave_uint8, xuint8_scalar_value, uint8_scalar_value)
2228XVALUE_EXTRACTOR (octave_uint16, xuint16_scalar_value, uint16_scalar_value)
2229XVALUE_EXTRACTOR (octave_uint32, xuint32_scalar_value, uint32_scalar_value)
2230XVALUE_EXTRACTOR (octave_uint64, xuint64_scalar_value, uint64_scalar_value)
2231
2232XVALUE_EXTRACTOR (int8NDArray, xint8_array_value, int8_array_value)
2233XVALUE_EXTRACTOR (int16NDArray, xint16_array_value, int16_array_value)
2234XVALUE_EXTRACTOR (int32NDArray, xint32_array_value, int32_array_value)
2235XVALUE_EXTRACTOR (int64NDArray, xint64_array_value, int64_array_value)
2236
2237XVALUE_EXTRACTOR (uint8NDArray, xuint8_array_value, uint8_array_value)
2238XVALUE_EXTRACTOR (uint16NDArray, xuint16_array_value, uint16_array_value)
2239XVALUE_EXTRACTOR (uint32NDArray, xuint32_array_value, uint32_array_value)
2240XVALUE_EXTRACTOR (uint64NDArray, xuint64_array_value, uint64_array_value)
2241
2242XVALUE_EXTRACTOR (std::string, xstring_value, m_rep->xstring_value)
2243XVALUE_EXTRACTOR (string_vector, xstring_vector_value, string_vector_value)
2244
2245XVALUE_EXTRACTOR (Cell, xcell_value, cell_value)
2246XVALUE_EXTRACTOR (Array<std::string>, xcellstr_value, cellstr_value)
2247
2248XVALUE_EXTRACTOR (octave::range<double>, xrange_value, range_value)
2249
2250// For now, disable all but ov_range<double>.
2251
2252#if 0
2253
2254XVALUE_EXTRACTOR (octave::range<float>, xfloat_range_value, float_range_value)
2255XVALUE_EXTRACTOR (octave::range<octave_int8>, xint8_range_value, int8_range_value)
2256XVALUE_EXTRACTOR (octave::range<octave_int16>, xint16_range_value, int16_range_value)
2257XVALUE_EXTRACTOR (octave::range<octave_int32>, xint32_range_value, int32_range_value)
2258XVALUE_EXTRACTOR (octave::range<octave_int64>, xint64_range_value, int64_range_value)
2259XVALUE_EXTRACTOR (octave::range<octave_uint8>, xuint8_range_value, uint8_range_value)
2260XVALUE_EXTRACTOR (octave::range<octave_uint16>, xuint16_range_value, uint16_range_value)
2261XVALUE_EXTRACTOR (octave::range<octave_uint32>, xuint32_range_value, uint32_range_value)
2262XVALUE_EXTRACTOR (octave::range<octave_uint64>, xuint64_range_value, uint64_range_value)
2263
2264#endif
2265
2266XVALUE_EXTRACTOR (octave_map, xmap_value, map_value)
2267XVALUE_EXTRACTOR (octave_scalar_map, xscalar_map_value, scalar_map_value)
2268
2269XVALUE_EXTRACTOR (ColumnVector, xcolumn_vector_value, column_vector_value)
2270XVALUE_EXTRACTOR (ComplexColumnVector, xcomplex_column_vector_value, complex_column_vector_value)
2271
2272XVALUE_EXTRACTOR (RowVector, xrow_vector_value, row_vector_value)
2273XVALUE_EXTRACTOR (ComplexRowVector, xcomplex_row_vector_value, complex_row_vector_value)
2274
2275XVALUE_EXTRACTOR (FloatColumnVector, xfloat_column_vector_value, float_column_vector_value)
2276XVALUE_EXTRACTOR (FloatComplexColumnVector, xfloat_complex_column_vector_value, float_complex_column_vector_value)
2277
2278XVALUE_EXTRACTOR (FloatRowVector, xfloat_row_vector_value, float_row_vector_value)
2279XVALUE_EXTRACTOR (FloatComplexRowVector, xfloat_complex_row_vector_value, float_complex_row_vector_value)
2280
2281XVALUE_EXTRACTOR (Array<int>, xint_vector_value, int_vector_value)
2282XVALUE_EXTRACTOR (Array<octave_idx_type>, xoctave_idx_type_vector_value, octave_idx_type_vector_value)
2283
2284XVALUE_EXTRACTOR (Array<double>, xvector_value, vector_value)
2285XVALUE_EXTRACTOR (Array<Complex>, xcomplex_vector_value, complex_vector_value)
2286
2287XVALUE_EXTRACTOR (Array<float>, xfloat_vector_value, float_vector_value)
2288XVALUE_EXTRACTOR (Array<FloatComplex>, xfloat_complex_vector_value, float_complex_vector_value)
2289
2290XVALUE_EXTRACTOR (octave_function *, xfunction_value, function_value)
2291XVALUE_EXTRACTOR (octave_user_function *, xuser_function_value, user_function_value)
2292XVALUE_EXTRACTOR (octave_user_script *, xuser_script_value, user_script_value)
2293XVALUE_EXTRACTOR (octave_user_code *, xuser_code_value, user_code_value)
2294XVALUE_EXTRACTOR (octave_fcn_handle *, xfcn_handle_value, fcn_handle_value)
2295
2296XVALUE_EXTRACTOR (octave_value_list, xlist_value, list_value)
2297
2298#undef XVALUE_EXTRACTOR
2299
2302{
2303 octave_value retval = *this;
2304 if (isnull ())
2305 retval = octave_value (m_rep->empty_clone ());
2306 else if (is_magic_int ())
2307 retval = octave_value (m_rep->double_value ());
2308 else if (is_range () && ! m_rep->is_storable ())
2309 error ("range with infinite number of elements cannot be stored");
2310 else
2311 retval.maybe_economize ();
2312
2313 return retval;
2314}
2315
2316void
2318{
2319 if (isnull ())
2320 {
2322 if (--m_rep->count == 0)
2323 delete m_rep;
2324 m_rep = rc;
2325 }
2326 else if (is_magic_int ())
2327 {
2329 if (--m_rep->count == 0)
2330 delete m_rep;
2331 m_rep = rc;
2332 }
2333 else if (is_range () && ! m_rep->is_storable ())
2334 error ("range with infinite number of elements cannot be stored");
2335 else
2336 maybe_economize ();
2337}
2338
2341{
2342 return m_rep->get_edit_display_format ();
2343}
2344
2345int
2346octave_value::write (octave::stream& os, int block_size,
2347 oct_data_conv::data_type output_type, int skip,
2348 octave::mach_info::float_format flt_fmt) const
2349{
2350 return m_rep->write (os, block_size, output_type, skip, flt_fmt);
2351}
2352
2353void
2354octave_value::print_info (std::ostream& os, const std::string& prefix) const
2355{
2356 os << prefix << "type_name: " << type_name () << "\n"
2357 << prefix << "count: " << get_count () << "\n"
2358 << prefix << "m_rep info: ";
2359
2360 m_rep->print_info (os, prefix + ' ');
2361}
2362
2363bool octave_value::load_ascii (std::istream& is)
2364{
2365 bool status = m_rep->load_ascii (is);
2366
2367 // Force conversion of legacy objects.
2368 if (is_legacy_object ())
2369 maybe_mutate ();
2370
2371 return status;
2372}
2373bool octave_value::load_binary (std::istream& is, bool swap,
2375{
2376 bool status = m_rep->load_binary (is, swap, fmt);
2377
2378 // Force conversion of legacy objects.
2379 if (is_legacy_object ())
2380 maybe_mutate ();
2381
2382 return status;
2383}
2384
2385bool octave_value::load_hdf5 (octave_hdf5_id loc_id, const char *name)
2386{
2387 bool status = m_rep->load_hdf5 (loc_id, name);
2388
2389 // Force conversion of legacy objects.
2390 if (is_legacy_object ())
2391 maybe_mutate ();
2392
2393 return status;
2394}
2395
2396const void *
2397octave_value::mex_get_data (mxClassID class_id, mxComplexity complexity) const
2398{
2399 // If class_id is set to mxUNKNOWN_CLASS, return data for any type.
2400 // Otherwise, require that REP matches the requested type and
2401 // complexity.
2402
2403 if (class_id != mxUNKNOWN_CLASS)
2404 {
2405 bool type_ok = false;
2406
2407 switch (class_id)
2408 {
2409 case mxDOUBLE_CLASS:
2410 type_ok = is_double_type ();
2411 break;
2412
2413 case mxSINGLE_CLASS:
2414 type_ok = is_single_type ();
2415 break;
2416
2417 case mxINT8_CLASS:
2418 type_ok = is_int8_type ();
2419 break;
2420
2421 case mxINT16_CLASS:
2422 type_ok = is_int16_type ();
2423 break;
2424
2425 case mxINT32_CLASS:
2426 type_ok = is_int32_type ();
2427 break;
2428
2429 case mxINT64_CLASS:
2430 type_ok = is_int64_type ();
2431 break;
2432
2433 case mxUINT8_CLASS:
2434 type_ok = is_uint8_type ();
2435 break;
2436
2437 case mxUINT16_CLASS:
2438 type_ok = is_uint16_type ();
2439 break;
2440
2441 case mxUINT32_CLASS:
2442 type_ok = is_uint32_type ();
2443 break;
2444
2445 case mxUINT64_CLASS:
2446 type_ok = is_uint64_type ();
2447 break;
2448
2449 default:
2450 // We only expect to see numeric types explicitly requested.
2451 error ("mex_get_data: unexpected type requested");
2452 }
2453
2454 if (! type_ok)
2455 error ("mex_get_data: type mismatch");
2456
2457 if (complexity == mxCOMPLEX && ! iscomplex ())
2458 error ("mex_get_data: objectis not complex as requested");
2459 }
2460
2461 return m_rep->mex_get_data ();
2462}
2463
2464OCTAVE_NORETURN static void
2465err_unary_op_conversion_failed (const std::string& op,
2466 const std::string& tn)
2467{
2468 error ("operator %s: type conversion for '%s' failed",
2469 op.c_str (), tn.c_str ());
2470}
2471
2472OCTAVE_NORETURN static void
2473err_unary_op (const std::string& on, const std::string& tn)
2474{
2475 error ("unary operator '%s' not implemented for '%s' operands",
2476 on.c_str (), tn.c_str ());
2477}
2478
2481{
2482 if (op == op_incr || op == op_decr)
2483 {
2484 // We want the error just here, because in the other branch this should
2485 // not happen, and if it did anyway (internal error), the message would
2486 // be confusing.
2487 if (is_undefined ())
2488 {
2489 std::string op_str = unary_op_as_string (op);
2490 error ("in x%s or %sx, x must be defined first",
2491 op_str.c_str (), op_str.c_str ());
2492 return *this;
2493 }
2494
2495 // Genuine.
2496 int t = type_id ();
2497
2498 octave::type_info& ti = octave::__get_type_info__ ("non_const_unary_op");
2499
2501 = ti.lookup_non_const_unary_op (op, t);
2502
2503 if (f)
2504 {
2505 make_unique ();
2506
2507 f (*m_rep);
2508 }
2509 else
2510 {
2512
2513 if (! cf)
2514 err_unary_op (octave_value::unary_op_as_string (op), type_name ());
2515
2516 octave_base_value *tmp = cf (*m_rep);
2517
2518 if (! tmp)
2519 err_unary_op_conversion_failed
2521
2522 octave_base_value *old_rep = m_rep;
2523 m_rep = tmp;
2524
2525 t = type_id ();
2526
2527 f = ti.lookup_non_const_unary_op (op, t);
2528
2529 if (f)
2530 {
2531 f (*m_rep);
2532
2533 if (old_rep && --old_rep->count == 0)
2534 delete old_rep;
2535 }
2536 else
2537 {
2538 if (old_rep)
2539 {
2540 if (--m_rep->count == 0)
2541 delete m_rep;
2542
2543 m_rep = old_rep;
2544 }
2545
2546 err_unary_op (octave_value::unary_op_as_string (op),
2547 type_name ());
2548 }
2549 }
2550 }
2551 else
2552 {
2553 // Non-genuine.
2554 int t = type_id ();
2555
2557
2558 // Only attempt to operate in-place if this variable is unshared.
2559 if (m_rep->count == 1)
2560 {
2561 octave::type_info& ti
2562 = octave::__get_type_info__ ("non_const_unary_op");
2563
2564 f = ti.lookup_non_const_unary_op (op, t);
2565 }
2566
2567 if (f)
2568 f (*m_rep);
2569 else
2570 *this = octave::unary_op (op, *this);
2571 }
2572
2573 return *this;
2574}
2575
2577octave_value::non_const_unary_op (unary_op op, const std::string& type,
2578 const std::list<octave_value_list>& idx)
2579{
2580 if (idx.empty ())
2581 non_const_unary_op (op);
2582 else
2583 {
2584 // FIXME: only do the following stuff if we can't find a
2585 // specific function to call to handle the op= operation for the
2586 // types we have.
2587
2588 assign_op assop = unary_op_to_assign_op (op);
2589
2590 assign (assop, type, idx, 1.0);
2591 }
2592
2593 return *this;
2594}
2595
2598{
2599 switch (op)
2600 {
2601 case op_incr:
2602 return op_add_eq;
2603
2604 case op_decr:
2605 return op_sub_eq;
2606
2607 default:
2608 {
2609 std::string on = unary_op_as_string (op);
2610 error ("operator %s: no assign operator found", on.c_str ());
2611 }
2612 }
2613}
2614
2617{
2618 switch (op)
2619 {
2620 case op_add_eq:
2621 return op_add;
2622
2623 case op_sub_eq:
2624 return op_sub;
2625
2626 case op_mul_eq:
2627 return op_mul;
2628
2629 case op_div_eq:
2630 return op_div;
2631
2632 case op_ldiv_eq:
2633 return op_ldiv;
2634
2635 case op_pow_eq:
2636 return op_pow;
2637
2638 case op_el_mul_eq:
2639 return op_el_mul;
2640
2641 case op_el_div_eq:
2642 return op_el_div;
2643
2644 case op_el_ldiv_eq:
2645 return op_el_ldiv;
2646
2647 case op_el_pow_eq:
2648 return op_el_pow;
2649
2650 case op_el_and_eq:
2651 return op_el_and;
2652
2653 case op_el_or_eq:
2654 return op_el_or;
2655
2656 default:
2657 {
2658 std::string on = assign_op_as_string (op);
2659 error ("operator %s: no binary operator found", on.c_str ());
2660 }
2661 }
2662}
2663
2665octave_value::empty_conv (const std::string& type, const octave_value& rhs)
2666{
2667 if (type.length () > 0)
2668 {
2669 switch (type[0])
2670 {
2671 case '(':
2672 if (type.length () > 1 && type[1] == '.')
2673 return octave_map ();
2674 else
2675 return octave_value (rhs.empty_clone ());
2676
2677 case '{':
2678 return Cell ();
2679
2680 case '.':
2681 return octave_scalar_map ();
2682
2683 default:
2685 }
2686 }
2687 else
2688 return octave_value (rhs.empty_clone ());
2689}
2690
2691OCTAVE_NAMESPACE_BEGIN
2692
2693 OCTAVE_NORETURN static void
2694 err_binary_op (const std::string& on, const std::string& tn1,
2695 const std::string& tn2)
2696 {
2697 error ("binary operator '%s' not implemented for '%s' by '%s' operations",
2698 on.c_str (), tn1.c_str (), tn2.c_str ());
2699 }
2700
2701 OCTAVE_NORETURN static void
2702 err_binary_op_conv (const std::string& on)
2703 {
2704 error ("type conversion failed for binary operator '%s'", on.c_str ());
2705 }
2706
2709 const octave_value& v1, const octave_value& v2)
2710 {
2711 octave_value retval;
2712
2713 int t1 = v1.type_id ();
2714 int t2 = v2.type_id ();
2715
2716 if (t1 == octave_class::static_type_id ()
2720 {
2722
2723 if (! f)
2724 err_binary_op (octave_value::binary_op_as_string (op),
2725 v1.class_name (), v2.class_name ());
2726
2727 retval = f (v1, v2);
2728 }
2729 else
2730 {
2731 // FIXME: we need to handle overloading operators for built-in
2732 // classes (double, char, int8, etc.)
2733
2735 = ti.lookup_binary_op (op, t1, t2);
2736
2737 if (f)
2738 retval = f (v1.get_rep (), v2.get_rep ());
2739 else
2740 {
2741 octave_value tv1;
2744
2745 octave_value tv2;
2748
2749 // Try biased (one-sided) conversions first.
2750 if (cf2.type_id () >= 0
2751 && ti.lookup_binary_op (op, t1, cf2.type_id ()))
2752 cf1 = nullptr;
2753 else if (cf1.type_id () >= 0
2754 && ti.lookup_binary_op (op, cf1.type_id (), t2))
2755 cf2 = nullptr;
2756
2757 if (cf1)
2758 {
2759 octave_base_value *tmp = cf1 (v1.get_rep ());
2760
2761 if (! tmp)
2762 err_binary_op_conv (octave_value::binary_op_as_string (op));
2763
2764 tv1 = octave_value (tmp);
2765 t1 = tv1.type_id ();
2766 }
2767 else
2768 tv1 = v1;
2769
2770 if (cf2)
2771 {
2772 octave_base_value *tmp = cf2 (v2.get_rep ());
2773
2774 if (! tmp)
2775 err_binary_op_conv (octave_value::binary_op_as_string (op));
2776
2777 tv2 = octave_value (tmp);
2778 t2 = tv2.type_id ();
2779 }
2780 else
2781 tv2 = v2;
2782
2783 if (cf1 || cf2)
2784 {
2785 retval = binary_op (op, tv1, tv2);
2786 }
2787 else
2788 {
2789 //demote double -> single and try again
2790 cf1 = tv1.numeric_demotion_function ();
2791
2792 cf2 = tv2.numeric_demotion_function ();
2793
2794 // Try biased (one-sided) conversions first.
2795 if (cf2.type_id () >= 0
2796 && ti.lookup_binary_op (op, t1, cf2.type_id ()))
2797 cf1 = nullptr;
2798 else if (cf1.type_id () >= 0
2799 && ti.lookup_binary_op (op, cf1.type_id (), t2))
2800 cf2 = nullptr;
2801
2802 if (cf1)
2803 {
2804 octave_base_value *tmp = cf1 (tv1.get_rep ());
2805
2806 if (! tmp)
2807 err_binary_op_conv (octave_value::binary_op_as_string (op));
2808
2809 tv1 = octave_value (tmp);
2810 t1 = tv1.type_id ();
2811 }
2812
2813 if (cf2)
2814 {
2815 octave_base_value *tmp = cf2 (tv2.get_rep ());
2816
2817 if (! tmp)
2818 err_binary_op_conv (octave_value::binary_op_as_string (op));
2819
2820 tv2 = octave_value (tmp);
2821 t2 = tv2.type_id ();
2822 }
2823
2824 if (! cf1 && ! cf2)
2825 err_binary_op (octave_value::binary_op_as_string (op),
2826 v1.type_name (), v2.type_name ());
2827
2828 f = ti.lookup_binary_op (op, t1, t2);
2829
2830 if (! f)
2831 err_binary_op (octave_value::binary_op_as_string (op),
2832 v1.type_name (), v2.type_name ());
2833
2834 retval = f (tv1.get_rep (), tv2.get_rep ());
2835 }
2836 }
2837 }
2838
2839 return retval;
2840 }
2841
2844 const octave_value& v2)
2845 {
2846 type_info& ti = __get_type_info__ ("binary_op");
2847
2848 return binary_op (ti, op, v1, v2);
2849 }
2850
2851 static octave_value
2852 decompose_binary_op (type_info& ti, octave_value::compound_binary_op op,
2853 const octave_value& v1, const octave_value& v2)
2854 {
2855 switch (op)
2856 {
2860
2862 return binary_op (ti, octave_value::op_mul,
2864
2866 return binary_op (ti, octave_value::op_mul,
2868
2870 return binary_op (ti, octave_value::op_mul,
2872
2874 return binary_op (ti, octave_value::op_ldiv,
2876
2878 return binary_op (ti, octave_value::op_ldiv,
2880
2884
2888
2892
2896
2897 default:
2898 error ("invalid compound operator");
2899 }
2900 }
2901
2904 const octave_value& v1, const octave_value& v2)
2905 {
2906 octave_value retval;
2907
2908 int t1 = v1.type_id ();
2909 int t2 = v2.type_id ();
2910
2911 if (t1 == octave_class::static_type_id ()
2915 {
2917
2918 if (f)
2919 retval = f (v1, v2);
2920 else
2921 retval = decompose_binary_op (ti, op, v1, v2);
2922 }
2923 else
2924 {
2926
2927 if (f)
2928 retval = f (v1.get_rep (), v2.get_rep ());
2929 else
2930 retval = decompose_binary_op (ti, op, v1, v2);
2931 }
2932
2933 return retval;
2934 }
2935
2938 const octave_value& v1, const octave_value& v2)
2939 {
2940 type_info& ti = __get_type_info__ ("binary_op");
2941
2942 return binary_op (ti, op, v1, v2);
2943 }
2944
2945 OCTAVE_NORETURN static void
2946 err_cat_op (const std::string& tn1, const std::string& tn2)
2947 {
2948 error ("concatenation operator not implemented for '%s' by '%s' operations",
2949 tn1.c_str (), tn2.c_str ());
2950 }
2951
2952 OCTAVE_NORETURN static void
2953 err_cat_op_conv (void)
2954 {
2955 error ("type conversion failed for concatenation operator");
2956 }
2957
2959 cat_op (type_info& ti, const octave_value& v1,
2961 {
2962 octave_value retval;
2963
2964 // Can't rapid return for concatenation with an empty object here as
2965 // something like cat(1,[],single([]) must return the correct type.
2966
2967 int t1 = v1.type_id ();
2968 int t2 = v2.type_id ();
2969
2971
2972 if (f)
2973 retval = f (v1.get_rep (), v2.get_rep (), ra_idx);
2974 else
2975 {
2976 octave_value tv1;
2978
2979 octave_value tv2;
2981
2982 // Try biased (one-sided) conversions first.
2983 if (cf2.type_id () >= 0 && ti.lookup_cat_op (t1, cf2.type_id ()))
2984 cf1 = nullptr;
2985 else if (cf1.type_id () >= 0 && ti.lookup_cat_op (cf1.type_id (), t2))
2986 cf2 = nullptr;
2987
2988 if (cf1)
2989 {
2990 octave_base_value *tmp = cf1 (v1.get_rep ());
2991
2992 if (! tmp)
2993 err_cat_op_conv ();
2994
2995 tv1 = octave_value (tmp);
2996 t1 = tv1.type_id ();
2997 }
2998 else
2999 tv1 = v1;
3000
3001 if (cf2)
3002 {
3003 octave_base_value *tmp = cf2 (v2.get_rep ());
3004
3005 if (! tmp)
3006 err_cat_op_conv ();
3007
3008 tv2 = octave_value (tmp);
3009 t2 = tv2.type_id ();
3010 }
3011 else
3012 tv2 = v2;
3013
3014 if (! cf1 && ! cf2)
3015 err_cat_op (v1.type_name (), v2.type_name ());
3016
3017 retval = cat_op (ti, tv1, tv2, ra_idx);
3018 }
3019
3020 return retval;
3021 }
3022
3024 cat_op (const octave_value& v1, const octave_value& v2,
3026 {
3027 type_info& ti = __get_type_info__ ("cat_op");
3028
3029 return cat_op (ti, v1, v2, ra_idx);
3030 }
3031
3032 // Unless the colon operator is used with a class or classdef object,
3033 // then all arguments must be the same type or mixed with double
3034 // values.
3035
3036 static builtin_type_t
3037 get_colon_op_type (builtin_type_t op1_type, builtin_type_t op2_type)
3038 {
3039 if (op1_type == op2_type)
3040 return op1_type;
3041
3042 if (op1_type == btyp_double)
3043 return op2_type;
3044
3045 if (op2_type == btyp_double)
3046 return op1_type;
3047
3048 return btyp_unknown;
3049 }
3050
3051 static builtin_type_t
3052 get_colon_op_type (const octave_value& base, const octave_value& increment,
3053 const octave_value& limit)
3054 {
3055 builtin_type_t typ
3056 = get_colon_op_type (base.builtin_type (), increment.builtin_type ());
3057
3058 if (typ == btyp_unknown)
3059 return typ;
3060
3061 return get_colon_op_type (typ, limit.builtin_type ());
3062 }
3063
3064 // This check depends on the type of VAL either being the expected
3065 // integer type or a double value.
3066
3067 template <typename T>
3068 static void
3069 check_colon_operand (const octave_value& val, const char *op_str)
3070 {
3071 if (! val.is_double_type ())
3072 return;
3073
3074 double dval = val.double_value ();
3075 double intpart;
3076 static const double out_of_range_top
3077 = static_cast<double> (std::numeric_limits<typename T::val_type>::max ())
3078 + 1.;
3079
3080 if (dval >= out_of_range_top
3082 || std::modf (dval, &intpart) != 0.0)
3083 error ("colon operator %s invalid (not an integer or out of range for given integer type)", op_str);
3084 }
3085
3086 // Return the difference between two unsigned integers as an unsigned
3087 // integer of the same type.
3088
3089 template <typename UT,
3090 typename std::enable_if<(std::is_integral<UT>::value
3091 && std::is_unsigned<UT>::value),
3092 bool>::type = true>
3093 UT
3094 integer_difference (UT a, UT b)
3095 {
3096 return a > b ? a - b : b - a;
3097 }
3098
3099 // Return the difference between two signed integers as an unsigned
3100 // integer corresponding to the signed type.
3101
3102 template <typename ST,
3103 typename UT = typename std::make_unsigned<ST>::type,
3104 typename std::enable_if<(std::is_integral<ST>::value
3105 && std::is_signed<ST>::value),
3106 bool>::type = true>
3107 UT
3108 integer_difference (ST a, ST b)
3109 {
3110 // Map to unsigned.
3111 // Idea from https://stackoverflow.com/questions/10589559
3112
3113 static const UT offset
3114 = UT (0) - static_cast<UT> (std::numeric_limits<ST>::min ());
3115
3116 UT au = static_cast<UT> (a) + offset;
3117 UT bu = static_cast<UT> (b) + offset;
3118
3119 return integer_difference (au, bu);
3120 }
3121
3122 // Number of elements in an integer range taking care to avoid
3123 // overflow. Base and limit are of the same type. If they are
3124 // unsigned, then increment is also of the same type. If they are
3125 // signed, then the type of increment is the unsigned type
3126 // corresponding to T. Assumes that the base and limit values are
3127 // consistent with the sign of the original increment (not an empty
3128 // range) so we can calculate numel with the absolute value of the
3129 // increment and the absolute difference between the base and limit
3130 // values.
3131
3132 template <typename T,
3133 typename UT = typename std::make_unsigned<T>::type,
3134 typename std::enable_if<std::is_integral<T>::value,
3135 bool>::type = true>
3137 range_numel_aux (T base, UT unsigned_increment, T limit)
3138 {
3139 // Adding one to DIFF/INCREMENT may overflow, so check whether it is
3140 // out of range before adding.
3141
3142 UT nel_m1 = integer_difference (limit, base) / unsigned_increment;
3143
3144 // FIXME: fix error message.
3146 error ("too many elements for range!");
3147
3148 return static_cast<octave_idx_type> (nel_m1) + 1;
3149 }
3150
3151 // Convert signed range increment to unsigned.
3152
3153 template <typename ST,
3154 typename UT = typename std::make_unsigned<ST>::type,
3155 typename std::enable_if<(std::is_integral<ST>::value
3156 && std::is_signed<ST>::value),
3157 bool>::type = true>
3158 UT
3159 range_increment (ST increment)
3160 {
3161 return (increment < 0
3162 ? UT (0) - static_cast<UT> (increment)
3163 : static_cast<UT> (increment));
3164 }
3165
3166 // "Convert" unsigned range increment to unsigned. A no-op, but
3167 // needed to provide a consistent interface for other template
3168 // functions.
3169
3170 template <typename T,
3171 typename UT = typename std::make_unsigned<T>::type,
3172 typename std::enable_if<(std::is_integral<UT>::value
3173 && std::is_unsigned<UT>::value),
3174 bool>::type = true>
3175 UT
3176 range_increment (UT increment)
3177 {
3178 return increment;
3179 }
3180
3181 // Convert double range increment to unsigned. Enable by return type.
3182
3183 template <typename T,
3184 typename UT = typename std::make_unsigned<T>::type>
3185 typename std::enable_if<(std::is_integral<UT>::value
3186 && std::is_unsigned<UT>::value), UT>::type
3187 range_increment (double increment)
3188 {
3189 double abs_increment = std::abs (increment);
3190
3191 return static_cast<UT> (abs_increment);
3192 }
3193
3194 // Number of elements in an integer range base:increment:limit. Base,
3195 // increment, and limit are of the same signed type.
3196
3197 template <typename ST,
3198 typename std::enable_if<(std::is_integral<ST>::value
3199 && std::is_signed<ST>::value),
3200 bool>::type = true>
3202 range_numel (ST base, ST increment, ST limit)
3203 {
3204 typedef typename std::make_unsigned<ST>::type UT;
3205
3206 if (increment == 0
3207 || (increment > 0 && base > limit)
3208 || (increment < 0 && base < limit))
3209 return 0;
3210
3211 UT unsigned_increment = range_increment<ST> (increment);
3212
3213 return range_numel_aux (base, unsigned_increment, limit);
3214 }
3215
3216 // Number of elements in an integer range base:increment:limit. Base,
3217 // increment, and limit are unsigned and of the same type.
3218
3219 template <typename UT,
3220 typename std::enable_if<(std::is_integral<UT>::value
3221 && std::is_unsigned<UT>::value),
3222 bool>::type = true>
3224 range_numel (UT base, UT increment, UT limit)
3225 {
3226 // Unsigned, INCREMENT is always >= 0.
3227 if (increment == 0 || base > limit)
3228 return 0;
3229
3230 return range_numel_aux (base, increment, limit);
3231 }
3232
3233 // Number of elements in an integer range base:increment:limit. Base
3234 // and limit are of the same type and increment is a double value.
3235
3236 template <typename T,
3237 typename UT = typename std::make_unsigned<T>::type,
3238 typename std::enable_if<std::is_integral<T>::value,
3239 bool>::type = true>
3241 range_numel (T base, double increment, T limit)
3242 {
3243 double intpart;
3244 if (math::isnan (increment) || std::modf (increment, &intpart) != 0.0)
3245 error ("colon operator increment invalid (not an integer)");
3246
3247 if (increment == 0
3248 || (increment > 0 && base > limit)
3249 || (increment < 0 && base < limit))
3250 return 0;
3251
3252 static const double out_of_range_top
3253 = static_cast<double> (std::numeric_limits<UT>::max ()) + 1.;
3254
3255 double abs_increment = std::abs (increment);
3256
3257 // Technically, this condition should be
3258 // `abs_increment > std::numeric_limits<UT>::max ()`.
3259 // But intmax('uint64') is not representable exactly as floating point
3260 // number. Instead, it "rounds" up by 1 to 2^64. To account for
3261 // this, use the following expression which works for all unsigned
3262 // integer types.
3263 if (abs_increment >= out_of_range_top)
3264 return 1;
3265
3266 UT unsigned_increment = range_increment<T> (increment);
3267
3268 return range_numel_aux (base, unsigned_increment, limit);
3269 }
3270
3271 // Make a range from integer values. Increment may be integer or double.
3272
3273 template <typename T,
3274 typename IT,
3275 typename std::enable_if<(std::is_integral<T>::value
3276 && std::is_arithmetic<IT>::value),
3277 bool>::type = true>
3279 make_int_range (T base, IT increment, T limit)
3280 {
3281 octave_idx_type nel = range_numel (base, increment, limit);
3282
3283 // For now, we create arrays instead of range<T> for all types
3284 // except double.
3285
3286 Array<octave_int<T>> result (dim_vector (1, nel));
3287
3288 if (nel > 0)
3289 {
3290 typedef typename std::make_unsigned<T>::type UT;
3291
3292 UT unsigned_increment = range_increment<T> (increment);
3293
3294 T val = base;
3295 result.xelem (0) = val;
3296
3297 if (limit > base)
3298 {
3299 for (octave_idx_type i = 1; i < nel; i++)
3300 {
3301 val += unsigned_increment;
3302 result.xelem (i) = val;
3303 }
3304 }
3305 else
3306 {
3307 for (octave_idx_type i = 1; i < nel; i++)
3308 {
3309 val -= unsigned_increment;
3310 result.xelem (i) = val;
3311 }
3312 }
3313 }
3314
3315 return octave_value (result);
3316 }
3317
3318 // Make a range from floating point values.
3319
3320 // FIXME: Try again to define memory efficient range classes for
3321 // integer and floating point values? Maybe with the templates
3322 // defined in this file we could do that in a reasonable way?
3323 // Regardless of that, it might be good to provide special treatment
3324 // of colon expressions in FOR loops so that we can eliminate the
3325 // "is_for_cmd_expr / force_range" flag from the parser and the
3326 // octave_value constructors for range objects.
3327
3328 // NOTE: We define this function separately for float and double so
3329 // that we can avoid having to instantiate ov_range<float>. We DO
3330 // instantiate range<float> but only so we can take advantage of the
3331 // range<T> class to generate the corresponding array of float values
3332 // and not have to duplicate that code here.
3333
3334 template <typename T,
3335 typename std::enable_if<std::is_same<T, double>::value,
3336 bool>::type = true>
3338 make_float_range (T base, T increment, T limit, bool is_for_cmd_expr)
3339 {
3340 if (math::isnan (base)
3341 || math::isnan (increment)
3342 || math::isnan (limit))
3344
3345 if (increment == 0
3346 || (increment > 0 && base > limit)
3347 || (increment < 0 && base < limit))
3348 return octave_value (Array<T> (dim_vector (1, 0)));
3349
3350 // At this point, we know that the base and limit values are
3351 // consistent with the sign of the increment (not an empty range).
3352
3353 range<T> r (base, increment, limit);
3354
3355 if (! is_for_cmd_expr && ! r.is_storable ())
3356 error ("range with infinite number of elements cannot be stored");
3357
3358 return octave_value (r, is_for_cmd_expr);
3359 }
3360
3361 template <typename T,
3362 typename std::enable_if<std::is_same<T, float>::value,
3363 bool>::type = true>
3365 make_float_range (T base, T increment, T limit, bool is_for_cmd_expr)
3366 {
3367 if (math::isnan (base)
3368 || math::isnan (increment)
3369 || math::isnan (limit))
3371
3372 if (increment == 0
3373 || (increment > 0 && base > limit)
3374 || (increment < 0 && base < limit))
3375 return octave_value (Array<T> (dim_vector (1, 0)));
3376
3377 // At this point, we know that the base and limit values are
3378 // consistent with the sign of the increment (not an empty range).
3379
3380 range<T> r (base, increment, limit);
3381
3382 if (! is_for_cmd_expr && ! r.is_storable ())
3383 error ("range with infinite number of elements cannot be stored");
3384
3385 return octave_value (r.array_value ());
3386 }
3387
3388 template <typename T,
3389 typename std::enable_if<(std::is_same<T, octave_int8>::value
3390 || std::is_same<T, octave_uint8>::value
3391 || std::is_same<T, octave_int16>::value
3392 || std::is_same<T, octave_uint16>::value
3393 || std::is_same<T, octave_int32>::value
3394 || std::is_same<T, octave_uint32>::value
3395 || std::is_same<T, octave_int64>::value
3396 || std::is_same<T, octave_uint64>::value),
3397 bool>::type = true>
3399 make_int_range (const octave_value& base, const octave_value& increment,
3400 const octave_value& limit)
3401 {
3402 if (base.isempty () || increment.isempty () || limit.isempty ())
3403 return octave_value (Array<T> (dim_vector (1, 0)));
3404
3405 check_colon_operand<T> (base, "lower bound");
3406 check_colon_operand<T> (limit, "upper bound");
3407
3408 typename T::val_type base_val = octave_value_extract<T> (base).value ();
3409 typename T::val_type limit_val = octave_value_extract<T> (limit).value ();
3410
3411 if (increment.is_double_type ())
3412 {
3413 double increment_val = increment.double_value ();
3414
3415 return make_int_range (base_val, increment_val, limit_val);
3416 }
3417
3418 check_colon_operand<T> (increment, "increment");
3419
3420 typename T::val_type increment_val
3421 = octave_value_extract<T> (increment).value ();
3422
3423 return make_int_range (base_val, increment_val, limit_val);
3424 }
3425
3426 template <typename T,
3427 typename std::enable_if<std::is_floating_point<T>::value,
3428 bool>::type = true>
3430 make_float_range (const octave_value& base, const octave_value& increment,
3431 const octave_value& limit, bool is_for_cmd_expr)
3432 {
3433 if (base.isempty () || increment.isempty () || limit.isempty ())
3434 return octave_value (Array<T> (dim_vector (1, 0)));
3435
3436 T base_val = octave_value_extract<T> (base);
3437 T increment_val = octave_value_extract<T> (increment);
3438 T limit_val = octave_value_extract<T> (limit);
3439
3440 return make_float_range (base_val, increment_val, limit_val,
3441 is_for_cmd_expr);
3442 }
3443
3444
3446 make_char_range (const octave_value& base, const octave_value& increment,
3447 const octave_value& limit)
3448 {
3449 octave_value retval;
3450
3451 bool dq_str = (base.is_dq_string () || increment.is_dq_string ()
3452 || limit.is_dq_string ());
3453
3454 char type = dq_str ? '"' : '\'';
3455
3456 if (base.isempty () || increment.isempty () || limit.isempty ())
3457 retval = octave_value ("", type);
3458 else
3459 {
3460 Matrix mtx_base = base.matrix_value (true);
3461 Matrix mtx_increment = increment.matrix_value (true);
3462 Matrix mtx_limit = limit.matrix_value (true);
3463
3464 range<double> tmp (mtx_base(0), mtx_increment(0), mtx_limit(0));
3465
3466 retval = octave_value (tmp);
3467 }
3468
3469 return retval.convert_to_str (false, true, type);
3470 }
3471
3473 colon_op (const octave_value& base, const octave_value& increment_arg,
3474 const octave_value& limit, bool is_for_cmd_expr)
3475 {
3476 if (base.isobject () || increment_arg.isobject () || limit.isobject ())
3477 {
3478 octave_value_list tmp1;
3479
3480 if (increment_arg.is_defined ())
3481 {
3482 tmp1(2) = limit;
3483 tmp1(1) = increment_arg;
3484 tmp1(0) = base;
3485 }
3486 else
3487 {
3488 tmp1(1) = limit;
3489 tmp1(0) = base;
3490 }
3491
3492 interpreter& interp = __get_interpreter__ ("colon_op");
3493
3494 symbol_table& symtab = interp.get_symbol_table ();
3495
3496 octave_value fcn = symtab.find_function ("colon", tmp1);
3497
3498 if (fcn.is_defined ())
3499 {
3500 octave_value_list tmp2 = interp.feval (fcn, tmp1, 1);
3501
3502 return tmp2(0);
3503 }
3504 }
3505
3506 octave_value increment
3507 = increment_arg.is_defined () ? increment_arg : octave_value (1.0);
3508
3509 if (base.numel () > 1 || limit.numel () > 1 || increment.numel () > 1)
3510 warning_with_id ("Octave:colon-nonscalar-argument",
3511 "colon arguments should be scalars");
3512
3513 if (base.iscomplex () || limit.iscomplex () || increment.iscomplex ())
3514 warning_with_id ("Octave:colon-complex-argument",
3515 "imaginary part of complex colon arguments is ignored");
3516
3517 // FIXME: is there a better way to do this job, maybe using type traits?
3518
3519 builtin_type_t type_id = get_colon_op_type (base, increment, limit);
3520
3521 // For compatibility with Matlab, don't allow the range used in
3522 // a FOR loop expression to be converted to a Matrix.
3523
3524 // For now, these functions create arrays instead of range<T> for
3525 // all types except double.
3526
3527 switch (type_id)
3528 {
3529 case btyp_double:
3530 case btyp_complex:
3531 return make_float_range<double> (base, increment, limit, is_for_cmd_expr);
3532
3533 case btyp_float:
3534 case btyp_float_complex:
3535 return make_float_range<float> (base, increment, limit, is_for_cmd_expr);
3536
3537 case btyp_int8:
3538 return make_int_range<octave_int8> (base, increment, limit);
3539
3540 case btyp_int16:
3541 return make_int_range<octave_int16> (base, increment, limit);
3542
3543 case btyp_int32:
3544 return make_int_range<octave_int32> (base, increment, limit);
3545
3546 case btyp_int64:
3547 return make_int_range<octave_int64> (base, increment, limit);
3548
3549 case btyp_uint8:
3550 return make_int_range<octave_uint8> (base, increment, limit);
3551
3552 case btyp_uint16:
3553 return make_int_range<octave_uint16> (base, increment, limit);
3554
3555 case btyp_uint32:
3556 return make_int_range<octave_uint32> (base, increment, limit);
3557
3558 case btyp_uint64:
3559 return make_int_range<octave_uint64> (base, increment, limit);
3560
3561 case btyp_char:
3562 return make_char_range (base, increment, limit);
3563
3564 case btyp_unknown:
3565 error ("incompatible types found in range expression");
3566
3567 default:
3568 error ("invalid types found in range expression");
3569 }
3570
3571 return octave_value ();
3572 }
3573
3574 OCTAVE_NORETURN static void
3575 err_unary_op_conv (const std::string& on)
3576 {
3577 error ("type conversion failed for unary operator '%s'", on.c_str ());
3578 }
3579
3582 const octave_value& v)
3583 {
3584 octave_value retval;
3585
3586 int t = v.type_id ();
3587
3590 {
3592
3593 if (! f)
3594 err_unary_op (octave_value::unary_op_as_string (op), v.class_name ());
3595
3596 retval = f (v);
3597 }
3598 else
3599 {
3600 // FIXME: we need to handle overloading operators for built-in
3601 // classes (double, char, int8, etc.)
3602
3604
3605 if (f)
3606 retval = f (v.get_rep ());
3607 else
3608 {
3609 octave_value tv;
3612
3613 if (! cf)
3614 err_unary_op (octave_value::unary_op_as_string (op),
3615 v.type_name ());
3616
3617 octave_base_value *tmp = cf (v.get_rep ());
3618
3619 if (! tmp)
3620 err_unary_op_conv (octave_value::unary_op_as_string (op));
3621
3622 tv = octave_value (tmp);
3623 retval = unary_op (op, tv);
3624 }
3625 }
3626
3627 return retval;
3628 }
3629
3632 {
3633 type_info& ti = __get_type_info__ ("unary_op");
3634
3635 return unary_op (ti, op, v);
3636 }
3637
3638OCTAVE_NAMESPACE_END
3639
3640void
3641install_types (octave::type_info& ti)
3642{
3651
3652 // Legacy range type, preserved to allow loading "constant" ranges
3653 // from data files.
3655
3657
3658 // For now, disable all but ov_range<double>.
3659
3660#if 0
3661
3671
3672#endif
3673
3721}
3722
3723OCTAVE_NAMESPACE_BEGIN
3724
3725DEFUN (sizeof, args, ,
3726 doc: /* -*- texinfo -*-
3727@deftypefn {} {} sizeof (@var{val})
3728Return the size of @var{val} in bytes.
3729@seealso{whos}
3730@end deftypefn */)
3731{
3732 if (args.length () != 1)
3733 print_usage ();
3734
3735 return ovl (args(0).byte_size ());
3736}
3737
3738/*
3739%!assert (sizeof (uint64 (ones (3))), 72)
3740%!assert (sizeof (double (zeros (2,4))), 64)
3741%!assert (sizeof ({"foo", "bar", "baaz"}), 10)
3742*/
3743
3744static void
3745decode_subscripts (const char *name, const octave_value& arg,
3746 std::string& type_string,
3747 std::list<octave_value_list>& idx)
3748{
3749 const octave_map m = arg.xmap_value ("%s: second argument must be a structure with fields 'type' and 'subs'", name);
3750
3751 if (m.nfields () != 2 || ! m.contains ("type") || ! m.contains ("subs"))
3752 error ("%s: second argument must be a structure with fields 'type' and 'subs'",
3753 name);
3754
3755 octave_idx_type nel = m.numel ();
3756
3757 type_string = std::string (nel, '\0');
3758 idx = std::list<octave_value_list> ();
3759
3760 if (nel == 0)
3761 return;
3762
3763 const Cell type = m.contents ("type");
3764 const Cell subs = m.contents ("subs");
3765
3766 for (int k = 0; k < nel; k++)
3767 {
3768 std::string item = type(k).xstring_value ("%s: type(%d) must be a string", name, k+1);
3769
3770 if (item == "{}")
3771 type_string[k] = '{';
3772 else if (item == "()")
3773 type_string[k] = '(';
3774 else if (item == ".")
3775 type_string[k] = '.';
3776 else
3777 error ("%s: invalid indexing type '%s'", name, item.c_str ());
3778
3779 octave_value_list idx_item;
3780
3781 if (subs(k).is_string ())
3782 idx_item(0) = subs(k);
3783 else if (subs(k).iscell ())
3784 {
3785 Cell subs_cell = subs(k).cell_value ();
3786
3787 for (int n = 0; n < subs_cell.numel (); n++)
3788 {
3789 if (subs_cell(n).is_string ()
3790 && subs_cell(n).string_value () == ":")
3792 else
3793 idx_item(n) = subs_cell(n);
3794 }
3795 }
3796 else
3797 error ("%s: subs(%d) must be a string or cell array", name, k+1);
3798
3799 idx.push_back (idx_item);
3800 }
3801}
3802
3803DEFUN (subsref, args, nargout,
3804 doc: /* -*- texinfo -*-
3805@deftypefn {} {} subsref (@var{val}, @var{idx})
3806Perform the subscripted element selection operation on @var{val} according
3807to the subscript specified by @var{idx}.
3808
3809The subscript @var{idx} must be a structure array with fields @samp{type}
3810and @samp{subs}. Valid values for @samp{type} are @qcode{"()"},
3811@qcode{"@{@}"}, and @qcode{"."}. The @samp{subs} field may be either
3812@qcode{":"} or a cell array of index values.
3813
3814The following example shows how to extract the first two columns of a matrix
3815
3816@example
3817@group
3818val = magic (3)
3819 @result{} val = [ 8 1 6
3820 3 5 7
3821 4 9 2 ]
3822idx.type = "()";
3823idx.subs = @{":", 1:2@};
3824subsref (val, idx)
3825 @result{} [ 8 1
3826 3 5
3827 4 9 ]
3828@end group
3829@end example
3830
3831@noindent
3832Note that this is the same as writing @code{val(:, 1:2)}.
3833
3834If @var{idx} is an empty structure array with fields @samp{type} and
3835@samp{subs}, return @var{val}.
3836@seealso{subsasgn, substruct}
3837@end deftypefn */)
3838{
3839 if (args.length () != 2)
3840 print_usage ();
3841
3842 std::string type;
3843 std::list<octave_value_list> idx;
3844
3845 decode_subscripts ("subsref", args(1), type, idx);
3846
3847 octave_value arg0 = args(0);
3848
3849 if (type.empty ())
3850 return ovl (arg0);
3851 else
3852 return arg0.subsref (type, idx, nargout);
3853}
3854
3855DEFUN (subsasgn, args, ,
3856 doc: /* -*- texinfo -*-
3857@deftypefn {} {} subsasgn (@var{val}, @var{idx}, @var{rhs})
3858Perform the subscripted assignment operation according to the subscript
3859specified by @var{idx}.
3860
3861The subscript @var{idx} must be a structure array with fields @samp{type}
3862and @samp{subs}. Valid values for @samp{type} are @qcode{"()"},
3863@qcode{"@{@}"}, and @qcode{"."}. The @samp{subs} field may be either
3864@qcode{":"} or a cell array of index values.
3865
3866The following example shows how to set the two first columns of a 3-by-3
3867matrix to zero.
3868
3869@example
3870@group
3871val = magic (3);
3872idx.type = "()";
3873idx.subs = @{":", 1:2@};
3874subsasgn (val, idx, 0)
3875 @result{} [ 0 0 6
3876 0 0 7
3877 0 0 2 ]
3878@end group
3879@end example
3880
3881Note that this is the same as writing @code{val(:, 1:2) = 0}.
3882
3883If @var{idx} is an empty structure array with fields @samp{type} and
3884@samp{subs}, return @var{rhs}.
3885@seealso{subsref, substruct, optimize_subsasgn_calls}
3886@end deftypefn */)
3887{
3888 if (args.length () != 3)
3889 print_usage ();
3890
3891 std::string type;
3892 std::list<octave_value_list> idx;
3893
3894 decode_subscripts ("subsasgn", args(1), type, idx);
3895
3896 if (type.empty ())
3897 {
3898 // Regularize a null matrix if stored into a variable.
3899 return ovl (args(2).storable_value ());
3900 }
3901 else
3902 {
3903 octave_value arg0 = args(0);
3904 octave_value arg2 = args(2);
3905
3906 arg0.make_unique ();
3907
3908 bool arg2_null = arg2.is_zero_by_zero () && arg2.is_double_type ();
3909
3910 return ovl (arg0.subsasgn (type, idx, (arg2_null
3912 : arg2)));
3913 }
3914}
3915
3916/*
3917%!test
3918%! a = reshape ([1:25], 5,5);
3919%! idx1 = substruct ("()", {3, 3});
3920%! idx2 = substruct ("()", {2:2:5, 2:2:5});
3921%! idx3 = substruct ("()", {":", [1,5]});
3922%! idx4 = struct ("type", {}, "subs", {});
3923%! assert (subsref (a, idx1), 13);
3924%! assert (subsref (a, idx2), [7 17; 9 19]);
3925%! assert (subsref (a, idx3), [1:5; 21:25]');
3926%! assert (subsref (a, idx4), a);
3927%! a = subsasgn (a, idx1, 0);
3928%! a = subsasgn (a, idx2, 0);
3929%! a = subsasgn (a, idx3, 0);
3930%!# a = subsasgn (a, idx4, 0);
3931%! b = [0 6 11 16 0
3932%! 0 0 12 0 0
3933%! 0 8 0 18 0
3934%! 0 0 14 0 0
3935%! 0 10 15 20 0];
3936%! assert (a, b);
3937
3938%!test
3939%! x = 1:10;
3940%! assert (subsasgn (x, substruct ("()", {1}), zeros (0, 0)), 2:10);
3941
3942%!test
3943%! c = num2cell (reshape ([1:25],5,5));
3944%! idx1 = substruct ("{}", {3, 3});
3945%! idx2 = substruct ("()", {2:2:5, 2:2:5});
3946%! idx3 = substruct ("()", {":", [1,5]});
3947%! idx2p = substruct ("{}", {2:2:5, 2:2:5});
3948%! idx3p = substruct ("{}", {":", [1,5]});
3949%! idx4 = struct ("type", {}, "subs", {});
3950%! assert ({ subsref(c, idx1) }, {13});
3951%! assert ({ subsref(c, idx2p) }, {7 9 17 19});
3952%! assert ({ subsref(c, idx3p) }, num2cell ([1:5, 21:25]));
3953%! assert (subsref (c, idx4), c);
3954%! c = subsasgn (c, idx1, 0);
3955%! c = subsasgn (c, idx2, 0);
3956%! c = subsasgn (c, idx3, 0);
3957%!# c = subsasgn (c, idx4, 0);
3958%! d = {0 6 11 16 0
3959%! 0 0 12 0 0
3960%! 0 8 0 18 0
3961%! 0 0 14 0 0
3962%! 0 10 15 20 0};
3963%! assert (c, d);
3964
3965%!test
3966%! s.a = "ohai";
3967%! s.b = "dere";
3968%! s.c = 42;
3969%! idx1 = substruct (".", "a");
3970%! idx2 = substruct (".", "b");
3971%! idx3 = substruct (".", "c");
3972%! idx4 = struct ("type", {}, "subs", {});
3973%! assert (subsref (s, idx1), "ohai");
3974%! assert (subsref (s, idx2), "dere");
3975%! assert (subsref (s, idx3), 42);
3976%! assert (subsref (s, idx4), s);
3977%! s = subsasgn (s, idx1, "Hello");
3978%! s = subsasgn (s, idx2, "There");
3979%! s = subsasgn (s, idx3, 163);
3980%!# s = subsasgn (s, idx4, 163);
3981%! t.a = "Hello";
3982%! t.b = "There";
3983%! t.c = 163;
3984%! assert (s, t);
3985*/
3986
3987DEFUN (is_sq_string, args, ,
3988 doc: /* -*- texinfo -*-
3989@deftypefn {} {} is_sq_string (@var{x})
3990Return true if @var{x} is a single-quoted character string.
3991@seealso{is_dq_string, ischar}
3992@end deftypefn */)
3993{
3994 if (args.length () != 1)
3995 print_usage ();
3996
3997 return ovl (args(0).is_sq_string ());
3998}
3999
4000/*
4001%!assert (is_sq_string ('foo'), true)
4002%!assert (is_sq_string ("foo"), false)
4003%!assert (is_sq_string (1.0), false)
4004%!assert (is_sq_string ({2.0}), false)
4005
4006%!error is_sq_string ()
4007%!error is_sq_string ('foo', 2)
4008*/
4009
4010DEFUN (is_dq_string, args, ,
4011 doc: /* -*- texinfo -*-
4012@deftypefn {} {} is_dq_string (@var{x})
4013Return true if @var{x} is a double-quoted character string.
4014@seealso{is_sq_string, ischar}
4015@end deftypefn */)
4016{
4017 if (args.length () != 1)
4018 print_usage ();
4019
4020 return ovl (args(0).is_dq_string ());
4021}
4022
4023/*
4024%!assert (is_dq_string ("foo"), true)
4025%!assert (is_dq_string ('foo'), false)
4026%!assert (is_dq_string (1.0), false)
4027%!assert (is_dq_string ({2.0}), false)
4028
4029%!error is_dq_string ()
4030%!error is_dq_string ("foo", 2)
4031*/
4032
4033DEFUN (optimize_permutation_matrix, args, nargout,
4034 doc: /* -*- texinfo -*-
4035@deftypefn {} {@var{val} =} optimize_permutation_matrix ()
4036@deftypefnx {} {@var{old_val} =} optimize_permutation_matrix (@var{new_val})
4037@deftypefnx {} {} optimize_permutation_matrix (@var{new_val}, "local")
4038Query or set whether a special space-efficient format is used for storing
4039permutation matrices.
4040
4041The default value is true. If this option is set to false, Octave will store
4042permutation matrices as full matrices.
4043
4044When called from inside a function with the @qcode{"local"} option, the setting
4045is changed locally for the function and any subroutines it calls. The original
4046setting is restored when exiting the function.
4047@seealso{optimize_range, optimize_diagonal_matrix}
4048@end deftypefn */)
4049{
4051 "optimize_permutation_matrix");
4052}
4053
4054/*
4055%!function p = __test_dpm__ (dpm)
4056%! optimize_permutation_matrix (dpm, "local");
4057%! [~, ~, p] = lu ([1,2;3,4]);
4058%!endfunction
4059
4060%!assert (typeinfo (__test_dpm__ (true)), "permutation matrix")
4061%!assert (typeinfo (__test_dpm__ (false)), "matrix")
4062*/
4063
4064DEFUN (optimize_diagonal_matrix, args, nargout,
4065 doc: /* -*- texinfo -*-
4066@deftypefn {} {@var{val} =} optimize_diagonal_matrix ()
4067@deftypefnx {} {@var{old_val} =} optimize_diagonal_matrix (@var{new_val})
4068@deftypefnx {} {} optimize_diagonal_matrix (@var{new_val}, "local")
4069Query or set whether a special space-efficient format is used for storing
4070diagonal matrices.
4071
4072The default value is true. If this option is set to false, Octave will store
4073diagonal matrices as full matrices.
4074
4075When called from inside a function with the @qcode{"local"} option, the setting
4076is changed locally for the function and any subroutines it calls. The original
4077setting is restored when exiting the function.
4078@seealso{optimize_range, optimize_permutation_matrix}
4079@end deftypefn */)
4080{
4081 return set_internal_variable (Voptimize_diagonal_matrix, args, nargout,
4082 "optimize_diagonal_matrix");
4083}
4084
4085/*
4086%!function [x, xi, fx, fxi] = __test_ddm__ (ddm)
4087%! optimize_diagonal_matrix (ddm, "local");
4088%! x = eye (2);
4089%! xi = x*i;
4090%! fx = single (x);
4091%! fxi = single (xi);
4092%!endfunction
4093
4094%!shared x, xi, fx, fxi
4095%! [x, xi, fx, fxi] = __test_ddm__ (true);
4096%!assert (typeinfo (x), "diagonal matrix")
4097%!assert (typeinfo (xi), "complex diagonal matrix")
4098%!assert (typeinfo (fx), "float diagonal matrix")
4099%!assert (typeinfo (fxi), "float complex diagonal matrix")
4100
4101%!shared x, xi, fx, fxi
4102%! [x, xi, fx, fxi] = __test_ddm__ (false);
4103%!assert (typeinfo (x), "matrix")
4104%!assert (typeinfo (xi), "complex matrix")
4105%!assert (typeinfo (fx), "float matrix")
4106%!assert (typeinfo (fxi), "float complex matrix")
4107*/
4108
4109DEFUN (optimize_range, args, nargout,
4110 doc: /* -*- texinfo -*-
4111@deftypefn {} {@var{val} =} optimize_range ()
4112@deftypefnx {} {@var{old_val} =} optimize_range (@var{new_val})
4113@deftypefnx {} {} optimize_range (@var{new_val}, "local")
4114Query or set whether a special space-efficient format is used for storing
4115ranges.
4116
4117The default value is true. If this option is set to false, Octave will store
4118ranges as full matrices.
4119
4120When called from inside a function with the @qcode{"local"} option, the setting
4121is changed locally for the function and any subroutines it calls. The original
4122setting is restored when exiting the function.
4123@seealso{optimize_diagonal_matrix, optimize_permutation_matrix}
4124@end deftypefn */)
4125{
4126 return set_internal_variable (Voptimize_range, args, nargout,
4127 "optimize_range");
4128}
4129
4130/*
4131%!function r = __test_dr__ (dr)
4132%! optimize_range (dr, "local");
4133%! ## Constant folding will produce range for 1:13.
4134%! base = 1;
4135%! limit = 13;
4136%! r = base:limit;
4137%!endfunction
4138
4139%!assert (typeinfo (__test_dr__ (true)), "double_range")
4140%!assert (typeinfo (__test_dr__ (false)), "matrix")
4141*/
4142
4143OCTAVE_NAMESPACE_END
#define NaN
Definition: Faddeeva.cc:261
#define C(a, b)
Definition: Faddeeva.cc:259
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:230
charNDArray min(char d, const charNDArray &m)
Definition: chNDArray.cc:207
T & xelem(octave_idx_type n)
Size of the specified dimension.
Definition: Array.h:504
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:411
const dim_vector & dims(void) const
Return a const-reference so that dims ()(i) works efficiently.
Definition: Array.h:487
T & elem(octave_idx_type n)
Size of the specified dimension.
Definition: Array.h:534
OCTARRAY_API void resize(const dim_vector &dv, const T &rfv)
Size of the specified dimension.
Definition: Array.cc:1010
Array< T, Alloc > reshape(octave_idx_type nr, octave_idx_type nc) const
Size of the specified dimension.
Definition: Array.h:595
Definition: Cell.h:43
Definition: dMatrix.h:42
Definition: Range.h:400
bool ok(void) const
Definition: Range.h:456
OCTAVE_API Matrix matrix_value(void) const
Definition: Range.cc:504
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:94
OCTAVE_API std::string str(char sep='x') const
Definition: dim-vector.cc:68
octave_idx_type numel(int n=0) const
Number of elements that a matrix with this dimensions would have.
Definition: dim-vector.h:335
static dim_vector alloc(int n)
Definition: dim-vector.h:202
octave_idx_type ndims(void) const
Number of dimensions.
Definition: dim-vector.h:257
symbol_table & get_symbol_table(void)
Definition: interpreter.h:296
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.
idx_class_type idx_class(void) const
Definition: idx-vector.h:535
OCTAVE_API void unconvert(idx_class_type &iclass, double &scalar, range< double > &range, Array< double > &array, Array< bool > &mask) const
Definition: idx-vector.cc:1181
virtual bool load_hdf5(octave_hdf5_id loc_id, const char *name)
Definition: ov-base.cc:1017
virtual type_conv_info numeric_conversion_function(void) const
Definition: ov-base.h:281
virtual octave_value subsref(const std::string &type, const std::list< octave_value_list > &idx)
Definition: ov-base.cc:201
octave::refcount< octave_idx_type > count
Definition: ov-base.h:906
virtual octave_base_value * try_narrowing_conversion(void)
Definition: ov-base.h:305
virtual const void * mex_get_data(void) const
Definition: ov-base.h:751
virtual Cell cell_value(void) const
Definition: ov-base.cc:537
virtual octave_scalar_map scalar_map_value(void) const
Definition: ov-base.cc:889
virtual octave_user_script * user_script_value(bool silent=false)
Definition: ov-base.cc:953
virtual bool is_storable(void) const
Definition: ov-base.h:387
virtual octave_map map_value(void) const
Definition: ov-base.cc:883
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
octave_base_value *(* type_conv_fcn)(const octave_base_value &)
Definition: ov-base.h:235
virtual octave_value_list list_value(void) const
Definition: ov-base.cc:980
virtual octave_base_value * empty_clone(void) const
Definition: ov-base.cc:106
virtual int type_id(void) const
Definition: ov-base.h:922
virtual std::string class_name(void) const
Definition: ov-base.h:922
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:455
virtual octave_base_value * clone(void) const
Definition: ov-base.h:266
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 std::string type_name(void) const
Definition: ov-base.h:922
virtual float_display_format get_edit_display_format(void) const
Definition: ov-base.cc:449
virtual octave_value subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
Definition: ov-base.cc:240
virtual octave_user_code * user_code_value(bool silent=false)
Definition: ov-base.cc:962
virtual double double_value(bool=false) const
Definition: ov-base.cc:525
virtual octave_value undef_subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
Definition: ov-base.cc:306
virtual void break_closure_cycles(const std::shared_ptr< octave::stack_frame > &)
Definition: ov-base.h:278
static void register_type(void)
Definition: ov-base.cc:99
virtual octave_function * function_value(bool silent=false)
Definition: ov-base.cc:935
static void register_type(void)
Definition: ov-bool-mat.cc:71
static void register_type(void)
Definition: ov-bool.cc:61
static void register_type(void)
Definition: ov-builtin.cc:43
static void register_type(void)
Definition: ov-cell.cc:145
static void register_type(void)
Definition: ov-str-mat.cc:62
static void register_type(void)
Definition: ov-str-mat.cc:60
static int static_type_id(void)
Definition: ov-class.h:225
static int static_type_id(void)
Definition: ov-classdef.h:155
static void register_type(void)
Definition: ov-cx-diag.cc:44
static void register_type(void)
Definition: ov-cx-mat.cc:71
static void register_type(void)
Definition: ov-complex.cc:66
static void register_type(void)
Definition: ov-cs-list.cc:39
static void register_type(void)
Definition: ov-re-diag.cc:43
static void register_type(void)
Definition: ov-dld-fcn.cc:44
octave_value make_weak_nested_handle(void) const
bool is_weak_anonymous(void) const
static void register_type(void)
bool is_anonymous(void) const
octave_value make_weak_anonymous_handle(void) const
bool is_nested(void) const
bool is_weak_nested(void) const
static void register_type(void)
static void register_type(void)
static void register_type(void)
static void register_type(void)
static void register_type(void)
Definition: ov-float.cc:65
static void register_type(void)
Definition: ov-lazy-idx.cc:36
static void register_type(void)
static void register_type(void)
Definition: ov-colon.cc:38
static void register_type(void)
static void register_type(void)
octave_idx_type nfields(void) const
Definition: oct-map.h:344
const Cell & contents(const_iterator p) const
Definition: oct-map.h:331
octave_idx_type numel(void) const
Definition: oct-map.h:389
bool contains(const std::string &name) const
Definition: oct-map.h:350
static void register_type(void)
Definition: ov-re-mat.cc:90
static const octave_value instance
Definition: ov-null-mat.h:52
static void register_type(void)
Definition: ov-null-mat.cc:35
static void register_type(void)
Definition: ov-null-mat.cc:78
static void register_type(void)
Definition: ov-null-mat.cc:56
static void register_type(void)
Definition: ov-oncleanup.cc:40
static void register_type(void)
Definition: ov-perm.cc:482
static void register_type(void)
Definition: ov-struct.cc:1096
static void register_type(void)
Definition: ov-scalar.cc:68
static void register_type(void)
static void register_type(void)
Definition: ov-cx-sparse.cc:58
static void register_type(void)
Definition: ov-re-sparse.cc:58
static void register_type(void)
Definition: ov-struct.cc:57
static void register_type(void)
Definition: ov-uint64.cc:72
static void register_type(void)
Definition: ov-uint64.cc:79
static void register_type(void)
Definition: ov-usr-fcn.cc:209
void maybe_economize(void)
Definition: ov.h:1393
OCTINTERP_API assign_op unary_op_to_assign_op(unary_op op)
octave_value & operator=(const octave_value &a)
Definition: ov.h:443
octave_idx_type get_count(void) const
Definition: ov.h:475
static OCTINTERP_API std::string unary_op_fcn_name(unary_op)
Definition: ov.cc:159
int32NDArray int32_array_value(void) const
Definition: ov.h:1001
OCTINTERP_API const void * mex_get_data(mxClassID class_id=mxUNKNOWN_CLASS, mxComplexity complexity=mxREAL) const
uint16NDArray uint16_array_value(void) const
Definition: ov.h:1010
static OCTINTERP_API octave_base_value * make_range_rep_deprecated(double base, double inc, double limit)
OCTINTERP_API Array< double > vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
OCTINTERP_API octave_value_list list_value(void) const
octave_value subsref(const std::string &type, const std::list< octave_value_list > &idx)
Definition: ov.h:525
OCTINTERP_API binary_op op_eq_to_binary_op(assign_op op)
static OCTINTERP_API std::string binary_op_as_string(binary_op)
Definition: ov.cc:184
OCTINTERP_API ComplexRowVector complex_row_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
OCTINTERP_API octave_function * function_value(bool silent=false) const
octave_base_value::type_conv_info numeric_conversion_function(void) const
Definition: ov.h:477
int int_value(bool req_int=false, bool frc_str_conv=false) const
Definition: ov.h:857
bool is_uint16_type(void) const
Definition: ov.h:766
builtin_type_t builtin_type(void) const
Definition: ov.h:735
unary_op
Definition: ov.h:77
@ op_hermitian
Definition: ov.h:82
@ op_uminus
Definition: ov.h:80
@ op_not
Definition: ov.h:78
@ op_transpose
Definition: ov.h:81
@ op_uplus
Definition: ov.h:79
@ op_incr
Definition: ov.h:83
@ op_decr
Definition: ov.h:84
int type_id(void) const
Definition: ov.h:1447
OCTINTERP_API bool load_ascii(std::istream &is)
int64_t int64_value(bool req_int=false, bool frc_str_conv=false) const
Definition: ov.h:876
OCTINTERP_API octave_scalar_map scalar_map_value(void) const
OCTINTERP_API 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
bool is_true(void) const
Definition: ov.h:803
OCTINTERP_API octave_fcn_handle * fcn_handle_value(bool silent=false) const
OCTINTERP_API octave_user_function * user_function_value(bool silent=false) const
bool is_int8_type(void) const
Definition: ov.h:751
octave_idx_type rows(void) const
Definition: ov.h:590
OCTINTERP_API octave_map xmap_value(const char *fmt,...) const
static OCTINTERP_API octave_value empty_conv(const std::string &type, const octave_value &rhs=octave_value())
static OCTINTERP_API std::string assign_op_as_string(assign_op)
Definition: ov.cc:355
octave_idx_type numel(void) const
Definition: ov.h:604
OCTINTERP_API RowVector row_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
OCTINTERP_API FloatComplexColumnVector float_complex_column_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
octave_idx_type idx_type_value(bool req_int=false, bool frc_str_conv=false) const
bool is_magic_int(void) const
Definition: ov.h:721
bool is_dq_string(void) const
Definition: ov.h:688
static OCTINTERP_API assign_op binary_op_to_assign_op(binary_op)
Definition: ov.cc:450
octave_base_value * empty_clone(void) const
Definition: ov.h:391
compound_binary_op
Definition: ov.h:115
@ op_herm_ldiv
Definition: ov.h:122
@ op_el_not_or
Definition: ov.h:124
@ op_el_not_and
Definition: ov.h:123
@ op_el_and_not
Definition: ov.h:125
@ op_mul_trans
Definition: ov.h:118
@ op_mul_herm
Definition: ov.h:120
@ op_trans_ldiv
Definition: ov.h:121
@ op_el_or_not
Definition: ov.h:126
@ op_herm_mul
Definition: ov.h:119
@ op_trans_mul
Definition: ov.h:117
ComplexNDArray complex_array_value(bool frc_str_conv=false) const
Definition: ov.h:923
OCTINTERP_API octave_value storable_value(void) const
bool is_defined(void) const
Definition: ov.h:637
bool isinteger(void) const
Definition: ov.h:775
bool is_double_type(void) const
Definition: ov.h:740
octave_value(void)
Definition: ov.h:170
Cell cell_value(void) const
Matrix size(void)
Definition: ov.h:511
void break_closure_cycles(const std::shared_ptr< octave::stack_frame > &)
bool is_function_handle(void) const
Definition: ov.h:813
bool is_equal(const octave_value &) const
std::string class_name(void) const
Definition: ov.h:1451
assign_op
Definition: ov.h:132
@ op_pow_eq
Definition: ov.h:139
@ op_asn_eq
Definition: ov.h:133
@ op_add_eq
Definition: ov.h:134
@ op_el_pow_eq
Definition: ov.h:143
@ op_mul_eq
Definition: ov.h:136
@ op_div_eq
Definition: ov.h:137
@ op_el_and_eq
Definition: ov.h:144
@ op_el_ldiv_eq
Definition: ov.h:142
@ op_sub_eq
Definition: ov.h:135
@ op_el_mul_eq
Definition: ov.h:140
@ op_el_or_eq
Definition: ov.h:145
@ unknown_assign_op
Definition: ov.h:147
@ op_el_div_eq
Definition: ov.h:141
@ op_ldiv_eq
Definition: ov.h:138
bool is_uint32_type(void) const
Definition: ov.h:769
octave_idx_type columns(void) const
Definition: ov.h:592
OCTINTERP_API ColumnVector column_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
int8NDArray int8_array_value(void) const
Definition: ov.h:995
static OCTINTERP_API std::string unary_op_as_string(unary_op)
Definition: ov.cc:128
OCTINTERP_API Array< int > int_vector_value(bool req_int=false, bool frc_str_conv=false, bool frc_vec_conv=false) const
bool is_int64_type(void) const
Definition: ov.h:760
int64NDArray int64_array_value(void) const
Definition: ov.h:1004
uint8NDArray uint8_array_value(void) const
Definition: ov.h:1007
OCTINTERP_API octave_classdef * classdef_object_value(bool silent=false) const
octave_value reshape(const dim_vector &dv) const
Definition: ov.h:616
OCTINTERP_API Array< FloatComplex > float_complex_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
bool isnull(void) const
Definition: ov.h:724
bool is_zero_by_zero(void) const
Definition: ov.h:601
OCTINTERP_API Array< octave_idx_type > octave_idx_type_vector_value(bool req_int=false, bool frc_str_conv=false, bool frc_vec_conv=false) const
OCTINTERP_API octave_value & assign(assign_op op, const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
magic_colon
Definition: ov.h:168
@ magic_colon_t
Definition: ov.h:168
OCTINTERP_API octave_value next_subsref(const std::string &type, const std::list< octave_value_list > &idx, std::size_t skip=1)
OCTINTERP_API Array< Complex > complex_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
bool is_int32_type(void) const
Definition: ov.h:757
static OCTINTERP_API octave_base_value * nil_rep(void)
Definition: ov.cc:121
bool is_uint64_type(void) const
Definition: ov.h:772
bool is_int16_type(void) const
Definition: ov.h:754
void make_unique(void)
Definition: ov.h:406
uint64NDArray uint64_array_value(void) const
Definition: ov.h:1016
binary_op
Definition: ov.h:90
@ op_ldiv
Definition: ov.h:96
@ op_ne
Definition: ov.h:102
@ unknown_binary_op
Definition: ov.h:111
@ op_el_or
Definition: ov.h:108
@ op_el_ldiv
Definition: ov.h:106
@ op_pow
Definition: ov.h:95
@ op_ge
Definition: ov.h:100
@ op_div
Definition: ov.h:94
@ op_el_pow
Definition: ov.h:105
@ op_mul
Definition: ov.h:93
@ op_add
Definition: ov.h:91
@ op_sub
Definition: ov.h:92
@ op_el_mul
Definition: ov.h:103
@ op_le
Definition: ov.h:98
@ op_struct_ref
Definition: ov.h:109
@ op_lt
Definition: ov.h:97
@ op_gt
Definition: ov.h:101
@ op_eq
Definition: ov.h:99
@ op_el_and
Definition: ov.h:107
@ op_el_div
Definition: ov.h:104
OCTINTERP_API FloatComplexRowVector float_complex_row_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
octave_base_value::type_conv_info numeric_demotion_function(void) const
Definition: ov.h:480
bool is_range(void) const
Definition: ov.h:691
OCTINTERP_API Array< float > float_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
bool isempty(void) const
Definition: ov.h:646
OCTINTERP_API octave_value & non_const_unary_op(unary_op op)
NDArray array_value(bool frc_str_conv=false) const
Definition: ov.h:904
static OCTINTERP_API binary_op assign_op_to_binary_op(assign_op)
Definition: ov.cc:404
static OCTINTERP_API std::string binary_op_fcn_name(binary_op)
Definition: ov.cc:251
bool is_single_type(void) const
Definition: ov.h:743
uint32NDArray uint32_array_value(void) const
Definition: ov.h:1013
OCTINTERP_API std::string get_dims_str(void) const
octave_value convert_to_str(bool pad=false, bool force=false, char type='\'') const
Definition: ov.h:1411
const octave_base_value & get_rep(void) const
Definition: ov.h:1480
OCTINTERP_API ComplexColumnVector complex_column_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
OCTINTERP_API octave_map map_value(void) const
octave_value all(int dim=0) const
Definition: ov.h:729
bool isobject(void) const
Definition: ov.h:709
octave_base_value * m_rep
The real representation.
Definition: ov.h:1666
OCTINTERP_API bool load_hdf5(octave_hdf5_id loc_id, const char *name)
bool is_undefined(void) const
Definition: ov.h:640
FloatComplexNDArray float_complex_array_value(bool frc_str_conv=false) const
Definition: ov.h:927
OCTINTERP_API octave_value single_subsref(const std::string &type, const octave_value_list &idx)
OCTINTERP_API octave_user_code * user_code_value(bool silent=false) const
OCTINTERP_API octave_idx_type length(void) const
FloatNDArray float_array_value(bool frc_str_conv=false) const
Definition: ov.h:907
bool is_uint8_type(void) const
Definition: ov.h:763
int16NDArray int16_array_value(void) const
Definition: ov.h:998
OCTINTERP_API bool load_binary(std::istream &is, bool swap, octave::mach_info::float_format fmt)
OCTINTERP_API octave_value subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
Matrix matrix_value(bool frc_str_conv=false) const
Definition: ov.h:898
bool iscomplex(void) const
Definition: ov.h:786
OCTINTERP_API octave_value undef_subsasgn(const std::string &type, const std::list< octave_value_list > &idx, const octave_value &rhs)
OCTINTERP_API void maybe_mutate(void)
double double_value(bool frc_str_conv=false) const
Definition: ov.h:886
OCTINTERP_API octave_base_value * clone(void) const
OCTINTERP_API float_display_format get_edit_display_format(void) const
OCTINTERP_API void make_storable_value(void)
OCTINTERP_API octave_user_script * user_script_value(bool silent=false) const
OCTINTERP_API void print_info(std::ostream &os, const std::string &prefix="") const
std::string type_name(void) const
Definition: ov.h:1449
bool is_legacy_object(void) const
Definition: ov.h:643
dim_vector dims(void) const
Definition: ov.h:586
OCTINTERP_API FloatColumnVector float_column_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
OCTINTERP_API FloatRowVector float_row_vector_value(bool frc_str_conv=false, bool frc_vec_conv=false) const
static void register_type(void)
octave_value find_function(const std::string &name, const symbol_scope &search_scope=symbol_scope())
Definition: symtab.cc:249
octave_value(* unary_op_fcn)(const octave_base_value &)
Definition: ov-typeinfo.h:50
octave_value(* binary_op_fcn)(const octave_base_value &, const octave_base_value &)
Definition: ov-typeinfo.h:58
octave_value(* binary_class_op_fcn)(const octave_value &, const octave_value &)
Definition: ov-typeinfo.h:55
binary_class_op_fcn lookup_binary_class_op(octave_value::binary_op)
Definition: ov-typeinfo.cc:519
octave_value(* cat_op_fcn)(const octave_base_value &, const octave_base_value &, const Array< octave_idx_type > &ra_idx)
Definition: ov-typeinfo.h:61
octave_value(* unary_class_op_fcn)(const octave_value &)
Definition: ov-typeinfo.h:48
unary_class_op_fcn lookup_unary_class_op(octave_value::unary_op)
Definition: ov-typeinfo.cc:498
cat_op_fcn lookup_cat_op(int, int)
Definition: ov-typeinfo.cc:548
binary_op_fcn lookup_binary_op(octave_value::binary_op, int, int)
Definition: ov-typeinfo.cc:526
unary_op_fcn lookup_unary_op(octave_value::unary_op, int)
Definition: ov-typeinfo.cc:505
OCTINTERP_API void print_usage(void)
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:1070
void error_with_cfn(const char *fmt,...)
Definition: error.cc:1010
void error(const char *fmt,...)
Definition: error.cc:980
#define panic_impossible()
Definition: error.h:411
void warn_implicit_conversion(const char *id, const char *from, const char *to)
Definition: errwarn.cc:344
QString name
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
class OCTAVE_API RowVector
Definition: mx-fwd.h:50
class OCTAVE_API FloatColumnVector
Definition: mx-fwd.h:47
class OCTAVE_API FloatComplexRowVector
Definition: mx-fwd.h:53
class OCTAVE_API ComplexColumnVector
Definition: mx-fwd.h:46
class OCTAVE_API ColumnVector
Definition: mx-fwd.h:45
class OCTAVE_API FloatComplexColumnVector
Definition: mx-fwd.h:48
class OCTAVE_API ComplexRowVector
Definition: mx-fwd.h:51
class OCTAVE_API FloatRowVector
Definition: mx-fwd.h:52
bool isnan(bool)
Definition: lo-mappers.h:178
int register_type(const std::string &t_name, const std::string &c_name, const octave_value &val)
Definition: ov-typeinfo.cc:767
octave::type_info::assign_op_fcn assign_op_fcn
Definition: ov-typeinfo.h:287
octave::type_info::non_const_unary_op_fcn non_const_unary_op_fcn
Definition: ov-typeinfo.h:279
class OCTAVE_API range
Definition: range-fwd.h:33
interpreter & __get_interpreter__(const std::string &who)
type_info & __get_type_info__(const std::string &who)
STL namespace.
std::complex< double > Complex
Definition: oct-cmplx.h:33
std::complex< float > FloatComplex
Definition: oct-cmplx.h:34
int64_t octave_hdf5_id
@ IT
static double as_double(OCTAVE_TIME_T sec, long usec)
Definition: oct-time.h:35
const octave_base_value const Array< octave_idx_type > & ra_idx
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))
const octave_char_matrix & v2
builtin_type_t
Definition: ov-base.h:75
@ btyp_float_complex
Definition: ov-base.h:79
@ btyp_double
Definition: ov-base.h:76
@ btyp_int32
Definition: ov-base.h:82
@ btyp_float
Definition: ov-base.h:77
@ btyp_uint16
Definition: ov-base.h:85
@ btyp_int64
Definition: ov-base.h:83
@ btyp_unknown
Definition: ov-base.h:93
@ btyp_uint64
Definition: ov-base.h:87
@ btyp_int16
Definition: ov-base.h:81
@ btyp_uint32
Definition: ov-base.h:86
@ btyp_char
Definition: ov-base.h:89
@ btyp_uint8
Definition: ov-base.h:84
@ btyp_int8
Definition: ov-base.h:80
@ btyp_complex
Definition: ov-base.h:78
octave_double_range octave_range
Definition: ov-range.h:620
static bool scalar(const dim_vector &dims)
Definition: ov-struct.cc:679
static bool Voptimize_range
Definition: ov.cc:114
static bool Voptimize_diagonal_matrix
Definition: ov.cc:106
static bool Voptimize_permutation_matrix
Definition: ov.cc:110
#define XVALUE_EXTRACTOR(TYPE, NAME, FCN)
OCTINTERP_API void install_types(octave::type_info &)
OCTINTERP_API octave_value cat_op(type_info &ti, const octave_value &a, const octave_value &b, const Array< octave_idx_type > &ra_idx)
OCTINTERP_API octave_value colon_op(const octave_value &base, const octave_value &increment, const octave_value &limit, bool is_for_cmd_expr=false)
OCTAVE_NAMESPACE_BEGIN OCTINTERP_API octave_value unary_op(type_info &ti, octave_value::unary_op op, const octave_value &a)
OCTINTERP_API octave_value binary_op(type_info &ti, octave_value::binary_op op, const octave_value &a, const octave_value &b)
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition: ovl.h:211
static T abs(T x)
Definition: pr-output.cc:1678
octave_value set_internal_variable(bool &var, const octave_value_list &args, int nargout, const char *nm)
Definition: variables.cc:587