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