00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "Ifpack_ConfigDefs.h"
00031 #include "Ifpack_IKLU_Utils.h"
00032
00033
00034
00035
00036
00037
00038 csr *csr_spalloc (int m, int n, int nzmax, int values, int triplet)
00039 {
00040 csr *A = (csr*)calloc (1, sizeof (csr)) ;
00041 if (!A) return (NULL) ;
00042 A->m = m ;
00043 A->n = n ;
00044 A->nzmax = nzmax = CS_MAX (nzmax, 1) ;
00045 A->nz = triplet ? 0 : -1 ;
00046 A->p = (int*)malloc (triplet ? CS_MAX(nzmax,1) * sizeof (int) : CS_MAX(m+1,1) * sizeof (int)) ;
00047 A->j = (int*)malloc (CS_MAX(nzmax,1) * sizeof (int)) ;
00048 A->x = values ? (double*)malloc (CS_MAX(nzmax,1) * sizeof (double)) : NULL ;
00049 return ((!A->p || !A->j || (values && !A->x)) ? csr_spfree (A) : A) ;
00050 }
00051
00052
00053 int csr_sprealloc (csr *A, int nzmax)
00054 {
00055 int ok, oki, okj = 1, okx = 1 ;
00056 if (!A) return (0) ;
00057 nzmax = (nzmax <= 0) ? (A->p [A->m]) : nzmax ;
00058 A->j = (int*)csr_realloc (A->j, nzmax, sizeof (int), &oki) ;
00059 if (CS_TRIPLET (A)) A->p = (int*)csr_realloc (A->p, nzmax, sizeof (int), &okj) ;
00060 if (A->x) A->x = (double*)csr_realloc (A->x, nzmax, sizeof (double), &okx) ;
00061 ok = (oki && okj && okx) ;
00062 if (ok) A->nzmax = nzmax ;
00063 return (ok) ;
00064 }
00065
00066
00067 void *csr_realloc (void *p, int n, size_t size, int *ok)
00068 {
00069 void *pnew ;
00070 pnew = realloc (p, CS_MAX (n,1) * size) ;
00071 *ok = (pnew != NULL) ;
00072 return ((*ok) ? pnew : p) ;
00073 }
00074
00075
00076 csr *csr_spfree (csr *A)
00077 {
00078 if (!A) return (NULL);
00079 if (A->p) free(A->p);
00080 if (A->j) free(A->j);
00081 if (A->x) free(A->x);
00082 if (A) free(A);
00083 return (NULL) ;
00084 }
00085
00086
00087 css *csr_sfree (css *S)
00088 {
00089 if (!S) return (NULL) ;
00090 if (S->pinv) free(S->pinv);
00091 if (S->q) free(S->q);
00092 if (S->parent) free(S->parent);
00093 if (S->cp) free(S->cp);
00094 if (S->leftmost) free(S->leftmost);
00095 if (S) free(S);
00096 return (NULL) ;
00097 }
00098
00099 csrn *csr_nfree (csrn *N)
00100 {
00101 if (!N) return (NULL) ;
00102 csr_spfree (N->L) ;
00103 csr_spfree (N->U) ;
00104 if (N->pinv) free(N->pinv);
00105 if (N->perm) free(N->perm);
00106 if (N->B) free(N->B);
00107 if (N) free(N);
00108 return (NULL) ;
00109 }
00110
00111
00112 csr *csr_done (csr *C, void *w, void *x, int ok)
00113 {
00114 if (w) free(w);
00115 if (x) free(x);
00116 return (ok ? C : csr_spfree (C)) ;
00117 }
00118
00119
00120 csrn *csr_ndone (csrn *N, csr *C, void *w, void *x, int ok)
00121 {
00122 csr_spfree (C) ;
00123 if (w) free(w);
00124 if (x) free(x);
00125 return (ok ? N : csr_nfree (N)) ;
00126 }
00127
00128
00129 int *csr_idone (int *p, csr *C, void *w, int ok)
00130 {
00131 csr_spfree (C) ;
00132 if (w) free(w);
00133
00134 if (ok)
00135 return p;
00136 else {
00137 if (p) free(p);
00138 return NULL;
00139 }
00140 }
00141
00142
00143
00144
00145
00146
00147 double csr_cumsum (int *p, int *c, int n)
00148 {
00149 int i, nz = 0 ;
00150 double nz2 = 0 ;
00151 if (!p || !c) return (-1) ;
00152 for (i = 0 ; i < n ; i++)
00153 {
00154 p [i] = nz ;
00155 nz += c [i] ;
00156 nz2 += c [i] ;
00157 c [i] = p [i] ;
00158 }
00159 p [n] = nz ;
00160 return (nz2) ;
00161 }
00162
00163
00164 int csr_scatter (const csr *B, int i, double alpha, int *w, double *x, int mark,
00165 csr *C, int nz)
00166 {
00167 int j, p, *Bp, *Bj, *Cj ;
00168 double *Bx ;
00169 if (!CS_CSC (B) || !w || !CS_CSC (C)) return (-1) ;
00170 Bp = B->p ; Bj = B->j ; Bx = B->x ; Cj = C->j ;
00171 for (p = Bp [i] ; p < Bp [i+1] ; p++)
00172 {
00173 j = Bj [p] ;
00174 if (w [j] < mark)
00175 {
00176 w [j] = mark ;
00177 Cj [nz++] = j ;
00178 if (x) x [j] = alpha * Bx [p] ;
00179 }
00180 else if (x) x [j] += alpha * Bx [p] ;
00181 }
00182 return (nz) ;
00183 }
00184
00185
00186 csr *csr_add (const csr *A, const csr *B, double alpha, double beta)
00187 {
00188 int p, j, nz = 0, anz, *Cp, *Cj, *Bp, m, n, bnz, *w, values ;
00189 double *x, *Bx, *Cx ;
00190 csr *C ;
00191 if (!CS_CSC (A) || !CS_CSC (B)) return (NULL) ;
00192 if ( (A->m != B->m) || (A->n != B->n) ) return (NULL);
00193 m = A->m ; anz = A->p [m] ;
00194 n = B->n ; Bp = B->p ; Bx = B->x ; bnz = Bp [m] ;
00195 w = (int*)calloc (CS_MAX(n,1), sizeof (int)) ;
00196 values = (A->x != NULL) && (Bx != NULL) ;
00197 x = values ? (double*)malloc (n * sizeof (double)) : NULL ;
00198 C = csr_spalloc (m, n, anz + bnz, values, 0) ;
00199 if (!C || !w || (values && !x)) return (csr_done (C, w, x, 0)) ;
00200 Cp = C->p ; Cj = C->j ; Cx = C->x ;
00201 for (j = 0 ; j < n ; j++)
00202 {
00203 Cp [j] = nz ;
00204 nz = csr_scatter (A, j, alpha, w, x, j+1, C, nz) ;
00205 nz = csr_scatter (B, j, beta, w, x, j+1, C, nz) ;
00206 if (values) for (p = Cp [j] ; p < nz ; p++) Cx [p] = x [Cj [p]] ;
00207 }
00208 Cp [m] = nz ;
00209 csr_sprealloc (C, 0) ;
00210 return (csr_done (C, w, x, 1)) ;
00211 }
00212
00213
00214 csr *csr_transpose (const csr *A, int values)
00215 {
00216 int p, q, i, *Cp, *Cj, n, m, *Ap, *Aj, *w ;
00217 double *Cx, *Ax ;
00218 csr *C ;
00219 if (!CS_CSC (A)) return (NULL) ;
00220 m = A->m ; n = A->n ; Ap = A->p ; Aj = A->j ; Ax = A->x ;
00221 C = csr_spalloc (n, m, Ap [m], values && Ax, 0) ;
00222 w = (int*)calloc (CS_MAX(n,1), sizeof (int)) ;
00223 if (!C || !w) return (csr_done (C, w, NULL, 0)) ;
00224 Cp = C->p ; Cj = C->j ; Cx = C->x ;
00225 for (p = 0 ; p < Ap [m] ; p++) w [Aj [p]]++ ;
00226 csr_cumsum (Cp, w, n) ;
00227 for (i = 0 ; i < m ; i++)
00228 {
00229 for (p = Ap [i] ; p < Ap [i+1] ; p++)
00230 {
00231 Cj [q = w [Aj [p]]++] = i ;
00232 if (Cx) Cx [q] = Ax [p] ;
00233 }
00234 }
00235 return (csr_done (C, w, NULL, 1)) ;
00236 }
00237
00238
00239 csr *csr_multiply (const csr *A, const csr *B)
00240 {
00241 int p, j, nz = 0, anz, *Cp, *Cj, *Ap, m, k, n, bnz, *w, values, *Aj;
00242 double *x, *Ax, *Cx ;
00243 csr *C ;
00244 if (!CS_CSC (A) || !CS_CSC (B)) return (NULL) ;
00245 k = A->n;
00246 if (k != B->m ) return(NULL);
00247 m = A->m ; anz = A->p [A->m] ;
00248 n = B->n ; Ap = A->p ; Aj = A->j ; Ax = A->x ; bnz = B->p [k] ;
00249 w = (int*)calloc (CS_MAX(n,1), sizeof (int)) ;
00250 values = (Ax != NULL) && (B->x != NULL) ;
00251 x = values ? (double*)malloc (n * sizeof (double)) : NULL ;
00252 C = csr_spalloc (m, n, anz + bnz, values, 0) ;
00253 if (!C || !w || (values && !x)) return (csr_done (C, w, x, 0)) ;
00254 Cp = C->p ;
00255 for (j = 0 ; j < m ; j++)
00256 {
00257 if (nz + n > C->nzmax && !csr_sprealloc (C, 2*(C->nzmax)+m))
00258 {
00259 return (csr_done (C, w, x, 0)) ;
00260 }
00261 Cj = C->j ; Cx = C->x ;
00262 Cp [j] = nz ;
00263 for (p = Ap [j] ; p < Ap [j+1] ; p++)
00264 {
00265 nz = csr_scatter (B, Aj [p], Ax ? Ax [p] : 1, w, x, j+1, C, nz) ;
00266 }
00267 if (values) for (p = Cp [j] ; p < nz ; p++) Cx [p] = x [Cj [p]] ;
00268 }
00269 Cp [m] = nz ;
00270 csr_sprealloc (C, 0) ;
00271 return (csr_done (C, w, x, 1)) ;
00272 }
00273
00274
00275
00276
00277
00278
00279
00280 css *csr_sqr (int order, const csr *A )
00281 {
00282 int n, ok = 1;
00283 css *S ;
00284 if (!CS_CSC (A)) return (NULL) ;
00285 n = A->n ;
00286 S = (css*)calloc(1, sizeof (css)) ;
00287 if (!S) return (NULL) ;
00288 S->q = csr_amd (order, A) ;
00289 if (!S->q)
00290 {
00291 printf(" csr_sqr error no permutation\n");
00292 }
00293 if (order && !S->q) return (csr_sfree (S)) ;
00294
00295
00296 S->unz = (double) CS_MIN(4*(A->p [n]) + n, n * n );
00297 S->lnz = S->unz ;
00298 return (ok ? S : csr_sfree (S)) ;
00299 }
00300
00301
00302
00303
00304 int csr_reach (csr *G, const csr *B, int k, int *xi, const int *pinv)
00305 {
00306 int p, m, top, *Bp, *Bj, *Gp ;
00307 if (!CS_CSC (G) || !CS_CSC (B) || !xi) return (-1) ;
00308 m = G->m ; Bp = B->p ; Bj = B->j ; Gp = G->p ;
00309 top = m ;
00310 for (p = Bp [k] ; p < Bp [k+1] ; p++)
00311 {
00312 if (!CS_MARKED (Gp, Bj [p]))
00313 {
00314 top = csr_dfs (Bj [p], G, top, xi, xi+m, pinv) ;
00315 }
00316 }
00317 for (p = top ; p < m ; p++) CS_MARK (Gp, xi [p]) ;
00318 return (top) ;
00319 }
00320
00321
00322 int csr_dfs (int j, csr *G, int top, int *xi, int *pstack, const int *pinv)
00323 {
00324 int i, p, p2, done, jnew, head = 0, *Gp, *Gj ;
00325 if (!CS_CSC (G) || !xi || !pstack) return (-1) ;
00326 Gp = G->p ; Gj = G->j ;
00327 xi [0] = j ;
00328 while (head >= 0)
00329 {
00330 j = xi [head] ;
00331 jnew = pinv ? (pinv [j]) : j ;
00332 if (!CS_MARKED (Gp, j))
00333 {
00334 CS_MARK (Gp, j) ;
00335 pstack [head] = (jnew < 0) ? 0 : CS_UNFLIP (Gp [jnew]) ;
00336 }
00337 done = 1 ;
00338 p2 = (jnew < 0) ? 0 : CS_UNFLIP (Gp [jnew+1]) ;
00339 for (p = pstack [head] ; p < p2 ; p++)
00340 {
00341 i = Gj [p] ;
00342 if (CS_MARKED (Gp, i)) continue ;
00343 pstack [head] = p ;
00344 xi [++head] = i ;
00345 done = 0 ;
00346 break ;
00347 }
00348 if (done)
00349 {
00350 head-- ;
00351 xi [--top] = j ;
00352 }
00353 }
00354 return (top) ;
00355 }
00356
00357
00358 int csr_tdfs (int j, int k, int *head, const int *next, int *post, int *stack)
00359 {
00360 int i, p, top = 0 ;
00361 if (!head || !next || !post || !stack) return (-1) ;
00362 stack [0] = j ;
00363 while (top >= 0)
00364 {
00365 p = stack [top] ;
00366 i = head [p] ;
00367 if (i == -1)
00368 {
00369 top-- ;
00370 post [k++] = p ;
00371 }
00372 else
00373 {
00374 head [p] = next [i] ;
00375 stack [++top] = i ;
00376 }
00377 }
00378 return (k) ;
00379 }
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390 csrn *csr_lu (const csr *A, const css *S, double tol)
00391 {
00392 csr *L, *U ;
00393 csrn *N ;
00394 double pivot, *Lx, *Ux, *x, a, t;
00395 int *Lp, *Lj, *Up, *Uj, *pinv, *xi, *q, n, ipiv, k, top, p, i, row, lnz, unz;
00396 int debug = 0;
00397
00398 if (!CS_CSC (A) ) printf(" error csrlu: A not csc\n");
00399 if (!CS_CSC (A) || !S) return (NULL) ;
00400 n = A->n ;
00401 if (n != A->m) return (NULL) ;
00402 q = S->q ; lnz = (int)S->lnz ; unz = (int)S->unz ;
00403 x = (double*)malloc(n * sizeof (double)) ;
00404 xi = (int*)malloc (2*n * sizeof (int)) ;
00405 N = (csrn*)calloc (1, sizeof (csrn)) ;
00406 if (!(A) ) printf(" error csrlu: allocation of N failed\n");
00407 if (!x || !xi || !N) return (csr_ndone (N, NULL, xi, x, 0)) ;
00408
00409 N->L = L = csr_spalloc (n, n, lnz, 1, 0) ;
00410 N->U = U = csr_spalloc (n, n, unz, 1, 0) ;
00411 N->pinv = pinv = (int*)malloc (n * sizeof (int)) ;
00412 N->perm = (int*)malloc (n * sizeof (int)) ;
00413 if (!L || !U || !pinv) return (csr_ndone (N, NULL, xi, x, 0)) ;
00414 Lp = L->p ; Up = U->p ;
00415 for (i = 0 ; i < n ; i++) x [i] = 0 ;
00416 for (i = 0 ; i < n ; i++) pinv [i] = -1 ;
00417 for (k = 1 ; k <= n ; k++) Up [k] = 0 ;
00418 for (k = 1 ; k <= n ; k++) Lp [k] = 0 ;
00419 lnz = unz = 0 ;
00420 if( debug )
00421 {
00422 printf ("A:\n") ; csr_print (A, 0) ;
00423 }
00424 for (k = 0 ; k < n ; k++)
00425 {
00426
00427 Lp [k] = lnz ;
00428 Up [k] = unz ;
00429 if ((lnz + n > L->nzmax && !csr_sprealloc (L, 2*L->nzmax + n)) ||
00430 (unz + n > U->nzmax && !csr_sprealloc (U, 2*U->nzmax + n)))
00431 {
00432 return (csr_ndone (N, NULL, xi, x, 0)) ;
00433 }
00434 Lj = L->j ; Lx = L->x ; Uj = U->j ; Ux = U->x ;
00435 row = q ? (q [k]) : k ;
00436 if( debug > 1 )
00437 {
00438 printf("--------------------------------\n");
00439 printf(" %d spsolve row=%d \n",k, row);
00440 printf(" pinv = %d %d %d %d \n", pinv[0], pinv[1], pinv[2], pinv[3]);
00441 }
00442 top = csr_spsolve (U, A, row, xi, x, pinv, 1) ;
00443 if( debug > 1 ) printf("top=%d x = %g %g %g %g \n", top,x[0],x[1],x[2],x[3]);
00444
00445 ipiv = -1 ;
00446 a = -1 ;
00447 for (p = top ; p < n ; p++)
00448 {
00449 i = xi [p] ;
00450 if (pinv [i] < 0)
00451 {
00452 if ((t = fabs (x [i])) > a)
00453 {
00454 a = t ;
00455 ipiv = i ;
00456 }
00457 }
00458 else
00459 {
00460 Lj [lnz] = pinv [i] ;
00461 Lx [lnz++] = x [i] ;
00462 }
00463 }
00464 if (ipiv == -1 || a <= 0) return (csr_ndone (N, NULL, xi, x, 0)) ;
00465 if (pinv [row] < 0 && fabs (x [row]) >= a*tol) ipiv = row;
00466 pivot = x [ipiv] ;
00467 Lj [lnz] = k ;
00468 Lx [lnz++] = pivot ;
00469 if( debug > 1 ) { printf ("L:") ; csr_print (L, 0) ; }
00470
00471
00472 pinv [ipiv] = k ;
00473 Uj [unz] = ipiv ;
00474 Ux [unz++] = 1 ;
00475 for (p = top ; p < n ; p++)
00476 {
00477 i = xi [p] ;
00478 if (pinv [i] < 0)
00479 {
00480 Uj [unz] = i ;
00481 Ux [unz++] = x [i] / pivot ;
00482 }
00483 x [i] = 0 ;
00484 }
00485 if( debug > 1 )
00486 {
00487 printf ("U:") ; csr_print (U, 0) ;
00488 printf("------------------------------------\n");
00489 }
00490 }
00491
00492 Lp [n] = lnz ;
00493 if( debug ) { printf ("L:") ; csr_print (L, 0) ; }
00494 Up [n] = unz ;
00495 Uj = U->j ;
00496 for (p = 0 ; p < unz ; p++) Uj [p] = pinv [Uj [p]] ;
00497
00498 csr_sprealloc (L, 0) ;
00499 csr_sprealloc (U, 0) ;
00500 if( debug ) { printf ("U:") ; csr_print (U, 0) ; }
00501 return (csr_ndone (N, NULL, xi, x, 1)) ;
00502 }
00503
00504
00505
00506
00507
00508
00509 int csr_spsolve (csr *G, const csr *B, int k, int *xi, double *x, const int *pinv, int up)
00510 {
00511 int i, I, p, q, px, top, n, *Gp, *Gj, *Bp, *Bj ;
00512 int debug = 0;
00513 double *Gx, *Bx ;
00514 if (!CS_CSC (G) || !CS_CSC (B) || !xi || !x) return (-1) ;
00515 Gp = G->p ; Gj = G->j ; Gx = G->x ; n = G->n ;
00516 Bp = B->p ; Bj = B->j ; Bx = B->x ;
00517 top = csr_reach (G, B, k, xi, pinv) ;
00518 for (p = top ; p < n ; p++) x [xi [p]] = 0 ;
00519 for (p = Bp [k] ; p < Bp [k+1] ; p++) x [Bj [p]] = Bx [p] ;
00520 if( debug )
00521 printf("solve k=%d x= %g %g %g %g \n", k, x[0], x[1], x[2], x[3]);
00522 if( debug )
00523 printf("top=%d xi= %d %d %d %d \n", top , xi[0], xi[1], xi[2], xi[3]);
00524 for (px = top ; px < n ; px++)
00525 {
00526 i = xi [px] ;
00527 I = pinv ? (pinv [i]) : i ;
00528 if (I < 0) continue ;
00529
00530 x [i] /= Gx [up ? (Gp [I]) : (Gp [I+1]-1)] ;
00531 p = up ? (Gp [I]+1) : (Gp [I]) ;
00532 q = up ? (Gp [I+1]) : (Gp [I+1]-1) ;
00533 for ( ; p < q ; p++)
00534 {
00535 if( debug )
00536 printf("%d %d solve %d %g %g \n", px, i ,p, Gx [p] , x [Gj [p]] );
00537
00538 x [Gj[p]] -= Gx [p] * x [i] ;
00539 }
00540 if( debug )
00541 printf(" x= %g %g %g %g \n", x[0], x[1], x[2], x[3]);
00542 }
00543 return (top) ;
00544 }
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555 static int csr_wclear (int mark, int lemax, int *w, int n)
00556 {
00557 int k ;
00558 if (mark < 2 || (mark + lemax < 0))
00559 {
00560 for (k = 0 ; k < n ; k++) if (w [k] != 0) w [k] = 1 ;
00561 mark = 2 ;
00562 }
00563 return (mark) ;
00564 }
00565
00566
00567 static int csr_diag (int i, int j, double aij, void *other) { return (i != j) ; }
00568
00569
00570 int *csr_amd (int order, const csr *A)
00571 {
00572 csr *C, *A2, *AT ;
00573 int *Cp, *Cj, *last, *W, *len, *nv, *next, *P, *head, *elen, *degree, *w,
00574 *hhead, *ATp, *ATj, d, dk, dext, lemax = 0, e, elenk, eln, i, j, k, k1,
00575 k2, k3, jlast, ln, dense, nzmax, mindeg = 0, nvi, nvj, nvk, mark, wnvi,
00576 ok, cnz, nel = 0, p, p1, p2, p3, p4, pj, pk, pk1, pk2, pn, q, n, m, t ;
00577 unsigned int h ;
00578
00579 if (!CS_CSC (A) || order <= 0 || order > 3) return (NULL) ;
00580 AT = csr_transpose (A, 0) ;
00581 if (!AT) return (NULL) ;
00582 m = A->m ; n = A->n ;
00583 if ( n != m) return(NULL);
00584 dense = (int)CS_MAX (16, 10 * sqrt ((double) n)) ;
00585 dense = CS_MIN (n-2, dense) ;
00586 if (order == 1 && n == m)
00587 {
00588 C = csr_add (A, AT, 0, 0) ;
00589 }
00590 else if (order == 2)
00591 {
00592 ATp = AT->p ;
00593 ATj = AT->j ;
00594 for (p2 = 0, j = 0 ; j < m ; j++)
00595 {
00596 p = ATp [j] ;
00597 ATp [j] = p2 ;
00598 if (ATp [j+1] - p > dense) continue ;
00599 for ( ; p < ATp [j+1] ; p++) ATj [p2++] = ATj [p] ;
00600 }
00601 ATp [m] = p2 ;
00602 A2 = csr_transpose (AT, 0) ;
00603 C = A2 ? csr_multiply (AT, A2) : NULL ;
00604 csr_spfree (A2) ;
00605 }
00606 else
00607 {
00608 C = csr_multiply (AT, A) ;
00609 }
00610 csr_spfree (AT) ;
00611 if (!C) return (NULL) ;
00612 csr_fkeep (C, &csr_diag, NULL) ;
00613 Cp = C->p ;
00614 cnz = Cp [n] ;
00615 P = (int*)malloc (CS_MAX(n+1,1) * sizeof (int)) ;
00616 W = (int*)malloc (CS_MAX(8*(n+1),1) * sizeof (int)) ;
00617 t = cnz + cnz/5 + 2*n ;
00618 if (!P || !W || !csr_sprealloc (C, t)) return (csr_idone (P, C, W, 0)) ;
00619 len = W ; nv = W + (n+1) ; next = W + 2*(n+1) ;
00620 head = W + 3*(n+1) ; elen = W + 4*(n+1) ; degree = W + 5*(n+1) ;
00621 w = W + 6*(n+1) ; hhead = W + 7*(n+1) ;
00622 last = P ;
00623
00624 for (k = 0 ; k < n ; k++) len [k] = Cp [k+1] - Cp [k] ;
00625 len [n] = 0 ;
00626 nzmax = C->nzmax ;
00627 Cj = C->j ;
00628 for (i = 0 ; i <= n ; i++)
00629 {
00630 head [i] = -1 ;
00631 last [i] = -1 ;
00632 next [i] = -1 ;
00633 hhead [i] = -1 ;
00634 nv [i] = 1 ;
00635 w [i] = 1 ;
00636 elen [i] = 0 ;
00637 degree [i] = len [i] ;
00638 }
00639 mark = csr_wclear (0, 0, w, n) ;
00640 elen [n] = -2 ;
00641 Cp [n] = -1 ;
00642 w [n] = 0 ;
00643
00644 for (i = 0 ; i < n ; i++)
00645 {
00646 d = degree [i] ;
00647 if (d == 0)
00648 {
00649 elen [i] = -2 ;
00650 nel++ ;
00651 Cp [i] = -1 ;
00652 w [i] = 0 ;
00653 }
00654 else if (d > dense)
00655 {
00656 nv [i] = 0 ;
00657 elen [i] = -1 ;
00658 nel++ ;
00659 Cp [i] = CS_FLIP (n) ;
00660 nv [n]++ ;
00661 }
00662 else
00663 {
00664 if (head [d] != -1) last [head [d]] = i ;
00665 next [i] = head [d] ;
00666 head [d] = i ;
00667 }
00668 }
00669 while (nel < n)
00670 {
00671
00672 for (k = -1 ; mindeg < n && (k = head [mindeg]) == -1 ; mindeg++) ;
00673 if (next [k] != -1) last [next [k]] = -1 ;
00674 head [mindeg] = next [k] ;
00675 elenk = elen [k] ;
00676 nvk = nv [k] ;
00677 nel += nvk ;
00678
00679 if (elenk > 0 && cnz + mindeg >= nzmax)
00680 {
00681 for (j = 0 ; j < n ; j++)
00682 {
00683 if ((p = Cp [j]) >= 0)
00684 {
00685 Cp [j] = Cj [p] ;
00686 Cj [p] = CS_FLIP (j) ;
00687 }
00688 }
00689 for (q = 0, p = 0 ; p < cnz ; )
00690 {
00691 if ((j = CS_FLIP (Cj [p++])) >= 0)
00692 {
00693 Cj [q] = Cp [j] ;
00694 Cp [j] = q++ ;
00695 for (k3 = 0 ; k3 < len [j]-1 ; k3++) Cj [q++] = Cj [p++] ;
00696 }
00697 }
00698 cnz = q ;
00699 }
00700
00701 dk = 0 ;
00702 nv [k] = -nvk ;
00703 p = Cp [k] ;
00704 pk1 = (elenk == 0) ? p : cnz ;
00705 pk2 = pk1 ;
00706 for (k1 = 1 ; k1 <= elenk + 1 ; k1++)
00707 {
00708 if (k1 > elenk)
00709 {
00710 e = k ;
00711 pj = p ;
00712 ln = len [k] - elenk ;
00713 }
00714 else
00715 {
00716 e = Cj [p++] ;
00717 pj = Cp [e] ;
00718 ln = len [e] ;
00719 }
00720 for (k2 = 1 ; k2 <= ln ; k2++)
00721 {
00722 i = Cj [pj++] ;
00723 if ((nvi = nv [i]) <= 0) continue ;
00724 dk += nvi ;
00725 nv [i] = -nvi ;
00726 Cj [pk2++] = i ;
00727 if (next [i] != -1) last [next [i]] = last [i] ;
00728 if (last [i] != -1)
00729 {
00730 next [last [i]] = next [i] ;
00731 }
00732 else
00733 {
00734 head [degree [i]] = next [i] ;
00735 }
00736 }
00737 if (e != k)
00738 {
00739 Cp [e] = CS_FLIP (k) ;
00740 w [e] = 0 ;
00741 }
00742 }
00743 if (elenk != 0) cnz = pk2 ;
00744 degree [k] = dk ;
00745 Cp [k] = pk1 ;
00746 len [k] = pk2 - pk1 ;
00747 elen [k] = -2 ;
00748
00749 mark = csr_wclear (mark, lemax, w, n) ;
00750 for (pk = pk1 ; pk < pk2 ; pk++)
00751 {
00752 i = Cj [pk] ;
00753 if ((eln = elen [i]) <= 0) continue ;
00754 nvi = -nv [i] ;
00755 wnvi = mark - nvi ;
00756 for (p = Cp [i] ; p <= Cp [i] + eln - 1 ; p++)
00757 {
00758 e = Cj [p] ;
00759 if (w [e] >= mark)
00760 {
00761 w [e] -= nvi ;
00762 }
00763 else if (w [e] != 0)
00764 {
00765 w [e] = degree [e] + wnvi ;
00766 }
00767 }
00768 }
00769
00770 for (pk = pk1 ; pk < pk2 ; pk++)
00771 {
00772 i = Cj [pk] ;
00773 p1 = Cp [i] ;
00774 p2 = p1 + elen [i] - 1 ;
00775 pn = p1 ;
00776 for (h = 0, d = 0, p = p1 ; p <= p2 ; p++)
00777 {
00778 e = Cj [p] ;
00779 if (w [e] != 0)
00780 {
00781 dext = w [e] - mark ;
00782 if (dext > 0)
00783 {
00784 d += dext ;
00785 Cj [pn++] = e ;
00786 h += e ;
00787 }
00788 else
00789 {
00790 Cp [e] = CS_FLIP (k) ;
00791 w [e] = 0 ;
00792 }
00793 }
00794 }
00795 elen [i] = pn - p1 + 1 ;
00796 p3 = pn ;
00797 p4 = p1 + len [i] ;
00798 for (p = p2 + 1 ; p < p4 ; p++)
00799 {
00800 j = Cj [p] ;
00801 if ((nvj = nv [j]) <= 0) continue ;
00802 d += nvj ;
00803 Cj [pn++] = j ;
00804 h += j ;
00805 }
00806 if (d == 0)
00807 {
00808 Cp [i] = CS_FLIP (k) ;
00809 nvi = -nv [i] ;
00810 dk -= nvi ;
00811 nvk += nvi ;
00812 nel += nvi ;
00813 nv [i] = 0 ;
00814 elen [i] = -1 ;
00815 }
00816 else
00817 {
00818 degree [i] = CS_MIN (degree [i], d) ;
00819 Cj [pn] = Cj [p3] ;
00820 Cj [p3] = Cj [p1] ;
00821 Cj [p1] = k ;
00822
00823 len [i] = pn - p1 + 1 ;
00824 h %= n ;
00825 next [i] = hhead [h] ;
00826 hhead [h] = i ;
00827 last [i] = h ;
00828 }
00829 }
00830 degree [k] = dk ;
00831 lemax = CS_MAX (lemax, dk) ;
00832 mark = csr_wclear (mark+lemax, lemax, w, n) ;
00833
00834 for (pk = pk1 ; pk < pk2 ; pk++)
00835 {
00836 i = Cj [pk] ;
00837 if (nv [i] >= 0) continue ;
00838 h = last [i] ;
00839 i = hhead [h] ;
00840 hhead [h] = -1 ;
00841 for ( ; i != -1 && next [i] != -1 ; i = next [i], mark++)
00842 {
00843 ln = len [i] ;
00844 eln = elen [i] ;
00845 for (p = Cp [i]+1 ; p <= Cp [i] + ln-1 ; p++) w [Cj [p]] = mark;
00846 jlast = i ;
00847 for (j = next [i] ; j != -1 ; )
00848 {
00849 ok = (len [j] == ln) && (elen [j] == eln) ;
00850 for (p = Cp [j] + 1 ; ok && p <= Cp [j] + ln - 1 ; p++)
00851 {
00852 if (w [Cj [p]] != mark) ok = 0 ;
00853 }
00854 if (ok)
00855 {
00856 Cp [j] = CS_FLIP (i) ;
00857 nv [i] += nv [j] ;
00858 nv [j] = 0 ;
00859 elen [j] = -1 ;
00860 j = next [j] ;
00861 next [jlast] = j ;
00862 }
00863 else
00864 {
00865 jlast = j ;
00866 j = next [j] ;
00867 }
00868 }
00869 }
00870 }
00871
00872 for (p = pk1, pk = pk1 ; pk < pk2 ; pk++)
00873 {
00874 i = Cj [pk] ;
00875 if ((nvi = -nv [i]) <= 0) continue ;
00876 nv [i] = nvi ;
00877 d = degree [i] + dk - nvi ;
00878 d = CS_MIN (d, n - nel - nvi) ;
00879 if (head [d] != -1) last [head [d]] = i ;
00880 next [i] = head [d] ;
00881 last [i] = -1 ;
00882 head [d] = i ;
00883 mindeg = CS_MIN (mindeg, d) ;
00884 degree [i] = d ;
00885 Cj [p++] = i ;
00886 }
00887 nv [k] = nvk ;
00888 if ((len [k] = p-pk1) == 0)
00889 {
00890 Cp [k] = -1 ;
00891 w [k] = 0 ;
00892 }
00893 if (elenk != 0) cnz = p ;
00894 }
00895
00896 for (i = 0 ; i < n ; i++) Cp [i] = CS_FLIP (Cp [i]) ;
00897 for (j = 0 ; j <= n ; j++) head [j] = -1 ;
00898 for (j = n ; j >= 0 ; j--)
00899 {
00900 if (nv [j] > 0) continue ;
00901 next [j] = head [Cp [j]] ;
00902 head [Cp [j]] = j ;
00903 }
00904 for (e = n ; e >= 0 ; e--)
00905 {
00906 if (nv [e] <= 0) continue ;
00907 if (Cp [e] != -1)
00908 {
00909 next [e] = head [Cp [e]] ;
00910 head [Cp [e]] = e ;
00911 }
00912 }
00913 for (k = 0, i = 0 ; i <= n ; i++)
00914 {
00915 if (Cp [i] == -1) k = csr_tdfs (i, k, head, next, P, w) ;
00916 }
00917 return (csr_idone (P, C, W, 1)) ;
00918 }
00919
00920
00921
00922
00923
00924
00925
00926 int csr_print (const csr *A, int brief)
00927 {
00928 int p, j, m, n, nzmax, nz, nnz, *Ap, *Aj ;
00929 double *Ax ;
00930 if (!A) { printf ("(null)\n") ; return (0) ; }
00931 m = A->m ; n = A->n ; Ap = A->p ; Aj = A->j ; Ax = A->x ;
00932 nzmax = A->nzmax ; nz = A->nz ; nnz = Ap [m];
00933 if (nz < 0)
00934 {
00935 if( nnz == 0)
00936 {
00937 while ((Ap[m] == 0) && (m > 0))
00938 {
00939 --m;
00940 }
00941 nnz = Ap [m];
00942 }
00943 if( nnz > 0)
00944 {
00945 printf ("%d-by-%d, nzmax: %d nnz: %d, mxnorm: %g\n", m, n, nzmax,
00946 Ap [m], csr_norm (A)) ;
00947 for (j = 0 ; j < m ; j++)
00948 {
00949 printf (" row %d : locations %d to %d\n", j, Ap [j], Ap [j+1]-1);
00950 for (p = Ap [j] ; p < Ap [j+1] ; p++)
00951 {
00952 printf (" %d : %g\n", Aj [p], Ax ? Ax [p] : 1) ;
00953 if (brief && p > 20) { printf (" ...\n") ; return (1) ; }
00954 }
00955 }
00956 }else{
00957 printf ("%d-by-%d, zero matrix with nzmax: %d\n", m, n, nzmax);
00958 }
00959 }
00960 else
00961 {
00962 printf ("triplet: %d-by-%d, nzmax: %d nnz: %d\n", m, n, nzmax, nz) ;
00963 for (p = 0 ; p < nz ; p++)
00964 {
00965 printf (" %d %d : %g\n", Aj [p], Ap [p], Ax ? Ax [p] : 1) ;
00966 if (brief && p > 20) { printf (" ...\n") ; return (1) ; }
00967 }
00968 }
00969 return (1) ;
00970 }
00971
00972
00973 double csr_norm (const csr *A)
00974 {
00975 int p, j, m, *Ap ;
00976 double *Ax, norm = 0, s ;
00977 if (!CS_CSC (A) || !A->x) return (-1) ;
00978 m = A->m ; Ap = A->p ; Ax = A->x ;
00979 for (j = 0 ; j < m ; j++)
00980 {
00981 for (s = 0, p = Ap [j] ; p < Ap [j+1] ; p++) s += fabs (Ax [p]);
00982 norm = CS_MAX (norm, s) ;
00983 }
00984 return (norm) ;
00985 }
00986
00987
00988 int csr_fkeep (csr *A, int (*fkeep) (int, int, double, void *), void *other)
00989 {
00990 int j, p, nz = 0, m, *Ap, *Aj ;
00991 double *Ax ;
00992 if (!CS_CSC (A) || !fkeep) return (-1) ;
00993 m = A->m ; Ap = A->p ; Aj = A->j ; Ax = A->x ;
00994 for (j = 0 ; j < m ; j++)
00995 {
00996 p = Ap [j] ;
00997 Ap [j] = nz ;
00998 for ( ; p < Ap [j+1] ; p++)
00999 {
01000 if (fkeep (Aj [p], j, Ax ? Ax [p] : 1, other))
01001 {
01002 if (Ax) Ax [nz] = Ax [p] ;
01003 Aj [nz++] = Aj [p] ;
01004 }
01005 }
01006 }
01007 Ap [m] = nz ;
01008 csr_sprealloc (A, 0) ;
01009 return (nz) ;
01010 }