~ubuntu-branches/ubuntu/karmic/python-scipy/karmic

« back to all changes in this revision

Viewing changes to Lib/sparse/SuperLU/SRC/get_perm_c.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel T. Chen (new)
  • Date: 2005-03-16 02:15:29 UTC
  • Revision ID: james.westby@ubuntu.com-20050316021529-xrjlowsejs0cijig
Tags: upstream-0.3.2
ImportĀ upstreamĀ versionĀ 0.3.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * -- SuperLU routine (version 2.0) --
 
3
 * Univ. of California Berkeley, Xerox Palo Alto Research Center,
 
4
 * and Lawrence Berkeley National Lab.
 
5
 * November 15, 1997
 
6
 *
 
7
 */
 
8
#include "dsp_defs.h"
 
9
#include "colamd.h"
 
10
 
 
11
extern int  genmmd_(int *, int *, int *, int *, int *, int *, int *, 
 
12
                    int *, int *, int *, int *, int *);
 
13
 
 
14
void
 
15
get_colamd(
 
16
           const int m,  /* number of rows in matrix A. */
 
17
           const int n,  /* number of columns in matrix A. */
 
18
           const int nnz,/* number of nonzeros in matrix A. */
 
19
           int *colptr,  /* column pointer of size n+1 for matrix A. */
 
20
           int *rowind,  /* row indices of size nz for matrix A. */
 
21
           int *perm_c   /* out - the column permutation vector. */
 
22
           )
 
23
{
 
24
    int Alen, *A, i, info, *p;
 
25
    double *knobs;
 
26
 
 
27
    Alen = colamd_recommended(nnz, m, n);
 
28
 
 
29
    if ( !(knobs = (double *) SUPERLU_MALLOC(COLAMD_KNOBS * sizeof(double))) )
 
30
        ABORT("Malloc fails for knobs");
 
31
    colamd_set_defaults(knobs);
 
32
 
 
33
    if (!(A = (int *) SUPERLU_MALLOC(Alen * sizeof(int))) )
 
34
        ABORT("Malloc fails for A[]");
 
35
    if (!(p = (int *) SUPERLU_MALLOC((n+1) * sizeof(int))) )
 
36
        ABORT("Malloc fails for p[]");
 
37
    for (i = 0; i <= n; ++i) p[i] = colptr[i];
 
38
    for (i = 0; i < nnz; ++i) A[i] = rowind[i];
 
39
    info = colamd(m, n, Alen, A, p, knobs);
 
40
    if ( info == FALSE ) ABORT("COLAMD failed");
 
41
 
 
42
    for (i = 0; i < n; ++i) perm_c[p[i]] = i;
 
43
 
 
44
    SUPERLU_FREE(knobs);
 
45
    SUPERLU_FREE(A);
 
46
    SUPERLU_FREE(p);
 
47
}
 
48
 
 
49
void
 
50
getata(
 
51
       const int m,      /* number of rows in matrix A. */
 
52
       const int n,      /* number of columns in matrix A. */
 
53
       const int nz,     /* number of nonzeros in matrix A */
 
54
       int *colptr,      /* column pointer of size n+1 for matrix A. */
 
55
       int *rowind,      /* row indices of size nz for matrix A. */
 
56
       int *atanz,       /* out - on exit, returns the actual number of
 
57
                            nonzeros in matrix A'*A. */
 
58
       int **ata_colptr, /* out - size n+1 */
 
59
       int **ata_rowind  /* out - size *atanz */
 
60
       )
 
61
/*
 
62
 * Purpose
 
63
 * =======
 
64
 *
 
65
 * Form the structure of A'*A. A is an m-by-n matrix in column oriented
 
66
 * format represented by (colptr, rowind). The output A'*A is in column
 
67
 * oriented format (symmetrically, also row oriented), represented by
 
68
 * (ata_colptr, ata_rowind).
 
69
 *
 
70
 * This routine is modified from GETATA routine by Tim Davis.
 
71
 * The complexity of this algorithm is: SUM_{i=1,m} r(i)^2,
 
72
 * i.e., the sum of the square of the row counts.
 
73
 *
 
74
 * Questions
 
75
 * =========
 
76
 *     o  Do I need to withhold the *dense* rows?
 
77
 *     o  How do I know the number of nonzeros in A'*A?
 
78
 * 
 
79
 */
 
80
{
 
81
    register int i, j, k, col, num_nz, ti, trow;
 
82
    int *marker, *b_colptr, *b_rowind;
 
83
    int *t_colptr, *t_rowind; /* a column oriented form of T = A' */
 
84
 
 
85
    if ( !(marker = (int*) SUPERLU_MALLOC((SUPERLU_MAX(m,n)+1)*sizeof(int))) )
 
86
        ABORT("SUPERLU_MALLOC fails for marker[]");
 
87
    if ( !(t_colptr = (int*) SUPERLU_MALLOC((m+1) * sizeof(int))) )
 
88
        ABORT("SUPERLU_MALLOC t_colptr[]");
 
89
    if ( !(t_rowind = (int*) SUPERLU_MALLOC(nz * sizeof(int))) )
 
90
        ABORT("SUPERLU_MALLOC fails for t_rowind[]");
 
91
 
 
92
    
 
93
    /* Get counts of each column of T, and set up column pointers */
 
94
    for (i = 0; i < m; ++i) marker[i] = 0;
 
95
    for (j = 0; j < n; ++j) {
 
96
        for (i = colptr[j]; i < colptr[j+1]; ++i)
 
97
            ++marker[rowind[i]];
 
98
    }
 
99
    t_colptr[0] = 0;
 
100
    for (i = 0; i < m; ++i) {
 
101
        t_colptr[i+1] = t_colptr[i] + marker[i];
 
102
        marker[i] = t_colptr[i];
 
103
    }
 
104
 
 
105
    /* Transpose the matrix from A to T */
 
106
    for (j = 0; j < n; ++j)
 
107
        for (i = colptr[j]; i < colptr[j+1]; ++i) {
 
108
            col = rowind[i];
 
109
            t_rowind[marker[col]] = j;
 
110
            ++marker[col];
 
111
        }
 
112
 
 
113
    
 
114
    /* ----------------------------------------------------------------
 
115
       compute B = T * A, where column j of B is:
 
116
 
 
117
       Struct (B_*j) =    UNION   ( Struct (T_*k) )
 
118
                        A_kj != 0
 
119
 
 
120
       do not include the diagonal entry
 
121
   
 
122
       ( Partition A as: A = (A_*1, ..., A_*n)
 
123
         Then B = T * A = (T * A_*1, ..., T * A_*n), where
 
124
         T * A_*j = (T_*1, ..., T_*m) * A_*j.  )
 
125
       ---------------------------------------------------------------- */
 
126
 
 
127
    /* Zero the diagonal flag */
 
128
    for (i = 0; i < n; ++i) marker[i] = -1;
 
129
 
 
130
    /* First pass determines number of nonzeros in B */
 
131
    num_nz = 0;
 
132
    for (j = 0; j < n; ++j) {
 
133
        /* Flag the diagonal so it's not included in the B matrix */
 
134
        marker[j] = j;
 
135
 
 
136
        for (i = colptr[j]; i < colptr[j+1]; ++i) {
 
137
            /* A_kj is nonzero, add pattern of column T_*k to B_*j */
 
138
            k = rowind[i];
 
139
            for (ti = t_colptr[k]; ti < t_colptr[k+1]; ++ti) {
 
140
                trow = t_rowind[ti];
 
141
                if ( marker[trow] != j ) {
 
142
                    marker[trow] = j;
 
143
                    num_nz++;
 
144
                }
 
145
            }
 
146
        }
 
147
    }
 
148
    *atanz = num_nz;
 
149
    
 
150
    /* Allocate storage for A'*A */
 
151
    if ( !(*ata_colptr = (int*) SUPERLU_MALLOC( (n+1) * sizeof(int)) ) )
 
152
        ABORT("SUPERLU_MALLOC fails for ata_colptr[]");
 
153
    if ( *atanz ) {
 
154
        if ( !(*ata_rowind = (int*) SUPERLU_MALLOC( *atanz * sizeof(int)) ) )
 
155
            ABORT("SUPERLU_MALLOC fails for ata_rowind[]");
 
156
    }
 
157
    b_colptr = *ata_colptr; /* aliasing */
 
158
    b_rowind = *ata_rowind;
 
159
    
 
160
    /* Zero the diagonal flag */
 
161
    for (i = 0; i < n; ++i) marker[i] = -1;
 
162
    
 
163
    /* Compute each column of B, one at a time */
 
164
    num_nz = 0;
 
165
    for (j = 0; j < n; ++j) {
 
166
        b_colptr[j] = num_nz;
 
167
        
 
168
        /* Flag the diagonal so it's not included in the B matrix */
 
169
        marker[j] = j;
 
170
 
 
171
        for (i = colptr[j]; i < colptr[j+1]; ++i) {
 
172
            /* A_kj is nonzero, add pattern of column T_*k to B_*j */
 
173
            k = rowind[i];
 
174
            for (ti = t_colptr[k]; ti < t_colptr[k+1]; ++ti) {
 
175
                trow = t_rowind[ti];
 
176
                if ( marker[trow] != j ) {
 
177
                    marker[trow] = j;
 
178
                    b_rowind[num_nz++] = trow;
 
179
                }
 
180
            }
 
181
        }
 
182
    }
 
183
    b_colptr[n] = num_nz;
 
184
       
 
185
    SUPERLU_FREE(marker);
 
186
    SUPERLU_FREE(t_colptr);
 
187
    SUPERLU_FREE(t_rowind);
 
188
}
 
189
 
 
190
 
 
191
void
 
192
at_plus_a(
 
193
          const int n,      /* number of columns in matrix A. */
 
194
          const int nz,     /* number of nonzeros in matrix A */
 
195
          int *colptr,      /* column pointer of size n+1 for matrix A. */
 
196
          int *rowind,      /* row indices of size nz for matrix A. */
 
197
          int *bnz,         /* out - on exit, returns the actual number of
 
198
                               nonzeros in matrix A'*A. */
 
199
          int **b_colptr,   /* out - size n+1 */
 
200
          int **b_rowind    /* out - size *bnz */
 
201
          )
 
202
{
 
203
/*
 
204
 * Purpose
 
205
 * =======
 
206
 *
 
207
 * Form the structure of A'+A. A is an n-by-n matrix in column oriented
 
208
 * format represented by (colptr, rowind). The output A'+A is in column
 
209
 * oriented format (symmetrically, also row oriented), represented by
 
210
 * (b_colptr, b_rowind).
 
211
 *
 
212
 */
 
213
    register int i, j, k, col, num_nz;
 
214
    int *t_colptr, *t_rowind; /* a column oriented form of T = A' */
 
215
    int *marker;
 
216
 
 
217
    if ( !(marker = (int*) SUPERLU_MALLOC( n * sizeof(int)) ) )
 
218
        ABORT("SUPERLU_MALLOC fails for marker[]");
 
219
    if ( !(t_colptr = (int*) SUPERLU_MALLOC( (n+1) * sizeof(int)) ) )
 
220
        ABORT("SUPERLU_MALLOC fails for t_colptr[]");
 
221
    if ( !(t_rowind = (int*) SUPERLU_MALLOC( nz * sizeof(int)) ) )
 
222
        ABORT("SUPERLU_MALLOC fails t_rowind[]");
 
223
 
 
224
    
 
225
    /* Get counts of each column of T, and set up column pointers */
 
226
    for (i = 0; i < n; ++i) marker[i] = 0;
 
227
    for (j = 0; j < n; ++j) {
 
228
        for (i = colptr[j]; i < colptr[j+1]; ++i)
 
229
            ++marker[rowind[i]];
 
230
    }
 
231
    t_colptr[0] = 0;
 
232
    for (i = 0; i < n; ++i) {
 
233
        t_colptr[i+1] = t_colptr[i] + marker[i];
 
234
        marker[i] = t_colptr[i];
 
235
    }
 
236
 
 
237
    /* Transpose the matrix from A to T */
 
238
    for (j = 0; j < n; ++j)
 
239
        for (i = colptr[j]; i < colptr[j+1]; ++i) {
 
240
            col = rowind[i];
 
241
            t_rowind[marker[col]] = j;
 
242
            ++marker[col];
 
243
        }
 
244
 
 
245
 
 
246
    /* ----------------------------------------------------------------
 
247
       compute B = A + T, where column j of B is:
 
248
 
 
249
       Struct (B_*j) = Struct (A_*k) UNION Struct (T_*k)
 
250
 
 
251
       do not include the diagonal entry
 
252
       ---------------------------------------------------------------- */
 
253
 
 
254
    /* Zero the diagonal flag */
 
255
    for (i = 0; i < n; ++i) marker[i] = -1;
 
256
 
 
257
    /* First pass determines number of nonzeros in B */
 
258
    num_nz = 0;
 
259
    for (j = 0; j < n; ++j) {
 
260
        /* Flag the diagonal so it's not included in the B matrix */
 
261
        marker[j] = j;
 
262
 
 
263
        /* Add pattern of column A_*k to B_*j */
 
264
        for (i = colptr[j]; i < colptr[j+1]; ++i) {
 
265
            k = rowind[i];
 
266
            if ( marker[k] != j ) {
 
267
                marker[k] = j;
 
268
                ++num_nz;
 
269
            }
 
270
        }
 
271
 
 
272
        /* Add pattern of column T_*k to B_*j */
 
273
        for (i = t_colptr[j]; i < t_colptr[j+1]; ++i) {
 
274
            k = t_rowind[i];
 
275
            if ( marker[k] != j ) {
 
276
                marker[k] = j;
 
277
                ++num_nz;
 
278
            }
 
279
        }
 
280
    }
 
281
    *bnz = num_nz;
 
282
    
 
283
    /* Allocate storage for A+A' */
 
284
    if ( !(*b_colptr = (int*) SUPERLU_MALLOC( (n+1) * sizeof(int)) ) )
 
285
        ABORT("SUPERLU_MALLOC fails for b_colptr[]");
 
286
    if ( *bnz) {
 
287
      if ( !(*b_rowind = (int*) SUPERLU_MALLOC( *bnz * sizeof(int)) ) )
 
288
        ABORT("SUPERLU_MALLOC fails for b_rowind[]");
 
289
    }
 
290
    
 
291
    /* Zero the diagonal flag */
 
292
    for (i = 0; i < n; ++i) marker[i] = -1;
 
293
    
 
294
    /* Compute each column of B, one at a time */
 
295
    num_nz = 0;
 
296
    for (j = 0; j < n; ++j) {
 
297
        (*b_colptr)[j] = num_nz;
 
298
        
 
299
        /* Flag the diagonal so it's not included in the B matrix */
 
300
        marker[j] = j;
 
301
 
 
302
        /* Add pattern of column A_*k to B_*j */
 
303
        for (i = colptr[j]; i < colptr[j+1]; ++i) {
 
304
            k = rowind[i];
 
305
            if ( marker[k] != j ) {
 
306
                marker[k] = j;
 
307
                (*b_rowind)[num_nz++] = k;
 
308
            }
 
309
        }
 
310
 
 
311
        /* Add pattern of column T_*k to B_*j */
 
312
        for (i = t_colptr[j]; i < t_colptr[j+1]; ++i) {
 
313
            k = t_rowind[i];
 
314
            if ( marker[k] != j ) {
 
315
                marker[k] = j;
 
316
                (*b_rowind)[num_nz++] = k;
 
317
            }
 
318
        }
 
319
    }
 
320
    (*b_colptr)[n] = num_nz;
 
321
       
 
322
    SUPERLU_FREE(marker);
 
323
    SUPERLU_FREE(t_colptr);
 
324
    SUPERLU_FREE(t_rowind);
 
325
}
 
326
 
 
327
void
 
328
get_perm_c(int ispec, SuperMatrix *A, int *perm_c)
 
329
/*
 
330
 * Purpose
 
331
 * =======
 
332
 *
 
333
 * GET_PERM_C obtains a permutation matrix Pc, by applying the multiple
 
334
 * minimum degree ordering code by Joseph Liu to matrix A'*A or A+A'.
 
335
 * or using approximate minimum degree column ordering by Davis et. al.
 
336
 * The LU factorization of A*Pc tends to have less fill than the LU 
 
337
 * factorization of A.
 
338
 *
 
339
 * Arguments
 
340
 * =========
 
341
 *
 
342
 * ispec   (input) int
 
343
 *         Specifies the type of column ordering to reduce fill:
 
344
 *         = 1: minimum degree on the structure of A^T * A
 
345
 *         = 2: minimum degree on the structure of A^T + A
 
346
 *         = 3: approximate minimum degree for unsymmetric matrices
 
347
 *         If ispec == 0, the natural ordering (i.e., Pc = I) is returned.
 
348
 * 
 
349
 * A       (input) SuperMatrix*
 
350
 *         Matrix A in A*X=B, of dimension (A->nrow, A->ncol). The number
 
351
 *         of the linear equations is A->nrow. Currently, the type of A 
 
352
 *         can be: Stype = NC; Dtype = _D; Mtype = GE. In the future,
 
353
 *         more general A can be handled.
 
354
 *
 
355
 * perm_c  (output) int*
 
356
 *         Column permutation vector of size A->ncol, which defines the 
 
357
 *         permutation matrix Pc; perm_c[i] = j means column i of A is 
 
358
 *         in position j in A*Pc.
 
359
 *
 
360
 */
 
361
{
 
362
    NCformat *Astore = A->Store;
 
363
    int m, n, bnz, *b_colptr, i;
 
364
    int delta, maxint, nofsub, *invp;
 
365
    int *b_rowind, *dhead, *qsize, *llist, *marker;
 
366
    double t, SuperLU_timer_();
 
367
    
 
368
    m = A->nrow;
 
369
    n = A->ncol;
 
370
 
 
371
    t = SuperLU_timer_();
 
372
    switch ( ispec ) {
 
373
        case 0: /* Natural ordering */
 
374
              for (i = 0; i < n; ++i) perm_c[i] = i;
 
375
              printf("Use natural column ordering.\n");
 
376
              return;
 
377
        case 1: /* Minimum degree ordering on A'*A */
 
378
              getata(m, n, Astore->nnz, Astore->colptr, Astore->rowind,
 
379
                     &bnz, &b_colptr, &b_rowind);
 
380
              printf("Use minimum degree ordering on A'*A.\n");
 
381
              t = SuperLU_timer_() - t;
 
382
              /*printf("Form A'*A time = %8.3f\n", t);*/
 
383
              break;
 
384
        case 2: /* Minimum degree ordering on A'+A */
 
385
              if ( m != n ) ABORT("Matrix is not square");
 
386
              at_plus_a(n, Astore->nnz, Astore->colptr, Astore->rowind,
 
387
                        &bnz, &b_colptr, &b_rowind);
 
388
              printf("Use minimum degree ordering on A'+A.\n");
 
389
              t = SuperLU_timer_() - t;
 
390
              /*printf("Form A'+A time = %8.3f\n", t);*/
 
391
              break;
 
392
        case 3: /* Approximate minimum degree column ordering. */
 
393
              get_colamd(m, n, Astore->nnz, Astore->colptr, Astore->rowind,
 
394
                         perm_c);
 
395
              printf(".. Use approximate minimum degree column ordering.\n");
 
396
              return; 
 
397
        default:
 
398
              ABORT("Invalid ISPEC");
 
399
    }
 
400
 
 
401
    if ( bnz != 0 ) {
 
402
        t = SuperLU_timer_();
 
403
 
 
404
        /* Initialize and allocate storage for GENMMD. */
 
405
        delta = 1; /* DELTA is a parameter to allow the choice of nodes
 
406
                      whose degree <= min-degree + DELTA. */
 
407
        maxint = 2147483647; /* 2**31 - 1 */
 
408
        invp = (int *) SUPERLU_MALLOC((n+delta)*sizeof(int));
 
409
        if ( !invp ) ABORT("SUPERLU_MALLOC fails for invp.");
 
410
        dhead = (int *) SUPERLU_MALLOC((n+delta)*sizeof(int));
 
411
        if ( !dhead ) ABORT("SUPERLU_MALLOC fails for dhead.");
 
412
        qsize = (int *) SUPERLU_MALLOC((n+delta)*sizeof(int));
 
413
        if ( !qsize ) ABORT("SUPERLU_MALLOC fails for qsize.");
 
414
        llist = (int *) SUPERLU_MALLOC(n*sizeof(int));
 
415
        if ( !llist ) ABORT("SUPERLU_MALLOC fails for llist.");
 
416
        marker = (int *) SUPERLU_MALLOC(n*sizeof(int));
 
417
        if ( !marker ) ABORT("SUPERLU_MALLOC fails for marker.");
 
418
 
 
419
        /* Transform adjacency list into 1-based indexing required by GENMMD.*/
 
420
        for (i = 0; i <= n; ++i) ++b_colptr[i];
 
421
        for (i = 0; i < bnz; ++i) ++b_rowind[i];
 
422
        
 
423
        genmmd_(&n, b_colptr, b_rowind, perm_c, invp, &delta, dhead, 
 
424
                qsize, llist, marker, &maxint, &nofsub);
 
425
 
 
426
        /* Transform perm_c into 0-based indexing. */
 
427
        for (i = 0; i < n; ++i) --perm_c[i];
 
428
 
 
429
        SUPERLU_FREE(b_colptr);
 
430
        SUPERLU_FREE(b_rowind);
 
431
        SUPERLU_FREE(invp);
 
432
        SUPERLU_FREE(dhead);
 
433
        SUPERLU_FREE(qsize);
 
434
        SUPERLU_FREE(llist);
 
435
        SUPERLU_FREE(marker);
 
436
 
 
437
        t = SuperLU_timer_() - t;
 
438
        /*  printf("call GENMMD time = %8.3f\n", t);*/
 
439
 
 
440
    } else { /* Empty adjacency structure */
 
441
        for (i = 0; i < n; ++i) perm_c[i] = i;
 
442
    }
 
443
 
 
444
}