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