/* ========================================================================= */1/* === AMD_preprocess ====================================================== */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/* Sorts, removes duplicate entries, and transposes from the nonzero pattern of12* a column-form matrix A, to obtain the matrix R.13* See amd.h for a complete description of AMD_preprocess14*/1516#include "amd_internal.h"1718GLOBAL Int AMD_preprocess /* returns AMD_OK if input is OK, AMD_INVALID19* if the matrix is invalid, or AMD_OUT_OF_MEMORY20* if out of memory for the 2n workspace. */21(22Int n, /* input matrix: A is n-by-n */23const Int Ap [ ], /* size n+1 */24const Int Ai [ ], /* size nz = Ap [n] */2526/* output matrix R: */27Int Rp [ ], /* size n+1 */28Int Ri [ ] /* size nz (or less, if duplicates present) */29)30{31/* --------------------------------------------------------------------- */32/* local variables */33/* --------------------------------------------------------------------- */3435Int *Flag, *W ;3637/* --------------------------------------------------------------------- */38/* check inputs (note: fewer restrictions than AMD_order) */39/* --------------------------------------------------------------------- */4041if (!AMD_preprocess_valid (n, Ap, Ai) || !Ri || !Rp)42{43return (AMD_INVALID) ;44}4546/* --------------------------------------------------------------------- */47/* allocate workspace */48/* --------------------------------------------------------------------- */4950W = (Int *) ALLOCATE (MAX (n,1) * sizeof (Int)) ;51if (!W)52{53return (AMD_OUT_OF_MEMORY) ;54}55Flag = (Int *) ALLOCATE (MAX (n,1) * sizeof (Int)) ;56if (!Flag)57{58FREE (W) ;59return (AMD_OUT_OF_MEMORY) ;60}6162/* --------------------------------------------------------------------- */63/* preprocess the matrix: sort, remove duplicates, and transpose */64/* --------------------------------------------------------------------- */6566AMD_wpreprocess (n, Ap, Ai, Rp, Ri, W, Flag) ;6768/* --------------------------------------------------------------------- */69/* free the workspace */70/* --------------------------------------------------------------------- */7172FREE (W) ;73FREE (Flag) ;74return (AMD_OK) ;75}767778/* ========================================================================= */79/* === AMD_wpreprocess ===================================================== */80/* ========================================================================= */8182/* The AMD_wpreprocess routine is not user-callable. It does not check its83* input for errors or allocate workspace (that is done by the user-callable84* AMD_preprocess routine). It does handle the n=0 case. */8586GLOBAL void AMD_wpreprocess87(88Int n, /* input matrix: A is n-by-n */89const Int Ap [ ], /* size n+1 */90const Int Ai [ ], /* size nz = Ap [n] */9192/* output matrix R: */93Int Rp [ ], /* size n+1 */94Int Ri [ ], /* size nz (or less, if duplicates present) */9596Int W [ ], /* workspace of size n */97Int Flag [ ] /* workspace of size n */98)99{100101/* --------------------------------------------------------------------- */102/* local variables */103/* --------------------------------------------------------------------- */104105Int i, j, p, p2 ;106107/* --------------------------------------------------------------------- */108/* count the entries in each row of A (excluding duplicates) */109/* --------------------------------------------------------------------- */110111for (i = 0 ; i < n ; i++)112{113W [i] = 0 ; /* # of nonzeros in row i (excl duplicates) */114Flag [i] = EMPTY ; /* Flag [i] = j if i appears in column j */115}116for (j = 0 ; j < n ; j++)117{118p2 = Ap [j+1] ;119for (p = Ap [j] ; p < p2 ; p++)120{121i = Ai [p] ;122if (Flag [i] != j)123{124/* row index i has not yet appeared in column j */125W [i]++ ; /* one more entry in row i */126Flag [i] = j ; /* flag row index i as appearing in col j*/127}128}129}130131/* --------------------------------------------------------------------- */132/* compute the row pointers for R */133/* --------------------------------------------------------------------- */134135Rp [0] = 0 ;136for (i = 0 ; i < n ; i++)137{138Rp [i+1] = Rp [i] + W [i] ;139}140for (i = 0 ; i < n ; i++)141{142W [i] = Rp [i] ;143Flag [i] = EMPTY ;144}145146/* --------------------------------------------------------------------- */147/* construct the row form matrix R */148/* --------------------------------------------------------------------- */149150/* R = row form of pattern of A */151for (j = 0 ; j < n ; j++)152{153p2 = Ap [j+1] ;154for (p = Ap [j] ; p < p2 ; p++)155{156i = Ai [p] ;157if (Flag [i] != j)158{159/* row index i has not yet appeared in column j */160Ri [W [i]++] = j ; /* put col j in row i */161Flag [i] = j ; /* flag row index i as appearing in col j*/162}163}164}165166#ifndef NDEBUG167for (j = 0 ; j < n ; j++)168{169ASSERT (W [j] == Rp [j+1]) ;170}171ASSERT (AMD_valid (n, n, Rp, Ri)) ;172#endif173}174175176/* ========================================================================= */177/* === AMD_preprocess_valid ================================================ */178/* ========================================================================= */179180/* Not user-callable. Checks a matrix and returns TRUE if it is valid as input181* to AMD_wpreprocess, FALSE otherwise. */182183GLOBAL Int AMD_preprocess_valid184(185Int n,186const Int Ap [ ],187const Int Ai [ ]188)189{190Int i, j, p, nz ;191192if (n < 0 || !Ai || !Ap)193{194return (FALSE) ;195}196nz = Ap [n] ;197if (Ap [0] != 0 || nz < 0)198{199/* column pointers must start at Ap [0] = 0, and Ap [n] must be >= 0 */200AMD_DEBUG0 (("column 0 pointer bad or nz < 0\n")) ;201return (FALSE) ;202}203for (j = 0 ; j < n ; j++)204{205if (Ap [j] > Ap [j+1])206{207/* column pointers must be ascending */208AMD_DEBUG0 (("column "ID" pointer bad\n", j)) ;209return (FALSE) ;210}211}212for (p = 0 ; p < nz ; p++)213{214i = Ai [p] ;215AMD_DEBUG3 (("row: "ID"\n", i)) ;216if (i < 0 || i >= n)217{218/* row index out of range */219AMD_DEBUG0 (("index out of range, col "ID" row "ID"\n", j, i)) ;220return (FALSE) ;221}222}223return (TRUE) ;224}225226227