ov.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1996-2012 John W. Eaton
00004 Copyright (C) 2009-2010 VZLU Prague
00005 
00006 This file is part of Octave.
00007 
00008 Octave is free software; you can redistribute it and/or modify it
00009 under the terms of the GNU General Public License as published by the
00010 Free Software Foundation; either version 3 of the License, or (at your
00011 option) any later version.
00012 
00013 Octave is distributed in the hope that it will be useful, but WITHOUT
00014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00015 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00016 for more details.
00017 
00018 You should have received a copy of the GNU General Public License
00019 along with Octave; see the file COPYING.  If not, see
00020 <http://www.gnu.org/licenses/>.
00021 
00022 */
00023 
00024 #ifdef HAVE_CONFIG_H
00025 #include <config.h>
00026 #endif
00027 
00028 #include "data-conv.h"
00029 #include "quit.h"
00030 #include "str-vec.h"
00031 
00032 #include "oct-obj.h"
00033 #include "oct-stream.h"
00034 #include "ov.h"
00035 #include "ov-base.h"
00036 #include "ov-bool.h"
00037 #include "ov-bool-mat.h"
00038 #include "ov-cell.h"
00039 #include "ov-scalar.h"
00040 #include "ov-float.h"
00041 #include "ov-re-mat.h"
00042 #include "ov-flt-re-mat.h"
00043 #include "ov-re-diag.h"
00044 #include "ov-flt-re-diag.h"
00045 #include "ov-perm.h"
00046 #include "ov-bool-sparse.h"
00047 #include "ov-cx-sparse.h"
00048 #include "ov-re-sparse.h"
00049 #include "ov-int8.h"
00050 #include "ov-int16.h"
00051 #include "ov-int32.h"
00052 #include "ov-int64.h"
00053 #include "ov-uint8.h"
00054 #include "ov-uint16.h"
00055 #include "ov-uint32.h"
00056 #include "ov-uint64.h"
00057 #include "ov-complex.h"
00058 #include "ov-flt-complex.h"
00059 #include "ov-cx-mat.h"
00060 #include "ov-flt-cx-mat.h"
00061 #include "ov-cx-diag.h"
00062 #include "ov-flt-cx-diag.h"
00063 #include "ov-ch-mat.h"
00064 #include "ov-str-mat.h"
00065 #include "ov-range.h"
00066 #include "ov-struct.h"
00067 #include "ov-class.h"
00068 #include "ov-oncleanup.h"
00069 #include "ov-cs-list.h"
00070 #include "ov-colon.h"
00071 #include "ov-builtin.h"
00072 #include "ov-dld-fcn.h"
00073 #include "ov-usr-fcn.h"
00074 #include "ov-fcn-handle.h"
00075 #include "ov-fcn-inline.h"
00076 #include "ov-typeinfo.h"
00077 #include "ov-null-mat.h"
00078 #include "ov-lazy-idx.h"
00079 
00080 #include "defun.h"
00081 #include "error.h"
00082 #include "gripes.h"
00083 #include "pager.h"
00084 #include "parse.h"
00085 #include "pr-output.h"
00086 #include "symtab.h"
00087 #include "utils.h"
00088 #include "variables.h"
00089 
00090 // We are likely to have a lot of octave_value objects to allocate, so
00091 // make the grow_size large.
00092 DEFINE_OCTAVE_ALLOCATOR2(octave_value, 1024);
00093 
00094 // FIXME
00095 
00096 // Octave's value type.
00097 
00098 std::string
00099 octave_value::unary_op_as_string (unary_op op)
00100 {
00101   std::string retval;
00102 
00103   switch (op)
00104     {
00105     case op_not:
00106       retval = "!";
00107       break;
00108 
00109     case op_uplus:
00110       retval = "+";
00111       break;
00112 
00113     case op_uminus:
00114       retval = "-";
00115       break;
00116 
00117     case op_transpose:
00118       retval = ".'";
00119       break;
00120 
00121     case op_hermitian:
00122       retval = "'";
00123       break;
00124 
00125     case op_incr:
00126       retval = "++";
00127       break;
00128 
00129     case op_decr:
00130       retval = "--";
00131       break;
00132 
00133     default:
00134       retval = "<unknown>";
00135     }
00136 
00137   return retval;
00138 }
00139 
00140 std::string
00141 octave_value::unary_op_fcn_name (unary_op op)
00142 {
00143   std::string retval;
00144 
00145   switch (op)
00146     {
00147     case op_not:
00148       retval = "not";
00149       break;
00150 
00151     case op_uplus:
00152       retval = "uplus";
00153       break;
00154 
00155     case op_uminus:
00156       retval = "uminus";
00157       break;
00158 
00159     case op_transpose:
00160       retval = "transpose";
00161       break;
00162 
00163     case op_hermitian:
00164       retval = "ctranspose";
00165       break;
00166 
00167     default:
00168       break;
00169     }
00170 
00171   return retval;
00172 }
00173 
00174 std::string
00175 octave_value::binary_op_as_string (binary_op op)
00176 {
00177   std::string retval;
00178 
00179   switch (op)
00180     {
00181     case op_add:
00182       retval = "+";
00183       break;
00184 
00185     case op_sub:
00186       retval = "-";
00187       break;
00188 
00189     case op_mul:
00190       retval = "*";
00191       break;
00192 
00193     case op_div:
00194       retval = "/";
00195       break;
00196 
00197     case op_pow:
00198       retval = "^";
00199       break;
00200 
00201     case op_ldiv:
00202       retval = "\\";
00203       break;
00204 
00205     case op_lshift:
00206       retval = "<<";
00207       break;
00208 
00209     case op_rshift:
00210       retval = ">>";
00211       break;
00212 
00213     case op_lt:
00214       retval = "<";
00215       break;
00216 
00217     case op_le:
00218       retval = "<=";
00219       break;
00220 
00221     case op_eq:
00222       retval = "==";
00223       break;
00224 
00225     case op_ge:
00226       retval = ">=";
00227       break;
00228 
00229     case op_gt:
00230       retval = ">";
00231       break;
00232 
00233     case op_ne:
00234       retval = "!=";
00235       break;
00236 
00237     case op_el_mul:
00238       retval = ".*";
00239       break;
00240 
00241     case op_el_div:
00242       retval = "./";
00243       break;
00244 
00245     case op_el_pow:
00246       retval = ".^";
00247       break;
00248 
00249     case op_el_ldiv:
00250       retval = ".\\";
00251       break;
00252 
00253     case op_el_and:
00254       retval = "&";
00255       break;
00256 
00257     case op_el_or:
00258       retval = "|";
00259       break;
00260 
00261     case op_struct_ref:
00262       retval = ".";
00263       break;
00264 
00265     default:
00266       retval = "<unknown>";
00267     }
00268 
00269   return retval;
00270 }
00271 
00272 std::string
00273 octave_value::binary_op_fcn_name (binary_op op)
00274 {
00275   std::string retval;
00276 
00277   switch (op)
00278     {
00279     case op_add:
00280       retval = "plus";
00281       break;
00282 
00283     case op_sub:
00284       retval = "minus";
00285       break;
00286 
00287     case op_mul:
00288       retval = "mtimes";
00289       break;
00290 
00291     case op_div:
00292       retval = "mrdivide";
00293       break;
00294 
00295     case op_pow:
00296       retval = "mpower";
00297       break;
00298 
00299     case op_ldiv:
00300       retval = "mldivide";
00301       break;
00302 
00303     case op_lt:
00304       retval = "lt";
00305       break;
00306 
00307     case op_le:
00308       retval = "le";
00309       break;
00310 
00311     case op_eq:
00312       retval = "eq";
00313       break;
00314 
00315     case op_ge:
00316       retval = "ge";
00317       break;
00318 
00319     case op_gt:
00320       retval = "gt";
00321       break;
00322 
00323     case op_ne:
00324       retval = "ne";
00325       break;
00326 
00327     case op_el_mul:
00328       retval = "times";
00329       break;
00330 
00331     case op_el_div:
00332       retval = "rdivide";
00333       break;
00334 
00335     case op_el_pow:
00336       retval = "power";
00337       break;
00338 
00339     case op_el_ldiv:
00340       retval = "ldivide";
00341       break;
00342 
00343     case op_el_and:
00344       retval = "and";
00345       break;
00346 
00347     case op_el_or:
00348       retval = "or";
00349       break;
00350 
00351     default:
00352       break;
00353     }
00354 
00355   return retval;
00356 }
00357 
00358 std::string
00359 octave_value::binary_op_fcn_name (compound_binary_op op)
00360 {
00361   std::string retval;
00362 
00363   switch (op)
00364     {
00365     case op_trans_mul:
00366       retval = "transtimes";
00367       break;
00368 
00369     case op_mul_trans:
00370       retval = "timestrans";
00371       break;
00372 
00373     case op_herm_mul:
00374       retval = "hermtimes";
00375       break;
00376 
00377     case op_mul_herm:
00378       retval = "timesherm";
00379       break;
00380 
00381     case op_trans_ldiv:
00382       retval = "transldiv";
00383       break;
00384 
00385     case op_herm_ldiv:
00386       retval = "hermldiv";
00387       break;
00388 
00389     case op_el_and_not:
00390       retval = "andnot";
00391       break;
00392 
00393     case op_el_or_not:
00394       retval = "ornot";
00395       break;
00396 
00397     case op_el_not_and:
00398       retval = "notand";
00399       break;
00400 
00401     case op_el_not_or:
00402       retval = "notor";
00403       break;
00404 
00405     default:
00406       break;
00407     }
00408 
00409   return retval;
00410 }
00411 
00412 std::string
00413 octave_value::assign_op_as_string (assign_op op)
00414 {
00415   std::string retval;
00416 
00417   switch (op)
00418     {
00419     case op_asn_eq:
00420       retval = "=";
00421       break;
00422 
00423     case op_add_eq:
00424       retval = "+=";
00425       break;
00426 
00427     case op_sub_eq:
00428       retval = "-=";
00429       break;
00430 
00431     case op_mul_eq:
00432       retval = "*=";
00433       break;
00434 
00435     case op_div_eq:
00436       retval = "/=";
00437       break;
00438 
00439     case op_ldiv_eq:
00440       retval = "\\=";
00441       break;
00442 
00443     case op_pow_eq:
00444       retval = "^=";
00445       break;
00446 
00447     case op_lshift_eq:
00448       retval = "<<=";
00449       break;
00450 
00451     case op_rshift_eq:
00452       retval = ">>=";
00453       break;
00454 
00455     case op_el_mul_eq:
00456       retval = ".*=";
00457       break;
00458 
00459     case op_el_div_eq:
00460       retval = "./=";
00461       break;
00462 
00463     case op_el_ldiv_eq:
00464       retval = ".\\=";
00465       break;
00466 
00467     case op_el_pow_eq:
00468       retval = ".^=";
00469       break;
00470 
00471     case op_el_and_eq:
00472       retval = "&=";
00473       break;
00474 
00475     case op_el_or_eq:
00476       retval = "|=";
00477       break;
00478 
00479     default:
00480       retval = "<unknown>";
00481     }
00482 
00483   return retval;
00484 }
00485 
00486 octave_value::assign_op
00487 octave_value::binary_op_to_assign_op (binary_op op)
00488 {
00489   assign_op retval;
00490 
00491   switch (op)
00492     {
00493     case op_add:
00494       retval = op_add_eq;
00495       break;
00496     case op_sub:
00497       retval = op_sub_eq;
00498       break;
00499     case op_mul:
00500       retval = op_mul_eq;
00501       break;
00502     case op_div:
00503       retval = op_div_eq;
00504       break;
00505     case op_el_mul:
00506       retval = op_el_mul_eq;
00507       break;
00508     case op_el_div:
00509       retval = op_el_div_eq;
00510       break;
00511     case op_el_and:
00512       retval = op_el_and_eq;
00513       break;
00514     case op_el_or:
00515       retval = op_el_or_eq;
00516       break;
00517     default:
00518       retval = unknown_assign_op;
00519     }
00520 
00521   return retval;
00522 }
00523 
00524 octave_value::octave_value (short int i)
00525   : rep (new octave_scalar (i))
00526 {
00527 }
00528 
00529 octave_value::octave_value (unsigned short int i)
00530   : rep (new octave_scalar (i))
00531 {
00532 }
00533 
00534 octave_value::octave_value (int i)
00535   : rep (new octave_scalar (i))
00536 {
00537 }
00538 
00539 octave_value::octave_value (unsigned int i)
00540   : rep (new octave_scalar (i))
00541 {
00542 }
00543 
00544 octave_value::octave_value (long int i)
00545   : rep (new octave_scalar (i))
00546 {
00547 }
00548 
00549 octave_value::octave_value (unsigned long int i)
00550   : rep (new octave_scalar (i))
00551 {
00552 }
00553 
00554 #if defined (HAVE_LONG_LONG_INT)
00555 octave_value::octave_value (long long int i)
00556   : rep (new octave_scalar (i))
00557 {
00558 }
00559 #endif
00560 
00561 #if defined (HAVE_UNSIGNED_LONG_LONG_INT)
00562 octave_value::octave_value (unsigned long long int i)
00563   : rep (new octave_scalar (i))
00564 {
00565 }
00566 #endif
00567 
00568 octave_value::octave_value (octave_time t)
00569   : rep (new octave_scalar (t.double_value ()))
00570 {
00571 }
00572 
00573 octave_value::octave_value (double d)
00574   : rep (new octave_scalar (d))
00575 {
00576 }
00577 
00578 octave_value::octave_value (float d)
00579   : rep (new octave_float_scalar (d))
00580 {
00581 }
00582 
00583 octave_value::octave_value (const Cell& c, bool is_csl)
00584   : rep (is_csl
00585          ? dynamic_cast<octave_base_value *> (new octave_cs_list (c))
00586          : dynamic_cast<octave_base_value *> (new octave_cell (c)))
00587 {
00588 }
00589 
00590 octave_value::octave_value (const Array<octave_value>& a, bool is_csl)
00591   : rep (is_csl
00592          ? dynamic_cast<octave_base_value *> (new octave_cs_list (Cell (a)))
00593          : dynamic_cast<octave_base_value *> (new octave_cell (Cell (a))))
00594 {
00595 }
00596 
00597 octave_value::octave_value (const Matrix& m, const MatrixType& t)
00598   : rep (new octave_matrix (m, t))
00599 {
00600   maybe_mutate ();
00601 }
00602 
00603 octave_value::octave_value (const FloatMatrix& m, const MatrixType& t)
00604   : rep (new octave_float_matrix (m, t))
00605 {
00606   maybe_mutate ();
00607 }
00608 
00609 octave_value::octave_value (const NDArray& a)
00610   : rep (new octave_matrix (a))
00611 {
00612   maybe_mutate ();
00613 }
00614 
00615 octave_value::octave_value (const FloatNDArray& a)
00616   : rep (new octave_float_matrix (a))
00617 {
00618   maybe_mutate ();
00619 }
00620 
00621 octave_value::octave_value (const Array<double>& a)
00622   : rep (new octave_matrix (a))
00623 {
00624   maybe_mutate ();
00625 }
00626 
00627 octave_value::octave_value (const Array<float>& a)
00628   : rep (new octave_float_matrix (a))
00629 {
00630   maybe_mutate ();
00631 }
00632 
00633 octave_value::octave_value (const DiagArray2<double>& d)
00634   : rep (new octave_diag_matrix (d))
00635 {
00636   maybe_mutate ();
00637 }
00638 
00639 octave_value::octave_value (const DiagArray2<float>& d)
00640   : rep (new octave_float_diag_matrix (d))
00641 {
00642   maybe_mutate ();
00643 }
00644 
00645 octave_value::octave_value (const DiagArray2<Complex>& d)
00646   : rep (new octave_complex_diag_matrix (d))
00647 {
00648   maybe_mutate ();
00649 }
00650 
00651 octave_value::octave_value (const DiagArray2<FloatComplex>& d)
00652   : rep (new octave_float_complex_diag_matrix (d))
00653 {
00654   maybe_mutate ();
00655 }
00656 
00657 octave_value::octave_value (const DiagMatrix& d)
00658   : rep (new octave_diag_matrix (d))
00659 {
00660   maybe_mutate ();
00661 }
00662 
00663 octave_value::octave_value (const FloatDiagMatrix& d)
00664   : rep (new octave_float_diag_matrix (d))
00665 {
00666   maybe_mutate ();
00667 }
00668 
00669 octave_value::octave_value (const RowVector& v)
00670   : rep (new octave_matrix (v))
00671 {
00672   maybe_mutate ();
00673 }
00674 
00675 octave_value::octave_value (const FloatRowVector& v)
00676   : rep (new octave_float_matrix (v))
00677 {
00678   maybe_mutate ();
00679 }
00680 
00681 octave_value::octave_value (const ColumnVector& v)
00682   : rep (new octave_matrix (v))
00683 {
00684   maybe_mutate ();
00685 }
00686 
00687 octave_value::octave_value (const FloatColumnVector& v)
00688   : rep (new octave_float_matrix (v))
00689 {
00690   maybe_mutate ();
00691 }
00692 
00693 octave_value::octave_value (const Complex& C)
00694   : rep (new octave_complex (C))
00695 {
00696   maybe_mutate ();
00697 }
00698 
00699 octave_value::octave_value (const FloatComplex& C)
00700   : rep (new octave_float_complex (C))
00701 {
00702   maybe_mutate ();
00703 }
00704 
00705 octave_value::octave_value (const ComplexMatrix& m, const MatrixType& t)
00706   : rep (new octave_complex_matrix (m, t))
00707 {
00708   maybe_mutate ();
00709 }
00710 
00711 octave_value::octave_value (const FloatComplexMatrix& m, const MatrixType& t)
00712   : rep (new octave_float_complex_matrix (m, t))
00713 {
00714   maybe_mutate ();
00715 }
00716 
00717 octave_value::octave_value (const ComplexNDArray& a)
00718   : rep (new octave_complex_matrix (a))
00719 {
00720   maybe_mutate ();
00721 }
00722 
00723 octave_value::octave_value (const FloatComplexNDArray& a)
00724   : rep (new octave_float_complex_matrix (a))
00725 {
00726   maybe_mutate ();
00727 }
00728 
00729 octave_value::octave_value (const Array<Complex>& a)
00730   : rep (new octave_complex_matrix (a))
00731 {
00732   maybe_mutate ();
00733 }
00734 
00735 octave_value::octave_value (const Array<FloatComplex>& a)
00736   : rep (new octave_float_complex_matrix (a))
00737 {
00738   maybe_mutate ();
00739 }
00740 
00741 octave_value::octave_value (const ComplexDiagMatrix& d)
00742   : rep (new octave_complex_diag_matrix (d))
00743 {
00744   maybe_mutate ();
00745 }
00746 
00747 octave_value::octave_value (const FloatComplexDiagMatrix& d)
00748   : rep (new octave_float_complex_diag_matrix (d))
00749 {
00750   maybe_mutate ();
00751 }
00752 
00753 octave_value::octave_value (const ComplexRowVector& v)
00754   : rep (new octave_complex_matrix (v))
00755 {
00756   maybe_mutate ();
00757 }
00758 
00759 octave_value::octave_value (const FloatComplexRowVector& v)
00760   : rep (new octave_float_complex_matrix (v))
00761 {
00762   maybe_mutate ();
00763 }
00764 
00765 octave_value::octave_value (const ComplexColumnVector& v)
00766   : rep (new octave_complex_matrix (v))
00767 {
00768   maybe_mutate ();
00769 }
00770 
00771 octave_value::octave_value (const FloatComplexColumnVector& v)
00772   : rep (new octave_float_complex_matrix (v))
00773 {
00774   maybe_mutate ();
00775 }
00776 
00777 octave_value::octave_value (const PermMatrix& p)
00778   : rep (new octave_perm_matrix (p))
00779 {
00780   maybe_mutate ();
00781 }
00782 
00783 octave_value::octave_value (bool b)
00784   : rep (new octave_bool (b))
00785 {
00786 }
00787 
00788 octave_value::octave_value (const boolMatrix& bm, const MatrixType& t)
00789   : rep (new octave_bool_matrix (bm, t))
00790 {
00791   maybe_mutate ();
00792 }
00793 
00794 octave_value::octave_value (const boolNDArray& bnda)
00795   : rep (new octave_bool_matrix (bnda))
00796 {
00797   maybe_mutate ();
00798 }
00799 
00800 octave_value::octave_value (const Array<bool>& bnda)
00801   : rep (new octave_bool_matrix (bnda))
00802 {
00803   maybe_mutate ();
00804 }
00805 
00806 octave_value::octave_value (char c, char type)
00807   : rep (type == '"'
00808          ? new octave_char_matrix_dq_str (c)
00809          : new octave_char_matrix_sq_str (c))
00810 {
00811   maybe_mutate ();
00812 }
00813 
00814 octave_value::octave_value (const char *s, char type)
00815   : rep (type == '"'
00816          ? new octave_char_matrix_dq_str (s)
00817          : new octave_char_matrix_sq_str (s))
00818 {
00819   maybe_mutate ();
00820 }
00821 
00822 octave_value::octave_value (const std::string& s, char type)
00823   : rep (type == '"'
00824          ? new octave_char_matrix_dq_str (s)
00825          : new octave_char_matrix_sq_str (s))
00826 {
00827   maybe_mutate ();
00828 }
00829 
00830 octave_value::octave_value (const string_vector& s, char type)
00831   : rep (type == '"'
00832          ? new octave_char_matrix_dq_str (s)
00833          : new octave_char_matrix_sq_str (s))
00834 {
00835   maybe_mutate ();
00836 }
00837 
00838 octave_value::octave_value (const charMatrix& chm, char type)
00839   : rep (type == '"'
00840          ? new octave_char_matrix_dq_str (chm)
00841          : new octave_char_matrix_sq_str (chm))
00842 {
00843   maybe_mutate ();
00844 }
00845 
00846 octave_value::octave_value (const charNDArray& chm, char type)
00847   : rep (type == '"'
00848          ? new octave_char_matrix_dq_str (chm)
00849          : new octave_char_matrix_sq_str (chm))
00850 {
00851   maybe_mutate ();
00852 }
00853 
00854 octave_value::octave_value (const Array<char>& chm, char type)
00855   : rep (type == '"'
00856          ? new octave_char_matrix_dq_str (chm)
00857          : new octave_char_matrix_sq_str (chm))
00858 {
00859   maybe_mutate ();
00860 }
00861 
00862 octave_value::octave_value (const charMatrix& chm, bool, char type)
00863   : rep (type == '"'
00864          ? new octave_char_matrix_dq_str (chm)
00865          : new octave_char_matrix_sq_str (chm))
00866 {
00867   maybe_mutate ();
00868 }
00869 
00870 octave_value::octave_value (const charNDArray& chm, bool, char type)
00871   : rep (type == '"'
00872          ? new octave_char_matrix_dq_str (chm)
00873          : new octave_char_matrix_sq_str (chm))
00874 {
00875   maybe_mutate ();
00876 }
00877 
00878 octave_value::octave_value (const Array<char>& chm, bool, char type)
00879   : rep (type == '"'
00880          ? new octave_char_matrix_dq_str (chm)
00881          : new octave_char_matrix_sq_str (chm))
00882 {
00883   maybe_mutate ();
00884 }
00885 
00886 octave_value::octave_value (const SparseMatrix& m, const MatrixType &t)
00887   : rep (new octave_sparse_matrix (m, t))
00888 {
00889   maybe_mutate ();
00890 }
00891 
00892 octave_value::octave_value (const Sparse<double>& m, const MatrixType &t)
00893   : rep (new octave_sparse_matrix (m, t))
00894 {
00895   maybe_mutate ();
00896 }
00897 
00898 octave_value::octave_value (const SparseComplexMatrix& m, const MatrixType &t)
00899   : rep (new octave_sparse_complex_matrix (m, t))
00900 {
00901   maybe_mutate ();
00902 }
00903 
00904 octave_value::octave_value (const Sparse<Complex>& m, const MatrixType &t)
00905   : rep (new octave_sparse_complex_matrix (m, t))
00906 {
00907   maybe_mutate ();
00908 }
00909 
00910 octave_value::octave_value (const SparseBoolMatrix& bm, const MatrixType &t)
00911   : rep (new octave_sparse_bool_matrix (bm, t))
00912 {
00913   maybe_mutate ();
00914 }
00915 
00916 octave_value::octave_value (const Sparse<bool>& bm, const MatrixType &t)
00917   : rep (new octave_sparse_bool_matrix (bm, t))
00918 {
00919   maybe_mutate ();
00920 }
00921 
00922 octave_value::octave_value (const octave_int8& i)
00923   : rep (new octave_int8_scalar (i))
00924 {
00925   maybe_mutate ();
00926 }
00927 
00928 octave_value::octave_value (const octave_uint8& i)
00929   : rep (new octave_uint8_scalar (i))
00930 {
00931   maybe_mutate ();
00932 }
00933 
00934 octave_value::octave_value (const octave_int16& i)
00935   : rep (new octave_int16_scalar (i))
00936 {
00937   maybe_mutate ();
00938 }
00939 
00940 octave_value::octave_value (const octave_uint16& i)
00941   : rep (new octave_uint16_scalar (i))
00942 {
00943   maybe_mutate ();
00944 }
00945 
00946 octave_value::octave_value (const octave_int32& i)
00947   : rep (new octave_int32_scalar (i))
00948 {
00949   maybe_mutate ();
00950 }
00951 
00952 octave_value::octave_value (const octave_uint32& i)
00953   : rep (new octave_uint32_scalar (i))
00954 {
00955   maybe_mutate ();
00956 }
00957 
00958 octave_value::octave_value (const octave_int64& i)
00959   : rep (new octave_int64_scalar (i))
00960 {
00961   maybe_mutate ();
00962 }
00963 
00964 octave_value::octave_value (const octave_uint64& i)
00965   : rep (new octave_uint64_scalar (i))
00966 {
00967   maybe_mutate ();
00968 }
00969 
00970 octave_value::octave_value (const int8NDArray& inda)
00971   : rep (new octave_int8_matrix (inda))
00972 {
00973   maybe_mutate ();
00974 }
00975 
00976 octave_value::octave_value (const Array<octave_int8>& inda)
00977   : rep (new octave_int8_matrix (inda))
00978 {
00979   maybe_mutate ();
00980 }
00981 
00982 octave_value::octave_value (const uint8NDArray& inda)
00983   : rep (new octave_uint8_matrix (inda))
00984 {
00985   maybe_mutate ();
00986 }
00987 
00988 octave_value::octave_value (const Array<octave_uint8>& inda)
00989   : rep (new octave_uint8_matrix (inda))
00990 {
00991   maybe_mutate ();
00992 }
00993 
00994 octave_value::octave_value (const int16NDArray& inda)
00995   : rep (new octave_int16_matrix (inda))
00996 {
00997   maybe_mutate ();
00998 }
00999 
01000 octave_value::octave_value (const Array<octave_int16>& inda)
01001   : rep (new octave_int16_matrix (inda))
01002 {
01003   maybe_mutate ();
01004 }
01005 
01006 octave_value::octave_value (const uint16NDArray& inda)
01007   : rep (new octave_uint16_matrix (inda))
01008 {
01009   maybe_mutate ();
01010 }
01011 
01012 octave_value::octave_value (const Array<octave_uint16>& inda)
01013   : rep (new octave_uint16_matrix (inda))
01014 {
01015   maybe_mutate ();
01016 }
01017 
01018 octave_value::octave_value (const int32NDArray& inda)
01019   : rep (new octave_int32_matrix (inda))
01020 {
01021   maybe_mutate ();
01022 }
01023 
01024 octave_value::octave_value (const Array<octave_int32>& inda)
01025   : rep (new octave_int32_matrix (inda))
01026 {
01027   maybe_mutate ();
01028 }
01029 
01030 octave_value::octave_value (const uint32NDArray& inda)
01031   : rep (new octave_uint32_matrix (inda))
01032 {
01033   maybe_mutate ();
01034 }
01035 
01036 octave_value::octave_value (const Array<octave_uint32>& inda)
01037   : rep (new octave_uint32_matrix (inda))
01038 {
01039   maybe_mutate ();
01040 }
01041 
01042 octave_value::octave_value (const int64NDArray& inda)
01043   : rep (new octave_int64_matrix (inda))
01044 {
01045   maybe_mutate ();
01046 }
01047 
01048 octave_value::octave_value (const Array<octave_int64>& inda)
01049   : rep (new octave_int64_matrix (inda))
01050 {
01051   maybe_mutate ();
01052 }
01053 
01054 octave_value::octave_value (const uint64NDArray& inda)
01055   : rep (new octave_uint64_matrix (inda))
01056 {
01057   maybe_mutate ();
01058 }
01059 
01060 octave_value::octave_value (const Array<octave_uint64>& inda)
01061   : rep (new octave_uint64_matrix (inda))
01062 {
01063   maybe_mutate ();
01064 }
01065 
01066 octave_value::octave_value (const Array<octave_idx_type>& inda, bool zero_based,
01067                             bool cache_index)
01068   : rep (new octave_matrix (inda, zero_based, cache_index))
01069 {
01070   maybe_mutate ();
01071 }
01072 
01073 octave_value::octave_value (const idx_vector& idx, bool lazy)
01074   : rep ()
01075 {
01076   double scalar;
01077   Range range;
01078   NDArray array;
01079   boolNDArray mask;
01080   idx_vector::idx_class_type idx_class;
01081 
01082   if (lazy)
01083     {
01084       // Only make lazy indices out of ranges and index vectors.
01085       switch (idx.idx_class ())
01086         {
01087         case idx_vector::class_range:
01088         case idx_vector::class_vector:
01089           rep = new octave_lazy_index (idx);
01090           maybe_mutate ();
01091           return;
01092         default:
01093           break;
01094         }
01095     }
01096 
01097   idx.unconvert (idx_class, scalar, range, array, mask);
01098 
01099   switch (idx_class)
01100     {
01101     case idx_vector::class_colon:
01102       rep = new octave_magic_colon ();
01103       break;
01104     case idx_vector::class_range:
01105       rep = new octave_range (range, idx);
01106       break;
01107     case idx_vector::class_scalar:
01108       rep = new octave_scalar (scalar);
01109       break;
01110     case idx_vector::class_vector:
01111       rep = new octave_matrix (array, idx);
01112       break;
01113     case idx_vector::class_mask:
01114       rep = new octave_bool_matrix (mask, idx);
01115       break;
01116     default:
01117       assert (false);
01118       break;
01119     }
01120 
01121   // FIXME: needed?
01122   maybe_mutate ();
01123 }
01124 
01125 octave_value::octave_value (const Array<std::string>& cellstr)
01126   : rep (new octave_cell (cellstr))
01127 {
01128   maybe_mutate ();
01129 }
01130 
01131 octave_value::octave_value (double base, double limit, double inc)
01132   : rep (new octave_range (base, limit, inc))
01133 {
01134   maybe_mutate ();
01135 }
01136 
01137 octave_value::octave_value (const Range& r)
01138   : rep (new octave_range (r))
01139 {
01140   maybe_mutate ();
01141 }
01142 
01143 octave_value::octave_value (const octave_map& m)
01144   : rep (new octave_struct (m))
01145 {
01146   maybe_mutate ();
01147 }
01148 
01149 octave_value::octave_value (const octave_scalar_map& m)
01150   : rep (new octave_scalar_struct (m))
01151 {
01152 }
01153 
01154 octave_value::octave_value (const Octave_map& m)
01155   : rep (new octave_struct (m))
01156 {
01157   maybe_mutate ();
01158 }
01159 
01160 octave_value::octave_value (const Octave_map& m, const std::string& id,
01161                             const std::list<std::string>& plist)
01162   : rep (new octave_class (m, id, plist))
01163 {
01164 }
01165 
01166 octave_value::octave_value (const octave_value_list& l, bool)
01167   : rep (new octave_cs_list (l))
01168 {
01169 }
01170 
01171 octave_value::octave_value (octave_value::magic_colon)
01172   : rep (new octave_magic_colon ())
01173 {
01174 }
01175 
01176 octave_value::octave_value (octave_base_value *new_rep, bool borrow)
01177   : rep (new_rep)
01178 {
01179   if (borrow)
01180     rep->count++;
01181 }
01182 
01183 octave_value::octave_value (octave_base_value *new_rep, int xcount)
01184   : rep (new_rep)
01185 {
01186   rep->count = xcount;
01187 }
01188 
01189 octave_base_value *
01190 octave_value::clone (void) const
01191 {
01192   return rep->clone ();
01193 }
01194 
01195 void
01196 octave_value::maybe_mutate (void)
01197 {
01198   octave_base_value *tmp = rep->try_narrowing_conversion ();
01199 
01200   if (tmp && tmp != rep)
01201     {
01202       if (--rep->count == 0)
01203         delete rep;
01204 
01205       rep = tmp;
01206     }
01207 }
01208 
01209 octave_value
01210 octave_value::single_subsref (const std::string& type,
01211                               const octave_value_list& idx)
01212 {
01213   std::list<octave_value_list> i;
01214 
01215   i.push_back (idx);
01216 
01217   return rep->subsref (type, i);
01218 }
01219 
01220 octave_value_list
01221 octave_value::subsref (const std::string& type,
01222                        const std::list<octave_value_list>& idx, int nargout)
01223 {
01224   if (nargout == 1)
01225     return rep->subsref (type, idx);
01226   else
01227     return rep->subsref (type, idx, nargout);
01228 }
01229 
01230 octave_value_list
01231 octave_value::subsref (const std::string& type,
01232                        const std::list<octave_value_list>& idx, int nargout,
01233                        const std::list<octave_lvalue> *lvalue_list)
01234 {
01235   if (lvalue_list)
01236     return rep->subsref (type, idx, nargout, lvalue_list);
01237   else
01238     return subsref (type, idx, nargout);
01239 }
01240 
01241 octave_value
01242 octave_value::next_subsref (const std::string& type,
01243                             const std::list<octave_value_list>& idx,
01244                             size_t skip)
01245 {
01246   if (! error_state && idx.size () > skip)
01247     {
01248       std::list<octave_value_list> new_idx (idx);
01249       for (size_t i = 0; i < skip; i++)
01250         new_idx.erase (new_idx.begin ());
01251       return subsref (type.substr (skip), new_idx);
01252     }
01253   else
01254     return *this;
01255 }
01256 
01257 octave_value_list
01258 octave_value::next_subsref (int nargout, const std::string& type,
01259                             const std::list<octave_value_list>& idx,
01260                             size_t skip)
01261 {
01262   if (! error_state && idx.size () > skip)
01263     {
01264       std::list<octave_value_list> new_idx (idx);
01265       for (size_t i = 0; i < skip; i++)
01266         new_idx.erase (new_idx.begin ());
01267       return subsref (type.substr (skip), new_idx, nargout);
01268     }
01269   else
01270     return *this;
01271 }
01272 
01273 octave_value
01274 octave_value::next_subsref (bool auto_add, const std::string& type,
01275                             const std::list<octave_value_list>& idx,
01276                             size_t skip)
01277 {
01278   if (! error_state && idx.size () > skip)
01279     {
01280       std::list<octave_value_list> new_idx (idx);
01281       for (size_t i = 0; i < skip; i++)
01282         new_idx.erase (new_idx.begin ());
01283       return subsref (type.substr (skip), new_idx, auto_add);
01284     }
01285   else
01286     return *this;
01287 }
01288 
01289 octave_value_list
01290 octave_value::do_multi_index_op (int nargout, const octave_value_list& idx)
01291 {
01292   return rep->do_multi_index_op (nargout, idx);
01293 }
01294 
01295 octave_value_list
01296 octave_value::do_multi_index_op (int nargout, const octave_value_list& idx,
01297                                  const std::list<octave_lvalue> *lvalue_list)
01298 {
01299   return rep->do_multi_index_op (nargout, idx, lvalue_list);
01300 }
01301 
01302 #if 0
01303 static void
01304 gripe_assign_failed (const std::string& on, const std::string& tn1,
01305                      const std::string& tn2)
01306 {
01307   error ("assignment failed for '%s %s %s'",
01308          tn1.c_str (), on.c_str (), tn2.c_str ());
01309 }
01310 #endif
01311 
01312 static void
01313 gripe_assign_failed_or_no_method (const std::string& on,
01314                                   const std::string& tn1,
01315                                   const std::string& tn2)
01316 {
01317   error ("assignment failed, or no method for '%s %s %s'",
01318          tn1.c_str (), on.c_str (), tn2.c_str ());
01319 }
01320 
01321 octave_value
01322 octave_value::subsasgn (const std::string& type,
01323                         const std::list<octave_value_list>& idx,
01324                         const octave_value& rhs)
01325 {
01326   return rep->subsasgn (type, idx, rhs);
01327 }
01328 
01329 octave_value
01330 octave_value::undef_subsasgn (const std::string& type,
01331                               const std::list<octave_value_list>& idx,
01332                               const octave_value& rhs)
01333 {
01334   return rep->undef_subsasgn (type, idx, rhs);
01335 }
01336 
01337 octave_value&
01338 octave_value::assign (assign_op op, const std::string& type,
01339                       const std::list<octave_value_list>& idx,
01340                       const octave_value& rhs)
01341 {
01342   octave_value retval;
01343 
01344   make_unique ();
01345 
01346   octave_value t_rhs = rhs;
01347 
01348   if (op != op_asn_eq)
01349     {
01350       if (is_defined ())
01351         {
01352           octave_value t = subsref (type, idx);
01353 
01354           if (! error_state)
01355             {
01356               binary_op binop = op_eq_to_binary_op (op);
01357 
01358               if (! error_state)
01359                 t_rhs = do_binary_op (binop, t, rhs);
01360             }
01361         }
01362       else
01363         error ("in computed assignment A(index) OP= X, A must be defined first");
01364     }
01365 
01366   if (! error_state)
01367     {
01368       octave_value tmp = subsasgn (type, idx, t_rhs);
01369 
01370       if (error_state)
01371         gripe_assign_failed_or_no_method (assign_op_as_string (op_asn_eq),
01372                                           type_name (), rhs.type_name ());
01373       else
01374         *this = tmp;
01375     }
01376 
01377   return *this;
01378 }
01379 
01380 octave_value&
01381 octave_value::assign (assign_op op, const octave_value& rhs)
01382 {
01383   if (op == op_asn_eq)
01384     // Regularize a null matrix if stored into a variable.
01385     operator = (rhs.storable_value ());
01386   else if (is_defined ())
01387     {
01388       octave_value_typeinfo::assign_op_fcn f = 0;
01389 
01390       // Only attempt to operate in-place if this variable is unshared.
01391       if (rep->count == 1)
01392         {
01393           int tthis = this->type_id ();
01394           int trhs = rhs.type_id ();
01395 
01396           f = octave_value_typeinfo::lookup_assign_op (op, tthis, trhs);
01397         }
01398 
01399       if (f)
01400         {
01401           try
01402             {
01403               f (*rep, octave_value_list (), *rhs.rep);
01404               maybe_mutate (); // Usually unnecessary, but may be needed (complex arrays).
01405             }
01406           catch (octave_execution_exception)
01407             {
01408               gripe_library_execution_error ();
01409             }
01410         }
01411       else
01412         {
01413 
01414           binary_op binop = op_eq_to_binary_op (op);
01415 
01416           if (! error_state)
01417             {
01418               octave_value t = do_binary_op (binop, *this, rhs);
01419 
01420               if (! error_state)
01421                 operator = (t);
01422             }
01423         }
01424     }
01425   else
01426     error ("in computed assignment A OP= X, A must be defined first");
01427 
01428   return *this;
01429 }
01430 
01431 octave_idx_type
01432 octave_value::length (void) const
01433 {
01434   octave_idx_type retval = 0;
01435 
01436   const dim_vector dv = dims ();
01437 
01438   for (int i = 0; i < dv.length (); i++)
01439     {
01440       if (dv(i) == 0)
01441         {
01442           retval = 0;
01443           break;
01444         }
01445 
01446       if (dv(i) > retval)
01447         retval = dv(i);
01448     }
01449 
01450   return retval;
01451 }
01452 
01453 bool
01454 octave_value::is_equal (const octave_value& test) const
01455 {
01456   bool retval = false;
01457 
01458   // If there is no op_eq for these types, we can't compare values.
01459 
01460   if (rows () == test.rows () && columns () == test.columns ())
01461     {
01462       octave_value tmp = do_binary_op (octave_value::op_eq, *this, test);
01463 
01464       // Empty array also means a match.
01465       if (! error_state && tmp.is_defined ())
01466         retval = tmp.is_true () || tmp.is_empty ();
01467     }
01468 
01469   return retval;
01470 }
01471 
01472 Cell
01473 octave_value::cell_value (void) const
01474 {
01475   return rep->cell_value ();
01476 }
01477 
01478 // Define the idx_type_value function here instead of in ov.h to avoid
01479 // needing definitions for the SIZEOF_X macros in ov.h.
01480 
01481 octave_idx_type
01482 octave_value::idx_type_value (bool req_int, bool frc_str_conv) const
01483 {
01484 #if SIZEOF_OCTAVE_IDX_TYPE == SIZEOF_LONG
01485   return long_value (req_int, frc_str_conv);
01486 #elif SIZEOF_OCTAVE_IDX_TYPE == SIZEOF_INT
01487   return int_value (req_int, frc_str_conv);
01488 #else
01489 #error "no octave_value extractor for octave_idx_type"
01490 #endif
01491 }
01492 
01493 octave_map
01494 octave_value::map_value (void) const
01495 {
01496   return rep->map_value ();
01497 }
01498 
01499 octave_scalar_map
01500 octave_value::scalar_map_value (void) const
01501 {
01502   return rep->scalar_map_value ();
01503 }
01504 
01505 octave_function *
01506 octave_value::function_value (bool silent) const
01507 {
01508   return rep->function_value (silent);
01509 }
01510 
01511 octave_user_function *
01512 octave_value::user_function_value (bool silent) const
01513 {
01514   return rep->user_function_value (silent);
01515 }
01516 
01517 octave_user_script *
01518 octave_value::user_script_value (bool silent) const
01519 {
01520   return rep->user_script_value (silent);
01521 }
01522 
01523 octave_user_code *
01524 octave_value::user_code_value (bool silent) const
01525 {
01526   return rep->user_code_value (silent);
01527 }
01528 
01529 octave_fcn_handle *
01530 octave_value::fcn_handle_value (bool silent) const
01531 {
01532   return rep->fcn_handle_value (silent);
01533 }
01534 
01535 octave_fcn_inline *
01536 octave_value::fcn_inline_value (bool silent) const
01537 {
01538   return rep->fcn_inline_value (silent);
01539 }
01540 
01541 octave_value_list
01542 octave_value::list_value (void) const
01543 {
01544   return rep->list_value ();
01545 }
01546 
01547 static dim_vector
01548 make_vector_dims (const dim_vector& dv, bool force_vector_conversion,
01549                   const std::string& my_type, const std::string& wanted_type)
01550 {
01551   dim_vector retval (dv);
01552   retval.chop_trailing_singletons ();
01553   octave_idx_type nel = dv.numel ();
01554 
01555   if (retval.length () > 2 || (retval(0) != 1 && retval(1) != 1))
01556     {
01557       if (!force_vector_conversion)
01558         gripe_implicit_conversion ("Octave:array-as-vector",
01559                                    my_type.c_str (), wanted_type.c_str ());
01560       retval = dim_vector (nel, 1);
01561     }
01562 
01563   return retval;
01564 }
01565 
01566 ColumnVector
01567 octave_value::column_vector_value (bool force_string_conv,
01568                                    bool frc_vec_conv) const
01569 {
01570   return ColumnVector (vector_value (force_string_conv,
01571                                      frc_vec_conv));
01572 }
01573 
01574 ComplexColumnVector
01575 octave_value::complex_column_vector_value (bool force_string_conv,
01576                                            bool frc_vec_conv) const
01577 {
01578   return ComplexColumnVector (complex_vector_value (force_string_conv,
01579                                                     frc_vec_conv));
01580 }
01581 
01582 RowVector
01583 octave_value::row_vector_value (bool force_string_conv,
01584                                 bool frc_vec_conv) const
01585 {
01586   return RowVector (vector_value (force_string_conv,
01587                                   frc_vec_conv));
01588 }
01589 
01590 ComplexRowVector
01591 octave_value::complex_row_vector_value (bool force_string_conv,
01592                                         bool frc_vec_conv) const
01593 {
01594   return ComplexRowVector (complex_vector_value (force_string_conv,
01595                                                  frc_vec_conv));
01596 }
01597 
01598 Array<double>
01599 octave_value::vector_value (bool force_string_conv,
01600                             bool force_vector_conversion) const
01601 {
01602   Array<double> retval = array_value (force_string_conv);
01603 
01604   if (error_state)
01605     return retval;
01606   else
01607     return retval.reshape (make_vector_dims (retval.dims (),
01608                                              force_vector_conversion,
01609                                              type_name (), "real vector"));
01610 }
01611 
01612 template <class T>
01613 static Array<int>
01614 convert_to_int_array (const Array<octave_int<T> >& A)
01615 {
01616   Array<int> retval (A.dims ());
01617   octave_idx_type n = A.numel ();
01618 
01619   for (octave_idx_type i = 0; i < n; i++)
01620     retval.xelem (i) = octave_int<int> (A.xelem (i));
01621 
01622   return retval;
01623 }
01624 
01625 Array<int>
01626 octave_value::int_vector_value (bool force_string_conv, bool require_int,
01627                                 bool force_vector_conversion) const
01628 {
01629   Array<int> retval;
01630 
01631   if (is_integer_type ())
01632     {
01633       if (is_int32_type ())
01634         retval = convert_to_int_array (int32_array_value ());
01635       else if (is_int64_type ())
01636         retval = convert_to_int_array (int64_array_value ());
01637       else if (is_int16_type ())
01638         retval = convert_to_int_array (int16_array_value ());
01639       else if (is_int8_type ())
01640         retval = convert_to_int_array (int8_array_value ());
01641       else if (is_uint32_type ())
01642         retval = convert_to_int_array (uint32_array_value ());
01643       else if (is_uint64_type ())
01644         retval = convert_to_int_array (uint64_array_value ());
01645       else if (is_uint16_type ())
01646         retval = convert_to_int_array (uint16_array_value ());
01647       else if (is_uint8_type ())
01648         retval = convert_to_int_array (uint8_array_value ());
01649       else
01650         retval = array_value (force_string_conv);
01651     }
01652   else
01653     {
01654       const NDArray a = array_value (force_string_conv);
01655       if (! error_state)
01656         {
01657           if (require_int)
01658             {
01659               retval.resize (a.dims ());
01660               for (octave_idx_type i = 0; i < a.numel (); i++)
01661                 {
01662                   double ai = a.elem (i);
01663                   int v = static_cast<int> (ai);
01664                   if (ai == v)
01665                     retval.xelem (i) = v;
01666                   else
01667                     {
01668                       error_with_cfn ("conversion to integer value failed");
01669                       break;
01670                     }
01671                 }
01672             }
01673           else
01674             retval = Array<int> (a);
01675         }
01676     }
01677 
01678 
01679   if (error_state)
01680     return retval;
01681   else
01682     return retval.reshape (make_vector_dims (retval.dims (),
01683                                              force_vector_conversion,
01684                                              type_name (), "integer vector"));
01685 }
01686 
01687 template <class T>
01688 static Array<octave_idx_type>
01689 convert_to_octave_idx_type_array (const Array<octave_int<T> >& A)
01690 {
01691   Array<octave_idx_type> retval (A.dims ());
01692   octave_idx_type n = A.numel ();
01693 
01694   for (octave_idx_type i = 0; i < n; i++)
01695     retval.xelem (i) = octave_int<octave_idx_type> (A.xelem (i));
01696 
01697   return retval;
01698 }
01699 
01700 Array<octave_idx_type>
01701 octave_value::octave_idx_type_vector_value (bool require_int,
01702                                             bool force_string_conv,
01703                                             bool force_vector_conversion) const
01704 {
01705   Array<octave_idx_type> retval;
01706 
01707   if (is_integer_type ())
01708     {
01709       if (is_int32_type ())
01710         retval = convert_to_octave_idx_type_array (int32_array_value ());
01711       else if (is_int64_type ())
01712         retval = convert_to_octave_idx_type_array (int64_array_value ());
01713       else if (is_int16_type ())
01714         retval = convert_to_octave_idx_type_array (int16_array_value ());
01715       else if (is_int8_type ())
01716         retval = convert_to_octave_idx_type_array (int8_array_value ());
01717       else if (is_uint32_type ())
01718         retval = convert_to_octave_idx_type_array (uint32_array_value ());
01719       else if (is_uint64_type ())
01720         retval = convert_to_octave_idx_type_array (uint64_array_value ());
01721       else if (is_uint16_type ())
01722         retval = convert_to_octave_idx_type_array (uint16_array_value ());
01723       else if (is_uint8_type ())
01724         retval = convert_to_octave_idx_type_array (uint8_array_value ());
01725       else
01726         retval = array_value (force_string_conv);
01727     }
01728   else
01729     {
01730       const NDArray a = array_value (force_string_conv);
01731       if (! error_state)
01732         {
01733           if (require_int)
01734             {
01735               retval.resize (a.dims ());
01736               for (octave_idx_type i = 0; i < a.numel (); i++)
01737                 {
01738                   double ai = a.elem (i);
01739                   octave_idx_type v = static_cast<octave_idx_type> (ai);
01740                   if (ai == v)
01741                     retval.xelem (i) = v;
01742                   else
01743                     {
01744                       error_with_cfn ("conversion to integer value failed");
01745                       break;
01746                     }
01747                 }
01748             }
01749           else
01750             retval = Array<octave_idx_type> (a);
01751         }
01752     }
01753 
01754 
01755   if (error_state)
01756     return retval;
01757   else
01758     return retval.reshape (make_vector_dims (retval.dims (),
01759                                              force_vector_conversion,
01760                                              type_name (), "integer vector"));
01761 }
01762 
01763 Array<Complex>
01764 octave_value::complex_vector_value (bool force_string_conv,
01765                                     bool force_vector_conversion) const
01766 {
01767   Array<Complex> retval = complex_array_value (force_string_conv);
01768 
01769   if (error_state)
01770     return retval;
01771   else
01772     return retval.reshape (make_vector_dims (retval.dims (),
01773                                              force_vector_conversion,
01774                                              type_name (), "complex vector"));
01775 }
01776 
01777 FloatColumnVector
01778 octave_value::float_column_vector_value (bool force_string_conv,
01779                                          bool frc_vec_conv) const
01780 {
01781   return FloatColumnVector (float_vector_value (force_string_conv,
01782                                                 frc_vec_conv));
01783 }
01784 
01785 FloatComplexColumnVector
01786 octave_value::float_complex_column_vector_value (bool force_string_conv,
01787                                                  bool frc_vec_conv) const
01788 {
01789   return FloatComplexColumnVector (float_complex_vector_value (force_string_conv,
01790                                                                frc_vec_conv));
01791 }
01792 
01793 FloatRowVector
01794 octave_value::float_row_vector_value (bool force_string_conv,
01795                                       bool frc_vec_conv) const
01796 {
01797   return FloatRowVector (float_vector_value (force_string_conv,
01798                                              frc_vec_conv));
01799 }
01800 
01801 FloatComplexRowVector
01802 octave_value::float_complex_row_vector_value (bool force_string_conv,
01803                                               bool frc_vec_conv) const
01804 {
01805   return FloatComplexRowVector (float_complex_vector_value (force_string_conv,
01806                                                            frc_vec_conv));
01807 }
01808 
01809 Array<float>
01810 octave_value::float_vector_value (bool force_string_conv,
01811                                   bool force_vector_conversion) const
01812 {
01813   Array<float> retval = float_array_value (force_string_conv);
01814 
01815   if (error_state)
01816     return retval;
01817   else
01818     return retval.reshape (make_vector_dims (retval.dims (),
01819                                              force_vector_conversion,
01820                                              type_name (), "real vector"));
01821 }
01822 
01823 Array<FloatComplex>
01824 octave_value::float_complex_vector_value (bool force_string_conv,
01825                                           bool force_vector_conversion) const
01826 {
01827   Array<FloatComplex> retval = float_complex_array_value (force_string_conv);
01828 
01829   if (error_state)
01830     return retval;
01831   else
01832     return retval.reshape (make_vector_dims (retval.dims (),
01833                                              force_vector_conversion,
01834                                              type_name (), "complex vector"));
01835 }
01836 
01837 octave_value
01838 octave_value::storable_value (void) const
01839 {
01840   octave_value retval = *this;
01841   if (is_null_value ())
01842     retval = octave_value (rep->empty_clone ());
01843   else
01844     retval.maybe_economize ();
01845 
01846   return retval;
01847 }
01848 
01849 void
01850 octave_value::make_storable_value (void)
01851 {
01852   if (is_null_value ())
01853     {
01854       octave_base_value *rc = rep->empty_clone ();
01855       if (--rep->count == 0)
01856         delete rep;
01857       rep = rc;
01858     }
01859   else
01860     maybe_economize ();
01861 }
01862 
01863 int
01864 octave_value::write (octave_stream& os, int block_size,
01865                      oct_data_conv::data_type output_type, int skip,
01866                      oct_mach_info::float_format flt_fmt) const
01867 {
01868   return rep->write (os, block_size, output_type, skip, flt_fmt);
01869 }
01870 
01871 static void
01872 gripe_binary_op (const std::string& on, const std::string& tn1,
01873                  const std::string& tn2)
01874 {
01875   error ("binary operator '%s' not implemented for '%s' by '%s' operations",
01876          on.c_str (), tn1.c_str (), tn2.c_str ());
01877 }
01878 
01879 static void
01880 gripe_binary_op_conv (const std::string& on)
01881 {
01882   error ("type conversion failed for binary operator '%s'", on.c_str ());
01883 }
01884 
01885 octave_value
01886 do_binary_op (octave_value::binary_op op,
01887               const octave_value& v1, const octave_value& v2)
01888 {
01889   octave_value retval;
01890 
01891   int t1 = v1.type_id ();
01892   int t2 = v2.type_id ();
01893 
01894   if (t1 == octave_class::static_type_id ()
01895       || t2 == octave_class::static_type_id ())
01896     {
01897       octave_value_typeinfo::binary_class_op_fcn f
01898         = octave_value_typeinfo::lookup_binary_class_op (op);
01899 
01900       if (f)
01901         {
01902           try
01903             {
01904               retval = f (v1, v2);
01905             }
01906           catch (octave_execution_exception)
01907             {
01908               gripe_library_execution_error ();
01909             }
01910         }
01911       else
01912         gripe_binary_op (octave_value::binary_op_as_string (op),
01913                          v1.class_name (), v2.class_name ());
01914     }
01915   else
01916     {
01917       // FIXME -- we need to handle overloading operators for built-in
01918       // classes (double, char, int8, etc.)
01919 
01920       octave_value_typeinfo::binary_op_fcn f
01921         = octave_value_typeinfo::lookup_binary_op (op, t1, t2);
01922 
01923       if (f)
01924         {
01925           try
01926             {
01927               retval = f (*v1.rep, *v2.rep);
01928             }
01929           catch (octave_execution_exception)
01930             {
01931               gripe_library_execution_error ();
01932             }
01933         }
01934       else
01935         {
01936           octave_value tv1;
01937           octave_base_value::type_conv_info cf1 = v1.numeric_conversion_function ();
01938 
01939           octave_value tv2;
01940           octave_base_value::type_conv_info cf2 = v2.numeric_conversion_function ();
01941 
01942           // Try biased (one-sided) conversions first.
01943           if (cf2.type_id () >= 0 &&
01944               octave_value_typeinfo::lookup_binary_op (op, t1, cf2.type_id ()))
01945             cf1 = 0;
01946           else if (cf1.type_id () >= 0 &&
01947                    octave_value_typeinfo::lookup_binary_op (op, cf1.type_id (), t2))
01948             cf2 = 0;
01949 
01950           if (cf1)
01951             {
01952               octave_base_value *tmp = cf1 (*v1.rep);
01953 
01954               if (tmp)
01955                 {
01956                   tv1 = octave_value (tmp);
01957                   t1 = tv1.type_id ();
01958                 }
01959               else
01960                 {
01961                   gripe_binary_op_conv (octave_value::binary_op_as_string (op));
01962                   return retval;
01963                 }
01964             }
01965           else
01966             tv1 = v1;
01967 
01968           if (cf2)
01969             {
01970               octave_base_value *tmp = cf2 (*v2.rep);
01971 
01972               if (tmp)
01973                 {
01974                   tv2 = octave_value (tmp);
01975                   t2 = tv2.type_id ();
01976                 }
01977               else
01978                 {
01979                   gripe_binary_op_conv (octave_value::binary_op_as_string (op));
01980                   return retval;
01981                 }
01982             }
01983           else
01984             tv2 = v2;
01985 
01986           if (cf1 || cf2)
01987             {
01988               retval = do_binary_op (op, tv1, tv2);
01989             }
01990           else
01991             {
01992               //demote double -> single and try again
01993               cf1 = tv1.numeric_demotion_function ();
01994 
01995               cf2 = tv2.numeric_demotion_function ();
01996 
01997               // Try biased (one-sided) conversions first.
01998               if (cf2.type_id () >= 0
01999                   && octave_value_typeinfo::lookup_binary_op (op, t1, cf2.type_id ()))
02000                 cf1 = 0;
02001               else if (cf1.type_id () >= 0
02002                        && octave_value_typeinfo::lookup_binary_op (op, cf1.type_id (), t2))
02003                 cf2 = 0;
02004 
02005               if (cf1)
02006                 {
02007                   octave_base_value *tmp = cf1 (*tv1.rep);
02008 
02009                   if (tmp)
02010                     {
02011                       tv1 = octave_value (tmp);
02012                       t1 = tv1.type_id ();
02013                     }
02014                   else
02015                     {
02016                       gripe_binary_op_conv (octave_value::binary_op_as_string (op));
02017                       return retval;
02018                     }
02019                 }
02020 
02021               if (cf2)
02022                 {
02023                   octave_base_value *tmp = cf2 (*tv2.rep);
02024 
02025                   if (tmp)
02026                     {
02027                       tv2 = octave_value (tmp);
02028                       t2 = tv2.type_id ();
02029                     }
02030                   else
02031                     {
02032                       gripe_binary_op_conv (octave_value::binary_op_as_string (op));
02033                       return retval;
02034                     }
02035                 }
02036 
02037               if (cf1 || cf2)
02038                 {
02039                   f = octave_value_typeinfo::lookup_binary_op (op, t1, t2);
02040 
02041                   if (f)
02042                     {
02043                       try
02044                         {
02045                           retval = f (*tv1.rep, *tv2.rep);
02046                         }
02047                       catch (octave_execution_exception)
02048                         {
02049                           gripe_library_execution_error ();
02050                         }
02051                     }
02052                   else
02053                     gripe_binary_op (octave_value::binary_op_as_string (op),
02054                                      v1.type_name (), v2.type_name ());
02055                 }
02056               else
02057                 gripe_binary_op (octave_value::binary_op_as_string (op),
02058                                  v1.type_name (), v2.type_name ());
02059             }
02060         }
02061     }
02062 
02063   return retval;
02064 }
02065 
02066 static octave_value
02067 decompose_binary_op (octave_value::compound_binary_op op,
02068                      const octave_value& v1, const octave_value& v2)
02069 {
02070   octave_value retval;
02071 
02072   switch (op)
02073     {
02074     case octave_value::op_trans_mul:
02075       retval = do_binary_op (octave_value::op_mul,
02076                              do_unary_op (octave_value::op_transpose, v1),
02077                              v2);
02078       break;
02079     case octave_value::op_mul_trans:
02080       retval = do_binary_op (octave_value::op_mul,
02081                              v1,
02082                              do_unary_op (octave_value::op_transpose, v2));
02083       break;
02084     case octave_value::op_herm_mul:
02085       retval = do_binary_op (octave_value::op_mul,
02086                              do_unary_op (octave_value::op_hermitian, v1),
02087                              v2);
02088       break;
02089     case octave_value::op_mul_herm:
02090       retval = do_binary_op (octave_value::op_mul,
02091                              v1,
02092                              do_unary_op (octave_value::op_hermitian, v2));
02093       break;
02094     case octave_value::op_trans_ldiv:
02095       retval = do_binary_op (octave_value::op_ldiv,
02096                              do_unary_op (octave_value::op_transpose, v1),
02097                              v2);
02098       break;
02099     case octave_value::op_herm_ldiv:
02100       retval = do_binary_op (octave_value::op_ldiv,
02101                              do_unary_op (octave_value::op_hermitian, v1),
02102                              v2);
02103       break;
02104     case octave_value::op_el_not_and:
02105       retval = do_binary_op (octave_value::op_el_and,
02106                              do_unary_op (octave_value::op_not, v1),
02107                              v2);
02108       break;
02109     case octave_value::op_el_not_or:
02110       retval = do_binary_op (octave_value::op_el_or,
02111                              do_unary_op (octave_value::op_not, v1),
02112                              v2);
02113       break;
02114     case octave_value::op_el_and_not:
02115       retval = do_binary_op (octave_value::op_el_and,
02116                              v1,
02117                              do_unary_op (octave_value::op_not, v2));
02118       break;
02119     case octave_value::op_el_or_not:
02120       retval = do_binary_op (octave_value::op_el_or,
02121                              v1,
02122                              do_unary_op (octave_value::op_not, v2));
02123       break;
02124     default:
02125       error ("invalid compound operator");
02126       break;
02127     }
02128 
02129   return retval;
02130 }
02131 
02132 octave_value
02133 do_binary_op (octave_value::compound_binary_op op,
02134               const octave_value& v1, const octave_value& v2)
02135 {
02136   octave_value retval;
02137 
02138   int t1 = v1.type_id ();
02139   int t2 = v2.type_id ();
02140 
02141   if (t1 == octave_class::static_type_id ()
02142       || t2 == octave_class::static_type_id ())
02143     {
02144       octave_value_typeinfo::binary_class_op_fcn f
02145         = octave_value_typeinfo::lookup_binary_class_op (op);
02146 
02147       if (f)
02148         {
02149           try
02150             {
02151               retval = f (v1, v2);
02152             }
02153           catch (octave_execution_exception)
02154             {
02155               gripe_library_execution_error ();
02156             }
02157         }
02158       else
02159         retval = decompose_binary_op (op, v1, v2);
02160     }
02161   else
02162     {
02163       octave_value_typeinfo::binary_op_fcn f
02164         = octave_value_typeinfo::lookup_binary_op (op, t1, t2);
02165 
02166       if (f)
02167         {
02168           try
02169             {
02170               retval = f (*v1.rep, *v2.rep);
02171             }
02172           catch (octave_execution_exception)
02173             {
02174               gripe_library_execution_error ();
02175             }
02176         }
02177       else
02178         retval = decompose_binary_op (op, v1, v2);
02179     }
02180 
02181   return retval;
02182 }
02183 
02184 static void
02185 gripe_cat_op (const std::string& tn1, const std::string& tn2)
02186 {
02187   error ("concatenation operator not implemented for '%s' by '%s' operations",
02188          tn1.c_str (), tn2.c_str ());
02189 }
02190 
02191 static void
02192 gripe_cat_op_conv (void)
02193 {
02194   error ("type conversion failed for concatenation operator");
02195 }
02196 
02197 octave_value
02198 do_cat_op (const octave_value& v1, const octave_value& v2,
02199            const Array<octave_idx_type>& ra_idx)
02200 {
02201   octave_value retval;
02202 
02203   // Can't rapid return for concatenation with an empty object here as
02204   // something like cat(1,[],single([]) must return the correct type.
02205 
02206   int t1 = v1.type_id ();
02207   int t2 = v2.type_id ();
02208 
02209   octave_value_typeinfo::cat_op_fcn f
02210     = octave_value_typeinfo::lookup_cat_op (t1, t2);
02211 
02212   if (f)
02213     {
02214       try
02215         {
02216           retval = f (*v1.rep, *v2.rep, ra_idx);
02217         }
02218       catch (octave_execution_exception)
02219         {
02220           gripe_library_execution_error ();
02221         }
02222     }
02223   else
02224     {
02225       octave_value tv1;
02226       octave_base_value::type_conv_info cf1 = v1.numeric_conversion_function ();
02227 
02228       octave_value tv2;
02229       octave_base_value::type_conv_info cf2 = v2.numeric_conversion_function ();
02230 
02231       // Try biased (one-sided) conversions first.
02232       if (cf2.type_id () >= 0
02233           && octave_value_typeinfo::lookup_cat_op (t1, cf2.type_id ()))
02234         cf1 = 0;
02235       else if (cf1.type_id () >= 0
02236                && octave_value_typeinfo::lookup_cat_op (cf1.type_id (), t2))
02237         cf2 = 0;
02238 
02239       if (cf1)
02240         {
02241           octave_base_value *tmp = cf1 (*v1.rep);
02242 
02243           if (tmp)
02244             {
02245               tv1 = octave_value (tmp);
02246               t1 = tv1.type_id ();
02247             }
02248           else
02249             {
02250               gripe_cat_op_conv ();
02251               return retval;
02252             }
02253         }
02254       else
02255         tv1 = v1;
02256 
02257       if (cf2)
02258         {
02259           octave_base_value *tmp = cf2 (*v2.rep);
02260 
02261           if (tmp)
02262             {
02263               tv2 = octave_value (tmp);
02264               t2 = tv2.type_id ();
02265             }
02266           else
02267             {
02268               gripe_cat_op_conv ();
02269               return retval;
02270             }
02271         }
02272       else
02273         tv2 = v2;
02274 
02275       if (cf1 || cf2)
02276         {
02277           retval = do_cat_op (tv1, tv2, ra_idx);
02278         }
02279       else
02280         gripe_cat_op (v1.type_name (), v2.type_name ());
02281     }
02282 
02283   return retval;
02284 }
02285 
02286 void
02287 octave_value::print_info (std::ostream& os, const std::string& prefix) const
02288 {
02289   os << prefix << "type_name: " << type_name () << "\n"
02290      << prefix << "count:     " << get_count () << "\n"
02291      << prefix << "rep info:  ";
02292 
02293   rep->print_info (os, prefix + " ");
02294 }
02295 
02296 static void
02297 gripe_unary_op (const std::string& on, const std::string& tn)
02298 {
02299   error ("unary operator '%s' not implemented for '%s' operands",
02300          on.c_str (), tn.c_str ());
02301 }
02302 
02303 static void
02304 gripe_unary_op_conv (const std::string& on)
02305 {
02306   error ("type conversion failed for unary operator '%s'", on.c_str ());
02307 }
02308 
02309 octave_value
02310 do_unary_op (octave_value::unary_op op, const octave_value& v)
02311 {
02312   octave_value retval;
02313 
02314   int t = v.type_id ();
02315 
02316   if (t == octave_class::static_type_id ())
02317     {
02318       octave_value_typeinfo::unary_class_op_fcn f
02319         = octave_value_typeinfo::lookup_unary_class_op (op);
02320 
02321       if (f)
02322         {
02323           try
02324             {
02325               retval = f (v);
02326             }
02327           catch (octave_execution_exception)
02328             {
02329               gripe_library_execution_error ();
02330             }
02331         }
02332       else
02333         gripe_unary_op (octave_value::unary_op_as_string (op),
02334                         v.class_name ());
02335     }
02336   else
02337     {
02338       // FIXME -- we need to handle overloading operators for built-in
02339       // classes (double, char, int8, etc.)
02340 
02341       octave_value_typeinfo::unary_op_fcn f
02342         = octave_value_typeinfo::lookup_unary_op (op, t);
02343 
02344       if (f)
02345         {
02346           try
02347             {
02348               retval = f (*v.rep);
02349             }
02350           catch (octave_execution_exception)
02351             {
02352               gripe_library_execution_error ();
02353             }
02354         }
02355       else
02356         {
02357           octave_value tv;
02358           octave_base_value::type_conv_fcn cf
02359             = v.numeric_conversion_function ();
02360 
02361           if (cf)
02362             {
02363               octave_base_value *tmp = cf (*v.rep);
02364 
02365               if (tmp)
02366                 {
02367                   tv = octave_value (tmp);
02368                   retval = do_unary_op (op, tv);
02369                 }
02370               else
02371                 gripe_unary_op_conv (octave_value::unary_op_as_string (op));
02372             }
02373           else
02374             gripe_unary_op (octave_value::unary_op_as_string (op),
02375                             v.type_name ());
02376         }
02377     }
02378 
02379   return retval;
02380 }
02381 
02382 static void
02383 gripe_unary_op_conversion_failed (const std::string& op,
02384                                   const std::string& tn)
02385 {
02386   error ("operator %s: type conversion for '%s' failed",
02387          op.c_str (), tn.c_str ());
02388 }
02389 
02390 octave_value&
02391 octave_value::do_non_const_unary_op (unary_op op)
02392 {
02393   if (op == op_incr || op == op_decr)
02394     {
02395       // We want the gripe just here, because in the other branch this should
02396       // not happen, and if it did anyway (internal error), the message would
02397       // be confusing.
02398       if (is_undefined ())
02399         {
02400           std::string op_str = unary_op_as_string (op);
02401           error ("in x%s or %sx, x must be defined first",
02402                  op_str.c_str (), op_str.c_str ());
02403           return *this;
02404         }
02405 
02406       // Genuine.
02407       int t = type_id ();
02408 
02409       octave_value_typeinfo::non_const_unary_op_fcn f
02410         = octave_value_typeinfo::lookup_non_const_unary_op (op, t);
02411 
02412       if (f)
02413         {
02414           make_unique ();
02415 
02416           try
02417             {
02418               f (*rep);
02419             }
02420           catch (octave_execution_exception)
02421             {
02422               gripe_library_execution_error ();
02423             }
02424         }
02425       else
02426         {
02427           octave_base_value::type_conv_fcn cf = numeric_conversion_function ();
02428 
02429           if (cf)
02430             {
02431               octave_base_value *tmp = cf (*rep);
02432 
02433               if (tmp)
02434                 {
02435                   octave_base_value *old_rep = rep;
02436                   rep = tmp;
02437 
02438                   t = type_id ();
02439 
02440                   f = octave_value_typeinfo::lookup_non_const_unary_op (op, t);
02441 
02442                   if (f)
02443                     {
02444                       try
02445                         {
02446                           f (*rep);
02447                         }
02448                       catch (octave_execution_exception)
02449                         {
02450                           gripe_library_execution_error ();
02451                         }
02452 
02453                       if (old_rep && --old_rep->count == 0)
02454                         delete old_rep;
02455                     }
02456                   else
02457                     {
02458                       if (old_rep)
02459                         {
02460                           if (--rep->count == 0)
02461                             delete rep;
02462 
02463                           rep = old_rep;
02464                         }
02465 
02466                       gripe_unary_op (octave_value::unary_op_as_string (op),
02467                                       type_name ());
02468                     }
02469                 }
02470               else
02471                 gripe_unary_op_conversion_failed
02472                   (octave_value::unary_op_as_string (op), type_name ());
02473             }
02474           else
02475             gripe_unary_op (octave_value::unary_op_as_string (op), type_name ());
02476         }
02477     }
02478   else
02479     {
02480       // Non-genuine.
02481       int t = type_id ();
02482 
02483       octave_value_typeinfo::non_const_unary_op_fcn f = 0;
02484 
02485       // Only attempt to operate in-place if this variable is unshared.
02486       if (rep->count == 1)
02487         f = octave_value_typeinfo::lookup_non_const_unary_op (op, t);
02488 
02489       if (f)
02490         {
02491           try
02492             {
02493               f (*rep);
02494             }
02495           catch (octave_execution_exception)
02496             {
02497               gripe_library_execution_error ();
02498             }
02499         }
02500       else
02501         *this = do_unary_op (op, *this);
02502     }
02503 
02504   return *this;
02505 }
02506 
02507 octave_value&
02508 octave_value::do_non_const_unary_op (unary_op op, const std::string& type,
02509                                      const std::list<octave_value_list>& idx)
02510 {
02511   if (idx.empty ())
02512     do_non_const_unary_op (op);
02513   else
02514     {
02515       // FIXME -- only do the following stuff if we can't find a
02516       // specific function to call to handle the op= operation for the
02517       // types we have.
02518 
02519       assign_op assop = unary_op_to_assign_op (op);
02520 
02521       assign (assop, type, idx, 1.0);
02522     }
02523 
02524   return *this;
02525 }
02526 
02527 octave_value::assign_op
02528 octave_value::unary_op_to_assign_op (unary_op op)
02529 {
02530   assign_op binop = unknown_assign_op;
02531 
02532   switch (op)
02533     {
02534     case op_incr:
02535       binop = op_add_eq;
02536       break;
02537 
02538     case op_decr:
02539       binop = op_sub_eq;
02540       break;
02541 
02542     default:
02543       {
02544         std::string on = unary_op_as_string (op);
02545         error ("operator %s: no assign operator found", on.c_str ());
02546       }
02547     }
02548 
02549   return binop;
02550 }
02551 
02552 octave_value::binary_op
02553 octave_value::op_eq_to_binary_op (assign_op op)
02554 {
02555   binary_op binop = unknown_binary_op;
02556 
02557   switch (op)
02558     {
02559     case op_add_eq:
02560       binop = op_add;
02561       break;
02562 
02563     case op_sub_eq:
02564       binop = op_sub;
02565       break;
02566 
02567     case op_mul_eq:
02568       binop = op_mul;
02569       break;
02570 
02571     case op_div_eq:
02572       binop = op_div;
02573       break;
02574 
02575     case op_ldiv_eq:
02576       binop = op_ldiv;
02577       break;
02578 
02579     case op_pow_eq:
02580       binop = op_pow;
02581       break;
02582 
02583     case op_lshift_eq:
02584       binop = op_lshift;
02585       break;
02586 
02587     case op_rshift_eq:
02588       binop = op_rshift;
02589       break;
02590 
02591     case op_el_mul_eq:
02592       binop = op_el_mul;
02593       break;
02594 
02595     case op_el_div_eq:
02596       binop = op_el_div;
02597       break;
02598 
02599     case op_el_ldiv_eq:
02600       binop = op_el_ldiv;
02601       break;
02602 
02603     case op_el_pow_eq:
02604       binop = op_el_pow;
02605       break;
02606 
02607     case op_el_and_eq:
02608       binop = op_el_and;
02609       break;
02610 
02611     case op_el_or_eq:
02612       binop = op_el_or;
02613       break;
02614 
02615     default:
02616       {
02617         std::string on = assign_op_as_string (op);
02618         error ("operator %s: no binary operator found", on.c_str ());
02619       }
02620     }
02621 
02622   return binop;
02623 }
02624 
02625 octave_value
02626 octave_value::empty_conv (const std::string& type, const octave_value& rhs)
02627 {
02628   octave_value retval;
02629 
02630   if (type.length () > 0)
02631     {
02632       switch (type[0])
02633         {
02634         case '(':
02635           {
02636             if (type.length () > 1 && type[1] == '.')
02637               retval = octave_map ();
02638             else
02639               retval = octave_value (rhs.empty_clone ());
02640           }
02641           break;
02642 
02643         case '{':
02644           retval = Cell ();
02645           break;
02646 
02647         case '.':
02648           retval = octave_scalar_map ();
02649           break;
02650 
02651         default:
02652           panic_impossible ();
02653         }
02654     }
02655   else
02656     retval = octave_value (rhs.empty_clone ());
02657 
02658   return retval;
02659 }
02660 
02661 void
02662 install_types (void)
02663 {
02664   octave_base_value::register_type ();
02665   octave_cell::register_type ();
02666   octave_scalar::register_type ();
02667   octave_complex::register_type ();
02668   octave_matrix::register_type ();
02669   octave_diag_matrix::register_type ();
02670   octave_complex_matrix::register_type ();
02671   octave_complex_diag_matrix::register_type ();
02672   octave_range::register_type ();
02673   octave_bool::register_type ();
02674   octave_bool_matrix::register_type ();
02675   octave_char_matrix_str::register_type ();
02676   octave_char_matrix_sq_str::register_type ();
02677   octave_int8_scalar::register_type ();
02678   octave_int16_scalar::register_type ();
02679   octave_int32_scalar::register_type ();
02680   octave_int64_scalar::register_type ();
02681   octave_uint8_scalar::register_type ();
02682   octave_uint16_scalar::register_type ();
02683   octave_uint32_scalar::register_type ();
02684   octave_uint64_scalar::register_type ();
02685   octave_int8_matrix::register_type ();
02686   octave_int16_matrix::register_type ();
02687   octave_int32_matrix::register_type ();
02688   octave_int64_matrix::register_type ();
02689   octave_uint8_matrix::register_type ();
02690   octave_uint16_matrix::register_type ();
02691   octave_uint32_matrix::register_type ();
02692   octave_uint64_matrix::register_type ();
02693   octave_sparse_bool_matrix::register_type ();
02694   octave_sparse_matrix::register_type ();
02695   octave_sparse_complex_matrix::register_type ();
02696   octave_struct::register_type ();
02697   octave_scalar_struct::register_type ();
02698   octave_class::register_type ();
02699   octave_cs_list::register_type ();
02700   octave_magic_colon::register_type ();
02701   octave_builtin::register_type ();
02702   octave_user_function::register_type ();
02703   octave_dld_function::register_type ();
02704   octave_fcn_handle::register_type ();
02705   octave_fcn_inline::register_type ();
02706   octave_float_scalar::register_type ();
02707   octave_float_complex::register_type ();
02708   octave_float_matrix::register_type ();
02709   octave_float_diag_matrix::register_type ();
02710   octave_float_complex_matrix::register_type ();
02711   octave_float_complex_diag_matrix::register_type ();
02712   octave_perm_matrix::register_type ();
02713   octave_null_matrix::register_type ();
02714   octave_null_str::register_type ();
02715   octave_null_sq_str::register_type ();
02716   octave_lazy_index::register_type ();
02717   octave_oncleanup::register_type ();
02718 }
02719 
02720 DEFUN (sizeof, args, ,
02721   "-*- texinfo -*-\n\
02722 @deftypefn {Built-in Function} {} sizeof (@var{val})\n\
02723 Return the size of @var{val} in bytes.\n\
02724 @seealso{whos}\n\
02725 @end deftypefn")
02726 {
02727   octave_value retval;
02728 
02729   if (args.length () == 1)
02730     retval = args(0).byte_size ();
02731   else
02732     print_usage ();
02733 
02734   return retval;
02735 }
02736 
02737 /*
02738 %!assert (sizeof (uint64 (ones (3))), 72)
02739 %!assert (sizeof (double (zeros (2,4))), 64)
02740 %!assert (sizeof ({"foo", "bar", "baaz"}), 10)
02741 */
02742 
02743 static void
02744 decode_subscripts (const char* name, const octave_value& arg,
02745                    std::string& type_string,
02746                    std::list<octave_value_list>& idx)
02747 {
02748   const octave_map m = arg.map_value ();
02749 
02750   if (! error_state
02751       && m.nfields () == 2 && m.contains ("type") && m.contains ("subs"))
02752     {
02753       octave_idx_type nel = m.numel ();
02754 
02755       type_string = std::string (nel, '\0');
02756       idx = std::list<octave_value_list> ();
02757 
02758       if (nel == 0)
02759         return;
02760 
02761       const Cell type = m.contents ("type");
02762       const Cell subs = m.contents ("subs");
02763 
02764       for (int k = 0; k < nel; k++)
02765         {
02766           std::string item = type(k).string_value ();
02767 
02768           if (! error_state)
02769             {
02770               if (item == "{}")
02771                 type_string[k] = '{';
02772               else if (item == "()")
02773                 type_string[k] = '(';
02774               else if (item == ".")
02775                 type_string[k] = '.';
02776               else
02777                 {
02778                   error("%s: invalid indexing type '%s'", name, item.c_str ());
02779                   return;
02780                 }
02781             }
02782           else
02783             {
02784               error ("%s: expecting type(%d) to be a character string",
02785                      name, k+1);
02786               return;
02787             }
02788 
02789           octave_value_list idx_item;
02790 
02791           if (subs(k).is_string ())
02792             idx_item(0) = subs(k);
02793           else if (subs(k).is_cell ())
02794             {
02795               Cell subs_cell = subs(k).cell_value ();
02796 
02797               for (int n = 0; n < subs_cell.length (); n++)
02798                 {
02799                   if (subs_cell(n).is_string ()
02800                       && subs_cell(n).string_value () == ":")
02801                     idx_item(n) = octave_value(octave_value::magic_colon_t);
02802                   else
02803                     idx_item(n) = subs_cell(n);
02804                 }
02805             }
02806           else
02807             {
02808               error ("%s: expecting subs(%d) to be a character string or cell array",
02809                      name, k+1);
02810               return;
02811             }
02812 
02813           idx.push_back (idx_item);
02814         }
02815     }
02816   else
02817     error ("%s: second argument must be a structure with fields 'type' and 'subs'", name);
02818 }
02819 
02820 DEFUN (subsref, args, nargout,
02821   "-*- texinfo -*-\n\
02822 @deftypefn {Built-in Function} {} subsref (@var{val}, @var{idx})\n\
02823 Perform the subscripted element selection operation according to\n\
02824 the subscript specified by @var{idx}.\n\
02825 \n\
02826 The subscript @var{idx} is expected to be a structure array with\n\
02827 fields @samp{type} and @samp{subs}.  Valid values for @samp{type}\n\
02828 are @samp{\"()\"}, @samp{\"@{@}\"}, and @samp{\".\"}.\n\
02829 The @samp{subs} field may be either @samp{\":\"} or a cell array\n\
02830 of index values.\n\
02831 \n\
02832 The following example shows how to extract the two first columns of\n\
02833 a matrix\n\
02834 \n\
02835 @example\n\
02836 @group\n\
02837 val = magic(3)\n\
02838      @result{} val = [ 8   1   6\n\
02839                 3   5   7\n\
02840                 4   9   2 ]\n\
02841 idx.type = \"()\";\n\
02842 idx.subs = @{\":\", 1:2@};\n\
02843 subsref(val, idx)\n\
02844      @result{} [ 8   1\n\
02845           3   5\n\
02846           4   9 ]\n\
02847 @end group\n\
02848 @end example\n\
02849 \n\
02850 @noindent\n\
02851 Note that this is the same as writing @code{val(:,1:2)}.\n\
02852 \n\
02853 If @var{idx} is an empty structure array with fields @samp{type}\n\
02854 and @samp{subs}, return @var{val}.\n\
02855 @seealso{subsasgn, substruct}\n\
02856 @end deftypefn")
02857 {
02858   octave_value_list retval;
02859 
02860   if (args.length () == 2)
02861     {
02862       std::string type;
02863       std::list<octave_value_list> idx;
02864 
02865       decode_subscripts ("subsref", args(1), type, idx);
02866 
02867       if (! error_state)
02868         {
02869           octave_value arg0 = args(0);
02870 
02871           if (type.empty ())
02872             retval = arg0;
02873           else
02874             retval = arg0.subsref (type, idx, nargout);
02875         }
02876     }
02877   else
02878     print_usage ();
02879 
02880   return retval;
02881 }
02882 
02883 DEFUN (subsasgn, args, ,
02884   "-*- texinfo -*-\n\
02885 @deftypefn {Built-in Function} {} subsasgn (@var{val}, @var{idx}, @var{rhs})\n\
02886 Perform the subscripted assignment operation according to\n\
02887 the subscript specified by @var{idx}.\n\
02888 \n\
02889 The subscript @var{idx} is expected to be a structure array with\n\
02890 fields @samp{type} and @samp{subs}.  Valid values for @samp{type}\n\
02891 are @samp{\"()\"}, @samp{\"@{@}\"}, and @samp{\".\"}.\n\
02892 The @samp{subs} field may be either @samp{\":\"} or a cell array\n\
02893 of index values.\n\
02894 \n\
02895 The following example shows how to set the two first columns of a\n\
02896 3-by-3 matrix to zero.\n\
02897 \n\
02898 @example\n\
02899 @group\n\
02900 val = magic(3);\n\
02901 idx.type = \"()\";\n\
02902 idx.subs = @{\":\", 1:2@};\n\
02903 subsasgn (val, idx, 0)\n\
02904      @result{} [ 0   0   6\n\
02905           0   0   7\n\
02906           0   0   2 ]\n\
02907 @end group\n\
02908 @end example\n\
02909 \n\
02910 Note that this is the same as writing @code{val(:,1:2) = 0}.\n\
02911 \n\
02912 If @var{idx} is an empty structure array with fields @samp{type}\n\
02913 and @samp{subs}, return @var{rhs}.\n\
02914 @seealso{subsref, substruct}\n\
02915 @end deftypefn")
02916 {
02917   octave_value retval;
02918 
02919   if (args.length () == 3)
02920     {
02921       std::string type;
02922       std::list<octave_value_list> idx;
02923 
02924       decode_subscripts ("subsasgn", args(1), type, idx);
02925 
02926       if (! error_state)
02927         {
02928           if (type.empty ())
02929             {
02930               // Regularize a null matrix if stored into a variable.
02931 
02932               retval = args(2).storable_value ();
02933             }
02934           else
02935             {
02936               octave_value arg0 = args(0);
02937 
02938               arg0.make_unique ();
02939 
02940               if (! error_state)
02941                 retval= arg0.subsasgn (type, idx, args(2));
02942             }
02943         }
02944     }
02945   else
02946     print_usage ();
02947 
02948   return retval;
02949 }
02950 
02951 /*
02952 %!test
02953 %! a = reshape ([1:25], 5,5);
02954 %! idx1 = substruct ("()", {3, 3});
02955 %! idx2 = substruct ("()", {2:2:5, 2:2:5});
02956 %! idx3 = substruct ("()", {":", [1,5]});
02957 %! idx4 = struct ("type", {}, "subs", {});
02958 %! assert (subsref (a, idx1), 13);
02959 %! assert (subsref (a, idx2), [7 17; 9 19]);
02960 %! assert (subsref (a, idx3), [1:5; 21:25]');
02961 %! assert (subsref (a, idx4), a);
02962 %! a = subsasgn (a, idx1, 0);
02963 %! a = subsasgn (a, idx2, 0);
02964 %! a = subsasgn (a, idx3, 0);
02965 %!# a = subsasgn (a, idx4, 0);
02966 %! b = [0    6   11   16    0
02967 %!      0    0   12    0    0
02968 %!      0    8    0   18    0
02969 %!      0    0   14    0    0
02970 %!      0   10   15   20    0];
02971 %! assert (a,b);
02972 
02973 %!test
02974 %! c = num2cell (reshape ([1:25],5,5));
02975 %! idx1 = substruct  ("{}", {3, 3});
02976 %! idx2 = substruct  ("()", {2:2:5, 2:2:5});
02977 %! idx3 = substruct  ("()", {":", [1,5]});
02978 %! idx2p = substruct ("{}", {2:2:5, 2:2:5});
02979 %! idx3p = substruct ("{}", {":", [1,5]});
02980 %! idx4 = struct ("type", {}, "subs", {});
02981 %! assert ({ subsref(c, idx1) }, {13});
02982 %! assert ({ subsref(c, idx2p) }, {7 9 17 19});
02983 %! assert ({ subsref(c, idx3p) }, num2cell ([1:5, 21:25]));
02984 %! assert (subsref(c, idx4), c);
02985 %! c = subsasgn (c, idx1, 0);
02986 %! c = subsasgn (c, idx2, 0);
02987 %! c = subsasgn (c, idx3, 0);
02988 %!# c = subsasgn (c, idx4, 0);
02989 %! d = {0    6   11   16    0
02990 %!      0    0   12    0    0
02991 %!      0    8    0   18    0
02992 %!      0    0   14    0    0
02993 %!      0   10   15   20    0};
02994 %! assert (c, d);
02995 
02996 %!test
02997 %! s.a = "ohai";
02998 %! s.b = "dere";
02999 %! s.c = 42;
03000 %! idx1 = substruct (".", "a");
03001 %! idx2 = substruct (".", "b");
03002 %! idx3 = substruct (".", "c");
03003 %! idx4 = struct ("type", {}, "subs", {});
03004 %! assert (subsref (s, idx1), "ohai");
03005 %! assert (subsref (s, idx2), "dere");
03006 %! assert (subsref (s, idx3), 42);
03007 %! assert (subsref (s, idx4), s);
03008 %! s = subsasgn (s, idx1, "Hello");
03009 %! s = subsasgn (s, idx2, "There");
03010 %! s = subsasgn (s, idx3, 163);
03011 %!# s = subsasgn (s, idx4, 163);
03012 %! t.a = "Hello";
03013 %! t.b = "There";
03014 %! t.c = 163;
03015 %! assert (s, t);
03016 
03017 */
03018 
03019 DEFUN (is_sq_string, args, ,
03020   "-*- texinfo -*-\n\
03021 @deftypefn {Built-in Function} {} is_sq_string (@var{x})\n\
03022 Return true if @var{x} is a single-quoted character string.\n\
03023 @seealso{is_dq_string, ischar}\n\
03024 @end deftypefn")
03025 {
03026   octave_value retval;
03027 
03028   if (args.length () == 1)
03029     retval = args(0).is_sq_string ();
03030   else
03031     print_usage ();
03032 
03033   return retval;
03034 }
03035 
03036 /*
03037 %!assert (is_sq_string ('foo'), true);
03038 %!assert (is_sq_string ("foo"), false);
03039 %!assert (is_sq_string (1.0), false);
03040 %!assert (is_sq_string ({2.0}), false);
03041 %!error is_sq_string ()
03042 %!error is_sq_string ('foo', 2)
03043 */
03044 
03045 DEFUN (is_dq_string, args, ,
03046   "-*- texinfo -*-\n\
03047 @deftypefn {Built-in Function} {} is_dq_string (@var{x})\n\
03048 Return true if @var{x} is a double-quoted character string.\n\
03049 @seealso{is_sq_string, ischar}\n\
03050 @end deftypefn")
03051 {
03052   octave_value retval;
03053 
03054   if (args.length () == 1)
03055     retval = args(0).is_dq_string ();
03056   else
03057     print_usage ();
03058 
03059   return retval;
03060 }
03061 
03062 /*
03063 %!assert (is_dq_string ("foo"), true);
03064 %!assert (is_dq_string ('foo'), false);
03065 %!assert (is_dq_string (1.0), false);
03066 %!assert (is_dq_string ({2.0}), false);
03067 %!error is_dq_string ()
03068 %!error is_dq_string ("foo", 2)
03069 */
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines