Amesos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
amesos_camd_1.c
Go to the documentation of this file.
1 /* ========================================================================= */
2 /* === CAMD_1 ============================================================== */
3 /* ========================================================================= */
4 
5 /* ------------------------------------------------------------------------- */
6 /* CAMD, Copyright (c) Timothy A. Davis, Yanqing Chen, */
7 /* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
8 /* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */
9 /* web: http://www.cise.ufl.edu/research/sparse/camd */
10 /* ------------------------------------------------------------------------- */
11 
12 /* CAMD_1: Construct A+A' for a sparse matrix A and perform the CAMD ordering.
13  *
14  * The n-by-n sparse matrix A can be unsymmetric. It is stored in MATLAB-style
15  * compressed-column form, with sorted row indices in each column, and no
16  * duplicate entries. Diagonal entries may be present, but they are ignored.
17  * Row indices of column j of A are stored in Ai [Ap [j] ... Ap [j+1]-1].
18  * Ap [0] must be zero, and nz = Ap [n] is the number of entries in A. The
19  * size of the matrix, n, must be greater than or equal to zero.
20  *
21  * This routine must be preceded by a call to CAMD_aat, which computes the
22  * number of entries in each row/column in A+A', excluding the diagonal.
23  * Len [j], on input, is the number of entries in row/column j of A+A'. This
24  * routine constructs the matrix A+A' and then calls CAMD_2. No error checking
25  * is performed (this was done in CAMD_valid).
26  */
27 
28 #include "amesos_camd_internal.h"
29 
30 GLOBAL void CAMD_1
31 (
32  Int n, /* n > 0 */
33  const Int Ap [ ], /* input of size n+1, not modified */
34  const Int Ai [ ], /* input of size nz = Ap [n], not modified */
35  Int P [ ], /* size n output permutation */
36  Int Pinv [ ], /* size n output inverse permutation */
37  Int Len [ ], /* size n input, undefined on output */
38  Int slen, /* slen >= sum (Len [0..n-1]) + 7n+2,
39  * ideally slen = 1.2 * sum (Len) + 8n+2 */
40  Int S [ ], /* size slen workspace */
41  double Control [ ], /* input array of size CAMD_CONTROL */
42  double Info [ ], /* output array of size CAMD_INFO */
43  const Int C [ ] /* Constraint set of size n */
44 )
45 {
46  Int i, j, k, p, pfree, iwlen, pj, p1, p2, pj2, *Iw, *Pe, *Nv, *Head,
47  *Elen, *Degree, *s, *W, *Sp, *Tp, *BucketSet ;
48 
49  /* --------------------------------------------------------------------- */
50  /* construct the matrix for CAMD_2 */
51  /* --------------------------------------------------------------------- */
52 
53  ASSERT (n > 0) ;
54 
55  iwlen = slen - (7*n+2) ; /* allocate 7*n+2 workspace from S */
56  s = S ;
57  Pe = s ; s += n ;
58  Nv = s ; s += n ;
59  Head = s ; s += n+1 ; /* NOTE: was size n in AMD; size n+1 in CAMD */
60  Elen = s ; s += n ;
61  Degree = s ; s += n ;
62  W = s ; s += n+1 ; /* NOTE: was size n in AMD; size n+1 in CAMD */
63  BucketSet = s ; s += n ;
64  Iw = s ; s += iwlen ;
65 
66  ASSERT (CAMD_valid (n, n, Ap, Ai) == CAMD_OK) ;
67  ASSERT (CAMD_cvalid (n, C)) ;
68 
69  /* construct the pointers for A+A' */
70  Sp = Nv ; /* use Nv and W as workspace for Sp and Tp [ */
71  Tp = W ;
72  pfree = 0 ;
73  for (j = 0 ; j < n ; j++)
74  {
75  Pe [j] = pfree ;
76  Sp [j] = pfree ;
77  pfree += Len [j] ;
78  }
79 
80  /* Note that this restriction on iwlen is slightly more restrictive than
81  * what is strictly required in CAMD_2. CAMD_2 can operate with no elbow
82  * room at all, but it will be very slow. For better performance, at
83  * least size-n elbow room is enforced. */
84  ASSERT (iwlen >= pfree + n) ;
85 
86 #ifndef NDEBUG
87  for (p = 0 ; p < iwlen ; p++) Iw [p] = EMPTY ;
88 #endif
89 
90  for (k = 0 ; k < n ; k++)
91  {
92  CAMD_DEBUG1 (("Construct row/column k= "ID" of A+A'\n", k)) ;
93  p1 = Ap [k] ;
94  p2 = Ap [k+1] ;
95 
96  /* construct A+A' */
97  for (p = p1 ; p < p2 ; )
98  {
99  /* scan the upper triangular part of A */
100  j = Ai [p] ;
101  ASSERT (j >= 0 && j < n) ;
102  if (j < k)
103  {
104  /* entry A (j,k) in the strictly upper triangular part */
105  ASSERT (Sp [j] < (j == n-1 ? pfree : Pe [j+1])) ;
106  ASSERT (Sp [k] < (k == n-1 ? pfree : Pe [k+1])) ;
107  Iw [Sp [j]++] = k ;
108  Iw [Sp [k]++] = j ;
109  p++ ;
110  }
111  else if (j == k)
112  {
113  /* skip the diagonal */
114  p++ ;
115  break ;
116  }
117  else /* j > k */
118  {
119  /* first entry below the diagonal */
120  break ;
121  }
122  /* scan lower triangular part of A, in column j until reaching
123  * row k. Start where last scan left off. */
124  ASSERT (Ap [j] <= Tp [j] && Tp [j] <= Ap [j+1]) ;
125  pj2 = Ap [j+1] ;
126  for (pj = Tp [j] ; pj < pj2 ; )
127  {
128  i = Ai [pj] ;
129  ASSERT (i >= 0 && i < n) ;
130  if (i < k)
131  {
132  /* A (i,j) is only in the lower part, not in upper */
133  ASSERT (Sp [i] < (i == n-1 ? pfree : Pe [i+1])) ;
134  ASSERT (Sp [j] < (j == n-1 ? pfree : Pe [j+1])) ;
135  Iw [Sp [i]++] = j ;
136  Iw [Sp [j]++] = i ;
137  pj++ ;
138  }
139  else if (i == k)
140  {
141  /* entry A (k,j) in lower part and A (j,k) in upper */
142  pj++ ;
143  break ;
144  }
145  else /* i > k */
146  {
147  /* consider this entry later, when k advances to i */
148  break ;
149  }
150  }
151  Tp [j] = pj ;
152  }
153  Tp [k] = p ;
154  }
155 
156  /* clean up, for remaining mismatched entries */
157  for (j = 0 ; j < n ; j++)
158  {
159  for (pj = Tp [j] ; pj < Ap [j+1] ; pj++)
160  {
161  i = Ai [pj] ;
162  ASSERT (i >= 0 && i < n) ;
163  /* A (i,j) is only in the lower part, not in upper */
164  ASSERT (Sp [i] < (i == n-1 ? pfree : Pe [i+1])) ;
165  ASSERT (Sp [j] < (j == n-1 ? pfree : Pe [j+1])) ;
166  Iw [Sp [i]++] = j ;
167  Iw [Sp [j]++] = i ;
168  }
169  }
170 
171 #ifndef NDEBUG
172  for (j = 0 ; j < n-1 ; j++) ASSERT (Sp [j] == Pe [j+1]) ;
173  ASSERT (Sp [n-1] == pfree) ;
174 #endif
175 
176  /* Tp and Sp no longer needed ] */
177 
178  /* --------------------------------------------------------------------- */
179  /* order the matrix */
180  /* --------------------------------------------------------------------- */
181 
182  CAMD_2 (n, Pe, Iw, Len, iwlen, pfree,
183  Nv, Pinv, P, Head, Elen, Degree, W, Control, Info, C, BucketSet) ;
184 }
#define EMPTY
#define GLOBAL
#define Int
#define P(k)
#define ASSERT(expression)
#define CAMD_2
GLOBAL void CAMD_1(Int n, const Int Ap[], const Int Ai[], Int P[], Int Pinv[], Int Len[], Int slen, Int S[], double Control[], double Info[], const Int C[])
Definition: amesos_camd_1.c:31
#define ID
#define CAMD_DEBUG1(params)
GLOBAL Int CAMD_cvalid(Int n, const Int C[])
#define CAMD_OK
Definition: amesos_camd.h:382
GLOBAL Int CAMD_valid(Int n_row, Int n_col, const Int Ap[], const Int Ai[])