1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
|
//------------------------------------------------------------------------------
// CHOLMOD/Modify/t_cholmod_updown_wdim: template for t_cholmod_updown_worker
//------------------------------------------------------------------------------
// CHOLMOD/Modify Module. Copyright (C) 2005-2023, Timothy A. Davis,
// and William W. Hager. All Rights Reserved.
// SPDX-License-Identifier: GPL-2.0+
//------------------------------------------------------------------------------
// 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 twice into
// t_cholmod_updown_worker.c, to create all the kernels for double and single
// precision update/downdate. 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. For the double case, 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_wdim.c
// caller routine. Thus, for the double case:
//
// t*_updown_wdim.c creates these versions of t_cholmod_updown_numkr.c:
// ---------------- ---------------------------------------------------
//
// d_updown_1_r d_updown_1_1
//
// d_updown_2_r d_updown_2_1 d_updown_2_2
//
// d_updown_4_r d_updown_4_1 d_updown_4_2 d_updown_4_3 d_updown_4_4
//
// d_updown_8_r d_updown_8_1 d_updown_8_2 d_updown_8_3 d_updown_8_4
// d_updown_8_5 d_updown_8_6 d_updown_8_7 d_updown_8_8
//
// For the single (float) case, all the functions are named s_updown_*_*.
//
// workspace: Xwork (nrow*wdim)
//------------------------------------------------------------------------------
// routines for numeric update/downdate along one path
//------------------------------------------------------------------------------
#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 UPDOWN (WDIM, r) // WDIM is a compile-time constant (1,2,4, or 8)
(
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:
Real W [ ], // n-by-WDIM dense matrix, initially zero
Path_type Path [ ],
Int npaths,
Int mask [ ], // size n
Int maskmark,
cholmod_common *Common
)
{
//--------------------------------------------------------------------------
// get inputs
//--------------------------------------------------------------------------
Real Alpha [8] ;
Real *Cx, *Wpath, *W1, *a ;
Int i, j, p, ccol, pend, wfirst, e, path, packed ;
Int *Ci, *Cp, *Cnz ;
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, L->dtype,
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] < maskmark)
{
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, L->dtype,
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
UPDOWN (WDIM,1) (update, j, e, a, W1, L, Common) ;
#else
switch (Path [path].rank)
{
case 1:
UPDOWN (WDIM,1) (update, j, e, a, W1, L, Common) ;
break ;
#if WDIM >= 2
case 2:
UPDOWN (WDIM,2) (update, j, e, a, W1, L, Common) ;
break ;
#endif
#if WDIM >= 4
case 3:
UPDOWN (WDIM,3) (update, j, e, a, W1, L, Common) ;
break ;
case 4:
UPDOWN (WDIM,4) (update, j, e, a, W1, L, Common) ;
break ;
#endif
#if WDIM == 8
case 5:
UPDOWN (WDIM,5) (update, j, e, a, W1, L, Common) ;
break ;
case 6:
UPDOWN (WDIM,6) (update, j, e, a, W1, L, Common) ;
break ;
case 7:
UPDOWN (WDIM,7) (update, j, e, a, W1, L, Common) ;
break ;
case 8:
UPDOWN (WDIM,8) (update, j, e, a, W1, L, Common) ;
break ;
#endif
}
#endif
}
}
// prepare for the next inclusion of this file in t_cholmod_updown_worker.c
#undef WDIM
|