diff src/corefcn/matrix_type.cc @ 15039:e753177cde93

maint: Move non-dynamically linked functions from DLD-FUNCTIONS/ to corefcn/ directory * __contourc__.cc, __dispatch__.cc, __lin_interpn__.cc, __pchip_deriv__.cc, __qp__.cc, balance.cc, besselj.cc, betainc.cc, bsxfun.cc, cellfun.cc, colloc.cc, conv2.cc, daspk.cc, dasrt.cc, dassl.cc, det.cc, dlmread.cc, dot.cc, eig.cc, fft.cc, fft2.cc, fftn.cc, filter.cc, find.cc, gammainc.cc, gcd.cc, getgrent.cc, getpwent.cc, getrusage.cc, givens.cc, hess.cc, hex2num.cc, inv.cc, kron.cc, lookup.cc, lsode.cc, lu.cc, luinc.cc, matrix_type.cc, max.cc, md5sum.cc, mgorth.cc, nproc.cc, pinv.cc, quad.cc, quadcc.cc, qz.cc, rand.cc, rcond.cc, regexp.cc, schur.cc, spparms.cc, sqrtm.cc, str2double.cc, strfind.cc, sub2ind.cc, svd.cc, syl.cc, time.cc, tril.cc, typecast.cc: Move functions from DLD-FUNCTIONS/ to corefcn/ directory. Include "defun.h", not "defun-dld.h". Change docstring to refer to these as "Built-in Functions". * build-aux/mk-opts.pl: Generate options code with '#include "defun.h"'. Change option docstrings to refer to these as "Built-in Functions". * corefcn/module.mk: List of functions to build in corefcn/ dir. * DLD-FUNCTIONS/config-module.awk: Update to new build system. * DLD-FUNCTIONS/module-files: Remove functions which are now in corefcn/ directory. * src/Makefile.am: Update to build "convenience library" in corefcn/. Octave program now links against all other libraries + corefcn libary. * src/find-defun-files.sh: Strip $srcdir from filename. * src/link-deps.mk: Add REGEX and FFTW link dependencies for liboctinterp. * type.m, which.m: Change failing tests to use 'amd', still a dynamic function, rather than 'dot', which isn't.
author Rik <rik@octave.org>
date Fri, 27 Jul 2012 15:35:00 -0700
parents src/DLD-FUNCTIONS/matrix_type.cc@460a3c6d8bf1
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/corefcn/matrix_type.cc	Fri Jul 27 15:35:00 2012 -0700
@@ -0,0 +1,621 @@
+/*
+
+Copyright (C) 2005-2012 David Bateman
+
+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 <algorithm>
+
+#include "ov.h"
+#include "defun.h"
+#include "error.h"
+#include "ov-re-mat.h"
+#include "ov-cx-mat.h"
+#include "ov-re-sparse.h"
+#include "ov-cx-sparse.h"
+#include "MatrixType.h"
+#include "oct-locbuf.h"
+
+DEFUN (matrix_type, args, ,
+  "-*- texinfo -*-\n\
+@deftypefn  {Built-in Function} {@var{type} =} matrix_type (@var{A})\n\
+@deftypefnx {Built-in Function} {@var{type} =} matrix_type (@var{A}, \"nocompute\")\n\
+@deftypefnx {Built-in Function} {@var{A} =} matrix_type (@var{A}, @var{type})\n\
+@deftypefnx {Built-in Function} {@var{A} =} matrix_type (@var{A}, \"upper\", @var{perm})\n\
+@deftypefnx {Built-in Function} {@var{A} =} matrix_type (@var{A}, \"lower\", @var{perm})\n\
+@deftypefnx {Built-in Function} {@var{A} =} matrix_type (@var{A}, \"banded\", @var{nl}, @var{nu})\n\
+Identify the matrix type or mark a matrix as a particular type.  This allows\n\
+more rapid solutions of linear equations involving @var{A} to be performed.\n\
+Called with a single argument, @code{matrix_type} returns the type of the\n\
+matrix and caches it for future use.  Called with more than one argument,\n\
+@code{matrix_type} allows the type of the matrix to be defined.\n\
+\n\
+If the option \"nocompute\" is given, the function will not attempt to guess\n\
+the type if it is still unknown.  This is useful for debugging purposes.\n\
+\n\
+The possible matrix types depend on whether the matrix is full or sparse, and\n\
+can be one of the following\n\
+\n\
+@table @asis\n\
+@item \"unknown\"\n\
+Remove any previously cached matrix type, and mark type as unknown.\n\
+\n\
+@item \"full\"\n\
+Mark the matrix as full.\n\
+\n\
+@item \"positive definite\"\n\
+Probable full positive definite matrix.\n\
+\n\
+@item \"diagonal\"\n\
+Diagonal matrix.  (Sparse matrices only)\n\
+\n\
+@item \"permuted diagonal\"\n\
+Permuted Diagonal matrix.  The permutation does not need to be specifically\n\
+indicated, as the structure of the matrix explicitly gives this.  (Sparse\n\
+matrices only)\n\
+\n\
+@item \"upper\"\n\
+Upper triangular.  If the optional third argument @var{perm} is given, the\n\
+matrix is assumed to be a permuted upper triangular with the permutations\n\
+defined by the vector @var{perm}.\n\
+\n\
+@item \"lower\"\n\
+Lower triangular.  If the optional third argument @var{perm} is given, the\n\
+matrix is assumed to be a permuted lower triangular with the permutations\n\
+defined by the vector @var{perm}.\n\
+\n\
+@item \"banded\"\n\
+@itemx \"banded positive definite\"\n\
+Banded matrix with the band size of @var{nl} below the diagonal and @var{nu}\n\
+above it.  If @var{nl} and @var{nu} are 1, then the matrix is tridiagonal and\n\
+treated with specialized code.  In addition the matrix can be marked as\n\
+probably a positive definite.  (Sparse matrices only)\n\
+\n\
+@item \"singular\"\n\
+The matrix is assumed to be singular and will be treated with a minimum norm\n\
+solution.\n\
+\n\
+@end table\n\
+\n\
+Note that the matrix type will be discovered automatically on the first\n\
+attempt to solve a linear equation involving @var{A}.  Therefore\n\
+@code{matrix_type} is only useful to give Octave hints of the matrix type.\n\
+Incorrectly defining the matrix type will result in incorrect results from\n\
+solutions of linear equations; it is entirely @strong{the responsibility of\n\
+the user} to correctly identify the matrix type.\n\
+\n\
+Also, the test for positive definiteness is a low-cost test for a Hermitian\n\
+matrix with a real positive diagonal.  This does not guarantee that the\n\
+matrix is positive definite, but only that it is a probable candidate.  When\n\
+such a matrix is factorized, a Cholesky@tie{}factorization is first\n\
+attempted, and if that fails the matrix is then treated with an\n\
+LU@tie{}factorization.  Once the matrix has been factorized,\n\
+@code{matrix_type} will return the correct classification of the matrix.\n\
+@end deftypefn")
+{
+  int nargin = args.length ();
+  octave_value retval;
+
+  if (nargin == 0)
+    print_usage ();
+  else if (nargin > 4)
+    error ("matrix_type: incorrect number of arguments");
+  else
+    {
+      bool autocomp = true;
+      if (nargin == 2 && args(1).is_string () && args(1).string_value () == "nocompute")
+        {
+          nargin = 1;
+          autocomp = false;
+        }
+
+      if (args(0).is_scalar_type ())
+        {
+          if (nargin == 1)
+            retval = octave_value ("Diagonal");
+          else
+            retval = args(0);
+        }
+      else if (args(0).is_sparse_type ())
+        {
+          if (nargin == 1)
+            {
+              MatrixType mattyp;
+
+              if (args(0).is_complex_type ())
+                {
+                  mattyp = args(0).matrix_type ();
+
+                  if (mattyp.is_unknown () && autocomp )
+                    {
+                      SparseComplexMatrix m =
+                        args(0).sparse_complex_matrix_value ();
+                      if (!error_state)
+                        {
+                          mattyp = MatrixType (m);
+                          args(0).matrix_type (mattyp);
+                        }
+                    }
+                }
+              else
+                {
+                  mattyp = args(0).matrix_type ();
+
+                  if (mattyp.is_unknown () && autocomp)
+                    {
+                      SparseMatrix m = args(0).sparse_matrix_value ();
+                      if (!error_state)
+                        {
+                          mattyp = MatrixType (m);
+                          args(0).matrix_type (mattyp);
+                        }
+                    }
+                }
+
+              int typ = mattyp.type ();
+
+              if (typ == MatrixType::Diagonal)
+                retval = octave_value ("Diagonal");
+              else if (typ == MatrixType::Permuted_Diagonal)
+                retval = octave_value ("Permuted Diagonal");
+              else if (typ == MatrixType::Upper)
+                retval = octave_value ("Upper");
+              else if (typ == MatrixType::Permuted_Upper)
+                retval = octave_value ("Permuted Upper");
+              else if (typ == MatrixType::Lower)
+                retval = octave_value ("Lower");
+              else if (typ == MatrixType::Permuted_Lower)
+                retval = octave_value ("Permuted Lower");
+              else if (typ == MatrixType::Banded)
+                retval = octave_value ("Banded");
+              else if (typ == MatrixType::Banded_Hermitian)
+                retval = octave_value ("Banded Positive Definite");
+              else if (typ == MatrixType::Tridiagonal)
+                retval = octave_value ("Tridiagonal");
+              else if (typ == MatrixType::Tridiagonal_Hermitian)
+                retval = octave_value ("Tridiagonal Positive Definite");
+              else if (typ == MatrixType::Hermitian)
+                retval = octave_value ("Positive Definite");
+              else if (typ == MatrixType::Rectangular)
+                {
+                  if (args(0).rows () == args(0).columns ())
+                    retval = octave_value ("Singular");
+                  else
+                    retval = octave_value ("Rectangular");
+                }
+              else if (typ == MatrixType::Full)
+                retval = octave_value ("Full");
+              else
+                retval = octave_value ("Unknown");
+            }
+          else
+            {
+              // Ok, we're changing the matrix type
+              std::string str_typ = args(1).string_value ();
+
+              // FIXME -- why do I have to explicitly call the constructor?
+              MatrixType mattyp = MatrixType ();
+
+              octave_idx_type nl = 0;
+              octave_idx_type nu = 0;
+
+              if (error_state)
+                error ("matrix_type: TYPE must be a string");
+              else
+                {
+                  // Use STL function to convert to lower case
+                  std::transform (str_typ.begin (), str_typ.end (),
+                                  str_typ.begin (), tolower);
+
+                  if (str_typ == "diagonal")
+                    mattyp.mark_as_diagonal ();
+                  if (str_typ == "permuted diagonal")
+                    mattyp.mark_as_permuted_diagonal ();
+                  else if (str_typ == "upper")
+                    mattyp.mark_as_upper_triangular ();
+                  else if (str_typ == "lower")
+                    mattyp.mark_as_lower_triangular ();
+                  else if (str_typ == "banded" || str_typ == "banded positive definite")
+                    {
+                      if (nargin != 4)
+                        error ("matrix_type: banded matrix type requires 4 arguments");
+                      else
+                        {
+                          nl = args(2).nint_value ();
+                          nu = args(3).nint_value ();
+
+                          if (error_state)
+                            error ("matrix_type: band size NL, NU must be integers");
+                          else
+                            {
+                              if (nl == 1 && nu == 1)
+                                mattyp.mark_as_tridiagonal ();
+                              else
+                                mattyp.mark_as_banded (nu, nl);
+
+                              if (str_typ == "banded positive definite")
+                                mattyp.mark_as_symmetric ();
+                            }
+                        }
+                    }
+                  else if (str_typ == "positive definite")
+                    {
+                      mattyp.mark_as_full ();
+                      mattyp.mark_as_symmetric ();
+                    }
+                  else if (str_typ == "singular")
+                    mattyp.mark_as_rectangular ();
+                  else if (str_typ == "full")
+                    mattyp.mark_as_full ();
+                  else if (str_typ == "unknown")
+                    mattyp.invalidate_type ();
+                  else
+                    error ("matrix_type: Unknown matrix type %s", str_typ.c_str ());
+
+                  if (! error_state)
+                    {
+                      if (nargin == 3 && (str_typ == "upper" || str_typ == "lower"))
+                        {
+                          const ColumnVector perm =
+                            ColumnVector (args (2).vector_value ());
+
+                          if (error_state)
+                            error ("matrix_type: Invalid permutation vector PERM");
+                          else
+                            {
+                              octave_idx_type len = perm.length ();
+                              dim_vector dv = args(0).dims ();
+
+                              if (len != dv(0))
+                                error ("matrix_type: Invalid permutation vector PERM");
+                              else
+                                {
+                                  OCTAVE_LOCAL_BUFFER (octave_idx_type, p, len);
+
+                                  for (octave_idx_type i = 0; i < len; i++)
+                                    p[i] = static_cast<octave_idx_type> (perm (i)) - 1;
+
+                                  if (str_typ == "upper")
+                                    mattyp.mark_as_permuted (len, p);
+                                  else
+                                    mattyp.mark_as_permuted (len, p);
+                                }
+                            }
+                        }
+                      else if (nargin != 2 && str_typ != "banded positive definite" &&
+                               str_typ != "banded")
+                        error ("matrix_type: Invalid number of arguments");
+
+                      if (! error_state)
+                        {
+                          // Set the matrix type
+                          if (args(0).is_complex_type ())
+                            retval =
+                              octave_value (args(0).sparse_complex_matrix_value (),
+                                            mattyp);
+                          else
+                            retval = octave_value (args(0).sparse_matrix_value (),
+                                                   mattyp);
+                        }
+                    }
+                }
+            }
+        }
+      else
+        {
+          if (nargin == 1)
+            {
+              MatrixType mattyp;
+
+              if (args(0).is_complex_type ())
+                {
+                  mattyp = args(0).matrix_type ();
+
+                  if (mattyp.is_unknown () && autocomp)
+                    {
+                      if (args(0).is_single_type ())
+                        {
+                          FloatComplexMatrix m = args(0).float_complex_matrix_value ();
+                          if (!error_state)
+                            {
+                              mattyp = MatrixType (m);
+                              args(0).matrix_type (mattyp);
+                            }
+                        }
+                      else
+                        {
+                          ComplexMatrix m = args(0).complex_matrix_value ();
+                          if (!error_state)
+                            {
+                              mattyp = MatrixType (m);
+                              args(0).matrix_type (mattyp);
+                            }
+                        }
+                    }
+                }
+              else
+                {
+                  mattyp = args(0).matrix_type ();
+
+                  if (mattyp.is_unknown () && autocomp)
+                    {
+                      if (args(0).is_single_type ())
+                        {
+                          FloatMatrix m = args(0).float_matrix_value ();
+                          if (!error_state)
+                            {
+                              mattyp = MatrixType (m);
+                              args(0).matrix_type (mattyp);
+                            }
+                        }
+                      else
+                        {
+                          Matrix m = args(0).matrix_value ();
+                          if (!error_state)
+                            {
+                              mattyp = MatrixType (m);
+                              args(0).matrix_type (mattyp);
+                            }
+                        }
+                    }
+                }
+
+              int typ = mattyp.type ();
+
+              if (typ == MatrixType::Upper)
+                retval = octave_value ("Upper");
+              else if (typ == MatrixType::Permuted_Upper)
+                retval = octave_value ("Permuted Upper");
+              else if (typ == MatrixType::Lower)
+                retval = octave_value ("Lower");
+              else if (typ == MatrixType::Permuted_Lower)
+                retval = octave_value ("Permuted Lower");
+              else if (typ == MatrixType::Hermitian)
+                retval = octave_value ("Positive Definite");
+              else if (typ == MatrixType::Rectangular)
+                {
+                  if (args(0).rows () == args(0).columns ())
+                    retval = octave_value ("Singular");
+                  else
+                    retval = octave_value ("Rectangular");
+                }
+              else if (typ == MatrixType::Full)
+                retval = octave_value ("Full");
+              else
+                retval = octave_value ("Unknown");
+            }
+          else
+            {
+              // Ok, we're changing the matrix type
+              std::string str_typ = args(1).string_value ();
+
+              // FIXME -- why do I have to explicitly call the constructor?
+              MatrixType mattyp = MatrixType (MatrixType::Unknown, true);
+
+              if (error_state)
+                error ("matrix_type: TYPE must be a string");
+              else
+                {
+                  // Use STL function to convert to lower case
+                  std::transform (str_typ.begin (), str_typ.end (),
+                                  str_typ.begin (), tolower);
+
+                  if (str_typ == "upper")
+                    mattyp.mark_as_upper_triangular ();
+                  else if (str_typ == "lower")
+                    mattyp.mark_as_lower_triangular ();
+                  else if (str_typ == "positive definite")
+                    {
+                      mattyp.mark_as_full ();
+                      mattyp.mark_as_symmetric ();
+                    }
+                  else if (str_typ == "singular")
+                    mattyp.mark_as_rectangular ();
+                  else if (str_typ == "full")
+                    mattyp.mark_as_full ();
+                  else if (str_typ == "unknown")
+                    mattyp.invalidate_type ();
+                  else
+                    error ("matrix_type: Unknown matrix type %s", str_typ.c_str ());
+
+                  if (! error_state)
+                    {
+                      if (nargin == 3 && (str_typ == "upper"
+                                          || str_typ == "lower"))
+                        {
+                          const ColumnVector perm =
+                            ColumnVector (args (2).vector_value ());
+
+                          if (error_state)
+                            error ("matrix_type: Invalid permutation vector PERM");
+                          else
+                            {
+                              octave_idx_type len = perm.length ();
+                              dim_vector dv = args(0).dims ();
+
+                              if (len != dv(0))
+                                error ("matrix_type: Invalid permutation vector PERM");
+                              else
+                                {
+                                  OCTAVE_LOCAL_BUFFER (octave_idx_type, p, len);
+
+                                  for (octave_idx_type i = 0; i < len; i++)
+                                    p[i] = static_cast<octave_idx_type> (perm (i)) - 1;
+
+                                  if (str_typ == "upper")
+                                    mattyp.mark_as_permuted (len, p);
+                                  else
+                                    mattyp.mark_as_permuted (len, p);
+                                }
+                            }
+                        }
+                      else if (nargin != 2)
+                        error ("matrix_type: Invalid number of arguments");
+
+                      if (! error_state)
+                        {
+                          // Set the matrix type
+                          if (args(0).is_single_type ())
+                            {
+                              if (args(0).is_complex_type ())
+                                retval = octave_value
+                                  (args(0).float_complex_matrix_value (),
+                                   mattyp);
+                              else
+                                retval = octave_value
+                                  (args(0).float_matrix_value (),
+                                   mattyp);
+                            }
+                          else
+                            {
+                              if (args(0).is_complex_type ())
+                                retval = octave_value
+                                  (args(0).complex_matrix_value (),
+                                   mattyp);
+                              else
+                                retval = octave_value
+                                  (args(0).matrix_value (),
+                                   mattyp);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+  return retval;
+}
+
+/*
+## FIXME:
+## Disable tests for lower under-determined and upper over-determined
+## matrices as this detection is disabled in MatrixType due to issues
+## of non minimum norm solution being found.
+
+%!assert (matrix_type (speye (10,10)), "Diagonal")
+%!assert (matrix_type (speye (10,10)([2:10,1],:)), "Permuted Diagonal")
+%!assert (matrix_type ([[speye(10,10);sparse(1,10)],[1;sparse(9,1);1]]), "Upper")
+%!assert (matrix_type ([[speye(10,10);sparse(1,10)],[1;sparse(9,1);1]](:,[2,1,3:11])), "Permuted Upper")
+%!assert (matrix_type ([speye(10,10),sparse(10,1);1,sparse(1,9),1]), "Lower")
+%!assert (matrix_type ([speye(10,10),sparse(10,1);1,sparse(1,9),1]([2,1,3:11],:)), "Permuted Lower")
+
+%!test
+%! bnd = spparms ("bandden");
+%! spparms ("bandden", 0.5);
+%! a = spdiags (rand (10,3)-0.5,[-1,0,1],10,10);
+%! assert (matrix_type (a), "Tridiagonal");
+%! assert (matrix_type (a'+a+2*speye (10)), "Tridiagonal Positive Definite");
+%! spparms ("bandden", bnd);
+%!test
+%! bnd=spparms ("bandden");
+%! spparms ("bandden", 0.5);
+%! a = spdiags (randn (10,4),[-2:1],10,10);
+%! assert (matrix_type (a), "Banded");
+%! assert (matrix_type (a'*a), "Banded Positive Definite");
+%! spparms ("bandden", bnd);
+%!test
+%! a = [speye(10,10),[sparse(9,1);1];-1,sparse(1,9),1];
+%! assert (matrix_type (a), "Full");
+%! assert (matrix_type (a'*a), "Positive Definite");
+
+%!assert (matrix_type (speye (10,11)), "Diagonal")
+%!assert (matrix_type (speye (10,11)([2:10,1],:)), "Permuted Diagonal")
+%!assert (matrix_type (speye (11,10)), "Diagonal")
+%!assert (matrix_type (speye (11,10)([2:11,1],:)), "Permuted Diagonal")
+%#!assert (matrix_type ([[speye(10,10);sparse(1,10)],[[1,1];sparse(9,2);[1,1]]]), "Upper")
+%#!assert (matrix_type ([[speye(10,10);sparse(1,10)],[[1,1];sparse(9,2);[1,1]]](:,[2,1,3:12])), "Permuted Upper")
+%!assert (matrix_type ([speye(11,9),[1;sparse(8,1);1;0]]), "Upper")
+%!assert (matrix_type ([speye(11,9),[1;sparse(8,1);1;0]](:,[2,1,3:10])), "Permuted Upper")
+%#!assert (matrix_type ([speye(10,10),sparse(10,1);[1;1],sparse(2,9),[1;1]]), "Lower")
+%#!assert (matrix_type ([speye(10,10),sparse(10,1);[1;1],sparse(2,9),[1;1]]([2,1,3:12],:)), "Permuted Lower")
+%!assert (matrix_type ([speye(9,11);[1,sparse(1,8),1,0]]), "Lower")
+%!assert (matrix_type ([speye(9,11);[1,sparse(1,8),1,0]]([2,1,3:10],:)), "Permuted Lower")
+%!assert (matrix_type (spdiags (randn (10,4),[-2:1],10,9)), "Rectangular")
+
+%!assert (matrix_type (1i*speye (10,10)), "Diagonal")
+%!assert (matrix_type (1i*speye (10,10)([2:10,1],:)), "Permuted Diagonal")
+%!assert (matrix_type ([[speye(10,10);sparse(1,10)],[1i;sparse(9,1);1]]), "Upper")
+%!assert (matrix_type ([[speye(10,10);sparse(1,10)],[1i;sparse(9,1);1]](:,[2,1,3:11])), "Permuted Upper")
+%!assert (matrix_type ([speye(10,10),sparse(10,1);1i,sparse(1,9),1]), "Lower")
+%!assert (matrix_type ([speye(10,10),sparse(10,1);1i,sparse(1,9),1]([2,1,3:11],:)), "Permuted Lower")
+
+%!test
+%! bnd = spparms ("bandden");
+%! spparms ("bandden", 0.5);
+%! assert (matrix_type (spdiags (1i*randn (10,3),[-1,0,1],10,10)), "Tridiagonal");
+%! a = 1i*(rand (9,1)-0.5);
+%! a = [[a;0],ones(10,1),[0;-a]];
+%! assert (matrix_type (spdiags (a,[-1,0,1],10,10)), "Tridiagonal Positive Definite");
+%! spparms ("bandden", bnd);
+%!test
+%! bnd = spparms ("bandden");
+%! spparms ("bandden", 0.5);
+%! assert (matrix_type (spdiags (1i*randn (10,4),[-2:1],10,10)), "Banded");
+%! a = 1i*(rand (9,2)-0.5);
+%! a = [[a;[0,0]],ones(10,1),[[0;-a(:,2)],[0;0;-a(1:8,1)]]];
+%! assert (matrix_type (spdiags (a,[-2:2],10,10)), "Banded Positive Definite");
+%! spparms ("bandden", bnd);
+%!test
+%! a = [speye(10,10),[sparse(9,1);1i];-1,sparse(1,9),1];
+%! assert (matrix_type (a), "Full");
+%! assert (matrix_type (a'*a), "Positive Definite");
+
+%!assert (matrix_type (1i*speye (10,11)), "Diagonal")
+%!assert (matrix_type (1i*speye (10,11)([2:10,1],:)), "Permuted Diagonal")
+%!assert (matrix_type (1i*speye (11,10)), "Diagonal")
+%!assert (matrix_type (1i*speye (11,10)([2:11,1],:)), "Permuted Diagonal")
+%#!assert (matrix_type ([[speye(10,10);sparse(1,10)],[[1i,1i];sparse(9,2);[1i,1i]]]), "Upper")
+%#!assert (matrix_type ([[speye(10,10);sparse(1,10)],[[1i,1i];sparse(9,2);[1i,1i]]](:,[2,1,3:12])), "Permuted Upper")
+%!assert (matrix_type ([speye(11,9),[1i;sparse(8,1);1i;0]]), "Upper")
+%!assert (matrix_type ([speye(11,9),[1i;sparse(8,1);1i;0]](:,[2,1,3:10])), "Permuted Upper")
+%#!assert (matrix_type ([speye(10,10),sparse(10,1);[1i;1i],sparse(2,9),[1i;1i]]), "Lower")
+%#!assert (matrix_type ([speye(10,10),sparse(10,1);[1i;1i],sparse(2,9),[1i;1i]]([2,1,3:12],:)), "Permuted Lower")
+%!assert (matrix_type ([speye(9,11);[1i,sparse(1,8),1i,0]]), "Lower")
+%!assert (matrix_type ([speye(9,11);[1i,sparse(1,8),1i,0]]([2,1,3:10],:)), "Permuted Lower")
+%!assert (matrix_type (1i*spdiags(randn(10,4),[-2:1],10,9)), "Rectangular")
+
+%!test
+%! a = matrix_type (spdiags (randn (10,3),[-1,0,1],10,10), "Singular");
+%! assert (matrix_type (a), "Singular");
+
+%!assert (matrix_type (triu (ones(10,10))), "Upper")
+%!assert (matrix_type (triu (ones(10,10),-1)), "Full")
+%!assert (matrix_type (tril (ones(10,10))), "Lower")
+%!assert (matrix_type (tril (ones(10,10),1)), "Full")
+%!assert (matrix_type (10*eye (10,10) + ones (10,10)), "Positive Definite")
+%!assert (matrix_type (ones (11,10)), "Rectangular")
+%!test
+%! a = matrix_type (ones (10,10), "Singular");
+%! assert (matrix_type (a), "Singular");
+
+%!assert (matrix_type (triu (1i*ones (10,10))), "Upper")
+%!assert (matrix_type (triu (1i*ones (10,10),-1)), "Full")
+%!assert (matrix_type (tril (1i*ones (10,10))), "Lower")
+%!assert (matrix_type (tril (1i*ones (10,10),1)), "Full")
+%!assert (matrix_type (10*eye (10,10) + 1i*triu (ones (10,10),1) -1i*tril (ones (10,10),-1)), "Positive Definite")
+%!assert (matrix_type (ones (11,10)), "Rectangular")
+%!test
+%! a = matrix_type (ones (10,10), "Singular");
+%! assert (matrix_type (a), "Singular");
+*/