diff src/ov-class.cc @ 9329:67fc970dad7d

improve indexed assignment using indexed numel
author Jaroslav Hajek <highegg@gmail.com>
date Wed, 10 Jun 2009 11:31:58 +0200
parents f27a8c07f0b2
children a76f391a3d02
line wrap: on
line diff
--- 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,