diff src/octave-value/ov-base.cc @ 15057:46b19589b593

maint: Partition src/ directory with more code in subdirs. Create new octave-value dir for ov* code. Create new parse-tre dir for pt* code. Move OPERATORS and TEMPLATE-INST directories to lowercase names * octave-value/module.mk: Hook code in octave-value dir into build system. * octave-value/ov-base-diag.cc, octave-value/ov-base-diag.h, octave-value/ov-base-int.cc, octave-value/ov-base-int.h, octave-value/ov-base-mat.cc, octave-value/ov-base-mat.h, octave-value/ov-base-scalar.cc, octave-value/ov-base-scalar.h, octave-value/ov-base-sparse.cc, octave-value/ov-base-sparse.h, octave-value/ov-base.cc, octave-value/ov-base.h, octave-value/ov-bool-mat.cc, octave-value/ov-bool-mat.h, octave-value/ov-bool-sparse.cc, octave-value/ov-bool-sparse.h, octave-value/ov-bool.cc, octave-value/ov-bool.h, octave-value/ov-builtin.cc, octave-value/ov-builtin.h, octave-value/ov-cell.cc, octave-value/ov-cell.h, octave-value/ov-ch-mat.cc, octave-value/ov-ch-mat.h, octave-value/ov-class.cc, octave-value/ov-class.h, octave-value/ov-colon.cc, octave-value/ov-colon.h, octave-value/ov-complex.cc, octave-value/ov-complex.h, octave-value/ov-cs-list.cc, octave-value/ov-cs-list.h, octave-value/ov-cx-diag.cc, octave-value/ov-cx-diag.h, octave-value/ov-cx-mat.cc, octave-value/ov-cx-mat.h, octave-value/ov-cx-sparse.cc, octave-value/ov-cx-sparse.h, octave-value/ov-dld-fcn.cc, octave-value/ov-dld-fcn.h, octave-value/ov-fcn-handle.cc, octave-value/ov-fcn-handle.h, octave-value/ov-fcn-inline.cc, octave-value/ov-fcn-inline.h, octave-value/ov-fcn.cc, octave-value/ov-fcn.h, octave-value/ov-float.cc, octave-value/ov-float.h, octave-value/ov-flt-complex.cc, octave-value/ov-flt-complex.h, octave-value/ov-flt-cx-diag.cc, octave-value/ov-flt-cx-diag.h, octave-value/ov-flt-cx-mat.cc, octave-value/ov-flt-cx-mat.h, octave-value/ov-flt-re-diag.cc, octave-value/ov-flt-re-diag.h, octave-value/ov-flt-re-mat.cc, octave-value/ov-flt-re-mat.h, octave-value/ov-int-traits.h, octave-value/ov-int16.cc, octave-value/ov-int16.h, octave-value/ov-int32.cc, octave-value/ov-int32.h, octave-value/ov-int64.cc, octave-value/ov-int64.h, octave-value/ov-int8.cc, octave-value/ov-int8.h, octave-value/ov-intx.h, octave-value/ov-lazy-idx.cc, octave-value/ov-lazy-idx.h, octave-value/ov-mex-fcn.cc, octave-value/ov-mex-fcn.h, octave-value/ov-null-mat.cc, octave-value/ov-null-mat.h, octave-value/ov-oncleanup.cc, octave-value/ov-oncleanup.h, octave-value/ov-perm.cc, octave-value/ov-perm.h, octave-value/ov-range.cc, octave-value/ov-range.h, octave-value/ov-re-diag.cc, octave-value/ov-re-diag.h, octave-value/ov-re-mat.cc, octave-value/ov-re-mat.h, octave-value/ov-re-sparse.cc, octave-value/ov-re-sparse.h, octave-value/ov-scalar.cc, octave-value/ov-scalar.h, octave-value/ov-str-mat.cc, octave-value/ov-str-mat.h, octave-value/ov-struct.cc, octave-value/ov-struct.h, octave-value/ov-type-conv.h, octave-value/ov-typeinfo.cc, octave-value/ov-typeinfo.h, octave-value/ov-uint16.cc, octave-value/ov-uint16.h, octave-value/ov-uint32.cc, octave-value/ov-uint32.h, octave-value/ov-uint64.cc, octave-value/ov-uint64.h, octave-value/ov-uint8.cc, octave-value/ov-uint8.h, octave-value/ov-usr-fcn.cc, octave-value/ov-usr-fcn.h, octave-value/ov.cc, octave-value/ov.h: Moved from src/ dir to octave-value dir. * operators/module.mk, operators/op-b-b.cc, operators/op-b-bm.cc, operators/op-b-sbm.cc, operators/op-bm-b.cc, operators/op-bm-bm.cc, operators/op-bm-sbm.cc, operators/op-cdm-cdm.cc, operators/op-cdm-cm.cc, operators/op-cdm-cs.cc, operators/op-cdm-dm.cc, operators/op-cdm-m.cc, operators/op-cdm-s.cc, operators/op-cell.cc, operators/op-chm.cc, operators/op-class.cc, operators/op-cm-cdm.cc, operators/op-cm-cm.cc, operators/op-cm-cs.cc, operators/op-cm-dm.cc, operators/op-cm-m.cc, operators/op-cm-pm.cc, operators/op-cm-s.cc, operators/op-cm-scm.cc, operators/op-cm-sm.cc, operators/op-cs-cm.cc, operators/op-cs-cs.cc, operators/op-cs-m.cc, operators/op-cs-s.cc, operators/op-cs-scm.cc, operators/op-cs-sm.cc, operators/op-dm-cdm.cc, operators/op-dm-cm.cc, operators/op-dm-cs.cc, operators/op-dm-dm.cc, operators/op-dm-m.cc, operators/op-dm-s.cc, operators/op-dm-scm.cc, operators/op-dm-sm.cc, operators/op-dm-template.cc, operators/op-dms-template.cc, operators/op-double-conv.cc, operators/op-fcdm-fcdm.cc, operators/op-fcdm-fcm.cc, operators/op-fcdm-fcs.cc, operators/op-fcdm-fdm.cc, operators/op-fcdm-fm.cc, operators/op-fcdm-fs.cc, operators/op-fcm-fcdm.cc, operators/op-fcm-fcm.cc, operators/op-fcm-fcs.cc, operators/op-fcm-fdm.cc, operators/op-fcm-fm.cc, operators/op-fcm-fs.cc, operators/op-fcm-pm.cc, operators/op-fcn.cc, operators/op-fcs-fcm.cc, operators/op-fcs-fcs.cc, operators/op-fcs-fm.cc, operators/op-fcs-fs.cc, operators/op-fdm-fcdm.cc, operators/op-fdm-fcm.cc, operators/op-fdm-fcs.cc, operators/op-fdm-fdm.cc, operators/op-fdm-fm.cc, operators/op-fdm-fs.cc, operators/op-float-conv.cc, operators/op-fm-fcdm.cc, operators/op-fm-fcm.cc, operators/op-fm-fcs.cc, operators/op-fm-fdm.cc, operators/op-fm-fm.cc, operators/op-fm-fs.cc, operators/op-fm-pm.cc, operators/op-fs-fcm.cc, operators/op-fs-fcs.cc, operators/op-fs-fm.cc, operators/op-fs-fs.cc, operators/op-i16-i16.cc, operators/op-i32-i32.cc, operators/op-i64-i64.cc, operators/op-i8-i8.cc, operators/op-int-concat.cc, operators/op-int-conv.cc, operators/op-int.h, operators/op-m-cdm.cc, operators/op-m-cm.cc, operators/op-m-cs.cc, operators/op-m-dm.cc, operators/op-m-m.cc, operators/op-m-pm.cc, operators/op-m-s.cc, operators/op-m-scm.cc, operators/op-m-sm.cc, operators/op-pm-cm.cc, operators/op-pm-fcm.cc, operators/op-pm-fm.cc, operators/op-pm-m.cc, operators/op-pm-pm.cc, operators/op-pm-scm.cc, operators/op-pm-sm.cc, operators/op-pm-template.cc, operators/op-range.cc, operators/op-s-cm.cc, operators/op-s-cs.cc, operators/op-s-m.cc, operators/op-s-s.cc, operators/op-s-scm.cc, operators/op-s-sm.cc, operators/op-sbm-b.cc, operators/op-sbm-bm.cc, operators/op-sbm-sbm.cc, operators/op-scm-cm.cc, operators/op-scm-cs.cc, operators/op-scm-m.cc, operators/op-scm-s.cc, operators/op-scm-scm.cc, operators/op-scm-sm.cc, operators/op-sm-cm.cc, operators/op-sm-cs.cc, operators/op-sm-m.cc, operators/op-sm-s.cc, operators/op-sm-scm.cc, operators/op-sm-sm.cc, operators/op-str-m.cc, operators/op-str-s.cc, operators/op-str-str.cc, operators/op-struct.cc, operators/op-ui16-ui16.cc, operators/op-ui32-ui32.cc, operators/op-ui64-ui64.cc, operators/op-ui8-ui8.cc: Moved from OPERATORS/ dir to operators/ directory. * mkops: Correctly print comment in generated file ops.cc that it is made by mkops. Change sed expression for OPERATORS/ to operators/. * parse-tree/module.mk: Hook code in parse-tree dir into build system. * parse-tree/pt-all.h, parse-tree/pt-arg-list.cc, parse-tree/pt-arg-list.h, parse-tree/pt-assign.cc, parse-tree/pt-assign.h, parse-tree/pt-binop.cc, parse-tree/pt-binop.h, parse-tree/pt-bp.cc, parse-tree/pt-bp.h, parse-tree/pt-cbinop.cc, parse-tree/pt-cbinop.h, parse-tree/pt-cell.cc, parse-tree/pt-cell.h, parse-tree/pt-check.cc, parse-tree/pt-check.h, parse-tree/pt-cmd.cc, parse-tree/pt-cmd.h, parse-tree/pt-colon.cc, parse-tree/pt-colon.h, parse-tree/pt-const.cc, parse-tree/pt-const.h, parse-tree/pt-decl.cc, parse-tree/pt-decl.h, parse-tree/pt-eval.cc, parse-tree/pt-eval.h, parse-tree/pt-except.cc, parse-tree/pt-except.h, parse-tree/pt-exp.cc, parse-tree/pt-exp.h, parse-tree/pt-fcn-handle.cc, parse-tree/pt-fcn-handle.h, parse-tree/pt-id.cc, parse-tree/pt-id.h, parse-tree/pt-idx.cc, parse-tree/pt-idx.h, parse-tree/pt-jump.cc, parse-tree/pt-jump.h, parse-tree/pt-loop.cc, parse-tree/pt-loop.h, parse-tree/pt-mat.cc, parse-tree/pt-mat.h, parse-tree/pt-misc.cc, parse-tree/pt-misc.h, parse-tree/pt-pr-code.cc, parse-tree/pt-pr-code.h, parse-tree/pt-select.cc, parse-tree/pt-select.h, parse-tree/pt-stmt.cc, parse-tree/pt-stmt.h, parse-tree/pt-unop.cc, parse-tree/pt-unop.h, parse-tree/pt-walk.h, parse-tree/pt.cc, parse-tree/pt.h: Moved from src/ dir to parse-tree dir. * template-inst/Array-jit.cc, template-inst/Array-os.cc, template-inst/Array-sym.cc, template-inst/Array-tc.cc, template-inst/module.mk: Moved from TEMPLATE-INST dir to template-inst/ directory. * src/Makefile.am: Add new directories to build system. * corefcn/module.mk: Use COREFCN_SRC with all capitals to indicate it is not an Automake special target.
author Rik <rik@octave.org>
date Mon, 30 Jul 2012 15:29:19 -0700
parents src/ov-base.cc@460a3c6d8bf1
children 62a35ae7d6a2
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/octave-value/ov-base.cc	Mon Jul 30 15:29:19 2012 -0700
@@ -0,0 +1,1579 @@
+/*
+
+Copyright (C) 1996-2012 John W. Eaton
+Copyright (C) 2009-2010 VZLU Prague
+
+This file is part of Octave.
+
+Octave is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3 of the License, or (at your
+option) any later version.
+
+Octave is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<http://www.gnu.org/licenses/>.
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <climits>
+
+#include <iostream>
+
+#include "lo-ieee.h"
+#include "lo-mappers.h"
+
+#include "defun.h"
+#include "gripes.h"
+#include "oct-map.h"
+#include "oct-obj.h"
+#include "oct-lvalue.h"
+#include "oct-stream.h"
+#include "ops.h"
+#include "ov-base.h"
+#include "ov-cell.h"
+#include "ov-ch-mat.h"
+#include "ov-complex.h"
+#include "ov-cx-mat.h"
+#include "ov-range.h"
+#include "ov-re-mat.h"
+#include "ov-scalar.h"
+#include "ov-str-mat.h"
+#include "ov-fcn-handle.h"
+#include "parse.h"
+#include "pr-output.h"
+#include "utils.h"
+#include "variables.h"
+
+builtin_type_t btyp_mixed_numeric (builtin_type_t x, builtin_type_t y)
+{
+  builtin_type_t retval = btyp_unknown;
+
+  if (x == btyp_bool)
+    x = btyp_double;
+  if (y == btyp_bool)
+    y = btyp_double;
+
+  if (x <= btyp_float_complex && y <= btyp_float_complex)
+    retval = static_cast<builtin_type_t> (x | y);
+  else if (x <= btyp_uint64 && y <= btyp_float)
+    retval = x;
+  else if (x <= btyp_float && y <= btyp_uint64)
+    retval = y;
+  else if ((x >= btyp_int8 && x <= btyp_int64
+            && y >= btyp_int8 && y <= btyp_int64)
+           || (x >= btyp_uint8 && x <= btyp_uint64
+               && y >= btyp_uint8 && y <= btyp_uint64))
+    retval = (x > y) ? x : y;
+
+  return retval;
+}
+
+std::string btyp_class_name[btyp_num_types] =
+{
+  "double", "single", "double", "single",
+  "int8", "int16", "int32", "int64",
+  "uint8", "uint16", "uint32", "uint64",
+  "logical", "char",
+  "struct", "cell", "function_handle"
+};
+
+string_vector
+get_builtin_classes (void)
+{
+  static string_vector retval;
+
+  if (retval.is_empty ())
+    {
+      int n = btyp_num_types - 2;
+      retval = string_vector (n);
+      int j = 0;
+      for (int i = 0; i < btyp_num_types; i++)
+        {
+          builtin_type_t ityp = static_cast<builtin_type_t> (i);
+          if (ityp != btyp_complex && ityp != btyp_float_complex)
+            retval(j++) = btyp_class_name[i];
+        }
+    }
+
+  return retval;
+}
+
+DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_base_value,
+                                     "<unknown type>", "unknown");
+
+// TRUE means to perform automatic sparse to real mutation if there
+// is memory to be saved
+bool Vsparse_auto_mutate = false;
+
+octave_base_value *
+octave_base_value::empty_clone (void) const
+{
+  return resize (dim_vector ()).clone ();
+}
+
+octave_value
+octave_base_value::squeeze (void) const
+{
+  std::string nm = type_name ();
+  error ("squeeze: invalid operation for %s type", nm.c_str ());
+  return octave_value ();
+}
+
+octave_value
+octave_base_value::full_value (void) const
+{
+  gripe_wrong_type_arg ("full: invalid operation for %s type", type_name ());
+  return octave_value ();
+}
+
+Matrix
+octave_base_value::size (void)
+{
+  const dim_vector dv = dims ();
+  Matrix mdv (1, dv.length ());
+  for (octave_idx_type i = 0; i < dv.length (); i++)
+    mdv(i) = dv(i);
+  return mdv;
+}
+
+octave_idx_type
+octave_base_value::numel (const octave_value_list& idx)
+{
+  return dims_to_numel (dims (), idx);
+}
+
+octave_value
+octave_base_value::subsref (const std::string&,
+                            const std::list<octave_value_list>&)
+{
+  std::string nm = type_name ();
+  error ("can't perform indexing operations for %s type", nm.c_str ());
+  return octave_value ();
+}
+
+octave_value_list
+octave_base_value::subsref (const std::string&,
+                            const std::list<octave_value_list>&, int)
+{
+  std::string nm = type_name ();
+  error ("can't perform indexing operations for %s type", nm.c_str ());
+  return octave_value ();
+}
+
+octave_value
+octave_base_value::subsref (const std::string& type,
+                            const std::list<octave_value_list>& idx,
+                            bool /* auto_add */)
+{
+  // This way we may get a more meaningful error message.
+  return subsref (type, idx);
+}
+
+octave_value_list
+octave_base_value::subsref (const std::string& type,
+                            const std::list<octave_value_list>& idx,
+                            int nargout,
+                            const std::list<octave_lvalue> *)
+{
+  // Fall back to call without passing lvalue list.
+  return subsref (type, idx, nargout);
+}
+
+octave_value
+octave_base_value::do_index_op (const octave_value_list&, bool)
+{
+  std::string nm = type_name ();
+  error ("can't perform indexing operations for %s type", nm.c_str ());
+  return octave_value ();
+}
+
+octave_value_list
+octave_base_value::do_multi_index_op (int, const octave_value_list&)
+{
+  std::string nm = type_name ();
+  error ("can't perform indexing operations for %s type", nm.c_str ());
+  return octave_value ();
+}
+
+octave_value_list
+octave_base_value::do_multi_index_op (int nargout, const octave_value_list& idx,
+                                      const std::list<octave_lvalue> *)
+{
+  // Fall back.
+  return do_multi_index_op (nargout, idx);
+}
+
+idx_vector
+octave_base_value::index_vector (void) const
+{
+  std::string nm = type_name ();
+  error ("%s type invalid as index value", nm.c_str ());
+  return idx_vector ();
+}
+
+octave_value
+octave_base_value::subsasgn (const std::string& type,
+                             const std::list<octave_value_list>& idx,
+                             const octave_value& rhs)
+{
+  octave_value retval;
+
+  if (is_defined ())
+    {
+      if (is_numeric_type ())
+        {
+          switch (type[0])
+            {
+            case '(':
+              {
+                if (type.length () == 1)
+                  retval = numeric_assign (type, idx, rhs);
+                else if (is_empty ())
+                  {
+                    // Allow conversion of empty matrix to some other
+                    // type in cases like
+                    //
+                    //  x = []; x(i).f = rhs
+
+                    octave_value tmp = octave_value::empty_conv (type, rhs);
+
+                    retval = tmp.subsasgn (type, idx, rhs);
+                  }
+                else
+                  {
+                    std::string nm = type_name ();
+                    error ("in indexed assignment of %s, last rhs index must be ()",
+                           nm.c_str ());
+                  }
+              }
+              break;
+
+            case '{':
+            case '.':
+              {
+                std::string nm = type_name ();
+                error ("%s cannot be indexed with %c", nm.c_str (), type[0]);
+              }
+              break;
+
+            default:
+              panic_impossible ();
+            }
+        }
+      else
+        {
+          std::string nm = type_name ();
+          error ("can't perform indexed assignment for %s type", nm.c_str ());
+        }
+    }
+  else
+    {
+      // Create new object of appropriate type for given index and rhs
+      // types and then call undef_subsasgn for that object.
+
+      octave_value tmp = octave_value::empty_conv (type, rhs);
+
+      retval = tmp.undef_subsasgn (type, idx, rhs);
+    }
+
+  return retval;
+}
+
+octave_value
+octave_base_value::undef_subsasgn (const std::string& type,
+                                   const std::list<octave_value_list>& idx,
+                                   const octave_value& rhs)
+{
+  // In most cases, undef_subsasgn is handled the sams as subsasgn.  One
+  // exception is octave_class objects.
+
+  return subsasgn (type, idx, rhs);
+}
+
+octave_idx_type
+octave_base_value::nnz (void) const
+{
+  gripe_wrong_type_arg ("octave_base_value::nnz ()", type_name ());
+  return -1;
+}
+
+octave_idx_type
+octave_base_value::nzmax (void) const
+{
+  return numel ();
+}
+
+octave_idx_type
+octave_base_value::nfields (void) const
+{
+  gripe_wrong_type_arg ("octave_base_value::nfields ()", type_name ());
+  return -1;
+}
+
+octave_value
+octave_base_value::reshape (const dim_vector&) const
+{
+  gripe_wrong_type_arg ("octave_base_value::reshape ()", type_name ());
+  return octave_value ();
+}
+
+octave_value
+octave_base_value::permute (const Array<int>&, bool) const
+{
+  gripe_wrong_type_arg ("octave_base_value::permute ()", type_name ());
+  return octave_value ();
+}
+
+octave_value
+octave_base_value::resize (const dim_vector&, bool) const
+{
+  gripe_wrong_type_arg ("octave_base_value::resize ()", type_name ());
+  return octave_value ();
+}
+
+MatrixType
+octave_base_value::matrix_type (void) const
+{
+  gripe_wrong_type_arg ("octave_base_value::matrix_type ()", type_name ());
+  return MatrixType ();
+}
+
+MatrixType
+octave_base_value::matrix_type (const MatrixType&) const
+{
+  gripe_wrong_type_arg ("octave_base_value::matrix_type ()", type_name ());
+  return MatrixType ();
+}
+
+octave_value
+octave_base_value::all (int) const
+{
+  return 0.0;
+}
+
+octave_value
+octave_base_value::any (int) const
+{
+  return 0.0;
+}
+
+octave_value
+octave_base_value::convert_to_str (bool pad, bool force, char type) const
+{
+  octave_value retval = convert_to_str_internal (pad, force, type);
+
+  if (! force && is_numeric_type ())
+    gripe_implicit_conversion ("Octave:num-to-str",
+                               type_name (), retval.type_name ());
+
+  return retval;
+}
+
+octave_value
+octave_base_value::convert_to_str_internal (bool, bool, char) const
+{
+  gripe_wrong_type_arg ("octave_base_value::convert_to_str_internal ()",
+                        type_name ());
+  return octave_value ();
+}
+
+void
+octave_base_value::convert_to_row_or_column_vector (void)
+{
+  gripe_wrong_type_arg
+    ("octave_base_value::convert_to_row_or_column_vector ()",
+     type_name ());
+}
+
+void
+octave_base_value::print (std::ostream&, bool) const
+{
+  gripe_wrong_type_arg ("octave_base_value::print ()", type_name ());
+}
+
+void
+octave_base_value::print_raw (std::ostream&, bool) const
+{
+  gripe_wrong_type_arg ("octave_base_value::print_raw ()", type_name ());
+}
+
+bool
+octave_base_value::print_name_tag (std::ostream& os, const std::string& name) const
+{
+  bool retval = false;
+
+  indent (os);
+
+  if (print_as_scalar ())
+    os << name << " = ";
+  else
+    {
+      os << name << " =";
+      newline (os);
+      if (! Vcompact_format)
+        newline (os);
+
+      retval = true;
+    }
+
+  return retval;
+}
+
+void
+octave_base_value::print_with_name (std::ostream& output_buf,
+                                    const std::string& name,
+                                    bool print_padding)
+{
+  bool pad_after = print_name_tag (output_buf, name);
+
+  print (output_buf);
+
+  if (print_padding  && pad_after && ! Vcompact_format)
+    newline (output_buf);
+}
+
+void
+octave_base_value::print_info (std::ostream& os,
+                               const std::string& /* prefix */) const
+{
+  os << "no info for type: " << type_name () << "\n";
+}
+
+#define INT_CONV_METHOD(T, F, MIN_LIMIT, MAX_LIMIT) \
+  T \
+  octave_base_value::F ## _value (bool require_int, bool frc_str_conv) const \
+  { \
+    T retval = 0; \
+ \
+    double d = double_value (frc_str_conv); \
+ \
+    if (! error_state) \
+      { \
+        if (require_int && D_NINT (d) != d) \
+          error_with_cfn ("conversion of %g to " #T " value failed", d); \
+        else if (d < MIN_LIMIT) \
+          retval = MIN_LIMIT; \
+        else if (d > MAX_LIMIT) \
+          retval = MAX_LIMIT; \
+        else \
+          retval = static_cast<T> (::fix (d));  \
+      } \
+    else \
+      gripe_wrong_type_arg ("octave_base_value::" #F "_value ()", \
+                            type_name ()); \
+ \
+    return retval; \
+  }
+
+INT_CONV_METHOD (short int, short, SHRT_MIN, SHRT_MAX)
+INT_CONV_METHOD (unsigned short int, ushort, 0, USHRT_MAX)
+
+INT_CONV_METHOD (int, int, INT_MIN, INT_MAX)
+INT_CONV_METHOD (unsigned int, uint, 0, UINT_MAX)
+
+INT_CONV_METHOD (long int, long, LONG_MIN, LONG_MAX)
+INT_CONV_METHOD (unsigned long int, ulong, 0, ULONG_MAX)
+
+int
+octave_base_value::nint_value (bool frc_str_conv) const
+{
+  int retval = 0;
+
+  double d = double_value (frc_str_conv);
+
+  if (! error_state)
+    {
+      if (xisnan (d))
+        {
+          error ("conversion of NaN to integer value failed");
+          return retval;
+        }
+
+      retval = static_cast<int> (::fix (d));
+    }
+  else
+    gripe_wrong_type_arg ("octave_base_value::nint_value ()", type_name ());
+
+  return retval;
+}
+
+double
+octave_base_value::double_value (bool) const
+{
+  double retval = lo_ieee_nan_value ();
+  gripe_wrong_type_arg ("octave_base_value::double_value ()", type_name ());
+  return retval;
+}
+
+float
+octave_base_value::float_value (bool) const
+{
+  float retval = lo_ieee_float_nan_value ();
+  gripe_wrong_type_arg ("octave_base_value::float_value ()", type_name ());
+  return retval;
+}
+
+Cell
+octave_base_value::cell_value () const
+{
+  Cell retval;
+  gripe_wrong_type_arg ("octave_base_value::cell_value()", type_name ());
+  return retval;
+}
+
+Matrix
+octave_base_value::matrix_value (bool) const
+{
+  Matrix retval;
+  gripe_wrong_type_arg ("octave_base_value::matrix_value()", type_name ());
+  return retval;
+}
+
+FloatMatrix
+octave_base_value::float_matrix_value (bool) const
+{
+  FloatMatrix retval;
+  gripe_wrong_type_arg ("octave_base_value::float_matrix_value()", type_name ());
+  return retval;
+}
+
+NDArray
+octave_base_value::array_value (bool) const
+{
+  FloatNDArray retval;
+  gripe_wrong_type_arg ("octave_base_value::array_value()", type_name ());
+  return retval;
+}
+
+FloatNDArray
+octave_base_value::float_array_value (bool) const
+{
+  FloatNDArray retval;
+  gripe_wrong_type_arg ("octave_base_value::float_array_value()", type_name ());
+  return retval;
+}
+
+Complex
+octave_base_value::complex_value (bool) const
+{
+  double tmp = lo_ieee_nan_value ();
+  Complex retval (tmp, tmp);
+  gripe_wrong_type_arg ("octave_base_value::complex_value()", type_name ());
+  return retval;
+}
+
+FloatComplex
+octave_base_value::float_complex_value (bool) const
+{
+  float tmp = lo_ieee_float_nan_value ();
+  FloatComplex retval (tmp, tmp);
+  gripe_wrong_type_arg ("octave_base_value::float_complex_value()", type_name ());
+  return retval;
+}
+
+ComplexMatrix
+octave_base_value::complex_matrix_value (bool) const
+{
+  ComplexMatrix retval;
+  gripe_wrong_type_arg ("octave_base_value::complex_matrix_value()",
+                        type_name ());
+  return retval;
+}
+
+FloatComplexMatrix
+octave_base_value::float_complex_matrix_value (bool) const
+{
+  FloatComplexMatrix retval;
+  gripe_wrong_type_arg ("octave_base_value::float_complex_matrix_value()",
+                        type_name ());
+  return retval;
+}
+
+ComplexNDArray
+octave_base_value::complex_array_value (bool) const
+{
+  ComplexNDArray retval;
+  gripe_wrong_type_arg ("octave_base_value::complex_array_value()",
+                        type_name ());
+  return retval;
+}
+
+FloatComplexNDArray
+octave_base_value::float_complex_array_value (bool) const
+{
+  FloatComplexNDArray retval;
+  gripe_wrong_type_arg ("octave_base_value::float_complex_array_value()",
+                        type_name ());
+  return retval;
+}
+
+bool
+octave_base_value::bool_value (bool) const
+{
+  bool retval = false;
+  gripe_wrong_type_arg ("octave_base_value::bool_value()", type_name ());
+  return retval;
+}
+
+boolMatrix
+octave_base_value::bool_matrix_value (bool) const
+{
+  boolMatrix retval;
+  gripe_wrong_type_arg ("octave_base_value::bool_matrix_value()",
+                        type_name ());
+  return retval;
+}
+
+boolNDArray
+octave_base_value::bool_array_value (bool) const
+{
+  boolNDArray retval;
+  gripe_wrong_type_arg ("octave_base_value::bool_array_value()",
+                        type_name ());
+  return retval;
+}
+
+charMatrix
+octave_base_value::char_matrix_value (bool force) const
+{
+  charMatrix retval;
+
+  octave_value tmp = convert_to_str (false, force);
+
+  if (! error_state)
+    retval = tmp.char_matrix_value ();
+
+  return retval;
+}
+
+charNDArray
+octave_base_value::char_array_value (bool) const
+{
+  charNDArray retval;
+  gripe_wrong_type_arg ("octave_base_value::char_array_value()",
+                        type_name ());
+  return retval;
+}
+
+SparseMatrix
+octave_base_value::sparse_matrix_value (bool) const
+{
+  SparseMatrix retval;
+  gripe_wrong_type_arg ("octave_base_value::sparse_matrix_value()", type_name ());
+  return retval;
+}
+
+SparseComplexMatrix
+octave_base_value::sparse_complex_matrix_value (bool) const
+{
+  SparseComplexMatrix retval;
+  gripe_wrong_type_arg ("octave_base_value::sparse_complex_matrix_value()", type_name ());
+  return retval;
+}
+
+SparseBoolMatrix
+octave_base_value::sparse_bool_matrix_value (bool) const
+{
+  SparseBoolMatrix retval;
+  gripe_wrong_type_arg ("octave_base_value::sparse_bool_matrix_value()", type_name ());
+  return retval;
+}
+
+DiagMatrix
+octave_base_value::diag_matrix_value (bool) const
+{
+  DiagMatrix retval;
+  gripe_wrong_type_arg ("octave_base_value::diag_matrix_value()", type_name ());
+  return retval;
+}
+
+FloatDiagMatrix
+octave_base_value::float_diag_matrix_value (bool) const
+{
+  FloatDiagMatrix retval;
+  gripe_wrong_type_arg ("octave_base_value::float_diag_matrix_value()", type_name ());
+  return retval;
+}
+
+ComplexDiagMatrix
+octave_base_value::complex_diag_matrix_value (bool) const
+{
+  ComplexDiagMatrix retval;
+  gripe_wrong_type_arg ("octave_base_value::complex_diag_matrix_value()", type_name ());
+  return retval;
+}
+
+FloatComplexDiagMatrix
+octave_base_value::float_complex_diag_matrix_value (bool) const
+{
+  FloatComplexDiagMatrix retval;
+  gripe_wrong_type_arg ("octave_base_value::float_complex_diag_matrix_value()", type_name ());
+  return retval;
+}
+
+PermMatrix
+octave_base_value::perm_matrix_value (void) const
+{
+  PermMatrix retval;
+  gripe_wrong_type_arg ("octave_base_value::perm_matrix_value()", type_name ());
+  return retval;
+}
+
+octave_int8
+octave_base_value::int8_scalar_value (void) const
+{
+  octave_int8 retval;
+  gripe_wrong_type_arg ("octave_base_value::int8_scalar_value()",
+                        type_name ());
+  return retval;
+}
+
+octave_int16
+octave_base_value::int16_scalar_value (void) const
+{
+  octave_int16 retval;
+  gripe_wrong_type_arg ("octave_base_value::int16_scalar_value()",
+                        type_name ());
+  return retval;
+}
+
+octave_int32
+octave_base_value::int32_scalar_value (void) const
+{
+  octave_int32 retval;
+  gripe_wrong_type_arg ("octave_base_value::int32_scalar_value()",
+                        type_name ());
+  return retval;
+}
+
+octave_int64
+octave_base_value::int64_scalar_value (void) const
+{
+  octave_int64 retval;
+  gripe_wrong_type_arg ("octave_base_value::int64_scalar_value()",
+                        type_name ());
+  return retval;
+}
+
+octave_uint8
+octave_base_value::uint8_scalar_value (void) const
+{
+  octave_uint8 retval;
+  gripe_wrong_type_arg ("octave_base_value::uint8_scalar_value()",
+                        type_name ());
+  return retval;
+}
+
+octave_uint16
+octave_base_value::uint16_scalar_value (void) const
+{
+  octave_uint16 retval;
+  gripe_wrong_type_arg ("octave_base_value::uint16_scalar_value()",
+                        type_name ());
+  return retval;
+}
+
+octave_uint32
+octave_base_value::uint32_scalar_value (void) const
+{
+  octave_uint32 retval;
+  gripe_wrong_type_arg ("octave_base_value::uint32_scalar_value()",
+                        type_name ());
+  return retval;
+}
+
+octave_uint64
+octave_base_value::uint64_scalar_value (void) const
+{
+  octave_uint64 retval;
+  gripe_wrong_type_arg ("octave_base_value::uint64_scalar_value()",
+                        type_name ());
+  return retval;
+}
+
+int8NDArray
+octave_base_value::int8_array_value (void) const
+{
+  int8NDArray retval;
+  gripe_wrong_type_arg ("octave_base_value::int8_array_value()",
+                        type_name ());
+  return retval;
+}
+
+int16NDArray
+octave_base_value::int16_array_value (void) const
+{
+  int16NDArray retval;
+  gripe_wrong_type_arg ("octave_base_value::int16_array_value()",
+                        type_name ());
+  return retval;
+}
+
+int32NDArray
+octave_base_value::int32_array_value (void) const
+{
+  int32NDArray retval;
+  gripe_wrong_type_arg ("octave_base_value::int32_array_value()",
+                        type_name ());
+  return retval;
+}
+
+int64NDArray
+octave_base_value::int64_array_value (void) const
+{
+  int64NDArray retval;
+  gripe_wrong_type_arg ("octave_base_value::int64_array_value()",
+                        type_name ());
+  return retval;
+}
+
+uint8NDArray
+octave_base_value::uint8_array_value (void) const
+{
+  uint8NDArray retval;
+  gripe_wrong_type_arg ("octave_base_value::uint8_array_value()",
+                        type_name ());
+  return retval;
+}
+
+uint16NDArray
+octave_base_value::uint16_array_value (void) const
+{
+  uint16NDArray retval;
+  gripe_wrong_type_arg ("octave_base_value::uint16_array_value()",
+                        type_name ());
+  return retval;
+}
+
+uint32NDArray
+octave_base_value::uint32_array_value (void) const
+{
+  uint32NDArray retval;
+  gripe_wrong_type_arg ("octave_base_value::uint32_array_value()",
+                        type_name ());
+  return retval;
+}
+
+uint64NDArray
+octave_base_value::uint64_array_value (void) const
+{
+  uint64NDArray retval;
+  gripe_wrong_type_arg ("octave_base_value::uint64_array_value()",
+                        type_name ());
+  return retval;
+}
+
+string_vector
+octave_base_value::all_strings (bool pad) const
+{
+  string_vector retval;
+
+  octave_value tmp = convert_to_str (pad, true);
+
+  if (! error_state)
+    retval = tmp.all_strings ();
+
+  return retval;
+}
+
+std::string
+octave_base_value::string_value (bool force) const
+{
+  std::string retval;
+
+  octave_value tmp = convert_to_str (force);
+
+  if (! error_state)
+    retval = tmp.string_value ();
+
+  return retval;
+}
+
+Array<std::string>
+octave_base_value::cellstr_value (void) const
+{
+  Array<std::string> retval;
+  gripe_wrong_type_arg ("octave_base_value::cellstry_value()",
+                        type_name ());
+  return retval;
+}
+
+Range
+octave_base_value::range_value (void) const
+{
+  Range retval;
+  gripe_wrong_type_arg ("octave_base_value::range_value()", type_name ());
+  return retval;
+}
+
+octave_map
+octave_base_value::map_value (void) const
+{
+  octave_map retval;
+  gripe_wrong_type_arg ("octave_base_value::map_value()", type_name ());
+  return retval;
+}
+
+octave_scalar_map
+octave_base_value::scalar_map_value (void) const
+{
+  octave_map tmp = map_value ();
+
+  if (tmp.numel () == 1)
+    return tmp.checkelem (0);
+  else
+    {
+      if (! error_state)
+        error ("invalid conversion of multi-dimensional struct to scalar struct");
+
+      return octave_scalar_map ();
+    }
+}
+
+string_vector
+octave_base_value::map_keys (void) const
+{
+  string_vector retval;
+  gripe_wrong_type_arg ("octave_base_value::map_keys()", type_name ());
+  return retval;
+}
+
+size_t
+octave_base_value::nparents (void) const
+{
+  size_t retval = 0;
+  gripe_wrong_type_arg ("octave_base_value::nparents()", type_name ());
+  return retval;
+}
+
+std::list<std::string>
+octave_base_value::parent_class_name_list (void) const
+{
+  std::list<std::string> retval;
+  gripe_wrong_type_arg ("octave_base_value::parent_class_name_list()",
+                        type_name ());
+  return retval;
+}
+
+string_vector
+octave_base_value::parent_class_names (void) const
+{
+  string_vector retval;
+  gripe_wrong_type_arg ("octave_base_value::parent_class_names()",
+                        type_name ());
+  return retval;
+}
+
+octave_function *
+octave_base_value::function_value (bool silent)
+{
+  octave_function *retval = 0;
+
+  if (! silent)
+    gripe_wrong_type_arg ("octave_base_value::function_value()",
+                          type_name ());
+  return retval;
+}
+
+octave_user_function *
+octave_base_value::user_function_value (bool silent)
+{
+  octave_user_function *retval = 0;
+
+  if (! silent)
+    gripe_wrong_type_arg ("octave_base_value::user_function_value()",
+                          type_name ());
+  return retval;
+}
+
+octave_user_script *
+octave_base_value::user_script_value (bool silent)
+{
+  octave_user_script *retval = 0;
+
+  if (! silent)
+    gripe_wrong_type_arg ("octave_base_value::user_script_value()",
+                          type_name ());
+  return retval;
+}
+
+octave_user_code *
+octave_base_value::user_code_value (bool silent)
+{
+  octave_user_code *retval = 0;
+
+  if (! silent)
+    gripe_wrong_type_arg ("octave_base_value::user_code_value()",
+                          type_name ());
+  return retval;
+}
+
+octave_fcn_handle *
+octave_base_value::fcn_handle_value (bool silent)
+{
+  octave_fcn_handle *retval = 0;
+
+  if (! silent)
+    gripe_wrong_type_arg ("octave_base_value::fcn_handle_value()",
+                          type_name ());
+  return retval;
+}
+
+octave_fcn_inline *
+octave_base_value::fcn_inline_value (bool silent)
+{
+  octave_fcn_inline *retval = 0;
+
+  if (! silent)
+    gripe_wrong_type_arg ("octave_base_value::fcn_inline_value()",
+                          type_name ());
+  return retval;
+}
+
+octave_value_list
+octave_base_value::list_value (void) const
+{
+  octave_value_list retval;
+  gripe_wrong_type_arg ("octave_base_value::list_value()", type_name ());
+  return retval;
+}
+
+bool
+octave_base_value::save_ascii (std::ostream&)
+{
+  gripe_wrong_type_arg ("octave_base_value::save_ascii()", type_name ());
+  return false;
+}
+
+bool
+octave_base_value::load_ascii (std::istream&)
+{
+  gripe_wrong_type_arg ("octave_base_value::load_ascii()", type_name ());
+  return false;
+}
+
+bool
+octave_base_value::save_binary (std::ostream&, bool&)
+{
+  gripe_wrong_type_arg ("octave_base_value::save_binary()", type_name ());
+  return false;
+}
+
+bool
+octave_base_value::load_binary (std::istream&, bool,
+                                oct_mach_info::float_format)
+{
+  gripe_wrong_type_arg ("octave_base_value::load_binary()", type_name ());
+  return false;
+}
+
+#if defined (HAVE_HDF5)
+
+bool
+octave_base_value::save_hdf5 (hid_t, const char *, bool)
+{
+  gripe_wrong_type_arg ("octave_base_value::save_binary()", type_name ());
+
+  return false;
+}
+
+bool
+octave_base_value::load_hdf5 (hid_t, const char *)
+{
+  gripe_wrong_type_arg ("octave_base_value::load_binary()", type_name ());
+
+  return false;
+}
+
+#endif
+
+int
+octave_base_value::write (octave_stream&, int, oct_data_conv::data_type,
+                          int, oct_mach_info::float_format) const
+{
+  gripe_wrong_type_arg ("octave_base_value::write()", type_name ());
+
+  return false;
+}
+
+mxArray *
+octave_base_value::as_mxArray (void) const
+{
+  return 0;
+}
+
+octave_value
+octave_base_value::diag (octave_idx_type) const
+{
+  gripe_wrong_type_arg ("octave_base_value::diag ()", type_name ());
+
+  return octave_value ();
+}
+
+octave_value
+octave_base_value::diag (octave_idx_type, octave_idx_type) const
+{
+  gripe_wrong_type_arg ("octave_base_value::diag ()", type_name ());
+
+  return octave_value ();
+}
+
+octave_value
+octave_base_value::sort (octave_idx_type, sortmode) const
+{
+  gripe_wrong_type_arg ("octave_base_value::sort ()", type_name ());
+
+  return octave_value ();
+}
+
+octave_value
+octave_base_value::sort (Array<octave_idx_type> &,
+                         octave_idx_type, sortmode) const
+{
+  gripe_wrong_type_arg ("octave_base_value::sort ()", type_name ());
+
+  return octave_value ();
+}
+
+sortmode
+octave_base_value::is_sorted (sortmode) const
+{
+  gripe_wrong_type_arg ("octave_base_value::is_sorted ()", type_name ());
+
+  return UNSORTED;
+}
+
+Array<octave_idx_type>
+octave_base_value::sort_rows_idx (sortmode) const
+{
+  gripe_wrong_type_arg ("octave_base_value::sort_rows_idx ()", type_name ());
+
+  return Array<octave_idx_type> ();
+}
+
+sortmode
+octave_base_value::is_sorted_rows (sortmode) const
+{
+  gripe_wrong_type_arg ("octave_base_value::is_sorted_rows ()", type_name ());
+
+  return UNSORTED;
+}
+
+
+const char *
+octave_base_value::get_umap_name (unary_mapper_t umap)
+{
+  static const char *names[num_unary_mappers] =
+    {
+      "abs",
+      "acos",
+      "acosh",
+      "angle",
+      "arg",
+      "asin",
+      "asinh",
+      "atan",
+      "atanh",
+      "cbrt",
+      "ceil",
+      "conj",
+      "cos",
+      "cosh",
+      "erf",
+      "erfinv",
+      "erfcinv",
+      "erfc",
+      "exp",
+      "expm1",
+      "finite",
+      "fix",
+      "floor",
+      "gamma",
+      "imag",
+      "isinf",
+      "isna",
+      "isnan",
+      "lgamma",
+      "log",
+      "log2",
+      "log10",
+      "log1p",
+      "real",
+      "round",
+      "roundb",
+      "signum",
+      "sin",
+      "sinh",
+      "sqrt",
+      "tan",
+      "tanh",
+      "isalnum",
+      "isalpha",
+      "isascii",
+      "iscntrl",
+      "isdigit",
+      "isgraph",
+      "islower",
+      "isprint",
+      "ispunct",
+      "isspace",
+      "isupper",
+      "isxdigit",
+      "toascii",
+      "tolower",
+      "toupper"
+    };
+
+  if (umap < 0 || umap >= num_unary_mappers)
+    return "unknown";
+  else
+    return names[umap];
+}
+
+octave_value
+octave_base_value::map (unary_mapper_t umap) const
+{
+  error ("%s: not defined for %s", get_umap_name (umap), type_name ().c_str ());
+  return octave_value ();
+}
+
+void
+octave_base_value::lock (void)
+{
+  gripe_wrong_type_arg ("octave_base_value::lock ()", type_name ());
+}
+
+void
+octave_base_value::unlock (void)
+{
+  gripe_wrong_type_arg ("octave_base_value::unlock ()", type_name ());
+}
+
+void
+octave_base_value::dump (std::ostream& os) const
+{
+  dim_vector dv = this->dims ();
+
+  os << "class: " << this->class_name ()
+     << " type: " << this->type_name ()
+     << " dims: " << dv.str ();
+}
+
+static void
+gripe_indexed_assignment (const std::string& tn1, const std::string& tn2)
+{
+  error ("assignment of `%s' to indexed `%s' not implemented",
+         tn2.c_str (), tn1.c_str ());
+}
+
+static void
+gripe_assign_conversion_failed (const std::string& tn1,
+                                const std::string& tn2)
+{
+  error ("type conversion for assignment of `%s' to indexed `%s' failed",
+         tn2.c_str (), tn1.c_str ());
+}
+
+static void
+gripe_no_conversion (const std::string& on, const std::string& tn1,
+                     const std::string& tn2)
+{
+  error ("operator %s: no conversion for assignment of `%s' to indexed `%s'",
+         on.c_str (), tn2.c_str (), tn1.c_str ());
+}
+
+octave_value
+octave_base_value::numeric_assign (const std::string& type,
+                                   const std::list<octave_value_list>& idx,
+                                   const octave_value& rhs)
+{
+  octave_value retval;
+
+  if (idx.front ().empty ())
+    {
+      error ("missing index in indexed assignment");
+      return retval;
+    }
+
+  int t_lhs = type_id ();
+  int t_rhs = rhs.type_id ();
+
+  octave_value_typeinfo::assign_op_fcn f
+    = octave_value_typeinfo::lookup_assign_op (octave_value::op_asn_eq,
+                                               t_lhs, t_rhs);
+
+  bool done = false;
+
+  if (f)
+    {
+      f (*this, idx.front (), rhs.get_rep ());
+
+      done = (! error_state);
+    }
+
+  if (done)
+    {
+      count++;
+      retval = octave_value (this);
+    }
+  else
+    {
+      int t_result
+        = octave_value_typeinfo::lookup_pref_assign_conv (t_lhs, t_rhs);
+
+      if (t_result >= 0)
+        {
+          octave_base_value::type_conv_fcn cf
+            = octave_value_typeinfo::lookup_widening_op (t_lhs, t_result);
+
+          if (cf)
+            {
+              octave_base_value *tmp = cf (*this);
+
+              if (tmp)
+                {
+                  octave_value val (tmp);
+
+                  retval = val.subsasgn (type, idx, rhs);
+
+                  done = (! error_state);
+                }
+              else
+                gripe_assign_conversion_failed (type_name (),
+                                                rhs.type_name ());
+            }
+          else
+            gripe_indexed_assignment (type_name (), rhs.type_name ());
+        }
+
+      if (! (done || error_state))
+        {
+          octave_value tmp_rhs;
+
+          octave_base_value::type_conv_info cf_rhs
+            = rhs.numeric_conversion_function ();
+
+          octave_base_value::type_conv_info cf_this
+            = numeric_conversion_function ();
+
+          // Try biased (one-sided) conversions first.
+          if (cf_rhs.type_id () >= 0
+              && (octave_value_typeinfo::lookup_assign_op (octave_value::op_asn_eq,
+                                                           t_lhs, cf_rhs.type_id ())
+                  || octave_value_typeinfo::lookup_pref_assign_conv (t_lhs,
+                                                                     cf_rhs.type_id ()) >= 0))
+            cf_this = 0;
+          else if (cf_this.type_id () >= 0
+                   && (octave_value_typeinfo::lookup_assign_op (octave_value::op_asn_eq,
+                                                                cf_this.type_id (), t_rhs)
+                       || octave_value_typeinfo::lookup_pref_assign_conv (cf_this.type_id (),
+                                                                          t_rhs) >= 0))
+            cf_rhs = 0;
+
+          if (cf_rhs)
+            {
+              octave_base_value *tmp = cf_rhs (rhs.get_rep ());
+
+              if (tmp)
+                tmp_rhs = octave_value (tmp);
+              else
+                {
+                  gripe_assign_conversion_failed (type_name (),
+                                                  rhs.type_name ());
+                  return octave_value ();
+                }
+            }
+          else
+            tmp_rhs = rhs;
+
+          count++;
+          octave_value tmp_lhs = octave_value (this);
+
+          if (cf_this)
+            {
+              octave_base_value *tmp = cf_this (*this);
+
+              if (tmp)
+                tmp_lhs = octave_value (tmp);
+              else
+                {
+                  gripe_assign_conversion_failed (type_name (),
+                                                  rhs.type_name ());
+                  return octave_value ();
+                }
+            }
+
+          if (cf_this || cf_rhs)
+            {
+              retval = tmp_lhs.subsasgn (type, idx, tmp_rhs);
+
+              done = (! error_state);
+            }
+          else
+            gripe_no_conversion (octave_value::assign_op_as_string (octave_value::op_asn_eq),
+                                 type_name (), rhs.type_name ());
+        }
+    }
+
+  // The assignment may have converted to a type that is wider than
+  // necessary.
+
+  retval.maybe_mutate ();
+
+  return retval;
+}
+
+// Current indentation.
+int octave_base_value::curr_print_indent_level = 0;
+
+// TRUE means we are at the beginning of a line.
+bool octave_base_value::beginning_of_line = true;
+
+// Each print() function should call this before printing anything.
+//
+// This doesn't need to be fast, but isn't there a better way?
+
+void
+octave_base_value::indent (std::ostream& os) const
+{
+  assert (curr_print_indent_level >= 0);
+
+  if (beginning_of_line)
+    {
+      // FIXME -- do we need this?
+      // os << prefix;
+
+      for (int i = 0; i < curr_print_indent_level; i++)
+        os << " ";
+
+      beginning_of_line = false;
+    }
+}
+
+// All print() functions should use this to print new lines.
+
+void
+octave_base_value::newline (std::ostream& os) const
+{
+  os << "\n";
+
+  beginning_of_line = true;
+}
+
+// For ressetting print state.
+
+void
+octave_base_value::reset (void) const
+{
+  beginning_of_line = true;
+  curr_print_indent_level = 0;
+}
+
+
+octave_value
+octave_base_value::fast_elem_extract (octave_idx_type) const
+{
+  return octave_value ();
+}
+
+bool
+octave_base_value::fast_elem_insert (octave_idx_type, const octave_value&)
+{
+  return false;
+}
+
+bool
+octave_base_value::fast_elem_insert_self (void *, builtin_type_t) const
+{
+  return false;
+}
+
+CONVDECLX (matrix_conv)
+{
+  return new octave_matrix ();
+}
+
+CONVDECLX (complex_matrix_conv)
+{
+  return new octave_complex_matrix ();
+}
+
+CONVDECLX (string_conv)
+{
+  return new octave_char_matrix_str ();
+}
+
+CONVDECLX (cell_conv)
+{
+  return new octave_cell ();
+}
+
+void
+install_base_type_conversions (void)
+{
+  INSTALL_ASSIGNCONV (octave_base_value, octave_scalar, octave_matrix);
+  INSTALL_ASSIGNCONV (octave_base_value, octave_matrix, octave_matrix);
+  INSTALL_ASSIGNCONV (octave_base_value, octave_complex, octave_complex_matrix);
+  INSTALL_ASSIGNCONV (octave_base_value, octave_complex_matrix, octave_complex_matrix);
+  INSTALL_ASSIGNCONV (octave_base_value, octave_range, octave_matrix);
+  INSTALL_ASSIGNCONV (octave_base_value, octave_char_matrix_str, octave_char_matrix_str);
+  INSTALL_ASSIGNCONV (octave_base_value, octave_cell, octave_cell);
+
+  INSTALL_WIDENOP (octave_base_value, octave_matrix, matrix_conv);
+  INSTALL_WIDENOP (octave_base_value, octave_complex_matrix, complex_matrix_conv);
+  INSTALL_WIDENOP (octave_base_value, octave_char_matrix_str, string_conv);
+  INSTALL_WIDENOP (octave_base_value, octave_cell, cell_conv);
+}
+
+DEFUN (sparse_auto_mutate, args, nargout,
+  "-*- texinfo -*-\n\
+@deftypefn  {Built-in Function} {@var{val} =} sparse_auto_mutate ()\n\
+@deftypefnx {Built-in Function} {@var{old_val} =} sparse_auto_mutate (@var{new_val})\n\
+@deftypefnx {Built-in Function} {} sparse_auto_mutate (@var{new_val}, \"local\")\n\
+Query or set the internal variable that controls whether Octave will\n\
+automatically mutate sparse matrices to full matrices to save memory.\n\
+For example:\n\
+\n\
+@example\n\
+@group\n\
+s = speye (3);\n\
+sparse_auto_mutate (false);\n\
+s(:, 1) = 1;\n\
+typeinfo (s)\n\
+@result{} sparse matrix\n\
+sparse_auto_mutate (true);\n\
+s(1, :) = 1;\n\
+typeinfo (s)\n\
+@result{} matrix\n\
+@end group\n\
+@end example\n\
+\n\
+When called from inside a function with the \"local\" option, the variable is\n\
+changed locally for the function and any subroutines it calls.  The original\n\
+variable value is restored when exiting the function.\n\
+@end deftypefn")
+{
+  return SET_INTERNAL_VARIABLE (sparse_auto_mutate);
+}
+
+/*
+%!test
+%! s = speye (3);
+%! sparse_auto_mutate (false);
+%! s(:, 1) = 1;
+%! assert (typeinfo (s), "sparse matrix");
+%! sparse_auto_mutate (true);
+%! s(1, :) = 1;
+%! assert (typeinfo (s), "matrix");
+%! sparse_auto_mutate (false);
+*/