// 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/.

/*

 * 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) {
    // No kid for the current node
    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
