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