The R Project SVN R-packages

Rev

Rev 4428 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

/* ========================================================================== */
/* === Modify/t_cholmod_updown ============================================== */
/* ========================================================================== */

/* -----------------------------------------------------------------------------
 * CHOLMOD/Modify Module.  Copyright (C) 2005-2006,
 * Timothy A. Davis and William W. Hager.
 * The CHOLMOD/Modify 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
 * -------------------------------------------------------------------------- */

/* Updates/downdates the LDL' factorization, by computing a new factorization of
 *
 *      Lnew * Dnew * Lnew' = Lold * Dold * Lold' +/- C*C'
 *
 * This file is not compiled separately.  It is included into
 * cholmod_updown.c.  There are no user-callable routines in this file.
 *
 * The next include statements, below, create the numerical update/downdate
 * kernels from t_cholmod_updown_numkr.c.  There are 4 compiled versions of this
 * file, one for each value of WDIM in the set 1, 2, 4, and 8.  Each calls
 * multiple versions of t_cholmod_updown_numkr; the number of versions of each
 * is equal to WDIM.  Each t_cholmod_updown_numkr version is included as a
 * static function within its t_cholmod_updown.c caller routine.  Thus:
 *
 *  t*_updown.c creates these versions of t_cholmod_updown_numkr.c:
 *  ---------   ---------------------------------------------------
 *
 *  updown_1_r  updown_1_1
 *
 *  updown_2_r  updown_2_1     updown_2_2
 *
 *  updown_4_r  updown_4_1     updown_4_2     updown_4_3     updown_4_4
 *
 *  updown_8_r  updown_8_1     updown_8_2     updown_8_3     updown_8_4
 *          updown_8_5     updown_8_6     updown_8_7     updown_8_8
 *
 * workspace: Xwork (nrow*wdim)
 */

/* ========================================================================== */
/* === routines for numeric update/downdate along one path ================== */
/* ========================================================================== */

#undef FORM_NAME
#undef NUMERIC

#define FORM_NAME(k,rank) updown_ ## k ## _ ## rank
#define NUMERIC(k,rank) FORM_NAME(k,rank)

#define RANK 1
#include "t_cholmod_updown_numkr.c"

#if WDIM >= 2
#define RANK 2
#include "t_cholmod_updown_numkr.c"
#endif

#if WDIM >= 4
#define RANK 3
#include "t_cholmod_updown_numkr.c"
#define RANK 4
#include "t_cholmod_updown_numkr.c"
#endif

#if WDIM == 8
#define RANK 5
#include "t_cholmod_updown_numkr.c"
#define RANK 6
#include "t_cholmod_updown_numkr.c"
#define RANK 7
#include "t_cholmod_updown_numkr.c"
#define RANK 8
#include "t_cholmod_updown_numkr.c"
#endif


/* ========================================================================== */
/* === numeric update/downdate for all paths ================================ */
/* ========================================================================== */

static void NUMERIC (WDIM, r)
(
    int update,     /* TRUE for update, FALSE for downdate */
    cholmod_sparse *C,  /* in packed or unpacked, and sorted form */
            /* no empty columns */
    Int rank,       /* rank of the update/downdate */
    cholmod_factor *L,  /* with unit diagonal (diagonal not stored) */
            /* temporary workspaces: */
    double W [ ],   /* n-by-WDIM dense matrix, initially zero */
    Path_type Path [ ],
    Int npaths,
    Int mask [ ],   /* size n */
    cholmod_common *Common
)
{
    double Alpha [8] ;
    double *Cx, *Wpath, *W1, *a ;
    Int i, j, p, ccol, pend, wfirst, e, path, packed ;
    Int *Ci, *Cp, *Cnz ;

    /* ---------------------------------------------------------------------- */
    /* get inputs */
    /* ---------------------------------------------------------------------- */

    Ci = C->i ;
    Cx = C->x ;
    Cp = C->p ;
    Cnz = C->nz ;
    packed = C->packed ;
    ASSERT (IMPLIES (!packed, Cnz != NULL)) ;
    ASSERT (L->n == C->nrow) ;
    DEBUG (CHOLMOD(dump_real) ("num_d: in W:", W, WDIM, L->n, FALSE, 1,Common));

    /* ---------------------------------------------------------------------- */
    /* scatter C into W */
    /* ---------------------------------------------------------------------- */

    for (path = 0 ; path < rank ; path++)
    {
    /* W (:, path) = C (:, Path [path].col) */
    ccol = Path [path].ccol ;
    Wpath = W + path ;
    PRINT1 (("Ordered Columns [path = "ID"] = "ID"\n", path, ccol)) ;
    p = Cp [ccol] ;
    pend = (packed) ? (Cp [ccol+1]) : (p + Cnz [ccol]) ;
    /* column C can be empty */
    for ( ; p < pend ; p++)
    {
        i = Ci [p] ;
        ASSERT (i >= 0 && i < (Int) (C->nrow)) ;
        if (mask == NULL || mask [i] < 0)
        {
        Wpath [WDIM * i] = Cx [p] ;
        }
        PRINT1 (("    row "ID" : %g mask "ID"\n", i, Cx [p],
            (mask) ? mask [i] : 0)) ;
    }
    Alpha [path] = 1.0 ;
    }
    DEBUG (CHOLMOD(dump_real) ("num_d: W:", W, WDIM, L->n, FALSE, 1,Common)) ;

    /* ---------------------------------------------------------------------- */
    /* numeric update/downdate of the paths */
    /* ---------------------------------------------------------------------- */

    /* for each disjoint subpath in Tbar in DFS order do */
    for (path = rank ; path < npaths ; path++)
    {

    /* determine which columns of W to use */
    wfirst = Path [path].wfirst ;
    e = Path [path].end ;
    j = Path [path].start ;
    ASSERT (e >= 0 && e < (Int) (L->n)) ;
    ASSERT (j >= 0 && j < (Int) (L->n)) ;

    W1 = W + wfirst ;   /* pointer to row 0, column wfirst of W */
    a = Alpha + wfirst ;    /* pointer to Alpha [wfirst] */

    PRINT1 (("Numerical update/downdate of path "ID"\n", path)) ;
    PRINT1 (("start "ID" end "ID" wfirst "ID" rank "ID" ccol "ID"\n", j, e,
        wfirst, Path [path].rank, Path [path].ccol)) ;

#if WDIM == 1
    NUMERIC (WDIM,1) (update, j, e, a, W1, L, Common) ;
#else

    switch (Path [path].rank)
    {
        case 1:
        NUMERIC (WDIM,1) (update, j, e, a, W1, L, Common) ;
        break ;

#if WDIM >= 2
        case 2:
        NUMERIC (WDIM,2) (update, j, e, a, W1, L, Common) ;
        break ;
#endif

#if WDIM >= 4
        case 3:
        NUMERIC (WDIM,3) (update, j, e, a, W1, L, Common) ;
        break ;
        case 4:
        NUMERIC (WDIM,4) (update, j, e, a, W1, L, Common) ;
        break ;
#endif

#if WDIM == 8
        case 5:
        NUMERIC (WDIM,5) (update, j, e, a, W1, L, Common) ;
        break ;
        case 6:
        NUMERIC (WDIM,6) (update, j, e, a, W1, L, Common) ;
        break ;
        case 7:
        NUMERIC (WDIM,7) (update, j, e, a, W1, L, Common) ;
        break ;
        case 8:
        NUMERIC (WDIM,8) (update, j, e, a, W1, L, Common) ;
        break ;
#endif

    }
#endif

    }
}

/* prepare for the next inclusion of this file in cholmod_updown.c */
#undef WDIM