/* ========================================================================= */1/* === AMD_order =========================================================== */2/* ========================================================================= */34/* ------------------------------------------------------------------------- */5/* AMD Version 1.1 (Jan. 21, 2004), Copyright (c) 2004 by Timothy A. Davis, */6/* Patrick R. Amestoy, and Iain S. Duff. See ../README for License. */7/* email: [email protected] CISE Department, Univ. of Florida. */8/* web: http://www.cise.ufl.edu/research/sparse/amd */9/* ------------------------------------------------------------------------- */1011/* User-callable AMD minimum degree ordering routine. See amd.h for12* documentation.13*/1415#include "amd_internal.h"1617GLOBAL Int AMD_order18(19Int n,20const Int Ap [ ],21const Int Ai [ ],22Int P [ ],23double Control [ ],24double Info [ ]25)26{27Int slen, *Len, *S, nz, nzaat, i, *Pinv, info ;2829#ifndef NDEBUG30AMD_debug_init ("amd") ;31#endif3233/* clear the Info array, if it exists */34info = Info != (double *) NULL ;35if (info)36{37for (i = 0 ; i < AMD_INFO ; i++)38{39Info [i] = EMPTY ;40}41Info [AMD_N] = n ;42Info [AMD_STATUS] = AMD_OK ;43}4445/* make sure inputs exist and n is >= 0 */46if (Ai == (Int *) NULL || Ap == (Int *) NULL || P == (Int *) NULL || n < 0)47{48if (info) Info [AMD_STATUS] = AMD_INVALID ;49return (AMD_INVALID) ; /* arguments are invalid */50}5152if (n == 0)53{54return (AMD_OK) ; /* n is 0 so there's nothing to do */55}5657nz = Ap [n] ;58if (info)59{60Info [AMD_NZ] = nz ;61}62if (nz < 0)63{64if (info) Info [AMD_STATUS] = AMD_INVALID ;65return (AMD_INVALID) ;66}6768/* Avoid integer overflow in memory size calculations. The space required69* by AMD is at most 2.4nz + 8n for S, and n for Len.70* Note nz - n <= nzaat <= 2*nz, below. */71if ((2.4 * (double) nz + 8 * (double) n) > (double) Int_MAX / sizeof (Int))72{73/* :: int overflow :: */74if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ;75return (AMD_OUT_OF_MEMORY) ;76}7778if (!AMD_valid (n, n, Ap, Ai))79{80if (info) Info [AMD_STATUS] = AMD_INVALID ;81return (AMD_INVALID) ; /* matrix is invalid */82}8384/* --------------------------------------------------------------------- */85/* determine the symmetry and count off-diagonal nonzeros in A+A' */86/* --------------------------------------------------------------------- */8788/* allocate size-n integer workspace */89Len = (Int *) ALLOCATE (n * sizeof (Int)) ;90if (!Len)91{92/* :: out of memory :: */93if (info) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ;94return (AMD_OUT_OF_MEMORY) ;95}96nzaat = AMD_aat (n, Ap, Ai, Len, P, Info) ;97AMD_DEBUG1 (("nzaat: "ID"\n", nzaat)) ;98ASSERT (nz-n <= nzaat && nzaat <= 2*nz) ;99100/* --------------------------------------------------------------------- */101/* allocate workspace for matrix, elbow room, and 7 size-n vectors */102/* --------------------------------------------------------------------- */103104slen = (nzaat + nzaat/5 + n) + 7*n ;105if (info)106{107/* memory usage (Len and S), in bytes. */108Info [AMD_MEMORY] = ((double) slen + n) * sizeof (Int) ;109}110S = (Int *) ALLOCATE (slen * sizeof (Int)) ;111AMD_DEBUG1 ((" S "ID" Len "ID" n "ID" nzaat "ID" slen "ID"\n",112(Int) S, (Int) Len, n, nzaat, slen)) ;113if (S == (Int *) NULL)114{115/* :: out of memory :: */116FREE (Len) ;117if (Info != (double *) NULL) Info [AMD_STATUS] = AMD_OUT_OF_MEMORY ;118return (AMD_OUT_OF_MEMORY) ;119}120121/* allocate space from S for Pinv */122Pinv = S + slen - n ;123slen -= n ;124125/* --------------------------------------------------------------------- */126/* order the matrix */127/* --------------------------------------------------------------------- */128129AMD_1 (n, Ap, Ai, P, Pinv, Len, slen, S, Control, Info) ;130131/* --------------------------------------------------------------------- */132/* free the workspace */133/* --------------------------------------------------------------------- */134135FREE (Len) ;136FREE (S) ;137return (AMD_OK) ; /* successful ordering */138}139140141