1 #include "cs.h"
2 /* sparse Cholesky update/downdate, L*L' + sigma*w*w' (sigma = +1 or -1) */
cs_updown(cs * L,CS_INT sigma,const cs * C,const CS_INT * parent)3 CS_INT cs_updown (cs *L, CS_INT sigma, const cs *C, const CS_INT *parent)
4 {
5     CS_INT n, p, f, j, *Lp, *Li, *Cp, *Ci ;
6     CS_ENTRY *Lx, *Cx, alpha, gamma, w1, w2, *w ;
7     double beta = 1, beta2 = 1, delta ;
8 #ifdef CS_COMPLEX
9     cs_complex_t phase ;
10 #endif
11     if (!CS_CSC (L) || !CS_CSC (C) || !parent) return (0) ;  /* check inputs */
12     Lp = L->p ; Li = L->i ; Lx = L->x ; n = L->n ;
13     Cp = C->p ; Ci = C->i ; Cx = C->x ;
14     if ((p = Cp [0]) >= Cp [1]) return (1) ;        /* return if C empty */
15     w = cs_malloc (n, sizeof (CS_ENTRY)) ;          /* get workspace */
16     if (!w) return (0) ;                            /* out of memory */
17     f = Ci [p] ;
18     for ( ; p < Cp [1] ; p++) f = CS_MIN (f, Ci [p]) ;  /* f = min (find (C)) */
19     for (j = f ; j != -1 ; j = parent [j]) w [j] = 0 ;  /* clear workspace w */
20     for (p = Cp [0] ; p < Cp [1] ; p++) w [Ci [p]] = Cx [p] ; /* w = C */
21     for (j = f ; j != -1 ; j = parent [j])          /* walk path f up to root */
22     {
23         p = Lp [j] ;
24         alpha = w [j] / Lx [p] ;                    /* alpha = w(j) / L(j,j) */
25         beta2 = beta*beta + sigma*alpha*CS_CONJ(alpha) ;
26         if (beta2 <= 0) break ;                     /* not positive definite */
27         beta2 = sqrt (beta2) ;
28         delta = (sigma > 0) ? (beta / beta2) : (beta2 / beta) ;
29         gamma = sigma * CS_CONJ(alpha) / (beta2 * beta) ;
30         Lx [p] = delta * Lx [p] + ((sigma > 0) ? (gamma * w [j]) : 0) ;
31         beta = beta2 ;
32 #ifdef CS_COMPLEX
33         phase = CS_ABS (Lx [p]) / Lx [p] ;  /* phase = abs(L(j,j))/L(j,j)*/
34         Lx [p] *= phase ;                   /* L(j,j) = L(j,j) * phase */
35 #endif
36         for (p++ ; p < Lp [j+1] ; p++)
37         {
38             w1 = w [Li [p]] ;
39             w [Li [p]] = w2 = w1 - alpha * Lx [p] ;
40             Lx [p] = delta * Lx [p] + gamma * ((sigma > 0) ? w1 : w2) ;
41 #ifdef CS_COMPLEX
42             Lx [p] *= phase ;               /* L(i,j) = L(i,j) * phase */
43 #endif
44         }
45     }
46     cs_free (w) ;
47     return (beta2 > 0) ;
48 }
49