Amesos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
amesos_cholmod_copy.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /* === Core/cholmod_copy ==================================================== */
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 = A, which allocates C and copies A into C, with possible change of
15  * stype. The diagonal can optionally be removed. The numerical entries
16  * can optionally be copied. This routine differs from cholmod_copy_sparse,
17  * which makes an exact copy of a sparse matrix.
18  *
19  * A can be of any type (packed/unpacked, upper/lower/unsymmetric). C is
20  * packed and can be of any stype (upper/lower/unsymmetric), except that if
21  * A is rectangular C can only be unsymmetric. If the stype of A and C
22  * differ, then the appropriate conversion is made.
23  *
24  * Symmetry of A (A->stype):
25  * <0: lower: assume A is symmetric with just tril(A); the rest of A is ignored
26  * 0 unsym: assume A is unsymmetric; consider all entries in A
27  * >0 upper: assume A is symmetric with just triu(A); the rest of A is ignored
28  *
29  * Symmetry of C (stype parameter):
30  * <0 lower: return just tril(C)
31  * 0 unsym: return all of C
32  * >0 upper: return just triu(C)
33  *
34  * In MATLAB: Using cholmod_copy:
35  * ---------- ----------------------------
36  * C = A ; A unsymmetric, C unsymmetric
37  * C = tril (A) ; A unsymmetric, C lower
38  * C = triu (A) ; A unsymmetric, C upper
39  * U = triu (A) ; L = tril (U',-1) ; C = L+U ; A upper, C unsymmetric
40  * C = triu (A)' ; A upper, C lower
41  * C = triu (A) ; A upper, C upper
42  * L = tril (A) ; U = triu (L',1) ; C = L+U ; A lower, C unsymmetric
43  * C = tril (A) ; A lower, C lower
44  * C = tril (A)' ; A lower, C upper
45  *
46  * workspace: Iwork (max (nrow,ncol))
47  *
48  * A can have an xtype of pattern or real. Complex and zomplex cases only
49  * supported when mode <= 0 (in which case the numerical values are ignored).
50  */
51 
53 #include "amesos_cholmod_core.h"
54 
55 
56 /* ========================================================================== */
57 /* === copy_sym_to_unsym ==================================================== */
58 /* ========================================================================== */
59 
60 /* Construct an unsymmetric copy of a symmetric sparse matrix. This does the
61  * work for as C = cholmod_copy (A, 0, mode, Common) when A is symmetric.
62  * In this case, extra space can be added to C.
63  */
64 
66 (
67  /* ---- input ---- */
68  cholmod_sparse *A, /* matrix to copy */
69  int mode, /* >0: numerical, 0: pattern, <0: pattern (no diag)
70  * -2: pattern only, no diagonal, add 50% + n extra
71  * space to C */
72  /* --------------- */
73  cholmod_common *Common
74 )
75 {
76  double aij ;
77  double *Ax, *Cx ;
78  Int *Ap, *Ai, *Anz, *Cp, *Ci, *Wj, *Iwork ;
79  cholmod_sparse *C ;
80  Int nrow, ncol, nz, packed, j, p, pend, i, pc, up, lo, values, diag,
81  astype, extra ;
82 
83  /* ---------------------------------------------------------------------- */
84  /* get inputs */
85  /* ---------------------------------------------------------------------- */
86 
87  nrow = A->nrow ;
88  ncol = A->ncol ;
89  Ap = A->p ;
90  Anz = A->nz ;
91  Ai = A->i ;
92  Ax = A->x ;
93  packed = A->packed ;
94  values = (mode > 0) && (A->xtype != CHOLMOD_PATTERN) ;
95  diag = (mode >= 0) ;
96 
97  astype = SIGN (A->stype) ;
98  up = (astype > 0) ;
99  lo = (astype < 0) ;
100  ASSERT (astype != 0) ;
101 
102  /* ---------------------------------------------------------------------- */
103  /* create an unsymmetric copy of a symmetric matrix */
104  /* ---------------------------------------------------------------------- */
105 
106  Iwork = Common->Iwork ;
107  Wj = Iwork ; /* size ncol (i/i/l) */
108 
109  /* In MATLAB notation, for converting a symmetric/upper matrix:
110  * U = triu (A) ;
111  * L = tril (U',-1) ;
112  * C = L + U ;
113  *
114  * For converting a symmetric/lower matrix to unsymmetric:
115  * L = tril (A) ;
116  * U = triu (L',1) ;
117  * C = L + U ;
118  */
119  ASSERT (up || lo) ;
120  PRINT1 (("copy: convert symmetric to unsym\n")) ;
121 
122  /* count the number of entries in each column of C */
123  for (j = 0 ; j < ncol ; j++)
124  {
125  Wj [j] = 0 ;
126  }
127  for (j = 0 ; j < ncol ; j++)
128  {
129  p = Ap [j] ;
130  pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ;
131  for ( ; p < pend ; p++)
132  {
133  i = Ai [p] ;
134  if (i == j)
135  {
136  /* the diagonal entry A(i,i) will appear just once
137  * (unless it is excluded with mode < 0) */
138  if (diag)
139  {
140  Wj [j]++ ;
141  }
142  }
143  else if ((up && i < j) || (lo && i > j))
144  {
145  /* upper case: A(i,j) is in the strictly upper part;
146  * A(j,i) will be added to the strictly lower part of C.
147  * lower case is the opposite. */
148  Wj [j]++ ;
149  Wj [i]++ ;
150  }
151  }
152  }
153  nz = 0 ;
154  for (j = 0 ; j < ncol ; j++)
155  {
156  nz += Wj [j] ;
157  }
158 
159  extra = (mode == -2) ? (nz/2 + ncol) : 0 ;
160 
161  /* allocate C. C is sorted if and only if A is sorted */
162  C = CHOLMOD(allocate_sparse) (nrow, ncol, nz + extra, A->sorted, TRUE, 0,
163  values ? A->xtype : CHOLMOD_PATTERN, Common) ;
164  if (Common->status < CHOLMOD_OK)
165  {
166  return (NULL) ;
167  }
168 
169  Cp = C->p ;
170  Ci = C->i ;
171  Cx = C->x ;
172 
173  /* construct the column pointers for C */
174  p = 0 ;
175  for (j = 0 ; j < ncol ; j++)
176  {
177  Cp [j] = p ;
178  p += Wj [j] ;
179  }
180  Cp [ncol] = p ;
181  for (j = 0 ; j < ncol ; j++)
182  {
183  Wj [j] = Cp [j] ;
184  }
185 
186  /* construct C */
187  if (values)
188  {
189 
190  /* pattern and values */
191  ASSERT (diag) ;
192  for (j = 0 ; j < ncol ; j++)
193  {
194  p = Ap [j] ;
195  pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ;
196  for ( ; p < pend ; p++)
197  {
198  i = Ai [p] ;
199  aij = Ax [p] ;
200  if (i == j)
201  {
202  /* add diagonal entry A(i,i) to column i */
203  pc = Wj [i]++ ;
204  Ci [pc] = i ;
205  Cx [pc] = aij ;
206  }
207  else if ((up && i < j) || (lo && i > j))
208  {
209  /* add A(i,j) to column j */
210  pc = Wj [j]++ ;
211  Ci [pc] = i ;
212  Cx [pc] = aij ;
213  /* add A(j,i) to column i */
214  pc = Wj [i]++ ;
215  Ci [pc] = j ;
216  Cx [pc] = aij ;
217  }
218  }
219  }
220 
221  }
222  else
223  {
224 
225  /* pattern only, possibly excluding the diagonal */
226  for (j = 0 ; j < ncol ; j++)
227  {
228  p = Ap [j] ;
229  pend = (packed) ? (Ap [j+1]) : (p + Anz [j]) ;
230  for ( ; p < pend ; p++)
231  {
232  i = Ai [p] ;
233  if (i == j)
234  {
235  /* add diagonal entry A(i,i) to column i
236  * (unless it is excluded with mode < 0) */
237  if (diag)
238  {
239  Ci [Wj [i]++] = i ;
240  }
241  }
242  else if ((up && i < j) || (lo && i > j))
243  {
244  /* add A(i,j) to column j */
245  Ci [Wj [j]++] = i ;
246  /* add A(j,i) to column i */
247  Ci [Wj [i]++] = j ;
248  }
249  }
250  }
251  }
252 
253  /* ---------------------------------------------------------------------- */
254  /* return the result */
255  /* ---------------------------------------------------------------------- */
256 
257  DEBUG (i = CHOLMOD(dump_sparse) (C, "copy_sym_to_unsym", Common)) ;
258  PRINT1 (("mode %d nnzdiag "ID"\n", mode, i)) ;
259  ASSERT (IMPLIES (mode < 0, i == 0)) ;
260  return (C) ;
261 }
262 
263 
264 /* ========================================================================== */
265 /* === cholmod_copy ========================================================= */
266 /* ========================================================================== */
267 
269 (
270  /* ---- input ---- */
271  cholmod_sparse *A, /* matrix to copy */
272  int stype, /* requested stype of C */
273  int mode, /* >0: numerical, 0: pattern, <0: pattern (no diag) */
274  /* --------------- */
275  cholmod_common *Common
276 )
277 {
278  cholmod_sparse *C ;
279  Int nrow, ncol, up, lo, values, diag, astype ;
280 
281  /* ---------------------------------------------------------------------- */
282  /* check inputs */
283  /* ---------------------------------------------------------------------- */
284 
286  RETURN_IF_NULL (A, NULL) ;
287  values = (mode > 0) && (A->xtype != CHOLMOD_PATTERN) ;
289  values ? CHOLMOD_REAL : CHOLMOD_ZOMPLEX, NULL) ;
290  nrow = A->nrow ;
291  ncol = A->ncol ;
292  if ((stype || A->stype) && nrow != ncol)
293  {
294  /* inputs invalid */
295  ERROR (CHOLMOD_INVALID, "matrix invalid") ;
296  return (NULL) ;
297  }
298  Common->status = CHOLMOD_OK ;
299 
300  /* ---------------------------------------------------------------------- */
301  /* allocate workspace */
302  /* ---------------------------------------------------------------------- */
303 
304  CHOLMOD(allocate_work) (0, MAX (nrow,ncol), 0, Common) ;
305  if (Common->status < CHOLMOD_OK)
306  {
307  /* out of memory */
308  return (NULL) ;
309  }
310 
311  /* ---------------------------------------------------------------------- */
312  /* get inputs */
313  /* ---------------------------------------------------------------------- */
314 
315  diag = (mode >= 0) ;
316  astype = SIGN (A->stype) ;
317  stype = SIGN (stype) ;
318  up = (astype > 0) ;
319  lo = (astype < 0) ;
320 
321  /* ---------------------------------------------------------------------- */
322  /* copy the matrix */
323  /* ---------------------------------------------------------------------- */
324 
325  if (astype == stype)
326  {
327 
328  /* ------------------------------------------------------------------ */
329  /* symmetry of A and C are the same */
330  /* ------------------------------------------------------------------ */
331 
332  /* copy A into C, keeping the same symmetry. If A is symmetric
333  * entries in the ignored part of A are not copied into C */
334  C = CHOLMOD(band) (A, -nrow, ncol, mode, Common) ;
335 
336  }
337  else if (!astype)
338  {
339 
340  /* ------------------------------------------------------------------ */
341  /* convert unsymmetric matrix A into a symmetric matrix C */
342  /* ------------------------------------------------------------------ */
343 
344  if (stype > 0)
345  {
346  /* C = triu (A) */
347  C = CHOLMOD(band) (A, 0, ncol, mode, Common) ;
348  }
349  else
350  {
351  /* C = tril (A) */
352  C = CHOLMOD(band) (A, -nrow, 0, mode, Common) ;
353  }
354  if (Common->status < CHOLMOD_OK)
355  {
356  /* out of memory */
357  return (NULL) ;
358  }
359  C->stype = stype ;
360 
361  }
362  else if (astype == -stype)
363  {
364 
365  /* ------------------------------------------------------------------ */
366  /* transpose a symmetric matrix */
367  /* ------------------------------------------------------------------ */
368 
369  /* converting upper to lower or lower to upper */
370  /* workspace: Iwork (nrow) */
371  C = CHOLMOD(transpose) (A, values, Common) ;
372  if (!diag)
373  {
374  /* remove diagonal, if requested */
375  CHOLMOD(band_inplace) (-nrow, ncol, -1, C, Common) ;
376  }
377 
378  }
379  else
380  {
381 
382  /* ------------------------------------------------------------------ */
383  /* create an unsymmetric copy of a symmetric matrix */
384  /* ------------------------------------------------------------------ */
385 
386  C = copy_sym_to_unsym (A, mode, Common) ;
387  }
388 
389  /* ---------------------------------------------------------------------- */
390  /* return if error */
391  /* ---------------------------------------------------------------------- */
392 
393  if (Common->status < CHOLMOD_OK)
394  {
395  /* out of memory */
396  return (NULL) ;
397  }
398 
399  /* ---------------------------------------------------------------------- */
400  /* return the result */
401  /* ---------------------------------------------------------------------- */
402 
403  DEBUG (diag = CHOLMOD(dump_sparse) (C, "copy", Common)) ;
404  PRINT1 (("mode %d nnzdiag "ID"\n", mode, diag)) ;
405  ASSERT (IMPLIES (mode < 0, diag == 0)) ;
406  return (C) ;
407 }
int CHOLMOD() band_inplace(UF_long k1, UF_long k2, int mode, cholmod_sparse *A, cholmod_common *Common)
#define Int
#define PRINT1(params)
cholmod_sparse *CHOLMOD() transpose(cholmod_sparse *A, int values, cholmod_common *Common)
#define RETURN_IF_NULL_COMMON(result)
static cholmod_sparse * copy_sym_to_unsym(cholmod_sparse *A, int mode, cholmod_common *Common)
#define SIGN(x)
#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 ID
#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)
int CHOLMOD() allocate_work(size_t nrow, size_t iworksize, size_t xworksize, cholmod_common *Common)
#define RETURN_IF_NULL(A, result)
#define DEBUG(statement)
#define IMPLIES(p, q)
#define ERROR(status, msg)
#define TRUE
#define RETURN_IF_XTYPE_INVALID(A, xtype1, xtype2, result)
#define CHOLMOD_ZOMPLEX
cholmod_sparse *CHOLMOD() copy(cholmod_sparse *A, int stype, int mode, cholmod_common *Common)