Amesos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
amesos_camd_order.c
Go to the documentation of this file.
1 /* ========================================================================= */
2 /* === CAMD_order ========================================================== */
3 /* ========================================================================= */
4 
5 /* ------------------------------------------------------------------------- */
6 /* CAMD, Copyright (c) Timothy A. Davis, Yanqing Chen, */
7 /* Patrick R. Amestoy, and Iain S. Duff. See ../README.txt for License. */
8 /* email: davis at cise.ufl.edu CISE Department, Univ. of Florida. */
9 /* web: http://www.cise.ufl.edu/research/sparse/camd */
10 /* ------------------------------------------------------------------------- */
11 
12 /* User-callable CAMD minimum degree ordering routine. See camd.h for
13  * documentation.
14  */
15 
16 #include "amesos_camd_internal.h"
17 
18 /* ========================================================================= */
19 /* === CAMD_order ========================================================== */
20 /* ========================================================================= */
21 
23 (
24  Int n,
25  const Int Ap [ ],
26  const Int Ai [ ],
27  Int P [ ],
28  double Control [ ],
29  double Info [ ],
30  const Int C [ ]
31 )
32 {
33  Int *Len, *S, nz, i, *Pinv, info, status, *Rp, *Ri, *Cp, *Ci, ok ;
34  size_t nzaat, slen ;
35  double mem = 0 ;
36 
37 #ifndef NDEBUG
38  CAMD_debug_init ("camd") ;
39 #endif
40 
41  /* clear the Info array, if it exists */
42  info = Info != (double *) NULL ;
43  if (info)
44  {
45  for (i = 0 ; i < CAMD_INFO ; i++)
46  {
47  Info [i] = EMPTY ;
48  }
49  Info [CAMD_N] = n ;
50  Info [CAMD_STATUS] = CAMD_OK ;
51  }
52 
53  /* make sure inputs exist and n is >= 0 */
54  if (Ai == (Int *) NULL || Ap == (Int *) NULL || P == (Int *) NULL || n < 0)
55  {
56  if (info) Info [CAMD_STATUS] = CAMD_INVALID ;
57  return (CAMD_INVALID) ; /* arguments are invalid */
58  }
59 
60  if (n == 0)
61  {
62  return (CAMD_OK) ; /* n is 0 so there's nothing to do */
63  }
64 
65  nz = Ap [n] ;
66  if (info)
67  {
68  Info [CAMD_NZ] = nz ;
69  }
70  if (nz < 0)
71  {
72  if (info) Info [CAMD_STATUS] = CAMD_INVALID ;
73  return (CAMD_INVALID) ;
74  }
75 
76  /* check if n or nz will cause size_t overflow */
77  if ((size_t) n >= SIZE_T_MAX / sizeof (Int)
78  || (size_t) nz >= SIZE_T_MAX / sizeof (Int))
79  {
80  if (info) Info [CAMD_STATUS] = CAMD_OUT_OF_MEMORY ;
81  return (CAMD_OUT_OF_MEMORY) ; /* problem too large */
82  }
83 
84  /* check the input matrix: CAMD_OK, CAMD_INVALID, or CAMD_OK_BUT_JUMBLED */
85  status = CAMD_valid (n, n, Ap, Ai) ;
86 
87  if (status == CAMD_INVALID)
88  {
89  if (info) Info [CAMD_STATUS] = CAMD_INVALID ;
90  return (CAMD_INVALID) ; /* matrix is invalid */
91  }
92 
93  /* allocate two size-n integer workspaces */
94  Len = amesos_camd_malloc (n * sizeof (Int)) ;
95  Pinv = amesos_camd_malloc (n * sizeof (Int)) ;
96  mem += n ;
97  mem += n ;
98  if (!Len || !Pinv)
99  {
100  /* :: out of memory :: */
101  amesos_camd_free (Len) ;
102  amesos_camd_free (Pinv) ;
103  if (info) Info [CAMD_STATUS] = CAMD_OUT_OF_MEMORY ;
104  return (CAMD_OUT_OF_MEMORY) ;
105  }
106 
107  if (status == CAMD_OK_BUT_JUMBLED)
108  {
109  /* sort the input matrix and remove duplicate entries */
110  CAMD_DEBUG1 (("Matrix is jumbled\n")) ;
111  Rp = amesos_camd_malloc ((n+1) * sizeof (Int)) ;
112  Ri = amesos_camd_malloc (MAX (nz,1) * sizeof (Int)) ;
113  mem += (n+1) ;
114  mem += MAX (nz,1) ;
115  if (!Rp || !Ri)
116  {
117  /* :: out of memory :: */
118  amesos_camd_free (Rp) ;
119  amesos_camd_free (Ri) ;
120  amesos_camd_free (Len) ;
121  amesos_camd_free (Pinv) ;
122  if (info) Info [CAMD_STATUS] = CAMD_OUT_OF_MEMORY ;
123  return (CAMD_OUT_OF_MEMORY) ;
124  }
125  /* use Len and Pinv as workspace to create R = A' */
126  CAMD_preprocess (n, Ap, Ai, Rp, Ri, Len, Pinv) ;
127  Cp = Rp ;
128  Ci = Ri ;
129  }
130  else
131  {
132  /* order the input matrix as-is. No need to compute R = A' first */
133  Rp = NULL ;
134  Ri = NULL ;
135  Cp = (Int *) Ap ;
136  Ci = (Int *) Ai ;
137  }
138 
139  /* --------------------------------------------------------------------- */
140  /* determine the symmetry and count off-diagonal nonzeros in A+A' */
141  /* --------------------------------------------------------------------- */
142 
143  nzaat = CAMD_aat (n, Cp, Ci, Len, P, Info) ;
144  CAMD_DEBUG1 (("nzaat: %g\n", (double) nzaat)) ;
145  ASSERT ((MAX (nz-n, 0) <= nzaat) && (nzaat <= 2 * (size_t) nz)) ;
146 
147  /* --------------------------------------------------------------------- */
148  /* allocate workspace for matrix, elbow room, and 7 size-n vectors */
149  /* --------------------------------------------------------------------- */
150 
151  S = NULL ;
152  slen = nzaat ; /* space for matrix */
153  ok = ((slen + nzaat/5) >= slen) ; /* check for size_t overflow */
154  slen += nzaat/5 ; /* add elbow room */
155  for (i = 0 ; ok && i < 8 ; i++)
156  {
157  ok = ((slen + n+1) > slen) ; /* check for size_t overflow */
158  slen += (n+1) ; /* size-n elbow room, 7 size-(n+1) workspace */
159  }
160  mem += slen ;
161  ok = ok && (slen < SIZE_T_MAX / sizeof (Int)) ; /* check for overflow */
162  ok = ok && (slen < Int_MAX) ; /* S[i] for Int i must be OK */
163  if (ok)
164  {
165  S = amesos_camd_malloc (slen * sizeof (Int)) ;
166  }
167  CAMD_DEBUG1 (("slen %g\n", (double) slen)) ;
168  if (!S)
169  {
170  /* :: out of memory :: (or problem too large) */
171  amesos_camd_free (Rp) ;
172  amesos_camd_free (Ri) ;
173  amesos_camd_free (Len) ;
174  amesos_camd_free (Pinv) ;
175  if (info) Info [CAMD_STATUS] = CAMD_OUT_OF_MEMORY ;
176  return (CAMD_OUT_OF_MEMORY) ;
177  }
178  if (info)
179  {
180  /* memory usage, in bytes. */
181  Info [CAMD_MEMORY] = mem * sizeof (Int) ;
182  }
183 
184  /* --------------------------------------------------------------------- */
185  /* order the matrix */
186  /* --------------------------------------------------------------------- */
187 
188  CAMD_1 (n, Cp, Ci, P, Pinv, Len, slen, S, Control, Info, C) ;
189 
190  /* --------------------------------------------------------------------- */
191  /* free the workspace */
192  /* --------------------------------------------------------------------- */
193 
194  amesos_camd_free (Rp) ;
195  amesos_camd_free (Ri) ;
196  amesos_camd_free (Len) ;
197  amesos_camd_free (Pinv) ;
198  amesos_camd_free (S) ;
199  if (info) Info [CAMD_STATUS] = status ;
200  return (status) ; /* successful ordering */
201 }
#define CAMD_INFO
Definition: amesos_camd.h:352
#define CAMD_NZ
Definition: amesos_camd.h:365
#define CAMD_MEMORY
Definition: amesos_camd.h:370
#define EMPTY
#define CAMD_STATUS
Definition: amesos_camd.h:363
#define GLOBAL
GLOBAL Int CAMD_order(Int n, const Int Ap[], const Int Ai[], Int P[], double Control[], double Info[], const Int C[])
#define Int
#define CAMD_aat
#define CAMD_1
#define CAMD_debug_init
#define P(k)
#define MAX(a, b)
#define NULL
#define ASSERT(expression)
#define CAMD_DEBUG1(params)
#define Int_MAX
#define SIZE_T_MAX
#define CAMD_INVALID
Definition: amesos_camd.h:384
#define CAMD_preprocess
EXTERN void *(* amesos_camd_malloc)(size_t)
Definition: amesos_camd.h:329
#define CAMD_OUT_OF_MEMORY
Definition: amesos_camd.h:383
#define CAMD_OK
Definition: amesos_camd.h:382
GLOBAL Int CAMD_valid(Int n_row, Int n_col, const Int Ap[], const Int Ai[])
#define CAMD_OK_BUT_JUMBLED
Definition: amesos_camd.h:385
#define CAMD_N
Definition: amesos_camd.h:364
EXTERN void(* amesos_camd_free)(void *)
Definition: amesos_camd.h:330