| // This file is part of Eigen, a lightweight C++ template library | 
 | // for linear algebra. | 
 | // | 
 | // Copyright (C) 2012 Désiré Nuentsa-Wakam <desire.nuentsa_wakam@inria.fr> | 
 | // | 
 | // This Source Code Form is subject to the terms of the Mozilla | 
 | // Public License v. 2.0. If a copy of the MPL was not distributed | 
 | // with this file, You can obtain one at http://mozilla.org/MPL/2.0/. | 
 |  | 
 | /* This file is a modified version of heap_relax_snode.c file in SuperLU | 
 |  * -- SuperLU routine (version 3.0) -- | 
 |  * Univ. of California Berkeley, Xerox Palo Alto Research Center, | 
 |  * and Lawrence Berkeley National Lab. | 
 |  * October 15, 2003 | 
 |  * | 
 |  * Copyright (c) 1994 by Xerox Corporation.  All rights reserved. | 
 |  * | 
 |  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY | 
 |  * EXPRESSED OR IMPLIED.  ANY USE IS AT YOUR OWN RISK. | 
 |  * | 
 |  * Permission is hereby granted to use or copy this program for any | 
 |  * purpose, provided the above notices are retained on all copies. | 
 |  * Permission to modify the code and to distribute modified code is | 
 |  * granted, provided the above notices are retained, and a notice that | 
 |  * the code was modified is included with the above copyright notice. | 
 |  */ | 
 |  | 
 | #ifndef SPARSELU_HEAP_RELAX_SNODE_H | 
 | #define SPARSELU_HEAP_RELAX_SNODE_H | 
 |  | 
 | // IWYU pragma: private | 
 | #include "./InternalHeaderCheck.h" | 
 |  | 
 | namespace Eigen { | 
 | namespace internal { | 
 |  | 
 | /** | 
 |  * \brief Identify the initial relaxed supernodes | 
 |  * | 
 |  * This routine applied to a symmetric elimination tree. | 
 |  * It assumes that the matrix has been reordered according to the postorder of the etree | 
 |  * \param n The number of columns | 
 |  * \param et elimination tree | 
 |  * \param relax_columns Maximum number of columns allowed in a relaxed snode | 
 |  * \param descendants Number of descendants of each node in the etree | 
 |  * \param relax_end last column in a supernode | 
 |  */ | 
 | template <typename Scalar, typename StorageIndex> | 
 | void SparseLUImpl<Scalar, StorageIndex>::heap_relax_snode(const Index n, IndexVector& et, const Index relax_columns, | 
 |                                                           IndexVector& descendants, IndexVector& relax_end) { | 
 |   // The etree may not be postordered, but its heap ordered | 
 |   IndexVector post; | 
 |   internal::treePostorder(StorageIndex(n), et, post);  // Post order etree | 
 |   IndexVector inv_post(n + 1); | 
 |   for (StorageIndex i = 0; i < n + 1; ++i) inv_post(post(i)) = i;  // inv_post = post.inverse()??? | 
 |  | 
 |   // Renumber etree in postorder | 
 |   IndexVector iwork(n); | 
 |   IndexVector et_save(n + 1); | 
 |   for (Index i = 0; i < n; ++i) { | 
 |     iwork(post(i)) = post(et(i)); | 
 |   } | 
 |   et_save = et;  // Save the original etree | 
 |   et = iwork; | 
 |  | 
 |   // compute the number of descendants of each node in the etree | 
 |   relax_end.setConstant(emptyIdxLU); | 
 |   Index j, parent; | 
 |   descendants.setZero(); | 
 |   for (j = 0; j < n; j++) { | 
 |     parent = et(j); | 
 |     if (parent != n)  // not the dummy root | 
 |       descendants(parent) += descendants(j) + 1; | 
 |   } | 
 |   // Identify the relaxed supernodes by postorder traversal of the etree | 
 |   Index snode_start;  // beginning of a snode | 
 |   StorageIndex k; | 
 |   StorageIndex l; | 
 |   for (j = 0; j < n;) { | 
 |     parent = et(j); | 
 |     snode_start = j; | 
 |     while (parent != n && descendants(parent) < relax_columns) { | 
 |       j = parent; | 
 |       parent = et(j); | 
 |     } | 
 |     // Found a supernode in postordered etree, j is the last column | 
 |     k = StorageIndex(n); | 
 |     for (Index i = snode_start; i <= j; ++i) k = (std::min)(k, inv_post(i)); | 
 |     l = inv_post(j); | 
 |     if ((l - k) == (j - snode_start))  // Same number of columns in the snode | 
 |     { | 
 |       // This is also a supernode in the original etree | 
 |       relax_end(k) = l;  // Record last column | 
 |     } else { | 
 |       for (Index i = snode_start; i <= j; ++i) { | 
 |         l = inv_post(i); | 
 |         if (descendants(i) == 0) { | 
 |           relax_end(l) = l; | 
 |         } | 
 |       } | 
 |     } | 
 |     j++; | 
 |     // Search for a new leaf | 
 |     while (descendants(j) != 0 && j < n) j++; | 
 |   }  // End postorder traversal of the etree | 
 |  | 
 |   // Recover the original etree | 
 |   et = et_save; | 
 | } | 
 |  | 
 | }  // end namespace internal | 
 |  | 
 | }  // end namespace Eigen | 
 | #endif  // SPARSELU_HEAP_RELAX_SNODE_H |