changelog shortlog tags changeset files revisions annotate raw

src/ov.cc

changeset 10289: 4b124317dc38
parent:cd96d29c5efa
author: John W. Eaton <jwe@octave.org>
date: Tue Feb 09 20:58:55 2010 -0500 (27 minutes ago)
permissions: -rw-r--r--
description: base_properties::set_children: account for hidden children
1/*
2
3Copyright (C) 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005,
4 2006, 2007, 2008, 2009 John W. Eaton
5
6This file is part of Octave.
7
8Octave is free software; you can redistribute it and/or modify it
9under the terms of the GNU General Public License as published by the
10Free Software Foundation; either version 3 of the License, or (at your
11option) any later version.
12
13Octave is distributed in the hope that it will be useful, but WITHOUT
14ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
19along 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-cs-list.h"
69#include "ov-colon.h"
70#include "ov-builtin.h"
71#include "ov-dld-fcn.h"
72#include "ov-usr-fcn.h"
73#include "ov-fcn-handle.h"
74#include "ov-fcn-inline.h"
75#include "ov-typeinfo.h"
76#include "ov-null-mat.h"
77
78#include "defun.h"
79#include "error.h"
80#include "gripes.h"
81#include "pager.h"
82#include "parse.h"
83#include "pr-output.h"
84#include "symtab.h"
85#include "utils.h"
86#include "variables.h"
87
88// We are likely to have a lot of octave_value objects to allocate, so
89// make the grow_size large.
90DEFINE_OCTAVE_ALLOCATOR2(octave_value, 1024);
91
92// FIXME
93
94// Octave's value type.
95
96std::string
97octave_value::unary_op_as_string (unary_op op)
98{
99 std::string retval;
100
101 switch (op)
102 {
103 case op_not:
104 retval = "!";
105 break;
106
107 case op_uplus:
108 retval = "+";
109 break;
110
111 case op_uminus:
112 retval = "-";
113 break;
114
115 case op_transpose:
116 retval = ".'";
117 break;
118
119 case op_hermitian:
120 retval = "'";
121 break;
122
123 case op_incr:
124 retval = "++";
125 break;
126
127 case op_decr:
128 retval = "--";
129 break;
130
131 default:
132 retval = "<unknown>";
133 }
134
135 return retval;
136}
137
138std::string
139octave_value::unary_op_fcn_name (unary_op op)
140{
141 std::string retval;
142
143 switch (op)
144 {
145 case op_not:
146 retval = "not";
147 break;
148
149 case op_uplus:
150 retval = "uplus";
151 break;
152
153 case op_uminus:
154 retval = "uminus";
155 break;
156
157 case op_transpose:
158 retval = "transpose";
159 break;
160
161 case op_hermitian:
162 retval = "ctranspose";
163 break;
164
165 default:
166 break;
167 }
168
169 return retval;
170}
171
172std::string
173octave_value::binary_op_as_string (binary_op op)
174{
175 std::string retval;
176
177 switch (op)
178 {
179 case op_add:
180 retval = "+";
181 break;
182
183 case op_sub:
184 retval = "-";
185 break;
186
187 case op_mul:
188 retval = "*";
189 break;
190
191 case op_div:
192 retval = "/";
193 break;
194
195 case op_pow:
196 retval = "^";
197 break;
198
199 case op_ldiv:
200 retval = "\\";
201 break;
202
203 case op_lshift:
204 retval = "<<";
205 break;
206
207 case op_rshift:
208 retval = ">>";
209 break;
210
211 case op_lt:
212 retval = "<";
213 break;
214
215 case op_le:
216 retval = "<=";
217 break;
218
219 case op_eq:
220 retval = "==";
221 break;
222
223 case op_ge:
224 retval = ">=";
225 break;
226
227 case op_gt:
228 retval = ">";
229 break;
230
231 case op_ne:
232 retval = "!=";
233 break;
234
235 case op_el_mul:
236 retval = ".*";
237 break;
238
239 case op_el_div:
240 retval = "./";
241 break;
242
243 case op_el_pow:
244 retval = ".^";
245 break;
246
247 case op_el_ldiv:
248 retval = ".\\";
249 break;
250
251 case op_el_and:
252 retval = "&";
253 break;
254
255 case op_el_or:
256 retval = "|";
257 break;
258
259 case op_struct_ref:
260 retval = ".";
261 break;
262
263 default:
264 retval = "<unknown>";
265 }
266
267 return retval;
268}
269
270std::string
271octave_value::binary_op_fcn_name (binary_op op)
272{
273 std::string retval;
274
275 switch (op)
276 {
277 case op_add:
278 retval = "plus";
279 break;
280
281 case op_sub:
282 retval = "minus";
283 break;
284
285 case op_mul:
286 retval = "mtimes";
287 break;
288
289 case op_div:
290 retval = "mrdivide";
291 break;
292
293 case op_pow:
294 retval = "mpower";
295 break;
296
297 case op_ldiv:
298 retval = "mldivide";
299 break;
300
301 case op_lt:
302 retval = "lt";
303 break;
304
305 case op_le:
306 retval = "le";
307 break;
308
309 case op_eq:
310 retval = "eq";
311 break;
312
313 case op_ge:
314 retval = "ge";
315 break;
316
317 case op_gt:
318 retval = "gt";
319 break;
320
321 case op_ne:
322 retval = "ne";
323 break;
324
325 case op_el_mul:
326 retval = "times";
327 break;
328
329 case op_el_div:
330 retval = "rdivide";
331 break;
332
333 case op_el_pow:
334 retval = "power";
335 break;
336
337 case op_el_ldiv:
338 retval = "ldivide";
339 break;
340
341 case op_el_and:
342 retval = "and";
343 break;
344
345 case op_el_or:
346 retval = "or";
347 break;
348
349 default:
350 break;
351 }
352
353 return retval;
354}
355
356std::string
357octave_value::binary_op_fcn_name (compound_binary_op op)
358{
359 std::string retval;
360
361 switch (op)
362 {
363 case op_trans_mul:
364 retval = "transtimes";
365 break;
366
367 case op_mul_trans:
368 retval = "timestrans";
369 break;
370
371 case op_herm_mul:
372 retval = "hermtimes";
373 break;
374
375 case op_mul_herm:
376 retval = "timesherm";
377 break;
378
379 case op_trans_ldiv:
380 retval = "transldiv";
381 break;
382
383 case op_herm_ldiv:
384 retval = "hermldiv";
385 break;
386
387 case op_el_and_not:
388 retval = "andnot";
389 break;
390
391 case op_el_or_not:
392 retval = "ornot";
393 break;
394
395 case op_el_not_and:
396 retval = "notand";
397 break;
398
399 case op_el_not_or:
400 retval = "notor";
401 break;
402
403 default:
404 break;
405 }
406
407 return retval;
408}
409
410std::string
411octave_value::assign_op_as_string (assign_op op)
412{
413 std::string retval;
414
415 switch (op)
416 {
417 case op_asn_eq:
418 retval = "=";
419 break;
420
421 case op_add_eq:
422 retval = "+=";
423 break;
424
425 case op_sub_eq:
426 retval = "-=";
427 break;
428
429 case op_mul_eq:
430 retval = "*=";
431 break;
432
433 case op_div_eq:
434 retval = "/=";
435 break;
436
437 case op_ldiv_eq:
438 retval = "\\=";
439 break;
440
441 case op_pow_eq:
442 retval = "^=";
443 break;
444
445 case op_lshift_eq:
446 retval = "<<=";
447 break;
448
449 case op_rshift_eq:
450 retval = ">>=";
451 break;
452
453 case op_el_mul_eq:
454 retval = ".*=";
455 break;
456
457 case op_el_div_eq:
458 retval = "./=";
459 break;
460
461 case op_el_ldiv_eq:
462 retval = ".\\=";
463 break;
464
465 case op_el_pow_eq:
466 retval = ".^=";
467 break;
468
469 case op_el_and_eq:
470 retval = "&=";
471 break;
472
473 case op_el_or_eq:
474 retval = "|=";
475 break;
476
477 default:
478 retval = "<unknown>";
479 }
480
481 return retval;
482}
483
484octave_value::assign_op
485octave_value::binary_op_to_assign_op (binary_op op)
486{
487 assign_op retval;
488
489 switch (op)
490 {
491 case op_add:
492 retval = op_add_eq;
493 break;
494 case op_sub:
495 retval = op_sub_eq;
496 break;
497 case op_mul:
498 retval = op_mul_eq;
499 break;
500 case op_div:
501 retval = op_div_eq;
502 break;
503 case op_el_mul:
504 retval = op_el_mul_eq;
505 break;
506 case op_el_div:
507 retval = op_el_div_eq;
508 break;
509 case op_el_and:
510 retval = op_el_and_eq;
511 break;
512 case op_el_or:
513 retval = op_el_or_eq;
514 break;
515 default:
516 retval = unknown_assign_op;
517 }
518
519 return retval;
520}
521
522octave_value::octave_value (short int i)
523 : rep (new octave_scalar (i))
524{
525}
526
527octave_value::octave_value (unsigned short int i)
528 : rep (new octave_scalar (i))
529{
530}
531
532octave_value::octave_value (int i)
533 : rep (new octave_scalar (i))
534{
535}
536
537octave_value::octave_value (unsigned int i)
538 : rep (new octave_scalar (i))
539{
540}
541
542octave_value::octave_value (long int i)
543 : rep (new octave_scalar (i))
544{
545}
546
547octave_value::octave_value (unsigned long int i)
548 : rep (new octave_scalar (i))
549{
550}
551
552#if defined (HAVE_LONG_LONG_INT)
553octave_value::octave_value (long long int i)
554 : rep (new octave_scalar (i))
555{
556}
557#endif
558
559#if defined (HAVE_UNSIGNED_LONG_LONG_INT)
560octave_value::octave_value (unsigned long long int i)
561 : rep (new octave_scalar (i))
562{
563}
564#endif
565
566octave_value::octave_value (octave_time t)
567 : rep (new octave_scalar (t.double_value ()))
568{
569}
570
571octave_value::octave_value (double d)
572 : rep (new octave_scalar (d))
573{
574}
575
576octave_value::octave_value (float d)
577 : rep (new octave_float_scalar (d))
578{
579}
580
581octave_value::octave_value (const Cell& c, bool is_csl)
582 : rep (is_csl
583 ? dynamic_cast<octave_base_value *> (new octave_cs_list (c))
584 : dynamic_cast<octave_base_value *> (new octave_cell (c)))
585{
586}
587
588octave_value::octave_value (const Array<octave_value>& a, bool is_csl)
589 : rep (is_csl
590 ? dynamic_cast<octave_base_value *> (new octave_cs_list (Cell (a)))
591 : dynamic_cast<octave_base_value *> (new octave_cell (Cell (a))))
592{
593}
594
595octave_value::octave_value (const Matrix& m, const MatrixType& t)
596 : rep (new octave_matrix (m, t))
597{
598 maybe_mutate ();
599}
600
601octave_value::octave_value (const FloatMatrix& m, const MatrixType& t)
602 : rep (new octave_float_matrix (m, t))
603{
604 maybe_mutate ();
605}
606
607octave_value::octave_value (const NDArray& a)
608 : rep (new octave_matrix (a))
609{
610 maybe_mutate ();
611}
612
613octave_value::octave_value (const FloatNDArray& a)
614 : rep (new octave_float_matrix (a))
615{
616 maybe_mutate ();
617}
618
619octave_value::octave_value (const Array<double>& a)
620 : rep (new octave_matrix (a))
621{
622 maybe_mutate ();
623}
624
625octave_value::octave_value (const Array<float>& a)
626 : rep (new octave_float_matrix (a))
627{
628 maybe_mutate ();
629}
630
631octave_value::octave_value (const DiagMatrix& d)
632 : rep (new octave_diag_matrix (d))
633{
634 maybe_mutate ();
635}
636
637octave_value::octave_value (const FloatDiagMatrix& d)
638 : rep (new octave_float_diag_matrix (d))
639{
640 maybe_mutate ();
641}
642
643octave_value::octave_value (const RowVector& v)
644 : rep (new octave_matrix (v))
645{
646 maybe_mutate ();
647}
648
649octave_value::octave_value (const FloatRowVector& v)
650 : rep (new octave_float_matrix (v))
651{
652 maybe_mutate ();
653}
654
655octave_value::octave_value (const ColumnVector& v)
656 : rep (new octave_matrix (v))
657{
658 maybe_mutate ();
659}
660
661octave_value::octave_value (const FloatColumnVector& v)
662 : rep (new octave_float_matrix (v))
663{
664 maybe_mutate ();
665}
666
667octave_value::octave_value (const Complex& C)
668 : rep (new octave_complex (C))
669{
670 maybe_mutate ();
671}
672
673octave_value::octave_value (const FloatComplex& C)
674 : rep (new octave_float_complex (C))
675{
676 maybe_mutate ();
677}
678
679octave_value::octave_value (const ComplexMatrix& m, const MatrixType& t)
680 : rep (new octave_complex_matrix (m, t))
681{
682 maybe_mutate ();
683}
684
685octave_value::octave_value (const FloatComplexMatrix& m, const MatrixType& t)
686 : rep (new octave_float_complex_matrix (m, t))
687{
688 maybe_mutate ();
689}
690
691octave_value::octave_value (const ComplexNDArray& a)
692 : rep (new octave_complex_matrix (a))
693{
694 maybe_mutate ();
695}
696
697octave_value::octave_value (const FloatComplexNDArray& a)
698 : rep (new octave_float_complex_matrix (a))
699{
700 maybe_mutate ();
701}
702
703octave_value::octave_value (const Array<Complex>& a)
704 : rep (new octave_complex_matrix (a))
705{
706 maybe_mutate ();
707}
708
709octave_value::octave_value (const Array<FloatComplex>& a)
710 : rep (new octave_float_complex_matrix (a))
711{
712 maybe_mutate ();
713}
714
715octave_value::octave_value (const ComplexDiagMatrix& d)
716 : rep (new octave_complex_diag_matrix (d))
717{
718 maybe_mutate ();
719}
720
721octave_value::octave_value (const FloatComplexDiagMatrix& d)
722 : rep (new octave_float_complex_diag_matrix (d))
723{
724 maybe_mutate ();
725}
726
727octave_value::octave_value (const ComplexRowVector& v)
728 : rep (new octave_complex_matrix (v))
729{
730 maybe_mutate ();
731}
732
733octave_value::octave_value (const FloatComplexRowVector& v)
734 : rep (new octave_float_complex_matrix (v))
735{
736 maybe_mutate ();
737}
738
739octave_value::octave_value (const ComplexColumnVector& v)
740 : rep (new octave_complex_matrix (v))
741{
742 maybe_mutate ();
743}
744
745octave_value::octave_value (const FloatComplexColumnVector& v)
746 : rep (new octave_float_complex_matrix (v))
747{
748 maybe_mutate ();
749}
750
751octave_value::octave_value (const PermMatrix& p)
752 : rep (new octave_perm_matrix (p))
753{
754 maybe_mutate ();
755}
756
757octave_value::octave_value (bool b)
758 : rep (new octave_bool (b))
759{
760}
761
762octave_value::octave_value (const boolMatrix& bm, const MatrixType& t)
763 : rep (new octave_bool_matrix (bm, t))
764{
765 maybe_mutate ();
766}
767
768octave_value::octave_value (const boolNDArray& bnda)
769 : rep (new octave_bool_matrix (bnda))
770{
771 maybe_mutate ();
772}
773
774octave_value::octave_value (const Array<bool>& bnda)
775 : rep (new octave_bool_matrix (bnda))
776{
777 maybe_mutate ();
778}
779
780octave_value::octave_value (char c, char type)
781 : rep (type == '"'
782 ? new octave_char_matrix_dq_str (c)
783 : new octave_char_matrix_sq_str (c))
784{
785 maybe_mutate ();
786}
787
788octave_value::octave_value (const char *s, char type)
789 : rep (type == '"'
790 ? new octave_char_matrix_dq_str (s)
791 : new octave_char_matrix_sq_str (s))
792{
793 maybe_mutate ();
794}
795
796octave_value::octave_value (const std::string& s, char type)
797 : rep (type == '"'
798 ? new octave_char_matrix_dq_str (s)
799 : new octave_char_matrix_sq_str (s))
800{
801 maybe_mutate ();
802}
803
804octave_value::octave_value (const string_vector& s, char type)
805 : rep (type == '"'
806 ? new octave_char_matrix_dq_str (s)
807 : new octave_char_matrix_sq_str (s))
808{
809 maybe_mutate ();
810}
811
812octave_value::octave_value (const charMatrix& chm, char type)
813 : rep (type == '"'
814 ? new octave_char_matrix_dq_str (chm)
815 : new octave_char_matrix_sq_str (chm))
816{
817 maybe_mutate ();
818}
819
820octave_value::octave_value (const charNDArray& chm, char type)
821 : rep (type == '"'
822 ? new octave_char_matrix_dq_str (chm)
823 : new octave_char_matrix_sq_str (chm))
824{
825 maybe_mutate ();
826}
827
828octave_value::octave_value (const Array<char>& chm, char type)
829 : rep (type == '"'
830 ? new octave_char_matrix_dq_str (chm)
831 : new octave_char_matrix_sq_str (chm))
832{
833 maybe_mutate ();
834}
835
836octave_value::octave_value (const charMatrix& chm, bool, char type)
837 : rep (type == '"'
838 ? new octave_char_matrix_dq_str (chm)
839 : new octave_char_matrix_sq_str (chm))
840{
841 maybe_mutate ();
842}
843
844octave_value::octave_value (const charNDArray& chm, bool, char type)
845 : rep (type == '"'
846 ? new octave_char_matrix_dq_str (chm)
847 : new octave_char_matrix_sq_str (chm))
848{
849 maybe_mutate ();
850}
851
852octave_value::octave_value (const Array<char>& chm, bool, char type)
853 : rep (type == '"'
854 ? new octave_char_matrix_dq_str (chm)
855 : new octave_char_matrix_sq_str (chm))
856{
857 maybe_mutate ();
858}
859
860octave_value::octave_value (const SparseMatrix& m, const MatrixType &t)
861 : rep (new octave_sparse_matrix (m, t))
862{
863 maybe_mutate ();
864}
865
866octave_value::octave_value (const Sparse<double>& m, const MatrixType &t)
867 : rep (new octave_sparse_matrix (m, t))
868{
869 maybe_mutate ();
870}
871
872octave_value::octave_value (const SparseComplexMatrix& m, const MatrixType &t)
873 : rep (new octave_sparse_complex_matrix (m, t))
874{
875 maybe_mutate ();
876}
877
878octave_value::octave_value (const Sparse<Complex>& m, const MatrixType &t)
879 : rep (new octave_sparse_complex_matrix (m, t))
880{
881 maybe_mutate ();
882}
883
884octave_value::octave_value (const SparseBoolMatrix& bm, const MatrixType &t)
885 : rep (new octave_sparse_bool_matrix (bm, t))
886{
887 maybe_mutate ();
888}
889
890octave_value::octave_value (const Sparse<bool>& bm, const MatrixType &t)
891 : rep (new octave_sparse_bool_matrix (bm, t))
892{
893 maybe_mutate ();
894}
895
896octave_value::octave_value (const octave_int8& i)
897 : rep (new octave_int8_scalar (i))
898{
899 maybe_mutate ();
900}
901
902octave_value::octave_value (const octave_uint8& i)
903 : rep (new octave_uint8_scalar (i))
904{
905 maybe_mutate ();
906}
907
908octave_value::octave_value (const octave_int16& i)
909 : rep (new octave_int16_scalar (i))
910{
911 maybe_mutate ();
912}
913
914octave_value::octave_value (const octave_uint16& i)
915 : rep (new octave_uint16_scalar (i))
916{
917 maybe_mutate ();
918}
919
920octave_value::octave_value (const octave_int32& i)
921 : rep (new octave_int32_scalar (i))
922{
923 maybe_mutate ();
924}
925
926octave_value::octave_value (const octave_uint32& i)
927 : rep (new octave_uint32_scalar (i))
928{
929 maybe_mutate ();
930}
931
932octave_value::octave_value (const octave_int64& i)
933 : rep (new octave_int64_scalar (i))
934{
935 maybe_mutate ();
936}
937
938octave_value::octave_value (const octave_uint64& i)
939 : rep (new octave_uint64_scalar (i))
940{
941 maybe_mutate ();
942}
943
944octave_value::octave_value (const int8NDArray& inda)
945 : rep (new octave_int8_matrix (inda))
946{
947 maybe_mutate ();
948}
949
950octave_value::octave_value (const Array<octave_int8>& inda)
951 : rep (new octave_int8_matrix (inda))
952{
953 maybe_mutate ();
954}
955
956octave_value::octave_value (const uint8NDArray& inda)
957 : rep (new octave_uint8_matrix (inda))
958{
959 maybe_mutate ();
960}
961
962octave_value::octave_value (const Array<octave_uint8>& inda)
963 : rep (new octave_uint8_matrix (inda))
964{
965 maybe_mutate ();
966}
967
968octave_value::octave_value (const int16NDArray& inda)
969 : rep (new octave_int16_matrix (inda))
970{
971 maybe_mutate ();
972}
973
974octave_value::octave_value (const Array<octave_int16>& inda)
975 : rep (new octave_int16_matrix (inda))
976{
977 maybe_mutate ();
978}
979
980octave_value::octave_value (const uint16NDArray& inda)
981 : rep (new octave_uint16_matrix (inda))
982{
983 maybe_mutate ();
984}
985
986octave_value::octave_value (const Array<octave_uint16>& inda)
987 : rep (new octave_uint16_matrix (inda))
988{
989 maybe_mutate ();
990}
991
992octave_value::octave_value (const int32NDArray& inda)
993 : rep (new octave_int32_matrix (inda))
994{
995 maybe_mutate ();
996}
997
998octave_value::octave_value (const Array<octave_int32>& inda)
999 : rep (new octave_int32_matrix (inda))
1000{
1001 maybe_mutate ();
1002}
1003
1004octave_value::octave_value (const uint32NDArray& inda)
1005 : rep (new octave_uint32_matrix (inda))
1006{
1007 maybe_mutate ();
1008}
1009
1010octave_value::octave_value (const Array<octave_uint32>& inda)
1011 : rep (new octave_uint32_matrix (inda))
1012{
1013 maybe_mutate ();
1014}
1015
1016octave_value::octave_value (const int64NDArray& inda)
1017 : rep (new octave_int64_matrix (inda))
1018{
1019 maybe_mutate ();
1020}
1021
1022octave_value::octave_value (const Array<octave_int64>& inda)
1023 : rep (new octave_int64_matrix (inda))
1024{
1025 maybe_mutate ();
1026}
1027
1028octave_value::octave_value (const uint64NDArray& inda)
1029 : rep (new octave_uint64_matrix (inda))
1030{
1031 maybe_mutate ();
1032}
1033
1034octave_value::octave_value (const Array<octave_uint64>& inda)
1035 : rep (new octave_uint64_matrix (inda))
1036{
1037 maybe_mutate ();
1038}
1039
1040octave_value::octave_value (const Array<octave_idx_type>& inda, bool zero_based,
1041 bool cache_index)
1042 : rep (new octave_matrix (inda, zero_based, cache_index))
1043{
1044 maybe_mutate ();
1045}
1046
1047octave_value::octave_value (const idx_vector& idx)
1048 : rep ()
1049{
1050 double scalar;
1051 Range range;
1052 NDArray array;
1053 boolNDArray mask;
1054 idx_vector::idx_class_type idx_class;
1055
1056 idx.unconvert (idx_class, scalar, range, array, mask);
1057
1058 switch (idx_class)
1059 {
1060 case idx_vector::class_colon:
1061 rep = new octave_magic_colon ();
1062 break;
1063 case idx_vector::class_range:
1064 rep = new octave_range (range, idx);
1065 break;
1066 case idx_vector::class_scalar:
1067 rep = new octave_scalar (scalar);
1068 break;
1069 case idx_vector::class_vector:
1070 rep = new octave_matrix (array, idx);
1071 break;
1072 case idx_vector::class_mask:
1073 rep = new octave_bool_matrix (mask, idx);
1074 break;
1075 default:
1076 assert (false);
1077 break;
1078 }
1079
1080 // FIXME: needed?
1081 maybe_mutate ();
1082}
1083
1084octave_value::octave_value (const Array<std::string>& cellstr)
1085 : rep (new octave_cell (cellstr))
1086{
1087 maybe_mutate ();
1088}
1089
1090octave_value::octave_value (double base, double limit, double inc)
1091 : rep (new octave_range (base, limit, inc))
1092{
1093 maybe_mutate ();
1094}
1095
1096octave_value::octave_value (const Range& r)
1097 : rep (new octave_range (r))
1098{
1099 maybe_mutate ();
1100}
1101
1102octave_value::octave_value (const Octave_map& m)
1103 : rep (new octave_struct (m))
1104{
1105}
1106
1107octave_value::octave_value (const Octave_map& m, const std::string& id)
1108 : rep (new octave_class (m, id))
1109{
1110}
1111
1112octave_value::octave_value (const octave_value_list& l, bool)
1113 : rep (new octave_cs_list (l))
1114{
1115}
1116
1117octave_value::octave_value (octave_value::magic_colon)
1118 : rep (new octave_magic_colon ())
1119{
1120}
1121
1122octave_value::octave_value (octave_base_value *new_rep, bool borrow)
1123 : rep (new_rep)
1124{
1125 if (borrow)
1126 rep->count++;
1127}
1128
1129octave_value::octave_value (octave_base_value *new_rep, int xcount)
1130 : rep (new_rep)
1131{
1132 rep->count = xcount;
1133}
1134
1135octave_base_value *
1136octave_value::clone (void) const
1137{
1138 panic_impossible ();
1139 return 0;
1140}
1141
1142void
1143octave_value::maybe_mutate (void)
1144{
1145 octave_base_value *tmp = rep->try_narrowing_conversion ();
1146
1147 if (tmp && tmp != rep)
1148 {
1149 if (--rep->count == 0)
1150 delete rep;
1151
1152 rep = tmp;
1153 }
1154}
1155
1156octave_value
1157octave_value::single_subsref (const std::string& type,
1158 const octave_value_list& idx)
1159{
1160 std::list<octave_value_list> i;
1161
1162 i.push_back (idx);
1163
1164 return rep->subsref (type, i);
1165}
1166
1167octave_value_list
1168octave_value::subsref (const std::string& type,
1169 const std::list<octave_value_list>& idx, int nargout)
1170{
1171 if (nargout == 1)
1172 return rep->subsref (type, idx);
1173 else
1174 return rep->subsref (type, idx, nargout);
1175}
1176
1177octave_value
1178octave_value::next_subsref (const std::string& type,
1179 const std::list<octave_value_list>& idx,
1180 size_t skip)
1181{
1182 if (! error_state && idx.size () > skip)
1183 {
1184 std::list<octave_value_list> new_idx (idx);
1185 for (size_t i = 0; i < skip; i++)
1186 new_idx.erase (new_idx.begin ());
1187 return subsref (type.substr (skip), new_idx);
1188 }
1189 else
1190 return *this;
1191}
1192
1193octave_value_list
1194octave_value::next_subsref (int nargout, const std::string& type,
1195 const std::list<octave_value_list>& idx,
1196 size_t skip)
1197{
1198 if (! error_state && idx.size () > skip)
1199 {
1200 std::list<octave_value_list> new_idx (idx);
1201 for (size_t i = 0; i < skip; i++)
1202 new_idx.erase (new_idx.begin ());
1203 return subsref (type.substr (skip), new_idx, nargout);
1204 }
1205 else
1206 return *this;
1207}
1208
1209octave_value
1210octave_value::next_subsref (bool auto_add, const std::string& type,
1211 const std::list<octave_value_list>& idx,
1212 size_t skip)
1213{
1214 if (! error_state && idx.size () > skip)
1215 {
1216 std::list<octave_value_list> new_idx (idx);
1217 for (size_t i = 0; i < skip; i++)
1218 new_idx.erase (new_idx.begin ());
1219 return subsref (type.substr (skip), new_idx, auto_add);
1220 }
1221 else
1222 return *this;
1223}
1224
1225octave_value_list
1226octave_value::do_multi_index_op (int nargout, const octave_value_list& idx)
1227{
1228 return rep->do_multi_index_op (nargout, idx);
1229}
1230
1231#if 0
1232static void
1233gripe_assign_failed (const std::string& on, const std::string& tn1,
1234 const std::string& tn2)
1235{
1236 error ("assignment failed for `%s %s %s'",
1237 tn1.c_str (), on.c_str (), tn2.c_str ());
1238}
1239#endif
1240
1241static void
1242gripe_assign_failed_or_no_method (const std::string& on,
1243 const std::string& tn1,
1244 const std::string& tn2)
1245{
1246 error ("assignment failed, or no method for `%s %s %s'",
1247 tn1.c_str (), on.c_str (), tn2.c_str ());
1248}
1249
1250octave_value
1251octave_value::subsasgn (const std::string& type,
1252 const std::list<octave_value_list>& idx,
1253 const octave_value& rhs)
1254{
1255 return rep->subsasgn (type, idx, rhs);
1256}
1257
1258octave_value
1259octave_value::assign (assign_op op, const std::string& type,
1260 const std::list<octave_value_list>& idx,
1261 const octave_value& rhs)
1262{
1263 octave_value retval;
1264
1265 make_unique ();
1266
1267 octave_value t_rhs = rhs;
1268
1269 if (op != op_asn_eq)
1270 {
1271 octave_value t = subsref (type, idx);
1272
1273 if (! error_state)
1274 {
1275 binary_op binop = op_eq_to_binary_op (op);
1276
1277 if (! error_state)
1278 t_rhs = do_binary_op (binop, t, rhs);
1279 }
1280 }
1281
1282 if (! error_state)
1283 {
1284 if (type[0] == '.' && ! (is_map () || is_object ()))
1285 {
1286 octave_value tmp = Octave_map ();
1287 retval = tmp.subsasgn (type, idx, t_rhs);
1288 }
1289 else
1290 retval = subsasgn (type, idx, t_rhs);
1291
1292 if (error_state)
1293 gripe_assign_failed_or_no_method (assign_op_as_string (op_asn_eq),
1294 type_name (), rhs.type_name ());
1295 }
1296
1297 return retval;
1298}
1299
1300const octave_value&
1301octave_value::assign (assign_op op, const octave_value& rhs)
1302{
1303 if (op == op_asn_eq)
1304 // Regularize a null matrix if stored into a variable.
1305 operator = (rhs.storable_value ());
1306 else
1307 {
1308 octave_value_typeinfo::assign_op_fcn f = 0;
1309
1310 // Only attempt to operate in-place if this variable is unshared.
1311 if (rep->count == 1)
1312 {
1313 int tthis = this->type_id ();
1314 int trhs = rhs.type_id ();
1315
1316 f = octave_value_typeinfo::lookup_assign_op (op, tthis, trhs);
1317 }
1318
1319 if (f)
1320 {
1321 try
1322 {
1323 f (*rep, octave_value_list (), *rhs.rep);
1324 maybe_mutate (); // Usually unnecessary, but may be needed (complex arrays).
1325 }
1326 catch (octave_execution_exception)
1327 {
1328 gripe_library_execution_error ();
1329 }
1330 }
1331 else
1332 {
1333
1334 binary_op binop = op_eq_to_binary_op (op);
1335
1336 if (! error_state)
1337 {
1338 octave_value t = do_binary_op (binop, *this, rhs);
1339
1340 if (! error_state)
1341 operator = (t);
1342 }
1343 }
1344 }
1345
1346 return *this;
1347}
1348
1349octave_idx_type
1350octave_value::length (void) const
1351{
1352 int retval = 0;
1353
1354 dim_vector dv = dims ();
1355
1356 for (int i = 0; i < dv.length (); i++)
1357 {
1358 if (dv(i) < 0)
1359 {
1360 retval = -1;
1361 break;
1362 }
1363
1364 if (dv(i) == 0)
1365 {
1366 retval = 0;
1367 break;
1368 }
1369
1370 if (dv(i) > retval)
1371 retval = dv(i);
1372 }
1373
1374 return retval;
1375}
1376
1377bool
1378octave_value::is_equal (const octave_value& test) const
1379{
1380 bool retval = false;
1381
1382 // If there is no op_eq for these types, we can't compare values.
1383
1384 if (rows () == test.rows () && columns () == test.columns ())
1385 {
1386 octave_value tmp = do_binary_op (octave_value::op_eq, *this, test);
1387
1388 // Empty array also means a match.
1389 if (! error_state && tmp.is_defined ())
1390 retval = tmp.is_true () || tmp.is_empty ();
1391 }
1392
1393 return retval;
1394}
1395
1396Cell
1397octave_value::cell_value (void) const
1398{
1399 return rep->cell_value ();
1400}
1401
1402// Define the idx_type_value function here instead of in ov.h to avoid
1403// needing definitions for the SIZEOF_X macros in ov.h.
1404
1405octave_idx_type
1406octave_value::idx_type_value (bool req_int, bool frc_str_conv) const
1407{
1408#if SIZEOF_OCTAVE_IDX_TYPE == SIZEOF_LONG
1409 return long_value (req_int, frc_str_conv);
1410#elif SIZEOF_OCTAVE_IDX_TYPE == SIZEOF_INT
1411 return int_value (req_int, frc_str_conv);
1412#else
1413#error "no octave_value extractor for octave_idx_type"
1414#endif
1415}
1416
1417Octave_map
1418octave_value::map_value (void) const
1419{
1420 return rep->map_value ();
1421}
1422
1423octave_function *
1424octave_value::function_value (bool silent) const
1425{
1426 return rep->function_value (silent);
1427}
1428
1429octave_user_function *
1430octave_value::user_function_value (bool silent) const
1431{
1432 return rep->user_function_value (silent);
1433}
1434
1435octave_user_script *
1436octave_value::user_script_value (bool silent) const
1437{
1438 return rep->user_script_value (silent);
1439}
1440
1441octave_user_code *
1442octave_value::user_code_value (bool silent) const
1443{
1444 return rep->user_code_value (silent);
1445}
1446
1447octave_fcn_handle *
1448octave_value::fcn_handle_value (bool silent) const
1449{
1450 return rep->fcn_handle_value (silent);
1451}
1452
1453octave_fcn_inline *
1454octave_value::fcn_inline_value (bool silent) const
1455{
1456 return rep->fcn_inline_value (silent);
1457}
1458
1459octave_value_list
1460octave_value::list_value (void) const
1461{
1462 return rep->list_value ();
1463}
1464
1465static dim_vector
1466make_vector_dims (const dim_vector& dv, bool force_vector_conversion,
1467 const std::string& my_type, const std::string& wanted_type)
1468{
1469 dim_vector retval (dv);
1470 retval.chop_trailing_singletons ();
1471 octave_idx_type nel = dv.numel ();
1472
1473 if (retval.length () > 2 || (retval(0) != 1 && retval(1) != 1))
1474 {
1475 if (!force_vector_conversion)
1476 gripe_implicit_conversion ("Octave:array-as-vector",
1477 my_type.c_str (), wanted_type.c_str ());
1478 retval = dim_vector (nel);
1479 }
1480
1481 return retval;
1482}
1483
1484ColumnVector
1485octave_value::column_vector_value (bool force_string_conv,
1486 bool frc_vec_conv) const
1487{
1488 return ColumnVector (vector_value (force_string_conv,
1489 frc_vec_conv));
1490}
1491
1492ComplexColumnVector
1493octave_value::complex_column_vector_value (bool force_string_conv,
1494 bool frc_vec_conv) const
1495{
1496 return ComplexColumnVector (complex_vector_value (force_string_conv,
1497 frc_vec_conv));
1498}
1499
1500RowVector
1501octave_value::row_vector_value (bool force_string_conv,
1502 bool frc_vec_conv) const
1503{
1504 return RowVector (vector_value (force_string_conv,
1505 frc_vec_conv));
1506}
1507
1508ComplexRowVector
1509octave_value::complex_row_vector_value (bool force_string_conv,
1510 bool frc_vec_conv) const
1511{
1512 return ComplexRowVector (complex_vector_value (force_string_conv,
1513 frc_vec_conv));
1514}
1515
1516Array<double>
1517octave_value::vector_value (bool force_string_conv,
1518 bool force_vector_conversion) const
1519{
1520 Array<double> retval = array_value (force_string_conv);
1521
1522 if (error_state)
1523 return retval;
1524 else
1525 return retval.reshape (make_vector_dims (retval.dims (),
1526 force_vector_conversion,
1527 type_name (), "real vector"));
1528}
1529
1530template <class T>
1531static Array<int>
1532convert_to_int_array (const Array<octave_int<T> >& A)
1533{
1534 Array<int> retval (A.dims ());
1535 octave_idx_type n = A.numel ();
1536
1537 octave_int<int>::clear_conv_flag ();
1538 for (octave_idx_type i = 0; i < n; i++)
1539 retval.xelem (i) = octave_int<int> (A.xelem (i));
1540
1541 if (octave_int<int>::get_trunc_flag ())
1542 gripe_truncated_conversion (octave_int<T>::type_name (), "int");
1543
1544 octave_int<int>::clear_conv_flag ();
1545
1546 return retval;
1547}
1548
1549Array<int>
1550octave_value::int_vector_value (bool force_string_conv, bool require_int,
1551 bool force_vector_conversion) const
1552{
1553 Array<int> retval;
1554
1555 if (is_integer_type ())
1556 {
1557 if (is_int32_type ())
1558 retval = convert_to_int_array (int32_array_value ());
1559 else if (is_int64_type ())
1560 retval = convert_to_int_array (int64_array_value ());
1561 else if (is_int16_type ())
1562 retval = convert_to_int_array (int16_array_value ());
1563 else if (is_int8_type ())
1564 retval = convert_to_int_array (int8_array_value ());
1565 else if (is_uint32_type ())
1566 retval = convert_to_int_array (uint32_array_value ());
1567 else if (is_uint64_type ())
1568 retval = convert_to_int_array (uint64_array_value ());
1569 else if (is_uint16_type ())
1570 retval = convert_to_int_array (uint16_array_value ());
1571 else if (is_uint8_type ())
1572 retval = convert_to_int_array (uint8_array_value ());
1573 else
1574 retval = array_value (force_string_conv);
1575 }
1576 else
1577 {
1578 const NDArray a = array_value (force_string_conv);
1579 if (! error_state)
1580 {
1581 if (require_int)
1582 {
1583 retval.resize (a.dims ());
1584 for (octave_idx_type i = 0; i < a.numel (); i++)
1585 {
1586 double ai = a.elem (i);
1587 int v = static_cast<int> (ai);
1588 if (ai == v)
1589 retval.xelem (i) = v;
1590 else
1591 {
1592 error_with_cfn ("conversion to integer value failed");
1593 break;
1594 }
1595 }
1596 }
1597 else
1598 retval = Array<int> (a);
1599 }
1600 }
1601
1602
1603 if (error_state)
1604 return retval;
1605 else
1606 return retval.reshape (make_vector_dims (retval.dims (),
1607 force_vector_conversion,
1608 type_name (), "integer vector"));
1609}
1610
1611template <class T>
1612static Array<octave_idx_type>
1613convert_to_octave_idx_type_array (const Array<octave_int<T> >& A)
1614{
1615 Array<octave_idx_type> retval (A.dims ());
1616 octave_idx_type n = A.numel ();
1617
1618 octave_int<int>::clear_conv_flag ();
1619 for (octave_idx_type i = 0; i < n; i++)
1620 retval.xelem (i) = octave_int<octave_idx_type> (A.xelem (i));
1621
1622 if (octave_int<int>::get_trunc_flag ())
1623 gripe_truncated_conversion (octave_int<T>::type_name (), "int");
1624
1625 octave_int<int>::clear_conv_flag ();
1626
1627 return retval;
1628}
1629
1630Array<octave_idx_type>
1631octave_value::octave_idx_type_vector_value (bool require_int,
1632 bool force_string_conv,
1633 bool force_vector_conversion) const
1634{
1635 Array<octave_idx_type> retval;
1636
1637 if (is_integer_type ())
1638 {
1639 if (is_int32_type ())
1640 retval = convert_to_octave_idx_type_array (int32_array_value ());
1641 else if (is_int64_type ())
1642 retval = convert_to_octave_idx_type_array (int64_array_value ());
1643 else if (is_int16_type ())
1644 retval = convert_to_octave_idx_type_array (int16_array_value ());
1645 else if (is_int8_type ())
1646 retval = convert_to_octave_idx_type_array (int8_array_value ());
1647 else if (is_uint32_type ())
1648 retval = convert_to_octave_idx_type_array (uint32_array_value ());
1649 else if (is_uint64_type ())
1650 retval = convert_to_octave_idx_type_array (uint64_array_value ());
1651 else if (is_uint16_type ())
1652 retval = convert_to_octave_idx_type_array (uint16_array_value ());
1653 else if (is_uint8_type ())
1654 retval = convert_to_octave_idx_type_array (uint8_array_value ());
1655 else
1656 retval = array_value (force_string_conv);
1657 }
1658 else
1659 {
1660 const NDArray a = array_value (force_string_conv);
1661 if (! error_state)
1662 {
1663 if (require_int)
1664 {
1665 retval.resize (a.dims ());
1666 for (octave_idx_type i = 0; i < a.numel (); i++)
1667 {
1668 double ai = a.elem (i);
1669 octave_idx_type v = static_cast<octave_idx_type> (ai);
1670 if (ai == v)
1671 retval.xelem (i) = v;
1672 else
1673 {
1674 error_with_cfn ("conversion to integer value failed");
1675 break;
1676 }
1677 }
1678 }
1679 else
1680 retval = Array<octave_idx_type> (a);
1681 }
1682 }
1683
1684
1685 if (error_state)
1686 return retval;
1687 else
1688 return retval.reshape (make_vector_dims (retval.dims (),
1689 force_vector_conversion,
1690 type_name (), "integer vector"));
1691}
1692
1693Array<Complex>
1694octave_value::complex_vector_value (bool force_string_conv,
1695 bool force_vector_conversion) const
1696{
1697 Array<Complex> retval = complex_array_value (force_string_conv);
1698
1699 if (error_state)
1700 return retval;
1701 else
1702 return retval.reshape (make_vector_dims (retval.dims (),
1703 force_vector_conversion,
1704 type_name (), "complex vector"));
1705}
1706
1707FloatColumnVector
1708octave_value::float_column_vector_value (bool force_string_conv,
1709 bool frc_vec_conv) const
1710{
1711 return FloatColumnVector (float_vector_value (force_string_conv,
1712 frc_vec_conv));
1713}
1714
1715FloatComplexColumnVector
1716octave_value::float_complex_column_vector_value (bool force_string_conv,
1717 bool frc_vec_conv) const
1718{
1719 return FloatComplexColumnVector (float_complex_vector_value (force_string_conv,
1720 frc_vec_conv));
1721}
1722
1723FloatRowVector
1724octave_value::float_row_vector_value (bool force_string_conv,
1725 bool frc_vec_conv) const
1726{
1727 return FloatRowVector (float_vector_value (force_string_conv,
1728 frc_vec_conv));
1729}
1730
1731FloatComplexRowVector
1732octave_value::float_complex_row_vector_value (bool force_string_conv,
1733 bool frc_vec_conv) const
1734{
1735 return FloatComplexRowVector (float_complex_vector_value (force_string_conv,
1736 frc_vec_conv));
1737}
1738
1739Array<float>
1740octave_value::float_vector_value (bool force_string_conv,
1741 bool force_vector_conversion) const
1742{
1743 Array<float> retval = float_array_value (force_string_conv);
1744
1745 if (error_state)
1746 return retval;
1747 else
1748 return retval.reshape (make_vector_dims (retval.dims (),
1749 force_vector_conversion,
1750 type_name (), "real vector"));
1751}
1752
1753Array<FloatComplex>
1754octave_value::float_complex_vector_value (bool force_string_conv,
1755 bool force_vector_conversion) const
1756{
1757 Array<FloatComplex> retval = float_complex_array_value (force_string_conv);
1758
1759 if (error_state)
1760 return retval;
1761 else
1762 return retval.reshape (make_vector_dims (retval.dims (),
1763 force_vector_conversion,
1764 type_name (), "complex vector"));
1765}
1766
1767octave_value
1768octave_value::storable_value (void) const
1769{
1770 octave_value retval = *this;
1771 if (is_null_value ())
1772 retval = octave_value (rep->empty_clone ());
1773 else
1774 retval.maybe_economize ();
1775
1776 return retval;
1777}
1778
1779void
1780octave_value::make_storable_value (void)
1781{
1782 if (is_null_value ())
1783 {
1784 octave_base_value *rc = rep->empty_clone ();
1785 if (--rep->count == 0)
1786 delete rep;
1787 rep = rc;
1788 }
1789 else
1790 maybe_economize ();
1791}
1792
1793int
1794octave_value::write (octave_stream& os, int block_size,
1795 oct_data_conv::data_type output_type, int skip,
1796 oct_mach_info::float_format flt_fmt) const
1797{
1798 return rep->write (os, block_size, output_type, skip, flt_fmt);
1799}
1800
1801static void
1802gripe_binary_op (const std::string& on, const std::string& tn1,
1803 const std::string& tn2)
1804{
1805 error ("binary operator `%s' not implemented for `%s' by `%s' operations",
1806 on.c_str (), tn1.c_str (), tn2.c_str ());
1807}
1808
1809static void
1810gripe_binary_op_conv (const std::string& on)
1811{
1812 error ("type conversion failed for binary operator `%s'", on.c_str ());
1813}
1814
1815octave_value
1816do_binary_op (octave_value::binary_op op,
1817 const octave_value& v1, const octave_value& v2)
1818{
1819 octave_value retval;
1820
1821 int t1 = v1.type_id ();
1822 int t2 = v2.type_id ();
1823
1824 if (t1 == octave_class::static_type_id ()
1825 || t2 == octave_class::static_type_id ())
1826 {
1827 octave_value_typeinfo::binary_class_op_fcn f
1828 = octave_value_typeinfo::lookup_binary_class_op (op);
1829
1830 if (f)
1831 {
1832 try
1833 {
1834 retval = f (v1, v2);
1835 }
1836 catch (octave_execution_exception)
1837 {
1838 gripe_library_execution_error ();
1839 }
1840 }
1841 else
1842 gripe_binary_op (octave_value::binary_op_as_string (op),
1843 v1.class_name (), v2.class_name ());
1844 }
1845 else
1846 {
1847 // FIXME -- we need to handle overloading operators for built-in
1848 // classes (double, char, int8, etc.)
1849
1850 octave_value_typeinfo::binary_op_fcn f
1851 = octave_value_typeinfo::lookup_binary_op (op, t1, t2);
1852
1853 if (f)
1854 {
1855 try
1856 {
1857 retval = f (*v1.rep, *v2.rep);
1858 }
1859 catch (octave_execution_exception)
1860 {
1861 gripe_library_execution_error ();
1862 }
1863 }
1864 else
1865 {
1866 octave_value tv1;
1867 octave_base_value::type_conv_info cf1 = v1.numeric_conversion_function ();
1868
1869 octave_value tv2;
1870 octave_base_value::type_conv_info cf2 = v2.numeric_conversion_function ();
1871
1872 // Try biased (one-sided) conversions first.
1873 if (cf2.type_id () >= 0 &&
1874 octave_value_typeinfo::lookup_binary_op (op, t1, cf2.type_id ()))
1875 cf1 = 0;
1876 else if (cf1.type_id () >= 0 &&
1877 octave_value_typeinfo::lookup_binary_op (op, cf1.type_id (), t2))
1878 cf2 = 0;
1879
1880 if (cf1)
1881 {
1882 octave_base_value *tmp = cf1 (*v1.rep);
1883
1884 if (tmp)
1885 {
1886 tv1 = octave_value (tmp);
1887 t1 = tv1.type_id ();
1888 }
1889 else
1890 {
1891 gripe_binary_op_conv (octave_value::binary_op_as_string (op));
1892 return retval;
1893 }
1894 }
1895 else
1896 tv1 = v1;
1897
1898 if (cf2)
1899 {
1900 octave_base_value *tmp = cf2 (*v2.rep);
1901
1902 if (tmp)
1903 {
1904 tv2 = octave_value (tmp);
1905 t2 = tv2.type_id ();
1906 }
1907 else
1908 {
1909 gripe_binary_op_conv (octave_value::binary_op_as_string (op));
1910 return retval;
1911 }
1912 }
1913 else
1914 tv2 = v2;
1915
1916 if (cf1 || cf2)
1917 {
1918 retval = do_binary_op (op, tv1, tv2);
1919 }
1920 else
1921 {
1922 //demote double -> single and try again
1923 cf1 = tv1.numeric_demotion_function ();
1924
1925 cf2 = tv2.numeric_demotion_function ();
1926
1927 // Try biased (one-sided) conversions first.
1928 if (cf2.type_id () >= 0
1929 && octave_value_typeinfo::lookup_binary_op (op, t1, cf2.type_id ()))
1930 cf1 = 0;
1931 else if (cf1.type_id () >= 0
1932 && octave_value_typeinfo::lookup_binary_op (op, cf1.type_id (), t2))
1933 cf2 = 0;
1934
1935 if (cf1)
1936 {
1937 octave_base_value *tmp = cf1 (*tv1.rep);
1938
1939 if (tmp)
1940 {
1941 tv1 = octave_value (tmp);
1942 t1 = tv1.type_id ();
1943 }
1944 else
1945 {
1946 gripe_binary_op_conv (octave_value::binary_op_as_string (op));
1947 return retval;
1948 }
1949 }
1950
1951 if (cf2)
1952 {
1953 octave_base_value *tmp = cf2 (*tv2.rep);
1954
1955 if (tmp)
1956 {
1957 tv2 = octave_value (tmp);
1958 t2 = tv2.type_id ();
1959 }
1960 else
1961 {
1962 gripe_binary_op_conv (octave_value::binary_op_as_string (op));
1963 return retval;
1964 }
1965 }
1966
1967 if (cf1 || cf2)
1968 {
1969 f = octave_value_typeinfo::lookup_binary_op (op, t1, t2);
1970
1971 if (f)
1972 {
1973 try
1974 {
1975 retval = f (*tv1.rep, *tv2.rep);
1976 }
1977 catch (octave_execution_exception)
1978 {
1979 gripe_library_execution_error ();
1980 }
1981 }
1982 else
1983 gripe_binary_op (octave_value::binary_op_as_string (op),
1984 v1.type_name (), v2.type_name ());
1985 }
1986 else
1987 gripe_binary_op (octave_value::binary_op_as_string (op),
1988 v1.type_name (), v2.type_name ());
1989 }
1990 }
1991 }
1992
1993 return retval;
1994}
1995
1996static octave_value
1997decompose_binary_op (octave_value::compound_binary_op op,
1998 const octave_value& v1, const octave_value& v2)
1999{
2000 octave_value retval;
2001
2002 switch (op)
2003 {
2004 case octave_value::op_trans_mul:
2005 retval = do_binary_op (octave_value::op_mul,
2006 do_unary_op (octave_value::op_transpose, v1),
2007 v2);
2008 break;
2009 case octave_value::op_mul_trans:
2010 retval = do_binary_op (octave_value::op_mul,
2011 v1,
2012 do_unary_op (octave_value::op_transpose, v2));
2013 break;
2014 case octave_value::op_herm_mul:
2015 retval = do_binary_op (octave_value::op_mul,
2016 do_unary_op (octave_value::op_hermitian, v1),
2017 v2);
2018 break;
2019 case octave_value::op_mul_herm:
2020 retval = do_binary_op (octave_value::op_mul,
2021 v1,
2022 do_unary_op (octave_value::op_hermitian, v2));
2023 break;
2024 case octave_value::op_trans_ldiv:
2025 retval = do_binary_op (octave_value::op_ldiv,
2026 do_unary_op (octave_value::op_transpose, v1),
2027 v2);
2028 break;
2029 case octave_value::op_herm_ldiv:
2030 retval = do_binary_op (octave_value::op_ldiv,
2031 do_unary_op (octave_value::op_hermitian, v1),
2032 v2);
2033 break;
2034 case octave_value::op_el_not_and:
2035 retval = do_binary_op (octave_value::op_el_and,
2036 do_unary_op (octave_value::op_not, v1),
2037 v2);
2038 break;
2039 case octave_value::op_el_not_or:
2040 retval = do_binary_op (octave_value::op_el_or,
2041 do_unary_op (octave_value::op_not, v1),
2042 v2);
2043 break;
2044 case octave_value::op_el_and_not:
2045 retval = do_binary_op (octave_value::op_el_and,
2046 v1,
2047 do_unary_op (octave_value::op_not, v2));
2048 break;
2049 case octave_value::op_el_or_not:
2050 retval = do_binary_op (octave_value::op_el_or,
2051 v1,
2052 do_unary_op (octave_value::op_not, v2));
2053 break;
2054 default:
2055 error ("invalid compound operator");
2056 break;
2057 }
2058
2059 return retval;
2060}
2061
2062octave_value
2063do_binary_op (octave_value::compound_binary_op op,
2064 const octave_value& v1, const octave_value& v2)
2065{
2066 octave_value retval;
2067
2068 int t1 = v1.type_id ();
2069 int t2 = v2.type_id ();
2070
2071 if (t1 == octave_class::static_type_id ()
2072 || t2 == octave_class::static_type_id ())
2073 {
2074 octave_value_typeinfo::binary_class_op_fcn f
2075 = octave_value_typeinfo::lookup_binary_class_op (op);
2076
2077 if (f)
2078 {
2079 try
2080 {
2081 retval = f (v1, v2);
2082 }
2083 catch (octave_execution_exception)
2084 {
2085 gripe_library_execution_error ();
2086 }
2087 }
2088 else
2089 retval = decompose_binary_op (op, v1, v2);
2090 }
2091 else
2092 {
2093 octave_value_typeinfo::binary_op_fcn f
2094 = octave_value_typeinfo::lookup_binary_op (op, t1, t2);
2095
2096 if (f)
2097 {
2098 try
2099 {
2100 retval = f (*v1.rep, *v2.rep);
2101 }
2102 catch (octave_execution_exception)
2103 {
2104 gripe_library_execution_error ();
2105 }
2106 }
2107 else
2108 retval = decompose_binary_op (op, v1, v2);
2109 }
2110
2111 return retval;
2112}
2113
2114static void
2115gripe_cat_op (const std::string& tn1, const std::string& tn2)
2116{
2117 error ("concatenation operator not implemented for `%s' by `%s' operations",
2118 tn1.c_str (), tn2.c_str ());
2119}
2120
2121static void
2122gripe_cat_op_conv (void)
2123{
2124 error ("type conversion failed for concatenation operator");
2125}
2126
2127octave_value
2128do_cat_op (const octave_value& v1, const octave_value& v2,
2129 const Array<octave_idx_type>& ra_idx)
2130{
2131 octave_value retval;
2132
2133 // Can't rapid return for concatenation with an empty object here as
2134 // something like cat(1,[],single([]) must return the correct type.
2135
2136 int t1 = v1.type_id ();
2137 int t2 = v2.type_id ();
2138
2139 octave_value_typeinfo::cat_op_fcn f
2140 = octave_value_typeinfo::lookup_cat_op (t1, t2);
2141
2142 if (f)
2143 {
2144 try
2145 {
2146 retval = f (*v1.rep, *v2.rep, ra_idx);
2147 }
2148 catch (octave_execution_exception)
2149 {
2150 gripe_library_execution_error ();
2151 }
2152 }
2153 else
2154 {
2155 octave_value tv1;
2156 octave_base_value::type_conv_info cf1 = v1.numeric_conversion_function ();
2157
2158 octave_value tv2;
2159 octave_base_value::type_conv_info cf2 = v2.numeric_conversion_function ();
2160
2161 // Try biased (one-sided) conversions first.
2162 if (cf2.type_id () >= 0
2163 && octave_value_typeinfo::lookup_cat_op (t1, cf2.type_id ()))
2164 cf1 = 0;
2165 else if (cf1.type_id () >= 0
2166 && octave_value_typeinfo::lookup_cat_op (cf1.type_id (), t2))
2167 cf2 = 0;
2168
2169 if (cf1)
2170 {
2171 octave_base_value *tmp = cf1 (*v1.rep);
2172
2173 if (tmp)
2174 {
2175 tv1 = octave_value (tmp);
2176 t1 = tv1.type_id ();
2177 }
2178 else
2179 {
2180 gripe_cat_op_conv ();
2181 return retval;
2182 }
2183 }
2184 else
2185 tv1 = v1;
2186
2187 if (cf2)
2188 {
2189 octave_base_value *tmp = cf2 (*v2.rep);
2190
2191 if (tmp)
2192 {
2193 tv2 = octave_value (tmp);
2194 t2 = tv2.type_id ();
2195 }
2196 else
2197 {
2198 gripe_cat_op_conv ();
2199 return retval;
2200 }
2201 }
2202 else
2203 tv2 = v2;
2204
2205 if (cf1 || cf2)
2206 {
2207 retval = do_cat_op (tv1, tv2, ra_idx);
2208 }
2209 else
2210 gripe_cat_op (v1.type_name (), v2.type_name ());
2211 }
2212
2213 return retval;
2214}
2215
2216void
2217octave_value::print_info (std::ostream& os, const std::string& prefix) const
2218{
2219 os << prefix << "type_name: " << type_name () << "\n"
2220 << prefix << "count: " << get_count () << "\n"
2221 << prefix << "rep info: ";
2222
2223 rep->print_info (os, prefix + " ");
2224}
2225
2226static void
2227gripe_unary_op (const std::string& on, const std::string& tn)
2228{
2229 error ("unary operator `%s' not implemented for `%s' operands",
2230 on.c_str (), tn.c_str ());
2231}
2232
2233static void
2234gripe_unary_op_conv (const std::string& on)
2235{
2236 error ("type conversion failed for unary operator `%s'", on.c_str ());
2237}
2238
2239octave_value
2240do_unary_op (octave_value::unary_op op, const octave_value& v)
2241{
2242 octave_value retval;
2243
2244 int t = v.type_id ();
2245
2246 if (t == octave_class::static_type_id ())
2247 {
2248 octave_value_typeinfo::unary_class_op_fcn f
2249 = octave_value_typeinfo::lookup_unary_class_op (op);
2250
2251 if (f)
2252 {
2253 try
2254 {
2255 retval = f (v);
2256 }
2257 catch (octave_execution_exception)
2258 {
2259 gripe_library_execution_error ();
2260 }
2261 }
2262 else
2263 gripe_unary_op (octave_value::unary_op_as_string (op),
2264 v.class_name ());
2265 }
2266 else
2267 {
2268 // FIXME -- we need to handle overloading operators for built-in
2269 // classes (double, char, int8, etc.)
2270
2271 octave_value_typeinfo::unary_op_fcn f
2272 = octave_value_typeinfo::lookup_unary_op (op, t);
2273
2274 if (f)
2275 {
2276 try
2277 {
2278 retval = f (*v.rep);
2279 }
2280 catch (octave_execution_exception)
2281 {
2282 gripe_library_execution_error ();
2283 }
2284 }
2285 else
2286 {
2287 octave_value tv;
2288 octave_base_value::type_conv_fcn cf
2289 = v.numeric_conversion_function ();
2290
2291 if (cf)
2292 {
2293 octave_base_value *tmp = cf (*v.rep);
2294
2295 if (tmp)
2296 {
2297 tv = octave_value (tmp);
2298 retval = do_unary_op (op, tv);
2299 }
2300 else
2301 gripe_unary_op_conv (octave_value::unary_op_as_string (op));
2302 }
2303 else
2304 gripe_unary_op (octave_value::unary_op_as_string (op),
2305 v.type_name ());
2306 }
2307 }
2308
2309 return retval;
2310}
2311
2312static void
2313gripe_unary_op_conversion_failed (const std::string& op,
2314 const std::string& tn)
2315{
2316 error ("operator %s: type conversion for `%s' failed",
2317 op.c_str (), tn.c_str ());
2318}
2319
2320const octave_value&
2321octave_value::do_non_const_unary_op (unary_op op)
2322{
2323 if (op == op_incr || op == op_decr)
2324 {
2325 // Genuine.
2326 int t = type_id ();
2327
2328 octave_value_typeinfo::non_const_unary_op_fcn f
2329 = octave_value_typeinfo::lookup_non_const_unary_op (op, t);
2330
2331 if (f)
2332 {
2333 make_unique ();
2334
2335 try
2336 {
2337 f (*rep);
2338 }
2339 catch (octave_execution_exception)
2340 {
2341 gripe_library_execution_error ();
2342 }
2343 }
2344 else
2345 {
2346 octave_base_value::type_conv_fcn cf = numeric_conversion_function ();
2347
2348 if (cf)
2349 {
2350 octave_base_value *tmp = cf (*rep);
2351
2352 if (tmp)
2353 {
2354 octave_base_value *old_rep = rep;
2355 rep = tmp;
2356
2357 t = type_id ();
2358
2359 f = octave_value_typeinfo::lookup_non_const_unary_op (op, t);
2360
2361 if (f)
2362 {
2363 try
2364 {
2365 f (*rep);
2366 }
2367 catch (octave_execution_exception)
2368 {
2369 gripe_library_execution_error ();
2370 }
2371
2372 if (old_rep && --old_rep->count == 0)
2373 delete old_rep;
2374 }
2375 else
2376 {
2377 if (old_rep)
2378 {
2379 if (--rep->count == 0)
2380 delete rep;
2381
2382 rep = old_rep;
2383 }
2384
2385 gripe_unary_op (octave_value::unary_op_as_string (op),
2386 type_name ());
2387 }
2388 }
2389 else
2390 gripe_unary_op_conversion_failed
2391 (octave_value::unary_op_as_string (op), type_name ());
2392 }
2393 else
2394 gripe_unary_op (octave_value::unary_op_as_string (op), type_name ());
2395 }
2396 }
2397 else
2398 {
2399 // Non-genuine.
2400 int t = type_id ();
2401
2402 octave_value_typeinfo::non_const_unary_op_fcn f = 0;
2403
2404 // Only attempt to operate in-place if this variable is unshared.
2405 if (rep->count == 1)
2406 f = octave_value_typeinfo::lookup_non_const_unary_op (op, t);
2407
2408 if (f)
2409 {
2410 try
2411 {
2412 f (*rep);
2413 }
2414 catch (octave_execution_exception)
2415 {
2416 gripe_library_execution_error ();
2417 }
2418 }
2419 else
2420 *this = do_unary_op (op, *this);
2421 }
2422
2423 return *this;
2424}
2425
2426#if 0
2427static void
2428gripe_unary_op_failed_or_no_method (const std::string& on,
2429 const std::string& tn)
2430{
2431 error ("operator %s: no method, or unable to evaluate for %s operand",
2432 on.c_str (), tn.c_str ());
2433}
2434#endif
2435
2436void
2437octave_value::do_non_const_unary_op (unary_op, const octave_value_list&)
2438{
2439 abort ();
2440}
2441
2442octave_value
2443octave_value::do_non_const_unary_op (unary_op op, const std::string& type,
2444 const std::list<octave_value_list>& idx)
2445{
2446 octave_value retval;
2447
2448 if (idx.empty ())
2449 {
2450 do_non_const_unary_op (op);
2451
2452 retval = *this;
2453 }
2454 else
2455 {
2456 // FIXME -- only do the following stuff if we can't find a
2457 // specific function to call to handle the op= operation for the
2458 // types we have.
2459
2460 assign_op assop = unary_op_to_assign_op (op);
2461
2462 retval = assign (assop, type, idx, 1.0);
2463 }
2464
2465 return retval;
2466}
2467
2468octave_value::assign_op
2469octave_value::unary_op_to_assign_op (unary_op op)
2470{
2471 assign_op binop = unknown_assign_op;
2472
2473 switch (op)
2474 {
2475 case op_incr:
2476 binop = op_add_eq;
2477 break;
2478
2479 case op_decr:
2480 binop = op_sub_eq;
2481 break;
2482
2483 default:
2484 {
2485 std::string on = unary_op_as_string (op);
2486 error ("operator %s: no assign operator found", on.c_str ());
2487 }
2488 }
2489
2490 return binop;
2491}
2492
2493octave_value::binary_op
2494octave_value::op_eq_to_binary_op (assign_op op)
2495{
2496 binary_op binop = unknown_binary_op;
2497
2498 switch (op)
2499 {
2500 case op_add_eq:
2501 binop = op_add;
2502 break;
2503
2504 case op_sub_eq:
2505 binop = op_sub;
2506 break;
2507
2508 case op_mul_eq:
2509 binop = op_mul;
2510 break;
2511
2512 case op_div_eq:
2513 binop = op_div;
2514 break;
2515
2516 case op_ldiv_eq:
2517 binop = op_ldiv;
2518 break;
2519
2520 case op_pow_eq:
2521 binop = op_pow;
2522 break;
2523
2524 case op_lshift_eq:
2525 binop = op_lshift;
2526 break;
2527
2528 case op_rshift_eq:
2529 binop = op_rshift;
2530 break;
2531
2532 case op_el_mul_eq:
2533 binop = op_el_mul;
2534 break;
2535
2536 case op_el_div_eq:
2537 binop = op_el_div;
2538 break;
2539
2540 case op_el_ldiv_eq:
2541 binop = op_el_ldiv;
2542 break;
2543
2544 case op_el_pow_eq:
2545 binop = op_el_pow;
2546 break;
2547
2548 case op_el_and_eq:
2549 binop = op_el_and;
2550 break;
2551
2552 case op_el_or_eq:
2553 binop = op_el_or;
2554 break;
2555
2556 default:
2557 {
2558 std::string on = assign_op_as_string (op);
2559 error ("operator %s: no binary operator found", on.c_str ());
2560 }
2561 }
2562
2563 return binop;
2564}
2565
2566octave_value
2567octave_value::empty_conv (const std::string& type, const octave_value& rhs)
2568{
2569 octave_value retval;
2570
2571 if (type.length () > 0)
2572 {
2573 switch (type[0])
2574 {
2575 case '(':
2576 {
2577 if (type.length () > 1 && type[1] == '.')
2578 retval = Octave_map ();
2579 else
2580 retval = octave_value (rhs.empty_clone ());
2581 }
2582 break;
2583
2584 case '{':
2585 retval = Cell ();
2586 break;
2587
2588 case '.':
2589 retval = Octave_map ();
2590 break;
2591
2592 default:
2593 panic_impossible ();
2594 }
2595 }
2596 else
2597 retval = octave_value (rhs.empty_clone ());
2598
2599 return retval;
2600}
2601
2602void
2603install_types (void)
2604{
2605 octave_base_value::register_type ();
2606 octave_cell::register_type ();
2607 octave_scalar::register_type ();
2608 octave_complex::register_type ();
2609 octave_matrix::register_type ();
2610 octave_diag_matrix::register_type ();
2611 octave_complex_matrix::register_type ();
2612 octave_complex_diag_matrix::register_type ();
2613 octave_range::register_type ();
2614 octave_bool::register_type ();
2615 octave_bool_matrix::register_type ();
2616 octave_char_matrix_str::register_type ();
2617 octave_char_matrix_sq_str::register_type ();
2618 octave_int8_scalar::register_type ();
2619 octave_int16_scalar::register_type ();
2620 octave_int32_scalar::register_type ();
2621 octave_int64_scalar::register_type ();
2622 octave_uint8_scalar::register_type ();
2623 octave_uint16_scalar::register_type ();
2624 octave_uint32_scalar::register_type ();
2625 octave_uint64_scalar::register_type ();
2626 octave_int8_matrix::register_type ();
2627 octave_int16_matrix::register_type ();
2628 octave_int32_matrix::register_type ();
2629 octave_int64_matrix::register_type ();
2630 octave_uint8_matrix::register_type ();
2631 octave_uint16_matrix::register_type ();
2632 octave_uint32_matrix::register_type ();
2633 octave_uint64_matrix::register_type ();
2634 octave_sparse_bool_matrix::register_type ();
2635 octave_sparse_matrix::register_type ();
2636 octave_sparse_complex_matrix::register_type ();
2637 octave_struct::register_type ();
2638 octave_class::register_type ();
2639 octave_cs_list::register_type ();
2640 octave_magic_colon::register_type ();
2641 octave_builtin::register_type ();
2642 octave_user_function::register_type ();
2643 octave_dld_function::register_type ();
2644 octave_fcn_handle::register_type ();
2645 octave_fcn_inline::register_type ();
2646 octave_float_scalar::register_type ();
2647 octave_float_complex::register_type ();
2648 octave_float_matrix::register_type ();
2649 octave_float_diag_matrix::register_type ();
2650 octave_float_complex_matrix::register_type ();
2651 octave_float_complex_diag_matrix::register_type ();
2652 octave_perm_matrix::register_type ();
2653 octave_null_matrix::register_type ();
2654 octave_null_str::register_type ();
2655 octave_null_sq_str::register_type ();
2656}
2657
2658#if 0
2659DEFUN (cast, args, ,
2660 "-*- texinfo -*-\n\
2661@deftypefn {Built-in Function} {} cast (@var{val}, @var{type})\n\
2662Convert @var{val} to the new data type @var{type}.\n\
2663@seealso{class, typeinfo}\n\
2664@end deftypefn")
2665{
2666 octave_value retval;
2667
2668 if (args.length () == 2)
2669 error ("cast: not implemented");
2670 else
2671 print_usage ();
2672
2673 return retval;
2674}
2675#endif
2676
2677DEFUN (sizeof, args, ,
2678 "-*- texinfo -*-\n\
2679@deftypefn {Built-in Function} {} sizeof (@var{val})\n\
2680Return the size of @var{val} in bytes\n\
2681@end deftypefn")
2682{
2683 octave_value retval;
2684
2685 if (args.length () == 1)
2686 retval = args(0).byte_size ();
2687 else
2688 print_usage ();
2689
2690 return retval;
2691}
2692
2693DEFUN (subsref, args, nargout,
2694 "-*- texinfo -*-\n\
2695@deftypefn {Built-in Function} {} subsref (@var{val}, @var{idx})\n\
2696Perform the subscripted element selection operation according to\n\
2697the subscript specified by @var{idx}.\n\
2698\n\
2699The subscript @var{idx} is expected to be a structure array with\n\
2700fields @samp{type} and @samp{subs}. Valid values for @samp{type}\n\
2701are @samp{\"()\"}, @samp{\"@{@}\"}, and @samp{\".\"}.\n\
2702The @samp{subs} field may be either @samp{\":\"} or a cell array\n\
2703of index values.\n\
2704\n\
2705The following example shows how to extract the two first columns of\n\
2706a matrix\n\
2707\n\
2708@example\n\
2709@group\n\
2710val = magic(3)\n\
2711 @result{} val = [ 8 1 6\n\
2712 3 5 7\n\
2713 4 9 2 ]\n\
2714idx.type = \"()\";\n\
2715idx.subs = @{\":\", 1:2@};\n\
2716subsref(val, idx)\n\
2717 @result{} [ 8 1 \n\
2718 3 5 \n\
2719 4 9 ]\n\
2720@end group\n\
2721@end example\n\
2722\n\
2723@noindent\n\
2724Note that this is the same as writing @code{val(:,1:2)}.\n\
2725@seealso{subsasgn, substruct}\n\
2726@end deftypefn")
2727{
2728 octave_value_list retval;
2729
2730 if (args.length () == 2)
2731 {
2732 std::string type;
2733 std::list<octave_value_list> idx;
2734
2735 decode_subscripts ("subsref", args(1), type, idx);
2736
2737 if (! error_state)
2738 {
2739 octave_value tmp = args(0);
2740 retval = tmp.subsref (type, idx, nargout);
2741 }
2742 }
2743 else
2744 print_usage ();
2745
2746 return retval;
2747}
2748
2749DEFUN (subsasgn, args, ,
2750 "-*- texinfo -*-\n\
2751@deftypefn {Built-in Function} {} subsasgn (@var{val}, @var{idx}, @var{rhs})\n\
2752Perform the subscripted assignment operation according to\n\
2753the subscript specified by @var{idx}.\n\
2754\n\
2755The subscript @var{idx} is expected to be a structure array with\n\
2756fields @samp{type} and @samp{subs}. Valid values for @samp{type}\n\
2757are @samp{\"()\"}, @samp{\"@{@}\"}, and @samp{\".\"}.\n\
2758The @samp{subs} field may be either @samp{\":\"} or a cell array\n\
2759of index values.\n\
2760\n\
2761The following example shows how to set the two first columns of a\n\
27623-by-3 matrix to zero.\n\
2763\n\
2764@example\n\
2765@group\n\
2766val = magic(3);\n\
2767idx.type = \"()\";\n\
2768idx.subs = @{\":\", 1:2@};\n\
2769subsasgn (val, idx, 0)\n\
2770 @result{} [ 0 0 6\n\
2771 0 0 7\n\
2772 0 0 2 ]\n\
2773@end group\n\
2774@end example\n\
2775\n\
2776Note that this is the same as writing @code{val(:,1:2) = 0}.\n\
2777@seealso{subsref, substruct}\n\
2778@end deftypefn")
2779{
2780 octave_value retval;
2781
2782 if (args.length () == 3)
2783 {
2784 std::string type;
2785 std::list<octave_value_list> idx;
2786
2787 decode_subscripts ("subsasgn", args(1), type, idx);
2788
2789 octave_value arg0 = args(0);
2790
2791 arg0.make_unique ();
2792
2793 if (! error_state)
2794 retval = arg0.subsasgn (type, idx, args(2));
2795 }
2796 else
2797 print_usage ();
2798
2799 return retval;
2800}