Amesos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
amesos_cholmod_amd.c
Go to the documentation of this file.
1 /* ========================================================================== */
2 /* === Cholesky/cholmod_amd ================================================= */
3 /* ========================================================================== */
4 
5 /* -----------------------------------------------------------------------------
6  * CHOLMOD/Cholesky Module. Copyright (C) 2005-2006, Timothy A. Davis
7  * The CHOLMOD/Cholesky 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 AMD 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_amd 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 (6*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 AMD.
30  *
31  * Supports any xtype (pattern, real, complex, or zomplex)
32  */
33 
34 #ifndef NCHOLESKY
35 
37 #include "amesos_amd.h"
39 
40 #if (!defined (AMD_VERSION) || (AMD_VERSION < AMD_VERSION_CODE (2,0)))
41 #error "AMD v2.0 or later is required"
42 #endif
43 
44 /* ========================================================================== */
45 /* === cholmod_amd ========================================================== */
46 /* ========================================================================== */
47 
48 int CHOLMOD(amd)
49 (
50  /* ---- input ---- */
51  cholmod_sparse *A, /* matrix to order */
52  Int *fset, /* subset of 0:(A->ncol)-1 */
53  size_t fsize, /* size of fset */
54  /* ---- output --- */
55  Int *Perm, /* size A->nrow, output permutation */
56  /* --------------- */
57  cholmod_common *Common
58 )
59 {
60  double Info [AMD_INFO], Control2 [AMD_CONTROL], *Control ;
61  Int *Cp, *Len, *Nv, *Head, *Elen, *Degree, *Wi, *Iwork, *Next ;
62  cholmod_sparse *C ;
63  Int j, n, cnz ;
64  size_t s ;
65  int ok = TRUE ;
66 
67  /* ---------------------------------------------------------------------- */
68  /* get inputs */
69  /* ---------------------------------------------------------------------- */
70 
72  RETURN_IF_NULL (A, FALSE) ;
73  n = A->nrow ;
74 
75  RETURN_IF_NULL (Perm, FALSE) ;
77  Common->status = CHOLMOD_OK ;
78  if (n == 0)
79  {
80  /* nothing to do */
81  Common->fl = 0 ;
82  Common->lnz = 0 ;
83  Common->anz = 0 ;
84  return (TRUE) ;
85  }
86 
87  /* ---------------------------------------------------------------------- */
88  /* get workspace */
89  /* ---------------------------------------------------------------------- */
90 
91  /* Note: this is less than the space used in cholmod_analyze, so if
92  * cholmod_amd is being called by that routine, no space will be
93  * allocated.
94  */
95 
96  /* s = MAX (6*n, A->ncol) */
97  s = CHOLMOD(mult_size_t) (n, 6, &ok) ;
98  if (!ok)
99  {
100  ERROR (CHOLMOD_TOO_LARGE, "problem too large") ;
101  return (FALSE) ;
102  }
103  s = MAX (s, A->ncol) ;
104 
105  CHOLMOD(allocate_work) (n, s, 0, Common) ;
106  if (Common->status < CHOLMOD_OK)
107  {
108  return (FALSE) ;
109  }
110 
111  Iwork = Common->Iwork ;
112  Degree = Iwork ; /* size n */
113  Wi = Iwork + n ; /* size n */
114  Len = Iwork + 2*((size_t) n) ; /* size n */
115  Nv = Iwork + 3*((size_t) n) ; /* size n */
116  Next = Iwork + 4*((size_t) n) ; /* size n */
117  Elen = Iwork + 5*((size_t) n) ; /* size n */
118 
119  Head = Common->Head ; /* size n+1, but only n is used */
120 
121  /* ---------------------------------------------------------------------- */
122  /* construct the input matrix for AMD */
123  /* ---------------------------------------------------------------------- */
124 
125  if (A->stype == 0)
126  {
127  /* C = A*A' or A(:,f)*A(:,f)', add extra space of nnz(C)/2+n to C */
128  C = CHOLMOD(aat) (A, fset, fsize, -2, Common) ;
129  }
130  else
131  {
132  /* C = A+A', but use only the upper triangular part of A if A->stype = 1
133  * and only the lower part of A if A->stype = -1. Add extra space of
134  * nnz(C)/2+n to C. */
135  C = CHOLMOD(copy) (A, 0, -2, Common) ;
136  }
137 
138  if (Common->status < CHOLMOD_OK)
139  {
140  /* out of memory, fset invalid, or other error */
141  return (FALSE) ;
142  }
143 
144  Cp = C->p ;
145  for (j = 0 ; j < n ; j++)
146  {
147  Len [j] = Cp [j+1] - Cp [j] ;
148  }
149 
150  /* C does not include the diagonal, and both upper and lower parts.
151  * Common->anz includes the diagonal, and just the lower part of C */
152  cnz = Cp [n] ;
153  Common->anz = cnz / 2 + n ;
154 
155  /* ---------------------------------------------------------------------- */
156  /* order C using AMD */
157  /* ---------------------------------------------------------------------- */
158 
159  /* get parameters */
160  if (Common->current < 0 || Common->current >= CHOLMOD_MAXMETHODS)
161  {
162  /* use AMD defaults */
163  Control = NULL ;
164  }
165  else
166  {
167  Control = Control2 ;
168  Control [AMD_DENSE] = Common->method [Common->current].prune_dense ;
169  Control [AMD_AGGRESSIVE] = Common->method [Common->current].aggressive ;
170  }
171 
172  /* AMD_2 does not use amd_malloc and amd_free, but set these pointers just
173  * be safe. */
174  amesos_amd_malloc = Common->malloc_memory ;
175  amesos_amd_free = Common->free_memory ;
176  amesos_amd_calloc = Common->calloc_memory ;
177  amesos_amd_realloc = Common->realloc_memory ;
178 
179  /* AMD_2 doesn't print anything either, but future versions might,
180  * so set the amd_printf pointer too. */
181  amesos_amd_printf = Common->print_function ;
182 
183 #ifdef LONG
184  amesos_amd_l2 (n, C->p, C->i, Len, C->nzmax, cnz, Nv, Next, Perm, Head, Elen,
185  Degree, Wi, Control, Info) ;
186 #else
187  amesos_amd_2 (n, C->p, C->i, Len, C->nzmax, cnz, Nv, Next, Perm, Head, Elen,
188  Degree, Wi, Control, Info) ;
189 #endif
190 
191  /* LL' flop count. Need to subtract n for LL' flop count. Note that this
192  * is a slight upper bound which is often exact (see AMD/Source/amd_2.c for
193  * details). cholmod_analyze computes an exact flop count and fill-in. */
194  Common->fl = Info [AMD_NDIV] + 2 * Info [AMD_NMULTSUBS_LDL] + n ;
195 
196  /* Info [AMD_LNZ] excludes the diagonal */
197  Common->lnz = n + Info [AMD_LNZ] ;
198 
199  /* ---------------------------------------------------------------------- */
200  /* free the AMD workspace and clear the persistent workspace in Common */
201  /* ---------------------------------------------------------------------- */
202 
203  ASSERT (IMPLIES (Common->status == CHOLMOD_OK,
204  CHOLMOD(dump_perm) (Perm, n, n, "AMD2 perm", Common))) ;
205  CHOLMOD(free_sparse) (&C, Common) ;
206  for (j = 0 ; j <= n ; j++)
207  {
208  Head [j] = EMPTY ;
209  }
210  return (TRUE) ;
211 }
212 #endif
#define CHOLMOD_TOO_LARGE
#define AMD_NMULTSUBS_LDL
Definition: amesos_amd.h:363
EXTERN void *(* amesos_amd_realloc)(void *, size_t)
Definition: amesos_amd.h:320
#define EMPTY
#define Int
#define FALSE
#define RETURN_IF_NULL_COMMON(result)
size_t CHOLMOD() mult_size_t(size_t a, size_t k, int *ok)
EXTERN void(* amesos_amd_free)(void *)
Definition: amesos_amd.h:319
cholmod_sparse *CHOLMOD() aat(cholmod_sparse *A, Int *fset, size_t fsize, int mode, cholmod_common *Common)
#define CHOLMOD_PATTERN
#define CHOLMOD(name)
#define MAX(a, b)
int CHOLMOD() free_sparse(cholmod_sparse **AHandle, cholmod_common *Common)
#define NULL
#define AMD_DENSE
Definition: amesos_amd.h:344
#define ASSERT(expression)
EXTERN void *(* amesos_amd_calloc)(size_t, size_t)
Definition: amesos_amd.h:321
EXTERN int(* amesos_amd_printf)(const char *,...)
Definition: amesos_amd.h:322
#define AMD_AGGRESSIVE
Definition: amesos_amd.h:345
#define AMD_CONTROL
Definition: amesos_amd.h:340
int CHOLMOD() dump_perm(Int *Perm, size_t len, size_t n, char *name, cholmod_common *Common)
#define CHOLMOD_OK
#define AMD_NDIV
Definition: amesos_amd.h:362
int CHOLMOD() allocate_work(size_t nrow, size_t iworksize, size_t xworksize, cholmod_common *Common)
#define CHOLMOD_MAXMETHODS
#define RETURN_IF_NULL(A, result)
void amesos_amd_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[])
void amesos_amd_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[])
#define IMPLIES(p, q)
int n
#define ERROR(status, msg)
#define TRUE
int CHOLMOD() amd(cholmod_sparse *A, Int *fset, size_t fsize, Int *Perm, cholmod_common *Common)
#define RETURN_IF_XTYPE_INVALID(A, xtype1, xtype2, result)
#define AMD_INFO
Definition: amesos_amd.h:341
#define CHOLMOD_ZOMPLEX
EXTERN void *(* amesos_amd_malloc)(size_t)
Definition: amesos_amd.h:318
#define AMD_LNZ
Definition: amesos_amd.h:361
cholmod_sparse *CHOLMOD() copy(cholmod_sparse *A, int stype, int mode, cholmod_common *Common)