Amesos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
amesos_cholmod_aat.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /* === Core/cholmod_aat ===================================================== */
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*A' or C = A(:,f)*A(:,f)'
15  *
16  * A can be packed or unpacked, sorted or unsorted, but must be stored with
17  * both upper and lower parts (A->stype of zero). C is returned as packed,
18  * C->stype of zero (both upper and lower parts present), and unsorted. See
19  * cholmod_ssmult in the MatrixOps Module for a more general matrix-matrix
20  * multiply.
21  *
22  * You can trivially convert C into a symmetric upper/lower matrix by
23  * changing C->stype = 1 or -1 after calling this routine.
24  *
25  * workspace:
26  * Flag (A->nrow),
27  * Iwork (max (A->nrow, A->ncol)) if fset present,
28  * Iwork (A->nrow) if no fset,
29  * W (A->nrow) if mode > 0,
30  * allocates temporary copy for A'.
31  *
32  * A can be pattern or real. Complex or zomplex cases are supported only
33  * if the mode is <= 0 (in which case the numerical values are ignored).
34  */
35 
37 #include "amesos_cholmod_core.h"
38 
40 (
41  /* ---- input ---- */
42  cholmod_sparse *A, /* input matrix; C=A*A' is constructed */
43  Int *fset, /* subset of 0:(A->ncol)-1 */
44  size_t fsize, /* size of fset */
45  int mode, /* >0: numerical, 0: pattern, <0: pattern (no diag)
46  * -2: pattern only, no diagonal, add 50% + n extra
47  * space to C */
48  /* --------------- */
49  cholmod_common *Common
50 )
51 {
52  double fjt ;
53  double *Ax, *Fx, *Cx, *W ;
54  Int *Ap, *Anz, *Ai, *Fp, *Fi, *Cp, *Ci, *Flag ;
55  cholmod_sparse *C, *F ;
56  Int packed, j, i, pa, paend, pf, pfend, n, mark, cnz, t, p, values, diag,
57  extra ;
58 
59  /* ---------------------------------------------------------------------- */
60  /* check inputs */
61  /* ---------------------------------------------------------------------- */
62 
64  RETURN_IF_NULL (A, NULL) ;
65  values = (mode > 0) && (A->xtype != CHOLMOD_PATTERN) ;
67  values ? CHOLMOD_REAL : CHOLMOD_ZOMPLEX, NULL) ;
68  if (A->stype)
69  {
70  ERROR (CHOLMOD_INVALID, "matrix cannot be symmetric") ;
71  return (NULL) ;
72  }
73  Common->status = CHOLMOD_OK ;
74 
75  /* ---------------------------------------------------------------------- */
76  /* allocate workspace */
77  /* ---------------------------------------------------------------------- */
78 
79  diag = (mode >= 0) ;
80  n = A->nrow ;
81  CHOLMOD(allocate_work) (n, MAX (A->ncol, A->nrow), values ? n : 0, Common) ;
82  if (Common->status < CHOLMOD_OK)
83  {
84  return (NULL) ; /* out of memory */
85  }
86  ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, values ? n : 0, Common)) ;
87 
88  /* ---------------------------------------------------------------------- */
89  /* get inputs */
90  /* ---------------------------------------------------------------------- */
91 
92  ASSERT (CHOLMOD(dump_sparse) (A, "A", Common) >= 0) ;
93 
94  /* get the A matrix */
95  Ap = A->p ;
96  Anz = A->nz ;
97  Ai = A->i ;
98  Ax = A->x ;
99  packed = A->packed ;
100 
101  /* get workspace */
102  W = Common->Xwork ; /* size n, unused if values is FALSE */
103  Flag = Common->Flag ; /* size n, Flag [0..n-1] < mark on input*/
104 
105  /* ---------------------------------------------------------------------- */
106  /* F = A' or A(:,f)' */
107  /* ---------------------------------------------------------------------- */
108 
109  /* workspace: Iwork (nrow if no fset; MAX (nrow,ncol) if fset)*/
110  F = CHOLMOD(ptranspose) (A, values, NULL, fset, fsize, Common) ;
111  if (Common->status < CHOLMOD_OK)
112  {
113  return (NULL) ; /* out of memory */
114  }
115 
116  Fp = F->p ;
117  Fi = F->i ;
118  Fx = F->x ;
119 
120  /* ---------------------------------------------------------------------- */
121  /* count the number of entries in the result C */
122  /* ---------------------------------------------------------------------- */
123 
124  cnz = 0 ;
125  for (j = 0 ; j < n ; j++)
126  {
127  /* clear the Flag array */
128  mark = CHOLMOD(clear_flag) (Common) ;
129 
130  /* exclude the diagonal, if requested */
131  if (!diag)
132  {
133  Flag [j] = mark ;
134  }
135 
136  /* for each nonzero F(t,j) in column j, do: */
137  pfend = Fp [j+1] ;
138  for (pf = Fp [j] ; pf < pfend ; pf++)
139  {
140  /* F(t,j) is nonzero */
141  t = Fi [pf] ;
142 
143  /* add the nonzero pattern of A(:,t) to the pattern of C(:,j) */
144  pa = Ap [t] ;
145  paend = (packed) ? (Ap [t+1]) : (pa + Anz [t]) ;
146  for ( ; pa < paend ; pa++)
147  {
148  i = Ai [pa] ;
149  if (Flag [i] != mark)
150  {
151  Flag [i] = mark ;
152  cnz++ ;
153  }
154  }
155  }
156  if (cnz < 0)
157  {
158  break ; /* integer overflow case */
159  }
160  }
161 
162  extra = (mode == -2) ? (cnz/2 + n) : 0 ;
163 
164  mark = CHOLMOD(clear_flag) (Common) ;
165 
166  /* ---------------------------------------------------------------------- */
167  /* check for integer overflow */
168  /* ---------------------------------------------------------------------- */
169 
170  if (cnz < 0 || (cnz + extra) < 0)
171  {
172  ERROR (CHOLMOD_TOO_LARGE, "problem too large") ;
173  CHOLMOD(clear_flag) (Common) ;
174  CHOLMOD(free_sparse) (&F, Common) ;
175  return (NULL) ; /* problem too large */
176  }
177 
178  /* ---------------------------------------------------------------------- */
179  /* allocate C */
180  /* ---------------------------------------------------------------------- */
181 
182  C = CHOLMOD(allocate_sparse) (n, n, cnz + extra, FALSE, TRUE, 0,
183  values ? A->xtype : CHOLMOD_PATTERN, Common) ;
184  if (Common->status < CHOLMOD_OK)
185  {
186  CHOLMOD(free_sparse) (&F, Common) ;
187  return (NULL) ; /* out of memory */
188  }
189 
190  Cp = C->p ;
191  Ci = C->i ;
192  Cx = C->x ;
193 
194  /* ---------------------------------------------------------------------- */
195  /* C = A*A' */
196  /* ---------------------------------------------------------------------- */
197 
198  cnz = 0 ;
199 
200  if (values)
201  {
202 
203  /* pattern and values */
204  for (j = 0 ; j < n ; j++)
205  {
206  /* clear the Flag array */
207  mark = CHOLMOD(clear_flag) (Common) ;
208 
209  /* start column j of C */
210  Cp [j] = cnz ;
211 
212  /* for each nonzero F(t,j) in column j, do: */
213  pfend = Fp [j+1] ;
214  for (pf = Fp [j] ; pf < pfend ; pf++)
215  {
216  /* F(t,j) is nonzero */
217  t = Fi [pf] ;
218  fjt = Fx [pf] ;
219 
220  /* add the nonzero pattern of A(:,t) to the pattern of C(:,j)
221  * and scatter the values into W */
222  pa = Ap [t] ;
223  paend = (packed) ? (Ap [t+1]) : (pa + Anz [t]) ;
224  for ( ; pa < paend ; pa++)
225  {
226  i = Ai [pa] ;
227  if (Flag [i] != mark)
228  {
229  Flag [i] = mark ;
230  Ci [cnz++] = i ;
231  }
232  W [i] += Ax [pa] * fjt ;
233  }
234  }
235 
236  /* gather the values into C(:,j) */
237  for (p = Cp [j] ; p < cnz ; p++)
238  {
239  i = Ci [p] ;
240  Cx [p] = W [i] ;
241  W [i] = 0 ;
242  }
243  }
244 
245  }
246  else
247  {
248 
249  /* pattern only */
250  for (j = 0 ; j < n ; j++)
251  {
252  /* clear the Flag array */
253  mark = CHOLMOD(clear_flag) (Common) ;
254 
255  /* exclude the diagonal, if requested */
256  if (!diag)
257  {
258  Flag [j] = mark ;
259  }
260 
261  /* start column j of C */
262  Cp [j] = cnz ;
263 
264  /* for each nonzero F(t,j) in column j, do: */
265  pfend = Fp [j+1] ;
266  for (pf = Fp [j] ; pf < pfend ; pf++)
267  {
268  /* F(t,j) is nonzero */
269  t = Fi [pf] ;
270 
271  /* add the nonzero pattern of A(:,t) to the pattern of C(:,j) */
272  pa = Ap [t] ;
273  paend = (packed) ? (Ap [t+1]) : (pa + Anz [t]) ;
274  for ( ; pa < paend ; pa++)
275  {
276  i = Ai [pa] ;
277  if (Flag [i] != mark)
278  {
279  Flag [i] = mark ;
280  Ci [cnz++] = i ;
281  }
282  }
283  }
284  }
285  }
286 
287  Cp [n] = cnz ;
288  ASSERT (IMPLIES (mode != -2, MAX (1,cnz) == C->nzmax)) ;
289 
290  /* ---------------------------------------------------------------------- */
291  /* clear workspace and free temporary matrices and return result */
292  /* ---------------------------------------------------------------------- */
293 
294  CHOLMOD(free_sparse) (&F, Common) ;
295  CHOLMOD(clear_flag) (Common) ;
296  ASSERT (CHOLMOD(dump_work) (TRUE, TRUE, values ? n : 0, Common)) ;
297  DEBUG (i = CHOLMOD(dump_sparse) (C, "aat", Common)) ;
298  ASSERT (IMPLIES (mode < 0, i == 0)) ;
299  return (C) ;
300 }
#define CHOLMOD_TOO_LARGE
#define Int
#define FALSE
#define RETURN_IF_NULL_COMMON(result)
cholmod_sparse *CHOLMOD() aat(cholmod_sparse *A, Int *fset, size_t fsize, int mode, cholmod_common *Common)
int CHOLMOD() dump_work(int flag, int head, UF_long wsize, cholmod_common *Common)
#define CHOLMOD_PATTERN
#define CHOLMOD(name)
#define MAX(a, b)
cholmod_sparse *CHOLMOD() ptranspose(cholmod_sparse *A, int values, Int *Perm, Int *fset, size_t fsize, cholmod_common *Common)
int CHOLMOD() free_sparse(cholmod_sparse **AHandle, cholmod_common *Common)
#define CHOLMOD_REAL
#define NULL
#define ASSERT(expression)
#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)
UF_long CHOLMOD() clear_flag(cholmod_common *Common)
#define IMPLIES(p, q)
int n
#define ERROR(status, msg)
#define TRUE
#define RETURN_IF_XTYPE_INVALID(A, xtype1, xtype2, result)
#define CHOLMOD_ZOMPLEX