Amesos Package Browser (Single Doxygen Collection)  Development
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
amesos_cholmod_l_add.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /* === Core/cholmod_add ===================================================== */
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 = alpha*A + beta*B, or spones(A+B). Result is packed, with sorted or
15  * unsorted columns. This routine is much faster and takes less memory if C
16  * is allowed to have unsorted columns.
17  *
18  * If A and B are both symmetric (in upper form) then C is the same. Likewise,
19  * if A and B are both symmetric (in lower form) then C is the same.
20  * Otherwise, C is unsymmetric. A and B must have the same dimension.
21  *
22  * workspace: Flag (nrow), W (nrow) if values, Iwork (max (nrow,ncol)).
23  * allocates temporary copies for A and B if they are symmetric.
24  * allocates temporary copy of C if it is to be returned sorted.
25  *
26  * A and B can have an xtype of pattern or real. Complex or zomplex cases
27  * are supported only if the "values" input parameter is FALSE.
28  */
29 
30 /* This file should make the long int version of CHOLMOD */
31 #define DLONG 1
32 
34 #include "amesos_cholmod_core.h"
35 
37 (
38  /* ---- input ---- */
39  cholmod_sparse *A, /* matrix to add */
40  cholmod_sparse *B, /* matrix to add */
41  double alpha [2], /* scale factor for A */
42  double beta [2], /* scale factor for B */
43  int values, /* if TRUE compute the numerical values of C */
44  int sorted, /* if TRUE, sort columns of C */
45  /* --------------- */
46  cholmod_common *Common
47 )
48 {
49  double *Ax, *Bx, *Cx, *W ;
50  Int apacked, up, lo, nrow, ncol, bpacked, nzmax, pa, paend, pb, pbend, i,
51  j, p, mark, nz ;
52  Int *Ap, *Ai, *Anz, *Bp, *Bi, *Bnz, *Flag, *Cp, *Ci ;
53  cholmod_sparse *A2, *B2, *C ;
54 
55  /* ---------------------------------------------------------------------- */
56  /* check inputs */
57  /* ---------------------------------------------------------------------- */
58 
60  RETURN_IF_NULL (A, NULL) ;
61  RETURN_IF_NULL (B, NULL) ;
62  values = values &&
63  (A->xtype != CHOLMOD_PATTERN) && (B->xtype != CHOLMOD_PATTERN) ;
65  values ? CHOLMOD_REAL : CHOLMOD_ZOMPLEX, NULL) ;
67  values ? CHOLMOD_REAL : CHOLMOD_ZOMPLEX, NULL) ;
68  if (A->nrow != B->nrow || A->ncol != B->ncol)
69  {
70  /* A and B must have the same dimensions */
71  ERROR (CHOLMOD_INVALID, "A and B dimesions do not match") ;
72  return (NULL) ;
73  }
74  /* A and B must have the same numerical type if values is TRUE (both must
75  * be CHOLMOD_REAL, this is implicitly checked above) */
76 
77  Common->status = CHOLMOD_OK ;
78 
79  /* ---------------------------------------------------------------------- */
80  /* allocate workspace */
81  /* ---------------------------------------------------------------------- */
82 
83  nrow = A->nrow ;
84  ncol = A->ncol ;
85  CHOLMOD(allocate_work) (nrow, MAX (nrow,ncol), values ? nrow : 0, Common) ;
86  if (Common->status < CHOLMOD_OK)
87  {
88  return (NULL) ; /* out of memory */
89  }
90 
91  /* ---------------------------------------------------------------------- */
92  /* get inputs */
93  /* ---------------------------------------------------------------------- */
94 
95  if (nrow <= 1)
96  {
97  /* C will be implicitly sorted, so no need to sort it here */
98  sorted = FALSE ;
99  }
100 
101  /* convert A or B to unsymmetric, if necessary */
102  A2 = NULL ;
103  B2 = NULL ;
104 
105  if (A->stype != B->stype)
106  {
107  if (A->stype)
108  {
109  /* workspace: Iwork (max (nrow,ncol)) */
110  A2 = CHOLMOD(copy) (A, 0, values, Common) ;
111  if (Common->status < CHOLMOD_OK)
112  {
113  return (NULL) ; /* out of memory */
114  }
115  A = A2 ;
116  }
117  if (B->stype)
118  {
119  /* workspace: Iwork (max (nrow,ncol)) */
120  B2 = CHOLMOD(copy) (B, 0, values, Common) ;
121  if (Common->status < CHOLMOD_OK)
122  {
123  CHOLMOD(free_sparse) (&A2, Common) ;
124  return (NULL) ; /* out of memory */
125  }
126  B = B2 ;
127  }
128  }
129 
130  /* get the A matrix */
131  ASSERT (A->stype == B->stype) ;
132  up = (A->stype > 0) ;
133  lo = (A->stype < 0) ;
134 
135  Ap = A->p ;
136  Anz = A->nz ;
137  Ai = A->i ;
138  Ax = A->x ;
139  apacked = A->packed ;
140 
141  /* get the B matrix */
142  Bp = B->p ;
143  Bnz = B->nz ;
144  Bi = B->i ;
145  Bx = B->x ;
146  bpacked = B->packed ;
147 
148  /* get workspace */
149  W = Common->Xwork ; /* size nrow, used if values is TRUE */
150  Flag = Common->Flag ; /* size nrow, Flag [0..nrow-1] < mark on input */
151 
152  /* ---------------------------------------------------------------------- */
153  /* allocate the result C */
154  /* ---------------------------------------------------------------------- */
155 
156  /* If integer overflow occurs, nzmax < 0 and the allocate fails properly
157  * (likewise in most other matrix manipulation routines). */
158  nzmax = A->nzmax + B->nzmax ;
159  C = CHOLMOD(allocate_sparse) (nrow, ncol, nzmax, FALSE, TRUE,
160  SIGN (A->stype), values ? A->xtype : CHOLMOD_PATTERN, Common) ;
161  if (Common->status < CHOLMOD_OK)
162  {
163  CHOLMOD(free_sparse) (&A2, Common) ;
164  CHOLMOD(free_sparse) (&B2, Common) ;
165  return (NULL) ; /* out of memory */
166  }
167 
168  Cp = C->p ;
169  Ci = C->i ;
170  Cx = C->x ;
171 
172  /* ---------------------------------------------------------------------- */
173  /* compute C = alpha*A + beta*B */
174  /* ---------------------------------------------------------------------- */
175 
176  nz = 0 ;
177  for (j = 0 ; j < ncol ; j++)
178  {
179  Cp [j] = nz ;
180 
181  /* clear the Flag array */
182  mark = CHOLMOD(clear_flag) (Common) ;
183 
184  /* scatter B into W */
185  pb = Bp [j] ;
186  pbend = (bpacked) ? (Bp [j+1]) : (pb + Bnz [j]) ;
187  for (p = pb ; p < pbend ; p++)
188  {
189  i = Bi [p] ;
190  if ((up && i > j) || (lo && i < j))
191  {
192  continue ;
193  }
194  Flag [i] = mark ;
195  if (values)
196  {
197  W [i] = beta [0] * Bx [p] ;
198  }
199  }
200 
201  /* add A and gather from W into C(:,j) */
202  pa = Ap [j] ;
203  paend = (apacked) ? (Ap [j+1]) : (pa + Anz [j]) ;
204  for (p = pa ; p < paend ; p++)
205  {
206  i = Ai [p] ;
207  if ((up && i > j) || (lo && i < j))
208  {
209  continue ;
210  }
211  Flag [i] = EMPTY ;
212  Ci [nz] = i ;
213  if (values)
214  {
215  Cx [nz] = W [i] + alpha [0] * Ax [p] ;
216  W [i] = 0 ;
217  }
218  nz++ ;
219  }
220 
221  /* gather remaining entries into C(:,j), using pattern of B */
222  for (p = pb ; p < pbend ; p++)
223  {
224  i = Bi [p] ;
225  if ((up && i > j) || (lo && i < j))
226  {
227  continue ;
228  }
229  if (Flag [i] == mark)
230  {
231  Ci [nz] = i ;
232  if (values)
233  {
234  Cx [nz] = W [i] ;
235  W [i] = 0 ;
236  }
237  nz++ ;
238  }
239  }
240  }
241 
242  Cp [ncol] = nz ;
243 
244  /* ---------------------------------------------------------------------- */
245  /* reduce C in size and free temporary matrices */
246  /* ---------------------------------------------------------------------- */
247 
248  ASSERT (MAX (1,nz) <= C->nzmax) ;
249  CHOLMOD(reallocate_sparse) (nz, C, Common) ;
250  ASSERT (Common->status >= CHOLMOD_OK) ;
251 
252  /* clear the Flag array */
253  mark = CHOLMOD(clear_flag) (Common) ;
254 
255  CHOLMOD(free_sparse) (&A2, Common) ;
256  CHOLMOD(free_sparse) (&B2, Common) ;
257 
258  /* ---------------------------------------------------------------------- */
259  /* sort C, if requested */
260  /* ---------------------------------------------------------------------- */
261 
262  if (sorted)
263  {
264  /* workspace: Iwork (max (nrow,ncol)) */
265  if (!CHOLMOD(sort) (C, Common))
266  {
267  CHOLMOD(free_sparse) (&C, Common) ;
268  if (Common->status < CHOLMOD_OK)
269  {
270  return (NULL) ; /* out of memory */
271  }
272  }
273  }
274 
275  /* ---------------------------------------------------------------------- */
276  /* return result */
277  /* ---------------------------------------------------------------------- */
278 
279  ASSERT (CHOLMOD(dump_sparse) (C, "add", Common) >= 0) ;
280  return (C) ;
281 }
#define EMPTY
#define Int
#define FALSE
int CHOLMOD() reallocate_sparse(size_t nznew, cholmod_sparse *A, cholmod_common *Common)
#define RETURN_IF_NULL_COMMON(result)
#define SIGN(x)
#define CHOLMOD_PATTERN
#define CHOLMOD(name)
#define MAX(a, b)
int CHOLMOD() sort(cholmod_sparse *A, cholmod_common *Common)
int CHOLMOD() free_sparse(cholmod_sparse **AHandle, cholmod_common *Common)
#define CHOLMOD_REAL
#define NULL
#define ASSERT(expression)
cholmod_sparse *CHOLMOD() add(cholmod_sparse *A, cholmod_sparse *B, double alpha[2], double beta[2], int values, int sorted, 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)
int CHOLMOD() allocate_work(size_t nrow, size_t iworksize, size_t xworksize, cholmod_common *Common)
#define RETURN_IF_NULL(A, result)
UF_long CHOLMOD() clear_flag(cholmod_common *Common)
#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)