// 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/.
// SPDX-License-Identifier: MPL-2.0

/*

 * NOTE: This file is the modified version of sp_coletree.c file in SuperLU

 * -- SuperLU routine (version 3.1) --
 * Univ. of California Berkeley, Xerox Palo Alto Research Center,
 * and Lawrence Berkeley National Lab.
 * August 1, 2008
 *
 * 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 SPARSE_COLETREE_H
#define SPARSE_COLETREE_H

// IWYU pragma: private
#include "./InternalHeaderCheck.h"

namespace Eigen {

namespace internal {

/** Find the root of the tree/set containing the vertex i : Use Path halving */
template <typename Index, typename IndexVector>
Index etree_find(Index i, IndexVector& pp) {
  Index p = pp(i);   // Parent
  Index gp = pp(p);  // Grand parent
  while (gp != p) {
    pp(i) = gp;  // Parent pointer on find path is changed to former grand parent
    i = gp;
    p = pp(i);
    gp = pp(p);
  }
  return p;
}

/** Compute the column elimination tree of a sparse matrix
 * \param mat The matrix in column-major format.
 * \param parent The elimination tree
 * \param firstRowElt The column index of the first element in each row
 * \param perm The permutation to apply to the column of \b mat
 */
template <typename MatrixType, typename IndexVector>
int coletree(const MatrixType& mat, IndexVector& parent, IndexVector& firstRowElt,
             typename MatrixType::StorageIndex* perm = 0) {
  typedef typename MatrixType::StorageIndex StorageIndex;
  StorageIndex nc = convert_index<StorageIndex>(mat.cols());  // Number of columns
  StorageIndex m = convert_index<StorageIndex>(mat.rows());
  StorageIndex diagSize = (std::min)(nc, m);
  IndexVector root(nc);  // root of subtree of etree
  root.setZero();
  IndexVector pp(nc);  // disjoint sets
  pp.setZero();        // Initialize disjoint sets
  parent.resize(mat.cols());
  // Compute first nonzero column in each row
  firstRowElt.resize(m);
  firstRowElt.setConstant(nc);
  firstRowElt.segment(0, diagSize).setLinSpaced(diagSize, 0, diagSize - 1);
  bool found_diag;
  for (StorageIndex col = 0; col < nc; col++) {
    StorageIndex pcol = col;
    if (perm) pcol = perm[col];
    for (typename MatrixType::InnerIterator it(mat, pcol); it; ++it) {
      Index row = it.row();
      firstRowElt(row) = (std::min)(firstRowElt(row), col);
    }
  }
  /* Compute etree by Liu's algorithm for symmetric matrices,
          except use (firstRowElt[r],c) in place of an edge (r,c) of A.
    Thus each row clique in A'*A is replaced by a star
    centered at its first vertex, which has the same fill. */
  StorageIndex rset, cset, rroot;
  for (StorageIndex col = 0; col < nc; col++) {
    found_diag = col >= m;
    pp(col) = col;
    cset = col;
    root(cset) = col;
    parent(col) = nc;
    /* The diagonal element is treated here even if it does not exist in the matrix
     * hence the loop is executed once more */
    StorageIndex pcol = col;
    if (perm) pcol = perm[col];
    for (typename MatrixType::InnerIterator it(mat, pcol); it || !found_diag;
         ++it) {  //  A sequence of interleaved find and union is performed
      Index i = col;
      if (it) i = it.index();
      if (i == col) found_diag = true;

      StorageIndex row = firstRowElt(i);
      if (row >= col) continue;
      rset = internal::etree_find(row, pp);  // Find the name of the set containing row
      rroot = root(rset);
      if (rroot != col) {
        parent(rroot) = col;
        pp(cset) = rset;
        cset = rset;
        root(cset) = col;
      }
    }
  }
  return 0;
}

/**
 * Depth-first search from vertex n.  No recursion.
 * This routine was contributed by Cédric Doucet, CEDRAT Group, Meylan, France.
 */
template <typename IndexVector>
void nr_etdfs(typename IndexVector::Scalar n, IndexVector& parent, IndexVector& first_kid, IndexVector& next_kid,
              IndexVector& post, typename IndexVector::Scalar postnum) {
  typedef typename IndexVector::Scalar StorageIndex;
  StorageIndex current = n, first, next;
  while (postnum != n) {
    first = first_kid(current);

    // no kid for the current node
    if (first == -1) {
      // Numbering this node because it has no kid
      post(current) = postnum++;

      // looking for the next kid
      next = next_kid(current);
      while (next == -1) {
        // No more kids : back to the parent node
        current = parent(current);
        // numbering the parent node
        post(current) = postnum++;

        // Get the next kid
        next = next_kid(current);
      }
      // stopping criterion
      if (postnum == n + 1) return;

      // Updating current node
      current = next;
    } else {
      current = first;
    }
  }
}

/**
 * \brief Post order a tree
 * \param n the number of nodes
 * \param parent Input tree
 * \param post postordered tree
 */
template <typename IndexVector>
void treePostorder(typename IndexVector::Scalar n, IndexVector& parent, IndexVector& post) {
  typedef typename IndexVector::Scalar StorageIndex;
  IndexVector first_kid, next_kid;  // Linked list of children
  StorageIndex postnum;
  // Allocate storage for working arrays and results
  first_kid.resize(n + 1);
  next_kid.setZero(n + 1);
  post.setZero(n + 1);

  // Set up structure describing children
  first_kid.setConstant(-1);
  for (StorageIndex v = n - 1; v >= 0; v--) {
    StorageIndex dad = parent(v);
    next_kid(v) = first_kid(dad);
    first_kid(dad) = v;
  }

  // Depth-first search from dummy root vertex #n
  postnum = 0;
  internal::nr_etdfs(n, parent, first_kid, next_kid, post, postnum);
}

}  // end namespace internal

}  // end namespace Eigen

#endif  // SPARSE_COLETREE_H
