├── Demo ├── Makefile ├── README.txt ├── cs_demo.c ├── cs_demo.h ├── cs_demo.out ├── cs_demo1.c ├── cs_demo2.c └── cs_demo3.c ├── Doc ├── ChangeLog ├── License.txt └── lesser.txt ├── Include └── cs.h ├── Lib └── Makefile ├── Makefile ├── README.txt ├── Source ├── README.txt ├── cs_add.c ├── cs_amd.c ├── cs_chol.c ├── cs_cholsol.c ├── cs_compress.c ├── cs_counts.c ├── cs_cumsum.c ├── cs_dfs.c ├── cs_dmperm.c ├── cs_droptol.c ├── cs_dropzeros.c ├── cs_dupl.c ├── cs_entry.c ├── cs_ereach.c ├── cs_etree.c ├── cs_fkeep.c ├── cs_gaxpy.c ├── cs_happly.c ├── cs_house.c ├── cs_ipvec.c ├── cs_leaf.c ├── cs_load.c ├── cs_lsolve.c ├── cs_ltsolve.c ├── cs_lu.c ├── cs_lusol.c ├── cs_malloc.c ├── cs_maxtrans.c ├── cs_multiply.c ├── cs_norm.c ├── cs_permute.c ├── cs_pinv.c ├── cs_post.c ├── cs_print.c ├── cs_pvec.c ├── cs_qr.c ├── cs_qrsol.c ├── cs_randperm.c ├── cs_reach.c ├── cs_scatter.c ├── cs_scc.c ├── cs_schol.c ├── cs_spsolve.c ├── cs_sqr.c ├── cs_symperm.c ├── cs_tdfs.c ├── cs_transpose.c ├── cs_updown.c ├── cs_usolve.c ├── cs_util.c └── cs_utsolve.c └── Tcov ├── Makefile ├── README.txt ├── cov.awk ├── covall ├── covall.linux ├── covall.sol ├── cover ├── covs ├── cstcov_malloc_test.c ├── cstcov_malloc_test.h ├── cstcov_test.c ├── gcovs ├── nil └── zero /Demo/Makefile: -------------------------------------------------------------------------------- 1 | CF = $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -O 2 | I = -I../Include 3 | 4 | CS = ../Lib/libcsparse.a 5 | 6 | all: lib cs_demo1 cs_demo2 cs_demo3 7 | - ./cs_demo1 < ../Matrix/t1 8 | - ./cs_demo2 < ../Matrix/t1 9 | - ./cs_demo2 < ../Matrix/ash219 10 | - ./cs_demo2 < ../Matrix/bcsstk01 11 | - ./cs_demo2 < ../Matrix/fs_183_1 12 | - ./cs_demo2 < ../Matrix/mbeacxc 13 | - ./cs_demo2 < ../Matrix/west0067 14 | - ./cs_demo2 < ../Matrix/lp_afiro 15 | - ./cs_demo2 < ../Matrix/bcsstk16 16 | - ./cs_demo3 < ../Matrix/bcsstk01 17 | - ./cs_demo3 < ../Matrix/bcsstk16 18 | 19 | lib: 20 | ( cd ../Lib ; $(MAKE) ) 21 | 22 | cs_demo1: lib cs_demo1.c Makefile 23 | $(CC) $(CF) $(I) -o cs_demo1 cs_demo1.c $(CS) -lm 24 | 25 | cs_demo2: lib cs_demo2.c cs_demo.c cs_demo.h Makefile 26 | $(CC) $(CF) $(I) -o cs_demo2 cs_demo2.c cs_demo.c $(CS) -lm 27 | 28 | cs_demo3: lib cs_demo3.c cs_demo.c cs_demo.h Makefile 29 | $(CC) $(CF) $(I) -o cs_demo3 cs_demo3.c cs_demo.c $(CS) -lm 30 | 31 | clean: 32 | - $(RM) *.o 33 | 34 | purge: distclean 35 | 36 | distclean: clean 37 | - $(RM) -r cs_demo1 cs_demo2 cs_demo3 *.a *.dSYM *.obj *.dll 38 | -------------------------------------------------------------------------------- /Demo/README.txt: -------------------------------------------------------------------------------- 1 | CSparse/Demo: to compile a run the demos, just type "make" in this directory. 2 | The printed residuals should all be small, except for the mbeacxc matrix 3 | (which is numerically and structurally singular), and ash219 (which is a 4 | least-squares problem). See cs_demo.out for the proper output of "make". 5 | 6 | Timothy A. Davis, http://www.suitesparse.com 7 | -------------------------------------------------------------------------------- /Demo/cs_demo.c: -------------------------------------------------------------------------------- 1 | #include "cs_demo.h" 2 | #include 3 | /* 1 if A is square & upper tri., -1 if square & lower tri., 0 otherwise */ 4 | static csi is_sym (cs *A) 5 | { 6 | csi is_upper, is_lower, j, p, n = A->n, m = A->m, *Ap = A->p, *Ai = A->i ; 7 | if (m != n) return (0) ; 8 | is_upper = 1 ; 9 | is_lower = 1 ; 10 | for (j = 0 ; j < n ; j++) 11 | { 12 | for (p = Ap [j] ; p < Ap [j+1] ; p++) 13 | { 14 | if (Ai [p] > j) is_upper = 0 ; 15 | if (Ai [p] < j) is_lower = 0 ; 16 | } 17 | } 18 | return (is_upper ? 1 : (is_lower ? -1 : 0)) ; 19 | } 20 | 21 | /* true for off-diagonal entries */ 22 | static csi dropdiag (csi i, csi j, double aij, void *other) { return (i != j) ;} 23 | 24 | /* C = A + triu(A,1)' */ 25 | static cs *make_sym (cs *A) 26 | { 27 | cs *AT, *C ; 28 | AT = cs_transpose (A, 1) ; /* AT = A' */ 29 | cs_fkeep (AT, &dropdiag, NULL) ; /* drop diagonal entries from AT */ 30 | C = cs_add (A, AT, 1, 1) ; /* C = A+AT */ 31 | cs_spfree (AT) ; 32 | return (C) ; 33 | } 34 | 35 | /* create a right-hand side */ 36 | static void rhs (double *x, double *b, csi m) 37 | { 38 | csi i ; 39 | for (i = 0 ; i < m ; i++) b [i] = 1 + ((double) i) / m ; 40 | for (i = 0 ; i < m ; i++) x [i] = b [i] ; 41 | } 42 | 43 | /* infinity-norm of x */ 44 | static double norm (double *x, csi n) 45 | { 46 | csi i ; 47 | double normx = 0 ; 48 | for (i = 0 ; i < n ; i++) normx = CS_MAX (normx, fabs (x [i])) ; 49 | return (normx) ; 50 | } 51 | 52 | /* compute residual, norm(A*x-b,inf) / (norm(A,1)*norm(x,inf) + norm(b,inf)) */ 53 | static void print_resid (csi ok, cs *A, double *x, double *b, double *resid) 54 | { 55 | csi i, m, n ; 56 | if (!ok) { printf (" (failed)\n") ; return ; } 57 | m = A->m ; n = A->n ; 58 | for (i = 0 ; i < m ; i++) resid [i] = -b [i] ; /* resid = -b */ 59 | cs_gaxpy (A, x, resid) ; /* resid = resid + A*x */ 60 | printf ("resid: %8.2e\n", norm (resid,m) / ((n == 0) ? 1 : 61 | (cs_norm (A) * norm (x,n) + norm (b,m)))) ; 62 | } 63 | 64 | static double tic (void) { return (clock () / (double) CLOCKS_PER_SEC) ; } 65 | static double toc (double t) { double s = tic () ; return (CS_MAX (0, s-t)) ; } 66 | 67 | static void print_order (csi order) 68 | { 69 | switch (order) 70 | { 71 | case 0: printf ("natural ") ; break ; 72 | case 1: printf ("amd(A+A') ") ; break ; 73 | case 2: printf ("amd(S'*S) ") ; break ; 74 | case 3: printf ("amd(A'*A) ") ; break ; 75 | } 76 | } 77 | 78 | /* read a problem from a file; use %g for integers to avoid csi conflicts */ 79 | problem *get_problem (FILE *f, double tol) 80 | { 81 | cs *T, *A, *C ; 82 | csi sym, m, n, mn, nz1, nz2 ; 83 | problem *Prob ; 84 | Prob = cs_calloc (1, sizeof (problem)) ; 85 | if (!Prob) return (NULL) ; 86 | T = cs_load (f) ; /* load triplet matrix T from a file */ 87 | Prob->A = A = cs_compress (T) ; /* A = compressed-column form of T */ 88 | cs_spfree (T) ; /* clear T */ 89 | if (!cs_dupl (A)) return (free_problem (Prob)) ; /* sum up duplicates */ 90 | Prob->sym = sym = is_sym (A) ; /* determine if A is symmetric */ 91 | m = A->m ; n = A->n ; 92 | mn = CS_MAX (m,n) ; 93 | nz1 = A->p [n] ; 94 | cs_dropzeros (A) ; /* drop zero entries */ 95 | nz2 = A->p [n] ; 96 | if (tol > 0) cs_droptol (A, tol) ; /* drop tiny entries (just to test) */ 97 | Prob->C = C = sym ? make_sym (A) : A ; /* C = A + triu(A,1)', or C=A */ 98 | if (!C) return (free_problem (Prob)) ; 99 | printf ("\n--- Matrix: %g-by-%g, nnz: %g (sym: %g: nnz %g), norm: %8.2e\n", 100 | (double) m, (double) n, (double) (A->p [n]), (double) sym, 101 | (double) (sym ? C->p [n] : 0), cs_norm (C)) ; 102 | if (nz1 != nz2) printf ("zero entries dropped: %g\n", (double) (nz1 - nz2)); 103 | if (nz2 != A->p [n]) printf ("tiny entries dropped: %g\n", 104 | (double) (nz2 - A->p [n])) ; 105 | Prob->b = cs_malloc (mn, sizeof (double)) ; 106 | Prob->x = cs_malloc (mn, sizeof (double)) ; 107 | Prob->resid = cs_malloc (mn, sizeof (double)) ; 108 | return ((!Prob->b || !Prob->x || !Prob->resid) ? free_problem (Prob) : Prob) ; 109 | } 110 | 111 | /* free a problem */ 112 | problem *free_problem (problem *Prob) 113 | { 114 | if (!Prob) return (NULL) ; 115 | cs_spfree (Prob->A) ; 116 | if (Prob->sym) cs_spfree (Prob->C) ; 117 | cs_free (Prob->b) ; 118 | cs_free (Prob->x) ; 119 | cs_free (Prob->resid) ; 120 | return (cs_free (Prob)) ; 121 | } 122 | 123 | /* solve a linear system using Cholesky, LU, and QR, with various orderings */ 124 | csi demo2 (problem *Prob) 125 | { 126 | cs *A, *C ; 127 | double *b, *x, *resid, t, tol ; 128 | csi k, m, n, ok, order, nb, ns, *r, *s, *rr, sprank ; 129 | csd *D ; 130 | if (!Prob) return (0) ; 131 | A = Prob->A ; C = Prob->C ; b = Prob->b ; x = Prob->x ; resid = Prob->resid; 132 | m = A->m ; n = A->n ; 133 | tol = Prob->sym ? 0.001 : 1 ; /* partial pivoting tolerance */ 134 | D = cs_dmperm (C, 1) ; /* randomized dmperm analysis */ 135 | if (!D) return (0) ; 136 | nb = D->nb ; r = D->r ; s = D->s ; rr = D->rr ; 137 | sprank = rr [3] ; 138 | for (ns = 0, k = 0 ; k < nb ; k++) 139 | { 140 | ns += ((r [k+1] == r [k]+1) && (s [k+1] == s [k]+1)) ; 141 | } 142 | printf ("blocks: %g singletons: %g structural rank: %g\n", 143 | (double) nb, (double) ns, (double) sprank) ; 144 | cs_dfree (D) ; 145 | for (order = 0 ; order <= 3 ; order += 3) /* natural and amd(A'*A) */ 146 | { 147 | if (!order && m > 1000) continue ; 148 | printf ("QR ") ; 149 | print_order (order) ; 150 | rhs (x, b, m) ; /* compute right-hand side */ 151 | t = tic () ; 152 | ok = cs_qrsol (order, C, x) ; /* min norm(Ax-b) with QR */ 153 | printf ("time: %8.2f ", toc (t)) ; 154 | print_resid (ok, C, x, b, resid) ; /* print residual */ 155 | } 156 | if (m != n || sprank < n) return (1) ; /* return if rect. or singular*/ 157 | for (order = 0 ; order <= 3 ; order++) /* try all orderings */ 158 | { 159 | if (!order && m > 1000) continue ; 160 | printf ("LU ") ; 161 | print_order (order) ; 162 | rhs (x, b, m) ; /* compute right-hand side */ 163 | t = tic () ; 164 | ok = cs_lusol (order, C, x, tol) ; /* solve Ax=b with LU */ 165 | printf ("time: %8.2f ", toc (t)) ; 166 | print_resid (ok, C, x, b, resid) ; /* print residual */ 167 | } 168 | if (!Prob->sym) return (1) ; 169 | for (order = 0 ; order <= 1 ; order++) /* natural and amd(A+A') */ 170 | { 171 | if (!order && m > 1000) continue ; 172 | printf ("Chol ") ; 173 | print_order (order) ; 174 | rhs (x, b, m) ; /* compute right-hand side */ 175 | t = tic () ; 176 | ok = cs_cholsol (order, C, x) ; /* solve Ax=b with Cholesky */ 177 | printf ("time: %8.2f ", toc (t)) ; 178 | print_resid (ok, C, x, b, resid) ; /* print residual */ 179 | } 180 | return (1) ; 181 | } 182 | 183 | /* free workspace for demo3 */ 184 | static csi done3 (csi ok, css *S, csn *N, double *y, cs *W, cs *E, csi *p) 185 | { 186 | cs_sfree (S) ; 187 | cs_nfree (N) ; 188 | cs_free (y) ; 189 | cs_spfree (W) ; 190 | cs_spfree (E) ; 191 | cs_free (p) ; 192 | return (ok) ; 193 | } 194 | 195 | /* Cholesky update/downdate */ 196 | csi demo3 (problem *Prob) 197 | { 198 | cs *A, *C, *W = NULL, *WW, *WT, *E = NULL, *W2 ; 199 | csi n, k, *Li, *Lp, *Wi, *Wp, p1, p2, *p = NULL, ok ; 200 | double *b, *x, *resid, *y = NULL, *Lx, *Wx, s, t, t1 ; 201 | css *S = NULL ; 202 | csn *N = NULL ; 203 | if (!Prob || !Prob->sym || Prob->A->n == 0) return (0) ; 204 | A = Prob->A ; C = Prob->C ; b = Prob->b ; x = Prob->x ; resid = Prob->resid; 205 | n = A->n ; 206 | if (!Prob->sym || n == 0) return (1) ; 207 | rhs (x, b, n) ; /* compute right-hand side */ 208 | printf ("\nchol then update/downdate ") ; 209 | print_order (1) ; 210 | y = cs_malloc (n, sizeof (double)) ; 211 | t = tic () ; 212 | S = cs_schol (1, C) ; /* symbolic Chol, amd(A+A') */ 213 | printf ("\nsymbolic chol time %8.2f\n", toc (t)) ; 214 | t = tic () ; 215 | N = cs_chol (C, S) ; /* numeric Cholesky */ 216 | printf ("numeric chol time %8.2f\n", toc (t)) ; 217 | if (!S || !N || !y) return (done3 (0, S, N, y, W, E, p)) ; 218 | t = tic () ; 219 | cs_ipvec (S->pinv, b, y, n) ; /* y = P*b */ 220 | cs_lsolve (N->L, y) ; /* y = L\y */ 221 | cs_ltsolve (N->L, y) ; /* y = L'\y */ 222 | cs_pvec (S->pinv, y, x, n) ; /* x = P'*y */ 223 | printf ("solve chol time %8.2f\n", toc (t)) ; 224 | printf ("original: ") ; 225 | print_resid (1, C, x, b, resid) ; /* print residual */ 226 | k = n/2 ; /* construct W */ 227 | W = cs_spalloc (n, 1, n, 1, 0) ; 228 | if (!W) return (done3 (0, S, N, y, W, E, p)) ; 229 | Lp = N->L->p ; Li = N->L->i ; Lx = N->L->x ; 230 | Wp = W->p ; Wi = W->i ; Wx = W->x ; 231 | Wp [0] = 0 ; 232 | p1 = Lp [k] ; 233 | Wp [1] = Lp [k+1] - p1 ; 234 | s = Lx [p1] ; 235 | srand (1) ; 236 | for ( ; p1 < Lp [k+1] ; p1++) 237 | { 238 | p2 = p1 - Lp [k] ; 239 | Wi [p2] = Li [p1] ; 240 | Wx [p2] = s * rand () / ((double) RAND_MAX) ; 241 | } 242 | t = tic () ; 243 | ok = cs_updown (N->L, +1, W, S->parent) ; /* update: L*L'+W*W' */ 244 | t1 = toc (t) ; 245 | printf ("update: time: %8.2f\n", t1) ; 246 | if (!ok) return (done3 (0, S, N, y, W, E, p)) ; 247 | t = tic () ; 248 | cs_ipvec (S->pinv, b, y, n) ; /* y = P*b */ 249 | cs_lsolve (N->L, y) ; /* y = L\y */ 250 | cs_ltsolve (N->L, y) ; /* y = L'\y */ 251 | cs_pvec (S->pinv, y, x, n) ; /* x = P'*y */ 252 | t = toc (t) ; 253 | p = cs_pinv (S->pinv, n) ; 254 | W2 = cs_permute (W, p, NULL, 1) ; /* E = C + (P'W)*(P'W)' */ 255 | WT = cs_transpose (W2,1) ; 256 | WW = cs_multiply (W2, WT) ; 257 | cs_spfree (WT) ; 258 | cs_spfree (W2) ; 259 | E = cs_add (C, WW, 1, 1) ; 260 | cs_spfree (WW) ; 261 | if (!E || !p) return (done3 (0, S, N, y, W, E, p)) ; 262 | printf ("update: time: %8.2f (incl solve) ", t1+t) ; 263 | print_resid (1, E, x, b, resid) ; /* print residual */ 264 | cs_nfree (N) ; /* clear N */ 265 | t = tic () ; 266 | N = cs_chol (E, S) ; /* numeric Cholesky */ 267 | if (!N) return (done3 (0, S, N, y, W, E, p)) ; 268 | cs_ipvec (S->pinv, b, y, n) ; /* y = P*b */ 269 | cs_lsolve (N->L, y) ; /* y = L\y */ 270 | cs_ltsolve (N->L, y) ; /* y = L'\y */ 271 | cs_pvec (S->pinv, y, x, n) ; /* x = P'*y */ 272 | t = toc (t) ; 273 | printf ("rechol: time: %8.2f (incl solve) ", t) ; 274 | print_resid (1, E, x, b, resid) ; /* print residual */ 275 | t = tic () ; 276 | ok = cs_updown (N->L, -1, W, S->parent) ; /* downdate: L*L'-W*W' */ 277 | t1 = toc (t) ; 278 | if (!ok) return (done3 (0, S, N, y, W, E, p)) ; 279 | printf ("downdate: time: %8.2f\n", t1) ; 280 | t = tic () ; 281 | cs_ipvec (S->pinv, b, y, n) ; /* y = P*b */ 282 | cs_lsolve (N->L, y) ; /* y = L\y */ 283 | cs_ltsolve (N->L, y) ; /* y = L'\y */ 284 | cs_pvec (S->pinv, y, x, n) ; /* x = P'*y */ 285 | t = toc (t) ; 286 | printf ("downdate: time: %8.2f (incl solve) ", t1+t) ; 287 | print_resid (1, C, x, b, resid) ; /* print residual */ 288 | return (done3 (1, S, N, y, W, E, p)) ; 289 | } 290 | -------------------------------------------------------------------------------- /Demo/cs_demo.h: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | typedef struct problem_struct 3 | { 4 | cs *A ; 5 | cs *C ; 6 | csi sym ; 7 | double *x ; 8 | double *b ; 9 | double *resid ; 10 | } problem ; 11 | 12 | problem *get_problem (FILE *f, double tol) ; 13 | csi demo2 (problem *Prob) ; 14 | csi demo3 (problem *Prob) ; 15 | problem *free_problem (problem *Prob) ; 16 | -------------------------------------------------------------------------------- /Demo/cs_demo.out: -------------------------------------------------------------------------------- 1 | ( cd ../Lib ; make ) 2 | make[1]: Entering directory `/cise/research/sparse/SuiteSparse/CSparse/Lib' 3 | make[1]: Nothing to be done for `all'. 4 | make[1]: Leaving directory `/cise/research/sparse/SuiteSparse/CSparse/Lib' 5 | cc -O -I../Include -o cs_demo1 cs_demo1.c ../Lib/libcsparse.a -lm 6 | cc -O -I../Include -o cs_demo2 cs_demo2.c cs_demo.c ../Lib/libcsparse.a -lm 7 | cc -O -I../Include -o cs_demo3 cs_demo3.c cs_demo.c ../Lib/libcsparse.a -lm 8 | ./cs_demo1 < ../Matrix/t1 9 | T: 10 | CSparse Version 3.1.3, Mar 26, 2014. Copyright (c) Timothy A. Davis, 2006-2014 11 | triplet: 4-by-4, nzmax: 16 nnz: 10 12 | 2 2 : 3 13 | 1 0 : 3.1 14 | 3 3 : 1 15 | 0 2 : 3.2 16 | 1 1 : 2.9 17 | 3 0 : 3.5 18 | 3 1 : 0.4 19 | 1 3 : 0.9 20 | 0 0 : 4.5 21 | 2 1 : 1.7 22 | A: 23 | CSparse Version 3.1.3, Mar 26, 2014. Copyright (c) Timothy A. Davis, 2006-2014 24 | 4-by-4, nzmax: 10 nnz: 10, 1-norm: 11.1 25 | col 0 : locations 0 to 2 26 | 1 : 3.1 27 | 3 : 3.5 28 | 0 : 4.5 29 | col 1 : locations 3 to 5 30 | 1 : 2.9 31 | 3 : 0.4 32 | 2 : 1.7 33 | col 2 : locations 6 to 7 34 | 2 : 3 35 | 0 : 3.2 36 | col 3 : locations 8 to 9 37 | 3 : 1 38 | 1 : 0.9 39 | AT: 40 | CSparse Version 3.1.3, Mar 26, 2014. Copyright (c) Timothy A. Davis, 2006-2014 41 | 4-by-4, nzmax: 10 nnz: 10, 1-norm: 7.7 42 | col 0 : locations 0 to 1 43 | 0 : 4.5 44 | 2 : 3.2 45 | col 1 : locations 2 to 4 46 | 0 : 3.1 47 | 1 : 2.9 48 | 3 : 0.9 49 | col 2 : locations 5 to 6 50 | 1 : 1.7 51 | 2 : 3 52 | col 3 : locations 7 to 9 53 | 0 : 3.5 54 | 1 : 0.4 55 | 3 : 1 56 | D: 57 | CSparse Version 3.1.3, Mar 26, 2014. Copyright (c) Timothy A. Davis, 2006-2014 58 | 4-by-4, nzmax: 16 nnz: 16, 1-norm: 139.58 59 | col 0 : locations 0 to 3 60 | 1 : 13.95 61 | 3 : 15.75 62 | 0 : 100.28 63 | 2 : 9.6 64 | col 1 : locations 4 to 7 65 | 1 : 88.62 66 | 3 : 12.91 67 | 0 : 13.95 68 | 2 : 4.93 69 | col 2 : locations 8 to 11 70 | 1 : 4.93 71 | 3 : 0.68 72 | 2 : 81.68 73 | 0 : 9.6 74 | col 3 : locations 12 to 15 75 | 1 : 12.91 76 | 3 : 83.2 77 | 0 : 15.75 78 | 2 : 0.68 79 | ./cs_demo2 < ../Matrix/t1 80 | 81 | --- Matrix: 4-by-4, nnz: 10 (sym: 0: nnz 0), norm: 1.11e+01 82 | blocks: 1 singletons: 0 structural rank: 4 83 | QR natural time: 0.00 resid: 3.06e-17 84 | QR amd(A'*A) time: 0.00 resid: 3.06e-17 85 | LU natural time: 0.00 resid: 1.53e-17 86 | LU amd(A+A') time: 0.00 resid: 1.53e-17 87 | LU amd(S'*S) time: 0.00 resid: 0.00e+00 88 | LU amd(A'*A) time: 0.00 resid: 1.53e-17 89 | ./cs_demo2 < ../Matrix/ash219 90 | 91 | --- Matrix: 219-by-85, nnz: 438 (sym: 0: nnz 0), norm: 9.00e+00 92 | blocks: 1 singletons: 0 structural rank: 85 93 | QR natural time: 0.00 resid: 1.61e-02 94 | QR amd(A'*A) time: 0.00 resid: 1.61e-02 95 | ./cs_demo2 < ../Matrix/bcsstk01 96 | 97 | --- Matrix: 48-by-48, nnz: 224 (sym: -1: nnz 400), norm: 3.57e+09 98 | blocks: 1 singletons: 0 structural rank: 48 99 | QR natural time: 0.00 resid: 2.62e-19 100 | QR amd(A'*A) time: 0.00 resid: 5.27e-19 101 | LU natural time: 0.00 resid: 2.17e-19 102 | LU amd(A+A') time: 0.00 resid: 1.87e-19 103 | LU amd(S'*S) time: 0.00 resid: 2.38e-19 104 | LU amd(A'*A) time: 0.00 resid: 2.38e-19 105 | Chol natural time: 0.00 resid: 2.64e-19 106 | Chol amd(A+A') time: 0.00 resid: 2.55e-19 107 | ./cs_demo2 < ../Matrix/fs_183_1 108 | 109 | --- Matrix: 183-by-183, nnz: 988 (sym: 0: nnz 0), norm: 1.70e+09 110 | zero entries dropped: 71 111 | tiny entries dropped: 10 112 | blocks: 38 singletons: 37 structural rank: 183 113 | QR natural time: 0.00 resid: 6.84e-28 114 | QR amd(A'*A) time: 0.00 resid: 9.38e-28 115 | LU natural time: 0.01 resid: 6.20e-28 116 | LU amd(A+A') time: 0.00 resid: 1.55e-27 117 | LU amd(S'*S) time: 0.00 resid: 6.98e-28 118 | LU amd(A'*A) time: 0.00 resid: 6.98e-28 119 | ./cs_demo2 < ../Matrix/mbeacxc 120 | 121 | --- Matrix: 492-by-490, nnz: 49920 (sym: 0: nnz 0), norm: 9.29e-01 122 | blocks: 10 singletons: 8 structural rank: 448 123 | QR natural time: 0.05 resid: nan 124 | QR amd(A'*A) time: 0.06 resid: nan 125 | ./cs_demo2 < ../Matrix/west0067 126 | 127 | --- Matrix: 67-by-67, nnz: 294 (sym: 0: nnz 0), norm: 6.14e+00 128 | blocks: 2 singletons: 1 structural rank: 67 129 | QR natural time: 0.00 resid: 7.14e-17 130 | QR amd(A'*A) time: 0.00 resid: 3.10e-17 131 | LU natural time: 0.00 resid: 3.89e-17 132 | LU amd(A+A') time: 0.00 resid: 2.27e-17 133 | LU amd(S'*S) time: 0.00 resid: 1.95e-17 134 | LU amd(A'*A) time: 0.00 resid: 2.60e-17 135 | ./cs_demo2 < ../Matrix/lp_afiro 136 | 137 | --- Matrix: 27-by-51, nnz: 102 (sym: 0: nnz 0), norm: 3.43e+00 138 | blocks: 1 singletons: 0 structural rank: 27 139 | QR natural time: 0.00 resid: 3.96e-16 140 | QR amd(A'*A) time: 0.00 resid: 2.25e-16 141 | ./cs_demo2 < ../Matrix/bcsstk16 142 | 143 | --- Matrix: 4884-by-4884, nnz: 147631 (sym: -1: nnz 290378), norm: 7.01e+09 144 | blocks: 75 singletons: 74 structural rank: 4884 145 | QR amd(A'*A) time: 0.61 resid: 1.39e-22 146 | LU amd(A+A') time: 0.30 resid: 1.10e-22 147 | LU amd(S'*S) time: 0.31 resid: 1.28e-22 148 | LU amd(A'*A) time: 0.33 resid: 1.78e-22 149 | Chol amd(A+A') time: 0.11 resid: 1.19e-22 150 | ./cs_demo3 < ../Matrix/bcsstk01 151 | 152 | --- Matrix: 48-by-48, nnz: 224 (sym: -1: nnz 400), norm: 3.57e+09 153 | 154 | chol then update/downdate amd(A+A') 155 | symbolic chol time 0.00 156 | numeric chol time 0.00 157 | solve chol time 0.00 158 | original: resid: 2.55e-19 159 | update: time: 0.00 160 | update: time: 0.00 (incl solve) resid: 9.66e-19 161 | rechol: time: 0.00 (incl solve) resid: 1.55e-18 162 | downdate: time: 0.00 163 | downdate: time: 0.00 (incl solve) resid: 3.74e-17 164 | ./cs_demo3 < ../Matrix/bcsstk16 165 | 166 | --- Matrix: 4884-by-4884, nnz: 147631 (sym: -1: nnz 290378), norm: 7.01e+09 167 | 168 | chol then update/downdate amd(A+A') 169 | symbolic chol time 0.00 170 | numeric chol time 0.10 171 | solve chol time 0.01 172 | original: resid: 1.19e-22 173 | update: time: 0.00 174 | update: time: 0.00 (incl solve) resid: 1.12e-23 175 | rechol: time: 0.11 (incl solve) resid: 1.17e-23 176 | downdate: time: 0.00 177 | downdate: time: 0.00 (incl solve) resid: 4.09e-22 178 | -------------------------------------------------------------------------------- /Demo/cs_demo1.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | int main (void) 3 | { 4 | cs *T, *A, *Eye, *AT, *C, *D ; 5 | csi i, m ; 6 | T = cs_load (stdin) ; /* load triplet matrix T from stdin */ 7 | printf ("T:\n") ; cs_print (T, 0) ; /* print T */ 8 | A = cs_compress (T) ; /* A = compressed-column form of T */ 9 | printf ("A:\n") ; cs_print (A, 0) ; /* print A */ 10 | cs_spfree (T) ; /* clear T */ 11 | AT = cs_transpose (A, 1) ; /* AT = A' */ 12 | printf ("AT:\n") ; cs_print (AT, 0) ; /* print AT */ 13 | m = A ? A->m : 0 ; /* m = # of rows of A */ 14 | T = cs_spalloc (m, m, m, 1, 1) ; /* create triplet identity matrix */ 15 | for (i = 0 ; i < m ; i++) cs_entry (T, i, i, 1) ; 16 | Eye = cs_compress (T) ; /* Eye = speye (m) */ 17 | cs_spfree (T) ; 18 | C = cs_multiply (A, AT) ; /* C = A*A' */ 19 | D = cs_add (C, Eye, 1, cs_norm (C)) ; /* D = C + Eye*norm (C,1) */ 20 | printf ("D:\n") ; cs_print (D, 0) ; /* print D */ 21 | cs_spfree (A) ; /* clear A AT C D Eye */ 22 | cs_spfree (AT) ; 23 | cs_spfree (C) ; 24 | cs_spfree (D) ; 25 | cs_spfree (Eye) ; 26 | return (0) ; 27 | } 28 | -------------------------------------------------------------------------------- /Demo/cs_demo2.c: -------------------------------------------------------------------------------- 1 | #include "cs_demo.h" 2 | /* cs_demo2: read a matrix and solve a linear system */ 3 | int main (void) 4 | { 5 | problem *Prob = get_problem (stdin, 1e-14) ; 6 | demo2 (Prob) ; 7 | free_problem (Prob) ; 8 | return (0) ; 9 | } 10 | -------------------------------------------------------------------------------- /Demo/cs_demo3.c: -------------------------------------------------------------------------------- 1 | #include "cs_demo.h" 2 | /* cs_demo3: read a matrix and test Cholesky update/downdate */ 3 | int main (void) 4 | { 5 | problem *Prob = get_problem (stdin, 0) ; 6 | demo3 (Prob) ; 7 | free_problem (Prob) ; 8 | return (0) ; 9 | } 10 | -------------------------------------------------------------------------------- /Doc/ChangeLog: -------------------------------------------------------------------------------- 1 | Mar 26, 2014: version 3.1.3 2 | 3 | * minor update to UFget 4 | 5 | Apr 16, 2013: verison 3.1.2 6 | 7 | * removed a useless line from cs_sqr.c (no integer overflow can 8 | occur in S->lnz, S->unz at that point) 9 | 10 | Jun 20, 2012: verison 3.1.1 11 | 12 | * minor update for Windows (removed filesep) 13 | 14 | Jun 1, 2012: version 3.1.0 15 | 16 | * minor changes to enable the creation of CXSparse 3.1.0 17 | 18 | Dec 7, 2011: version 3.0.2 19 | 20 | * fixed the Makefile to better align with CFLAGS and other standards 21 | * minor fix to MATLAB cs_install.m 22 | 23 | Jan 18, 2010: version 3.0.0 24 | 25 | * changed "int" to "csi", which is normally "ptrdiff_t". This way, 26 | CSparse can be used on a 64-bit platform (and in 64-bit MATLAB 27 | in particular), without the need to use CXSparse. If you wish 28 | to use "int", simply edit CSparse/Include/cs.h and change the 29 | definition of csi, or compile with -Dcsi=int. 30 | 31 | Jan 25, 2011: version 2.2.5 32 | 33 | * minor fix to "make install" 34 | * minor change to cs_util.c, typecast return (cs_free (...)) 35 | * minor fixes to UFget: help file, UFsettings.txt 36 | 37 | Nov 30, 2009: version 2.2.4 38 | 39 | * added "make install" and "make uninstall" 40 | * minor change to cs_make.m 41 | 42 | Jan 20, 2009, v2.2.3 43 | 44 | * all tabs expanded to 8 spaces (except for Makefiles) 45 | * example corrected in cs_gaxpy.m 46 | * minor change to cs_sparse to allow for i,j,x to be either 47 | row or column vectors (or any mixture) 48 | 49 | Sept 8, 2008, v2.2.2 50 | 51 | * minor change to cs_make.m, to change "/" to filesep ("/" on Unix, "\" 52 | on Windows), to handle limitations in some Windows compilers 53 | 54 | Nov 1, 2007, v2.2.1 55 | 56 | * very minor change to Include/cs.h: Changed name of 2nd argument of 57 | cs_permute, to match the code. This has no affect on the code itself, 58 | since the type ("int *") is unchanged. It's just a documentation issue. 59 | 60 | * minor lint cleanup in mexFunctions 61 | 62 | Mar 31, 2007, v2.2.0 63 | 64 | * few changes to primary Source/ files. Changes mostly affect MATLAB 65 | interface. 66 | 67 | * Source/cs_house.c: correction to comment 68 | 69 | * Souce/cs_updown.c: whitespace changed to reflect change in CXSparse, 70 | no impact at all on CSparse itself. 71 | 72 | * Doc/, Lib/ and Include/ directories created. 73 | 74 | * Source/cs.h moved to Include/cs.h, version number changed to 2.2.0. 75 | 76 | * modification to Makefiles, cs_make.m 77 | 78 | * correction to help comments in cs_dmperm.m, cs_qr.m, cs_scc2.m, cs_scc.m 79 | 80 | * if complex matrix passed to CSparse in MATLAB, error message 81 | suggests using CXSparse instead 82 | 83 | * minor performance fix to cs_sparse_mex.c 84 | 85 | * cs_randperm added to MATLAB/Makefile; already appeared in cs_make.m 86 | 87 | * minor improvements to MATLAB/ demos. 88 | 89 | Mar 1, 2007, v2.1.0 90 | 91 | * Source/cs_add.c: added test for matrix dimensions 92 | 93 | * Source/cs_multiply.c: added test for matrix dimensions 94 | 95 | * correction to MATLAB demo3 (no error in C code version of the demo) 96 | 97 | * minor corrections to MATLAB m-file help comments. 98 | 99 | Dec 12, 2006, v2.0.7 100 | 101 | * minor MATLAB cleanup 102 | 103 | Dec 6, 2006, v2.0.6 104 | 105 | * Update to UFget. Now relies on the MATLAB urlwrite function instead of 106 | my own Java code. 107 | 108 | Nov 2006, v2.0.5 109 | 110 | * Added UFgrep to UFget toolbox. 111 | 112 | * No changes to C Source code, except for version number and date. 113 | 114 | * Added two test matrices: ibm32a and ibm32b. ibm32a is the Harwell/ 115 | Boeing matrix ibm32, but with the last column removed. ibm32b 116 | is the transpose of ibm32a. With optimization enabled (-O), 117 | 2 lines in cs_maxtrans.c are not tested; these matrices correct 118 | that problem. 119 | 120 | * Fixed UFget. Earlier version could not download matrices larger than 121 | 32MB. 122 | 123 | * Modified UFget/UFweb, to reflect changes in the UF Sparse Matrix 124 | Collection. 125 | 126 | * Added ccspy.m and cs_scc2.m MATLAB functions 127 | 128 | * Added examples to help info in each *.m MATLAB file 129 | 130 | * modified cs_dmspy to speed up the plotting of large matrices with many 131 | singletons 132 | 133 | * minor change to cspy: now draws a box around the matrix. 134 | 135 | * minor changes to MATLAB demos and tests. 136 | 137 | Oct 13, 2006, v2.0.4 138 | 139 | * minor modification to cs_updown.c. "n" was incorrectly declared "double". 140 | It should be "int". This was safe, just a little confusing (n was only 141 | used in an argument to cs_malloc, and is thus typecast). 142 | 143 | Sept 28, 2006, v2.0.3 144 | 145 | * minor modifications to MATLAB interface, to allow CSparse to be used 146 | in MATLAB 6.5. 147 | 148 | * added examples to m-files, other minor m-file cleanup. 149 | 150 | * bug fix to cspy, to handle NaN's properly. 151 | 152 | Aug 23, 2006: v2.0.2 153 | 154 | * change to cs_updown mexFunction, to handle multiple rank updates 155 | 156 | * symbolic links removed from Tcov/ directory in the distribution. 157 | They are now created by Tcov/Makefile as needed. This makes the 158 | zip files cleaner. Tcov/*test.c test files renamed. 159 | 160 | July 19, 2006: 161 | 162 | * minor fix to cs_must_compile.m and cs_make.m, to allow CSparse to be 163 | compiled in MATLAB 6.5 with cs_make. 164 | 165 | * minor fix to cspy for complex matrices (imaginary part was ignored). 166 | 167 | * no change to version number or date, since there are no changes that 168 | affect the appearance of CSparse in the book ("Direct Methods for 169 | Sparse Linear Systems", SIAM, 2006). 170 | 171 | June 24, 2006: 172 | 173 | * minor typos in comments corrected. No change in code itself, 174 | and no change in version number or date. 175 | 176 | May 27, 2006, v2.0.1: (this version is printed in the book) 177 | 178 | * minor bug fix. cs_util.c modified, so that cs_sprealloc (T,0) works 179 | properly for a triplet matrix T (setting T->nzmax equal to T->nz). 180 | The line in v2.0.0: 181 | 182 | nzmax = (nzmax <= 0) ? (A->p [A->n]) : nzmax ; 183 | 184 | changes to the following in v2.0.1: 185 | 186 | if (nzmax <= 0) nzmax = (CS_CSC (A)) ? (A->p [A->n]) : A->nz ; 187 | 188 | * minor typographical changes arising from the editting of the book. 189 | 190 | Apr 12, 2006, v2.0.0: 191 | 192 | * random permutation option added to cs_maxtrans and cs_dmperm, to help 193 | avoid rare cases where the O(|A|n) time complexity is reached in 194 | practice (GHS_indef/boyd2 in the UF sparse matrix collection, for 195 | example). New cs_randperm function added. 196 | 197 | Apr 10, 2006: 198 | 199 | * stylistic changes for the book (except for the bug fix): 200 | 201 | * "int order" parameter of cs_amd, cs_lusol, cs_cholsol, cs_qrsol, cs_sqr, 202 | cs_schol changed. Now 0 means no ordering, 1 is A+A', 2 is S*S', and 203 | 3 is A*A'. In v1.2 and earlier, "order" took on a value ranging from 204 | -1 to 2. "int n" parameter rearranged for cs_ipvec, cs_pvec, cs_post 205 | (int n moved to the end). cs_triplet renamed cs_compress. 206 | 207 | To ensure that these changes are propagated into user code that calls 208 | CSparse, the "order" parameter has been placed as the first parameter 209 | in all these routines. Your compiler will complain (gcc will halt) if 210 | you upgrade from v1.2 to v2.0 without changing your code. This is much 211 | better than a silent error in which you get the wrong ordering by 212 | mistake (with a huge penalty in run-time performance and no compiler 213 | warnings). 214 | 215 | New syntax (v2.0 and later): 216 | ---------------------------- 217 | 218 | order = 0: natural ordering 219 | order = 1: amd (A+A') 220 | order = 2: amd (S'*S), where S=A except dense rows dropped 221 | order = 3: amd (A'*A) 222 | 223 | int cs_cholsol (int order, const cs *A, double *b) ; 224 | int cs_lusol (int order, const cs *A, double *b, double tol) ; 225 | int cs_qrsol (int order, const cs *A, double *b) ; 226 | int *cs_amd (int order, const cs *A) ; 227 | css *cs_schol (int order, const cs *A) ; 228 | css *cs_sqr (int order, const cs *A, int qr) ; 229 | 230 | int *cs_post (const int *parent, int n) ; 231 | int cs_ipvec (const int *p, const double *b, double *x, int n) ; 232 | int cs_pvec (const int *p, const double *b, double *x, int n) ; 233 | 234 | cs *cs_compress (const cs *T) ; 235 | 236 | Old syntax (v1.2 and earlier): 237 | ------------------------------ 238 | 239 | order = -1: natural ordering 240 | order = 0: amd (A+A') 241 | order = 1: amd (S'*S), where S=A except dense rows dropped 242 | order = 2: amd (A'*A) 243 | 244 | int cs_cholsol (const cs *A, double *b, int order) ; 245 | int cs_lusol (const cs *A, double *b, int order, double tol) ; 246 | int cs_qrsol (const cs *A, double *b, int order) ; 247 | int *cs_amd (const cs *A, int order) ; 248 | css *cs_schol (const cs *A, int order) ; 249 | css *cs_sqr (const cs *A, int order, int qr) ; 250 | 251 | int *cs_post (int n, const int *parent) ; 252 | int cs_ipvec (int n, const int *p, const double *b, double *x) ; 253 | int cs_pvec (int n, const int *p, const double *b, double *x) ; 254 | 255 | cs *cs_triplet (const cs *T) ; 256 | 257 | * CS_OVERFLOW macro removed (removed from cs_malloc.c; not needed). 258 | 259 | * S->leftmost added to css (it was tacked onto S->pinv before). 260 | 261 | * P,Q,R,S components of csd struct changed to p,q,r,s. 262 | 263 | * Pinv and Q components of css struct changed to pinv and q. 264 | 265 | * CS_CSC and CS_TRIPLET macros added, to clarify which CSparse functions 266 | accept cs matrices in compressed column form, triplet form, or both. 267 | 268 | * check for negative row/column indices added to cs_entry. 269 | 270 | * cs_ereach and cs_leaf functions added. 271 | 272 | * call to cs_sprealloc added to cs_fkeep. 273 | 274 | * bug fixes in cs_counts and cs_amd (memory leak under rare out-of-memory 275 | conditions). 276 | 277 | Mar 15, 2006: 278 | 279 | * cs_scc modified so that the row and columns of each component are put in 280 | their natural order. cs_dmperm modified so that columns of each block 281 | (instead of rows) are placed in their natural order. 282 | 283 | * cs_splsolve renamed cs_spsolve, generalized to handle both Lx=b and 284 | Ux=b, and non-unit diagonal, and placed in its own file (cs_spsolve.c; 285 | it was a static function in cs_lu.c). cs_lsolve_mex.c and 286 | cs_splsolve_mex.c merged (the latter was removed). cs_spsolve.c file 287 | added 288 | 289 | * cs_dmspy changed, so that block borders line up better with the matrix. 290 | 291 | Mar 6, 2006: 292 | 293 | * Makefile modified so that the Tcov tests (which may not be portable) 294 | are not compiled and run by the default "make" in the CSparse directory. 295 | To compile everything, including the Tcov tests, use "make all". 296 | Trivial change to cs.h. 297 | 298 | Feb 27, 2006: 299 | 300 | * cs_reach, cs_dfs, cs_splsolve, cs_lu, and cs_scc changed to remove O(n) 301 | initialized workspace. 302 | * cs_reach and cs_splsolve now user-callable (were static in cs_lu.c). 303 | 304 | Feb 20, 2006: 305 | 306 | * various changes to simplify the construction of CXSparse 307 | 308 | Feb 7, 2006: 309 | 310 | * changed prototypes, adding "const" where appropriate. 311 | 312 | -------------------------------------------------------------------------------- /Doc/License.txt: -------------------------------------------------------------------------------- 1 | CSparse: a Concise Sparse matrix package. 2 | Copyright (c) 2006, Timothy A. Davis. 3 | http://www.suitesparse.com 4 | 5 | -------------------------------------------------------------------------------- 6 | 7 | CSparse is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU Lesser General Public 9 | License as published by the Free Software Foundation; either 10 | version 2.1 of the License, or (at your option) any later version. 11 | 12 | CSparse is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 | Lesser General Public License for more details. 16 | 17 | You should have received a copy of the GNU Lesser General Public 18 | License along with this Module; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 | -------------------------------------------------------------------------------- /Doc/lesser.txt: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 2.1, February 1999 3 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 5 | 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | [This is the first released version of the Lesser GPL. It also counts 10 | as the successor of the GNU Library Public License, version 2, hence 11 | the version number 2.1.] 12 | 13 | Preamble 14 | 15 | The licenses for most software are designed to take away your 16 | freedom to share and change it. By contrast, the GNU General Public 17 | Licenses are intended to guarantee your freedom to share and change 18 | free software--to make sure the software is free for all its users. 19 | 20 | This license, the Lesser General Public License, applies to some 21 | specially designated software packages--typically libraries--of the 22 | Free Software Foundation and other authors who decide to use it. You 23 | can use it too, but we suggest you first think carefully about whether 24 | this license or the ordinary General Public License is the better 25 | strategy to use in any particular case, based on the explanations below. 26 | 27 | When we speak of free software, we are referring to freedom of use, 28 | not price. Our General Public Licenses are designed to make sure that 29 | you have the freedom to distribute copies of free software (and charge 30 | for this service if you wish); that you receive source code or can get 31 | it if you want it; that you can change the software and use pieces of 32 | it in new free programs; and that you are informed that you can do 33 | these things. 34 | 35 | To protect your rights, we need to make restrictions that forbid 36 | distributors to deny you these rights or to ask you to surrender these 37 | rights. These restrictions translate to certain responsibilities for 38 | you if you distribute copies of the library or if you modify it. 39 | 40 | For example, if you distribute copies of the library, whether gratis 41 | or for a fee, you must give the recipients all the rights that we gave 42 | you. You must make sure that they, too, receive or can get the source 43 | code. If you link other code with the library, you must provide 44 | complete object files to the recipients, so that they can relink them 45 | with the library after making changes to the library and recompiling 46 | it. And you must show them these terms so they know their rights. 47 | 48 | We protect your rights with a two-step method: (1) we copyright the 49 | library, and (2) we offer you this license, which gives you legal 50 | permission to copy, distribute and/or modify the library. 51 | 52 | To protect each distributor, we want to make it very clear that 53 | there is no warranty for the free library. Also, if the library is 54 | modified by someone else and passed on, the recipients should know 55 | that what they have is not the original version, so that the original 56 | author's reputation will not be affected by problems that might be 57 | introduced by others. 58 | 59 | Finally, software patents pose a constant threat to the existence of 60 | any free program. We wish to make sure that a company cannot 61 | effectively restrict the users of a free program by obtaining a 62 | restrictive license from a patent holder. Therefore, we insist that 63 | any patent license obtained for a version of the library must be 64 | consistent with the full freedom of use specified in this license. 65 | 66 | Most GNU software, including some libraries, is covered by the 67 | ordinary GNU General Public License. This license, the GNU Lesser 68 | General Public License, applies to certain designated libraries, and 69 | is quite different from the ordinary General Public License. We use 70 | this license for certain libraries in order to permit linking those 71 | libraries into non-free programs. 72 | 73 | When a program is linked with a library, whether statically or using 74 | a shared library, the combination of the two is legally speaking a 75 | combined work, a derivative of the original library. The ordinary 76 | General Public License therefore permits such linking only if the 77 | entire combination fits its criteria of freedom. The Lesser General 78 | Public License permits more lax criteria for linking other code with 79 | the library. 80 | 81 | We call this license the "Lesser" General Public License because it 82 | does Less to protect the user's freedom than the ordinary General 83 | Public License. It also provides other free software developers Less 84 | of an advantage over competing non-free programs. These disadvantages 85 | are the reason we use the ordinary General Public License for many 86 | libraries. However, the Lesser license provides advantages in certain 87 | special circumstances. 88 | 89 | For example, on rare occasions, there may be a special need to 90 | encourage the widest possible use of a certain library, so that it becomes 91 | a de-facto standard. To achieve this, non-free programs must be 92 | allowed to use the library. A more frequent case is that a free 93 | library does the same job as widely used non-free libraries. In this 94 | case, there is little to gain by limiting the free library to free 95 | software only, so we use the Lesser General Public License. 96 | 97 | In other cases, permission to use a particular library in non-free 98 | programs enables a greater number of people to use a large body of 99 | free software. For example, permission to use the GNU C Library in 100 | non-free programs enables many more people to use the whole GNU 101 | operating system, as well as its variant, the GNU/Linux operating 102 | system. 103 | 104 | Although the Lesser General Public License is Less protective of the 105 | users' freedom, it does ensure that the user of a program that is 106 | linked with the Library has the freedom and the wherewithal to run 107 | that program using a modified version of the Library. 108 | 109 | The precise terms and conditions for copying, distribution and 110 | modification follow. Pay close attention to the difference between a 111 | "work based on the library" and a "work that uses the library". The 112 | former contains code derived from the library, whereas the latter must 113 | be combined with the library in order to run. 114 | 115 | GNU LESSER GENERAL PUBLIC LICENSE 116 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 117 | 118 | 0. This License Agreement applies to any software library or other 119 | program which contains a notice placed by the copyright holder or 120 | other authorized party saying it may be distributed under the terms of 121 | this Lesser General Public License (also called "this License"). 122 | Each licensee is addressed as "you". 123 | 124 | A "library" means a collection of software functions and/or data 125 | prepared so as to be conveniently linked with application programs 126 | (which use some of those functions and data) to form executables. 127 | 128 | The "Library", below, refers to any such software library or work 129 | which has been distributed under these terms. A "work based on the 130 | Library" means either the Library or any derivative work under 131 | copyright law: that is to say, a work containing the Library or a 132 | portion of it, either verbatim or with modifications and/or translated 133 | straightforwardly into another language. (Hereinafter, translation is 134 | included without limitation in the term "modification".) 135 | 136 | "Source code" for a work means the preferred form of the work for 137 | making modifications to it. For a library, complete source code means 138 | all the source code for all modules it contains, plus any associated 139 | interface definition files, plus the scripts used to control compilation 140 | and installation of the library. 141 | 142 | Activities other than copying, distribution and modification are not 143 | covered by this License; they are outside its scope. The act of 144 | running a program using the Library is not restricted, and output from 145 | such a program is covered only if its contents constitute a work based 146 | on the Library (independent of the use of the Library in a tool for 147 | writing it). Whether that is true depends on what the Library does 148 | and what the program that uses the Library does. 149 | 150 | 1. You may copy and distribute verbatim copies of the Library's 151 | complete source code as you receive it, in any medium, provided that 152 | you conspicuously and appropriately publish on each copy an 153 | appropriate copyright notice and disclaimer of warranty; keep intact 154 | all the notices that refer to this License and to the absence of any 155 | warranty; and distribute a copy of this License along with the 156 | Library. 157 | 158 | You may charge a fee for the physical act of transferring a copy, 159 | and you may at your option offer warranty protection in exchange for a 160 | fee. 161 | 162 | 2. You may modify your copy or copies of the Library or any portion 163 | of it, thus forming a work based on the Library, and copy and 164 | distribute such modifications or work under the terms of Section 1 165 | above, provided that you also meet all of these conditions: 166 | 167 | a) The modified work must itself be a software library. 168 | 169 | b) You must cause the files modified to carry prominent notices 170 | stating that you changed the files and the date of any change. 171 | 172 | c) You must cause the whole of the work to be licensed at no 173 | charge to all third parties under the terms of this License. 174 | 175 | d) If a facility in the modified Library refers to a function or a 176 | table of data to be supplied by an application program that uses 177 | the facility, other than as an argument passed when the facility 178 | is invoked, then you must make a good faith effort to ensure that, 179 | in the event an application does not supply such function or 180 | table, the facility still operates, and performs whatever part of 181 | its purpose remains meaningful. 182 | 183 | (For example, a function in a library to compute square roots has 184 | a purpose that is entirely well-defined independent of the 185 | application. Therefore, Subsection 2d requires that any 186 | application-supplied function or table used by this function must 187 | be optional: if the application does not supply it, the square 188 | root function must still compute square roots.) 189 | 190 | These requirements apply to the modified work as a whole. If 191 | identifiable sections of that work are not derived from the Library, 192 | and can be reasonably considered independent and separate works in 193 | themselves, then this License, and its terms, do not apply to those 194 | sections when you distribute them as separate works. But when you 195 | distribute the same sections as part of a whole which is a work based 196 | on the Library, the distribution of the whole must be on the terms of 197 | this License, whose permissions for other licensees extend to the 198 | entire whole, and thus to each and every part regardless of who wrote 199 | it. 200 | 201 | Thus, it is not the intent of this section to claim rights or contest 202 | your rights to work written entirely by you; rather, the intent is to 203 | exercise the right to control the distribution of derivative or 204 | collective works based on the Library. 205 | 206 | In addition, mere aggregation of another work not based on the Library 207 | with the Library (or with a work based on the Library) on a volume of 208 | a storage or distribution medium does not bring the other work under 209 | the scope of this License. 210 | 211 | 3. You may opt to apply the terms of the ordinary GNU General Public 212 | License instead of this License to a given copy of the Library. To do 213 | this, you must alter all the notices that refer to this License, so 214 | that they refer to the ordinary GNU General Public License, version 2, 215 | instead of to this License. (If a newer version than version 2 of the 216 | ordinary GNU General Public License has appeared, then you can specify 217 | that version instead if you wish.) Do not make any other change in 218 | these notices. 219 | 220 | Once this change is made in a given copy, it is irreversible for 221 | that copy, so the ordinary GNU General Public License applies to all 222 | subsequent copies and derivative works made from that copy. 223 | 224 | This option is useful when you wish to copy part of the code of 225 | the Library into a program that is not a library. 226 | 227 | 4. You may copy and distribute the Library (or a portion or 228 | derivative of it, under Section 2) in object code or executable form 229 | under the terms of Sections 1 and 2 above provided that you accompany 230 | it with the complete corresponding machine-readable source code, which 231 | must be distributed under the terms of Sections 1 and 2 above on a 232 | medium customarily used for software interchange. 233 | 234 | If distribution of object code is made by offering access to copy 235 | from a designated place, then offering equivalent access to copy the 236 | source code from the same place satisfies the requirement to 237 | distribute the source code, even though third parties are not 238 | compelled to copy the source along with the object code. 239 | 240 | 5. A program that contains no derivative of any portion of the 241 | Library, but is designed to work with the Library by being compiled or 242 | linked with it, is called a "work that uses the Library". Such a 243 | work, in isolation, is not a derivative work of the Library, and 244 | therefore falls outside the scope of this License. 245 | 246 | However, linking a "work that uses the Library" with the Library 247 | creates an executable that is a derivative of the Library (because it 248 | contains portions of the Library), rather than a "work that uses the 249 | library". The executable is therefore covered by this License. 250 | Section 6 states terms for distribution of such executables. 251 | 252 | When a "work that uses the Library" uses material from a header file 253 | that is part of the Library, the object code for the work may be a 254 | derivative work of the Library even though the source code is not. 255 | Whether this is true is especially significant if the work can be 256 | linked without the Library, or if the work is itself a library. The 257 | threshold for this to be true is not precisely defined by law. 258 | 259 | If such an object file uses only numerical parameters, data 260 | structure layouts and accessors, and small macros and small inline 261 | functions (ten lines or less in length), then the use of the object 262 | file is unrestricted, regardless of whether it is legally a derivative 263 | work. (Executables containing this object code plus portions of the 264 | Library will still fall under Section 6.) 265 | 266 | Otherwise, if the work is a derivative of the Library, you may 267 | distribute the object code for the work under the terms of Section 6. 268 | Any executables containing that work also fall under Section 6, 269 | whether or not they are linked directly with the Library itself. 270 | 271 | 6. As an exception to the Sections above, you may also combine or 272 | link a "work that uses the Library" with the Library to produce a 273 | work containing portions of the Library, and distribute that work 274 | under terms of your choice, provided that the terms permit 275 | modification of the work for the customer's own use and reverse 276 | engineering for debugging such modifications. 277 | 278 | You must give prominent notice with each copy of the work that the 279 | Library is used in it and that the Library and its use are covered by 280 | this License. You must supply a copy of this License. If the work 281 | during execution displays copyright notices, you must include the 282 | copyright notice for the Library among them, as well as a reference 283 | directing the user to the copy of this License. Also, you must do one 284 | of these things: 285 | 286 | a) Accompany the work with the complete corresponding 287 | machine-readable source code for the Library including whatever 288 | changes were used in the work (which must be distributed under 289 | Sections 1 and 2 above); and, if the work is an executable linked 290 | with the Library, with the complete machine-readable "work that 291 | uses the Library", as object code and/or source code, so that the 292 | user can modify the Library and then relink to produce a modified 293 | executable containing the modified Library. (It is understood 294 | that the user who changes the contents of definitions files in the 295 | Library will not necessarily be able to recompile the application 296 | to use the modified definitions.) 297 | 298 | b) Use a suitable shared library mechanism for linking with the 299 | Library. A suitable mechanism is one that (1) uses at run time a 300 | copy of the library already present on the user's computer system, 301 | rather than copying library functions into the executable, and (2) 302 | will operate properly with a modified version of the library, if 303 | the user installs one, as long as the modified version is 304 | interface-compatible with the version that the work was made with. 305 | 306 | c) Accompany the work with a written offer, valid for at 307 | least three years, to give the same user the materials 308 | specified in Subsection 6a, above, for a charge no more 309 | than the cost of performing this distribution. 310 | 311 | d) If distribution of the work is made by offering access to copy 312 | from a designated place, offer equivalent access to copy the above 313 | specified materials from the same place. 314 | 315 | e) Verify that the user has already received a copy of these 316 | materials or that you have already sent this user a copy. 317 | 318 | For an executable, the required form of the "work that uses the 319 | Library" must include any data and utility programs needed for 320 | reproducing the executable from it. However, as a special exception, 321 | the materials to be distributed need not include anything that is 322 | normally distributed (in either source or binary form) with the major 323 | components (compiler, kernel, and so on) of the operating system on 324 | which the executable runs, unless that component itself accompanies 325 | the executable. 326 | 327 | It may happen that this requirement contradicts the license 328 | restrictions of other proprietary libraries that do not normally 329 | accompany the operating system. Such a contradiction means you cannot 330 | use both them and the Library together in an executable that you 331 | distribute. 332 | 333 | 7. You may place library facilities that are a work based on the 334 | Library side-by-side in a single library together with other library 335 | facilities not covered by this License, and distribute such a combined 336 | library, provided that the separate distribution of the work based on 337 | the Library and of the other library facilities is otherwise 338 | permitted, and provided that you do these two things: 339 | 340 | a) Accompany the combined library with a copy of the same work 341 | based on the Library, uncombined with any other library 342 | facilities. This must be distributed under the terms of the 343 | Sections above. 344 | 345 | b) Give prominent notice with the combined library of the fact 346 | that part of it is a work based on the Library, and explaining 347 | where to find the accompanying uncombined form of the same work. 348 | 349 | 8. You may not copy, modify, sublicense, link with, or distribute 350 | the Library except as expressly provided under this License. Any 351 | attempt otherwise to copy, modify, sublicense, link with, or 352 | distribute the Library is void, and will automatically terminate your 353 | rights under this License. However, parties who have received copies, 354 | or rights, from you under this License will not have their licenses 355 | terminated so long as such parties remain in full compliance. 356 | 357 | 9. You are not required to accept this License, since you have not 358 | signed it. However, nothing else grants you permission to modify or 359 | distribute the Library or its derivative works. These actions are 360 | prohibited by law if you do not accept this License. Therefore, by 361 | modifying or distributing the Library (or any work based on the 362 | Library), you indicate your acceptance of this License to do so, and 363 | all its terms and conditions for copying, distributing or modifying 364 | the Library or works based on it. 365 | 366 | 10. Each time you redistribute the Library (or any work based on the 367 | Library), the recipient automatically receives a license from the 368 | original licensor to copy, distribute, link with or modify the Library 369 | subject to these terms and conditions. You may not impose any further 370 | restrictions on the recipients' exercise of the rights granted herein. 371 | You are not responsible for enforcing compliance by third parties with 372 | this License. 373 | 374 | 11. If, as a consequence of a court judgment or allegation of patent 375 | infringement or for any other reason (not limited to patent issues), 376 | conditions are imposed on you (whether by court order, agreement or 377 | otherwise) that contradict the conditions of this License, they do not 378 | excuse you from the conditions of this License. If you cannot 379 | distribute so as to satisfy simultaneously your obligations under this 380 | License and any other pertinent obligations, then as a consequence you 381 | may not distribute the Library at all. For example, if a patent 382 | license would not permit royalty-free redistribution of the Library by 383 | all those who receive copies directly or indirectly through you, then 384 | the only way you could satisfy both it and this License would be to 385 | refrain entirely from distribution of the Library. 386 | 387 | If any portion of this section is held invalid or unenforceable under any 388 | particular circumstance, the balance of the section is intended to apply, 389 | and the section as a whole is intended to apply in other circumstances. 390 | 391 | It is not the purpose of this section to induce you to infringe any 392 | patents or other property right claims or to contest validity of any 393 | such claims; this section has the sole purpose of protecting the 394 | integrity of the free software distribution system which is 395 | implemented by public license practices. Many people have made 396 | generous contributions to the wide range of software distributed 397 | through that system in reliance on consistent application of that 398 | system; it is up to the author/donor to decide if he or she is willing 399 | to distribute software through any other system and a licensee cannot 400 | impose that choice. 401 | 402 | This section is intended to make thoroughly clear what is believed to 403 | be a consequence of the rest of this License. 404 | 405 | 12. If the distribution and/or use of the Library is restricted in 406 | certain countries either by patents or by copyrighted interfaces, the 407 | original copyright holder who places the Library under this License may add 408 | an explicit geographical distribution limitation excluding those countries, 409 | so that distribution is permitted only in or among countries not thus 410 | excluded. In such case, this License incorporates the limitation as if 411 | written in the body of this License. 412 | 413 | 13. The Free Software Foundation may publish revised and/or new 414 | versions of the Lesser General Public License from time to time. 415 | Such new versions will be similar in spirit to the present version, 416 | but may differ in detail to address new problems or concerns. 417 | 418 | Each version is given a distinguishing version number. If the Library 419 | specifies a version number of this License which applies to it and 420 | "any later version", you have the option of following the terms and 421 | conditions either of that version or of any later version published by 422 | the Free Software Foundation. If the Library does not specify a 423 | license version number, you may choose any version ever published by 424 | the Free Software Foundation. 425 | 426 | 14. If you wish to incorporate parts of the Library into other free 427 | programs whose distribution conditions are incompatible with these, 428 | write to the author to ask for permission. For software which is 429 | copyrighted by the Free Software Foundation, write to the Free 430 | Software Foundation; we sometimes make exceptions for this. Our 431 | decision will be guided by the two goals of preserving the free status 432 | of all derivatives of our free software and of promoting the sharing 433 | and reuse of software generally. 434 | 435 | NO WARRANTY 436 | 437 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 438 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 439 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 440 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 441 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 442 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 443 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 444 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 445 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 446 | 447 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 448 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 449 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 450 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 451 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 452 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 453 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 454 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 455 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 456 | DAMAGES. 457 | 458 | END OF TERMS AND CONDITIONS 459 | 460 | How to Apply These Terms to Your New Libraries 461 | 462 | If you develop a new library, and you want it to be of the greatest 463 | possible use to the public, we recommend making it free software that 464 | everyone can redistribute and change. You can do so by permitting 465 | redistribution under these terms (or, alternatively, under the terms of the 466 | ordinary General Public License). 467 | 468 | To apply these terms, attach the following notices to the library. It is 469 | safest to attach them to the start of each source file to most effectively 470 | convey the exclusion of warranty; and each file should have at least the 471 | "copyright" line and a pointer to where the full notice is found. 472 | 473 | 474 | Copyright (C) 475 | 476 | This library is free software; you can redistribute it and/or 477 | modify it under the terms of the GNU Lesser General Public 478 | License as published by the Free Software Foundation; either 479 | version 2.1 of the License, or (at your option) any later version. 480 | 481 | This library is distributed in the hope that it will be useful, 482 | but WITHOUT ANY WARRANTY; without even the implied warranty of 483 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 484 | Lesser General Public License for more details. 485 | 486 | You should have received a copy of the GNU Lesser General Public 487 | License along with this library; if not, write to the Free Software 488 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 489 | 490 | Also add information on how to contact you by electronic and paper mail. 491 | 492 | You should also get your employer (if you work as a programmer) or your 493 | school, if any, to sign a "copyright disclaimer" for the library, if 494 | necessary. Here is a sample; alter the names: 495 | 496 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 497 | library `Frob' (a library for tweaking knobs) written by James Random Hacker. 498 | 499 | , 1 April 1990 500 | Ty Coon, President of Vice 501 | 502 | That's all there is to it! 503 | 504 | 505 | -------------------------------------------------------------------------------- /Include/cs.h: -------------------------------------------------------------------------------- 1 | #ifndef _CS_H 2 | #define _CS_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #ifdef MATLAB_MEX_FILE 9 | #include "mex.h" 10 | #endif 11 | #define CS_VER 3 /* CSparse Version */ 12 | #define CS_SUBVER 1 13 | #define CS_SUBSUB 3 14 | #define CS_DATE "Mar 26, 2014" /* CSparse release date */ 15 | #define CS_COPYRIGHT "Copyright (c) Timothy A. Davis, 2006-2014" 16 | 17 | #ifdef MATLAB_MEX_FILE 18 | #undef csi 19 | #define csi mwSignedIndex 20 | #endif 21 | #ifndef csi 22 | #define csi ptrdiff_t 23 | #endif 24 | 25 | /* --- primary CSparse routines and data structures ------------------------- */ 26 | typedef struct cs_sparse /* matrix in compressed-column or triplet form */ 27 | { 28 | csi nzmax ; /* maximum number of entries */ 29 | csi m ; /* number of rows */ 30 | csi n ; /* number of columns */ 31 | csi *p ; /* column pointers (size n+1) or col indices (size nzmax) */ 32 | csi *i ; /* row indices, size nzmax */ 33 | double *x ; /* numerical values, size nzmax */ 34 | csi nz ; /* # of entries in triplet matrix, -1 for compressed-col */ 35 | } cs ; 36 | 37 | cs *cs_add (const cs *A, const cs *B, double alpha, double beta) ; 38 | csi cs_cholsol (csi order, const cs *A, double *b) ; 39 | cs *cs_compress (const cs *T) ; 40 | csi cs_dupl (cs *A) ; 41 | csi cs_entry (cs *T, csi i, csi j, double x) ; 42 | csi cs_gaxpy (const cs *A, const double *x, double *y) ; 43 | cs *cs_load (FILE *f) ; 44 | csi cs_lusol (csi order, const cs *A, double *b, double tol) ; 45 | cs *cs_multiply (const cs *A, const cs *B) ; 46 | double cs_norm (const cs *A) ; 47 | csi cs_print (const cs *A, csi brief) ; 48 | csi cs_qrsol (csi order, const cs *A, double *b) ; 49 | cs *cs_transpose (const cs *A, csi values) ; 50 | /* utilities */ 51 | void *cs_calloc (csi n, size_t size) ; 52 | void *cs_free (void *p) ; 53 | void *cs_realloc (void *p, csi n, size_t size, csi *ok) ; 54 | cs *cs_spalloc (csi m, csi n, csi nzmax, csi values, csi triplet) ; 55 | cs *cs_spfree (cs *A) ; 56 | csi cs_sprealloc (cs *A, csi nzmax) ; 57 | void *cs_malloc (csi n, size_t size) ; 58 | 59 | /* --- secondary CSparse routines and data structures ----------------------- */ 60 | typedef struct cs_symbolic /* symbolic Cholesky, LU, or QR analysis */ 61 | { 62 | csi *pinv ; /* inverse row perm. for QR, fill red. perm for Chol */ 63 | csi *q ; /* fill-reducing column permutation for LU and QR */ 64 | csi *parent ; /* elimination tree for Cholesky and QR */ 65 | csi *cp ; /* column pointers for Cholesky, row counts for QR */ 66 | csi *leftmost ; /* leftmost[i] = min(find(A(i,:))), for QR */ 67 | csi m2 ; /* # of rows for QR, after adding fictitious rows */ 68 | double lnz ; /* # entries in L for LU or Cholesky; in V for QR */ 69 | double unz ; /* # entries in U for LU; in R for QR */ 70 | } css ; 71 | 72 | typedef struct cs_numeric /* numeric Cholesky, LU, or QR factorization */ 73 | { 74 | cs *L ; /* L for LU and Cholesky, V for QR */ 75 | cs *U ; /* U for LU, R for QR, not used for Cholesky */ 76 | csi *pinv ; /* partial pivoting for LU */ 77 | double *B ; /* beta [0..n-1] for QR */ 78 | } csn ; 79 | 80 | typedef struct cs_dmperm_results /* cs_dmperm or cs_scc output */ 81 | { 82 | csi *p ; /* size m, row permutation */ 83 | csi *q ; /* size n, column permutation */ 84 | csi *r ; /* size nb+1, block k is rows r[k] to r[k+1]-1 in A(p,q) */ 85 | csi *s ; /* size nb+1, block k is cols s[k] to s[k+1]-1 in A(p,q) */ 86 | csi nb ; /* # of blocks in fine dmperm decomposition */ 87 | csi rr [5] ; /* coarse row decomposition */ 88 | csi cc [5] ; /* coarse column decomposition */ 89 | } csd ; 90 | 91 | csi *cs_amd (csi order, const cs *A) ; 92 | csn *cs_chol (const cs *A, const css *S) ; 93 | csd *cs_dmperm (const cs *A, csi seed) ; 94 | csi cs_droptol (cs *A, double tol) ; 95 | csi cs_dropzeros (cs *A) ; 96 | csi cs_happly (const cs *V, csi i, double beta, double *x) ; 97 | csi cs_ipvec (const csi *p, const double *b, double *x, csi n) ; 98 | csi cs_lsolve (const cs *L, double *x) ; 99 | csi cs_ltsolve (const cs *L, double *x) ; 100 | csn *cs_lu (const cs *A, const css *S, double tol) ; 101 | cs *cs_permute (const cs *A, const csi *pinv, const csi *q, csi values) ; 102 | csi *cs_pinv (const csi *p, csi n) ; 103 | csi cs_pvec (const csi *p, const double *b, double *x, csi n) ; 104 | csn *cs_qr (const cs *A, const css *S) ; 105 | css *cs_schol (csi order, const cs *A) ; 106 | css *cs_sqr (csi order, const cs *A, csi qr) ; 107 | cs *cs_symperm (const cs *A, const csi *pinv, csi values) ; 108 | csi cs_updown (cs *L, csi sigma, const cs *C, const csi *parent) ; 109 | csi cs_usolve (const cs *U, double *x) ; 110 | csi cs_utsolve (const cs *U, double *x) ; 111 | /* utilities */ 112 | css *cs_sfree (css *S) ; 113 | csn *cs_nfree (csn *N) ; 114 | csd *cs_dfree (csd *D) ; 115 | 116 | /* --- tertiary CSparse routines -------------------------------------------- */ 117 | csi *cs_counts (const cs *A, const csi *parent, const csi *post, csi ata) ; 118 | double cs_cumsum (csi *p, csi *c, csi n) ; 119 | csi cs_dfs (csi j, cs *G, csi top, csi *xi, csi *pstack, const csi *pinv) ; 120 | csi cs_ereach (const cs *A, csi k, const csi *parent, csi *s, csi *w) ; 121 | csi *cs_etree (const cs *A, csi ata) ; 122 | csi cs_fkeep (cs *A, csi (*fkeep) (csi, csi, double, void *), void *other) ; 123 | double cs_house (double *x, double *beta, csi n) ; 124 | csi cs_leaf (csi i, csi j, const csi *first, csi *maxfirst, csi *prevleaf, 125 | csi *ancestor, csi *jleaf) ; 126 | csi *cs_maxtrans (const cs *A, csi seed) ; 127 | csi *cs_post (const csi *parent, csi n) ; 128 | csi *cs_randperm (csi n, csi seed) ; 129 | csi cs_reach (cs *G, const cs *B, csi k, csi *xi, const csi *pinv) ; 130 | csi cs_scatter (const cs *A, csi j, double beta, csi *w, double *x, csi mark, 131 | cs *C, csi nz) ; 132 | csd *cs_scc (cs *A) ; 133 | csi cs_spsolve (cs *G, const cs *B, csi k, csi *xi, double *x, 134 | const csi *pinv, csi lo) ; 135 | csi cs_tdfs (csi j, csi k, csi *head, const csi *next, csi *post, 136 | csi *stack) ; 137 | /* utilities */ 138 | csd *cs_dalloc (csi m, csi n) ; 139 | csd *cs_ddone (csd *D, cs *C, void *w, csi ok) ; 140 | cs *cs_done (cs *C, void *w, void *x, csi ok) ; 141 | csi *cs_idone (csi *p, cs *C, void *w, csi ok) ; 142 | csn *cs_ndone (csn *N, cs *C, void *w, void *x, csi ok) ; 143 | 144 | #define CS_MAX(a,b) (((a) > (b)) ? (a) : (b)) 145 | #define CS_MIN(a,b) (((a) < (b)) ? (a) : (b)) 146 | #define CS_FLIP(i) (-(i)-2) 147 | #define CS_UNFLIP(i) (((i) < 0) ? CS_FLIP(i) : (i)) 148 | #define CS_MARKED(w,j) (w [j] < 0) 149 | #define CS_MARK(w,j) { w [j] = CS_FLIP (w [j]) ; } 150 | #define CS_CSC(A) (A && (A->nz == -1)) 151 | #define CS_TRIPLET(A) (A && (A->nz >= 0)) 152 | #endif 153 | -------------------------------------------------------------------------------- /Lib/Makefile: -------------------------------------------------------------------------------- 1 | CF = $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -O 2 | I = -I../Include 3 | RANLIB = ranlib 4 | ARCHIVE = $(AR) $(ARFLAGS) 5 | 6 | all: libcsparse.a 7 | 8 | CS = cs_add.o cs_amd.o cs_chol.o cs_cholsol.o cs_counts.o cs_cumsum.o \ 9 | cs_droptol.o cs_dropzeros.o cs_dupl.o cs_entry.o \ 10 | cs_etree.o cs_fkeep.o cs_gaxpy.o cs_happly.o cs_house.o cs_ipvec.o \ 11 | cs_lsolve.o cs_ltsolve.o cs_lu.o cs_lusol.o cs_util.o cs_multiply.o \ 12 | cs_permute.o cs_pinv.o cs_post.o cs_pvec.o cs_qr.o cs_qrsol.o \ 13 | cs_scatter.o cs_schol.o cs_sqr.o cs_symperm.o cs_tdfs.o cs_malloc.o \ 14 | cs_transpose.o cs_compress.o cs_usolve.o cs_utsolve.o cs_scc.o \ 15 | cs_maxtrans.o cs_dmperm.o cs_updown.o cs_print.o cs_norm.o cs_load.o \ 16 | cs_dfs.o cs_reach.o cs_spsolve.o cs_ereach.o cs_leaf.o cs_randperm.o 17 | 18 | $(CS): ../Include/cs.h Makefile 19 | 20 | %.o: ../Source/%.c ../Include/cs.h 21 | $(CC) $(CF) $(I) -c $< 22 | 23 | libcsparse.a: $(CS) 24 | $(ARCHIVE) libcsparse.a $(CS) 25 | - $(RANLIB) libcsparse.a 26 | 27 | clean: 28 | - $(RM) *.o 29 | 30 | purge: distclean 31 | 32 | distclean: clean 33 | - $(RM) *.a *.obj *.dll 34 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------------ 2 | # CSparse Makefile 3 | #------------------------------------------------------------------------------ 4 | 5 | VERSION = 3.1.3 6 | 7 | C: 8 | ( cd Lib ; $(MAKE) ) 9 | ( cd Demo ; $(MAKE) ) 10 | 11 | all: C cov 12 | 13 | library: 14 | ( cd Lib ; $(MAKE) ) 15 | 16 | cov: 17 | ( cd Tcov ; $(MAKE) ) 18 | 19 | clean: 20 | ( cd Lib ; $(MAKE) clean ) 21 | ( cd Demo ; $(MAKE) clean ) 22 | ( cd Tcov ; $(MAKE) clean ) 23 | ( cd MATLAB/CSparse ; $(RM) *.o ) 24 | ( cd MATLAB/Test ; $(RM) *.o ) 25 | 26 | purge: 27 | ( cd Lib ; $(MAKE) purge ) 28 | ( cd Demo ; $(MAKE) purge ) 29 | ( cd Tcov ; $(MAKE) purge ) 30 | ( cd MATLAB/CSparse ; $(RM) *.o *.mex* ) 31 | ( cd MATLAB/Test ; $(RM) *.o *.mex* ) 32 | 33 | distclean: purge 34 | 35 | # do not install CSparse; use CXSparse instead 36 | install: 37 | 38 | # uninstall CSparse: do nothing 39 | uninstall: 40 | 41 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | ### 2 | This is a copy of the CSParse library without the /MATLAB and Matrix/ 3 | folders. 4 | ### 5 | 6 | CSparse: a Concise Sparse Matrix package. 7 | VERSION 3.1.3, Copyright (c) 2006-2014, Timothy A. Davis, Mar 26, 2014 8 | http://www.suitesparse.com 9 | 10 | Refer to "Direct Methods for Sparse Linear Systems," Timothy A. Davis, 11 | SIAM, Philadelphia, 2006. No detailed user guide is included in this 12 | package; the user guide is the book itself. 13 | 14 | The algorithms contained in CSparse have been chosen with five goals in mind: 15 | (1) they must embody much of the theory behind sparse matrix algorithms, 16 | (2) they must be either asymptotically optimal in their run time and memory 17 | usage or be fast in practice, 18 | (3) they must be concise so as to be easily understood and short enough to 19 | print in the book, 20 | (4) they must cover a wide spectrum of matrix operations, and 21 | (5) they must be accurate and robust. 22 | The focus is on direct methods; iterative methods and solvers for 23 | eigenvalue problems are beyond the scope of this package. 24 | 25 | No detailed user guide is included in this package; the user guide is the 26 | book itself. Some indication of how to call the CSparse C routines is given 27 | by the M-files in the MATLAB/CSparse directory. 28 | 29 | Complex matrices are not supported, except for methods that operate only 30 | on the nonzero pattern of a matrix. A complex version of CSparse appears 31 | as a separate package, CXSparse ("Concise Extended Sparse matrix package"). 32 | 33 | The performance of the sparse factorization methods in CSparse will not be 34 | competitive with UMFPACK or CHOLMOD, but the codes are much more concise and 35 | easy to understand (see the above goals). Other methods are competitive. 36 | 37 | Some of the MATLAB tests require the AMD package. 38 | See http://www.suitesparse.com for CSparse and the AMD ordering 39 | package. See the Doc/License.txt file for the license (GNU LGPL). 40 | 41 | To compile the C-library (./Source) and C demo programs (./Demo) just type 42 | "make" in this directory. This should work on any system with the "make" 43 | command. To run the exhaustive tests, type "make" in the Tcov directory 44 | (Linux is assumed). To compile the MATLAB mexFunctions type "make mex" in 45 | this directory, or just "make" in the MATLAB directory. To remove all files 46 | not in the original distribution, type "make distclean". I recommend that you 47 | use a different level of optimization than "cc -O", which was chosen so that 48 | the Makefile is portable. See Source/Makefile. 49 | 50 | You can simply type "cs_install" while in the CSparse/MATLAB directory to 51 | compile and install CSparse for use in MATLAB. This is especially useful for 52 | a typical Microsoft Windows system, which does not include "make". For more 53 | details, see CSparse/MATLAB/README.txt. 54 | 55 | -------------------------------------------------------------------------------- 56 | Contents: 57 | -------------------------------------------------------------------------------- 58 | 59 | Demo/ demo C programs that use CSparse 60 | Doc/ license and change log 61 | Makefile Makefile for the whole package 62 | MATLAB/ MATLAB interface, demos, and tests for CSparse 63 | Matrix/ sample matrices 64 | README.txt this file 65 | Source/ primary CSparse source files (C only, no MATLAB) 66 | Tcov/ CSparse tests 67 | 68 | -------------------------------------------------------------------------------- 69 | ./Doc: license and change log 70 | -------------------------------------------------------------------------------- 71 | 72 | ChangeLog changes in CSparse since first release 73 | lesser.txt the GNU LGPL 74 | License.txt license (GNU LGPL) 75 | 76 | -------------------------------------------------------------------------------- 77 | ./Source: Primary source code for CSparse 78 | -------------------------------------------------------------------------------- 79 | 80 | cs_add.c add sparse matrices 81 | cs_amd.c approximate minimum degree 82 | cs_chol.c sparse Cholesky 83 | cs_cholsol.c x=A\b using sparse Cholesky 84 | cs_compress.c convert a triplet form to compressed-column form 85 | cs_counts.c column counts for Cholesky and QR 86 | cs_cumsum.c cumulative sum 87 | cs_dfs.c depth-first-search 88 | cs_dmperm.c Dulmage-Mendelsohn permutation 89 | cs_droptol.c drop small entries from a sparse matrix 90 | cs_dropzeros.c drop zeros from a sparse matrix 91 | cs_dupl.c remove (and sum) duplicates 92 | cs_entry.c add an entry to a triplet matrix 93 | cs_ereach.c nonzero pattern of Cholesky L(k,:) from etree and triu(A(:,k)) 94 | cs_etree.c find elimination tree 95 | cs_fkeep.c drop entries from a sparse matrix 96 | cs_gaxpy.c sparse matrix times dense matrix 97 | cs.h include file for CSparse 98 | cs_happly.c apply Householder reflection 99 | cs_house.c compute Householder reflection 100 | cs_ipvec.c x(p)=b 101 | cs_leaf.c determine if j is a leaf of the skeleton matrix and find lca 102 | cs_load.c load a sparse matrix from a file 103 | cs_lsolve.c x=L\b 104 | cs_ltsolve.c x=L'\b 105 | cs_lu.c sparse LU factorization 106 | cs_lusol.c x=A\b using sparse LU factorization 107 | cs_malloc.c memory manager 108 | cs_maxtrans.c maximum transveral (permutation for zero-free diagonal) 109 | cs_multiply.c sparse matrix multiply 110 | cs_norm.c sparse matrix norm 111 | cs_permute.c permute a sparse matrix 112 | cs_pinv.c invert a permutation vector 113 | cs_post.c postorder an elimination tree 114 | cs_print.c print a sparse matrix 115 | cs_pvec.c x=b(p) 116 | cs_qr.c sparse QR 117 | cs_qrsol.c solve a least-squares problem 118 | cs_randperm.c random permutation 119 | cs_reach.c find nonzero pattern of x=L\b for sparse L and b 120 | cs_scatter.c scatter a sparse vector 121 | cs_scc.c strongly-connected components 122 | cs_schol.c symbolic Cholesky 123 | cs_spsolve.c x=G\b where G, x, and b are sparse, and G upper/lower triangular 124 | cs_sqr.c symbolic QR (also can be used for LU) 125 | cs_symperm.c symmetric permutation of a sparse matrix 126 | cs_tdfs.c depth-first-search of a tree 127 | cs_transpose.c transpose a sparse matrix 128 | cs_updown.c sparse rank-1 Cholesky update/downate 129 | cs_usolve.c x=U\b 130 | cs_util.c various utilities (allocate/free matrices, workspace, etc) 131 | cs_utsolve.c x=U'\b 132 | Makefile Makefile for CSparse 133 | README.txt README file for CSparse 134 | 135 | 136 | -------------------------------------------------------------------------------- 137 | ./Demo: C program demos 138 | -------------------------------------------------------------------------------- 139 | 140 | cs_demo1.c read a matrix from a file and perform basic matrix operations 141 | cs_demo2.c read a matrix from a file and solve a linear system 142 | cs_demo3.c read a matrix, solve a linear system, update/downdate 143 | cs_demo.c support routines for cs_demo*.c 144 | cs_demo.h include file for demo programs 145 | cs_demo.out output of "make", which runs the demos on some matrices 146 | Makefile Makefile for Demo programs 147 | readhb.f read a Rutherford-Boeing matrix 148 | README.txt Demo README file 149 | 150 | 151 | -------------------------------------------------------------------------------- 152 | ./MATLAB: MATLAB interface, demos, and tests 153 | -------------------------------------------------------------------------------- 154 | 155 | cs_install.m MATLAB function for compiling and installing CSparse for MATLAB 156 | CSparse/ MATLAB interface for CSparse 157 | Demo/ MATLAB demos for CSparse 158 | Makefile MATLAB interface Makefile 159 | README.txt MATLAB README file 160 | Test/ MATLAB test for CSparse, and "textbook" routines 161 | UFget/ MATLAB interface to UF Sparse Matrix Collection 162 | 163 | 164 | -------------------------------------------------------------------------------- 165 | ./MATLAB/CSparse: MATLAB interface for CSparse 166 | -------------------------------------------------------------------------------- 167 | 168 | Contents.m Contents of MATLAB interface to CSparse 169 | cs_add.m add two sparse matrices 170 | cs_add_mex.c 171 | cs_amd.m approximate minimum degree 172 | cs_amd_mex.c 173 | cs_chol.m sparse Cholesky 174 | cs_chol_mex.c 175 | cs_cholsol.m x=A\b using a sparse Cholesky 176 | cs_cholsol_mex.c 177 | cs_counts.m column counts for Cholesky or QR (like "symbfact" in MATLAB) 178 | cs_counts_mex.c 179 | cs_dmperm.m Dulmage-Mendelsohn permutation 180 | cs_dmperm_mex.c 181 | cs_dmsol.m x=A\b using dmperm 182 | cs_dmspy.m plot a picture of a dmperm-permuted matrix 183 | cs_droptol.m drop small entries 184 | cs_droptol_mex.c 185 | cs_esep.m find edge separator 186 | cs_etree.m compute elimination tree 187 | cs_etree_mex.c 188 | cs_gaxpy.m sparse matrix times dense vector 189 | cs_gaxpy_mex.c 190 | cs_lsolve.m x=L\b where L is lower triangular 191 | cs_lsolve_mex.c 192 | cs_ltsolve.m x=L'\b where L is lower triangular 193 | cs_ltsolve_mex.c 194 | cs_lu.m sparse LU factorization 195 | cs_lu_mex.c 196 | cs_lusol.m x=A\b using sparse LU factorization 197 | cs_lusol_mex.c 198 | cs_make.m compiles CSparse for use in MATLAB 199 | cs_mex.c support routines for CSparse mexFunctions 200 | cs_mex.h 201 | cs_multiply.m sparse matrix multiply 202 | cs_multiply_mex.c 203 | cs_must_compile.m determine if a source file needs to be compiled with mex 204 | cs_nd.m nested dissection 205 | cs_nsep.m find node separator 206 | cs_permute.m permute a sparse matrix 207 | cs_permute_mex.c 208 | cs_print.m print a sparse matrix 209 | cs_print_mex.c 210 | cs_qleft.m apply Householder vectors to the left 211 | cs_qright.m apply Householder vectors to the right 212 | cs_qr.m sparse QR factorization 213 | cs_qr_mex.c 214 | cs_qrsol.m solve a sparse least squares problem 215 | cs_qrsol_mex.c 216 | cs_randperm.m randdom permutation 217 | cs_randperm_mex.c 218 | cs_scc.m strongly-connected components 219 | cs_scc_mex.c 220 | cs_sep.m convert an edge separator into a node separator 221 | cs_sparse.m convert a triplet form matrix to a compress-column form 222 | cs_sparse_mex.c 223 | cs_symperm.m symmetric permutation of a sparse matrix 224 | cs_symperm_mex.c 225 | cs_sqr.m symbolic QR ordering and analysis 226 | cs_sqr_mex.c 227 | cs_thumb_mex.c compute small "thumbnail" of a sparse matrix (for cspy). 228 | cs_transpose.m transpose a sparse matrix 229 | cs_transpose_mex.c 230 | cs_updown.m sparse Cholesky update/downdate 231 | cs_updown_mex.c 232 | cs_usolve.m x=U\b where U is upper triangular 233 | cs_usolve_mex.c 234 | cs_utsolve.m x=U'\b where U is upper triangular 235 | cs_utsolve_mex.c 236 | cspy.m a color "spy" 237 | Makefile Makefile for CSparse MATLAB interface 238 | README.txt README file for CSparse MATLAB interface 239 | 240 | 241 | -------------------------------------------------------------------------------- 242 | ./MATLAB/Demo: MATLAB demos for CSparse 243 | -------------------------------------------------------------------------------- 244 | 245 | Contents.m Contents of MATLAB demo for CSparse 246 | cs_demo.m run all MATLAB demos for CSparse 247 | cs_demo1.m MATLAB version of Demo/cs_demo1.c 248 | cs_demo2.m MATLAB version of Demo/cs_demo2.c 249 | cs_demo3.m MATLAB version of Demo/cs_demo3.c 250 | private/ private functions for MATLAB demos 251 | README.txt README file for CSparse MATLAB demo 252 | 253 | 254 | -------------------------------------------------------------------------------- 255 | ./MATLAB/Demo/private: private functions for MATLAB demos 256 | -------------------------------------------------------------------------------- 257 | 258 | demo2.m demo 2 259 | demo3.m demo 3 260 | ex_1.m example 1 261 | ex2.m example 2 262 | ex3.m example 3 263 | frand.m generate a random finite-element matrix 264 | get_problem.m get a matrix 265 | is_sym.m determine if a matrix is symmetric 266 | mesh2d1.m construct a 2D mesh (method 1) 267 | mesh2d2.m construct a 2D mesh (method 2) 268 | mesh3d1.m construct a 3D mesh (method 1) 269 | mesh3d2.m construct a 3D mesh (method 2) 270 | print_order.m print the ordering method used 271 | resid.m compute residual 272 | rhs.m create right-hand-side 273 | 274 | 275 | -------------------------------------------------------------------------------- 276 | ./MATLAB/Test: Extensive test of CSparse, in MATLAB 277 | -------------------------------------------------------------------------------- 278 | 279 | Makefile Makefile for MATLAB Test directory 280 | README.txt README file for MATLAB/Test 281 | Contents.m Contents of MATLAB/Test, "textbook" files only 282 | 283 | chol_downdate.m downdate a Cholesky factorization. 284 | chol_left.m left-looking Cholesky factorization. 285 | chol_left2.m left-looking Cholesky factorization, more details. 286 | chol_right.m right-looking Cholesky factorization. 287 | chol_super.m left-looking "supernodal" Cholesky factorization. 288 | chol_up.m up-looking Cholesky factorization. 289 | chol_update.m update a Cholesky factorization. 290 | chol_updown.m update or downdate a Cholesky factorization. 291 | cond1est.m 1-norm condition estimate. 292 | cs_fiedler.m the Fiedler vector of a connected graph. 293 | givens2.m find a Givens rotation. 294 | house.m find a Householder reflection. 295 | lu_left.m left-looking LU factorization. 296 | lu_right.m right-looking LU factorization. 297 | lu_rightp.m right-looking LU factorization, with partial pivoting. 298 | lu_rightpr.m recursive right-looking LU, with partial pivoting. 299 | lu_rightr.m recursive right-looking LU. 300 | norm1est.m 1-norm estimate. 301 | qr_givens.m Givens-rotation QR factorization. 302 | qr_givens_full.m Givens-rotation QR factorization, for full matrices. 303 | qr_left.m left-looking Householder QR factorization. 304 | qr_right.m right-looking Householder QR factorization. 305 | cs_fiedler.m Fiedler vector 306 | 307 | cs_frand.m generate a random finite-element matrix 308 | cs_frand_mex.c 309 | cs_ipvec.m x(p)=b 310 | cs_ipvec_mex.c 311 | cs_maxtransr.m recursive maximum matching algorithm 312 | cs_maxtransr_mex.c 313 | cs_pvec.m x=b(p) 314 | cs_pvec_mex.c interface for cs_pvec 315 | cs_reach.m non-recursive reach (interface to CSparse cs_reach) 316 | cs_reach_mex.c non-recursive x=spones(L\sparse(b)) 317 | cs_reachr.m recursive reach (interface to CSparse cs_reachr) 318 | cs_reachr_mex.c 319 | cs_rowcnt.m row counts for sparse Cholesky 320 | cs_rowcnt_mex.c row counts for sparse Cholesky 321 | cs_sparse2.m same as cs_sparse, to test cs_entry function 322 | cs_sparse2_mex.c like cs_sparse, but for testing cs_entry 323 | 324 | cs_test_make.m compiles MATLAB tests 325 | 326 | check_if_same.m check if two inputs are identical or not 327 | choldn.m Cholesky downdate 328 | cholup.m Cholesky update, using Given's rotations 329 | cholupdown.m Cholesky update/downdate (Bischof, Pan, and Tang method) 330 | cs_q1.m construct Q from Householder vectors 331 | cs_test_make.m compiles the CSparse, Demo, and Test mexFunctions. 332 | dmperm_test.m test cs_dmperm 333 | chol_example.m simple Cholesky factorization example 334 | etree_sample.m construct a sample etree and symbolic factorization 335 | gqr3.m QR factorization, based on Givens rotations 336 | happly.m apply Householder reflection to a vector 337 | hmake1.m construct a Householder reflection 338 | mynormest1.m estimate norm(A,1), using LU factorization (L*U = P*A*Q). 339 | myqr.m QR factorization using Householder reflections 340 | another_colormap.m try another color map 341 | cspy_test.m test cspy and cs_dmspy 342 | qr2.m QR factorization based on Householder reflections 343 | sample_colormap.m try a colormap for use in cspy 344 | signum.m compute and display the sign of a column vector x 345 | sqr_example.m test cs_sqr 346 | dmspy_test.m test cspy, cs_dmspy, and cs_dmperm 347 | test_qr.m test various QR factorization methods 348 | test_randperms.m test random permutations 349 | testh.m test Householder reflections 350 | test_qr1.m test QR factorizations 351 | test_qrsol.m test cs_qrsol 352 | test_sep.m test cs_sep, and compare with Gilbert's meshpart vtxsep 353 | testall.m test all CSparse functions (run tests 1 to 28 below) 354 | test1.m test cs_transpose 355 | test2.m test cs_sparse 356 | test3.m test cs_lsolve, cs_ltsolve, cs_usolve, cs_chol 357 | test4.m test cs_multiply 358 | test5.m test cs_add 359 | test6.m test cs_reach, cs_reachr, cs_lsolve, cs_usolve 360 | test7.m test cs_lu 361 | test8.m test cs_cholsol, cs_lusol 362 | test9.m test cs_qr 363 | test10.m test cs_qr 364 | test11.m test cs_rowcnt 365 | test12.m test cs_qr and compare with svd 366 | test13.m test cs_counts, cs_etree 367 | test14.m test cs_droptol 368 | test15.m test cs_amd 369 | test16.m test cs_amd 370 | test17.m test cs_qr, cs_qright, cs_q1, cs_qrleft, cs_qrsol 371 | test18.m test iterative refinement after backslash 372 | test19.m test cs_dmperm, cs_maxtransr, cs_dmspy, cs_scc 373 | test20.m test cholupdown 374 | test21.m test cs_updown 375 | test22.m test cond1est 376 | test23.m test cs_dmspy 377 | test24.m test cs_fielder 378 | test25.m test cs_nd 379 | test26.m test cs_dmsol and cs_dmspy 380 | test27.m test cs_qr, cs_utsolve, cs_qrsol 381 | test28.m test cs_randperm, cs_dmperm 382 | 383 | 384 | -------------------------------------------------------------------------------- 385 | ./MATLAB/UFget: MATLAB interface for the UF Sparse Matrix Collection 386 | -------------------------------------------------------------------------------- 387 | 388 | Contents.m Contents of UFget 389 | mat/ default directory where downloaded matrices will be put 390 | README.txt README file for UFget 391 | UFget_defaults.m default parameter settings 392 | UFget_example.m example of use 393 | UFget_install.m installs UFget temporarily (for current session) 394 | UFget_java.class read a url and load it in into MATLAB (compiled Java code) 395 | UFget_java.java read a url and load it in into MATLAB (Java source code) 396 | UFget_lookup.m look up a matrix in the index 397 | UFget.m UFget itself (primary user interface) 398 | UFweb.m open url for a matrix or collection 399 | mat/UF_Index.mat index of matrices in UF Sparse Matrix Collection 400 | 401 | 402 | -------------------------------------------------------------------------------- 403 | ./Matrix: Sample matrices, most from Rutherford/Boeing collection 404 | -------------------------------------------------------------------------------- 405 | 406 | ash219 overdetermined pattern of Holland survey. Ashkenazi, 1974. 407 | bcsstk01 stiffness matrix for small generalized eigenvalue problem 408 | bcsstk16 stiffness matrix, Corp of Engineers dam 409 | fs_183_1 unsymmetric facsimile convergence matrix 410 | lp_afiro NETLIB afiro linear programming problem 411 | mbeacxc US economy, 1972. Dan Szyld, while at NYU 412 | t1 small example used in Chapter 2 413 | west0067 Cavett problem with 5 components (chemical eng., Westerberg) 414 | 415 | 416 | -------------------------------------------------------------------------------- 417 | ./Tcov: Exhaustive test coverage of CSparse 418 | -------------------------------------------------------------------------------- 419 | 420 | covall same as covall.linux 421 | covall.linux find coverage (Linux) 422 | covall.sol find coverage (Solaris) 423 | cov.awk coverage summary 424 | cover print uncovered lines 425 | covs print uncovered lines 426 | cstcov_malloc_test.c malloc test 427 | cstcov_malloc_test.h 428 | cstcov_test.c main program for Tcov tests 429 | gcovs run gcov (Linux) 430 | Makefile Makefile for Tcov tests 431 | nil an empty matrix 432 | zero a 1-by-1 zero matrix 433 | README.txt README file for Tcov directory 434 | 435 | -------------------------------------------------------------------------------- /Source/README.txt: -------------------------------------------------------------------------------- 1 | CSparse/Source directory: primary ANSI C source code files for CSparse. 2 | All of these files are printed verbatim in the book. To compile the 3 | libcsparse.a C-callable library, just type "make" in this directory. 4 | 5 | Timothy A. Davis, http://www.suitesparse.com 6 | -------------------------------------------------------------------------------- /Source/cs_add.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* C = alpha*A + beta*B */ 3 | cs *cs_add (const cs *A, const cs *B, double alpha, double beta) 4 | { 5 | csi p, j, nz = 0, anz, *Cp, *Ci, *Bp, m, n, bnz, *w, values ; 6 | double *x, *Bx, *Cx ; 7 | cs *C ; 8 | if (!CS_CSC (A) || !CS_CSC (B)) return (NULL) ; /* check inputs */ 9 | if (A->m != B->m || A->n != B->n) return (NULL) ; 10 | m = A->m ; anz = A->p [A->n] ; 11 | n = B->n ; Bp = B->p ; Bx = B->x ; bnz = Bp [n] ; 12 | w = cs_calloc (m, sizeof (csi)) ; /* get workspace */ 13 | values = (A->x != NULL) && (Bx != NULL) ; 14 | x = values ? cs_malloc (m, sizeof (double)) : NULL ; /* get workspace */ 15 | C = cs_spalloc (m, n, anz + bnz, values, 0) ; /* allocate result*/ 16 | if (!C || !w || (values && !x)) return (cs_done (C, w, x, 0)) ; 17 | Cp = C->p ; Ci = C->i ; Cx = C->x ; 18 | for (j = 0 ; j < n ; j++) 19 | { 20 | Cp [j] = nz ; /* column j of C starts here */ 21 | nz = cs_scatter (A, j, alpha, w, x, j+1, C, nz) ; /* alpha*A(:,j)*/ 22 | nz = cs_scatter (B, j, beta, w, x, j+1, C, nz) ; /* beta*B(:,j) */ 23 | if (values) for (p = Cp [j] ; p < nz ; p++) Cx [p] = x [Ci [p]] ; 24 | } 25 | Cp [n] = nz ; /* finalize the last column of C */ 26 | cs_sprealloc (C, 0) ; /* remove extra space from C */ 27 | return (cs_done (C, w, x, 1)) ; /* success; free workspace, return C */ 28 | } 29 | -------------------------------------------------------------------------------- /Source/cs_amd.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* clear w */ 3 | static csi cs_wclear (csi mark, csi lemax, csi *w, csi n) 4 | { 5 | csi k ; 6 | if (mark < 2 || (mark + lemax < 0)) 7 | { 8 | for (k = 0 ; k < n ; k++) if (w [k] != 0) w [k] = 1 ; 9 | mark = 2 ; 10 | } 11 | return (mark) ; /* at this point, w [0..n-1] < mark holds */ 12 | } 13 | 14 | /* keep off-diagonal entries; drop diagonal entries */ 15 | static csi cs_diag (csi i, csi j, double aij, void *other) { return (i != j) ; } 16 | 17 | /* p = amd(A+A') if symmetric is true, or amd(A'A) otherwise */ 18 | csi *cs_amd (csi order, const cs *A) /* order 0:natural, 1:Chol, 2:LU, 3:QR */ 19 | { 20 | cs *C, *A2, *AT ; 21 | csi *Cp, *Ci, *last, *W, *len, *nv, *next, *P, *head, *elen, *degree, *w, 22 | *hhead, *ATp, *ATi, d, dk, dext, lemax = 0, e, elenk, eln, i, j, k, k1, 23 | k2, k3, jlast, ln, dense, nzmax, mindeg = 0, nvi, nvj, nvk, mark, wnvi, 24 | ok, cnz, nel = 0, p, p1, p2, p3, p4, pj, pk, pk1, pk2, pn, q, n, m, t ; 25 | csi h ; 26 | /* --- Construct matrix C ----------------------------------------------- */ 27 | if (!CS_CSC (A) || order <= 0 || order > 3) return (NULL) ; /* check */ 28 | AT = cs_transpose (A, 0) ; /* compute A' */ 29 | if (!AT) return (NULL) ; 30 | m = A->m ; n = A->n ; 31 | dense = CS_MAX (16, 10 * sqrt ((double) n)) ; /* find dense threshold */ 32 | dense = CS_MIN (n-2, dense) ; 33 | if (order == 1 && n == m) 34 | { 35 | C = cs_add (A, AT, 0, 0) ; /* C = A+A' */ 36 | } 37 | else if (order == 2) 38 | { 39 | ATp = AT->p ; /* drop dense columns from AT */ 40 | ATi = AT->i ; 41 | for (p2 = 0, j = 0 ; j < m ; j++) 42 | { 43 | p = ATp [j] ; /* column j of AT starts here */ 44 | ATp [j] = p2 ; /* new column j starts here */ 45 | if (ATp [j+1] - p > dense) continue ; /* skip dense col j */ 46 | for ( ; p < ATp [j+1] ; p++) ATi [p2++] = ATi [p] ; 47 | } 48 | ATp [m] = p2 ; /* finalize AT */ 49 | A2 = cs_transpose (AT, 0) ; /* A2 = AT' */ 50 | C = A2 ? cs_multiply (AT, A2) : NULL ; /* C=A'*A with no dense rows */ 51 | cs_spfree (A2) ; 52 | } 53 | else 54 | { 55 | C = cs_multiply (AT, A) ; /* C=A'*A */ 56 | } 57 | cs_spfree (AT) ; 58 | if (!C) return (NULL) ; 59 | cs_fkeep (C, &cs_diag, NULL) ; /* drop diagonal entries */ 60 | Cp = C->p ; 61 | cnz = Cp [n] ; 62 | P = cs_malloc (n+1, sizeof (csi)) ; /* allocate result */ 63 | W = cs_malloc (8*(n+1), sizeof (csi)) ; /* get workspace */ 64 | t = cnz + cnz/5 + 2*n ; /* add elbow room to C */ 65 | if (!P || !W || !cs_sprealloc (C, t)) return (cs_idone (P, C, W, 0)) ; 66 | len = W ; nv = W + (n+1) ; next = W + 2*(n+1) ; 67 | head = W + 3*(n+1) ; elen = W + 4*(n+1) ; degree = W + 5*(n+1) ; 68 | w = W + 6*(n+1) ; hhead = W + 7*(n+1) ; 69 | last = P ; /* use P as workspace for last */ 70 | /* --- Initialize quotient graph ---------------------------------------- */ 71 | for (k = 0 ; k < n ; k++) len [k] = Cp [k+1] - Cp [k] ; 72 | len [n] = 0 ; 73 | nzmax = C->nzmax ; 74 | Ci = C->i ; 75 | for (i = 0 ; i <= n ; i++) 76 | { 77 | head [i] = -1 ; /* degree list i is empty */ 78 | last [i] = -1 ; 79 | next [i] = -1 ; 80 | hhead [i] = -1 ; /* hash list i is empty */ 81 | nv [i] = 1 ; /* node i is just one node */ 82 | w [i] = 1 ; /* node i is alive */ 83 | elen [i] = 0 ; /* Ek of node i is empty */ 84 | degree [i] = len [i] ; /* degree of node i */ 85 | } 86 | mark = cs_wclear (0, 0, w, n) ; /* clear w */ 87 | elen [n] = -2 ; /* n is a dead element */ 88 | Cp [n] = -1 ; /* n is a root of assembly tree */ 89 | w [n] = 0 ; /* n is a dead element */ 90 | /* --- Initialize degree lists ------------------------------------------ */ 91 | for (i = 0 ; i < n ; i++) 92 | { 93 | d = degree [i] ; 94 | if (d == 0) /* node i is empty */ 95 | { 96 | elen [i] = -2 ; /* element i is dead */ 97 | nel++ ; 98 | Cp [i] = -1 ; /* i is a root of assembly tree */ 99 | w [i] = 0 ; 100 | } 101 | else if (d > dense) /* node i is dense */ 102 | { 103 | nv [i] = 0 ; /* absorb i into element n */ 104 | elen [i] = -1 ; /* node i is dead */ 105 | nel++ ; 106 | Cp [i] = CS_FLIP (n) ; 107 | nv [n]++ ; 108 | } 109 | else 110 | { 111 | if (head [d] != -1) last [head [d]] = i ; 112 | next [i] = head [d] ; /* put node i in degree list d */ 113 | head [d] = i ; 114 | } 115 | } 116 | while (nel < n) /* while (selecting pivots) do */ 117 | { 118 | /* --- Select node of minimum approximate degree -------------------- */ 119 | for (k = -1 ; mindeg < n && (k = head [mindeg]) == -1 ; mindeg++) ; 120 | if (next [k] != -1) last [next [k]] = -1 ; 121 | head [mindeg] = next [k] ; /* remove k from degree list */ 122 | elenk = elen [k] ; /* elenk = |Ek| */ 123 | nvk = nv [k] ; /* # of nodes k represents */ 124 | nel += nvk ; /* nv[k] nodes of A eliminated */ 125 | /* --- Garbage collection ------------------------------------------- */ 126 | if (elenk > 0 && cnz + mindeg >= nzmax) 127 | { 128 | for (j = 0 ; j < n ; j++) 129 | { 130 | if ((p = Cp [j]) >= 0) /* j is a live node or element */ 131 | { 132 | Cp [j] = Ci [p] ; /* save first entry of object */ 133 | Ci [p] = CS_FLIP (j) ; /* first entry is now CS_FLIP(j) */ 134 | } 135 | } 136 | for (q = 0, p = 0 ; p < cnz ; ) /* scan all of memory */ 137 | { 138 | if ((j = CS_FLIP (Ci [p++])) >= 0) /* found object j */ 139 | { 140 | Ci [q] = Cp [j] ; /* restore first entry of object */ 141 | Cp [j] = q++ ; /* new pointer to object j */ 142 | for (k3 = 0 ; k3 < len [j]-1 ; k3++) Ci [q++] = Ci [p++] ; 143 | } 144 | } 145 | cnz = q ; /* Ci [cnz...nzmax-1] now free */ 146 | } 147 | /* --- Construct new element ---------------------------------------- */ 148 | dk = 0 ; 149 | nv [k] = -nvk ; /* flag k as in Lk */ 150 | p = Cp [k] ; 151 | pk1 = (elenk == 0) ? p : cnz ; /* do in place if elen[k] == 0 */ 152 | pk2 = pk1 ; 153 | for (k1 = 1 ; k1 <= elenk + 1 ; k1++) 154 | { 155 | if (k1 > elenk) 156 | { 157 | e = k ; /* search the nodes in k */ 158 | pj = p ; /* list of nodes starts at Ci[pj]*/ 159 | ln = len [k] - elenk ; /* length of list of nodes in k */ 160 | } 161 | else 162 | { 163 | e = Ci [p++] ; /* search the nodes in e */ 164 | pj = Cp [e] ; 165 | ln = len [e] ; /* length of list of nodes in e */ 166 | } 167 | for (k2 = 1 ; k2 <= ln ; k2++) 168 | { 169 | i = Ci [pj++] ; 170 | if ((nvi = nv [i]) <= 0) continue ; /* node i dead, or seen */ 171 | dk += nvi ; /* degree[Lk] += size of node i */ 172 | nv [i] = -nvi ; /* negate nv[i] to denote i in Lk*/ 173 | Ci [pk2++] = i ; /* place i in Lk */ 174 | if (next [i] != -1) last [next [i]] = last [i] ; 175 | if (last [i] != -1) /* remove i from degree list */ 176 | { 177 | next [last [i]] = next [i] ; 178 | } 179 | else 180 | { 181 | head [degree [i]] = next [i] ; 182 | } 183 | } 184 | if (e != k) 185 | { 186 | Cp [e] = CS_FLIP (k) ; /* absorb e into k */ 187 | w [e] = 0 ; /* e is now a dead element */ 188 | } 189 | } 190 | if (elenk != 0) cnz = pk2 ; /* Ci [cnz...nzmax] is free */ 191 | degree [k] = dk ; /* external degree of k - |Lk\i| */ 192 | Cp [k] = pk1 ; /* element k is in Ci[pk1..pk2-1] */ 193 | len [k] = pk2 - pk1 ; 194 | elen [k] = -2 ; /* k is now an element */ 195 | /* --- Find set differences ----------------------------------------- */ 196 | mark = cs_wclear (mark, lemax, w, n) ; /* clear w if necessary */ 197 | for (pk = pk1 ; pk < pk2 ; pk++) /* scan 1: find |Le\Lk| */ 198 | { 199 | i = Ci [pk] ; 200 | if ((eln = elen [i]) <= 0) continue ;/* skip if elen[i] empty */ 201 | nvi = -nv [i] ; /* nv [i] was negated */ 202 | wnvi = mark - nvi ; 203 | for (p = Cp [i] ; p <= Cp [i] + eln - 1 ; p++) /* scan Ei */ 204 | { 205 | e = Ci [p] ; 206 | if (w [e] >= mark) 207 | { 208 | w [e] -= nvi ; /* decrement |Le\Lk| */ 209 | } 210 | else if (w [e] != 0) /* ensure e is a live element */ 211 | { 212 | w [e] = degree [e] + wnvi ; /* 1st time e seen in scan 1 */ 213 | } 214 | } 215 | } 216 | /* --- Degree update ------------------------------------------------ */ 217 | for (pk = pk1 ; pk < pk2 ; pk++) /* scan2: degree update */ 218 | { 219 | i = Ci [pk] ; /* consider node i in Lk */ 220 | p1 = Cp [i] ; 221 | p2 = p1 + elen [i] - 1 ; 222 | pn = p1 ; 223 | for (h = 0, d = 0, p = p1 ; p <= p2 ; p++) /* scan Ei */ 224 | { 225 | e = Ci [p] ; 226 | if (w [e] != 0) /* e is an unabsorbed element */ 227 | { 228 | dext = w [e] - mark ; /* dext = |Le\Lk| */ 229 | if (dext > 0) 230 | { 231 | d += dext ; /* sum up the set differences */ 232 | Ci [pn++] = e ; /* keep e in Ei */ 233 | h += e ; /* compute the hash of node i */ 234 | } 235 | else 236 | { 237 | Cp [e] = CS_FLIP (k) ; /* aggressive absorb. e->k */ 238 | w [e] = 0 ; /* e is a dead element */ 239 | } 240 | } 241 | } 242 | elen [i] = pn - p1 + 1 ; /* elen[i] = |Ei| */ 243 | p3 = pn ; 244 | p4 = p1 + len [i] ; 245 | for (p = p2 + 1 ; p < p4 ; p++) /* prune edges in Ai */ 246 | { 247 | j = Ci [p] ; 248 | if ((nvj = nv [j]) <= 0) continue ; /* node j dead or in Lk */ 249 | d += nvj ; /* degree(i) += |j| */ 250 | Ci [pn++] = j ; /* place j in node list of i */ 251 | h += j ; /* compute hash for node i */ 252 | } 253 | if (d == 0) /* check for mass elimination */ 254 | { 255 | Cp [i] = CS_FLIP (k) ; /* absorb i into k */ 256 | nvi = -nv [i] ; 257 | dk -= nvi ; /* |Lk| -= |i| */ 258 | nvk += nvi ; /* |k| += nv[i] */ 259 | nel += nvi ; 260 | nv [i] = 0 ; 261 | elen [i] = -1 ; /* node i is dead */ 262 | } 263 | else 264 | { 265 | degree [i] = CS_MIN (degree [i], d) ; /* update degree(i) */ 266 | Ci [pn] = Ci [p3] ; /* move first node to end */ 267 | Ci [p3] = Ci [p1] ; /* move 1st el. to end of Ei */ 268 | Ci [p1] = k ; /* add k as 1st element in of Ei */ 269 | len [i] = pn - p1 + 1 ; /* new len of adj. list of node i */ 270 | h = ((h<0) ? (-h):h) % n ; /* finalize hash of i */ 271 | next [i] = hhead [h] ; /* place i in hash bucket */ 272 | hhead [h] = i ; 273 | last [i] = h ; /* save hash of i in last[i] */ 274 | } 275 | } /* scan2 is done */ 276 | degree [k] = dk ; /* finalize |Lk| */ 277 | lemax = CS_MAX (lemax, dk) ; 278 | mark = cs_wclear (mark+lemax, lemax, w, n) ; /* clear w */ 279 | /* --- Supernode detection ------------------------------------------ */ 280 | for (pk = pk1 ; pk < pk2 ; pk++) 281 | { 282 | i = Ci [pk] ; 283 | if (nv [i] >= 0) continue ; /* skip if i is dead */ 284 | h = last [i] ; /* scan hash bucket of node i */ 285 | i = hhead [h] ; 286 | hhead [h] = -1 ; /* hash bucket will be empty */ 287 | for ( ; i != -1 && next [i] != -1 ; i = next [i], mark++) 288 | { 289 | ln = len [i] ; 290 | eln = elen [i] ; 291 | for (p = Cp [i]+1 ; p <= Cp [i] + ln-1 ; p++) w [Ci [p]] = mark; 292 | jlast = i ; 293 | for (j = next [i] ; j != -1 ; ) /* compare i with all j */ 294 | { 295 | ok = (len [j] == ln) && (elen [j] == eln) ; 296 | for (p = Cp [j] + 1 ; ok && p <= Cp [j] + ln - 1 ; p++) 297 | { 298 | if (w [Ci [p]] != mark) ok = 0 ; /* compare i and j*/ 299 | } 300 | if (ok) /* i and j are identical */ 301 | { 302 | Cp [j] = CS_FLIP (i) ; /* absorb j into i */ 303 | nv [i] += nv [j] ; 304 | nv [j] = 0 ; 305 | elen [j] = -1 ; /* node j is dead */ 306 | j = next [j] ; /* delete j from hash bucket */ 307 | next [jlast] = j ; 308 | } 309 | else 310 | { 311 | jlast = j ; /* j and i are different */ 312 | j = next [j] ; 313 | } 314 | } 315 | } 316 | } 317 | /* --- Finalize new element------------------------------------------ */ 318 | for (p = pk1, pk = pk1 ; pk < pk2 ; pk++) /* finalize Lk */ 319 | { 320 | i = Ci [pk] ; 321 | if ((nvi = -nv [i]) <= 0) continue ;/* skip if i is dead */ 322 | nv [i] = nvi ; /* restore nv[i] */ 323 | d = degree [i] + dk - nvi ; /* compute external degree(i) */ 324 | d = CS_MIN (d, n - nel - nvi) ; 325 | if (head [d] != -1) last [head [d]] = i ; 326 | next [i] = head [d] ; /* put i back in degree list */ 327 | last [i] = -1 ; 328 | head [d] = i ; 329 | mindeg = CS_MIN (mindeg, d) ; /* find new minimum degree */ 330 | degree [i] = d ; 331 | Ci [p++] = i ; /* place i in Lk */ 332 | } 333 | nv [k] = nvk ; /* # nodes absorbed into k */ 334 | if ((len [k] = p-pk1) == 0) /* length of adj list of element k*/ 335 | { 336 | Cp [k] = -1 ; /* k is a root of the tree */ 337 | w [k] = 0 ; /* k is now a dead element */ 338 | } 339 | if (elenk != 0) cnz = p ; /* free unused space in Lk */ 340 | } 341 | /* --- Postordering ----------------------------------------------------- */ 342 | for (i = 0 ; i < n ; i++) Cp [i] = CS_FLIP (Cp [i]) ;/* fix assembly tree */ 343 | for (j = 0 ; j <= n ; j++) head [j] = -1 ; 344 | for (j = n ; j >= 0 ; j--) /* place unordered nodes in lists */ 345 | { 346 | if (nv [j] > 0) continue ; /* skip if j is an element */ 347 | next [j] = head [Cp [j]] ; /* place j in list of its parent */ 348 | head [Cp [j]] = j ; 349 | } 350 | for (e = n ; e >= 0 ; e--) /* place elements in lists */ 351 | { 352 | if (nv [e] <= 0) continue ; /* skip unless e is an element */ 353 | if (Cp [e] != -1) 354 | { 355 | next [e] = head [Cp [e]] ; /* place e in list of its parent */ 356 | head [Cp [e]] = e ; 357 | } 358 | } 359 | for (k = 0, i = 0 ; i <= n ; i++) /* postorder the assembly tree */ 360 | { 361 | if (Cp [i] == -1) k = cs_tdfs (i, k, head, next, P, w) ; 362 | } 363 | return (cs_idone (P, C, W, 1)) ; 364 | } 365 | -------------------------------------------------------------------------------- /Source/cs_chol.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* L = chol (A, [pinv parent cp]), pinv is optional */ 3 | csn *cs_chol (const cs *A, const css *S) 4 | { 5 | double d, lki, *Lx, *x, *Cx ; 6 | csi top, i, p, k, n, *Li, *Lp, *cp, *pinv, *s, *c, *parent, *Cp, *Ci ; 7 | cs *L, *C, *E ; 8 | csn *N ; 9 | if (!CS_CSC (A) || !S || !S->cp || !S->parent) return (NULL) ; 10 | n = A->n ; 11 | N = cs_calloc (1, sizeof (csn)) ; /* allocate result */ 12 | c = cs_malloc (2*n, sizeof (csi)) ; /* get csi workspace */ 13 | x = cs_malloc (n, sizeof (double)) ; /* get double workspace */ 14 | cp = S->cp ; pinv = S->pinv ; parent = S->parent ; 15 | C = pinv ? cs_symperm (A, pinv, 1) : ((cs *) A) ; 16 | E = pinv ? C : NULL ; /* E is alias for A, or a copy E=A(p,p) */ 17 | if (!N || !c || !x || !C) return (cs_ndone (N, E, c, x, 0)) ; 18 | s = c + n ; 19 | Cp = C->p ; Ci = C->i ; Cx = C->x ; 20 | N->L = L = cs_spalloc (n, n, cp [n], 1, 0) ; /* allocate result */ 21 | if (!L) return (cs_ndone (N, E, c, x, 0)) ; 22 | Lp = L->p ; Li = L->i ; Lx = L->x ; 23 | for (k = 0 ; k < n ; k++) Lp [k] = c [k] = cp [k] ; 24 | for (k = 0 ; k < n ; k++) /* compute L(k,:) for L*L' = C */ 25 | { 26 | /* --- Nonzero pattern of L(k,:) ------------------------------------ */ 27 | top = cs_ereach (C, k, parent, s, c) ; /* find pattern of L(k,:) */ 28 | x [k] = 0 ; /* x (0:k) is now zero */ 29 | for (p = Cp [k] ; p < Cp [k+1] ; p++) /* x = full(triu(C(:,k))) */ 30 | { 31 | if (Ci [p] <= k) x [Ci [p]] = Cx [p] ; 32 | } 33 | d = x [k] ; /* d = C(k,k) */ 34 | x [k] = 0 ; /* clear x for k+1st iteration */ 35 | /* --- Triangular solve --------------------------------------------- */ 36 | for ( ; top < n ; top++) /* solve L(0:k-1,0:k-1) * x = C(:,k) */ 37 | { 38 | i = s [top] ; /* s [top..n-1] is pattern of L(k,:) */ 39 | lki = x [i] / Lx [Lp [i]] ; /* L(k,i) = x (i) / L(i,i) */ 40 | x [i] = 0 ; /* clear x for k+1st iteration */ 41 | for (p = Lp [i] + 1 ; p < c [i] ; p++) 42 | { 43 | x [Li [p]] -= Lx [p] * lki ; 44 | } 45 | d -= lki * lki ; /* d = d - L(k,i)*L(k,i) */ 46 | p = c [i]++ ; 47 | Li [p] = k ; /* store L(k,i) in column i */ 48 | Lx [p] = lki ; 49 | } 50 | /* --- Compute L(k,k) ----------------------------------------------- */ 51 | if (d <= 0) return (cs_ndone (N, E, c, x, 0)) ; /* not pos def */ 52 | p = c [k]++ ; 53 | Li [p] = k ; /* store L(k,k) = sqrt (d) in column k */ 54 | Lx [p] = sqrt (d) ; 55 | } 56 | Lp [n] = cp [n] ; /* finalize L */ 57 | return (cs_ndone (N, E, c, x, 1)) ; /* success: free E,s,x; return N */ 58 | } 59 | -------------------------------------------------------------------------------- /Source/cs_cholsol.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* x=A\b where A is symmetric positive definite; b overwritten with solution */ 3 | csi cs_cholsol (csi order, const cs *A, double *b) 4 | { 5 | double *x ; 6 | css *S ; 7 | csn *N ; 8 | csi n, ok ; 9 | if (!CS_CSC (A) || !b) return (0) ; /* check inputs */ 10 | n = A->n ; 11 | S = cs_schol (order, A) ; /* ordering and symbolic analysis */ 12 | N = cs_chol (A, S) ; /* numeric Cholesky factorization */ 13 | x = cs_malloc (n, sizeof (double)) ; /* get workspace */ 14 | ok = (S && N && x) ; 15 | if (ok) 16 | { 17 | cs_ipvec (S->pinv, b, x, n) ; /* x = P*b */ 18 | cs_lsolve (N->L, x) ; /* x = L\x */ 19 | cs_ltsolve (N->L, x) ; /* x = L'\x */ 20 | cs_pvec (S->pinv, x, b, n) ; /* b = P'*x */ 21 | } 22 | cs_free (x) ; 23 | cs_sfree (S) ; 24 | cs_nfree (N) ; 25 | return (ok) ; 26 | } 27 | -------------------------------------------------------------------------------- /Source/cs_compress.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* C = compressed-column form of a triplet matrix T */ 3 | cs *cs_compress (const cs *T) 4 | { 5 | csi m, n, nz, p, k, *Cp, *Ci, *w, *Ti, *Tj ; 6 | double *Cx, *Tx ; 7 | cs *C ; 8 | if (!CS_TRIPLET (T)) return (NULL) ; /* check inputs */ 9 | m = T->m ; n = T->n ; Ti = T->i ; Tj = T->p ; Tx = T->x ; nz = T->nz ; 10 | C = cs_spalloc (m, n, nz, Tx != NULL, 0) ; /* allocate result */ 11 | w = cs_calloc (n, sizeof (csi)) ; /* get workspace */ 12 | if (!C || !w) return (cs_done (C, w, NULL, 0)) ; /* out of memory */ 13 | Cp = C->p ; Ci = C->i ; Cx = C->x ; 14 | for (k = 0 ; k < nz ; k++) w [Tj [k]]++ ; /* column counts */ 15 | cs_cumsum (Cp, w, n) ; /* column pointers */ 16 | for (k = 0 ; k < nz ; k++) 17 | { 18 | Ci [p = w [Tj [k]]++] = Ti [k] ; /* A(i,j) is the pth entry in C */ 19 | if (Cx) Cx [p] = Tx [k] ; 20 | } 21 | return (cs_done (C, w, NULL, 1)) ; /* success; free w and return C */ 22 | } 23 | -------------------------------------------------------------------------------- /Source/cs_counts.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* column counts of LL'=A or LL'=A'A, given parent & post ordering */ 3 | #define HEAD(k,j) (ata ? head [k] : j) 4 | #define NEXT(J) (ata ? next [J] : -1) 5 | static void init_ata (cs *AT, const csi *post, csi *w, csi **head, csi **next) 6 | { 7 | csi i, k, p, m = AT->n, n = AT->m, *ATp = AT->p, *ATi = AT->i ; 8 | *head = w+4*n, *next = w+5*n+1 ; 9 | for (k = 0 ; k < n ; k++) w [post [k]] = k ; /* invert post */ 10 | for (i = 0 ; i < m ; i++) 11 | { 12 | for (k = n, p = ATp[i] ; p < ATp[i+1] ; p++) k = CS_MIN (k, w [ATi[p]]); 13 | (*next) [i] = (*head) [k] ; /* place row i in linked list k */ 14 | (*head) [k] = i ; 15 | } 16 | } 17 | csi *cs_counts (const cs *A, const csi *parent, const csi *post, csi ata) 18 | { 19 | csi i, j, k, n, m, J, s, p, q, jleaf, *ATp, *ATi, *maxfirst, *prevleaf, 20 | *ancestor, *head = NULL, *next = NULL, *colcount, *w, *first, *delta ; 21 | cs *AT ; 22 | if (!CS_CSC (A) || !parent || !post) return (NULL) ; /* check inputs */ 23 | m = A->m ; n = A->n ; 24 | s = 4*n + (ata ? (n+m+1) : 0) ; 25 | delta = colcount = cs_malloc (n, sizeof (csi)) ; /* allocate result */ 26 | w = cs_malloc (s, sizeof (csi)) ; /* get workspace */ 27 | AT = cs_transpose (A, 0) ; /* AT = A' */ 28 | if (!AT || !colcount || !w) return (cs_idone (colcount, AT, w, 0)) ; 29 | ancestor = w ; maxfirst = w+n ; prevleaf = w+2*n ; first = w+3*n ; 30 | for (k = 0 ; k < s ; k++) w [k] = -1 ; /* clear workspace w [0..s-1] */ 31 | for (k = 0 ; k < n ; k++) /* find first [j] */ 32 | { 33 | j = post [k] ; 34 | delta [j] = (first [j] == -1) ? 1 : 0 ; /* delta[j]=1 if j is a leaf */ 35 | for ( ; j != -1 && first [j] == -1 ; j = parent [j]) first [j] = k ; 36 | } 37 | ATp = AT->p ; ATi = AT->i ; 38 | if (ata) init_ata (AT, post, w, &head, &next) ; 39 | for (i = 0 ; i < n ; i++) ancestor [i] = i ; /* each node in its own set */ 40 | for (k = 0 ; k < n ; k++) 41 | { 42 | j = post [k] ; /* j is the kth node in postordered etree */ 43 | if (parent [j] != -1) delta [parent [j]]-- ; /* j is not a root */ 44 | for (J = HEAD (k,j) ; J != -1 ; J = NEXT (J)) /* J=j for LL'=A case */ 45 | { 46 | for (p = ATp [J] ; p < ATp [J+1] ; p++) 47 | { 48 | i = ATi [p] ; 49 | q = cs_leaf (i, j, first, maxfirst, prevleaf, ancestor, &jleaf); 50 | if (jleaf >= 1) delta [j]++ ; /* A(i,j) is in skeleton */ 51 | if (jleaf == 2) delta [q]-- ; /* account for overlap in q */ 52 | } 53 | } 54 | if (parent [j] != -1) ancestor [j] = parent [j] ; 55 | } 56 | for (j = 0 ; j < n ; j++) /* sum up delta's of each child */ 57 | { 58 | if (parent [j] != -1) colcount [parent [j]] += colcount [j] ; 59 | } 60 | return (cs_idone (colcount, AT, w, 1)) ; /* success: free workspace */ 61 | } 62 | -------------------------------------------------------------------------------- /Source/cs_cumsum.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* p [0..n] = cumulative sum of c [0..n-1], and then copy p [0..n-1] into c */ 3 | double cs_cumsum (csi *p, csi *c, csi n) 4 | { 5 | csi i, nz = 0 ; 6 | double nz2 = 0 ; 7 | if (!p || !c) return (-1) ; /* check inputs */ 8 | for (i = 0 ; i < n ; i++) 9 | { 10 | p [i] = nz ; 11 | nz += c [i] ; 12 | nz2 += c [i] ; /* also in double to avoid csi overflow */ 13 | c [i] = p [i] ; /* also copy p[0..n-1] back into c[0..n-1]*/ 14 | } 15 | p [n] = nz ; 16 | return (nz2) ; /* return sum (c [0..n-1]) */ 17 | } 18 | -------------------------------------------------------------------------------- /Source/cs_dfs.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* depth-first-search of the graph of a matrix, starting at node j */ 3 | csi cs_dfs (csi j, cs *G, csi top, csi *xi, csi *pstack, const csi *pinv) 4 | { 5 | csi i, p, p2, done, jnew, head = 0, *Gp, *Gi ; 6 | if (!CS_CSC (G) || !xi || !pstack) return (-1) ; /* check inputs */ 7 | Gp = G->p ; Gi = G->i ; 8 | xi [0] = j ; /* initialize the recursion stack */ 9 | while (head >= 0) 10 | { 11 | j = xi [head] ; /* get j from the top of the recursion stack */ 12 | jnew = pinv ? (pinv [j]) : j ; 13 | if (!CS_MARKED (Gp, j)) 14 | { 15 | CS_MARK (Gp, j) ; /* mark node j as visited */ 16 | pstack [head] = (jnew < 0) ? 0 : CS_UNFLIP (Gp [jnew]) ; 17 | } 18 | done = 1 ; /* node j done if no unvisited neighbors */ 19 | p2 = (jnew < 0) ? 0 : CS_UNFLIP (Gp [jnew+1]) ; 20 | for (p = pstack [head] ; p < p2 ; p++) /* examine all neighbors of j */ 21 | { 22 | i = Gi [p] ; /* consider neighbor node i */ 23 | if (CS_MARKED (Gp, i)) continue ; /* skip visited node i */ 24 | pstack [head] = p ; /* pause depth-first search of node j */ 25 | xi [++head] = i ; /* start dfs at node i */ 26 | done = 0 ; /* node j is not done */ 27 | break ; /* break, to start dfs (i) */ 28 | } 29 | if (done) /* depth-first search at node j is done */ 30 | { 31 | head-- ; /* remove j from the recursion stack */ 32 | xi [--top] = j ; /* and place in the output stack */ 33 | } 34 | } 35 | return (top) ; 36 | } 37 | -------------------------------------------------------------------------------- /Source/cs_dmperm.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* breadth-first search for coarse decomposition (C0,C1,R1 or R0,R3,C3) */ 3 | static csi cs_bfs (const cs *A, csi n, csi *wi, csi *wj, csi *queue, 4 | const csi *imatch, const csi *jmatch, csi mark) 5 | { 6 | csi *Ap, *Ai, head = 0, tail = 0, j, i, p, j2 ; 7 | cs *C ; 8 | for (j = 0 ; j < n ; j++) /* place all unmatched nodes in queue */ 9 | { 10 | if (imatch [j] >= 0) continue ; /* skip j if matched */ 11 | wj [j] = 0 ; /* j in set C0 (R0 if transpose) */ 12 | queue [tail++] = j ; /* place unmatched col j in queue */ 13 | } 14 | if (tail == 0) return (1) ; /* quick return if no unmatched nodes */ 15 | C = (mark == 1) ? ((cs *) A) : cs_transpose (A, 0) ; 16 | if (!C) return (0) ; /* bfs of C=A' to find R3,C3 from R0 */ 17 | Ap = C->p ; Ai = C->i ; 18 | while (head < tail) /* while queue is not empty */ 19 | { 20 | j = queue [head++] ; /* get the head of the queue */ 21 | for (p = Ap [j] ; p < Ap [j+1] ; p++) 22 | { 23 | i = Ai [p] ; 24 | if (wi [i] >= 0) continue ; /* skip if i is marked */ 25 | wi [i] = mark ; /* i in set R1 (C3 if transpose) */ 26 | j2 = jmatch [i] ; /* traverse alternating path to j2 */ 27 | if (wj [j2] >= 0) continue ;/* skip j2 if it is marked */ 28 | wj [j2] = mark ; /* j2 in set C1 (R3 if transpose) */ 29 | queue [tail++] = j2 ; /* add j2 to queue */ 30 | } 31 | } 32 | if (mark != 1) cs_spfree (C) ; /* free A' if it was created */ 33 | return (1) ; 34 | } 35 | 36 | /* collect matched rows and columns into p and q */ 37 | static void cs_matched (csi n, const csi *wj, const csi *imatch, csi *p, csi *q, 38 | csi *cc, csi *rr, csi set, csi mark) 39 | { 40 | csi kc = cc [set], j ; 41 | csi kr = rr [set-1] ; 42 | for (j = 0 ; j < n ; j++) 43 | { 44 | if (wj [j] != mark) continue ; /* skip if j is not in C set */ 45 | p [kr++] = imatch [j] ; 46 | q [kc++] = j ; 47 | } 48 | cc [set+1] = kc ; 49 | rr [set] = kr ; 50 | } 51 | 52 | /* collect unmatched rows into the permutation vector p */ 53 | static void cs_unmatched (csi m, const csi *wi, csi *p, csi *rr, csi set) 54 | { 55 | csi i, kr = rr [set] ; 56 | for (i = 0 ; i < m ; i++) if (wi [i] == 0) p [kr++] = i ; 57 | rr [set+1] = kr ; 58 | } 59 | 60 | /* return 1 if row i is in R2 */ 61 | static csi cs_rprune (csi i, csi j, double aij, void *other) 62 | { 63 | csi *rr = (csi *) other ; 64 | return (i >= rr [1] && i < rr [2]) ; 65 | } 66 | 67 | /* Given A, compute coarse and then fine dmperm */ 68 | csd *cs_dmperm (const cs *A, csi seed) 69 | { 70 | csi m, n, i, j, k, cnz, nc, *jmatch, *imatch, *wi, *wj, *pinv, *Cp, *Ci, 71 | *ps, *rs, nb1, nb2, *p, *q, *cc, *rr, *r, *s, ok ; 72 | cs *C ; 73 | csd *D, *scc ; 74 | /* --- Maximum matching ------------------------------------------------- */ 75 | if (!CS_CSC (A)) return (NULL) ; /* check inputs */ 76 | m = A->m ; n = A->n ; 77 | D = cs_dalloc (m, n) ; /* allocate result */ 78 | if (!D) return (NULL) ; 79 | p = D->p ; q = D->q ; r = D->r ; s = D->s ; cc = D->cc ; rr = D->rr ; 80 | jmatch = cs_maxtrans (A, seed) ; /* max transversal */ 81 | imatch = jmatch + m ; /* imatch = inverse of jmatch */ 82 | if (!jmatch) return (cs_ddone (D, NULL, jmatch, 0)) ; 83 | /* --- Coarse decomposition --------------------------------------------- */ 84 | wi = r ; wj = s ; /* use r and s as workspace */ 85 | for (j = 0 ; j < n ; j++) wj [j] = -1 ; /* unmark all cols for bfs */ 86 | for (i = 0 ; i < m ; i++) wi [i] = -1 ; /* unmark all rows for bfs */ 87 | cs_bfs (A, n, wi, wj, q, imatch, jmatch, 1) ; /* find C1, R1 from C0*/ 88 | ok = cs_bfs (A, m, wj, wi, p, jmatch, imatch, 3) ; /* find R3, C3 from R0*/ 89 | if (!ok) return (cs_ddone (D, NULL, jmatch, 0)) ; 90 | cs_unmatched (n, wj, q, cc, 0) ; /* unmatched set C0 */ 91 | cs_matched (n, wj, imatch, p, q, cc, rr, 1, 1) ; /* set R1 and C1 */ 92 | cs_matched (n, wj, imatch, p, q, cc, rr, 2, -1) ; /* set R2 and C2 */ 93 | cs_matched (n, wj, imatch, p, q, cc, rr, 3, 3) ; /* set R3 and C3 */ 94 | cs_unmatched (m, wi, p, rr, 3) ; /* unmatched set R0 */ 95 | cs_free (jmatch) ; 96 | /* --- Fine decomposition ----------------------------------------------- */ 97 | pinv = cs_pinv (p, m) ; /* pinv=p' */ 98 | if (!pinv) return (cs_ddone (D, NULL, NULL, 0)) ; 99 | C = cs_permute (A, pinv, q, 0) ;/* C=A(p,q) (it will hold A(R2,C2)) */ 100 | cs_free (pinv) ; 101 | if (!C) return (cs_ddone (D, NULL, NULL, 0)) ; 102 | Cp = C->p ; 103 | nc = cc [3] - cc [2] ; /* delete cols C0, C1, and C3 from C */ 104 | if (cc [2] > 0) for (j = cc [2] ; j <= cc [3] ; j++) Cp [j-cc[2]] = Cp [j] ; 105 | C->n = nc ; 106 | if (rr [2] - rr [1] < m) /* delete rows R0, R1, and R3 from C */ 107 | { 108 | cs_fkeep (C, cs_rprune, rr) ; 109 | cnz = Cp [nc] ; 110 | Ci = C->i ; 111 | if (rr [1] > 0) for (k = 0 ; k < cnz ; k++) Ci [k] -= rr [1] ; 112 | } 113 | C->m = nc ; 114 | scc = cs_scc (C) ; /* find strongly connected components of C*/ 115 | if (!scc) return (cs_ddone (D, C, NULL, 0)) ; 116 | /* --- Combine coarse and fine decompositions --------------------------- */ 117 | ps = scc->p ; /* C(ps,ps) is the permuted matrix */ 118 | rs = scc->r ; /* kth block is rs[k]..rs[k+1]-1 */ 119 | nb1 = scc->nb ; /* # of blocks of A(R2,C2) */ 120 | for (k = 0 ; k < nc ; k++) wj [k] = q [ps [k] + cc [2]] ; 121 | for (k = 0 ; k < nc ; k++) q [k + cc [2]] = wj [k] ; 122 | for (k = 0 ; k < nc ; k++) wi [k] = p [ps [k] + rr [1]] ; 123 | for (k = 0 ; k < nc ; k++) p [k + rr [1]] = wi [k] ; 124 | nb2 = 0 ; /* create the fine block partitions */ 125 | r [0] = s [0] = 0 ; 126 | if (cc [2] > 0) nb2++ ; /* leading coarse block A (R1, [C0 C1]) */ 127 | for (k = 0 ; k < nb1 ; k++) /* coarse block A (R2,C2) */ 128 | { 129 | r [nb2] = rs [k] + rr [1] ; /* A (R2,C2) splits into nb1 fine blocks */ 130 | s [nb2] = rs [k] + cc [2] ; 131 | nb2++ ; 132 | } 133 | if (rr [2] < m) 134 | { 135 | r [nb2] = rr [2] ; /* trailing coarse block A ([R3 R0], C3) */ 136 | s [nb2] = cc [3] ; 137 | nb2++ ; 138 | } 139 | r [nb2] = m ; 140 | s [nb2] = n ; 141 | D->nb = nb2 ; 142 | cs_dfree (scc) ; 143 | return (cs_ddone (D, C, NULL, 1)) ; 144 | } 145 | -------------------------------------------------------------------------------- /Source/cs_droptol.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | static csi cs_tol (csi i, csi j, double aij, void *tol) 3 | { 4 | return (fabs (aij) > *((double *) tol)) ; 5 | } 6 | csi cs_droptol (cs *A, double tol) 7 | { 8 | return (cs_fkeep (A, &cs_tol, &tol)) ; /* keep all large entries */ 9 | } 10 | -------------------------------------------------------------------------------- /Source/cs_dropzeros.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | static csi cs_nonzero (csi i, csi j, double aij, void *other) 3 | { 4 | return (aij != 0) ; 5 | } 6 | csi cs_dropzeros (cs *A) 7 | { 8 | return (cs_fkeep (A, &cs_nonzero, NULL)) ; /* keep all nonzero entries */ 9 | } 10 | -------------------------------------------------------------------------------- /Source/cs_dupl.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* remove duplicate entries from A */ 3 | csi cs_dupl (cs *A) 4 | { 5 | csi i, j, p, q, nz = 0, n, m, *Ap, *Ai, *w ; 6 | double *Ax ; 7 | if (!CS_CSC (A)) return (0) ; /* check inputs */ 8 | m = A->m ; n = A->n ; Ap = A->p ; Ai = A->i ; Ax = A->x ; 9 | w = cs_malloc (m, sizeof (csi)) ; /* get workspace */ 10 | if (!w) return (0) ; /* out of memory */ 11 | for (i = 0 ; i < m ; i++) w [i] = -1 ; /* row i not yet seen */ 12 | for (j = 0 ; j < n ; j++) 13 | { 14 | q = nz ; /* column j will start at q */ 15 | for (p = Ap [j] ; p < Ap [j+1] ; p++) 16 | { 17 | i = Ai [p] ; /* A(i,j) is nonzero */ 18 | if (w [i] >= q) 19 | { 20 | Ax [w [i]] += Ax [p] ; /* A(i,j) is a duplicate */ 21 | } 22 | else 23 | { 24 | w [i] = nz ; /* record where row i occurs */ 25 | Ai [nz] = i ; /* keep A(i,j) */ 26 | Ax [nz++] = Ax [p] ; 27 | } 28 | } 29 | Ap [j] = q ; /* record start of column j */ 30 | } 31 | Ap [n] = nz ; /* finalize A */ 32 | cs_free (w) ; /* free workspace */ 33 | return (cs_sprealloc (A, 0)) ; /* remove extra space from A */ 34 | } 35 | -------------------------------------------------------------------------------- /Source/cs_entry.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* add an entry to a triplet matrix; return 1 if ok, 0 otherwise */ 3 | csi cs_entry (cs *T, csi i, csi j, double x) 4 | { 5 | if (!CS_TRIPLET (T) || i < 0 || j < 0) return (0) ; /* check inputs */ 6 | if (T->nz >= T->nzmax && !cs_sprealloc (T,2*(T->nzmax))) return (0) ; 7 | if (T->x) T->x [T->nz] = x ; 8 | T->i [T->nz] = i ; 9 | T->p [T->nz++] = j ; 10 | T->m = CS_MAX (T->m, i+1) ; 11 | T->n = CS_MAX (T->n, j+1) ; 12 | return (1) ; 13 | } 14 | -------------------------------------------------------------------------------- /Source/cs_ereach.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* find nonzero pattern of Cholesky L(k,1:k-1) using etree and triu(A(:,k)) */ 3 | csi cs_ereach (const cs *A, csi k, const csi *parent, csi *s, csi *w) 4 | { 5 | csi i, p, n, len, top, *Ap, *Ai ; 6 | if (!CS_CSC (A) || !parent || !s || !w) return (-1) ; /* check inputs */ 7 | top = n = A->n ; Ap = A->p ; Ai = A->i ; 8 | CS_MARK (w, k) ; /* mark node k as visited */ 9 | for (p = Ap [k] ; p < Ap [k+1] ; p++) 10 | { 11 | i = Ai [p] ; /* A(i,k) is nonzero */ 12 | if (i > k) continue ; /* only use upper triangular part of A */ 13 | for (len = 0 ; !CS_MARKED (w,i) ; i = parent [i]) /* traverse up etree*/ 14 | { 15 | s [len++] = i ; /* L(k,i) is nonzero */ 16 | CS_MARK (w, i) ; /* mark i as visited */ 17 | } 18 | while (len > 0) s [--top] = s [--len] ; /* push path onto stack */ 19 | } 20 | for (p = top ; p < n ; p++) CS_MARK (w, s [p]) ; /* unmark all nodes */ 21 | CS_MARK (w, k) ; /* unmark node k */ 22 | return (top) ; /* s [top..n-1] contains pattern of L(k,:)*/ 23 | } 24 | -------------------------------------------------------------------------------- /Source/cs_etree.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* compute the etree of A (using triu(A), or A'A without forming A'A */ 3 | csi *cs_etree (const cs *A, csi ata) 4 | { 5 | csi i, k, p, m, n, inext, *Ap, *Ai, *w, *parent, *ancestor, *prev ; 6 | if (!CS_CSC (A)) return (NULL) ; /* check inputs */ 7 | m = A->m ; n = A->n ; Ap = A->p ; Ai = A->i ; 8 | parent = cs_malloc (n, sizeof (csi)) ; /* allocate result */ 9 | w = cs_malloc (n + (ata ? m : 0), sizeof (csi)) ; /* get workspace */ 10 | if (!w || !parent) return (cs_idone (parent, NULL, w, 0)) ; 11 | ancestor = w ; prev = w + n ; 12 | if (ata) for (i = 0 ; i < m ; i++) prev [i] = -1 ; 13 | for (k = 0 ; k < n ; k++) 14 | { 15 | parent [k] = -1 ; /* node k has no parent yet */ 16 | ancestor [k] = -1 ; /* nor does k have an ancestor */ 17 | for (p = Ap [k] ; p < Ap [k+1] ; p++) 18 | { 19 | i = ata ? (prev [Ai [p]]) : (Ai [p]) ; 20 | for ( ; i != -1 && i < k ; i = inext) /* traverse from i to k */ 21 | { 22 | inext = ancestor [i] ; /* inext = ancestor of i */ 23 | ancestor [i] = k ; /* path compression */ 24 | if (inext == -1) parent [i] = k ; /* no anc., parent is k */ 25 | } 26 | if (ata) prev [Ai [p]] = k ; 27 | } 28 | } 29 | return (cs_idone (parent, NULL, w, 1)) ; 30 | } 31 | -------------------------------------------------------------------------------- /Source/cs_fkeep.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* drop entries for which fkeep(A(i,j)) is false; return nz if OK, else -1 */ 3 | csi cs_fkeep (cs *A, csi (*fkeep) (csi, csi, double, void *), void *other) 4 | { 5 | csi j, p, nz = 0, n, *Ap, *Ai ; 6 | double *Ax ; 7 | if (!CS_CSC (A) || !fkeep) return (-1) ; /* check inputs */ 8 | n = A->n ; Ap = A->p ; Ai = A->i ; Ax = A->x ; 9 | for (j = 0 ; j < n ; j++) 10 | { 11 | p = Ap [j] ; /* get current location of col j */ 12 | Ap [j] = nz ; /* record new location of col j */ 13 | for ( ; p < Ap [j+1] ; p++) 14 | { 15 | if (fkeep (Ai [p], j, Ax ? Ax [p] : 1, other)) 16 | { 17 | if (Ax) Ax [nz] = Ax [p] ; /* keep A(i,j) */ 18 | Ai [nz++] = Ai [p] ; 19 | } 20 | } 21 | } 22 | Ap [n] = nz ; /* finalize A */ 23 | cs_sprealloc (A, 0) ; /* remove extra space from A */ 24 | return (nz) ; 25 | } 26 | -------------------------------------------------------------------------------- /Source/cs_gaxpy.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* y = A*x+y */ 3 | csi cs_gaxpy (const cs *A, const double *x, double *y) 4 | { 5 | csi p, j, n, *Ap, *Ai ; 6 | double *Ax ; 7 | if (!CS_CSC (A) || !x || !y) return (0) ; /* check inputs */ 8 | n = A->n ; Ap = A->p ; Ai = A->i ; Ax = A->x ; 9 | for (j = 0 ; j < n ; j++) 10 | { 11 | for (p = Ap [j] ; p < Ap [j+1] ; p++) 12 | { 13 | y [Ai [p]] += Ax [p] * x [j] ; 14 | } 15 | } 16 | return (1) ; 17 | } 18 | -------------------------------------------------------------------------------- /Source/cs_happly.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* apply the ith Householder vector to x */ 3 | csi cs_happly (const cs *V, csi i, double beta, double *x) 4 | { 5 | csi p, *Vp, *Vi ; 6 | double *Vx, tau = 0 ; 7 | if (!CS_CSC (V) || !x) return (0) ; /* check inputs */ 8 | Vp = V->p ; Vi = V->i ; Vx = V->x ; 9 | for (p = Vp [i] ; p < Vp [i+1] ; p++) /* tau = v'*x */ 10 | { 11 | tau += Vx [p] * x [Vi [p]] ; 12 | } 13 | tau *= beta ; /* tau = beta*(v'*x) */ 14 | for (p = Vp [i] ; p < Vp [i+1] ; p++) /* x = x - v*tau */ 15 | { 16 | x [Vi [p]] -= Vx [p] * tau ; 17 | } 18 | return (1) ; 19 | } 20 | -------------------------------------------------------------------------------- /Source/cs_house.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* create a Householder reflection [v,beta,s]=house(x), overwrite x with v, 3 | * where (I-beta*v*v')*x = s*e1. See Algo 5.1.1, Golub & Van Loan, 3rd ed. */ 4 | double cs_house (double *x, double *beta, csi n) 5 | { 6 | double s, sigma = 0 ; 7 | csi i ; 8 | if (!x || !beta) return (-1) ; /* check inputs */ 9 | for (i = 1 ; i < n ; i++) sigma += x [i] * x [i] ; 10 | if (sigma == 0) 11 | { 12 | s = fabs (x [0]) ; /* s = |x(0)| */ 13 | (*beta) = (x [0] <= 0) ? 2 : 0 ; 14 | x [0] = 1 ; 15 | } 16 | else 17 | { 18 | s = sqrt (x [0] * x [0] + sigma) ; /* s = norm (x) */ 19 | x [0] = (x [0] <= 0) ? (x [0] - s) : (-sigma / (x [0] + s)) ; 20 | (*beta) = -1. / (s * x [0]) ; 21 | } 22 | return (s) ; 23 | } 24 | -------------------------------------------------------------------------------- /Source/cs_ipvec.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* x(p) = b, for dense vectors x and b; p=NULL denotes identity */ 3 | csi cs_ipvec (const csi *p, const double *b, double *x, csi n) 4 | { 5 | csi k ; 6 | if (!x || !b) return (0) ; /* check inputs */ 7 | for (k = 0 ; k < n ; k++) x [p ? p [k] : k] = b [k] ; 8 | return (1) ; 9 | } 10 | -------------------------------------------------------------------------------- /Source/cs_leaf.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* consider A(i,j), node j in ith row subtree and return lca(jprev,j) */ 3 | csi cs_leaf (csi i, csi j, const csi *first, csi *maxfirst, csi *prevleaf, 4 | csi *ancestor, csi *jleaf) 5 | { 6 | csi q, s, sparent, jprev ; 7 | if (!first || !maxfirst || !prevleaf || !ancestor || !jleaf) return (-1) ; 8 | *jleaf = 0 ; 9 | if (i <= j || first [j] <= maxfirst [i]) return (-1) ; /* j not a leaf */ 10 | maxfirst [i] = first [j] ; /* update max first[j] seen so far */ 11 | jprev = prevleaf [i] ; /* jprev = previous leaf of ith subtree */ 12 | prevleaf [i] = j ; 13 | *jleaf = (jprev == -1) ? 1: 2 ; /* j is first or subsequent leaf */ 14 | if (*jleaf == 1) return (i) ; /* if 1st leaf, q = root of ith subtree */ 15 | for (q = jprev ; q != ancestor [q] ; q = ancestor [q]) ; 16 | for (s = jprev ; s != q ; s = sparent) 17 | { 18 | sparent = ancestor [s] ; /* path compression */ 19 | ancestor [s] = q ; 20 | } 21 | return (q) ; /* q = least common ancester (jprev,j) */ 22 | } 23 | -------------------------------------------------------------------------------- /Source/cs_load.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* load a triplet matrix from a file */ 3 | cs *cs_load (FILE *f) 4 | { 5 | double i, j ; /* use double for integers to avoid csi conflicts */ 6 | double x ; 7 | cs *T ; 8 | if (!f) return (NULL) ; /* check inputs */ 9 | T = cs_spalloc (0, 0, 1, 1, 1) ; /* allocate result */ 10 | while (fscanf (f, "%lg %lg %lg\n", &i, &j, &x) == 3) 11 | { 12 | if (!cs_entry (T, (csi) i, (csi) j, x)) return (cs_spfree (T)) ; 13 | } 14 | return (T) ; 15 | } 16 | -------------------------------------------------------------------------------- /Source/cs_lsolve.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* solve Lx=b where x and b are dense. x=b on input, solution on output. */ 3 | csi cs_lsolve (const cs *L, double *x) 4 | { 5 | csi p, j, n, *Lp, *Li ; 6 | double *Lx ; 7 | if (!CS_CSC (L) || !x) return (0) ; /* check inputs */ 8 | n = L->n ; Lp = L->p ; Li = L->i ; Lx = L->x ; 9 | for (j = 0 ; j < n ; j++) 10 | { 11 | x [j] /= Lx [Lp [j]] ; 12 | for (p = Lp [j]+1 ; p < Lp [j+1] ; p++) 13 | { 14 | x [Li [p]] -= Lx [p] * x [j] ; 15 | } 16 | } 17 | return (1) ; 18 | } 19 | -------------------------------------------------------------------------------- /Source/cs_ltsolve.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* solve L'x=b where x and b are dense. x=b on input, solution on output. */ 3 | csi cs_ltsolve (const cs *L, double *x) 4 | { 5 | csi p, j, n, *Lp, *Li ; 6 | double *Lx ; 7 | if (!CS_CSC (L) || !x) return (0) ; /* check inputs */ 8 | n = L->n ; Lp = L->p ; Li = L->i ; Lx = L->x ; 9 | for (j = n-1 ; j >= 0 ; j--) 10 | { 11 | for (p = Lp [j]+1 ; p < Lp [j+1] ; p++) 12 | { 13 | x [j] -= Lx [p] * x [Li [p]] ; 14 | } 15 | x [j] /= Lx [Lp [j]] ; 16 | } 17 | return (1) ; 18 | } 19 | -------------------------------------------------------------------------------- /Source/cs_lu.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* [L,U,pinv]=lu(A, [q lnz unz]). lnz and unz can be guess */ 3 | csn *cs_lu (const cs *A, const css *S, double tol) 4 | { 5 | cs *L, *U ; 6 | csn *N ; 7 | double pivot, *Lx, *Ux, *x, a, t ; 8 | csi *Lp, *Li, *Up, *Ui, *pinv, *xi, *q, n, ipiv, k, top, p, i, col, lnz,unz; 9 | if (!CS_CSC (A) || !S) return (NULL) ; /* check inputs */ 10 | n = A->n ; 11 | q = S->q ; lnz = S->lnz ; unz = S->unz ; 12 | x = cs_malloc (n, sizeof (double)) ; /* get double workspace */ 13 | xi = cs_malloc (2*n, sizeof (csi)) ; /* get csi workspace */ 14 | N = cs_calloc (1, sizeof (csn)) ; /* allocate result */ 15 | if (!x || !xi || !N) return (cs_ndone (N, NULL, xi, x, 0)) ; 16 | N->L = L = cs_spalloc (n, n, lnz, 1, 0) ; /* allocate result L */ 17 | N->U = U = cs_spalloc (n, n, unz, 1, 0) ; /* allocate result U */ 18 | N->pinv = pinv = cs_malloc (n, sizeof (csi)) ; /* allocate result pinv */ 19 | if (!L || !U || !pinv) return (cs_ndone (N, NULL, xi, x, 0)) ; 20 | Lp = L->p ; Up = U->p ; 21 | for (i = 0 ; i < n ; i++) x [i] = 0 ; /* clear workspace */ 22 | for (i = 0 ; i < n ; i++) pinv [i] = -1 ; /* no rows pivotal yet */ 23 | for (k = 0 ; k <= n ; k++) Lp [k] = 0 ; /* no cols of L yet */ 24 | lnz = unz = 0 ; 25 | for (k = 0 ; k < n ; k++) /* compute L(:,k) and U(:,k) */ 26 | { 27 | /* --- Triangular solve --------------------------------------------- */ 28 | Lp [k] = lnz ; /* L(:,k) starts here */ 29 | Up [k] = unz ; /* U(:,k) starts here */ 30 | if ((lnz + n > L->nzmax && !cs_sprealloc (L, 2*L->nzmax + n)) || 31 | (unz + n > U->nzmax && !cs_sprealloc (U, 2*U->nzmax + n))) 32 | { 33 | return (cs_ndone (N, NULL, xi, x, 0)) ; 34 | } 35 | Li = L->i ; Lx = L->x ; Ui = U->i ; Ux = U->x ; 36 | col = q ? (q [k]) : k ; 37 | top = cs_spsolve (L, A, col, xi, x, pinv, 1) ; /* x = L\A(:,col) */ 38 | /* --- Find pivot --------------------------------------------------- */ 39 | ipiv = -1 ; 40 | a = -1 ; 41 | for (p = top ; p < n ; p++) 42 | { 43 | i = xi [p] ; /* x(i) is nonzero */ 44 | if (pinv [i] < 0) /* row i is not yet pivotal */ 45 | { 46 | if ((t = fabs (x [i])) > a) 47 | { 48 | a = t ; /* largest pivot candidate so far */ 49 | ipiv = i ; 50 | } 51 | } 52 | else /* x(i) is the entry U(pinv[i],k) */ 53 | { 54 | Ui [unz] = pinv [i] ; 55 | Ux [unz++] = x [i] ; 56 | } 57 | } 58 | if (ipiv == -1 || a <= 0) return (cs_ndone (N, NULL, xi, x, 0)) ; 59 | if (pinv [col] < 0 && fabs (x [col]) >= a*tol) ipiv = col ; 60 | /* --- Divide by pivot ---------------------------------------------- */ 61 | pivot = x [ipiv] ; /* the chosen pivot */ 62 | Ui [unz] = k ; /* last entry in U(:,k) is U(k,k) */ 63 | Ux [unz++] = pivot ; 64 | pinv [ipiv] = k ; /* ipiv is the kth pivot row */ 65 | Li [lnz] = ipiv ; /* first entry in L(:,k) is L(k,k) = 1 */ 66 | Lx [lnz++] = 1 ; 67 | for (p = top ; p < n ; p++) /* L(k+1:n,k) = x / pivot */ 68 | { 69 | i = xi [p] ; 70 | if (pinv [i] < 0) /* x(i) is an entry in L(:,k) */ 71 | { 72 | Li [lnz] = i ; /* save unpermuted row in L */ 73 | Lx [lnz++] = x [i] / pivot ; /* scale pivot column */ 74 | } 75 | x [i] = 0 ; /* x [0..n-1] = 0 for next k */ 76 | } 77 | } 78 | /* --- Finalize L and U ------------------------------------------------- */ 79 | Lp [n] = lnz ; 80 | Up [n] = unz ; 81 | Li = L->i ; /* fix row indices of L for final pinv */ 82 | for (p = 0 ; p < lnz ; p++) Li [p] = pinv [Li [p]] ; 83 | cs_sprealloc (L, 0) ; /* remove extra space from L and U */ 84 | cs_sprealloc (U, 0) ; 85 | return (cs_ndone (N, NULL, xi, x, 1)) ; /* success */ 86 | } 87 | -------------------------------------------------------------------------------- /Source/cs_lusol.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* x=A\b where A is unsymmetric; b overwritten with solution */ 3 | csi cs_lusol (csi order, const cs *A, double *b, double tol) 4 | { 5 | double *x ; 6 | css *S ; 7 | csn *N ; 8 | csi n, ok ; 9 | if (!CS_CSC (A) || !b) return (0) ; /* check inputs */ 10 | n = A->n ; 11 | S = cs_sqr (order, A, 0) ; /* ordering and symbolic analysis */ 12 | N = cs_lu (A, S, tol) ; /* numeric LU factorization */ 13 | x = cs_malloc (n, sizeof (double)) ; /* get workspace */ 14 | ok = (S && N && x) ; 15 | if (ok) 16 | { 17 | cs_ipvec (N->pinv, b, x, n) ; /* x = b(p) */ 18 | cs_lsolve (N->L, x) ; /* x = L\x */ 19 | cs_usolve (N->U, x) ; /* x = U\x */ 20 | cs_ipvec (S->q, x, b, n) ; /* b(q) = x */ 21 | } 22 | cs_free (x) ; 23 | cs_sfree (S) ; 24 | cs_nfree (N) ; 25 | return (ok) ; 26 | } 27 | -------------------------------------------------------------------------------- /Source/cs_malloc.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | #ifdef MATLAB_MEX_FILE 3 | #define malloc mxMalloc 4 | #define free mxFree 5 | #define realloc mxRealloc 6 | #define calloc mxCalloc 7 | #endif 8 | 9 | /* wrapper for malloc */ 10 | void *cs_malloc (csi n, size_t size) 11 | { 12 | return (malloc (CS_MAX (n,1) * size)) ; 13 | } 14 | 15 | /* wrapper for calloc */ 16 | void *cs_calloc (csi n, size_t size) 17 | { 18 | return (calloc (CS_MAX (n,1), size)) ; 19 | } 20 | 21 | /* wrapper for free */ 22 | void *cs_free (void *p) 23 | { 24 | if (p) free (p) ; /* free p if it is not already NULL */ 25 | return (NULL) ; /* return NULL to simplify the use of cs_free */ 26 | } 27 | 28 | /* wrapper for realloc */ 29 | void *cs_realloc (void *p, csi n, size_t size, csi *ok) 30 | { 31 | void *pnew ; 32 | pnew = realloc (p, CS_MAX (n,1) * size) ; /* realloc the block */ 33 | *ok = (pnew != NULL) ; /* realloc fails if pnew is NULL */ 34 | return ((*ok) ? pnew : p) ; /* return original p if failure */ 35 | } 36 | -------------------------------------------------------------------------------- /Source/cs_maxtrans.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* find an augmenting path starting at column k and extend the match if found */ 3 | static void cs_augment (csi k, const cs *A, csi *jmatch, csi *cheap, csi *w, 4 | csi *js, csi *is, csi *ps) 5 | { 6 | csi found = 0, p, i = -1, *Ap = A->p, *Ai = A->i, head = 0, j ; 7 | js [0] = k ; /* start with just node k in jstack */ 8 | while (head >= 0) 9 | { 10 | /* --- Start (or continue) depth-first-search at node j ------------- */ 11 | j = js [head] ; /* get j from top of jstack */ 12 | if (w [j] != k) /* 1st time j visited for kth path */ 13 | { 14 | w [j] = k ; /* mark j as visited for kth path */ 15 | for (p = cheap [j] ; p < Ap [j+1] && !found ; p++) 16 | { 17 | i = Ai [p] ; /* try a cheap assignment (i,j) */ 18 | found = (jmatch [i] == -1) ; 19 | } 20 | cheap [j] = p ; /* start here next time j is traversed*/ 21 | if (found) 22 | { 23 | is [head] = i ; /* column j matched with row i */ 24 | break ; /* end of augmenting path */ 25 | } 26 | ps [head] = Ap [j] ; /* no cheap match: start dfs for j */ 27 | } 28 | /* --- Depth-first-search of neighbors of j ------------------------- */ 29 | for (p = ps [head] ; p < Ap [j+1] ; p++) 30 | { 31 | i = Ai [p] ; /* consider row i */ 32 | if (w [jmatch [i]] == k) continue ; /* skip jmatch [i] if marked */ 33 | ps [head] = p + 1 ; /* pause dfs of node j */ 34 | is [head] = i ; /* i will be matched with j if found */ 35 | js [++head] = jmatch [i] ; /* start dfs at column jmatch [i] */ 36 | break ; 37 | } 38 | if (p == Ap [j+1]) head-- ; /* node j is done; pop from stack */ 39 | } /* augment the match if path found: */ 40 | if (found) for (p = head ; p >= 0 ; p--) jmatch [is [p]] = js [p] ; 41 | } 42 | 43 | /* find a maximum transveral */ 44 | csi *cs_maxtrans (const cs *A, csi seed) /*[jmatch [0..m-1]; imatch [0..n-1]]*/ 45 | { 46 | csi i, j, k, n, m, p, n2 = 0, m2 = 0, *Ap, *jimatch, *w, *cheap, *js, *is, 47 | *ps, *Ai, *Cp, *jmatch, *imatch, *q ; 48 | cs *C ; 49 | if (!CS_CSC (A)) return (NULL) ; /* check inputs */ 50 | n = A->n ; m = A->m ; Ap = A->p ; Ai = A->i ; 51 | w = jimatch = cs_calloc (m+n, sizeof (csi)) ; /* allocate result */ 52 | if (!jimatch) return (NULL) ; 53 | for (k = 0, j = 0 ; j < n ; j++) /* count nonempty rows and columns */ 54 | { 55 | n2 += (Ap [j] < Ap [j+1]) ; 56 | for (p = Ap [j] ; p < Ap [j+1] ; p++) 57 | { 58 | w [Ai [p]] = 1 ; 59 | k += (j == Ai [p]) ; /* count entries already on diagonal */ 60 | } 61 | } 62 | if (k == CS_MIN (m,n)) /* quick return if diagonal zero-free */ 63 | { 64 | jmatch = jimatch ; imatch = jimatch + m ; 65 | for (i = 0 ; i < k ; i++) jmatch [i] = i ; 66 | for ( ; i < m ; i++) jmatch [i] = -1 ; 67 | for (j = 0 ; j < k ; j++) imatch [j] = j ; 68 | for ( ; j < n ; j++) imatch [j] = -1 ; 69 | return (cs_idone (jimatch, NULL, NULL, 1)) ; 70 | } 71 | for (i = 0 ; i < m ; i++) m2 += w [i] ; 72 | C = (m2 < n2) ? cs_transpose (A,0) : ((cs *) A) ; /* transpose if needed */ 73 | if (!C) return (cs_idone (jimatch, (m2 < n2) ? C : NULL, NULL, 0)) ; 74 | n = C->n ; m = C->m ; Cp = C->p ; 75 | jmatch = (m2 < n2) ? jimatch + n : jimatch ; 76 | imatch = (m2 < n2) ? jimatch : jimatch + m ; 77 | w = cs_malloc (5*n, sizeof (csi)) ; /* get workspace */ 78 | if (!w) return (cs_idone (jimatch, (m2 < n2) ? C : NULL, w, 0)) ; 79 | cheap = w + n ; js = w + 2*n ; is = w + 3*n ; ps = w + 4*n ; 80 | for (j = 0 ; j < n ; j++) cheap [j] = Cp [j] ; /* for cheap assignment */ 81 | for (j = 0 ; j < n ; j++) w [j] = -1 ; /* all columns unflagged */ 82 | for (i = 0 ; i < m ; i++) jmatch [i] = -1 ; /* nothing matched yet */ 83 | q = cs_randperm (n, seed) ; /* q = random permutation */ 84 | for (k = 0 ; k < n ; k++) /* augment, starting at column q[k] */ 85 | { 86 | cs_augment (q ? q [k]: k, C, jmatch, cheap, w, js, is, ps) ; 87 | } 88 | cs_free (q) ; 89 | for (j = 0 ; j < n ; j++) imatch [j] = -1 ; /* find row match */ 90 | for (i = 0 ; i < m ; i++) if (jmatch [i] >= 0) imatch [jmatch [i]] = i ; 91 | return (cs_idone (jimatch, (m2 < n2) ? C : NULL, w, 1)) ; 92 | } 93 | -------------------------------------------------------------------------------- /Source/cs_multiply.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* C = A*B */ 3 | cs *cs_multiply (const cs *A, const cs *B) 4 | { 5 | csi p, j, nz = 0, anz, *Cp, *Ci, *Bp, m, n, bnz, *w, values, *Bi ; 6 | double *x, *Bx, *Cx ; 7 | cs *C ; 8 | if (!CS_CSC (A) || !CS_CSC (B)) return (NULL) ; /* check inputs */ 9 | if (A->n != B->m) return (NULL) ; 10 | m = A->m ; anz = A->p [A->n] ; 11 | n = B->n ; Bp = B->p ; Bi = B->i ; Bx = B->x ; bnz = Bp [n] ; 12 | w = cs_calloc (m, sizeof (csi)) ; /* get workspace */ 13 | values = (A->x != NULL) && (Bx != NULL) ; 14 | x = values ? cs_malloc (m, sizeof (double)) : NULL ; /* get workspace */ 15 | C = cs_spalloc (m, n, anz + bnz, values, 0) ; /* allocate result */ 16 | if (!C || !w || (values && !x)) return (cs_done (C, w, x, 0)) ; 17 | Cp = C->p ; 18 | for (j = 0 ; j < n ; j++) 19 | { 20 | if (nz + m > C->nzmax && !cs_sprealloc (C, 2*(C->nzmax)+m)) 21 | { 22 | return (cs_done (C, w, x, 0)) ; /* out of memory */ 23 | } 24 | Ci = C->i ; Cx = C->x ; /* C->i and C->x may be reallocated */ 25 | Cp [j] = nz ; /* column j of C starts here */ 26 | for (p = Bp [j] ; p < Bp [j+1] ; p++) 27 | { 28 | nz = cs_scatter (A, Bi [p], Bx ? Bx [p] : 1, w, x, j+1, C, nz) ; 29 | } 30 | if (values) for (p = Cp [j] ; p < nz ; p++) Cx [p] = x [Ci [p]] ; 31 | } 32 | Cp [n] = nz ; /* finalize the last column of C */ 33 | cs_sprealloc (C, 0) ; /* remove extra space from C */ 34 | return (cs_done (C, w, x, 1)) ; /* success; free workspace, return C */ 35 | } 36 | -------------------------------------------------------------------------------- /Source/cs_norm.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* 1-norm of a sparse matrix = max (sum (abs (A))), largest column sum */ 3 | double cs_norm (const cs *A) 4 | { 5 | csi p, j, n, *Ap ; 6 | double *Ax, norm = 0, s ; 7 | if (!CS_CSC (A) || !A->x) return (-1) ; /* check inputs */ 8 | n = A->n ; Ap = A->p ; Ax = A->x ; 9 | for (j = 0 ; j < n ; j++) 10 | { 11 | for (s = 0, p = Ap [j] ; p < Ap [j+1] ; p++) s += fabs (Ax [p]) ; 12 | norm = CS_MAX (norm, s) ; 13 | } 14 | return (norm) ; 15 | } 16 | -------------------------------------------------------------------------------- /Source/cs_permute.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* C = A(p,q) where p and q are permutations of 0..m-1 and 0..n-1. */ 3 | cs *cs_permute (const cs *A, const csi *pinv, const csi *q, csi values) 4 | { 5 | csi t, j, k, nz = 0, m, n, *Ap, *Ai, *Cp, *Ci ; 6 | double *Cx, *Ax ; 7 | cs *C ; 8 | if (!CS_CSC (A)) return (NULL) ; /* check inputs */ 9 | m = A->m ; n = A->n ; Ap = A->p ; Ai = A->i ; Ax = A->x ; 10 | C = cs_spalloc (m, n, Ap [n], values && Ax != NULL, 0) ; /* alloc result */ 11 | if (!C) return (cs_done (C, NULL, NULL, 0)) ; /* out of memory */ 12 | Cp = C->p ; Ci = C->i ; Cx = C->x ; 13 | for (k = 0 ; k < n ; k++) 14 | { 15 | Cp [k] = nz ; /* column k of C is column q[k] of A */ 16 | j = q ? (q [k]) : k ; 17 | for (t = Ap [j] ; t < Ap [j+1] ; t++) 18 | { 19 | if (Cx) Cx [nz] = Ax [t] ; /* row i of A is row pinv[i] of C */ 20 | Ci [nz++] = pinv ? (pinv [Ai [t]]) : Ai [t] ; 21 | } 22 | } 23 | Cp [n] = nz ; /* finalize the last column of C */ 24 | return (cs_done (C, NULL, NULL, 1)) ; 25 | } 26 | -------------------------------------------------------------------------------- /Source/cs_pinv.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* pinv = p', or p = pinv' */ 3 | csi *cs_pinv (csi const *p, csi n) 4 | { 5 | csi k, *pinv ; 6 | if (!p) return (NULL) ; /* p = NULL denotes identity */ 7 | pinv = cs_malloc (n, sizeof (csi)) ; /* allocate result */ 8 | if (!pinv) return (NULL) ; /* out of memory */ 9 | for (k = 0 ; k < n ; k++) pinv [p [k]] = k ;/* invert the permutation */ 10 | return (pinv) ; /* return result */ 11 | } 12 | -------------------------------------------------------------------------------- /Source/cs_post.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* post order a forest */ 3 | csi *cs_post (const csi *parent, csi n) 4 | { 5 | csi j, k = 0, *post, *w, *head, *next, *stack ; 6 | if (!parent) return (NULL) ; /* check inputs */ 7 | post = cs_malloc (n, sizeof (csi)) ; /* allocate result */ 8 | w = cs_malloc (3*n, sizeof (csi)) ; /* get workspace */ 9 | if (!w || !post) return (cs_idone (post, NULL, w, 0)) ; 10 | head = w ; next = w + n ; stack = w + 2*n ; 11 | for (j = 0 ; j < n ; j++) head [j] = -1 ; /* empty linked lists */ 12 | for (j = n-1 ; j >= 0 ; j--) /* traverse nodes in reverse order*/ 13 | { 14 | if (parent [j] == -1) continue ; /* j is a root */ 15 | next [j] = head [parent [j]] ; /* add j to list of its parent */ 16 | head [parent [j]] = j ; 17 | } 18 | for (j = 0 ; j < n ; j++) 19 | { 20 | if (parent [j] != -1) continue ; /* skip j if it is not a root */ 21 | k = cs_tdfs (j, k, head, next, post, stack) ; 22 | } 23 | return (cs_idone (post, NULL, w, 1)) ; /* success; free w, return post */ 24 | } 25 | -------------------------------------------------------------------------------- /Source/cs_print.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* print a sparse matrix; use %g for integers to avoid differences with csi */ 3 | csi cs_print (const cs *A, csi brief) 4 | { 5 | csi p, j, m, n, nzmax, nz, *Ap, *Ai ; 6 | double *Ax ; 7 | if (!A) { printf ("(null)\n") ; return (0) ; } 8 | m = A->m ; n = A->n ; Ap = A->p ; Ai = A->i ; Ax = A->x ; 9 | nzmax = A->nzmax ; nz = A->nz ; 10 | printf ("CSparse Version %d.%d.%d, %s. %s\n", CS_VER, CS_SUBVER, 11 | CS_SUBSUB, CS_DATE, CS_COPYRIGHT) ; 12 | if (nz < 0) 13 | { 14 | printf ("%g-by-%g, nzmax: %g nnz: %g, 1-norm: %g\n", (double) m, 15 | (double) n, (double) nzmax, (double) (Ap [n]), cs_norm (A)) ; 16 | for (j = 0 ; j < n ; j++) 17 | { 18 | printf (" col %g : locations %g to %g\n", (double) j, 19 | (double) (Ap [j]), (double) (Ap [j+1]-1)) ; 20 | for (p = Ap [j] ; p < Ap [j+1] ; p++) 21 | { 22 | printf (" %g : %g\n", (double) (Ai [p]), Ax ? Ax [p] : 1) ; 23 | if (brief && p > 20) { printf (" ...\n") ; return (1) ; } 24 | } 25 | } 26 | } 27 | else 28 | { 29 | printf ("triplet: %g-by-%g, nzmax: %g nnz: %g\n", (double) m, 30 | (double) n, (double) nzmax, (double) nz) ; 31 | for (p = 0 ; p < nz ; p++) 32 | { 33 | printf (" %g %g : %g\n", (double) (Ai [p]), (double) (Ap [p]), 34 | Ax ? Ax [p] : 1) ; 35 | if (brief && p > 20) { printf (" ...\n") ; return (1) ; } 36 | } 37 | } 38 | return (1) ; 39 | } 40 | -------------------------------------------------------------------------------- /Source/cs_pvec.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* x = b(p), for dense vectors x and b; p=NULL denotes identity */ 3 | csi cs_pvec (const csi *p, const double *b, double *x, csi n) 4 | { 5 | csi k ; 6 | if (!x || !b) return (0) ; /* check inputs */ 7 | for (k = 0 ; k < n ; k++) x [k] = b [p ? p [k] : k] ; 8 | return (1) ; 9 | } 10 | -------------------------------------------------------------------------------- /Source/cs_qr.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* sparse QR factorization [V,beta,pinv,R] = qr (A) */ 3 | csn *cs_qr (const cs *A, const css *S) 4 | { 5 | double *Rx, *Vx, *Ax, *x, *Beta ; 6 | csi i, k, p, m, n, vnz, p1, top, m2, len, col, rnz, *s, *leftmost, *Ap, *Ai, 7 | *parent, *Rp, *Ri, *Vp, *Vi, *w, *pinv, *q ; 8 | cs *R, *V ; 9 | csn *N ; 10 | if (!CS_CSC (A) || !S) return (NULL) ; 11 | m = A->m ; n = A->n ; Ap = A->p ; Ai = A->i ; Ax = A->x ; 12 | q = S->q ; parent = S->parent ; pinv = S->pinv ; m2 = S->m2 ; 13 | vnz = S->lnz ; rnz = S->unz ; leftmost = S->leftmost ; 14 | w = cs_malloc (m2+n, sizeof (csi)) ; /* get csi workspace */ 15 | x = cs_malloc (m2, sizeof (double)) ; /* get double workspace */ 16 | N = cs_calloc (1, sizeof (csn)) ; /* allocate result */ 17 | if (!w || !x || !N) return (cs_ndone (N, NULL, w, x, 0)) ; 18 | s = w + m2 ; /* s is size n */ 19 | for (k = 0 ; k < m2 ; k++) x [k] = 0 ; /* clear workspace x */ 20 | N->L = V = cs_spalloc (m2, n, vnz, 1, 0) ; /* allocate result V */ 21 | N->U = R = cs_spalloc (m2, n, rnz, 1, 0) ; /* allocate result R */ 22 | N->B = Beta = cs_malloc (n, sizeof (double)) ; /* allocate result Beta */ 23 | if (!R || !V || !Beta) return (cs_ndone (N, NULL, w, x, 0)) ; 24 | Rp = R->p ; Ri = R->i ; Rx = R->x ; 25 | Vp = V->p ; Vi = V->i ; Vx = V->x ; 26 | for (i = 0 ; i < m2 ; i++) w [i] = -1 ; /* clear w, to mark nodes */ 27 | rnz = 0 ; vnz = 0 ; 28 | for (k = 0 ; k < n ; k++) /* compute V and R */ 29 | { 30 | Rp [k] = rnz ; /* R(:,k) starts here */ 31 | Vp [k] = p1 = vnz ; /* V(:,k) starts here */ 32 | w [k] = k ; /* add V(k,k) to pattern of V */ 33 | Vi [vnz++] = k ; 34 | top = n ; 35 | col = q ? q [k] : k ; 36 | for (p = Ap [col] ; p < Ap [col+1] ; p++) /* find R(:,k) pattern */ 37 | { 38 | i = leftmost [Ai [p]] ; /* i = min(find(A(i,q))) */ 39 | for (len = 0 ; w [i] != k ; i = parent [i]) /* traverse up to k */ 40 | { 41 | s [len++] = i ; 42 | w [i] = k ; 43 | } 44 | while (len > 0) s [--top] = s [--len] ; /* push path on stack */ 45 | i = pinv [Ai [p]] ; /* i = permuted row of A(:,col) */ 46 | x [i] = Ax [p] ; /* x (i) = A(:,col) */ 47 | if (i > k && w [i] < k) /* pattern of V(:,k) = x (k+1:m) */ 48 | { 49 | Vi [vnz++] = i ; /* add i to pattern of V(:,k) */ 50 | w [i] = k ; 51 | } 52 | } 53 | for (p = top ; p < n ; p++) /* for each i in pattern of R(:,k) */ 54 | { 55 | i = s [p] ; /* R(i,k) is nonzero */ 56 | cs_happly (V, i, Beta [i], x) ; /* apply (V(i),Beta(i)) to x */ 57 | Ri [rnz] = i ; /* R(i,k) = x(i) */ 58 | Rx [rnz++] = x [i] ; 59 | x [i] = 0 ; 60 | if (parent [i] == k) vnz = cs_scatter (V, i, 0, w, NULL, k, V, vnz); 61 | } 62 | for (p = p1 ; p < vnz ; p++) /* gather V(:,k) = x */ 63 | { 64 | Vx [p] = x [Vi [p]] ; 65 | x [Vi [p]] = 0 ; 66 | } 67 | Ri [rnz] = k ; /* R(k,k) = norm (x) */ 68 | Rx [rnz++] = cs_house (Vx+p1, Beta+k, vnz-p1) ; /* [v,beta]=house(x) */ 69 | } 70 | Rp [n] = rnz ; /* finalize R */ 71 | Vp [n] = vnz ; /* finalize V */ 72 | return (cs_ndone (N, NULL, w, x, 1)) ; /* success */ 73 | } 74 | -------------------------------------------------------------------------------- /Source/cs_qrsol.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* x=A\b where A can be rectangular; b overwritten with solution */ 3 | csi cs_qrsol (csi order, const cs *A, double *b) 4 | { 5 | double *x ; 6 | css *S ; 7 | csn *N ; 8 | cs *AT = NULL ; 9 | csi k, m, n, ok ; 10 | if (!CS_CSC (A) || !b) return (0) ; /* check inputs */ 11 | n = A->n ; 12 | m = A->m ; 13 | if (m >= n) 14 | { 15 | S = cs_sqr (order, A, 1) ; /* ordering and symbolic analysis */ 16 | N = cs_qr (A, S) ; /* numeric QR factorization */ 17 | x = cs_calloc (S ? S->m2 : 1, sizeof (double)) ; /* get workspace */ 18 | ok = (S && N && x) ; 19 | if (ok) 20 | { 21 | cs_ipvec (S->pinv, b, x, m) ; /* x(0:m-1) = b(p(0:m-1) */ 22 | for (k = 0 ; k < n ; k++) /* apply Householder refl. to x */ 23 | { 24 | cs_happly (N->L, k, N->B [k], x) ; 25 | } 26 | cs_usolve (N->U, x) ; /* x = R\x */ 27 | cs_ipvec (S->q, x, b, n) ; /* b(q(0:n-1)) = x(0:n-1) */ 28 | } 29 | } 30 | else 31 | { 32 | AT = cs_transpose (A, 1) ; /* Ax=b is underdetermined */ 33 | S = cs_sqr (order, AT, 1) ; /* ordering and symbolic analysis */ 34 | N = cs_qr (AT, S) ; /* numeric QR factorization of A' */ 35 | x = cs_calloc (S ? S->m2 : 1, sizeof (double)) ; /* get workspace */ 36 | ok = (AT && S && N && x) ; 37 | if (ok) 38 | { 39 | cs_pvec (S->q, b, x, m) ; /* x(q(0:m-1)) = b(0:m-1) */ 40 | cs_utsolve (N->U, x) ; /* x = R'\x */ 41 | for (k = m-1 ; k >= 0 ; k--) /* apply Householder refl. to x */ 42 | { 43 | cs_happly (N->L, k, N->B [k], x) ; 44 | } 45 | cs_pvec (S->pinv, x, b, n) ; /* b(0:n-1) = x(p(0:n-1)) */ 46 | } 47 | } 48 | cs_free (x) ; 49 | cs_sfree (S) ; 50 | cs_nfree (N) ; 51 | cs_spfree (AT) ; 52 | return (ok) ; 53 | } 54 | -------------------------------------------------------------------------------- /Source/cs_randperm.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* return a random permutation vector, the identity perm, or p = n-1:-1:0. 3 | * seed = -1 means p = n-1:-1:0. seed = 0 means p = identity. otherwise 4 | * p = random permutation. */ 5 | csi *cs_randperm (csi n, csi seed) 6 | { 7 | csi *p, k, j, t ; 8 | if (seed == 0) return (NULL) ; /* return p = NULL (identity) */ 9 | p = cs_malloc (n, sizeof (csi)) ; /* allocate result */ 10 | if (!p) return (NULL) ; /* out of memory */ 11 | for (k = 0 ; k < n ; k++) p [k] = n-k-1 ; 12 | if (seed == -1) return (p) ; /* return reverse permutation */ 13 | srand (seed) ; /* get new random number seed */ 14 | for (k = 0 ; k < n ; k++) 15 | { 16 | j = k + (rand ( ) % (n-k)) ; /* j = rand integer in range k to n-1 */ 17 | t = p [j] ; /* swap p[k] and p[j] */ 18 | p [j] = p [k] ; 19 | p [k] = t ; 20 | } 21 | return (p) ; 22 | } 23 | -------------------------------------------------------------------------------- /Source/cs_reach.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* xi [top...n-1] = nodes reachable from graph of G*P' via nodes in B(:,k). 3 | * xi [n...2n-1] used as workspace */ 4 | csi cs_reach (cs *G, const cs *B, csi k, csi *xi, const csi *pinv) 5 | { 6 | csi p, n, top, *Bp, *Bi, *Gp ; 7 | if (!CS_CSC (G) || !CS_CSC (B) || !xi) return (-1) ; /* check inputs */ 8 | n = G->n ; Bp = B->p ; Bi = B->i ; Gp = G->p ; 9 | top = n ; 10 | for (p = Bp [k] ; p < Bp [k+1] ; p++) 11 | { 12 | if (!CS_MARKED (Gp, Bi [p])) /* start a dfs at unmarked node i */ 13 | { 14 | top = cs_dfs (Bi [p], G, top, xi, xi+n, pinv) ; 15 | } 16 | } 17 | for (p = top ; p < n ; p++) CS_MARK (Gp, xi [p]) ; /* restore G */ 18 | return (top) ; 19 | } 20 | -------------------------------------------------------------------------------- /Source/cs_scatter.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* x = x + beta * A(:,j), where x is a dense vector and A(:,j) is sparse */ 3 | csi cs_scatter (const cs *A, csi j, double beta, csi *w, double *x, csi mark, 4 | cs *C, csi nz) 5 | { 6 | csi i, p, *Ap, *Ai, *Ci ; 7 | double *Ax ; 8 | if (!CS_CSC (A) || !w || !CS_CSC (C)) return (-1) ; /* check inputs */ 9 | Ap = A->p ; Ai = A->i ; Ax = A->x ; Ci = C->i ; 10 | for (p = Ap [j] ; p < Ap [j+1] ; p++) 11 | { 12 | i = Ai [p] ; /* A(i,j) is nonzero */ 13 | if (w [i] < mark) 14 | { 15 | w [i] = mark ; /* i is new entry in column j */ 16 | Ci [nz++] = i ; /* add i to pattern of C(:,j) */ 17 | if (x) x [i] = beta * Ax [p] ; /* x(i) = beta*A(i,j) */ 18 | } 19 | else if (x) x [i] += beta * Ax [p] ; /* i exists in C(:,j) already */ 20 | } 21 | return (nz) ; 22 | } 23 | -------------------------------------------------------------------------------- /Source/cs_scc.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* find the strongly connected components of a square matrix */ 3 | csd *cs_scc (cs *A) /* matrix A temporarily modified, then restored */ 4 | { 5 | csi n, i, k, b, nb = 0, top, *xi, *pstack, *p, *r, *Ap, *ATp, *rcopy, *Blk ; 6 | cs *AT ; 7 | csd *D ; 8 | if (!CS_CSC (A)) return (NULL) ; /* check inputs */ 9 | n = A->n ; Ap = A->p ; 10 | D = cs_dalloc (n, 0) ; /* allocate result */ 11 | AT = cs_transpose (A, 0) ; /* AT = A' */ 12 | xi = cs_malloc (2*n+1, sizeof (csi)) ; /* get workspace */ 13 | if (!D || !AT || !xi) return (cs_ddone (D, AT, xi, 0)) ; 14 | Blk = xi ; rcopy = pstack = xi + n ; 15 | p = D->p ; r = D->r ; ATp = AT->p ; 16 | top = n ; 17 | for (i = 0 ; i < n ; i++) /* first dfs(A) to find finish times (xi) */ 18 | { 19 | if (!CS_MARKED (Ap, i)) top = cs_dfs (i, A, top, xi, pstack, NULL) ; 20 | } 21 | for (i = 0 ; i < n ; i++) CS_MARK (Ap, i) ; /* restore A; unmark all nodes*/ 22 | top = n ; 23 | nb = n ; 24 | for (k = 0 ; k < n ; k++) /* dfs(A') to find strongly connnected comp */ 25 | { 26 | i = xi [k] ; /* get i in reverse order of finish times */ 27 | if (CS_MARKED (ATp, i)) continue ; /* skip node i if already ordered */ 28 | r [nb--] = top ; /* node i is the start of a component in p */ 29 | top = cs_dfs (i, AT, top, p, pstack, NULL) ; 30 | } 31 | r [nb] = 0 ; /* first block starts at zero; shift r up */ 32 | for (k = nb ; k <= n ; k++) r [k-nb] = r [k] ; 33 | D->nb = nb = n-nb ; /* nb = # of strongly connected components */ 34 | for (b = 0 ; b < nb ; b++) /* sort each block in natural order */ 35 | { 36 | for (k = r [b] ; k < r [b+1] ; k++) Blk [p [k]] = b ; 37 | } 38 | for (b = 0 ; b <= nb ; b++) rcopy [b] = r [b] ; 39 | for (i = 0 ; i < n ; i++) p [rcopy [Blk [i]]++] = i ; 40 | return (cs_ddone (D, AT, xi, 1)) ; 41 | } 42 | -------------------------------------------------------------------------------- /Source/cs_schol.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* ordering and symbolic analysis for a Cholesky factorization */ 3 | css *cs_schol (csi order, const cs *A) 4 | { 5 | csi n, *c, *post, *P ; 6 | cs *C ; 7 | css *S ; 8 | if (!CS_CSC (A)) return (NULL) ; /* check inputs */ 9 | n = A->n ; 10 | S = cs_calloc (1, sizeof (css)) ; /* allocate result S */ 11 | if (!S) return (NULL) ; /* out of memory */ 12 | P = cs_amd (order, A) ; /* P = amd(A+A'), or natural */ 13 | S->pinv = cs_pinv (P, n) ; /* find inverse permutation */ 14 | cs_free (P) ; 15 | if (order && !S->pinv) return (cs_sfree (S)) ; 16 | C = cs_symperm (A, S->pinv, 0) ; /* C = spones(triu(A(P,P))) */ 17 | S->parent = cs_etree (C, 0) ; /* find etree of C */ 18 | post = cs_post (S->parent, n) ; /* postorder the etree */ 19 | c = cs_counts (C, S->parent, post, 0) ; /* find column counts of chol(C) */ 20 | cs_free (post) ; 21 | cs_spfree (C) ; 22 | S->cp = cs_malloc (n+1, sizeof (csi)) ; /* allocate result S->cp */ 23 | S->unz = S->lnz = cs_cumsum (S->cp, c, n) ; /* find column pointers for L */ 24 | cs_free (c) ; 25 | return ((S->lnz >= 0) ? S : cs_sfree (S)) ; 26 | } 27 | -------------------------------------------------------------------------------- /Source/cs_spsolve.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* solve Gx=b(:,k), where G is either upper (lo=0) or lower (lo=1) triangular */ 3 | csi cs_spsolve (cs *G, const cs *B, csi k, csi *xi, double *x, const csi *pinv, 4 | csi lo) 5 | { 6 | csi j, J, p, q, px, top, n, *Gp, *Gi, *Bp, *Bi ; 7 | double *Gx, *Bx ; 8 | if (!CS_CSC (G) || !CS_CSC (B) || !xi || !x) return (-1) ; 9 | Gp = G->p ; Gi = G->i ; Gx = G->x ; n = G->n ; 10 | Bp = B->p ; Bi = B->i ; Bx = B->x ; 11 | top = cs_reach (G, B, k, xi, pinv) ; /* xi[top..n-1]=Reach(B(:,k)) */ 12 | for (p = top ; p < n ; p++) x [xi [p]] = 0 ; /* clear x */ 13 | for (p = Bp [k] ; p < Bp [k+1] ; p++) x [Bi [p]] = Bx [p] ; /* scatter B */ 14 | for (px = top ; px < n ; px++) 15 | { 16 | j = xi [px] ; /* x(j) is nonzero */ 17 | J = pinv ? (pinv [j]) : j ; /* j maps to col J of G */ 18 | if (J < 0) continue ; /* column J is empty */ 19 | x [j] /= Gx [lo ? (Gp [J]) : (Gp [J+1]-1)] ;/* x(j) /= G(j,j) */ 20 | p = lo ? (Gp [J]+1) : (Gp [J]) ; /* lo: L(j,j) 1st entry */ 21 | q = lo ? (Gp [J+1]) : (Gp [J+1]-1) ; /* up: U(j,j) last entry */ 22 | for ( ; p < q ; p++) 23 | { 24 | x [Gi [p]] -= Gx [p] * x [j] ; /* x(i) -= G(i,j) * x(j) */ 25 | } 26 | } 27 | return (top) ; /* return top of stack */ 28 | } 29 | -------------------------------------------------------------------------------- /Source/cs_sqr.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* compute nnz(V) = S->lnz, S->pinv, S->leftmost, S->m2 from A and S->parent */ 3 | static csi cs_vcount (const cs *A, css *S) 4 | { 5 | csi i, k, p, pa, n = A->n, m = A->m, *Ap = A->p, *Ai = A->i, *next, *head, 6 | *tail, *nque, *pinv, *leftmost, *w, *parent = S->parent ; 7 | S->pinv = pinv = cs_malloc (m+n, sizeof (csi)) ; /* allocate pinv, */ 8 | S->leftmost = leftmost = cs_malloc (m, sizeof (csi)) ; /* and leftmost */ 9 | w = cs_malloc (m+3*n, sizeof (csi)) ; /* get workspace */ 10 | if (!pinv || !w || !leftmost) 11 | { 12 | cs_free (w) ; /* pinv and leftmost freed later */ 13 | return (0) ; /* out of memory */ 14 | } 15 | next = w ; head = w + m ; tail = w + m + n ; nque = w + m + 2*n ; 16 | for (k = 0 ; k < n ; k++) head [k] = -1 ; /* queue k is empty */ 17 | for (k = 0 ; k < n ; k++) tail [k] = -1 ; 18 | for (k = 0 ; k < n ; k++) nque [k] = 0 ; 19 | for (i = 0 ; i < m ; i++) leftmost [i] = -1 ; 20 | for (k = n-1 ; k >= 0 ; k--) 21 | { 22 | for (p = Ap [k] ; p < Ap [k+1] ; p++) 23 | { 24 | leftmost [Ai [p]] = k ; /* leftmost[i] = min(find(A(i,:)))*/ 25 | } 26 | } 27 | for (i = m-1 ; i >= 0 ; i--) /* scan rows in reverse order */ 28 | { 29 | pinv [i] = -1 ; /* row i is not yet ordered */ 30 | k = leftmost [i] ; 31 | if (k == -1) continue ; /* row i is empty */ 32 | if (nque [k]++ == 0) tail [k] = i ; /* first row in queue k */ 33 | next [i] = head [k] ; /* put i at head of queue k */ 34 | head [k] = i ; 35 | } 36 | S->lnz = 0 ; 37 | S->m2 = m ; 38 | for (k = 0 ; k < n ; k++) /* find row permutation and nnz(V)*/ 39 | { 40 | i = head [k] ; /* remove row i from queue k */ 41 | S->lnz++ ; /* count V(k,k) as nonzero */ 42 | if (i < 0) i = S->m2++ ; /* add a fictitious row */ 43 | pinv [i] = k ; /* associate row i with V(:,k) */ 44 | if (--nque [k] <= 0) continue ; /* skip if V(k+1:m,k) is empty */ 45 | S->lnz += nque [k] ; /* nque [k] is nnz (V(k+1:m,k)) */ 46 | if ((pa = parent [k]) != -1) /* move all rows to parent of k */ 47 | { 48 | if (nque [pa] == 0) tail [pa] = tail [k] ; 49 | next [tail [k]] = head [pa] ; 50 | head [pa] = next [i] ; 51 | nque [pa] += nque [k] ; 52 | } 53 | } 54 | for (i = 0 ; i < m ; i++) if (pinv [i] < 0) pinv [i] = k++ ; 55 | cs_free (w) ; 56 | return (1) ; 57 | } 58 | 59 | /* symbolic ordering and analysis for QR or LU */ 60 | css *cs_sqr (csi order, const cs *A, csi qr) 61 | { 62 | csi n, k, ok = 1, *post ; 63 | css *S ; 64 | if (!CS_CSC (A)) return (NULL) ; /* check inputs */ 65 | n = A->n ; 66 | S = cs_calloc (1, sizeof (css)) ; /* allocate result S */ 67 | if (!S) return (NULL) ; /* out of memory */ 68 | S->q = cs_amd (order, A) ; /* fill-reducing ordering */ 69 | if (order && !S->q) return (cs_sfree (S)) ; 70 | if (qr) /* QR symbolic analysis */ 71 | { 72 | cs *C = order ? cs_permute (A, NULL, S->q, 0) : ((cs *) A) ; 73 | S->parent = cs_etree (C, 1) ; /* etree of C'*C, where C=A(:,q) */ 74 | post = cs_post (S->parent, n) ; 75 | S->cp = cs_counts (C, S->parent, post, 1) ; /* col counts chol(C'*C) */ 76 | cs_free (post) ; 77 | ok = C && S->parent && S->cp && cs_vcount (C, S) ; 78 | if (ok) for (S->unz = 0, k = 0 ; k < n ; k++) S->unz += S->cp [k] ; 79 | if (order) cs_spfree (C) ; 80 | } 81 | else 82 | { 83 | S->unz = 4*(A->p [n]) + n ; /* for LU factorization only, */ 84 | S->lnz = S->unz ; /* guess nnz(L) and nnz(U) */ 85 | } 86 | return (ok ? S : cs_sfree (S)) ; /* return result S */ 87 | } 88 | -------------------------------------------------------------------------------- /Source/cs_symperm.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* C = A(p,p) where A and C are symmetric the upper part stored; pinv not p */ 3 | cs *cs_symperm (const cs *A, const csi *pinv, csi values) 4 | { 5 | csi i, j, p, q, i2, j2, n, *Ap, *Ai, *Cp, *Ci, *w ; 6 | double *Cx, *Ax ; 7 | cs *C ; 8 | if (!CS_CSC (A)) return (NULL) ; /* check inputs */ 9 | n = A->n ; Ap = A->p ; Ai = A->i ; Ax = A->x ; 10 | C = cs_spalloc (n, n, Ap [n], values && (Ax != NULL), 0) ; /* alloc result*/ 11 | w = cs_calloc (n, sizeof (csi)) ; /* get workspace */ 12 | if (!C || !w) return (cs_done (C, w, NULL, 0)) ; /* out of memory */ 13 | Cp = C->p ; Ci = C->i ; Cx = C->x ; 14 | for (j = 0 ; j < n ; j++) /* count entries in each column of C */ 15 | { 16 | j2 = pinv ? pinv [j] : j ; /* column j of A is column j2 of C */ 17 | for (p = Ap [j] ; p < Ap [j+1] ; p++) 18 | { 19 | i = Ai [p] ; 20 | if (i > j) continue ; /* skip lower triangular part of A */ 21 | i2 = pinv ? pinv [i] : i ; /* row i of A is row i2 of C */ 22 | w [CS_MAX (i2, j2)]++ ; /* column count of C */ 23 | } 24 | } 25 | cs_cumsum (Cp, w, n) ; /* compute column pointers of C */ 26 | for (j = 0 ; j < n ; j++) 27 | { 28 | j2 = pinv ? pinv [j] : j ; /* column j of A is column j2 of C */ 29 | for (p = Ap [j] ; p < Ap [j+1] ; p++) 30 | { 31 | i = Ai [p] ; 32 | if (i > j) continue ; /* skip lower triangular part of A*/ 33 | i2 = pinv ? pinv [i] : i ; /* row i of A is row i2 of C */ 34 | Ci [q = w [CS_MAX (i2, j2)]++] = CS_MIN (i2, j2) ; 35 | if (Cx) Cx [q] = Ax [p] ; 36 | } 37 | } 38 | return (cs_done (C, w, NULL, 1)) ; /* success; free workspace, return C */ 39 | } 40 | -------------------------------------------------------------------------------- /Source/cs_tdfs.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* depth-first search and postorder of a tree rooted at node j */ 3 | csi cs_tdfs (csi j, csi k, csi *head, const csi *next, csi *post, csi *stack) 4 | { 5 | csi i, p, top = 0 ; 6 | if (!head || !next || !post || !stack) return (-1) ; /* check inputs */ 7 | stack [0] = j ; /* place j on the stack */ 8 | while (top >= 0) /* while (stack is not empty) */ 9 | { 10 | p = stack [top] ; /* p = top of stack */ 11 | i = head [p] ; /* i = youngest child of p */ 12 | if (i == -1) 13 | { 14 | top-- ; /* p has no unordered children left */ 15 | post [k++] = p ; /* node p is the kth postordered node */ 16 | } 17 | else 18 | { 19 | head [p] = next [i] ; /* remove i from children of p */ 20 | stack [++top] = i ; /* start dfs on child node i */ 21 | } 22 | } 23 | return (k) ; 24 | } 25 | -------------------------------------------------------------------------------- /Source/cs_transpose.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* C = A' */ 3 | cs *cs_transpose (const cs *A, csi values) 4 | { 5 | csi p, q, j, *Cp, *Ci, n, m, *Ap, *Ai, *w ; 6 | double *Cx, *Ax ; 7 | cs *C ; 8 | if (!CS_CSC (A)) return (NULL) ; /* check inputs */ 9 | m = A->m ; n = A->n ; Ap = A->p ; Ai = A->i ; Ax = A->x ; 10 | C = cs_spalloc (n, m, Ap [n], values && Ax, 0) ; /* allocate result */ 11 | w = cs_calloc (m, sizeof (csi)) ; /* get workspace */ 12 | if (!C || !w) return (cs_done (C, w, NULL, 0)) ; /* out of memory */ 13 | Cp = C->p ; Ci = C->i ; Cx = C->x ; 14 | for (p = 0 ; p < Ap [n] ; p++) w [Ai [p]]++ ; /* row counts */ 15 | cs_cumsum (Cp, w, m) ; /* row pointers */ 16 | for (j = 0 ; j < n ; j++) 17 | { 18 | for (p = Ap [j] ; p < Ap [j+1] ; p++) 19 | { 20 | Ci [q = w [Ai [p]]++] = j ; /* place A(i,j) as entry C(j,i) */ 21 | if (Cx) Cx [q] = Ax [p] ; 22 | } 23 | } 24 | return (cs_done (C, w, NULL, 1)) ; /* success; free w and return C */ 25 | } 26 | -------------------------------------------------------------------------------- /Source/cs_updown.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* sparse Cholesky update/downdate, L*L' + sigma*w*w' (sigma = +1 or -1) */ 3 | csi cs_updown (cs *L, csi sigma, const cs *C, const csi *parent) 4 | { 5 | csi n, p, f, j, *Lp, *Li, *Cp, *Ci ; 6 | double *Lx, *Cx, alpha, beta = 1, delta, gamma, w1, w2, *w, beta2 = 1 ; 7 | if (!CS_CSC (L) || !CS_CSC (C) || !parent) return (0) ; /* check inputs */ 8 | Lp = L->p ; Li = L->i ; Lx = L->x ; n = L->n ; 9 | Cp = C->p ; Ci = C->i ; Cx = C->x ; 10 | if ((p = Cp [0]) >= Cp [1]) return (1) ; /* return if C empty */ 11 | w = cs_malloc (n, sizeof (double)) ; /* get workspace */ 12 | if (!w) return (0) ; /* out of memory */ 13 | f = Ci [p] ; 14 | for ( ; p < Cp [1] ; p++) f = CS_MIN (f, Ci [p]) ; /* f = min (find (C)) */ 15 | for (j = f ; j != -1 ; j = parent [j]) w [j] = 0 ; /* clear workspace w */ 16 | for (p = Cp [0] ; p < Cp [1] ; p++) w [Ci [p]] = Cx [p] ; /* w = C */ 17 | for (j = f ; j != -1 ; j = parent [j]) /* walk path f up to root */ 18 | { 19 | p = Lp [j] ; 20 | alpha = w [j] / Lx [p] ; /* alpha = w(j) / L(j,j) */ 21 | beta2 = beta*beta + sigma*alpha*alpha ; 22 | if (beta2 <= 0) break ; /* not positive definite */ 23 | beta2 = sqrt (beta2) ; 24 | delta = (sigma > 0) ? (beta / beta2) : (beta2 / beta) ; 25 | gamma = sigma * alpha / (beta2 * beta) ; 26 | Lx [p] = delta * Lx [p] + ((sigma > 0) ? (gamma * w [j]) : 0) ; 27 | beta = beta2 ; 28 | for (p++ ; p < Lp [j+1] ; p++) 29 | { 30 | w1 = w [Li [p]] ; 31 | w [Li [p]] = w2 = w1 - alpha * Lx [p] ; 32 | Lx [p] = delta * Lx [p] + gamma * ((sigma > 0) ? w1 : w2) ; 33 | } 34 | } 35 | cs_free (w) ; 36 | return (beta2 > 0) ; 37 | } 38 | -------------------------------------------------------------------------------- /Source/cs_usolve.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* solve Ux=b where x and b are dense. x=b on input, solution on output. */ 3 | csi cs_usolve (const cs *U, double *x) 4 | { 5 | csi p, j, n, *Up, *Ui ; 6 | double *Ux ; 7 | if (!CS_CSC (U) || !x) return (0) ; /* check inputs */ 8 | n = U->n ; Up = U->p ; Ui = U->i ; Ux = U->x ; 9 | for (j = n-1 ; j >= 0 ; j--) 10 | { 11 | x [j] /= Ux [Up [j+1]-1] ; 12 | for (p = Up [j] ; p < Up [j+1]-1 ; p++) 13 | { 14 | x [Ui [p]] -= Ux [p] * x [j] ; 15 | } 16 | } 17 | return (1) ; 18 | } 19 | -------------------------------------------------------------------------------- /Source/cs_util.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* allocate a sparse matrix (triplet form or compressed-column form) */ 3 | cs *cs_spalloc (csi m, csi n, csi nzmax, csi values, csi triplet) 4 | { 5 | cs *A = cs_calloc (1, sizeof (cs)) ; /* allocate the cs struct */ 6 | if (!A) return (NULL) ; /* out of memory */ 7 | A->m = m ; /* define dimensions and nzmax */ 8 | A->n = n ; 9 | A->nzmax = nzmax = CS_MAX (nzmax, 1) ; 10 | A->nz = triplet ? 0 : -1 ; /* allocate triplet or comp.col */ 11 | A->p = cs_malloc (triplet ? nzmax : n+1, sizeof (csi)) ; 12 | A->i = cs_malloc (nzmax, sizeof (csi)) ; 13 | A->x = values ? cs_malloc (nzmax, sizeof (double)) : NULL ; 14 | return ((!A->p || !A->i || (values && !A->x)) ? cs_spfree (A) : A) ; 15 | } 16 | 17 | /* change the max # of entries sparse matrix */ 18 | csi cs_sprealloc (cs *A, csi nzmax) 19 | { 20 | csi ok, oki, okj = 1, okx = 1 ; 21 | if (!A) return (0) ; 22 | if (nzmax <= 0) nzmax = (CS_CSC (A)) ? (A->p [A->n]) : A->nz ; 23 | A->i = cs_realloc (A->i, nzmax, sizeof (csi), &oki) ; 24 | if (CS_TRIPLET (A)) A->p = cs_realloc (A->p, nzmax, sizeof (csi), &okj) ; 25 | if (A->x) A->x = cs_realloc (A->x, nzmax, sizeof (double), &okx) ; 26 | ok = (oki && okj && okx) ; 27 | if (ok) A->nzmax = nzmax ; 28 | return (ok) ; 29 | } 30 | 31 | /* free a sparse matrix */ 32 | cs *cs_spfree (cs *A) 33 | { 34 | if (!A) return (NULL) ; /* do nothing if A already NULL */ 35 | cs_free (A->p) ; 36 | cs_free (A->i) ; 37 | cs_free (A->x) ; 38 | return ((cs *) cs_free (A)) ; /* free the cs struct and return NULL */ 39 | } 40 | 41 | /* free a numeric factorization */ 42 | csn *cs_nfree (csn *N) 43 | { 44 | if (!N) return (NULL) ; /* do nothing if N already NULL */ 45 | cs_spfree (N->L) ; 46 | cs_spfree (N->U) ; 47 | cs_free (N->pinv) ; 48 | cs_free (N->B) ; 49 | return ((csn *) cs_free (N)) ; /* free the csn struct and return NULL */ 50 | } 51 | 52 | /* free a symbolic factorization */ 53 | css *cs_sfree (css *S) 54 | { 55 | if (!S) return (NULL) ; /* do nothing if S already NULL */ 56 | cs_free (S->pinv) ; 57 | cs_free (S->q) ; 58 | cs_free (S->parent) ; 59 | cs_free (S->cp) ; 60 | cs_free (S->leftmost) ; 61 | return ((css *) cs_free (S)) ; /* free the css struct and return NULL */ 62 | } 63 | 64 | /* allocate a cs_dmperm or cs_scc result */ 65 | csd *cs_dalloc (csi m, csi n) 66 | { 67 | csd *D ; 68 | D = cs_calloc (1, sizeof (csd)) ; 69 | if (!D) return (NULL) ; 70 | D->p = cs_malloc (m, sizeof (csi)) ; 71 | D->r = cs_malloc (m+6, sizeof (csi)) ; 72 | D->q = cs_malloc (n, sizeof (csi)) ; 73 | D->s = cs_malloc (n+6, sizeof (csi)) ; 74 | return ((!D->p || !D->r || !D->q || !D->s) ? cs_dfree (D) : D) ; 75 | } 76 | 77 | /* free a cs_dmperm or cs_scc result */ 78 | csd *cs_dfree (csd *D) 79 | { 80 | if (!D) return (NULL) ; /* do nothing if D already NULL */ 81 | cs_free (D->p) ; 82 | cs_free (D->q) ; 83 | cs_free (D->r) ; 84 | cs_free (D->s) ; 85 | return ((csd *) cs_free (D)) ; /* free the csd struct and return NULL */ 86 | } 87 | 88 | /* free workspace and return a sparse matrix result */ 89 | cs *cs_done (cs *C, void *w, void *x, csi ok) 90 | { 91 | cs_free (w) ; /* free workspace */ 92 | cs_free (x) ; 93 | return (ok ? C : cs_spfree (C)) ; /* return result if OK, else free it */ 94 | } 95 | 96 | /* free workspace and return csi array result */ 97 | csi *cs_idone (csi *p, cs *C, void *w, csi ok) 98 | { 99 | cs_spfree (C) ; /* free temporary matrix */ 100 | cs_free (w) ; /* free workspace */ 101 | return (ok ? p : (csi *) cs_free (p)) ; /* return result, or free it */ 102 | } 103 | 104 | /* free workspace and return a numeric factorization (Cholesky, LU, or QR) */ 105 | csn *cs_ndone (csn *N, cs *C, void *w, void *x, csi ok) 106 | { 107 | cs_spfree (C) ; /* free temporary matrix */ 108 | cs_free (w) ; /* free workspace */ 109 | cs_free (x) ; 110 | return (ok ? N : cs_nfree (N)) ; /* return result if OK, else free it */ 111 | } 112 | 113 | /* free workspace and return a csd result */ 114 | csd *cs_ddone (csd *D, cs *C, void *w, csi ok) 115 | { 116 | cs_spfree (C) ; /* free temporary matrix */ 117 | cs_free (w) ; /* free workspace */ 118 | return (ok ? D : cs_dfree (D)) ; /* return result if OK, else free it */ 119 | } 120 | -------------------------------------------------------------------------------- /Source/cs_utsolve.c: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | /* solve U'x=b where x and b are dense. x=b on input, solution on output. */ 3 | csi cs_utsolve (const cs *U, double *x) 4 | { 5 | csi p, j, n, *Up, *Ui ; 6 | double *Ux ; 7 | if (!CS_CSC (U) || !x) return (0) ; /* check inputs */ 8 | n = U->n ; Up = U->p ; Ui = U->i ; Ux = U->x ; 9 | for (j = 0 ; j < n ; j++) 10 | { 11 | for (p = Up [j] ; p < Up [j+1]-1 ; p++) 12 | { 13 | x [j] -= Ux [p] * x [Ui [p]] ; 14 | } 15 | x [j] /= Ux [Up [j+1]-1] ; 16 | } 17 | return (1) ; 18 | } 19 | -------------------------------------------------------------------------------- /Tcov/Makefile: -------------------------------------------------------------------------------- 1 | # To run with valgrind: 2 | V = 3 | # V = valgrind -q 4 | 5 | # Linux test coverage 6 | CC = gcc 7 | CFLAGS = -O -g -fprofile-arcs -ftest-coverage \ 8 | -Wall -W -Wshadow -Wmissing-prototypes -Wstrict-prototypes \ 9 | -Wredundant-decls -Wnested-externs -Wdisabled-optimization -ansi \ 10 | -Wno-unused-parameter -I../Include -I../Demo 11 | 12 | run: all run1 runbook run3 runtest 13 | ./covall 14 | 15 | all: cs_demo1 cs_demo2 cs_demo3 cstcov_test 16 | 17 | CS = cs_add.o cs_amd.o cs_chol.o cs_cholsol.o cs_counts.o cs_cumsum.o \ 18 | cs_droptol.o cs_dropzeros.o cs_dupl.o cs_entry.o \ 19 | cs_etree.o cs_fkeep.o cs_gaxpy.o cs_happly.o cs_house.o cs_ipvec.o \ 20 | cs_lsolve.o cs_ltsolve.o cs_lu.o cs_lusol.o cs_util.o cs_multiply.o \ 21 | cs_permute.o cs_pinv.o cs_post.o cs_pvec.o cs_qr.o cs_qrsol.o \ 22 | cs_scatter.o cs_schol.o cs_sqr.o cs_symperm.o cs_tdfs.o \ 23 | cs_transpose.o cs_compress.o cs_usolve.o cs_scc.o cs_maxtrans.o \ 24 | cs_dmperm.o cs_updown.o cs_print.o cs_norm.o cs_load.o cs_dfs.o \ 25 | cstcov_malloc_test.o cs_utsolve.o cs_reach.o cs_spsolve.o cs_ereach.o \ 26 | cs_leaf.o cs_randperm.o 27 | 28 | $(CS): ../Include/cs.h cstcov_malloc_test.h 29 | 30 | .PRECIOUS: cs_%.c cs_dem%.c 31 | 32 | cs_dem%.c: 33 | - ln -s ../Demo/$@ 34 | 35 | cs_%.c: 36 | - ln -s ../Source/$@ 37 | 38 | cs_demo1: $(CS) cs_demo1.c 39 | $(CC) $(CFLAGS) -o cs_demo1 cs_demo1.c $(CS) -lm 40 | 41 | cs_demo2: $(CS) cs_demo2.c cs_demo.c 42 | $(CC) $(CFLAGS) -o cs_demo2 cs_demo2.c cs_demo.c $(CS) -lm 43 | 44 | cs_demo3: $(CS) cs_demo3.c cs_demo.c 45 | $(CC) $(CFLAGS) -o cs_demo3 cs_demo3.c cs_demo.c $(CS) -lm 46 | 47 | cstcov_test: $(CS) cstcov_test.c cs_demo.c 48 | $(CC) $(CFLAGS) -o cstcov_test cstcov_test.c cs_demo.c $(CS) -lm 49 | 50 | # tiny tests 51 | run1: all 52 | - $(V) ./cs_demo1 < nil 53 | - $(V) ./cs_demo1 < zero 54 | - $(V) ./cs_demo2 < nil 55 | - $(V) ./cs_demo2 < zero 56 | - $(V) ./cs_demo3 < nil 57 | 58 | # test coverage for book: 59 | runbook: all 60 | - $(V) ./cs_demo1 < ../Matrix/t1 61 | - $(V) ./cs_demo2 < ../Matrix/bcsstk01 62 | - $(V) ./cs_demo2 < ../Matrix/fs_183_1 63 | - $(V) ./cs_demo2 < ../Matrix/mbeacxc 64 | - $(V) ./cs_demo2 < ../Matrix/west0067 65 | - $(V) ./cs_demo2 < ../Matrix/lp_afiro 66 | - $(V) ./cs_demo3 < ../Matrix/bcsstk16 67 | 68 | # other tests 69 | run3: all 70 | - $(V) ./cs_demo2 < ../Matrix/t1 71 | - $(V) ./cs_demo2 < ../Matrix/ash219 72 | - $(V) ./cs_demo3 < ../Matrix/bcsstk01 73 | - $(V) ./cs_demo2 < ../Matrix/bcsstk16 74 | - $(V) ./cs_demo2 < ../Matrix/ibm32a 75 | - $(V) ./cs_demo2 < ../Matrix/ibm32b 76 | 77 | # exhaustive memory tests 78 | runtest: all 79 | - $(V) ./cstcov_test nil > test_nil.out 80 | - $(V) ./cstcov_test zero > test_zero.out 81 | - $(V) ./cstcov_test ../Matrix/t1 > test_t1.out 82 | - $(V) ./cstcov_test ../Matrix/bcsstk01 > test_k1.out 83 | - $(V) ./cstcov_test ../Matrix/fs_183_1 > test_fs.out 84 | - $(V) ./cstcov_test ../Matrix/west0067 > test_we.out 85 | - $(V) ./cstcov_test ../Matrix/ash219 > test_ash.out 86 | - $(V) ./cstcov_test ../Matrix/lp_afiro > test_afiro.out 87 | 88 | readhb: readhb.f 89 | f77 -o readhb readhb.f 90 | 91 | readhb.f: 92 | - ln -s readhb.f 93 | 94 | clean: 95 | - $(RM) *.o *.bbg *.da *.gcov *.gcda *.gcno 96 | 97 | purge: distclean 98 | 99 | # remove everything for distribution, including all symbolic links 100 | distclean: clean 101 | - $(RM) cs_demo1 cs_demo2 readhb *.out *.a cs_demo3 cstcov_test cov.sort 102 | - $(RM) -r cs_*.c *.dSYM 103 | -------------------------------------------------------------------------------- /Tcov/README.txt: -------------------------------------------------------------------------------- 1 | CSparse/Tcov: comprehensive test coverage for CSparse. Requires Linux. 2 | Type "make" to compile, and then "make run" to run the tests. 3 | The test coverage is in cover.out. The test output is 4 | printed on stdout, except for cs_test (which prints its output in various 5 | *.out files). 6 | 7 | If the test is successful, the last line printed should be 8 | "statements not yet tested: 0", and all printed residuals should be small. 9 | 10 | Note that you will get warnings about unused parameters for some functions. 11 | These warnings can be safely ignored. They are parameters for functions that 12 | are passed to cs_fkeep, and all functions used in this manner must have the 13 | same calling sequence, even if some of the parameters are not used. 14 | 15 | Timothy A. Davis, http://www.suitesparse.com 16 | -------------------------------------------------------------------------------- /Tcov/cov.awk: -------------------------------------------------------------------------------- 1 | /cannot/ 2 | 3 | /function/ { f = $8 } 4 | 5 | /file/ { f = $8 } 6 | 7 | /lines/ { 8 | 9 | k = match ($1, "%") ; 10 | p = substr ($1, 1, k-1) ; 11 | 12 | if ((p+0) != 100) 13 | { 14 | printf "%8s %s\n", p, f 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /Tcov/covall: -------------------------------------------------------------------------------- 1 | #!/bin/csh 2 | ./gcovs cs*.c |& awk -f cov.awk | sort -n > cov.out 3 | sort -n cov.out > cov.sort 4 | ./covs > covs.out 5 | echo -n "statments not yet tested: " 6 | grep "#####" *gcov | wc -l 7 | ./cover *v > cover.out 8 | -------------------------------------------------------------------------------- /Tcov/covall.linux: -------------------------------------------------------------------------------- 1 | #!/bin/csh 2 | ./gcovs cs*.c |& awk -f cov.awk | sort -n > cov.out 3 | sort -n cov.out > cov.sort 4 | ./covs > covs.out 5 | echo -n "statments not yet tested: " 6 | grep "#####" *gcov | wc -l 7 | ./cover *v > cover.out 8 | -------------------------------------------------------------------------------- /Tcov/covall.sol: -------------------------------------------------------------------------------- 1 | #!/bin/csh 2 | tcov -x cm.profile cs*.c >& /dev/null 3 | echo -n "statments not yet tested: " 4 | ./covs > covs.out 5 | grep "#####" *tcov | wc -l 6 | -------------------------------------------------------------------------------- /Tcov/cover: -------------------------------------------------------------------------------- 1 | #!/bin/csh 2 | # usage: cover files 3 | echo '=================================================================' 4 | foreach file ($argv[1-]) 5 | echo $file 6 | echo '=================================================================' 7 | grep "#####" -A5 -B5 $file 8 | echo '=================================================================' 9 | end 10 | -------------------------------------------------------------------------------- /Tcov/covs: -------------------------------------------------------------------------------- 1 | #!/bin/csh 2 | echo '=================================================================' 3 | foreach file (*.?cov) 4 | echo $file 5 | grep "#####" $file 6 | echo '=================================================================' 7 | end 8 | -------------------------------------------------------------------------------- /Tcov/cstcov_malloc_test.c: -------------------------------------------------------------------------------- 1 | #include "cstcov_malloc_test.h" 2 | csi malloc_count = INT_MAX ; 3 | 4 | /* wrapper for malloc */ 5 | void *cs_malloc (csi n, size_t size) 6 | { 7 | if (--malloc_count < 0) return (NULL) ; /* pretend to fail */ 8 | return (malloc (CS_MAX (n,1) * size)) ; 9 | } 10 | 11 | /* wrapper for calloc */ 12 | void *cs_calloc (csi n, size_t size) 13 | { 14 | if (--malloc_count < 0) return (NULL) ; /* pretend to fail */ 15 | return (calloc (CS_MAX (n,1), size)) ; 16 | } 17 | 18 | /* wrapper for free */ 19 | void *cs_free (void *p) 20 | { 21 | if (p) free (p) ; /* free p if it is not already NULL */ 22 | return (NULL) ; /* return NULL to simplify the use of cs_free */ 23 | } 24 | 25 | /* wrapper for realloc */ 26 | void *cs_realloc (void *p, csi n, size_t size, csi *ok) 27 | { 28 | void *pnew ; 29 | *ok = 0 ; 30 | if (--malloc_count < 0) return (p) ; /* pretend to fail */ 31 | pnew = realloc (p, CS_MAX (n,1) * size) ; /* realloc the block */ 32 | *ok = (pnew != NULL) ; 33 | return ((*ok) ? pnew : p) ; /* return original p if failure */ 34 | } 35 | -------------------------------------------------------------------------------- /Tcov/cstcov_malloc_test.h: -------------------------------------------------------------------------------- 1 | #include "cs.h" 2 | #ifndef EXTERN 3 | #define EXTERN extern 4 | #endif 5 | EXTERN csi malloc_count ; 6 | -------------------------------------------------------------------------------- /Tcov/cstcov_test.c: -------------------------------------------------------------------------------- 1 | #include "cs_demo.h" 2 | /* cs_test: read a matrix and run cs_demo2 and cs_demo3, using malloc tests. */ 3 | 4 | #include "cstcov_malloc_test.h" 5 | 6 | int main (int argc, char **argv) 7 | { 8 | FILE *f ; 9 | problem *Prob ; 10 | int trials, ok, demo ; 11 | if (argc < 2) return (-1) ; 12 | printf ("cs_test, file: %s\n", argv [1]) ; 13 | for (demo = 2 ; demo <= 3 ; demo++) 14 | { 15 | printf ("demo: %g\n", (double) demo) ; 16 | for (trials = 0 ; trials < 4000 ; trials++) 17 | { 18 | malloc_count = trials ; 19 | f = fopen (argv [1], "r") ; 20 | if (!f) return (-1) ; 21 | Prob = get_problem (f, (demo == 2) ? 1e-14 : 0) ; 22 | fclose (f) ; 23 | if (Prob) ok = (demo == 2) ? demo2 (Prob) : demo3 (Prob) ; 24 | free_problem (Prob) ; 25 | if (malloc_count > 0) break ; 26 | } 27 | printf ("demo %g # trials: %g\n", (double) demo, (double) trials) ; 28 | } 29 | return (0) ; 30 | } 31 | -------------------------------------------------------------------------------- /Tcov/gcovs: -------------------------------------------------------------------------------- 1 | # usage: gcovs files 2 | echo '=================================================================' 3 | foreach file ($argv[1-]) 4 | gcov -f $file 5 | echo '=================================================================' 6 | end 7 | -------------------------------------------------------------------------------- /Tcov/nil: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ibayer/CSparse/c8d48ca8b1064ad38b220ea57e95249cf9f44e57/Tcov/nil -------------------------------------------------------------------------------- /Tcov/zero: -------------------------------------------------------------------------------- 1 | 0 0 0 2 | --------------------------------------------------------------------------------