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