$search
00001 #include "cs.h" 00002 /* sparse Cholesky update/downdate, L*L' + sigma*w*w' (sigma = +1 or -1) */ 00003 int cs_updown (cs *L, int sigma, const cs *C, const int *parent) 00004 { 00005 int n, p, f, j, *Lp, *Li, *Cp, *Ci ; 00006 double *Lx, *Cx, alpha, beta = 1, delta, gamma, w1, w2, *w, beta2 = 1 ; 00007 if (!CS_CSC (L) || !CS_CSC (C) || !parent) return (0) ; /* check inputs */ 00008 Lp = L->p ; Li = L->i ; Lx = L->x ; n = L->n ; 00009 Cp = C->p ; Ci = C->i ; Cx = C->x ; 00010 if ((p = Cp [0]) >= Cp [1]) return (1) ; /* return if C empty */ 00011 w = cs_malloc (n, sizeof (double)) ; /* get workspace */ 00012 if (!w) return (0) ; /* out of memory */ 00013 f = Ci [p] ; 00014 for ( ; p < Cp [1] ; p++) f = CS_MIN (f, Ci [p]) ; /* f = min (find (C)) */ 00015 for (j = f ; j != -1 ; j = parent [j]) w [j] = 0 ; /* clear workspace w */ 00016 for (p = Cp [0] ; p < Cp [1] ; p++) w [Ci [p]] = Cx [p] ; /* w = C */ 00017 for (j = f ; j != -1 ; j = parent [j]) /* walk path f up to root */ 00018 { 00019 p = Lp [j] ; 00020 alpha = w [j] / Lx [p] ; /* alpha = w(j) / L(j,j) */ 00021 beta2 = beta*beta + sigma*alpha*alpha ; 00022 if (beta2 <= 0) break ; /* not positive definite */ 00023 beta2 = sqrt (beta2) ; 00024 delta = (sigma > 0) ? (beta / beta2) : (beta2 / beta) ; 00025 gamma = sigma * alpha / (beta2 * beta) ; 00026 Lx [p] = delta * Lx [p] + ((sigma > 0) ? (gamma * w [j]) : 0) ; 00027 beta = beta2 ; 00028 for (p++ ; p < Lp [j+1] ; p++) 00029 { 00030 w1 = w [Li [p]] ; 00031 w [Li [p]] = w2 = w1 - alpha * Lx [p] ; 00032 Lx [p] = delta * Lx [p] + gamma * ((sigma > 0) ? w1 : w2) ; 00033 } 00034 } 00035 cs_free (w) ; 00036 return (beta2 > 0) ; 00037 }