octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Make sparse automatic mutation to dense matrices optional


From: David Bateman
Subject: Make sparse automatic mutation to dense matrices optional
Date: Fri, 16 Nov 2007 00:05:45 +0100
User-agent: Thunderbird 1.5.0.7 (X11/20060921)

While looking at SeDuMi one issue I had was that much of the code
assumes that once a matrix is sparse it will stay that way and it so
SeDuMi just assumes that certain matrices are sparse in some of its
internal mex functions. Octave's habit of converting sparse matrices to
full ones if that saves space, plays havoc with this.

I therefore propose to include an internal variable Vsparse_auto_mutate
that can be used to enable or disable this functionality and that the
"-traditional" option turns this off as that is what matlab does.

Consider the attached patch.

D.
Index: src/octave.cc
===================================================================
RCS file: /usr/local/cvsroot/octave/src/octave.cc,v
retrieving revision 1.239
diff -u -r1.239 octave.cc
--- src/octave.cc       12 Oct 2007 21:27:31 -0000      1.239
+++ src/octave.cc       15 Nov 2007 22:52:05 -0000
@@ -517,6 +517,7 @@
                         "%%-- %D %I:%M %p --%%");
   bind_internal_variable ("page_screen_output", false);
   bind_internal_variable ("print_empty_dimensions", false);
+  bind_internal_variable ("sparse_auto_mutate", false);
 
   disable_warning ("Octave:fopen-file-in-path");
   disable_warning ("Octave:function-name-clash");
Index: src/ov-base.cc
===================================================================
RCS file: /usr/local/cvsroot/octave/src/ov-base.cc,v
retrieving revision 1.92
diff -u -r1.92 ov-base.cc
--- src/ov-base.cc      12 Oct 2007 21:27:31 -0000      1.92
+++ src/ov-base.cc      15 Nov 2007 22:52:05 -0000
@@ -65,6 +65,10 @@
 // semicolon has been appended to each statement).
 static bool Vsilent_functions = false;
 
+// TRUE means to perform automatic sparse to real mutation if there
+// is memory to be saved
+bool Vsparse_auto_mutate = true;
+
 octave_value
 octave_base_value::squeeze (void) const
 {
@@ -1131,6 +1135,30 @@
   return SET_INTERNAL_VARIABLE (silent_functions);
 }
 
+DEFUN (sparse_auto_mutate, args, nargout,
+  "-*- texinfo -*-\n\
address@hidden {Built-in Function} address@hidden =} sparse_auto_mutate ()\n\
address@hidden {Built-in Function} address@hidden =} sparse_auto_mutate 
(@var{new_val})\n\
+Query or set the internal variable that controls whether Octave will\n\
+automatically mutate sparse matrices to real matrices to save memory.\n\
+For example,\n\
+\n\
address@hidden
+s = speye(3);\n\
+sparse_auto_mutate (false)\n\
+s (:, 1) = 1;\n\
+typeinfo (s)\n\
address@hidden sparse matrix\n\
+sparse_auto_mutate (true)\n\
+s (1, :) = 1;\n\
+typeinfo (s)\n\
address@hidden matrix\n\
address@hidden example\n\
address@hidden deftypefn")
+{
+  return SET_INTERNAL_VARIABLE (sparse_auto_mutate);
+}
+
 /*
 ;;; Local Variables: ***
 ;;; mode: C++ ***
Index: src/ov-base.h
===================================================================
RCS file: /usr/local/cvsroot/octave/src/ov-base.h,v
retrieving revision 1.108
diff -u -r1.108 ov-base.h
--- src/ov-base.h       25 Oct 2007 06:57:17 -0000      1.108
+++ src/ov-base.h       15 Nov 2007 22:52:06 -0000
@@ -487,6 +487,10 @@
   DECLARE_OV_BASE_TYPEID_FUNCTIONS_AND_DATA
 };
 
+// TRUE means to perform automatic sparse to real mutation if there
+// is memory to be saved
+extern bool Vsparse_auto_mutate;
+
 #endif
 
 /*
Index: src/ov-bool-sparse.cc
===================================================================
RCS file: /usr/local/cvsroot/octave/src/ov-bool-sparse.cc,v
retrieving revision 1.26
diff -u -r1.26 ov-bool-sparse.cc
--- src/ov-bool-sparse.cc       12 Oct 2007 21:27:31 -0000      1.26
+++ src/ov-bool-sparse.cc       15 Nov 2007 22:52:06 -0000
@@ -69,20 +69,23 @@
 {
   octave_base_value *retval = 0;
 
-  // Don't use numel, since it can overflow for very large matrices
-  // Note that for the second test, this means it becomes approximative
-  // since it involves a cast to double to avoid issues of overflow
-  if (matrix.rows () == 1 && matrix.cols () == 1)
-    {
-      // Const copy of the matrix, so the right version of () operator used
-      const SparseBoolMatrix tmp (matrix);
-
-      retval = new octave_bool (tmp (0));
-    }
-  else if (matrix.cols () > 0 && matrix.rows () > 0 && 
-          double (matrix.byte_size ()) > double (matrix.rows ()) *
-          double (matrix.cols ()) * sizeof (bool))
-    retval = new octave_bool_matrix (matrix.matrix_value ());
+  if (Vsparse_auto_mutate)
+    {
+      // Don't use numel, since it can overflow for very large matrices
+      // Note that for the second test, this means it becomes approximative
+      // since it involves a cast to double to avoid issues of overflow
+      if (matrix.rows () == 1 && matrix.cols () == 1)
+       {
+         // Const copy of the matrix, so the right version of () operator used
+         const SparseBoolMatrix tmp (matrix);
+
+         retval = new octave_bool (tmp (0));
+       }
+      else if (matrix.cols () > 0 && matrix.rows () > 0 && 
+              double (matrix.byte_size ()) > double (matrix.rows ()) *
+              double (matrix.cols ()) * sizeof (bool))
+       retval = new octave_bool_matrix (matrix.matrix_value ());
+    }
 
   return retval;
 }
Index: src/ov-cx-sparse.cc
===================================================================
RCS file: /usr/local/cvsroot/octave/src/ov-cx-sparse.cc,v
retrieving revision 1.21
diff -u -r1.21 ov-cx-sparse.cc
--- src/ov-cx-sparse.cc 12 Oct 2007 21:27:31 -0000      1.21
+++ src/ov-cx-sparse.cc 15 Nov 2007 22:52:06 -0000
@@ -54,37 +54,45 @@
 {
   octave_base_value *retval = 0;
 
-  int nr = matrix.rows ();
-  int nc = matrix.cols ();
-
-  // Don't use numel, since it can overflow for very large matrices
-  // Note that for the tests on matrix size, they become approximative
-  // since they involves a cast to double to avoid issues of overflow
-  if (matrix.rows () == 1 && matrix.cols () == 1)
+  if (Vsparse_auto_mutate)
     {
-      // Const copy of the matrix, so the right version of () operator used
-      const SparseComplexMatrix tmp (matrix);
+      int nr = matrix.rows ();
+      int nc = matrix.cols ();
+
+      // Don't use numel, since it can overflow for very large matrices
+      // Note that for the tests on matrix size, they become approximative
+      // since they involves a cast to double to avoid issues of overflow
+      if (matrix.rows () == 1 && matrix.cols () == 1)
+       {
+         // Const copy of the matrix, so the right version of () operator used
+         const SparseComplexMatrix tmp (matrix);
 
-      Complex c = tmp (0, 0);
+         Complex c = tmp (0, 0);
 
-      if (imag (c) == 0.0)
-       retval = new octave_scalar (std::real (c));
-      else
-       retval = new octave_complex (c);
+         if (imag (c) == 0.0)
+           retval = new octave_scalar (std::real (c));
+         else
+           retval = new octave_complex (c);
+       }
+      else if (nr == 0 || nc == 0)
+       retval = new octave_matrix (Matrix (nr, nc));
+      else if (matrix.all_elements_are_real ())
+       if (matrix.cols () > 0 && matrix.rows () > 0 && 
+           double (matrix.byte_size ()) > double (matrix.rows ()) *
+           double (matrix.cols ()) * sizeof (double))
+         retval = new octave_matrix (::real (matrix.matrix_value ()));
+       else
+         retval = new octave_sparse_matrix (::real (matrix));
+      else if (matrix.cols () > 0 && matrix.rows () > 0 && 
+              double (matrix.byte_size ()) > double (matrix.rows ()) *
+              double (matrix.cols ()) * sizeof (Complex))
+       retval = new octave_complex_matrix (matrix.matrix_value ());
+    }
+  else
+    {
+      if (matrix.all_elements_are_real ())
+       retval = new octave_sparse_matrix (::real (matrix));
     }
-  else if (nr == 0 || nc == 0)
-    retval = new octave_matrix (Matrix (nr, nc));
-  else if (matrix.all_elements_are_real ())
-    if (matrix.cols () > 0 && matrix.rows () > 0 && 
-       double (matrix.byte_size ()) > double (matrix.rows ()) *
-       double (matrix.cols ()) * sizeof (double))
-      retval = new octave_matrix (::real (matrix.matrix_value ()));
-    else
-      retval = new octave_sparse_matrix (::real (matrix));
-  else if (matrix.cols () > 0 && matrix.rows () > 0 && 
-          double (matrix.byte_size ()) > double (matrix.rows ()) *
-          double (matrix.cols ()) * sizeof (Complex))
-    retval = new octave_complex_matrix (matrix.matrix_value ());
     
   return retval;
 }
Index: src/ov-re-sparse.cc
===================================================================
RCS file: /usr/local/cvsroot/octave/src/ov-re-sparse.cc,v
retrieving revision 1.24
diff -u -r1.24 ov-re-sparse.cc
--- src/ov-re-sparse.cc 12 Oct 2007 21:27:32 -0000      1.24
+++ src/ov-re-sparse.cc 15 Nov 2007 22:52:06 -0000
@@ -67,20 +67,23 @@
 {
   octave_base_value *retval = 0;
 
-  // Don't use numel, since it can overflow for very large matrices
-  // Note that for the second test, this means it becomes approximative
-  // since it involves a cast to double to avoid issues of overflow
-  if (matrix.rows () == 1 && matrix.cols () == 1)
-    {
-      // Const copy of the matrix, so the right version of () operator used
-      const SparseMatrix tmp (matrix);
-
-      retval = new octave_scalar (tmp (0));
-    }
-  else if (matrix.cols () > 0 && matrix.rows () > 0 && 
-          double (matrix.byte_size ()) > double (matrix.rows ()) *
-          double (matrix.cols ()) * sizeof (double))
-    retval = new octave_matrix (matrix.matrix_value ());
+  if (Vsparse_auto_mutate)
+    {
+      // Don't use numel, since it can overflow for very large matrices
+      // Note that for the second test, this means it becomes approximative
+      // since it involves a cast to double to avoid issues of overflow
+      if (matrix.rows () == 1 && matrix.cols () == 1)
+       {
+         // Const copy of the matrix, so the right version of () operator used
+         const SparseMatrix tmp (matrix);
+
+         retval = new octave_scalar (tmp (0));
+       }
+      else if (matrix.cols () > 0 && matrix.rows () > 0 && 
+              double (matrix.byte_size ()) > double (matrix.rows ()) *
+              double (matrix.cols ()) * sizeof (double))
+       retval = new octave_matrix (matrix.matrix_value ());
+    }
 
   return retval;
 }
2007-11-15  David Bateman  <address@hidden>

        * ov_base.cc (Vsparse_auto_mutate, Fsparse_auto_mutate): New
        internal variable and built-in function to set it.
        * ov_base.h (extern bool Vsparse_auto_mutate): Export internal
        variable to other functions.
        * ov-re-sparse.cc (octave_sparse_matrix::try_narrowing_conversion
        (void)), ov-cx-sparse.cc 
        (octave_sparse_complex_matrix::try_narrowing_conversion (void)), 
        ov-bool-sparse.cc
        (octave_sparse_bool_matrix::try_narrowing_conversion (void)):
        Use Vsparse_auto_mutate flag to determine whether to convert
        sparse matrices to full matrices if that saves space.
        * octave.cc (maximum_braindamage): Also clear sparse_auto_mutate.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]