/* ========================================================================== */
/* === MatrixOps/cholmod_scale ============================================== */
/* ========================================================================== */
/* -----------------------------------------------------------------------------
* CHOLMOD/MatrixOps Module. Copyright (C) 2005-2006, Timothy A. Davis
* The CHOLMOD/MatrixOps Module is licensed under Version 2.0 of the GNU
* General Public License. See gpl.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
* -------------------------------------------------------------------------- */
/* scale a matrix: A = diag(s)*A, A*diag(s), s*A, or diag(s)*A*diag(s)
*
* A can be of any type (packed/unpacked, upper/lower/unsymmetric).
* The symmetry of A is ignored; all entries in the matrix are modified.
*
* If A is m-by-n unsymmetric but scaled symmtrically, the result is
* A = diag (s (1:m)) * A * diag (s (1:n)).
*
* Note: diag(s) should be interpretted as spdiags(s,0,n,n) where n=length(s).
*
* Row or column scaling of a symmetric matrix still results in a symmetric
* matrix, since entries are still ignored by other routines.
* For example, when row-scaling a symmetric matrix where just the upper
* triangular part is stored (and lower triangular entries ignored)
* A = diag(s)*triu(A) is performed, where the result A is also
* symmetric-upper. This has the effect of modifying the implicit lower
* triangular part. In MATLAB notation:
*
* U = diag(s)*triu(A) ;
* L = tril (U',-1)
* A = L + U ;
*
* The scale parameter determines the kind of scaling to perform:
*
* CHOLMOD_SCALAR: s[0]*A
* CHOLMOD_ROW: diag(s)*A
* CHOLMOD_COL: A*diag(s)
* CHOLMOD_SYM: diag(s)*A*diag(s)
*
* The size of S depends on the scale parameter:
*
* CHOLMOD_SCALAR: size 1
* CHOLMOD_ROW: size nrow-by-1 or 1-by-nrow
* CHOLMOD_COL: size ncol-by-1 or 1-by-ncol
* CHOLMOD_SYM: size max(nrow,ncol)-by-1, or 1-by-max(nrow,ncol)
*
* workspace: none
*
* Only real matrices are supported.
*/
#ifndef NMATRIXOPS
#include "cholmod_internal.h"
#include "cholmod_matrixops.h"
/* ========================================================================== */
/* === cholmod_scale ======================================================== */
/* ========================================================================== */
int CHOLMOD(scale)
(
/* ---- input ---- */
cholmod_dense *S, /* scale factors (scalar or vector) */
int scale, /* type of scaling to compute */
/* ---- in/out --- */
cholmod_sparse *A, /* matrix to scale */
/* --------------- */
cholmod_common *Common
)
{
double t ;
double *Ax, *s ;
Int *Ap, *Anz, *Ai ;
Int packed, j, ncol, nrow, p, pend, sncol, snrow, nn, ok ;
/* ---------------------------------------------------------------------- */
/* check inputs */
/* ---------------------------------------------------------------------- */
RETURN_IF_NULL_COMMON (FALSE) ;
RETURN_IF_NULL (A, FALSE) ;
RETURN_IF_NULL (S, FALSE) ;
RETURN_IF_XTYPE_INVALID (A, CHOLMOD_REAL, CHOLMOD_REAL, FALSE) ;
RETURN_IF_XTYPE_INVALID (S, CHOLMOD_REAL, CHOLMOD_REAL, FALSE) ;
ncol = A->ncol ;
nrow = A->nrow ;
sncol = S->ncol ;
snrow = S->nrow ;
if (scale == CHOLMOD_SCALAR)
{
ok = (snrow == 1 && sncol == 1) ;
}
else if (scale == CHOLMOD_ROW)
{
ok = (snrow == nrow && sncol == 1) || (snrow == 1 && sncol == nrow) ;
}
else if (scale == CHOLMOD_COL)
{
ok = (snrow == ncol && sncol == 1) || (snrow == 1 && sncol == ncol) ;
}
else if (scale == CHOLMOD_SYM)
{
nn = MAX (nrow, ncol) ;
ok = (snrow == nn && sncol == 1) || (snrow == 1 && sncol == nn) ;
}
else
{
/* scale invalid */
ERROR (CHOLMOD_INVALID, "invalid scaling option") ;
return (FALSE) ;
}
if (!ok)
{
/* S is wrong size */
ERROR (CHOLMOD_INVALID, "invalid scale factors") ;
return (FALSE) ;
}
Common->status = CHOLMOD_OK ;
/* ---------------------------------------------------------------------- */
/* get inputs */
/* ---------------------------------------------------------------------- */
Ap = A->p ;
Anz = A->nz ;
Ai = A->i ;
Ax = A->x ;
packed = A->packed ;
s = S->x ;
/* ---------------------------------------------------------------------- */
/* scale the matrix */
/* ---------------------------------------------------------------------- */
if (scale == CHOLMOD_ROW)
{
/* ------------------------------------------------------------------ */
/* A = diag(s)*A, row scaling */
/* ------------------------------------------------------------------ */
for (j = 0 ; j < ncol ; j++)
{
p = Ap [j] ;
pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ;
for ( ; p < pend ; p++)
{
Ax [p] *= s [Ai [p]] ;
}
}
}
else if (scale == CHOLMOD_COL)
{
/* ------------------------------------------------------------------ */
/* A = A*diag(s), column scaling */
/* ------------------------------------------------------------------ */
for (j = 0 ; j < ncol ; j++)
{
t = s [j] ;
p = Ap [j] ;
pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ;
for ( ; p < pend ; p++)
{
Ax [p] *= t ;
}
}
}
else if (scale == CHOLMOD_SYM)
{
/* ------------------------------------------------------------------ */
/* A = diag(s)*A*diag(s), symmetric scaling */
/* ------------------------------------------------------------------ */
for (j = 0 ; j < ncol ; j++)
{
t = s [j] ;
p = Ap [j] ;
pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ;
for ( ; p < pend ; p++)
{
Ax [p] *= t * s [Ai [p]] ;
}
}
}
else if (scale == CHOLMOD_SCALAR)
{
/* ------------------------------------------------------------------ */
/* A = s[0] * A, scalar scaling */
/* ------------------------------------------------------------------ */
t = s [0] ;
for (j = 0 ; j < ncol ; j++)
{
p = Ap [j] ;
pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ;
for ( ; p < pend ; p++)
{
Ax [p] *= t ;
}
}
}
ASSERT (CHOLMOD(dump_sparse) (A, "A scaled", Common) >= 0) ;
return (TRUE) ;
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1