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