Amesos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
amesos_klu_l_analyze_given.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /* === klu_analyze_given ==================================================== */
3 /* ========================================================================== */
4 
5 /* Given an input permutation P and Q, create the Symbolic object. BTF can
6  * be done to modify the user's P and Q (does not perform the max transversal;
7  * just finds the strongly-connected components). */
8 
9 /* This file should make the long int version of KLU */
10 #define DLONG 1
11 
12 #include "amesos_klu_internal.h"
13 
14 /* ========================================================================== */
15 /* === klu_alloc_symbolic =================================================== */
16 /* ========================================================================== */
17 
18 /* Allocate Symbolic object, and check input matrix. Not user callable. */
19 
21 (
22  Int n,
23  Int *Ap,
24  Int *Ai,
25  KLU_common *Common
26 )
27 {
28  KLU_symbolic *Symbolic ;
29  Int *P, *Q, *R ;
30  double *Lnz ;
31  Int nz, i, j, p, pend ;
32 
33  if (Common == NULL)
34  {
35  return (NULL) ;
36  }
37  Common->status = KLU_OK ;
38 
39  /* A is n-by-n, with n > 0. Ap [0] = 0 and nz = Ap [n] >= 0 required.
40  * Ap [j] <= Ap [j+1] must hold for all j = 0 to n-1. Row indices in Ai
41  * must be in the range 0 to n-1, and no duplicate entries can be present.
42  * The list of row indices in each column of A need not be sorted.
43  */
44 
45  if (n <= 0 || Ap == NULL || Ai == NULL)
46  {
47  /* Ap and Ai must be present, and n must be > 0 */
48  Common->status = KLU_INVALID ;
49  return (NULL) ;
50  }
51 
52  nz = Ap [n] ;
53  if (Ap [0] != 0 || nz < 0)
54  {
55  /* nz must be >= 0 and Ap [0] must equal zero */
56  Common->status = KLU_INVALID ;
57  return (NULL) ;
58  }
59 
60  for (j = 0 ; j < n ; j++)
61  {
62  if (Ap [j] > Ap [j+1])
63  {
64  /* column pointers must be non-decreasing */
65  Common->status = KLU_INVALID ;
66  return (NULL) ;
67  }
68  }
69  P = KLU_malloc (n, sizeof (Int), Common) ;
70  if (Common->status < KLU_OK)
71  {
72  /* out of memory */
73  Common->status = KLU_OUT_OF_MEMORY ;
74  return (NULL) ;
75  }
76  for (i = 0 ; i < n ; i++)
77  {
78  P [i] = EMPTY ;
79  }
80  for (j = 0 ; j < n ; j++)
81  {
82  pend = Ap [j+1] ;
83  for (p = Ap [j] ; p < pend ; p++)
84  {
85  i = Ai [p] ;
86  if (i < 0 || i >= n || P [i] == j)
87  {
88  /* row index out of range, or duplicate entry */
89  KLU_free (P, n, sizeof (Int), Common) ;
90  Common->status = KLU_INVALID ;
91  return (NULL) ;
92  }
93  /* flag row i as appearing in column j */
94  P [i] = j ;
95  }
96  }
97 
98  /* ---------------------------------------------------------------------- */
99  /* allocate the Symbolic object */
100  /* ---------------------------------------------------------------------- */
101 
102  Symbolic = KLU_malloc (sizeof (KLU_symbolic), 1, Common) ;
103  if (Common->status < KLU_OK)
104  {
105  /* out of memory */
106  KLU_free (P, n, sizeof (Int), Common) ;
107  Common->status = KLU_OUT_OF_MEMORY ;
108  return (NULL) ;
109  }
110 
111  Q = KLU_malloc (n, sizeof (Int), Common) ;
112  R = KLU_malloc (n+1, sizeof (Int), Common) ;
113  Lnz = KLU_malloc (n, sizeof (double), Common) ;
114 
115  Symbolic->n = n ;
116  Symbolic->nz = nz ;
117  Symbolic->P = P ;
118  Symbolic->Q = Q ;
119  Symbolic->R = R ;
120  Symbolic->Lnz = Lnz ;
121 
122  if (Common->status < KLU_OK)
123  {
124  /* out of memory */
125  KLU_free_symbolic (&Symbolic, Common) ;
126  Common->status = KLU_OUT_OF_MEMORY ;
127  return (NULL) ;
128  }
129 
130  return (Symbolic) ;
131 }
132 
133 
134 /* ========================================================================== */
135 /* === KLU_analyze_given ==================================================== */
136 /* ========================================================================== */
137 
138 KLU_symbolic *KLU_analyze_given /* returns NULL if error, or a valid
139  KLU_symbolic object if successful */
140 (
141  /* inputs, not modified */
142  Int n, /* A is n-by-n */
143  Int Ap [ ], /* size n+1, column pointers */
144  Int Ai [ ], /* size nz, row indices */
145  Int Puser [ ], /* size n, user's row permutation (may be NULL) */
146  Int Quser [ ], /* size n, user's column permutation (may be NULL) */
147  /* -------------------- */
148  KLU_common *Common
149 )
150 {
151  KLU_symbolic *Symbolic ;
152  double *Lnz ;
153  Int nblocks, nz, block, maxblock, *P, *Q, *R, nzoff, p, pend, do_btf, k ;
154 
155  /* ---------------------------------------------------------------------- */
156  /* determine if input matrix is valid, and get # of nonzeros */
157  /* ---------------------------------------------------------------------- */
158 
159  Symbolic = KLU_alloc_symbolic (n, Ap, Ai, Common) ;
160  if (Symbolic == NULL)
161  {
162  return (NULL) ;
163  }
164  P = Symbolic->P ;
165  Q = Symbolic->Q ;
166  R = Symbolic->R ;
167  Lnz = Symbolic->Lnz ;
168  nz = Symbolic->nz ;
169 
170  /* ---------------------------------------------------------------------- */
171  /* Q = Quser, or identity if Quser is NULL */
172  /* ---------------------------------------------------------------------- */
173 
174  if (Quser == (Int *) NULL)
175  {
176  for (k = 0 ; k < n ; k++)
177  {
178  Q [k] = k ;
179  }
180  }
181  else
182  {
183  for (k = 0 ; k < n ; k++)
184  {
185  Q [k] = Quser [k] ;
186  }
187  }
188 
189  /* ---------------------------------------------------------------------- */
190  /* get the control parameters for BTF and ordering method */
191  /* ---------------------------------------------------------------------- */
192 
193  do_btf = Common->btf ;
194  do_btf = (do_btf) ? TRUE : FALSE ;
195  Symbolic->ordering = 2 ;
196  Symbolic->do_btf = do_btf ;
197 
198  /* ---------------------------------------------------------------------- */
199  /* find the block triangular form, if requested */
200  /* ---------------------------------------------------------------------- */
201 
202  if (do_btf)
203  {
204 
205  /* ------------------------------------------------------------------ */
206  /* get workspace for BTF_strongcomp */
207  /* ------------------------------------------------------------------ */
208 
209  Int *Pinv, *Work, *Bi, k1, k2, nk, oldcol ;
210 
211  Work = KLU_malloc (4*n, sizeof (Int), Common) ;
212  Pinv = KLU_malloc (n, sizeof (Int), Common) ;
213  if (Puser != (Int *) NULL)
214  {
215  Bi = KLU_malloc (nz+1, sizeof (Int), Common) ;
216  }
217  else
218  {
219  Bi = Ai ;
220  }
221 
222  if (Common->status < KLU_OK)
223  {
224  /* out of memory */
225  KLU_free (Work, 4*n, sizeof (Int), Common) ;
226  KLU_free (Pinv, n, sizeof (Int), Common) ;
227  if (Puser != (Int *) NULL)
228  {
229  KLU_free (Bi, nz+1, sizeof (Int), Common) ;
230  }
231  KLU_free_symbolic (&Symbolic, Common) ;
232  Common->status = KLU_OUT_OF_MEMORY ;
233  return (NULL) ;
234  }
235 
236  /* ------------------------------------------------------------------ */
237  /* B = Puser * A */
238  /* ------------------------------------------------------------------ */
239 
240  if (Puser != (Int *) NULL)
241  {
242  for (k = 0 ; k < n ; k++)
243  {
244  Pinv [Puser [k]] = k ;
245  }
246  for (p = 0 ; p < nz ; p++)
247  {
248  Bi [p] = Pinv [Ai [p]] ;
249  }
250  }
251 
252  /* ------------------------------------------------------------------ */
253  /* find the strongly-connected components */
254  /* ------------------------------------------------------------------ */
255 
256  /* modifies Q, and determines P and R */
257  nblocks = BTF_strongcomp (n, Ap, Bi, Q, P, R, Work) ;
258 
259  /* ------------------------------------------------------------------ */
260  /* P = P * Puser */
261  /* ------------------------------------------------------------------ */
262 
263  if (Puser != (Int *) NULL)
264  {
265  for (k = 0 ; k < n ; k++)
266  {
267  Work [k] = Puser [P [k]] ;
268  }
269  for (k = 0 ; k < n ; k++)
270  {
271  P [k] = Work [k] ;
272  }
273  }
274 
275  /* ------------------------------------------------------------------ */
276  /* Pinv = inverse of P */
277  /* ------------------------------------------------------------------ */
278 
279  for (k = 0 ; k < n ; k++)
280  {
281  Pinv [P [k]] = k ;
282  }
283 
284  /* ------------------------------------------------------------------ */
285  /* analyze each block */
286  /* ------------------------------------------------------------------ */
287 
288  nzoff = 0 ; /* nz in off-diagonal part */
289  maxblock = 1 ; /* size of the largest block */
290 
291  for (block = 0 ; block < nblocks ; block++)
292  {
293 
294  /* -------------------------------------------------------------- */
295  /* the block is from rows/columns k1 to k2-1 */
296  /* -------------------------------------------------------------- */
297 
298  k1 = R [block] ;
299  k2 = R [block+1] ;
300  nk = k2 - k1 ;
301  PRINTF (("BLOCK %d, k1 %d k2-1 %d nk %d\n", block, k1, k2-1, nk)) ;
302  maxblock = MAX (maxblock, nk) ;
303 
304  /* -------------------------------------------------------------- */
305  /* scan the kth block, C */
306  /* -------------------------------------------------------------- */
307 
308  for (k = k1 ; k < k2 ; k++)
309  {
310  oldcol = Q [k] ;
311  pend = Ap [oldcol+1] ;
312  for (p = Ap [oldcol] ; p < pend ; p++)
313  {
314  if (Pinv [Ai [p]] < k1)
315  {
316  nzoff++ ;
317  }
318  }
319  }
320 
321  /* fill-in not estimated */
322  Lnz [block] = EMPTY ;
323  }
324 
325  /* ------------------------------------------------------------------ */
326  /* free all workspace */
327  /* ------------------------------------------------------------------ */
328 
329  KLU_free (Work, 4*n, sizeof (Int), Common) ;
330  KLU_free (Pinv, n, sizeof (Int), Common) ;
331  if (Puser != (Int *) NULL)
332  {
333  KLU_free (Bi, nz+1, sizeof (Int), Common) ;
334  }
335 
336  }
337  else
338  {
339 
340  /* ------------------------------------------------------------------ */
341  /* BTF not requested */
342  /* ------------------------------------------------------------------ */
343 
344  nzoff = 0 ;
345  nblocks = 1 ;
346  maxblock = n ;
347  R [0] = 0 ;
348  R [1] = n ;
349  Lnz [0] = EMPTY ;
350 
351  /* ------------------------------------------------------------------ */
352  /* P = Puser, or identity if Puser is NULL */
353  /* ------------------------------------------------------------------ */
354 
355  for (k = 0 ; k < n ; k++)
356  {
357  P [k] = (Puser == NULL) ? k : Puser [k] ;
358  }
359  }
360 
361  /* ---------------------------------------------------------------------- */
362  /* return the symbolic object */
363  /* ---------------------------------------------------------------------- */
364 
365  Symbolic->nblocks = nblocks ;
366  Symbolic->maxblock = maxblock ;
367  Symbolic->lnz = EMPTY ;
368  Symbolic->unz = EMPTY ;
369  Symbolic->nzoff = nzoff ;
370 
371  return (Symbolic) ;
372 }
KLU_symbolic * KLU_alloc_symbolic(Int n, Int *Ap, Int *Ai, KLU_common *Common)
#define KLU_INVALID
#define EMPTY
#define KLU_symbolic
#define Int
#define FALSE
#define P(k)
#define MAX(a, b)
#define KLU_OUT_OF_MEMORY
#define NULL
#define KLU_malloc
#define KLU_free_symbolic
KLU_symbolic * KLU_analyze_given(Int n, Int Ap[], Int Ai[], Int Puser[], Int Quser[], KLU_common *Common)
#define KLU_common
#define PRINTF(params)
#define BTF_strongcomp
#define TRUE
#define KLU_free
#define KLU_OK