# HG changeset patch # User John W. Eaton # Date 1453843854 18000 # Node ID 307096fb67e14016af0ee0f9d856588633afd843 # Parent 76e0ef020dae2bac7d03540ab7a1dc3073afa0be revamp sparse Cholesky factorization classes * sparse-chol.h, sparse-chol.cc: Rename from sparse-base-chol.h and sparse-base-chol.cc, respectively. (class sparse_chol): Rename from sparse_base_chol. Incorporate code from SparseCmplxCHOL and SparsedbleCHOL classes into the sparse_chol template. Hide representation and HAVE_CHOLMOD macro from public interface. * sparse-chol-inst.cc: New file. * SparseCmplxCHOL.cc, SparseCmplxCHOL.h, SparsedbleCHOL.cc, SparsedbleCHOL.h: Delete. * chol.cc, symbfact.cc, CSparse.cc, dSparse.cc, eigs-base.cc: Change all uses of SparsedbleCHOL and SparseCmplxCHOL to use new sparse_chol template class. * liboctave/numeric/module.mk: Update. diff -r 76e0ef020dae -r 307096fb67e1 libinterp/dldfcn/chol.cc --- a/libinterp/dldfcn/chol.cc Wed Jan 27 14:15:17 2016 +0100 +++ b/libinterp/dldfcn/chol.cc Tue Jan 26 16:30:54 2016 -0500 @@ -31,8 +31,7 @@ #include "dbleCHOL.h" #include "fCmplxCHOL.h" #include "floatCHOL.h" -#include "SparseCmplxCHOL.h" -#include "SparsedbleCHOL.h" +#include "sparse-chol.h" #include "oct-spparms.h" #include "sparse-util.h" @@ -194,7 +193,7 @@ { SparseMatrix m = arg.sparse_matrix_value (); - SparseCHOL fact (m, info, natural, force); + sparse_chol fact (m, info, natural, force); if (nargout == 3) { @@ -219,7 +218,7 @@ { SparseComplexMatrix m = arg.sparse_complex_matrix_value (); - SparseComplexCHOL fact (m, info, natural, force); + sparse_chol fact (m, info, natural, force); if (nargout == 3) { @@ -358,7 +357,7 @@ { SparseMatrix m = arg.sparse_matrix_value (); - SparseCHOL chol (m, info); + sparse_chol chol (m, info); if (info == 0) retval = chol.inverse (); @@ -369,7 +368,7 @@ { SparseComplexMatrix m = arg.sparse_complex_matrix_value (); - SparseComplexCHOL chol (m, info); + sparse_chol chol (m, info); if (info == 0) retval = chol.inverse (); diff -r 76e0ef020dae -r 307096fb67e1 libinterp/dldfcn/symbfact.cc --- a/libinterp/dldfcn/symbfact.cc Wed Jan 27 14:15:17 2016 +0100 +++ b/libinterp/dldfcn/symbfact.cc Tue Jan 26 16:30:54 2016 -0500 @@ -25,8 +25,7 @@ #include #endif -#include "SparseCmplxCHOL.h" -#include "SparsedbleCHOL.h" +#include "sparse-chol.h" #include "oct-spparms.h" #include "sparse-util.h" #include "oct-locbuf.h" diff -r 76e0ef020dae -r 307096fb67e1 liboctave/array/CSparse.cc --- a/liboctave/array/CSparse.cc Wed Jan 27 14:15:17 2016 +0100 +++ b/liboctave/array/CSparse.cc Tue Jan 26 16:30:54 2016 -0500 @@ -54,7 +54,7 @@ #include "SparseCmplxLU.h" #include "oct-sparse.h" #include "sparse-util.h" -#include "SparseCmplxCHOL.h" +#include "sparse-chol.h" #include "SparseCmplxQR.h" #include "Sparse-op-defs.h" @@ -1079,7 +1079,7 @@ if (mattype.is_hermitian ()) { MatrixType tmp_typ (MatrixType::Upper); - SparseComplexCHOL fact (*this, info, false); + sparse_chol fact (*this, info, false); rcond = fact.rcond (); if (info == 0) { diff -r 76e0ef020dae -r 307096fb67e1 liboctave/array/dSparse.cc --- a/liboctave/array/dSparse.cc Wed Jan 27 14:15:17 2016 +0100 +++ b/liboctave/array/dSparse.cc Tue Jan 26 16:30:54 2016 -0500 @@ -49,7 +49,7 @@ #include "MatrixType.h" #include "oct-sparse.h" #include "sparse-util.h" -#include "SparsedbleCHOL.h" +#include "sparse-chol.h" #include "SparseQR.h" #include "Sparse-op-defs.h" @@ -1169,7 +1169,7 @@ if (mattype.is_hermitian ()) { MatrixType tmp_typ (MatrixType::Upper); - SparseCHOL fact (*this, info, false); + sparse_chol fact (*this, info, false); rcond = fact.rcond (); if (info == 0) { diff -r 76e0ef020dae -r 307096fb67e1 liboctave/numeric/SparseCmplxCHOL.cc --- a/liboctave/numeric/SparseCmplxCHOL.cc Wed Jan 27 14:15:17 2016 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/* - -Copyright (C) 2005-2015 David Bateman -Copyright (C) 1998-2005 Andy Adler - -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 -. - -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "SparseCmplxCHOL.h" - -// Instantiate the base CHOL class for the type we need -#define OCTAVE_CHOLMOD_TYPE CHOLMOD_COMPLEX -#include "sparse-base-chol.h" -#include "sparse-base-chol.cc" -template class sparse_base_chol ; - -// Compute the inverse of a matrix using the Cholesky factorization. -SparseComplexMatrix -chol2inv (const SparseComplexMatrix& r) -{ - octave_idx_type r_nr = r.rows (); - octave_idx_type r_nc = r.cols (); - - if (r_nr != r_nc) - (*current_liboctave_error_handler) ("U must be a square matrix"); - - SparseComplexMatrix retval; - MatrixType mattype (r); - int typ = mattype.type (false); - double rcond; - octave_idx_type info; - SparseComplexMatrix rinv; - - if (typ == MatrixType::Upper) - { - rinv = r.inverse (mattype, info, rcond, true, false); - retval = rinv.transpose () * rinv; - } - else if (typ == MatrixType::Lower) - { - rinv = r.transpose ().inverse (mattype, info, rcond, true, false); - retval = rinv.transpose () * rinv; - } - else - (*current_liboctave_error_handler) ("U must be a triangular matrix"); - - return retval; -} diff -r 76e0ef020dae -r 307096fb67e1 liboctave/numeric/SparseCmplxCHOL.h --- a/liboctave/numeric/SparseCmplxCHOL.h Wed Jan 27 14:15:17 2016 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,109 +0,0 @@ -/* - -Copyright (C) 2005-2015 David Bateman -Copyright (C) 1998-2005 Andy Adler - -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 -. - -*/ - -#if ! defined (octave_SparseCmplxCHOL_h) -#define octave_SparseCmplxCHOL_h 1 - -#include "sparse-base-chol.h" -#include "dSparse.h" -#include "CSparse.h" - -class -OCTAVE_API -SparseComplexCHOL - : public sparse_base_chol -{ -public: - - SparseComplexCHOL (void) - : sparse_base_chol () { } - - SparseComplexCHOL (const SparseComplexMatrix& a, bool natural = true, - bool force = false) - : sparse_base_chol - (a, natural, force) { } - - SparseComplexCHOL (const SparseComplexMatrix& a, octave_idx_type& info, - bool natural = true, bool force = false) - : sparse_base_chol - (a, info, natural, force) { } - - SparseComplexCHOL (const SparseComplexCHOL& a) - : sparse_base_chol (a) { } - - ~SparseComplexCHOL (void) { } - - SparseComplexCHOL& operator = (const SparseComplexCHOL& a) - { - if (this != &a) - sparse_base_chol :: - operator = (a); - - return *this; - } - - SparseComplexMatrix chol_matrix (void) const { return R (); } - - SparseComplexMatrix L (void) const - { - return sparse_base_chol:: L (); - } - - SparseComplexMatrix R (void) const - { - return sparse_base_chol:: R (); - } - - octave_idx_type P (void) const - { - return sparse_base_chol:: P (); - } - - ColumnVector perm (void) const - { - return sparse_base_chol:: perm (); - } - - SparseMatrix Q (void) const - { - return sparse_base_chol:: Q (); - } - - double rcond (void) const - { - return sparse_base_chol:: rcond (); - } - - // Compute the inverse of a matrix using the Cholesky factorization. - SparseComplexMatrix inverse (void) const - { - return sparse_base_chol:: inverse (); - } -}; - -SparseComplexMatrix OCTAVE_API chol2inv (const SparseComplexMatrix& r); - -#endif diff -r 76e0ef020dae -r 307096fb67e1 liboctave/numeric/SparsedbleCHOL.cc --- a/liboctave/numeric/SparsedbleCHOL.cc Wed Jan 27 14:15:17 2016 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -/* - -Copyright (C) 2005-2015 David Bateman -Copyright (C) 1998-2005 Andy Adler - -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 -. - -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "SparsedbleCHOL.h" - -// Instantiate the base CHOL class for the type we need -#define OCTAVE_CHOLMOD_TYPE CHOLMOD_REAL -#include "sparse-base-chol.h" -#include "sparse-base-chol.cc" -template class sparse_base_chol ; - -// Compute the inverse of a matrix using the Cholesky factorization. -SparseMatrix -chol2inv (const SparseMatrix& r) -{ - octave_idx_type r_nr = r.rows (); - octave_idx_type r_nc = r.cols (); - SparseMatrix retval; - - if (r_nr != r_nc) - (*current_liboctave_error_handler) ("U must be a square matrix"); - - MatrixType mattype (r); - int typ = mattype.type (false); - double rcond; - octave_idx_type info; - SparseMatrix rinv; - - if (typ == MatrixType::Upper) - { - rinv = r.inverse (mattype, info, rcond, true, false); - retval = rinv.transpose () * rinv; - } - else if (typ == MatrixType::Lower) - { - rinv = r.transpose ().inverse (mattype, info, rcond, true, false); - retval = rinv.transpose () * rinv; - } - else - (*current_liboctave_error_handler) ("U must be a triangular matrix"); - - return retval; -} diff -r 76e0ef020dae -r 307096fb67e1 liboctave/numeric/SparsedbleCHOL.h --- a/liboctave/numeric/SparsedbleCHOL.h Wed Jan 27 14:15:17 2016 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,91 +0,0 @@ -/* - -Copyright (C) 2005-2015 David Bateman -Copyright (C) 1998-2005 Andy Adler - -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 -. - -*/ - -#if ! defined (octave_SparsedbleCHOL_h) -#define octave_SparsedbleCHOL_h 1 - -#include "sparse-base-chol.h" -#include "dSparse.h" - -class -OCTAVE_API -SparseCHOL : public sparse_base_chol -{ -public: - - SparseCHOL (void) : sparse_base_chol () - { } - - SparseCHOL (const SparseMatrix& a, bool natural = true, bool force = false) - : sparse_base_chol (a, natural, force) - { } - - SparseCHOL (const SparseMatrix& a, octave_idx_type& info, - bool natural = false, bool force = false) - : sparse_base_chol (a, info, natural, - force) - { } - - SparseCHOL (const SparseCHOL& a) : - sparse_base_chol (a) { } - - ~SparseCHOL (void) { } - - SparseCHOL& operator = (const SparseCHOL& a) - { - if (this != &a) - sparse_base_chol :: operator = (a); - - return *this; - } - - SparseMatrix chol_matrix (void) const { return R (); } - - SparseMatrix L (void) const - { return sparse_base_chol:: L (); } - - SparseMatrix R (void) const - { return sparse_base_chol:: R (); } - - octave_idx_type P (void) const - { return sparse_base_chol:: P (); } - - ColumnVector perm (void) const - { return sparse_base_chol:: perm (); } - - SparseMatrix Q (void) const - { return sparse_base_chol:: Q (); } - - double rcond (void) const - { return sparse_base_chol:: rcond (); } - - // Compute the inverse of a matrix using the Cholesky factorization. - SparseMatrix inverse (void) const - { - return sparse_base_chol:: inverse (); - } -}; - -SparseMatrix OCTAVE_API chol2inv (const SparseMatrix& r); - -#endif diff -r 76e0ef020dae -r 307096fb67e1 liboctave/numeric/eigs-base.cc --- a/liboctave/numeric/eigs-base.cc Wed Jan 27 14:15:17 2016 +0100 +++ b/liboctave/numeric/eigs-base.cc Tue Jan 26 16:30:54 2016 -0500 @@ -37,8 +37,7 @@ #include "dSparse.h" #include "CSparse.h" #include "MatrixType.h" -#include "SparsedbleCHOL.h" -#include "SparseCmplxCHOL.h" +#include "sparse-chol.h" #include "oct-rand.h" #include "dbleCHOL.h" #include "CmplxCHOL.h" @@ -370,7 +369,7 @@ make_cholb (SparseMatrix& b, SparseMatrix& bt, ColumnVector& permB) { octave_idx_type info; - SparseCHOL fact (b, info, false); + sparse_chol fact (b, info, false); if (fact.P () != 0) return false; @@ -408,7 +407,7 @@ ColumnVector& permB) { octave_idx_type info; - SparseComplexCHOL fact (b, info, false); + sparse_chol fact (b, info, false); if (fact.P () != 0) return false; diff -r 76e0ef020dae -r 307096fb67e1 liboctave/numeric/module.mk --- a/liboctave/numeric/module.mk Wed Jan 27 14:15:17 2016 +0100 +++ b/liboctave/numeric/module.mk Tue Jan 26 16:30:54 2016 -0500 @@ -79,12 +79,10 @@ liboctave/numeric/randgamma.h \ liboctave/numeric/randmtzig.h \ liboctave/numeric/randpoisson.h \ - liboctave/numeric/sparse-base-chol.h \ + liboctave/numeric/sparse-chol.h \ liboctave/numeric/sparse-base-lu.h \ - liboctave/numeric/SparseCmplxCHOL.h \ liboctave/numeric/SparseCmplxLU.h \ liboctave/numeric/SparseCmplxQR.h \ - liboctave/numeric/SparsedbleCHOL.h \ liboctave/numeric/SparsedbleLU.h \ liboctave/numeric/SparseQR.h @@ -146,12 +144,11 @@ liboctave/numeric/oct-spparms.cc \ liboctave/numeric/ODES.cc \ liboctave/numeric/Quad.cc \ - liboctave/numeric/SparseCmplxCHOL.cc \ liboctave/numeric/SparseCmplxLU.cc \ liboctave/numeric/SparseCmplxQR.cc \ - liboctave/numeric/SparsedbleCHOL.cc \ liboctave/numeric/SparsedbleLU.cc \ liboctave/numeric/SparseQR.cc \ + liboctave/numeric/sparse-chol-inst.cc \ $(NUMERIC_C_SRC) LIBOCTAVE_TEMPLATE_SRC += \ @@ -159,7 +156,7 @@ liboctave/numeric/base-qr.cc \ liboctave/numeric/bsxfun-defs.cc \ liboctave/numeric/eigs-base.cc \ - liboctave/numeric/sparse-base-chol.cc \ + liboctave/numeric/sparse-chol.cc \ liboctave/numeric/sparse-base-lu.cc \ liboctave/numeric/sparse-dmsolve.cc diff -r 76e0ef020dae -r 307096fb67e1 liboctave/numeric/sparse-base-chol.cc --- a/liboctave/numeric/sparse-base-chol.cc Wed Jan 27 14:15:17 2016 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,289 +0,0 @@ -/* - -Copyright (C) 2005-2015 David Bateman -Copyright (C) 1998-2005 Andy Adler - -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 -. - -*/ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "sparse-base-chol.h" -#include "sparse-util.h" -#include "lo-error.h" -#include "oct-sparse.h" -#include "oct-spparms.h" -#include "quit.h" -#include "MatrixType.h" - -#ifdef HAVE_CHOLMOD -// Can't use CHOLMOD_NAME(drop)(0.0, S, cm). It doesn't treat complex matrices -template -void -sparse_base_chol::sparse_base_chol_rep::drop_zeros - (const cholmod_sparse* S) -{ - chol_elt sik; - octave_idx_type *Sp, *Si; - chol_elt *Sx; - octave_idx_type pdest, k, ncol, p, pend; - - if (! S) - return; - - Sp = static_cast(S->p); - Si = static_cast(S->i); - Sx = static_cast(S->x); - pdest = 0; - ncol = S->ncol; - - for (k = 0; k < ncol; k++) - { - p = Sp[k]; - pend = Sp[k+1]; - Sp[k] = pdest; - for (; p < pend; p++) - { - sik = Sx[p]; - if (CHOLMOD_IS_NONZERO (sik)) - { - if (p != pdest) - { - Si[pdest] = Si[p]; - Sx[pdest] = sik; - } - pdest++; - } - } - } - Sp[ncol] = pdest; -} -#endif - -template -octave_idx_type -sparse_base_chol::sparse_base_chol_rep::init - (const chol_type& a, bool natural, bool force) -{ - volatile octave_idx_type info = 0; - -#ifdef HAVE_CHOLMOD - octave_idx_type a_nr = a.rows (); - octave_idx_type a_nc = a.cols (); - - if (a_nr != a_nc) - (*current_liboctave_error_handler) ("SparseCHOL requires square matrix"); - - cholmod_common *cm = &Common; - - // Setup initial parameters - CHOLMOD_NAME(start) (cm); - cm->prefer_zomplex = false; - - double spu = octave_sparse_params::get_key ("spumoni"); - if (spu == 0.) - { - cm->print = -1; - SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, 0); - } - else - { - cm->print = static_cast (spu) + 2; - SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, &SparseCholPrint); - } - - cm->error_handler = &SparseCholError; - SUITESPARSE_ASSIGN_FPTR2 (divcomplex_func, cm->complex_divide, divcomplex); - SUITESPARSE_ASSIGN_FPTR2 (hypot_func, cm->hypotenuse, hypot); - - cm->final_asis = false; - cm->final_super = false; - cm->final_ll = true; - cm->final_pack = true; - cm->final_monotonic = true; - cm->final_resymbol = false; - - cholmod_sparse A; - cholmod_sparse *ac = &A; - double dummy; - ac->nrow = a_nr; - ac->ncol = a_nc; - - ac->p = a.cidx (); - ac->i = a.ridx (); - ac->nzmax = a.nnz (); - ac->packed = true; - ac->sorted = true; - ac->nz = 0; -#if defined (ENABLE_64) - ac->itype = CHOLMOD_LONG; -#else - ac->itype = CHOLMOD_INT; -#endif - ac->dtype = CHOLMOD_DOUBLE; - ac->stype = 1; -#ifdef OCTAVE_CHOLMOD_TYPE - ac->xtype = OCTAVE_CHOLMOD_TYPE; -#else - ac->xtype = CHOLMOD_REAL; -#endif - - if (a_nr < 1) - ac->x = &dummy; - else - ac->x = a.data (); - - // use natural ordering if no q output parameter - if (natural) - { - cm->nmethods = 1 ; - cm->method[0].ordering = CHOLMOD_NATURAL ; - cm->postorder = false ; - } - - cholmod_factor *Lfactor; - BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; - Lfactor = CHOLMOD_NAME(analyze) (ac, cm); - CHOLMOD_NAME(factorize) (ac, Lfactor, cm); - END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; - - is_pd = cm->status == CHOLMOD_OK; - info = (is_pd ? 0 : cm->status); - - if (is_pd || force) - { - BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; - cond = CHOLMOD_NAME(rcond) (Lfactor, cm); - END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; - - minor_p = Lfactor->minor; - - BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; - Lsparse = CHOLMOD_NAME(factor_to_sparse) (Lfactor, cm); - END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; - - if (minor_p > 0 && minor_p < a_nr) - { - size_t n1 = a_nr + 1; - Lsparse->p = CHOLMOD_NAME(realloc) (minor_p+1, - sizeof(octave_idx_type), - Lsparse->p, &n1, cm); - BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; - CHOLMOD_NAME(reallocate_sparse) - (static_cast(Lsparse->p)[minor_p], Lsparse, cm); - END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; - Lsparse->ncol = minor_p; - } - - drop_zeros (Lsparse); - - if (! natural) - { - perms.resize (a_nr); - for (octave_idx_type i = 0; i < a_nr; i++) - perms(i) = static_cast(Lfactor->Perm)[i]; - } - - static char tmp[] = " "; - - BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; - CHOLMOD_NAME(free_factor) (&Lfactor, cm); - CHOLMOD_NAME(finish) (cm); - CHOLMOD_NAME(print_common) (tmp, cm); - END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; - } - - return info; - -#else - (*current_liboctave_error_handler) - ("support for CHOLMOD was unavailable or disabled when liboctave was built"); -#endif -} - -template -chol_type -sparse_base_chol::L (void) const -{ -#ifdef HAVE_CHOLMOD - cholmod_sparse *m = rep->L (); - octave_idx_type nc = m->ncol; - octave_idx_type nnz = m->nzmax; - chol_type ret (m->nrow, nc, nnz); - for (octave_idx_type j = 0; j < nc+1; j++) - ret.xcidx (j) = static_cast(m->p)[j]; - for (octave_idx_type i = 0; i < nnz; i++) - { - ret.xridx (i) = static_cast(m->i)[i]; - ret.xdata (i) = static_cast(m->x)[i]; - } - return ret; -#else - return chol_type (); -#endif -} - -template -p_type -sparse_base_chol:: -sparse_base_chol_rep::Q (void) const -{ -#ifdef HAVE_CHOLMOD - octave_idx_type n = Lsparse->nrow; - p_type p (n, n, n); - - for (octave_idx_type i = 0; i < n; i++) - { - p.xcidx (i) = i; - p.xridx (i) = static_cast(perms (i)); - p.xdata (i) = 1; - } - p.xcidx (n) = n; - - return p; -#else - return p_type (); -#endif -} - -template -chol_type -sparse_base_chol::inverse (void) const -{ - chol_type retval; -#ifdef HAVE_CHOLMOD - cholmod_sparse *m = rep->L (); - octave_idx_type n = m->ncol; - ColumnVector perms = rep->perm (); - double rcond2; - octave_idx_type info; - MatrixType mattype (MatrixType::Upper); - chol_type linv = L ().hermitian ().inverse (mattype, info, rcond2, 1, 0); - - if (perms.numel () == n) - { - p_type Qc = Q (); - retval = Qc * linv * linv.hermitian () * Qc.transpose (); - } - else - retval = linv * linv.hermitian (); -#endif - return retval; -} diff -r 76e0ef020dae -r 307096fb67e1 liboctave/numeric/sparse-base-chol.h --- a/liboctave/numeric/sparse-base-chol.h Wed Jan 27 14:15:17 2016 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,225 +0,0 @@ -/* - -Copyright (C) 2005-2015 David Bateman -Copyright (C) 1998-2005 Andy Adler - -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 -. - -*/ - -#if ! defined (octave_sparse_base_chol_h) -#define octave_sparse_base_chol_h 1 - -#include "oct-sparse.h" -#include "dColVector.h" - -template -class -sparse_base_chol -{ -protected: -#ifdef HAVE_CHOLMOD - class sparse_base_chol_rep - { - public: - sparse_base_chol_rep (void) - : count (1), Lsparse (0), Common (), is_pd (false), minor_p (0), - perms (), cond (0) - { } - - sparse_base_chol_rep (const chol_type& a, bool natural, bool force) - : count (1), Lsparse (0), Common (), is_pd (false), minor_p (0), - perms (), cond (0) - { - init (a, natural, force); - } - - sparse_base_chol_rep (const chol_type& a, octave_idx_type& info, - bool natural, bool force) - : count (1), Lsparse (0), Common (), is_pd (false), minor_p (0), - perms (), cond (0) - { - info = init (a, natural, force); - } - - ~sparse_base_chol_rep (void) - { - if (is_pd) - CHOLMOD_NAME (free_sparse) (&Lsparse, &Common); - } - - cholmod_sparse * L (void) const { return Lsparse; } - - octave_idx_type P (void) const - { - return (minor_p == static_cast(Lsparse->ncol) ? - 0 : minor_p + 1); - } - - ColumnVector perm (void) const { return perms + 1; } - - p_type Q (void) const; - - bool is_positive_definite (void) const { return is_pd; } - - double rcond (void) const { return cond; } - - octave_refcount count; - - private: - cholmod_sparse *Lsparse; - - cholmod_common Common; - - bool is_pd; - - octave_idx_type minor_p; - - ColumnVector perms; - - double cond; - - octave_idx_type init (const chol_type& a, bool natural, bool force); - - void drop_zeros (const cholmod_sparse* S); - - // No copying! - - sparse_base_chol_rep (const sparse_base_chol_rep&); - - sparse_base_chol_rep& operator = (const sparse_base_chol_rep&); - }; -#else - class sparse_base_chol_rep - { - public: - sparse_base_chol_rep (void) - : count (1), is_pd (false), minor_p (0), perms (), cond (0) { } - - sparse_base_chol_rep (const chol_type& a, bool natural, bool force) - : count (1), is_pd (false), minor_p (0), perms (), cond (0) - { - init (a, natural, force); - } - - sparse_base_chol_rep (const chol_type& a, octave_idx_type& info, - bool natural, bool force) - : count (1), is_pd (false), minor_p (0), perms (), cond (0) - { - info = init (a, natural, force); - } - - ~sparse_base_chol_rep (void) { } - - octave_idx_type P (void) const { return 0; } - - ColumnVector perm (void) const { return perms + 1; } - - p_type Q (void) const; - - bool is_positive_definite (void) const { return is_pd; } - - double rcond (void) const { return cond; } - - octave_refcount count; - - private: - bool is_pd; - - octave_idx_type minor_p; - - ColumnVector perms; - - double cond; - - octave_idx_type init (const chol_type& a, bool natural, bool force); - - // No copying! - - sparse_base_chol_rep (const sparse_base_chol_rep&); - - sparse_base_chol_rep& operator = (const sparse_base_chol_rep&); - }; -#endif - -private: - sparse_base_chol_rep *rep; - -public: - - sparse_base_chol (void) - : rep (new typename - sparse_base_chol - ::sparse_base_chol_rep ()) - { } - - sparse_base_chol (const chol_type& a, bool natural, bool force) - : rep (new typename - sparse_base_chol - ::sparse_base_chol_rep (a, natural, force)) - { } - - sparse_base_chol (const chol_type& a, octave_idx_type& info, - bool natural, bool force) - : rep (new typename - sparse_base_chol - ::sparse_base_chol_rep (a, info, natural, force)) - { } - - sparse_base_chol (const sparse_base_chol& a) - : rep (a.rep) - { rep->count++; } - - virtual ~sparse_base_chol (void) - { - if (--rep->count == 0) - delete rep; - } - - sparse_base_chol& operator = (const sparse_base_chol& a) - { - if (this != &a) - { - if (--rep->count == 0) - delete rep; - - rep = a.rep; - rep->count++; - } - - return *this; - } - - chol_type L (void) const; - - chol_type R (void) const { return L ().hermitian (); } - - octave_idx_type P (void) const { return rep->P (); } - - ColumnVector perm (void) const { return rep->perm (); } - - p_type Q (void) const { return rep->Q (); } - - bool is_positive_definite (void) const - { return rep->is_positive_definite (); } - - double rcond (void) const { return rep->rcond (); } - - chol_type inverse (void) const; -}; - -#endif diff -r 76e0ef020dae -r 307096fb67e1 liboctave/numeric/sparse-chol-inst.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liboctave/numeric/sparse-chol-inst.cc Tue Jan 26 16:30:54 2016 -0500 @@ -0,0 +1,38 @@ +/* + +Copyright (C) 2016 John W. Eaton + +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 +. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "sparse-chol.h" +#include "sparse-chol.cc" + +template class sparse_chol; + +template class sparse_chol; + +template SparseMatrix +chol2inv (const SparseMatrix& r); + +template SparseComplexMatrix +chol2inv (const SparseComplexMatrix& r); diff -r 76e0ef020dae -r 307096fb67e1 liboctave/numeric/sparse-chol.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liboctave/numeric/sparse-chol.cc Tue Jan 26 16:30:54 2016 -0500 @@ -0,0 +1,542 @@ +/* + +Copyright (C) 2005-2015 David Bateman +Copyright (C) 1998-2005 Andy Adler + +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 +. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "sparse-chol.h" +#include "sparse-util.h" +#include "lo-error.h" +#include "oct-sparse.h" +#include "oct-spparms.h" +#include "quit.h" +#include "MatrixType.h" + +template +class sparse_chol::sparse_chol_rep +{ +public: + + sparse_chol_rep (void) + : count (1), is_pd (false), minor_p (0), perms (), cond (0), +#ifdef HAVE_CHOLMOD + Lsparse (0), Common () +#endif + { } + + sparse_chol_rep (const chol_type& a, bool natural, bool force) + : count (1), is_pd (false), minor_p (0), perms (), cond (0), +#ifdef HAVE_CHOLMOD + Lsparse (0), Common () +#endif + { + init (a, natural, force); + } + + sparse_chol_rep (const chol_type& a, octave_idx_type& info, + bool natural, bool force) + : count (1), is_pd (false), minor_p (0), perms (), cond (0), +#ifdef HAVE_CHOLMOD + Lsparse (0), Common () +#endif + { + info = init (a, natural, force); + } + + ~sparse_chol_rep (void) + { +#ifdef HAVE_CHOLMOD + if (is_pd) + CHOLMOD_NAME (free_sparse) (&Lsparse, &Common); +#endif + } + + cholmod_sparse *L (void) const + { +#ifdef HAVE_CHOLMOD + return Lsparse; +#else + return 0; +#endif + } + + octave_idx_type P (void) const + { +#ifdef HAVE_CHOLMOD + return (minor_p == static_cast(Lsparse->ncol) ? + 0 : minor_p + 1); +#else + return 0; +#endif + } + + ColumnVector perm (void) const { return perms + 1; } + + SparseMatrix Q (void) const; + + bool is_positive_definite (void) const { return is_pd; } + + double rcond (void) const { return cond; } + + octave_refcount count; + +private: + + bool is_pd; + + octave_idx_type minor_p; + + ColumnVector perms; + + double cond; + +#ifdef HAVE_CHOLMOD + cholmod_sparse *Lsparse; + + cholmod_common Common; + + void drop_zeros (const cholmod_sparse *S); +#endif + + octave_idx_type init (const chol_type& a, bool natural, bool force); + + // No copying! + + sparse_chol_rep (const sparse_chol_rep&); + + sparse_chol_rep& operator = (const sparse_chol_rep&); +}; + +#ifdef HAVE_CHOLMOD + +// Can't use CHOLMOD_NAME(drop)(0.0, S, cm) because it doesn't treat +// complex matrices. + +template +void +sparse_chol::sparse_chol_rep::drop_zeros (const cholmod_sparse *S) +{ + chol_elt sik; + octave_idx_type *Sp, *Si; + chol_elt *Sx; + octave_idx_type pdest, k, ncol, p, pend; + + if (! S) + return; + + Sp = static_cast(S->p); + Si = static_cast(S->i); + Sx = static_cast(S->x); + pdest = 0; + ncol = S->ncol; + + for (k = 0; k < ncol; k++) + { + p = Sp[k]; + pend = Sp[k+1]; + Sp[k] = pdest; + for (; p < pend; p++) + { + sik = Sx[p]; + if (CHOLMOD_IS_NONZERO (sik)) + { + if (p != pdest) + { + Si[pdest] = Si[p]; + Sx[pdest] = sik; + } + pdest++; + } + } + } + Sp[ncol] = pdest; +} + +// Must provide a specialization for this function. +template +int +get_xtype (void); + +template <> +inline int +get_xtype (void) +{ + return CHOLMOD_REAL; +} + +template <> +inline int +get_xtype (void) +{ + return CHOLMOD_COMPLEX; +} + +#endif + +template +octave_idx_type +sparse_chol::sparse_chol_rep::init (const chol_type& a, + bool natural, bool force) +{ + volatile octave_idx_type info = 0; + +#ifdef HAVE_CHOLMOD + octave_idx_type a_nr = a.rows (); + octave_idx_type a_nc = a.cols (); + + if (a_nr != a_nc) + (*current_liboctave_error_handler) ("sparse_chol requires square matrix"); + + cholmod_common *cm = &Common; + + // Setup initial parameters + CHOLMOD_NAME(start) (cm); + cm->prefer_zomplex = false; + + double spu = octave_sparse_params::get_key ("spumoni"); + if (spu == 0.) + { + cm->print = -1; + SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, 0); + } + else + { + cm->print = static_cast (spu) + 2; + SUITESPARSE_ASSIGN_FPTR (printf_func, cm->print_function, &SparseCholPrint); + } + + cm->error_handler = &SparseCholError; + SUITESPARSE_ASSIGN_FPTR2 (divcomplex_func, cm->complex_divide, divcomplex); + SUITESPARSE_ASSIGN_FPTR2 (hypot_func, cm->hypotenuse, hypot); + + cm->final_asis = false; + cm->final_super = false; + cm->final_ll = true; + cm->final_pack = true; + cm->final_monotonic = true; + cm->final_resymbol = false; + + cholmod_sparse A; + cholmod_sparse *ac = &A; + double dummy; + ac->nrow = a_nr; + ac->ncol = a_nc; + + ac->p = a.cidx (); + ac->i = a.ridx (); + ac->nzmax = a.nnz (); + ac->packed = true; + ac->sorted = true; + ac->nz = 0; +#if defined (ENABLE_64) + ac->itype = CHOLMOD_LONG; +#else + ac->itype = CHOLMOD_INT; +#endif + ac->dtype = CHOLMOD_DOUBLE; + ac->stype = 1; + ac->xtype = get_xtype (); + + if (a_nr < 1) + ac->x = &dummy; + else + ac->x = a.data (); + + // use natural ordering if no q output parameter + if (natural) + { + cm->nmethods = 1 ; + cm->method[0].ordering = CHOLMOD_NATURAL ; + cm->postorder = false ; + } + + cholmod_factor *Lfactor; + BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; + Lfactor = CHOLMOD_NAME(analyze) (ac, cm); + CHOLMOD_NAME(factorize) (ac, Lfactor, cm); + END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; + + is_pd = cm->status == CHOLMOD_OK; + info = (is_pd ? 0 : cm->status); + + if (is_pd || force) + { + BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; + cond = CHOLMOD_NAME(rcond) (Lfactor, cm); + END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; + + minor_p = Lfactor->minor; + + BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; + Lsparse = CHOLMOD_NAME(factor_to_sparse) (Lfactor, cm); + END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; + + if (minor_p > 0 && minor_p < a_nr) + { + size_t n1 = a_nr + 1; + Lsparse->p = CHOLMOD_NAME(realloc) (minor_p+1, + sizeof(octave_idx_type), + Lsparse->p, &n1, cm); + BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; + CHOLMOD_NAME(reallocate_sparse) + (static_cast(Lsparse->p)[minor_p], Lsparse, cm); + END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; + Lsparse->ncol = minor_p; + } + + drop_zeros (Lsparse); + + if (! natural) + { + perms.resize (a_nr); + for (octave_idx_type i = 0; i < a_nr; i++) + perms(i) = static_cast(Lfactor->Perm)[i]; + } + + static char tmp[] = " "; + + BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; + CHOLMOD_NAME(free_factor) (&Lfactor, cm); + CHOLMOD_NAME(finish) (cm); + CHOLMOD_NAME(print_common) (tmp, cm); + END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; + } + + return info; + +#else + (*current_liboctave_error_handler) + ("support for CHOLMOD was unavailable or disabled when liboctave was built"); +#endif +} + +template +SparseMatrix +sparse_chol::sparse_chol_rep::Q (void) const +{ +#ifdef HAVE_CHOLMOD + octave_idx_type n = Lsparse->nrow; + SparseMatrix p (n, n, n); + + for (octave_idx_type i = 0; i < n; i++) + { + p.xcidx (i) = i; + p.xridx (i) = static_cast(perms (i)); + p.xdata (i) = 1; + } + p.xcidx (n) = n; + + return p; +#else + return SparseMatrix (); +#endif +} + +template +sparse_chol::sparse_chol (void) + : rep (new typename sparse_chol::sparse_chol_rep ()) +{ } + +template +sparse_chol::sparse_chol (const chol_type& a, bool natural, + bool force) + : rep (new typename + sparse_chol::sparse_chol_rep (a, natural, force)) +{ } + +template +sparse_chol::sparse_chol (const chol_type& a, octave_idx_type& info, + bool natural, bool force) + : rep (new typename + sparse_chol::sparse_chol_rep (a, info, natural, force)) +{ } + +template +sparse_chol::sparse_chol (const chol_type& a, octave_idx_type& info, + bool natural) + : rep (new typename + sparse_chol::sparse_chol_rep (a, info, natural, false)) +{ } + +template +sparse_chol::sparse_chol (const chol_type& a, octave_idx_type& info) + : rep (new typename + sparse_chol::sparse_chol_rep (a, info, false, false)) +{ } + +template +sparse_chol::sparse_chol (const sparse_chol& a) + : rep (a.rep) +{ + rep->count++; +} + +template +sparse_chol::~sparse_chol (void) +{ + if (--rep->count == 0) + delete rep; +} + +template +sparse_chol& +sparse_chol::operator = (const sparse_chol& a) +{ + if (this != &a) + { + if (--rep->count == 0) + delete rep; + + rep = a.rep; + rep->count++; + } + + return *this; +} + +template +chol_type +sparse_chol::L (void) const +{ +#ifdef HAVE_CHOLMOD + cholmod_sparse *m = rep->L (); + octave_idx_type nc = m->ncol; + octave_idx_type nnz = m->nzmax; + chol_type ret (m->nrow, nc, nnz); + for (octave_idx_type j = 0; j < nc+1; j++) + ret.xcidx (j) = static_cast(m->p)[j]; + for (octave_idx_type i = 0; i < nnz; i++) + { + ret.xridx (i) = static_cast(m->i)[i]; + ret.xdata (i) = static_cast(m->x)[i]; + } + return ret; +#else + return chol_type (); +#endif +} + +template +octave_idx_type +sparse_chol::P (void) const +{ + return rep->P (); +} + +template +ColumnVector +sparse_chol::perm (void) const +{ + return rep->perm (); +} + +template +SparseMatrix +sparse_chol::Q (void) const +{ + return rep->Q (); +} + +template +bool +sparse_chol::is_positive_definite (void) const +{ + return rep->is_positive_definite (); +} + +template +double +sparse_chol::rcond (void) const +{ + return rep->rcond (); +} + +template +chol_type +sparse_chol::inverse (void) const +{ + chol_type retval; +#ifdef HAVE_CHOLMOD + cholmod_sparse *m = rep->L (); + octave_idx_type n = m->ncol; + ColumnVector perms = rep->perm (); + double rcond2; + octave_idx_type info; + MatrixType mattype (MatrixType::Upper); + chol_type linv = L ().hermitian ().inverse (mattype, info, rcond2, 1, 0); + + if (perms.numel () == n) + { + SparseMatrix Qc = Q (); + retval = Qc * linv * linv.hermitian () * Qc.transpose (); + } + else + retval = linv * linv.hermitian (); +#endif + return retval; +} + +template +chol_type +chol2inv (const chol_type& r) +{ + octave_idx_type r_nr = r.rows (); + octave_idx_type r_nc = r.cols (); + chol_type retval; + + if (r_nr != r_nc) + (*current_liboctave_error_handler) ("U must be a square matrix"); + + MatrixType mattype (r); + int typ = mattype.type (false); + double rcond; + octave_idx_type info; + chol_type rinv; + + if (typ == MatrixType::Upper) + { + rinv = r.inverse (mattype, info, rcond, true, false); + retval = rinv.transpose () * rinv; + } + else if (typ == MatrixType::Lower) + { + rinv = r.transpose ().inverse (mattype, info, rcond, true, false); + retval = rinv.transpose () * rinv; + } + else + (*current_liboctave_error_handler) ("U must be a triangular matrix"); + + return retval; +} + +// SparseComplexMatrix specialization (the value for the NATURAL +// parameter in the sparse_chol::sparse_chol_rep constructor is +// different from the default). + +template <> +sparse_chol::sparse_chol (const SparseComplexMatrix& a, + octave_idx_type& info) + : rep (new typename + sparse_chol::sparse_chol_rep (a, info, true, false)) +{ } diff -r 76e0ef020dae -r 307096fb67e1 liboctave/numeric/sparse-chol.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/liboctave/numeric/sparse-chol.h Tue Jan 26 16:30:54 2016 -0500 @@ -0,0 +1,92 @@ +/* + +Copyright (C) 2005-2015 David Bateman +Copyright (C) 1998-2005 Andy Adler + +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 +. + +*/ + +#if ! defined (octave_sparse_chol_h) +#define octave_sparse_chol_h 1 + +#include "CSparse.h" +#include "dColVector.h" +#include "dSparse.h" +#include "oct-sparse.h" + +template +class +sparse_chol +{ +public: + + sparse_chol (void); + + sparse_chol (const chol_type& a, bool natural, bool force); + + sparse_chol (const chol_type& a, octave_idx_type& info, + bool natural, bool force); + + sparse_chol (const chol_type& a, octave_idx_type& info, bool natural); + + sparse_chol (const chol_type& a, octave_idx_type& info); + + sparse_chol (const sparse_chol& a); + + virtual ~sparse_chol (void); + + sparse_chol& operator = (const sparse_chol& a); + + chol_type L (void) const; + + chol_type R (void) const { return L ().hermitian (); } + + octave_idx_type P (void) const; + + ColumnVector perm (void) const; + + SparseMatrix Q (void) const; + + bool is_positive_definite (void) const; + + double rcond (void) const; + + chol_type inverse (void) const; + +protected: + + typedef typename chol_type::element_type chol_elt; + + class sparse_chol_rep; + +private: + + sparse_chol_rep *rep; +}; + +template +chol_type +chol2inv (const chol_type& r); + +// SparseComplexMatrix specialization. + +template <> +sparse_chol::sparse_chol (const SparseComplexMatrix& a, + octave_idx_type& info); + +#endif