Amesos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
amesos_cholmod_l_camd.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /* === Partition/cholmod_camd =============================================== */
3 /* ========================================================================== */
4 
5 /* -----------------------------------------------------------------------------
6  * CHOLMOD/Partition Module. Copyright (C) 2005-2006, Timothy A. Davis
7  * The CHOLMOD/Partition Module is licensed under Version 2.1 of the GNU
8  * Lesser General Public License. See lesser.txt for a text of the license.
9  * CHOLMOD is also available under other licenses; contact authors for details.
10  * http://www.cise.ufl.edu/research/sparse
11  * -------------------------------------------------------------------------- */
12 
13 /* CHOLMOD interface to the CAMD ordering routine. Orders A if the matrix is
14  * symmetric. On output, Perm [k] = i if row/column i of A is the kth
15  * row/column of P*A*P'. This corresponds to A(p,p) in MATLAB notation.
16  *
17  * If A is unsymmetric, cholmod_camd orders A*A'. On output, Perm [k] = i if
18  * row/column i of A*A' is the kth row/column of P*A*A'*P'. This corresponds to
19  * A(p,:)*A(p,:)' in MATLAB notation. If f is present, A(p,f)*A(p,f)' is
20  * ordered.
21  *
22  * Computes the flop count for a subsequent LL' factorization, the number
23  * of nonzeros in L, and the number of nonzeros in the matrix ordered (A,
24  * A*A' or A(:,f)*A(:,f)').
25  *
26  * workspace: Iwork (4*nrow). Head (nrow).
27  *
28  * Allocates a temporary copy of A+A' or A*A' (with
29  * both upper and lower triangular parts) as input to CAMD.
30  * Also allocates 3*(n+1) additional integer workspace (not in Common).
31  *
32  * Supports any xtype (pattern, real, complex, or zomplex)
33  */
34 
35 #ifndef NPARTITION
36 
37 /* This file should make the long int version of CHOLMOD */
38 #define DLONG 1
39 
41 #include "amesos_camd.h"
43 
44 #if (CAMD_VERSION < CAMD_VERSION_CODE (2,0))
45 #error "CAMD v2.0 or later is required"
46 #endif
47 
48 /* ========================================================================== */
49 /* === cholmod_camd ========================================================= */
50 /* ========================================================================== */
51 
52 int CHOLMOD(camd)
53 (
54  /* ---- input ---- */
55  cholmod_sparse *A, /* matrix to order */
56  Int *fset, /* subset of 0:(A->ncol)-1 */
57  size_t fsize, /* size of fset */
58  Int *Cmember, /* size nrow. see cholmod_ccolamd.c for description.*/
59  /* ---- output ---- */
60  Int *Perm, /* size A->nrow, output permutation */
61  /* --------------- */
62  cholmod_common *Common
63 )
64 {
65  double Info [CAMD_INFO], Control2 [CAMD_CONTROL], *Control ;
66  Int *Cp, *Len, *Nv, *Head, *Elen, *Degree, *Wi, *Next, *BucketSet,
67  *Work3n, *p ;
68  cholmod_sparse *C ;
69  Int j, n, cnz ;
70  size_t s ;
71  int ok = TRUE ;
72 
73  /* ---------------------------------------------------------------------- */
74  /* get inputs */
75  /* ---------------------------------------------------------------------- */
76 
78  RETURN_IF_NULL (A, FALSE) ;
79  n = A->nrow ;
80 
81  /* s = 4*n */
82  s = CHOLMOD(mult_size_t) (n, 4, &ok) ;
83  if (!ok)
84  {
85  ERROR (CHOLMOD_TOO_LARGE, "problem too large") ;
86  return (FALSE) ;
87  }
88 
89  RETURN_IF_NULL (Perm, FALSE) ;
91  Common->status = CHOLMOD_OK ;
92  if (n == 0)
93  {
94  /* nothing to do */
95  Common->fl = 0 ;
96  Common->lnz = 0 ;
97  Common->anz = 0 ;
98  return (TRUE) ;
99  }
100 
101  /* ---------------------------------------------------------------------- */
102  /* get workspace */
103  /* ---------------------------------------------------------------------- */
104 
105  /* cholmod_analyze has allocated Cmember at Common->Iwork + 5*n+uncol, and
106  * CParent at Common->Iwork + 4*n+uncol, where uncol is 0 if A is symmetric
107  * or A->ncol otherwise. Thus, only the first 4n integers in Common->Iwork
108  * can be used here. */
109 
110  CHOLMOD(allocate_work) (n, s, 0, Common) ;
111  if (Common->status < CHOLMOD_OK)
112  {
113  return (FALSE) ;
114  }
115 
116  p = Common->Iwork ;
117  Degree = p ; p += n ; /* size n */
118  Elen = p ; p += n ; /* size n */
119  Len = p ; p += n ; /* size n */
120  Nv = p ; p += n ; /* size n */
121 
122  Work3n = CHOLMOD(malloc) (n+1, 3*sizeof (Int), Common) ;
123  if (Common->status < CHOLMOD_OK)
124  {
125  return (FALSE) ;
126  }
127  p = Work3n ;
128  Next = p ; p += n ; /* size n */
129  Wi = p ; p += (n+1) ; /* size n+1 */
130  BucketSet = p ; /* size n */
131 
132  Head = Common->Head ; /* size n+1 */
133 
134  /* ---------------------------------------------------------------------- */
135  /* construct the input matrix for CAMD */
136  /* ---------------------------------------------------------------------- */
137 
138  if (A->stype == 0)
139  {
140  /* C = A*A' or A(:,f)*A(:,f)', add extra space of nnz(C)/2+n to C */
141  C = CHOLMOD(aat) (A, fset, fsize, -2, Common) ;
142  }
143  else
144  {
145  /* C = A+A', but use only the upper triangular part of A if A->stype = 1
146  * and only the lower part of A if A->stype = -1. Add extra space of
147  * nnz(C)/2+n to C. */
148  C = CHOLMOD(copy) (A, 0, -2, Common) ;
149  }
150 
151  if (Common->status < CHOLMOD_OK)
152  {
153  /* out of memory, fset invalid, or other error */
154  CHOLMOD(free) (n+1, 3*sizeof (Int), Work3n, Common) ;
155  return (FALSE) ;
156  }
157 
158  Cp = C->p ;
159  for (j = 0 ; j < n ; j++)
160  {
161  Len [j] = Cp [j+1] - Cp [j] ;
162  }
163 
164  /* C does not include the diagonal, and both upper and lower parts.
165  * Common->anz includes the diagonal, and just the lower part of C */
166  cnz = Cp [n] ;
167  Common->anz = cnz / 2 + n ;
168 
169  /* ---------------------------------------------------------------------- */
170  /* order C using CAMD */
171  /* ---------------------------------------------------------------------- */
172 
173  /* get parameters */
174  if (Common->current < 0 || Common->current >= CHOLMOD_MAXMETHODS)
175  {
176  /* use CAMD defaults */
177  Control = NULL ;
178  }
179  else
180  {
181  Control = Control2 ;
182  Control [CAMD_DENSE] = Common->method [Common->current].prune_dense ;
183  Control [CAMD_AGGRESSIVE] = Common->method [Common->current].aggressive;
184  }
185 
186  /* CAMD_2 does not use camd_malloc and camd_free, but set these pointers
187  * just be safe. */
188  amesos_camd_malloc = Common->malloc_memory ;
189  amesos_camd_free = Common->free_memory ;
190  amesos_camd_calloc = Common->calloc_memory ;
191  amesos_camd_realloc = Common->realloc_memory ;
192 
193  /* CAMD_2 doesn't print anything either, but future versions might,
194  * so set the camd_printf pointer too. */
195  amesos_camd_printf = Common->print_function ;
196 
197 #ifdef LONG
198  /* DEBUG (camd_l_debug_init ("cholmod_l_camd")) ; */
199  amesos_camd_l2 (n, C->p, C->i, Len, C->nzmax, cnz, Nv, Next, Perm, Head, Elen,
200  Degree, Wi, Control, Info, Cmember, BucketSet) ;
201 #else
202  /* DEBUG (camd_debug_init ("cholmod_camd")) ; */
203  amesos_camd_2 (n, C->p, C->i, Len, C->nzmax, cnz, Nv, Next, Perm, Head, Elen,
204  Degree, Wi, Control, Info, Cmember, BucketSet) ;
205 #endif
206 
207  /* LL' flop count. Need to subtract n for LL' flop count. Note that this
208  * is a slight upper bound which is often exact (see CAMD/Source/camd_2.c
209  * for details). cholmod_analyze computes an exact flop count and
210  * fill-in. */
211  Common->fl = Info [CAMD_NDIV] + 2 * Info [CAMD_NMULTSUBS_LDL] + n ;
212 
213  /* Info [CAMD_LNZ] excludes the diagonal */
214  Common->lnz = n + Info [CAMD_LNZ] ;
215 
216  /* ---------------------------------------------------------------------- */
217  /* free the CAMD workspace and clear the persistent workspace in Common */
218  /* ---------------------------------------------------------------------- */
219 
220  ASSERT (IMPLIES (Common->status == CHOLMOD_OK,
221  CHOLMOD(dump_perm) (Perm, n, n, "CAMD2 perm", Common))) ;
222  CHOLMOD(free_sparse) (&C, Common) ;
223  for (j = 0 ; j <= n ; j++)
224  {
225  Head [j] = EMPTY ;
226  }
227  CHOLMOD(free) (n+1, 3*sizeof (Int), Work3n, Common) ;
228  return (TRUE) ;
229 }
230 #endif
#define CAMD_INFO
Definition: amesos_camd.h:352
#define CHOLMOD_TOO_LARGE
#define CAMD_DENSE
Definition: amesos_camd.h:355
#define EMPTY
int CHOLMOD() camd(cholmod_sparse *A, Int *fset, size_t fsize, Int *Cmember, Int *Perm, cholmod_common *Common)
EXTERN void *(* amesos_camd_realloc)(void *, size_t)
Definition: amesos_camd.h:331
#define Int
#define CAMD_AGGRESSIVE
Definition: amesos_camd.h:356
#define CAMD_LNZ
Definition: amesos_camd.h:372
#define FALSE
#define RETURN_IF_NULL_COMMON(result)
size_t CHOLMOD() mult_size_t(size_t a, size_t k, int *ok)
#define CAMD_NMULTSUBS_LDL
Definition: amesos_camd.h:374
EXTERN int(* amesos_camd_printf)(const char *,...)
Definition: amesos_camd.h:333
cholmod_sparse *CHOLMOD() aat(cholmod_sparse *A, Int *fset, size_t fsize, int mode, cholmod_common *Common)
#define CHOLMOD_PATTERN
#define CHOLMOD(name)
int CHOLMOD() free_sparse(cholmod_sparse **AHandle, cholmod_common *Common)
#define NULL
#define ASSERT(expression)
void amesos_camd_2(int n, int Pe[], int Iw[], int Len[], int iwlen, int pfree, int Nv[], int Next[], int Last[], int Head[], int Elen[], int Degree[], int W[], double Control[], double Info[], const int C[], int BucketSet[])
#define CAMD_NDIV
Definition: amesos_camd.h:373
EXTERN void *(* amesos_camd_calloc)(size_t, size_t)
Definition: amesos_camd.h:332
int CHOLMOD() dump_perm(Int *Perm, size_t len, size_t n, char *name, cholmod_common *Common)
#define CHOLMOD_OK
#define CAMD_CONTROL
Definition: amesos_camd.h:351
int CHOLMOD() allocate_work(size_t nrow, size_t iworksize, size_t xworksize, cholmod_common *Common)
#define CHOLMOD_MAXMETHODS
EXTERN void *(* amesos_camd_malloc)(size_t)
Definition: amesos_camd.h:329
#define RETURN_IF_NULL(A, result)
#define IMPLIES(p, q)
int n
#define ERROR(status, msg)
#define TRUE
EXTERN void(* amesos_camd_free)(void *)
Definition: amesos_camd.h:330
#define RETURN_IF_XTYPE_INVALID(A, xtype1, xtype2, result)
#define CHOLMOD_ZOMPLEX
void amesos_camd_l2(UF_long n, UF_long Pe[], UF_long Iw[], UF_long Len[], UF_long iwlen, UF_long pfree, UF_long Nv[], UF_long Next[], UF_long Last[], UF_long Head[], UF_long Elen[], UF_long Degree[], UF_long W[], double Control[], double Info[], const UF_long C[], UF_long BucketSet[])
cholmod_sparse *CHOLMOD() copy(cholmod_sparse *A, int stype, int mode, cholmod_common *Common)