/* symbolic ordering and analysis for QR or LU */ css *cs_sqr (CS_INT order, const cs *A, CS_INT qr) { CS_INT n, k, ok = 1, *post ; css *S ; if (!CS_CSC (A)) return (NULL) ; /* check inputs */ n = A->n ; S = cs_calloc (1, sizeof (css)) ; /* allocate result S */ if (!S) return (NULL) ; /* out of memory */ S->q = cs_amd (order, A) ; /* fill-reducing ordering */ if (order && !S->q) return (cs_sfree (S)) ; if (qr) /* QR symbolic analysis */ { cs *C = order ? cs_permute (A, NULL, S->q, 0) : ((cs *) A) ; S->parent = cs_etree (C, 1) ; /* etree of C'*C, where C=A(:,q) */ post = cs_post (S->parent, n) ; S->cp = cs_counts (C, S->parent, post, 1) ; /* col counts chol(C'*C) */ cs_free (post) ; ok = C && S->parent && S->cp && cs_vcount (C, S) ; if (ok) for (S->unz = 0, k = 0 ; k < n ; k++) S->unz += S->cp [k] ; if (order) cs_spfree (C) ; } else { S->unz = 4*(A->p [n]) + n ; /* for LU factorization only, */ S->lnz = S->unz ; /* guess nnz(L) and nnz(U) */ } return (ok ? S : cs_sfree (S)) ; /* return result S */ }
css *cs_schol(int order, const cs *A) { int n, *c, *post, *P; cs *C; css *S; if (!CS_CSC (A)) return (NULL); /* check inputs */ n = A->n; S = (css *) cs_calloc(1, sizeof(css)); /* allocate result S */ if (!S) return (NULL); /* out of memory */ P = cs_amd(order, A); /* P = amd(A+A'), or natural */ S->pinv = cs_pinv(P, n); /* find inverse permutation */ cs_free(P); if (order && !S->pinv) return (cs_sfree(S)); C = cs_symperm(A, S->pinv, 0); /* C = spones(triu(A(P,P))) */ S->parent = cs_etree(C, 0); /* find etree of C */ post = cs_post(S->parent, n); /* postorder the etree */ c = cs_counts(C, S->parent, post, 0); /* find column counts of chol(C) */ cs_free(post); cs_spfree(C); S->cp = (int *) cs_malloc(n + 1, sizeof(int)); /* allocate result S->cp */ S->unz = S->lnz = cs_cumsum(S->cp, c, n); /* find column pointers for L */ cs_free(c); return ((S->lnz >= 0) ? S : cs_sfree(S)); }