Amesos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
amesos_cholmod_sparse.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /* === Core/cholmod_sparse ================================================== */
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 /* Core utility routines for the cholmod_sparse object:
15  *
16  * A sparse matrix is held in compressed column form. In the basic type
17  * ("packed", which corresponds to a MATLAB sparse matrix), an n-by-n matrix
18  * with nz entries is held in three arrays: p of size n+1, i of size nz, and x
19  * of size nz. Row indices of column j are held in i [p [j] ... p [j+1]-1] and
20  * in the same locations in x. There may be no duplicate entries in a column.
21  * Row indices in each column may be sorted or unsorted (CHOLMOD keeps track).
22  *
23  * Primary routines:
24  * -----------------
25  * cholmod_allocate_sparse allocate a sparse matrix
26  * cholmod_free_sparse free a sparse matrix
27  *
28  * Secondary routines:
29  * -------------------
30  * cholmod_reallocate_sparse change the size (# entries) of sparse matrix
31  * cholmod_nnz number of nonzeros in a sparse matrix
32  * cholmod_speye sparse identity matrix
33  * cholmod_spzeros sparse zero matrix
34  * cholmod_copy_sparse create a copy of a sparse matrix
35  *
36  * All xtypes are supported (pattern, real, complex, and zomplex)
37  */
38 
40 #include "amesos_cholmod_core.h"
41 
42 
43 /* ========================================================================== */
44 /* === cholmod_allocate_sparse ============================================== */
45 /* ========================================================================== */
46 
47 /* Allocate space for a matrix. A->i and A->x are not initialized. A->p
48  * (and A->nz if A is not packed) are set to zero, so a matrix containing no
49  * entries (all zero) is returned. See also cholmod_spzeros.
50  *
51  * workspace: none
52  */
53 
55 (
56  /* ---- input ---- */
57  size_t nrow, /* # of rows of A */
58  size_t ncol, /* # of columns of A */
59  size_t nzmax, /* max # of nonzeros of A */
60  int sorted, /* TRUE if columns of A sorted, FALSE otherwise */
61  int packed, /* TRUE if A will be packed, FALSE otherwise */
62  int stype, /* stype of A */
63  int xtype, /* CHOLMOD_PATTERN, _REAL, _COMPLEX, or _ZOMPLEX */
64  /* --------------- */
65  cholmod_common *Common
66 )
67 {
68  cholmod_sparse *A ;
69  Int *Ap, *Anz ;
70  size_t nzmax0 ;
71  Int j ;
72  int ok = TRUE ;
73 
74  /* ---------------------------------------------------------------------- */
75  /* get inputs */
76  /* ---------------------------------------------------------------------- */
77 
79  if (stype != 0 && nrow != ncol)
80  {
81  ERROR (CHOLMOD_INVALID, "rectangular matrix with stype != 0 invalid") ;
82  return (NULL) ;
83  }
84  if (xtype < CHOLMOD_PATTERN || xtype > CHOLMOD_ZOMPLEX)
85  {
86  ERROR (CHOLMOD_INVALID, "xtype invalid") ;
87  return (NULL) ;
88  }
89  /* ensure the dimensions do not cause integer overflow */
90  (void) CHOLMOD(add_size_t) (ncol, 2, &ok) ;
91  if (!ok || nrow > Int_max || ncol > Int_max || nzmax > Int_max)
92  {
93  ERROR (CHOLMOD_TOO_LARGE, "problem too large") ;
94  return (NULL) ;
95  }
96  Common->status = CHOLMOD_OK ;
97 
98  /* ---------------------------------------------------------------------- */
99  /* allocate header */
100  /* ---------------------------------------------------------------------- */
101 
102  A = CHOLMOD(malloc) (sizeof (cholmod_sparse), 1, Common) ;
103  if (Common->status < CHOLMOD_OK)
104  {
105  return (NULL) ; /* out of memory */
106  }
107  PRINT1 (("cholmod_allocate_sparse %d-by-%d nzmax %d sorted %d packed %d"
108  " xtype %d\n", nrow, ncol, nzmax, sorted, packed, xtype)) ;
109 
110  nzmax = MAX (1, nzmax) ;
111 
112  A->nrow = nrow ;
113  A->ncol = ncol ;
114  A->nzmax = nzmax ;
115  A->packed = packed ; /* default is packed (A->nz not present) */
116  A->stype = stype ;
117  A->itype = ITYPE ;
118  A->xtype = xtype ;
119  A->dtype = DTYPE ;
120 
121  A->nz = NULL ;
122  A->p = NULL ;
123  A->i = NULL ;
124  A->x = NULL ;
125  A->z = NULL ;
126 
127  /* A 1-by-m matrix always has sorted columns */
128  A->sorted = (nrow <= 1) ? TRUE : sorted ;
129 
130  /* ---------------------------------------------------------------------- */
131  /* allocate the matrix itself */
132  /* ---------------------------------------------------------------------- */
133 
134  /* allocate O(ncol) space */
135  A->p = CHOLMOD(malloc) (((size_t) ncol)+1, sizeof (Int), Common) ;
136  if (!packed)
137  {
138  A->nz = CHOLMOD(malloc) (ncol, sizeof (Int), Common) ;
139  }
140 
141  /* allocate O(nz) space */
142  nzmax0 = 0 ;
143  CHOLMOD(realloc_multiple) (nzmax, 1, xtype, &(A->i), NULL, &(A->x), &(A->z),
144  &nzmax0, Common) ;
145 
146  if (Common->status < CHOLMOD_OK)
147  {
148  CHOLMOD(free_sparse) (&A, Common) ;
149  return (NULL) ; /* out of memory */
150  }
151 
152  /* ---------------------------------------------------------------------- */
153  /* initialize A->p and A->nz so that A is an empty matrix */
154  /* ---------------------------------------------------------------------- */
155 
156  Ap = A->p ;
157  for (j = 0 ; j <= (Int) ncol ; j++)
158  {
159  Ap [j] = 0 ;
160  }
161  if (!packed)
162  {
163  Anz = A->nz ;
164  for (j = 0 ; j < (Int) ncol ; j++)
165  {
166  Anz [j] = 0 ;
167  }
168  }
169  return (A) ;
170 }
171 
172 
173 /* ========================================================================== */
174 /* === cholmod_free_sparse ================================================== */
175 /* ========================================================================== */
176 
177 /* free a sparse matrix
178  *
179  * workspace: none
180  */
181 
182 int CHOLMOD(free_sparse)
183 (
184  /* ---- in/out --- */
185  cholmod_sparse **AHandle, /* matrix to deallocate, NULL on output */
186  /* --------------- */
187  cholmod_common *Common
188 )
189 {
190  Int n, nz ;
191  cholmod_sparse *A ;
192 
194 
195  if (AHandle == NULL)
196  {
197  /* nothing to do */
198  return (TRUE) ;
199  }
200  A = *AHandle ;
201  if (A == NULL)
202  {
203  /* nothing to do */
204  return (TRUE) ;
205  }
206  n = A->ncol ;
207  nz = A->nzmax ;
208  A->p = CHOLMOD(free) (n+1, sizeof (Int), A->p, Common) ;
209  A->i = CHOLMOD(free) (nz, sizeof (Int), A->i, Common) ;
210  A->nz = CHOLMOD(free) (n, sizeof (Int), A->nz, Common) ;
211 
212  switch (A->xtype)
213  {
214  case CHOLMOD_REAL:
215  A->x = CHOLMOD(free) (nz, sizeof (double), A->x, Common) ;
216  break ;
217 
218  case CHOLMOD_COMPLEX:
219  A->x = CHOLMOD(free) (nz, 2*sizeof (double), A->x, Common) ;
220  break ;
221 
222  case CHOLMOD_ZOMPLEX:
223  A->x = CHOLMOD(free) (nz, sizeof (double), A->x, Common) ;
224  A->z = CHOLMOD(free) (nz, sizeof (double), A->z, Common) ;
225  break ;
226  }
227 
228  *AHandle = CHOLMOD(free) (1, sizeof (cholmod_sparse), (*AHandle), Common) ;
229  return (TRUE) ;
230 }
231 
232 
233 /* ========================================================================== */
234 /* === cholmod_reallocate_sparse ============================================ */
235 /* ========================================================================== */
236 
237 /* Change the size of A->i, A->x, and A->z, or allocate them if their current
238  * size is zero. A->x and A->z are not modified if A->xtype is CHOLMOD_PATTERN.
239  * A->z is not modified unless A->xtype is CHOLMOD_ZOMPLEX.
240  *
241  * workspace: none
242  */
243 
245 (
246  /* ---- input ---- */
247  size_t nznew, /* new # of entries in A */
248  /* ---- in/out --- */
249  cholmod_sparse *A, /* matrix to reallocate */
250  /* --------------- */
251  cholmod_common *Common
252 )
253 {
254 
255  /* ---------------------------------------------------------------------- */
256  /* get inputs */
257  /* ---------------------------------------------------------------------- */
258 
260  RETURN_IF_NULL (A, FALSE) ;
262  Common->status = CHOLMOD_OK ;
263  PRINT1 (("realloc matrix %d to %d, xtype: %d\n",
264  A->nzmax, nznew, A->xtype)) ;
265 
266  /* ---------------------------------------------------------------------- */
267  /* resize the matrix */
268  /* ---------------------------------------------------------------------- */
269 
270  CHOLMOD(realloc_multiple) (MAX (1,nznew), 1, A->xtype, &(A->i), NULL,
271  &(A->x), &(A->z), &(A->nzmax), Common) ;
272 
273  return (Common->status == CHOLMOD_OK) ;
274 }
275 
276 
277 /* ========================================================================== */
278 /* === cholmod_speye ======================================================== */
279 /* ========================================================================== */
280 
281 /* Return a sparse identity matrix. */
282 
284 (
285  /* ---- input ---- */
286  size_t nrow, /* # of rows of A */
287  size_t ncol, /* # of columns of A */
288  int xtype, /* CHOLMOD_PATTERN, _REAL, _COMPLEX, or _ZOMPLEX */
289  /* --------------- */
290  cholmod_common *Common
291 )
292 {
293  double *Ax, *Az ;
294  cholmod_sparse *A ;
295  Int *Ap, *Ai ;
296  Int j, n ;
297 
298  /* ---------------------------------------------------------------------- */
299  /* get inputs */
300  /* ---------------------------------------------------------------------- */
301 
303  Common->status = CHOLMOD_OK ;
304 
305  /* ---------------------------------------------------------------------- */
306  /* allocate the matrix */
307  /* ---------------------------------------------------------------------- */
308 
309  n = MIN (nrow, ncol) ;
310  A = CHOLMOD(allocate_sparse) (nrow, ncol, n, TRUE, TRUE, 0, xtype,
311  Common) ;
312 
313  if (Common->status < CHOLMOD_OK)
314  {
315  return (NULL) ; /* out of memory or inputs invalid */
316  }
317 
318  /* ---------------------------------------------------------------------- */
319  /* create the identity matrix */
320  /* ---------------------------------------------------------------------- */
321 
322  Ap = A->p ;
323  Ai = A->i ;
324  Ax = A->x ;
325  Az = A->z ;
326 
327  for (j = 0 ; j < n ; j++)
328  {
329  Ap [j] = j ;
330  }
331  for (j = n ; j <= ((Int) ncol) ; j++)
332  {
333  Ap [j] = n ;
334  }
335  for (j = 0 ; j < n ; j++)
336  {
337  Ai [j] = j ;
338  }
339 
340  switch (xtype)
341  {
342  case CHOLMOD_REAL:
343  for (j = 0 ; j < n ; j++)
344  {
345  Ax [j] = 1 ;
346  }
347  break ;
348 
349  case CHOLMOD_COMPLEX:
350  for (j = 0 ; j < n ; j++)
351  {
352  Ax [2*j ] = 1 ;
353  Ax [2*j+1] = 0 ;
354  }
355  break ;
356 
357  case CHOLMOD_ZOMPLEX:
358  for (j = 0 ; j < n ; j++)
359  {
360  Ax [j] = 1 ;
361  }
362  for (j = 0 ; j < n ; j++)
363  {
364  Az [j] = 0 ;
365  }
366  break ;
367  }
368 
369  return (A) ;
370 }
371 
372 
373 /* ========================================================================== */
374 /* === cholmod_spzeros ====================================================== */
375 /* ========================================================================== */
376 
377 /* Return a sparse zero matrix. */
378 
380 (
381  /* ---- input ---- */
382  size_t nrow, /* # of rows of A */
383  size_t ncol, /* # of columns of A */
384  size_t nzmax, /* max # of nonzeros of A */
385  int xtype, /* CHOLMOD_PATTERN, _REAL, _COMPLEX, or _ZOMPLEX */
386  /* --------------- */
387  cholmod_common *Common
388 )
389 {
390 
391  /* ---------------------------------------------------------------------- */
392  /* get inputs */
393  /* ---------------------------------------------------------------------- */
394 
396  Common->status = CHOLMOD_OK ;
397 
398  /* ---------------------------------------------------------------------- */
399  /* allocate the matrix */
400  /* ---------------------------------------------------------------------- */
401 
402  return (CHOLMOD(allocate_sparse) (nrow, ncol, nzmax, TRUE, TRUE, 0, xtype,
403  Common)) ;
404 }
405 
406 
407 /* ========================================================================== */
408 /* === cholmod_nnz ========================================================== */
409 /* ========================================================================== */
410 
411 /* Return the number of entries in a sparse matrix.
412  *
413  * workspace: none
414  * integer overflow cannot occur, since the matrix is already allocated.
415  */
416 
418 (
419  /* ---- input ---- */
420  cholmod_sparse *A,
421  /* --------------- */
422  cholmod_common *Common
423 )
424 {
425  Int *Ap, *Anz ;
426  size_t nz ;
427  Int j, ncol ;
428 
429  /* ---------------------------------------------------------------------- */
430  /* get inputs */
431  /* ---------------------------------------------------------------------- */
432 
434  RETURN_IF_NULL (A, EMPTY) ;
436  Common->status = CHOLMOD_OK ;
437 
438  /* ---------------------------------------------------------------------- */
439  /* return nnz (A) */
440  /* ---------------------------------------------------------------------- */
441 
442  ncol = A->ncol ;
443  if (A->packed)
444  {
445  Ap = A->p ;
446  RETURN_IF_NULL (Ap, EMPTY) ;
447  nz = Ap [ncol] ;
448  }
449  else
450  {
451  Anz = A->nz ;
452  RETURN_IF_NULL (Anz, EMPTY) ;
453  nz = 0 ;
454  for (j = 0 ; j < ncol ; j++)
455  {
456  nz += MAX (0, Anz [j]) ;
457  }
458  }
459  return (nz) ;
460 }
461 
462 
463 /* ========================================================================== */
464 /* === cholmod_copy_sparse ================================================== */
465 /* ========================================================================== */
466 
467 /* C = A. Create an exact copy of a sparse matrix, with one exception.
468  * Entries in unused space are not copied (they might not be initialized,
469  * and copying them would cause program checkers such as purify and
470  * valgrind to complain). The xtype of the resulting matrix C is the same as
471  * the xtype of the input matrix A.
472  *
473  * See also Core/cholmod_copy, which copies a matrix with possible changes
474  * in stype, presence of diagonal entries, pattern vs. numerical values,
475  * real and/or imaginary parts, and so on.
476  */
477 
479 (
480  /* ---- input ---- */
481  cholmod_sparse *A, /* matrix to copy */
482  /* --------------- */
483  cholmod_common *Common
484 )
485 {
486  double *Ax, *Cx, *Az, *Cz ;
487  Int *Ap, *Ai, *Anz, *Cp, *Ci, *Cnz ;
488  cholmod_sparse *C ;
489  Int p, pend, j, ncol, packed, nzmax, nz, xtype ;
490 
491  /* ---------------------------------------------------------------------- */
492  /* check inputs */
493  /* ---------------------------------------------------------------------- */
494 
496  RETURN_IF_NULL (A, NULL) ;
498  if (A->stype != 0 && A->nrow != A->ncol)
499  {
500  ERROR (CHOLMOD_INVALID, "rectangular matrix with stype != 0 invalid") ;
501  return (NULL) ;
502  }
503  Common->status = CHOLMOD_OK ;
504  ASSERT (CHOLMOD(dump_sparse) (A, "A original", Common) >= 0) ;
505 
506  /* ---------------------------------------------------------------------- */
507  /* get inputs */
508  /* ---------------------------------------------------------------------- */
509 
510  ncol = A->ncol ;
511  nzmax = A->nzmax ;
512  packed = A->packed ;
513  Ap = A->p ;
514  Ai = A->i ;
515  Ax = A->x ;
516  Az = A->z ;
517  Anz = A->nz ;
518  xtype = A->xtype ;
519 
520  /* ---------------------------------------------------------------------- */
521  /* allocate the copy */
522  /* ---------------------------------------------------------------------- */
523 
524  C = CHOLMOD(allocate_sparse) (A->nrow, A->ncol, A->nzmax, A->sorted,
525  A->packed, A->stype, A->xtype, Common) ;
526 
527  if (Common->status < CHOLMOD_OK)
528  {
529  return (NULL) ; /* out of memory */
530  }
531 
532  Cp = C->p ;
533  Ci = C->i ;
534  Cx = C->x ;
535  Cz = C->z ;
536  Cnz = C->nz ;
537 
538  /* ---------------------------------------------------------------------- */
539  /* copy the matrix */
540  /* ---------------------------------------------------------------------- */
541 
542  for (j = 0 ; j <= ncol ; j++)
543  {
544  Cp [j] = Ap [j] ;
545  }
546 
547  if (packed)
548  {
549  nz = Ap [ncol] ;
550  for (p = 0 ; p < nz ; p++)
551  {
552  Ci [p] = Ai [p] ;
553  }
554 
555  switch (xtype)
556  {
557  case CHOLMOD_REAL:
558  for (p = 0 ; p < nz ; p++)
559  {
560  Cx [p] = Ax [p] ;
561  }
562  break ;
563 
564  case CHOLMOD_COMPLEX:
565  for (p = 0 ; p < 2*nz ; p++)
566  {
567  Cx [p] = Ax [p] ;
568  }
569  break ;
570 
571  case CHOLMOD_ZOMPLEX:
572  for (p = 0 ; p < nz ; p++)
573  {
574  Cx [p] = Ax [p] ;
575  Cz [p] = Az [p] ;
576  }
577  break ;
578  }
579 
580  }
581  else
582  {
583 
584  for (j = 0 ; j < ncol ; j++)
585  {
586  Cnz [j] = Anz [j] ;
587  }
588 
589  switch (xtype)
590  {
591  case CHOLMOD_PATTERN:
592  for (j = 0 ; j < ncol ; j++)
593  {
594  p = Ap [j] ;
595  pend = p + Anz [j] ;
596  for ( ; p < pend ; p++)
597  {
598  Ci [p] = Ai [p] ;
599  }
600  }
601  break ;
602 
603  case CHOLMOD_REAL:
604  for (j = 0 ; j < ncol ; j++)
605  {
606  p = Ap [j] ;
607  pend = p + Anz [j] ;
608  for ( ; p < pend ; p++)
609  {
610  Ci [p] = Ai [p] ;
611  Cx [p] = Ax [p] ;
612  }
613  }
614  break ;
615 
616  case CHOLMOD_COMPLEX:
617  for (j = 0 ; j < ncol ; j++)
618  {
619  p = Ap [j] ;
620  pend = p + Anz [j] ;
621  for ( ; p < pend ; p++)
622  {
623  Ci [p] = Ai [p] ;
624  Cx [2*p ] = Ax [2*p ] ;
625  Cx [2*p+1] = Ax [2*p+1] ;
626  }
627  }
628  break ;
629 
630  case CHOLMOD_ZOMPLEX:
631  for (j = 0 ; j < ncol ; j++)
632  {
633  p = Ap [j] ;
634  pend = p + Anz [j] ;
635  for ( ; p < pend ; p++)
636  {
637  Ci [p] = Ai [p] ;
638  Cx [p] = Ax [p] ;
639  Cz [p] = Az [p] ;
640  }
641  }
642  break ;
643  }
644  }
645 
646  /* ---------------------------------------------------------------------- */
647  /* return the result */
648  /* ---------------------------------------------------------------------- */
649 
650  ASSERT (CHOLMOD(dump_sparse) (C, "C copy", Common) >= 0) ;
651  return (C) ;
652 }
#define CHOLMOD_TOO_LARGE
#define EMPTY
int CHOLMOD() realloc_multiple(size_t nnew, int nint, int xtype, void **I, void **J, void **X, void **Z, size_t *nold_p, cholmod_common *Common)
#define Int
size_t CHOLMOD() add_size_t(size_t a, size_t b, int *ok)
#define CHOLMOD_COMPLEX
#define FALSE
#define PRINT1(params)
int CHOLMOD() reallocate_sparse(size_t nznew, cholmod_sparse *A, cholmod_common *Common)
#define RETURN_IF_NULL_COMMON(result)
#define CHOLMOD_PATTERN
#define CHOLMOD(name)
#define MAX(a, b)
#define CHOLMOD_REAL
#define NULL
#define Int_max
#define ASSERT(expression)
UF_long CHOLMOD() nnz(cholmod_sparse *A, cholmod_common *Common)
#define DTYPE
cholmod_sparse *CHOLMOD() copy_sparse(cholmod_sparse *A, cholmod_common *Common)
#define CHOLMOD_INVALID
#define CHOLMOD_OK
cholmod_sparse *CHOLMOD() spzeros(size_t nrow, size_t ncol, size_t nzmax, int xtype, cholmod_common *Common)
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)
struct cholmod_sparse_struct cholmod_sparse
#define RETURN_IF_NULL(A, result)
#define MIN(a, b)
int CHOLMOD() free_sparse(cholmod_sparse **AHandle, cholmod_common *Common)
#define UF_long
int n
cholmod_sparse *CHOLMOD() speye(size_t nrow, size_t ncol, int xtype, cholmod_common *Common)
#define ERROR(status, msg)
#define TRUE
#define RETURN_IF_XTYPE_INVALID(A, xtype1, xtype2, result)
#define CHOLMOD_ZOMPLEX
#define ITYPE