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