// 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
#ifndef METIS_SUPPORT_H
#define METIS_SUPPORT_H

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

namespace Eigen {
/**
 * Get the fill-reducing ordering from the METIS package
 *
 * If A is the original matrix and Ap is the permuted matrix,
 * the fill-reducing permutation is defined as follows :
 * Row (column) i of Ap is the matperm(i) row (column) of A.
 * WARNING: As computed by METIS, this corresponds to the vector perm (instead of iperm)
 */
template <typename StorageIndex>
class MetisOrdering {
 public:
  typedef PermutationMatrix<Dynamic, Dynamic, StorageIndex> PermutationType;
  typedef Matrix<StorageIndex, Dynamic, 1> IndexVector;

  template <typename MatrixType>
  void get_symmetrized_graph(const MatrixType& A) {
    Index m = A.cols();
    eigen_assert((A.rows() == A.cols()) && "ONLY FOR SQUARED MATRICES");
    // Get the transpose of the input matrix
    MatrixType At = A.transpose();
    // Get the number of nonzeros elements in each row/col of At+A
    Index TotNz = 0;
    IndexVector visited(m);
    visited.setConstant(-1);
    for (StorageIndex j = 0; j < m; j++) {
      // Compute the union structure of A(j,:) and At(j,:)
      visited(j) = j;  // Do not include the diagonal element
      // Get the nonzeros in row/column j of A
      for (typename MatrixType::InnerIterator it(A, j); it; ++it) {
        Index idx = it.index();  // Get the row index (for column major) or column index (for row major)
        if (visited(idx) != j) {
          visited(idx) = j;
          ++TotNz;
        }
      }
      // Get the nonzeros in row/column j of At
      for (typename MatrixType::InnerIterator it(At, j); it; ++it) {
        Index idx = it.index();
        if (visited(idx) != j) {
          visited(idx) = j;
          ++TotNz;
        }
      }
    }
    // Reserve place for A + At
    m_indexPtr.resize(m + 1);
    m_innerIndices.resize(TotNz);

    // Now compute the real adjacency list of each column/row
    visited.setConstant(-1);
    StorageIndex CurNz = 0;
    for (StorageIndex j = 0; j < m; j++) {
      m_indexPtr(j) = CurNz;

      visited(j) = j;  // Do not include the diagonal element
      // Add the pattern of row/column j of A to A+At
      for (typename MatrixType::InnerIterator it(A, j); it; ++it) {
        StorageIndex idx = it.index();  // Get the row index (for column major) or column index (for row major)
        if (visited(idx) != j) {
          visited(idx) = j;
          m_innerIndices(CurNz) = idx;
          CurNz++;
        }
      }
      // Add the pattern of row/column j of At to A+At
      for (typename MatrixType::InnerIterator it(At, j); it; ++it) {
        StorageIndex idx = it.index();
        if (visited(idx) != j) {
          visited(idx) = j;
          m_innerIndices(CurNz) = idx;
          ++CurNz;
        }
      }
    }
    m_indexPtr(m) = CurNz;
  }

  template <typename MatrixType>
  void operator()(const MatrixType& A, PermutationType& matperm) {
    StorageIndex m = internal::convert_index<StorageIndex>(
        A.cols());  // must be StorageIndex, because it is passed by address to METIS
    IndexVector perm(m), iperm(m);
    // First, symmetrize the matrix graph.
    get_symmetrized_graph(A);
    int output_error;

    // Call the fill-reducing routine from METIS
    output_error =
        METIS_NodeND(&m, m_indexPtr.data(), m_innerIndices.data(), nullptr, nullptr, perm.data(), iperm.data());

    if (output_error != METIS_OK) {
      // FIXME The ordering interface should define a class of possible errors
      std::cerr << "ERROR WHILE CALLING THE METIS PACKAGE \n";
      return;
    }

    // Get the fill-reducing permutation
    // NOTE:  If Ap is the permuted matrix then perm and iperm vectors are defined as follows
    // Row (column) i of Ap is the perm(i) row(column) of A, and row (column) i of A is the iperm(i) row(column) of Ap

    matperm.resize(m);
    for (int j = 0; j < m; j++) matperm.indices()(iperm(j)) = j;
  }

 protected:
  IndexVector m_indexPtr;      // Pointer to the adjacency list of each row/column
  IndexVector m_innerIndices;  // Adjacency list
};

}  // namespace Eigen
#endif
