Amesos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
amesos_cholmod_band.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /* === Core/cholmod_band ==================================================== */
3 /* ========================================================================== */
4 
5 /* -----------------------------------------------------------------------------
6  * CHOLMOD/Core Module. Copyright (C) 2005-2006,
7  * Univ. of Florida. Author: Timothy A. Davis
8  * The CHOLMOD/Core Module is licensed under Version 2.1 of the GNU
9  * Lesser General Public License. See lesser.txt for a text of the license.
10  * CHOLMOD is also available under other licenses; contact authors for details.
11  * http://www.cise.ufl.edu/research/sparse
12  * -------------------------------------------------------------------------- */
13 
14 /* C = tril (triu (A,k1), k2)
15  *
16  * C is a matrix consisting of the diagonals of A from k1 to k2.
17  *
18  * k=0 is the main diagonal of A, k=1 is the superdiagonal, k=-1 is the
19  * subdiagonal, and so on. If A is m-by-n, then:
20  *
21  * k1=-m C = tril (A,k2)
22  * k2=n C = triu (A,k1)
23  * k1=0 and k2=0 C = diag(A), except C is a matrix, not a vector
24  *
25  * Values of k1 and k2 less than -m are treated as -m, and values greater
26  * than n are treated as n.
27  *
28  * A can be of any symmetry (upper, lower, or unsymmetric); C is returned in
29  * the same form, and packed. If A->stype > 0, entries in the lower
30  * triangular part of A are ignored, and the opposite is true if
31  * A->stype < 0. If A has sorted columns, then so does C.
32  * C has the same size as A.
33  *
34  * If inplace is TRUE, then the matrix A is modified in place.
35  * Only packed matrices can be converted in place.
36  *
37  * C can be returned as a numerical valued matrix (if A has numerical values
38  * and mode > 0), as a pattern-only (mode == 0), or as a pattern-only but with
39  * the diagonal entries removed (mode < 0).
40  *
41  * workspace: none
42  *
43  * A can have an xtype of pattern or real. Complex and zomplex cases supported
44  * only if mode <= 0 (in which case the numerical values are ignored).
45  */
46 
48 #include "amesos_cholmod_core.h"
49 
50 static cholmod_sparse *band /* returns C, or NULL if failure */
51 (
52  /* ---- input or in/out if inplace is TRUE --- */
54  /* ---- input ---- */
55  UF_long k1, /* ignore entries below the k1-st diagonal */
56  UF_long k2, /* ignore entries above the k2-nd diagonal */
57  int mode, /* >0: numerical, 0: pattern, <0: pattern (no diagonal) */
58  int inplace, /* if TRUE, then convert A in place */
59  /* --------------- */
60  cholmod_common *Common
61 )
62 {
63  double *Ax, *Cx ;
64  Int packed, nz, j, p, pend, i, ncol, nrow, jlo, jhi, ilo, ihi, sorted,
65  values, diag ;
66  Int *Ap, *Anz, *Ai, *Cp, *Ci ;
67  cholmod_sparse *C ;
68 
69  /* ---------------------------------------------------------------------- */
70  /* check inputs */
71  /* ---------------------------------------------------------------------- */
72 
74  RETURN_IF_NULL (A, NULL) ;
75  values = (mode > 0) && (A->xtype != CHOLMOD_PATTERN) ;
77  values ? CHOLMOD_REAL : CHOLMOD_ZOMPLEX, NULL) ;
78  packed = A->packed ;
79  diag = (mode >= 0) ;
80  if (inplace && !packed)
81  {
82  /* cannot operate on an unpacked matrix in place */
83  ERROR (CHOLMOD_INVALID, "cannot operate on unpacked matrix in-place") ;
84  return (NULL) ;
85  }
86  Common->status = CHOLMOD_OK ;
87 
88  /* ---------------------------------------------------------------------- */
89  /* get inputs */
90  /* ---------------------------------------------------------------------- */
91 
92 
93  PRINT1 (("k1 %ld k2 %ld\n", k1, k2)) ;
94  Ap = A->p ;
95  Anz = A->nz ;
96  Ai = A->i ;
97  Ax = A->x ;
98  sorted = A->sorted ;
99 
100 
101  if (A->stype > 0)
102  {
103  /* ignore any entries in strictly lower triangular part of A */
104  k1 = MAX (k1, 0) ;
105  }
106  if (A->stype < 0)
107  {
108  /* ignore any entries in strictly upper triangular part of A */
109  k2 = MIN (k2, 0) ;
110  }
111  ncol = A->ncol ;
112  nrow = A->nrow ;
113 
114  /* ensure k1 and k2 are in the range -nrow to +ncol to
115  * avoid possible integer overflow if k1 and k2 are huge */
116  k1 = MAX (-nrow, k1) ;
117  k1 = MIN (k1, ncol) ;
118  k2 = MAX (-nrow, k2) ;
119  k2 = MIN (k2, ncol) ;
120 
121  /* consider columns jlo to jhi. columns outside this range are empty */
122  jlo = MAX (k1, 0) ;
123  jhi = MIN (k2+nrow, ncol) ;
124 
125  if (k1 > k2)
126  {
127  /* nothing to do */
128  jlo = ncol ;
129  jhi = ncol ;
130  }
131 
132  /* ---------------------------------------------------------------------- */
133  /* allocate C, or operate on A in place */
134  /* ---------------------------------------------------------------------- */
135 
136  if (inplace)
137  {
138  /* convert A in place */
139  C = A ;
140  }
141  else
142  {
143  /* count the number of entries in the result C */
144  nz = 0 ;
145  if (sorted)
146  {
147  for (j = jlo ; j < jhi ; j++)
148  {
149  ilo = j-k2 ;
150  ihi = j-k1 ;
151  p = Ap [j] ;
152  pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ;
153  for ( ; p < pend ; p++)
154  {
155  i = Ai [p] ;
156  if (i > ihi)
157  {
158  break ;
159  }
160  if (i >= ilo && (diag || i != j))
161  {
162  nz++ ;
163  }
164  }
165  }
166  }
167  else
168  {
169  for (j = jlo ; j < jhi ; j++)
170  {
171  ilo = j-k2 ;
172  ihi = j-k1 ;
173  p = Ap [j] ;
174  pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ;
175  for ( ; p < pend ; p++)
176  {
177  i = Ai [p] ;
178  if (i >= ilo && i <= ihi && (diag || i != j))
179  {
180  nz++ ;
181  }
182  }
183  }
184  }
185  /* allocate C; A will not be modified. C is sorted if A is sorted */
186  C = CHOLMOD(allocate_sparse) (A->nrow, ncol, nz, sorted, TRUE,
187  A->stype, values ? A->xtype : CHOLMOD_PATTERN, Common) ;
188  if (Common->status < CHOLMOD_OK)
189  {
190  return (NULL) ; /* out of memory */
191  }
192  }
193 
194  Cp = C->p ;
195  Ci = C->i ;
196  Cx = C->x ;
197 
198  /* ---------------------------------------------------------------------- */
199  /* construct C */
200  /* ---------------------------------------------------------------------- */
201 
202  /* columns 0 to jlo-1 are empty */
203  for (j = 0 ; j < jlo ; j++)
204  {
205  Cp [j] = 0 ;
206  }
207 
208  nz = 0 ;
209  if (sorted)
210  {
211  if (values)
212  {
213  /* pattern and values */
214  ASSERT (diag) ;
215  for (j = jlo ; j < jhi ; j++)
216  {
217  ilo = j-k2 ;
218  ihi = j-k1 ;
219  p = Ap [j] ;
220  pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ;
221  Cp [j] = nz ;
222  for ( ; p < pend ; p++)
223  {
224  i = Ai [p] ;
225  if (i > ihi)
226  {
227  break ;
228  }
229  if (i >= ilo)
230  {
231  Ci [nz] = i ;
232  Cx [nz] = Ax [p] ;
233  nz++ ;
234  }
235  }
236  }
237  }
238  else
239  {
240  /* pattern only, perhaps with no diagonal */
241  for (j = jlo ; j < jhi ; j++)
242  {
243  ilo = j-k2 ;
244  ihi = j-k1 ;
245  p = Ap [j] ;
246  pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ;
247  Cp [j] = nz ;
248  for ( ; p < pend ; p++)
249  {
250  i = Ai [p] ;
251  if (i > ihi)
252  {
253  break ;
254  }
255  if (i >= ilo && (diag || i != j))
256  {
257  Ci [nz++] = i ;
258  }
259  }
260  }
261  }
262  }
263  else
264  {
265  if (values)
266  {
267  /* pattern and values */
268  ASSERT (diag) ;
269  for (j = jlo ; j < jhi ; j++)
270  {
271  ilo = j-k2 ;
272  ihi = j-k1 ;
273  p = Ap [j] ;
274  pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ;
275  Cp [j] = nz ;
276  for ( ; p < pend ; p++)
277  {
278  i = Ai [p] ;
279  if (i >= ilo && i <= ihi)
280  {
281  Ci [nz] = i ;
282  Cx [nz] = Ax [p] ;
283  nz++ ;
284  }
285  }
286  }
287  }
288  else
289  {
290  /* pattern only, perhaps with no diagonal */
291  for (j = jlo ; j < jhi ; j++)
292  {
293  ilo = j-k2 ;
294  ihi = j-k1 ;
295  p = Ap [j] ;
296  pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ;
297  Cp [j] = nz ;
298  for ( ; p < pend ; p++)
299  {
300  i = Ai [p] ;
301  if (i >= ilo && i <= ihi && (diag || i != j))
302  {
303  Ci [nz++] = i ;
304  }
305  }
306  }
307  }
308  }
309 
310  /* columns jhi to ncol-1 are empty */
311  for (j = jhi ; j <= ncol ; j++)
312  {
313  Cp [j] = nz ;
314  }
315 
316  /* ---------------------------------------------------------------------- */
317  /* reduce A in size if done in place */
318  /* ---------------------------------------------------------------------- */
319 
320  if (inplace)
321  {
322  /* free the unused parts of A, and reduce A->i and A->x in size */
323  ASSERT (MAX (1,nz) <= A->nzmax) ;
324  CHOLMOD(reallocate_sparse) (nz, A, Common) ;
325  ASSERT (Common->status >= CHOLMOD_OK) ;
326  }
327 
328  /* ---------------------------------------------------------------------- */
329  /* return the result C */
330  /* ---------------------------------------------------------------------- */
331 
332  DEBUG (i = CHOLMOD(dump_sparse) (C, "band", Common)) ;
333  ASSERT (IMPLIES (mode < 0, i == 0)) ;
334  return (C) ;
335 }
336 
337 
338 /* ========================================================================== */
339 /* === cholmod_band ========================================================= */
340 /* ========================================================================== */
341 
343 (
344  /* ---- input ---- */
345  cholmod_sparse *A, /* matrix to extract band matrix from */
346  UF_long k1, /* ignore entries below the k1-st diagonal */
347  UF_long k2, /* ignore entries above the k2-nd diagonal */
348  int mode, /* >0: numerical, 0: pattern, <0: pattern (no diag) */
349  /* --------------- */
350  cholmod_common *Common
351 )
352 {
353  return (band (A, k1, k2, mode, FALSE, Common)) ;
354 }
355 
356 
357 /* ========================================================================== */
358 /* === cholmod_band_inplace ================================================= */
359 /* ========================================================================== */
360 
362 (
363  /* ---- input ---- */
364  UF_long k1, /* ignore entries below the k1-st diagonal */
365  UF_long k2, /* ignore entries above the k2-nd diagonal */
366  int mode, /* >0: numerical, 0: pattern, <0: pattern (no diag) */
367  /* ---- in/out --- */
368  cholmod_sparse *A, /* matrix from which entries not in band are removed */
369  /* --------------- */
370  cholmod_common *Common
371 )
372 {
373  return (band (A, k1, k2, mode, TRUE, Common) != NULL) ;
374 }
int CHOLMOD() band_inplace(UF_long k1, UF_long k2, int mode, cholmod_sparse *A, cholmod_common *Common)
#define Int
#define FALSE
#define PRINT1(params)
int CHOLMOD() reallocate_sparse(size_t nznew, cholmod_sparse *A, cholmod_common *Common)
#define RETURN_IF_NULL_COMMON(result)
#define CHOLMOD_PATTERN
#define CHOLMOD(name)
#define MAX(a, b)
#define CHOLMOD_REAL
#define NULL
#define ASSERT(expression)
static cholmod_sparse * band(cholmod_sparse *A, UF_long k1, UF_long k2, int mode, int inplace, cholmod_common *Common)
#define CHOLMOD_INVALID
#define CHOLMOD_OK
cholmod_sparse *CHOLMOD() allocate_sparse(size_t nrow, size_t ncol, size_t nzmax, int sorted, int packed, int stype, int xtype, cholmod_common *Common)
#define RETURN_IF_NULL(A, result)
#define DEBUG(statement)
#define MIN(a, b)
#define UF_long
#define IMPLIES(p, q)
#define ERROR(status, msg)
#define TRUE
#define RETURN_IF_XTYPE_INVALID(A, xtype1, xtype2, result)
#define CHOLMOD_ZOMPLEX