changeset 10325:8b3cfc1288e2

implement lazy index conversions
author Jaroslav Hajek <highegg@gmail.com>
date Tue, 16 Feb 2010 15:28:53 +0100
parents 7673850d6adf
children ade59ae10e80
files src/ChangeLog src/Makefile.am src/ls-hdf5.cc src/ov-lazy-idx.cc src/ov-lazy-idx.h src/ov.cc src/ov.h
diffstat 7 files changed, 413 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Mon Feb 15 08:55:46 2010 +0100
+++ b/src/ChangeLog	Tue Feb 16 15:28:53 2010 +0100
@@ -1,3 +1,13 @@
+2010-02-16  Jaroslav Hajek  <highegg@gmail.com>
+
+	* ov-lazy-idx.h: New source.
+	* ov-lazy-idx.cc: New source.
+	* ov.cc (install_types): Register lazy_index here.
+	(octave_value::octave_value (const idx_vector&)): Use lazy
+	construction if possible, under control of an optional flag.
+	(octave_value::clone): Implement.
+	* ls-hdf5.cc (save_hdf5): Avoid saving lazy indices.
+
 2010-02-15  Jaroslav Hajek  <highegg@gmail.com>
 
 	* ov-fcn-handle.h (octave_fcn_handle::print_as_scalar): New method
--- a/src/Makefile.am	Mon Feb 15 08:55:46 2010 +0100
+++ b/src/Makefile.am	Tue Feb 16 15:28:53 2010 +0100
@@ -165,6 +165,7 @@
   ov-flt-cx-mat.h \
   ov-flt-re-diag.h \
   ov-flt-re-mat.h \
+  ov-lazy-idx.h \
   ov-mex-fcn.h \
   ov-null-mat.h \
   ov-perm.h \
@@ -337,6 +338,7 @@
   ov-flt-cx-mat.cc \
   ov-flt-re-diag.cc \
   ov-flt-re-mat.cc \
+  ov-lazy-idx.cc \
   ov-mex-fcn.cc \
   ov-null-mat.cc \
   ov-perm.cc \
--- a/src/ls-hdf5.cc	Mon Feb 15 08:55:46 2010 +0100
+++ b/src/ls-hdf5.cc	Tue Feb 16 15:28:53 2010 +0100
@@ -67,6 +67,7 @@
 #include "variables.h"
 #include "version.h"
 #include "dMatrix.h"
+#include "ov-lazy-idx.h"
 
 #include "ls-utils.h"
 #include "ls-hdf5.h"
@@ -753,7 +754,8 @@
   // FIXME: diagonal & permutation matrices currently don't know how to save
   // themselves, so we convert them first to normal matrices using A = A(:,:).
   // This is a temporary hack.
-  if (val.is_diag_matrix () || val.is_perm_matrix ())
+  if (val.is_diag_matrix () || val.is_perm_matrix () 
+      || val.type_id () == octave_lazy_index::static_type_id ())
     val = val.full_value ();
 
   std::string t = val.type_name();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ov-lazy-idx.cc	Tue Feb 16 15:28:53 2010 +0100
@@ -0,0 +1,115 @@
+
+/*
+
+Copyright (C) 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 "ov-lazy-idx.h"
+#include "ops.h"
+#include "ov-scalar.h"
+#include "ls-oct-ascii.h"
+#include "ls-oct-binary.h"
+
+DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_lazy_index, "lazy_index", "double");
+
+static octave_base_value *
+default_numeric_conversion_function (const octave_base_value& a)
+{
+  CAST_CONV_ARG (const octave_lazy_index&);
+
+  return v.full_value ().clone ();
+}
+
+octave_base_value::type_conv_info
+octave_lazy_index::numeric_conversion_function (void) const
+{
+  return octave_base_value::type_conv_info (default_numeric_conversion_function,
+                                            octave_matrix::static_type_id ());
+}
+
+octave_base_value *
+octave_lazy_index::try_narrowing_conversion (void)
+{
+  octave_base_value *retval = 0;
+
+  switch (index.length (0))
+    {
+    case 1:
+      retval = new octave_scalar (static_cast<double> (index(0) + 1));
+      break;
+
+    case 0:
+      retval = new octave_matrix (NDArray (index.orig_dimensions ()));
+      break;
+
+    default:
+      break;
+    }
+
+  return retval;
+}
+
+static const std::string value_save_tag ("index_value");
+
+bool octave_lazy_index::save_ascii (std::ostream& os)
+{
+  return save_ascii_data (os, make_value (), value_save_tag, false, 0);
+}
+
+bool octave_lazy_index::load_ascii (std::istream& is)
+{
+  bool dummy;
+
+  std::string nm = read_ascii_data (is, std::string (), dummy, value, 0);
+
+  if (nm != value_save_tag)
+    error ("lazy_index: corrupted data on load");
+  else
+    index = value.index_vector ();
+
+  return ! error_state;
+}
+
+
+bool octave_lazy_index::save_binary (std::ostream& os, bool& save_as_floats)
+{
+  return save_binary_data (os, make_value (), value_save_tag, false, 0, save_as_floats);
+}
+
+bool octave_lazy_index::load_binary (std::istream& is, bool swap, 
+                                     oct_mach_info::float_format fmt)
+{
+  bool dummy;
+  std::string doc;
+
+  std::string nm = read_binary_data (is, swap, fmt, std::string (), 
+                                     dummy, value, doc);
+
+  if (nm != value_save_tag)
+    error ("lazy_index: corrupted data on load");
+  else
+    index = value.index_vector ();
+
+  return ! error_state;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/ov-lazy-idx.h	Tue Feb 16 15:28:53 2010 +0100
@@ -0,0 +1,263 @@
+/*
+
+Copyright (C) 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/>.
+
+*/
+
+#if !defined (octave_lazy_idx_h)
+#define octave_lazy_idx_h 1
+
+#include "ov-re-mat.h"
+
+// Lazy indices that stay in idx_vector form until the conversion to NDArray is
+// actually needed.
+
+class
+OCTINTERP_API
+octave_lazy_index : public octave_base_value
+{
+public:
+
+  octave_lazy_index (void)
+    : octave_base_value () { }
+
+  octave_lazy_index (const idx_vector& idx)
+    : octave_base_value (), index (idx) { } 
+
+  octave_lazy_index (const octave_lazy_index& i)
+    : octave_base_value (), index (i.index), value (i.value) { } 
+
+  ~octave_lazy_index (void) { }
+
+  octave_base_value *clone (void) const { return new octave_lazy_index (*this); }
+  octave_base_value *empty_clone (void) const { return new octave_matrix (); }
+
+  type_conv_info numeric_conversion_function (void) const;
+
+  octave_base_value *try_narrowing_conversion (void);
+
+  size_t byte_size (void) const { return numel () * sizeof (octave_idx_type); }
+
+  // FIXME: should avoid conversion.
+  octave_value squeeze (void) const { return make_value ().squeeze (); }
+
+  octave_value full_value (void) const { return make_value (); }
+
+  idx_vector index_vector (void) const
+    { return index; }
+
+  builtin_type_t builtin_type (void) const { return btyp_double; }
+
+  bool is_real_matrix (void) const { return true; }
+
+  bool is_real_type (void) const { return true; }
+
+  bool is_double_type (void) const { return true; }
+
+  bool is_float_type (void) const { return true; }
+
+  octave_value subsref (const std::string& type,
+                        const std::list<octave_value_list>& idx)
+    { return make_value ().subsref (type, idx); }
+
+  octave_value_list subsref (const std::string& type,
+                             const std::list<octave_value_list>& idx, int)
+    { return subsref (type, idx); }
+
+  octave_value subsasgn (const std::string& type,
+                         const std::list<octave_value_list>& idx,
+                         const octave_value& rhs)
+    { return make_value ().subsasgn (type, idx, rhs); }
+
+  octave_value do_index_op (const octave_value_list& idx,
+                            bool resize_ok = false)
+    { return make_value ().do_index_op (idx, resize_ok); }
+
+  dim_vector dims (void) const { return index.orig_dimensions (); }
+
+  octave_idx_type numel (void) const { return index.length (0); }
+
+  octave_idx_type nnz (void) const { return numel (); }
+
+  // FIXME: should avoid conversion.
+  octave_value reshape (const dim_vector& new_dims) const
+    { return make_value ().reshape (new_dims); }
+
+  octave_value permute (const Array<int>& vec, bool inv = false) const
+    { return make_value ().permute (vec, inv); }
+
+  octave_value resize (const dim_vector& dv, bool fill = false) const
+    { return make_value ().resize (dv, fill); }
+
+  octave_value all (int dim = 0) const { return make_value ().all (dim); }
+  octave_value any (int dim = 0) const { return make_value ().any (dim); }
+
+  MatrixType matrix_type (void) const { return make_value ().matrix_type (); }
+  MatrixType matrix_type (const MatrixType& _typ) const
+    { return make_value ().matrix_type (_typ); }
+
+  // FIXME: should avoid conversion.
+  sortmode is_sorted (sortmode mode = UNSORTED) const
+    { return make_value ().is_sorted (mode); }
+
+  Array<octave_idx_type> sort_rows_idx (sortmode mode = ASCENDING) const
+    { return make_value ().sort_rows_idx (mode); }
+
+  sortmode is_sorted_rows (sortmode mode = UNSORTED) const
+    { return make_value ().is_sorted_rows (mode); }
+
+  bool is_matrix_type (void) const { return true; }
+
+  bool is_numeric_type (void) const { return true; }
+
+  bool is_defined (void) const { return true; }
+
+  bool is_constant (void) const { return true; }
+
+  bool is_true (void) const
+    { return make_value ().is_true (); }
+
+  bool print_as_scalar (void) const
+    { return make_value ().print_as_scalar (); }
+
+  void print (std::ostream& os, bool pr_as_read_syntax = false) const
+    { make_value ().print (os, pr_as_read_syntax); }
+
+  void print_info (std::ostream& os, const std::string& prefix) const
+    { make_value ().print_info (os, prefix); }
+
+#define FORWARD_VALUE_QUERY(TYPE,NAME) \
+  TYPE \
+  NAME (void) const { return make_value ().NAME (); }
+
+  FORWARD_VALUE_QUERY (int8NDArray,  int8_array_value)
+  FORWARD_VALUE_QUERY (int16NDArray, int16_array_value)
+  FORWARD_VALUE_QUERY (int32NDArray, int32_array_value)
+  FORWARD_VALUE_QUERY (int64NDArray, int64_array_value)
+  FORWARD_VALUE_QUERY (uint8NDArray,  uint8_array_value)
+  FORWARD_VALUE_QUERY (uint16NDArray, uint16_array_value)
+  FORWARD_VALUE_QUERY (uint32NDArray, uint32_array_value)
+  FORWARD_VALUE_QUERY (uint64NDArray, uint64_array_value)
+
+#define FORWARD_VALUE_QUERY1(TYPE,NAME) \
+  TYPE \
+  NAME (bool flag = false) const { return make_value ().NAME (flag); }
+
+  FORWARD_VALUE_QUERY1 (double, double_value)
+
+  FORWARD_VALUE_QUERY1 (float, float_value)
+
+  FORWARD_VALUE_QUERY1 (double, scalar_value)
+
+  FORWARD_VALUE_QUERY1 (Matrix, matrix_value)
+
+  FORWARD_VALUE_QUERY1 (FloatMatrix, float_matrix_value)
+
+  FORWARD_VALUE_QUERY1 (Complex, complex_value)
+
+  FORWARD_VALUE_QUERY1 (FloatComplex, float_complex_value)
+
+  FORWARD_VALUE_QUERY1 (ComplexMatrix, complex_matrix_value)
+
+  FORWARD_VALUE_QUERY1 (FloatComplexMatrix, float_complex_matrix_value)
+
+  FORWARD_VALUE_QUERY1 (ComplexNDArray, complex_array_value)
+   
+  FORWARD_VALUE_QUERY1 (FloatComplexNDArray, float_complex_array_value)
+   
+  FORWARD_VALUE_QUERY1 (boolNDArray, bool_array_value)
+
+  FORWARD_VALUE_QUERY1 (charNDArray, char_array_value)
+  
+  FORWARD_VALUE_QUERY1 (NDArray, array_value)
+
+  FORWARD_VALUE_QUERY1 (FloatNDArray, float_array_value)
+
+  FORWARD_VALUE_QUERY1 (SparseMatrix, sparse_matrix_value)
+
+  FORWARD_VALUE_QUERY1 (SparseComplexMatrix, sparse_complex_matrix_value)
+
+  octave_value diag (octave_idx_type k = 0) const
+    { return make_value ().diag (k); }
+
+  octave_value sort (octave_idx_type dim = 0, sortmode mode = ASCENDING) const
+    { return make_value ().sort (dim, mode); }
+
+  octave_value sort (Array<octave_idx_type> &sidx, octave_idx_type dim = 0,
+                     sortmode mode = ASCENDING) const
+    { return make_value ().sort (sidx, dim, mode); }
+
+  octave_value convert_to_str_internal (bool pad, bool force, char type) const
+    { return make_value ().convert_to_str_internal (pad, force, type); }
+
+  void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const
+    { return make_value ().print_raw (os, pr_as_read_syntax); }
+
+  bool save_ascii (std::ostream& os);
+
+  bool load_ascii (std::istream& is);
+
+  bool save_binary (std::ostream& os, bool& save_as_floats);
+
+  bool load_binary (std::istream& is, bool swap, 
+                    oct_mach_info::float_format fmt);
+
+  // HDF5 functions not defined.
+
+  int write (octave_stream& os, int block_size,
+             oct_data_conv::data_type output_type, int skip,
+             oct_mach_info::float_format flt_fmt) const
+    { return make_value ().write (os, block_size, output_type, skip, flt_fmt); }
+
+  // Unsafe.  This function exists to support the MEX interface.
+  // You should not use it anywhere else.
+  void *mex_get_data (void) const 
+    { return make_value ().mex_get_data (); }
+
+  mxArray *as_mxArray (void) const
+    { return make_value ().as_mxArray (); }
+
+  octave_value map (unary_mapper_t umap) const
+    { return make_value ().map (umap); }
+
+private:
+  const octave_value& make_value (void) const
+    {
+      if (value.is_undefined ())
+        value = octave_value (index, false);
+
+      return value;
+    }
+
+  octave_value& make_value (void)
+    {
+      if (value.is_undefined ())
+        value = octave_value (index, false);
+
+      return value;
+    }
+
+  idx_vector index;
+  mutable octave_value value;
+
+  DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA
+};
+
+#endif
+
--- a/src/ov.cc	Mon Feb 15 08:55:46 2010 +0100
+++ b/src/ov.cc	Tue Feb 16 15:28:53 2010 +0100
@@ -74,6 +74,7 @@
 #include "ov-fcn-inline.h"
 #include "ov-typeinfo.h"
 #include "ov-null-mat.h"
+#include "ov-lazy-idx.h"
 
 #include "defun.h"
 #include "error.h"
@@ -1044,7 +1045,7 @@
   maybe_mutate ();
 }
 
-octave_value::octave_value (const idx_vector& idx)
+octave_value::octave_value (const idx_vector& idx, bool lazy)
   : rep ()
 {
   double scalar;
@@ -1053,6 +1054,21 @@
   boolNDArray mask;
   idx_vector::idx_class_type idx_class;
 
+  if (lazy)
+    {
+      // Only make lazy indices out of ranges and index vectors.
+      switch (idx.idx_class ())
+        {
+        case idx_vector::class_range:
+        case idx_vector::class_vector:
+          rep = new octave_lazy_index (idx);
+          maybe_mutate ();
+          return;
+        default:
+          break;
+        }
+    }
+
   idx.unconvert (idx_class, scalar, range, array, mask);
 
   switch (idx_class)
@@ -1135,8 +1151,7 @@
 octave_base_value *
 octave_value::clone (void) const
 {
-  panic_impossible ();
-  return 0;
+  return rep->clone ();
 }
 
 void
@@ -2653,6 +2668,7 @@
   octave_null_matrix::register_type ();
   octave_null_str::register_type ();
   octave_null_sq_str::register_type ();
+  octave_lazy_index::register_type ();
 }
 
 #if 0
--- a/src/ov.h	Mon Feb 15 08:55:46 2010 +0100
+++ b/src/ov.h	Tue Feb 16 15:28:53 2010 +0100
@@ -271,7 +271,7 @@
   octave_value (const Array<octave_idx_type>& inda, 
                 bool zero_based = false, bool cache_index = false);
   octave_value (const Array<std::string>& cellstr);
-  octave_value (const idx_vector& idx);
+  octave_value (const idx_vector& idx, bool lazy = true);
   octave_value (double base, double limit, double inc);
   octave_value (const Range& r);
   octave_value (const Octave_map& m);