GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
ov.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2013 John W. Eaton
4 Copyright (C) 2009-2010 VZLU Prague
5 
6 This file is part of Octave.
7 
8 Octave is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, see
20 <http://www.gnu.org/licenses/>.
21 
22 */
23 
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27 
28 #include "data-conv.h"
29 #include "quit.h"
30 #include "str-vec.h"
31 
32 #include "oct-obj.h"
33 #include "oct-stream.h"
34 #include "ov.h"
35 #include "ov-base.h"
36 #include "ov-bool.h"
37 #include "ov-bool-mat.h"
38 #include "ov-cell.h"
39 #include "ov-scalar.h"
40 #include "ov-float.h"
41 #include "ov-re-mat.h"
42 #include "ov-flt-re-mat.h"
43 #include "ov-re-diag.h"
44 #include "ov-flt-re-diag.h"
45 #include "ov-perm.h"
46 #include "ov-bool-sparse.h"
47 #include "ov-cx-sparse.h"
48 #include "ov-re-sparse.h"
49 #include "ov-int8.h"
50 #include "ov-int16.h"
51 #include "ov-int32.h"
52 #include "ov-int64.h"
53 #include "ov-uint8.h"
54 #include "ov-uint16.h"
55 #include "ov-uint32.h"
56 #include "ov-uint64.h"
57 #include "ov-complex.h"
58 #include "ov-flt-complex.h"
59 #include "ov-cx-mat.h"
60 #include "ov-flt-cx-mat.h"
61 #include "ov-cx-diag.h"
62 #include "ov-flt-cx-diag.h"
63 #include "ov-ch-mat.h"
64 #include "ov-str-mat.h"
65 #include "ov-range.h"
66 #include "ov-struct.h"
67 #include "ov-class.h"
68 #include "ov-oncleanup.h"
69 #include "ov-cs-list.h"
70 #include "ov-colon.h"
71 #include "ov-builtin.h"
72 #include "ov-dld-fcn.h"
73 #include "ov-usr-fcn.h"
74 #include "ov-fcn-handle.h"
75 #include "ov-fcn-inline.h"
76 #include "ov-typeinfo.h"
77 #include "ov-null-mat.h"
78 #include "ov-lazy-idx.h"
79 #ifdef HAVE_JAVA
80 #include "ov-java.h"
81 #endif
82 
83 #include "defun.h"
84 #include "error.h"
85 #include "gripes.h"
86 #include "pager.h"
87 #include "parse.h"
88 #include "pr-output.h"
89 #include "symtab.h"
90 #include "utils.h"
91 #include "variables.h"
92 
93 // We are likely to have a lot of octave_value objects to allocate, so
94 // make the grow_size large.
96 
97 // FIXME
98 
99 // Octave's value type.
100 
101 std::string
103 {
104  std::string retval;
105 
106  switch (op)
107  {
108  case op_not:
109  retval = "!";
110  break;
111 
112  case op_uplus:
113  retval = "+";
114  break;
115 
116  case op_uminus:
117  retval = "-";
118  break;
119 
120  case op_transpose:
121  retval = ".'";
122  break;
123 
124  case op_hermitian:
125  retval = "'";
126  break;
127 
128  case op_incr:
129  retval = "++";
130  break;
131 
132  case op_decr:
133  retval = "--";
134  break;
135 
136  default:
137  retval = "<unknown>";
138  }
139 
140  return retval;
141 }
142 
143 std::string
145 {
146  std::string retval;
147 
148  switch (op)
149  {
150  case op_not:
151  retval = "not";
152  break;
153 
154  case op_uplus:
155  retval = "uplus";
156  break;
157 
158  case op_uminus:
159  retval = "uminus";
160  break;
161 
162  case op_transpose:
163  retval = "transpose";
164  break;
165 
166  case op_hermitian:
167  retval = "ctranspose";
168  break;
169 
170  default:
171  break;
172  }
173 
174  return retval;
175 }
176 
177 std::string
179 {
180  std::string retval;
181 
182  switch (op)
183  {
184  case op_add:
185  retval = "+";
186  break;
187 
188  case op_sub:
189  retval = "-";
190  break;
191 
192  case op_mul:
193  retval = "*";
194  break;
195 
196  case op_div:
197  retval = "/";
198  break;
199 
200  case op_pow:
201  retval = "^";
202  break;
203 
204  case op_ldiv:
205  retval = "\\";
206  break;
207 
208  case op_lshift:
209  retval = "<<";
210  break;
211 
212  case op_rshift:
213  retval = ">>";
214  break;
215 
216  case op_lt:
217  retval = "<";
218  break;
219 
220  case op_le:
221  retval = "<=";
222  break;
223 
224  case op_eq:
225  retval = "==";
226  break;
227 
228  case op_ge:
229  retval = ">=";
230  break;
231 
232  case op_gt:
233  retval = ">";
234  break;
235 
236  case op_ne:
237  retval = "!=";
238  break;
239 
240  case op_el_mul:
241  retval = ".*";
242  break;
243 
244  case op_el_div:
245  retval = "./";
246  break;
247 
248  case op_el_pow:
249  retval = ".^";
250  break;
251 
252  case op_el_ldiv:
253  retval = ".\\";
254  break;
255 
256  case op_el_and:
257  retval = "&";
258  break;
259 
260  case op_el_or:
261  retval = "|";
262  break;
263 
264  case op_struct_ref:
265  retval = ".";
266  break;
267 
268  default:
269  retval = "<unknown>";
270  }
271 
272  return retval;
273 }
274 
275 std::string
277 {
278  std::string retval;
279 
280  switch (op)
281  {
282  case op_add:
283  retval = "plus";
284  break;
285 
286  case op_sub:
287  retval = "minus";
288  break;
289 
290  case op_mul:
291  retval = "mtimes";
292  break;
293 
294  case op_div:
295  retval = "mrdivide";
296  break;
297 
298  case op_pow:
299  retval = "mpower";
300  break;
301 
302  case op_ldiv:
303  retval = "mldivide";
304  break;
305 
306  case op_lt:
307  retval = "lt";
308  break;
309 
310  case op_le:
311  retval = "le";
312  break;
313 
314  case op_eq:
315  retval = "eq";
316  break;
317 
318  case op_ge:
319  retval = "ge";
320  break;
321 
322  case op_gt:
323  retval = "gt";
324  break;
325 
326  case op_ne:
327  retval = "ne";
328  break;
329 
330  case op_el_mul:
331  retval = "times";
332  break;
333 
334  case op_el_div:
335  retval = "rdivide";
336  break;
337 
338  case op_el_pow:
339  retval = "power";
340  break;
341 
342  case op_el_ldiv:
343  retval = "ldivide";
344  break;
345 
346  case op_el_and:
347  retval = "and";
348  break;
349 
350  case op_el_or:
351  retval = "or";
352  break;
353 
354  default:
355  break;
356  }
357 
358  return retval;
359 }
360 
361 std::string
363 {
364  std::string retval;
365 
366  switch (op)
367  {
368  case op_trans_mul:
369  retval = "transtimes";
370  break;
371 
372  case op_mul_trans:
373  retval = "timestrans";
374  break;
375 
376  case op_herm_mul:
377  retval = "hermtimes";
378  break;
379 
380  case op_mul_herm:
381  retval = "timesherm";
382  break;
383 
384  case op_trans_ldiv:
385  retval = "transldiv";
386  break;
387 
388  case op_herm_ldiv:
389  retval = "hermldiv";
390  break;
391 
392  case op_el_and_not:
393  retval = "andnot";
394  break;
395 
396  case op_el_or_not:
397  retval = "ornot";
398  break;
399 
400  case op_el_not_and:
401  retval = "notand";
402  break;
403 
404  case op_el_not_or:
405  retval = "notor";
406  break;
407 
408  default:
409  break;
410  }
411 
412  return retval;
413 }
414 
415 std::string
417 {
418  std::string retval;
419 
420  switch (op)
421  {
422  case op_asn_eq:
423  retval = "=";
424  break;
425 
426  case op_add_eq:
427  retval = "+=";
428  break;
429 
430  case op_sub_eq:
431  retval = "-=";
432  break;
433 
434  case op_mul_eq:
435  retval = "*=";
436  break;
437 
438  case op_div_eq:
439  retval = "/=";
440  break;
441 
442  case op_ldiv_eq:
443  retval = "\\=";
444  break;
445 
446  case op_pow_eq:
447  retval = "^=";
448  break;
449 
450  case op_lshift_eq:
451  retval = "<<=";
452  break;
453 
454  case op_rshift_eq:
455  retval = ">>=";
456  break;
457 
458  case op_el_mul_eq:
459  retval = ".*=";
460  break;
461 
462  case op_el_div_eq:
463  retval = "./=";
464  break;
465 
466  case op_el_ldiv_eq:
467  retval = ".\\=";
468  break;
469 
470  case op_el_pow_eq:
471  retval = ".^=";
472  break;
473 
474  case op_el_and_eq:
475  retval = "&=";
476  break;
477 
478  case op_el_or_eq:
479  retval = "|=";
480  break;
481 
482  default:
483  retval = "<unknown>";
484  }
485 
486  return retval;
487 }
488 
491 {
492  switch (op)
493  {
494  case op_add_eq:
495  return op_add;
496  case op_sub_eq:
497  return op_sub;
498  case op_mul_eq:
499  return op_mul;
500  case op_div_eq:
501  return op_div;
502  case op_ldiv_eq:
503  return op_ldiv;
504  case op_pow_eq:
505  return op_pow;
506  case op_lshift_eq:
507  return op_lshift;
508  case op_rshift_eq:
509  return op_rshift;
510  case op_el_mul_eq:
511  return op_el_mul;
512  case op_el_div_eq:
513  return op_el_div;
514  case op_el_ldiv_eq:
515  return op_el_ldiv;
516  case op_el_pow_eq:
517  return op_el_pow;
518  case op_el_and_eq:
519  return op_el_and;
520  case op_el_or_eq:
521  return op_el_or;
522  default:
523  return unknown_binary_op;
524  }
525 
526 }
527 
530 {
531  assign_op retval;
532 
533  switch (op)
534  {
535  case op_add:
536  retval = op_add_eq;
537  break;
538  case op_sub:
539  retval = op_sub_eq;
540  break;
541  case op_mul:
542  retval = op_mul_eq;
543  break;
544  case op_div:
545  retval = op_div_eq;
546  break;
547  case op_el_mul:
548  retval = op_el_mul_eq;
549  break;
550  case op_el_div:
551  retval = op_el_div_eq;
552  break;
553  case op_el_and:
554  retval = op_el_and_eq;
555  break;
556  case op_el_or:
557  retval = op_el_or_eq;
558  break;
559  default:
560  retval = unknown_assign_op;
561  }
562 
563  return retval;
564 }
565 
567  : rep (new octave_scalar (i))
568 {
569 }
570 
571 octave_value::octave_value (unsigned short int i)
572  : rep (new octave_scalar (i))
573 {
574 }
575 
577  : rep (new octave_scalar (i))
578 {
579 }
580 
582  : rep (new octave_scalar (i))
583 {
584 }
585 
587  : rep (new octave_scalar (i))
588 {
589 }
590 
591 octave_value::octave_value (unsigned long int i)
592  : rep (new octave_scalar (i))
593 {
594 }
595 
596 #if defined (HAVE_LONG_LONG_INT)
597 octave_value::octave_value (long long int i)
598  : rep (new octave_scalar (i))
599 {
600 }
601 #endif
602 
603 #if defined (HAVE_UNSIGNED_LONG_LONG_INT)
604 octave_value::octave_value (unsigned long long int i)
605  : rep (new octave_scalar (i))
606 {
607 }
608 #endif
609 
611  : rep (new octave_scalar (t.double_value ()))
612 {
613 }
614 
616  : rep (new octave_scalar (d))
617 {
618 }
619 
621  : rep (new octave_float_scalar (d))
622 {
623 }
624 
625 octave_value::octave_value (const Cell& c, bool is_csl)
626  : rep (is_csl
627  ? dynamic_cast<octave_base_value *> (new octave_cs_list (c))
628  : dynamic_cast<octave_base_value *> (new octave_cell (c)))
629 {
630 }
631 
633  : rep (is_csl
634  ? dynamic_cast<octave_base_value *> (new octave_cs_list (Cell (a)))
635  : dynamic_cast<octave_base_value *> (new octave_cell (Cell (a))))
636 {
637 }
638 
640  : rep (new octave_matrix (m, t))
641 {
642  maybe_mutate ();
643 }
644 
646  : rep (new octave_float_matrix (m, t))
647 {
648  maybe_mutate ();
649 }
650 
652  : rep (new octave_matrix (a))
653 {
654  maybe_mutate ();
655 }
656 
658  : rep (new octave_float_matrix (a))
659 {
660  maybe_mutate ();
661 }
662 
664  : rep (new octave_matrix (a))
665 {
666  maybe_mutate ();
667 }
668 
670  : rep (new octave_float_matrix (a))
671 {
672  maybe_mutate ();
673 }
674 
676  : rep (new octave_diag_matrix (d))
677 {
678  maybe_mutate ();
679 }
680 
682  : rep (new octave_float_diag_matrix (d))
683 {
684  maybe_mutate ();
685 }
686 
688  : rep (new octave_complex_diag_matrix (d))
689 {
690  maybe_mutate ();
691 }
692 
694  : rep (new octave_float_complex_diag_matrix (d))
695 {
696  maybe_mutate ();
697 }
698 
700  : rep (new octave_diag_matrix (d))
701 {
702  maybe_mutate ();
703 }
704 
706  : rep (new octave_float_diag_matrix (d))
707 {
708  maybe_mutate ();
709 }
710 
712  : rep (new octave_matrix (v))
713 {
714  maybe_mutate ();
715 }
716 
718  : rep (new octave_float_matrix (v))
719 {
720  maybe_mutate ();
721 }
722 
724  : rep (new octave_matrix (v))
725 {
726  maybe_mutate ();
727 }
728 
730  : rep (new octave_float_matrix (v))
731 {
732  maybe_mutate ();
733 }
734 
736  : rep (new octave_complex (C))
737 {
738  maybe_mutate ();
739 }
740 
742  : rep (new octave_float_complex (C))
743 {
744  maybe_mutate ();
745 }
746 
748  : rep (new octave_complex_matrix (m, t))
749 {
750  maybe_mutate ();
751 }
752 
754  : rep (new octave_float_complex_matrix (m, t))
755 {
756  maybe_mutate ();
757 }
758 
760  : rep (new octave_complex_matrix (a))
761 {
762  maybe_mutate ();
763 }
764 
766  : rep (new octave_float_complex_matrix (a))
767 {
768  maybe_mutate ();
769 }
770 
772  : rep (new octave_complex_matrix (a))
773 {
774  maybe_mutate ();
775 }
776 
778  : rep (new octave_float_complex_matrix (a))
779 {
780  maybe_mutate ();
781 }
782 
784  : rep (new octave_complex_diag_matrix (d))
785 {
786  maybe_mutate ();
787 }
788 
790  : rep (new octave_float_complex_diag_matrix (d))
791 {
792  maybe_mutate ();
793 }
794 
796  : rep (new octave_complex_matrix (v))
797 {
798  maybe_mutate ();
799 }
800 
802  : rep (new octave_float_complex_matrix (v))
803 {
804  maybe_mutate ();
805 }
806 
808  : rep (new octave_complex_matrix (v))
809 {
810  maybe_mutate ();
811 }
812 
814  : rep (new octave_float_complex_matrix (v))
815 {
816  maybe_mutate ();
817 }
818 
820  : rep (new octave_perm_matrix (p))
821 {
822  maybe_mutate ();
823 }
824 
826  : rep (new octave_bool (b))
827 {
828 }
829 
831  : rep (new octave_bool_matrix (bm, t))
832 {
833  maybe_mutate ();
834 }
835 
837  : rep (new octave_bool_matrix (bnda))
838 {
839  maybe_mutate ();
840 }
841 
843  : rep (new octave_bool_matrix (bnda))
844 {
845  maybe_mutate ();
846 }
847 
849  : rep (type == '"'
850  ? new octave_char_matrix_dq_str (c)
851  : new octave_char_matrix_sq_str (c))
852 {
853  maybe_mutate ();
854 }
855 
856 octave_value::octave_value (const char *s, char type)
857  : rep (type == '"'
858  ? new octave_char_matrix_dq_str (s)
859  : new octave_char_matrix_sq_str (s))
860 {
861  maybe_mutate ();
862 }
863 
864 octave_value::octave_value (const std::string& s, char type)
865  : rep (type == '"'
866  ? new octave_char_matrix_dq_str (s)
867  : new octave_char_matrix_sq_str (s))
868 {
869  maybe_mutate ();
870 }
871 
873  : rep (type == '"'
874  ? new octave_char_matrix_dq_str (s)
875  : new octave_char_matrix_sq_str (s))
876 {
877  maybe_mutate ();
878 }
879 
881  : rep (type == '"'
882  ? new octave_char_matrix_dq_str (chm)
883  : new octave_char_matrix_sq_str (chm))
884 {
885  maybe_mutate ();
886 }
887 
889  : rep (type == '"'
890  ? new octave_char_matrix_dq_str (chm)
891  : new octave_char_matrix_sq_str (chm))
892 {
893  maybe_mutate ();
894 }
895 
897  : rep (type == '"'
898  ? new octave_char_matrix_dq_str (chm)
899  : new octave_char_matrix_sq_str (chm))
900 {
901  maybe_mutate ();
902 }
903 
905  : rep (type == '"'
906  ? new octave_char_matrix_dq_str (chm)
907  : new octave_char_matrix_sq_str (chm))
908 {
909  maybe_mutate ();
910 }
911 
913  : rep (type == '"'
914  ? new octave_char_matrix_dq_str (chm)
915  : new octave_char_matrix_sq_str (chm))
916 {
917  maybe_mutate ();
918 }
919 
921  : rep (type == '"'
922  ? new octave_char_matrix_dq_str (chm)
923  : new octave_char_matrix_sq_str (chm))
924 {
925  maybe_mutate ();
926 }
927 
929  : rep (new octave_sparse_matrix (m, t))
930 {
931  maybe_mutate ();
932 }
933 
935  : rep (new octave_sparse_matrix (m, t))
936 {
937  maybe_mutate ();
938 }
939 
941  : rep (new octave_sparse_complex_matrix (m, t))
942 {
943  maybe_mutate ();
944 }
945 
947  : rep (new octave_sparse_complex_matrix (m, t))
948 {
949  maybe_mutate ();
950 }
951 
953  : rep (new octave_sparse_bool_matrix (bm, t))
954 {
955  maybe_mutate ();
956 }
957 
959  : rep (new octave_sparse_bool_matrix (bm, t))
960 {
961  maybe_mutate ();
962 }
963 
965  : rep (new octave_int8_scalar (i))
966 {
967  maybe_mutate ();
968 }
969 
971  : rep (new octave_uint8_scalar (i))
972 {
973  maybe_mutate ();
974 }
975 
977  : rep (new octave_int16_scalar (i))
978 {
979  maybe_mutate ();
980 }
981 
983  : rep (new octave_uint16_scalar (i))
984 {
985  maybe_mutate ();
986 }
987 
989  : rep (new octave_int32_scalar (i))
990 {
991  maybe_mutate ();
992 }
993 
995  : rep (new octave_uint32_scalar (i))
996 {
997  maybe_mutate ();
998 }
999 
1001  : rep (new octave_int64_scalar (i))
1002 {
1003  maybe_mutate ();
1004 }
1005 
1007  : rep (new octave_uint64_scalar (i))
1008 {
1009  maybe_mutate ();
1010 }
1011 
1013  : rep (new octave_int8_matrix (inda))
1014 {
1015  maybe_mutate ();
1016 }
1017 
1019  : rep (new octave_int8_matrix (inda))
1020 {
1021  maybe_mutate ();
1022 }
1023 
1025  : rep (new octave_uint8_matrix (inda))
1026 {
1027  maybe_mutate ();
1028 }
1029 
1031  : rep (new octave_uint8_matrix (inda))
1032 {
1033  maybe_mutate ();
1034 }
1035 
1037  : rep (new octave_int16_matrix (inda))
1038 {
1039  maybe_mutate ();
1040 }
1041 
1043  : rep (new octave_int16_matrix (inda))
1044 {
1045  maybe_mutate ();
1046 }
1047 
1049  : rep (new octave_uint16_matrix (inda))
1050 {
1051  maybe_mutate ();
1052 }
1053 
1055  : rep (new octave_uint16_matrix (inda))
1056 {
1057  maybe_mutate ();
1058 }
1059 
1061  : rep (new octave_int32_matrix (inda))
1062 {
1063  maybe_mutate ();
1064 }
1065 
1067  : rep (new octave_int32_matrix (inda))
1068 {
1069  maybe_mutate ();
1070 }
1071 
1073  : rep (new octave_uint32_matrix (inda))
1074 {
1075  maybe_mutate ();
1076 }
1077 
1079  : rep (new octave_uint32_matrix (inda))
1080 {
1081  maybe_mutate ();
1082 }
1083 
1085  : rep (new octave_int64_matrix (inda))
1086 {
1087  maybe_mutate ();
1088 }
1089 
1091  : rep (new octave_int64_matrix (inda))
1092 {
1093  maybe_mutate ();
1094 }
1095 
1097  : rep (new octave_uint64_matrix (inda))
1098 {
1099  maybe_mutate ();
1100 }
1101 
1103  : rep (new octave_uint64_matrix (inda))
1104 {
1105  maybe_mutate ();
1106 }
1107 
1109  bool cache_index)
1110  : rep (new octave_matrix (inda, zero_based, cache_index))
1111 {
1112  maybe_mutate ();
1113 }
1114 
1116  : rep ()
1117 {
1118  double scalar;
1119  Range range;
1120  NDArray array;
1121  boolNDArray mask;
1122  idx_vector::idx_class_type idx_class;
1123 
1124  if (lazy)
1125  {
1126  // Only make lazy indices out of ranges and index vectors.
1127  switch (idx.idx_class ())
1128  {
1131  rep = new octave_lazy_index (idx);
1132  maybe_mutate ();
1133  return;
1134  default:
1135  break;
1136  }
1137  }
1138 
1139  idx.unconvert (idx_class, scalar, range, array, mask);
1140 
1141  switch (idx_class)
1142  {
1144  rep = new octave_magic_colon ();
1145  break;
1147  rep = new octave_range (range, idx);
1148  break;
1150  rep = new octave_scalar (scalar);
1151  break;
1153  rep = new octave_matrix (array, idx);
1154  break;
1156  rep = new octave_bool_matrix (mask, idx);
1157  break;
1158  default:
1159  assert (false);
1160  break;
1161  }
1162 
1163  // FIXME: needed?
1164  maybe_mutate ();
1165 }
1166 
1168  : rep (new octave_cell (cellstr))
1169 {
1170  maybe_mutate ();
1171 }
1172 
1173 octave_value::octave_value (double base, double limit, double inc)
1174  : rep (new octave_range (base, limit, inc))
1175 {
1176  maybe_mutate ();
1177 }
1178 
1180  : rep (new octave_range (r))
1181 {
1182  maybe_mutate ();
1183 }
1184 
1186  : rep (new octave_struct (m))
1187 {
1188  maybe_mutate ();
1189 }
1190 
1192  : rep (new octave_scalar_struct (m))
1193 {
1194 }
1195 
1197  : rep (new octave_struct (m))
1198 {
1199  maybe_mutate ();
1200 }
1201 
1202 octave_value::octave_value (const Octave_map& m, const std::string& id,
1203  const std::list<std::string>& plist)
1204  : rep (new octave_class (m, id, plist))
1205 {
1206 }
1207 
1209  : rep (new octave_cs_list (l))
1210 {
1211 }
1212 
1214  : rep (new octave_magic_colon ())
1215 {
1216 }
1217 
1219  : rep (new_rep)
1220 {
1221  if (borrow)
1222  rep->count++;
1223 }
1224 
1225 octave_value::octave_value (octave_base_value *new_rep, int xcount)
1226  : rep (new_rep)
1227 {
1228  rep->count = xcount;
1229 }
1230 
1233 {
1234  return rep->clone ();
1235 }
1236 
1237 void
1239 {
1241 
1242  if (tmp && tmp != rep)
1243  {
1244  if (--rep->count == 0)
1245  delete rep;
1246 
1247  rep = tmp;
1248  }
1249 }
1250 
1253  const octave_value_list& idx)
1254 {
1255  std::list<octave_value_list> i;
1256 
1257  i.push_back (idx);
1258 
1259  return rep->subsref (type, i);
1260 }
1261 
1263 octave_value::subsref (const std::string& type,
1264  const std::list<octave_value_list>& idx, int nargout)
1265 {
1266  if (nargout == 1)
1267  return rep->subsref (type, idx);
1268  else
1269  return rep->subsref (type, idx, nargout);
1270 }
1271 
1273 octave_value::subsref (const std::string& type,
1274  const std::list<octave_value_list>& idx, int nargout,
1275  const std::list<octave_lvalue> *lvalue_list)
1276 {
1277  if (lvalue_list)
1278  return rep->subsref (type, idx, nargout, lvalue_list);
1279  else
1280  return subsref (type, idx, nargout);
1281 }
1282 
1284 octave_value::next_subsref (const std::string& type,
1285  const std::list<octave_value_list>& idx,
1286  size_t skip)
1287 {
1288  if (! error_state && idx.size () > skip)
1289  {
1290  std::list<octave_value_list> new_idx (idx);
1291  for (size_t i = 0; i < skip; i++)
1292  new_idx.erase (new_idx.begin ());
1293  return subsref (type.substr (skip), new_idx);
1294  }
1295  else
1296  return *this;
1297 }
1298 
1300 octave_value::next_subsref (int nargout, const std::string& type,
1301  const std::list<octave_value_list>& idx,
1302  size_t skip)
1303 {
1304  if (! error_state && idx.size () > skip)
1305  {
1306  std::list<octave_value_list> new_idx (idx);
1307  for (size_t i = 0; i < skip; i++)
1308  new_idx.erase (new_idx.begin ());
1309  return subsref (type.substr (skip), new_idx, nargout);
1310  }
1311  else
1312  return *this;
1313 }
1314 
1316 octave_value::next_subsref (int nargout, const std::string& type,
1317  const std::list<octave_value_list>& idx,
1318  const std::list<octave_lvalue> *lvalue_list,
1319  size_t skip)
1320 {
1321  if (! error_state && idx.size () > skip)
1322  {
1323  std::list<octave_value_list> new_idx (idx);
1324  for (size_t i = 0; i < skip; i++)
1325  new_idx.erase (new_idx.begin ());
1326  return subsref (type.substr (skip), new_idx, nargout, lvalue_list);
1327  }
1328  else
1329  return *this;
1330 }
1331 
1333 octave_value::next_subsref (bool auto_add, const std::string& type,
1334  const std::list<octave_value_list>& idx,
1335  size_t skip)
1336 {
1337  if (! error_state && idx.size () > skip)
1338  {
1339  std::list<octave_value_list> new_idx (idx);
1340  for (size_t i = 0; i < skip; i++)
1341  new_idx.erase (new_idx.begin ());
1342  return subsref (type.substr (skip), new_idx, auto_add);
1343  }
1344  else
1345  return *this;
1346 }
1347 
1350 {
1351  return rep->do_multi_index_op (nargout, idx);
1352 }
1353 
1356  const std::list<octave_lvalue> *lvalue_list)
1357 {
1358  return rep->do_multi_index_op (nargout, idx, lvalue_list);
1359 }
1360 
1361 #if 0
1362 static void
1363 gripe_assign_failed (const std::string& on, const std::string& tn1,
1364  const std::string& tn2)
1365 {
1366  error ("assignment failed for '%s %s %s'",
1367  tn1.c_str (), on.c_str (), tn2.c_str ());
1368 }
1369 #endif
1370 
1371 static void
1372 gripe_assign_failed_or_no_method (const std::string& on,
1373  const std::string& tn1,
1374  const std::string& tn2)
1375 {
1376  error ("assignment failed, or no method for '%s %s %s'",
1377  tn1.c_str (), on.c_str (), tn2.c_str ());
1378 }
1379 
1381 octave_value::subsasgn (const std::string& type,
1382  const std::list<octave_value_list>& idx,
1383  const octave_value& rhs)
1384 {
1385  return rep->subsasgn (type, idx, rhs);
1386 }
1387 
1389 octave_value::undef_subsasgn (const std::string& type,
1390  const std::list<octave_value_list>& idx,
1391  const octave_value& rhs)
1392 {
1393  return rep->undef_subsasgn (type, idx, rhs);
1394 }
1395 
1396 octave_value&
1397 octave_value::assign (assign_op op, const std::string& type,
1398  const std::list<octave_value_list>& idx,
1399  const octave_value& rhs)
1400 {
1401  octave_value retval;
1402 
1403  make_unique ();
1404 
1405  octave_value t_rhs = rhs;
1406 
1407  if (op != op_asn_eq)
1408  {
1409  if (is_defined ())
1410  {
1411  octave_value t = subsref (type, idx);
1412 
1413  if (! error_state)
1414  {
1415  binary_op binop = op_eq_to_binary_op (op);
1416 
1417  if (! error_state)
1418  t_rhs = do_binary_op (binop, t, rhs);
1419  }
1420  }
1421  else
1422  error ("in computed assignment A(index) OP= X, A must be defined first");
1423  }
1424 
1425  if (! error_state)
1426  {
1427  octave_value tmp = subsasgn (type, idx, t_rhs);
1428 
1429  if (error_state)
1431  type_name (), rhs.type_name ());
1432  else
1433  *this = tmp;
1434  }
1435 
1436  return *this;
1437 }
1438 
1439 octave_value&
1441 {
1442  if (op == op_asn_eq)
1443  // Regularize a null matrix if stored into a variable.
1444  operator = (rhs.storable_value ());
1445  else if (is_defined ())
1446  {
1448 
1449  // Only attempt to operate in-place if this variable is unshared.
1450  if (rep->count == 1)
1451  {
1452  int tthis = this->type_id ();
1453  int trhs = rhs.type_id ();
1454 
1455  f = octave_value_typeinfo::lookup_assign_op (op, tthis, trhs);
1456  }
1457 
1458  if (f)
1459  {
1460  try
1461  {
1462  f (*rep, octave_value_list (), *rhs.rep);
1463  // Usually unnecessary, but may be needed (complex arrays).
1464  maybe_mutate ();
1465  }
1466  catch (octave_execution_exception)
1467  {
1469  }
1470  }
1471  else
1472  {
1473 
1474  binary_op binop = op_eq_to_binary_op (op);
1475 
1476  if (! error_state)
1477  {
1478  octave_value t = do_binary_op (binop, *this, rhs);
1479 
1480  if (! error_state)
1481  operator = (t);
1482  }
1483  }
1484  }
1485  else
1486  error ("in computed assignment A OP= X, A must be defined first");
1487 
1488  return *this;
1489 }
1490 
1493 {
1494  octave_idx_type retval = 0;
1495 
1496  const dim_vector dv = dims ();
1497 
1498  for (int i = 0; i < dv.length (); i++)
1499  {
1500  if (dv(i) == 0)
1501  {
1502  retval = 0;
1503  break;
1504  }
1505 
1506  if (dv(i) > retval)
1507  retval = dv(i);
1508  }
1509 
1510  return retval;
1511 }
1512 
1513 bool
1515 {
1516  bool retval = false;
1517 
1518  // If there is no op_eq for these types, we can't compare values.
1519 
1520  if (rows () == test.rows () && columns () == test.columns ())
1521  {
1522  octave_value tmp = do_binary_op (octave_value::op_eq, *this, test);
1523 
1524  // Empty array also means a match.
1525  if (! error_state && tmp.is_defined ())
1526  retval = tmp.is_true () || tmp.is_empty ();
1527  }
1528 
1529  return retval;
1530 }
1531 
1532 Cell
1534 {
1535  return rep->cell_value ();
1536 }
1537 
1538 // Define the idx_type_value function here instead of in ov.h to avoid
1539 // needing definitions for the SIZEOF_X macros in ov.h.
1540 
1542 octave_value::idx_type_value (bool req_int, bool frc_str_conv) const
1543 {
1544 #if defined (USE_64_BIT_IDX_T)
1545  return int64_value (req_int, frc_str_conv);
1546 #else
1547  return int_value (req_int, frc_str_conv);
1548 #endif
1549 }
1550 
1551 octave_map
1553 {
1554  return rep->map_value ();
1555 }
1556 
1559 {
1560  return rep->scalar_map_value ();
1561 }
1562 
1564 octave_value::function_value (bool silent) const
1565 {
1566  return rep->function_value (silent);
1567 }
1568 
1571 {
1572  return rep->user_function_value (silent);
1573 }
1574 
1577 {
1578  return rep->user_script_value (silent);
1579 }
1580 
1583 {
1584  return rep->user_code_value (silent);
1585 }
1586 
1589 {
1590  return rep->fcn_handle_value (silent);
1591 }
1592 
1595 {
1596  return rep->fcn_inline_value (silent);
1597 }
1598 
1601 {
1602  return rep->list_value ();
1603 }
1604 
1605 static dim_vector
1606 make_vector_dims (const dim_vector& dv, bool force_vector_conversion,
1607  const std::string& my_type, const std::string& wanted_type)
1608 {
1609  dim_vector retval (dv);
1610  retval.chop_trailing_singletons ();
1611  octave_idx_type nel = dv.numel ();
1612 
1613  if (retval.length () > 2 || (retval(0) != 1 && retval(1) != 1))
1614  {
1615  if (!force_vector_conversion)
1616  gripe_implicit_conversion ("Octave:array-to-vector",
1617  my_type.c_str (), wanted_type.c_str ());
1618  retval = dim_vector (nel, 1);
1619  }
1620 
1621  return retval;
1622 }
1623 
1625 octave_value::column_vector_value (bool force_string_conv,
1626  bool frc_vec_conv) const
1627 {
1628  return ColumnVector (vector_value (force_string_conv,
1629  frc_vec_conv));
1630 }
1631 
1634  bool frc_vec_conv) const
1635 {
1636  return ComplexColumnVector (complex_vector_value (force_string_conv,
1637  frc_vec_conv));
1638 }
1639 
1640 RowVector
1641 octave_value::row_vector_value (bool force_string_conv,
1642  bool frc_vec_conv) const
1643 {
1644  return RowVector (vector_value (force_string_conv,
1645  frc_vec_conv));
1646 }
1647 
1650  bool frc_vec_conv) const
1651 {
1652  return ComplexRowVector (complex_vector_value (force_string_conv,
1653  frc_vec_conv));
1654 }
1655 
1657 octave_value::vector_value (bool force_string_conv,
1658  bool force_vector_conversion) const
1659 {
1660  Array<double> retval = array_value (force_string_conv);
1661 
1662  if (error_state)
1663  return retval;
1664  else
1665  return retval.reshape (make_vector_dims (retval.dims (),
1666  force_vector_conversion,
1667  type_name (), "real vector"));
1668 }
1669 
1670 template <class T>
1671 static Array<int>
1673 {
1674  Array<int> retval (A.dims ());
1675  octave_idx_type n = A.numel ();
1676 
1677  for (octave_idx_type i = 0; i < n; i++)
1678  retval.xelem (i) = octave_int<int> (A.xelem (i));
1679 
1680  return retval;
1681 }
1682 
1683 Array<int>
1684 octave_value::int_vector_value (bool force_string_conv, bool require_int,
1685  bool force_vector_conversion) const
1686 {
1687  Array<int> retval;
1688 
1689  if (is_integer_type ())
1690  {
1691  if (is_int32_type ())
1693  else if (is_int64_type ())
1695  else if (is_int16_type ())
1697  else if (is_int8_type ())
1698  retval = convert_to_int_array (int8_array_value ());
1699  else if (is_uint32_type ())
1701  else if (is_uint64_type ())
1703  else if (is_uint16_type ())
1705  else if (is_uint8_type ())
1707  else
1708  retval = array_value (force_string_conv);
1709  }
1710  else
1711  {
1712  const NDArray a = array_value (force_string_conv);
1713  if (! error_state)
1714  {
1715  if (require_int)
1716  {
1717  retval.resize (a.dims ());
1718  for (octave_idx_type i = 0; i < a.numel (); i++)
1719  {
1720  double ai = a.elem (i);
1721  int v = static_cast<int> (ai);
1722  if (ai == v)
1723  retval.xelem (i) = v;
1724  else
1725  {
1726  error_with_cfn ("conversion to integer value failed");
1727  break;
1728  }
1729  }
1730  }
1731  else
1732  retval = Array<int> (a);
1733  }
1734  }
1735 
1736 
1737  if (error_state)
1738  return retval;
1739  else
1740  return retval.reshape (make_vector_dims (retval.dims (),
1741  force_vector_conversion,
1742  type_name (), "integer vector"));
1743 }
1744 
1745 template <class T>
1748 {
1749  Array<octave_idx_type> retval (A.dims ());
1750  octave_idx_type n = A.numel ();
1751 
1752  for (octave_idx_type i = 0; i < n; i++)
1753  retval.xelem (i) = octave_int<octave_idx_type> (A.xelem (i));
1754 
1755  return retval;
1756 }
1757 
1760  bool force_string_conv,
1761  bool force_vector_conversion) const
1762 {
1763  Array<octave_idx_type> retval;
1764 
1765  if (is_integer_type ())
1766  {
1767  if (is_int32_type ())
1769  else if (is_int64_type ())
1771  else if (is_int16_type ())
1773  else if (is_int8_type ())
1775  else if (is_uint32_type ())
1777  else if (is_uint64_type ())
1779  else if (is_uint16_type ())
1781  else if (is_uint8_type ())
1783  else
1784  retval = array_value (force_string_conv);
1785  }
1786  else
1787  {
1788  const NDArray a = array_value (force_string_conv);
1789  if (! error_state)
1790  {
1791  if (require_int)
1792  {
1793  retval.resize (a.dims ());
1794  for (octave_idx_type i = 0; i < a.numel (); i++)
1795  {
1796  double ai = a.elem (i);
1797  octave_idx_type v = static_cast<octave_idx_type> (ai);
1798  if (ai == v)
1799  retval.xelem (i) = v;
1800  else
1801  {
1802  error_with_cfn ("conversion to integer value failed");
1803  break;
1804  }
1805  }
1806  }
1807  else
1808  retval = Array<octave_idx_type> (a);
1809  }
1810  }
1811 
1812 
1813  if (error_state)
1814  return retval;
1815  else
1816  return retval.reshape (make_vector_dims (retval.dims (),
1817  force_vector_conversion,
1818  type_name (), "integer vector"));
1819 }
1820 
1822 octave_value::complex_vector_value (bool force_string_conv,
1823  bool force_vector_conversion) const
1824 {
1825  Array<Complex> retval = complex_array_value (force_string_conv);
1826 
1827  if (error_state)
1828  return retval;
1829  else
1830  return retval.reshape (make_vector_dims (retval.dims (),
1831  force_vector_conversion,
1832  type_name (), "complex vector"));
1833 }
1834 
1837  bool frc_vec_conv) const
1838 {
1839  return FloatColumnVector (float_vector_value (force_string_conv,
1840  frc_vec_conv));
1841 }
1842 
1845  bool frc_vec_conv) const
1846 {
1847  return
1849  frc_vec_conv));
1850 }
1851 
1854  bool frc_vec_conv) const
1855 {
1856  return FloatRowVector (float_vector_value (force_string_conv,
1857  frc_vec_conv));
1858 }
1859 
1862  bool frc_vec_conv) const
1863 {
1864  return FloatComplexRowVector (float_complex_vector_value (force_string_conv,
1865  frc_vec_conv));
1866 }
1867 
1869 octave_value::float_vector_value (bool force_string_conv,
1870  bool force_vector_conversion) const
1871 {
1872  Array<float> retval = float_array_value (force_string_conv);
1873 
1874  if (error_state)
1875  return retval;
1876  else
1877  return retval.reshape (make_vector_dims (retval.dims (),
1878  force_vector_conversion,
1879  type_name (), "real vector"));
1880 }
1881 
1884  bool force_vector_conversion) const
1885 {
1886  Array<FloatComplex> retval = float_complex_array_value (force_string_conv);
1887 
1888  if (error_state)
1889  return retval;
1890  else
1891  return retval.reshape (make_vector_dims (retval.dims (),
1892  force_vector_conversion,
1893  type_name (), "complex vector"));
1894 }
1895 
1898 {
1899  octave_value retval = *this;
1900  if (is_null_value ())
1901  retval = octave_value (rep->empty_clone ());
1902  else
1903  retval.maybe_economize ();
1904 
1905  return retval;
1906 }
1907 
1908 void
1910 {
1911  if (is_null_value ())
1912  {
1913  octave_base_value *rc = rep->empty_clone ();
1914  if (--rep->count == 0)
1915  delete rep;
1916  rep = rc;
1917  }
1918  else
1919  maybe_economize ();
1920 }
1921 
1922 int
1923 octave_value::write (octave_stream& os, int block_size,
1924  oct_data_conv::data_type output_type, int skip,
1925  oct_mach_info::float_format flt_fmt) const
1926 {
1927  return rep->write (os, block_size, output_type, skip, flt_fmt);
1928 }
1929 
1930 static void
1931 gripe_binary_op (const std::string& on, const std::string& tn1,
1932  const std::string& tn2)
1933 {
1934  error ("binary operator '%s' not implemented for '%s' by '%s' operations",
1935  on.c_str (), tn1.c_str (), tn2.c_str ());
1936 }
1937 
1938 static void
1939 gripe_binary_op_conv (const std::string& on)
1940 {
1941  error ("type conversion failed for binary operator '%s'", on.c_str ());
1942 }
1943 
1946  const octave_value& v1, const octave_value& v2)
1947 {
1948  octave_value retval;
1949 
1950  int t1 = v1.type_id ();
1951  int t2 = v2.type_id ();
1952 
1953  if (t1 == octave_class::static_type_id ()
1954  || t2 == octave_class::static_type_id ())
1955  {
1958 
1959  if (f)
1960  {
1961  try
1962  {
1963  retval = f (v1, v2);
1964  }
1965  catch (octave_execution_exception)
1966  {
1968  }
1969  }
1970  else
1972  v1.class_name (), v2.class_name ());
1973  }
1974  else
1975  {
1976  // FIXME: we need to handle overloading operators for built-in
1977  // classes (double, char, int8, etc.)
1978 
1981 
1982  if (f)
1983  {
1984  try
1985  {
1986  retval = f (*v1.rep, *v2.rep);
1987  }
1988  catch (octave_execution_exception)
1989  {
1991  }
1992  }
1993  else
1994  {
1995  octave_value tv1;
1998 
1999  octave_value tv2;
2002 
2003  // Try biased (one-sided) conversions first.
2004  if (cf2.type_id () >= 0 &&
2006  cf1 = 0;
2007  else if (cf1.type_id () >= 0
2009  cf1.type_id (),
2010  t2))
2011  cf2 = 0;
2012 
2013  if (cf1)
2014  {
2015  octave_base_value *tmp = cf1 (*v1.rep);
2016 
2017  if (tmp)
2018  {
2019  tv1 = octave_value (tmp);
2020  t1 = tv1.type_id ();
2021  }
2022  else
2023  {
2025  return retval;
2026  }
2027  }
2028  else
2029  tv1 = v1;
2030 
2031  if (cf2)
2032  {
2033  octave_base_value *tmp = cf2 (*v2.rep);
2034 
2035  if (tmp)
2036  {
2037  tv2 = octave_value (tmp);
2038  t2 = tv2.type_id ();
2039  }
2040  else
2041  {
2043  return retval;
2044  }
2045  }
2046  else
2047  tv2 = v2;
2048 
2049  if (cf1 || cf2)
2050  {
2051  retval = do_binary_op (op, tv1, tv2);
2052  }
2053  else
2054  {
2055  //demote double -> single and try again
2056  cf1 = tv1.numeric_demotion_function ();
2057 
2058  cf2 = tv2.numeric_demotion_function ();
2059 
2060  // Try biased (one-sided) conversions first.
2061  if (cf2.type_id () >= 0
2063  cf2.type_id ()))
2064  cf1 = 0;
2065  else if (cf1.type_id () >= 0 &&
2067  cf1.type_id (),
2068  t2))
2069  cf2 = 0;
2070 
2071  if (cf1)
2072  {
2073  octave_base_value *tmp = cf1 (*tv1.rep);
2074 
2075  if (tmp)
2076  {
2077  tv1 = octave_value (tmp);
2078  t1 = tv1.type_id ();
2079  }
2080  else
2081  {
2084  return retval;
2085  }
2086  }
2087 
2088  if (cf2)
2089  {
2090  octave_base_value *tmp = cf2 (*tv2.rep);
2091 
2092  if (tmp)
2093  {
2094  tv2 = octave_value (tmp);
2095  t2 = tv2.type_id ();
2096  }
2097  else
2098  {
2101  return retval;
2102  }
2103  }
2104 
2105  if (cf1 || cf2)
2106  {
2107  f = octave_value_typeinfo::lookup_binary_op (op, t1, t2);
2108 
2109  if (f)
2110  {
2111  try
2112  {
2113  retval = f (*tv1.rep, *tv2.rep);
2114  }
2115  catch (octave_execution_exception)
2116  {
2118  }
2119  }
2120  else
2122  v1.type_name (), v2.type_name ());
2123  }
2124  else
2126  v1.type_name (), v2.type_name ());
2127  }
2128  }
2129  }
2130 
2131  return retval;
2132 }
2133 
2134 static octave_value
2136  const octave_value& v1, const octave_value& v2)
2137 {
2138  octave_value retval;
2139 
2140  switch (op)
2141  {
2145  v2);
2146  break;
2149  v1,
2151  break;
2155  v2);
2156  break;
2159  v1,
2161  break;
2165  v2);
2166  break;
2170  v2);
2171  break;
2175  v2);
2176  break;
2180  v2);
2181  break;
2184  v1,
2186  break;
2189  v1,
2191  break;
2192  default:
2193  error ("invalid compound operator");
2194  break;
2195  }
2196 
2197  return retval;
2198 }
2199 
2202  const octave_value& v1, const octave_value& v2)
2203 {
2204  octave_value retval;
2205 
2206  int t1 = v1.type_id ();
2207  int t2 = v2.type_id ();
2208 
2209  if (t1 == octave_class::static_type_id ()
2210  || t2 == octave_class::static_type_id ())
2211  {
2214 
2215  if (f)
2216  {
2217  try
2218  {
2219  retval = f (v1, v2);
2220  }
2221  catch (octave_execution_exception)
2222  {
2224  }
2225  }
2226  else
2227  retval = decompose_binary_op (op, v1, v2);
2228  }
2229  else
2230  {
2233 
2234  if (f)
2235  {
2236  try
2237  {
2238  retval = f (*v1.rep, *v2.rep);
2239  }
2240  catch (octave_execution_exception)
2241  {
2243  }
2244  }
2245  else
2246  retval = decompose_binary_op (op, v1, v2);
2247  }
2248 
2249  return retval;
2250 }
2251 
2252 static void
2253 gripe_cat_op (const std::string& tn1, const std::string& tn2)
2254 {
2255  error ("concatenation operator not implemented for '%s' by '%s' operations",
2256  tn1.c_str (), tn2.c_str ());
2257 }
2258 
2259 static void
2261 {
2262  error ("type conversion failed for concatenation operator");
2263 }
2264 
2267  const Array<octave_idx_type>& ra_idx)
2268 {
2269  octave_value retval;
2270 
2271  // Can't rapid return for concatenation with an empty object here as
2272  // something like cat(1,[],single([]) must return the correct type.
2273 
2274  int t1 = v1.type_id ();
2275  int t2 = v2.type_id ();
2276 
2279 
2280  if (f)
2281  {
2282  try
2283  {
2284  retval = f (*v1.rep, *v2.rep, ra_idx);
2285  }
2286  catch (octave_execution_exception)
2287  {
2289  }
2290  }
2291  else
2292  {
2293  octave_value tv1;
2295 
2296  octave_value tv2;
2298 
2299  // Try biased (one-sided) conversions first.
2300  if (cf2.type_id () >= 0
2302  cf1 = 0;
2303  else if (cf1.type_id () >= 0
2305  cf2 = 0;
2306 
2307  if (cf1)
2308  {
2309  octave_base_value *tmp = cf1 (*v1.rep);
2310 
2311  if (tmp)
2312  {
2313  tv1 = octave_value (tmp);
2314  t1 = tv1.type_id ();
2315  }
2316  else
2317  {
2318  gripe_cat_op_conv ();
2319  return retval;
2320  }
2321  }
2322  else
2323  tv1 = v1;
2324 
2325  if (cf2)
2326  {
2327  octave_base_value *tmp = cf2 (*v2.rep);
2328 
2329  if (tmp)
2330  {
2331  tv2 = octave_value (tmp);
2332  t2 = tv2.type_id ();
2333  }
2334  else
2335  {
2336  gripe_cat_op_conv ();
2337  return retval;
2338  }
2339  }
2340  else
2341  tv2 = v2;
2342 
2343  if (cf1 || cf2)
2344  {
2345  retval = do_cat_op (tv1, tv2, ra_idx);
2346  }
2347  else
2348  gripe_cat_op (v1.type_name (), v2.type_name ());
2349  }
2350 
2351  return retval;
2352 }
2353 
2354 void
2355 octave_value::print_info (std::ostream& os, const std::string& prefix) const
2356 {
2357  os << prefix << "type_name: " << type_name () << "\n"
2358  << prefix << "count: " << get_count () << "\n"
2359  << prefix << "rep info: ";
2360 
2361  rep->print_info (os, prefix + " ");
2362 }
2363 
2364 static void
2365 gripe_unary_op (const std::string& on, const std::string& tn)
2366 {
2367  error ("unary operator '%s' not implemented for '%s' operands",
2368  on.c_str (), tn.c_str ());
2369 }
2370 
2371 static void
2372 gripe_unary_op_conv (const std::string& on)
2373 {
2374  error ("type conversion failed for unary operator '%s'", on.c_str ());
2375 }
2376 
2379 {
2380  octave_value retval;
2381 
2382  int t = v.type_id ();
2383 
2384  if (t == octave_class::static_type_id ())
2385  {
2388 
2389  if (f)
2390  {
2391  try
2392  {
2393  retval = f (v);
2394  }
2395  catch (octave_execution_exception)
2396  {
2398  }
2399  }
2400  else
2402  v.class_name ());
2403  }
2404  else
2405  {
2406  // FIXME: we need to handle overloading operators for built-in
2407  // classes (double, char, int8, etc.)
2408 
2411 
2412  if (f)
2413  {
2414  try
2415  {
2416  retval = f (*v.rep);
2417  }
2418  catch (octave_execution_exception)
2419  {
2421  }
2422  }
2423  else
2424  {
2425  octave_value tv;
2428 
2429  if (cf)
2430  {
2431  octave_base_value *tmp = cf (*v.rep);
2432 
2433  if (tmp)
2434  {
2435  tv = octave_value (tmp);
2436  retval = do_unary_op (op, tv);
2437  }
2438  else
2440  }
2441  else
2443  v.type_name ());
2444  }
2445  }
2446 
2447  return retval;
2448 }
2449 
2450 static void
2451 gripe_unary_op_conversion_failed (const std::string& op,
2452  const std::string& tn)
2453 {
2454  error ("operator %s: type conversion for '%s' failed",
2455  op.c_str (), tn.c_str ());
2456 }
2457 
2458 octave_value&
2460 {
2461  if (op == op_incr || op == op_decr)
2462  {
2463  // We want the gripe just here, because in the other branch this should
2464  // not happen, and if it did anyway (internal error), the message would
2465  // be confusing.
2466  if (is_undefined ())
2467  {
2468  std::string op_str = unary_op_as_string (op);
2469  error ("in x%s or %sx, x must be defined first",
2470  op_str.c_str (), op_str.c_str ());
2471  return *this;
2472  }
2473 
2474  // Genuine.
2475  int t = type_id ();
2476 
2479 
2480  if (f)
2481  {
2482  make_unique ();
2483 
2484  try
2485  {
2486  f (*rep);
2487  }
2488  catch (octave_execution_exception)
2489  {
2491  }
2492  }
2493  else
2494  {
2496 
2497  if (cf)
2498  {
2499  octave_base_value *tmp = cf (*rep);
2500 
2501  if (tmp)
2502  {
2503  octave_base_value *old_rep = rep;
2504  rep = tmp;
2505 
2506  t = type_id ();
2507 
2509 
2510  if (f)
2511  {
2512  try
2513  {
2514  f (*rep);
2515  }
2516  catch (octave_execution_exception)
2517  {
2519  }
2520 
2521  if (old_rep && --old_rep->count == 0)
2522  delete old_rep;
2523  }
2524  else
2525  {
2526  if (old_rep)
2527  {
2528  if (--rep->count == 0)
2529  delete rep;
2530 
2531  rep = old_rep;
2532  }
2533 
2535  type_name ());
2536  }
2537  }
2538  else
2541  }
2542  else
2544  type_name ());
2545  }
2546  }
2547  else
2548  {
2549  // Non-genuine.
2550  int t = type_id ();
2551 
2553 
2554  // Only attempt to operate in-place if this variable is unshared.
2555  if (rep->count == 1)
2557 
2558  if (f)
2559  {
2560  try
2561  {
2562  f (*rep);
2563  }
2564  catch (octave_execution_exception)
2565  {
2567  }
2568  }
2569  else
2570  *this = do_unary_op (op, *this);
2571  }
2572 
2573  return *this;
2574 }
2575 
2576 octave_value&
2577 octave_value::do_non_const_unary_op (unary_op op, const std::string& type,
2578  const std::list<octave_value_list>& idx)
2579 {
2580  if (idx.empty ())
2581  do_non_const_unary_op (op);
2582  else
2583  {
2584  // FIXME: only do the following stuff if we can't find a
2585  // specific function to call to handle the op= operation for the
2586  // types we have.
2587 
2588  assign_op assop = unary_op_to_assign_op (op);
2589 
2590  assign (assop, type, idx, 1.0);
2591  }
2592 
2593  return *this;
2594 }
2595 
2598 {
2599  assign_op binop = unknown_assign_op;
2600 
2601  switch (op)
2602  {
2603  case op_incr:
2604  binop = op_add_eq;
2605  break;
2606 
2607  case op_decr:
2608  binop = op_sub_eq;
2609  break;
2610 
2611  default:
2612  {
2613  std::string on = unary_op_as_string (op);
2614  error ("operator %s: no assign operator found", on.c_str ());
2615  }
2616  }
2617 
2618  return binop;
2619 }
2620 
2623 {
2624  binary_op binop = unknown_binary_op;
2625 
2626  switch (op)
2627  {
2628  case op_add_eq:
2629  binop = op_add;
2630  break;
2631 
2632  case op_sub_eq:
2633  binop = op_sub;
2634  break;
2635 
2636  case op_mul_eq:
2637  binop = op_mul;
2638  break;
2639 
2640  case op_div_eq:
2641  binop = op_div;
2642  break;
2643 
2644  case op_ldiv_eq:
2645  binop = op_ldiv;
2646  break;
2647 
2648  case op_pow_eq:
2649  binop = op_pow;
2650  break;
2651 
2652  case op_lshift_eq:
2653  binop = op_lshift;
2654  break;
2655 
2656  case op_rshift_eq:
2657  binop = op_rshift;
2658  break;
2659 
2660  case op_el_mul_eq:
2661  binop = op_el_mul;
2662  break;
2663 
2664  case op_el_div_eq:
2665  binop = op_el_div;
2666  break;
2667 
2668  case op_el_ldiv_eq:
2669  binop = op_el_ldiv;
2670  break;
2671 
2672  case op_el_pow_eq:
2673  binop = op_el_pow;
2674  break;
2675 
2676  case op_el_and_eq:
2677  binop = op_el_and;
2678  break;
2679 
2680  case op_el_or_eq:
2681  binop = op_el_or;
2682  break;
2683 
2684  default:
2685  {
2686  std::string on = assign_op_as_string (op);
2687  error ("operator %s: no binary operator found", on.c_str ());
2688  }
2689  }
2690 
2691  return binop;
2692 }
2693 
2695 octave_value::empty_conv (const std::string& type, const octave_value& rhs)
2696 {
2697  octave_value retval;
2698 
2699  if (type.length () > 0)
2700  {
2701  switch (type[0])
2702  {
2703  case '(':
2704  {
2705  if (type.length () > 1 && type[1] == '.')
2706  retval = octave_map ();
2707  else
2708  retval = octave_value (rhs.empty_clone ());
2709  }
2710  break;
2711 
2712  case '{':
2713  retval = Cell ();
2714  break;
2715 
2716  case '.':
2717  retval = octave_scalar_map ();
2718  break;
2719 
2720  default:
2721  panic_impossible ();
2722  }
2723  }
2724  else
2725  retval = octave_value (rhs.empty_clone ());
2726 
2727  return retval;
2728 }
2729 
2730 void
2732 {
2746  octave_int8_scalar::register_type ();
2747  octave_int16_scalar::register_type ();
2748  octave_int32_scalar::register_type ();
2749  octave_int64_scalar::register_type ();
2750  octave_uint8_scalar::register_type ();
2751  octave_uint16_scalar::register_type ();
2752  octave_uint32_scalar::register_type ();
2753  octave_uint64_scalar::register_type ();
2754  octave_int8_matrix::register_type ();
2755  octave_int16_matrix::register_type ();
2756  octave_int32_matrix::register_type ();
2757  octave_int64_matrix::register_type ();
2758  octave_uint8_matrix::register_type ();
2759  octave_uint16_matrix::register_type ();
2760  octave_uint32_matrix::register_type ();
2761  octave_uint64_matrix::register_type ();
2787 #ifdef HAVE_JAVA
2789 #endif
2790 }
2791 
2792 DEFUN (sizeof, args, ,
2793  "-*- texinfo -*-\n\
2794 @deftypefn {Built-in Function} {} sizeof (@var{val})\n\
2795 Return the size of @var{val} in bytes.\n\
2796 @seealso{whos}\n\
2797 @end deftypefn")
2798 {
2799  octave_value retval;
2800 
2801  if (args.length () == 1)
2802  retval = args(0).byte_size ();
2803  else
2804  print_usage ();
2805 
2806  return retval;
2807 }
2808 
2809 /*
2810 %!assert (sizeof (uint64 (ones (3))), 72)
2811 %!assert (sizeof (double (zeros (2,4))), 64)
2812 %!assert (sizeof ({"foo", "bar", "baaz"}), 10)
2813 */
2814 
2815 static void
2816 decode_subscripts (const char* name, const octave_value& arg,
2817  std::string& type_string,
2818  std::list<octave_value_list>& idx)
2819 {
2820  const octave_map m = arg.map_value ();
2821 
2822  if (! error_state
2823  && m.nfields () == 2 && m.contains ("type") && m.contains ("subs"))
2824  {
2825  octave_idx_type nel = m.numel ();
2826 
2827  type_string = std::string (nel, '\0');
2828  idx = std::list<octave_value_list> ();
2829 
2830  if (nel == 0)
2831  return;
2832 
2833  const Cell type = m.contents ("type");
2834  const Cell subs = m.contents ("subs");
2835 
2836  for (int k = 0; k < nel; k++)
2837  {
2838  std::string item = type(k).string_value ();
2839 
2840  if (! error_state)
2841  {
2842  if (item == "{}")
2843  type_string[k] = '{';
2844  else if (item == "()")
2845  type_string[k] = '(';
2846  else if (item == ".")
2847  type_string[k] = '.';
2848  else
2849  {
2850  error ("%s: invalid indexing type '%s'", name, item.c_str ());
2851  return;
2852  }
2853  }
2854  else
2855  {
2856  error ("%s: expecting type(%d) to be a character string",
2857  name, k+1);
2858  return;
2859  }
2860 
2861  octave_value_list idx_item;
2862 
2863  if (subs(k).is_string ())
2864  idx_item(0) = subs(k);
2865  else if (subs(k).is_cell ())
2866  {
2867  Cell subs_cell = subs(k).cell_value ();
2868 
2869  for (int n = 0; n < subs_cell.length (); n++)
2870  {
2871  if (subs_cell(n).is_string ()
2872  && subs_cell(n).string_value () == ":")
2874  else
2875  idx_item(n) = subs_cell(n);
2876  }
2877  }
2878  else
2879  {
2880  error ("%s: expecting subs(%d) to be a character string or cell array",
2881  name, k+1);
2882  return;
2883  }
2884 
2885  idx.push_back (idx_item);
2886  }
2887  }
2888  else
2889  error ("%s: second argument must be a structure with fields 'type' and 'subs'",
2890  name);
2891 }
2892 
2893 DEFUN (subsref, args, nargout,
2894  "-*- texinfo -*-\n\
2895 @deftypefn {Built-in Function} {} subsref (@var{val}, @var{idx})\n\
2896 Perform the subscripted element selection operation according to\n\
2897 the subscript specified by @var{idx}.\n\
2898 \n\
2899 The subscript @var{idx} is expected to be a structure array with\n\
2900 fields @samp{type} and @samp{subs}. Valid values for @samp{type}\n\
2901 are @samp{\"()\"}, @samp{\"@{@}\"}, and @samp{\".\"}.\n\
2902 The @samp{subs} field may be either @samp{\":\"} or a cell array\n\
2903 of index values.\n\
2904 \n\
2905 The following example shows how to extract the two first columns of\n\
2906 a matrix\n\
2907 \n\
2908 @example\n\
2909 @group\n\
2910 val = magic (3)\n\
2911  @result{} val = [ 8 1 6\n\
2912  3 5 7\n\
2913  4 9 2 ]\n\
2914 idx.type = \"()\";\n\
2915 idx.subs = @{\":\", 1:2@};\n\
2916 subsref (val, idx)\n\
2917  @result{} [ 8 1\n\
2918  3 5\n\
2919  4 9 ]\n\
2920 @end group\n\
2921 @end example\n\
2922 \n\
2923 @noindent\n\
2924 Note that this is the same as writing @code{val(:,1:2)}.\n\
2925 \n\
2926 If @var{idx} is an empty structure array with fields @samp{type}\n\
2927 and @samp{subs}, return @var{val}.\n\
2928 @seealso{subsasgn, substruct}\n\
2929 @end deftypefn")
2930 {
2931  octave_value_list retval;
2932 
2933  if (args.length () == 2)
2934  {
2935  std::string type;
2936  std::list<octave_value_list> idx;
2937 
2938  decode_subscripts ("subsref", args(1), type, idx);
2939 
2940  if (! error_state)
2941  {
2942  octave_value arg0 = args(0);
2943 
2944  if (type.empty ())
2945  retval = arg0;
2946  else
2947  retval = arg0.subsref (type, idx, nargout);
2948  }
2949  }
2950  else
2951  print_usage ();
2952 
2953  return retval;
2954 }
2955 
2956 DEFUN (subsasgn, args, ,
2957  "-*- texinfo -*-\n\
2958 @deftypefn {Built-in Function} {} subsasgn (@var{val}, @var{idx}, @var{rhs})\n\
2959 Perform the subscripted assignment operation according to\n\
2960 the subscript specified by @var{idx}.\n\
2961 \n\
2962 The subscript @var{idx} is expected to be a structure array with\n\
2963 fields @samp{type} and @samp{subs}. Valid values for @samp{type}\n\
2964 are @samp{\"()\"}, @samp{\"@{@}\"}, and @samp{\".\"}.\n\
2965 The @samp{subs} field may be either @samp{\":\"} or a cell array\n\
2966 of index values.\n\
2967 \n\
2968 The following example shows how to set the two first columns of a\n\
2969 3-by-3 matrix to zero.\n\
2970 \n\
2971 @example\n\
2972 @group\n\
2973 val = magic (3);\n\
2974 idx.type = \"()\";\n\
2975 idx.subs = @{\":\", 1:2@};\n\
2976 subsasgn (val, idx, 0)\n\
2977  @result{} [ 0 0 6\n\
2978  0 0 7\n\
2979  0 0 2 ]\n\
2980 @end group\n\
2981 @end example\n\
2982 \n\
2983 Note that this is the same as writing @code{val(:,1:2) = 0}.\n\
2984 \n\
2985 If @var{idx} is an empty structure array with fields @samp{type}\n\
2986 and @samp{subs}, return @var{rhs}.\n\
2987 @seealso{subsref, substruct}\n\
2988 @end deftypefn")
2989 {
2990  octave_value retval;
2991 
2992  if (args.length () == 3)
2993  {
2994  std::string type;
2995  std::list<octave_value_list> idx;
2996 
2997  decode_subscripts ("subsasgn", args(1), type, idx);
2998 
2999  if (! error_state)
3000  {
3001  if (type.empty ())
3002  {
3003  // Regularize a null matrix if stored into a variable.
3004 
3005  retval = args(2).storable_value ();
3006  }
3007  else
3008  {
3009  octave_value arg0 = args(0);
3010 
3011  arg0.make_unique ();
3012 
3013  if (! error_state)
3014  retval= arg0.subsasgn (type, idx, args(2));
3015  }
3016  }
3017  }
3018  else
3019  print_usage ();
3020 
3021  return retval;
3022 }
3023 
3024 /*
3025 %!test
3026 %! a = reshape ([1:25], 5,5);
3027 %! idx1 = substruct ("()", {3, 3});
3028 %! idx2 = substruct ("()", {2:2:5, 2:2:5});
3029 %! idx3 = substruct ("()", {":", [1,5]});
3030 %! idx4 = struct ("type", {}, "subs", {});
3031 %! assert (subsref (a, idx1), 13);
3032 %! assert (subsref (a, idx2), [7 17; 9 19]);
3033 %! assert (subsref (a, idx3), [1:5; 21:25]');
3034 %! assert (subsref (a, idx4), a);
3035 %! a = subsasgn (a, idx1, 0);
3036 %! a = subsasgn (a, idx2, 0);
3037 %! a = subsasgn (a, idx3, 0);
3038 %!# a = subsasgn (a, idx4, 0);
3039 %! b = [0 6 11 16 0
3040 %! 0 0 12 0 0
3041 %! 0 8 0 18 0
3042 %! 0 0 14 0 0
3043 %! 0 10 15 20 0];
3044 %! assert (a, b);
3045 
3046 %!test
3047 %! c = num2cell (reshape ([1:25],5,5));
3048 %! idx1 = substruct ("{}", {3, 3});
3049 %! idx2 = substruct ("()", {2:2:5, 2:2:5});
3050 %! idx3 = substruct ("()", {":", [1,5]});
3051 %! idx2p = substruct ("{}", {2:2:5, 2:2:5});
3052 %! idx3p = substruct ("{}", {":", [1,5]});
3053 %! idx4 = struct ("type", {}, "subs", {});
3054 %! assert ({ subsref(c, idx1) }, {13});
3055 %! assert ({ subsref(c, idx2p) }, {7 9 17 19});
3056 %! assert ({ subsref(c, idx3p) }, num2cell ([1:5, 21:25]));
3057 %! assert (subsref (c, idx4), c);
3058 %! c = subsasgn (c, idx1, 0);
3059 %! c = subsasgn (c, idx2, 0);
3060 %! c = subsasgn (c, idx3, 0);
3061 %!# c = subsasgn (c, idx4, 0);
3062 %! d = {0 6 11 16 0
3063 %! 0 0 12 0 0
3064 %! 0 8 0 18 0
3065 %! 0 0 14 0 0
3066 %! 0 10 15 20 0};
3067 %! assert (c, d);
3068 
3069 %!test
3070 %! s.a = "ohai";
3071 %! s.b = "dere";
3072 %! s.c = 42;
3073 %! idx1 = substruct (".", "a");
3074 %! idx2 = substruct (".", "b");
3075 %! idx3 = substruct (".", "c");
3076 %! idx4 = struct ("type", {}, "subs", {});
3077 %! assert (subsref (s, idx1), "ohai");
3078 %! assert (subsref (s, idx2), "dere");
3079 %! assert (subsref (s, idx3), 42);
3080 %! assert (subsref (s, idx4), s);
3081 %! s = subsasgn (s, idx1, "Hello");
3082 %! s = subsasgn (s, idx2, "There");
3083 %! s = subsasgn (s, idx3, 163);
3084 %!# s = subsasgn (s, idx4, 163);
3085 %! t.a = "Hello";
3086 %! t.b = "There";
3087 %! t.c = 163;
3088 %! assert (s, t);
3089 */
3090 
3091 DEFUN (is_sq_string, args, ,
3092  "-*- texinfo -*-\n\
3093 @deftypefn {Built-in Function} {} is_sq_string (@var{x})\n\
3094 Return true if @var{x} is a single-quoted character string.\n\
3095 @seealso{is_dq_string, ischar}\n\
3096 @end deftypefn")
3097 {
3098  octave_value retval;
3099 
3100  if (args.length () == 1)
3101  retval = args(0).is_sq_string ();
3102  else
3103  print_usage ();
3104 
3105  return retval;
3106 }
3107 
3108 /*
3109 %!assert (is_sq_string ('foo'), true)
3110 %!assert (is_sq_string ("foo"), false)
3111 %!assert (is_sq_string (1.0), false)
3112 %!assert (is_sq_string ({2.0}), false)
3113 
3114 %!error is_sq_string ()
3115 %!error is_sq_string ('foo', 2)
3116 */
3117 
3118 DEFUN (is_dq_string, args, ,
3119  "-*- texinfo -*-\n\
3120 @deftypefn {Built-in Function} {} is_dq_string (@var{x})\n\
3121 Return true if @var{x} is a double-quoted character string.\n\
3122 @seealso{is_sq_string, ischar}\n\
3123 @end deftypefn")
3124 {
3125  octave_value retval;
3126 
3127  if (args.length () == 1)
3128  retval = args(0).is_dq_string ();
3129  else
3130  print_usage ();
3131 
3132  return retval;
3133 }
3134 
3135 /*
3136 %!assert (is_dq_string ("foo"), true)
3137 %!assert (is_dq_string ('foo'), false)
3138 %!assert (is_dq_string (1.0), false)
3139 %!assert (is_dq_string ({2.0}), false)
3140 
3141 %!error is_dq_string ()
3142 %!error is_dq_string ("foo", 2)
3143 */