changeset 9329:67fc970dad7d

improve indexed assignment using indexed numel
author Jaroslav Hajek <highegg@gmail.com>
date Wed, 10 Jun 2009 11:31:58 +0200
parents 0307f5e5568c
children e903c92d2f02
files ChangeLog src/ChangeLog src/data.cc src/ov-base.cc src/ov-base.h src/ov-class.cc src/ov-class.h src/ov.cc src/ov.h src/pt-idx.cc
diffstat 10 files changed, 222 insertions(+), 184 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Jun 10 20:33:10 2009 -0400
+++ b/ChangeLog	Wed Jun 10 11:31:58 2009 +0200
@@ -1,3 +1,7 @@
+2009-06-11  Jaroslav Hajek  <highegg@gmail.com>
+
+	* example/@polynomial/numel.m: New method.
+
 2009-05-22 Benjamin Lindner <lindnerb@users.sourceforge.net>
 
 	* mkoctfile.cc.in: mask MSVC specific linker flags for mex output
--- a/src/ChangeLog	Wed Jun 10 20:33:10 2009 -0400
+++ b/src/ChangeLog	Wed Jun 10 11:31:58 2009 +0200
@@ -1,3 +1,16 @@
+2009-06-10  Jaroslav Hajek  <highegg@gmail.com>
+
+	* ov-base.cc (octave_base_value::numel (const octave_value_list&),
+	octave_base_value::size): New virtual methods.
+	* ov-base.h: Declare them.
+	* ov.h (octave_value::numel (const octave_value_list&)): New method.
+	(octave_value::size): Forward to octave_base_value.
+	* ov-class.cc (octave_class::numel (const octave_value_list&),
+	octave_base_value::size): New method overrides.
+	* ov-class.h: Declare them.
+	* pt-idx.cc (tree_index_expression::lvalue): Rewrite.
+	* data.cc (Fnumel): Allow indexed query.
+
 2009-06-10  John W. Eaton  <jwe@octave.org>
 
 	* pt-fcn-handle.cc (tree_anon_fcn_handle::dup): Don't convert to
--- a/src/data.cc	Wed Jun 10 20:33:10 2009 -0400
+++ b/src/data.cc	Wed Jun 10 11:31:58 2009 +0200
@@ -2334,18 +2334,14 @@
 @end deftypefn")
 {
   octave_value retval;
-
-  if (args.length () == 1)
+  octave_idx_type nargin = args.length ();
+
+  if (nargin >= 1)
     {
-      int numel = args(0).numel ();
+      octave_idx_type numel = args(0).numel (args.slice (1, nargin-1));
 
       if (! error_state)
-	{
-	  if (numel < 0)
-	    numel = 0;
-
 	  retval = numel;
-	}
     }
   else
     print_usage ();
--- a/src/ov-base.cc	Wed Jun 10 20:33:10 2009 -0400
+++ b/src/ov-base.cc	Wed Jun 10 11:31:58 2009 +0200
@@ -76,6 +76,41 @@
   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)
+{
+  octave_idx_type retval;
+
+  octave_idx_type len = idx.length ();
+
+  if (len == 0)
+    retval = numel ();
+  else
+    {
+      const dim_vector dv = dims ().redim (len);
+      retval = 1;
+      for (octave_idx_type i = 0; i < len; i++)
+        {
+          if (idx(i).is_magic_colon ())
+            retval *= dv(i);
+          else
+            retval *= idx(i).numel ();
+        }
+    }
+
+  return retval;
+}
+
 octave_value
 octave_base_value::subsref (const std::string&,
 			    const std::list<octave_value_list>&)
--- a/src/ov-base.h	Wed Jun 10 20:33:10 2009 -0400
+++ b/src/ov-base.h	Wed Jun 10 11:31:58 2009 +0200
@@ -151,6 +151,10 @@
 
   virtual void maybe_economize (void) { }
 
+  virtual Matrix size (void); 
+
+  virtual octave_idx_type numel (const octave_value_list&);
+
   virtual octave_value
   subsref (const std::string& type,
 	   const std::list<octave_value_list>& idx);
--- a/src/ov-class.cc	Wed Jun 10 20:33:10 2009 -0400
+++ b/src/ov-class.cc	Wed Jun 10 11:31:58 2009 +0200
@@ -29,6 +29,7 @@
 #include "Array-util.h"
 #include "byte-swap.h"
 #include "oct-locbuf.h"
+#include "lo-mappers.h"
 
 #include "Cell.h"
 #include "defun.h"
@@ -275,6 +276,90 @@
   return (fcn && fcn->name () == "builtin");
 }
 
+Matrix
+octave_class::size (void)
+{
+  Matrix retval (1, 2, 1.0);
+  octave_value meth = symbol_table::find_method ("size", class_name ());
+
+  if (meth.is_defined ())
+    {
+      count++;
+      octave_value_list args (1, octave_value (this));
+
+      octave_value_list lv = feval (meth.function_value (), args, 1);
+      if (lv.length () == 1 && lv(0).is_matrix_type () && lv(0).dims ().is_vector ())
+        retval = lv(0).matrix_value ();
+      else
+        error ("@%s/size: invalid return value");
+    }
+
+  return retval;
+}
+
+octave_idx_type
+octave_class::numel (const octave_value_list& idx)
+{
+  octave_idx_type retval = -1;
+  const std::string cn = class_name ();
+
+  octave_value meth = symbol_table::find_method ("numel", cn);
+
+  if (meth.is_defined ())
+    {
+      octave_value_list args (idx.length () + 1, octave_value ());
+
+      count++;
+      args(0) = octave_value (this);
+
+      for (octave_idx_type i = 0; i < idx.length (); i++)
+        args(i+1) = idx(i);
+
+      octave_value_list lv = feval (meth.function_value (), args, 1);
+      if (lv.length () == 1 && lv(0).is_scalar_type ())
+        retval = lv(0).idx_type_value (true);
+      else
+        error ("@%s/numel: invalid return value", cn.c_str ());
+    }
+  else
+    {
+      // If method is not found, calculate using size ().
+      const Matrix mdv = size ();
+      octave_idx_type nmdv = mdv.numel ();
+      dim_vector dv; dv.resize (std::max (nmdv, 2));
+      for (octave_idx_type i = 0; i < nmdv && !error_state; i++)
+        {
+          if (mdv(i) == xround (mdv(i)) && xfinite (mdv(i)) && mdv(i) >= 0)
+            dv(i) = mdv(i);
+          else
+            error ("@%s/numel: expected nonnegative integers from @%s/size",
+                   cn.c_str (), cn.c_str ());
+        }
+
+      if (! error_state)
+        {
+          octave_idx_type len = idx.length ();
+          if (len == 0)
+            retval = dv.numel ();
+          else
+            {
+              dv = dv.redim (len);
+              retval = 1;
+              for (octave_idx_type i = 0; i < len; i++)
+                {
+                  if (idx(i).is_magic_colon ())
+                    retval *= dv(i);
+                  else
+                    retval *= idx(i).numel ();
+                }
+            }
+        }
+
+    }
+
+  return retval;
+}
+
 octave_value_list
 octave_class::subsref (const std::string& type,
 		       const std::list<octave_value_list>& idx,
--- a/src/ov-class.h	Wed Jun 10 20:33:10 2009 -0400
+++ b/src/ov-class.h	Wed Jun 10 11:31:58 2009 +0200
@@ -72,6 +72,10 @@
 
   Cell dotref (const octave_value_list& idx);
 
+  Matrix size (void);
+
+  octave_idx_type numel (const octave_value_list&); 
+
   octave_value subsref (const std::string& type,
 			const std::list<octave_value_list>& idx)
     {
--- a/src/ov.cc	Wed Jun 10 20:33:10 2009 -0400
+++ b/src/ov.cc	Wed Jun 10 11:31:58 2009 +0200
@@ -1246,21 +1246,6 @@
   return retval;
 }
 
-Matrix
-octave_value::size (void) const
-{
-  dim_vector dv = dims ();
-
-  int n_dims = dv.length ();
-
-  Matrix retval (1, n_dims);
-
-  while (n_dims--)
-    retval(n_dims) = dv(n_dims);
-
-  return retval;
-}
-
 bool
 octave_value::is_equal (const octave_value& test) const
 {
--- a/src/ov.h	Wed Jun 10 20:33:10 2009 -0400
+++ b/src/ov.h	Wed Jun 10 11:31:58 2009 +0200
@@ -354,6 +354,13 @@
   octave_base_value *try_narrowing_conversion (void)
     { return rep->try_narrowing_conversion (); }
 
+  // Close to dims (), but can be overloaded for classes.
+  Matrix size (void)
+    { return rep->size (); }
+
+  octave_idx_type numel (const octave_value_list& idx)
+    { return rep->numel (idx); }
+
   octave_value single_subsref (const std::string& type,
 			       const octave_value_list& idx);
 
@@ -424,8 +431,6 @@
   octave_idx_type capacity (void) const
     { return rep->capacity (); }
 
-  Matrix size (void) const;
-
   size_t byte_size (void) const
     { return rep->byte_size (); }
 
--- a/src/pt-idx.cc	Wed Jun 10 20:33:10 2009 -0400
+++ b/src/pt-idx.cc	Wed Jun 10 11:31:58 2009 +0200
@@ -409,6 +409,7 @@
   octave_lvalue retval;
 
   std::list<octave_value_list> idx;
+  std::string tmp_type;
 
   int n = args.size ();
 
@@ -420,16 +421,13 @@
 
   if (! error_state)
     {
-      // I think it is OK to have a copy here.
-
       const octave_value *tro = retval.object ();
 
-      octave_value first_retval_object;
+      octave_value tmp;
 
       if (tro)
-	first_retval_object = *tro;
+	tmp = *tro;
 
-      octave_value tmp = first_retval_object;
       octave_idx_type tmpi = 0;
       std::list<octave_value_list> tmpidx;
 
@@ -437,45 +435,14 @@
 	{
           if (retval.numel () != 1)
             gripe_indexed_cs_list ();
-
-          if (i > 0)
+          else if (tmpi < i)
             {
-              tree_argument_list *al = *p_args;
-
-              if (al && al->has_magic_end ())
-                {
-                  // We have an expression like
-                  //
-                  //   x{end}.a(end)
-                  //
-                  // and we are looking at the argument list that
-                  // contains the second (or third, etc.) "end" token,
-                  // so we must evaluate everything up to the point of
-                  // that argument list so we pass the appropriate
-                  // value to the built-in __end__ function.
+              tmp = tmp.subsref (type.substr (tmpi, i - tmpi), tmpidx, true);
+              tmpidx.clear ();
+            }
 
-                  if (tmp.is_defined ())
-                    {
-                      if (tmpi < i)
-                        {
-                          tmp = tmp.subsref (type.substr (tmpi, i - tmpi), tmpidx, true);
-
-                          tmpi = i;
-                          tmpidx.clear ();
-                        }
-                    }
-                  else
-                    gripe_invalid_inquiry_subscript ();
-
-                  if (tmp.is_undefined ())
-                    gripe_invalid_inquiry_subscript ();
-                  else if (tmp.is_cs_list ())
-                    gripe_indexed_cs_list ();
-
-                  if (error_state)
-                    break;
-                }
-            }
+          if (error_state)
+            break;
 
 	  switch (type[i])
 	    {
@@ -483,8 +450,19 @@
               {
                 octave_value_list tidx
                   = make_value_list (*p_args, *p_arg_nm, &tmp);
+
                 idx.push_back (tidx);
-                tmpidx.push_back (tidx);
+
+                if (i < n - 1)
+                  {
+                    if (type[i+1] == '.')
+                      {
+                        tmpidx.push_back (tidx);
+                        tmpi = i+1;
+                      }
+                    else
+                      error ("() must be followed by . or close the index chain");
+                  }
               }
               break;
 
@@ -493,60 +471,27 @@
 		octave_value_list tidx
 		  = make_value_list (*p_args, *p_arg_nm, &tmp);
 
-		if (! tidx.all_scalars ())
-		  {
-                    octave_idx_type nel = 1;
-
-                    octave_idx_type nidx = tidx.length ();
-
-                    // Possible cs-list.
-                    bool has_magic_colon = tidx.has_magic_colon ();
-                    dim_vector dims;
-
-		    if (has_magic_colon)
-		      {
-                        if (tmp.is_defined ())
-                          {
-                            if (tmpi < i)
-                              {
-                                tmp = tmp.subsref (type.substr (tmpi, i - tmpi), tmpidx, true);
-                                tmpi = i;
-                                tmpidx.clear ();
-                              }
+                if (tmp.is_undefined ())
+                  {
+                    if (tidx.has_magic_colon ())
+                      gripe_invalid_inquiry_subscript ();
+                    else
+                      tmp = Cell ();
+                  }
+                else if (tmp.is_zero_by_zero () 
+                         && (tmp.is_matrix_type () || tmp.is_string ()))
+                  {
+                    tmp = Cell ();
+                  }
 
-                            if (tmp.is_undefined ())
-                              gripe_invalid_inquiry_subscript ();
-                            else if (tmp.is_cs_list ())
-                              gripe_indexed_cs_list ();
-
-                            dims = (nidx == 1) ? dim_vector (tmp.numel (), 1) : tmp.dims ();
-                          }
-                        else
-                          gripe_invalid_inquiry_subscript ();
-
-                        if (error_state)
-                          break;
-                      }
-
-                    for (octave_idx_type j = 0; j < nidx; j++)
-                      {
-                        octave_value val = tidx(j);
-
-                        if (val.is_magic_colon ())
-                          nel *= dims (j);
-                        else
-                          nel *= val.numel ();
-                      }
-
-                    retval.numel (nel);
-		  }
+                retval.numel (tmp.numel (tidx));
 
                 if (error_state)
                   break;
 
 		idx.push_back (tidx);
                 tmpidx.push_back (tidx);
-
+                tmpi = i;
 	      }
 	      break;
 
@@ -556,90 +501,49 @@
                 if (error_state)
                   break;
 
+                bool autoconv = (tmp.is_zero_by_zero () 
+                                 && (tmp.is_matrix_type () || tmp.is_string ()
+                                     || tmp.is_cell ()));
+
                 if (i > 0 && type [i-1] == '(')
                   {
-                    // Possible cs-list.
-
-                    octave_value_list xidx = idx.back ();
-
-                    if (! xidx.all_scalars ())
-                      {
-                        octave_idx_type nel = 1;
-
-                        octave_idx_type nidx = xidx.length ();
-
-                        // Possible cs-list.
-                        bool has_magic_colon = xidx.has_magic_colon ();
-                        dim_vector dims;
+                    octave_value_list pidx = idx.back ();
 
-                        if (has_magic_colon)
-                          {
-                            // Evaluate everything up to the point preceding the last paren.
-                            if (tmp.is_defined ())
-                              {
-                                if (tmpi < i-1)
-                                  {
-                                    tmpidx.pop_back ();
-                                    tmp = tmp.subsref (type.substr (tmpi, i-1 - tmpi), tmpidx, true);
-                                    tmpi = i - 1;
-                                    tmpidx.clear ();
-                                    tmpidx.push_back (xidx);
-                                  }
-
-                                if (tmp.is_undefined ())
-                                  gripe_invalid_inquiry_subscript ();
-                                else if (tmp.is_cs_list ())
-                                  gripe_indexed_cs_list ();
+                    if (tmp.is_undefined ())
+                      {
+                        if (pidx.has_magic_colon ())
+                          gripe_invalid_inquiry_subscript ();
+                        else
+                          tmp = Octave_map ();
+                      }
+                    else if (autoconv)
+                      tmp = Octave_map ();
 
-                                dims = (nidx == 1) ? dim_vector (tmp.numel (), 1) : tmp.dims ();
-                              }
-                            else
-                              gripe_invalid_inquiry_subscript ();
-
-                            if (error_state)
-                              break;
-                          }
+                    retval.numel (tmp.numel (pidx));
 
-                        for (octave_idx_type j = 0; j < nidx; j++)
-                          {
-                            octave_value val = xidx(j);
-
-                            if (val.is_magic_colon ())
-                              nel *= dims (j);
-                            else
-                              nel *= val.numel ();
-                          }
-
-                        retval.numel (nel);
-                      }
+                    tmpi = i-1;
+                    tmpidx.push_back (tidx);
                   }
                 else
                   {
-                    // A plain struct component can also yield a list reference.
-                    if (tmp.is_defined () && tmpi < i)
-                        tmp = tmp.subsref (type.substr (tmpi, i - tmpi), tmpidx, true);
-
-                    tmpi = i;
-                    tmpidx.clear ();
+                    if (tmp.is_undefined () || autoconv)
+                      {
+                        tmpi = i+1;
+                        tmp = octave_value ();
+                      }
+                    else
+                      {
+                        retval.numel (tmp.numel (octave_value_list ()));
 
-                    if (tmp.is_cs_list ())
-                      gripe_indexed_cs_list ();
-                    else if (tmp.is_map ())
-                      retval.numel (tmp.numel ());
-                    else
-                      tmp = Octave_map ();
-
-                    if (error_state)
-                      break;
-
+                        tmpi = i;
+                        tmpidx.push_back (tidx);
+                      }
                   }
 
                 if (error_state)
                   break;
 
                 idx.push_back (tidx);
-                tmpidx.push_back (tidx);
-
 	      }
 	      break;
 
@@ -647,6 +551,9 @@
 	      panic_impossible ();
 	    }
 
+          if (idx.back ().empty ())
+            error ("invalid empty index list");
+
 	  if (error_state)
 	    break;