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