Mercurial > octave
changeset 32693:ecda14873740 stable
Fix memory leak in min2norm_solve family of functions.
* sparse-qr.cc (min2norm_solve): For each template specialization, call
cholmod_l_free_dense() or cholmod_l_free_sparse() on the output of
library call SuiteSparseQR_min2norm(). Rename temporary variable "vec"
to "xdata" for clarity. Use consistent arrangement of variable declarations
and function calls in each template specialization.
author | Rik <rik@octave.org> |
---|---|
date | Sun, 07 Jan 2024 18:09:28 -0800 |
parents | 9fe15105eba6 |
children | 1ea103a6aa31 1f6b33749810 |
files | liboctave/numeric/sparse-qr.cc |
diffstat | 1 files changed, 191 insertions(+), 212 deletions(-) [+] |
line wrap: on
line diff
--- a/liboctave/numeric/sparse-qr.cc Wed Jan 03 16:24:29 2024 -0800 +++ b/liboctave/numeric/sparse-qr.cc Sun Jan 07 18:09:28 2024 -0800 @@ -2764,10 +2764,10 @@ template <> OCTAVE_API Matrix sparse_qr<SparseMatrix>::min2norm_solve<MArray<double>, Matrix> -(const SparseMatrix& a, const MArray<double>& b, - octave_idx_type& info, int order) + (const SparseMatrix& a, const MArray<double>& b, octave_idx_type& info, int order) { info = -1; + octave_idx_type b_nc = b.cols (); octave_idx_type nc = a.cols (); Matrix x (nc, b_nc); @@ -2781,30 +2781,30 @@ X = SuiteSparseQR_min2norm<double> (order, SPQR_DEFAULT_TOL, &A, &B, &cc); spqr_error_handler (&cc); - double *vec = x.fortran_vec (); + double *xdata = x.fortran_vec (); for (volatile octave_idx_type i = 0; i < nc * b_nc; i++) - vec[i] = reinterpret_cast<double *> (X->x)[i]; - + xdata[i] = reinterpret_cast<double *> (X->x)[i]; info = 0; + if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) { delete [] reinterpret_cast<SuiteSparse_long *> (A.p); delete [] reinterpret_cast<SuiteSparse_long *> (A.i); } + cholmod_l_free_dense (&X, &cc); cholmod_l_finish (&cc); return x; - } template <> template <> OCTAVE_API SparseMatrix sparse_qr<SparseMatrix>::min2norm_solve<SparseMatrix, SparseMatrix> -(const SparseMatrix& a, const SparseMatrix& b, octave_idx_type& info, - int order) + (const SparseMatrix& a, const SparseMatrix& b, octave_idx_type& info, int order) { info = -1; + SparseMatrix x; cholmod_common cc; @@ -2816,203 +2816,9 @@ X = SuiteSparseQR_min2norm<double> (order, SPQR_DEFAULT_TOL, &A, &B, &cc); spqr_error_handler (&cc); - if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) - { - delete [] reinterpret_cast<SuiteSparse_long *> (A.p); - delete [] reinterpret_cast<SuiteSparse_long *> (A.i); - delete [] reinterpret_cast<SuiteSparse_long *> (B.p); - delete [] reinterpret_cast<SuiteSparse_long *> (B.i); - } - x = rcs2ros (X, &cc); - cholmod_l_finish (&cc); - info = 0; - - return x; - -} - -template <> -template <> -OCTAVE_API ComplexMatrix -sparse_qr<SparseMatrix>::min2norm_solve<MArray<Complex>, ComplexMatrix> -(const SparseMatrix& a, const MArray<Complex>& b, - octave_idx_type& info, int order) -{ - info = -1; - - octave_idx_type b_nc = b.cols (); - octave_idx_type nc = a.cols (); - - ComplexMatrix x (nc, b_nc); - - cholmod_common cc; - - cholmod_l_start (&cc); - - cholmod_sparse *A = ros2ccs (a, &cc); - cholmod_dense B = cod2ccd (b); - cholmod_dense *X; - - X = SuiteSparseQR_min2norm<Complex> (order, SPQR_DEFAULT_TOL, A, &B, &cc); - spqr_error_handler (&cc); - - Complex *vec = x.fortran_vec (); - for (volatile octave_idx_type i = 0; i < nc * b_nc; i++) - vec[i] = reinterpret_cast<Complex *> (X->x)[i]; - - cholmod_l_free_sparse (&A, &cc); - cholmod_l_finish (&cc); - - info = 0; - - return x; - -} - -template <> -template <> -OCTAVE_API SparseComplexMatrix -sparse_qr<SparseMatrix>::min2norm_solve<SparseComplexMatrix, - SparseComplexMatrix> - (const SparseMatrix& a, const SparseComplexMatrix& b, - octave_idx_type& info, int order) -{ - info = -1; - - cholmod_common cc; - - cholmod_l_start (&cc); - - cholmod_sparse *A = ros2ccs (a, &cc); - cholmod_sparse B = cos2ccs (b); - cholmod_sparse *X; - - X = SuiteSparseQR_min2norm<Complex> (order, SPQR_DEFAULT_TOL, A, &B, &cc); - spqr_error_handler (&cc); - - cholmod_l_free_sparse (&A, &cc); - if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) - { - delete [] reinterpret_cast<SuiteSparse_long *> (B.p); - delete [] reinterpret_cast<SuiteSparse_long *> (B.i); - } - cholmod_l_finish (&cc); - - SparseComplexMatrix ret = ccs2cos (X, &cc); - info = 0; - return ret; - -} - -template <> -template <> -OCTAVE_API ComplexMatrix -sparse_qr<SparseComplexMatrix>::min2norm_solve<MArray<Complex>, - ComplexMatrix> - (const SparseComplexMatrix& a, const MArray<Complex>& b, - octave_idx_type& info, int order) -{ - info = -1; - octave_idx_type b_nc = b.cols (); - octave_idx_type nc = a.cols (); - ComplexMatrix x (nc, b_nc); - - cholmod_common cc; - - cholmod_l_start (&cc); - - cholmod_sparse A = cos2ccs (a); - cholmod_dense B = cod2ccd (b); - cholmod_dense *X; - - X = SuiteSparseQR_min2norm<Complex> (order, SPQR_DEFAULT_TOL, &A, &B, &cc); - spqr_error_handler (&cc); - - Complex *vec = x.fortran_vec (); - for (volatile octave_idx_type i = 0; i < nc * b_nc; i++) - vec[i] = reinterpret_cast<Complex *> (X->x)[i]; - - if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) - { - delete [] reinterpret_cast<SuiteSparse_long *> (A.p); - delete [] reinterpret_cast<SuiteSparse_long *> (A.i); - } - cholmod_l_finish (&cc); - - info = 0; - - return x; - -} - -template <> -template <> -OCTAVE_API ComplexMatrix -sparse_qr<SparseComplexMatrix>::min2norm_solve<MArray<double>, - ComplexMatrix> - (const SparseComplexMatrix& a, const MArray<double>& b, - octave_idx_type& info, int order) -{ - info = -1; - - octave_idx_type b_nc = b.cols (); - octave_idx_type nc = a.cols (); - ComplexMatrix x (nc, b_nc); - - cholmod_common cc; - - cholmod_l_start (&cc); - - cholmod_sparse A = cos2ccs (a); - cholmod_dense *B = rod2ccd (b, &cc); - cholmod_dense *X; - - X = SuiteSparseQR_min2norm<Complex> (order, SPQR_DEFAULT_TOL, &A, B, &cc); - spqr_error_handler (&cc); - - Complex *vec = x.fortran_vec (); - - for (volatile octave_idx_type i = 0; i < nc * b_nc; i++) - vec[i] = reinterpret_cast<Complex *> (X->x)[i]; - - if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) - { - delete [] reinterpret_cast<SuiteSparse_long *> (A.p); - delete [] reinterpret_cast<SuiteSparse_long *> (A.i); - } - cholmod_l_free_dense (&B, &cc); - cholmod_l_finish (&cc); - - info = 0; - - return x; - -} - -template <> -template <> -OCTAVE_API SparseComplexMatrix -sparse_qr<SparseComplexMatrix>::min2norm_solve<SparseComplexMatrix, - SparseComplexMatrix> - (const SparseComplexMatrix& a, const SparseComplexMatrix& b, - octave_idx_type& info, int order) -{ - info = -1; - - cholmod_common cc; - - cholmod_l_start (&cc); - - cholmod_sparse A = cos2ccs (a); - cholmod_sparse B = cos2ccs (b); - cholmod_sparse *X; - - X = SuiteSparseQR_min2norm<Complex> (order, SPQR_DEFAULT_TOL, &A, &B, &cc); - spqr_error_handler (&cc); - if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) { delete [] reinterpret_cast<SuiteSparse_long *> (A.p); @@ -3020,28 +2826,202 @@ delete [] reinterpret_cast<SuiteSparse_long *> (B.p); delete [] reinterpret_cast<SuiteSparse_long *> (B.i); } + cholmod_l_free_sparse (&X, &cc); cholmod_l_finish (&cc); + return x; +} + +template <> +template <> +OCTAVE_API ComplexMatrix +sparse_qr<SparseMatrix>::min2norm_solve<MArray<Complex>, ComplexMatrix> + (const SparseMatrix& a, const MArray<Complex>& b, octave_idx_type& info, int order) +{ + info = -1; + + octave_idx_type b_nc = b.cols (); + octave_idx_type nc = a.cols (); + ComplexMatrix x (nc, b_nc); + cholmod_common cc; + + cholmod_l_start (&cc); + cholmod_sparse *A = ros2ccs (a, &cc); + cholmod_dense B = cod2ccd (b); + cholmod_dense *X; + + X = SuiteSparseQR_min2norm<Complex> (order, SPQR_DEFAULT_TOL, A, &B, &cc); + spqr_error_handler (&cc); + + Complex *xdata = x.fortran_vec (); + for (volatile octave_idx_type i = 0; i < nc * b_nc; i++) + xdata[i] = reinterpret_cast<Complex *> (X->x)[i]; info = 0; - return ccs2cos (X, &cc); - + cholmod_l_free_sparse (&A, &cc); + cholmod_l_free_dense (&X, &cc); + cholmod_l_finish (&cc); + + return x; } template <> template <> OCTAVE_API SparseComplexMatrix -sparse_qr<SparseComplexMatrix>::min2norm_solve<SparseMatrix, - SparseComplexMatrix> - (const SparseComplexMatrix& a, const SparseMatrix& b, - octave_idx_type& info, int order) +sparse_qr<SparseMatrix>::min2norm_solve<SparseComplexMatrix, SparseComplexMatrix> + (const SparseMatrix& a, const SparseComplexMatrix& b, octave_idx_type& info, int order) { info = -1; cholmod_common cc; cholmod_l_start (&cc); - + cholmod_sparse *A = ros2ccs (a, &cc); + cholmod_sparse B = cos2ccs (b); + cholmod_sparse *X; + + X = SuiteSparseQR_min2norm<Complex> (order, SPQR_DEFAULT_TOL, A, &B, &cc); + spqr_error_handler (&cc); + + SparseComplexMatrix ret = ccs2cos (X, &cc); + info = 0; + + if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) + { + delete [] reinterpret_cast<SuiteSparse_long *> (B.p); + delete [] reinterpret_cast<SuiteSparse_long *> (B.i); + } + cholmod_l_free_sparse (&A, &cc); + cholmod_l_free_sparse (&X, &cc); + cholmod_l_finish (&cc); + + return ret; +} + +template <> +template <> +OCTAVE_API ComplexMatrix +sparse_qr<SparseComplexMatrix>::min2norm_solve<MArray<Complex>, ComplexMatrix> + (const SparseComplexMatrix& a, const MArray<Complex>& b, octave_idx_type& info, int order) +{ + info = -1; + + octave_idx_type b_nc = b.cols (); + octave_idx_type nc = a.cols (); + ComplexMatrix x (nc, b_nc); + cholmod_common cc; + + cholmod_l_start (&cc); + cholmod_sparse A = cos2ccs (a); + cholmod_dense B = cod2ccd (b); + cholmod_dense *X; + + X = SuiteSparseQR_min2norm<Complex> (order, SPQR_DEFAULT_TOL, &A, &B, &cc); + spqr_error_handler (&cc); + + Complex *xdata = x.fortran_vec (); + for (volatile octave_idx_type i = 0; i < nc * b_nc; i++) + xdata[i] = reinterpret_cast<Complex *> (X->x)[i]; + info = 0; + + if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) + { + delete [] reinterpret_cast<SuiteSparse_long *> (A.p); + delete [] reinterpret_cast<SuiteSparse_long *> (A.i); + } + cholmod_l_free_dense (&X, &cc); + cholmod_l_finish (&cc); + + return x; +} + +// FIXME: 2024/01/07: This template specialization does not appear to be +// reachable from current Octave code calling qrsolve from sparse-dmsolve.cc. +template <> +template <> +OCTAVE_API ComplexMatrix +sparse_qr<SparseComplexMatrix>::min2norm_solve<MArray<double>, ComplexMatrix> + (const SparseComplexMatrix& a, const MArray<double>& b, octave_idx_type& info, int order) +{ + info = -1; + + octave_idx_type b_nc = b.cols (); + octave_idx_type nc = a.cols (); + ComplexMatrix x (nc, b_nc); + cholmod_common cc; + + cholmod_l_start (&cc); + cholmod_sparse A = cos2ccs (a); + cholmod_dense *B = rod2ccd (b, &cc); + cholmod_dense *X; + + X = SuiteSparseQR_min2norm<Complex> (order, SPQR_DEFAULT_TOL, &A, B, &cc); + spqr_error_handler (&cc); + + Complex *xdata = x.fortran_vec (); + for (volatile octave_idx_type i = 0; i < nc * b_nc; i++) + xdata[i] = reinterpret_cast<Complex *> (X->x)[i]; + info = 0; + + if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) + { + delete [] reinterpret_cast<SuiteSparse_long *> (A.p); + delete [] reinterpret_cast<SuiteSparse_long *> (A.i); + } + cholmod_l_free_dense (&B, &cc); + cholmod_l_free_dense (&X, &cc); + cholmod_l_finish (&cc); + + return x; +} + +template <> +template <> +OCTAVE_API SparseComplexMatrix +sparse_qr<SparseComplexMatrix>::min2norm_solve<SparseComplexMatrix, SparseComplexMatrix> + (const SparseComplexMatrix& a, const SparseComplexMatrix& b, octave_idx_type& info, int order) +{ + info = -1; + + cholmod_common cc; + + cholmod_l_start (&cc); + cholmod_sparse A = cos2ccs (a); + cholmod_sparse B = cos2ccs (b); + cholmod_sparse *X; + + X = SuiteSparseQR_min2norm<Complex> (order, SPQR_DEFAULT_TOL, &A, &B, &cc); + spqr_error_handler (&cc); + + SparseComplexMatrix ret = ccs2cos (X, &cc); + info = 0; + + if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) + { + delete [] reinterpret_cast<SuiteSparse_long *> (A.p); + delete [] reinterpret_cast<SuiteSparse_long *> (A.i); + delete [] reinterpret_cast<SuiteSparse_long *> (B.p); + delete [] reinterpret_cast<SuiteSparse_long *> (B.i); + } + cholmod_l_free_sparse (&X, &cc); + cholmod_l_finish (&cc); + + return ret; +} + +// FIXME: 2024/01/07: This template specialization does not appear to be +// reachable from current Octave code calling qrsolve from sparse-dmsolve.cc. +template <> +template <> +OCTAVE_API SparseComplexMatrix +sparse_qr<SparseComplexMatrix>::min2norm_solve<SparseMatrix, SparseComplexMatrix> + (const SparseComplexMatrix& a, const SparseMatrix& b, octave_idx_type& info, int order) +{ + info = -1; + + cholmod_common cc; + + cholmod_l_start (&cc); cholmod_sparse A = cos2ccs (a); cholmod_sparse *B = ros2ccs (b, &cc); cholmod_sparse *X; @@ -3050,6 +3030,7 @@ spqr_error_handler (&cc); SparseComplexMatrix ret = ccs2cos (X, &cc); + info = 0; if (sizeof (octave_idx_type) != sizeof (SuiteSparse_long)) { @@ -3057,12 +3038,10 @@ delete [] reinterpret_cast<SuiteSparse_long *> (A.i); } cholmod_l_free_sparse (&B, &cc); + cholmod_l_free_sparse (&X, &cc); cholmod_l_finish (&cc); - info = 0; - return ret; - } #endif