diff src/DLD-FUNCTIONS/chol.cc @ 7515:f3c00dc0912b

Eliminate the rest of the dispatched sparse functions
author David Bateman <dbateman@free.fr>
date Fri, 22 Feb 2008 15:50:51 +0100
parents a1dbe9d80eee
children 40574114c514
line wrap: on
line diff
--- a/src/DLD-FUNCTIONS/chol.cc	Fri Feb 22 13:47:38 2008 -0500
+++ b/src/DLD-FUNCTIONS/chol.cc	Fri Feb 22 15:50:51 2008 +0100
@@ -27,7 +27,13 @@
 
 #include "CmplxCHOL.h"
 #include "dbleCHOL.h"
+#include "SparseCmplxCHOL.h"
+#include "SparsedbleCHOL.h"
+#include "oct-spparms.h"
+#include "sparse-util.h"
 
+#include "ov-re-sparse.h"
+#include "ov-cx-sparse.h"
 #include "defun-dld.h"
 #include "error.h"
 #include "gripes.h"
@@ -36,7 +42,11 @@
 
 DEFUN_DLD (chol, args, nargout,
   "-*- texinfo -*-\n\
-@deftypefn {Loadable Function} {} chol (@var{a})\n\
+@deftypefn {Loadable Function} {@var{r}} = chol (@var{a})\n\
+@deftypefnx {Loadable Function} {[@var{r}, @var{p}]} = chol (@var{a})\n\
+@deftypefnx {Loadable Function} {[@var{r}, @var{p}, @var{q}]} = chol (@var{s})\n\
+@deftypefnx {Loadable Function} {[@var{r}, @var{p}, @var{q}]} = chol (@var{s}, 'vector')\n\
+@deftypefnx {Loadable Function} {[@var{l}, @dots{}]} = chol (@dots{}, 'lower')\n\
 @cindex Cholesky factorization\n\
 Compute the Cholesky factor, @var{r}, of the symmetric positive definite\n\
 matrix @var{a}, where\n\
@@ -48,72 +58,216 @@
 @ifinfo\n\
 \n\
 @example\n\
-r' * r = a.\n\
+@var{r}' * @var{r} = @var{a}.\n\
+@end example\n\
+@end ifinfo\n\
+\n\
+Called with one output argument @code{chol} fails if @var{a} or @var{s} is\n\
+not positive definite. With two or more output arguments @var{p} flags\n\
+whether the matrix was positive definite and @code{chol} does not fail. A\n\
+zero value indicated that the matrix was positive definite and the @var{r}\n\
+gives the factorization, annd @var{p} will have a positive value otherwise.\n\
+\n\
+If called with 3 outputs then a sparsity preserving row/column permutation\n\
+is applied to @var{a} prior to the factorization. That is @var{r}\n\
+is the factorization of @code{@var{a}(@var{q},@var{q})} such that\n\
+@iftex\n\
+@tex\n\
+$ R^T R = Q^T A Q$.\n\
+@end tex\n\
+@end iftex\n\
+@ifinfo\n\
+\n\
+@example\n\
+@var{r}' * @var{r} = @var{q}' * @var{a} * @var{q}.\n\
 @end example\n\
 @end ifinfo\n\
+\n\
+The sparsity preserving permutation is generally returned as a matrix.\n\
+However, given the flag 'vector', @var{q} will be returned as a vector\n\
+such that\n\
+@iftex\n\
+@tex\n\
+$ R^T R = A (Q, Q)$.\n\
+@end tex\n\
+@end iftex\n\
+@ifinfo\n\
+\n\
+@example\n\
+@var{r}' * @var{r} = a (@var{q}, @var{q}).\n\
+@end example\n\
+@end ifinfo\n\
+\n\
+Called with either a sparse or full matrix and uing the 'lower' flag,\n\
+@code{chol} returns the lower triangular factorization such that\n\
+@iftex\n\
+@tex\n\
+$ L L^T = A $.\n\
+@end tex\n\
+@end iftex\n\
+@ifinfo\n\
+\n\
+@example\n\
+@var{l} * @var{l}' = @var{a}.\n\
+@end example\n\
+@end ifinfo\n\
+\n\
+In general the lower trinagular factorization is significantly faster for\n\
+sparse matrices.\n\
 @seealso{cholinv, chol2inv}\n\
 @end deftypefn")
 {
   octave_value_list retval;
+  int nargin = args.length ();
+  bool LLt = false;
+  bool vecout = false;
 
-  int nargin = args.length ();
-
-  if (nargin != 1 || nargout > 2)
+  if (nargin < 1 || nargin > 3 || nargout > 3 
+      || (! args(0).is_sparse_type () && nargout > 2))
     {
       print_usage ();
       return retval;
     }
 
-  octave_value arg = args(0);
-    
-  octave_idx_type nr = arg.rows ();
-  octave_idx_type nc = arg.columns ();
+  int n = 1;
+  while (n < nargin && ! error_state)
+    {
+      std::string tmp = args(n++).string_value ();
+
+      if (! error_state )
+	{
+	  if (tmp.compare ("vector") == 0)
+	    vecout = true;
+	  else if (tmp.compare ("lower") == 0)
+	    LLt = true;
+	  else if (tmp.compare ("upper") == 0)
+	    LLt = false;
+	  else
+	    error ("chol: unexpected second or third input");
+	}
+      else
+	error ("chol: expecting trailing string arguments");
+    }
 
-  int arg_is_empty = empty_arg ("chol", nr, nc);
+  if (! error_state)
+    {
+      octave_value arg = args(0);
+    
+      octave_idx_type nr = arg.rows ();
+      octave_idx_type nc = arg.columns ();
+      bool natural = (nargout != 3);
+
+      int arg_is_empty = empty_arg ("chol", nr, nc);
 
-  if (arg_is_empty < 0)
-    return retval;
-  if (arg_is_empty > 0)
-    return octave_value (Matrix ());
+      if (arg_is_empty < 0)
+	return retval;
+      if (arg_is_empty > 0)
+	return octave_value (Matrix ());
+
+      if (arg.is_sparse_type ())
+	{
+	  if (arg.is_real_type ())
+	    {
+	      SparseMatrix m = arg.sparse_matrix_value ();
 
-  if (arg.is_real_type ())
-    {
-      Matrix m = arg.matrix_value ();
+	      if (! error_state)
+		{
+		  octave_idx_type info;
+		  SparseCHOL fact (m, info, natural);
+		  if (nargout == 3)
+		    if (vecout)
+		      retval(2) = fact.perm ();
+		    else
+		      retval(2) = fact.Q();
 
-      if (! error_state)
-	{
-	  octave_idx_type info;
-	  CHOL fact (m, info);
-	  if (nargout == 2 || info == 0)
+		  if (nargout > 1 || info == 0)
+		    {
+		      retval(1) = fact.P();
+		      if (LLt)
+			retval(0) = fact.L();
+		      else
+			retval(0) = fact.R();
+		    }
+		  else
+		    error ("chol: matrix not positive definite");
+		}
+	    }
+	  else if (arg.is_complex_type ())
 	    {
-	      retval(1) = static_cast<double> (info);
-	      retval(0) = fact.chol_matrix ();
+	      SparseComplexMatrix m = arg.sparse_complex_matrix_value ();
+
+	      if (! error_state)
+		{
+		  octave_idx_type info;
+		  SparseComplexCHOL fact (m, info, natural);
+
+		  if (nargout == 3)
+		    if (vecout)
+		      retval(2) = fact.perm ();
+		    else
+		      retval(2) = fact.Q();
+	  
+		  if (nargout > 1 || info == 0)
+		    {
+		      retval(1) = fact.P();
+		      if (LLt)
+			retval(0) = fact.L();
+		      else
+			retval(0) = fact.R();
+		    }
+		  else
+		    error ("chol: matrix not positive definite");
+		}
 	    }
 	  else
-	    error ("chol: matrix not positive definite");
+	    gripe_wrong_type_arg ("chol", arg);
 	}
-    }
-  else if (arg.is_complex_type ())
-    {
-      ComplexMatrix m = arg.complex_matrix_value ();
+      else
+	{
+	  if (arg.is_real_type ())
+	    {
+	      Matrix m = arg.matrix_value ();
 
-      if (! error_state)
-	{
-	  octave_idx_type info;
-	  ComplexCHOL fact (m, info);
-	  if (nargout == 2 || info == 0)
+	      if (! error_state)
+		{
+		  octave_idx_type info;
+		  CHOL fact (m, info);
+		  if (nargout == 2 || info == 0)
+		    {
+		      retval(1) = static_cast<double> (info);
+		      if (LLt)
+			retval(0) = fact.chol_matrix ().transpose ();
+		      else
+			retval(0) = fact.chol_matrix ();
+		    }
+		  else
+		    error ("chol: matrix not positive definite");
+		}
+	    }
+	  else if (arg.is_complex_type ())
 	    {
-	      retval(1) = static_cast<double> (info);
-	      retval(0) = fact.chol_matrix ();
+	      ComplexMatrix m = arg.complex_matrix_value ();
+
+	      if (! error_state)
+		{
+		  octave_idx_type info;
+		  ComplexCHOL fact (m, info);
+		  if (nargout == 2 || info == 0)
+		    {
+		      retval(1) = static_cast<double> (info);
+		      if (LLt)
+			retval(0) = fact.chol_matrix ().hermitian ();
+		      else
+			retval(0) = fact.chol_matrix ();
+		    }
+		  else
+		    error ("chol: matrix not positive definite");
+		}
 	    }
 	  else
-	    error ("chol: matrix not positive definite");
+	    gripe_wrong_type_arg ("chol", arg);
 	}
     }
-  else
-    {
-      gripe_wrong_type_arg ("chol", arg);
-    }
 
   return retval;
 }
@@ -141,36 +295,72 @@
 	retval = Matrix ();
       else
 	{
-	  if (arg.is_real_type ())
+	  if (arg.is_sparse_type ())
 	    {
-	      Matrix m = arg.matrix_value ();
-
-	      if (! error_state)
+	      if (arg.is_real_type ())
 		{
-		  octave_idx_type info;
-		  CHOL chol (m, info);
-		  if (info == 0)
-		    retval = chol.inverse ();
-		  else
-		    error ("cholinv: matrix not positive definite");
+		  SparseMatrix m = arg.sparse_matrix_value ();
+
+		  if (! error_state)
+		    {
+		      octave_idx_type info;
+		      SparseCHOL chol (m, info);
+		      if (info == 0)
+			retval = chol.inverse ();
+		      else
+			error ("cholinv: matrix not positive definite");
+		    }
 		}
-	    }
-	  else if (arg.is_complex_type ())
-	    {
-	      ComplexMatrix m = arg.complex_matrix_value ();
-
-	      if (! error_state)
+	      else if (arg.is_complex_type ())
 		{
-		  octave_idx_type info;
-		  ComplexCHOL chol (m, info);
-		  if (info == 0)
-		    retval = chol.inverse ();
-		  else
-		    error ("cholinv: matrix not positive definite");
+		  SparseComplexMatrix m = arg.sparse_complex_matrix_value ();
+
+		  if (! error_state)
+		    {
+		      octave_idx_type info;
+		      SparseComplexCHOL chol (m, info);
+		      if (info == 0)
+			retval = chol.inverse ();
+		      else
+			error ("cholinv: matrix not positive definite");
+		    }
 		}
+	      else
+		gripe_wrong_type_arg ("cholinv", arg);
 	    }
 	  else
-	    gripe_wrong_type_arg ("chol", arg);
+	    {
+	      if (arg.is_real_type ())
+		{
+		  Matrix m = arg.matrix_value ();
+
+		  if (! error_state)
+		    {
+		      octave_idx_type info;
+		      CHOL chol (m, info);
+		      if (info == 0)
+			retval = chol.inverse ();
+		      else
+			error ("cholinv: matrix not positive definite");
+		    }
+		}
+	      else if (arg.is_complex_type ())
+		{
+		  ComplexMatrix m = arg.complex_matrix_value ();
+
+		  if (! error_state)
+		    {
+		      octave_idx_type info;
+		      ComplexCHOL chol (m, info);
+		      if (info == 0)
+			retval = chol.inverse ();
+		      else
+			error ("cholinv: matrix not positive definite");
+		    }
+		}
+	      else
+		gripe_wrong_type_arg ("chol", arg);
+	    }
 	}
     }
   else
@@ -205,22 +395,44 @@
 	retval = Matrix ();
       else
 	{
-	  if (arg.is_real_type ())
+	  if (arg.is_sparse_type ())
 	    {
-	      Matrix r = arg.matrix_value ();
+	      if (arg.is_real_type ())
+		{
+		  SparseMatrix r = arg.sparse_matrix_value ();
 
-	      if (! error_state)
-		retval = chol2inv (r);
-	    }
-	  else if (arg.is_complex_type ())
-	    {
-	      ComplexMatrix r = arg.complex_matrix_value ();
+		  if (! error_state)
+		    retval = chol2inv (r);
+		}
+	      else if (arg.is_complex_type ())
+		{
+		  SparseComplexMatrix r = arg.sparse_complex_matrix_value ();
 
-	      if (! error_state)
-		retval = chol2inv (r);
+		  if (! error_state)
+		    retval = chol2inv (r);
+		}
+	      else
+		gripe_wrong_type_arg ("chol2inv", arg);
 	    }
 	  else
-	    gripe_wrong_type_arg ("chol2inv", arg);
+	    {
+	      if (arg.is_real_type ())
+		{
+		  Matrix r = arg.matrix_value ();
+
+		  if (! error_state)
+		    retval = chol2inv (r);
+		}
+	      else if (arg.is_complex_type ())
+		{
+		  ComplexMatrix r = arg.complex_matrix_value ();
+
+		  if (! error_state)
+		    retval = chol2inv (r);
+		}
+	      else
+		gripe_wrong_type_arg ("chol2inv", arg);
+	    }
 	}
     }
   else