// 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 [s,d,c,z]memory.c files 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 EIGEN_SPARSELU_MEMORY
#define EIGEN_SPARSELU_MEMORY

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

namespace Eigen {
namespace internal {

enum { LUNoMarker = 3 };
enum { emptyIdxLU = -1 };
inline Index LUnumTempV(Index& m, Index& w, Index& t, Index& b) { return (std::max)(m, (t + b) * w); }

template <typename Scalar>
inline Index LUTempSpace(Index& m, Index& w) {
  return (2 * w + 4 + LUNoMarker) * m * sizeof(Index) + (w + 1) * m * sizeof(Scalar);
}

/**
 * Expand the existing storage to accommodate more fill-ins
 * \param vec Valid pointer to the vector to allocate or expand
 * \param[in,out] length  At input, contain the current length of the vector that is to be increased. At output, length
 * of the newly allocated vector \param[in] nbElts Current number of elements in the factors \param keep_prev  1: use
 * length  and do not expand the vector; 0: compute new_len and expand \param[in,out] num_expansions Number of times the
 * memory has been expanded
 */
template <typename Scalar, typename StorageIndex>
template <typename VectorType>
Index SparseLUImpl<Scalar, StorageIndex>::expand(VectorType& vec, Index& length, Index nbElts, Index keep_prev,
                                                 Index& num_expansions) {
  float alpha = 1.5;  // Ratio of the memory increase
  Index new_len;      // New size of the allocated memory

  if (num_expansions == 0 || keep_prev)
    new_len = length;  // First time allocate requested
  else
    new_len = (std::max)(length + 1, Index(alpha * length));

  VectorType old_vec;  // Temporary vector to hold the previous values
  if (nbElts > 0) old_vec = vec.segment(0, nbElts);

    // Allocate or expand the current vector
#ifdef EIGEN_EXCEPTIONS
  try
#endif
  {
    vec.resize(new_len);
  }
#ifdef EIGEN_EXCEPTIONS
  catch (std::bad_alloc&)
#else
  if (!vec.size())
#endif
  {
    if (!num_expansions) {
      // First time to allocate from LUMemInit()
      // Let LUMemInit() deals with it.
      return -1;
    }
    if (keep_prev) {
      // In this case, the memory length should not not be reduced
      return new_len;
    } else {
      // Reduce the size and increase again
      Index tries = 0;  // Number of attempts
      do {
        alpha = (alpha + 1) / 2;
        new_len = (std::max)(length + 1, Index(alpha * length));
#ifdef EIGEN_EXCEPTIONS
        try
#endif
        {
          vec.resize(new_len);
        }
#ifdef EIGEN_EXCEPTIONS
        catch (std::bad_alloc&)
#else
        if (!vec.size())
#endif
        {
          tries += 1;
          if (tries > 10) return new_len;
        }
      } while (!vec.size());
    }
  }
  // Copy the previous values to the newly allocated space
  if (nbElts > 0) vec.segment(0, nbElts) = old_vec;

  length = new_len;
  if (num_expansions) ++num_expansions;
  return 0;
}

/**
 * \brief  Allocate various working space for the numerical factorization phase.
 * \param m number of rows of the input matrix
 * \param n number of columns
 * \param annz number of initial nonzeros in the matrix
 * \param lwork  if lwork=-1, this routine returns an estimated size of the required memory
 * \param glu persistent data to facilitate multiple factors : will be deleted later ??
 * \param fillratio estimated ratio of fill in the factors
 * \param panel_size Size of a panel
 * \return an estimated size of the required memory if lwork = -1; otherwise, return the size of actually allocated
 * memory when allocation failed, and 0 on success \note Unlike SuperLU, this routine does not support successive
 * factorization with the same pattern and the same row permutation
 */
template <typename Scalar, typename StorageIndex>
Index SparseLUImpl<Scalar, StorageIndex>::memInit(Index m, Index n, Index annz, Index lwork, Index fillratio,
                                                  Index panel_size, GlobalLU_t& glu) {
  Index& num_expansions = glu.num_expansions;  // No memory expansions so far
  num_expansions = 0;
  glu.nzumax = glu.nzlumax = (std::min)(fillratio * (annz + 1) / n, m) * n;  // estimated number of nonzeros in U
  glu.nzlmax = (std::max)(Index(4), fillratio) * (annz + 1) / 4;             // estimated  nnz in L factor
  // Return the estimated size to the user if necessary
  Index tempSpace;
  tempSpace = (2 * panel_size + 4 + LUNoMarker) * m * sizeof(Index) + (panel_size + 1) * m * sizeof(Scalar);
  if (lwork == emptyIdxLU) {
    Index estimated_size;
    estimated_size = (5 * n + 5) * sizeof(Index) + tempSpace + (glu.nzlmax + glu.nzumax) * sizeof(Index) +
                     (glu.nzlumax + glu.nzumax) * sizeof(Scalar) + n;
    return estimated_size;
  }

  // Setup the required space

  // First allocate Integer pointers for L\U factors
  glu.xsup.resize(n + 1);
  glu.supno.resize(n + 1);
  glu.xlsub.resize(n + 1);
  glu.xlusup.resize(n + 1);
  glu.xusub.resize(n + 1);

  // Reserve memory for L/U factors
  do {
    if ((expand<ScalarVector>(glu.lusup, glu.nzlumax, 0, 0, num_expansions) < 0) ||
        (expand<ScalarVector>(glu.ucol, glu.nzumax, 0, 0, num_expansions) < 0) ||
        (expand<IndexVector>(glu.lsub, glu.nzlmax, 0, 0, num_expansions) < 0) ||
        (expand<IndexVector>(glu.usub, glu.nzumax, 0, 1, num_expansions) < 0)) {
      // Reduce the estimated size and retry
      glu.nzlumax /= 2;
      glu.nzumax /= 2;
      glu.nzlmax /= 2;
      if (glu.nzlumax < annz) return glu.nzlumax;
    }
  } while (!glu.lusup.size() || !glu.ucol.size() || !glu.lsub.size() || !glu.usub.size());

  ++num_expansions;
  return 0;

}  // end LuMemInit

/**
 * \brief Expand the existing storage
 * \param vec vector to expand
 * \param[in,out] maxlen On input, previous size of vec (Number of elements to copy ). on output, new size
 * \param nbElts current number of elements in the vector.
 * \param memtype Type of the element to expand
 * \param num_expansions Number of expansions
 * \return 0 on success, > 0 size of the memory allocated so far
 */
template <typename Scalar, typename StorageIndex>
template <typename VectorType>
Index SparseLUImpl<Scalar, StorageIndex>::memXpand(VectorType& vec, Index& maxlen, Index nbElts, MemType memtype,
                                                   Index& num_expansions) {
  Index failed_size;
  if (memtype == USUB)
    failed_size = this->expand<VectorType>(vec, maxlen, nbElts, 1, num_expansions);
  else
    failed_size = this->expand<VectorType>(vec, maxlen, nbElts, 0, num_expansions);

  if (failed_size) return failed_size;

  return 0;
}

}  // end namespace internal

}  // end namespace Eigen
#endif  // EIGEN_SPARSELU_MEMORY
