// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@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 EIGEN_RANDOMSETTER_H
#define EIGEN_RANDOMSETTER_H

#if defined(EIGEN_GOOGLEHASH_SUPPORT)
// Ensure the ::google namespace exists, required for checking existence of
// ::google::dense_hash_map and ::google::sparse_hash_map.
namespace google {}
#endif

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

namespace Eigen {

/** Represents a std::map
 *
 * \see RandomSetter
 */
template <typename Scalar>
struct StdMapTraits {
  typedef int KeyType;
  typedef std::map<KeyType, Scalar> Type;
  enum { IsSorted = 1 };

  static void setInvalidKey(Type&, const KeyType&) {}
};

/** Represents a std::unordered_map
 * \see RandomSetter
 */
template <typename Scalar>
struct StdUnorderedMapTraits {
  typedef int KeyType;
  typedef std::unordered_map<KeyType, Scalar> Type;
  enum { IsSorted = 0 };

  static void setInvalidKey(Type&, const KeyType&) {}
};

#if defined(EIGEN_GOOGLEHASH_SUPPORT)

namespace google {

// Namespace work-around, since sometimes dense_hash_map and sparse_hash_map
// are in the global namespace, and other times they are under ::google.
using namespace ::google;

template <typename KeyType, typename Scalar>
struct DenseHashMap {
  typedef dense_hash_map<KeyType, Scalar> type;
};

template <typename KeyType, typename Scalar>
struct SparseHashMap {
  typedef sparse_hash_map<KeyType, Scalar> type;
};

}  // namespace google

/** Represents a google::dense_hash_map
 *
 * \see RandomSetter
 */
template <typename Scalar>
struct GoogleDenseHashMapTraits {
  typedef int KeyType;
  typedef typename google::DenseHashMap<KeyType, Scalar>::type Type;
  enum { IsSorted = 0 };

  static void setInvalidKey(Type& map, const KeyType& k) { map.set_empty_key(k); }
};

/** Represents a google::sparse_hash_map
 *
 * \see RandomSetter
 */
template <typename Scalar>
struct GoogleSparseHashMapTraits {
  typedef int KeyType;
  typedef typename google::SparseHashMap<KeyType, Scalar>::type Type;
  enum { IsSorted = 0 };

  static void setInvalidKey(Type&, const KeyType&) {}
};
#endif

/** \class RandomSetter
 * \ingroup SparseExtra_Module
 * \brief The RandomSetter is a wrapper object allowing to set/update a sparse matrix with random access
 *
 * \tparam SparseMatrixType the type of the sparse matrix we are updating
 * \tparam MapTraits a traits class representing the map implementation used for the temporary sparse storage.
 *                  Its default value depends on the system.
 * \tparam OuterPacketBits defines the number of rows (or columns) managed by a single map object
 *                        as a power of two exponent.
 *
 * This class temporarily represents a sparse matrix object using a generic map implementation allowing for
 * efficient random access. The conversion from the compressed representation to a hash_map object is performed
 * in the RandomSetter constructor, while the sparse matrix is updated back at destruction time. This strategy
 * suggests the use of nested blocks as in this example:
 *
 * \code
 * SparseMatrix<double> m(rows,cols);
 * {
 *   RandomSetter<SparseMatrix<double> > w(m);
 *   // don't use m but w instead with read/write random access to the coefficients:
 *   for(;;)
 *     w(rand(),rand()) = rand;
 * }
 * // when w is deleted, the data are copied back to m
 * // and m is ready to use.
 * \endcode
 *
 * Since hash_map objects are not fully sorted, representing a full matrix as a single hash_map would
 * involve a big and costly sort to update the compressed matrix back. To overcome this issue, a RandomSetter
 * use multiple hash_map, each representing 2^OuterPacketBits columns or rows according to the storage order.
 * To reach optimal performance, this value should be adjusted according to the average number of nonzeros
 * per rows/columns.
 *
 * The possible values for the template parameter MapTraits are:
 *  - \b StdMapTraits: corresponds to std::map. (does not perform very well)
 *  - \b StdUnorderedMapTraits: corresponds to std::unordered_map
 *  - \b GoogleDenseHashMapTraits: corresponds to google::dense_hash_map (best efficiency, reasonable memory
 * consumption)
 *  - \b GoogleSparseHashMapTraits: corresponds to google::sparse_hash_map (best memory consumption, relatively good
 * performance)
 *
 * The default map implementation is GoogleDenseHashMapTraits if EIGEN_GOOGLEHASH_SUPPORT is defined, and
 * StdUnorderedMapTraits otherwise; StdMapTraits is never selected by default.
 *
 * For performance and memory consumption reasons it is highly recommended to use one of
 * Google's hash_map implementations. To enable the support for them, you must define
 * EIGEN_GOOGLEHASH_SUPPORT. This will include both <google/dense_hash_map> and
 * <google/sparse_hash_map> for you.
 *
 * \see https://github.com/sparsehash/sparsehash
 */
template <typename SparseMatrixType,
          template <typename T> class MapTraits =
#if defined(EIGEN_GOOGLEHASH_SUPPORT)
              GoogleDenseHashMapTraits
#else
              StdUnorderedMapTraits
#endif
          ,
          int OuterPacketBits = 6>
class RandomSetter {
  typedef typename SparseMatrixType::Scalar Scalar;
  typedef typename SparseMatrixType::StorageIndex StorageIndex;

  struct ScalarWrapper {
    Scalar value = Scalar(0);
  };
  typedef typename MapTraits<ScalarWrapper>::KeyType KeyType;
  typedef typename MapTraits<ScalarWrapper>::Type HashMapType;
  static constexpr int OuterPacketMask = (1 << OuterPacketBits) - 1;
  enum {
    SwapStorage = 1 - MapTraits<ScalarWrapper>::IsSorted,
    TargetRowMajor = (SparseMatrixType::Flags & RowMajorBit) ? 1 : 0,
    SetterRowMajor = SwapStorage ? 1 - TargetRowMajor : TargetRowMajor
  };

 public:
  /** Constructs a random setter object from the sparse matrix \a target
   *
   * Note that the initial values of \a target are imported. If you want to re-set
   * a sparse matrix from scratch, then you must set it to zero first using the
   * setZero() function.
   */
  inline RandomSetter(SparseMatrixType& target) : m_target(&target) {
    const Index outerSize = SwapStorage ? target.innerSize() : target.outerSize();
    const Index innerSize = SwapStorage ? target.outerSize() : target.innerSize();
    m_outerPackets = outerSize >> OuterPacketBits;
    if (outerSize & OuterPacketMask) m_outerPackets += 1;
    m_hashmaps = new HashMapType[m_outerPackets];
    // compute number of bits needed to store inner indices
    Index aux = innerSize - 1;
    m_keyBitsOffset = 0;
    while (aux) {
      ++m_keyBitsOffset;
      aux = aux >> 1;
    }
    KeyType ik = (1 << (OuterPacketBits + m_keyBitsOffset));
    for (Index k = 0; k < m_outerPackets; ++k) MapTraits<ScalarWrapper>::setInvalidKey(m_hashmaps[k], ik);

    // insert current coeffs
    for (Index j = 0; j < m_target->outerSize(); ++j)
      for (typename SparseMatrixType::InnerIterator it(*m_target, j); it; ++it)
        (*this)(TargetRowMajor ? j : it.index(), TargetRowMajor ? it.index() : j) = it.value();
  }

  /** Destructor updating back the sparse matrix target */
  ~RandomSetter() {
    KeyType keyBitsMask = (1 << m_keyBitsOffset) - 1;
    if (!SwapStorage)  // also means the map is sorted
    {
      m_target->setZero();
      m_target->makeCompressed();
      m_target->reserve(nonZeros());
      Index prevOuter = -1;
      for (Index k = 0; k < m_outerPackets; ++k) {
        const Index outerOffset = (1 << OuterPacketBits) * k;
        typename HashMapType::iterator end = m_hashmaps[k].end();
        for (typename HashMapType::iterator it = m_hashmaps[k].begin(); it != end; ++it) {
          const Index outer = (it->first >> m_keyBitsOffset) + outerOffset;
          const Index inner = it->first & keyBitsMask;
          if (prevOuter != outer) {
            for (Index j = prevOuter + 1; j <= outer; ++j) m_target->startVec(j);
            prevOuter = outer;
          }
          m_target->insertBackByOuterInner(outer, inner) = it->second.value;
        }
      }
      m_target->finalize();
    } else {
      VectorXi positions(m_target->outerSize());
      positions.setZero();
      // pass 1
      for (Index k = 0; k < m_outerPackets; ++k) {
        typename HashMapType::iterator end = m_hashmaps[k].end();
        for (typename HashMapType::iterator it = m_hashmaps[k].begin(); it != end; ++it) {
          const Index outer = it->first & keyBitsMask;
          ++positions[outer];
        }
      }
      // prefix sum
      StorageIndex count = 0;
      for (Index j = 0; j < m_target->outerSize(); ++j) {
        StorageIndex tmp = positions[j];
        m_target->outerIndexPtr()[j] = count;
        positions[j] = count;
        count += tmp;
      }
      m_target->makeCompressed();
      m_target->outerIndexPtr()[m_target->outerSize()] = count;
      m_target->resizeNonZeros(count);
      // pass 2
      for (Index k = 0; k < m_outerPackets; ++k) {
        const Index outerOffset = (1 << OuterPacketBits) * k;
        typename HashMapType::iterator end = m_hashmaps[k].end();
        for (typename HashMapType::iterator it = m_hashmaps[k].begin(); it != end; ++it) {
          const Index inner = (it->first >> m_keyBitsOffset) + outerOffset;
          const Index outer = it->first & keyBitsMask;
          // sorted insertion
          // Note that we have to deal with at most 2^OuterPacketBits unsorted coefficients,
          // moreover those 2^OuterPacketBits coeffs are likely to be sparse, and so only a
          // small fraction of them have to be sorted, whence the following simple procedure:
          Index posStart = m_target->outerIndexPtr()[outer];
          Index i = (positions[outer]++) - 1;
          while ((i >= posStart) && (m_target->innerIndexPtr()[i] > inner)) {
            m_target->valuePtr()[i + 1] = m_target->valuePtr()[i];
            m_target->innerIndexPtr()[i + 1] = m_target->innerIndexPtr()[i];
            --i;
          }
          m_target->innerIndexPtr()[i + 1] = internal::convert_index<StorageIndex>(inner);
          m_target->valuePtr()[i + 1] = it->second.value;
        }
      }
    }
    delete[] m_hashmaps;
  }

  /** \returns a reference to the coefficient at given coordinates \a row, \a col */
  Scalar& operator()(Index row, Index col) {
    const Index outer = SetterRowMajor ? row : col;
    const Index inner = SetterRowMajor ? col : row;
    const Index outerMajor = outer >> OuterPacketBits;  // index of the packet/map
    const Index outerMinor = outer & OuterPacketMask;   // index of the inner vector in the packet
    const KeyType key = internal::convert_index<KeyType>((outerMinor << m_keyBitsOffset) | inner);
    return m_hashmaps[outerMajor][key].value;
  }

#ifdef EIGEN_MULTIDIMENSIONAL_SUBSCRIPT
  /** \returns a reference to the coefficient at given coordinates \a row, \a col */
  Scalar& operator[](Index row, Index col) { return operator()(row, col); }
#endif

  /** \returns the number of non zero coefficients
   *
   * \note According to the underlying map/hash_map implementation,
   * this function might be quite expensive.
   */
  Index nonZeros() const {
    Index nz = 0;
    for (Index k = 0; k < m_outerPackets; ++k) nz += static_cast<Index>(m_hashmaps[k].size());
    return nz;
  }

 protected:
  HashMapType* m_hashmaps;
  SparseMatrixType* m_target;
  Index m_outerPackets;
  unsigned char m_keyBitsOffset;
};

}  // end namespace Eigen

#endif  // EIGEN_RANDOMSETTER_H
