1c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This file is part of Eigen, a lightweight C++ template library 2c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// for linear algebra. 3c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// 4c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Copyright (C) 2010 Gael Guennebaud <gael.guennebaud@inria.fr> 5c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// 6c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// This Source Code Form is subject to the terms of the Mozilla 7c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// Public License v. 2.0. If a copy of the MPL was not distributed 8c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath// with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 9c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 10c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/* 11c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 12c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathNOTE: this routine has been adapted from the CSparse library: 13c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 14c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathCopyright (c) 2006, Timothy A. Davis. 15c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathhttp://www.cise.ufl.edu/research/sparse/CSparse 16c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 17c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathCSparse is free software; you can redistribute it and/or 18c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathmodify it under the terms of the GNU Lesser General Public 19c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathLicense as published by the Free Software Foundation; either 20c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathversion 2.1 of the License, or (at your option) any later version. 21c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 22c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathCSparse is distributed in the hope that it will be useful, 23c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathbut WITHOUT ANY WARRANTY; without even the implied warranty of 24c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 25c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathLesser General Public License for more details. 26c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 27c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathYou should have received a copy of the GNU Lesser General Public 28c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathLicense along with this Module; if not, write to the Free Software 29c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathFoundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 30c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 31c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath*/ 32c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 33c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#include "../Core/util/NonMPL2.h" 34c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 35c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#ifndef EIGEN_SPARSE_AMD_H 36c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#define EIGEN_SPARSE_AMD_H 37c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 38c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathnamespace Eigen { 39c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 40c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathnamespace internal { 41c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 42c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename T> inline T amd_flip(const T& i) { return -i-2; } 43c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename T> inline T amd_unflip(const T& i) { return i<0 ? amd_flip(i) : i; } 44c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename T0, typename T1> inline bool amd_marked(const T0* w, const T1& j) { return w[j]<0; } 45c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename T0, typename T1> inline void amd_mark(const T0* w, const T1& j) { return w[j] = amd_flip(w[j]); } 46c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 47c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/* clear w */ 48c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Index> 49c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathstatic int cs_wclear (Index mark, Index lemax, Index *w, Index n) 50c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 51c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Index k; 52c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(mark < 2 || (mark + lemax < 0)) 53c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 54c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(k = 0; k < n; k++) 55c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(w[k] != 0) 56c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath w[k] = 1; 57c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mark = 2; 58c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 59c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return (mark); /* at this point, w[0..n-1] < mark holds */ 60c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 61c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 62c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/* depth-first search and postorder of a tree rooted at node j */ 63c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Index> 64c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan KamathIndex cs_tdfs(Index j, Index k, Index *head, const Index *next, Index *post, Index *stack) 65c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 66c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath int i, p, top = 0; 67c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(!head || !next || !post || !stack) return (-1); /* check inputs */ 68c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath stack[0] = j; /* place j on the stack */ 69c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath while (top >= 0) /* while (stack is not empty) */ 70c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 71c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath p = stack[top]; /* p = top of stack */ 72c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath i = head[p]; /* i = youngest child of p */ 73c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(i == -1) 74c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 75c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath top--; /* p has no unordered children left */ 76c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath post[k++] = p; /* node p is the kth postordered node */ 77c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 78c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath else 79c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 80c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath head[p] = next[i]; /* remove i from children of p */ 81c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath stack[++top] = i; /* start dfs on child node i */ 82c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 83c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 84c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath return k; 85c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 86c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 87c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 88c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath/** \internal 89c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * Approximate minimum degree ordering algorithm. 90c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * \returns the permutation P reducing the fill-in of the input matrix \a C 91c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * The input matrix \a C must be a selfadjoint compressed column major SparseMatrix object. Both the upper and lower parts have to be stored, but the diagonal entries are optional. 92c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath * On exit the values of C are destroyed */ 93c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathtemplate<typename Scalar, typename Index> 94c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamathvoid minimum_degree_ordering(SparseMatrix<Scalar,ColMajor,Index>& C, PermutationMatrix<Dynamic,Dynamic,Index>& perm) 95c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath{ 96c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath using std::sqrt; 97c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath typedef SparseMatrix<Scalar,ColMajor,Index> CCS; 98c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 99c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath int d, dk, dext, lemax = 0, e, elenk, eln, i, j, k, k1, 100c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath k2, k3, jlast, ln, dense, nzmax, mindeg = 0, nvi, nvj, nvk, mark, wnvi, 101c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath ok, nel = 0, p, p1, p2, p3, p4, pj, pk, pk1, pk2, pn, q, t; 102c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath unsigned int h; 103c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 104c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Index n = C.cols(); 105c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath dense = std::max<Index> (16, Index(10 * sqrt(double(n)))); /* find dense threshold */ 106c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath dense = std::min<Index> (n-2, dense); 107c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 108c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Index cnz = C.nonZeros(); 109c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath perm.resize(n+1); 110c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath t = cnz + cnz/5 + 2*n; /* add elbow room to C */ 111c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath C.resizeNonZeros(t); 112c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 113c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Index* W = new Index[8*(n+1)]; /* get workspace */ 114c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Index* len = W; 115c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Index* nv = W + (n+1); 116c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Index* next = W + 2*(n+1); 117c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Index* head = W + 3*(n+1); 118c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Index* elen = W + 4*(n+1); 119c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Index* degree = W + 5*(n+1); 120c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Index* w = W + 6*(n+1); 121c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Index* hhead = W + 7*(n+1); 122c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Index* last = perm.indices().data(); /* use P as workspace for last */ 123c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 124c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath /* --- Initialize quotient graph ---------------------------------------- */ 125c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Index* Cp = C.outerIndexPtr(); 126c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Index* Ci = C.innerIndexPtr(); 127c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(k = 0; k < n; k++) 128c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath len[k] = Cp[k+1] - Cp[k]; 129c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath len[n] = 0; 130c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath nzmax = t; 131c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 132c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(i = 0; i <= n; i++) 133c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 134c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath head[i] = -1; // degree list i is empty 135c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath last[i] = -1; 136c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath next[i] = -1; 137c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath hhead[i] = -1; // hash list i is empty 138c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath nv[i] = 1; // node i is just one node 139c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath w[i] = 1; // node i is alive 140c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath elen[i] = 0; // Ek of node i is empty 141c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath degree[i] = len[i]; // degree of node i 142c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 143c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mark = internal::cs_wclear<Index>(0, 0, w, n); /* clear w */ 144c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath elen[n] = -2; /* n is a dead element */ 145c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Cp[n] = -1; /* n is a root of assembly tree */ 146c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath w[n] = 0; /* n is a dead element */ 147c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 148c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath /* --- Initialize degree lists ------------------------------------------ */ 149c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(i = 0; i < n; i++) 150c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 151c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath d = degree[i]; 152c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(d == 0) /* node i is empty */ 153c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 154c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath elen[i] = -2; /* element i is dead */ 155c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath nel++; 156c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Cp[i] = -1; /* i is a root of assembly tree */ 157c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath w[i] = 0; 158c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 159c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath else if(d > dense) /* node i is dense */ 160c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 161c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath nv[i] = 0; /* absorb i into element n */ 162c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath elen[i] = -1; /* node i is dead */ 163c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath nel++; 164c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Cp[i] = amd_flip (n); 165c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath nv[n]++; 166c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 167c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath else 168c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 169c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(head[d] != -1) last[head[d]] = i; 170c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath next[i] = head[d]; /* put node i in degree list d */ 171c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath head[d] = i; 172c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 173c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 174c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 175c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath while (nel < n) /* while (selecting pivots) do */ 176c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 177c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath /* --- Select node of minimum approximate degree -------------------- */ 178c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(k = -1; mindeg < n && (k = head[mindeg]) == -1; mindeg++) {} 179c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(next[k] != -1) last[next[k]] = -1; 180c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath head[mindeg] = next[k]; /* remove k from degree list */ 181c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath elenk = elen[k]; /* elenk = |Ek| */ 182c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath nvk = nv[k]; /* # of nodes k represents */ 183c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath nel += nvk; /* nv[k] nodes of A eliminated */ 184c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 185c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath /* --- Garbage collection ------------------------------------------- */ 186c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(elenk > 0 && cnz + mindeg >= nzmax) 187c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 188c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(j = 0; j < n; j++) 189c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 190c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if((p = Cp[j]) >= 0) /* j is a live node or element */ 191c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 192c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Cp[j] = Ci[p]; /* save first entry of object */ 193c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Ci[p] = amd_flip (j); /* first entry is now amd_flip(j) */ 194c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 195c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 196c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(q = 0, p = 0; p < cnz; ) /* scan all of memory */ 197c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 198c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if((j = amd_flip (Ci[p++])) >= 0) /* found object j */ 199c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 200c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Ci[q] = Cp[j]; /* restore first entry of object */ 201c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Cp[j] = q++; /* new pointer to object j */ 202c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(k3 = 0; k3 < len[j]-1; k3++) Ci[q++] = Ci[p++]; 203c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 204c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 205c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath cnz = q; /* Ci[cnz...nzmax-1] now free */ 206c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 207c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 208c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath /* --- Construct new element ---------------------------------------- */ 209c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath dk = 0; 210c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath nv[k] = -nvk; /* flag k as in Lk */ 211c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath p = Cp[k]; 212c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath pk1 = (elenk == 0) ? p : cnz; /* do in place if elen[k] == 0 */ 213c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath pk2 = pk1; 214c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(k1 = 1; k1 <= elenk + 1; k1++) 215c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 216c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(k1 > elenk) 217c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 218c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath e = k; /* search the nodes in k */ 219c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath pj = p; /* list of nodes starts at Ci[pj]*/ 220c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath ln = len[k] - elenk; /* length of list of nodes in k */ 221c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 222c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath else 223c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 224c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath e = Ci[p++]; /* search the nodes in e */ 225c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath pj = Cp[e]; 226c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath ln = len[e]; /* length of list of nodes in e */ 227c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 228c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(k2 = 1; k2 <= ln; k2++) 229c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 230c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath i = Ci[pj++]; 231c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if((nvi = nv[i]) <= 0) continue; /* node i dead, or seen */ 232c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath dk += nvi; /* degree[Lk] += size of node i */ 233c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath nv[i] = -nvi; /* negate nv[i] to denote i in Lk*/ 234c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Ci[pk2++] = i; /* place i in Lk */ 235c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(next[i] != -1) last[next[i]] = last[i]; 236c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(last[i] != -1) /* remove i from degree list */ 237c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 238c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath next[last[i]] = next[i]; 239c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 240c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath else 241c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 242c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath head[degree[i]] = next[i]; 243c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 244c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 245c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(e != k) 246c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 247c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Cp[e] = amd_flip (k); /* absorb e into k */ 248c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath w[e] = 0; /* e is now a dead element */ 249c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 250c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 251c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(elenk != 0) cnz = pk2; /* Ci[cnz...nzmax] is free */ 252c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath degree[k] = dk; /* external degree of k - |Lk\i| */ 253c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Cp[k] = pk1; /* element k is in Ci[pk1..pk2-1] */ 254c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath len[k] = pk2 - pk1; 255c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath elen[k] = -2; /* k is now an element */ 256c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 257c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath /* --- Find set differences ----------------------------------------- */ 258c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mark = internal::cs_wclear<Index>(mark, lemax, w, n); /* clear w if necessary */ 259c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(pk = pk1; pk < pk2; pk++) /* scan 1: find |Le\Lk| */ 260c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 261c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath i = Ci[pk]; 262c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if((eln = elen[i]) <= 0) continue;/* skip if elen[i] empty */ 263c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath nvi = -nv[i]; /* nv[i] was negated */ 264c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath wnvi = mark - nvi; 265c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(p = Cp[i]; p <= Cp[i] + eln - 1; p++) /* scan Ei */ 266c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 267c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath e = Ci[p]; 268c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(w[e] >= mark) 269c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 270c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath w[e] -= nvi; /* decrement |Le\Lk| */ 271c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 272c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath else if(w[e] != 0) /* ensure e is a live element */ 273c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 274c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath w[e] = degree[e] + wnvi; /* 1st time e seen in scan 1 */ 275c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 276c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 277c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 278c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 279c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath /* --- Degree update ------------------------------------------------ */ 280c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(pk = pk1; pk < pk2; pk++) /* scan2: degree update */ 281c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 282c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath i = Ci[pk]; /* consider node i in Lk */ 283c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath p1 = Cp[i]; 284c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath p2 = p1 + elen[i] - 1; 285c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath pn = p1; 286c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(h = 0, d = 0, p = p1; p <= p2; p++) /* scan Ei */ 287c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 288c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath e = Ci[p]; 289c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(w[e] != 0) /* e is an unabsorbed element */ 290c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 291c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath dext = w[e] - mark; /* dext = |Le\Lk| */ 292c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(dext > 0) 293c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 294c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath d += dext; /* sum up the set differences */ 295c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Ci[pn++] = e; /* keep e in Ei */ 296c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath h += e; /* compute the hash of node i */ 297c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 298c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath else 299c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 300c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Cp[e] = amd_flip (k); /* aggressive absorb. e->k */ 301c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath w[e] = 0; /* e is a dead element */ 302c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 303c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 304c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 305c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath elen[i] = pn - p1 + 1; /* elen[i] = |Ei| */ 306c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath p3 = pn; 307c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath p4 = p1 + len[i]; 308c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(p = p2 + 1; p < p4; p++) /* prune edges in Ai */ 309c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 310c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath j = Ci[p]; 311c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if((nvj = nv[j]) <= 0) continue; /* node j dead or in Lk */ 312c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath d += nvj; /* degree(i) += |j| */ 313c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Ci[pn++] = j; /* place j in node list of i */ 314c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath h += j; /* compute hash for node i */ 315c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 316c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(d == 0) /* check for mass elimination */ 317c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 318c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Cp[i] = amd_flip (k); /* absorb i into k */ 319c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath nvi = -nv[i]; 320c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath dk -= nvi; /* |Lk| -= |i| */ 321c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath nvk += nvi; /* |k| += nv[i] */ 322c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath nel += nvi; 323c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath nv[i] = 0; 324c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath elen[i] = -1; /* node i is dead */ 325c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 326c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath else 327c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 328c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath degree[i] = std::min<Index> (degree[i], d); /* update degree(i) */ 329c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Ci[pn] = Ci[p3]; /* move first node to end */ 330c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Ci[p3] = Ci[p1]; /* move 1st el. to end of Ei */ 331c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Ci[p1] = k; /* add k as 1st element in of Ei */ 332c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath len[i] = pn - p1 + 1; /* new len of adj. list of node i */ 333c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath h %= n; /* finalize hash of i */ 334c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath next[i] = hhead[h]; /* place i in hash bucket */ 335c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath hhead[h] = i; 336c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath last[i] = h; /* save hash of i in last[i] */ 337c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 338c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } /* scan2 is done */ 339c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath degree[k] = dk; /* finalize |Lk| */ 340c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath lemax = std::max<Index>(lemax, dk); 341c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mark = internal::cs_wclear<Index>(mark+lemax, lemax, w, n); /* clear w */ 342c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 343c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath /* --- Supernode detection ------------------------------------------ */ 344c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(pk = pk1; pk < pk2; pk++) 345c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 346c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath i = Ci[pk]; 347c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(nv[i] >= 0) continue; /* skip if i is dead */ 348c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath h = last[i]; /* scan hash bucket of node i */ 349c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath i = hhead[h]; 350c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath hhead[h] = -1; /* hash bucket will be empty */ 351c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(; i != -1 && next[i] != -1; i = next[i], mark++) 352c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 353c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath ln = len[i]; 354c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath eln = elen[i]; 355c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(p = Cp[i]+1; p <= Cp[i] + ln-1; p++) w[Ci[p]] = mark; 356c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath jlast = i; 357c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(j = next[i]; j != -1; ) /* compare i with all j */ 358c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 359c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath ok = (len[j] == ln) && (elen[j] == eln); 360c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(p = Cp[j] + 1; ok && p <= Cp[j] + ln - 1; p++) 361c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 362c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(w[Ci[p]] != mark) ok = 0; /* compare i and j*/ 363c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 364c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(ok) /* i and j are identical */ 365c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 366c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Cp[j] = amd_flip (i); /* absorb j into i */ 367c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath nv[i] += nv[j]; 368c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath nv[j] = 0; 369c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath elen[j] = -1; /* node j is dead */ 370c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath j = next[j]; /* delete j from hash bucket */ 371c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath next[jlast] = j; 372c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 373c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath else 374c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 375c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath jlast = j; /* j and i are different */ 376c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath j = next[j]; 377c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 378c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 379c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 380c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 381c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 382c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath /* --- Finalize new element------------------------------------------ */ 383c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(p = pk1, pk = pk1; pk < pk2; pk++) /* finalize Lk */ 384c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 385c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath i = Ci[pk]; 386c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if((nvi = -nv[i]) <= 0) continue;/* skip if i is dead */ 387c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath nv[i] = nvi; /* restore nv[i] */ 388c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath d = degree[i] + dk - nvi; /* compute external degree(i) */ 389c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath d = std::min<Index> (d, n - nel - nvi); 390c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(head[d] != -1) last[head[d]] = i; 391c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath next[i] = head[d]; /* put i back in degree list */ 392c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath last[i] = -1; 393c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath head[d] = i; 394c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath mindeg = std::min<Index> (mindeg, d); /* find new minimum degree */ 395c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath degree[i] = d; 396c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Ci[p++] = i; /* place i in Lk */ 397c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 398c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath nv[k] = nvk; /* # nodes absorbed into k */ 399c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if((len[k] = p-pk1) == 0) /* length of adj list of element k*/ 400c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 401c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath Cp[k] = -1; /* k is a root of the tree */ 402c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath w[k] = 0; /* k is now a dead element */ 403c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 404c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(elenk != 0) cnz = p; /* free unused space in Lk */ 405c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 406c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 407c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath /* --- Postordering ----------------------------------------------------- */ 408c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(i = 0; i < n; i++) Cp[i] = amd_flip (Cp[i]);/* fix assembly tree */ 409c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(j = 0; j <= n; j++) head[j] = -1; 410c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(j = n; j >= 0; j--) /* place unordered nodes in lists */ 411c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 412c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(nv[j] > 0) continue; /* skip if j is an element */ 413c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath next[j] = head[Cp[j]]; /* place j in list of its parent */ 414c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath head[Cp[j]] = j; 415c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 416c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(e = n; e >= 0; e--) /* place elements in lists */ 417c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 418c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(nv[e] <= 0) continue; /* skip unless e is an element */ 419c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(Cp[e] != -1) 420c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 421c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath next[e] = head[Cp[e]]; /* place e in list of its parent */ 422c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath head[Cp[e]] = e; 423c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 424c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 425c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath for(k = 0, i = 0; i <= n; i++) /* postorder the assembly tree */ 426c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath { 427c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath if(Cp[i] == -1) k = internal::cs_tdfs<Index>(i, k, head, next, perm.indices().data(), w); 428c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath } 429c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 430c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath perm.indices().conservativeResize(n); 431c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 432c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath delete[] W; 433c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} 434c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 435c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} // namespace internal 436c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 437c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath} // end namespace Eigen 438c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath 439c981c48f5bc9aefeffc0bcb0cc3934c2fae179ddNarayan Kamath#endif // EIGEN_SPARSE_AMD_H 440