1 /* ========================================================================= */
2 /* === AMD_order =========================================================== */
3 /* ========================================================================= */
5 /* ------------------------------------------------------------------------- */
6 /* AMD, Copyright (c) Timothy A. Davis, */
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/amd */
10 /* ------------------------------------------------------------------------- */
12 /* User-callable AMD minimum degree ordering routine. See amd.h for
16 #include "amd_internal.h"
18 /* ========================================================================= */
19 /* === AMD_order =========================================================== */
20 /* ========================================================================= */
32 Int *Len, *S, nz, i, *Pinv, info, status, *Rp, *Ri, *Cp, *Ci, ok ;
37 AMD_debug_init ("amd") ;
40 /* clear the Info array, if it exists */
41 info = Info != (double *) NULL ;
44 for (i = 0 ; i < AMD_INFO ; i++)
49 Info [AMD_STATUS] = AMD_OK ;
52 /* make sure inputs exist and n is >= 0 */
53 if (Ai == (Int *) NULL || Ap == (Int *) NULL || P == (Int *) NULL || n < 0)
55 if (info) Info [AMD_STATUS] = AMD_INVALID ;
56 return (AMD_INVALID) ; /* arguments are invalid */
61 return (AMD_OK) ; /* n is 0 so there's nothing to do */
71 if (info) Info [AMD_STATUS] = AMD_INVALID ;
72 return (AMD_INVALID) ;
75 /* check if n or nz will cause size_t overflow */
76 if (((size_t) n) >= SIZE_T_MAX / sizeof (Int)
77 || ((size_t) nz) >= SIZE_T_MAX / sizeof (Int))
79 if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ;
80 return (AMD_OUT_OF_MEMORY) ; /* problem too large */
83 /* check the input matrix: AMD_OK, AMD_INVALID, or AMD_OK_BUT_JUMBLED */
84 status = AMD_valid (n, n, Ap, Ai) ;
86 if (status == AMD_INVALID)
88 if (info) Info [AMD_STATUS] = AMD_INVALID ;
89 return (AMD_INVALID) ; /* matrix is invalid */
92 /* allocate two size-n integer workspaces */
93 Len = amd_malloc (n * sizeof (Int)) ;
94 Pinv = amd_malloc (n * sizeof (Int)) ;
99 /* :: out of memory :: */
102 if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ;
103 return (AMD_OUT_OF_MEMORY) ;
106 if (status == AMD_OK_BUT_JUMBLED)
108 /* sort the input matrix and remove duplicate entries */
109 AMD_DEBUG1 (("Matrix is jumbled\n")) ;
110 Rp = amd_malloc ((n+1) * sizeof (Int)) ;
111 Ri = amd_malloc (MAX (nz,1) * sizeof (Int)) ;
116 /* :: out of memory :: */
121 if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ;
122 return (AMD_OUT_OF_MEMORY) ;
124 /* use Len and Pinv as workspace to create R = A' */
125 AMD_preprocess (n, Ap, Ai, Rp, Ri, Len, Pinv) ;
131 /* order the input matrix as-is. No need to compute R = A' first */
138 /* --------------------------------------------------------------------- */
139 /* determine the symmetry and count off-diagonal nonzeros in A+A' */
140 /* --------------------------------------------------------------------- */
142 nzaat = AMD_aat (n, Cp, Ci, Len, P, Info) ;
143 AMD_DEBUG1 (("nzaat: %g\n", (double) nzaat)) ;
144 ASSERT ((MAX (nz-n, 0) <= nzaat) && (nzaat <= 2 * (size_t) nz)) ;
146 /* --------------------------------------------------------------------- */
147 /* allocate workspace for matrix, elbow room, and 6 size-n vectors */
148 /* --------------------------------------------------------------------- */
151 slen = nzaat ; /* space for matrix */
152 ok = ((slen + nzaat/5) >= slen) ; /* check for size_t overflow */
153 slen += nzaat/5 ; /* add elbow room */
154 for (i = 0 ; ok && i < 7 ; i++)
156 ok = ((slen + n) > slen) ; /* check for size_t overflow */
157 slen += n ; /* size-n elbow room, 6 size-n work */
160 ok = ok && (slen < SIZE_T_MAX / sizeof (Int)) ; /* check for overflow */
161 ok = ok && (slen < Int_MAX) ; /* S[i] for Int i must be OK */
164 S = amd_malloc (slen * sizeof (Int)) ;
166 AMD_DEBUG1 (("slen %g\n", (double) slen)) ;
169 /* :: out of memory :: (or problem too large) */
174 if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ;
175 return (AMD_OUT_OF_MEMORY) ;
179 /* memory usage, in bytes. */
180 Info [AMD_MEMORY] = mem * sizeof (Int) ;
183 /* --------------------------------------------------------------------- */
184 /* order the matrix */
185 /* --------------------------------------------------------------------- */
187 AMD_1 (n, Cp, Ci, P, Pinv, Len, slen, S, Control, Info) ;
189 /* --------------------------------------------------------------------- */
190 /* free the workspace */
191 /* --------------------------------------------------------------------- */
198 if (info) Info [AMD_STATUS] = status ;
199 return (status) ; /* successful ordering */