/* ========================================================================== */
/* === Core/cholmod_dense =================================================== */
/* ========================================================================== */
/* -----------------------------------------------------------------------------
* CHOLMOD/Core Module. Copyright (C) 2005-2006,
* Univ. of Florida. Author: Timothy A. Davis
* The CHOLMOD/Core Module is licensed under Version 2.1 of the GNU
* Lesser General Public License. See lesser.txt for a text of the license.
* CHOLMOD is also available under other licenses; contact authors for details.
* http://www.cise.ufl.edu/research/sparse
* -------------------------------------------------------------------------- */
/* Core utility routines for the cholmod_dense object:
*
* The solve routines and some of the MatrixOps and Modify routines use dense
* matrices as inputs. These are held in column-major order. With a leading
* dimension of d, the entry in row i and column j is held in x [i+j*d].
*
* Primary routines:
* -----------------
* cholmod_allocate_dense allocate a dense matrix
* cholmod_free_dense free a dense matrix
*
* Secondary routines:
* -------------------
* cholmod_zeros allocate a dense matrix of all zeros
* cholmod_ones allocate a dense matrix of all ones
* cholmod_eye allocate a dense identity matrix
* cholmod_sparse_to_dense create a dense matrix copy of a sparse matrix
* cholmod_dense_to_sparse create a sparse matrix copy of a dense matrix
* cholmod_copy_dense create a copy of a dense matrix
* cholmod_copy_dense2 copy a dense matrix (pre-allocated)
*
* All routines in this file can handle the real, complex, and zomplex cases.
* Pattern-only dense matrices are not supported. cholmod_sparse_to_dense can
* take a pattern-only input sparse matrix, however, and cholmod_dense_to_sparse
* can generate a pattern-only output sparse matrix.
*/
#include "cholmod_internal.h"
#include "cholmod_core.h"
/* ========================================================================== */
/* === TEMPLATE ============================================================= */
/* ========================================================================== */
#define PATTERN
#include "t_cholmod_dense.c"
#define REAL
#include "t_cholmod_dense.c"
#define COMPLEX
#include "t_cholmod_dense.c"
#define ZOMPLEX
#include "t_cholmod_dense.c"
/* ========================================================================== */
/* === cholmod_allocate_dense =============================================== */
/* ========================================================================== */
/* Allocate a dense matrix with leading dimension d. The space is not
* initialized.
*/
cholmod_dense *CHOLMOD(allocate_dense)
(
/* ---- input ---- */
size_t nrow, /* # of rows of matrix */
size_t ncol, /* # of columns of matrix */
size_t d, /* leading dimension */
int xtype, /* CHOLMOD_REAL, _COMPLEX, or _ZOMPLEX */
/* --------------- */
cholmod_common *Common
)
{
cholmod_dense *X ;
size_t nzmax, nzmax0 ;
int ok = TRUE ;
/* ---------------------------------------------------------------------- */
/* get inputs */
/* ---------------------------------------------------------------------- */
RETURN_IF_NULL_COMMON (NULL) ;
if (d < nrow)
{
ERROR (CHOLMOD_INVALID, "leading dimension invalid") ;
return (NULL) ;
}
if (xtype < CHOLMOD_REAL || xtype > CHOLMOD_ZOMPLEX)
{
ERROR (CHOLMOD_INVALID, "xtype invalid") ;
return (NULL) ;
}
/* ensure the dimensions do not cause integer overflow */
(void) CHOLMOD(add_size_t) (ncol, 2, &ok) ;
/* nzmax = MAX (1, d*ncol) ; */
nzmax = CHOLMOD(mult_size_t) (d, ncol, &ok) ;
nzmax = MAX (1, nzmax) ;
if (!ok || nrow > Int_max || ncol > Int_max || nzmax > Int_max)
{
ERROR (CHOLMOD_TOO_LARGE, "problem too large") ;
return (NULL) ;
}
Common->status = CHOLMOD_OK ;
/* ---------------------------------------------------------------------- */
/* allocate header */
/* ---------------------------------------------------------------------- */
X = CHOLMOD(malloc) (sizeof (cholmod_dense), 1, Common) ;
if (Common->status < CHOLMOD_OK)
{
return (NULL) ; /* out of memory */
}
PRINT1 (("cholmod_allocate_dense %d-by-%d nzmax %d xtype %d\n",
nrow, ncol, nzmax, xtype)) ;
X->nrow = nrow ;
X->ncol = ncol ;
X->nzmax = nzmax ;
X->xtype = xtype ;
X->dtype = DTYPE ;
X->x = NULL ;
X->z = NULL ;
X->d = d ;
/* ---------------------------------------------------------------------- */
/* allocate the matrix itself */
/* ---------------------------------------------------------------------- */
nzmax0 = 0 ;
CHOLMOD(realloc_multiple) (nzmax, 0, xtype, NULL, NULL, &(X->x), &(X->z),
&nzmax0, Common) ;
if (Common->status < CHOLMOD_OK)
{
CHOLMOD(free_dense) (&X, Common) ;
return (NULL) ; /* out of memory */
}
return (X) ;
}
/* ========================================================================== */
/* === cholmod_zeros ======================================================== */
/* ========================================================================== */
/* Allocate a dense matrix and set it to zero */
cholmod_dense *CHOLMOD(zeros)
(
/* ---- input ---- */
size_t nrow, /* # of rows of matrix */
size_t ncol, /* # of columns of matrix */
int xtype, /* CHOLMOD_REAL, _COMPLEX, or _ZOMPLEX */
/* --------------- */
cholmod_common *Common
)
{
cholmod_dense *X ;
double *Xx, *Xz ;
Int i, nz ;
/* ---------------------------------------------------------------------- */
/* allocate a dense matrix and set it to zero */
/* ---------------------------------------------------------------------- */
RETURN_IF_NULL_COMMON (NULL) ;
X = CHOLMOD(allocate_dense) (nrow, ncol, nrow, xtype, Common) ;
if (Common->status < CHOLMOD_OK)
{
return (NULL) ; /* NULL Common, out of memory, or inputs invalid */
}
Xx = X->x ;
Xz = X->z ;
nz = MAX (1, X->nzmax) ;
switch (xtype)
{
case CHOLMOD_REAL:
for (i = 0 ; i < nz ; i++)
{
Xx [i] = 0 ;
}
break ;
case CHOLMOD_COMPLEX:
for (i = 0 ; i < 2*nz ; i++)
{
Xx [i] = 0 ;
}
break ;
case CHOLMOD_ZOMPLEX:
for (i = 0 ; i < nz ; i++)
{
Xx [i] = 0 ;
}
for (i = 0 ; i < nz ; i++)
{
Xz [i] = 0 ;
}
break ;
}
return (X) ;
}
/* ========================================================================== */
/* === cholmod_ones ========================================================= */
/* ========================================================================== */
/* Allocate a dense matrix and set it to zero */
cholmod_dense *CHOLMOD(ones)
(
/* ---- input ---- */
size_t nrow, /* # of rows of matrix */
size_t ncol, /* # of columns of matrix */
int xtype, /* CHOLMOD_REAL, _COMPLEX, or _ZOMPLEX */
/* --------------- */
cholmod_common *Common
)
{
cholmod_dense *X ;
double *Xx, *Xz ;
Int i, nz ;
/* ---------------------------------------------------------------------- */
/* allocate a dense matrix and set it to all ones */
/* ---------------------------------------------------------------------- */
RETURN_IF_NULL_COMMON (NULL) ;
X = CHOLMOD(allocate_dense) (nrow, ncol, nrow, xtype, Common) ;
if (Common->status < CHOLMOD_OK)
{
return (NULL) ; /* NULL Common, out of memory, or inputs invalid */
}
Xx = X->x ;
Xz = X->z ;
nz = MAX (1, X->nzmax) ;
switch (xtype)
{
case CHOLMOD_REAL:
for (i = 0 ; i < nz ; i++)
{
Xx [i] = 1 ;
}
break ;
case CHOLMOD_COMPLEX:
for (i = 0 ; i < nz ; i++)
{
Xx [2*i ] = 1 ;
Xx [2*i+1] = 0 ;
}
break ;
case CHOLMOD_ZOMPLEX:
for (i = 0 ; i < nz ; i++)
{
Xx [i] = 1 ;
}
for (i = 0 ; i < nz ; i++)
{
Xz [i] = 0 ;
}
break ;
}
return (X) ;
}
/* ========================================================================== */
/* === cholmod_eye ========================================================== */
/* ========================================================================== */
/* Allocate a dense matrix and set it to the identity matrix */
cholmod_dense *CHOLMOD(eye)
(
/* ---- input ---- */
size_t nrow, /* # of rows of matrix */
size_t ncol, /* # of columns of matrix */
int xtype, /* CHOLMOD_REAL, _COMPLEX, or _ZOMPLEX */
/* --------------- */
cholmod_common *Common
)
{
cholmod_dense *X ;
double *Xx, *Xz ;
Int i, n, nz ;
/* ---------------------------------------------------------------------- */
/* allocate a dense matrix and set it to the identity matrix */
/* ---------------------------------------------------------------------- */
RETURN_IF_NULL_COMMON (NULL) ;
X = CHOLMOD(zeros) (nrow, ncol, xtype, Common) ;
if (Common->status < CHOLMOD_OK)
{
return (NULL) ; /* NULL Common, out of memory, or inputs invalid */
}
nz = MAX (1, nrow*ncol) ;
Xx = X->x ;
Xz = X->z ;
n = MIN (nrow, ncol) ;
switch (xtype)
{
case CHOLMOD_REAL:
case CHOLMOD_ZOMPLEX:
for (i = 0 ; i < n ; i++)
{
Xx [i + i*nrow] = 1 ;
}
break ;
case CHOLMOD_COMPLEX:
for (i = 0 ; i < n ; i++)
{
Xx [2 * (i + i*nrow)] = 1 ;
}
break ;
}
return (X) ;
}
/* ========================================================================== */
/* === cholmod_free_dense =================================================== */
/* ========================================================================== */
/* free a dense matrix
*
* workspace: none
*/
int CHOLMOD(free_dense)
(
/* ---- in/out --- */
cholmod_dense **XHandle, /* dense matrix to deallocate, NULL on output */
/* --------------- */
cholmod_common *Common
)
{
cholmod_dense *X ;
RETURN_IF_NULL_COMMON (FALSE) ;
if (XHandle == NULL)
{
/* nothing to do */
return (TRUE) ;
}
X = *XHandle ;
if (X == NULL)
{
/* nothing to do */
return (TRUE) ;
}
switch (X->xtype)
{
case CHOLMOD_REAL:
X->x = CHOLMOD(free) (X->nzmax, sizeof (double), X->x, Common) ;
break ;
case CHOLMOD_COMPLEX:
X->x = CHOLMOD(free) (X->nzmax, 2*sizeof (double), X->x, Common) ;
break ;
case CHOLMOD_ZOMPLEX:
X->x = CHOLMOD(free) (X->nzmax, sizeof (double), X->x, Common) ;
X->z = CHOLMOD(free) (X->nzmax, sizeof (double), X->z, Common) ;
break ;
}
*XHandle = CHOLMOD(free) (1, sizeof (cholmod_dense), (*XHandle), Common) ;
return (TRUE) ;
}
/* ========================================================================== */
/* === cholmod_sparse_to_dense ============================================== */
/* ========================================================================== */
/* Convert a sparse matrix to a dense matrix.
* The output dense matrix has the same xtype as the input sparse matrix,
* except that a pattern-only sparse matrix A is converted into a real dense
* matrix X, with 1's and 0's. All xtypes are supported.
*/
cholmod_dense *CHOLMOD(sparse_to_dense)
(
/* ---- input ---- */
cholmod_sparse *A, /* matrix to copy */
/* --------------- */
cholmod_common *Common
)
{
cholmod_dense *X = NULL ;
/* ---------------------------------------------------------------------- */
/* check inputs */
/* ---------------------------------------------------------------------- */
RETURN_IF_NULL_COMMON (NULL) ;
RETURN_IF_NULL (A, NULL) ;
RETURN_IF_XTYPE_INVALID (A, CHOLMOD_PATTERN, CHOLMOD_ZOMPLEX, NULL) ;
if (A->stype && A->nrow != A->ncol)
{
ERROR (CHOLMOD_INVALID, "matrix invalid") ;
return (NULL) ;
}
Common->status = CHOLMOD_OK ;
ASSERT (CHOLMOD(dump_sparse) (A, "A", Common) >= 0) ;
/* ---------------------------------------------------------------------- */
/* convert the matrix, using template routine */
/* ---------------------------------------------------------------------- */
switch (A->xtype)
{
case CHOLMOD_PATTERN:
X = p_cholmod_sparse_to_dense (A, Common) ;
break ;
case CHOLMOD_REAL:
X = r_cholmod_sparse_to_dense (A, Common) ;
break ;
case CHOLMOD_COMPLEX:
X = c_cholmod_sparse_to_dense (A, Common) ;
break ;
case CHOLMOD_ZOMPLEX:
X = z_cholmod_sparse_to_dense (A, Common) ;
break ;
}
return (X) ;
}
/* ========================================================================== */
/* === cholmod_dense_to_sparse ============================================== */
/* ========================================================================== */
/* Convert a dense matrix to a sparse matrix, similar to the MATLAB statements:
*
* C = sparse (X) values = TRUE
* C = spones (sparse (X)) values = FALSE
*
* except that X must be double (it can be of many different types in MATLAB)
*
* The resulting sparse matrix C has the same numeric xtype as the input dense
* matrix X, unless "values" is FALSE (in which case C is real, where C(i,j)=1
* if (i,j) is an entry in X.
*/
cholmod_sparse *CHOLMOD(dense_to_sparse)
(
/* ---- input ---- */
cholmod_dense *X, /* matrix to copy */
int values, /* TRUE if values to be copied, FALSE otherwise */
/* --------------- */
cholmod_common *Common
)
{
cholmod_sparse *C = NULL ;
DEBUG (CHOLMOD(dump_dense) (X, "X", Common)) ;
/* ---------------------------------------------------------------------- */
/* check inputs */
/* ---------------------------------------------------------------------- */
RETURN_IF_NULL_COMMON (NULL) ;
RETURN_IF_NULL (X, NULL) ;
RETURN_IF_XTYPE_INVALID (X, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, NULL) ;
if (X->d < X->nrow)
{
ERROR (CHOLMOD_INVALID, "matrix invalid") ;
return (NULL) ;
}
Common->status = CHOLMOD_OK ;
/* ---------------------------------------------------------------------- */
/* convert the matrix, using template routine */
/* ---------------------------------------------------------------------- */
switch (X->xtype)
{
case CHOLMOD_REAL:
C = r_cholmod_dense_to_sparse (X, values, Common) ;
break ;
case CHOLMOD_COMPLEX:
C = c_cholmod_dense_to_sparse (X, values, Common) ;
break ;
case CHOLMOD_ZOMPLEX:
C = z_cholmod_dense_to_sparse (X, values, Common) ;
break ;
}
return (C) ;
}
/* ========================================================================== */
/* === cholmod_copy_dense2 ================================================== */
/* ========================================================================== */
/* Y = X, where X and Y are both already allocated. The leading dimensions of
* X and Y may differ, but both must be >= the # of rows in X and Y.
* Entries in rows nrow to d-1 are not copied from X, since the space might not
* be initialized. Y->nzmax is unchanged. X->nzmax is typically
* (X->d)*(X->ncol), but a user might modify that condition outside of any
* CHOLMOD routine.
*
* The two dense matrices X and Y must have the same numeric xtype.
*/
int CHOLMOD(copy_dense2)
(
/* ---- input ---- */
cholmod_dense *X, /* matrix to copy */
/* ---- output --- */
cholmod_dense *Y, /* copy of matrix X */
/* --------------- */
cholmod_common *Common
)
{
/* ---------------------------------------------------------------------- */
/* check inputs */
/* ---------------------------------------------------------------------- */
RETURN_IF_NULL_COMMON (FALSE) ;
RETURN_IF_NULL (X, FALSE) ;
RETURN_IF_NULL (Y, FALSE) ;
RETURN_IF_XTYPE_INVALID (X, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, FALSE) ;
RETURN_IF_XTYPE_INVALID (Y, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, FALSE) ;
if (X->nrow != Y->nrow || X->ncol != Y->ncol || X->xtype != Y->xtype)
{
ERROR (CHOLMOD_INVALID, "X and Y must have same dimensions and xtype") ;
return (FALSE) ;
}
if (X->d < X->nrow || Y->d < Y->nrow
|| (X->d * X->ncol) > X->nzmax || (Y->d * Y->ncol) > Y->nzmax)
{
ERROR (CHOLMOD_INVALID, "X and/or Y invalid") ;
return (FALSE) ;
}
Common->status = CHOLMOD_OK ;
/* ---------------------------------------------------------------------- */
/* copy the matrix, using template routine */
/* ---------------------------------------------------------------------- */
switch (X->xtype)
{
case CHOLMOD_REAL:
r_cholmod_copy_dense2 (X, Y) ;
break ;
case CHOLMOD_COMPLEX:
c_cholmod_copy_dense2 (X, Y) ;
break ;
case CHOLMOD_ZOMPLEX:
z_cholmod_copy_dense2 (X, Y) ;
break ;
}
return (TRUE) ;
}
/* ========================================================================== */
/* === cholmod_copy_dense =================================================== */
/* ========================================================================== */
/* Y = X, copy a dense matrix */
cholmod_dense *CHOLMOD(copy_dense)
(
/* ---- input ---- */
cholmod_dense *X, /* matrix to copy */
/* --------------- */
cholmod_common *Common
)
{
cholmod_dense *Y ;
/* ---------------------------------------------------------------------- */
/* check inputs */
/* ---------------------------------------------------------------------- */
RETURN_IF_NULL_COMMON (NULL) ;
RETURN_IF_NULL (X, NULL) ;
RETURN_IF_XTYPE_INVALID (X, CHOLMOD_REAL, CHOLMOD_ZOMPLEX, NULL) ;
Common->status = CHOLMOD_OK ;
/* ---------------------------------------------------------------------- */
/* allocate result */
/* ---------------------------------------------------------------------- */
Y = CHOLMOD(allocate_dense) (X->nrow, X->ncol, X->d, X->xtype, Common) ;
if (Common->status < CHOLMOD_OK)
{
return (NULL) ; /* out of memory or X invalid */
}
/* ---------------------------------------------------------------------- */
/* Y = X */
/* ---------------------------------------------------------------------- */
/* This cannot fail (X and Y are allocated, and have the same nrow, ncol
* d, and xtype) */
CHOLMOD(copy_dense2) (X, Y, Common) ;
/* ---------------------------------------------------------------------- */
/* return result */
/* ---------------------------------------------------------------------- */
return (Y) ;
}
syntax highlighted by Code2HTML, v. 0.9.1